@lukeashford/aurelius 2.20.0 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -38,6 +38,8 @@ __export(index_exports, {
38
38
  Alert: () => Alert,
39
39
  AlertDialog: () => AlertDialog,
40
40
  ArtifactCard: () => ArtifactCard,
41
+ ArtifactGroup: () => ArtifactGroup,
42
+ ArtifactVariantStack: () => ArtifactVariantStack,
41
43
  ArtifactsPanel: () => ArtifactsPanel,
42
44
  ArtifactsPanelToggle: () => ArtifactsPanelToggle,
43
45
  AttachmentPreview: () => AttachmentPreview,
@@ -88,6 +90,7 @@ __export(index_exports, {
88
90
  ListItemText: () => ListItemText,
89
91
  ListSubheader: () => ListSubheader,
90
92
  MarkdownContent: () => MarkdownContent,
93
+ MediaIcon: () => MediaIcon,
91
94
  Menu: () => Menu,
92
95
  MenuContent: () => MenuContent,
93
96
  MenuItem: () => MenuItem,
@@ -97,6 +100,7 @@ __export(index_exports, {
97
100
  Message: () => Message,
98
101
  MessageActions: () => MessageActions,
99
102
  Modal: () => Modal,
103
+ NODE_TYPES: () => NODE_TYPES,
100
104
  Navbar: () => Navbar,
101
105
  NavbarBrand: () => NavbarBrand,
102
106
  NavbarContent: () => NavbarContent,
@@ -141,9 +145,12 @@ __export(index_exports, {
141
145
  ThinkingIndicator: () => ThinkingIndicator,
142
146
  ToastProvider: () => ToastProvider,
143
147
  TodosList: () => TodosList,
148
+ ToolPanelContainer: () => ToolPanelContainer,
149
+ ToolSidebar: () => ToolSidebar,
144
150
  Tooltip: () => Tooltip,
145
151
  VideoCard: () => VideoCard,
146
152
  addMessageToTree: () => addMessageToTree,
153
+ areAllTasksSettled: () => areAllTasksSettled,
147
154
  createEmptyTree: () => createEmptyTree,
148
155
  createPreviewUrl: () => createPreviewUrl,
149
156
  generateId: () => generateId,
@@ -155,7 +162,7 @@ __export(index_exports, {
155
162
  revokePreviewUrl: () => revokePreviewUrl,
156
163
  switchBranch: () => switchBranch,
157
164
  updateNodeContent: () => updateNodeContent,
158
- useArtifacts: () => useArtifacts,
165
+ useArtifactTreeNavigation: () => useArtifactTreeNavigation,
159
166
  useResizable: () => useResizable,
160
167
  useScrollAnchor: () => useScrollAnchor,
161
168
  useToast: () => useToast,
@@ -2334,7 +2341,7 @@ var Modal = ({ isOpen, onClose, title, children, className }) => {
2334
2341
  role: "dialog",
2335
2342
  "aria-modal": "true",
2336
2343
  className: cx(
2337
- "bg-charcoal border border-gold/30 shadow-2xl z-50 w-full max-w-lg p-6 rounded-none relative",
2344
+ "bg-charcoal border border-gold/30 shadow-2xl z-50 w-full max-w-lg p-6 rounded-none relative flex flex-col",
2338
2345
  className
2339
2346
  ),
2340
2347
  "data-state": "open",
@@ -2349,7 +2356,7 @@ var Modal = ({ isOpen, onClose, title, children, className }) => {
2349
2356
  /* @__PURE__ */ import_react30.default.createElement(import_lucide_react5.X, { className: "h-5 w-5" }),
2350
2357
  /* @__PURE__ */ import_react30.default.createElement("span", { className: "sr-only" }, "Close")
2351
2358
  )),
2352
- /* @__PURE__ */ import_react30.default.createElement("div", null, children)
2359
+ /* @__PURE__ */ import_react30.default.createElement("div", { className: "overflow-y-auto min-h-0" }, children)
2353
2360
  )
2354
2361
  );
2355
2362
  return (0, import_react_dom2.createPortal)(content, document.body);
@@ -3611,9 +3618,9 @@ function LayersIcon({ className, ...props }) {
3611
3618
  );
3612
3619
  }
3613
3620
 
3614
- // src/components/icons/PlusIcon.tsx
3621
+ // src/components/icons/MediaIcon.tsx
3615
3622
  var import_react47 = __toESM(require("react"));
3616
- function PlusIcon({ className, ...props }) {
3623
+ function MediaIcon({ className, ...props }) {
3617
3624
  return /* @__PURE__ */ import_react47.default.createElement(
3618
3625
  "svg",
3619
3626
  {
@@ -3624,6 +3631,29 @@ function PlusIcon({ className, ...props }) {
3624
3631
  ...props
3625
3632
  },
3626
3633
  /* @__PURE__ */ import_react47.default.createElement(
3634
+ "path",
3635
+ {
3636
+ fillRule: "evenodd",
3637
+ d: "M2 4.5A1.5 1.5 0 013.5 3h13A1.5 1.5 0 0118 4.5v11a1.5 1.5 0 01-1.5 1.5h-13A1.5 1.5 0 012 15.5v-11zM4 5v1h1V5H4zm2 0v1h1V5H6zm7 0v1h1V5h-1zm2 0v1h1V5h-1zM4 14v1h1v-1H4zm2 0v1h1v-1H6zm7 0v1h1v-1h-1zm2 0v1h1v-1h-1zM8 8.118a.5.5 0 01.757-.429l4 2.382a.5.5 0 010 .858l-4 2.382A.5.5 0 018 12.882V8.118z",
3638
+ clipRule: "evenodd"
3639
+ }
3640
+ )
3641
+ );
3642
+ }
3643
+
3644
+ // src/components/icons/PlusIcon.tsx
3645
+ var import_react48 = __toESM(require("react"));
3646
+ function PlusIcon({ className, ...props }) {
3647
+ return /* @__PURE__ */ import_react48.default.createElement(
3648
+ "svg",
3649
+ {
3650
+ xmlns: "http://www.w3.org/2000/svg",
3651
+ viewBox: "0 0 20 20",
3652
+ fill: "currentColor",
3653
+ className,
3654
+ ...props
3655
+ },
3656
+ /* @__PURE__ */ import_react48.default.createElement(
3627
3657
  "path",
3628
3658
  {
3629
3659
  d: "M10.75 4.75a.75.75 0 00-1.5 0v4.5h-4.5a.75.75 0 000 1.5h4.5v4.5a.75.75 0 001.5 0v-4.5h4.5a.75.75 0 000-1.5h-4.5v-4.5z"
@@ -3633,9 +3663,9 @@ function PlusIcon({ className, ...props }) {
3633
3663
  }
3634
3664
 
3635
3665
  // src/components/icons/CheckSquareIcon.tsx
3636
- var import_react48 = __toESM(require("react"));
3666
+ var import_react49 = __toESM(require("react"));
3637
3667
  function CheckSquareIcon({ className, ...props }) {
3638
- return /* @__PURE__ */ import_react48.default.createElement(
3668
+ return /* @__PURE__ */ import_react49.default.createElement(
3639
3669
  "div",
3640
3670
  {
3641
3671
  className: cx(
@@ -3644,14 +3674,14 @@ function CheckSquareIcon({ className, ...props }) {
3644
3674
  ),
3645
3675
  ...props
3646
3676
  },
3647
- /* @__PURE__ */ import_react48.default.createElement(
3677
+ /* @__PURE__ */ import_react49.default.createElement(
3648
3678
  "svg",
3649
3679
  {
3650
3680
  viewBox: "0 0 16 16",
3651
3681
  fill: "none",
3652
3682
  className: "absolute inset-0 w-full h-full p-0.5"
3653
3683
  },
3654
- /* @__PURE__ */ import_react48.default.createElement(
3684
+ /* @__PURE__ */ import_react49.default.createElement(
3655
3685
  "path",
3656
3686
  {
3657
3687
  d: "M3 8l3 3 7-7",
@@ -3667,9 +3697,9 @@ function CheckSquareIcon({ className, ...props }) {
3667
3697
  }
3668
3698
 
3669
3699
  // src/components/icons/EmptySquareIcon.tsx
3670
- var import_react49 = __toESM(require("react"));
3700
+ var import_react50 = __toESM(require("react"));
3671
3701
  function EmptySquareIcon({ className, ...props }) {
3672
- return /* @__PURE__ */ import_react49.default.createElement(
3702
+ return /* @__PURE__ */ import_react50.default.createElement(
3673
3703
  "div",
3674
3704
  {
3675
3705
  className: cx(
@@ -3682,9 +3712,9 @@ function EmptySquareIcon({ className, ...props }) {
3682
3712
  }
3683
3713
 
3684
3714
  // src/components/icons/CrossSquareIcon.tsx
3685
- var import_react50 = __toESM(require("react"));
3715
+ var import_react51 = __toESM(require("react"));
3686
3716
  function CrossSquareIcon({ className, variant = "cancelled", ...props }) {
3687
- return /* @__PURE__ */ import_react50.default.createElement(
3717
+ return /* @__PURE__ */ import_react51.default.createElement(
3688
3718
  "div",
3689
3719
  {
3690
3720
  className: cx(
@@ -3694,14 +3724,14 @@ function CrossSquareIcon({ className, variant = "cancelled", ...props }) {
3694
3724
  ),
3695
3725
  ...props
3696
3726
  },
3697
- /* @__PURE__ */ import_react50.default.createElement(
3727
+ /* @__PURE__ */ import_react51.default.createElement(
3698
3728
  "svg",
3699
3729
  {
3700
3730
  viewBox: "0 0 16 16",
3701
3731
  fill: "none",
3702
3732
  className: "absolute inset-0 w-full h-full p-0.5"
3703
3733
  },
3704
- /* @__PURE__ */ import_react50.default.createElement(
3734
+ /* @__PURE__ */ import_react51.default.createElement(
3705
3735
  "path",
3706
3736
  {
3707
3737
  d: "M4 4l8 8M12 4l-8 8",
@@ -3716,15 +3746,15 @@ function CrossSquareIcon({ className, variant = "cancelled", ...props }) {
3716
3746
  }
3717
3747
 
3718
3748
  // src/components/icons/SquareLoaderIcon.tsx
3719
- var import_react51 = __toESM(require("react"));
3749
+ var import_react52 = __toESM(require("react"));
3720
3750
  function SquareLoaderIcon({ className, ...props }) {
3721
- return /* @__PURE__ */ import_react51.default.createElement("div", { className: cx("relative w-4 h-4 flex-shrink-0", className), ...props }, /* @__PURE__ */ import_react51.default.createElement(
3751
+ return /* @__PURE__ */ import_react52.default.createElement("div", { className: cx("relative w-4 h-4 flex-shrink-0", className), ...props }, /* @__PURE__ */ import_react52.default.createElement(
3722
3752
  "svg",
3723
3753
  {
3724
3754
  viewBox: "0 0 16 16",
3725
3755
  className: "w-full h-full animate-snake-spin"
3726
3756
  },
3727
- /* @__PURE__ */ import_react51.default.createElement(
3757
+ /* @__PURE__ */ import_react52.default.createElement(
3728
3758
  "rect",
3729
3759
  {
3730
3760
  x: "1",
@@ -3737,7 +3767,7 @@ function SquareLoaderIcon({ className, ...props }) {
3737
3767
  className: "text-ash/40"
3738
3768
  }
3739
3769
  ),
3740
- /* @__PURE__ */ import_react51.default.createElement(
3770
+ /* @__PURE__ */ import_react52.default.createElement(
3741
3771
  "rect",
3742
3772
  {
3743
3773
  x: "1",
@@ -3756,10 +3786,10 @@ function SquareLoaderIcon({ className, ...props }) {
3756
3786
  }
3757
3787
 
3758
3788
  // src/components/Message.tsx
3759
- var import_react53 = __toESM(require("react"));
3789
+ var import_react54 = __toESM(require("react"));
3760
3790
 
3761
3791
  // src/components/MarkdownContent.tsx
3762
- var import_react52 = __toESM(require("react"));
3792
+ var import_react53 = __toESM(require("react"));
3763
3793
  var import_dompurify = __toESM(require("dompurify"));
3764
3794
  var import_marked = require("marked");
3765
3795
  var DEFAULT_SANITIZE_CONFIG = {
@@ -3830,7 +3860,7 @@ var DEFAULT_SANITIZE_CONFIG = {
3830
3860
  ALLOWED_URI_REGEXP: /^(?:(?:https?|mailto|tel):|[^a-z]|[a-z+.-]+(?:[^a-z+.\-:]|$))/i
3831
3861
  };
3832
3862
  function useDOMPurifySetup() {
3833
- (0, import_react52.useMemo)(() => {
3863
+ (0, import_react53.useMemo)(() => {
3834
3864
  import_dompurify.default.addHook("afterSanitizeAttributes", (node) => {
3835
3865
  if (node.tagName === "A") {
3836
3866
  node.setAttribute("target", "_blank");
@@ -3866,10 +3896,10 @@ function injectStreamingCursor(html, cursorClassName) {
3866
3896
  target.insertAdjacentHTML("beforeend", cursorHtml);
3867
3897
  return container.innerHTML;
3868
3898
  }
3869
- var MarkdownContent = import_react52.default.forwardRef(
3899
+ var MarkdownContent = import_react53.default.forwardRef(
3870
3900
  ({ className, content, isMarkdown = true, sanitizeConfig, isStreaming, cursorClassName, ...rest }, ref) => {
3871
3901
  useDOMPurifySetup();
3872
- const sanitizedHtml = (0, import_react52.useMemo)(() => {
3902
+ const sanitizedHtml = (0, import_react53.useMemo)(() => {
3873
3903
  if (!content && !isStreaming) {
3874
3904
  return "";
3875
3905
  }
@@ -3891,7 +3921,7 @@ var MarkdownContent = import_react52.default.forwardRef(
3891
3921
  }
3892
3922
  return sanitized;
3893
3923
  }, [content, sanitizeConfig, isStreaming, cursorClassName]);
3894
- return /* @__PURE__ */ import_react52.default.createElement(
3924
+ return /* @__PURE__ */ import_react53.default.createElement(
3895
3925
  "div",
3896
3926
  {
3897
3927
  ref,
@@ -3909,7 +3939,7 @@ var variantStyles2 = {
3909
3939
  user: "bg-gold text-obsidian ml-auto",
3910
3940
  assistant: "bg-charcoal border border-ash text-white mr-auto"
3911
3941
  };
3912
- var ActionButton = ({ onClick, label, children, className, disabled }) => /* @__PURE__ */ import_react53.default.createElement(
3942
+ var ActionButton = ({ onClick, label, children, className, disabled }) => /* @__PURE__ */ import_react54.default.createElement(
3913
3943
  "button",
3914
3944
  {
3915
3945
  type: "button",
@@ -3925,7 +3955,7 @@ var ActionButton = ({ onClick, label, children, className, disabled }) => /* @__
3925
3955
  },
3926
3956
  children
3927
3957
  );
3928
- var CopyIcon = () => /* @__PURE__ */ import_react53.default.createElement(
3958
+ var CopyIcon = () => /* @__PURE__ */ import_react54.default.createElement(
3929
3959
  "svg",
3930
3960
  {
3931
3961
  xmlns: "http://www.w3.org/2000/svg",
@@ -3937,10 +3967,10 @@ var CopyIcon = () => /* @__PURE__ */ import_react53.default.createElement(
3937
3967
  strokeLinejoin: "round",
3938
3968
  className: "w-3.5 h-3.5"
3939
3969
  },
3940
- /* @__PURE__ */ import_react53.default.createElement("rect", { width: "14", height: "14", x: "8", y: "8", rx: "2", ry: "2" }),
3941
- /* @__PURE__ */ import_react53.default.createElement("path", { d: "M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2" })
3970
+ /* @__PURE__ */ import_react54.default.createElement("rect", { width: "14", height: "14", x: "8", y: "8", rx: "2", ry: "2" }),
3971
+ /* @__PURE__ */ import_react54.default.createElement("path", { d: "M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2" })
3942
3972
  );
3943
- var CheckIcon = () => /* @__PURE__ */ import_react53.default.createElement(
3973
+ var CheckIcon = () => /* @__PURE__ */ import_react54.default.createElement(
3944
3974
  "svg",
3945
3975
  {
3946
3976
  xmlns: "http://www.w3.org/2000/svg",
@@ -3952,9 +3982,9 @@ var CheckIcon = () => /* @__PURE__ */ import_react53.default.createElement(
3952
3982
  strokeLinejoin: "round",
3953
3983
  className: "w-3.5 h-3.5 text-success"
3954
3984
  },
3955
- /* @__PURE__ */ import_react53.default.createElement("polyline", { points: "20 6 9 17 4 12" })
3985
+ /* @__PURE__ */ import_react54.default.createElement("polyline", { points: "20 6 9 17 4 12" })
3956
3986
  );
3957
- var PencilIcon = () => /* @__PURE__ */ import_react53.default.createElement(
3987
+ var PencilIcon = () => /* @__PURE__ */ import_react54.default.createElement(
3958
3988
  "svg",
3959
3989
  {
3960
3990
  xmlns: "http://www.w3.org/2000/svg",
@@ -3966,10 +3996,10 @@ var PencilIcon = () => /* @__PURE__ */ import_react53.default.createElement(
3966
3996
  strokeLinejoin: "round",
3967
3997
  className: "w-3.5 h-3.5"
3968
3998
  },
3969
- /* @__PURE__ */ import_react53.default.createElement("path", { d: "M17 3a2.85 2.83 0 1 1 4 4L7.5 20.5 2 22l1.5-5.5Z" }),
3970
- /* @__PURE__ */ import_react53.default.createElement("path", { d: "m15 5 4 4" })
3999
+ /* @__PURE__ */ import_react54.default.createElement("path", { d: "M17 3a2.85 2.83 0 1 1 4 4L7.5 20.5 2 22l1.5-5.5Z" }),
4000
+ /* @__PURE__ */ import_react54.default.createElement("path", { d: "m15 5 4 4" })
3971
4001
  );
3972
- var RetryIcon = () => /* @__PURE__ */ import_react53.default.createElement(
4002
+ var RetryIcon = () => /* @__PURE__ */ import_react54.default.createElement(
3973
4003
  "svg",
3974
4004
  {
3975
4005
  xmlns: "http://www.w3.org/2000/svg",
@@ -3981,12 +4011,12 @@ var RetryIcon = () => /* @__PURE__ */ import_react53.default.createElement(
3981
4011
  strokeLinejoin: "round",
3982
4012
  className: "w-3.5 h-3.5"
3983
4013
  },
3984
- /* @__PURE__ */ import_react53.default.createElement("path", { d: "M3 12a9 9 0 0 1 9-9 9.75 9.75 0 0 1 6.74 2.74L21 8" }),
3985
- /* @__PURE__ */ import_react53.default.createElement("path", { d: "M21 3v5h-5" }),
3986
- /* @__PURE__ */ import_react53.default.createElement("path", { d: "M21 12a9 9 0 0 1-9 9 9.75 9.75 0 0 1-6.74-2.74L3 16" }),
3987
- /* @__PURE__ */ import_react53.default.createElement("path", { d: "M8 16H3v5" })
4014
+ /* @__PURE__ */ import_react54.default.createElement("path", { d: "M3 12a9 9 0 0 1 9-9 9.75 9.75 0 0 1 6.74 2.74L21 8" }),
4015
+ /* @__PURE__ */ import_react54.default.createElement("path", { d: "M21 3v5h-5" }),
4016
+ /* @__PURE__ */ import_react54.default.createElement("path", { d: "M21 12a9 9 0 0 1-9 9 9.75 9.75 0 0 1-6.74-2.74L3 16" }),
4017
+ /* @__PURE__ */ import_react54.default.createElement("path", { d: "M8 16H3v5" })
3988
4018
  );
3989
- var ChevronLeftIcon2 = () => /* @__PURE__ */ import_react53.default.createElement(
4019
+ var ChevronLeftIcon2 = () => /* @__PURE__ */ import_react54.default.createElement(
3990
4020
  "svg",
3991
4021
  {
3992
4022
  xmlns: "http://www.w3.org/2000/svg",
@@ -3998,9 +4028,9 @@ var ChevronLeftIcon2 = () => /* @__PURE__ */ import_react53.default.createElemen
3998
4028
  strokeLinejoin: "round",
3999
4029
  className: "w-3 h-3"
4000
4030
  },
4001
- /* @__PURE__ */ import_react53.default.createElement("path", { d: "m15 18-6-6 6-6" })
4031
+ /* @__PURE__ */ import_react54.default.createElement("path", { d: "m15 18-6-6 6-6" })
4002
4032
  );
4003
- var ChevronRightIcon2 = () => /* @__PURE__ */ import_react53.default.createElement(
4033
+ var ChevronRightIcon2 = () => /* @__PURE__ */ import_react54.default.createElement(
4004
4034
  "svg",
4005
4035
  {
4006
4036
  xmlns: "http://www.w3.org/2000/svg",
@@ -4012,9 +4042,9 @@ var ChevronRightIcon2 = () => /* @__PURE__ */ import_react53.default.createEleme
4012
4042
  strokeLinejoin: "round",
4013
4043
  className: "w-3 h-3"
4014
4044
  },
4015
- /* @__PURE__ */ import_react53.default.createElement("path", { d: "m9 18 6-6-6-6" })
4045
+ /* @__PURE__ */ import_react54.default.createElement("path", { d: "m9 18 6-6-6-6" })
4016
4046
  );
4017
- var GitBranchIcon = () => /* @__PURE__ */ import_react53.default.createElement(
4047
+ var GitBranchIcon = () => /* @__PURE__ */ import_react54.default.createElement(
4018
4048
  "svg",
4019
4049
  {
4020
4050
  xmlns: "http://www.w3.org/2000/svg",
@@ -4026,12 +4056,12 @@ var GitBranchIcon = () => /* @__PURE__ */ import_react53.default.createElement(
4026
4056
  strokeLinejoin: "round",
4027
4057
  className: "w-3 h-3 mr-0.5 text-silver/50"
4028
4058
  },
4029
- /* @__PURE__ */ import_react53.default.createElement("line", { x1: "6", x2: "6", y1: "3", y2: "15" }),
4030
- /* @__PURE__ */ import_react53.default.createElement("circle", { cx: "18", cy: "6", r: "3" }),
4031
- /* @__PURE__ */ import_react53.default.createElement("circle", { cx: "6", cy: "18", r: "3" }),
4032
- /* @__PURE__ */ import_react53.default.createElement("path", { d: "M18 9a9 9 0 0 1-9 9" })
4059
+ /* @__PURE__ */ import_react54.default.createElement("line", { x1: "6", x2: "6", y1: "3", y2: "15" }),
4060
+ /* @__PURE__ */ import_react54.default.createElement("circle", { cx: "18", cy: "6", r: "3" }),
4061
+ /* @__PURE__ */ import_react54.default.createElement("circle", { cx: "6", cy: "18", r: "3" }),
4062
+ /* @__PURE__ */ import_react54.default.createElement("path", { d: "M18 9a9 9 0 0 1-9 9" })
4033
4063
  );
4034
- var XIcon = () => /* @__PURE__ */ import_react53.default.createElement(
4064
+ var XIcon = () => /* @__PURE__ */ import_react54.default.createElement(
4035
4065
  "svg",
4036
4066
  {
4037
4067
  xmlns: "http://www.w3.org/2000/svg",
@@ -4043,10 +4073,10 @@ var XIcon = () => /* @__PURE__ */ import_react53.default.createElement(
4043
4073
  strokeLinejoin: "round",
4044
4074
  className: "w-4 h-4"
4045
4075
  },
4046
- /* @__PURE__ */ import_react53.default.createElement("path", { d: "M18 6 6 18" }),
4047
- /* @__PURE__ */ import_react53.default.createElement("path", { d: "m6 6 12 12" })
4076
+ /* @__PURE__ */ import_react54.default.createElement("path", { d: "M18 6 6 18" }),
4077
+ /* @__PURE__ */ import_react54.default.createElement("path", { d: "m6 6 12 12" })
4048
4078
  );
4049
- var SendIcon = () => /* @__PURE__ */ import_react53.default.createElement(
4079
+ var SendIcon = () => /* @__PURE__ */ import_react54.default.createElement(
4050
4080
  "svg",
4051
4081
  {
4052
4082
  xmlns: "http://www.w3.org/2000/svg",
@@ -4058,10 +4088,10 @@ var SendIcon = () => /* @__PURE__ */ import_react53.default.createElement(
4058
4088
  strokeLinejoin: "round",
4059
4089
  className: "w-4 h-4"
4060
4090
  },
4061
- /* @__PURE__ */ import_react53.default.createElement("path", { d: "m22 2-7 20-4-9-9-4Z" }),
4062
- /* @__PURE__ */ import_react53.default.createElement("path", { d: "M22 2 11 13" })
4091
+ /* @__PURE__ */ import_react54.default.createElement("path", { d: "m22 2-7 20-4-9-9-4Z" }),
4092
+ /* @__PURE__ */ import_react54.default.createElement("path", { d: "M22 2 11 13" })
4063
4093
  );
4064
- var Message = import_react53.default.forwardRef(
4094
+ var Message = import_react54.default.forwardRef(
4065
4095
  ({
4066
4096
  variant = "assistant",
4067
4097
  className,
@@ -4073,13 +4103,13 @@ var Message = import_react53.default.forwardRef(
4073
4103
  ...rest
4074
4104
  }, ref) => {
4075
4105
  const isUser = variant === "user";
4076
- const [copied, setCopied] = (0, import_react53.useState)(false);
4077
- const [isEditing, setIsEditing] = (0, import_react53.useState)(false);
4078
- const [editValue, setEditValue] = (0, import_react53.useState)(content);
4079
- const textareaRef = (0, import_react53.useRef)(null);
4106
+ const [copied, setCopied] = (0, import_react54.useState)(false);
4107
+ const [isEditing, setIsEditing] = (0, import_react54.useState)(false);
4108
+ const [editValue, setEditValue] = (0, import_react54.useState)(content);
4109
+ const textareaRef = (0, import_react54.useRef)(null);
4080
4110
  const showBranchNav = branchInfo && branchInfo.total > 1;
4081
4111
  const showActions = actions && !hideActions && !isStreaming;
4082
- (0, import_react53.useEffect)(() => {
4112
+ (0, import_react54.useEffect)(() => {
4083
4113
  if (isEditing && textareaRef.current) {
4084
4114
  const textarea = textareaRef.current;
4085
4115
  textarea.style.height = "auto";
@@ -4133,7 +4163,7 @@ var Message = import_react53.default.forwardRef(
4133
4163
  textarea.style.height = "auto";
4134
4164
  textarea.style.height = `${textarea.scrollHeight}px`;
4135
4165
  };
4136
- return /* @__PURE__ */ import_react53.default.createElement(
4166
+ return /* @__PURE__ */ import_react54.default.createElement(
4137
4167
  "div",
4138
4168
  {
4139
4169
  ref,
@@ -4144,7 +4174,7 @@ var Message = import_react53.default.forwardRef(
4144
4174
  ),
4145
4175
  ...rest
4146
4176
  },
4147
- isUser && isEditing ? /* @__PURE__ */ import_react53.default.createElement("div", { className: "w-full max-w-11/12" }, /* @__PURE__ */ import_react53.default.createElement("div", { className: "relative bg-gold" }, /* @__PURE__ */ import_react53.default.createElement(
4177
+ isUser && isEditing ? /* @__PURE__ */ import_react54.default.createElement("div", { className: "w-full max-w-11/12" }, /* @__PURE__ */ import_react54.default.createElement("div", { className: "relative bg-gold" }, /* @__PURE__ */ import_react54.default.createElement(
4148
4178
  "textarea",
4149
4179
  {
4150
4180
  ref: textareaRef,
@@ -4154,7 +4184,7 @@ var Message = import_react53.default.forwardRef(
4154
4184
  className: "w-full bg-transparent text-obsidian px-3 py-2 pr-20 resize-none outline-none min-h-10 text-sm",
4155
4185
  rows: 1
4156
4186
  }
4157
- ), /* @__PURE__ */ import_react53.default.createElement("div", { className: "absolute right-1 top-1/2 -translate-y-1/2 flex gap-0.5" }, /* @__PURE__ */ import_react53.default.createElement(
4187
+ ), /* @__PURE__ */ import_react54.default.createElement("div", { className: "absolute right-1 top-1/2 -translate-y-1/2 flex gap-0.5" }, /* @__PURE__ */ import_react54.default.createElement(
4158
4188
  "button",
4159
4189
  {
4160
4190
  type: "button",
@@ -4162,8 +4192,8 @@ var Message = import_react53.default.forwardRef(
4162
4192
  className: "p-1.5 text-obsidian/60 hover:text-obsidian transition-colors",
4163
4193
  "aria-label": "Cancel edit"
4164
4194
  },
4165
- /* @__PURE__ */ import_react53.default.createElement(XIcon, null)
4166
- ), /* @__PURE__ */ import_react53.default.createElement(
4195
+ /* @__PURE__ */ import_react54.default.createElement(XIcon, null)
4196
+ ), /* @__PURE__ */ import_react54.default.createElement(
4167
4197
  "button",
4168
4198
  {
4169
4199
  type: "button",
@@ -4172,8 +4202,8 @@ var Message = import_react53.default.forwardRef(
4172
4202
  className: "p-1.5 text-obsidian/60 hover:text-obsidian transition-colors disabled:opacity-30",
4173
4203
  "aria-label": "Submit edit"
4174
4204
  },
4175
- /* @__PURE__ */ import_react53.default.createElement(SendIcon, null)
4176
- )))) : /* @__PURE__ */ import_react53.default.createElement(
4205
+ /* @__PURE__ */ import_react54.default.createElement(SendIcon, null)
4206
+ )))) : /* @__PURE__ */ import_react54.default.createElement(
4177
4207
  "div",
4178
4208
  {
4179
4209
  className: cx(
@@ -4181,7 +4211,7 @@ var Message = import_react53.default.forwardRef(
4181
4211
  variantStyles2[variant]
4182
4212
  )
4183
4213
  },
4184
- /* @__PURE__ */ import_react53.default.createElement(
4214
+ /* @__PURE__ */ import_react54.default.createElement(
4185
4215
  MarkdownContent,
4186
4216
  {
4187
4217
  content,
@@ -4191,17 +4221,17 @@ var Message = import_react53.default.forwardRef(
4191
4221
  }
4192
4222
  )
4193
4223
  ),
4194
- showActions && !isEditing && /* @__PURE__ */ import_react53.default.createElement("div", { className: cx(
4224
+ showActions && !isEditing && /* @__PURE__ */ import_react54.default.createElement("div", { className: cx(
4195
4225
  "flex items-center gap-0.5 mt-1",
4196
4226
  isUser ? "mr-1" : "ml-1"
4197
- ) }, actions.showCopy !== false && /* @__PURE__ */ import_react53.default.createElement(
4227
+ ) }, actions.showCopy !== false && /* @__PURE__ */ import_react54.default.createElement(
4198
4228
  ActionButton,
4199
4229
  {
4200
4230
  onClick: handleCopy,
4201
4231
  label: copied ? "Copied!" : "Copy message"
4202
4232
  },
4203
- copied ? /* @__PURE__ */ import_react53.default.createElement(CheckIcon, null) : /* @__PURE__ */ import_react53.default.createElement(CopyIcon, null)
4204
- ), isUser && actions.onEdit && /* @__PURE__ */ import_react53.default.createElement(ActionButton, { onClick: handleStartEdit, label: "Edit message" }, /* @__PURE__ */ import_react53.default.createElement(PencilIcon, null)), !isUser && actions.onRetry && /* @__PURE__ */ import_react53.default.createElement(ActionButton, { onClick: actions.onRetry, label: "Regenerate response" }, /* @__PURE__ */ import_react53.default.createElement(RetryIcon, null)), showBranchNav && /* @__PURE__ */ import_react53.default.createElement(import_react53.default.Fragment, null, /* @__PURE__ */ import_react53.default.createElement("div", { className: "w-px h-4 bg-ash/40 mx-1" }), /* @__PURE__ */ import_react53.default.createElement("div", { className: "flex items-center gap-0.5 text-silver/70" }, /* @__PURE__ */ import_react53.default.createElement(GitBranchIcon, null), /* @__PURE__ */ import_react53.default.createElement(
4233
+ copied ? /* @__PURE__ */ import_react54.default.createElement(CheckIcon, null) : /* @__PURE__ */ import_react54.default.createElement(CopyIcon, null)
4234
+ ), isUser && actions.onEdit && /* @__PURE__ */ import_react54.default.createElement(ActionButton, { onClick: handleStartEdit, label: "Edit message" }, /* @__PURE__ */ import_react54.default.createElement(PencilIcon, null)), !isUser && actions.onRetry && /* @__PURE__ */ import_react54.default.createElement(ActionButton, { onClick: actions.onRetry, label: "Regenerate response" }, /* @__PURE__ */ import_react54.default.createElement(RetryIcon, null)), showBranchNav && /* @__PURE__ */ import_react54.default.createElement(import_react54.default.Fragment, null, /* @__PURE__ */ import_react54.default.createElement("div", { className: "w-px h-4 bg-ash/40 mx-1" }), /* @__PURE__ */ import_react54.default.createElement("div", { className: "flex items-center gap-0.5 text-silver/70" }, /* @__PURE__ */ import_react54.default.createElement(GitBranchIcon, null), /* @__PURE__ */ import_react54.default.createElement(
4205
4235
  "button",
4206
4236
  {
4207
4237
  type: "button",
@@ -4213,8 +4243,8 @@ var Message = import_react53.default.forwardRef(
4213
4243
  ),
4214
4244
  "aria-label": "Previous branch"
4215
4245
  },
4216
- /* @__PURE__ */ import_react53.default.createElement(ChevronLeftIcon2, null)
4217
- ), /* @__PURE__ */ import_react53.default.createElement("span", { className: "text-xs tabular-nums min-w-6 text-center" }, branchInfo.current, "/", branchInfo.total), /* @__PURE__ */ import_react53.default.createElement(
4246
+ /* @__PURE__ */ import_react54.default.createElement(ChevronLeftIcon2, null)
4247
+ ), /* @__PURE__ */ import_react54.default.createElement("span", { className: "text-xs tabular-nums min-w-6 text-center" }, branchInfo.current, "/", branchInfo.total), /* @__PURE__ */ import_react54.default.createElement(
4218
4248
  "button",
4219
4249
  {
4220
4250
  type: "button",
@@ -4226,7 +4256,7 @@ var Message = import_react53.default.forwardRef(
4226
4256
  ),
4227
4257
  "aria-label": "Next branch"
4228
4258
  },
4229
- /* @__PURE__ */ import_react53.default.createElement(ChevronRightIcon2, null)
4259
+ /* @__PURE__ */ import_react54.default.createElement(ChevronRightIcon2, null)
4230
4260
  ))))
4231
4261
  );
4232
4262
  }
@@ -4234,15 +4264,15 @@ var Message = import_react53.default.forwardRef(
4234
4264
  Message.displayName = "Message";
4235
4265
 
4236
4266
  // src/components/StreamingCursor.tsx
4237
- var import_react54 = __toESM(require("react"));
4238
- var StreamingCursor = import_react54.default.forwardRef(
4267
+ var import_react55 = __toESM(require("react"));
4268
+ var StreamingCursor = import_react55.default.forwardRef(
4239
4269
  ({ className, variant = "line", ...rest }, ref) => {
4240
4270
  const variantStyles3 = {
4241
4271
  block: "w-2.5 h-cursor translate-y-cursor-offset",
4242
4272
  line: "w-0.5 h-cursor translate-y-cursor-offset",
4243
4273
  underscore: "w-2.5 h-0.5 self-end mb-0.5"
4244
4274
  };
4245
- return /* @__PURE__ */ import_react54.default.createElement(
4275
+ return /* @__PURE__ */ import_react55.default.createElement(
4246
4276
  "span",
4247
4277
  {
4248
4278
  ref,
@@ -4260,18 +4290,18 @@ var StreamingCursor = import_react54.default.forwardRef(
4260
4290
  StreamingCursor.displayName = "StreamingCursor";
4261
4291
 
4262
4292
  // src/components/chat/ChatInterface.tsx
4263
- var import_react72 = __toESM(require("react"));
4293
+ var import_react77 = __toESM(require("react"));
4264
4294
 
4265
4295
  // src/components/chat/ChatView.tsx
4266
- var import_react58 = __toESM(require("react"));
4296
+ var import_react59 = __toESM(require("react"));
4267
4297
 
4268
4298
  // src/components/chat/hooks/useScrollAnchor.ts
4269
- var import_react55 = require("react");
4299
+ var import_react56 = require("react");
4270
4300
  function useScrollAnchor(options = {}) {
4271
4301
  const { behavior = "smooth", block = "start" } = options;
4272
- const containerRef = (0, import_react55.useRef)(null);
4273
- const anchorRef = (0, import_react55.useRef)(null);
4274
- const scrollToAnchor = (0, import_react55.useCallback)(() => {
4302
+ const containerRef = (0, import_react56.useRef)(null);
4303
+ const anchorRef = (0, import_react56.useRef)(null);
4304
+ const scrollToAnchor = (0, import_react56.useCallback)(() => {
4275
4305
  const el = anchorRef.current;
4276
4306
  if (!el) {
4277
4307
  return;
@@ -4282,7 +4312,7 @@ function useScrollAnchor(options = {}) {
4282
4312
  });
4283
4313
  });
4284
4314
  }, [behavior, block]);
4285
- const scrollToBottom = (0, import_react55.useCallback)(() => {
4315
+ const scrollToBottom = (0, import_react56.useCallback)(() => {
4286
4316
  const container = containerRef.current;
4287
4317
  if (!container) {
4288
4318
  return;
@@ -4293,7 +4323,7 @@ function useScrollAnchor(options = {}) {
4293
4323
  container.scrollTop = container.scrollHeight;
4294
4324
  }
4295
4325
  }, [behavior]);
4296
- const isScrolledToBottom = (0, import_react55.useCallback)(() => {
4326
+ const isScrolledToBottom = (0, import_react56.useCallback)(() => {
4297
4327
  const container = containerRef.current;
4298
4328
  if (!container) {
4299
4329
  return true;
@@ -4312,15 +4342,15 @@ function useScrollAnchor(options = {}) {
4312
4342
  }
4313
4343
 
4314
4344
  // src/components/chat/hooks/useAdaptiveSpacer.ts
4315
- var import_react56 = require("react");
4345
+ var import_react57 = require("react");
4316
4346
  function useAdaptiveSpacer(options = {}) {
4317
4347
  const { minHeight = 0, containerRef: externalContainerRef, anchorRef } = options;
4318
- const internalContainerRef = (0, import_react56.useRef)(null);
4348
+ const internalContainerRef = (0, import_react57.useRef)(null);
4319
4349
  const containerRef = externalContainerRef ?? internalContainerRef;
4320
- const contentRef = (0, import_react56.useRef)(null);
4321
- const spacerRef = (0, import_react56.useRef)(null);
4322
- const [spacerHeight, setSpacerHeight] = (0, import_react56.useState)(0);
4323
- const recalculate = (0, import_react56.useCallback)(() => {
4350
+ const contentRef = (0, import_react57.useRef)(null);
4351
+ const spacerRef = (0, import_react57.useRef)(null);
4352
+ const [spacerHeight, setSpacerHeight] = (0, import_react57.useState)(0);
4353
+ const recalculate = (0, import_react57.useCallback)(() => {
4324
4354
  const container = containerRef.current;
4325
4355
  const content = contentRef.current;
4326
4356
  if (!container || !content) {
@@ -4344,7 +4374,7 @@ function useAdaptiveSpacer(options = {}) {
4344
4374
  }
4345
4375
  setSpacerHeight(newSpacerHeight);
4346
4376
  }, [minHeight, anchorRef]);
4347
- (0, import_react56.useEffect)(() => {
4377
+ (0, import_react57.useEffect)(() => {
4348
4378
  const container = containerRef.current;
4349
4379
  const content = contentRef.current;
4350
4380
  if (!container || !content) {
@@ -4379,7 +4409,7 @@ function useAdaptiveSpacer(options = {}) {
4379
4409
  }
4380
4410
 
4381
4411
  // src/components/chat/ThinkingIndicator.tsx
4382
- var import_react57 = __toESM(require("react"));
4412
+ var import_react58 = __toESM(require("react"));
4383
4413
  var THINKING_PHRASES = [
4384
4414
  "Consulting the ancient tomes...",
4385
4415
  "Parsing the ineffable...",
@@ -4395,7 +4425,7 @@ var THINKING_PHRASES = [
4395
4425
  "Consulting my inner monologue...",
4396
4426
  "Summoning the muse..."
4397
4427
  ];
4398
- var ThinkingIndicator = import_react57.default.forwardRef(
4428
+ var ThinkingIndicator = import_react58.default.forwardRef(
4399
4429
  ({
4400
4430
  isVisible = true,
4401
4431
  phraseInterval = 2500,
@@ -4403,11 +4433,11 @@ var ThinkingIndicator = import_react57.default.forwardRef(
4403
4433
  className,
4404
4434
  ...rest
4405
4435
  }, ref) => {
4406
- const [currentIndex, setCurrentIndex] = (0, import_react57.useState)(
4436
+ const [currentIndex, setCurrentIndex] = (0, import_react58.useState)(
4407
4437
  () => Math.floor(Math.random() * phrases.length)
4408
4438
  );
4409
- const [isTransitioning, setIsTransitioning] = (0, import_react57.useState)(false);
4410
- (0, import_react57.useEffect)(() => {
4439
+ const [isTransitioning, setIsTransitioning] = (0, import_react58.useState)(false);
4440
+ (0, import_react58.useEffect)(() => {
4411
4441
  if (!isVisible || phrases.length <= 1) {
4412
4442
  return;
4413
4443
  }
@@ -4423,7 +4453,7 @@ var ThinkingIndicator = import_react57.default.forwardRef(
4423
4453
  if (!isVisible) {
4424
4454
  return null;
4425
4455
  }
4426
- return /* @__PURE__ */ import_react57.default.createElement(
4456
+ return /* @__PURE__ */ import_react58.default.createElement(
4427
4457
  "div",
4428
4458
  {
4429
4459
  ref,
@@ -4437,26 +4467,26 @@ var ThinkingIndicator = import_react57.default.forwardRef(
4437
4467
  "aria-live": "polite",
4438
4468
  ...rest
4439
4469
  },
4440
- /* @__PURE__ */ import_react57.default.createElement("div", { className: "flex gap-1", "aria-hidden": "true" }, /* @__PURE__ */ import_react57.default.createElement(
4470
+ /* @__PURE__ */ import_react58.default.createElement("div", { className: "flex gap-1", "aria-hidden": "true" }, /* @__PURE__ */ import_react58.default.createElement(
4441
4471
  "span",
4442
4472
  {
4443
4473
  className: "w-1.5 h-1.5 bg-gold/60 rounded-full animate-pulse",
4444
4474
  style: { animationDelay: "0ms" }
4445
4475
  }
4446
- ), /* @__PURE__ */ import_react57.default.createElement(
4476
+ ), /* @__PURE__ */ import_react58.default.createElement(
4447
4477
  "span",
4448
4478
  {
4449
4479
  className: "w-1.5 h-1.5 bg-gold/60 rounded-full animate-pulse",
4450
4480
  style: { animationDelay: "150ms" }
4451
4481
  }
4452
- ), /* @__PURE__ */ import_react57.default.createElement(
4482
+ ), /* @__PURE__ */ import_react58.default.createElement(
4453
4483
  "span",
4454
4484
  {
4455
4485
  className: "w-1.5 h-1.5 bg-gold/60 rounded-full animate-pulse",
4456
4486
  style: { animationDelay: "300ms" }
4457
4487
  }
4458
4488
  )),
4459
- /* @__PURE__ */ import_react57.default.createElement(
4489
+ /* @__PURE__ */ import_react58.default.createElement(
4460
4490
  "span",
4461
4491
  {
4462
4492
  className: cx(
@@ -4472,7 +4502,7 @@ var ThinkingIndicator = import_react57.default.forwardRef(
4472
4502
  ThinkingIndicator.displayName = "ThinkingIndicator";
4473
4503
 
4474
4504
  // src/components/chat/ChatView.tsx
4475
- var ChatView = import_react58.default.forwardRef(
4505
+ var ChatView = import_react59.default.forwardRef(
4476
4506
  ({ messages, latestUserMessageIndex, isStreaming, isThinking, onScroll, className, ...rest }, ref) => {
4477
4507
  const { containerRef, anchorRef, scrollToAnchor } = useScrollAnchor({
4478
4508
  behavior: "smooth",
@@ -4482,7 +4512,7 @@ var ChatView = import_react58.default.forwardRef(
4482
4512
  containerRef,
4483
4513
  anchorRef
4484
4514
  });
4485
- (0, import_react58.useEffect)(() => {
4515
+ (0, import_react59.useEffect)(() => {
4486
4516
  if (latestUserMessageIndex !== void 0 && latestUserMessageIndex >= 0) {
4487
4517
  scrollToAnchor();
4488
4518
  }
@@ -4494,7 +4524,7 @@ var ChatView = import_react58.default.forwardRef(
4494
4524
  return found;
4495
4525
  }, -1);
4496
4526
  const showThinking = isThinking && messages.length > 0 && messages[messages.length - 1]?.variant === "user";
4497
- return /* @__PURE__ */ import_react58.default.createElement(
4527
+ return /* @__PURE__ */ import_react59.default.createElement(
4498
4528
  "div",
4499
4529
  {
4500
4530
  ref: (node) => {
@@ -4514,7 +4544,7 @@ var ChatView = import_react58.default.forwardRef(
4514
4544
  ),
4515
4545
  ...rest
4516
4546
  },
4517
- /* @__PURE__ */ import_react58.default.createElement("div", { ref: contentRef, className: "relative flex flex-col gap-3" }, messages.map(({
4547
+ /* @__PURE__ */ import_react59.default.createElement("div", { ref: contentRef, className: "relative flex flex-col gap-3" }, messages.map(({
4518
4548
  id,
4519
4549
  variant,
4520
4550
  className: messageClassName,
@@ -4527,14 +4557,14 @@ var ChatView = import_react58.default.forwardRef(
4527
4557
  const isLastMessage = index === messages.length - 1;
4528
4558
  const showStreaming = isLastMessage && isStreaming && variant === "assistant";
4529
4559
  const isMessageStreaming = showStreaming || !!nodeIsStreaming;
4530
- return /* @__PURE__ */ import_react58.default.createElement(
4560
+ return /* @__PURE__ */ import_react59.default.createElement(
4531
4561
  "div",
4532
4562
  {
4533
4563
  key: id ?? `msg-${index}`,
4534
4564
  ref: isAnchor ? anchorRef : void 0,
4535
4565
  className: isAnchor ? "scroll-mt-4" : void 0
4536
4566
  },
4537
- /* @__PURE__ */ import_react58.default.createElement(
4567
+ /* @__PURE__ */ import_react59.default.createElement(
4538
4568
  Message,
4539
4569
  {
4540
4570
  variant,
@@ -4547,8 +4577,8 @@ var ChatView = import_react58.default.forwardRef(
4547
4577
  }
4548
4578
  )
4549
4579
  );
4550
- }), showThinking && /* @__PURE__ */ import_react58.default.createElement(ThinkingIndicator, { isVisible: true })),
4551
- /* @__PURE__ */ import_react58.default.createElement(
4580
+ }), showThinking && /* @__PURE__ */ import_react59.default.createElement(ThinkingIndicator, { isVisible: true })),
4581
+ /* @__PURE__ */ import_react59.default.createElement(
4552
4582
  "div",
4553
4583
  {
4554
4584
  ref: spacerRef,
@@ -4563,7 +4593,7 @@ var ChatView = import_react58.default.forwardRef(
4563
4593
  ChatView.displayName = "ChatView";
4564
4594
 
4565
4595
  // src/components/chat/ChatInput.tsx
4566
- var import_react59 = __toESM(require("react"));
4596
+ var import_react60 = __toESM(require("react"));
4567
4597
  var import_lucide_react11 = require("lucide-react");
4568
4598
 
4569
4599
  // src/components/chat/types.ts
@@ -4732,7 +4762,7 @@ function isBranchPoint(tree, nodeId) {
4732
4762
  }
4733
4763
 
4734
4764
  // src/components/chat/ChatInput.tsx
4735
- var ChatInput = import_react59.default.forwardRef(
4765
+ var ChatInput = import_react60.default.forwardRef(
4736
4766
  ({
4737
4767
  position = "bottom",
4738
4768
  placeholder = "Send a message...",
@@ -4749,13 +4779,13 @@ var ChatInput = import_react59.default.forwardRef(
4749
4779
  className,
4750
4780
  ...rest
4751
4781
  }, ref) => {
4752
- const [value, setValue] = (0, import_react59.useState)("");
4753
- const [localAttachments, setLocalAttachments] = (0, import_react59.useState)([]);
4754
- const [isDragOver, setIsDragOver] = (0, import_react59.useState)(false);
4755
- const textareaRef = (0, import_react59.useRef)(null);
4756
- const fileInputRef = (0, import_react59.useRef)(null);
4782
+ const [value, setValue] = (0, import_react60.useState)("");
4783
+ const [localAttachments, setLocalAttachments] = (0, import_react60.useState)([]);
4784
+ const [isDragOver, setIsDragOver] = (0, import_react60.useState)(false);
4785
+ const textareaRef = (0, import_react60.useRef)(null);
4786
+ const fileInputRef = (0, import_react60.useRef)(null);
4757
4787
  const attachments = controlledAttachments ?? localAttachments;
4758
- const setAttachments = (0, import_react59.useCallback)(
4788
+ const setAttachments = (0, import_react60.useCallback)(
4759
4789
  (newAttachments) => {
4760
4790
  if (onAttachmentsChange) {
4761
4791
  if (typeof newAttachments === "function") {
@@ -4769,7 +4799,7 @@ var ChatInput = import_react59.default.forwardRef(
4769
4799
  },
4770
4800
  [attachments, onAttachmentsChange]
4771
4801
  );
4772
- const handleSubmit = (0, import_react59.useCallback)(() => {
4802
+ const handleSubmit = (0, import_react60.useCallback)(() => {
4773
4803
  const trimmed = value.trim();
4774
4804
  if (!trimmed || disabled || isStreaming) {
4775
4805
  return;
@@ -4781,7 +4811,7 @@ var ChatInput = import_react59.default.forwardRef(
4781
4811
  textareaRef.current.style.height = "auto";
4782
4812
  }
4783
4813
  }, [value, disabled, isStreaming, onSubmit, attachments, setAttachments]);
4784
- const handleKeyDown = (0, import_react59.useCallback)(
4814
+ const handleKeyDown = (0, import_react60.useCallback)(
4785
4815
  (e) => {
4786
4816
  if (e.key === "Enter" && !e.shiftKey) {
4787
4817
  e.preventDefault();
@@ -4790,18 +4820,18 @@ var ChatInput = import_react59.default.forwardRef(
4790
4820
  },
4791
4821
  [handleSubmit]
4792
4822
  );
4793
- const handleChange = (0, import_react59.useCallback)((e) => {
4823
+ const handleChange = (0, import_react60.useCallback)((e) => {
4794
4824
  setValue(e.target.value);
4795
4825
  const textarea = e.target;
4796
4826
  textarea.style.height = "auto";
4797
4827
  textarea.style.height = `${Math.min(textarea.scrollHeight, 200)}px`;
4798
4828
  }, []);
4799
- (0, import_react59.useEffect)(() => {
4829
+ (0, import_react60.useEffect)(() => {
4800
4830
  if (!disabled && !isStreaming && textareaRef.current) {
4801
4831
  textareaRef.current.focus();
4802
4832
  }
4803
4833
  }, [disabled, isStreaming]);
4804
- const addFiles = (0, import_react59.useCallback)(
4834
+ const addFiles = (0, import_react60.useCallback)(
4805
4835
  (files) => {
4806
4836
  const newAttachments = Array.from(files).map((file) => ({
4807
4837
  id: generateId(),
@@ -4813,7 +4843,7 @@ var ChatInput = import_react59.default.forwardRef(
4813
4843
  },
4814
4844
  [setAttachments]
4815
4845
  );
4816
- const handleFileSelect = (0, import_react59.useCallback)(
4846
+ const handleFileSelect = (0, import_react60.useCallback)(
4817
4847
  (e) => {
4818
4848
  const files = e.target.files;
4819
4849
  if (files && files.length > 0) {
@@ -4823,7 +4853,7 @@ var ChatInput = import_react59.default.forwardRef(
4823
4853
  },
4824
4854
  [addFiles]
4825
4855
  );
4826
- const handleRemoveAttachment = (0, import_react59.useCallback)(
4856
+ const handleRemoveAttachment = (0, import_react60.useCallback)(
4827
4857
  (id) => {
4828
4858
  setAttachments((prev) => {
4829
4859
  const attachment = prev.find((a) => a.id === id);
@@ -4835,23 +4865,23 @@ var ChatInput = import_react59.default.forwardRef(
4835
4865
  },
4836
4866
  [setAttachments]
4837
4867
  );
4838
- const handleDragEnter = (0, import_react59.useCallback)((e) => {
4868
+ const handleDragEnter = (0, import_react60.useCallback)((e) => {
4839
4869
  e.preventDefault();
4840
4870
  e.stopPropagation();
4841
4871
  setIsDragOver(true);
4842
4872
  }, []);
4843
- const handleDragLeave = (0, import_react59.useCallback)((e) => {
4873
+ const handleDragLeave = (0, import_react60.useCallback)((e) => {
4844
4874
  e.preventDefault();
4845
4875
  e.stopPropagation();
4846
4876
  if (!e.currentTarget.contains(e.relatedTarget)) {
4847
4877
  setIsDragOver(false);
4848
4878
  }
4849
4879
  }, []);
4850
- const handleDragOver = (0, import_react59.useCallback)((e) => {
4880
+ const handleDragOver = (0, import_react60.useCallback)((e) => {
4851
4881
  e.preventDefault();
4852
4882
  e.stopPropagation();
4853
4883
  }, []);
4854
- const handleDrop = (0, import_react59.useCallback)(
4884
+ const handleDrop = (0, import_react60.useCallback)(
4855
4885
  (e) => {
4856
4886
  e.preventDefault();
4857
4887
  e.stopPropagation();
@@ -4866,7 +4896,7 @@ var ChatInput = import_react59.default.forwardRef(
4866
4896
  const isCentered = position === "centered";
4867
4897
  const hasAttachments = attachments.length > 0;
4868
4898
  const canSubmit = value.trim() && !disabled && !isStreaming;
4869
- return /* @__PURE__ */ import_react59.default.createElement(
4899
+ return /* @__PURE__ */ import_react60.default.createElement(
4870
4900
  "div",
4871
4901
  {
4872
4902
  ref,
@@ -4878,8 +4908,8 @@ var ChatInput = import_react59.default.forwardRef(
4878
4908
  ),
4879
4909
  ...rest
4880
4910
  },
4881
- isCentered && helperText && /* @__PURE__ */ import_react59.default.createElement("p", { className: "text-silver text-sm mb-4 text-center" }, helperText),
4882
- /* @__PURE__ */ import_react59.default.createElement(
4911
+ isCentered && helperText && /* @__PURE__ */ import_react60.default.createElement("p", { className: "text-silver text-sm mb-4 text-center" }, helperText),
4912
+ /* @__PURE__ */ import_react60.default.createElement(
4883
4913
  "div",
4884
4914
  {
4885
4915
  className: cx(
@@ -4894,7 +4924,7 @@ var ChatInput = import_react59.default.forwardRef(
4894
4924
  onDragOver: showAttachmentButton ? handleDragOver : void 0,
4895
4925
  onDrop: showAttachmentButton ? handleDrop : void 0
4896
4926
  },
4897
- hasAttachments && /* @__PURE__ */ import_react59.default.createElement("div", { className: "px-3 pt-3 pb-1" }, /* @__PURE__ */ import_react59.default.createElement(
4927
+ hasAttachments && /* @__PURE__ */ import_react60.default.createElement("div", { className: "px-3 pt-3 pb-1" }, /* @__PURE__ */ import_react60.default.createElement(
4898
4928
  AttachmentPreview,
4899
4929
  {
4900
4930
  attachments,
@@ -4902,14 +4932,14 @@ var ChatInput = import_react59.default.forwardRef(
4902
4932
  removable: !isStreaming
4903
4933
  }
4904
4934
  )),
4905
- isDragOver && /* @__PURE__ */ import_react59.default.createElement(
4935
+ isDragOver && /* @__PURE__ */ import_react60.default.createElement(
4906
4936
  "div",
4907
4937
  {
4908
4938
  className: "absolute inset-0 bg-gold/10 flex items-center justify-center z-10 pointer-events-none"
4909
4939
  },
4910
- /* @__PURE__ */ import_react59.default.createElement("span", { className: "text-gold text-sm font-medium" }, "Drop files here")
4940
+ /* @__PURE__ */ import_react60.default.createElement("span", { className: "text-gold text-sm font-medium" }, "Drop files here")
4911
4941
  ),
4912
- /* @__PURE__ */ import_react59.default.createElement("div", { className: "flex items-end" }, showAttachmentButton && /* @__PURE__ */ import_react59.default.createElement(import_react59.default.Fragment, null, /* @__PURE__ */ import_react59.default.createElement(
4942
+ /* @__PURE__ */ import_react60.default.createElement("div", { className: "flex items-end" }, showAttachmentButton && /* @__PURE__ */ import_react60.default.createElement(import_react60.default.Fragment, null, /* @__PURE__ */ import_react60.default.createElement(
4913
4943
  "button",
4914
4944
  {
4915
4945
  type: "button",
@@ -4921,8 +4951,8 @@ var ChatInput = import_react59.default.forwardRef(
4921
4951
  ),
4922
4952
  "aria-label": "Attach file"
4923
4953
  },
4924
- /* @__PURE__ */ import_react59.default.createElement(import_lucide_react11.Paperclip, { className: "w-5 h-5" })
4925
- ), /* @__PURE__ */ import_react59.default.createElement(
4954
+ /* @__PURE__ */ import_react60.default.createElement(import_lucide_react11.Paperclip, { className: "w-5 h-5" })
4955
+ ), /* @__PURE__ */ import_react60.default.createElement(
4926
4956
  "input",
4927
4957
  {
4928
4958
  ref: fileInputRef,
@@ -4933,7 +4963,7 @@ var ChatInput = import_react59.default.forwardRef(
4933
4963
  className: "hidden",
4934
4964
  "aria-hidden": "true"
4935
4965
  }
4936
- )), /* @__PURE__ */ import_react59.default.createElement(
4966
+ )), /* @__PURE__ */ import_react60.default.createElement(
4937
4967
  "textarea",
4938
4968
  {
4939
4969
  ref: textareaRef,
@@ -4951,7 +4981,7 @@ var ChatInput = import_react59.default.forwardRef(
4951
4981
  ),
4952
4982
  style: { maxHeight: 200 }
4953
4983
  }
4954
- ), isStreaming ? /* @__PURE__ */ import_react59.default.createElement(
4984
+ ), isStreaming ? /* @__PURE__ */ import_react60.default.createElement(
4955
4985
  "button",
4956
4986
  {
4957
4987
  type: "button",
@@ -4962,8 +4992,8 @@ var ChatInput = import_react59.default.forwardRef(
4962
4992
  ),
4963
4993
  "aria-label": "Stop generation"
4964
4994
  },
4965
- /* @__PURE__ */ import_react59.default.createElement(import_lucide_react11.Square, { className: "w-5 h-5 fill-current" })
4966
- ) : /* @__PURE__ */ import_react59.default.createElement(
4995
+ /* @__PURE__ */ import_react60.default.createElement(import_lucide_react11.Square, { className: "w-5 h-5 fill-current" })
4996
+ ) : /* @__PURE__ */ import_react60.default.createElement(
4967
4997
  "button",
4968
4998
  {
4969
4999
  type: "button",
@@ -4976,7 +5006,7 @@ var ChatInput = import_react59.default.forwardRef(
4976
5006
  ),
4977
5007
  "aria-label": "Send message"
4978
5008
  },
4979
- /* @__PURE__ */ import_react59.default.createElement(import_lucide_react11.Send, { className: "w-5 h-5" })
5009
+ /* @__PURE__ */ import_react60.default.createElement(import_lucide_react11.Send, { className: "w-5 h-5" })
4980
5010
  ))
4981
5011
  )
4982
5012
  );
@@ -4985,9 +5015,9 @@ var ChatInput = import_react59.default.forwardRef(
4985
5015
  ChatInput.displayName = "ChatInput";
4986
5016
 
4987
5017
  // src/components/chat/ConversationSidebar.tsx
4988
- var import_react60 = __toESM(require("react"));
5018
+ var import_react61 = __toESM(require("react"));
4989
5019
  function HistoryIcon2({ className }) {
4990
- return /* @__PURE__ */ import_react60.default.createElement(
5020
+ return /* @__PURE__ */ import_react61.default.createElement(
4991
5021
  "svg",
4992
5022
  {
4993
5023
  xmlns: "http://www.w3.org/2000/svg",
@@ -4995,7 +5025,7 @@ function HistoryIcon2({ className }) {
4995
5025
  fill: "currentColor",
4996
5026
  className
4997
5027
  },
4998
- /* @__PURE__ */ import_react60.default.createElement(
5028
+ /* @__PURE__ */ import_react61.default.createElement(
4999
5029
  "path",
5000
5030
  {
5001
5031
  fillRule: "evenodd",
@@ -5006,7 +5036,7 @@ function HistoryIcon2({ className }) {
5006
5036
  );
5007
5037
  }
5008
5038
  function ChevronLeftIcon3({ className }) {
5009
- return /* @__PURE__ */ import_react60.default.createElement(
5039
+ return /* @__PURE__ */ import_react61.default.createElement(
5010
5040
  "svg",
5011
5041
  {
5012
5042
  xmlns: "http://www.w3.org/2000/svg",
@@ -5014,7 +5044,7 @@ function ChevronLeftIcon3({ className }) {
5014
5044
  fill: "currentColor",
5015
5045
  className
5016
5046
  },
5017
- /* @__PURE__ */ import_react60.default.createElement(
5047
+ /* @__PURE__ */ import_react61.default.createElement(
5018
5048
  "path",
5019
5049
  {
5020
5050
  fillRule: "evenodd",
@@ -5024,7 +5054,7 @@ function ChevronLeftIcon3({ className }) {
5024
5054
  )
5025
5055
  );
5026
5056
  }
5027
- var ConversationSidebar = import_react60.default.forwardRef(
5057
+ var ConversationSidebar = import_react61.default.forwardRef(
5028
5058
  ({
5029
5059
  conversations,
5030
5060
  isCollapsed = false,
@@ -5037,7 +5067,7 @@ var ConversationSidebar = import_react60.default.forwardRef(
5037
5067
  ...rest
5038
5068
  }, ref) => {
5039
5069
  if (isCollapsed) {
5040
- return /* @__PURE__ */ import_react60.default.createElement(
5070
+ return /* @__PURE__ */ import_react61.default.createElement(
5041
5071
  "div",
5042
5072
  {
5043
5073
  ref,
@@ -5048,7 +5078,7 @@ var ConversationSidebar = import_react60.default.forwardRef(
5048
5078
  ),
5049
5079
  ...rest
5050
5080
  },
5051
- /* @__PURE__ */ import_react60.default.createElement(
5081
+ /* @__PURE__ */ import_react61.default.createElement(
5052
5082
  "button",
5053
5083
  {
5054
5084
  onClick: onToggleCollapse,
@@ -5059,11 +5089,11 @@ var ConversationSidebar = import_react60.default.forwardRef(
5059
5089
  ),
5060
5090
  "aria-label": "Expand sidebar"
5061
5091
  },
5062
- /* @__PURE__ */ import_react60.default.createElement(HistoryIcon2, { className: "w-5 h-5" })
5092
+ /* @__PURE__ */ import_react61.default.createElement(HistoryIcon2, { className: "w-5 h-5" })
5063
5093
  )
5064
5094
  );
5065
5095
  }
5066
- return /* @__PURE__ */ import_react60.default.createElement(
5096
+ return /* @__PURE__ */ import_react61.default.createElement(
5067
5097
  "div",
5068
5098
  {
5069
5099
  ref,
@@ -5077,7 +5107,7 @@ var ConversationSidebar = import_react60.default.forwardRef(
5077
5107
  style: width ? { width } : void 0,
5078
5108
  ...rest
5079
5109
  },
5080
- /* @__PURE__ */ import_react60.default.createElement(
5110
+ /* @__PURE__ */ import_react61.default.createElement(
5081
5111
  "div",
5082
5112
  {
5083
5113
  onMouseDown: onResizeStart,
@@ -5090,7 +5120,7 @@ var ConversationSidebar = import_react60.default.forwardRef(
5090
5120
  )
5091
5121
  }
5092
5122
  ),
5093
- /* @__PURE__ */ import_react60.default.createElement("div", { className: "p-3 border-b border-ash/40 flex-shrink-0 flex items-center gap-2" }, /* @__PURE__ */ import_react60.default.createElement(
5123
+ /* @__PURE__ */ import_react61.default.createElement("div", { className: "p-3 border-b border-ash/40 flex-shrink-0 flex items-center gap-2" }, /* @__PURE__ */ import_react61.default.createElement(
5094
5124
  "button",
5095
5125
  {
5096
5126
  onClick: onToggleCollapse,
@@ -5101,8 +5131,8 @@ var ConversationSidebar = import_react60.default.forwardRef(
5101
5131
  ),
5102
5132
  "aria-label": "Collapse sidebar"
5103
5133
  },
5104
- /* @__PURE__ */ import_react60.default.createElement(ChevronLeftIcon3, { className: "w-5 h-5" })
5105
- ), /* @__PURE__ */ import_react60.default.createElement(
5134
+ /* @__PURE__ */ import_react61.default.createElement(ChevronLeftIcon3, { className: "w-5 h-5" })
5135
+ ), /* @__PURE__ */ import_react61.default.createElement(
5106
5136
  "button",
5107
5137
  {
5108
5138
  onClick: onNewChat,
@@ -5114,7 +5144,7 @@ var ConversationSidebar = import_react60.default.forwardRef(
5114
5144
  "transition-colors duration-200"
5115
5145
  )
5116
5146
  },
5117
- /* @__PURE__ */ import_react60.default.createElement(
5147
+ /* @__PURE__ */ import_react61.default.createElement(
5118
5148
  "svg",
5119
5149
  {
5120
5150
  xmlns: "http://www.w3.org/2000/svg",
@@ -5122,16 +5152,16 @@ var ConversationSidebar = import_react60.default.forwardRef(
5122
5152
  fill: "currentColor",
5123
5153
  className: "w-4 h-4"
5124
5154
  },
5125
- /* @__PURE__ */ import_react60.default.createElement(
5155
+ /* @__PURE__ */ import_react61.default.createElement(
5126
5156
  "path",
5127
5157
  {
5128
5158
  d: "M10.75 4.75a.75.75 0 00-1.5 0v4.5h-4.5a.75.75 0 000 1.5h4.5v4.5a.75.75 0 001.5 0v-4.5h4.5a.75.75 0 000-1.5h-4.5v-4.5z"
5129
5159
  }
5130
5160
  )
5131
5161
  ),
5132
- /* @__PURE__ */ import_react60.default.createElement("span", { className: "text-sm font-medium" }, "New Chat")
5162
+ /* @__PURE__ */ import_react61.default.createElement("span", { className: "text-sm font-medium" }, "New Chat")
5133
5163
  )),
5134
- /* @__PURE__ */ import_react60.default.createElement("div", { className: "flex-1 overflow-y-auto py-2" }, conversations.length === 0 ? /* @__PURE__ */ import_react60.default.createElement("p", { className: "px-4 py-2 text-sm text-silver/60" }, "No conversations yet") : /* @__PURE__ */ import_react60.default.createElement("div", { className: "space-y-1 px-2" }, conversations.map((conversation) => /* @__PURE__ */ import_react60.default.createElement(
5164
+ /* @__PURE__ */ import_react61.default.createElement("div", { className: "flex-1 overflow-y-auto py-2" }, conversations.length === 0 ? /* @__PURE__ */ import_react61.default.createElement("p", { className: "px-4 py-2 text-sm text-silver/60" }, "No conversations yet") : /* @__PURE__ */ import_react61.default.createElement("div", { className: "space-y-1 px-2" }, conversations.map((conversation) => /* @__PURE__ */ import_react61.default.createElement(
5135
5165
  "button",
5136
5166
  {
5137
5167
  key: conversation.id,
@@ -5142,16 +5172,16 @@ var ConversationSidebar = import_react60.default.forwardRef(
5142
5172
  conversation.isActive ? "bg-ash/40 text-white" : "text-silver hover:bg-ash/20 hover:text-white"
5143
5173
  )
5144
5174
  },
5145
- /* @__PURE__ */ import_react60.default.createElement("p", { className: "text-sm font-medium truncate" }, conversation.title),
5146
- conversation.preview && /* @__PURE__ */ import_react60.default.createElement("p", { className: "text-xs text-silver/60 truncate mt-0.5" }, conversation.preview),
5147
- conversation.timestamp && /* @__PURE__ */ import_react60.default.createElement("p", { className: "text-xs text-silver/40 mt-1" }, conversation.timestamp)
5175
+ /* @__PURE__ */ import_react61.default.createElement("p", { className: "text-sm font-medium truncate" }, conversation.title),
5176
+ conversation.preview && /* @__PURE__ */ import_react61.default.createElement("p", { className: "text-xs text-silver/60 truncate mt-0.5" }, conversation.preview),
5177
+ conversation.timestamp && /* @__PURE__ */ import_react61.default.createElement("p", { className: "text-xs text-silver/40 mt-1" }, conversation.timestamp)
5148
5178
  ))))
5149
5179
  );
5150
5180
  }
5151
5181
  );
5152
5182
  ConversationSidebar.displayName = "ConversationSidebar";
5153
- var CollapsedSidebarToggle = import_react60.default.forwardRef(({ onExpand, className, ...rest }, ref) => {
5154
- return /* @__PURE__ */ import_react60.default.createElement(
5183
+ var CollapsedSidebarToggle = import_react61.default.forwardRef(({ onExpand, className, ...rest }, ref) => {
5184
+ return /* @__PURE__ */ import_react61.default.createElement(
5155
5185
  "button",
5156
5186
  {
5157
5187
  ref,
@@ -5166,19 +5196,19 @@ var CollapsedSidebarToggle = import_react60.default.forwardRef(({ onExpand, clas
5166
5196
  "aria-label": "Expand sidebar",
5167
5197
  ...rest
5168
5198
  },
5169
- /* @__PURE__ */ import_react60.default.createElement(HistoryIcon2, { className: "w-5 h-5" })
5199
+ /* @__PURE__ */ import_react61.default.createElement(HistoryIcon2, { className: "w-5 h-5" })
5170
5200
  );
5171
5201
  });
5172
5202
  CollapsedSidebarToggle.displayName = "CollapsedSidebarToggle";
5173
5203
 
5174
5204
  // src/components/chat/ArtifactsPanel.tsx
5175
- var import_react68 = __toESM(require("react"));
5205
+ var import_react72 = __toESM(require("react"));
5176
5206
 
5177
5207
  // src/components/ArtifactCard.tsx
5178
- var import_react67 = __toESM(require("react"));
5208
+ var import_react68 = __toESM(require("react"));
5179
5209
 
5180
5210
  // src/components/ImageCard.tsx
5181
- var import_react61 = __toESM(require("react"));
5211
+ var import_react62 = __toESM(require("react"));
5182
5212
  var ASPECT_RATIO_PRESETS = {
5183
5213
  landscape: "3 / 2",
5184
5214
  portrait: "2 / 3",
@@ -5190,7 +5220,7 @@ function resolveAspectRatio(ratio) {
5190
5220
  }
5191
5221
  return ratio.replace("/", " / ");
5192
5222
  }
5193
- var ImageCard = import_react61.default.forwardRef(
5223
+ var ImageCard = import_react62.default.forwardRef(
5194
5224
  ({
5195
5225
  src,
5196
5226
  alt = "",
@@ -5206,7 +5236,7 @@ var ImageCard = import_react61.default.forwardRef(
5206
5236
  loading,
5207
5237
  ...props
5208
5238
  }, ref) => {
5209
- return /* @__PURE__ */ import_react61.default.createElement(
5239
+ return /* @__PURE__ */ import_react62.default.createElement(
5210
5240
  Card,
5211
5241
  {
5212
5242
  ref,
@@ -5214,13 +5244,13 @@ var ImageCard = import_react61.default.forwardRef(
5214
5244
  loading,
5215
5245
  ...props
5216
5246
  },
5217
- /* @__PURE__ */ import_react61.default.createElement(
5247
+ /* @__PURE__ */ import_react62.default.createElement(
5218
5248
  Card.Media,
5219
5249
  {
5220
5250
  className: mediaClassName,
5221
5251
  style: { aspectRatio: resolveAspectRatio(aspectRatio) }
5222
5252
  },
5223
- /* @__PURE__ */ import_react61.default.createElement(import_react61.default.Fragment, null, src && /* @__PURE__ */ import_react61.default.createElement(
5253
+ /* @__PURE__ */ import_react62.default.createElement(import_react62.default.Fragment, null, src && /* @__PURE__ */ import_react62.default.createElement(
5224
5254
  "img",
5225
5255
  {
5226
5256
  src,
@@ -5230,7 +5260,7 @@ var ImageCard = import_react61.default.forwardRef(
5230
5260
  objectFit === "cover" ? "object-cover" : "object-contain"
5231
5261
  )
5232
5262
  }
5233
- ), overlay && /* @__PURE__ */ import_react61.default.createElement(
5263
+ ), overlay && /* @__PURE__ */ import_react62.default.createElement(
5234
5264
  "div",
5235
5265
  {
5236
5266
  className: "absolute inset-0 bg-obsidian/80 opacity-0 group-hover:opacity-100 transition-opacity duration-200 flex items-center justify-center"
@@ -5238,7 +5268,7 @@ var ImageCard = import_react61.default.forwardRef(
5238
5268
  overlay
5239
5269
  ))
5240
5270
  ),
5241
- /* @__PURE__ */ import_react61.default.createElement(
5271
+ /* @__PURE__ */ import_react62.default.createElement(
5242
5272
  Card.Header,
5243
5273
  {
5244
5274
  title,
@@ -5246,14 +5276,14 @@ var ImageCard = import_react61.default.forwardRef(
5246
5276
  className: contentClassName
5247
5277
  }
5248
5278
  ),
5249
- children && /* @__PURE__ */ import_react61.default.createElement(Card.Body, { className: contentClassName }, children)
5279
+ children && /* @__PURE__ */ import_react62.default.createElement(Card.Body, { className: contentClassName }, children)
5250
5280
  );
5251
5281
  }
5252
5282
  );
5253
5283
  ImageCard.displayName = "ImageCard";
5254
5284
 
5255
5285
  // src/components/VideoCard.tsx
5256
- var import_react62 = __toESM(require("react"));
5286
+ var import_react63 = __toESM(require("react"));
5257
5287
  var import_react_player = __toESM(require("react-player"));
5258
5288
  var ASPECT_RATIO_PRESETS2 = {
5259
5289
  video: "16 / 9",
@@ -5266,7 +5296,7 @@ function resolveAspectRatio2(ratio) {
5266
5296
  }
5267
5297
  return ratio.replace("/", " / ");
5268
5298
  }
5269
- var VideoCard = import_react62.default.forwardRef(
5299
+ var VideoCard = import_react63.default.forwardRef(
5270
5300
  ({
5271
5301
  src,
5272
5302
  title,
@@ -5286,7 +5316,7 @@ var VideoCard = import_react62.default.forwardRef(
5286
5316
  loading,
5287
5317
  ...props
5288
5318
  }, ref) => {
5289
- return /* @__PURE__ */ import_react62.default.createElement(
5319
+ return /* @__PURE__ */ import_react63.default.createElement(
5290
5320
  Card,
5291
5321
  {
5292
5322
  ref,
@@ -5294,13 +5324,13 @@ var VideoCard = import_react62.default.forwardRef(
5294
5324
  loading,
5295
5325
  ...props
5296
5326
  },
5297
- /* @__PURE__ */ import_react62.default.createElement(
5327
+ /* @__PURE__ */ import_react63.default.createElement(
5298
5328
  Card.Media,
5299
5329
  {
5300
5330
  className: mediaClassName,
5301
5331
  style: { aspectRatio: resolveAspectRatio2(aspectRatio) }
5302
5332
  },
5303
- src && /* @__PURE__ */ import_react62.default.createElement(
5333
+ src && /* @__PURE__ */ import_react63.default.createElement(
5304
5334
  import_react_player.default,
5305
5335
  {
5306
5336
  src,
@@ -5317,7 +5347,7 @@ var VideoCard = import_react62.default.forwardRef(
5317
5347
  }
5318
5348
  )
5319
5349
  ),
5320
- /* @__PURE__ */ import_react62.default.createElement(
5350
+ /* @__PURE__ */ import_react63.default.createElement(
5321
5351
  Card.Header,
5322
5352
  {
5323
5353
  title,
@@ -5325,17 +5355,17 @@ var VideoCard = import_react62.default.forwardRef(
5325
5355
  className: contentClassName
5326
5356
  }
5327
5357
  ),
5328
- children && /* @__PURE__ */ import_react62.default.createElement(Card.Body, { className: contentClassName }, children)
5358
+ children && /* @__PURE__ */ import_react63.default.createElement(Card.Body, { className: contentClassName }, children)
5329
5359
  );
5330
5360
  }
5331
5361
  );
5332
5362
  VideoCard.displayName = "VideoCard";
5333
5363
 
5334
5364
  // src/components/AudioCard.tsx
5335
- var import_react63 = __toESM(require("react"));
5365
+ var import_react64 = __toESM(require("react"));
5336
5366
  var import_react_player2 = __toESM(require("react-player"));
5337
5367
  var import_lucide_react12 = require("lucide-react");
5338
- var AudioCard = import_react63.default.forwardRef(
5368
+ var AudioCard = import_react64.default.forwardRef(
5339
5369
  ({
5340
5370
  src,
5341
5371
  title,
@@ -5354,7 +5384,7 @@ var AudioCard = import_react63.default.forwardRef(
5354
5384
  loading,
5355
5385
  ...props
5356
5386
  }, ref) => {
5357
- return /* @__PURE__ */ import_react63.default.createElement(
5387
+ return /* @__PURE__ */ import_react64.default.createElement(
5358
5388
  Card,
5359
5389
  {
5360
5390
  ref,
@@ -5362,10 +5392,10 @@ var AudioCard = import_react63.default.forwardRef(
5362
5392
  loading,
5363
5393
  ...props
5364
5394
  },
5365
- /* @__PURE__ */ import_react63.default.createElement(Card.Media, { className: cx(
5395
+ /* @__PURE__ */ import_react64.default.createElement(Card.Media, { className: cx(
5366
5396
  "bg-obsidian py-8 flex flex-col items-center justify-center",
5367
5397
  mediaClassName
5368
- ) }, /* @__PURE__ */ import_react63.default.createElement("div", { className: "mb-4 text-gold" }, /* @__PURE__ */ import_react63.default.createElement(import_lucide_react12.Music, { size: 48 })), src && /* @__PURE__ */ import_react63.default.createElement("div", { className: "w-full px-4" }, /* @__PURE__ */ import_react63.default.createElement(
5398
+ ) }, /* @__PURE__ */ import_react64.default.createElement("div", { className: "mb-4 text-gold" }, /* @__PURE__ */ import_react64.default.createElement(import_lucide_react12.Music, { size: 48 })), src && /* @__PURE__ */ import_react64.default.createElement("div", { className: "w-full px-4" }, /* @__PURE__ */ import_react64.default.createElement(
5369
5399
  import_react_player2.default,
5370
5400
  {
5371
5401
  src,
@@ -5388,7 +5418,7 @@ var AudioCard = import_react63.default.forwardRef(
5388
5418
  ...playerProps
5389
5419
  }
5390
5420
  ))),
5391
- /* @__PURE__ */ import_react63.default.createElement(
5421
+ /* @__PURE__ */ import_react64.default.createElement(
5392
5422
  Card.Header,
5393
5423
  {
5394
5424
  title,
@@ -5396,16 +5426,16 @@ var AudioCard = import_react63.default.forwardRef(
5396
5426
  className: contentClassName
5397
5427
  }
5398
5428
  ),
5399
- children && /* @__PURE__ */ import_react63.default.createElement(Card.Body, { className: contentClassName }, children)
5429
+ children && /* @__PURE__ */ import_react64.default.createElement(Card.Body, { className: contentClassName }, children)
5400
5430
  );
5401
5431
  }
5402
5432
  );
5403
5433
  AudioCard.displayName = "AudioCard";
5404
5434
 
5405
5435
  // src/components/PdfCard.tsx
5406
- var import_react64 = __toESM(require("react"));
5436
+ var import_react65 = __toESM(require("react"));
5407
5437
  var import_lucide_react13 = require("lucide-react");
5408
- var PdfCard = import_react64.default.forwardRef(
5438
+ var PdfCard = import_react65.default.forwardRef(
5409
5439
  ({
5410
5440
  src,
5411
5441
  title,
@@ -5418,7 +5448,7 @@ var PdfCard = import_react64.default.forwardRef(
5418
5448
  loading,
5419
5449
  ...props
5420
5450
  }, ref) => {
5421
- return /* @__PURE__ */ import_react64.default.createElement(
5451
+ return /* @__PURE__ */ import_react65.default.createElement(
5422
5452
  Card,
5423
5453
  {
5424
5454
  ref,
@@ -5426,13 +5456,13 @@ var PdfCard = import_react64.default.forwardRef(
5426
5456
  loading,
5427
5457
  ...props
5428
5458
  },
5429
- /* @__PURE__ */ import_react64.default.createElement(
5459
+ /* @__PURE__ */ import_react65.default.createElement(
5430
5460
  Card.Media,
5431
5461
  {
5432
5462
  className: cx("bg-obsidian", mediaClassName),
5433
5463
  style: { height }
5434
5464
  },
5435
- src && /* @__PURE__ */ import_react64.default.createElement(
5465
+ src && /* @__PURE__ */ import_react65.default.createElement(
5436
5466
  "iframe",
5437
5467
  {
5438
5468
  src: `${src}#view=FitH`,
@@ -5441,23 +5471,23 @@ var PdfCard = import_react64.default.forwardRef(
5441
5471
  }
5442
5472
  )
5443
5473
  ),
5444
- /* @__PURE__ */ import_react64.default.createElement(
5474
+ /* @__PURE__ */ import_react65.default.createElement(
5445
5475
  Card.Header,
5446
5476
  {
5447
5477
  title,
5448
5478
  subtitle,
5449
5479
  className: contentClassName,
5450
- action: /* @__PURE__ */ import_react64.default.createElement("div", { className: "p-2 bg-ash/20 text-gold shrink-0" }, /* @__PURE__ */ import_react64.default.createElement(import_lucide_react13.FileText, { size: 20 }))
5480
+ action: /* @__PURE__ */ import_react65.default.createElement("div", { className: "p-2 bg-ash/20 text-gold shrink-0" }, /* @__PURE__ */ import_react65.default.createElement(import_lucide_react13.FileText, { size: 20 }))
5451
5481
  }
5452
5482
  ),
5453
- children && /* @__PURE__ */ import_react64.default.createElement(Card.Body, { className: contentClassName }, children)
5483
+ children && /* @__PURE__ */ import_react65.default.createElement(Card.Body, { className: contentClassName }, children)
5454
5484
  );
5455
5485
  }
5456
5486
  );
5457
5487
  PdfCard.displayName = "PdfCard";
5458
5488
 
5459
5489
  // src/components/ScriptCard.tsx
5460
- var import_react65 = __toESM(require("react"));
5490
+ var import_react66 = __toESM(require("react"));
5461
5491
  var SCRIPT_ELEMENT_TYPES = {
5462
5492
  SCENE_HEADING: "scene-heading",
5463
5493
  ACTION: "action",
@@ -5471,28 +5501,28 @@ var SCRIPT_ELEMENT_TYPES = {
5471
5501
  function ScriptElementRenderer({ element }) {
5472
5502
  switch (element.type) {
5473
5503
  case "scene-heading":
5474
- return /* @__PURE__ */ import_react65.default.createElement("p", { className: "mt-4 mb-2 font-bold uppercase text-gold text-xs tracking-wide" }, element.content);
5504
+ return /* @__PURE__ */ import_react66.default.createElement("p", { className: "mt-4 mb-2 font-bold uppercase text-gold text-xs tracking-wide" }, element.content);
5475
5505
  case "action":
5476
- return /* @__PURE__ */ import_react65.default.createElement("p", { className: "my-2 text-silver text-xs leading-relaxed" }, element.content);
5506
+ return /* @__PURE__ */ import_react66.default.createElement("p", { className: "my-2 text-silver text-xs leading-relaxed" }, element.content);
5477
5507
  case "character":
5478
- return /* @__PURE__ */ import_react65.default.createElement("p", { className: "mt-4 mb-0.5 ml-8 font-bold text-white text-xs uppercase tracking-wide" }, element.content);
5508
+ return /* @__PURE__ */ import_react66.default.createElement("p", { className: "mt-4 mb-0.5 ml-8 font-bold text-white text-xs uppercase tracking-wide" }, element.content);
5479
5509
  case "parenthetical":
5480
- return /* @__PURE__ */ import_react65.default.createElement("p", { className: "ml-6 text-silver/70 text-xs italic" }, "(", element.content, ")");
5510
+ return /* @__PURE__ */ import_react66.default.createElement("p", { className: "ml-6 text-silver/70 text-xs italic" }, "(", element.content, ")");
5481
5511
  case "dialogue":
5482
- return /* @__PURE__ */ import_react65.default.createElement("p", { className: "ml-4 mr-8 text-silver text-xs leading-relaxed" }, element.content);
5512
+ return /* @__PURE__ */ import_react66.default.createElement("p", { className: "ml-4 mr-8 text-silver text-xs leading-relaxed" }, element.content);
5483
5513
  case "transition":
5484
- return /* @__PURE__ */ import_react65.default.createElement("p", { className: "mt-4 mb-2 text-right font-bold uppercase text-gold/80 text-xs tracking-wide" }, element.content);
5514
+ return /* @__PURE__ */ import_react66.default.createElement("p", { className: "mt-4 mb-2 text-right font-bold uppercase text-gold/80 text-xs tracking-wide" }, element.content);
5485
5515
  case "title":
5486
- return /* @__PURE__ */ import_react65.default.createElement("p", { className: "mt-6 mb-2 text-center font-bold text-gold text-sm" }, element.content);
5516
+ return /* @__PURE__ */ import_react66.default.createElement("p", { className: "mt-6 mb-2 text-center font-bold text-gold text-sm" }, element.content);
5487
5517
  case "subtitle":
5488
- return /* @__PURE__ */ import_react65.default.createElement("p", { className: "text-center italic text-gold/70 text-xs" }, element.content);
5518
+ return /* @__PURE__ */ import_react66.default.createElement("p", { className: "text-center italic text-gold/70 text-xs" }, element.content);
5489
5519
  default:
5490
5520
  return null;
5491
5521
  }
5492
5522
  }
5493
- var ScriptCard = import_react65.default.forwardRef(
5523
+ var ScriptCard = import_react66.default.forwardRef(
5494
5524
  ({ title, subtitle, elements, maxHeight = "16rem", className, style, loading, ...rest }, ref) => {
5495
- return /* @__PURE__ */ import_react65.default.createElement(
5525
+ return /* @__PURE__ */ import_react66.default.createElement(
5496
5526
  Card,
5497
5527
  {
5498
5528
  ref,
@@ -5500,20 +5530,20 @@ var ScriptCard = import_react65.default.forwardRef(
5500
5530
  loading,
5501
5531
  ...rest
5502
5532
  },
5503
- /* @__PURE__ */ import_react65.default.createElement(
5533
+ /* @__PURE__ */ import_react66.default.createElement(
5504
5534
  Card.Header,
5505
5535
  {
5506
5536
  title,
5507
5537
  subtitle
5508
5538
  }
5509
5539
  ),
5510
- /* @__PURE__ */ import_react65.default.createElement(
5540
+ /* @__PURE__ */ import_react66.default.createElement(
5511
5541
  Card.Body,
5512
5542
  {
5513
5543
  className: "font-mono overflow-y-auto",
5514
5544
  style: { maxHeight, ...style }
5515
5545
  },
5516
- elements.map((element, index) => /* @__PURE__ */ import_react65.default.createElement(ScriptElementRenderer, { key: index, element }))
5546
+ elements.map((element, index) => /* @__PURE__ */ import_react66.default.createElement(ScriptElementRenderer, { key: index, element }))
5517
5547
  )
5518
5548
  );
5519
5549
  }
@@ -5521,8 +5551,8 @@ var ScriptCard = import_react65.default.forwardRef(
5521
5551
  ScriptCard.displayName = "ScriptCard";
5522
5552
 
5523
5553
  // src/components/TextCard.tsx
5524
- var import_react66 = __toESM(require("react"));
5525
- var TextCard = import_react66.default.forwardRef(
5554
+ var import_react67 = __toESM(require("react"));
5555
+ var TextCard = import_react67.default.forwardRef(
5526
5556
  ({
5527
5557
  content,
5528
5558
  title,
@@ -5534,7 +5564,7 @@ var TextCard = import_react66.default.forwardRef(
5534
5564
  loading,
5535
5565
  ...props
5536
5566
  }, ref) => {
5537
- return /* @__PURE__ */ import_react66.default.createElement(
5567
+ return /* @__PURE__ */ import_react67.default.createElement(
5538
5568
  Card,
5539
5569
  {
5540
5570
  ref,
@@ -5542,20 +5572,20 @@ var TextCard = import_react66.default.forwardRef(
5542
5572
  loading,
5543
5573
  ...props
5544
5574
  },
5545
- /* @__PURE__ */ import_react66.default.createElement(
5575
+ /* @__PURE__ */ import_react67.default.createElement(
5546
5576
  Card.Header,
5547
5577
  {
5548
5578
  title,
5549
5579
  subtitle
5550
5580
  }
5551
5581
  ),
5552
- /* @__PURE__ */ import_react66.default.createElement(
5582
+ /* @__PURE__ */ import_react67.default.createElement(
5553
5583
  Card.Body,
5554
5584
  {
5555
5585
  className: cx("overflow-y-auto", contentClassName),
5556
5586
  style: { maxHeight }
5557
5587
  },
5558
- /* @__PURE__ */ import_react66.default.createElement(
5588
+ /* @__PURE__ */ import_react67.default.createElement(
5559
5589
  MarkdownContent,
5560
5590
  {
5561
5591
  content,
@@ -5593,7 +5623,7 @@ var ARTIFACT_TYPES = {
5593
5623
  SCRIPT: "SCRIPT",
5594
5624
  PDF: "PDF"
5595
5625
  };
5596
- var ArtifactCard = import_react67.default.forwardRef(
5626
+ var ArtifactCard = import_react68.default.forwardRef(
5597
5627
  ({ artifact, onExpand, loading, className, ...props }, ref) => {
5598
5628
  const derivedLoading = deriveCardSlotLoading(artifact);
5599
5629
  const commonProps = {
@@ -5611,7 +5641,7 @@ var ArtifactCard = import_react67.default.forwardRef(
5611
5641
  const renderContent = () => {
5612
5642
  switch (artifact.type) {
5613
5643
  case "IMAGE":
5614
- return /* @__PURE__ */ import_react67.default.createElement(
5644
+ return /* @__PURE__ */ import_react68.default.createElement(
5615
5645
  ImageCard,
5616
5646
  {
5617
5647
  ...commonProps,
@@ -5621,7 +5651,7 @@ var ArtifactCard = import_react67.default.forwardRef(
5621
5651
  }
5622
5652
  );
5623
5653
  case "VIDEO":
5624
- return /* @__PURE__ */ import_react67.default.createElement(
5654
+ return /* @__PURE__ */ import_react68.default.createElement(
5625
5655
  VideoCard,
5626
5656
  {
5627
5657
  ...commonProps,
@@ -5631,7 +5661,7 @@ var ArtifactCard = import_react67.default.forwardRef(
5631
5661
  }
5632
5662
  );
5633
5663
  case "AUDIO":
5634
- return /* @__PURE__ */ import_react67.default.createElement(
5664
+ return /* @__PURE__ */ import_react68.default.createElement(
5635
5665
  AudioCard,
5636
5666
  {
5637
5667
  ...commonProps,
@@ -5640,7 +5670,7 @@ var ArtifactCard = import_react67.default.forwardRef(
5640
5670
  }
5641
5671
  );
5642
5672
  case "PDF":
5643
- return /* @__PURE__ */ import_react67.default.createElement(
5673
+ return /* @__PURE__ */ import_react68.default.createElement(
5644
5674
  PdfCard,
5645
5675
  {
5646
5676
  ...commonProps,
@@ -5648,7 +5678,7 @@ var ArtifactCard = import_react67.default.forwardRef(
5648
5678
  }
5649
5679
  );
5650
5680
  case "SCRIPT":
5651
- return /* @__PURE__ */ import_react67.default.createElement(
5681
+ return /* @__PURE__ */ import_react68.default.createElement(
5652
5682
  ScriptCard,
5653
5683
  {
5654
5684
  ...commonProps,
@@ -5657,7 +5687,7 @@ var ArtifactCard = import_react67.default.forwardRef(
5657
5687
  }
5658
5688
  );
5659
5689
  case "TEXT":
5660
- return /* @__PURE__ */ import_react67.default.createElement(
5690
+ return /* @__PURE__ */ import_react68.default.createElement(
5661
5691
  TextCard,
5662
5692
  {
5663
5693
  ...commonProps,
@@ -5673,7 +5703,7 @@ var ArtifactCard = import_react67.default.forwardRef(
5673
5703
  }
5674
5704
  };
5675
5705
  const isCardExpandable = !!onExpand && (artifact.type === "IMAGE" || artifact.type === "PDF" || artifact.type === "SCRIPT" || artifact.type === "TEXT");
5676
- return /* @__PURE__ */ import_react67.default.createElement(
5706
+ return /* @__PURE__ */ import_react68.default.createElement(
5677
5707
  "div",
5678
5708
  {
5679
5709
  ref,
@@ -5686,7 +5716,7 @@ var ArtifactCard = import_react67.default.forwardRef(
5686
5716
  onClick: isCardExpandable ? handleExpand : void 0,
5687
5717
  ...props
5688
5718
  },
5689
- onExpand && /* @__PURE__ */ import_react67.default.createElement(
5719
+ onExpand && /* @__PURE__ */ import_react68.default.createElement(
5690
5720
  "button",
5691
5721
  {
5692
5722
  onClick: handleExpand,
@@ -5697,7 +5727,7 @@ var ArtifactCard = import_react67.default.forwardRef(
5697
5727
  ),
5698
5728
  "aria-label": "Expand artifact"
5699
5729
  },
5700
- /* @__PURE__ */ import_react67.default.createElement(ExpandIcon, { className: "w-4 h-4" })
5730
+ /* @__PURE__ */ import_react68.default.createElement(ExpandIcon, { className: "w-4 h-4" })
5701
5731
  ),
5702
5732
  renderContent()
5703
5733
  );
@@ -5705,12 +5735,178 @@ var ArtifactCard = import_react67.default.forwardRef(
5705
5735
  );
5706
5736
  ArtifactCard.displayName = "ArtifactCard";
5707
5737
 
5738
+ // src/components/ArtifactGroup.tsx
5739
+ var import_react69 = __toESM(require("react"));
5740
+ var LAYER_OFFSET = "8px";
5741
+ var LAYER_OFFSET_2X = "16px";
5742
+ var ArtifactGroup = import_react69.default.forwardRef(
5743
+ ({ node, onClick, className, ...props }, ref) => {
5744
+ const children = node.children;
5745
+ const count = children.length;
5746
+ const frontChild = children[0];
5747
+ const prevCountRef = (0, import_react69.useRef)(count);
5748
+ const [badgePing, setBadgePing] = (0, import_react69.useState)(false);
5749
+ (0, import_react69.useEffect)(() => {
5750
+ if (count !== prevCountRef.current) {
5751
+ prevCountRef.current = count;
5752
+ setBadgePing(true);
5753
+ const timer = setTimeout(() => setBadgePing(false), 500);
5754
+ return () => clearTimeout(timer);
5755
+ }
5756
+ }, [count]);
5757
+ const handleClick = () => {
5758
+ if (onClick) {
5759
+ onClick(node);
5760
+ }
5761
+ };
5762
+ const renderFrontContent = () => {
5763
+ if (!frontChild) {
5764
+ return /* @__PURE__ */ import_react69.default.createElement("div", { className: "w-full aspect-video bg-graphite border border-ash/40 flex items-center justify-center" }, /* @__PURE__ */ import_react69.default.createElement("span", { className: "text-silver text-sm" }, "Empty group"));
5765
+ }
5766
+ if (frontChild.type === "ARTIFACT" && frontChild.artifact) {
5767
+ return /* @__PURE__ */ import_react69.default.createElement(ArtifactCard, { artifact: frontChild.artifact, className: "w-full" });
5768
+ }
5769
+ return /* @__PURE__ */ import_react69.default.createElement(
5770
+ "div",
5771
+ {
5772
+ className: "w-full aspect-video bg-graphite border border-gold/30 flex flex-col items-center justify-center gap-2 p-4"
5773
+ },
5774
+ /* @__PURE__ */ import_react69.default.createElement("span", { className: "text-sm text-silver uppercase tracking-wider" }, frontChild.type === "GROUP" ? "Group" : "Variants"),
5775
+ /* @__PURE__ */ import_react69.default.createElement("span", { className: "text-white font-semibold" }, frontChild.label)
5776
+ );
5777
+ };
5778
+ return /* @__PURE__ */ import_react69.default.createElement(
5779
+ "div",
5780
+ {
5781
+ ref,
5782
+ className: cx(
5783
+ "cursor-pointer group",
5784
+ className
5785
+ ),
5786
+ onClick: handleClick,
5787
+ role: "button",
5788
+ tabIndex: 0,
5789
+ onKeyDown: (e) => {
5790
+ if (e.key === "Enter" || e.key === " ") {
5791
+ e.preventDefault();
5792
+ handleClick();
5793
+ }
5794
+ },
5795
+ "aria-label": `${node.label} \u2014 ${count} items`,
5796
+ ...props
5797
+ },
5798
+ /* @__PURE__ */ import_react69.default.createElement(Card, { noPadding: true, className: "p-5" }, /* @__PURE__ */ import_react69.default.createElement("h3", { className: "text-lg font-semibold text-white m-0 mb-4" }, node.label), /* @__PURE__ */ import_react69.default.createElement("div", { style: { paddingRight: LAYER_OFFSET_2X, paddingBottom: LAYER_OFFSET_2X } }, /* @__PURE__ */ import_react69.default.createElement("div", { className: "relative" }, /* @__PURE__ */ import_react69.default.createElement(
5799
+ "div",
5800
+ {
5801
+ className: "absolute inset-0 bg-charcoal border border-ash/30 pointer-events-none",
5802
+ style: { transform: `translate(${LAYER_OFFSET_2X}, ${LAYER_OFFSET_2X})` },
5803
+ "aria-hidden": "true"
5804
+ }
5805
+ ), /* @__PURE__ */ import_react69.default.createElement(
5806
+ "div",
5807
+ {
5808
+ className: "absolute inset-0 bg-charcoal border border-ash/40 pointer-events-none",
5809
+ style: { transform: `translate(${LAYER_OFFSET}, ${LAYER_OFFSET})` },
5810
+ "aria-hidden": "true"
5811
+ }
5812
+ ), /* @__PURE__ */ import_react69.default.createElement("div", { className: "relative transition-transform duration-200 group-hover:-translate-y-0.5" }, renderFrontContent()), /* @__PURE__ */ import_react69.default.createElement(
5813
+ "div",
5814
+ {
5815
+ className: "absolute -top-2 -right-2 z-10 min-w-6 h-6 px-1.5 flex items-center justify-center bg-gold text-obsidian text-xs font-bold",
5816
+ style: badgePing ? { animation: "badge-invert 0.6s ease-in-out" } : void 0
5817
+ },
5818
+ count
5819
+ ))))
5820
+ );
5821
+ }
5822
+ );
5823
+ ArtifactGroup.displayName = "ArtifactGroup";
5824
+
5825
+ // src/components/ArtifactVariantStack.tsx
5826
+ var import_react70 = __toESM(require("react"));
5827
+ var ArtifactVariantStack = import_react70.default.forwardRef(
5828
+ ({ node, onExpandArtifact, onGroupClick, className, ...props }, ref) => {
5829
+ const children = node.children;
5830
+ const renderChild = (child) => {
5831
+ if (child.type === "ARTIFACT" && child.artifact) {
5832
+ return /* @__PURE__ */ import_react70.default.createElement("div", { key: child.id, className: "flex-1 min-w-0" }, /* @__PURE__ */ import_react70.default.createElement(
5833
+ ArtifactCard,
5834
+ {
5835
+ artifact: child.artifact,
5836
+ onExpand: onExpandArtifact,
5837
+ className: "w-full"
5838
+ }
5839
+ ));
5840
+ }
5841
+ if (child.type === "GROUP") {
5842
+ return /* @__PURE__ */ import_react70.default.createElement("div", { key: child.id, className: "flex-1 min-w-0" }, /* @__PURE__ */ import_react70.default.createElement(ArtifactGroup, { node: child, onClick: onGroupClick }));
5843
+ }
5844
+ return /* @__PURE__ */ import_react70.default.createElement("div", { key: child.id, className: "flex-1 min-w-0" }, /* @__PURE__ */ import_react70.default.createElement(
5845
+ "div",
5846
+ {
5847
+ className: "aspect-video bg-graphite border border-gold/30 flex flex-col items-center justify-center gap-2 p-4"
5848
+ },
5849
+ /* @__PURE__ */ import_react70.default.createElement("span", { className: "text-xs text-silver uppercase tracking-wider" }, "Variants"),
5850
+ /* @__PURE__ */ import_react70.default.createElement("span", { className: "text-sm text-white font-semibold truncate max-w-full" }, child.label)
5851
+ ));
5852
+ };
5853
+ return /* @__PURE__ */ import_react70.default.createElement(
5854
+ Card,
5855
+ {
5856
+ ref,
5857
+ noPadding: true,
5858
+ className: cx("w-full p-5", className),
5859
+ ...props
5860
+ },
5861
+ /* @__PURE__ */ import_react70.default.createElement("h3", { className: "text-lg font-semibold text-white m-0 mb-4" }, node.label),
5862
+ /* @__PURE__ */ import_react70.default.createElement("div", { className: "flex gap-3" }, children.map(renderChild))
5863
+ );
5864
+ }
5865
+ );
5866
+ ArtifactVariantStack.displayName = "ArtifactVariantStack";
5867
+
5868
+ // src/components/chat/hooks/useArtifactTreeNavigation.ts
5869
+ var import_react71 = require("react");
5870
+ function useArtifactTreeNavigation(rootNodes) {
5871
+ const [stack, setStack] = (0, import_react71.useState)([]);
5872
+ const currentNodes = (0, import_react71.useMemo)(() => {
5873
+ if (stack.length === 0) return rootNodes;
5874
+ return stack[stack.length - 1].children;
5875
+ }, [rootNodes, stack]);
5876
+ const breadcrumbs = (0, import_react71.useMemo)(() => {
5877
+ const entries = [{ label: "Project", node: null }];
5878
+ for (const node of stack) {
5879
+ entries.push({ label: node.label, node });
5880
+ }
5881
+ return entries;
5882
+ }, [stack]);
5883
+ const isAtRoot = stack.length === 0;
5884
+ const navigateInto = (0, import_react71.useCallback)((node) => {
5885
+ setStack((prev) => [...prev, node]);
5886
+ }, []);
5887
+ const navigateTo = (0, import_react71.useCallback)((index) => {
5888
+ setStack((prev) => prev.slice(0, index));
5889
+ }, []);
5890
+ const navigateBack = (0, import_react71.useCallback)(() => {
5891
+ setStack((prev) => prev.slice(0, -1));
5892
+ }, []);
5893
+ return {
5894
+ currentNodes,
5895
+ breadcrumbs,
5896
+ isAtRoot,
5897
+ navigateInto,
5898
+ navigateTo,
5899
+ navigateBack
5900
+ };
5901
+ }
5902
+
5708
5903
  // src/components/chat/ArtifactsPanel.tsx
5904
+ var ZOOM_LEVELS = [0.25, 0.5, 0.75, 1];
5709
5905
  function ArtifactModal({
5710
5906
  artifact,
5711
5907
  onClose
5712
5908
  }) {
5713
- (0, import_react68.useEffect)(() => {
5909
+ (0, import_react72.useEffect)(() => {
5714
5910
  const handleKeyDown = (e) => {
5715
5911
  if (e.key === "Escape") {
5716
5912
  onClose();
@@ -5719,46 +5915,46 @@ function ArtifactModal({
5719
5915
  document.addEventListener("keydown", handleKeyDown);
5720
5916
  return () => document.removeEventListener("keydown", handleKeyDown);
5721
5917
  }, [onClose]);
5722
- const handleBackdropClick = (0, import_react68.useCallback)((e) => {
5918
+ const handleBackdropClick = (0, import_react72.useCallback)((e) => {
5723
5919
  if (e.target === e.currentTarget) {
5724
5920
  onClose();
5725
5921
  }
5726
5922
  }, [onClose]);
5727
- return /* @__PURE__ */ import_react68.default.createElement(
5923
+ return /* @__PURE__ */ import_react72.default.createElement(
5728
5924
  "div",
5729
5925
  {
5730
5926
  className: "fixed inset-0 z-50 flex items-center justify-center bg-void/90 backdrop-blur-sm animate-fade-in",
5731
5927
  onClick: handleBackdropClick
5732
5928
  },
5733
- /* @__PURE__ */ import_react68.default.createElement(
5929
+ /* @__PURE__ */ import_react72.default.createElement(
5734
5930
  "div",
5735
5931
  {
5736
5932
  className: "relative w-11/12 h-5/6 max-w-6xl bg-charcoal border border-ash/40 flex flex-col overflow-hidden"
5737
5933
  },
5738
- /* @__PURE__ */ import_react68.default.createElement(
5934
+ /* @__PURE__ */ import_react72.default.createElement(
5739
5935
  "div",
5740
5936
  {
5741
5937
  className: "flex items-center justify-between p-4 border-b border-ash/40 shrink-0"
5742
5938
  },
5743
- /* @__PURE__ */ import_react68.default.createElement("div", null, artifact.title && /* @__PURE__ */ import_react68.default.createElement("h3", { className: "text-sm font-semibold text-white" }, artifact.title), artifact.subtitle && /* @__PURE__ */ import_react68.default.createElement("p", { className: "text-xs text-silver" }, artifact.subtitle)),
5744
- /* @__PURE__ */ import_react68.default.createElement(
5939
+ /* @__PURE__ */ import_react72.default.createElement("div", null, artifact.title && /* @__PURE__ */ import_react72.default.createElement("h3", { className: "text-sm font-semibold text-white" }, artifact.title), artifact.subtitle && /* @__PURE__ */ import_react72.default.createElement("p", { className: "text-xs text-silver" }, artifact.subtitle)),
5940
+ /* @__PURE__ */ import_react72.default.createElement(
5745
5941
  "button",
5746
5942
  {
5747
5943
  onClick: onClose,
5748
5944
  className: "p-2 text-silver hover:text-white hover:bg-ash/20 transition-colors",
5749
5945
  "aria-label": "Close modal"
5750
5946
  },
5751
- /* @__PURE__ */ import_react68.default.createElement(CloseIcon, { className: "w-5 h-5" })
5947
+ /* @__PURE__ */ import_react72.default.createElement(CloseIcon, { className: "w-5 h-5" })
5752
5948
  )
5753
5949
  ),
5754
- /* @__PURE__ */ import_react68.default.createElement("div", { className: "flex-1 overflow-auto p-4" }, artifact.type === "IMAGE" && /* @__PURE__ */ import_react68.default.createElement(
5950
+ /* @__PURE__ */ import_react72.default.createElement("div", { className: "flex-1 overflow-auto p-4" }, artifact.type === "IMAGE" && /* @__PURE__ */ import_react72.default.createElement(
5755
5951
  "img",
5756
5952
  {
5757
5953
  src: artifact.url,
5758
5954
  alt: artifact.alt || "Artifact image",
5759
5955
  className: "max-w-full max-h-full object-contain mx-auto"
5760
5956
  }
5761
- ), artifact.type === "VIDEO" && /* @__PURE__ */ import_react68.default.createElement(
5957
+ ), artifact.type === "VIDEO" && /* @__PURE__ */ import_react72.default.createElement(
5762
5958
  VideoCard,
5763
5959
  {
5764
5960
  src: artifact.url || "",
@@ -5766,20 +5962,20 @@ function ArtifactModal({
5766
5962
  controls: true,
5767
5963
  className: "max-w-full max-h-full mx-auto"
5768
5964
  }
5769
- ), artifact.type === "AUDIO" && /* @__PURE__ */ import_react68.default.createElement(
5965
+ ), artifact.type === "AUDIO" && /* @__PURE__ */ import_react72.default.createElement(
5770
5966
  AudioCard,
5771
5967
  {
5772
5968
  src: artifact.url || "",
5773
5969
  controls: true,
5774
5970
  className: "max-w-xl mx-auto"
5775
5971
  }
5776
- ), artifact.type === "PDF" && /* @__PURE__ */ import_react68.default.createElement(
5972
+ ), artifact.type === "PDF" && /* @__PURE__ */ import_react72.default.createElement(
5777
5973
  PdfCard,
5778
5974
  {
5779
5975
  src: artifact.url || "",
5780
5976
  className: "h-full border-0"
5781
5977
  }
5782
- ), artifact.type === "TEXT" && /* @__PURE__ */ import_react68.default.createElement(
5978
+ ), artifact.type === "TEXT" && /* @__PURE__ */ import_react72.default.createElement(
5783
5979
  MarkdownContent,
5784
5980
  {
5785
5981
  content: artifact.inlineContent || "",
@@ -5789,7 +5985,7 @@ function ArtifactModal({
5789
5985
  artifact.mimeType === "text/plain" && "whitespace-pre-wrap"
5790
5986
  )
5791
5987
  }
5792
- ), artifact.type === "SCRIPT" && artifact.scriptElements && /* @__PURE__ */ import_react68.default.createElement(
5988
+ ), artifact.type === "SCRIPT" && artifact.scriptElements && /* @__PURE__ */ import_react72.default.createElement(
5793
5989
  ScriptCard,
5794
5990
  {
5795
5991
  elements: artifact.scriptElements,
@@ -5800,138 +5996,181 @@ function ArtifactModal({
5800
5996
  )
5801
5997
  );
5802
5998
  }
5803
- function ArtifactRenderer({
5804
- artifact,
5999
+ function NodeRenderer({
6000
+ node,
5805
6001
  loading,
5806
- onExpand
6002
+ onExpandArtifact,
6003
+ onGroupClick
5807
6004
  }) {
5808
- return /* @__PURE__ */ import_react68.default.createElement(
5809
- ArtifactCard,
5810
- {
5811
- artifact,
5812
- loading,
5813
- onExpand
5814
- }
5815
- );
6005
+ if (node.type === "ARTIFACT" && node.artifact) {
6006
+ return /* @__PURE__ */ import_react72.default.createElement(
6007
+ ArtifactCard,
6008
+ {
6009
+ artifact: node.artifact,
6010
+ loading,
6011
+ onExpand: onExpandArtifact
6012
+ }
6013
+ );
6014
+ }
6015
+ if (node.type === "GROUP") {
6016
+ return /* @__PURE__ */ import_react72.default.createElement(ArtifactGroup, { node, onClick: onGroupClick });
6017
+ }
6018
+ if (node.type === "VARIANT_SET") {
6019
+ return /* @__PURE__ */ import_react72.default.createElement(
6020
+ ArtifactVariantStack,
6021
+ {
6022
+ node,
6023
+ onExpandArtifact,
6024
+ onGroupClick
6025
+ }
6026
+ );
6027
+ }
6028
+ return null;
5816
6029
  }
5817
- var ArtifactsPanel = import_react68.default.forwardRef(
6030
+ var ArtifactsPanel = import_react72.default.forwardRef(
5818
6031
  ({
5819
- artifacts,
5820
- isOpen = false,
5821
- onClose,
6032
+ nodes,
5822
6033
  loading,
5823
- width,
5824
- widthPercent,
5825
- onResizeStart,
5826
6034
  className,
5827
6035
  ...rest
5828
6036
  }, ref) => {
5829
- const [expandedArtifact, setExpandedArtifact] = (0, import_react68.useState)(null);
5830
- const columns = widthPercent && widthPercent > 55 ? 3 : widthPercent && widthPercent > 35 ? 2 : 1;
5831
- if (!isOpen) {
5832
- return /* @__PURE__ */ import_react68.default.createElement(
5833
- "div",
5834
- {
5835
- ref,
5836
- className: cx(
5837
- "h-full bg-charcoal/80 border-l border-ash/40 flex flex-col items-center py-3",
5838
- "w-12 shrink-0",
5839
- className
5840
- ),
5841
- ...rest
5842
- },
5843
- /* @__PURE__ */ import_react68.default.createElement(
5844
- "button",
5845
- {
5846
- onClick: onClose,
5847
- className: cx(
5848
- "p-2",
5849
- "text-silver hover:text-white hover:bg-ash/20",
5850
- "transition-colors duration-150",
5851
- "relative"
5852
- ),
5853
- "aria-label": "Expand artifacts panel"
5854
- },
5855
- /* @__PURE__ */ import_react68.default.createElement(LayersIcon, { className: "w-5 h-5" }),
5856
- artifacts.length > 0 && /* @__PURE__ */ import_react68.default.createElement(
5857
- "span",
5858
- {
5859
- className: "absolute -top-1 -right-1 w-4 h-4 bg-gold text-obsidian text-xs font-medium flex items-center justify-center rounded-full"
5860
- },
5861
- artifacts.length
5862
- )
5863
- )
5864
- );
5865
- }
5866
- return /* @__PURE__ */ import_react68.default.createElement(import_react68.default.Fragment, null, /* @__PURE__ */ import_react68.default.createElement(
6037
+ const [expandedArtifact, setExpandedArtifact] = (0, import_react72.useState)(null);
6038
+ const [zoomIndex, setZoomIndex] = (0, import_react72.useState)(ZOOM_LEVELS.length - 1);
6039
+ const treeNav = useArtifactTreeNavigation(nodes || []);
6040
+ const hasNodes = !!nodes && nodes.length > 0;
6041
+ const handleExpandArtifact = (0, import_react72.useCallback)((artifact) => {
6042
+ setExpandedArtifact(artifact);
6043
+ }, []);
6044
+ const handleGroupClick = (0, import_react72.useCallback)((node) => {
6045
+ treeNav.navigateInto(node);
6046
+ }, [treeNav]);
6047
+ const zoomIn = (0, import_react72.useCallback)(() => {
6048
+ setZoomIndex((prev) => Math.min(prev + 1, ZOOM_LEVELS.length - 1));
6049
+ }, []);
6050
+ const zoomOut = (0, import_react72.useCallback)(() => {
6051
+ setZoomIndex((prev) => Math.max(prev - 1, 0));
6052
+ }, []);
6053
+ const currentZoom = ZOOM_LEVELS[zoomIndex];
6054
+ const contentRef = (0, import_react72.useRef)(null);
6055
+ const [contentHeight, setContentHeight] = (0, import_react72.useState)(void 0);
6056
+ (0, import_react72.useEffect)(() => {
6057
+ const el = contentRef.current;
6058
+ if (!el) return;
6059
+ const observer = new ResizeObserver(([entry]) => {
6060
+ setContentHeight(entry.contentRect.height);
6061
+ });
6062
+ observer.observe(el);
6063
+ return () => observer.disconnect();
6064
+ }, []);
6065
+ return /* @__PURE__ */ import_react72.default.createElement(import_react72.default.Fragment, null, /* @__PURE__ */ import_react72.default.createElement(
5867
6066
  "div",
5868
6067
  {
5869
6068
  ref,
5870
6069
  "data-testid": "artifacts-panel",
5871
6070
  className: cx(
5872
- "h-full bg-charcoal/50 border-l border-ash/40 flex flex-col relative",
5873
- !width && "w-96",
5874
- "shrink-0",
6071
+ "h-full flex flex-col relative",
5875
6072
  className
5876
6073
  ),
5877
- style: width ? { width } : void 0,
5878
6074
  ...rest
5879
6075
  },
5880
- /* @__PURE__ */ import_react68.default.createElement(
5881
- "div",
5882
- {
5883
- onMouseDown: onResizeStart,
5884
- "data-testid": "artifacts-resize-handle",
5885
- className: cx(
5886
- "absolute top-0 left-0 w-1 h-full cursor-col-resize z-50",
5887
- "hover:bg-gold/50 transition-colors",
5888
- "after:absolute after:inset-y-0 after:-left-1 after:w-2"
5889
- // Larger hit area
5890
- )
5891
- }
5892
- ),
5893
- /* @__PURE__ */ import_react68.default.createElement(
6076
+ /* @__PURE__ */ import_react72.default.createElement(
5894
6077
  "div",
5895
6078
  {
5896
6079
  className: "flex items-center justify-between p-4 border-b border-ash/40 shrink-0"
5897
6080
  },
5898
- /* @__PURE__ */ import_react68.default.createElement("h3", { className: "text-sm font-semibold text-white" }, "Artifacts"),
5899
- /* @__PURE__ */ import_react68.default.createElement(
5900
- "button",
6081
+ /* @__PURE__ */ import_react72.default.createElement("h3", { className: "text-sm font-semibold text-white" }, "Artifacts"),
6082
+ hasNodes && /* @__PURE__ */ import_react72.default.createElement(
6083
+ "div",
5901
6084
  {
5902
- onClick: onClose,
5903
- className: cx(
5904
- "p-1.5",
5905
- "text-silver hover:text-white hover:bg-ash/20",
5906
- "transition-colors duration-150"
5907
- ),
5908
- "aria-label": "Collapse artifacts panel"
6085
+ className: "flex items-center gap-0.5",
6086
+ "data-testid": "zoom-controls"
5909
6087
  },
5910
- /* @__PURE__ */ import_react68.default.createElement(ChevronRightIcon, { className: "w-5 h-5" })
6088
+ /* @__PURE__ */ import_react72.default.createElement(
6089
+ "button",
6090
+ {
6091
+ onClick: zoomOut,
6092
+ disabled: zoomIndex === 0,
6093
+ className: cx(
6094
+ "w-6 h-6 flex items-center justify-center text-xs font-bold",
6095
+ "bg-charcoal border border-ash/40",
6096
+ zoomIndex === 0 ? "text-silver/30 cursor-not-allowed" : "text-silver hover:text-gold hover:border-gold/40 transition-colors"
6097
+ ),
6098
+ "aria-label": "Zoom out"
6099
+ },
6100
+ "\u2212"
6101
+ ),
6102
+ /* @__PURE__ */ import_react72.default.createElement("span", { className: "text-xs text-silver w-8 text-center tabular-nums", "data-testid": "zoom-level" }, Math.round(currentZoom * 100), "%"),
6103
+ /* @__PURE__ */ import_react72.default.createElement(
6104
+ "button",
6105
+ {
6106
+ onClick: zoomIn,
6107
+ disabled: zoomIndex === ZOOM_LEVELS.length - 1,
6108
+ className: cx(
6109
+ "w-6 h-6 flex items-center justify-center text-xs font-bold",
6110
+ "bg-charcoal border border-ash/40",
6111
+ zoomIndex === ZOOM_LEVELS.length - 1 ? "text-silver/30 cursor-not-allowed" : "text-silver hover:text-gold hover:border-gold/40 transition-colors"
6112
+ ),
6113
+ "aria-label": "Zoom in"
6114
+ },
6115
+ "+"
6116
+ )
5911
6117
  )
5912
6118
  ),
5913
- /* @__PURE__ */ import_react68.default.createElement(
6119
+ hasNodes && !treeNav.isAtRoot && /* @__PURE__ */ import_react72.default.createElement(
6120
+ "nav",
6121
+ {
6122
+ className: "flex items-center gap-1 px-4 py-2 border-b border-ash/40 shrink-0 overflow-x-auto text-xs",
6123
+ "aria-label": "Breadcrumb",
6124
+ "data-testid": "breadcrumb-nav"
6125
+ },
6126
+ treeNav.breadcrumbs.map((crumb, i) => {
6127
+ const isLast = i === treeNav.breadcrumbs.length - 1;
6128
+ return /* @__PURE__ */ import_react72.default.createElement("span", { key: i, className: "flex items-center gap-1 shrink-0" }, i > 0 && /* @__PURE__ */ import_react72.default.createElement(ChevronRightIcon, { className: "w-3 h-3 text-silver/50", "aria-hidden": true }), isLast ? /* @__PURE__ */ import_react72.default.createElement("span", { className: "text-gold font-medium" }, crumb.label) : /* @__PURE__ */ import_react72.default.createElement(
6129
+ "button",
6130
+ {
6131
+ onClick: () => treeNav.navigateTo(i),
6132
+ className: "text-silver hover:text-white transition-colors"
6133
+ },
6134
+ crumb.label
6135
+ ));
6136
+ })
6137
+ ),
6138
+ /* @__PURE__ */ import_react72.default.createElement(
5914
6139
  "div",
5915
6140
  {
5916
- "data-testid": "artifacts-grid",
5917
- className: cx(
5918
- "flex-1 overflow-y-auto p-4",
5919
- columns === 1 ? "space-y-4" : "grid gap-4",
5920
- columns === 2 && "grid-cols-2",
5921
- columns === 3 && "grid-cols-3"
5922
- )
6141
+ className: "flex-1 overflow-auto relative",
6142
+ "data-testid": "artifacts-scroll-area"
5923
6143
  },
5924
- artifacts.length === 0 && !loading ? /* @__PURE__ */ import_react68.default.createElement("p", { className: "text-xs text-silver/60 text-center py-8" }, "No artifacts to display") : artifacts.map((artifact) => /* @__PURE__ */ import_react68.default.createElement(
5925
- ArtifactRenderer,
6144
+ /* @__PURE__ */ import_react72.default.createElement(
6145
+ "div",
5926
6146
  {
5927
- key: artifact.id,
5928
- artifact,
5929
- loading,
5930
- onExpand: () => setExpandedArtifact(artifact)
5931
- }
5932
- ))
6147
+ style: currentZoom !== 1 && contentHeight !== void 0 ? { height: contentHeight * currentZoom } : void 0
6148
+ },
6149
+ /* @__PURE__ */ import_react72.default.createElement(
6150
+ "div",
6151
+ {
6152
+ ref: contentRef,
6153
+ "data-testid": "artifacts-grid",
6154
+ className: "p-4 space-y-4",
6155
+ style: currentZoom !== 1 ? {
6156
+ transform: `scale(${currentZoom})`,
6157
+ transformOrigin: "top center"
6158
+ } : void 0
6159
+ },
6160
+ treeNav.currentNodes.length === 0 ? /* @__PURE__ */ import_react72.default.createElement("p", { className: "text-xs text-silver/60 text-center py-8" }, hasNodes ? "Empty group" : "No artifacts to display") : treeNav.currentNodes.map((node) => /* @__PURE__ */ import_react72.default.createElement(
6161
+ NodeRenderer,
6162
+ {
6163
+ key: node.id,
6164
+ node,
6165
+ loading,
6166
+ onExpandArtifact: handleExpandArtifact,
6167
+ onGroupClick: handleGroupClick
6168
+ }
6169
+ ))
6170
+ )
6171
+ )
5933
6172
  )
5934
- ), expandedArtifact && /* @__PURE__ */ import_react68.default.createElement(
6173
+ ), expandedArtifact && /* @__PURE__ */ import_react72.default.createElement(
5935
6174
  ArtifactModal,
5936
6175
  {
5937
6176
  artifact: expandedArtifact,
@@ -5941,8 +6180,8 @@ var ArtifactsPanel = import_react68.default.forwardRef(
5941
6180
  }
5942
6181
  );
5943
6182
  ArtifactsPanel.displayName = "ArtifactsPanel";
5944
- var ArtifactsPanelToggle = import_react68.default.forwardRef(({ artifactCount = 0, onExpand, className, ...rest }, ref) => {
5945
- return /* @__PURE__ */ import_react68.default.createElement(
6183
+ var ArtifactsPanelToggle = import_react72.default.forwardRef(({ artifactCount = 0, onExpand, className, ...rest }, ref) => {
6184
+ return /* @__PURE__ */ import_react72.default.createElement(
5946
6185
  "button",
5947
6186
  {
5948
6187
  ref,
@@ -5959,11 +6198,27 @@ var ArtifactsPanelToggle = import_react68.default.forwardRef(({ artifactCount =
5959
6198
  "aria-label": "Expand artifacts panel",
5960
6199
  ...rest
5961
6200
  },
5962
- /* @__PURE__ */ import_react68.default.createElement(LayersIcon, { className: "w-5 h-5" }),
5963
- artifactCount > 0 && /* @__PURE__ */ import_react68.default.createElement(
6201
+ /* @__PURE__ */ import_react72.default.createElement(
6202
+ "svg",
6203
+ {
6204
+ xmlns: "http://www.w3.org/2000/svg",
6205
+ viewBox: "0 0 20 20",
6206
+ fill: "currentColor",
6207
+ className: "w-5 h-5"
6208
+ },
6209
+ /* @__PURE__ */ import_react72.default.createElement(
6210
+ "path",
6211
+ {
6212
+ fillRule: "evenodd",
6213
+ d: "M2 4.5A1.5 1.5 0 013.5 3h13A1.5 1.5 0 0118 4.5v11a1.5 1.5 0 01-1.5 1.5h-13A1.5 1.5 0 012 15.5v-11zM4 5v1h1V5H4zm2 0v1h1V5H6zm7 0v1h1V5h-1zm2 0v1h1V5h-1zM4 14v1h1v-1H4zm2 0v1h1v-1H6zm7 0v1h1v-1h-1zm2 0v1h1v-1h-1zM8 8.118a.5.5 0 01.757-.429l4 2.382a.5.5 0 010 .858l-4 2.382A.5.5 0 018 12.882V8.118z",
6214
+ clipRule: "evenodd"
6215
+ }
6216
+ )
6217
+ ),
6218
+ artifactCount > 0 && /* @__PURE__ */ import_react72.default.createElement(
5964
6219
  "span",
5965
6220
  {
5966
- className: "absolute -top-1 -right-1 w-4 h-4 bg-gold text-obsidian text-xs font-medium flex items-center justify-center rounded-full"
6221
+ className: "absolute -top-1 -right-1 w-4 h-4 bg-gold text-obsidian text-xs font-medium flex items-center justify-center"
5967
6222
  },
5968
6223
  artifactCount
5969
6224
  )
@@ -5972,7 +6227,7 @@ var ArtifactsPanelToggle = import_react68.default.forwardRef(({ artifactCount =
5972
6227
  ArtifactsPanelToggle.displayName = "ArtifactsPanelToggle";
5973
6228
 
5974
6229
  // src/components/chat/TodosList.tsx
5975
- var import_react69 = __toESM(require("react"));
6230
+ var import_react73 = __toESM(require("react"));
5976
6231
  var TASK_STATUSES = {
5977
6232
  PENDING: "pending",
5978
6233
  IN_PROGRESS: "in_progress",
@@ -5983,16 +6238,16 @@ var TASK_STATUSES = {
5983
6238
  function TaskIcon({ status }) {
5984
6239
  switch (status) {
5985
6240
  case "done":
5986
- return /* @__PURE__ */ import_react69.default.createElement(CheckSquareIcon, null);
6241
+ return /* @__PURE__ */ import_react73.default.createElement(CheckSquareIcon, null);
5987
6242
  case "in_progress":
5988
- return /* @__PURE__ */ import_react69.default.createElement(SquareLoaderIcon, null);
6243
+ return /* @__PURE__ */ import_react73.default.createElement(SquareLoaderIcon, null);
5989
6244
  case "cancelled":
5990
- return /* @__PURE__ */ import_react69.default.createElement(CrossSquareIcon, { variant: "cancelled" });
6245
+ return /* @__PURE__ */ import_react73.default.createElement(CrossSquareIcon, { variant: "cancelled" });
5991
6246
  case "failed":
5992
- return /* @__PURE__ */ import_react69.default.createElement(CrossSquareIcon, { variant: "failed" });
6247
+ return /* @__PURE__ */ import_react73.default.createElement(CrossSquareIcon, { variant: "failed" });
5993
6248
  case "pending":
5994
6249
  default:
5995
- return /* @__PURE__ */ import_react69.default.createElement(EmptySquareIcon, null);
6250
+ return /* @__PURE__ */ import_react73.default.createElement(EmptySquareIcon, null);
5996
6251
  }
5997
6252
  }
5998
6253
  function sortTasks(tasks) {
@@ -6012,7 +6267,7 @@ function TaskItem({ task, depth = 0 }) {
6012
6267
  const isSubtle = task.status === "cancelled" || task.status === "failed";
6013
6268
  const showSubtasks = (task.status === "in_progress" || task.status === "done") && task.subtasks && task.subtasks.length > 0;
6014
6269
  const sortedSubtasks = showSubtasks ? sortTasks(task.subtasks) : [];
6015
- return /* @__PURE__ */ import_react69.default.createElement("div", { className: "flex flex-col" }, /* @__PURE__ */ import_react69.default.createElement(
6270
+ return /* @__PURE__ */ import_react73.default.createElement("div", { className: "flex flex-col" }, /* @__PURE__ */ import_react73.default.createElement(
6016
6271
  "div",
6017
6272
  {
6018
6273
  className: cx(
@@ -6020,8 +6275,8 @@ function TaskItem({ task, depth = 0 }) {
6020
6275
  depth > 0 && "pl-6"
6021
6276
  )
6022
6277
  },
6023
- /* @__PURE__ */ import_react69.default.createElement(TaskIcon, { status: task.status }),
6024
- /* @__PURE__ */ import_react69.default.createElement(
6278
+ /* @__PURE__ */ import_react73.default.createElement(TaskIcon, { status: task.status }),
6279
+ /* @__PURE__ */ import_react73.default.createElement(
6025
6280
  "span",
6026
6281
  {
6027
6282
  className: cx(
@@ -6033,14 +6288,14 @@ function TaskItem({ task, depth = 0 }) {
6033
6288
  )
6034
6289
  },
6035
6290
  task.label,
6036
- task.status === "cancelled" && /* @__PURE__ */ import_react69.default.createElement("span", { className: "text-silver/40 ml-1" }, "(cancelled)"),
6037
- task.status === "failed" && /* @__PURE__ */ import_react69.default.createElement("span", { className: "text-error/60 ml-1" }, "(failed)")
6291
+ task.status === "cancelled" && /* @__PURE__ */ import_react73.default.createElement("span", { className: "text-silver/40 ml-1" }, "(cancelled)"),
6292
+ task.status === "failed" && /* @__PURE__ */ import_react73.default.createElement("span", { className: "text-error/60 ml-1" }, "(failed)")
6038
6293
  )
6039
- ), showSubtasks && /* @__PURE__ */ import_react69.default.createElement("div", { className: "flex flex-col" }, sortedSubtasks.map((subtask) => /* @__PURE__ */ import_react69.default.createElement(TaskItem, { key: subtask.id, task: subtask, depth: depth + 1 }))));
6294
+ ), showSubtasks && /* @__PURE__ */ import_react73.default.createElement("div", { className: "flex flex-col" }, sortedSubtasks.map((subtask) => /* @__PURE__ */ import_react73.default.createElement(TaskItem, { key: subtask.id, task: subtask, depth: depth + 1 }))));
6040
6295
  }
6041
- var TodosList = import_react69.default.forwardRef(
6296
+ var TodosList = import_react73.default.forwardRef(
6042
6297
  ({ tasks, title = "Tasks", className, ...rest }, ref) => {
6043
- const sortedTasks = (0, import_react69.useMemo)(() => sortTasks(tasks), [tasks]);
6298
+ const sortedTasks = (0, import_react73.useMemo)(() => sortTasks(tasks), [tasks]);
6044
6299
  const countCompleted = (taskList) => {
6045
6300
  let count = 0;
6046
6301
  for (const task of taskList) {
@@ -6065,84 +6320,217 @@ var TodosList = import_react69.default.forwardRef(
6065
6320
  if (tasks.length === 0) {
6066
6321
  return null;
6067
6322
  }
6068
- return /* @__PURE__ */ import_react69.default.createElement(
6323
+ return /* @__PURE__ */ import_react73.default.createElement(
6069
6324
  "div",
6070
6325
  {
6071
6326
  ref,
6072
6327
  className: cx(
6073
- "flex flex-col bg-charcoal/30 border-l border-ash/40",
6328
+ "flex flex-col h-full",
6074
6329
  "overflow-hidden",
6075
6330
  className
6076
6331
  ),
6077
- style: { maxHeight: "25vh" },
6078
6332
  ...rest
6079
6333
  },
6080
- /* @__PURE__ */ import_react69.default.createElement(
6334
+ /* @__PURE__ */ import_react73.default.createElement(
6081
6335
  "div",
6082
6336
  {
6083
6337
  className: "flex items-center justify-between px-4 py-2 border-b border-ash/40 flex-shrink-0"
6084
6338
  },
6085
- /* @__PURE__ */ import_react69.default.createElement("h4", { className: "text-xs font-medium text-white" }, title),
6086
- /* @__PURE__ */ import_react69.default.createElement("span", { className: "text-xs text-silver/60" }, countCompleted(tasks), "/", countTotal(tasks))
6339
+ /* @__PURE__ */ import_react73.default.createElement("h4", { className: "text-xs font-medium text-white" }, title),
6340
+ /* @__PURE__ */ import_react73.default.createElement("span", { className: "text-xs text-silver/60" }, countCompleted(tasks), "/", countTotal(tasks))
6087
6341
  ),
6088
- /* @__PURE__ */ import_react69.default.createElement("div", { className: "flex-1 overflow-y-auto px-4 py-2" }, sortedTasks.map((task) => /* @__PURE__ */ import_react69.default.createElement(TaskItem, { key: task.id, task })))
6342
+ /* @__PURE__ */ import_react73.default.createElement("div", { className: "flex-1 overflow-y-auto px-4 py-2" }, sortedTasks.map((task) => /* @__PURE__ */ import_react73.default.createElement(TaskItem, { key: task.id, task })))
6089
6343
  );
6090
6344
  }
6091
6345
  );
6092
6346
  TodosList.displayName = "TodosList";
6347
+ function areAllTasksSettled(tasks) {
6348
+ return tasks.every((t) => {
6349
+ const settled = t.status === "done" || t.status === "cancelled" || t.status === "failed";
6350
+ if (!settled) return false;
6351
+ if (t.subtasks && t.subtasks.length > 0) return areAllTasksSettled(t.subtasks);
6352
+ return true;
6353
+ });
6354
+ }
6093
6355
 
6094
- // src/components/chat/hooks/useArtifacts.ts
6095
- var import_react70 = require("react");
6096
- function useArtifacts() {
6097
- const [artifacts, setArtifacts] = (0, import_react70.useState)([]);
6098
- const scheduleArtifact = (0, import_react70.useCallback)((artifact) => {
6099
- setArtifacts((prev) => [...prev, { ...artifact, isPending: true }]);
6100
- }, []);
6101
- const showArtifact = (0, import_react70.useCallback)(
6102
- (artifactId, updates) => {
6103
- setArtifacts((prev) => {
6104
- const existingIndex = prev.findIndex((a) => a.id === artifactId);
6105
- if (existingIndex >= 0) {
6106
- return prev.map(
6107
- (a) => a.id === artifactId ? { ...a, ...updates, isPending: false } : a
6108
- );
6109
- } else {
6110
- return [...prev, { id: artifactId, ...updates, isPending: false }];
6356
+ // src/components/chat/ToolSidebar.tsx
6357
+ var import_react74 = __toESM(require("react"));
6358
+ var ToolSidebar = import_react74.default.forwardRef(
6359
+ ({ tools, activeTools, onToggleTool, className, ...rest }, ref) => {
6360
+ const topTools = tools.filter((t) => t.group === "top");
6361
+ const bottomTools = tools.filter((t) => t.group === "bottom");
6362
+ const isActive = (toolId) => {
6363
+ const tool = tools.find((t) => t.id === toolId);
6364
+ if (!tool) return false;
6365
+ return activeTools[tool.group] === toolId;
6366
+ };
6367
+ const renderButton = (tool) => {
6368
+ const active = isActive(tool.id);
6369
+ return /* @__PURE__ */ import_react74.default.createElement(
6370
+ "button",
6371
+ {
6372
+ key: tool.id,
6373
+ onClick: () => onToggleTool(tool.id),
6374
+ className: cx(
6375
+ "w-8 h-8 flex items-center justify-center transition-colors duration-150",
6376
+ active ? "bg-gold/15 text-gold border border-gold/30" : "text-silver hover:text-white hover:bg-ash/20"
6377
+ ),
6378
+ "aria-label": tool.label,
6379
+ "aria-pressed": active
6380
+ },
6381
+ /* @__PURE__ */ import_react74.default.createElement("span", { className: "w-4 h-4 block" }, tool.icon)
6382
+ );
6383
+ };
6384
+ return /* @__PURE__ */ import_react74.default.createElement(
6385
+ "div",
6386
+ {
6387
+ ref,
6388
+ className: cx(
6389
+ "h-full w-9 bg-charcoal/80 border-l border-ash/40 flex flex-col items-center shrink-0 py-2",
6390
+ className
6391
+ ),
6392
+ ...rest
6393
+ },
6394
+ /* @__PURE__ */ import_react74.default.createElement("div", { className: "flex flex-col items-center gap-1" }, topTools.map(renderButton)),
6395
+ /* @__PURE__ */ import_react74.default.createElement("div", { className: "flex-1 flex items-center justify-center" }, /* @__PURE__ */ import_react74.default.createElement("div", { className: "w-5 border-t border-ash/30" })),
6396
+ /* @__PURE__ */ import_react74.default.createElement("div", { className: "flex flex-col items-center gap-1" }, bottomTools.map(renderButton))
6397
+ );
6398
+ }
6399
+ );
6400
+ ToolSidebar.displayName = "ToolSidebar";
6401
+
6402
+ // src/components/chat/ToolPanelContainer.tsx
6403
+ var import_react75 = __toESM(require("react"));
6404
+ var ToolPanelContainer = import_react75.default.forwardRef(
6405
+ ({ topContent, bottomContent, width, onResizeStart, className, ...rest }, ref) => {
6406
+ const [topPercent, setTopPercent] = (0, import_react75.useState)(60);
6407
+ const [isResizingHeight, setIsResizingHeight] = (0, import_react75.useState)(false);
6408
+ const containerRef = (0, import_react75.useRef)(null);
6409
+ const lastY = (0, import_react75.useRef)(null);
6410
+ const hasBoth = topContent !== null && bottomContent !== null;
6411
+ const startHeightResize = (0, import_react75.useCallback)((e) => {
6412
+ e.preventDefault();
6413
+ setIsResizingHeight(true);
6414
+ lastY.current = e.clientY;
6415
+ }, []);
6416
+ const stopHeightResize = (0, import_react75.useCallback)(() => {
6417
+ setIsResizingHeight(false);
6418
+ lastY.current = null;
6419
+ }, []);
6420
+ const resizeHeight = (0, import_react75.useCallback)(
6421
+ (e) => {
6422
+ if (!isResizingHeight || lastY.current === null || !containerRef.current) return;
6423
+ const containerHeight = containerRef.current.getBoundingClientRect().height;
6424
+ if (containerHeight === 0) return;
6425
+ const deltaY = e.clientY - lastY.current;
6426
+ const deltaPercent = deltaY / containerHeight * 100;
6427
+ setTopPercent((prev) => {
6428
+ const next = prev + deltaPercent;
6429
+ return Math.min(Math.max(next, 20), 80);
6430
+ });
6431
+ lastY.current = e.clientY;
6432
+ },
6433
+ [isResizingHeight]
6434
+ );
6435
+ (0, import_react75.useEffect)(() => {
6436
+ if (isResizingHeight) {
6437
+ window.addEventListener("mousemove", resizeHeight);
6438
+ window.addEventListener("mouseup", stopHeightResize);
6439
+ document.body.style.cursor = "row-resize";
6440
+ document.body.style.userSelect = "none";
6441
+ } else {
6442
+ window.removeEventListener("mousemove", resizeHeight);
6443
+ window.removeEventListener("mouseup", stopHeightResize);
6444
+ document.body.style.cursor = "";
6445
+ document.body.style.userSelect = "";
6446
+ }
6447
+ return () => {
6448
+ window.removeEventListener("mousemove", resizeHeight);
6449
+ window.removeEventListener("mouseup", stopHeightResize);
6450
+ document.body.style.cursor = "";
6451
+ document.body.style.userSelect = "";
6452
+ };
6453
+ }, [isResizingHeight, resizeHeight, stopHeightResize]);
6454
+ return /* @__PURE__ */ import_react75.default.createElement(
6455
+ "div",
6456
+ {
6457
+ ref: (node) => {
6458
+ containerRef.current = node;
6459
+ if (typeof ref === "function") ref(node);
6460
+ else if (ref) ref.current = node;
6461
+ },
6462
+ className: cx(
6463
+ "h-full bg-charcoal/50 border-l border-ash/40 flex flex-col relative shrink-0",
6464
+ className
6465
+ ),
6466
+ style: width ? { width } : void 0,
6467
+ ...rest
6468
+ },
6469
+ /* @__PURE__ */ import_react75.default.createElement(
6470
+ "div",
6471
+ {
6472
+ onMouseDown: onResizeStart,
6473
+ className: cx(
6474
+ "absolute top-0 left-0 w-1 h-full cursor-col-resize z-50",
6475
+ "hover:bg-gold/50 transition-colors",
6476
+ "after:absolute after:inset-y-0 after:-left-1 after:w-2"
6477
+ )
6111
6478
  }
6112
- });
6113
- },
6114
- []
6115
- );
6116
- const removeArtifact = (0, import_react70.useCallback)((artifactId) => {
6117
- setArtifacts((prev) => prev.filter((a) => a.id !== artifactId));
6118
- }, []);
6119
- const clearArtifacts = (0, import_react70.useCallback)(() => {
6120
- setArtifacts([]);
6121
- }, []);
6122
- return { artifacts, scheduleArtifact, showArtifact, removeArtifact, clearArtifacts };
6123
- }
6479
+ ),
6480
+ topContent !== null && /* @__PURE__ */ import_react75.default.createElement(
6481
+ "div",
6482
+ {
6483
+ className: "min-h-0 overflow-hidden flex flex-col",
6484
+ style: hasBoth ? { height: `${topPercent}%` } : { flex: "1 1 0%" }
6485
+ },
6486
+ topContent
6487
+ ),
6488
+ hasBoth && /* @__PURE__ */ import_react75.default.createElement(
6489
+ "div",
6490
+ {
6491
+ onMouseDown: startHeightResize,
6492
+ className: cx(
6493
+ "h-1 cursor-row-resize z-50 shrink-0",
6494
+ "bg-ash/40 hover:bg-gold/50 transition-colors",
6495
+ "relative",
6496
+ "after:absolute after:-top-1 after:left-0 after:right-0 after:h-3"
6497
+ )
6498
+ }
6499
+ ),
6500
+ bottomContent !== null && /* @__PURE__ */ import_react75.default.createElement(
6501
+ "div",
6502
+ {
6503
+ className: "min-h-0 overflow-hidden flex flex-col",
6504
+ style: hasBoth ? { height: `${100 - topPercent}%` } : { flex: "1 1 0%" }
6505
+ },
6506
+ bottomContent
6507
+ )
6508
+ );
6509
+ }
6510
+ );
6511
+ ToolPanelContainer.displayName = "ToolPanelContainer";
6124
6512
 
6125
6513
  // src/components/chat/hooks/useResizable.ts
6126
- var import_react71 = require("react");
6514
+ var import_react76 = require("react");
6127
6515
  function useResizable({
6128
6516
  initialWidthPercent,
6129
6517
  minWidthPercent,
6130
6518
  maxWidthPercent,
6131
6519
  direction
6132
6520
  }) {
6133
- const [widthPercent, setWidthPercent] = (0, import_react71.useState)(initialWidthPercent);
6134
- const [isResizing, setIsResizing] = (0, import_react71.useState)(false);
6135
- const lastX = (0, import_react71.useRef)(null);
6136
- const startResizing = (0, import_react71.useCallback)((e) => {
6521
+ const [widthPercent, setWidthPercent] = (0, import_react76.useState)(initialWidthPercent);
6522
+ const [isResizing, setIsResizing] = (0, import_react76.useState)(false);
6523
+ const lastX = (0, import_react76.useRef)(null);
6524
+ const startResizing = (0, import_react76.useCallback)((e) => {
6137
6525
  e.preventDefault();
6138
6526
  setIsResizing(true);
6139
6527
  lastX.current = e.clientX;
6140
6528
  }, []);
6141
- const stopResizing = (0, import_react71.useCallback)(() => {
6529
+ const stopResizing = (0, import_react76.useCallback)(() => {
6142
6530
  setIsResizing(false);
6143
6531
  lastX.current = null;
6144
6532
  }, []);
6145
- const resize = (0, import_react71.useCallback)(
6533
+ const resize = (0, import_react76.useCallback)(
6146
6534
  (e) => {
6147
6535
  if (!isResizing || lastX.current === null) {
6148
6536
  return;
@@ -6158,7 +6546,7 @@ function useResizable({
6158
6546
  },
6159
6547
  [isResizing, direction, minWidthPercent, maxWidthPercent]
6160
6548
  );
6161
- (0, import_react71.useEffect)(() => {
6549
+ (0, import_react76.useEffect)(() => {
6162
6550
  if (isResizing) {
6163
6551
  window.addEventListener("mousemove", resize);
6164
6552
  window.addEventListener("mouseup", stopResizing);
@@ -6182,7 +6570,7 @@ function useResizable({
6182
6570
  }
6183
6571
 
6184
6572
  // src/components/chat/ChatInterface.tsx
6185
- var ChatInterface = import_react72.default.forwardRef(
6573
+ var ChatInterface = import_react77.default.forwardRef(
6186
6574
  ({
6187
6575
  messages = [],
6188
6576
  conversationTree,
@@ -6204,7 +6592,7 @@ var ChatInterface = import_react72.default.forwardRef(
6204
6592
  enableMessageActions = true,
6205
6593
  attachments: propsAttachments,
6206
6594
  onAttachmentsChange,
6207
- artifacts = [],
6595
+ artifactNodes,
6208
6596
  isArtifactsPanelOpen,
6209
6597
  onArtifactsPanelOpenChange,
6210
6598
  tasks = [],
@@ -6212,10 +6600,25 @@ var ChatInterface = import_react72.default.forwardRef(
6212
6600
  className,
6213
6601
  ...rest
6214
6602
  }, ref) => {
6215
- const [sidebarCollapsed, setSidebarCollapsed] = (0, import_react72.useState)(initialSidebarCollapsed);
6216
- const [internalPanelOpen, setInternalPanelOpen] = (0, import_react72.useState)(false);
6217
- const prevArtifactsRef = (0, import_react72.useRef)([]);
6218
- const prevTasksRef = (0, import_react72.useRef)([]);
6603
+ const [sidebarCollapsed, setSidebarCollapsed] = (0, import_react77.useState)(initialSidebarCollapsed);
6604
+ const prevArtifactNodesRef = (0, import_react77.useRef)([]);
6605
+ const prevTasksRef = (0, import_react77.useRef)([]);
6606
+ const [internalTools, setInternalTools] = (0, import_react77.useState)({
6607
+ top: null,
6608
+ bottom: null
6609
+ });
6610
+ const dismissedToolsRef = (0, import_react77.useRef)(/* @__PURE__ */ new Set());
6611
+ const isPanelControlled = isArtifactsPanelOpen !== void 0;
6612
+ const activeTools = (0, import_react77.useMemo)(() => {
6613
+ if (isPanelControlled) {
6614
+ return {
6615
+ top: isArtifactsPanelOpen ? "artifacts" : internalTools.top,
6616
+ bottom: internalTools.bottom
6617
+ };
6618
+ }
6619
+ return internalTools;
6620
+ }, [isPanelControlled, isArtifactsPanelOpen, internalTools]);
6621
+ const isAnyToolOpen = activeTools.top !== null || activeTools.bottom !== null;
6219
6622
  const {
6220
6623
  width: sidebarWidth,
6221
6624
  startResizing: startResizingSidebar
@@ -6226,19 +6629,43 @@ var ChatInterface = import_react72.default.forwardRef(
6226
6629
  direction: "right"
6227
6630
  });
6228
6631
  const {
6229
- width: artifactsWidth,
6230
- widthPercent: artifactsWidthPercent,
6231
- startResizing: startResizingArtifacts
6632
+ width: toolsWidth,
6633
+ startResizing: startResizingTools
6232
6634
  } = useResizable({
6233
6635
  initialWidthPercent: 50,
6234
6636
  minWidthPercent: 25,
6235
6637
  maxWidthPercent: 70,
6236
6638
  direction: "left"
6237
6639
  });
6238
- const isPanelControlled = isArtifactsPanelOpen !== void 0;
6239
- const artifactsPanelOpen = isPanelControlled ? isArtifactsPanelOpen : internalPanelOpen;
6640
+ const toggleTool = (0, import_react77.useCallback)((toolId) => {
6641
+ const toolDef = TOOL_DEFINITIONS.find((t) => t.id === toolId);
6642
+ if (!toolDef) return;
6643
+ const group = toolDef.group;
6644
+ if (toolId === "artifacts" && isPanelControlled) {
6645
+ const isCurrentlyOpen = activeTools.top === "artifacts";
6646
+ if (isCurrentlyOpen) {
6647
+ dismissedToolsRef.current.add("artifacts");
6648
+ } else {
6649
+ dismissedToolsRef.current.delete("artifacts");
6650
+ }
6651
+ onArtifactsPanelOpenChange?.(!isCurrentlyOpen);
6652
+ return;
6653
+ }
6654
+ setInternalTools((prev) => {
6655
+ const isCurrentlyOpen = prev[group] === toolId;
6656
+ if (isCurrentlyOpen) {
6657
+ dismissedToolsRef.current.add(toolId);
6658
+ } else {
6659
+ dismissedToolsRef.current.delete(toolId);
6660
+ }
6661
+ return {
6662
+ ...prev,
6663
+ [group]: isCurrentlyOpen ? null : toolId
6664
+ };
6665
+ });
6666
+ }, [isPanelControlled, activeTools.top, onArtifactsPanelOpenChange]);
6240
6667
  const isTreeMode = !!conversationTree;
6241
- const effectiveMessages = (0, import_react72.useMemo)(() => {
6668
+ const effectiveMessages = (0, import_react77.useMemo)(() => {
6242
6669
  if (isTreeMode && conversationTree) {
6243
6670
  const pathNodes = getActivePathMessages(conversationTree);
6244
6671
  return pathNodes.map((node) => ({
@@ -6250,63 +6677,43 @@ var ChatInterface = import_react72.default.forwardRef(
6250
6677
  }
6251
6678
  return messages;
6252
6679
  }, [isTreeMode, conversationTree, messages]);
6253
- const latestUserMessageIndex = (0, import_react72.useMemo)(() => {
6680
+ const latestUserMessageIndex = (0, import_react77.useMemo)(() => {
6254
6681
  for (let i = effectiveMessages.length - 1; i >= 0; i--) {
6255
- if (effectiveMessages[i].variant === "user") {
6256
- return i;
6257
- }
6682
+ if (effectiveMessages[i].variant === "user") return i;
6258
6683
  }
6259
6684
  return -1;
6260
6685
  }, [effectiveMessages]);
6261
- (0, import_react72.useEffect)(() => {
6262
- if (isPanelControlled) {
6263
- return;
6686
+ (0, import_react77.useEffect)(() => {
6687
+ const nodes = artifactNodes || [];
6688
+ const prevNodes = prevArtifactNodesRef.current;
6689
+ const hasNewOrChangedNode = nodes.length !== prevNodes.length || nodes.some((n, i) => n.id !== prevNodes[i]?.id);
6690
+ if (!isPanelControlled && hasNewOrChangedNode && nodes.length > 0 && !dismissedToolsRef.current.has("artifacts")) {
6691
+ setInternalTools((prev) => ({ ...prev, top: "artifacts" }));
6264
6692
  }
6265
- const hasNewOrSignificantArtifact = artifacts.some((a) => {
6266
- const p = prevArtifactsRef.current.find((prev) => prev.id === a.id);
6267
- if (!p) {
6268
- return true;
6269
- }
6270
- if (p.isPending && !a.isPending) {
6271
- return true;
6272
- }
6273
- if (p.title !== a.title || p.type !== a.type) {
6274
- return true;
6275
- }
6276
- return false;
6277
- });
6278
6693
  const hasNewOrUpdatedTask = (curr, prev) => {
6279
6694
  return curr.some((c) => {
6280
6695
  const p = prev.find((x) => x.id === c.id);
6281
- if (!p) {
6282
- return true;
6283
- }
6284
- if (c.status !== p.status || c.label !== p.label) {
6285
- return true;
6286
- }
6287
- if (c.subtasks && hasNewOrUpdatedTask(c.subtasks, p?.subtasks || [])) {
6288
- return true;
6289
- }
6696
+ if (!p) return true;
6697
+ if (c.status !== p.status || c.label !== p.label) return true;
6698
+ if (c.subtasks && hasNewOrUpdatedTask(c.subtasks, p?.subtasks || [])) return true;
6290
6699
  return false;
6291
6700
  });
6292
6701
  };
6293
- if (hasNewOrSignificantArtifact || hasNewOrUpdatedTask(tasks, prevTasksRef.current)) {
6294
- setInternalPanelOpen(true);
6702
+ if (hasNewOrUpdatedTask(tasks, prevTasksRef.current) && !dismissedToolsRef.current.has("todos")) {
6703
+ setInternalTools((prev) => ({ ...prev, bottom: "todos" }));
6295
6704
  }
6296
- prevArtifactsRef.current = artifacts;
6705
+ prevArtifactNodesRef.current = nodes;
6297
6706
  prevTasksRef.current = tasks;
6298
- }, [artifacts, tasks, isPanelControlled]);
6299
- const handleBranchSwitch = (0, import_react72.useCallback)(
6707
+ }, [artifactNodes, tasks, isPanelControlled]);
6708
+ const handleBranchSwitch = (0, import_react77.useCallback)(
6300
6709
  (nodeId, direction) => {
6301
- if (!isTreeMode || !conversationTree || !onTreeChange) {
6302
- return;
6303
- }
6710
+ if (!isTreeMode || !conversationTree || !onTreeChange) return;
6304
6711
  const newTree = switchBranch(conversationTree, nodeId, direction);
6305
6712
  onTreeChange(newTree);
6306
6713
  },
6307
6714
  [isTreeMode, conversationTree, onTreeChange]
6308
6715
  );
6309
- const displayMessages = (0, import_react72.useMemo)(() => {
6716
+ const displayMessages = (0, import_react77.useMemo)(() => {
6310
6717
  return effectiveMessages.map((msg) => {
6311
6718
  let branchInfo = void 0;
6312
6719
  if (isTreeMode && conversationTree) {
@@ -6325,11 +6732,7 @@ var ChatInterface = import_react72.default.forwardRef(
6325
6732
  onEdit: msg.variant === "user" && onEditMessage ? (newContent) => onEditMessage(msg.id, newContent) : void 0,
6326
6733
  onRetry: msg.variant === "assistant" && onRetryMessage ? () => onRetryMessage(msg.id) : void 0
6327
6734
  } : void 0;
6328
- return {
6329
- ...msg,
6330
- branchInfo,
6331
- actions
6332
- };
6735
+ return { ...msg, branchInfo, actions };
6333
6736
  });
6334
6737
  }, [
6335
6738
  effectiveMessages,
@@ -6340,31 +6743,56 @@ var ChatInterface = import_react72.default.forwardRef(
6340
6743
  onRetryMessage,
6341
6744
  handleBranchSwitch
6342
6745
  ]);
6343
- const handleSubmit = (0, import_react72.useCallback)(
6746
+ const handleSubmit = (0, import_react77.useCallback)(
6344
6747
  (message, attachments) => {
6345
6748
  onMessageSubmit?.(message, attachments);
6346
6749
  },
6347
6750
  [onMessageSubmit]
6348
6751
  );
6349
- const toggleSidebar = (0, import_react72.useCallback)(() => {
6752
+ const toggleSidebar = (0, import_react77.useCallback)(() => {
6350
6753
  setSidebarCollapsed((prev) => !prev);
6351
6754
  }, []);
6352
- const toggleArtifactsPanel = (0, import_react72.useCallback)(() => {
6353
- if (isPanelControlled) {
6354
- onArtifactsPanelOpenChange?.(!artifactsPanelOpen);
6355
- } else {
6356
- setInternalPanelOpen((prev) => !prev);
6357
- }
6358
- }, [isPanelControlled, artifactsPanelOpen, onArtifactsPanelOpenChange]);
6359
6755
  const isEmpty = effectiveMessages.length === 0;
6360
- return /* @__PURE__ */ import_react72.default.createElement(
6756
+ const allSettled = tasks.length === 0 || areAllTasksSettled(tasks);
6757
+ const toolDefinitions = (0, import_react77.useMemo)(() => [
6758
+ {
6759
+ id: "artifacts",
6760
+ icon: /* @__PURE__ */ import_react77.default.createElement(MediaIcon, null),
6761
+ label: "Artifacts",
6762
+ group: "top"
6763
+ },
6764
+ {
6765
+ id: "todos",
6766
+ icon: allSettled ? /* @__PURE__ */ import_react77.default.createElement(CheckSquareIcon, null) : /* @__PURE__ */ import_react77.default.createElement(SquareLoaderIcon, null),
6767
+ label: "Tasks",
6768
+ group: "bottom"
6769
+ }
6770
+ ], [allSettled]);
6771
+ const renderToolContent = (toolId) => {
6772
+ if (!toolId) return null;
6773
+ switch (toolId) {
6774
+ case "artifacts":
6775
+ return /* @__PURE__ */ import_react77.default.createElement(
6776
+ ArtifactsPanel,
6777
+ {
6778
+ nodes: artifactNodes,
6779
+ className: "h-full"
6780
+ }
6781
+ );
6782
+ case "todos":
6783
+ return tasks.length > 0 ? /* @__PURE__ */ import_react77.default.createElement(TodosList, { tasks, title: tasksTitle, className: "h-full" }) : /* @__PURE__ */ import_react77.default.createElement("div", { className: "h-full flex flex-col" }, /* @__PURE__ */ import_react77.default.createElement("div", { className: "flex items-center p-4 border-b border-ash/40 shrink-0" }, /* @__PURE__ */ import_react77.default.createElement("h3", { className: "text-xs font-medium text-white" }, "Tasks")), /* @__PURE__ */ import_react77.default.createElement("div", { className: "flex-1 flex items-center justify-center" }, /* @__PURE__ */ import_react77.default.createElement("p", { className: "text-xs text-silver/60" }, "No tasks")));
6784
+ default:
6785
+ return null;
6786
+ }
6787
+ };
6788
+ return /* @__PURE__ */ import_react77.default.createElement(
6361
6789
  "div",
6362
6790
  {
6363
6791
  ref,
6364
6792
  className: cx("flex h-full w-full bg-obsidian overflow-hidden", className),
6365
6793
  ...rest
6366
6794
  },
6367
- /* @__PURE__ */ import_react72.default.createElement(
6795
+ /* @__PURE__ */ import_react77.default.createElement(
6368
6796
  ConversationSidebar,
6369
6797
  {
6370
6798
  conversations,
@@ -6376,16 +6804,16 @@ var ChatInterface = import_react72.default.forwardRef(
6376
6804
  onResizeStart: startResizingSidebar
6377
6805
  }
6378
6806
  ),
6379
- /* @__PURE__ */ import_react72.default.createElement("div", { className: "flex-1 flex flex-col min-w-0 relative" }, /* @__PURE__ */ import_react72.default.createElement("div", { className: cx(
6807
+ /* @__PURE__ */ import_react77.default.createElement("div", { className: "flex-1 flex flex-col min-w-0 relative" }, /* @__PURE__ */ import_react77.default.createElement("div", { className: cx(
6380
6808
  "flex-1 flex flex-col min-h-0 relative",
6381
6809
  isEmpty ? "justify-center" : "justify-start"
6382
- ) }, /* @__PURE__ */ import_react72.default.createElement("div", { className: cx(
6810
+ ) }, /* @__PURE__ */ import_react77.default.createElement("div", { className: cx(
6383
6811
  "transition-all duration-500 ease-in-out",
6384
6812
  isEmpty ? "flex-1" : "flex-zero"
6385
- ) }), /* @__PURE__ */ import_react72.default.createElement("div", { className: cx(
6813
+ ) }), /* @__PURE__ */ import_react77.default.createElement("div", { className: cx(
6386
6814
  "transition-all duration-500 ease-in-out overflow-hidden flex flex-col",
6387
6815
  isEmpty ? "flex-zero opacity-0" : "flex-1 opacity-100"
6388
- ) }, /* @__PURE__ */ import_react72.default.createElement(
6816
+ ) }, /* @__PURE__ */ import_react77.default.createElement(
6389
6817
  ChatView,
6390
6818
  {
6391
6819
  messages: displayMessages,
@@ -6394,10 +6822,10 @@ var ChatInterface = import_react72.default.forwardRef(
6394
6822
  isThinking,
6395
6823
  className: "flex-1"
6396
6824
  }
6397
- )), /* @__PURE__ */ import_react72.default.createElement("div", { className: cx(
6825
+ )), /* @__PURE__ */ import_react77.default.createElement("div", { className: cx(
6398
6826
  "transition-all duration-500 ease-in-out z-10 w-full flex flex-col items-center",
6399
6827
  isEmpty ? "p-4" : "shrink-0 p-4 border-t border-ash/40 bg-obsidian"
6400
- ) }, isEmpty && /* @__PURE__ */ import_react72.default.createElement("div", { className: "mb-8 text-center animate-fade-in duration-500" }, emptyState ? emptyState : /* @__PURE__ */ import_react72.default.createElement("h1", { className: "text-4xl md:text-5xl font-heading text-gold mb-2 tracking-tight" }, "Welcome!")), /* @__PURE__ */ import_react72.default.createElement(
6828
+ ) }, isEmpty && /* @__PURE__ */ import_react77.default.createElement("div", { className: "mb-8 text-center animate-fade-in duration-500" }, emptyState ? emptyState : /* @__PURE__ */ import_react77.default.createElement("h1", { className: "text-4xl md:text-5xl font-heading text-gold mb-2 tracking-tight" }, "Welcome!")), /* @__PURE__ */ import_react77.default.createElement(
6401
6829
  ChatInput,
6402
6830
  {
6403
6831
  position: isEmpty ? "centered" : "bottom",
@@ -6411,38 +6839,40 @@ var ChatInterface = import_react72.default.forwardRef(
6411
6839
  attachments: propsAttachments,
6412
6840
  onAttachmentsChange
6413
6841
  }
6414
- )), /* @__PURE__ */ import_react72.default.createElement("div", { className: cx(
6842
+ )), /* @__PURE__ */ import_react77.default.createElement("div", { className: cx(
6415
6843
  "transition-all duration-500 ease-in-out",
6416
6844
  isEmpty ? "flex-1" : "flex-zero"
6417
6845
  ) }))),
6418
- /* @__PURE__ */ import_react72.default.createElement("div", { className: "h-full flex flex-col shrink-0" }, /* @__PURE__ */ import_react72.default.createElement("div", { className: "flex-1 min-h-0" }, /* @__PURE__ */ import_react72.default.createElement(
6419
- ArtifactsPanel,
6846
+ isAnyToolOpen && /* @__PURE__ */ import_react77.default.createElement(
6847
+ ToolPanelContainer,
6420
6848
  {
6421
- artifacts,
6422
- isOpen: artifactsPanelOpen,
6423
- onClose: toggleArtifactsPanel,
6424
- width: artifactsWidth,
6425
- widthPercent: artifactsWidthPercent,
6426
- onResizeStart: startResizingArtifacts,
6427
- className: "h-full"
6849
+ topContent: renderToolContent(activeTools.top),
6850
+ bottomContent: renderToolContent(activeTools.bottom),
6851
+ width: toolsWidth,
6852
+ onResizeStart: startResizingTools
6428
6853
  }
6429
- )), tasks.length > 0 && artifactsPanelOpen && /* @__PURE__ */ import_react72.default.createElement(
6430
- TodosList,
6854
+ ),
6855
+ /* @__PURE__ */ import_react77.default.createElement(
6856
+ ToolSidebar,
6431
6857
  {
6432
- tasks,
6433
- title: tasksTitle,
6434
- style: { width: artifactsWidth }
6858
+ tools: toolDefinitions,
6859
+ activeTools,
6860
+ onToggleTool: toggleTool
6435
6861
  }
6436
- ))
6862
+ )
6437
6863
  );
6438
6864
  }
6439
6865
  );
6440
6866
  ChatInterface.displayName = "ChatInterface";
6867
+ var TOOL_DEFINITIONS = [
6868
+ { id: "artifacts", icon: null, label: "Artifacts", group: "top" },
6869
+ { id: "todos", icon: null, label: "Tasks", group: "bottom" }
6870
+ ];
6441
6871
 
6442
6872
  // src/components/chat/MessageActions.tsx
6443
- var import_react73 = __toESM(require("react"));
6873
+ var import_react78 = __toESM(require("react"));
6444
6874
  var import_lucide_react14 = require("lucide-react");
6445
- var ActionButton2 = ({ onClick, label, children, className, disabled }) => /* @__PURE__ */ import_react73.default.createElement(
6875
+ var ActionButton2 = ({ onClick, label, children, className, disabled }) => /* @__PURE__ */ import_react78.default.createElement(
6446
6876
  "button",
6447
6877
  {
6448
6878
  type: "button",
@@ -6458,7 +6888,7 @@ var ActionButton2 = ({ onClick, label, children, className, disabled }) => /* @_
6458
6888
  },
6459
6889
  children
6460
6890
  );
6461
- var MessageActions = import_react73.default.forwardRef(
6891
+ var MessageActions = import_react78.default.forwardRef(
6462
6892
  ({
6463
6893
  variant,
6464
6894
  content,
@@ -6470,12 +6900,12 @@ var MessageActions = import_react73.default.forwardRef(
6470
6900
  className,
6471
6901
  ...rest
6472
6902
  }, ref) => {
6473
- const [localIsEditing, setLocalIsEditing] = (0, import_react73.useState)(false);
6474
- const [localEditValue, setLocalEditValue] = (0, import_react73.useState)(content);
6475
- const [copied, setCopied] = (0, import_react73.useState)(false);
6903
+ const [localIsEditing, setLocalIsEditing] = (0, import_react78.useState)(false);
6904
+ const [localEditValue, setLocalEditValue] = (0, import_react78.useState)(content);
6905
+ const [copied, setCopied] = (0, import_react78.useState)(false);
6476
6906
  const isEditing = controlledIsEditing ?? localIsEditing;
6477
6907
  const editValue = controlledEditValue ?? localEditValue;
6478
- const setIsEditing = (0, import_react73.useCallback)(
6908
+ const setIsEditing = (0, import_react78.useCallback)(
6479
6909
  (value) => {
6480
6910
  if (onEditingChange) {
6481
6911
  onEditingChange(value);
@@ -6485,10 +6915,10 @@ var MessageActions = import_react73.default.forwardRef(
6485
6915
  },
6486
6916
  [onEditingChange]
6487
6917
  );
6488
- const setEditValue = (0, import_react73.useCallback)((value) => {
6918
+ const setEditValue = (0, import_react78.useCallback)((value) => {
6489
6919
  setLocalEditValue(value);
6490
6920
  }, []);
6491
- const handleCopy = (0, import_react73.useCallback)(async () => {
6921
+ const handleCopy = (0, import_react78.useCallback)(async () => {
6492
6922
  try {
6493
6923
  await navigator.clipboard.writeText(content);
6494
6924
  setCopied(true);
@@ -6504,22 +6934,22 @@ var MessageActions = import_react73.default.forwardRef(
6504
6934
  setTimeout(() => setCopied(false), 2e3);
6505
6935
  }
6506
6936
  }, [content]);
6507
- const handleStartEdit = (0, import_react73.useCallback)(() => {
6937
+ const handleStartEdit = (0, import_react78.useCallback)(() => {
6508
6938
  setLocalEditValue(content);
6509
6939
  setIsEditing(true);
6510
6940
  }, [content, setIsEditing]);
6511
- const handleCancelEdit = (0, import_react73.useCallback)(() => {
6941
+ const handleCancelEdit = (0, import_react78.useCallback)(() => {
6512
6942
  setIsEditing(false);
6513
6943
  setLocalEditValue(content);
6514
6944
  }, [content, setIsEditing]);
6515
- const handleSubmitEdit = (0, import_react73.useCallback)(() => {
6945
+ const handleSubmitEdit = (0, import_react78.useCallback)(() => {
6516
6946
  const trimmed = editValue.trim();
6517
6947
  if (trimmed && trimmed !== content) {
6518
6948
  onEdit?.(trimmed);
6519
6949
  }
6520
6950
  setIsEditing(false);
6521
6951
  }, [editValue, content, onEdit, setIsEditing]);
6522
- const handleEditKeyDown = (0, import_react73.useCallback)(
6952
+ const handleEditKeyDown = (0, import_react78.useCallback)(
6523
6953
  (e) => {
6524
6954
  if (e.key === "Enter" && !e.shiftKey) {
6525
6955
  e.preventDefault();
@@ -6532,19 +6962,19 @@ var MessageActions = import_react73.default.forwardRef(
6532
6962
  );
6533
6963
  const isUser = variant === "user";
6534
6964
  if (isUser && isEditing) {
6535
- return /* @__PURE__ */ import_react73.default.createElement(
6965
+ return /* @__PURE__ */ import_react78.default.createElement(
6536
6966
  "div",
6537
6967
  {
6538
6968
  ref,
6539
6969
  className: cx("mt-2", className),
6540
6970
  ...rest
6541
6971
  },
6542
- /* @__PURE__ */ import_react73.default.createElement(
6972
+ /* @__PURE__ */ import_react78.default.createElement(
6543
6973
  "div",
6544
6974
  {
6545
6975
  className: "relative bg-charcoal border border-ash/60 focus-within:border-gold/60 focus-within:ring-1 focus-within:ring-gold/20"
6546
6976
  },
6547
- /* @__PURE__ */ import_react73.default.createElement(
6977
+ /* @__PURE__ */ import_react78.default.createElement(
6548
6978
  "textarea",
6549
6979
  {
6550
6980
  value: editValue,
@@ -6555,15 +6985,15 @@ var MessageActions = import_react73.default.forwardRef(
6555
6985
  rows: 2
6556
6986
  }
6557
6987
  ),
6558
- /* @__PURE__ */ import_react73.default.createElement("div", { className: "absolute right-2 bottom-2 flex gap-1" }, /* @__PURE__ */ import_react73.default.createElement(
6988
+ /* @__PURE__ */ import_react78.default.createElement("div", { className: "absolute right-2 bottom-2 flex gap-1" }, /* @__PURE__ */ import_react78.default.createElement(
6559
6989
  ActionButton2,
6560
6990
  {
6561
6991
  onClick: handleCancelEdit,
6562
6992
  label: "Cancel edit",
6563
6993
  className: "text-silver/60 hover:text-error"
6564
6994
  },
6565
- /* @__PURE__ */ import_react73.default.createElement(import_lucide_react14.X, { className: "w-4 h-4" })
6566
- ), /* @__PURE__ */ import_react73.default.createElement(
6995
+ /* @__PURE__ */ import_react78.default.createElement(import_lucide_react14.X, { className: "w-4 h-4" })
6996
+ ), /* @__PURE__ */ import_react78.default.createElement(
6567
6997
  ActionButton2,
6568
6998
  {
6569
6999
  onClick: handleSubmitEdit,
@@ -6571,13 +7001,13 @@ var MessageActions = import_react73.default.forwardRef(
6571
7001
  className: "text-silver/60 hover:text-gold",
6572
7002
  disabled: !editValue.trim() || editValue.trim() === content
6573
7003
  },
6574
- /* @__PURE__ */ import_react73.default.createElement(import_lucide_react14.Send, { className: "w-4 h-4" })
7004
+ /* @__PURE__ */ import_react78.default.createElement(import_lucide_react14.Send, { className: "w-4 h-4" })
6575
7005
  ))
6576
7006
  ),
6577
- /* @__PURE__ */ import_react73.default.createElement("p", { className: "text-xs text-silver/50 mt-1" }, "Press Enter to submit, Esc to cancel. This will create a new branch.")
7007
+ /* @__PURE__ */ import_react78.default.createElement("p", { className: "text-xs text-silver/50 mt-1" }, "Press Enter to submit, Esc to cancel. This will create a new branch.")
6578
7008
  );
6579
7009
  }
6580
- return /* @__PURE__ */ import_react73.default.createElement(
7010
+ return /* @__PURE__ */ import_react78.default.createElement(
6581
7011
  "div",
6582
7012
  {
6583
7013
  ref,
@@ -6588,18 +7018,18 @@ var MessageActions = import_react73.default.forwardRef(
6588
7018
  ),
6589
7019
  ...rest
6590
7020
  },
6591
- /* @__PURE__ */ import_react73.default.createElement(ActionButton2, { onClick: handleCopy, label: copied ? "Copied!" : "Copy message" }, copied ? /* @__PURE__ */ import_react73.default.createElement(import_lucide_react14.Check, { className: "w-3.5 h-3.5 text-success" }) : /* @__PURE__ */ import_react73.default.createElement(import_lucide_react14.Copy, { className: "w-3.5 h-3.5" })),
6592
- isUser && onEdit && /* @__PURE__ */ import_react73.default.createElement(ActionButton2, { onClick: handleStartEdit, label: "Edit message" }, /* @__PURE__ */ import_react73.default.createElement(import_lucide_react14.Pencil, { className: "w-3.5 h-3.5" })),
6593
- !isUser && onRetry && /* @__PURE__ */ import_react73.default.createElement(ActionButton2, { onClick: onRetry, label: "Regenerate response" }, /* @__PURE__ */ import_react73.default.createElement(import_lucide_react14.RotateCcw, { className: "w-3.5 h-3.5" }))
7021
+ /* @__PURE__ */ import_react78.default.createElement(ActionButton2, { onClick: handleCopy, label: copied ? "Copied!" : "Copy message" }, copied ? /* @__PURE__ */ import_react78.default.createElement(import_lucide_react14.Check, { className: "w-3.5 h-3.5 text-success" }) : /* @__PURE__ */ import_react78.default.createElement(import_lucide_react14.Copy, { className: "w-3.5 h-3.5" })),
7022
+ isUser && onEdit && /* @__PURE__ */ import_react78.default.createElement(ActionButton2, { onClick: handleStartEdit, label: "Edit message" }, /* @__PURE__ */ import_react78.default.createElement(import_lucide_react14.Pencil, { className: "w-3.5 h-3.5" })),
7023
+ !isUser && onRetry && /* @__PURE__ */ import_react78.default.createElement(ActionButton2, { onClick: onRetry, label: "Regenerate response" }, /* @__PURE__ */ import_react78.default.createElement(import_lucide_react14.RotateCcw, { className: "w-3.5 h-3.5" }))
6594
7024
  );
6595
7025
  }
6596
7026
  );
6597
7027
  MessageActions.displayName = "MessageActions";
6598
7028
 
6599
7029
  // src/components/chat/BranchNavigator.tsx
6600
- var import_react74 = __toESM(require("react"));
7030
+ var import_react79 = __toESM(require("react"));
6601
7031
  var import_lucide_react15 = require("lucide-react");
6602
- var BranchNavigator = import_react74.default.forwardRef(
7032
+ var BranchNavigator = import_react79.default.forwardRef(
6603
7033
  ({
6604
7034
  current,
6605
7035
  total,
@@ -6618,7 +7048,7 @@ var BranchNavigator = import_react74.default.forwardRef(
6618
7048
  const buttonSize = size === "sm" ? "p-0.5" : "p-1";
6619
7049
  const iconSize = size === "sm" ? "w-3 h-3" : "w-4 h-4";
6620
7050
  const textSize = size === "sm" ? "text-xs" : "text-sm";
6621
- return /* @__PURE__ */ import_react74.default.createElement(
7051
+ return /* @__PURE__ */ import_react79.default.createElement(
6622
7052
  "div",
6623
7053
  {
6624
7054
  ref,
@@ -6630,8 +7060,8 @@ var BranchNavigator = import_react74.default.forwardRef(
6630
7060
  "aria-label": "Branch navigation",
6631
7061
  ...rest
6632
7062
  },
6633
- showIcon && /* @__PURE__ */ import_react74.default.createElement(import_lucide_react15.GitBranch, { className: cx(iconSize, "mr-0.5 text-silver/50"), "aria-hidden": "true" }),
6634
- /* @__PURE__ */ import_react74.default.createElement(
7063
+ showIcon && /* @__PURE__ */ import_react79.default.createElement(import_lucide_react15.GitBranch, { className: cx(iconSize, "mr-0.5 text-silver/50"), "aria-hidden": "true" }),
7064
+ /* @__PURE__ */ import_react79.default.createElement(
6635
7065
  "button",
6636
7066
  {
6637
7067
  type: "button",
@@ -6644,10 +7074,10 @@ var BranchNavigator = import_react74.default.forwardRef(
6644
7074
  ),
6645
7075
  "aria-label": "Previous branch"
6646
7076
  },
6647
- /* @__PURE__ */ import_react74.default.createElement(import_lucide_react15.ChevronLeft, { className: iconSize })
7077
+ /* @__PURE__ */ import_react79.default.createElement(import_lucide_react15.ChevronLeft, { className: iconSize })
6648
7078
  ),
6649
- /* @__PURE__ */ import_react74.default.createElement("span", { className: cx(textSize, "tabular-nums min-w-6 text-center") }, current, "/", total),
6650
- /* @__PURE__ */ import_react74.default.createElement(
7079
+ /* @__PURE__ */ import_react79.default.createElement("span", { className: cx(textSize, "tabular-nums min-w-6 text-center") }, current, "/", total),
7080
+ /* @__PURE__ */ import_react79.default.createElement(
6651
7081
  "button",
6652
7082
  {
6653
7083
  type: "button",
@@ -6660,7 +7090,7 @@ var BranchNavigator = import_react74.default.forwardRef(
6660
7090
  ),
6661
7091
  "aria-label": "Next branch"
6662
7092
  },
6663
- /* @__PURE__ */ import_react74.default.createElement(import_lucide_react15.ChevronRight, { className: iconSize })
7093
+ /* @__PURE__ */ import_react79.default.createElement(import_lucide_react15.ChevronRight, { className: iconSize })
6664
7094
  )
6665
7095
  );
6666
7096
  }
@@ -6668,16 +7098,16 @@ var BranchNavigator = import_react74.default.forwardRef(
6668
7098
  BranchNavigator.displayName = "BranchNavigator";
6669
7099
 
6670
7100
  // src/components/BrandIcon.tsx
6671
- var import_react75 = __toESM(require("react"));
7101
+ var import_react80 = __toESM(require("react"));
6672
7102
  var sizeMap2 = {
6673
7103
  sm: "h-8 w-8 text-sm",
6674
7104
  md: "h-12 w-12 text-base",
6675
7105
  lg: "h-16 w-16 text-lg"
6676
7106
  };
6677
- var BrandIcon = import_react75.default.forwardRef(
7107
+ var BrandIcon = import_react80.default.forwardRef(
6678
7108
  ({ size = "md", variant = "solid", children, className, ...rest }, ref) => {
6679
7109
  const variantClasses = variant === "solid" ? "bg-gold text-obsidian border-2 border-gold" : "bg-transparent text-gold border-2 border-gold";
6680
- return /* @__PURE__ */ import_react75.default.createElement(
7110
+ return /* @__PURE__ */ import_react80.default.createElement(
6681
7111
  "div",
6682
7112
  {
6683
7113
  ref,
@@ -6696,17 +7126,17 @@ var BrandIcon = import_react75.default.forwardRef(
6696
7126
  BrandIcon.displayName = "BrandIcon";
6697
7127
 
6698
7128
  // src/components/ColorSwatch.tsx
6699
- var import_react76 = __toESM(require("react"));
6700
- var ColorSwatch = import_react76.default.forwardRef(
7129
+ var import_react81 = __toESM(require("react"));
7130
+ var ColorSwatch = import_react81.default.forwardRef(
6701
7131
  ({ color, label, className, ...rest }, ref) => {
6702
- return /* @__PURE__ */ import_react76.default.createElement(
7132
+ return /* @__PURE__ */ import_react81.default.createElement(
6703
7133
  "div",
6704
7134
  {
6705
7135
  ref,
6706
7136
  className: cx("flex flex-col items-center gap-2", className),
6707
7137
  ...rest
6708
7138
  },
6709
- /* @__PURE__ */ import_react76.default.createElement(
7139
+ /* @__PURE__ */ import_react81.default.createElement(
6710
7140
  "div",
6711
7141
  {
6712
7142
  className: "h-16 w-16 border-2 border-ash rounded-none shadow-sm",
@@ -6714,22 +7144,22 @@ var ColorSwatch = import_react76.default.forwardRef(
6714
7144
  "aria-label": label || color
6715
7145
  }
6716
7146
  ),
6717
- label && /* @__PURE__ */ import_react76.default.createElement("span", { className: "text-xs text-silver font-medium" }, label)
7147
+ label && /* @__PURE__ */ import_react81.default.createElement("span", { className: "text-xs text-silver font-medium" }, label)
6718
7148
  );
6719
7149
  }
6720
7150
  );
6721
7151
  ColorSwatch.displayName = "ColorSwatch";
6722
7152
 
6723
7153
  // src/components/SectionHeading.tsx
6724
- var import_react77 = __toESM(require("react"));
7154
+ var import_react82 = __toESM(require("react"));
6725
7155
  var levelStyles = {
6726
7156
  h2: "text-2xl mb-4",
6727
7157
  h3: "text-xl mb-3"
6728
7158
  };
6729
- var SectionHeading = import_react77.default.forwardRef(
7159
+ var SectionHeading = import_react82.default.forwardRef(
6730
7160
  ({ level = "h2", children, className, ...rest }, ref) => {
6731
7161
  const Component = level;
6732
- return /* @__PURE__ */ import_react77.default.createElement(
7162
+ return /* @__PURE__ */ import_react82.default.createElement(
6733
7163
  Component,
6734
7164
  {
6735
7165
  ref,
@@ -6746,6 +7176,13 @@ var SectionHeading = import_react77.default.forwardRef(
6746
7176
  );
6747
7177
  SectionHeading.displayName = "SectionHeading";
6748
7178
 
7179
+ // src/components/ArtifactNode.ts
7180
+ var NODE_TYPES = {
7181
+ ARTIFACT: "ARTIFACT",
7182
+ GROUP: "GROUP",
7183
+ VARIANT_SET: "VARIANT_SET"
7184
+ };
7185
+
6749
7186
  // src/index.ts
6750
7187
  var version = "2.0.0";
6751
7188
  // Annotate the CommonJS export names for ESM import in node:
@@ -6758,6 +7195,8 @@ var version = "2.0.0";
6758
7195
  Alert,
6759
7196
  AlertDialog,
6760
7197
  ArtifactCard,
7198
+ ArtifactGroup,
7199
+ ArtifactVariantStack,
6761
7200
  ArtifactsPanel,
6762
7201
  ArtifactsPanelToggle,
6763
7202
  AttachmentPreview,
@@ -6808,6 +7247,7 @@ var version = "2.0.0";
6808
7247
  ListItemText,
6809
7248
  ListSubheader,
6810
7249
  MarkdownContent,
7250
+ MediaIcon,
6811
7251
  Menu,
6812
7252
  MenuContent,
6813
7253
  MenuItem,
@@ -6817,6 +7257,7 @@ var version = "2.0.0";
6817
7257
  Message,
6818
7258
  MessageActions,
6819
7259
  Modal,
7260
+ NODE_TYPES,
6820
7261
  Navbar,
6821
7262
  NavbarBrand,
6822
7263
  NavbarContent,
@@ -6861,9 +7302,12 @@ var version = "2.0.0";
6861
7302
  ThinkingIndicator,
6862
7303
  ToastProvider,
6863
7304
  TodosList,
7305
+ ToolPanelContainer,
7306
+ ToolSidebar,
6864
7307
  Tooltip,
6865
7308
  VideoCard,
6866
7309
  addMessageToTree,
7310
+ areAllTasksSettled,
6867
7311
  createEmptyTree,
6868
7312
  createPreviewUrl,
6869
7313
  generateId,
@@ -6875,7 +7319,7 @@ var version = "2.0.0";
6875
7319
  revokePreviewUrl,
6876
7320
  switchBranch,
6877
7321
  updateNodeContent,
6878
- useArtifacts,
7322
+ useArtifactTreeNavigation,
6879
7323
  useResizable,
6880
7324
  useScrollAnchor,
6881
7325
  useToast,