@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.esm.js CHANGED
@@ -867,6 +867,29 @@ function findParentIdFromAuiParent(messages, auiParentId) {
867
867
  // src/index.ts
868
868
  import { parseSSELine as parseSSELine2 } from "@timbal-ai/timbal-sdk";
869
869
 
870
+ // src/components/thread.tsx
871
+ import {
872
+ ActionBarMorePrimitive,
873
+ ActionBarPrimitive,
874
+ AuiIf as AuiIf2,
875
+ ComposerPrimitive as ComposerPrimitive3,
876
+ ErrorPrimitive,
877
+ MessagePartPrimitive,
878
+ MessagePrimitive as MessagePrimitive2,
879
+ ThreadPrimitive,
880
+ useThread
881
+ } from "@assistant-ui/react";
882
+ import {
883
+ ArrowDownIcon,
884
+ CheckIcon as CheckIcon3,
885
+ CopyIcon as CopyIcon2,
886
+ DownloadIcon,
887
+ MoreHorizontalIcon,
888
+ PencilIcon,
889
+ RefreshCwIcon
890
+ } from "lucide-react";
891
+ import { motion as motion4 } from "motion/react";
892
+
870
893
  // src/components/attachment.tsx
871
894
  import { useEffect as useEffect2, useState as useState2 } from "react";
872
895
  import { XIcon as XIcon2, PlusIcon, FileText } from "lucide-react";
@@ -1079,87 +1102,147 @@ function AvatarFallback({
1079
1102
  }
1080
1103
 
1081
1104
  // src/components/tooltip-icon-button.tsx
1082
- import { forwardRef } from "react";
1083
- import { Slottable } from "@radix-ui/react-slot";
1105
+ import { forwardRef as forwardRef2 } from "react";
1084
1106
 
1085
- // src/ui/button.tsx
1086
- import { cva } from "class-variance-authority";
1107
+ // src/ui/timbal-v2-button.tsx
1108
+ import * as React from "react";
1087
1109
  import { Slot } from "radix-ui";
1088
- import { jsx as jsx5 } from "react/jsx-runtime";
1089
- var buttonVariants = cva(
1090
- "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",
1091
- {
1092
- variants: {
1093
- variant: {
1094
- default: "bg-primary text-primary-foreground hover:bg-primary/90",
1095
- destructive: "bg-destructive text-white hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60",
1096
- 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",
1097
- secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80",
1098
- ghost: "hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50",
1099
- link: "text-primary underline-offset-4 hover:underline"
1100
- },
1101
- size: {
1102
- default: "h-9 px-4 py-2 has-[>svg]:px-3",
1103
- xs: "h-6 gap-1 rounded-md px-2 text-xs has-[>svg]:px-1.5 [&_svg:not([class*='size-'])]:size-3",
1104
- sm: "h-8 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5",
1105
- lg: "h-10 rounded-md px-6 has-[>svg]:px-4",
1106
- icon: "size-9",
1107
- "icon-xs": "size-6 rounded-md [&_svg:not([class*='size-'])]:size-3",
1108
- "icon-sm": "size-8",
1109
- "icon-lg": "size-10"
1110
- }
1111
- },
1112
- defaultVariants: {
1113
- variant: "default",
1114
- size: "default"
1115
- }
1116
- }
1117
- );
1118
- function Button({
1119
- className,
1120
- variant = "default",
1121
- size = "default",
1110
+
1111
+ // src/ui/timbal-v2-button-tokens.ts
1112
+ var TIMBAL_V2_SIZE_HEIGHT = {
1113
+ xs: "min-h-8 h-8",
1114
+ sm: "min-h-9 h-9",
1115
+ md: "min-h-10 h-10",
1116
+ lg: "min-h-11 h-11"
1117
+ };
1118
+ var TIMBAL_V2_SIZE_ICON = {
1119
+ xs: "min-h-8 min-w-8 size-8",
1120
+ sm: "min-h-8 min-w-8 size-8",
1121
+ md: "min-h-10 min-w-10 size-10",
1122
+ lg: "min-h-11 min-w-11 size-11"
1123
+ };
1124
+ var TIMBAL_V2_SIZE_LABEL_PX = {
1125
+ xs: "px-3",
1126
+ sm: "px-4",
1127
+ md: "px-5",
1128
+ lg: "px-6"
1129
+ };
1130
+ var TIMBAL_V2_FILL = {
1131
+ 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",
1132
+ informative: "bg-blue-600 group-active/tbv2:[background-image:linear-gradient(to_top,rgba(0,0,0,0.08),transparent_55%)]",
1133
+ 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",
1134
+ 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]",
1135
+ 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",
1136
+ link: "bg-transparent"
1137
+ };
1138
+ var TIMBAL_V2_LABEL = {
1139
+ primary: "text-white dark:text-neutral-900",
1140
+ informative: "text-white",
1141
+ destructive: "text-destructive dark:text-red-400",
1142
+ secondary: "text-foreground",
1143
+ ghost: "text-foreground",
1144
+ 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"
1145
+ };
1146
+ var TIMBAL_V2_BORDER = {
1147
+ primary: "",
1148
+ informative: "border border-white/15 dark:border-white/10",
1149
+ destructive: "border border-destructive/45 dark:border-red-500/55",
1150
+ secondary: "border border-neutral-200/80 dark:border-white/[0.08]",
1151
+ ghost: "",
1152
+ link: ""
1153
+ };
1154
+ var TIMBAL_V2_SHADOW = {
1155
+ primary: "shadow-sm shadow-black/15 dark:shadow-black/40",
1156
+ informative: "shadow-sm shadow-blue-900/20 dark:shadow-black/40",
1157
+ destructive: "shadow-[0_1px_2px_-0.5px_rgba(0,0,0,0.05)] dark:shadow-[0_1px_3px_rgba(0,0,0,0.22)]",
1158
+ secondary: "shadow-[0_1px_2px_-0.5px_rgba(0,0,0,0.05)] dark:shadow-[0_1px_3px_rgba(0,0,0,0.22)]",
1159
+ ghost: "",
1160
+ link: ""
1161
+ };
1162
+ 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)]";
1163
+ 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]";
1164
+
1165
+ // src/ui/timbal-v2-button.tsx
1166
+ import { jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
1167
+ var TimbalV2Button = React.forwardRef(function TimbalV2Button2({
1168
+ variant = "secondary",
1169
+ size = "sm",
1170
+ isIconOnly = false,
1171
+ isLoading = false,
1172
+ fullWidth = false,
1122
1173
  asChild = false,
1174
+ className,
1175
+ disabled,
1176
+ type = "button",
1177
+ children,
1123
1178
  ...props
1124
- }) {
1179
+ }, ref) {
1180
+ const isDisabled = disabled || isLoading;
1125
1181
  const Comp = asChild ? Slot.Root : "button";
1126
- return /* @__PURE__ */ jsx5(
1182
+ const sizeClass = isIconOnly ? TIMBAL_V2_SIZE_ICON[size] : TIMBAL_V2_SIZE_HEIGHT[size];
1183
+ const radiusClass = variant === "link" || variant === "ghost" ? "rounded-md" : "rounded-full";
1184
+ return /* @__PURE__ */ jsxs3(
1127
1185
  Comp,
1128
1186
  {
1129
- "data-slot": "button",
1187
+ ref,
1188
+ type: asChild ? void 0 : type,
1189
+ disabled: asChild ? void 0 : isDisabled,
1190
+ "aria-disabled": asChild && isDisabled ? true : void 0,
1191
+ "data-slot": "timbal-v2-button",
1130
1192
  "data-variant": variant,
1131
- "data-size": size,
1132
- className: cn(buttonVariants({ variant, size, className })),
1133
- ...props
1193
+ className: cn(
1194
+ "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",
1195
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-neutral-400/60 focus-visible:ring-offset-1 focus-visible:ring-offset-background",
1196
+ sizeClass,
1197
+ radiusClass,
1198
+ TIMBAL_V2_BORDER[variant],
1199
+ TIMBAL_V2_SHADOW[variant],
1200
+ fullWidth && "w-full",
1201
+ isDisabled && "pointer-events-none opacity-50",
1202
+ className
1203
+ ),
1204
+ ...props,
1205
+ children: [
1206
+ /* @__PURE__ */ jsx5(
1207
+ "span",
1208
+ {
1209
+ "aria-hidden": true,
1210
+ className: cn(
1211
+ "pointer-events-none absolute inset-0 transition duration-200 ease-in-out",
1212
+ TIMBAL_V2_FILL[variant]
1213
+ )
1214
+ }
1215
+ ),
1216
+ /* @__PURE__ */ jsx5(
1217
+ "span",
1218
+ {
1219
+ className: cn(
1220
+ "relative z-10 flex min-h-0 flex-1 items-center justify-center gap-1 leading-tight",
1221
+ !isIconOnly && TIMBAL_V2_SIZE_LABEL_PX[size],
1222
+ TIMBAL_V2_LABEL[variant]
1223
+ ),
1224
+ children: isLoading ? /* @__PURE__ */ jsx5("span", { className: "size-4 animate-spin rounded-full border-2 border-current border-t-transparent" }) : children
1225
+ }
1226
+ )
1227
+ ]
1134
1228
  }
1135
1229
  );
1136
- }
1230
+ });
1137
1231
 
1138
1232
  // src/components/tooltip-icon-button.tsx
1139
- import { jsx as jsx6, jsxs as jsxs3 } from "react/jsx-runtime";
1140
- var TooltipIconButton = forwardRef(({ children, tooltip, side = "bottom", className, ...rest }, ref) => {
1141
- return /* @__PURE__ */ jsxs3(Tooltip, { children: [
1142
- /* @__PURE__ */ jsx6(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxs3(
1143
- Button,
1144
- {
1145
- variant: "ghost",
1146
- size: "icon",
1147
- ...rest,
1148
- className: cn("aui-button-icon size-6 p-1", className),
1149
- ref,
1150
- children: [
1151
- /* @__PURE__ */ jsx6(Slottable, { children }),
1152
- /* @__PURE__ */ jsx6("span", { className: "aui-sr-only sr-only", children: tooltip })
1153
- ]
1154
- }
1155
- ) }),
1233
+ import { jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
1234
+ var TooltipIconButton = forwardRef2(function TooltipIconButton2({ tooltip, side = "bottom", variant = "secondary", children, ...props }, ref) {
1235
+ return /* @__PURE__ */ jsxs4(Tooltip, { children: [
1236
+ /* @__PURE__ */ jsx6(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxs4(TimbalV2Button, { ref, variant, size: "sm", isIconOnly: true, ...props, children: [
1237
+ children,
1238
+ /* @__PURE__ */ jsx6("span", { className: "sr-only", children: tooltip })
1239
+ ] }) }),
1156
1240
  /* @__PURE__ */ jsx6(TooltipContent, { side, children: tooltip })
1157
1241
  ] });
1158
1242
  });
1159
- TooltipIconButton.displayName = "TooltipIconButton";
1160
1243
 
1161
1244
  // src/components/attachment.tsx
1162
- import { jsx as jsx7, jsxs as jsxs4 } from "react/jsx-runtime";
1245
+ import { jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
1163
1246
  var useFileSrc = (file) => {
1164
1247
  const [src, setSrc] = useState2(void 0);
1165
1248
  useEffect2(() => {
@@ -1205,7 +1288,7 @@ var AttachmentPreview = ({ src }) => {
1205
1288
  var AttachmentPreviewDialog = ({ children }) => {
1206
1289
  const src = useAttachmentSrc();
1207
1290
  if (!src) return children;
1208
- return /* @__PURE__ */ jsxs4(Dialog, { children: [
1291
+ return /* @__PURE__ */ jsxs5(Dialog, { children: [
1209
1292
  /* @__PURE__ */ jsx7(
1210
1293
  DialogTrigger,
1211
1294
  {
@@ -1214,7 +1297,7 @@ var AttachmentPreviewDialog = ({ children }) => {
1214
1297
  children
1215
1298
  }
1216
1299
  ),
1217
- /* @__PURE__ */ jsxs4(DialogContent, { className: "aui-attachment-preview-dialog-content p-2 sm:max-w-3xl [&>button]:rounded-full [&>button]:bg-foreground/60 [&>button]:p-1 [&>button]:opacity-100 [&>button]:ring-0! [&_svg]:text-background [&>button]:hover:[&_svg]:text-destructive", children: [
1300
+ /* @__PURE__ */ jsxs5(DialogContent, { className: "aui-attachment-preview-dialog-content p-2 sm:max-w-3xl [&>button]:rounded-full [&>button]:bg-foreground/60 [&>button]:p-1 [&>button]:opacity-100 [&>button]:ring-0! [&_svg]:text-background [&>button]:hover:[&_svg]:text-destructive", children: [
1218
1301
  /* @__PURE__ */ jsx7(DialogTitle, { className: "aui-sr-only sr-only", children: "Image Attachment Preview" }),
1219
1302
  /* @__PURE__ */ jsx7("div", { className: "aui-attachment-preview relative mx-auto flex max-h-[80dvh] w-full items-center justify-center overflow-hidden bg-background", children: /* @__PURE__ */ jsx7(AttachmentPreview, { src }) })
1220
1303
  ] })
@@ -1223,7 +1306,7 @@ var AttachmentPreviewDialog = ({ children }) => {
1223
1306
  var AttachmentThumb = () => {
1224
1307
  const isImage = useAuiState((s) => s.attachment.type === "image");
1225
1308
  const src = useAttachmentSrc();
1226
- return /* @__PURE__ */ jsxs4(Avatar, { className: "aui-attachment-tile-avatar h-full w-full rounded-none", children: [
1309
+ return /* @__PURE__ */ jsxs5(Avatar, { className: "aui-attachment-tile-avatar h-full w-full rounded-none", children: [
1227
1310
  /* @__PURE__ */ jsx7(
1228
1311
  AvatarImage,
1229
1312
  {
@@ -1252,8 +1335,8 @@ var AttachmentUI = () => {
1252
1335
  throw new Error(`Unknown attachment type: ${type}`);
1253
1336
  }
1254
1337
  });
1255
- return /* @__PURE__ */ jsxs4(Tooltip, { children: [
1256
- /* @__PURE__ */ jsxs4(
1338
+ return /* @__PURE__ */ jsxs5(Tooltip, { children: [
1339
+ /* @__PURE__ */ jsxs5(
1257
1340
  AttachmentPrimitive.Root,
1258
1341
  {
1259
1342
  className: cn(
@@ -1309,11 +1392,10 @@ var ComposerAddAttachment = () => {
1309
1392
  {
1310
1393
  tooltip: "Add Attachment",
1311
1394
  side: "bottom",
1312
- variant: "ghost",
1313
- size: "icon",
1314
- 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",
1395
+ variant: "secondary",
1396
+ className: "aui-composer-add-attachment shrink-0 text-neutral-500 dark:text-muted-foreground",
1315
1397
  "aria-label": "Add Attachment",
1316
- children: /* @__PURE__ */ jsx7(PlusIcon, { className: "aui-attachment-add-icon size-5 stroke-[1.5px]" })
1398
+ children: /* @__PURE__ */ jsx7(PlusIcon, { className: "aui-attachment-add-icon size-4 stroke-[1.5]" })
1317
1399
  }
1318
1400
  ) });
1319
1401
  };
@@ -1344,10 +1426,10 @@ import { createContext as createContext3, useContext as useContext3, useMemo as
1344
1426
  import { useMemo as useMemo2 } from "react";
1345
1427
 
1346
1428
  // src/artifacts/artifact-card.tsx
1347
- import { jsx as jsx8, jsxs as jsxs5 } from "react/jsx-runtime";
1429
+ import { jsx as jsx8, jsxs as jsxs6 } from "react/jsx-runtime";
1348
1430
  var ArtifactCard = ({ title, kind, className, bodyClassName, toolbar, children }) => {
1349
1431
  const hasHeader = Boolean(title || toolbar);
1350
- return /* @__PURE__ */ jsxs5(
1432
+ return /* @__PURE__ */ jsxs6(
1351
1433
  "div",
1352
1434
  {
1353
1435
  className: cn(
@@ -1356,7 +1438,7 @@ var ArtifactCard = ({ title, kind, className, bodyClassName, toolbar, children }
1356
1438
  ),
1357
1439
  "data-artifact-kind": kind,
1358
1440
  children: [
1359
- hasHeader && /* @__PURE__ */ jsxs5("div", { className: "aui-artifact-header flex items-center gap-2 border-b border-border/40 bg-muted/30 px-3 py-1.5", children: [
1441
+ hasHeader && /* @__PURE__ */ jsxs6("div", { className: "aui-artifact-header flex items-center gap-2 border-b border-border/40 bg-muted/30 px-3 py-1.5", children: [
1360
1442
  title && /* @__PURE__ */ jsx8("span", { className: "aui-artifact-title flex-1 truncate text-xs font-semibold text-foreground/80", children: title }),
1361
1443
  !title && /* @__PURE__ */ jsx8("span", { className: "flex-1" }),
1362
1444
  toolbar
@@ -1368,7 +1450,7 @@ var ArtifactCard = ({ title, kind, className, bodyClassName, toolbar, children }
1368
1450
  };
1369
1451
 
1370
1452
  // src/artifacts/chart-artifact.tsx
1371
- import { Fragment, jsx as jsx9, jsxs as jsxs6 } from "react/jsx-runtime";
1453
+ import { Fragment, jsx as jsx9, jsxs as jsxs7 } from "react/jsx-runtime";
1372
1454
  var ChartArtifactView = ({
1373
1455
  artifact
1374
1456
  }) => {
@@ -1379,7 +1461,7 @@ var ChartArtifactView = ({
1379
1461
  if (typeof artifact.dataKey === "string") return [artifact.dataKey];
1380
1462
  return inferDataKeys(data, xKey);
1381
1463
  }, [artifact.dataKey, data, xKey]);
1382
- return /* @__PURE__ */ jsx9(ArtifactCard, { title: artifact.title, kind: "chart", children: /* @__PURE__ */ jsxs6("div", { className: "aui-artifact-chart p-3", children: [
1464
+ return /* @__PURE__ */ jsx9(ArtifactCard, { title: artifact.title, kind: "chart", children: /* @__PURE__ */ jsxs7("div", { className: "aui-artifact-chart p-3", children: [
1383
1465
  /* @__PURE__ */ jsx9(
1384
1466
  ChartSvg,
1385
1467
  {
@@ -1422,7 +1504,7 @@ var ChartSvg = ({ chartType, data, xKey, dataKeys, unit }) => {
1422
1504
  const xStep = xCount > 1 ? innerW / (xCount - 1) : innerW;
1423
1505
  const xPos = (i) => chartType === "bar" ? PAD.left + innerW * (i + 0.5) / xCount : PAD.left + i * xStep;
1424
1506
  const ticks = niceTicks(minV, maxV);
1425
- return /* @__PURE__ */ jsxs6(
1507
+ return /* @__PURE__ */ jsxs7(
1426
1508
  "svg",
1427
1509
  {
1428
1510
  viewBox: `0 0 ${W} ${H}`,
@@ -1430,7 +1512,7 @@ var ChartSvg = ({ chartType, data, xKey, dataKeys, unit }) => {
1430
1512
  role: "img",
1431
1513
  "aria-label": "Chart",
1432
1514
  children: [
1433
- ticks.map((t, i) => /* @__PURE__ */ jsxs6("g", { children: [
1515
+ ticks.map((t, i) => /* @__PURE__ */ jsxs7("g", { children: [
1434
1516
  /* @__PURE__ */ jsx9(
1435
1517
  "line",
1436
1518
  {
@@ -1538,7 +1620,7 @@ var Area = ({ data, dataKey, xPos, yScale, baseY, color }) => {
1538
1620
  if (data.length === 0) return null;
1539
1621
  const top = data.map((d, i) => `${xPos(i)},${yScale(toNum(d[dataKey]))}`).join(" ");
1540
1622
  const path = `M ${xPos(0)},${baseY} L ${top} L ${xPos(data.length - 1)},${baseY} Z`;
1541
- return /* @__PURE__ */ jsxs6(Fragment, { children: [
1623
+ return /* @__PURE__ */ jsxs7(Fragment, { children: [
1542
1624
  /* @__PURE__ */ jsx9("path", { d: path, fill: color, fillOpacity: 0.18 }),
1543
1625
  /* @__PURE__ */ jsx9(Polyline, { data, dataKey, xPos, yScale, color })
1544
1626
  ] });
@@ -1588,7 +1670,7 @@ var PieSlice = ({ cx, cy, r, start, end, color, label }) => {
1588
1670
  const mid = (start + end) / 2;
1589
1671
  const lx = cx + Math.sin(mid) * (r * 0.65);
1590
1672
  const ly = cy - Math.cos(mid) * (r * 0.65);
1591
- return /* @__PURE__ */ jsxs6("g", { children: [
1673
+ return /* @__PURE__ */ jsxs7("g", { children: [
1592
1674
  /* @__PURE__ */ jsx9("path", { d: path, fill: color, stroke: "var(--background, #fff)", strokeWidth: 1 }),
1593
1675
  /* @__PURE__ */ jsx9(
1594
1676
  "text",
@@ -1603,7 +1685,7 @@ var PieSlice = ({ cx, cy, r, start, end, color, label }) => {
1603
1685
  )
1604
1686
  ] });
1605
1687
  };
1606
- var Legend = ({ dataKeys }) => /* @__PURE__ */ jsx9("div", { className: "aui-artifact-chart-legend mt-2 flex flex-wrap items-center gap-x-3 gap-y-1 text-xs text-muted-foreground", children: dataKeys.map((k, i) => /* @__PURE__ */ jsxs6("span", { className: "inline-flex items-center gap-1.5", children: [
1688
+ var Legend = ({ dataKeys }) => /* @__PURE__ */ jsx9("div", { className: "aui-artifact-chart-legend mt-2 flex flex-wrap items-center gap-x-3 gap-y-1 text-xs text-muted-foreground", children: dataKeys.map((k, i) => /* @__PURE__ */ jsxs7("span", { className: "inline-flex items-center gap-1.5", children: [
1607
1689
  /* @__PURE__ */ jsx9(
1608
1690
  "span",
1609
1691
  {
@@ -1661,89 +1743,182 @@ function formatTick(v, unit) {
1661
1743
  }
1662
1744
 
1663
1745
  // src/artifacts/question-artifact.tsx
1664
- import { useState as useState3 } from "react";
1746
+ import { useCallback as useCallback2, useState as useState3 } from "react";
1665
1747
  import { useThreadRuntime } from "@assistant-ui/react";
1666
1748
  import { CheckIcon } from "lucide-react";
1667
- import { jsx as jsx10, jsxs as jsxs7 } from "react/jsx-runtime";
1749
+
1750
+ // src/ui/chrome.ts
1751
+ var STUDIO_TOPBAR_GAP = "0.5rem";
1752
+ var STUDIO_TOPBAR_HEIGHT = "3rem";
1753
+ var STUDIO_PILL_HEIGHT = "2.5rem";
1754
+ var STUDIO_SIDEBAR_GAP = "0.5rem";
1755
+ var STUDIO_SIDEBAR_WIDTH = "3rem";
1756
+ var STUDIO_INSET_LEFT = `calc(${STUDIO_SIDEBAR_GAP} + ${STUDIO_SIDEBAR_WIDTH})`;
1757
+ var studioChromeShellStyle = {
1758
+ "--studio-topbar-gap": STUDIO_TOPBAR_GAP,
1759
+ "--studio-topbar-height": STUDIO_TOPBAR_HEIGHT,
1760
+ "--studio-chrome-pill-height": STUDIO_PILL_HEIGHT,
1761
+ "--studio-inset-top": `calc(${STUDIO_TOPBAR_GAP} + ${STUDIO_TOPBAR_HEIGHT})`,
1762
+ "--studio-sidebar-gap": STUDIO_SIDEBAR_GAP,
1763
+ "--studio-sidebar-width": STUDIO_SIDEBAR_WIDTH,
1764
+ "--studio-inset-left": STUDIO_INSET_LEFT
1765
+ };
1766
+ var studioTopbarPillHeightClass = "h-[var(--studio-chrome-pill-height)] min-h-[var(--studio-chrome-pill-height)]";
1767
+ 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)]";
1768
+ 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";
1769
+ 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";
1770
+ var studioPillSurfaceClass = TIMBAL_V2_PILL_SURFACE;
1771
+ var studioSecondaryChromeClass = TIMBAL_V2_SECONDARY_CHROME;
1772
+ 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)]";
1773
+ var studioIntegrationBorder = "border border-neutral-200/80 dark:border-white/[0.08]";
1774
+ var studioIntegrationCardClass = cn(
1775
+ "rounded-xl",
1776
+ studioIntegrationSurfaceSolid,
1777
+ studioIntegrationBorder
1778
+ );
1779
+ var studioIntegrationIconTileClass = cn(
1780
+ "flex size-9 shrink-0 items-center justify-center rounded-lg",
1781
+ studioIntegrationSurfaceSolid,
1782
+ studioIntegrationBorder
1783
+ );
1784
+ var studioListRowButtonClass = cn(
1785
+ "flex w-full cursor-pointer items-center gap-3 rounded-xl px-3 py-2.5 text-left",
1786
+ studioIntegrationCardClass,
1787
+ "transition-[background-color,box-shadow,border-color] duration-200 ease-in-out",
1788
+ "hover:border-neutral-300 dark:hover:border-white/15",
1789
+ "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"
1790
+ );
1791
+ var studioComposerIoWellClass = cn(
1792
+ "rounded-lg",
1793
+ studioIntegrationSurfaceSolid,
1794
+ studioIntegrationBorder
1795
+ );
1796
+ var studioToolCardShellClass = cn(
1797
+ studioIntegrationCardClass,
1798
+ "my-2 min-h-0 overflow-hidden"
1799
+ );
1800
+ 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";
1801
+ var studioTimelineTextClass = "text-xs font-normal leading-snug";
1802
+ var studioTimelineActionClass = cn(
1803
+ studioTimelineTextClass,
1804
+ "shrink-0 text-foreground/70 transition-colors duration-150 group-hover:text-foreground/80"
1805
+ );
1806
+ var studioTimelineShimmerActionClass = cn(
1807
+ studioTimelineTextClass,
1808
+ "shrink-0"
1809
+ );
1810
+ var studioTimelineDetailClass = cn(
1811
+ studioTimelineTextClass,
1812
+ "min-w-0 truncate text-muted-foreground transition-colors duration-150"
1813
+ );
1814
+ function studioTimelineChevronClass(expanded) {
1815
+ return cn(
1816
+ "ml-0.5 size-3 min-h-3 min-w-3 shrink-0 transition-all duration-150",
1817
+ expanded ? "rotate-90 text-foreground opacity-60" : "text-muted-foreground opacity-0 group-hover:opacity-70"
1818
+ );
1819
+ }
1820
+ var studioTimelineBodyPadClass = "flex flex-col gap-2 pt-0.5 pb-0.5";
1821
+ var studioArtifactShellClass = cn(
1822
+ studioIntegrationCardClass,
1823
+ "my-2 w-full min-w-0 overflow-hidden"
1824
+ );
1825
+ 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";
1826
+ var studioQuestionOptionSelectedClass = cn(
1827
+ studioQuestionOptionClass,
1828
+ "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"
1829
+ );
1830
+
1831
+ // src/artifacts/question-artifact.tsx
1832
+ import { jsx as jsx10, jsxs as jsxs8 } from "react/jsx-runtime";
1833
+ function optionKey(option, index) {
1834
+ const id = option.id?.trim();
1835
+ return id ? id : `__option-${index}`;
1836
+ }
1837
+ var OptionRadio = ({ selected }) => /* @__PURE__ */ jsx10(
1838
+ "span",
1839
+ {
1840
+ className: cn(
1841
+ "flex size-4 shrink-0 items-center justify-center rounded-full border-2 transition-colors",
1842
+ selected ? "border-foreground bg-foreground text-background" : "border-neutral-300 bg-background dark:border-white/20"
1843
+ ),
1844
+ "aria-hidden": true,
1845
+ children: selected ? /* @__PURE__ */ jsx10(CheckIcon, { className: "size-2.5 stroke-[3]" }) : null
1846
+ }
1847
+ );
1668
1848
  var QuestionArtifactView = ({
1669
1849
  artifact
1670
1850
  }) => {
1671
1851
  const runtime = useThreadRuntime();
1672
1852
  const [selected, setSelected] = useState3([]);
1673
- const [submitted, setSubmitted] = useState3(null);
1853
+ const [submittedIds, setSubmittedIds] = useState3(null);
1674
1854
  const isMulti = artifact.multi === true;
1675
- const send = (labels) => {
1676
- if (labels.length === 0) return;
1677
- const text = labels.join(", ");
1678
- setSubmitted(text);
1679
- runtime.append({ role: "user", content: [{ type: "text", text }] });
1680
- };
1681
- const onPick = (option) => {
1682
- if (submitted) return;
1683
- if (!isMulti) {
1684
- send([option.label]);
1685
- return;
1686
- }
1687
- setSelected(
1688
- (prev) => prev.includes(option.id) ? prev.filter((id) => id !== option.id) : [...prev, option.id]
1689
- );
1690
- };
1691
- const onConfirm = () => {
1692
- const labels = artifact.options.filter((o) => selected.includes(o.id)).map((o) => o.label);
1693
- send(labels);
1694
- };
1695
- return /* @__PURE__ */ jsx10(ArtifactCard, { kind: "question", children: /* @__PURE__ */ jsxs7("div", { className: "aui-artifact-question p-3", children: [
1696
- artifact.prompt && /* @__PURE__ */ jsx10("p", { className: "aui-artifact-question-prompt mb-2 text-sm text-foreground/85", children: artifact.prompt }),
1697
- /* @__PURE__ */ jsx10("div", { className: "aui-artifact-question-options flex flex-col gap-1.5", children: artifact.options.map((option) => {
1698
- const isSelected = isMulti && selected.includes(option.id);
1699
- const isDisabled = Boolean(submitted);
1700
- return /* @__PURE__ */ jsxs7(
1855
+ const isDisabled = submittedIds !== null;
1856
+ const send = useCallback2(
1857
+ (keys) => {
1858
+ if (keys.length === 0) return;
1859
+ const labels = artifact.options.map((option, index) => ({ option, key: optionKey(option, index) })).filter(({ key }) => keys.includes(key)).map(({ option }) => option.label);
1860
+ setSubmittedIds(keys);
1861
+ runtime.append({
1862
+ role: "user",
1863
+ content: [{ type: "text", text: labels.join(", ") }]
1864
+ });
1865
+ },
1866
+ [artifact.options, runtime]
1867
+ );
1868
+ const onPick = useCallback2(
1869
+ (key) => {
1870
+ if (isDisabled) return;
1871
+ if (!isMulti) {
1872
+ send([key]);
1873
+ return;
1874
+ }
1875
+ setSelected(
1876
+ (prev) => prev.includes(key) ? prev.filter((id) => id !== key) : [...prev, key]
1877
+ );
1878
+ },
1879
+ [isDisabled, isMulti, send]
1880
+ );
1881
+ const onConfirm = useCallback2(() => {
1882
+ send(selected);
1883
+ }, [selected, send]);
1884
+ return /* @__PURE__ */ jsx10("div", { className: studioArtifactShellClass, "data-artifact-kind": "question", children: /* @__PURE__ */ jsxs8("div", { className: "px-2.5 py-2", children: [
1885
+ artifact.prompt ? /* @__PURE__ */ jsx10("p", { className: "mb-2 text-sm font-normal leading-snug text-foreground", children: artifact.prompt }) : null,
1886
+ /* @__PURE__ */ jsx10("div", { className: "flex flex-col gap-0.5", role: "list", children: artifact.options.map((option, index) => {
1887
+ const key = optionKey(option, index);
1888
+ const isSelected = submittedIds ? submittedIds.includes(key) : isMulti && selected.includes(key);
1889
+ return /* @__PURE__ */ jsxs8(
1701
1890
  "button",
1702
1891
  {
1703
1892
  type: "button",
1893
+ role: "listitem",
1704
1894
  disabled: isDisabled,
1705
- onClick: () => onPick(option),
1895
+ onClick: () => onPick(key),
1706
1896
  className: cn(
1707
- "aui-artifact-question-option flex items-center gap-2 rounded-lg border px-3 py-2 text-left text-sm transition-colors",
1708
- "border-border/60 hover:border-primary/40 hover:bg-muted/40",
1709
- isSelected && "border-primary/60 bg-primary/5",
1710
- isDisabled && "cursor-not-allowed opacity-60 hover:border-border/60 hover:bg-transparent"
1897
+ isSelected ? studioQuestionOptionSelectedClass : studioQuestionOptionClass,
1898
+ isDisabled && (isSelected ? "cursor-default" : "cursor-not-allowed opacity-50")
1711
1899
  ),
1712
1900
  children: [
1713
- /* @__PURE__ */ jsx10(
1714
- "span",
1715
- {
1716
- className: cn(
1717
- "flex size-4 shrink-0 items-center justify-center rounded-full border",
1718
- isSelected ? "border-primary bg-primary text-primary-foreground" : "border-border"
1719
- ),
1720
- "aria-hidden": true,
1721
- children: isSelected && /* @__PURE__ */ jsx10(CheckIcon, { className: "size-3" })
1722
- }
1723
- ),
1724
- /* @__PURE__ */ jsxs7("div", { className: "aui-artifact-question-option-text flex-1", children: [
1725
- /* @__PURE__ */ jsx10("div", { className: "font-medium text-foreground/90", children: option.label }),
1726
- option.description && /* @__PURE__ */ jsx10("div", { className: "text-xs text-muted-foreground", children: option.description })
1901
+ /* @__PURE__ */ jsx10(OptionRadio, { selected: isSelected }),
1902
+ /* @__PURE__ */ jsxs8("span", { className: "min-w-0 flex-1 text-left", children: [
1903
+ /* @__PURE__ */ jsx10("span", { className: "block font-normal text-foreground", children: option.label }),
1904
+ option.description ? /* @__PURE__ */ jsx10("span", { className: "mt-0.5 block text-xs text-muted-foreground", children: option.description }) : null
1727
1905
  ] })
1728
1906
  ]
1729
1907
  },
1730
- option.id
1908
+ key
1731
1909
  );
1732
1910
  }) }),
1733
- isMulti && !submitted && /* @__PURE__ */ jsx10("div", { className: "mt-2 flex justify-end", children: /* @__PURE__ */ jsx10(
1734
- Button,
1911
+ isMulti && !submittedIds ? /* @__PURE__ */ jsx10("div", { className: "mt-2 flex justify-end", children: /* @__PURE__ */ jsx10(
1912
+ TimbalV2Button,
1735
1913
  {
1736
1914
  type: "button",
1915
+ variant: "primary",
1737
1916
  size: "sm",
1738
1917
  disabled: selected.length === 0,
1739
1918
  onClick: onConfirm,
1740
1919
  children: "Confirm"
1741
1920
  }
1742
- ) }),
1743
- submitted && /* @__PURE__ */ jsxs7("p", { className: "aui-artifact-question-submitted mt-2 text-xs text-muted-foreground", children: [
1744
- "Sent: ",
1745
- submitted
1746
- ] })
1921
+ ) }) : null
1747
1922
  ] }) });
1748
1923
  };
1749
1924
 
@@ -1782,11 +1957,11 @@ var JsonArtifactView = ({
1782
1957
  };
1783
1958
 
1784
1959
  // src/artifacts/table-artifact.tsx
1785
- import { jsx as jsx13, jsxs as jsxs8 } from "react/jsx-runtime";
1960
+ import { jsx as jsx13, jsxs as jsxs9 } from "react/jsx-runtime";
1786
1961
  var TableArtifactView = ({ artifact }) => {
1787
1962
  const rows = artifact.rows ?? [];
1788
1963
  const columns = artifact.columns ?? deriveColumns(rows);
1789
- return /* @__PURE__ */ jsx13(ArtifactCard, { title: artifact.title, kind: "table", children: /* @__PURE__ */ jsx13("div", { className: "aui-artifact-table-wrap overflow-x-auto", children: /* @__PURE__ */ jsxs8("table", { className: "aui-artifact-table w-full border-collapse text-sm", children: [
1964
+ return /* @__PURE__ */ jsx13(ArtifactCard, { title: artifact.title, kind: "table", children: /* @__PURE__ */ jsx13("div", { className: "aui-artifact-table-wrap overflow-x-auto", children: /* @__PURE__ */ jsxs9("table", { className: "aui-artifact-table w-full border-collapse text-sm", children: [
1790
1965
  /* @__PURE__ */ jsx13("thead", { children: /* @__PURE__ */ jsx13("tr", { className: "border-b border-border/40 bg-muted/20", children: columns.map((col) => /* @__PURE__ */ jsx13(
1791
1966
  "th",
1792
1967
  {
@@ -1914,32 +2089,87 @@ function useUiCustomNodeRegistry() {
1914
2089
  }
1915
2090
 
1916
2091
  // src/artifacts/ui/nodes.tsx
1917
- import { useCallback as useCallback2 } from "react";
2092
+ import { useCallback as useCallback3 } from "react";
1918
2093
  import { motion } from "motion/react";
1919
2094
  import { useThreadRuntime as useThreadRuntime2 } from "@assistant-ui/react";
1920
- import { jsx as jsx15, jsxs as jsxs9 } from "react/jsx-runtime";
2095
+
2096
+ // src/ui/button.tsx
2097
+ import { cva } from "class-variance-authority";
2098
+ import { Slot as Slot2 } from "radix-ui";
2099
+ import { jsx as jsx15 } from "react/jsx-runtime";
2100
+ var buttonVariants = cva(
2101
+ "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",
2102
+ {
2103
+ variants: {
2104
+ variant: {
2105
+ default: "bg-primary text-primary-foreground hover:bg-primary/90",
2106
+ destructive: "bg-destructive text-white hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60",
2107
+ 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",
2108
+ secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80",
2109
+ ghost: "hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50",
2110
+ link: "text-primary underline-offset-4 hover:underline"
2111
+ },
2112
+ size: {
2113
+ default: "h-9 px-4 py-2 has-[>svg]:px-3",
2114
+ xs: "h-6 gap-1 rounded-md px-2 text-xs has-[>svg]:px-1.5 [&_svg:not([class*='size-'])]:size-3",
2115
+ sm: "h-8 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5",
2116
+ lg: "h-10 rounded-md px-6 has-[>svg]:px-4",
2117
+ icon: "size-9",
2118
+ "icon-xs": "size-6 rounded-md [&_svg:not([class*='size-'])]:size-3",
2119
+ "icon-sm": "size-8",
2120
+ "icon-lg": "size-10"
2121
+ }
2122
+ },
2123
+ defaultVariants: {
2124
+ variant: "default",
2125
+ size: "default"
2126
+ }
2127
+ }
2128
+ );
2129
+ function Button({
2130
+ className,
2131
+ variant = "default",
2132
+ size = "default",
2133
+ asChild = false,
2134
+ ...props
2135
+ }) {
2136
+ const Comp = asChild ? Slot2.Root : "button";
2137
+ return /* @__PURE__ */ jsx15(
2138
+ Comp,
2139
+ {
2140
+ "data-slot": "button",
2141
+ "data-variant": variant,
2142
+ "data-size": size,
2143
+ className: cn(buttonVariants({ variant, size, className })),
2144
+ ...props
2145
+ }
2146
+ );
2147
+ }
2148
+
2149
+ // src/artifacts/ui/nodes.tsx
2150
+ import { jsx as jsx16, jsxs as jsxs10 } from "react/jsx-runtime";
1921
2151
  var UiNodeView = ({ node }) => {
1922
2152
  switch (node.kind) {
1923
2153
  case "box":
1924
- return /* @__PURE__ */ jsx15(BoxNode, { node });
2154
+ return /* @__PURE__ */ jsx16(BoxNode, { node });
1925
2155
  case "text":
1926
- return /* @__PURE__ */ jsx15(TextNode, { node });
2156
+ return /* @__PURE__ */ jsx16(TextNode, { node });
1927
2157
  case "heading":
1928
- return /* @__PURE__ */ jsx15(HeadingNode, { node });
2158
+ return /* @__PURE__ */ jsx16(HeadingNode, { node });
1929
2159
  case "badge":
1930
- return /* @__PURE__ */ jsx15(BadgeNode, { node });
2160
+ return /* @__PURE__ */ jsx16(BadgeNode, { node });
1931
2161
  case "button":
1932
- return /* @__PURE__ */ jsx15(ButtonNode, { node });
2162
+ return /* @__PURE__ */ jsx16(ButtonNode, { node });
1933
2163
  case "toggle":
1934
- return /* @__PURE__ */ jsx15(ToggleNode, { node });
2164
+ return /* @__PURE__ */ jsx16(ToggleNode, { node });
1935
2165
  case "slider":
1936
- return /* @__PURE__ */ jsx15(SliderNode, { node });
2166
+ return /* @__PURE__ */ jsx16(SliderNode, { node });
1937
2167
  case "tooltip":
1938
- return /* @__PURE__ */ jsx15(TooltipNode, { node });
2168
+ return /* @__PURE__ */ jsx16(TooltipNode, { node });
1939
2169
  case "draggable":
1940
- return /* @__PURE__ */ jsx15(DraggableNode, { node });
2170
+ return /* @__PURE__ */ jsx16(DraggableNode, { node });
1941
2171
  case "custom":
1942
- return /* @__PURE__ */ jsx15(CustomNode, { node });
2172
+ return /* @__PURE__ */ jsx16(CustomNode, { node });
1943
2173
  default:
1944
2174
  return null;
1945
2175
  }
@@ -1949,7 +2179,7 @@ function useActionRunner() {
1949
2179
  const dispatch = useUiDispatch();
1950
2180
  const runtime = useThreadRuntime2();
1951
2181
  const emit = useUiEventEmitter();
1952
- return useCallback2(
2182
+ return useCallback3(
1953
2183
  (actions) => {
1954
2184
  if (!actions) return;
1955
2185
  const list = Array.isArray(actions) ? actions : [actions];
@@ -1999,7 +2229,7 @@ var JUSTIFY_CLS = {
1999
2229
  };
2000
2230
  var BoxNode = ({ node }) => {
2001
2231
  const dir = node.direction ?? "col";
2002
- return /* @__PURE__ */ jsx15(
2232
+ return /* @__PURE__ */ jsx16(
2003
2233
  "div",
2004
2234
  {
2005
2235
  className: cn(
@@ -2014,7 +2244,7 @@ var BoxNode = ({ node }) => {
2014
2244
  gap: node.gap !== void 0 ? `${node.gap * 0.25}rem` : void 0,
2015
2245
  padding: node.padding !== void 0 ? `${node.padding * 0.25}rem` : void 0
2016
2246
  },
2017
- children: node.children?.map((child, i) => /* @__PURE__ */ jsx15(UiNodeView, { node: child }, child.id ?? i))
2247
+ children: node.children?.map((child, i) => /* @__PURE__ */ jsx16(UiNodeView, { node: child }, child.id ?? i))
2018
2248
  }
2019
2249
  );
2020
2250
  };
@@ -2033,7 +2263,7 @@ var TEXT_WEIGHT = {
2033
2263
  var TextNode = ({ node }) => {
2034
2264
  const state = useUiState();
2035
2265
  const value = resolveBindable(node.value, state);
2036
- return /* @__PURE__ */ jsx15(
2266
+ return /* @__PURE__ */ jsx16(
2037
2267
  "span",
2038
2268
  {
2039
2269
  className: cn(
@@ -2064,13 +2294,13 @@ var HeadingNode = ({ node }) => {
2064
2294
  );
2065
2295
  switch (level) {
2066
2296
  case 1:
2067
- return /* @__PURE__ */ jsx15("h1", { className: cls, children: value });
2297
+ return /* @__PURE__ */ jsx16("h1", { className: cls, children: value });
2068
2298
  case 2:
2069
- return /* @__PURE__ */ jsx15("h2", { className: cls, children: value });
2299
+ return /* @__PURE__ */ jsx16("h2", { className: cls, children: value });
2070
2300
  case 3:
2071
- return /* @__PURE__ */ jsx15("h3", { className: cls, children: value });
2301
+ return /* @__PURE__ */ jsx16("h3", { className: cls, children: value });
2072
2302
  case 4:
2073
- return /* @__PURE__ */ jsx15("h4", { className: cls, children: value });
2303
+ return /* @__PURE__ */ jsx16("h4", { className: cls, children: value });
2074
2304
  }
2075
2305
  };
2076
2306
  var BADGE_TONE = {
@@ -2083,7 +2313,7 @@ var BADGE_TONE = {
2083
2313
  var BadgeNode = ({ node }) => {
2084
2314
  const state = useUiState();
2085
2315
  const value = String(resolveBindable(node.value, state) ?? "");
2086
- return /* @__PURE__ */ jsx15(
2316
+ return /* @__PURE__ */ jsx16(
2087
2317
  "span",
2088
2318
  {
2089
2319
  className: cn(
@@ -2100,7 +2330,7 @@ var ButtonNode = ({ node }) => {
2100
2330
  const run = useActionRunner();
2101
2331
  const label = String(resolveBindable(node.label, state) ?? "");
2102
2332
  const disabled = node.disabled !== void 0 ? Boolean(resolveBindable(node.disabled, state)) : false;
2103
- return /* @__PURE__ */ jsx15(
2333
+ return /* @__PURE__ */ jsx16(
2104
2334
  Button,
2105
2335
  {
2106
2336
  variant: node.variant ?? "default",
@@ -2122,7 +2352,7 @@ var ToggleNode = ({ node }) => {
2122
2352
  dispatch({ type: "toggle", path: node.binding });
2123
2353
  run(node.onChange);
2124
2354
  };
2125
- return /* @__PURE__ */ jsxs9(
2355
+ return /* @__PURE__ */ jsxs10(
2126
2356
  "label",
2127
2357
  {
2128
2358
  className: cn(
@@ -2130,7 +2360,7 @@ var ToggleNode = ({ node }) => {
2130
2360
  node.className
2131
2361
  ),
2132
2362
  children: [
2133
- /* @__PURE__ */ jsx15(
2363
+ /* @__PURE__ */ jsx16(
2134
2364
  "button",
2135
2365
  {
2136
2366
  type: "button",
@@ -2141,7 +2371,7 @@ var ToggleNode = ({ node }) => {
2141
2371
  "relative inline-flex h-5 w-9 shrink-0 items-center rounded-full border transition-colors",
2142
2372
  value ? "border-primary bg-primary" : "border-border bg-muted hover:bg-muted/80"
2143
2373
  ),
2144
- children: /* @__PURE__ */ jsx15(
2374
+ children: /* @__PURE__ */ jsx16(
2145
2375
  "span",
2146
2376
  {
2147
2377
  className: cn(
@@ -2153,7 +2383,7 @@ var ToggleNode = ({ node }) => {
2153
2383
  )
2154
2384
  }
2155
2385
  ),
2156
- label && /* @__PURE__ */ jsx15("span", { className: "text-foreground/85", children: label })
2386
+ label && /* @__PURE__ */ jsx16("span", { className: "text-foreground/85", children: label })
2157
2387
  ]
2158
2388
  }
2159
2389
  );
@@ -2173,12 +2403,12 @@ var SliderNode = ({ node }) => {
2173
2403
  const next = Number(e.target.value);
2174
2404
  dispatch({ type: "set", path: node.binding, value: next });
2175
2405
  };
2176
- return /* @__PURE__ */ jsxs9("div", { className: cn("aui-ui-slider flex flex-col gap-1", node.className), children: [
2177
- (label || showValue) && /* @__PURE__ */ jsxs9("div", { className: "flex items-center justify-between text-xs text-muted-foreground", children: [
2178
- label && /* @__PURE__ */ jsx15("span", { children: label }),
2179
- showValue && /* @__PURE__ */ jsx15("span", { className: "font-mono", children: value })
2406
+ return /* @__PURE__ */ jsxs10("div", { className: cn("aui-ui-slider flex flex-col gap-1", node.className), children: [
2407
+ (label || showValue) && /* @__PURE__ */ jsxs10("div", { className: "flex items-center justify-between text-xs text-muted-foreground", children: [
2408
+ label && /* @__PURE__ */ jsx16("span", { children: label }),
2409
+ showValue && /* @__PURE__ */ jsx16("span", { className: "font-mono", children: value })
2180
2410
  ] }),
2181
- /* @__PURE__ */ jsx15(
2411
+ /* @__PURE__ */ jsx16(
2182
2412
  "input",
2183
2413
  {
2184
2414
  type: "range",
@@ -2200,9 +2430,9 @@ var SliderNode = ({ node }) => {
2200
2430
  var TooltipNode = ({ node }) => {
2201
2431
  const state = useUiState();
2202
2432
  const content = String(resolveBindable(node.content, state) ?? "");
2203
- return /* @__PURE__ */ jsx15(TooltipProvider, { children: /* @__PURE__ */ jsxs9(Tooltip, { children: [
2204
- /* @__PURE__ */ jsx15(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx15("span", { className: cn("aui-ui-tooltip-trigger inline-flex", node.className), children: /* @__PURE__ */ jsx15(UiNodeView, { node: node.child }) }) }),
2205
- /* @__PURE__ */ jsx15(TooltipContent, { side: node.side ?? "top", children: content })
2433
+ return /* @__PURE__ */ jsx16(TooltipProvider, { children: /* @__PURE__ */ jsxs10(Tooltip, { children: [
2434
+ /* @__PURE__ */ jsx16(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx16("span", { className: cn("aui-ui-tooltip-trigger inline-flex", node.className), children: /* @__PURE__ */ jsx16(UiNodeView, { node: node.child }) }) }),
2435
+ /* @__PURE__ */ jsx16(TooltipContent, { side: node.side ?? "top", children: content })
2206
2436
  ] }) });
2207
2437
  };
2208
2438
  var DraggableNode = ({ node }) => {
@@ -2210,7 +2440,7 @@ var DraggableNode = ({ node }) => {
2210
2440
  const snapBack = node.snapBack ?? true;
2211
2441
  const axis = node.axis ?? "both";
2212
2442
  const dragProp = axis === "both" ? true : axis;
2213
- return /* @__PURE__ */ jsx15(
2443
+ return /* @__PURE__ */ jsx16(
2214
2444
  motion.div,
2215
2445
  {
2216
2446
  drag: dragProp,
@@ -2222,7 +2452,7 @@ var DraggableNode = ({ node }) => {
2222
2452
  "aui-ui-draggable inline-block cursor-grab touch-none",
2223
2453
  node.className
2224
2454
  ),
2225
- children: /* @__PURE__ */ jsx15(UiNodeView, { node: node.child })
2455
+ children: /* @__PURE__ */ jsx16(UiNodeView, { node: node.child })
2226
2456
  }
2227
2457
  );
2228
2458
  };
@@ -2232,8 +2462,8 @@ var CustomNode = ({ node }) => {
2232
2462
  const Renderer = registry[node.name];
2233
2463
  if (!Renderer) return null;
2234
2464
  const resolvedProps = resolveProps(node.props ?? {}, state);
2235
- const children = node.children?.map((child, i) => /* @__PURE__ */ jsx15(UiNodeView, { node: child }, child.id ?? i));
2236
- return /* @__PURE__ */ jsx15(Renderer, { props: resolvedProps, children });
2465
+ const children = node.children?.map((child, i) => /* @__PURE__ */ jsx16(UiNodeView, { node: child }, child.id ?? i));
2466
+ return /* @__PURE__ */ jsx16(Renderer, { props: resolvedProps, children });
2237
2467
  };
2238
2468
  function resolveProps(props, state) {
2239
2469
  const out = {};
@@ -2244,17 +2474,17 @@ function resolveProps(props, state) {
2244
2474
  }
2245
2475
 
2246
2476
  // src/artifacts/ui/ui-artifact.tsx
2247
- import { jsx as jsx16 } from "react/jsx-runtime";
2477
+ import { jsx as jsx17 } from "react/jsx-runtime";
2248
2478
  var UiArtifactView = ({ artifact }) => {
2249
2479
  const [state, dispatch] = useReducer(
2250
2480
  uiStateReducer,
2251
2481
  artifact.initialState ?? {}
2252
2482
  );
2253
- return /* @__PURE__ */ jsx16(ArtifactCard, { title: artifact.title, kind: "ui", children: /* @__PURE__ */ jsx16(UiStateProvider, { state, dispatch, children: /* @__PURE__ */ jsx16("div", { className: "aui-ui-root p-3", children: /* @__PURE__ */ jsx16(UiNodeView, { node: artifact.root }) }) }) });
2483
+ return /* @__PURE__ */ jsx17(ArtifactCard, { title: artifact.title, kind: "ui", children: /* @__PURE__ */ jsx17(UiStateProvider, { state, dispatch, children: /* @__PURE__ */ jsx17("div", { className: "aui-ui-root p-3", children: /* @__PURE__ */ jsx17(UiNodeView, { node: artifact.root }) }) }) });
2254
2484
  };
2255
2485
 
2256
2486
  // src/artifacts/registry.tsx
2257
- import { jsx as jsx17 } from "react/jsx-runtime";
2487
+ import { jsx as jsx18 } from "react/jsx-runtime";
2258
2488
  var defaultArtifactRenderers = {
2259
2489
  chart: ChartArtifactView,
2260
2490
  question: QuestionArtifactView,
@@ -2272,7 +2502,7 @@ var ArtifactRegistryProvider = ({ renderers, override, children }) => {
2272
2502
  if (override) return renderers;
2273
2503
  return { ...defaultArtifactRenderers, ...renderers };
2274
2504
  }, [renderers, override]);
2275
- return /* @__PURE__ */ jsx17(ArtifactRegistryContext.Provider, { value: merged, children });
2505
+ return /* @__PURE__ */ jsx18(ArtifactRegistryContext.Provider, { value: merged, children });
2276
2506
  };
2277
2507
  function useArtifactRegistry() {
2278
2508
  return useContext3(ArtifactRegistryContext);
@@ -2281,7 +2511,7 @@ var ArtifactView = ({ artifact }) => {
2281
2511
  const registry = useArtifactRegistry();
2282
2512
  const Renderer = registry[artifact.type] ?? registry.json;
2283
2513
  if (!Renderer) return null;
2284
- return /* @__PURE__ */ jsx17(Renderer, { artifact });
2514
+ return /* @__PURE__ */ jsx18(Renderer, { artifact });
2285
2515
  };
2286
2516
 
2287
2517
  // src/artifacts/parse.ts
@@ -2397,7 +2627,7 @@ import langC from "shiki/langs/c.mjs";
2397
2627
  import langCpp from "shiki/langs/cpp.mjs";
2398
2628
  import themeVitesseDark from "shiki/themes/vitesse-dark.mjs";
2399
2629
  import themeVitesseLight from "shiki/themes/vitesse-light.mjs";
2400
- import { jsx as jsx18 } from "react/jsx-runtime";
2630
+ import { jsx as jsx19 } from "react/jsx-runtime";
2401
2631
  var SHIKI_THEME_DARK = "vitesse-dark";
2402
2632
  var SHIKI_THEME_LIGHT = "vitesse-light";
2403
2633
  var highlighterPromise = null;
@@ -2466,13 +2696,13 @@ var ShikiSyntaxHighlighter = ({
2466
2696
  try {
2467
2697
  const parsed = JSON.parse(code);
2468
2698
  if (isArtifact(parsed)) {
2469
- return /* @__PURE__ */ jsx18(ArtifactView, { artifact: parsed });
2699
+ return /* @__PURE__ */ jsx19(ArtifactView, { artifact: parsed });
2470
2700
  }
2471
2701
  } catch {
2472
2702
  }
2473
2703
  }
2474
2704
  if (html) {
2475
- return /* @__PURE__ */ jsx18(
2705
+ return /* @__PURE__ */ jsx19(
2476
2706
  "div",
2477
2707
  {
2478
2708
  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",
@@ -2480,14 +2710,14 @@ var ShikiSyntaxHighlighter = ({
2480
2710
  }
2481
2711
  );
2482
2712
  }
2483
- return /* @__PURE__ */ jsx18(Pre, { children: /* @__PURE__ */ jsx18(Code2, { children: code }) });
2713
+ return /* @__PURE__ */ jsx19(Pre, { children: /* @__PURE__ */ jsx19(Code2, { children: code }) });
2484
2714
  };
2485
2715
  var syntax_highlighter_default = ShikiSyntaxHighlighter;
2486
2716
 
2487
2717
  // src/components/markdown-text.tsx
2488
- import { jsx as jsx19, jsxs as jsxs10 } from "react/jsx-runtime";
2718
+ import { jsx as jsx20, jsxs as jsxs11 } from "react/jsx-runtime";
2489
2719
  var MarkdownTextImpl = () => {
2490
- return /* @__PURE__ */ jsx19(
2720
+ return /* @__PURE__ */ jsx20(
2491
2721
  MarkdownTextPrimitive,
2492
2722
  {
2493
2723
  remarkPlugins: [remarkGfm, remarkMath],
@@ -2508,20 +2738,20 @@ var CodeHeader = ({ language, code }) => {
2508
2738
  if (!code || isCopied) return;
2509
2739
  copyToClipboard(code);
2510
2740
  };
2511
- return /* @__PURE__ */ jsxs10("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: [
2512
- /* @__PURE__ */ jsxs10("span", { className: "flex items-center gap-2 text-xs font-semibold tracking-wide text-muted-foreground/80 uppercase", children: [
2513
- /* @__PURE__ */ jsx19("span", { className: "inline-block h-2 w-2 rounded-full bg-primary/40" }),
2741
+ return /* @__PURE__ */ jsxs11("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: [
2742
+ /* @__PURE__ */ jsxs11("span", { className: "flex items-center gap-2 text-xs font-semibold tracking-wide text-muted-foreground/80 uppercase", children: [
2743
+ /* @__PURE__ */ jsx20("span", { className: "inline-block h-2 w-2 rounded-full bg-primary/40" }),
2514
2744
  language
2515
2745
  ] }),
2516
- /* @__PURE__ */ jsxs10(
2746
+ /* @__PURE__ */ jsxs11(
2517
2747
  TooltipIconButton,
2518
2748
  {
2519
2749
  tooltip: isCopied ? "Copied!" : "Copy",
2520
2750
  onClick: onCopy,
2521
2751
  className: "transition-colors hover:text-foreground",
2522
2752
  children: [
2523
- !isCopied && /* @__PURE__ */ jsx19(CopyIcon, { className: "h-3.5 w-3.5" }),
2524
- isCopied && /* @__PURE__ */ jsx19(CheckIcon2, { className: "h-3.5 w-3.5 text-emerald-500" })
2753
+ !isCopied && /* @__PURE__ */ jsx20(CopyIcon, { className: "h-3.5 w-3.5" }),
2754
+ isCopied && /* @__PURE__ */ jsx20(CheckIcon2, { className: "h-3.5 w-3.5 text-emerald-500" })
2525
2755
  ]
2526
2756
  }
2527
2757
  )
@@ -2541,7 +2771,7 @@ var useCopyToClipboard = ({
2541
2771
  return { isCopied, copyToClipboard };
2542
2772
  };
2543
2773
  var defaultComponents = memoizeMarkdownComponents({
2544
- h1: ({ className, ...props }) => /* @__PURE__ */ jsx19(
2774
+ h1: ({ className, ...props }) => /* @__PURE__ */ jsx20(
2545
2775
  "h1",
2546
2776
  {
2547
2777
  className: cn(
@@ -2551,7 +2781,7 @@ var defaultComponents = memoizeMarkdownComponents({
2551
2781
  ...props
2552
2782
  }
2553
2783
  ),
2554
- h2: ({ className, ...props }) => /* @__PURE__ */ jsx19(
2784
+ h2: ({ className, ...props }) => /* @__PURE__ */ jsx20(
2555
2785
  "h2",
2556
2786
  {
2557
2787
  className: cn(
@@ -2561,7 +2791,7 @@ var defaultComponents = memoizeMarkdownComponents({
2561
2791
  ...props
2562
2792
  }
2563
2793
  ),
2564
- h3: ({ className, ...props }) => /* @__PURE__ */ jsx19(
2794
+ h3: ({ className, ...props }) => /* @__PURE__ */ jsx20(
2565
2795
  "h3",
2566
2796
  {
2567
2797
  className: cn(
@@ -2571,7 +2801,7 @@ var defaultComponents = memoizeMarkdownComponents({
2571
2801
  ...props
2572
2802
  }
2573
2803
  ),
2574
- h4: ({ className, ...props }) => /* @__PURE__ */ jsx19(
2804
+ h4: ({ className, ...props }) => /* @__PURE__ */ jsx20(
2575
2805
  "h4",
2576
2806
  {
2577
2807
  className: cn(
@@ -2581,7 +2811,7 @@ var defaultComponents = memoizeMarkdownComponents({
2581
2811
  ...props
2582
2812
  }
2583
2813
  ),
2584
- h5: ({ className, ...props }) => /* @__PURE__ */ jsx19(
2814
+ h5: ({ className, ...props }) => /* @__PURE__ */ jsx20(
2585
2815
  "h5",
2586
2816
  {
2587
2817
  className: cn(
@@ -2591,7 +2821,7 @@ var defaultComponents = memoizeMarkdownComponents({
2591
2821
  ...props
2592
2822
  }
2593
2823
  ),
2594
- h6: ({ className, ...props }) => /* @__PURE__ */ jsx19(
2824
+ h6: ({ className, ...props }) => /* @__PURE__ */ jsx20(
2595
2825
  "h6",
2596
2826
  {
2597
2827
  className: cn(
@@ -2601,7 +2831,7 @@ var defaultComponents = memoizeMarkdownComponents({
2601
2831
  ...props
2602
2832
  }
2603
2833
  ),
2604
- p: ({ className, ...props }) => /* @__PURE__ */ jsx19(
2834
+ p: ({ className, ...props }) => /* @__PURE__ */ jsx20(
2605
2835
  "p",
2606
2836
  {
2607
2837
  className: cn(
@@ -2611,7 +2841,7 @@ var defaultComponents = memoizeMarkdownComponents({
2611
2841
  ...props
2612
2842
  }
2613
2843
  ),
2614
- a: ({ className, ...props }) => /* @__PURE__ */ jsx19(
2844
+ a: ({ className, ...props }) => /* @__PURE__ */ jsx20(
2615
2845
  "a",
2616
2846
  {
2617
2847
  className: cn(
@@ -2623,7 +2853,7 @@ var defaultComponents = memoizeMarkdownComponents({
2623
2853
  ...props
2624
2854
  }
2625
2855
  ),
2626
- blockquote: ({ className, ...props }) => /* @__PURE__ */ jsx19(
2856
+ blockquote: ({ className, ...props }) => /* @__PURE__ */ jsx20(
2627
2857
  "blockquote",
2628
2858
  {
2629
2859
  className: cn(
@@ -2633,7 +2863,7 @@ var defaultComponents = memoizeMarkdownComponents({
2633
2863
  ...props
2634
2864
  }
2635
2865
  ),
2636
- ul: ({ className, ...props }) => /* @__PURE__ */ jsx19(
2866
+ ul: ({ className, ...props }) => /* @__PURE__ */ jsx20(
2637
2867
  "ul",
2638
2868
  {
2639
2869
  className: cn(
@@ -2643,7 +2873,7 @@ var defaultComponents = memoizeMarkdownComponents({
2643
2873
  ...props
2644
2874
  }
2645
2875
  ),
2646
- ol: ({ className, ...props }) => /* @__PURE__ */ jsx19(
2876
+ ol: ({ className, ...props }) => /* @__PURE__ */ jsx20(
2647
2877
  "ol",
2648
2878
  {
2649
2879
  className: cn(
@@ -2653,7 +2883,7 @@ var defaultComponents = memoizeMarkdownComponents({
2653
2883
  ...props
2654
2884
  }
2655
2885
  ),
2656
- hr: ({ className, ...props }) => /* @__PURE__ */ jsx19(
2886
+ hr: ({ className, ...props }) => /* @__PURE__ */ jsx20(
2657
2887
  "hr",
2658
2888
  {
2659
2889
  className: cn(
@@ -2663,14 +2893,14 @@ var defaultComponents = memoizeMarkdownComponents({
2663
2893
  ...props
2664
2894
  }
2665
2895
  ),
2666
- table: ({ className, ...props }) => /* @__PURE__ */ jsx19("div", { className: "my-4 w-full overflow-x-auto rounded-lg border border-border/50", children: /* @__PURE__ */ jsx19(
2896
+ table: ({ className, ...props }) => /* @__PURE__ */ jsx20("div", { className: "my-4 w-full overflow-x-auto rounded-lg border border-border/50", children: /* @__PURE__ */ jsx20(
2667
2897
  "table",
2668
2898
  {
2669
2899
  className: cn("aui-md-table w-full border-collapse text-sm", className),
2670
2900
  ...props
2671
2901
  }
2672
2902
  ) }),
2673
- th: ({ className, ...props }) => /* @__PURE__ */ jsx19(
2903
+ th: ({ className, ...props }) => /* @__PURE__ */ jsx20(
2674
2904
  "th",
2675
2905
  {
2676
2906
  className: cn(
@@ -2680,7 +2910,7 @@ var defaultComponents = memoizeMarkdownComponents({
2680
2910
  ...props
2681
2911
  }
2682
2912
  ),
2683
- td: ({ className, ...props }) => /* @__PURE__ */ jsx19(
2913
+ td: ({ className, ...props }) => /* @__PURE__ */ jsx20(
2684
2914
  "td",
2685
2915
  {
2686
2916
  className: cn(
@@ -2690,7 +2920,7 @@ var defaultComponents = memoizeMarkdownComponents({
2690
2920
  ...props
2691
2921
  }
2692
2922
  ),
2693
- tr: ({ className, ...props }) => /* @__PURE__ */ jsx19(
2923
+ tr: ({ className, ...props }) => /* @__PURE__ */ jsx20(
2694
2924
  "tr",
2695
2925
  {
2696
2926
  className: cn(
@@ -2700,8 +2930,8 @@ var defaultComponents = memoizeMarkdownComponents({
2700
2930
  ...props
2701
2931
  }
2702
2932
  ),
2703
- li: ({ className, ...props }) => /* @__PURE__ */ jsx19("li", { className: cn("aui-md-li leading-[1.7]", className), ...props }),
2704
- sup: ({ className, ...props }) => /* @__PURE__ */ jsx19(
2933
+ li: ({ className, ...props }) => /* @__PURE__ */ jsx20("li", { className: cn("aui-md-li leading-[1.7]", className), ...props }),
2934
+ sup: ({ className, ...props }) => /* @__PURE__ */ jsx20(
2705
2935
  "sup",
2706
2936
  {
2707
2937
  className: cn(
@@ -2711,7 +2941,7 @@ var defaultComponents = memoizeMarkdownComponents({
2711
2941
  ...props
2712
2942
  }
2713
2943
  ),
2714
- pre: ({ className, ...props }) => /* @__PURE__ */ jsx19(
2944
+ pre: ({ className, ...props }) => /* @__PURE__ */ jsx20(
2715
2945
  "pre",
2716
2946
  {
2717
2947
  className: cn(
@@ -2723,7 +2953,7 @@ var defaultComponents = memoizeMarkdownComponents({
2723
2953
  ),
2724
2954
  code: function Code({ className, ...props }) {
2725
2955
  const isCodeBlock = useIsMarkdownCodeBlock();
2726
- return /* @__PURE__ */ jsx19(
2956
+ return /* @__PURE__ */ jsx20(
2727
2957
  "code",
2728
2958
  {
2729
2959
  className: cn(
@@ -2734,14 +2964,17 @@ var defaultComponents = memoizeMarkdownComponents({
2734
2964
  }
2735
2965
  );
2736
2966
  },
2737
- strong: ({ className, ...props }) => /* @__PURE__ */ jsx19("strong", { className: cn("font-semibold text-foreground", className), ...props }),
2738
- em: ({ className, ...props }) => /* @__PURE__ */ jsx19("em", { className: cn("italic", className), ...props }),
2967
+ strong: ({ className, ...props }) => /* @__PURE__ */ jsx20("strong", { className: cn("font-semibold text-foreground", className), ...props }),
2968
+ em: ({ className, ...props }) => /* @__PURE__ */ jsx20("em", { className: cn("italic", className), ...props }),
2739
2969
  CodeHeader
2740
2970
  });
2741
2971
 
2742
2972
  // src/components/tool-fallback.tsx
2743
- import { memo as memo3, useState as useState6 } from "react";
2744
- import { ChevronDownIcon, WrenchIcon } from "lucide-react";
2973
+ import { memo as memo3, useMemo as useMemo5, useState as useState6 } from "react";
2974
+ import { ChevronRightIcon } from "lucide-react";
2975
+ import {
2976
+ useAuiState as useAuiState2
2977
+ } from "@assistant-ui/react";
2745
2978
 
2746
2979
  // src/ui/shimmer.tsx
2747
2980
  import { motion as motion2 } from "motion/react";
@@ -2749,7 +2982,7 @@ import {
2749
2982
  memo as memo2,
2750
2983
  useMemo as useMemo4
2751
2984
  } from "react";
2752
- import { jsx as jsx20 } from "react/jsx-runtime";
2985
+ import { jsx as jsx21 } from "react/jsx-runtime";
2753
2986
  var ShimmerComponent = ({
2754
2987
  children,
2755
2988
  as: Component = "p",
@@ -2764,7 +2997,7 @@ var ShimmerComponent = ({
2764
2997
  () => (children?.length ?? 0) * spread,
2765
2998
  [children, spread]
2766
2999
  );
2767
- return /* @__PURE__ */ jsx20(
3000
+ return /* @__PURE__ */ jsx21(
2768
3001
  MotionComponent,
2769
3002
  {
2770
3003
  animate: { backgroundPosition: "0% center" },
@@ -2789,78 +3022,130 @@ var ShimmerComponent = ({
2789
3022
  };
2790
3023
  var Shimmer = memo2(ShimmerComponent);
2791
3024
 
2792
- // src/components/tool-fallback.tsx
2793
- import { jsx as jsx21, jsxs as jsxs11 } from "react/jsx-runtime";
2794
- var ToolFallbackImpl = ({
2795
- toolName,
2796
- argsText,
2797
- result,
2798
- status
2799
- }) => {
2800
- const isRunning = status?.type === "running";
2801
- const isError = status?.type === "incomplete" && status.reason !== "cancelled";
2802
- if (isRunning) {
2803
- return /* @__PURE__ */ jsxs11("div", { className: "aui-tool-fallback-running flex items-center gap-2 py-1 text-sm text-muted-foreground", children: [
2804
- /* @__PURE__ */ jsx21(WrenchIcon, { className: "size-4" }),
2805
- /* @__PURE__ */ jsx21(Shimmer, { as: "span", duration: 1.8, spread: 2.5, children: `Using tool: ${toolName}` })
2806
- ] });
3025
+ // src/components/motion.tsx
3026
+ import { AnimatePresence, motion as motion3, useReducedMotion } from "motion/react";
3027
+ import { jsx as jsx22 } from "react/jsx-runtime";
3028
+ var luxuryEase = [0.16, 1, 0.3, 1];
3029
+ var TOOL_ENTER_MS = 0.78;
3030
+ var TOOL_EXIT_MS = 0.28;
3031
+ function toolPresenceTransition(reduced) {
3032
+ return {
3033
+ enter: {
3034
+ duration: reduced ? 0.35 : TOOL_ENTER_MS,
3035
+ ease: luxuryEase
3036
+ },
3037
+ exit: {
3038
+ duration: reduced ? 0.2 : TOOL_EXIT_MS,
3039
+ ease: [0.4, 0, 1, 1]
3040
+ }
3041
+ };
3042
+ }
3043
+ function toolMotionState(reduced, entering, variant) {
3044
+ if (reduced) {
3045
+ return entering ? { opacity: 0, y: variant === "executing" ? 8 : 10 } : { opacity: 1, y: 0 };
2807
3046
  }
2808
- return /* @__PURE__ */ jsx21(
2809
- ToolPanel,
3047
+ if (variant === "executing") {
3048
+ return entering ? { opacity: 0, y: 12 } : { opacity: 1, y: 0 };
3049
+ }
3050
+ return entering ? { opacity: 0, y: 14, filter: "blur(10px)" } : { opacity: 1, y: 0, filter: "blur(0px)" };
3051
+ }
3052
+ function ToolMotion({ children, className, motionKey }) {
3053
+ const reduced = useReducedMotion() ?? false;
3054
+ const { enter, exit } = toolPresenceTransition(reduced);
3055
+ return /* @__PURE__ */ jsx22(
3056
+ motion3.div,
2810
3057
  {
2811
- toolName,
2812
- argsText,
2813
- result,
2814
- isError
2815
- }
3058
+ className: cn("aui-tool-motion w-full min-w-0", className),
3059
+ initial: toolMotionState(reduced, true, "settled"),
3060
+ animate: toolMotionState(reduced, false, "settled"),
3061
+ exit: reduced ? { opacity: 0, y: 6, transition: exit } : { opacity: 0, y: 8, filter: "blur(6px)", transition: exit },
3062
+ transition: enter,
3063
+ style: { willChange: "opacity, transform, filter" },
3064
+ children
3065
+ },
3066
+ motionKey
2816
3067
  );
2817
- };
2818
- var ToolPanel = ({ toolName, argsText, result, isError }) => {
2819
- const [open, setOpen] = useState6(false);
2820
- return /* @__PURE__ */ jsxs11(
3068
+ }
3069
+ function ToolPresence({
3070
+ presenceKey,
3071
+ children,
3072
+ className,
3073
+ variant = "settled"
3074
+ }) {
3075
+ const reduced = useReducedMotion() ?? false;
3076
+ const { enter, exit } = toolPresenceTransition(reduced);
3077
+ const enterTransition = variant === "executing" ? { duration: reduced ? 0.3 : 0.52, ease: luxuryEase } : enter;
3078
+ return /* @__PURE__ */ jsx22(AnimatePresence, { mode: "wait", initial: true, children: /* @__PURE__ */ jsx22(
3079
+ motion3.div,
3080
+ {
3081
+ className: cn("aui-tool-presence w-full min-w-0", className),
3082
+ initial: toolMotionState(reduced, true, variant),
3083
+ animate: toolMotionState(reduced, false, variant),
3084
+ exit: reduced ? { opacity: 0, y: 6, transition: exit } : { opacity: 0, y: 8, filter: "blur(6px)", transition: exit },
3085
+ transition: enterTransition,
3086
+ style: {
3087
+ willChange: variant === "executing" ? "opacity, transform" : "opacity, transform, filter"
3088
+ },
3089
+ children
3090
+ },
3091
+ presenceKey
3092
+ ) });
3093
+ }
3094
+ function ToolBodyPresence({
3095
+ open,
3096
+ children,
3097
+ className
3098
+ }) {
3099
+ const reduced = useReducedMotion() ?? false;
3100
+ return /* @__PURE__ */ jsx22(
2821
3101
  "div",
2822
3102
  {
2823
3103
  className: cn(
2824
- "aui-tool-fallback-root my-2 overflow-hidden rounded-lg border border-border/60 bg-muted/30 text-sm",
2825
- isError && "border-destructive/50 bg-destructive/5"
3104
+ "aui-tool-body grid min-h-0 transition-[grid-template-rows]",
3105
+ 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)]"
2826
3106
  ),
2827
- children: [
2828
- /* @__PURE__ */ jsxs11(
2829
- "button",
2830
- {
2831
- type: "button",
2832
- onClick: () => setOpen((v) => !v),
2833
- 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",
2834
- "aria-expanded": open,
2835
- children: [
2836
- /* @__PURE__ */ jsx21(WrenchIcon, { className: "size-3.5" }),
2837
- /* @__PURE__ */ jsx21("span", { className: "aui-tool-fallback-name flex-1 truncate font-mono text-xs font-medium text-foreground/80", children: toolName }),
2838
- isError && /* @__PURE__ */ jsx21("span", { className: "aui-tool-fallback-status text-xs font-medium text-destructive", children: "error" }),
2839
- /* @__PURE__ */ jsx21(
2840
- ChevronDownIcon,
2841
- {
2842
- className: cn(
2843
- "size-3.5 shrink-0 transition-transform",
2844
- open && "rotate-180"
2845
- )
2846
- }
2847
- )
2848
- ]
2849
- }
2850
- ),
2851
- open && /* @__PURE__ */ jsxs11("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: [
2852
- argsText && argsText !== "{}" && /* @__PURE__ */ jsx21(Section, { label: "Input", value: argsText }),
2853
- result !== void 0 && result !== null && /* @__PURE__ */ jsx21(Section, { label: "Output", value: formatResult(result) })
2854
- ] })
2855
- ]
3107
+ style: { gridTemplateRows: open ? "1fr" : "0fr" },
3108
+ children: /* @__PURE__ */ jsx22("div", { className: "min-h-0 overflow-hidden", children: /* @__PURE__ */ jsx22(
3109
+ "div",
3110
+ {
3111
+ className: cn(
3112
+ className,
3113
+ "transition-opacity",
3114
+ 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)]"
3115
+ ),
3116
+ children
3117
+ }
3118
+ ) })
2856
3119
  }
2857
3120
  );
2858
- };
2859
- var Section = ({ label, value }) => /* @__PURE__ */ jsxs11("div", { className: "aui-tool-fallback-section", children: [
2860
- /* @__PURE__ */ jsx21("div", { className: "aui-tool-fallback-section-label mb-0.5 text-[10px] font-semibold uppercase tracking-wider text-muted-foreground", children: label }),
2861
- /* @__PURE__ */ jsx21("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 })
2862
- ] });
2863
- function formatResult(result) {
3121
+ }
3122
+
3123
+ // src/components/tool-fallback.tsx
3124
+ import { jsx as jsx23, jsxs as jsxs12 } from "react/jsx-runtime";
3125
+ function detectRunning({
3126
+ status,
3127
+ result,
3128
+ streamRunning
3129
+ }) {
3130
+ const isError = status?.type === "incomplete" && status.reason !== "cancelled";
3131
+ if (isError) return false;
3132
+ if (status?.type === "running") return true;
3133
+ if (status?.type === "complete") return false;
3134
+ return streamRunning && result === void 0;
3135
+ }
3136
+ function useToolRunning(props) {
3137
+ const { isRunning: streamRunning } = useTimbalRuntime();
3138
+ const partStatus = useAuiState2((s) => s.part.status);
3139
+ return detectRunning({
3140
+ status: partStatus ?? props.status,
3141
+ result: props.result,
3142
+ streamRunning
3143
+ });
3144
+ }
3145
+ function formatToolLabel(toolName) {
3146
+ return toolName.replace(/_/g, " ").replace(/([a-z])([A-Z])/g, "$1 $2").toLowerCase();
3147
+ }
3148
+ function formatToolResult(result) {
2864
3149
  if (typeof result === "string") return result;
2865
3150
  try {
2866
3151
  return JSON.stringify(result, null, 2);
@@ -2868,26 +3153,166 @@ function formatResult(result) {
2868
3153
  return String(result);
2869
3154
  }
2870
3155
  }
3156
+ var TimelineActionLabel = ({ action, detail, shimmer = false }) => /* @__PURE__ */ jsxs12("span", { className: "inline-flex min-w-0 max-w-full items-baseline gap-1", children: [
3157
+ action ? shimmer ? /* @__PURE__ */ jsx23(
3158
+ Shimmer,
3159
+ {
3160
+ as: "span",
3161
+ className: cn(studioTimelineShimmerActionClass, "aui-tool-shimmer"),
3162
+ duration: 1.8,
3163
+ spread: 2.5,
3164
+ children: action
3165
+ }
3166
+ ) : /* @__PURE__ */ jsx23("span", { className: studioTimelineActionClass, children: action }) : null,
3167
+ detail ? /* @__PURE__ */ jsx23("span", { className: studioTimelineDetailClass, children: detail }) : null
3168
+ ] });
3169
+ var TimelineHoverChevron = ({ expanded }) => /* @__PURE__ */ jsx23(
3170
+ ChevronRightIcon,
3171
+ {
3172
+ className: studioTimelineChevronClass(expanded),
3173
+ "aria-hidden": true
3174
+ }
3175
+ );
3176
+ var ToolPanel = ({ toolName, argsText, result, isError }) => {
3177
+ const [open, setOpen] = useState6(false);
3178
+ const detail = formatToolLabel(toolName);
3179
+ const formattedArgs = useMemo5(() => {
3180
+ if (!argsText || argsText === "{}") return null;
3181
+ try {
3182
+ return JSON.stringify(JSON.parse(argsText), null, 2);
3183
+ } catch {
3184
+ return argsText;
3185
+ }
3186
+ }, [argsText]);
3187
+ const formattedResult = useMemo5(() => {
3188
+ if (result === void 0 || result === null) return null;
3189
+ return formatToolResult(result);
3190
+ }, [result]);
3191
+ const hasBody = Boolean(formattedArgs || formattedResult);
3192
+ const action = isError ? "Failed" : "Used";
3193
+ if (!hasBody) {
3194
+ return /* @__PURE__ */ jsx23("div", { className: "aui-tool-row w-full min-w-0", children: /* @__PURE__ */ jsx23(TimelineActionLabel, { action, detail }) });
3195
+ }
3196
+ return /* @__PURE__ */ jsxs12("div", { className: "aui-tool-row w-full min-w-0", children: [
3197
+ /* @__PURE__ */ jsx23(
3198
+ "button",
3199
+ {
3200
+ type: "button",
3201
+ onClick: () => setOpen((v) => !v),
3202
+ "aria-expanded": open,
3203
+ "aria-label": `${action} ${detail}`,
3204
+ className: studioTimelineRowButtonClass,
3205
+ children: /* @__PURE__ */ jsxs12(
3206
+ "span",
3207
+ {
3208
+ className: cn(
3209
+ "inline-flex min-w-0 max-w-full items-center gap-0.5",
3210
+ studioTimelineTextClass,
3211
+ "text-foreground"
3212
+ ),
3213
+ children: [
3214
+ /* @__PURE__ */ jsx23(TimelineActionLabel, { action, detail }),
3215
+ /* @__PURE__ */ jsx23(TimelineHoverChevron, { expanded: open })
3216
+ ]
3217
+ }
3218
+ )
3219
+ }
3220
+ ),
3221
+ /* @__PURE__ */ jsxs12(
3222
+ ToolBodyPresence,
3223
+ {
3224
+ open,
3225
+ className: cn(studioTimelineBodyPadClass, "gap-2"),
3226
+ children: [
3227
+ formattedArgs ? /* @__PURE__ */ jsx23(
3228
+ "div",
3229
+ {
3230
+ className: cn(
3231
+ studioComposerIoWellClass,
3232
+ "max-h-48 overflow-auto px-2.5 py-2"
3233
+ ),
3234
+ children: /* @__PURE__ */ jsx23("pre", { className: "whitespace-pre-wrap break-words font-mono text-[11px] font-normal leading-relaxed text-foreground", children: formattedArgs })
3235
+ }
3236
+ ) : null,
3237
+ formattedResult ? /* @__PURE__ */ jsx23(
3238
+ "div",
3239
+ {
3240
+ className: cn(
3241
+ studioComposerIoWellClass,
3242
+ "max-h-48 overflow-auto px-2.5 py-2"
3243
+ ),
3244
+ children: /* @__PURE__ */ jsx23("pre", { className: "whitespace-pre-wrap break-words font-mono text-[11px] font-normal leading-relaxed text-foreground", children: formattedResult })
3245
+ }
3246
+ ) : null
3247
+ ]
3248
+ }
3249
+ )
3250
+ ] });
3251
+ };
3252
+ var ToolFallbackImpl = ({
3253
+ toolName,
3254
+ argsText,
3255
+ result,
3256
+ status
3257
+ }) => {
3258
+ const isRunning = useToolRunning({ status, result });
3259
+ const isError = status?.type === "incomplete" && status.reason !== "cancelled";
3260
+ const presenceKey = isRunning ? "running" : isError ? "error" : "complete";
3261
+ return /* @__PURE__ */ jsx23(
3262
+ ToolPresence,
3263
+ {
3264
+ presenceKey,
3265
+ variant: isRunning ? "executing" : "settled",
3266
+ className: "py-0.5",
3267
+ children: isRunning ? /* @__PURE__ */ jsx23("div", { className: "aui-tool-running", children: /* @__PURE__ */ jsx23(
3268
+ TimelineActionLabel,
3269
+ {
3270
+ action: "Using",
3271
+ detail: formatToolLabel(toolName),
3272
+ shimmer: true
3273
+ }
3274
+ ) }) : /* @__PURE__ */ jsx23(
3275
+ ToolPanel,
3276
+ {
3277
+ toolName,
3278
+ argsText,
3279
+ result,
3280
+ isError
3281
+ }
3282
+ )
3283
+ }
3284
+ );
3285
+ };
2871
3286
  var ToolFallback = memo3(
2872
3287
  ToolFallbackImpl
2873
3288
  );
2874
3289
  ToolFallback.displayName = "ToolFallback";
2875
3290
 
2876
3291
  // src/artifacts/tool-artifact.tsx
2877
- import { jsx as jsx22 } from "react/jsx-runtime";
3292
+ import { jsx as jsx24 } from "react/jsx-runtime";
2878
3293
  var ToolArtifactFallback = (props) => {
2879
3294
  const registry = useArtifactRegistry();
2880
- const isRunning = props.status?.type === "running";
3295
+ const isRunning = useToolRunning({
3296
+ status: props.status,
3297
+ result: props.result
3298
+ });
2881
3299
  if (!isRunning) {
2882
3300
  const artifact = parseArtifactFromToolResult(props.result);
2883
3301
  if (artifact) {
2884
3302
  const Renderer = registry[artifact.type];
2885
3303
  if (Renderer) {
2886
- return /* @__PURE__ */ jsx22(Renderer, { artifact });
3304
+ return /* @__PURE__ */ jsx24(
3305
+ ToolMotion,
3306
+ {
3307
+ motionKey: `artifact-${artifact.type}`,
3308
+ className: "aui-tool-artifact",
3309
+ children: /* @__PURE__ */ jsx24(Renderer, { artifact })
3310
+ }
3311
+ );
2887
3312
  }
2888
3313
  }
2889
3314
  }
2890
- return /* @__PURE__ */ jsx22(ToolFallback, { ...props });
3315
+ return /* @__PURE__ */ jsx24(ToolFallback, { ...props });
2891
3316
  };
2892
3317
 
2893
3318
  // src/components/composer.tsx
@@ -2897,7 +3322,7 @@ import {
2897
3322
  useComposerRuntime
2898
3323
  } from "@assistant-ui/react";
2899
3324
  import { ArrowUpIcon, SquareIcon } from "lucide-react";
2900
- import { Fragment as Fragment2, jsx as jsx23, jsxs as jsxs12 } from "react/jsx-runtime";
3325
+ import { Fragment as Fragment2, jsx as jsx25, jsxs as jsxs13 } from "react/jsx-runtime";
2901
3326
  var Composer = ({
2902
3327
  placeholder = "Send a message...",
2903
3328
  showAttachments = true,
@@ -2906,21 +3331,24 @@ var Composer = ({
2906
3331
  noAutoFocus,
2907
3332
  className
2908
3333
  }) => {
2909
- return /* @__PURE__ */ jsx23(
3334
+ return /* @__PURE__ */ jsx25(
2910
3335
  ComposerPrimitive2.Root,
2911
3336
  {
2912
3337
  className: cn(
2913
- "aui-composer-root relative mt-3 flex w-full flex-col",
3338
+ "aui-composer-root relative flex w-full flex-col",
2914
3339
  className
2915
3340
  ),
2916
- children: /* @__PURE__ */ jsxs12(
3341
+ children: /* @__PURE__ */ jsxs13(
2917
3342
  ComposerPrimitive2.AttachmentDropzone,
2918
3343
  {
2919
- 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",
3344
+ className: cn(
3345
+ studioComposeInputShellClass,
3346
+ "data-[dragging=true]:border-2 data-[dragging=true]:border-dashed data-[dragging=true]:border-primary data-[dragging=true]:bg-accent/50"
3347
+ ),
2920
3348
  children: [
2921
- showAttachments && /* @__PURE__ */ jsx23(ComposerAttachments, {}),
2922
- /* @__PURE__ */ jsx23(ComposerInput, { placeholder, autoFocus: !noAutoFocus }),
2923
- /* @__PURE__ */ jsx23(
3349
+ showAttachments && /* @__PURE__ */ jsx25(ComposerAttachments, {}),
3350
+ /* @__PURE__ */ jsx25(ComposerInput, { placeholder, autoFocus: !noAutoFocus }),
3351
+ /* @__PURE__ */ jsx25(
2924
3352
  ComposerToolbar,
2925
3353
  {
2926
3354
  showAttachments,
@@ -2950,11 +3378,11 @@ var ComposerInput = ({
2950
3378
  el.style.height = "auto";
2951
3379
  el.style.height = `${Math.min(el.scrollHeight, 240)}px`;
2952
3380
  };
2953
- return /* @__PURE__ */ jsx23(
3381
+ return /* @__PURE__ */ jsx25(
2954
3382
  ComposerPrimitive2.Input,
2955
3383
  {
2956
3384
  placeholder,
2957
- 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",
3385
+ 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",
2958
3386
  rows: 1,
2959
3387
  autoFocus,
2960
3388
  "aria-label": "Message input",
@@ -2964,37 +3392,35 @@ var ComposerInput = ({
2964
3392
  );
2965
3393
  };
2966
3394
  var ComposerToolbar = ({ showAttachments, toolbar, sendTooltip }) => {
2967
- return /* @__PURE__ */ jsxs12("div", { className: "aui-composer-action-wrapper relative mx-2 mb-2 flex items-center gap-1", children: [
2968
- showAttachments && /* @__PURE__ */ jsx23(ComposerAddAttachment, {}),
2969
- toolbar,
2970
- /* @__PURE__ */ jsx23("div", { className: "flex-1" }),
2971
- /* @__PURE__ */ jsx23(ComposerSendOrCancel, { sendTooltip })
3395
+ return /* @__PURE__ */ jsxs13("div", { className: "aui-composer-action-wrapper flex items-center justify-between gap-1 px-2.5 pb-2.5", children: [
3396
+ /* @__PURE__ */ jsxs13("div", { className: "flex items-center gap-1", children: [
3397
+ showAttachments && /* @__PURE__ */ jsx25(ComposerAddAttachment, {}),
3398
+ toolbar
3399
+ ] }),
3400
+ /* @__PURE__ */ jsx25(ComposerSendOrCancel, { sendTooltip })
2972
3401
  ] });
2973
3402
  };
2974
3403
  var ComposerSendOrCancel = ({ sendTooltip }) => {
2975
- return /* @__PURE__ */ jsxs12(Fragment2, { children: [
2976
- /* @__PURE__ */ jsx23(AuiIf, { condition: (s) => !s.thread.isRunning, children: /* @__PURE__ */ jsx23(ComposerPrimitive2.Send, { asChild: true, children: /* @__PURE__ */ jsx23(
3404
+ return /* @__PURE__ */ jsxs13(Fragment2, { children: [
3405
+ /* @__PURE__ */ jsx25(AuiIf, { condition: (s) => !s.thread.isRunning, children: /* @__PURE__ */ jsx25(ComposerPrimitive2.Send, { asChild: true, children: /* @__PURE__ */ jsx25(
2977
3406
  TooltipIconButton,
2978
3407
  {
2979
3408
  tooltip: sendTooltip,
2980
- side: "bottom",
3409
+ variant: "primary",
2981
3410
  type: "submit",
2982
- variant: "default",
2983
- size: "icon",
2984
- className: "aui-composer-send size-8 rounded-full",
3411
+ className: "aui-composer-send shrink-0 disabled:opacity-30",
2985
3412
  "aria-label": "Send message",
2986
- children: /* @__PURE__ */ jsx23(ArrowUpIcon, { className: "aui-composer-send-icon size-4" })
3413
+ children: /* @__PURE__ */ jsx25(ArrowUpIcon, { className: "aui-composer-send-icon size-4" })
2987
3414
  }
2988
3415
  ) }) }),
2989
- /* @__PURE__ */ jsx23(AuiIf, { condition: (s) => s.thread.isRunning, children: /* @__PURE__ */ jsx23(ComposerPrimitive2.Cancel, { asChild: true, children: /* @__PURE__ */ jsx23(
2990
- Button,
3416
+ /* @__PURE__ */ jsx25(AuiIf, { condition: (s) => s.thread.isRunning, children: /* @__PURE__ */ jsx25(ComposerPrimitive2.Cancel, { asChild: true, children: /* @__PURE__ */ jsx25(
3417
+ TooltipIconButton,
2991
3418
  {
2992
- type: "button",
2993
- variant: "default",
2994
- size: "icon",
2995
- className: "aui-composer-cancel size-8 rounded-full",
3419
+ tooltip: "Stop generating",
3420
+ variant: "primary",
3421
+ className: "aui-composer-cancel shrink-0",
2996
3422
  "aria-label": "Stop generating",
2997
- children: /* @__PURE__ */ jsx23(SquareIcon, { className: "aui-composer-cancel-icon size-3 fill-current" })
3423
+ children: /* @__PURE__ */ jsx25(SquareIcon, { className: "aui-composer-cancel-icon size-3 fill-current" })
2998
3424
  }
2999
3425
  ) }) })
3000
3426
  ] });
@@ -3003,55 +3429,53 @@ var ComposerSendOrCancel = ({ sendTooltip }) => {
3003
3429
  // src/components/suggestions.tsx
3004
3430
  import {
3005
3431
  useEffect as useEffect4,
3006
- useMemo as useMemo5,
3432
+ useMemo as useMemo6,
3007
3433
  useState as useState7
3008
3434
  } from "react";
3009
3435
  import { useThreadRuntime as useThreadRuntime3 } from "@assistant-ui/react";
3010
- import { jsx as jsx24, jsxs as jsxs13 } from "react/jsx-runtime";
3436
+ import { ArrowUpIcon as ArrowUpIcon2 } from "lucide-react";
3437
+ import { jsx as jsx26, jsxs as jsxs14 } from "react/jsx-runtime";
3011
3438
  var Suggestions = ({
3012
3439
  suggestions,
3013
- layout = "grid",
3014
3440
  className
3015
3441
  }) => {
3016
3442
  const items = useResolvedSuggestions(suggestions);
3017
3443
  if (!items || items.length === 0) return null;
3018
- return /* @__PURE__ */ jsx24(
3444
+ return /* @__PURE__ */ jsx26(
3019
3445
  "div",
3020
3446
  {
3021
3447
  className: cn(
3022
- "aui-thread-suggestions w-full pb-4",
3023
- layout === "grid" ? "grid gap-2 @md:grid-cols-2" : "flex gap-2 overflow-x-auto pb-1 [&::-webkit-scrollbar]:hidden",
3448
+ "aui-thread-suggestions flex w-full flex-col gap-2 pb-2.5",
3024
3449
  className
3025
3450
  ),
3026
- children: items.map((s, i) => /* @__PURE__ */ jsx24(SuggestionChip, { suggestion: s, compact: layout === "row" }, s.title + i))
3451
+ role: "list",
3452
+ "aria-label": "Suggested prompts",
3453
+ children: items.map((suggestion, i) => /* @__PURE__ */ jsx26(SuggestionRow, { suggestion }, (suggestion.prompt ?? suggestion.title) + i))
3027
3454
  }
3028
3455
  );
3029
3456
  };
3030
- var SuggestionChip = ({
3031
- suggestion,
3032
- compact
3033
- }) => {
3457
+ var SuggestionRow = ({ suggestion }) => {
3034
3458
  const runtime = useThreadRuntime3();
3035
3459
  const onClick = () => {
3036
3460
  const text = suggestion.prompt ?? suggestion.title;
3037
3461
  runtime.append({ role: "user", content: [{ type: "text", text }] });
3038
3462
  };
3039
- return /* @__PURE__ */ jsx24("div", { className: "aui-thread-suggestion-display fade-in slide-in-from-bottom-2 animate-in fill-mode-both duration-200", children: /* @__PURE__ */ jsxs13(
3040
- Button,
3463
+ return /* @__PURE__ */ jsxs14(
3464
+ "button",
3041
3465
  {
3042
- variant: "ghost",
3466
+ type: "button",
3467
+ role: "listitem",
3043
3468
  onClick,
3044
- className: cn(
3045
- "aui-thread-suggestion h-auto rounded-2xl border text-left text-sm transition-colors hover:bg-muted",
3046
- 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"
3047
- ),
3469
+ className: cn("aui-thread-suggestion", studioListRowButtonClass),
3048
3470
  children: [
3049
- suggestion.icon && /* @__PURE__ */ jsx24("span", { className: "aui-thread-suggestion-icon shrink-0 text-muted-foreground", children: suggestion.icon }),
3050
- /* @__PURE__ */ jsx24("span", { className: "aui-thread-suggestion-text-1 font-medium", children: suggestion.title }),
3051
- suggestion.description && !compact && /* @__PURE__ */ jsx24("span", { className: "aui-thread-suggestion-text-2 text-muted-foreground", children: suggestion.description })
3471
+ /* @__PURE__ */ jsx26("span", { className: "aui-thread-suggestion-icon shrink-0 text-neutral-500 dark:text-muted-foreground", children: suggestion.icon ?? /* @__PURE__ */ jsx26(ArrowUpIcon2, { className: "size-4", strokeWidth: 1.75, "aria-hidden": true }) }),
3472
+ /* @__PURE__ */ jsxs14("span", { className: "aui-thread-suggestion-text min-w-0 flex-1 text-left", children: [
3473
+ /* @__PURE__ */ jsx26("span", { className: "aui-thread-suggestion-text-1 block truncate text-sm font-normal text-foreground dark:text-foreground/95", children: suggestion.title }),
3474
+ suggestion.description && /* @__PURE__ */ jsx26("span", { className: "aui-thread-suggestion-text-2 mt-0.5 block truncate text-xs text-muted-foreground", children: suggestion.description })
3475
+ ] })
3052
3476
  ]
3053
3477
  }
3054
- ) });
3478
+ );
3055
3479
  };
3056
3480
  function useResolvedSuggestions(source) {
3057
3481
  const [resolved, setResolved] = useState7(
@@ -3076,29 +3500,11 @@ function useResolvedSuggestions(source) {
3076
3500
  cancelled = true;
3077
3501
  };
3078
3502
  }, [source]);
3079
- return useMemo5(() => resolved, [resolved]);
3503
+ return useMemo6(() => resolved, [resolved]);
3080
3504
  }
3081
3505
 
3082
3506
  // src/components/thread.tsx
3083
- import {
3084
- ActionBarMorePrimitive,
3085
- ActionBarPrimitive,
3086
- AuiIf as AuiIf2,
3087
- ComposerPrimitive as ComposerPrimitive3,
3088
- ErrorPrimitive,
3089
- MessagePrimitive as MessagePrimitive2,
3090
- ThreadPrimitive
3091
- } from "@assistant-ui/react";
3092
- import {
3093
- ArrowDownIcon,
3094
- CheckIcon as CheckIcon3,
3095
- CopyIcon as CopyIcon2,
3096
- DownloadIcon,
3097
- MoreHorizontalIcon,
3098
- PencilIcon,
3099
- RefreshCwIcon
3100
- } from "lucide-react";
3101
- import { jsx as jsx25, jsxs as jsxs14 } from "react/jsx-runtime";
3507
+ import { jsx as jsx27, jsxs as jsxs15 } from "react/jsx-runtime";
3102
3508
  var Thread = ({
3103
3509
  className,
3104
3510
  maxWidth = "44rem",
@@ -3116,13 +3522,13 @@ var Thread = ({
3116
3522
  const EditComposerSlot = components?.EditComposer ?? EditComposer;
3117
3523
  const ScrollToBottomSlot = components?.ScrollToBottom ?? ThreadScrollToBottom;
3118
3524
  const SuggestionsSlot = components?.Suggestions ?? Suggestions;
3119
- return /* @__PURE__ */ jsx25(
3525
+ return /* @__PURE__ */ jsx27(
3120
3526
  ArtifactRegistryProvider,
3121
3527
  {
3122
3528
  renderers: artifacts?.renderers,
3123
3529
  override: artifacts?.override,
3124
- children: /* @__PURE__ */ jsx25(UiEventProvider, { onEvent: onArtifactEvent ?? (() => {
3125
- }), children: /* @__PURE__ */ jsx25(
3530
+ children: /* @__PURE__ */ jsx27(UiEventProvider, { onEvent: onArtifactEvent ?? (() => {
3531
+ }), children: /* @__PURE__ */ jsx27(
3126
3532
  ThreadPrimitive.Root,
3127
3533
  {
3128
3534
  className: cn(
@@ -3130,13 +3536,13 @@ var Thread = ({
3130
3536
  className
3131
3537
  ),
3132
3538
  style: { ["--thread-max-width"]: maxWidth },
3133
- children: /* @__PURE__ */ jsxs14(
3539
+ children: /* @__PURE__ */ jsxs15(
3134
3540
  ThreadPrimitive.Viewport,
3135
3541
  {
3136
3542
  turnAnchor: "bottom",
3137
3543
  className: "aui-thread-viewport relative flex flex-1 flex-col overflow-x-auto overflow-y-scroll px-4 pt-4",
3138
3544
  children: [
3139
- /* @__PURE__ */ jsx25(
3545
+ /* @__PURE__ */ jsx27(
3140
3546
  WelcomeSlot,
3141
3547
  {
3142
3548
  config: welcome,
@@ -3144,7 +3550,7 @@ var Thread = ({
3144
3550
  Suggestions: SuggestionsSlot
3145
3551
  }
3146
3552
  ),
3147
- /* @__PURE__ */ jsx25(
3553
+ /* @__PURE__ */ jsx27(
3148
3554
  ThreadPrimitive.Messages,
3149
3555
  {
3150
3556
  components: {
@@ -3154,9 +3560,9 @@ var Thread = ({
3154
3560
  }
3155
3561
  }
3156
3562
  ),
3157
- /* @__PURE__ */ jsxs14(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: [
3158
- /* @__PURE__ */ jsx25(ScrollToBottomSlot, {}),
3159
- /* @__PURE__ */ jsx25(ComposerSlot, { placeholder: composerPlaceholder })
3563
+ /* @__PURE__ */ jsxs15(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: [
3564
+ /* @__PURE__ */ jsx27(ScrollToBottomSlot, {}),
3565
+ /* @__PURE__ */ jsx27(ComposerSlot, { placeholder: composerPlaceholder })
3160
3566
  ] })
3161
3567
  ]
3162
3568
  }
@@ -3167,105 +3573,165 @@ var Thread = ({
3167
3573
  );
3168
3574
  };
3169
3575
  var ThreadScrollToBottom = () => {
3170
- return /* @__PURE__ */ jsx25(ThreadPrimitive.ScrollToBottom, { asChild: true, children: /* @__PURE__ */ jsx25(
3576
+ return /* @__PURE__ */ jsx27(ThreadPrimitive.ScrollToBottom, { asChild: true, children: /* @__PURE__ */ jsx27(
3171
3577
  TooltipIconButton,
3172
3578
  {
3173
3579
  tooltip: "Scroll to bottom",
3174
- variant: "outline",
3175
- 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",
3176
- children: /* @__PURE__ */ jsx25(ArrowDownIcon, {})
3580
+ variant: "secondary",
3581
+ className: "aui-thread-scroll-to-bottom absolute -top-12 z-10 self-center disabled:invisible",
3582
+ children: /* @__PURE__ */ jsx27(ArrowDownIcon, { className: "size-4" })
3177
3583
  }
3178
3584
  ) });
3179
3585
  };
3586
+ var welcomeStagger = {
3587
+ initial: {},
3588
+ animate: {
3589
+ transition: { staggerChildren: 0.16, delayChildren: 0.12 }
3590
+ }
3591
+ };
3592
+ var welcomeItem = {
3593
+ initial: { opacity: 0, y: 14 },
3594
+ animate: {
3595
+ opacity: 1,
3596
+ y: 0,
3597
+ transition: { duration: 0.9, ease: luxuryEase }
3598
+ }
3599
+ };
3600
+ var welcomeIcon = {
3601
+ initial: { opacity: 0, y: 10, scale: 0.96 },
3602
+ animate: {
3603
+ opacity: 1,
3604
+ y: 0,
3605
+ scale: 1,
3606
+ transition: { duration: 1.1, ease: luxuryEase }
3607
+ }
3608
+ };
3180
3609
  var ThreadWelcome = ({
3181
3610
  config,
3182
3611
  suggestions,
3183
3612
  Suggestions: SuggestionsSlot = Suggestions
3184
3613
  }) => {
3185
- return /* @__PURE__ */ jsx25(AuiIf2, { condition: (s) => s.thread.isEmpty, children: /* @__PURE__ */ jsxs14("div", { className: "aui-thread-welcome-root mx-auto my-auto flex w-full max-w-(--thread-max-width) grow flex-col", children: [
3186
- /* @__PURE__ */ jsx25("div", { className: "aui-thread-welcome-center flex w-full grow flex-col items-center justify-center", children: /* @__PURE__ */ jsxs14("div", { className: "aui-thread-welcome-message flex size-full flex-col items-center justify-center px-4 text-center", children: [
3187
- /* @__PURE__ */ jsxs14("div", { className: "fade-in animate-in fill-mode-both relative mb-6 flex size-14 items-center justify-center duration-300", children: [
3188
- /* @__PURE__ */ jsx25("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" }),
3189
- /* @__PURE__ */ jsx25("div", { className: "animate-ai-pulse-ring absolute inset-0" }),
3190
- /* @__PURE__ */ jsx25(
3191
- "svg",
3192
- {
3193
- xmlns: "http://www.w3.org/2000/svg",
3194
- viewBox: "0 0 24 24",
3195
- fill: "none",
3196
- stroke: "currentColor",
3197
- strokeWidth: "1.5",
3198
- strokeLinecap: "round",
3199
- strokeLinejoin: "round",
3200
- className: "animate-ai-breathe relative size-7 text-primary/75",
3201
- children: /* @__PURE__ */ jsx25("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" })
3202
- }
3203
- )
3204
- ] }),
3205
- /* @__PURE__ */ jsx25("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?" }),
3206
- /* @__PURE__ */ jsx25("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." })
3207
- ] }) }),
3208
- suggestions && /* @__PURE__ */ jsx25(SuggestionsSlot, { suggestions })
3209
- ] }) });
3614
+ const isEmpty = useThread((s) => s.messages.length === 0);
3615
+ if (!isEmpty) return null;
3616
+ return /* @__PURE__ */ jsxs15("div", { className: "aui-thread-welcome-root mx-auto my-auto flex w-full max-w-(--thread-max-width) grow flex-col", children: [
3617
+ /* @__PURE__ */ jsx27("div", { className: "aui-thread-welcome-center flex w-full grow flex-col items-center justify-center", children: /* @__PURE__ */ jsxs15(
3618
+ motion4.div,
3619
+ {
3620
+ className: "aui-thread-welcome-message flex flex-col items-center justify-center px-4 text-center",
3621
+ variants: welcomeStagger,
3622
+ initial: "initial",
3623
+ animate: "animate",
3624
+ children: [
3625
+ config?.icon && /* @__PURE__ */ jsx27(motion4.div, { variants: welcomeIcon, className: "mb-5", children: config.icon }),
3626
+ /* @__PURE__ */ jsx27(
3627
+ motion4.h1,
3628
+ {
3629
+ variants: welcomeItem,
3630
+ className: "aui-thread-welcome-message-inner font-semibold text-2xl",
3631
+ children: config?.heading ?? "How can I help you today?"
3632
+ }
3633
+ ),
3634
+ /* @__PURE__ */ jsx27(
3635
+ motion4.p,
3636
+ {
3637
+ variants: welcomeItem,
3638
+ className: "aui-thread-welcome-message-inner mt-2 text-muted-foreground",
3639
+ children: config?.subheading ?? "Send a message to start a conversation."
3640
+ }
3641
+ )
3642
+ ]
3643
+ }
3644
+ ) }),
3645
+ suggestions && /* @__PURE__ */ jsx27("div", { className: "aui-thread-welcome-suggestions mx-auto w-full max-w-(--thread-max-width) px-2", children: /* @__PURE__ */ jsx27(SuggestionsSlot, { suggestions }) })
3646
+ ] });
3210
3647
  };
3211
3648
  var MessageError = () => {
3212
- return /* @__PURE__ */ jsx25(MessagePrimitive2.Error, { children: /* @__PURE__ */ jsx25(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__ */ jsx25(ErrorPrimitive.Message, { className: "aui-message-error-message line-clamp-2" }) }) });
3649
+ return /* @__PURE__ */ jsx27(MessagePrimitive2.Error, { children: /* @__PURE__ */ jsx27(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__ */ jsx27(ErrorPrimitive.Message, { className: "aui-message-error-message line-clamp-2" }) }) });
3213
3650
  };
3214
3651
  var AssistantMessage = () => {
3215
- return /* @__PURE__ */ jsxs14(
3652
+ return /* @__PURE__ */ jsxs15(
3216
3653
  MessagePrimitive2.Root,
3217
3654
  {
3218
3655
  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",
3219
3656
  "data-role": "assistant",
3220
3657
  children: [
3221
- /* @__PURE__ */ jsxs14("div", { className: "aui-assistant-message-content wrap-break-word px-2 text-foreground leading-relaxed", children: [
3222
- /* @__PURE__ */ jsx25(
3658
+ /* @__PURE__ */ jsxs15("div", { className: "aui-assistant-message-content wrap-break-word px-2 text-foreground leading-relaxed", children: [
3659
+ /* @__PURE__ */ jsx27(
3223
3660
  MessagePrimitive2.Parts,
3224
3661
  {
3225
3662
  components: {
3226
3663
  Text: MarkdownText,
3227
- tools: { Fallback: ToolArtifactFallback }
3664
+ // `Override` (not `Fallback`) replaces the default tool renderer
3665
+ // entirely so we never fall back to the assistant-ui boilerplate.
3666
+ tools: { Override: ToolArtifactFallback }
3228
3667
  }
3229
3668
  }
3230
3669
  ),
3231
- /* @__PURE__ */ jsx25(MessageError, {})
3670
+ /* @__PURE__ */ jsx27(MessageError, {})
3232
3671
  ] }),
3233
- /* @__PURE__ */ jsx25("div", { className: "aui-assistant-message-footer mt-1 ml-2 flex", children: /* @__PURE__ */ jsx25(AssistantActionBar, {}) })
3672
+ /* @__PURE__ */ jsx27("div", { className: "aui-assistant-message-footer mt-0 ml-1 flex", children: /* @__PURE__ */ jsx27(AssistantActionBar, {}) })
3234
3673
  ]
3235
3674
  }
3236
3675
  );
3237
3676
  };
3677
+ var ASSISTANT_ACTION_ICON_CLASS = cn(
3678
+ "size-6 min-h-6 min-w-6 text-muted-foreground/45 hover:text-muted-foreground/80",
3679
+ // The v2 fill span sits inside `group/tbv2 > span:first-child`. We mute it
3680
+ // here so action-bar buttons read as subtle icons rather than full pills.
3681
+ "[&>span:first-child]:bg-transparent",
3682
+ "[&>span:first-child]:group-hover/tbv2:bg-neutral-100/50",
3683
+ "dark:[&>span:first-child]:group-hover/tbv2:bg-white/8"
3684
+ );
3238
3685
  var AssistantActionBar = () => {
3239
- return /* @__PURE__ */ jsxs14(
3686
+ return /* @__PURE__ */ jsxs15(
3240
3687
  ActionBarPrimitive.Root,
3241
3688
  {
3242
3689
  hideWhenRunning: true,
3243
3690
  autohide: "not-last",
3244
- autohideFloat: "single-branch",
3245
- 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",
3691
+ className: "aui-assistant-action-bar-root flex items-center gap-0 bg-transparent px-0 py-0.5 text-muted-foreground/60",
3246
3692
  children: [
3247
- /* @__PURE__ */ jsx25(ActionBarPrimitive.Copy, { asChild: true, children: /* @__PURE__ */ jsxs14(TooltipIconButton, { tooltip: "Copy", children: [
3248
- /* @__PURE__ */ jsx25(AuiIf2, { condition: (s) => s.message.isCopied, children: /* @__PURE__ */ jsx25(CheckIcon3, {}) }),
3249
- /* @__PURE__ */ jsx25(AuiIf2, { condition: (s) => !s.message.isCopied, children: /* @__PURE__ */ jsx25(CopyIcon2, {}) })
3250
- ] }) }),
3251
- /* @__PURE__ */ jsx25(ActionBarPrimitive.Reload, { asChild: true, children: /* @__PURE__ */ jsx25(TooltipIconButton, { tooltip: "Refresh", children: /* @__PURE__ */ jsx25(RefreshCwIcon, {}) }) }),
3252
- /* @__PURE__ */ jsxs14(ActionBarMorePrimitive.Root, { children: [
3253
- /* @__PURE__ */ jsx25(ActionBarMorePrimitive.Trigger, { asChild: true, children: /* @__PURE__ */ jsx25(
3693
+ /* @__PURE__ */ jsx27(ActionBarPrimitive.Copy, { asChild: true, children: /* @__PURE__ */ jsxs15(
3694
+ TooltipIconButton,
3695
+ {
3696
+ tooltip: "Copy",
3697
+ variant: "ghost",
3698
+ className: ASSISTANT_ACTION_ICON_CLASS,
3699
+ children: [
3700
+ /* @__PURE__ */ jsx27(AuiIf2, { condition: (s) => s.message.isCopied, children: /* @__PURE__ */ jsx27(CheckIcon3, { className: "size-3" }) }),
3701
+ /* @__PURE__ */ jsx27(AuiIf2, { condition: (s) => !s.message.isCopied, children: /* @__PURE__ */ jsx27(CopyIcon2, { className: "size-3" }) })
3702
+ ]
3703
+ }
3704
+ ) }),
3705
+ /* @__PURE__ */ jsx27(ActionBarPrimitive.Reload, { asChild: true, children: /* @__PURE__ */ jsx27(
3706
+ TooltipIconButton,
3707
+ {
3708
+ tooltip: "Regenerate",
3709
+ variant: "ghost",
3710
+ className: ASSISTANT_ACTION_ICON_CLASS,
3711
+ children: /* @__PURE__ */ jsx27(RefreshCwIcon, { className: "size-3" })
3712
+ }
3713
+ ) }),
3714
+ /* @__PURE__ */ jsxs15(ActionBarMorePrimitive.Root, { children: [
3715
+ /* @__PURE__ */ jsx27(ActionBarMorePrimitive.Trigger, { asChild: true, children: /* @__PURE__ */ jsx27(
3254
3716
  TooltipIconButton,
3255
3717
  {
3256
3718
  tooltip: "More",
3257
- className: "data-[state=open]:bg-accent",
3258
- children: /* @__PURE__ */ jsx25(MoreHorizontalIcon, {})
3719
+ variant: "ghost",
3720
+ className: cn(
3721
+ ASSISTANT_ACTION_ICON_CLASS,
3722
+ "data-[state=open]:text-muted-foreground/80"
3723
+ ),
3724
+ children: /* @__PURE__ */ jsx27(MoreHorizontalIcon, { className: "size-3" })
3259
3725
  }
3260
3726
  ) }),
3261
- /* @__PURE__ */ jsx25(
3727
+ /* @__PURE__ */ jsx27(
3262
3728
  ActionBarMorePrimitive.Content,
3263
3729
  {
3264
3730
  side: "bottom",
3265
3731
  align: "start",
3266
- 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",
3267
- children: /* @__PURE__ */ jsx25(ActionBarPrimitive.ExportMarkdown, { asChild: true, children: /* @__PURE__ */ jsxs14(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: [
3268
- /* @__PURE__ */ jsx25(DownloadIcon, { className: "size-4" }),
3732
+ 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",
3733
+ children: /* @__PURE__ */ jsx27(ActionBarPrimitive.ExportMarkdown, { asChild: true, children: /* @__PURE__ */ jsxs15(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: [
3734
+ /* @__PURE__ */ jsx27(DownloadIcon, { className: "size-4 shrink-0" }),
3269
3735
  "Export as Markdown"
3270
3736
  ] }) })
3271
3737
  }
@@ -3275,51 +3741,71 @@ var AssistantActionBar = () => {
3275
3741
  }
3276
3742
  );
3277
3743
  };
3744
+ var UserMessageText = () => {
3745
+ return /* @__PURE__ */ jsx27("span", { className: "whitespace-pre-wrap", children: /* @__PURE__ */ jsx27(MessagePartPrimitive.Text, { smooth: false }) });
3746
+ };
3278
3747
  var UserMessage = () => {
3279
- return /* @__PURE__ */ jsxs14(
3748
+ return /* @__PURE__ */ jsxs15(
3280
3749
  MessagePrimitive2.Root,
3281
3750
  {
3282
- 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",
3751
+ 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",
3283
3752
  "data-role": "user",
3284
3753
  children: [
3285
- /* @__PURE__ */ jsx25(UserMessageAttachments, {}),
3286
- /* @__PURE__ */ jsxs14("div", { className: "aui-user-message-content-wrapper relative col-start-2 min-w-0", children: [
3287
- /* @__PURE__ */ jsx25("div", { className: "aui-user-message-content wrap-break-word rounded-2xl bg-muted px-4 py-2.5 text-foreground", children: /* @__PURE__ */ jsx25(MessagePrimitive2.Parts, {}) }),
3288
- /* @__PURE__ */ jsx25("div", { className: "aui-user-action-bar-wrapper absolute top-1/2 left-0 -translate-x-full -translate-y-1/2 pr-2", children: /* @__PURE__ */ jsx25(UserActionBar, {}) })
3289
- ] })
3754
+ /* @__PURE__ */ jsx27(UserMessageAttachments, {}),
3755
+ /* @__PURE__ */ jsxs15(
3756
+ motion4.div,
3757
+ {
3758
+ 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",
3759
+ initial: { opacity: 0, y: 8, scale: 0.99 },
3760
+ animate: { opacity: 1, y: 0, scale: 1 },
3761
+ transition: { duration: 0.65, ease: luxuryEase },
3762
+ children: [
3763
+ /* @__PURE__ */ jsx27(MessagePrimitive2.Parts, { components: { Text: UserMessageText } }),
3764
+ /* @__PURE__ */ jsx27("div", { className: "aui-user-action-bar-wrapper absolute top-1/2 left-0 -translate-x-full -translate-y-1/2 pr-2", children: /* @__PURE__ */ jsx27(UserActionBar, {}) })
3765
+ ]
3766
+ }
3767
+ )
3290
3768
  ]
3291
3769
  }
3292
3770
  );
3293
3771
  };
3294
3772
  var UserActionBar = () => {
3295
- return /* @__PURE__ */ jsx25(
3773
+ return /* @__PURE__ */ jsx27(
3296
3774
  ActionBarPrimitive.Root,
3297
3775
  {
3298
3776
  hideWhenRunning: true,
3299
3777
  autohide: "not-last",
3300
3778
  className: "aui-user-action-bar-root flex flex-col items-end",
3301
- children: /* @__PURE__ */ jsx25(ActionBarPrimitive.Edit, { asChild: true, children: /* @__PURE__ */ jsx25(TooltipIconButton, { tooltip: "Edit", className: "aui-user-action-edit p-4", children: /* @__PURE__ */ jsx25(PencilIcon, {}) }) })
3779
+ children: /* @__PURE__ */ jsx27(ActionBarPrimitive.Edit, { asChild: true, children: /* @__PURE__ */ jsx27(
3780
+ TooltipIconButton,
3781
+ {
3782
+ tooltip: "Edit",
3783
+ variant: "ghost",
3784
+ className: ASSISTANT_ACTION_ICON_CLASS,
3785
+ children: /* @__PURE__ */ jsx27(PencilIcon, { className: "size-3" })
3786
+ }
3787
+ ) })
3302
3788
  }
3303
3789
  );
3304
3790
  };
3305
3791
  var EditComposer = () => {
3306
- return /* @__PURE__ */ jsx25(MessagePrimitive2.Root, { className: "aui-edit-composer-wrapper mx-auto flex w-full max-w-(--thread-max-width) flex-col px-2 py-3", children: /* @__PURE__ */ jsxs14(ComposerPrimitive3.Root, { className: "aui-edit-composer-root ml-auto flex w-full max-w-[85%] flex-col rounded-2xl bg-muted", children: [
3307
- /* @__PURE__ */ jsx25(
3792
+ return /* @__PURE__ */ jsx27(MessagePrimitive2.Root, { className: "aui-edit-composer-wrapper mx-auto flex w-full max-w-(--thread-max-width) flex-col px-2 py-3", children: /* @__PURE__ */ jsxs15(ComposerPrimitive3.Root, { className: "aui-edit-composer-root ml-auto flex w-full max-w-[85%] flex-col rounded-2xl bg-muted", children: [
3793
+ /* @__PURE__ */ jsx27(
3308
3794
  ComposerPrimitive3.Input,
3309
3795
  {
3310
3796
  className: "aui-edit-composer-input min-h-14 w-full resize-none bg-transparent p-4 text-foreground text-sm outline-none",
3311
3797
  autoFocus: true
3312
3798
  }
3313
3799
  ),
3314
- /* @__PURE__ */ jsxs14("div", { className: "aui-edit-composer-footer mx-3 mb-3 flex items-center gap-2 self-end", children: [
3315
- /* @__PURE__ */ jsx25(ComposerPrimitive3.Cancel, { asChild: true, children: /* @__PURE__ */ jsx25(Button, { variant: "ghost", size: "sm", children: "Cancel" }) }),
3316
- /* @__PURE__ */ jsx25(ComposerPrimitive3.Send, { asChild: true, children: /* @__PURE__ */ jsx25(Button, { size: "sm", children: "Update" }) })
3800
+ /* @__PURE__ */ jsxs15("div", { className: "aui-edit-composer-footer mx-3 mb-3 flex items-center gap-2 self-end", children: [
3801
+ /* @__PURE__ */ jsx27(ComposerPrimitive3.Cancel, { asChild: true, children: /* @__PURE__ */ jsx27(TimbalV2Button, { variant: "ghost", size: "sm", children: "Cancel" }) }),
3802
+ /* @__PURE__ */ jsx27(ComposerPrimitive3.Send, { asChild: true, children: /* @__PURE__ */ jsx27(TimbalV2Button, { variant: "primary", size: "sm", children: "Update" }) })
3317
3803
  ] })
3318
3804
  ] }) });
3319
3805
  };
3320
3806
 
3321
3807
  // src/components/chat.tsx
3322
- import { jsx as jsx26 } from "react/jsx-runtime";
3808
+ import { jsx as jsx28 } from "react/jsx-runtime";
3323
3809
  function TimbalChat({
3324
3810
  workforceId,
3325
3811
  baseUrl,
@@ -3330,7 +3816,7 @@ function TimbalChat({
3330
3816
  debug,
3331
3817
  ...threadProps
3332
3818
  }) {
3333
- return /* @__PURE__ */ jsx26(
3819
+ return /* @__PURE__ */ jsx28(
3334
3820
  TimbalRuntimeProvider,
3335
3821
  {
3336
3822
  workforceId,
@@ -3340,7 +3826,7 @@ function TimbalChat({
3340
3826
  attachmentsUploadUrl,
3341
3827
  attachmentsAccept,
3342
3828
  debug,
3343
- children: /* @__PURE__ */ jsx26(Thread, { ...threadProps })
3829
+ children: /* @__PURE__ */ jsx28(Thread, { ...threadProps })
3344
3830
  }
3345
3831
  );
3346
3832
  }
@@ -3475,17 +3961,22 @@ When you call a tool that returns an artifact (\`make_chart\`, \`ask_question\`,
3475
3961
  import {
3476
3962
  ThreadPrimitive as ThreadPrimitive2,
3477
3963
  MessagePrimitive as MessagePrimitive3,
3964
+ MessagePartPrimitive as MessagePartPrimitive2,
3478
3965
  ComposerPrimitive as ComposerPrimitive4,
3479
3966
  ActionBarPrimitive as ActionBarPrimitive2,
3967
+ ActionBarMorePrimitive as ActionBarMorePrimitive2,
3968
+ ErrorPrimitive as ErrorPrimitive2,
3969
+ AuiIf as AuiIf3,
3480
3970
  AssistantRuntimeProvider as AssistantRuntimeProvider2,
3481
- useThread,
3971
+ useThread as useThread2,
3482
3972
  useThreadRuntime as useThreadRuntime4,
3483
3973
  useMessageRuntime,
3484
- useComposerRuntime as useComposerRuntime2
3974
+ useComposerRuntime as useComposerRuntime2,
3975
+ useAuiState as useAuiState3
3485
3976
  } from "@assistant-ui/react";
3486
3977
 
3487
3978
  // src/hooks/use-workforces.ts
3488
- import { useEffect as useEffect5, useMemo as useMemo6, useRef as useRef2, useState as useState8 } from "react";
3979
+ import { useEffect as useEffect5, useMemo as useMemo7, useRef as useRef2, useState as useState8 } from "react";
3489
3980
  function useWorkforces(options = {}) {
3490
3981
  const { baseUrl = "/api", fetch: fetchFn, pickInitial } = options;
3491
3982
  const [workforces, setWorkforces] = useState8([]);
@@ -3500,7 +3991,7 @@ function useWorkforces(options = {}) {
3500
3991
  useEffect5(() => {
3501
3992
  pickInitialRef.current = pickInitial;
3502
3993
  }, [pickInitial]);
3503
- const load = useMemo6(() => {
3994
+ const load = useMemo7(() => {
3504
3995
  return async () => {
3505
3996
  setIsLoading(true);
3506
3997
  setError(null);
@@ -3524,7 +4015,7 @@ function useWorkforces(options = {}) {
3524
4015
  useEffect5(() => {
3525
4016
  load();
3526
4017
  }, [load]);
3527
- const selected = useMemo6(
4018
+ const selected = useMemo7(
3528
4019
  () => workforces.find((w) => idOf(w) === selectedId),
3529
4020
  [workforces, selectedId]
3530
4021
  );
@@ -3543,8 +4034,8 @@ function idOf(item) {
3543
4034
  }
3544
4035
 
3545
4036
  // src/components/workforce-selector.tsx
3546
- import { ChevronDownIcon as ChevronDownIcon2 } from "lucide-react";
3547
- import { jsx as jsx27, jsxs as jsxs15 } from "react/jsx-runtime";
4037
+ import { ChevronDownIcon } from "lucide-react";
4038
+ import { jsx as jsx29, jsxs as jsxs16 } from "react/jsx-runtime";
3548
4039
  var WorkforceSelector = ({
3549
4040
  workforces,
3550
4041
  value,
@@ -3555,32 +4046,50 @@ var WorkforceSelector = ({
3555
4046
  }) => {
3556
4047
  if (workforces.length === 0) return null;
3557
4048
  if (hideWhenSingle && workforces.length === 1) return null;
3558
- return /* @__PURE__ */ jsxs15("div", { className: cn("aui-workforce-selector relative inline-flex items-center", className), children: [
3559
- /* @__PURE__ */ jsxs15(
3560
- "select",
3561
- {
3562
- 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",
3563
- value,
3564
- onChange: (e) => onChange(e.target.value),
3565
- "aria-label": placeholder,
3566
- children: [
3567
- !value && /* @__PURE__ */ jsx27("option", { value: "", children: placeholder }),
3568
- workforces.map((w) => {
3569
- const id = idOf2(w);
3570
- return /* @__PURE__ */ jsx27("option", { value: id, children: w.name ?? id }, id);
3571
- })
3572
- ]
3573
- }
3574
- ),
3575
- /* @__PURE__ */ jsx27(ChevronDownIcon2, { className: "aui-workforce-selector-icon pointer-events-none absolute right-1 size-3 text-muted-foreground" })
3576
- ] });
4049
+ return /* @__PURE__ */ jsxs16(
4050
+ "div",
4051
+ {
4052
+ className: cn(
4053
+ "aui-workforce-selector relative inline-flex items-center",
4054
+ studioTopbarPillHeightClass,
4055
+ studioSecondaryChromeClass,
4056
+ "rounded-full",
4057
+ className
4058
+ ),
4059
+ children: [
4060
+ /* @__PURE__ */ jsxs16(
4061
+ "select",
4062
+ {
4063
+ 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",
4064
+ value,
4065
+ onChange: (e) => onChange(e.target.value),
4066
+ "aria-label": placeholder,
4067
+ children: [
4068
+ !value && /* @__PURE__ */ jsx29("option", { value: "", children: placeholder }),
4069
+ workforces.map((w) => {
4070
+ const id = idOf2(w);
4071
+ return /* @__PURE__ */ jsx29("option", { value: id, children: w.name ?? id }, id);
4072
+ })
4073
+ ]
4074
+ }
4075
+ ),
4076
+ /* @__PURE__ */ jsx29(
4077
+ ChevronDownIcon,
4078
+ {
4079
+ className: "aui-workforce-selector-icon pointer-events-none absolute right-3 size-3.5 text-muted-foreground/70",
4080
+ "aria-hidden": true
4081
+ }
4082
+ )
4083
+ ]
4084
+ }
4085
+ );
3577
4086
  };
3578
4087
  function idOf2(item) {
3579
4088
  return item.id ?? item.uid ?? item.name ?? "";
3580
4089
  }
3581
4090
 
3582
4091
  // src/components/chat-shell.tsx
3583
- import { Fragment as Fragment3, jsx as jsx28, jsxs as jsxs16 } from "react/jsx-runtime";
4092
+ import { jsx as jsx30, jsxs as jsxs17 } from "react/jsx-runtime";
3584
4093
  var TimbalChatShell = ({
3585
4094
  workforceId,
3586
4095
  brand,
@@ -3592,54 +4101,62 @@ var TimbalChatShell = ({
3592
4101
  fetch: fetch2,
3593
4102
  ...chatProps
3594
4103
  }) => {
3595
- const {
3596
- workforces,
3597
- selectedId,
3598
- setSelectedId
3599
- } = useWorkforces({ baseUrl, fetch: fetch2 });
4104
+ const { workforces, selectedId, setSelectedId } = useWorkforces({
4105
+ baseUrl,
4106
+ fetch: fetch2
4107
+ });
3600
4108
  const effectiveId = workforceId ?? selectedId;
3601
4109
  const showSelector = !hideWorkforceSelector && !workforceId && workforces.length > 0;
3602
- return /* @__PURE__ */ jsxs16(
4110
+ return /* @__PURE__ */ jsxs17(
3603
4111
  "div",
3604
4112
  {
3605
4113
  className: cn(
3606
- "aui-chat-shell flex h-screen flex-col overflow-hidden",
4114
+ "aui-chat-shell relative flex h-dvh flex-col overflow-hidden bg-background",
3607
4115
  className
3608
4116
  ),
4117
+ style: studioChromeShellStyle,
3609
4118
  children: [
3610
- /* @__PURE__ */ jsxs16(
4119
+ /* @__PURE__ */ jsx30(
4120
+ "div",
4121
+ {
4122
+ className: cn(
4123
+ "pointer-events-none absolute inset-0 z-0",
4124
+ studioPlaygroundGradientClass
4125
+ ),
4126
+ "aria-hidden": true
4127
+ }
4128
+ ),
4129
+ /* @__PURE__ */ jsxs17(
3611
4130
  "header",
3612
4131
  {
3613
4132
  className: cn(
3614
- "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",
4133
+ "aui-chat-shell-header relative z-10 flex shrink-0 items-center justify-between px-4 pt-[var(--studio-topbar-gap)] pb-2",
3615
4134
  headerClassName
3616
4135
  ),
4136
+ style: { minHeight: "var(--studio-topbar-height)" },
3617
4137
  children: [
3618
- /* @__PURE__ */ jsxs16("div", { className: "flex items-center", children: [
4138
+ /* @__PURE__ */ jsxs17("div", { className: "flex min-w-0 items-center gap-2", children: [
3619
4139
  brand,
3620
- showSelector && /* @__PURE__ */ jsxs16(Fragment3, { children: [
3621
- /* @__PURE__ */ jsx28("div", { className: "mx-3.5 h-3.5 w-px bg-border" }),
3622
- /* @__PURE__ */ jsx28(
3623
- WorkforceSelector,
3624
- {
3625
- workforces,
3626
- value: selectedId,
3627
- onChange: setSelectedId
3628
- }
3629
- )
3630
- ] })
4140
+ showSelector && /* @__PURE__ */ jsx30(
4141
+ WorkforceSelector,
4142
+ {
4143
+ workforces,
4144
+ value: selectedId,
4145
+ onChange: setSelectedId
4146
+ }
4147
+ )
3631
4148
  ] }),
3632
- /* @__PURE__ */ jsx28("div", { className: "flex items-center gap-0.5", children: headerActions })
4149
+ /* @__PURE__ */ jsx30("div", { className: "flex shrink-0 items-center gap-1", children: headerActions })
3633
4150
  ]
3634
4151
  }
3635
4152
  ),
3636
- /* @__PURE__ */ jsx28(
4153
+ /* @__PURE__ */ jsx30(
3637
4154
  TimbalChat,
3638
4155
  {
3639
4156
  workforceId: effectiveId,
3640
4157
  baseUrl,
3641
4158
  fetch: fetch2,
3642
- className: "min-h-0 flex-1",
4159
+ className: "relative z-10 min-h-0 flex-1 bg-transparent",
3643
4160
  ...chatProps
3644
4161
  },
3645
4162
  effectiveId
@@ -3652,12 +4169,12 @@ var TimbalChatShell = ({
3652
4169
  // src/auth/provider.tsx
3653
4170
  import {
3654
4171
  createContext as createContext4,
3655
- useCallback as useCallback3,
4172
+ useCallback as useCallback4,
3656
4173
  useContext as useContext4,
3657
4174
  useEffect as useEffect6,
3658
4175
  useState as useState9
3659
4176
  } from "react";
3660
- import { jsx as jsx29 } from "react/jsx-runtime";
4177
+ import { jsx as jsx31 } from "react/jsx-runtime";
3661
4178
  function isInsideIframe() {
3662
4179
  try {
3663
4180
  return typeof window !== "undefined" && window.self !== window.top;
@@ -3741,7 +4258,7 @@ var SessionProvider = ({
3741
4258
  messageCleanup?.();
3742
4259
  };
3743
4260
  }, [enabled, embedded]);
3744
- const logout = useCallback3(() => {
4261
+ const logout = useCallback4(() => {
3745
4262
  clearTokens();
3746
4263
  setUser(null);
3747
4264
  const returnTo = encodeURIComponent(
@@ -3751,7 +4268,7 @@ var SessionProvider = ({
3751
4268
  () => window.location.href = `/api/auth/login?return_to=${returnTo}`
3752
4269
  );
3753
4270
  }, []);
3754
- return /* @__PURE__ */ jsx29(
4271
+ return /* @__PURE__ */ jsx31(
3755
4272
  SessionContext.Provider,
3756
4273
  {
3757
4274
  value: {
@@ -3768,7 +4285,7 @@ var SessionProvider = ({
3768
4285
 
3769
4286
  // src/auth/guard.tsx
3770
4287
  import { Loader2 } from "lucide-react";
3771
- import { jsx as jsx30 } from "react/jsx-runtime";
4288
+ import { jsx as jsx32 } from "react/jsx-runtime";
3772
4289
  var AuthGuard = ({
3773
4290
  children,
3774
4291
  requireAuth = false,
@@ -3779,7 +4296,7 @@ var AuthGuard = ({
3779
4296
  return children;
3780
4297
  }
3781
4298
  if (loading) {
3782
- return /* @__PURE__ */ jsx30("div", { className: "flex items-center justify-center h-screen", children: /* @__PURE__ */ jsx30(Loader2, { className: "w-8 h-8 animate-spin" }) });
4299
+ return /* @__PURE__ */ jsx32("div", { className: "flex items-center justify-center h-screen", children: /* @__PURE__ */ jsx32(Loader2, { className: "w-8 h-8 animate-spin" }) });
3783
4300
  }
3784
4301
  if (requireAuth && !isAuthenticated && !isEmbedded) {
3785
4302
  const returnTo = encodeURIComponent(
@@ -3793,11 +4310,13 @@ var AuthGuard = ({
3793
4310
  export {
3794
4311
  ARTIFACT_AGENT_INSTRUCTIONS,
3795
4312
  ARTIFACT_FENCE_LANGUAGES,
4313
+ ActionBarMorePrimitive2 as ActionBarMorePrimitive,
3796
4314
  ActionBarPrimitive2 as ActionBarPrimitive,
3797
4315
  ArtifactCard,
3798
4316
  ArtifactRegistryProvider,
3799
4317
  ArtifactView,
3800
4318
  AssistantRuntimeProvider2 as AssistantRuntimeProvider,
4319
+ AuiIf3 as AuiIf,
3801
4320
  AuthGuard,
3802
4321
  Avatar,
3803
4322
  AvatarFallback,
@@ -3816,23 +4335,44 @@ export {
3816
4335
  DialogPortal,
3817
4336
  DialogTitle,
3818
4337
  DialogTrigger,
4338
+ ErrorPrimitive2 as ErrorPrimitive,
3819
4339
  HtmlArtifactView,
3820
4340
  JsonArtifactView,
3821
4341
  MarkdownText,
4342
+ MessagePartPrimitive2 as MessagePartPrimitive,
3822
4343
  MessagePrimitive3 as MessagePrimitive,
3823
4344
  QuestionArtifactView,
4345
+ STUDIO_INSET_LEFT,
4346
+ STUDIO_PILL_HEIGHT,
4347
+ STUDIO_SIDEBAR_GAP,
4348
+ STUDIO_SIDEBAR_WIDTH,
4349
+ STUDIO_TOPBAR_GAP,
4350
+ STUDIO_TOPBAR_HEIGHT,
3824
4351
  SessionProvider,
3825
4352
  Shimmer,
3826
4353
  Suggestions,
3827
4354
  syntax_highlighter_default as SyntaxHighlighter,
4355
+ TIMBAL_V2_BORDER,
4356
+ TIMBAL_V2_FILL,
4357
+ TIMBAL_V2_LABEL,
4358
+ TIMBAL_V2_PILL_SURFACE,
4359
+ TIMBAL_V2_SECONDARY_CHROME,
4360
+ TIMBAL_V2_SHADOW,
4361
+ TIMBAL_V2_SIZE_HEIGHT,
4362
+ TIMBAL_V2_SIZE_ICON,
4363
+ TIMBAL_V2_SIZE_LABEL_PX,
3828
4364
  TableArtifactView,
3829
4365
  Thread,
3830
4366
  ThreadPrimitive2 as ThreadPrimitive,
3831
4367
  TimbalChat,
3832
4368
  TimbalChatShell,
3833
4369
  TimbalRuntimeProvider,
4370
+ TimbalV2Button,
3834
4371
  ToolArtifactFallback,
4372
+ ToolBodyPresence,
3835
4373
  ToolFallback,
4374
+ ToolMotion,
4375
+ ToolPresence,
3836
4376
  Tooltip,
3837
4377
  TooltipContent,
3838
4378
  TooltipIconButton,
@@ -3859,6 +4399,7 @@ export {
3859
4399
  isArtifact,
3860
4400
  isArtifactFenceLanguage,
3861
4401
  isUiBinding,
4402
+ luxuryEase,
3862
4403
  parseArtifactFromToolResult,
3863
4404
  parseSSELine2 as parseSSELine,
3864
4405
  refreshAccessToken,
@@ -3868,15 +4409,42 @@ export {
3868
4409
  setPath,
3869
4410
  setRefreshToken,
3870
4411
  splitMarkdownByArtifacts,
4412
+ studioArtifactShellClass,
4413
+ studioChromeShellStyle,
4414
+ studioComposeInputShellClass,
4415
+ studioComposerIoWellClass,
4416
+ studioIntegrationBorder,
4417
+ studioIntegrationCardClass,
4418
+ studioIntegrationIconTileClass,
4419
+ studioIntegrationSurfaceSolid,
4420
+ studioListRowButtonClass,
4421
+ studioPillSurfaceClass,
4422
+ studioPlaygroundGradientClass,
4423
+ studioQuestionOptionClass,
4424
+ studioQuestionOptionSelectedClass,
4425
+ studioSecondaryChromeClass,
4426
+ studioTimelineActionClass,
4427
+ studioTimelineBodyPadClass,
4428
+ studioTimelineChevronClass,
4429
+ studioTimelineDetailClass,
4430
+ studioTimelineRowButtonClass,
4431
+ studioTimelineShimmerActionClass,
4432
+ studioTimelineTextClass,
4433
+ studioToolCardShellClass,
4434
+ studioTopbarIconPillClass,
4435
+ studioTopbarPillHeightClass,
4436
+ toolPresenceTransition,
3871
4437
  useArtifactRegistry,
4438
+ useAuiState3 as useAuiState,
3872
4439
  useComposerRuntime2 as useComposerRuntime,
3873
4440
  useMessageRuntime,
3874
4441
  useResolvedSuggestions,
3875
4442
  useSession,
3876
- useThread,
4443
+ useThread2 as useThread,
3877
4444
  useThreadRuntime4 as useThreadRuntime,
3878
4445
  useTimbalRuntime,
3879
4446
  useTimbalStream,
4447
+ useToolRunning,
3880
4448
  useUiCustomNodeRegistry,
3881
4449
  useUiDispatch,
3882
4450
  useUiEventEmitter,