@lukeashford/aurelius 4.2.0 → 4.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -1275,7 +1275,7 @@ var ListSubheader = React14.forwardRef(
1275
1275
  ListSubheader.displayName = "ListSubheader";
1276
1276
 
1277
1277
  // src/components/FileChip.tsx
1278
- import React15 from "react";
1278
+ import React15, { useState as useState2 } from "react";
1279
1279
  import {
1280
1280
  File,
1281
1281
  FileArchive,
@@ -1320,42 +1320,91 @@ function getFileIcon(type) {
1320
1320
  }
1321
1321
  return File;
1322
1322
  }
1323
- var statusStyles = {
1323
+ var statusBorderClass = {
1324
1324
  pending: "border-silver/30",
1325
1325
  uploading: "border-gold/50",
1326
- complete: "border-success/50",
1327
- error: "border-error/50"
1326
+ uploaded: "border-info/50",
1327
+ analyzing: "border-info/50",
1328
+ analyzed: "border-success/50",
1329
+ upload_failed: "border-error/50",
1330
+ analysis_failed: "border-error/50"
1328
1331
  };
1332
+ var statusHoverLabel = {
1333
+ pending: null,
1334
+ uploading: "Uploading",
1335
+ uploaded: "Analyzing",
1336
+ analyzing: "Analyzing",
1337
+ analyzed: null,
1338
+ upload_failed: "Upload failed",
1339
+ analysis_failed: "Couldn't process this file"
1340
+ };
1341
+ function isErrorStatus(status) {
1342
+ return status === "upload_failed" || status === "analysis_failed";
1343
+ }
1329
1344
  var FileChip = React15.forwardRef(
1330
1345
  ({
1331
1346
  name,
1332
1347
  size,
1333
1348
  type,
1334
- status = "complete",
1349
+ status = "analyzed",
1335
1350
  previewUrl,
1336
1351
  onRemove,
1337
1352
  removable = true,
1338
1353
  error,
1354
+ artifactId,
1355
+ onOpen,
1339
1356
  className,
1357
+ title,
1340
1358
  ...rest
1341
1359
  }, ref) => {
1342
1360
  const Icon = getFileIcon(type);
1343
1361
  const isImage = type?.startsWith("image/");
1344
1362
  const showPreview = isImage && previewUrl;
1345
- return /* @__PURE__ */ React15.createElement(
1363
+ const clickable = !!(artifactId && onOpen);
1364
+ const hoverLabel = statusHoverLabel[status];
1365
+ const tooltipContent = isErrorStatus(status) ? error ?? hoverLabel ?? null : hoverLabel;
1366
+ const [hovered, setHovered] = useState2(false);
1367
+ const [focused, setFocused] = useState2(false);
1368
+ const showError = isErrorStatus(status);
1369
+ const handleClick = () => {
1370
+ if (clickable) {
1371
+ onOpen(artifactId);
1372
+ }
1373
+ };
1374
+ const handleKeyDown = (e) => {
1375
+ if (!clickable) {
1376
+ return;
1377
+ }
1378
+ if (e.key === "Enter" || e.key === " ") {
1379
+ e.preventDefault();
1380
+ onOpen(artifactId);
1381
+ }
1382
+ };
1383
+ const tooltipOpen = tooltipContent !== null && (hovered || focused);
1384
+ const chip = /* @__PURE__ */ React15.createElement(
1346
1385
  "div",
1347
1386
  {
1387
+ ...rest,
1348
1388
  ref,
1349
1389
  className: cx(
1350
1390
  "group relative inline-flex items-center gap-2 px-2 py-1.5",
1351
1391
  "bg-charcoal border text-sm text-white",
1352
1392
  "transition-colors duration-150",
1353
- statusStyles[status],
1354
- status === "error" && "bg-error/10",
1393
+ statusBorderClass[status],
1394
+ showError && "bg-error/10",
1395
+ clickable && "cursor-pointer hover:bg-graphite",
1355
1396
  className
1356
1397
  ),
1357
- role: "listitem",
1358
- ...rest
1398
+ role: clickable ? "button" : "listitem",
1399
+ tabIndex: clickable ? 0 : void 0,
1400
+ onClick: clickable ? handleClick : void 0,
1401
+ onKeyDown: clickable ? handleKeyDown : void 0,
1402
+ onMouseEnter: () => setHovered(true),
1403
+ onMouseLeave: () => setHovered(false),
1404
+ onFocus: () => setFocused(true),
1405
+ onBlur: () => setFocused(false),
1406
+ title,
1407
+ "aria-label": hoverLabel ? `${name}: ${hoverLabel}` : name
1359
1408
  },
1360
1409
  showPreview ? /* @__PURE__ */ React15.createElement("div", { className: "w-8 h-8 flex-shrink-0 overflow-hidden bg-slate" }, /* @__PURE__ */ React15.createElement(
1361
1410
  "img",
@@ -1366,10 +1415,11 @@ var FileChip = React15.forwardRef(
1366
1415
  }
1367
1416
  )) : /* @__PURE__ */ React15.createElement(Icon, { className: cx(
1368
1417
  "w-4 h-4 flex-shrink-0",
1369
- status === "error" ? "text-error" : "text-silver"
1418
+ showError ? "text-error" : "text-silver"
1370
1419
  ) }),
1371
- /* @__PURE__ */ React15.createElement("div", { className: "flex flex-col min-w-0 flex-1" }, /* @__PURE__ */ React15.createElement("span", { className: "truncate max-w-40", title: name }, name), size !== void 0 && status !== "error" && /* @__PURE__ */ React15.createElement("span", { className: "text-xs text-silver/60" }, formatBytes(size)), status === "error" && error && /* @__PURE__ */ React15.createElement("span", { className: "text-xs text-error truncate", title: error }, error)),
1420
+ /* @__PURE__ */ React15.createElement("div", { className: "flex flex-col min-w-0 flex-1" }, /* @__PURE__ */ React15.createElement("span", { className: "truncate max-w-40", title: name }, name), size !== void 0 && !showError && /* @__PURE__ */ React15.createElement("span", { className: "text-xs text-silver/60" }, formatBytes(size)), showError && error && /* @__PURE__ */ React15.createElement("span", { className: "text-xs text-error truncate", title: error }, error)),
1372
1421
  status === "uploading" && /* @__PURE__ */ React15.createElement(Loader2, { className: "w-3.5 h-3.5 text-gold animate-spin flex-shrink-0" }),
1422
+ (status === "uploaded" || status === "analyzing") && /* @__PURE__ */ React15.createElement(Loader2, { className: "w-3.5 h-3.5 text-info animate-spin flex-shrink-0" }),
1373
1423
  status === "pending" && /* @__PURE__ */ React15.createElement("div", { className: "w-2 h-2 rounded-full bg-silver/50 flex-shrink-0" }),
1374
1424
  removable && onRemove && /* @__PURE__ */ React15.createElement(
1375
1425
  "button",
@@ -1390,6 +1440,10 @@ var FileChip = React15.forwardRef(
1390
1440
  /* @__PURE__ */ React15.createElement(X, { className: "w-3.5 h-3.5" })
1391
1441
  )
1392
1442
  );
1443
+ if (tooltipContent === null) {
1444
+ return chip;
1445
+ }
1446
+ return /* @__PURE__ */ React15.createElement(Tooltip, { content: tooltipContent, open: tooltipOpen, side: "top" }, chip);
1393
1447
  }
1394
1448
  );
1395
1449
  FileChip.displayName = "FileChip";
@@ -1402,6 +1456,7 @@ var AttachmentPreview = React16.forwardRef(
1402
1456
  onRemove,
1403
1457
  removable = true,
1404
1458
  maxVisible,
1459
+ onOpen,
1405
1460
  className,
1406
1461
  ...rest
1407
1462
  }, ref) => {
@@ -1430,7 +1485,9 @@ var AttachmentPreview = React16.forwardRef(
1430
1485
  previewUrl: attachment.previewUrl,
1431
1486
  error: attachment.error,
1432
1487
  removable,
1433
- onRemove: onRemove ? () => onRemove(attachment.id) : void 0
1488
+ onRemove: onRemove ? () => onRemove(attachment.id) : void 0,
1489
+ artifactId: attachment.artifactId,
1490
+ onOpen
1434
1491
  }
1435
1492
  )),
1436
1493
  hiddenCount > 0 && /* @__PURE__ */ React16.createElement(
@@ -1649,7 +1706,7 @@ var Radio = React22.forwardRef(
1649
1706
  Radio.displayName = "Radio";
1650
1707
 
1651
1708
  // src/components/Switch.tsx
1652
- import React23, { useCallback as useCallback4, useRef as useRef2, useState as useState2 } from "react";
1709
+ import React23, { useCallback as useCallback4, useRef as useRef2, useState as useState3 } from "react";
1653
1710
  var Switch = React23.forwardRef(
1654
1711
  ({
1655
1712
  checked: controlledChecked,
@@ -1660,7 +1717,7 @@ var Switch = React23.forwardRef(
1660
1717
  label,
1661
1718
  ...rest
1662
1719
  }, ref) => {
1663
- const [internalChecked, setInternalChecked] = useState2(defaultChecked);
1720
+ const [internalChecked, setInternalChecked] = useState3(defaultChecked);
1664
1721
  const isControlled = controlledChecked !== void 0;
1665
1722
  const checked = isControlled ? controlledChecked : internalChecked;
1666
1723
  const buttonRef = useRef2(null);
@@ -1734,7 +1791,7 @@ var Switch = React23.forwardRef(
1734
1791
  Switch.displayName = "Switch";
1735
1792
 
1736
1793
  // src/components/Slider.tsx
1737
- import React24, { useCallback as useCallback5, useRef as useRef3, useState as useState3 } from "react";
1794
+ import React24, { useCallback as useCallback5, useRef as useRef3, useState as useState4 } from "react";
1738
1795
  var SIZE_TRACK = {
1739
1796
  sm: "h-1",
1740
1797
  md: "h-2",
@@ -1761,8 +1818,8 @@ var Slider = React24.forwardRef(
1761
1818
  className,
1762
1819
  ...props
1763
1820
  }, ref) => {
1764
- const [internalValue, setInternalValue] = useState3(defaultValue);
1765
- const [isDragging, setIsDragging] = useState3(false);
1821
+ const [internalValue, setInternalValue] = useState4(defaultValue);
1822
+ const [isDragging, setIsDragging] = useState4(false);
1766
1823
  const trackRef = useRef3(null);
1767
1824
  const isControlled = controlledValue !== void 0;
1768
1825
  const value = isControlled ? controlledValue : internalValue;
@@ -2123,7 +2180,7 @@ var Progress = React28.forwardRef(
2123
2180
  Progress.displayName = "Progress";
2124
2181
 
2125
2182
  // src/components/Toast.tsx
2126
- import React29, { createContext as createContext2, useCallback as useCallback6, useContext as useContext2, useEffect as useEffect2, useState as useState4 } from "react";
2183
+ import React29, { createContext as createContext2, useCallback as useCallback6, useContext as useContext2, useEffect as useEffect2, useState as useState5 } from "react";
2127
2184
  import { createPortal } from "react-dom";
2128
2185
  import { AlertCircle, AlertTriangle as AlertTriangle2, CheckCircle as CheckCircle2, Info as Info2, X as X2 } from "lucide-react";
2129
2186
  var toastCounter = 0;
@@ -2153,8 +2210,8 @@ var ToastProvider = ({
2153
2210
  position = "bottom-right",
2154
2211
  defaultDuration = 5e3
2155
2212
  }) => {
2156
- const [toasts, setToasts] = useState4([]);
2157
- const [mounted, setMounted] = useState4(false);
2213
+ const [toasts, setToasts] = useState5([]);
2214
+ const [mounted, setMounted] = useState5(false);
2158
2215
  useEffect2(() => {
2159
2216
  setMounted(true);
2160
2217
  }, []);
@@ -2260,11 +2317,11 @@ var Toast = ({
2260
2317
  Toast.displayName = "Toast";
2261
2318
 
2262
2319
  // src/components/Modal.tsx
2263
- import React30, { useEffect as useEffect3, useState as useState5 } from "react";
2320
+ import React30, { useEffect as useEffect3, useState as useState6 } from "react";
2264
2321
  import { createPortal as createPortal2 } from "react-dom";
2265
2322
  import { X as X3 } from "lucide-react";
2266
2323
  var Modal = ({ isOpen, onClose, title, children, className }) => {
2267
- const [mounted, setMounted] = useState5(false);
2324
+ const [mounted, setMounted] = useState6(false);
2268
2325
  useEffect3(() => {
2269
2326
  setMounted(true);
2270
2327
  }, []);
@@ -2309,7 +2366,7 @@ var Modal = ({ isOpen, onClose, title, children, className }) => {
2309
2366
  Modal.displayName = "Modal";
2310
2367
 
2311
2368
  // src/components/Drawer.tsx
2312
- import React31, { useEffect as useEffect4, useState as useState6 } from "react";
2369
+ import React31, { useEffect as useEffect4, useState as useState7 } from "react";
2313
2370
  import { createPortal as createPortal3 } from "react-dom";
2314
2371
  import { X as X4 } from "lucide-react";
2315
2372
  var SIZE_MAP2 = {
@@ -2365,7 +2422,7 @@ var Drawer = ({
2365
2422
  children,
2366
2423
  className
2367
2424
  }) => {
2368
- const [mounted, setMounted] = useState6(false);
2425
+ const [mounted, setMounted] = useState7(false);
2369
2426
  useEffect4(() => {
2370
2427
  setMounted(true);
2371
2428
  }, []);
@@ -2428,7 +2485,7 @@ var Drawer = ({
2428
2485
  Drawer.displayName = "Drawer";
2429
2486
 
2430
2487
  // src/components/Popover.tsx
2431
- import React32, { useCallback as useCallback7, useId as useId3, useRef as useRef4, useState as useState7 } from "react";
2488
+ import React32, { useCallback as useCallback7, useId as useId3, useRef as useRef4, useState as useState8 } from "react";
2432
2489
  var POSITION_CLASSES3 = {
2433
2490
  top: {
2434
2491
  start: "bottom-full left-0 mb-2",
@@ -2460,7 +2517,7 @@ var Popover = ({
2460
2517
  onOpenChange,
2461
2518
  closeOnClickOutside = true
2462
2519
  }) => {
2463
- const [internalOpen, setInternalOpen] = useState7(false);
2520
+ const [internalOpen, setInternalOpen] = useState8(false);
2464
2521
  const isControlled = controlledOpen !== void 0;
2465
2522
  const isOpen = isControlled ? controlledOpen : internalOpen;
2466
2523
  const containerRef = useRef4(null);
@@ -2608,7 +2665,7 @@ var PromptDialog = ({
2608
2665
  PromptDialog.displayName = "PromptDialog";
2609
2666
 
2610
2667
  // src/components/Tabs.tsx
2611
- import React34, { createContext as createContext3, useCallback as useCallback9, useContext as useContext3, useId as useId4, useState as useState8 } from "react";
2668
+ import React34, { createContext as createContext3, useCallback as useCallback9, useContext as useContext3, useId as useId4, useState as useState9 } from "react";
2612
2669
  var TabsContext = createContext3(null);
2613
2670
  function useTabsContext() {
2614
2671
  const context = useContext3(TabsContext);
@@ -2619,7 +2676,7 @@ function useTabsContext() {
2619
2676
  }
2620
2677
  var Tabs = React34.forwardRef(
2621
2678
  ({ defaultValue, value, onValueChange, children, className, ...props }, ref) => {
2622
- const [internalValue, setInternalValue] = useState8(defaultValue ?? "");
2679
+ const [internalValue, setInternalValue] = useState9(defaultValue ?? "");
2623
2680
  const isControlled = value !== void 0;
2624
2681
  const activeTab = isControlled ? value : internalValue;
2625
2682
  const baseId = useId4();
@@ -2719,7 +2776,7 @@ var TabPanel = React34.forwardRef(
2719
2776
  TabPanel.displayName = "TabPanel";
2720
2777
 
2721
2778
  // src/components/Accordion.tsx
2722
- import React35, { createContext as createContext4, useCallback as useCallback10, useContext as useContext4, useId as useId5, useState as useState9 } from "react";
2779
+ import React35, { createContext as createContext4, useCallback as useCallback10, useContext as useContext4, useId as useId5, useState as useState10 } from "react";
2723
2780
  import { ChevronDown } from "lucide-react";
2724
2781
  var AccordionContext = createContext4(null);
2725
2782
  function useAccordionContext() {
@@ -2731,7 +2788,7 @@ function useAccordionContext() {
2731
2788
  }
2732
2789
  var Accordion = React35.forwardRef(
2733
2790
  ({ type = "single", defaultValue, value, onValueChange, children, className, ...props }, ref) => {
2734
- const [internalValue, setInternalValue] = useState9(() => {
2791
+ const [internalValue, setInternalValue] = useState10(() => {
2735
2792
  if (defaultValue) {
2736
2793
  return new Set(Array.isArray(defaultValue) ? defaultValue : [defaultValue]);
2737
2794
  }
@@ -2870,7 +2927,7 @@ import React36, {
2870
2927
  useEffect as useEffect5,
2871
2928
  useId as useId6,
2872
2929
  useRef as useRef5,
2873
- useState as useState10
2930
+ useState as useState11
2874
2931
  } from "react";
2875
2932
  var MenuContext = createContext5(null);
2876
2933
  function useMenuContext() {
@@ -2881,7 +2938,7 @@ function useMenuContext() {
2881
2938
  return context;
2882
2939
  }
2883
2940
  var Menu = ({ children, open, onOpenChange }) => {
2884
- const [internalOpen, setInternalOpen] = useState10(false);
2941
+ const [internalOpen, setInternalOpen] = useState11(false);
2885
2942
  const isControlled = open !== void 0;
2886
2943
  const isOpen = isControlled ? open : internalOpen;
2887
2944
  const baseId = useId6();
@@ -3705,7 +3762,7 @@ function SquareLoaderIcon({ className, ...props }) {
3705
3762
  }
3706
3763
 
3707
3764
  // src/components/Message.tsx
3708
- import React55, { useCallback as useCallback12, useEffect as useEffect6, useRef as useRef6, useState as useState11 } from "react";
3765
+ import React55, { useCallback as useCallback12, useEffect as useEffect6, useRef as useRef6, useState as useState12 } from "react";
3709
3766
  import { Check as Check3, ChevronLeft as ChevronLeft2, ChevronRight as ChevronRight3, Copy, GitBranch, Pencil, RotateCcw, Send, X as X5 } from "lucide-react";
3710
3767
 
3711
3768
  // src/components/MarkdownContent.tsx
@@ -3890,12 +3947,14 @@ var Message = React55.forwardRef(
3890
3947
  branchInfo,
3891
3948
  actions,
3892
3949
  hideActions,
3950
+ attachments,
3951
+ onAttachmentOpen,
3893
3952
  ...rest
3894
3953
  }, ref) => {
3895
3954
  const isUser = variant === "user";
3896
3955
  const { copied, copy } = useCopyToClipboard();
3897
- const [isEditing, setIsEditing] = useState11(false);
3898
- const [editValue, setEditValue] = useState11(typeof content === "string" ? content : "");
3956
+ const [isEditing, setIsEditing] = useState12(false);
3957
+ const [editValue, setEditValue] = useState12(typeof content === "string" ? content : "");
3899
3958
  const textareaRef = useRef6(null);
3900
3959
  const showBranchNav = branchInfo && branchInfo.total > 1;
3901
3960
  const showActions = actions && !hideActions && !isStreaming;
@@ -3957,6 +4016,14 @@ var Message = React55.forwardRef(
3957
4016
  ),
3958
4017
  ...rest
3959
4018
  },
4019
+ attachments && attachments.length > 0 && /* @__PURE__ */ React55.createElement("div", { className: cx("mb-1.5", isUser ? "self-end" : "self-start") }, /* @__PURE__ */ React55.createElement(
4020
+ AttachmentPreview,
4021
+ {
4022
+ attachments,
4023
+ removable: false,
4024
+ onOpen: onAttachmentOpen
4025
+ }
4026
+ )),
3960
4027
  isUser && isEditing ? /* @__PURE__ */ React55.createElement("div", { className: "w-full max-w-11/12" }, /* @__PURE__ */ React55.createElement("div", { className: "relative bg-gold" }, /* @__PURE__ */ React55.createElement(
3961
4028
  "textarea",
3962
4029
  {
@@ -4067,7 +4134,7 @@ var StreamingCursor = React56.forwardRef(
4067
4134
  StreamingCursor.displayName = "StreamingCursor";
4068
4135
 
4069
4136
  // src/components/chat/ChatInterface.tsx
4070
- import React76, { useCallback as useCallback22, useEffect as useEffect16, useMemo as useMemo5, useRef as useRef15, useState as useState22 } from "react";
4137
+ import React76, { useCallback as useCallback22, useEffect as useEffect16, useMemo as useMemo5, useRef as useRef15, useState as useState23 } from "react";
4071
4138
 
4072
4139
  // src/components/chat/ChatView.tsx
4073
4140
  import React60, { useEffect as useEffect9 } from "react";
@@ -4119,14 +4186,14 @@ function useScrollAnchor(options = {}) {
4119
4186
  }
4120
4187
 
4121
4188
  // src/components/chat/hooks/useAdaptiveSpacer.ts
4122
- import { useCallback as useCallback14, useEffect as useEffect7, useRef as useRef8, useState as useState12 } from "react";
4189
+ import { useCallback as useCallback14, useEffect as useEffect7, useRef as useRef8, useState as useState13 } from "react";
4123
4190
  function useAdaptiveSpacer(options = {}) {
4124
4191
  const { minHeight = 0, containerRef: externalContainerRef, anchorRef } = options;
4125
4192
  const internalContainerRef = useRef8(null);
4126
4193
  const containerRef = externalContainerRef ?? internalContainerRef;
4127
4194
  const contentRef = useRef8(null);
4128
4195
  const spacerRef = useRef8(null);
4129
- const [spacerHeight, setSpacerHeight] = useState12(0);
4196
+ const [spacerHeight, setSpacerHeight] = useState13(0);
4130
4197
  const recalculate = useCallback14(() => {
4131
4198
  const container = containerRef.current;
4132
4199
  const content = contentRef.current;
@@ -4186,7 +4253,7 @@ function useAdaptiveSpacer(options = {}) {
4186
4253
  }
4187
4254
 
4188
4255
  // src/components/chat/ThinkingIndicator.tsx
4189
- import React57, { useEffect as useEffect8, useState as useState13 } from "react";
4256
+ import React57, { useEffect as useEffect8, useState as useState14 } from "react";
4190
4257
  var THINKING_PHRASES = [
4191
4258
  "Consulting the ancient tomes...",
4192
4259
  "Parsing the ineffable...",
@@ -4207,15 +4274,17 @@ var ThinkingIndicator = React57.forwardRef(
4207
4274
  isVisible = true,
4208
4275
  phraseInterval = 2500,
4209
4276
  phrases = THINKING_PHRASES,
4277
+ manualLabel,
4210
4278
  className,
4211
4279
  ...rest
4212
4280
  }, ref) => {
4213
- const [currentIndex, setCurrentIndex] = useState13(
4281
+ const [currentIndex, setCurrentIndex] = useState14(
4214
4282
  () => Math.floor(Math.random() * phrases.length)
4215
4283
  );
4216
- const [isTransitioning, setIsTransitioning] = useState13(false);
4284
+ const [isTransitioning, setIsTransitioning] = useState14(false);
4285
+ const isManual = manualLabel !== void 0;
4217
4286
  useEffect8(() => {
4218
- if (!isVisible || phrases.length <= 1) {
4287
+ if (!isVisible || isManual || phrases.length <= 1) {
4219
4288
  return;
4220
4289
  }
4221
4290
  let fadeTimeout = null;
@@ -4233,7 +4302,7 @@ var ThinkingIndicator = React57.forwardRef(
4233
4302
  clearTimeout(fadeTimeout);
4234
4303
  }
4235
4304
  };
4236
- }, [isVisible, phrases.length, phraseInterval]);
4305
+ }, [isVisible, isManual, phrases.length, phraseInterval]);
4237
4306
  if (!isVisible) {
4238
4307
  return null;
4239
4308
  }
@@ -4270,7 +4339,7 @@ var ThinkingIndicator = React57.forwardRef(
4270
4339
  style: { animationDelay: "300ms" }
4271
4340
  }
4272
4341
  )),
4273
- /* @__PURE__ */ React57.createElement(
4342
+ isManual ? /* @__PURE__ */ React57.createElement("span", { className: "text-sm italic" }, manualLabel) : /* @__PURE__ */ React57.createElement(
4274
4343
  "span",
4275
4344
  {
4276
4345
  className: cx(
@@ -4294,19 +4363,22 @@ import {
4294
4363
  GitBranch as GitBranch2,
4295
4364
  GitCommitVertical,
4296
4365
  GitMerge,
4297
- PencilLine
4366
+ PencilLine,
4367
+ Upload
4298
4368
  } from "lucide-react";
4299
4369
  var KIND_ICONS = {
4300
4370
  task: GitBranch2,
4301
4371
  submit: GitMerge,
4302
4372
  rename: PencilLine,
4303
- init: GitCommitVertical
4373
+ init: GitCommitVertical,
4374
+ ingest: Upload
4304
4375
  };
4305
4376
  var KIND_ARIA_LABELS = {
4306
4377
  task: "Task checkpoint",
4307
4378
  submit: "Submit checkpoint",
4308
4379
  rename: "Rename checkpoint",
4309
- init: "Project head checkpoint"
4380
+ init: "Project head checkpoint",
4381
+ ingest: "Upload batch checkpoint"
4310
4382
  };
4311
4383
  var Checkpoint = React58.forwardRef(
4312
4384
  function Checkpoint2({ name, executionKind, status = "completed", isActive, muted, branchInfo, onJumpHere }, ref) {
@@ -4455,7 +4527,16 @@ GreyedDivider.displayName = "GreyedDivider";
4455
4527
 
4456
4528
  // src/components/chat/ChatView.tsx
4457
4529
  var ChatView = React60.forwardRef(
4458
- function ChatView2({ items, latestUserMessageIndex, isStreaming, isThinking, onScroll, className, ...rest }, ref) {
4530
+ function ChatView2({
4531
+ items,
4532
+ latestUserMessageIndex,
4533
+ isStreaming,
4534
+ isThinking,
4535
+ thinkingLabel,
4536
+ onScroll,
4537
+ className,
4538
+ ...rest
4539
+ }, ref) {
4459
4540
  const { containerRef, anchorRef, scrollToAnchor } = useScrollAnchor({
4460
4541
  behavior: "smooth",
4461
4542
  block: "start"
@@ -4538,7 +4619,7 @@ var ChatView = React60.forwardRef(
4538
4619
  }
4539
4620
  )
4540
4621
  );
4541
- }), showThinking && /* @__PURE__ */ React60.createElement(ThinkingIndicator, { isVisible: true })),
4622
+ }), showThinking && /* @__PURE__ */ React60.createElement(ThinkingIndicator, { isVisible: true, manualLabel: thinkingLabel })),
4542
4623
  /* @__PURE__ */ React60.createElement(
4543
4624
  "div",
4544
4625
  {
@@ -4554,7 +4635,7 @@ var ChatView = React60.forwardRef(
4554
4635
  ChatView.displayName = "ChatView";
4555
4636
 
4556
4637
  // src/components/chat/ChatInput.tsx
4557
- import React61, { useCallback as useCallback15, useEffect as useEffect10, useRef as useRef9, useState as useState14 } from "react";
4638
+ import React61, { useCallback as useCallback15, useEffect as useEffect10, useRef as useRef9, useState as useState15 } from "react";
4558
4639
  import { Paperclip, Send as Send2, Square, X as X6 } from "lucide-react";
4559
4640
 
4560
4641
  // src/components/chat/types.ts
@@ -4602,9 +4683,9 @@ var ChatInput = React61.forwardRef(
4602
4683
  className,
4603
4684
  ...rest
4604
4685
  }, ref) => {
4605
- const [value, setValue] = useState14(initialInputValue);
4606
- const [localAttachments, setLocalAttachments] = useState14([]);
4607
- const [isDragOver, setIsDragOver] = useState14(false);
4686
+ const [value, setValue] = useState15(initialInputValue);
4687
+ const [localAttachments, setLocalAttachments] = useState15([]);
4688
+ const [isDragOver, setIsDragOver] = useState15(false);
4608
4689
  const textareaRef = useRef9(null);
4609
4690
  const fileInputRef = useRef9(null);
4610
4691
  const attachments = controlledAttachments ?? localAttachments;
@@ -4723,8 +4804,8 @@ var ChatInput = React61.forwardRef(
4723
4804
  );
4724
4805
  const isCentered = position === "centered";
4725
4806
  const hasAttachments = attachments.length > 0;
4726
- const isUploading = attachments.some((a) => a.status === "uploading");
4727
- const canSubmit = value.trim() && !disabled && !isStreaming && !isUploading;
4807
+ const isUploadIncomplete = attachments.some((a) => a.status === "pending" || a.status === "uploading" || a.status === "upload_failed");
4808
+ const canSubmit = value.trim() && !disabled && !isStreaming && !isUploadIncomplete;
4728
4809
  return /* @__PURE__ */ React61.createElement(
4729
4810
  "div",
4730
4811
  {
@@ -4861,7 +4942,7 @@ var ChatInput = React61.forwardRef(
4861
4942
  ChatInput.displayName = "ChatInput";
4862
4943
 
4863
4944
  // src/components/chat/ArtifactsPanel.tsx
4864
- import React71, { useCallback as useCallback17, useEffect as useEffect12, useRef as useRef11, useState as useState17 } from "react";
4945
+ import React71, { useCallback as useCallback18, useEffect as useEffect13, useRef as useRef12, useState as useState19 } from "react";
4865
4946
  import { Image } from "lucide-react";
4866
4947
 
4867
4948
  // src/components/ArtifactCard.tsx
@@ -5390,7 +5471,7 @@ var ArtifactCard = React68.forwardRef(
5390
5471
  ArtifactCard.displayName = "ArtifactCard";
5391
5472
 
5392
5473
  // src/components/ArtifactGroup.tsx
5393
- import React69, { useEffect as useEffect11, useRef as useRef10, useState as useState15 } from "react";
5474
+ import React69, { useEffect as useEffect11, useRef as useRef10, useState as useState16 } from "react";
5394
5475
  var LAYER_OFFSET = "8px";
5395
5476
  var LAYER_OFFSET_2X = "16px";
5396
5477
  var ArtifactGroup = React69.forwardRef(
@@ -5399,7 +5480,7 @@ var ArtifactGroup = React69.forwardRef(
5399
5480
  const count = children.length;
5400
5481
  const frontChild = children[0];
5401
5482
  const prevCountRef = useRef10(count);
5402
- const [badgePing, setBadgePing] = useState15(false);
5483
+ const [badgePing, setBadgePing] = useState16(false);
5403
5484
  useEffect11(() => {
5404
5485
  if (count !== prevCountRef.current) {
5405
5486
  prevCountRef.current = count;
@@ -5519,10 +5600,69 @@ var ArtifactVariantStack = React70.forwardRef(
5519
5600
  );
5520
5601
  ArtifactVariantStack.displayName = "ArtifactVariantStack";
5521
5602
 
5603
+ // src/components/chat/hooks/useResizable.ts
5604
+ import { useCallback as useCallback16, useEffect as useEffect12, useRef as useRef11, useState as useState17 } from "react";
5605
+ function useResizable({
5606
+ initialWidthPercent,
5607
+ minWidthPercent,
5608
+ maxWidthPercent,
5609
+ direction
5610
+ }) {
5611
+ const [widthPercent, setWidthPercent] = useState17(initialWidthPercent);
5612
+ const [isResizing, setIsResizing] = useState17(false);
5613
+ const lastX = useRef11(null);
5614
+ const startResizing = useCallback16((e) => {
5615
+ e.preventDefault();
5616
+ setIsResizing(true);
5617
+ lastX.current = e.clientX;
5618
+ }, []);
5619
+ const stopResizing = useCallback16(() => {
5620
+ setIsResizing(false);
5621
+ lastX.current = null;
5622
+ }, []);
5623
+ const resize = useCallback16(
5624
+ (e) => {
5625
+ if (!isResizing || lastX.current === null) {
5626
+ return;
5627
+ }
5628
+ const deltaX = e.clientX - lastX.current;
5629
+ const factor = direction === "right" ? 1 : -1;
5630
+ const deltaPercent = deltaX / window.innerWidth * 100;
5631
+ setWidthPercent((prevPercent) => {
5632
+ const newPercent = prevPercent + deltaPercent * factor;
5633
+ return Math.min(Math.max(newPercent, minWidthPercent), maxWidthPercent);
5634
+ });
5635
+ lastX.current = e.clientX;
5636
+ },
5637
+ [isResizing, direction, minWidthPercent, maxWidthPercent]
5638
+ );
5639
+ useEffect12(() => {
5640
+ if (isResizing) {
5641
+ window.addEventListener("mousemove", resize);
5642
+ window.addEventListener("mouseup", stopResizing);
5643
+ document.body.style.cursor = "col-resize";
5644
+ document.body.style.userSelect = "none";
5645
+ } else {
5646
+ window.removeEventListener("mousemove", resize);
5647
+ window.removeEventListener("mouseup", stopResizing);
5648
+ document.body.style.cursor = "";
5649
+ document.body.style.userSelect = "";
5650
+ }
5651
+ return () => {
5652
+ window.removeEventListener("mousemove", resize);
5653
+ window.removeEventListener("mouseup", stopResizing);
5654
+ document.body.style.cursor = "";
5655
+ document.body.style.userSelect = "";
5656
+ };
5657
+ }, [isResizing, resize, stopResizing]);
5658
+ const width = `${widthPercent}vw`;
5659
+ return { width, widthPercent, isResizing, startResizing };
5660
+ }
5661
+
5522
5662
  // src/components/chat/hooks/useArtifactTreeNavigation.ts
5523
- import { useCallback as useCallback16, useMemo as useMemo2, useState as useState16 } from "react";
5663
+ import { useCallback as useCallback17, useMemo as useMemo2, useState as useState18 } from "react";
5524
5664
  function useArtifactTreeNavigation(rootNodes) {
5525
- const [stack, setStack] = useState16([]);
5665
+ const [stack, setStack] = useState18([]);
5526
5666
  const currentNodes = useMemo2(() => {
5527
5667
  if (stack.length === 0) return rootNodes;
5528
5668
  return stack[stack.length - 1].children;
@@ -5535,13 +5675,13 @@ function useArtifactTreeNavigation(rootNodes) {
5535
5675
  return entries;
5536
5676
  }, [stack]);
5537
5677
  const isAtRoot = stack.length === 0;
5538
- const navigateInto = useCallback16((node) => {
5678
+ const navigateInto = useCallback17((node) => {
5539
5679
  setStack((prev) => [...prev, node]);
5540
5680
  }, []);
5541
- const navigateTo = useCallback16((index) => {
5681
+ const navigateTo = useCallback17((index) => {
5542
5682
  setStack((prev) => prev.slice(0, index));
5543
5683
  }, []);
5544
- const navigateBack = useCallback16(() => {
5684
+ const navigateBack = useCallback17(() => {
5545
5685
  setStack((prev) => prev.slice(0, -1));
5546
5686
  }, []);
5547
5687
  return {
@@ -5561,7 +5701,7 @@ function ArtifactModal({
5561
5701
  onClose
5562
5702
  }) {
5563
5703
  useEscapeKey(onClose);
5564
- const handleBackdropClick = useCallback17((e) => {
5704
+ const handleBackdropClick = useCallback18((e) => {
5565
5705
  if (e.target === e.currentTarget) {
5566
5706
  onClose();
5567
5707
  }
@@ -5642,6 +5782,20 @@ function ArtifactModal({
5642
5782
  )
5643
5783
  );
5644
5784
  }
5785
+ function findArtifactInNodes(nodes, artifactId) {
5786
+ for (const node of nodes) {
5787
+ if (node.type === "ARTIFACT" && node.artifact?.id === artifactId) {
5788
+ return node.artifact;
5789
+ }
5790
+ if (node.children && node.children.length > 0) {
5791
+ const found = findArtifactInNodes(node.children, artifactId);
5792
+ if (found) {
5793
+ return found;
5794
+ }
5795
+ }
5796
+ }
5797
+ return null;
5798
+ }
5645
5799
  function NodeRenderer({
5646
5800
  node,
5647
5801
  loading,
@@ -5677,31 +5831,48 @@ var ArtifactsPanel = React71.forwardRef(
5677
5831
  ({
5678
5832
  nodes,
5679
5833
  loading,
5834
+ openArtifactId,
5835
+ onArtifactClosed,
5680
5836
  className,
5681
5837
  ...rest
5682
5838
  }, ref) => {
5683
- const [expandedArtifact, setExpandedArtifact] = useState17(null);
5684
- const [zoomIndex, setZoomIndex] = useState17(ZOOM_LEVELS.length - 1);
5839
+ const [expandedArtifact, setExpandedArtifact] = useState19(null);
5840
+ const [zoomIndex, setZoomIndex] = useState19(ZOOM_LEVELS.length - 1);
5685
5841
  const treeNav = useArtifactTreeNavigation(nodes || []);
5686
5842
  const hasNodes = !!nodes && nodes.length > 0;
5687
- const handleExpandArtifact = useCallback17((artifact) => {
5843
+ const handleExpandArtifact = useCallback18((artifact) => {
5688
5844
  setExpandedArtifact(artifact);
5689
5845
  }, []);
5690
- const handleGroupClick = useCallback17((node) => {
5846
+ const handleGroupClick = useCallback18((node) => {
5691
5847
  treeNav.navigateInto(node);
5692
5848
  }, [treeNav]);
5693
- const zoomIn = useCallback17(() => {
5849
+ useEffect13(() => {
5850
+ if (!openArtifactId || !nodes) {
5851
+ return;
5852
+ }
5853
+ const found = findArtifactInNodes(nodes, openArtifactId);
5854
+ if (found) {
5855
+ setExpandedArtifact(found);
5856
+ }
5857
+ }, [openArtifactId, nodes]);
5858
+ const handleModalClose = useCallback18(() => {
5859
+ setExpandedArtifact(null);
5860
+ onArtifactClosed?.();
5861
+ }, [onArtifactClosed]);
5862
+ const zoomIn = useCallback18(() => {
5694
5863
  setZoomIndex((prev) => Math.min(prev + 1, ZOOM_LEVELS.length - 1));
5695
5864
  }, []);
5696
- const zoomOut = useCallback17(() => {
5865
+ const zoomOut = useCallback18(() => {
5697
5866
  setZoomIndex((prev) => Math.max(prev - 1, 0));
5698
5867
  }, []);
5699
5868
  const currentZoom = ZOOM_LEVELS[zoomIndex];
5700
- const contentRef = useRef11(null);
5701
- const [contentHeight, setContentHeight] = useState17(void 0);
5702
- useEffect12(() => {
5869
+ const contentRef = useRef12(null);
5870
+ const [contentHeight, setContentHeight] = useState19(void 0);
5871
+ useEffect13(() => {
5703
5872
  const el = contentRef.current;
5704
- if (!el) return;
5873
+ if (!el) {
5874
+ return;
5875
+ }
5705
5876
  const observer = new ResizeObserver(([entry]) => {
5706
5877
  setContentHeight(entry.contentRect.height);
5707
5878
  });
@@ -5745,7 +5916,15 @@ var ArtifactsPanel = React71.forwardRef(
5745
5916
  },
5746
5917
  "\u2212"
5747
5918
  ),
5748
- /* @__PURE__ */ React71.createElement("span", { className: "text-xs text-silver w-8 text-center tabular-nums", "data-testid": "zoom-level" }, Math.round(currentZoom * 100), "%"),
5919
+ /* @__PURE__ */ React71.createElement(
5920
+ "span",
5921
+ {
5922
+ className: "text-xs text-silver w-8 text-center tabular-nums",
5923
+ "data-testid": "zoom-level"
5924
+ },
5925
+ Math.round(currentZoom * 100),
5926
+ "%"
5927
+ ),
5749
5928
  /* @__PURE__ */ React71.createElement(
5750
5929
  "button",
5751
5930
  {
@@ -5820,7 +5999,7 @@ var ArtifactsPanel = React71.forwardRef(
5820
5999
  ArtifactModal,
5821
6000
  {
5822
6001
  artifact: expandedArtifact,
5823
- onClose: () => setExpandedArtifact(null)
6002
+ onClose: handleModalClose
5824
6003
  }
5825
6004
  ));
5826
6005
  }
@@ -5857,7 +6036,7 @@ var ArtifactsPanelToggle = React71.forwardRef(({ artifactCount = 0, onExpand, cl
5857
6036
  ArtifactsPanelToggle.displayName = "ArtifactsPanelToggle";
5858
6037
 
5859
6038
  // src/components/chat/HistoryPanel.tsx
5860
- import React72, { useCallback as useCallback18, useEffect as useEffect13, useMemo as useMemo3, useRef as useRef12, useState as useState18 } from "react";
6039
+ import React72, { useCallback as useCallback19, useEffect as useEffect14, useMemo as useMemo3, useRef as useRef13, useState as useState20 } from "react";
5861
6040
  import { ChevronDown as ChevronDown2, Pencil as Pencil2 } from "lucide-react";
5862
6041
  function parseTimestamp(ts) {
5863
6042
  if (ts == null) {
@@ -5900,9 +6079,9 @@ function ProjectFilter({
5900
6079
  onChange,
5901
6080
  className
5902
6081
  }) {
5903
- const [open, setOpen] = useState18(false);
5904
- const ref = useRef12(null);
5905
- const closeFilter = useCallback18(() => setOpen(false), []);
6082
+ const [open, setOpen] = useState20(false);
6083
+ const ref = useRef13(null);
6084
+ const closeFilter = useCallback19(() => setOpen(false), []);
5906
6085
  useClickOutside(ref, closeFilter, open);
5907
6086
  const label = value ?? "All projects";
5908
6087
  return /* @__PURE__ */ React72.createElement("div", { className: cx("relative min-w-0", className), ref }, /* @__PURE__ */ React72.createElement(
@@ -5977,28 +6156,28 @@ function ConversationRow({
5977
6156
  onSelect,
5978
6157
  onRename
5979
6158
  }) {
5980
- const [isEditing, setIsEditing] = useState18(false);
5981
- const [draft, setDraft] = useState18(conversation.title);
5982
- const inputRef = useRef12(null);
5983
- useEffect13(() => {
6159
+ const [isEditing, setIsEditing] = useState20(false);
6160
+ const [draft, setDraft] = useState20(conversation.title);
6161
+ const inputRef = useRef13(null);
6162
+ useEffect14(() => {
5984
6163
  if (isEditing && inputRef.current) {
5985
6164
  inputRef.current.focus();
5986
6165
  inputRef.current.select();
5987
6166
  }
5988
6167
  }, [isEditing]);
5989
- const startEdit = useCallback18((e) => {
6168
+ const startEdit = useCallback19((e) => {
5990
6169
  e.stopPropagation();
5991
6170
  setDraft(conversation.title);
5992
6171
  setIsEditing(true);
5993
6172
  }, [conversation.title]);
5994
- const commit = useCallback18(() => {
6173
+ const commit = useCallback19(() => {
5995
6174
  const trimmed = draft.trim();
5996
6175
  if (trimmed && trimmed !== conversation.title) {
5997
6176
  onRename?.(conversation.id, trimmed);
5998
6177
  }
5999
6178
  setIsEditing(false);
6000
6179
  }, [draft, conversation.id, conversation.title, onRename]);
6001
- const cancel = useCallback18(() => {
6180
+ const cancel = useCallback19(() => {
6002
6181
  setDraft(conversation.title);
6003
6182
  setIsEditing(false);
6004
6183
  }, [conversation.title]);
@@ -6082,7 +6261,7 @@ function HistoryPanel({
6082
6261
  onNewChat,
6083
6262
  onRenameConversation
6084
6263
  }) {
6085
- const [projectFilter, setProjectFilter] = useState18(null);
6264
+ const [projectFilter, setProjectFilter] = useState20(null);
6086
6265
  const projects = useMemo3(() => {
6087
6266
  const set = /* @__PURE__ */ new Set();
6088
6267
  for (const c of conversations) {
@@ -6092,7 +6271,7 @@ function HistoryPanel({
6092
6271
  }
6093
6272
  return Array.from(set).sort((a, b) => a.localeCompare(b));
6094
6273
  }, [conversations]);
6095
- useEffect13(() => {
6274
+ useEffect14(() => {
6096
6275
  if (projectFilter && !projects.includes(projectFilter)) {
6097
6276
  setProjectFilter(null);
6098
6277
  }
@@ -6148,7 +6327,7 @@ function HistoryPanel({
6148
6327
  }
6149
6328
 
6150
6329
  // src/components/chat/TodosList.tsx
6151
- import React73, { useCallback as useCallback19, useMemo as useMemo4, useState as useState19 } from "react";
6330
+ import React73, { useCallback as useCallback20, useMemo as useMemo4, useState as useState21 } from "react";
6152
6331
  import { Loader2 as Loader22, Square as Square2 } from "lucide-react";
6153
6332
  var TASK_STATUSES = {
6154
6333
  PENDING: "pending",
@@ -6227,8 +6406,8 @@ function hasInProgressTask(tasks) {
6227
6406
  var TodosList = React73.forwardRef(
6228
6407
  ({ tasks, title = "Tasks", onStopAllTasks, className, ...rest }, ref) => {
6229
6408
  const sortedTasks = useMemo4(() => sortTasks(tasks), [tasks]);
6230
- const [isStopping, setIsStopping] = useState19(false);
6231
- const handleStopClick = useCallback19(async () => {
6409
+ const [isStopping, setIsStopping] = useState21(false);
6410
+ const handleStopClick = useCallback20(async () => {
6232
6411
  if (!onStopAllTasks || isStopping) {
6233
6412
  return;
6234
6413
  }
@@ -6353,7 +6532,7 @@ var ToolSidebar = React74.forwardRef(
6353
6532
  ToolSidebar.displayName = "ToolSidebar";
6354
6533
 
6355
6534
  // src/components/chat/ToolPanelContainer.tsx
6356
- import React75, { useCallback as useCallback20, useEffect as useEffect14, useRef as useRef13, useState as useState20 } from "react";
6535
+ import React75, { useCallback as useCallback21, useEffect as useEffect15, useRef as useRef14, useState as useState22 } from "react";
6357
6536
  var ToolPanelContainer = React75.forwardRef(
6358
6537
  ({
6359
6538
  topContent,
@@ -6365,21 +6544,21 @@ var ToolPanelContainer = React75.forwardRef(
6365
6544
  initialTopPercent = 60,
6366
6545
  ...rest
6367
6546
  }, ref) => {
6368
- const [topPercent, setTopPercent] = useState20(initialTopPercent);
6369
- const [isResizingHeight, setIsResizingHeight] = useState20(false);
6370
- const containerRef = useRef13(null);
6371
- const lastY = useRef13(null);
6547
+ const [topPercent, setTopPercent] = useState22(initialTopPercent);
6548
+ const [isResizingHeight, setIsResizingHeight] = useState22(false);
6549
+ const containerRef = useRef14(null);
6550
+ const lastY = useRef14(null);
6372
6551
  const hasBoth = topContent !== null && bottomContent !== null;
6373
- const startHeightResize = useCallback20((e) => {
6552
+ const startHeightResize = useCallback21((e) => {
6374
6553
  e.preventDefault();
6375
6554
  setIsResizingHeight(true);
6376
6555
  lastY.current = e.clientY;
6377
6556
  }, []);
6378
- const stopHeightResize = useCallback20(() => {
6557
+ const stopHeightResize = useCallback21(() => {
6379
6558
  setIsResizingHeight(false);
6380
6559
  lastY.current = null;
6381
6560
  }, []);
6382
- const resizeHeight = useCallback20(
6561
+ const resizeHeight = useCallback21(
6383
6562
  (e) => {
6384
6563
  if (!isResizingHeight || lastY.current === null || !containerRef.current) {
6385
6564
  return;
@@ -6398,7 +6577,7 @@ var ToolPanelContainer = React75.forwardRef(
6398
6577
  },
6399
6578
  [isResizingHeight]
6400
6579
  );
6401
- useEffect14(() => {
6580
+ useEffect15(() => {
6402
6581
  if (isResizingHeight) {
6403
6582
  window.addEventListener("mousemove", resizeHeight);
6404
6583
  window.addEventListener("mouseup", stopHeightResize);
@@ -6473,65 +6652,6 @@ var ToolPanelContainer = React75.forwardRef(
6473
6652
  );
6474
6653
  ToolPanelContainer.displayName = "ToolPanelContainer";
6475
6654
 
6476
- // src/components/chat/hooks/useResizable.ts
6477
- import { useCallback as useCallback21, useEffect as useEffect15, useRef as useRef14, useState as useState21 } from "react";
6478
- function useResizable({
6479
- initialWidthPercent,
6480
- minWidthPercent,
6481
- maxWidthPercent,
6482
- direction
6483
- }) {
6484
- const [widthPercent, setWidthPercent] = useState21(initialWidthPercent);
6485
- const [isResizing, setIsResizing] = useState21(false);
6486
- const lastX = useRef14(null);
6487
- const startResizing = useCallback21((e) => {
6488
- e.preventDefault();
6489
- setIsResizing(true);
6490
- lastX.current = e.clientX;
6491
- }, []);
6492
- const stopResizing = useCallback21(() => {
6493
- setIsResizing(false);
6494
- lastX.current = null;
6495
- }, []);
6496
- const resize = useCallback21(
6497
- (e) => {
6498
- if (!isResizing || lastX.current === null) {
6499
- return;
6500
- }
6501
- const deltaX = e.clientX - lastX.current;
6502
- const factor = direction === "right" ? 1 : -1;
6503
- const deltaPercent = deltaX / window.innerWidth * 100;
6504
- setWidthPercent((prevPercent) => {
6505
- const newPercent = prevPercent + deltaPercent * factor;
6506
- return Math.min(Math.max(newPercent, minWidthPercent), maxWidthPercent);
6507
- });
6508
- lastX.current = e.clientX;
6509
- },
6510
- [isResizing, direction, minWidthPercent, maxWidthPercent]
6511
- );
6512
- useEffect15(() => {
6513
- if (isResizing) {
6514
- window.addEventListener("mousemove", resize);
6515
- window.addEventListener("mouseup", stopResizing);
6516
- document.body.style.cursor = "col-resize";
6517
- document.body.style.userSelect = "none";
6518
- } else {
6519
- window.removeEventListener("mousemove", resize);
6520
- window.removeEventListener("mouseup", stopResizing);
6521
- document.body.style.cursor = "";
6522
- document.body.style.userSelect = "";
6523
- }
6524
- return () => {
6525
- window.removeEventListener("mousemove", resize);
6526
- window.removeEventListener("mouseup", stopResizing);
6527
- document.body.style.cursor = "";
6528
- document.body.style.userSelect = "";
6529
- };
6530
- }, [isResizing, resize, stopResizing]);
6531
- const width = `${widthPercent}vw`;
6532
- return { width, widthPercent, isResizing, startResizing };
6533
- }
6534
-
6535
6655
  // src/components/chat/tree.ts
6536
6656
  function createEmptyTree() {
6537
6657
  return { nodes: {}, rootIds: [], activeLeafId: null, lastLeafId: null };
@@ -6692,6 +6812,7 @@ var ChatInterface = React76.forwardRef(
6692
6812
  onRenameConversation,
6693
6813
  isStreaming = false,
6694
6814
  isThinking = false,
6815
+ thinkingLabel,
6695
6816
  placeholder = "Send a message...",
6696
6817
  emptyStateHelper = "Let's talk.",
6697
6818
  emptyState,
@@ -6700,6 +6821,7 @@ var ChatInterface = React76.forwardRef(
6700
6821
  attachments: propsAttachments,
6701
6822
  onAttachmentsChange,
6702
6823
  onAttachmentRemove,
6824
+ onAttachmentOpen,
6703
6825
  artifactNodes,
6704
6826
  isArtifactsPanelOpen,
6705
6827
  onArtifactsPanelOpenChange,
@@ -6716,7 +6838,15 @@ var ChatInterface = React76.forwardRef(
6716
6838
  }, ref) => {
6717
6839
  const prevArtifactNodesRef = useRef15([]);
6718
6840
  const prevTasksRef = useRef15([]);
6719
- const [internalTools, setInternalTools] = useState22({
6841
+ const [panelOpenArtifactId, setPanelOpenArtifactId] = useState23(null);
6842
+ const handleAttachmentOpen = useCallback22((artifactId) => {
6843
+ setPanelOpenArtifactId(artifactId);
6844
+ onAttachmentOpen?.(artifactId);
6845
+ }, [onAttachmentOpen]);
6846
+ const handleArtifactPanelClosed = useCallback22(() => {
6847
+ setPanelOpenArtifactId(null);
6848
+ }, []);
6849
+ const [internalTools, setInternalTools] = useState23({
6720
6850
  "top-left": "history",
6721
6851
  "bottom-left": null,
6722
6852
  "top-right": null,
@@ -6903,7 +7033,15 @@ var ChatInterface = React76.forwardRef(
6903
7033
  isStreaming: node.isStreaming,
6904
7034
  muted: opts.muted,
6905
7035
  branchInfo,
6906
- actions
7036
+ actions,
7037
+ attachments: node.attachments ? node.attachments.map((a) => ({
7038
+ id: a.id,
7039
+ file: { name: a.name, size: a.size ?? 0, type: a.type },
7040
+ previewUrl: a.previewUrl,
7041
+ artifactId: a.artifactId,
7042
+ status: a.status ?? "analyzed"
7043
+ })) : void 0,
7044
+ onAttachmentOpen: handleAttachmentOpen
6907
7045
  };
6908
7046
  },
6909
7047
  [
@@ -6913,7 +7051,8 @@ var ChatInterface = React76.forwardRef(
6913
7051
  onEditMessage,
6914
7052
  onRetryMessage,
6915
7053
  handleBranchSwitch,
6916
- handleJumpToCheckpoint
7054
+ handleJumpToCheckpoint,
7055
+ handleAttachmentOpen
6917
7056
  ]
6918
7057
  );
6919
7058
  const displayItems = useMemo5(() => {
@@ -6982,6 +7121,8 @@ var ChatInterface = React76.forwardRef(
6982
7121
  ArtifactsPanel,
6983
7122
  {
6984
7123
  nodes: artifactNodes,
7124
+ openArtifactId: panelOpenArtifactId,
7125
+ onArtifactClosed: handleArtifactPanelClosed,
6985
7126
  className: "h-full"
6986
7127
  }
6987
7128
  );
@@ -7044,6 +7185,7 @@ var ChatInterface = React76.forwardRef(
7044
7185
  latestUserMessageIndex,
7045
7186
  isStreaming,
7046
7187
  isThinking,
7188
+ thinkingLabel,
7047
7189
  className: "flex-1"
7048
7190
  }
7049
7191
  )), /* @__PURE__ */ React76.createElement("div", { className: cx(
@@ -7098,7 +7240,7 @@ var ChatInterface = React76.forwardRef(
7098
7240
  ChatInterface.displayName = "ChatInterface";
7099
7241
 
7100
7242
  // src/components/chat/MessageActions.tsx
7101
- import React77, { useCallback as useCallback23, useState as useState23 } from "react";
7243
+ import React77, { useCallback as useCallback23, useState as useState24 } from "react";
7102
7244
  import { Check as Check4, Copy as Copy2, Pencil as Pencil3, RotateCcw as RotateCcw2, Send as Send3, X as X7 } from "lucide-react";
7103
7245
  var ActionButton2 = ({ onClick, label, children, className, disabled }) => /* @__PURE__ */ React77.createElement(
7104
7246
  "button",
@@ -7128,8 +7270,8 @@ var MessageActions = React77.forwardRef(
7128
7270
  className,
7129
7271
  ...rest
7130
7272
  }, ref) => {
7131
- const [localIsEditing, setLocalIsEditing] = useState23(false);
7132
- const [localEditValue, setLocalEditValue] = useState23(content);
7273
+ const [localIsEditing, setLocalIsEditing] = useState24(false);
7274
+ const [localEditValue, setLocalEditValue] = useState24(content);
7133
7275
  const { copied, copy } = useCopyToClipboard();
7134
7276
  const isEditing = controlledIsEditing ?? localIsEditing;
7135
7277
  const editValue = controlledEditValue ?? localEditValue;