@gendive/chatllm 0.21.7 → 0.21.9

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.
@@ -54,6 +54,7 @@ __export(index_exports, {
54
54
  Icon: () => Icon,
55
55
  IconSvg: () => IconSvg,
56
56
  ImageContentCard: () => ImageContentCard,
57
+ ImageErrorContext: () => ImageErrorContext,
57
58
  LinkChip: () => LinkChip,
58
59
  MarkdownRenderer: () => MarkdownRenderer,
59
60
  MemoryPanel: () => MemoryPanel,
@@ -75,6 +76,7 @@ __export(index_exports, {
75
76
  useDeepResearch: () => useDeepResearch,
76
77
  useDragResize: () => useDragResize,
77
78
  useFloatingWidget: () => useFloatingWidget,
79
+ useImageError: () => useImageError,
78
80
  useObserver: () => useObserver,
79
81
  useProject: () => useProject,
80
82
  useSkills: () => useSkills
@@ -82,7 +84,7 @@ __export(index_exports, {
82
84
  module.exports = __toCommonJS(index_exports);
83
85
 
84
86
  // src/react/ChatUI.tsx
85
- var import_react23 = __toESM(require("react"));
87
+ var import_react24 = __toESM(require("react"));
86
88
 
87
89
  // src/react/hooks/useChatUI.ts
88
90
  var import_react6 = require("react");
@@ -2327,6 +2329,7 @@ var useChatUI = (options) => {
2327
2329
  onAnalyzePatterns,
2328
2330
  // Image upload
2329
2331
  onUploadImage,
2332
+ onImageError,
2330
2333
  // External storage options
2331
2334
  useExternalStorage = false,
2332
2335
  startWithNewSession = false,
@@ -2433,6 +2436,7 @@ var useChatUI = (options) => {
2433
2436
  const onSessionContextChangeRef = (0, import_react6.useRef)(onSessionContextChange);
2434
2437
  const onLoadModelsRef = (0, import_react6.useRef)(onLoadModels);
2435
2438
  const onUploadImageRef = (0, import_react6.useRef)(onUploadImage);
2439
+ const onImageErrorRef = (0, import_react6.useRef)(onImageError);
2436
2440
  const globalMemoryRef = (0, import_react6.useRef)(null);
2437
2441
  (0, import_react6.useEffect)(() => {
2438
2442
  onSendMessageRef.current = onSendMessage;
@@ -2453,6 +2457,7 @@ var useChatUI = (options) => {
2453
2457
  onSkillCompleteRef.current = onSkillComplete;
2454
2458
  onSessionContextChangeRef.current = onSessionContextChange;
2455
2459
  onUploadImageRef.current = onUploadImage;
2460
+ onImageErrorRef.current = onImageError;
2456
2461
  onLoadModelsRef.current = onLoadModels;
2457
2462
  });
2458
2463
  const abortControllersRef = (0, import_react6.useRef)(/* @__PURE__ */ new Map());
@@ -3542,7 +3547,7 @@ ${finalContent}`;
3542
3547
  if (att.type === "image" && att.file) {
3543
3548
  const dataUri = await fileToDataUri(att.file);
3544
3549
  const imageUrl = onUploadImageRef.current ? await onUploadImageRef.current(dataUri, att.name) : dataUri;
3545
- userContentParts.push({ type: "image", url: imageUrl, alt: att.name });
3550
+ userContentParts.push({ type: "image", url: imageUrl, alt: att.name, fileName: att.name });
3546
3551
  } else {
3547
3552
  userContentParts.push({ type: "file", name: att.name, url: att.previewUrl || "", mimeType: att.mimeType, size: att.size });
3548
3553
  }
@@ -5738,8 +5743,13 @@ ${result.content}
5738
5743
  };
5739
5744
  };
5740
5745
 
5746
+ // src/react/contexts/ImageErrorContext.ts
5747
+ var import_react7 = require("react");
5748
+ var ImageErrorContext = (0, import_react7.createContext)(null);
5749
+ var useImageError = () => (0, import_react7.useContext)(ImageErrorContext);
5750
+
5741
5751
  // src/react/components/ChatSidebar.tsx
5742
- var import_react10 = require("react");
5752
+ var import_react11 = require("react");
5743
5753
 
5744
5754
  // src/react/components/Icon.tsx
5745
5755
  var import_jsx_runtime = require("react/jsx-runtime");
@@ -5839,10 +5849,10 @@ var IconSvg = ({
5839
5849
  };
5840
5850
 
5841
5851
  // src/react/components/MarkdownRenderer.tsx
5842
- var import_react8 = __toESM(require("react"));
5852
+ var import_react9 = __toESM(require("react"));
5843
5853
 
5844
5854
  // src/react/components/LinkChip.tsx
5845
- var import_react7 = require("react");
5855
+ var import_react8 = require("react");
5846
5856
  var import_jsx_runtime2 = require("react/jsx-runtime");
5847
5857
  var getDomain = (url) => {
5848
5858
  try {
@@ -5896,7 +5906,7 @@ var LinkChip = ({
5896
5906
  index,
5897
5907
  style
5898
5908
  }) => {
5899
- const [isHovered, setIsHovered] = (0, import_react7.useState)(false);
5909
+ const [isHovered, setIsHovered] = (0, import_react8.useState)(false);
5900
5910
  const domain = getDomain(url);
5901
5911
  const shortName = getShortName(domain);
5902
5912
  const domainColor = getDomainColor(domain);
@@ -6266,8 +6276,8 @@ var parseTableRow = (row) => {
6266
6276
  return row.split("|").slice(1, -1).map((cell) => cell.trim());
6267
6277
  };
6268
6278
  var MarkdownTable = ({ data }) => {
6269
- const [copied, setCopied] = import_react8.default.useState(false);
6270
- const [isHovered, setIsHovered] = import_react8.default.useState(false);
6279
+ const [copied, setCopied] = import_react9.default.useState(false);
6280
+ const [isHovered, setIsHovered] = import_react9.default.useState(false);
6271
6281
  const handleCopy = async () => {
6272
6282
  const headerLine = data.headers.join(" ");
6273
6283
  const bodyLines = data.rows.map((row) => row.join(" "));
@@ -6379,7 +6389,7 @@ var ThinkingSpinner = () => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
6379
6389
  }
6380
6390
  );
6381
6391
  var ThinkingBlock = ({ content, defaultOpen = false }) => {
6382
- const [isOpen, setIsOpen] = import_react8.default.useState(defaultOpen);
6392
+ const [isOpen, setIsOpen] = import_react9.default.useState(defaultOpen);
6383
6393
  const isStreaming = content.trim().endsWith("...");
6384
6394
  return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
6385
6395
  "details",
@@ -6454,7 +6464,7 @@ var ThinkingBlock = ({ content, defaultOpen = false }) => {
6454
6464
  );
6455
6465
  };
6456
6466
  var CodeBlock = ({ language, code }) => {
6457
- const [copied, setCopied] = import_react8.default.useState(false);
6467
+ const [copied, setCopied] = import_react9.default.useState(false);
6458
6468
  const handleCopy = async () => {
6459
6469
  try {
6460
6470
  await navigator.clipboard.writeText(code);
@@ -6537,9 +6547,20 @@ var CodeBlock = ({ language, code }) => {
6537
6547
  );
6538
6548
  };
6539
6549
  var ImageWithCopyButton = ({ src, alt, imageKey }) => {
6540
- const [isHovered, setIsHovered] = import_react8.default.useState(false);
6541
- const [copyState, setCopyState] = import_react8.default.useState("idle");
6542
- const imgRef = import_react8.default.useRef(null);
6550
+ const [isHovered, setIsHovered] = import_react9.default.useState(false);
6551
+ const [imgSrc, setImgSrc] = import_react9.default.useState(src);
6552
+ const onImageError = useImageError();
6553
+ const handleImageError = import_react9.default.useCallback(async () => {
6554
+ if (onImageError) {
6555
+ const newUrl = await onImageError(imgSrc);
6556
+ if (newUrl) {
6557
+ setImgSrc(newUrl);
6558
+ return;
6559
+ }
6560
+ }
6561
+ }, [onImageError, imgSrc]);
6562
+ const [copyState, setCopyState] = import_react9.default.useState("idle");
6563
+ const imgRef = import_react9.default.useRef(null);
6543
6564
  const getImageBlob = async () => {
6544
6565
  const img = imgRef.current;
6545
6566
  if (img && img.complete && img.naturalWidth > 0) {
@@ -6559,9 +6580,9 @@ var ImageWithCopyButton = ({ src, alt, imageKey }) => {
6559
6580
  console.log("Canvas method failed (CORS), trying fetch...");
6560
6581
  }
6561
6582
  }
6562
- if (!src.startsWith("data:")) {
6583
+ if (!imgSrc.startsWith("data:")) {
6563
6584
  try {
6564
- const response = await fetch(src, { mode: "cors" });
6585
+ const response = await fetch(imgSrc, { mode: "cors" });
6565
6586
  if (response.ok) {
6566
6587
  const blob = await response.blob();
6567
6588
  if (blob.type === "image/png") return blob;
@@ -6601,7 +6622,7 @@ var ImageWithCopyButton = ({ src, alt, imageKey }) => {
6601
6622
  setCopyState("copying");
6602
6623
  try {
6603
6624
  if (!navigator.clipboard?.write) {
6604
- await navigator.clipboard.writeText(src);
6625
+ await navigator.clipboard.writeText(imgSrc);
6605
6626
  setCopyState("copied");
6606
6627
  setTimeout(() => setCopyState("idle"), 2e3);
6607
6628
  return;
@@ -6611,7 +6632,7 @@ var ImageWithCopyButton = ({ src, alt, imageKey }) => {
6611
6632
  await navigator.clipboard.write([new ClipboardItem({ "image/png": blob })]);
6612
6633
  setCopyState("copied");
6613
6634
  } else {
6614
- await navigator.clipboard.writeText(src);
6635
+ await navigator.clipboard.writeText(imgSrc);
6615
6636
  setCopyState("copied");
6616
6637
  }
6617
6638
  setTimeout(() => setCopyState("idle"), 2e3);
@@ -6624,7 +6645,7 @@ var ImageWithCopyButton = ({ src, alt, imageKey }) => {
6624
6645
  const handleDownload = async () => {
6625
6646
  try {
6626
6647
  const blob = await getImageBlob();
6627
- const url = blob ? URL.createObjectURL(blob) : src;
6648
+ const url = blob ? URL.createObjectURL(blob) : imgSrc;
6628
6649
  const link = document.createElement("a");
6629
6650
  link.href = url;
6630
6651
  link.download = alt || `image-${Date.now()}.png`;
@@ -6634,7 +6655,7 @@ var ImageWithCopyButton = ({ src, alt, imageKey }) => {
6634
6655
  if (blob) URL.revokeObjectURL(url);
6635
6656
  } catch (error) {
6636
6657
  console.error("Failed to download image:", error);
6637
- window.open(src, "_blank");
6658
+ window.open(imgSrc, "_blank");
6638
6659
  }
6639
6660
  };
6640
6661
  return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
@@ -6652,10 +6673,11 @@ var ImageWithCopyButton = ({ src, alt, imageKey }) => {
6652
6673
  "img",
6653
6674
  {
6654
6675
  ref: imgRef,
6655
- src,
6676
+ src: imgSrc,
6656
6677
  alt,
6657
6678
  className: "chatllm-image",
6658
- crossOrigin: src.startsWith("data:") ? void 0 : "anonymous",
6679
+ crossOrigin: imgSrc.startsWith("data:") ? void 0 : "anonymous",
6680
+ onError: handleImageError,
6659
6681
  style: {
6660
6682
  maxWidth: "100%",
6661
6683
  borderRadius: "8px",
@@ -6754,7 +6776,7 @@ var ImageWithCopyButton = ({ src, alt, imageKey }) => {
6754
6776
  );
6755
6777
  };
6756
6778
  var ChoiceButtons = ({ choices, title, onChoiceClick }) => {
6757
- const [hoveredIndex, setHoveredIndex] = import_react8.default.useState(null);
6779
+ const [hoveredIndex, setHoveredIndex] = import_react9.default.useState(null);
6758
6780
  return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
6759
6781
  "div",
6760
6782
  {
@@ -6884,11 +6906,11 @@ var MarkdownRenderer = ({
6884
6906
  sources,
6885
6907
  inline = false
6886
6908
  }) => {
6887
- const inlineRendered = (0, import_react8.useMemo)(() => {
6909
+ const inlineRendered = (0, import_react9.useMemo)(() => {
6888
6910
  if (!inline) return null;
6889
6911
  return parseInlineElements(content, "inline-md", sources);
6890
6912
  }, [inline, content, sources]);
6891
- const rendered = (0, import_react8.useMemo)(() => {
6913
+ const rendered = (0, import_react9.useMemo)(() => {
6892
6914
  if (inline) return null;
6893
6915
  const elements = [];
6894
6916
  let processedContent = content;
@@ -7041,7 +7063,7 @@ var MarkdownRenderer = ({
7041
7063
  borderRadius: "0 8px 8px 0",
7042
7064
  color: "var(--chatllm-text, #374151)"
7043
7065
  },
7044
- children: blockquoteLines.map((line, i) => /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_react8.default.Fragment, { children: [
7066
+ children: blockquoteLines.map((line, i) => /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_react9.default.Fragment, { children: [
7045
7067
  parseInlineElements(line, `bq-line-${i}`, sources),
7046
7068
  i < blockquoteLines.length - 1 && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("br", {})
7047
7069
  ] }, i))
@@ -7285,7 +7307,7 @@ var MarkdownRenderer = ({
7285
7307
  };
7286
7308
 
7287
7309
  // src/react/components/ProjectSelector.tsx
7288
- var import_react9 = require("react");
7310
+ var import_react10 = require("react");
7289
7311
  var import_jsx_runtime4 = require("react/jsx-runtime");
7290
7312
  var ProjectSelector = ({
7291
7313
  projects,
@@ -7294,10 +7316,10 @@ var ProjectSelector = ({
7294
7316
  onNewProject,
7295
7317
  onProjectSettings
7296
7318
  }) => {
7297
- const [isOpen, setIsOpen] = (0, import_react9.useState)(false);
7298
- const dropdownRef = (0, import_react9.useRef)(null);
7319
+ const [isOpen, setIsOpen] = (0, import_react10.useState)(false);
7320
+ const dropdownRef = (0, import_react10.useRef)(null);
7299
7321
  const currentProject = projects.find((p) => p.id === currentProjectId);
7300
- (0, import_react9.useEffect)(() => {
7322
+ (0, import_react10.useEffect)(() => {
7301
7323
  const handleClickOutside = (e) => {
7302
7324
  if (dropdownRef.current && !dropdownRef.current.contains(e.target)) {
7303
7325
  setIsOpen(false);
@@ -7531,10 +7553,10 @@ var ChatSidebar = ({
7531
7553
  isLoading = false
7532
7554
  }) => {
7533
7555
  const sidebarWidth = typeof widthProp === "number" ? `${widthProp}px` : widthProp || "288px";
7534
- const [editingId, setEditingId] = (0, import_react10.useState)(null);
7535
- const [editingTitle, setEditingTitle] = (0, import_react10.useState)("");
7536
- const inputRef = (0, import_react10.useRef)(null);
7537
- (0, import_react10.useEffect)(() => {
7556
+ const [editingId, setEditingId] = (0, import_react11.useState)(null);
7557
+ const [editingTitle, setEditingTitle] = (0, import_react11.useState)("");
7558
+ const inputRef = (0, import_react11.useRef)(null);
7559
+ (0, import_react11.useEffect)(() => {
7538
7560
  if (editingId && inputRef.current) {
7539
7561
  inputRef.current.focus();
7540
7562
  inputRef.current.select();
@@ -7906,7 +7928,7 @@ var ChatSidebar = ({
7906
7928
  };
7907
7929
 
7908
7930
  // src/react/components/ChatHeader.tsx
7909
- var import_react11 = require("react");
7931
+ var import_react12 = require("react");
7910
7932
  var import_jsx_runtime6 = require("react/jsx-runtime");
7911
7933
  var ChatHeader = ({
7912
7934
  title,
@@ -7920,7 +7942,7 @@ var ChatHeader = ({
7920
7942
  showSettings = true,
7921
7943
  renderHeaderExtra
7922
7944
  }) => {
7923
- const [modelDropdownOpen, setModelDropdownOpen] = (0, import_react11.useState)(false);
7945
+ const [modelDropdownOpen, setModelDropdownOpen] = (0, import_react12.useState)(false);
7924
7946
  const currentModel = models.find((m) => m.id === model);
7925
7947
  return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
7926
7948
  "header",
@@ -8175,7 +8197,7 @@ var ChatHeader = ({
8175
8197
  };
8176
8198
 
8177
8199
  // src/react/components/ChatInput.tsx
8178
- var import_react12 = __toESM(require("react"));
8200
+ var import_react13 = __toESM(require("react"));
8179
8201
  var import_jsx_runtime7 = require("react/jsx-runtime");
8180
8202
  var ChatInput = ({
8181
8203
  value,
@@ -8203,20 +8225,20 @@ var ChatInput = ({
8203
8225
  onDisclaimerClick,
8204
8226
  inline = false
8205
8227
  }) => {
8206
- const [mainMenuOpen, setMainMenuOpen] = import_react12.default.useState(false);
8207
- const textareaRef = (0, import_react12.useRef)(null);
8208
- const fileInputRef = (0, import_react12.useRef)(null);
8209
- const [actionMenuOpen, setActionMenuOpen] = (0, import_react12.useState)(false);
8210
- const [isDragOver, setIsDragOver] = (0, import_react12.useState)(false);
8211
- const mainMenuRef = (0, import_react12.useRef)(null);
8212
- const actionMenuRef = (0, import_react12.useRef)(null);
8213
- (0, import_react12.useEffect)(() => {
8228
+ const [mainMenuOpen, setMainMenuOpen] = import_react13.default.useState(false);
8229
+ const textareaRef = (0, import_react13.useRef)(null);
8230
+ const fileInputRef = (0, import_react13.useRef)(null);
8231
+ const [actionMenuOpen, setActionMenuOpen] = (0, import_react13.useState)(false);
8232
+ const [isDragOver, setIsDragOver] = (0, import_react13.useState)(false);
8233
+ const mainMenuRef = (0, import_react13.useRef)(null);
8234
+ const actionMenuRef = (0, import_react13.useRef)(null);
8235
+ (0, import_react13.useEffect)(() => {
8214
8236
  if (textareaRef.current) {
8215
8237
  textareaRef.current.style.height = "auto";
8216
8238
  textareaRef.current.style.height = `${Math.min(textareaRef.current.scrollHeight, 200)}px`;
8217
8239
  }
8218
8240
  }, [value]);
8219
- (0, import_react12.useEffect)(() => {
8241
+ (0, import_react13.useEffect)(() => {
8220
8242
  const handleClickOutside = (event) => {
8221
8243
  if (mainMenuRef.current && !mainMenuRef.current.contains(event.target)) {
8222
8244
  setMainMenuOpen(false);
@@ -8938,13 +8960,13 @@ var iconButtonStyle = {
8938
8960
  };
8939
8961
 
8940
8962
  // src/react/components/MessageList.tsx
8941
- var import_react20 = __toESM(require("react"));
8963
+ var import_react21 = __toESM(require("react"));
8942
8964
 
8943
8965
  // src/react/components/MessageBubble.tsx
8944
- var import_react19 = require("react");
8966
+ var import_react20 = require("react");
8945
8967
 
8946
8968
  // src/react/components/DeepResearchProgressUI.tsx
8947
- var import_react13 = __toESM(require("react"));
8969
+ var import_react14 = __toESM(require("react"));
8948
8970
  var import_jsx_runtime8 = require("react/jsx-runtime");
8949
8971
  var StatusIcon = ({ status }) => {
8950
8972
  switch (status) {
@@ -9008,7 +9030,7 @@ var PhaseProgress = ({ phase }) => {
9008
9030
  gap: "8px",
9009
9031
  marginBottom: "16px"
9010
9032
  },
9011
- children: phases.slice(0, 4).map((p, index) => /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_react13.default.Fragment, { children: [
9033
+ children: phases.slice(0, 4).map((p, index) => /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_react14.default.Fragment, { children: [
9012
9034
  /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
9013
9035
  "div",
9014
9036
  {
@@ -9227,7 +9249,7 @@ var DeepResearchProgressUI = ({ progress }) => {
9227
9249
  };
9228
9250
 
9229
9251
  // src/react/components/PollCard.tsx
9230
- var import_react14 = require("react");
9252
+ var import_react15 = require("react");
9231
9253
  var import_jsx_runtime9 = require("react/jsx-runtime");
9232
9254
  var renderInlineMarkdown = (text) => {
9233
9255
  const parts = [];
@@ -9266,12 +9288,12 @@ var PollCard = ({
9266
9288
  onSubmit,
9267
9289
  onSkip
9268
9290
  }) => {
9269
- const [activeTab, setActiveTab] = (0, import_react14.useState)(0);
9270
- const [selections, setSelections] = (0, import_react14.useState)({});
9271
- const [otherTexts, setOtherTexts] = (0, import_react14.useState)({});
9272
- const [otherSelected, setOtherSelected] = (0, import_react14.useState)({});
9291
+ const [activeTab, setActiveTab] = (0, import_react15.useState)(0);
9292
+ const [selections, setSelections] = (0, import_react15.useState)({});
9293
+ const [otherTexts, setOtherTexts] = (0, import_react15.useState)({});
9294
+ const [otherSelected, setOtherSelected] = (0, import_react15.useState)({});
9273
9295
  const currentQuestion = questions[activeTab];
9274
- const handleOptionToggle = (0, import_react14.useCallback)(
9296
+ const handleOptionToggle = (0, import_react15.useCallback)(
9275
9297
  (questionId, optionId, multiSelect) => {
9276
9298
  setSelections((prev) => {
9277
9299
  const current = prev[questionId] || /* @__PURE__ */ new Set();
@@ -9293,7 +9315,7 @@ var PollCard = ({
9293
9315
  },
9294
9316
  []
9295
9317
  );
9296
- const handleOtherToggle = (0, import_react14.useCallback)((questionId, multiSelect) => {
9318
+ const handleOtherToggle = (0, import_react15.useCallback)((questionId, multiSelect) => {
9297
9319
  if (multiSelect) {
9298
9320
  setOtherSelected((prev) => ({ ...prev, [questionId]: !prev[questionId] }));
9299
9321
  } else {
@@ -9301,7 +9323,7 @@ var PollCard = ({
9301
9323
  setOtherSelected((prev) => ({ ...prev, [questionId]: true }));
9302
9324
  }
9303
9325
  }, []);
9304
- const handleSubmit = (0, import_react14.useCallback)(() => {
9326
+ const handleSubmit = (0, import_react15.useCallback)(() => {
9305
9327
  const responses = questions.map((q) => {
9306
9328
  const selected = selections[q.id] || /* @__PURE__ */ new Set();
9307
9329
  const other = otherSelected[q.id] && otherTexts[q.id]?.trim();
@@ -9314,7 +9336,7 @@ var PollCard = ({
9314
9336
  });
9315
9337
  onSubmit(responses);
9316
9338
  }, [questions, selections, otherSelected, otherTexts, onSubmit]);
9317
- const handleSkip = (0, import_react14.useCallback)(() => {
9339
+ const handleSkip = (0, import_react15.useCallback)(() => {
9318
9340
  const responses = questions.map((q) => ({
9319
9341
  questionId: q.id,
9320
9342
  selectedOptions: [],
@@ -9323,7 +9345,7 @@ var PollCard = ({
9323
9345
  onSubmit(responses);
9324
9346
  onSkip?.();
9325
9347
  }, [questions, onSubmit, onSkip]);
9326
- (0, import_react14.useEffect)(() => {
9348
+ (0, import_react15.useEffect)(() => {
9327
9349
  if (typeof window === "undefined") return;
9328
9350
  const handleKeyDown = (e) => {
9329
9351
  if (e.key !== "Escape") return;
@@ -9342,9 +9364,9 @@ var PollCard = ({
9342
9364
  const currentHasSelection = getSelectionCount(currentQuestion.id) > 0;
9343
9365
  const isLastTab = activeTab === questions.length - 1;
9344
9366
  const totalSelected = questions.reduce((sum, q) => sum + getSelectionCount(q.id), 0);
9345
- const [visibleCount, setVisibleCount] = (0, import_react14.useState)(0);
9346
- const [cardVisible, setCardVisible] = (0, import_react14.useState)(false);
9347
- (0, import_react14.useEffect)(() => {
9367
+ const [visibleCount, setVisibleCount] = (0, import_react15.useState)(0);
9368
+ const [cardVisible, setCardVisible] = (0, import_react15.useState)(false);
9369
+ (0, import_react15.useEffect)(() => {
9348
9370
  const fadeTimer = setTimeout(() => setCardVisible(true), 50);
9349
9371
  const totalItems = currentQuestion.options.length + 1;
9350
9372
  const timers = [fadeTimer];
@@ -9353,7 +9375,7 @@ var PollCard = ({
9353
9375
  }
9354
9376
  return () => timers.forEach(clearTimeout);
9355
9377
  }, [currentQuestion.options.length]);
9356
- (0, import_react14.useEffect)(() => {
9378
+ (0, import_react15.useEffect)(() => {
9357
9379
  setVisibleCount(0);
9358
9380
  const totalItems = currentQuestion.options.length + 1;
9359
9381
  const timers = [];
@@ -9362,7 +9384,7 @@ var PollCard = ({
9362
9384
  }
9363
9385
  return () => timers.forEach(clearTimeout);
9364
9386
  }, [activeTab, currentQuestion.options.length]);
9365
- const handleNext = (0, import_react14.useCallback)(() => {
9387
+ const handleNext = (0, import_react15.useCallback)(() => {
9366
9388
  if (!isLastTab) {
9367
9389
  setActiveTab((prev) => prev + 1);
9368
9390
  } else {
@@ -9780,12 +9802,25 @@ var SkillProgressUI = ({
9780
9802
  };
9781
9803
 
9782
9804
  // src/react/components/ImageContentCard.tsx
9783
- var import_react15 = require("react");
9805
+ var import_react16 = require("react");
9784
9806
  var import_jsx_runtime11 = require("react/jsx-runtime");
9785
9807
  var ImageContentCard = ({ part }) => {
9786
- const [isExpanded, setIsExpanded] = (0, import_react15.useState)(false);
9787
- const [isLoaded, setIsLoaded] = (0, import_react15.useState)(false);
9788
- const [hasError, setHasError] = (0, import_react15.useState)(false);
9808
+ const [isExpanded, setIsExpanded] = (0, import_react16.useState)(false);
9809
+ const [isLoaded, setIsLoaded] = (0, import_react16.useState)(false);
9810
+ const [hasError, setHasError] = (0, import_react16.useState)(false);
9811
+ const [imgSrc, setImgSrc] = (0, import_react16.useState)(part.url);
9812
+ const onImageError = useImageError();
9813
+ const handleImageError = (0, import_react16.useCallback)(async () => {
9814
+ if (onImageError) {
9815
+ const newUrl = await onImageError(imgSrc, part.fileName);
9816
+ if (newUrl) {
9817
+ setImgSrc(newUrl);
9818
+ setIsLoaded(false);
9819
+ return;
9820
+ }
9821
+ }
9822
+ setHasError(true);
9823
+ }, [onImageError, imgSrc, part.fileName]);
9789
9824
  if (hasError) {
9790
9825
  return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
9791
9826
  "div",
@@ -9838,10 +9873,10 @@ var ImageContentCard = ({ part }) => {
9838
9873
  /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
9839
9874
  "img",
9840
9875
  {
9841
- src: part.url,
9876
+ src: imgSrc,
9842
9877
  alt: part.alt || "",
9843
9878
  onLoad: () => setIsLoaded(true),
9844
- onError: () => setHasError(true),
9879
+ onError: handleImageError,
9845
9880
  style: {
9846
9881
  display: isLoaded ? "block" : "none",
9847
9882
  width: "100%",
@@ -9884,7 +9919,7 @@ var ImageContentCard = ({ part }) => {
9884
9919
  children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
9885
9920
  "img",
9886
9921
  {
9887
- src: part.url,
9922
+ src: imgSrc,
9888
9923
  alt: part.alt || "",
9889
9924
  style: {
9890
9925
  maxWidth: "90vw",
@@ -9988,7 +10023,7 @@ var FileContentCard = ({ part }) => {
9988
10023
  };
9989
10024
 
9990
10025
  // src/react/components/ToolStatusCard.tsx
9991
- var import_react16 = require("react");
10026
+ var import_react17 = require("react");
9992
10027
  var import_jsx_runtime13 = require("react/jsx-runtime");
9993
10028
  var mapIcon2 = (icon) => {
9994
10029
  const iconMap = {
@@ -10021,7 +10056,7 @@ var ToolStatusCard = ({
10021
10056
  sources,
10022
10057
  errorMessage
10023
10058
  }) => {
10024
- const [isExpanded, setIsExpanded] = (0, import_react16.useState)(false);
10059
+ const [isExpanded, setIsExpanded] = (0, import_react17.useState)(false);
10025
10060
  const displayLabel = label || getDefaultLabel(toolName);
10026
10061
  const statusText = getStatusSuffix(displayLabel, status);
10027
10062
  const hasSources = sources && sources.length > 0;
@@ -10152,7 +10187,7 @@ var ToolStatusCard = ({
10152
10187
  };
10153
10188
 
10154
10189
  // src/react/components/ArtifactCard.tsx
10155
- var import_react17 = require("react");
10190
+ var import_react18 = require("react");
10156
10191
  var import_jsx_runtime14 = require("react/jsx-runtime");
10157
10192
  var getThemeStyles = () => {
10158
10193
  const root = document.documentElement;
@@ -10193,10 +10228,10 @@ var getAutoResizeScript = (id) => `
10193
10228
  });
10194
10229
  </script>`;
10195
10230
  var HtmlArtifact = ({ code }) => {
10196
- const iframeRef = (0, import_react17.useRef)(null);
10197
- const [height, setHeight] = (0, import_react17.useState)(200);
10198
- const artifactId = (0, import_react17.useRef)(`artifact-${Date.now()}-${Math.random().toString(36).slice(2, 7)}`);
10199
- (0, import_react17.useEffect)(() => {
10231
+ const iframeRef = (0, import_react18.useRef)(null);
10232
+ const [height, setHeight] = (0, import_react18.useState)(200);
10233
+ const artifactId = (0, import_react18.useRef)(`artifact-${Date.now()}-${Math.random().toString(36).slice(2, 7)}`);
10234
+ (0, import_react18.useEffect)(() => {
10200
10235
  const id = artifactId.current;
10201
10236
  const handleMessage = (e) => {
10202
10237
  if (e.data?.type === "artifact-resize" && e.data.id === id && typeof e.data.height === "number") {
@@ -10242,10 +10277,10 @@ var SvgArtifact = ({ code }) => {
10242
10277
  );
10243
10278
  };
10244
10279
  var MermaidArtifact = ({ code }) => {
10245
- const containerRef = (0, import_react17.useRef)(null);
10246
- const [svgHtml, setSvgHtml] = (0, import_react17.useState)(null);
10247
- const [error, setError] = (0, import_react17.useState)(null);
10248
- const renderMermaid = (0, import_react17.useCallback)(async () => {
10280
+ const containerRef = (0, import_react18.useRef)(null);
10281
+ const [svgHtml, setSvgHtml] = (0, import_react18.useState)(null);
10282
+ const [error, setError] = (0, import_react18.useState)(null);
10283
+ const renderMermaid = (0, import_react18.useCallback)(async () => {
10249
10284
  try {
10250
10285
  let mermaid;
10251
10286
  try {
@@ -10261,7 +10296,7 @@ var MermaidArtifact = ({ code }) => {
10261
10296
  setError(e instanceof Error ? e.message : "Mermaid \uB80C\uB354\uB9C1 \uC2E4\uD328");
10262
10297
  }
10263
10298
  }, [code]);
10264
- (0, import_react17.useEffect)(() => {
10299
+ (0, import_react18.useEffect)(() => {
10265
10300
  renderMermaid();
10266
10301
  }, [renderMermaid]);
10267
10302
  if (error) {
@@ -10337,9 +10372,9 @@ var svgToPngBlob = (svgString, scale = 2) => {
10337
10372
  });
10338
10373
  };
10339
10374
  var ArtifactActions = ({ code, language, containerRef }) => {
10340
- const [showCode, setShowCode] = (0, import_react17.useState)(false);
10341
- const [copied, setCopied] = (0, import_react17.useState)(false);
10342
- const [saving, setSaving] = (0, import_react17.useState)(false);
10375
+ const [showCode, setShowCode] = (0, import_react18.useState)(false);
10376
+ const [copied, setCopied] = (0, import_react18.useState)(false);
10377
+ const [saving, setSaving] = (0, import_react18.useState)(false);
10343
10378
  const handleCopy = async () => {
10344
10379
  try {
10345
10380
  await navigator.clipboard.writeText(code);
@@ -10504,7 +10539,7 @@ var ArtifactActions = ({ code, language, containerRef }) => {
10504
10539
  ] });
10505
10540
  };
10506
10541
  var ArtifactCard = ({ part, index = 0 }) => {
10507
- const contentRef = (0, import_react17.useRef)(null);
10542
+ const contentRef = (0, import_react18.useRef)(null);
10508
10543
  return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(
10509
10544
  "div",
10510
10545
  {
@@ -10629,7 +10664,7 @@ var ContentPartRenderer = ({
10629
10664
  effectiveType === "image" && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
10630
10665
  ImageContentCard,
10631
10666
  {
10632
- part: { type: "image", url: result.content, alt: result.metadata?.alt }
10667
+ part: { type: "image", url: result.content, alt: result.metadata?.alt, fileName: result.metadata?.fileName }
10633
10668
  }
10634
10669
  ),
10635
10670
  effectiveType === "file" && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
@@ -10676,7 +10711,7 @@ var ContentPartRenderer = ({
10676
10711
  };
10677
10712
 
10678
10713
  // src/react/components/ChecklistCard.tsx
10679
- var import_react18 = require("react");
10714
+ var import_react19 = require("react");
10680
10715
  var import_jsx_runtime16 = require("react/jsx-runtime");
10681
10716
  var ChecklistCard = ({
10682
10717
  items,
@@ -10686,8 +10721,8 @@ var ChecklistCard = ({
10686
10721
  onSkipStep,
10687
10722
  onStart
10688
10723
  }) => {
10689
- const [expandedItems, setExpandedItems] = (0, import_react18.useState)(/* @__PURE__ */ new Set());
10690
- const { doneCount, isRunning, hasError, isWaiting } = (0, import_react18.useMemo)(() => {
10724
+ const [expandedItems, setExpandedItems] = (0, import_react19.useState)(/* @__PURE__ */ new Set());
10725
+ const { doneCount, isRunning, hasError, isWaiting } = (0, import_react19.useMemo)(() => {
10691
10726
  const done = items.filter((it) => it.status === "done").length;
10692
10727
  const running = items.some((it) => it.status === "in_progress");
10693
10728
  const waiting = items.every((it) => it.status === "pending");
@@ -11184,9 +11219,9 @@ var MessageBubble = ({
11184
11219
  onToggleChecklistPanel,
11185
11220
  onChecklistStart
11186
11221
  }) => {
11187
- const [showActions, setShowActions] = (0, import_react19.useState)(false);
11188
- const [showModelMenu, setShowModelMenu] = (0, import_react19.useState)(false);
11189
- const [stepExpanded, setStepExpanded] = (0, import_react19.useState)(false);
11222
+ const [showActions, setShowActions] = (0, import_react20.useState)(false);
11223
+ const [showModelMenu, setShowModelMenu] = (0, import_react20.useState)(false);
11224
+ const [stepExpanded, setStepExpanded] = (0, import_react20.useState)(false);
11190
11225
  const isUser = message.role === "user";
11191
11226
  const isAssistant = message.role === "assistant";
11192
11227
  const relevantAlternatives = isUser ? alternatives : message.alternatives;
@@ -11937,14 +11972,14 @@ var MessageList = ({
11937
11972
  onExport,
11938
11973
  onToggleChecklistPanel
11939
11974
  }) => {
11940
- const messagesEndRef = (0, import_react20.useRef)(null);
11941
- const containerRef = (0, import_react20.useRef)(null);
11942
- const [selectedText, setSelectedText] = (0, import_react20.useState)("");
11943
- const [selectionPosition, setSelectionPosition] = (0, import_react20.useState)(null);
11944
- const [showScrollButton, setShowScrollButton] = (0, import_react20.useState)(false);
11945
- const userScrollLockRef = (0, import_react20.useRef)(false);
11975
+ const messagesEndRef = (0, import_react21.useRef)(null);
11976
+ const containerRef = (0, import_react21.useRef)(null);
11977
+ const [selectedText, setSelectedText] = (0, import_react21.useState)("");
11978
+ const [selectionPosition, setSelectionPosition] = (0, import_react21.useState)(null);
11979
+ const [showScrollButton, setShowScrollButton] = (0, import_react21.useState)(false);
11980
+ const userScrollLockRef = (0, import_react21.useRef)(false);
11946
11981
  const SCROLL_THRESHOLD = 100;
11947
- (0, import_react20.useEffect)(() => {
11982
+ (0, import_react21.useEffect)(() => {
11948
11983
  const container = containerRef.current;
11949
11984
  if (!container) return;
11950
11985
  const handleWheel = (e) => {
@@ -11981,7 +12016,7 @@ var MessageList = ({
11981
12016
  container.removeEventListener("touchmove", handleTouchMove);
11982
12017
  };
11983
12018
  }, []);
11984
- const handleScroll = (0, import_react20.useCallback)(() => {
12019
+ const handleScroll = (0, import_react21.useCallback)(() => {
11985
12020
  if (!containerRef.current) return;
11986
12021
  const { scrollTop, scrollHeight, clientHeight } = containerRef.current;
11987
12022
  const distanceFromBottom = scrollHeight - scrollTop - clientHeight;
@@ -11990,14 +12025,14 @@ var MessageList = ({
11990
12025
  setShowScrollButton(false);
11991
12026
  }
11992
12027
  }, []);
11993
- (0, import_react20.useEffect)(() => {
12028
+ (0, import_react21.useEffect)(() => {
11994
12029
  if (userScrollLockRef.current) return;
11995
12030
  containerRef.current?.scrollTo({
11996
12031
  top: containerRef.current.scrollHeight,
11997
12032
  behavior: "smooth"
11998
12033
  });
11999
12034
  }, [messages]);
12000
- const scrollToBottom = (0, import_react20.useCallback)(() => {
12035
+ const scrollToBottom = (0, import_react21.useCallback)(() => {
12001
12036
  userScrollLockRef.current = false;
12002
12037
  setShowScrollButton(false);
12003
12038
  containerRef.current?.scrollTo({
@@ -12005,7 +12040,7 @@ var MessageList = ({
12005
12040
  behavior: "smooth"
12006
12041
  });
12007
12042
  }, []);
12008
- const handleMouseUp = (0, import_react20.useCallback)(() => {
12043
+ const handleMouseUp = (0, import_react21.useCallback)(() => {
12009
12044
  const selection = typeof window !== "undefined" ? window.getSelection() : null;
12010
12045
  const text = selection?.toString().trim();
12011
12046
  if (text && text.length > 0) {
@@ -12106,7 +12141,7 @@ var MessageList = ({
12106
12141
  },
12107
12142
  message.id
12108
12143
  );
12109
- return renderMessage ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_react20.default.Fragment, { children: renderMessage(message, bubbleElement) }, message.id) : bubbleElement;
12144
+ return renderMessage ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_react21.default.Fragment, { children: renderMessage(message, bubbleElement) }, message.id) : bubbleElement;
12110
12145
  }),
12111
12146
  /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { ref: messagesEndRef })
12112
12147
  ]
@@ -12200,7 +12235,7 @@ var MessageList = ({
12200
12235
  };
12201
12236
 
12202
12237
  // src/react/components/SettingsModal.tsx
12203
- var import_react21 = require("react");
12238
+ var import_react22 = require("react");
12204
12239
  var import_jsx_runtime19 = require("react/jsx-runtime");
12205
12240
  var DEFAULT_IMPORT_MEMORY_PROMPT = `Export all of my stored memories and any context you've learned about me from past conversations. Preserve my words verbatim where possible, especially for instructions and preferences.
12206
12241
 
@@ -12265,9 +12300,9 @@ var SettingsModal = ({
12265
12300
  onImportMemory,
12266
12301
  importMemoryPrompt
12267
12302
  }) => {
12268
- const [activeTab, setActiveTab] = (0, import_react21.useState)("general");
12269
- const [localApiKey, setLocalApiKey] = (0, import_react21.useState)(apiKey);
12270
- (0, import_react21.useEffect)(() => {
12303
+ const [activeTab, setActiveTab] = (0, import_react22.useState)("general");
12304
+ const [localApiKey, setLocalApiKey] = (0, import_react22.useState)(apiKey);
12305
+ (0, import_react22.useEffect)(() => {
12271
12306
  setLocalApiKey(apiKey);
12272
12307
  }, [apiKey]);
12273
12308
  if (!isOpen) return null;
@@ -12743,11 +12778,11 @@ var memoryCategoryColors = {
12743
12778
  preference: "#8b5cf6"
12744
12779
  };
12745
12780
  var MemoryTabContent = ({ items, contextSummary, onDelete, onClearAll, title = "AI \uBA54\uBAA8\uB9AC", emptyMessage = "\uC800\uC7A5\uB41C \uBA54\uBAA8\uB9AC\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4", emptyDescription = "\uB300\uD654\uAC00 \uC9C4\uD589\uB418\uBA74 AI\uAC00 \uC790\uB3D9\uC73C\uB85C \uC815\uBCF4\uB97C \uD559\uC2B5\uD569\uB2C8\uB2E4", onImportMemory, importMemoryPrompt }) => {
12746
- const [activeFilter, setActiveFilter] = (0, import_react21.useState)("all");
12747
- const [expandedId, setExpandedId] = (0, import_react21.useState)(null);
12748
- const [importModalOpen, setImportModalOpen] = (0, import_react21.useState)(false);
12749
- const [importText, setImportText] = (0, import_react21.useState)("");
12750
- const [promptCopied, setPromptCopied] = (0, import_react21.useState)(false);
12781
+ const [activeFilter, setActiveFilter] = (0, import_react22.useState)("all");
12782
+ const [expandedId, setExpandedId] = (0, import_react22.useState)(null);
12783
+ const [importModalOpen, setImportModalOpen] = (0, import_react22.useState)(false);
12784
+ const [importText, setImportText] = (0, import_react22.useState)("");
12785
+ const [promptCopied, setPromptCopied] = (0, import_react22.useState)(false);
12751
12786
  const filteredItems = activeFilter === "all" ? items : items.filter((item) => item.category === activeFilter);
12752
12787
  const formatDate = (timestamp) => {
12753
12788
  const date = new Date(timestamp);
@@ -13204,7 +13239,7 @@ var MemoryTabContent = ({ items, contextSummary, onDelete, onClearAll, title = "
13204
13239
  };
13205
13240
 
13206
13241
  // src/react/components/ProjectSettingsModal.tsx
13207
- var import_react22 = require("react");
13242
+ var import_react23 = require("react");
13208
13243
  var import_jsx_runtime20 = require("react/jsx-runtime");
13209
13244
  var COLOR_PRESETS = [
13210
13245
  "#3584FA",
@@ -13225,12 +13260,12 @@ var ProjectSettingsModal = ({
13225
13260
  onDeleteFile,
13226
13261
  onDeleteProject
13227
13262
  }) => {
13228
- const [activeTab, setActiveTab] = (0, import_react22.useState)("general");
13229
- const [title, setTitle] = (0, import_react22.useState)("");
13230
- const [description, setDescription] = (0, import_react22.useState)("");
13231
- const [instructions, setInstructions] = (0, import_react22.useState)("");
13232
- const [color, setColor] = (0, import_react22.useState)("#3584FA");
13233
- (0, import_react22.useEffect)(() => {
13263
+ const [activeTab, setActiveTab] = (0, import_react23.useState)("general");
13264
+ const [title, setTitle] = (0, import_react23.useState)("");
13265
+ const [description, setDescription] = (0, import_react23.useState)("");
13266
+ const [instructions, setInstructions] = (0, import_react23.useState)("");
13267
+ const [color, setColor] = (0, import_react23.useState)("#3584FA");
13268
+ (0, import_react23.useEffect)(() => {
13234
13269
  if (project) {
13235
13270
  setTitle(project.title);
13236
13271
  setDescription(project.description || "");
@@ -14695,28 +14730,28 @@ var ChatUIView = ({
14695
14730
  handleChecklistSkip,
14696
14731
  activeChecklistMessage
14697
14732
  } = state;
14698
- const [disclaimerOpen, setDisclaimerOpen] = import_react23.default.useState(false);
14699
- const [isMobile, setIsMobile] = import_react23.default.useState(false);
14700
- import_react23.default.useEffect(() => {
14733
+ const [disclaimerOpen, setDisclaimerOpen] = import_react24.default.useState(false);
14734
+ const [isMobile, setIsMobile] = import_react24.default.useState(false);
14735
+ import_react24.default.useEffect(() => {
14701
14736
  if (typeof window === "undefined") return;
14702
14737
  const check = () => setIsMobile(window.innerWidth < 768);
14703
14738
  check();
14704
14739
  window.addEventListener("resize", check);
14705
14740
  return () => window.removeEventListener("resize", check);
14706
14741
  }, []);
14707
- const [checklistPanelDismissed, setChecklistPanelDismissed] = import_react23.default.useState(false);
14742
+ const [checklistPanelDismissed, setChecklistPanelDismissed] = import_react24.default.useState(false);
14708
14743
  const isChecklistPanelOpen = !!activeChecklistMessage && !checklistPanelDismissed;
14709
- const prevChecklistIdRef = import_react23.default.useRef(void 0);
14710
- import_react23.default.useEffect(() => {
14744
+ const prevChecklistIdRef = import_react24.default.useRef(void 0);
14745
+ import_react24.default.useEffect(() => {
14711
14746
  const currentId = activeChecklistMessage?.checklistBlock?.id;
14712
14747
  if (currentId && currentId !== prevChecklistIdRef.current && !activeChecklistMessage?.checklistBlock?.completed) {
14713
14748
  setChecklistPanelDismissed(false);
14714
14749
  }
14715
14750
  prevChecklistIdRef.current = currentId;
14716
14751
  }, [activeChecklistMessage?.checklistBlock?.id, activeChecklistMessage?.checklistBlock?.completed]);
14717
- const [welcomeExiting, setWelcomeExiting] = import_react23.default.useState(false);
14718
- const prevMessageCountRef = import_react23.default.useRef(messages.length);
14719
- import_react23.default.useEffect(() => {
14752
+ const [welcomeExiting, setWelcomeExiting] = import_react24.default.useState(false);
14753
+ const prevMessageCountRef = import_react24.default.useRef(messages.length);
14754
+ import_react24.default.useEffect(() => {
14720
14755
  let timer;
14721
14756
  if (prevMessageCountRef.current === 0 && messages.length > 0) {
14722
14757
  setWelcomeExiting(true);
@@ -14740,7 +14775,7 @@ var ChatUIView = ({
14740
14775
  const handleChoiceClick = (choice) => {
14741
14776
  setInput(choice.text);
14742
14777
  };
14743
- const memoryItems = import_react23.default.useMemo(() => {
14778
+ const memoryItems = import_react24.default.useMemo(() => {
14744
14779
  if (!globalMemory?.state.entries) return [];
14745
14780
  const items = [];
14746
14781
  for (const [key, entry] of globalMemory.state.entries) {
@@ -14754,7 +14789,7 @@ var ChatUIView = ({
14754
14789
  }
14755
14790
  return items;
14756
14791
  }, [globalMemory?.state.entries]);
14757
- const projectMemoryItems = import_react23.default.useMemo(() => {
14792
+ const projectMemoryItems = import_react24.default.useMemo(() => {
14758
14793
  if (!projectMemory?.state.entries) return [];
14759
14794
  const items = [];
14760
14795
  for (const [key, entry] of projectMemory.state.entries) {
@@ -15126,7 +15161,8 @@ var ChatUIWithHook = ({
15126
15161
  onWorkflowSuggested,
15127
15162
  onAnalyzePatterns,
15128
15163
  // Image upload
15129
- onUploadImage
15164
+ onUploadImage,
15165
+ onImageError
15130
15166
  }) => {
15131
15167
  const hookOptions = {
15132
15168
  models,
@@ -15176,10 +15212,11 @@ var ChatUIWithHook = ({
15176
15212
  onWorkflowSuggested,
15177
15213
  onAnalyzePatterns,
15178
15214
  // Image upload
15179
- onUploadImage
15215
+ onUploadImage,
15216
+ onImageError
15180
15217
  };
15181
15218
  const state = useChatUI(hookOptions);
15182
- return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
15219
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(ImageErrorContext.Provider, { value: onImageError || null, children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
15183
15220
  ChatUIView,
15184
15221
  {
15185
15222
  state,
@@ -15206,7 +15243,7 @@ var ChatUIWithHook = ({
15206
15243
  onImportMemory,
15207
15244
  importMemoryPrompt
15208
15245
  }
15209
- );
15246
+ ) });
15210
15247
  };
15211
15248
  var ChatUI = (props) => {
15212
15249
  injectStyles();
@@ -15236,7 +15273,7 @@ var ChatUI = (props) => {
15236
15273
  onImportMemory,
15237
15274
  importMemoryPrompt
15238
15275
  } = props;
15239
- return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
15276
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(ImageErrorContext.Provider, { value: props.onImageError || null, children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
15240
15277
  ChatUIView,
15241
15278
  {
15242
15279
  state: props.chatState,
@@ -15264,19 +15301,19 @@ var ChatUI = (props) => {
15264
15301
  onImportMemory,
15265
15302
  importMemoryPrompt
15266
15303
  }
15267
- );
15304
+ ) });
15268
15305
  }
15269
15306
  return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(ChatUIWithHook, { ...props });
15270
15307
  };
15271
15308
 
15272
15309
  // src/react/ChatFloatingWidget.tsx
15273
- var import_react31 = require("react");
15310
+ var import_react32 = require("react");
15274
15311
 
15275
15312
  // src/react/hooks/useFloatingWidget.ts
15276
- var import_react25 = require("react");
15313
+ var import_react26 = require("react");
15277
15314
 
15278
15315
  // src/react/hooks/useDragResize.ts
15279
- var import_react24 = require("react");
15316
+ var import_react25 = require("react");
15280
15317
  var DRAG_THRESHOLD = 5;
15281
15318
  var FAB_SIZE = 56;
15282
15319
  var EDGE_MARGIN = 24;
@@ -15344,8 +15381,8 @@ var useDragResize = (options) => {
15344
15381
  maxWidth = DEFAULT_MAX_WIDTH,
15345
15382
  minHeight = DEFAULT_MIN_HEIGHT
15346
15383
  } = options;
15347
- const [isMobile, setIsMobile] = (0, import_react24.useState)(false);
15348
- (0, import_react24.useEffect)(() => {
15384
+ const [isMobile, setIsMobile] = (0, import_react25.useState)(false);
15385
+ (0, import_react25.useEffect)(() => {
15349
15386
  if (typeof window === "undefined") return;
15350
15387
  const mql = window.matchMedia("(max-width: 767px)");
15351
15388
  setIsMobile(mql.matches);
@@ -15360,19 +15397,19 @@ var useDragResize = (options) => {
15360
15397
  panelWidth: initialWidth,
15361
15398
  panelHeight: initialHeight
15362
15399
  });
15363
- const [fabPos, setFabPos] = (0, import_react24.useState)({ x: persisted.fabX, y: persisted.fabY });
15364
- const [panelSize, setPanelSize] = (0, import_react24.useState)({ width: persisted.panelWidth, height: persisted.panelHeight });
15365
- const [isDragging, setIsDragging] = (0, import_react24.useState)(false);
15366
- const [isResizing, setIsResizing] = (0, import_react24.useState)(false);
15367
- const [isDizzy, setIsDizzy] = (0, import_react24.useState)(false);
15368
- const [viewport, setViewport] = (0, import_react24.useState)(() => ({
15400
+ const [fabPos, setFabPos] = (0, import_react25.useState)({ x: persisted.fabX, y: persisted.fabY });
15401
+ const [panelSize, setPanelSize] = (0, import_react25.useState)({ width: persisted.panelWidth, height: persisted.panelHeight });
15402
+ const [isDragging, setIsDragging] = (0, import_react25.useState)(false);
15403
+ const [isResizing, setIsResizing] = (0, import_react25.useState)(false);
15404
+ const [isDizzy, setIsDizzy] = (0, import_react25.useState)(false);
15405
+ const [viewport, setViewport] = (0, import_react25.useState)(() => ({
15369
15406
  width: typeof window !== "undefined" ? window.innerWidth : 1024,
15370
15407
  height: typeof window !== "undefined" ? window.innerHeight : 768
15371
15408
  }));
15372
15409
  const vw = viewport.width;
15373
15410
  const vh = viewport.height;
15374
- const initializedRef = (0, import_react24.useRef)(false);
15375
- (0, import_react24.useEffect)(() => {
15411
+ const initializedRef = (0, import_react25.useRef)(false);
15412
+ (0, import_react25.useEffect)(() => {
15376
15413
  if (initializedRef.current || typeof window === "undefined") return;
15377
15414
  initializedRef.current = true;
15378
15415
  const correctFab = getInitialFabPosition(initialPosition);
@@ -15385,40 +15422,40 @@ var useDragResize = (options) => {
15385
15422
  setFabPos({ x: loaded.fabX, y: loaded.fabY });
15386
15423
  setPanelSize({ width: loaded.panelWidth, height: loaded.panelHeight });
15387
15424
  }, [initialPosition, storageKey, initialWidth, initialHeight]);
15388
- const dragStartRef = (0, import_react24.useRef)(null);
15389
- const isDraggingRef = (0, import_react24.useRef)(false);
15390
- const wasDragRef = (0, import_react24.useRef)(false);
15391
- const userDraggedRef = (0, import_react24.useRef)(false);
15392
- const dragDeltaRef = (0, import_react24.useRef)({ dx: 0, dy: 0 });
15393
- const fabElRef = (0, import_react24.useRef)(null);
15394
- const dragCleanupRef = (0, import_react24.useRef)(null);
15395
- const snapTimerRef = (0, import_react24.useRef)(null);
15396
- const prevDragRef = (0, import_react24.useRef)(null);
15397
- const shakeScoreRef = (0, import_react24.useRef)(0);
15398
- const prevVelocityRef = (0, import_react24.useRef)(null);
15399
- const isDizzyRef = (0, import_react24.useRef)(false);
15400
- const dizzyTimerRef = (0, import_react24.useRef)(null);
15401
- const lastVelocityRef = (0, import_react24.useRef)({ vx: 0, vy: 0, speed: 0 });
15402
- const dragRafRef = (0, import_react24.useRef)(null);
15403
- const animCleanupRef = (0, import_react24.useRef)(null);
15404
- const snapEnabledRef = (0, import_react24.useRef)(snapEnabled);
15405
- const storageKeyRef = (0, import_react24.useRef)(storageKey);
15406
- const panelSizeRef = (0, import_react24.useRef)(panelSize);
15407
- const fabPosRef = (0, import_react24.useRef)(fabPos);
15408
- (0, import_react24.useEffect)(() => {
15425
+ const dragStartRef = (0, import_react25.useRef)(null);
15426
+ const isDraggingRef = (0, import_react25.useRef)(false);
15427
+ const wasDragRef = (0, import_react25.useRef)(false);
15428
+ const userDraggedRef = (0, import_react25.useRef)(false);
15429
+ const dragDeltaRef = (0, import_react25.useRef)({ dx: 0, dy: 0 });
15430
+ const fabElRef = (0, import_react25.useRef)(null);
15431
+ const dragCleanupRef = (0, import_react25.useRef)(null);
15432
+ const snapTimerRef = (0, import_react25.useRef)(null);
15433
+ const prevDragRef = (0, import_react25.useRef)(null);
15434
+ const shakeScoreRef = (0, import_react25.useRef)(0);
15435
+ const prevVelocityRef = (0, import_react25.useRef)(null);
15436
+ const isDizzyRef = (0, import_react25.useRef)(false);
15437
+ const dizzyTimerRef = (0, import_react25.useRef)(null);
15438
+ const lastVelocityRef = (0, import_react25.useRef)({ vx: 0, vy: 0, speed: 0 });
15439
+ const dragRafRef = (0, import_react25.useRef)(null);
15440
+ const animCleanupRef = (0, import_react25.useRef)(null);
15441
+ const snapEnabledRef = (0, import_react25.useRef)(snapEnabled);
15442
+ const storageKeyRef = (0, import_react25.useRef)(storageKey);
15443
+ const panelSizeRef = (0, import_react25.useRef)(panelSize);
15444
+ const fabPosRef = (0, import_react25.useRef)(fabPos);
15445
+ (0, import_react25.useEffect)(() => {
15409
15446
  snapEnabledRef.current = snapEnabled;
15410
15447
  }, [snapEnabled]);
15411
- (0, import_react24.useEffect)(() => {
15448
+ (0, import_react25.useEffect)(() => {
15412
15449
  storageKeyRef.current = storageKey;
15413
15450
  }, [storageKey]);
15414
- (0, import_react24.useEffect)(() => {
15451
+ (0, import_react25.useEffect)(() => {
15415
15452
  panelSizeRef.current = panelSize;
15416
15453
  }, [panelSize]);
15417
- (0, import_react24.useEffect)(() => {
15454
+ (0, import_react25.useEffect)(() => {
15418
15455
  fabPosRef.current = fabPos;
15419
15456
  }, [fabPos]);
15420
- const resizeStartRef = (0, import_react24.useRef)(null);
15421
- (0, import_react24.useEffect)(() => {
15457
+ const resizeStartRef = (0, import_react25.useRef)(null);
15458
+ (0, import_react25.useEffect)(() => {
15422
15459
  return () => {
15423
15460
  dragCleanupRef.current?.();
15424
15461
  if (snapTimerRef.current) clearTimeout(snapTimerRef.current);
@@ -15426,7 +15463,7 @@ var useDragResize = (options) => {
15426
15463
  if (dragRafRef.current) cancelAnimationFrame(dragRafRef.current);
15427
15464
  };
15428
15465
  }, []);
15429
- const handleFabPointerDown = (0, import_react24.useCallback)((e) => {
15466
+ const handleFabPointerDown = (0, import_react25.useCallback)((e) => {
15430
15467
  if (disabled || isMobile) return;
15431
15468
  dragCleanupRef.current?.();
15432
15469
  const el = e.currentTarget;
@@ -15608,7 +15645,7 @@ var useDragResize = (options) => {
15608
15645
  }, [disabled, isMobile]);
15609
15646
  const fabCenterX = fabPos.x + FAB_SIZE / 2;
15610
15647
  const panelDirection = fabCenterX > vw / 2 ? "left" : "right";
15611
- const panelPositionStyle = (0, import_react24.useMemo)(() => {
15648
+ const panelPositionStyle = (0, import_react25.useMemo)(() => {
15612
15649
  if (isMobile || disabled) return {};
15613
15650
  const fabIsTop = fabPos.y < vh / 2;
15614
15651
  let panelBottom;
@@ -15640,7 +15677,7 @@ var useDragResize = (options) => {
15640
15677
  borderRadius: "var(--floating-panel-radius, 16px)"
15641
15678
  };
15642
15679
  }, [isMobile, disabled, fabPos.x, fabPos.y, panelSize.width, panelSize.height, vw, vh, panelDirection, minHeight]);
15643
- const handleResizePointerDown = (0, import_react24.useCallback)((edge, e) => {
15680
+ const handleResizePointerDown = (0, import_react25.useCallback)((edge, e) => {
15644
15681
  if (disabled || isMobile) return;
15645
15682
  e.preventDefault();
15646
15683
  e.stopPropagation();
@@ -15656,7 +15693,7 @@ var useDragResize = (options) => {
15656
15693
  };
15657
15694
  setIsResizing(true);
15658
15695
  }, [disabled, isMobile]);
15659
- const handleResizePointerMove = (0, import_react24.useCallback)((e) => {
15696
+ const handleResizePointerMove = (0, import_react25.useCallback)((e) => {
15660
15697
  if (!resizeStartRef.current) return;
15661
15698
  const { startX, startY, width, height, edge, fabY } = resizeStartRef.current;
15662
15699
  const dx = e.clientX - startX;
@@ -15680,7 +15717,7 @@ var useDragResize = (options) => {
15680
15717
  newHeight = Math.max(minHeight, Math.min(maxH, newHeight));
15681
15718
  setPanelSize({ width: newWidth, height: newHeight });
15682
15719
  }, [minWidth, maxWidth, minHeight]);
15683
- const handleResizePointerUp = (0, import_react24.useCallback)((e) => {
15720
+ const handleResizePointerUp = (0, import_react25.useCallback)((e) => {
15684
15721
  if (!resizeStartRef.current) return;
15685
15722
  e.currentTarget.releasePointerCapture(e.pointerId);
15686
15723
  resizeStartRef.current = null;
@@ -15689,7 +15726,7 @@ var useDragResize = (options) => {
15689
15726
  const fp = fabPosRef.current;
15690
15727
  persistState(storageKeyRef.current, { fabX: fp.x, fabY: fp.y, panelWidth: ps.width, panelHeight: ps.height });
15691
15728
  }, []);
15692
- (0, import_react24.useEffect)(() => {
15729
+ (0, import_react25.useEffect)(() => {
15693
15730
  if (typeof window === "undefined") return;
15694
15731
  const handleResize = () => {
15695
15732
  const newVw = window.innerWidth;
@@ -15751,9 +15788,9 @@ var useFloatingWidget = (options) => {
15751
15788
  maxWidth,
15752
15789
  minHeight
15753
15790
  } = options || {};
15754
- const [isOpen, setIsOpen] = (0, import_react25.useState)(defaultOpen);
15755
- const [activeTab, setActiveTab] = (0, import_react25.useState)(defaultTab);
15756
- const panelRef = (0, import_react25.useRef)(null);
15791
+ const [isOpen, setIsOpen] = (0, import_react26.useState)(defaultOpen);
15792
+ const [activeTab, setActiveTab] = (0, import_react26.useState)(defaultTab);
15793
+ const panelRef = (0, import_react26.useRef)(null);
15757
15794
  const dragResize = useDragResize({
15758
15795
  initialPosition: position,
15759
15796
  initialWidth: width,
@@ -15765,27 +15802,27 @@ var useFloatingWidget = (options) => {
15765
15802
  maxWidth,
15766
15803
  minHeight
15767
15804
  });
15768
- const onOpenRef = (0, import_react25.useRef)(onOpen);
15769
- const onCloseRef = (0, import_react25.useRef)(onClose);
15770
- const onTabChangeRef = (0, import_react25.useRef)(onTabChange);
15771
- (0, import_react25.useEffect)(() => {
15805
+ const onOpenRef = (0, import_react26.useRef)(onOpen);
15806
+ const onCloseRef = (0, import_react26.useRef)(onClose);
15807
+ const onTabChangeRef = (0, import_react26.useRef)(onTabChange);
15808
+ (0, import_react26.useEffect)(() => {
15772
15809
  onOpenRef.current = onOpen;
15773
15810
  }, [onOpen]);
15774
- (0, import_react25.useEffect)(() => {
15811
+ (0, import_react26.useEffect)(() => {
15775
15812
  onCloseRef.current = onClose;
15776
15813
  }, [onClose]);
15777
- (0, import_react25.useEffect)(() => {
15814
+ (0, import_react26.useEffect)(() => {
15778
15815
  onTabChangeRef.current = onTabChange;
15779
15816
  }, [onTabChange]);
15780
- const open = (0, import_react25.useCallback)(() => {
15817
+ const open = (0, import_react26.useCallback)(() => {
15781
15818
  setIsOpen(true);
15782
15819
  onOpenRef.current?.();
15783
15820
  }, []);
15784
- const close = (0, import_react25.useCallback)(() => {
15821
+ const close = (0, import_react26.useCallback)(() => {
15785
15822
  setIsOpen(false);
15786
15823
  onCloseRef.current?.();
15787
15824
  }, []);
15788
- const toggle = (0, import_react25.useCallback)(() => {
15825
+ const toggle = (0, import_react26.useCallback)(() => {
15789
15826
  setIsOpen((prev) => {
15790
15827
  const next = !prev;
15791
15828
  if (next) onOpenRef.current?.();
@@ -15793,15 +15830,15 @@ var useFloatingWidget = (options) => {
15793
15830
  return next;
15794
15831
  });
15795
15832
  }, []);
15796
- const setTab = (0, import_react25.useCallback)((tabKey) => {
15833
+ const setTab = (0, import_react26.useCallback)((tabKey) => {
15797
15834
  setActiveTab(tabKey);
15798
15835
  onTabChangeRef.current?.(tabKey);
15799
15836
  }, []);
15800
- const handleFabInteraction = (0, import_react25.useCallback)(() => {
15837
+ const handleFabInteraction = (0, import_react26.useCallback)(() => {
15801
15838
  if (dragResize.isDragging) return;
15802
15839
  toggle();
15803
15840
  }, [dragResize.isDragging, toggle]);
15804
- (0, import_react25.useEffect)(() => {
15841
+ (0, import_react26.useEffect)(() => {
15805
15842
  if (!isOpen) return;
15806
15843
  const handleKeyDown = (e) => {
15807
15844
  if (e.key === "Escape") {
@@ -15811,7 +15848,7 @@ var useFloatingWidget = (options) => {
15811
15848
  document.addEventListener("keydown", handleKeyDown);
15812
15849
  return () => document.removeEventListener("keydown", handleKeyDown);
15813
15850
  }, [isOpen, close]);
15814
- (0, import_react25.useEffect)(() => {
15851
+ (0, import_react26.useEffect)(() => {
15815
15852
  if (!isOpen) return;
15816
15853
  const handleClickOutside = (e) => {
15817
15854
  if (dragResize.isDragging || dragResize.isResizing) return;
@@ -15827,10 +15864,10 @@ var useFloatingWidget = (options) => {
15827
15864
  };
15828
15865
 
15829
15866
  // src/react/components/floating/FloatingFab.tsx
15830
- var import_react27 = require("react");
15867
+ var import_react28 = require("react");
15831
15868
 
15832
15869
  // src/react/components/floating/DevDiveCharacter.tsx
15833
- var import_react26 = require("react");
15870
+ var import_react27 = require("react");
15834
15871
  var import_jsx_runtime24 = require("react/jsx-runtime");
15835
15872
  var THEMES = {
15836
15873
  dark: { body: "#2ecc71", stroke: "#27ae60", highlight: "#3ddc84", face: "#1a1a2e", eyeLight: "#fff" },
@@ -15851,32 +15888,32 @@ var DevDiveFabCharacter = ({
15851
15888
  isComplete = false
15852
15889
  }) => {
15853
15890
  const c = THEMES[theme];
15854
- const [eyeOffset, setEyeOffset] = (0, import_react26.useState)({ x: 0, y: 0 });
15855
- const [isBlinking, setIsBlinking] = (0, import_react26.useState)(false);
15856
- const [isHappy, setIsHappy] = (0, import_react26.useState)(false);
15857
- const [isPressed, setIsPressed] = (0, import_react26.useState)(false);
15858
- const [mouthOpen, setMouthOpen] = (0, import_react26.useState)(false);
15859
- const [isSleepy, setIsSleepy] = (0, import_react26.useState)(false);
15860
- const [isSurprised, setIsSurprised] = (0, import_react26.useState)(false);
15861
- const [isWinking, setIsWinking] = (0, import_react26.useState)(false);
15862
- const [isCatMouth, setIsCatMouth] = (0, import_react26.useState)(false);
15863
- const [isEntering, setIsEntering] = (0, import_react26.useState)(true);
15864
- const svgRef = (0, import_react26.useRef)(null);
15865
- const cleanupRef = (0, import_react26.useRef)(null);
15866
- const lastActivityRef = (0, import_react26.useRef)(Date.now());
15867
- const isSleepyRef = (0, import_react26.useRef)(false);
15868
- const markActivity = (0, import_react26.useCallback)(() => {
15891
+ const [eyeOffset, setEyeOffset] = (0, import_react27.useState)({ x: 0, y: 0 });
15892
+ const [isBlinking, setIsBlinking] = (0, import_react27.useState)(false);
15893
+ const [isHappy, setIsHappy] = (0, import_react27.useState)(false);
15894
+ const [isPressed, setIsPressed] = (0, import_react27.useState)(false);
15895
+ const [mouthOpen, setMouthOpen] = (0, import_react27.useState)(false);
15896
+ const [isSleepy, setIsSleepy] = (0, import_react27.useState)(false);
15897
+ const [isSurprised, setIsSurprised] = (0, import_react27.useState)(false);
15898
+ const [isWinking, setIsWinking] = (0, import_react27.useState)(false);
15899
+ const [isCatMouth, setIsCatMouth] = (0, import_react27.useState)(false);
15900
+ const [isEntering, setIsEntering] = (0, import_react27.useState)(true);
15901
+ const svgRef = (0, import_react27.useRef)(null);
15902
+ const cleanupRef = (0, import_react27.useRef)(null);
15903
+ const lastActivityRef = (0, import_react27.useRef)(Date.now());
15904
+ const isSleepyRef = (0, import_react27.useRef)(false);
15905
+ const markActivity = (0, import_react27.useCallback)(() => {
15869
15906
  lastActivityRef.current = Date.now();
15870
15907
  if (isSleepyRef.current) {
15871
15908
  isSleepyRef.current = false;
15872
15909
  setIsSleepy(false);
15873
15910
  }
15874
15911
  }, []);
15875
- (0, import_react26.useEffect)(() => {
15912
+ (0, import_react27.useEffect)(() => {
15876
15913
  const t = setTimeout(() => setIsEntering(false), 600);
15877
15914
  return () => clearTimeout(t);
15878
15915
  }, []);
15879
- (0, import_react26.useEffect)(() => {
15916
+ (0, import_react27.useEffect)(() => {
15880
15917
  let timer;
15881
15918
  let blinkTimer;
15882
15919
  const scheduleBlink = () => {
@@ -15892,7 +15929,7 @@ var DevDiveFabCharacter = ({
15892
15929
  clearTimeout(blinkTimer);
15893
15930
  };
15894
15931
  }, []);
15895
- (0, import_react26.useEffect)(() => {
15932
+ (0, import_react27.useEffect)(() => {
15896
15933
  if (!isTalking) {
15897
15934
  setMouthOpen(false);
15898
15935
  return;
@@ -15905,7 +15942,7 @@ var DevDiveFabCharacter = ({
15905
15942
  toggle();
15906
15943
  return () => clearTimeout(timer);
15907
15944
  }, [isTalking]);
15908
- (0, import_react26.useEffect)(() => {
15945
+ (0, import_react27.useEffect)(() => {
15909
15946
  if (typeof window === "undefined") return;
15910
15947
  let rafId = 0;
15911
15948
  const onMouseMove = (e) => {
@@ -15929,7 +15966,7 @@ var DevDiveFabCharacter = ({
15929
15966
  cancelAnimationFrame(rafId);
15930
15967
  };
15931
15968
  }, []);
15932
- (0, import_react26.useEffect)(() => {
15969
+ (0, import_react27.useEffect)(() => {
15933
15970
  let upTimer;
15934
15971
  let surpriseTimer;
15935
15972
  const rafId = requestAnimationFrame(() => {
@@ -15972,10 +16009,10 @@ var DevDiveFabCharacter = ({
15972
16009
  cleanupRef.current?.();
15973
16010
  };
15974
16011
  }, [markActivity]);
15975
- (0, import_react26.useEffect)(() => {
16012
+ (0, import_react27.useEffect)(() => {
15976
16013
  markActivity();
15977
16014
  }, [isOpen, isTalking, markActivity]);
15978
- (0, import_react26.useEffect)(() => {
16015
+ (0, import_react27.useEffect)(() => {
15979
16016
  if (isOpen || isTalking || isDizzy) return;
15980
16017
  const check = setInterval(() => {
15981
16018
  if (Date.now() - lastActivityRef.current > IDLE_TIMEOUT_MS && !isSleepyRef.current) {
@@ -15985,8 +16022,8 @@ var DevDiveFabCharacter = ({
15985
16022
  }, 5e3);
15986
16023
  return () => clearInterval(check);
15987
16024
  }, [isOpen, isTalking, isDizzy]);
15988
- const prevCompleteRef = (0, import_react26.useRef)(false);
15989
- (0, import_react26.useEffect)(() => {
16025
+ const prevCompleteRef = (0, import_react27.useRef)(false);
16026
+ (0, import_react27.useEffect)(() => {
15990
16027
  const wasComplete = prevCompleteRef.current;
15991
16028
  prevCompleteRef.current = isComplete;
15992
16029
  if (wasComplete || !isComplete) return;
@@ -15994,7 +16031,7 @@ var DevDiveFabCharacter = ({
15994
16031
  const t = setTimeout(() => setIsWinking(false), WINK_DURATION_MS);
15995
16032
  return () => clearTimeout(t);
15996
16033
  }, [isComplete]);
15997
- (0, import_react26.useEffect)(() => {
16034
+ (0, import_react27.useEffect)(() => {
15998
16035
  if (isOpen || isTalking || isDizzy || isError || isSleepy) {
15999
16036
  setIsCatMouth(false);
16000
16037
  return;
@@ -16186,12 +16223,12 @@ var FloatingFab = ({
16186
16223
  }) => {
16187
16224
  const isRight = position.includes("right");
16188
16225
  const isBottom = position.includes("bottom");
16189
- const fabRef = (0, import_react27.useRef)(null);
16226
+ const fabRef = (0, import_react28.useRef)(null);
16190
16227
  const isCharacterMode = !icon;
16191
- const [bubbleOnRight, setBubbleOnRight] = (0, import_react27.useState)(!isRight);
16228
+ const [bubbleOnRight, setBubbleOnRight] = (0, import_react28.useState)(!isRight);
16192
16229
  const posLeft = positionStyle?.left;
16193
16230
  const posTop = positionStyle?.top;
16194
- (0, import_react27.useEffect)(() => {
16231
+ (0, import_react28.useEffect)(() => {
16195
16232
  if (!fabRef.current || typeof window === "undefined") {
16196
16233
  setBubbleOnRight(!isRight);
16197
16234
  return;
@@ -16199,14 +16236,14 @@ var FloatingFab = ({
16199
16236
  const rect = fabRef.current.getBoundingClientRect();
16200
16237
  setBubbleOnRight(rect.left + rect.width / 2 < window.innerWidth / 2);
16201
16238
  }, [isRight, posLeft, posTop]);
16202
- const [bubbleText, setBubbleText] = (0, import_react27.useState)(null);
16203
- const [bubbleExiting, setBubbleExiting] = (0, import_react27.useState)(false);
16204
- const bubbleTextRef = (0, import_react27.useRef)(bubbleText);
16239
+ const [bubbleText, setBubbleText] = (0, import_react28.useState)(null);
16240
+ const [bubbleExiting, setBubbleExiting] = (0, import_react28.useState)(false);
16241
+ const bubbleTextRef = (0, import_react28.useRef)(bubbleText);
16205
16242
  bubbleTextRef.current = bubbleText;
16206
- const [displayText, setDisplayText] = (0, import_react27.useState)(null);
16207
- const [isTyping, setIsTyping] = (0, import_react27.useState)(false);
16208
- const typingTimerRef = (0, import_react27.useRef)(null);
16209
- (0, import_react27.useEffect)(() => {
16243
+ const [displayText, setDisplayText] = (0, import_react28.useState)(null);
16244
+ const [isTyping, setIsTyping] = (0, import_react28.useState)(false);
16245
+ const typingTimerRef = (0, import_react28.useRef)(null);
16246
+ (0, import_react28.useEffect)(() => {
16210
16247
  if (notification) {
16211
16248
  setBubbleText(notification);
16212
16249
  setBubbleExiting(false);
@@ -16242,9 +16279,9 @@ var FloatingFab = ({
16242
16279
  }, 300);
16243
16280
  return () => clearTimeout(timer);
16244
16281
  }, [notification]);
16245
- const notifContentRef = (0, import_react27.useRef)(null);
16246
- const [needsMarquee, setNeedsMarquee] = (0, import_react27.useState)(false);
16247
- (0, import_react27.useEffect)(() => {
16282
+ const notifContentRef = (0, import_react28.useRef)(null);
16283
+ const [needsMarquee, setNeedsMarquee] = (0, import_react28.useState)(false);
16284
+ (0, import_react28.useEffect)(() => {
16248
16285
  if (isTyping || !notification) {
16249
16286
  setNeedsMarquee(false);
16250
16287
  return;
@@ -16386,7 +16423,7 @@ var FloatingFab = ({
16386
16423
  };
16387
16424
 
16388
16425
  // src/react/components/floating/FloatingPanel.tsx
16389
- var import_react28 = require("react");
16426
+ var import_react29 = require("react");
16390
16427
  var import_jsx_runtime26 = require("react/jsx-runtime");
16391
16428
  var FloatingPanel = ({
16392
16429
  isOpen,
@@ -16404,8 +16441,8 @@ var FloatingPanel = ({
16404
16441
  }) => {
16405
16442
  const isRight = position.includes("right");
16406
16443
  const themeClass = theme?.mode === "dark" ? "chatllm-dark" : "";
16407
- const [isMobile, setIsMobile] = (0, import_react28.useState)(false);
16408
- (0, import_react28.useEffect)(() => {
16444
+ const [isMobile, setIsMobile] = (0, import_react29.useState)(false);
16445
+ (0, import_react29.useEffect)(() => {
16409
16446
  if (typeof window === "undefined") return;
16410
16447
  const mql = window.matchMedia("(max-width: 767px)");
16411
16448
  setIsMobile(mql.matches);
@@ -16413,10 +16450,10 @@ var FloatingPanel = ({
16413
16450
  mql.addEventListener("change", handler);
16414
16451
  return () => mql.removeEventListener("change", handler);
16415
16452
  }, []);
16416
- const [shouldRender, setShouldRender] = (0, import_react28.useState)(isOpen);
16417
- const [isVisible, setIsVisible] = (0, import_react28.useState)(isOpen);
16418
- const rafRef = (0, import_react28.useRef)(0);
16419
- (0, import_react28.useEffect)(() => {
16453
+ const [shouldRender, setShouldRender] = (0, import_react29.useState)(isOpen);
16454
+ const [isVisible, setIsVisible] = (0, import_react29.useState)(isOpen);
16455
+ const rafRef = (0, import_react29.useRef)(0);
16456
+ (0, import_react29.useEffect)(() => {
16420
16457
  if (isOpen) {
16421
16458
  setShouldRender(true);
16422
16459
  rafRef.current = requestAnimationFrame(() => {
@@ -16431,7 +16468,7 @@ var FloatingPanel = ({
16431
16468
  }
16432
16469
  return () => cancelAnimationFrame(rafRef.current);
16433
16470
  }, [isOpen]);
16434
- (0, import_react28.useEffect)(() => {
16471
+ (0, import_react29.useEffect)(() => {
16435
16472
  if (!isOpen || !isMobile) return;
16436
16473
  const prev = document.body.style.overflow;
16437
16474
  document.body.style.overflow = "hidden";
@@ -16592,10 +16629,10 @@ var FloatingTabBar = ({
16592
16629
  };
16593
16630
 
16594
16631
  // src/react/components/floating/CompactChatView.tsx
16595
- var import_react30 = require("react");
16632
+ var import_react31 = require("react");
16596
16633
 
16597
16634
  // src/react/components/floating/CompactSessionMenu.tsx
16598
- var import_react29 = require("react");
16635
+ var import_react30 = require("react");
16599
16636
  var import_jsx_runtime28 = require("react/jsx-runtime");
16600
16637
  var CompactSessionMenu = ({
16601
16638
  sessions,
@@ -16607,13 +16644,13 @@ var CompactSessionMenu = ({
16607
16644
  onClose,
16608
16645
  isLoading = false
16609
16646
  }) => {
16610
- const menuRef = (0, import_react29.useRef)(null);
16611
- const inputRef = (0, import_react29.useRef)(null);
16612
- const onCloseRef = (0, import_react29.useRef)(onClose);
16647
+ const menuRef = (0, import_react30.useRef)(null);
16648
+ const inputRef = (0, import_react30.useRef)(null);
16649
+ const onCloseRef = (0, import_react30.useRef)(onClose);
16613
16650
  onCloseRef.current = onClose;
16614
- const [editingId, setEditingId] = (0, import_react29.useState)(null);
16615
- const [editingTitle, setEditingTitle] = (0, import_react29.useState)("");
16616
- (0, import_react29.useEffect)(() => {
16651
+ const [editingId, setEditingId] = (0, import_react30.useState)(null);
16652
+ const [editingTitle, setEditingTitle] = (0, import_react30.useState)("");
16653
+ (0, import_react30.useEffect)(() => {
16617
16654
  const handleMouseDown = (e) => {
16618
16655
  if (menuRef.current && !menuRef.current.contains(e.target)) {
16619
16656
  onCloseRef.current();
@@ -16622,7 +16659,7 @@ var CompactSessionMenu = ({
16622
16659
  document.addEventListener("mousedown", handleMouseDown);
16623
16660
  return () => document.removeEventListener("mousedown", handleMouseDown);
16624
16661
  }, []);
16625
- (0, import_react29.useEffect)(() => {
16662
+ (0, import_react30.useEffect)(() => {
16626
16663
  if (editingId && inputRef.current) {
16627
16664
  inputRef.current.focus();
16628
16665
  inputRef.current.select();
@@ -16937,16 +16974,16 @@ var CompactChatView = ({
16937
16974
  const handleChoiceClick = (choice) => {
16938
16975
  setInput(choice.text);
16939
16976
  };
16940
- const [showSessionMenu, setShowSessionMenu] = (0, import_react30.useState)(false);
16941
- const handleSessionSelect = (0, import_react30.useCallback)((id) => {
16977
+ const [showSessionMenu, setShowSessionMenu] = (0, import_react31.useState)(false);
16978
+ const handleSessionSelect = (0, import_react31.useCallback)((id) => {
16942
16979
  selectSession(id);
16943
16980
  setShowSessionMenu(false);
16944
16981
  }, [selectSession]);
16945
- const handleNewSession = (0, import_react30.useCallback)(() => {
16982
+ const handleNewSession = (0, import_react31.useCallback)(() => {
16946
16983
  newSession();
16947
16984
  setShowSessionMenu(false);
16948
16985
  }, [newSession]);
16949
- const handleCloseMenu = (0, import_react30.useCallback)(() => {
16986
+ const handleCloseMenu = (0, import_react31.useCallback)(() => {
16950
16987
  setShowSessionMenu(false);
16951
16988
  }, []);
16952
16989
  const greeting = personalization?.userProfile?.nickname ? `${personalization.userProfile.nickname}\uB2D8, \uBB34\uC5C7\uC774\uB4E0 \uBB3C\uC5B4\uBCF4\uC138\uC694` : "\uBB34\uC5C7\uC774\uB4E0 \uBB3C\uC5B4\uBCF4\uC138\uC694";
@@ -17266,11 +17303,11 @@ var ChatFloatingWidget = ({
17266
17303
  maxWidth,
17267
17304
  minHeight
17268
17305
  });
17269
- const notifObj = (0, import_react31.useMemo)(() => {
17306
+ const notifObj = (0, import_react32.useMemo)(() => {
17270
17307
  if (!notification) return null;
17271
17308
  return typeof notification === "string" ? { text: notification } : notification;
17272
17309
  }, [notification]);
17273
- const handleFabClick = (0, import_react31.useCallback)(() => {
17310
+ const handleFabClick = (0, import_react32.useCallback)(() => {
17274
17311
  if (notifObj?.onClick) {
17275
17312
  notifObj.onClick();
17276
17313
  if (!isOpen) handleFabInteraction();
@@ -17284,7 +17321,7 @@ var ChatFloatingWidget = ({
17284
17321
  }
17285
17322
  handleFabInteraction();
17286
17323
  }, [notifObj, isOpen, handleFabInteraction, setTab, tabs]);
17287
- const allTabs = (0, import_react31.useMemo)(() => {
17324
+ const allTabs = (0, import_react32.useMemo)(() => {
17288
17325
  const chatTab = {
17289
17326
  key: "chat",
17290
17327
  label: "\uCC44\uD305",
@@ -17298,16 +17335,16 @@ var ChatFloatingWidget = ({
17298
17335
  }));
17299
17336
  return [chatTab, ...customTabs];
17300
17337
  }, [tabs]);
17301
- const [unreadBadge, setUnreadBadge] = (0, import_react31.useState)(0);
17302
- const seenMessageIdsRef = (0, import_react31.useRef)(/* @__PURE__ */ new Set());
17303
- (0, import_react31.useEffect)(() => {
17338
+ const [unreadBadge, setUnreadBadge] = (0, import_react32.useState)(0);
17339
+ const seenMessageIdsRef = (0, import_react32.useRef)(/* @__PURE__ */ new Set());
17340
+ (0, import_react32.useEffect)(() => {
17304
17341
  if (seenMessageIdsRef.current.size === 0 && chatState.messages.length > 0) {
17305
17342
  for (const m of chatState.messages) {
17306
17343
  seenMessageIdsRef.current.add(m.id);
17307
17344
  }
17308
17345
  }
17309
17346
  }, [chatState.messages]);
17310
- (0, import_react31.useEffect)(() => {
17347
+ (0, import_react32.useEffect)(() => {
17311
17348
  if (isOpen) {
17312
17349
  for (const m of chatState.messages) {
17313
17350
  seenMessageIdsRef.current.add(m.id);
@@ -17324,7 +17361,7 @@ var ChatFloatingWidget = ({
17324
17361
  }
17325
17362
  }
17326
17363
  }, [chatState.messages, isOpen]);
17327
- (0, import_react31.useEffect)(() => {
17364
+ (0, import_react32.useEffect)(() => {
17328
17365
  if (isOpen) {
17329
17366
  setUnreadBadge(0);
17330
17367
  for (const m of chatState.messages) {
@@ -17332,13 +17369,13 @@ var ChatFloatingWidget = ({
17332
17369
  }
17333
17370
  }
17334
17371
  }, [isOpen, chatState.messages]);
17335
- const totalBadge = (0, import_react31.useMemo)(() => {
17372
+ const totalBadge = (0, import_react32.useMemo)(() => {
17336
17373
  return tabs.reduce((sum, t) => sum + (t.badge || 0), 0) + unreadBadge;
17337
17374
  }, [tabs, unreadBadge]);
17338
- const isTalking = (0, import_react31.useMemo)(() => !!notification || chatState.isLoading, [notification, chatState.isLoading]);
17339
- const prevLoadingRef = (0, import_react31.useRef)(chatState.isLoading);
17340
- const [isComplete, setIsComplete] = (0, import_react31.useState)(false);
17341
- (0, import_react31.useEffect)(() => {
17375
+ const isTalking = (0, import_react32.useMemo)(() => !!notification || chatState.isLoading, [notification, chatState.isLoading]);
17376
+ const prevLoadingRef = (0, import_react32.useRef)(chatState.isLoading);
17377
+ const [isComplete, setIsComplete] = (0, import_react32.useState)(false);
17378
+ (0, import_react32.useEffect)(() => {
17342
17379
  const wasLoading = prevLoadingRef.current;
17343
17380
  prevLoadingRef.current = chatState.isLoading;
17344
17381
  if (!wasLoading || chatState.isLoading || chatState.messages.length === 0) return;
@@ -17454,7 +17491,7 @@ var ChatFloatingWidget = ({
17454
17491
  };
17455
17492
 
17456
17493
  // src/react/hooks/useDeepResearch.ts
17457
- var import_react32 = require("react");
17494
+ var import_react33 = require("react");
17458
17495
  var REPORT_GENERATION_PROMPT2 = `\uB2F9\uC2E0\uC740 \uB9AC\uC11C\uCE58 \uBCF4\uACE0\uC11C \uC791\uC131 \uC804\uBB38\uAC00\uC785\uB2C8\uB2E4.
17459
17496
 
17460
17497
  <collected_sources>
@@ -17505,10 +17542,10 @@ var QUERY_ANALYSIS_PROMPT2 = `\uC0AC\uC6A9\uC790 \uC9C8\uBB38\uC744 \uBD84\uC11D
17505
17542
  - JSON \uC678 \uB2E4\uB978 \uD14D\uC2A4\uD2B8 \uCD9C\uB825 \uAE08\uC9C0`;
17506
17543
  var useDeepResearch = (options) => {
17507
17544
  const { onWebSearch, onExtractContent, apiEndpoint, apiKey, model, provider } = options;
17508
- const [isResearching, setIsResearching] = (0, import_react32.useState)(false);
17509
- const [progress, setProgress] = (0, import_react32.useState)(null);
17510
- const abortControllerRef = (0, import_react32.useRef)(null);
17511
- const callLLM2 = (0, import_react32.useCallback)(
17545
+ const [isResearching, setIsResearching] = (0, import_react33.useState)(false);
17546
+ const [progress, setProgress] = (0, import_react33.useState)(null);
17547
+ const abortControllerRef = (0, import_react33.useRef)(null);
17548
+ const callLLM2 = (0, import_react33.useCallback)(
17512
17549
  async (prompt, stream = false) => {
17513
17550
  const response = await fetch(apiEndpoint, {
17514
17551
  method: "POST",
@@ -17535,7 +17572,7 @@ var useDeepResearch = (options) => {
17535
17572
  },
17536
17573
  [apiEndpoint, apiKey, model, provider]
17537
17574
  );
17538
- const analyzeQuery2 = (0, import_react32.useCallback)(
17575
+ const analyzeQuery2 = (0, import_react33.useCallback)(
17539
17576
  async (query) => {
17540
17577
  const prompt = QUERY_ANALYSIS_PROMPT2.replace("{question}", query);
17541
17578
  const response = await callLLM2(prompt);
@@ -17554,7 +17591,7 @@ var useDeepResearch = (options) => {
17554
17591
  },
17555
17592
  [callLLM2]
17556
17593
  );
17557
- const runSubAgent2 = (0, import_react32.useCallback)(
17594
+ const runSubAgent2 = (0, import_react33.useCallback)(
17558
17595
  async (topic, queries, agentId, updateProgress) => {
17559
17596
  updateProgress({ status: "searching", searchCount: 0, resultsCount: 0 });
17560
17597
  const allResults = [];
@@ -17593,7 +17630,7 @@ var useDeepResearch = (options) => {
17593
17630
  },
17594
17631
  [onWebSearch, onExtractContent]
17595
17632
  );
17596
- const generateReport2 = (0, import_react32.useCallback)(
17633
+ const generateReport2 = (0, import_react33.useCallback)(
17597
17634
  async (query, results, onStreamContent) => {
17598
17635
  const allSources = [];
17599
17636
  const sourcesForPrompt = [];
@@ -17651,7 +17688,7 @@ var useDeepResearch = (options) => {
17651
17688
  },
17652
17689
  [callLLM2]
17653
17690
  );
17654
- const runDeepResearch = (0, import_react32.useCallback)(
17691
+ const runDeepResearch = (0, import_react33.useCallback)(
17655
17692
  async (query, onStreamContent) => {
17656
17693
  abortControllerRef.current = new AbortController();
17657
17694
  setIsResearching(true);
@@ -17754,7 +17791,7 @@ var useDeepResearch = (options) => {
17754
17791
  },
17755
17792
  [analyzeQuery2, runSubAgent2, generateReport2]
17756
17793
  );
17757
- const stopResearch = (0, import_react32.useCallback)(() => {
17794
+ const stopResearch = (0, import_react33.useCallback)(() => {
17758
17795
  abortControllerRef.current?.abort();
17759
17796
  setIsResearching(false);
17760
17797
  setProgress(null);
@@ -17957,7 +17994,7 @@ var EmptyState = ({
17957
17994
  };
17958
17995
 
17959
17996
  // src/react/components/MemoryPanel.tsx
17960
- var import_react33 = require("react");
17997
+ var import_react34 = require("react");
17961
17998
  var import_jsx_runtime33 = require("react/jsx-runtime");
17962
17999
  var categoryLabels = {
17963
18000
  fact: "\uC0AC\uC6A9\uC790 \uC815\uBCF4",
@@ -17977,8 +18014,8 @@ var MemoryPanel = ({
17977
18014
  isOpen,
17978
18015
  onToggle
17979
18016
  }) => {
17980
- const [expandedId, setExpandedId] = (0, import_react33.useState)(null);
17981
- const [activeTab, setActiveTab] = (0, import_react33.useState)("all");
18017
+ const [expandedId, setExpandedId] = (0, import_react34.useState)(null);
18018
+ const [activeTab, setActiveTab] = (0, import_react34.useState)("all");
17982
18019
  const filteredItems = activeTab === "all" ? items : items.filter((item) => item.category === activeTab);
17983
18020
  const formatDate = (timestamp) => {
17984
18021
  const date = new Date(timestamp);
@@ -18320,6 +18357,7 @@ var MemoryPanel = ({
18320
18357
  Icon,
18321
18358
  IconSvg,
18322
18359
  ImageContentCard,
18360
+ ImageErrorContext,
18323
18361
  LinkChip,
18324
18362
  MarkdownRenderer,
18325
18363
  MemoryPanel,
@@ -18341,6 +18379,7 @@ var MemoryPanel = ({
18341
18379
  useDeepResearch,
18342
18380
  useDragResize,
18343
18381
  useFloatingWidget,
18382
+ useImageError,
18344
18383
  useObserver,
18345
18384
  useProject,
18346
18385
  useSkills