@meetsmore-oss/use-ai-client 1.2.4 → 1.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/bundled.js CHANGED
@@ -4,7 +4,7 @@ import {
4
4
  __toESM,
5
5
  generateChatId,
6
6
  generateMessageId
7
- } from "./chunk-EGD4LT6R.js";
7
+ } from "./chunk-AKQM6IWU.js";
8
8
 
9
9
  // ../../node_modules/.bun/is-buffer@2.0.5/node_modules/is-buffer/index.js
10
10
  var require_is_buffer = __commonJS({
@@ -5753,7 +5753,9 @@ var defaultStrings = {
5753
5753
  /** Input placeholder when connecting */
5754
5754
  connectingPlaceholder: "Connecting...",
5755
5755
  /** Loading indicator text */
5756
- thinking: "Thinking"
5756
+ thinking: "Thinking",
5757
+ /** File processing indicator text (shown during file transformation like OCR) */
5758
+ processingFile: "Processing file..."
5757
5759
  },
5758
5760
  // File upload
5759
5761
  fileUpload: {
@@ -14684,8 +14686,131 @@ function MarkdownContent({ content: content3 }) {
14684
14686
  );
14685
14687
  }
14686
14688
 
14687
- // src/components/FileChip.tsx
14689
+ // src/components/Spinner.tsx
14688
14690
  import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
14691
+ function Spinner({
14692
+ size = 16,
14693
+ color: color2 = "currentColor",
14694
+ trackColor,
14695
+ strokeWidth = 2
14696
+ }) {
14697
+ const radius = 10;
14698
+ const circumference = 2 * Math.PI * radius;
14699
+ return /* @__PURE__ */ jsxs2(
14700
+ "svg",
14701
+ {
14702
+ "data-testid": "spinner",
14703
+ width: size,
14704
+ height: size,
14705
+ viewBox: "0 0 24 24",
14706
+ style: {
14707
+ animation: "use-ai-spin 1s linear infinite"
14708
+ },
14709
+ children: [
14710
+ /* @__PURE__ */ jsx3("style", { children: `
14711
+ @keyframes use-ai-spin {
14712
+ from { transform: rotate(0deg); }
14713
+ to { transform: rotate(360deg); }
14714
+ }
14715
+ ` }),
14716
+ /* @__PURE__ */ jsx3(
14717
+ "circle",
14718
+ {
14719
+ cx: "12",
14720
+ cy: "12",
14721
+ r: radius,
14722
+ fill: "none",
14723
+ stroke: trackColor || color2,
14724
+ strokeWidth,
14725
+ opacity: trackColor ? 1 : 0.25
14726
+ }
14727
+ ),
14728
+ /* @__PURE__ */ jsx3(
14729
+ "circle",
14730
+ {
14731
+ cx: "12",
14732
+ cy: "12",
14733
+ r: radius,
14734
+ fill: "none",
14735
+ stroke: color2,
14736
+ strokeWidth,
14737
+ strokeLinecap: "round",
14738
+ strokeDasharray: circumference,
14739
+ strokeDashoffset: circumference * 0.75,
14740
+ style: {
14741
+ transformOrigin: "center"
14742
+ }
14743
+ }
14744
+ )
14745
+ ]
14746
+ }
14747
+ );
14748
+ }
14749
+
14750
+ // src/components/ProgressBar.tsx
14751
+ import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
14752
+ function ProgressBar({
14753
+ progress,
14754
+ size = 16,
14755
+ color: color2 = "currentColor",
14756
+ trackColor,
14757
+ strokeWidth = 2
14758
+ }) {
14759
+ const clampedProgress = Math.min(100, Math.max(0, progress));
14760
+ const radius = 10;
14761
+ const circumference = 2 * Math.PI * radius;
14762
+ const strokeDashoffset = circumference * (1 - clampedProgress / 100);
14763
+ return /* @__PURE__ */ jsxs3(
14764
+ "svg",
14765
+ {
14766
+ "data-testid": "progress-bar",
14767
+ role: "progressbar",
14768
+ "aria-valuenow": clampedProgress,
14769
+ "aria-valuemin": 0,
14770
+ "aria-valuemax": 100,
14771
+ width: size,
14772
+ height: size,
14773
+ viewBox: "0 0 24 24",
14774
+ style: {
14775
+ transform: "rotate(-90deg)"
14776
+ },
14777
+ children: [
14778
+ /* @__PURE__ */ jsx4(
14779
+ "circle",
14780
+ {
14781
+ cx: "12",
14782
+ cy: "12",
14783
+ r: radius,
14784
+ fill: "none",
14785
+ stroke: trackColor || color2,
14786
+ strokeWidth,
14787
+ opacity: trackColor ? 1 : 0.25
14788
+ }
14789
+ ),
14790
+ /* @__PURE__ */ jsx4(
14791
+ "circle",
14792
+ {
14793
+ cx: "12",
14794
+ cy: "12",
14795
+ r: radius,
14796
+ fill: "none",
14797
+ stroke: color2,
14798
+ strokeWidth,
14799
+ strokeLinecap: "round",
14800
+ strokeDasharray: circumference,
14801
+ strokeDashoffset,
14802
+ style: {
14803
+ transition: "stroke-dashoffset 0.2s ease"
14804
+ }
14805
+ }
14806
+ )
14807
+ ]
14808
+ }
14809
+ );
14810
+ }
14811
+
14812
+ // src/components/FileChip.tsx
14813
+ import { jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
14689
14814
  function formatFileSize(bytes) {
14690
14815
  if (bytes < 1024) return `${bytes} B`;
14691
14816
  if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
@@ -14700,11 +14825,14 @@ function truncateFilename(name, maxLength = 20) {
14700
14825
  if (maxBaseLength < 5) return name.substring(0, maxLength - 3) + "...";
14701
14826
  return baseName.substring(0, maxBaseLength) + "..." + ext;
14702
14827
  }
14703
- function FileChip({ attachment, onRemove, disabled }) {
14828
+ function FileChip({ attachment, onRemove, disabled, processingState }) {
14704
14829
  const theme = useTheme();
14705
14830
  const { file: file2, preview } = attachment;
14706
14831
  const isImage = file2.type.startsWith("image/");
14707
- return /* @__PURE__ */ jsxs2(
14832
+ const isProcessing = processingState?.status === "processing";
14833
+ const hasError = processingState?.status === "error";
14834
+ const progress = processingState?.progress;
14835
+ return /* @__PURE__ */ jsxs4(
14708
14836
  "div",
14709
14837
  {
14710
14838
  "data-testid": "file-chip",
@@ -14717,10 +14845,12 @@ function FileChip({ attachment, onRemove, disabled }) {
14717
14845
  borderRadius: "8px",
14718
14846
  fontSize: "13px",
14719
14847
  color: theme.textColor,
14720
- maxWidth: "200px"
14848
+ maxWidth: "200px",
14849
+ position: "relative",
14850
+ opacity: isProcessing ? 0.7 : 1
14721
14851
  },
14722
14852
  children: [
14723
- isImage && preview ? /* @__PURE__ */ jsx3(
14853
+ isImage && preview ? /* @__PURE__ */ jsx5(
14724
14854
  "img",
14725
14855
  {
14726
14856
  src: preview,
@@ -14732,7 +14862,7 @@ function FileChip({ attachment, onRemove, disabled }) {
14732
14862
  objectFit: "cover"
14733
14863
  }
14734
14864
  }
14735
- ) : /* @__PURE__ */ jsx3(
14865
+ ) : /* @__PURE__ */ jsx5(
14736
14866
  "div",
14737
14867
  {
14738
14868
  style: {
@@ -14748,8 +14878,8 @@ function FileChip({ attachment, onRemove, disabled }) {
14748
14878
  children: "\u{1F4CE}"
14749
14879
  }
14750
14880
  ),
14751
- /* @__PURE__ */ jsxs2("div", { style: { flex: 1, minWidth: 0, overflow: "hidden" }, children: [
14752
- /* @__PURE__ */ jsx3(
14881
+ /* @__PURE__ */ jsxs4("div", { style: { flex: 1, minWidth: 0, overflow: "hidden" }, children: [
14882
+ /* @__PURE__ */ jsx5(
14753
14883
  "div",
14754
14884
  {
14755
14885
  style: {
@@ -14762,28 +14892,28 @@ function FileChip({ attachment, onRemove, disabled }) {
14762
14892
  children: truncateFilename(file2.name)
14763
14893
  }
14764
14894
  ),
14765
- /* @__PURE__ */ jsx3("div", { style: { fontSize: "11px", color: theme.secondaryTextColor }, children: formatFileSize(file2.size) })
14895
+ /* @__PURE__ */ jsx5("div", { style: { fontSize: "11px", color: theme.secondaryTextColor }, children: formatFileSize(file2.size) })
14766
14896
  ] }),
14767
- /* @__PURE__ */ jsx3(
14897
+ /* @__PURE__ */ jsx5(
14768
14898
  "button",
14769
14899
  {
14770
14900
  "data-testid": "file-chip-remove",
14771
14901
  onClick: onRemove,
14772
- disabled,
14902
+ disabled: disabled || isProcessing,
14773
14903
  style: {
14774
14904
  background: "transparent",
14775
14905
  border: "none",
14776
14906
  padding: "2px 4px",
14777
- cursor: disabled ? "not-allowed" : "pointer",
14907
+ cursor: disabled || isProcessing ? "not-allowed" : "pointer",
14778
14908
  color: theme.placeholderTextColor,
14779
14909
  fontSize: "16px",
14780
14910
  lineHeight: 1,
14781
14911
  borderRadius: "4px",
14782
14912
  transition: "all 0.15s",
14783
- opacity: disabled ? 0.5 : 1
14913
+ opacity: disabled || isProcessing ? 0.5 : 1
14784
14914
  },
14785
14915
  onMouseEnter: (e) => {
14786
- if (!disabled) {
14916
+ if (!disabled && !isProcessing) {
14787
14917
  e.currentTarget.style.background = theme.borderColor;
14788
14918
  e.currentTarget.style.color = theme.textColor;
14789
14919
  }
@@ -14794,6 +14924,44 @@ function FileChip({ attachment, onRemove, disabled }) {
14794
14924
  },
14795
14925
  children: "\xD7"
14796
14926
  }
14927
+ ),
14928
+ isProcessing && /* @__PURE__ */ jsx5(
14929
+ "div",
14930
+ {
14931
+ "data-testid": "file-chip-processing",
14932
+ style: {
14933
+ position: "absolute",
14934
+ inset: 0,
14935
+ display: "flex",
14936
+ alignItems: "center",
14937
+ justifyContent: "center",
14938
+ background: "rgba(255, 255, 255, 0.7)",
14939
+ borderRadius: "inherit"
14940
+ },
14941
+ children: progress !== void 0 ? /* @__PURE__ */ jsx5(ProgressBar, { progress, size: 16, color: theme.secondaryTextColor }) : /* @__PURE__ */ jsx5(Spinner, { size: 16, color: theme.secondaryTextColor })
14942
+ }
14943
+ ),
14944
+ hasError && /* @__PURE__ */ jsx5(
14945
+ "div",
14946
+ {
14947
+ "data-testid": "file-chip-error",
14948
+ style: {
14949
+ position: "absolute",
14950
+ bottom: "-2px",
14951
+ right: "-2px",
14952
+ width: "12px",
14953
+ height: "12px",
14954
+ borderRadius: "50%",
14955
+ background: "#ef4444",
14956
+ display: "flex",
14957
+ alignItems: "center",
14958
+ justifyContent: "center",
14959
+ fontSize: "8px",
14960
+ color: "white",
14961
+ fontWeight: "bold"
14962
+ },
14963
+ children: "!"
14964
+ }
14797
14965
  )
14798
14966
  ]
14799
14967
  }
@@ -14801,7 +14969,7 @@ function FileChip({ attachment, onRemove, disabled }) {
14801
14969
  }
14802
14970
  function FilePlaceholder({ name, size }) {
14803
14971
  const theme = useTheme();
14804
- return /* @__PURE__ */ jsxs2(
14972
+ return /* @__PURE__ */ jsxs4(
14805
14973
  "div",
14806
14974
  {
14807
14975
  "data-testid": "file-placeholder",
@@ -14818,9 +14986,9 @@ function FilePlaceholder({ name, size }) {
14818
14986
  maxWidth: "200px"
14819
14987
  },
14820
14988
  children: [
14821
- /* @__PURE__ */ jsx3("span", { children: "\u{1F4CE}" }),
14822
- /* @__PURE__ */ jsxs2("div", { style: { flex: 1, minWidth: 0, overflow: "hidden" }, children: [
14823
- /* @__PURE__ */ jsx3(
14989
+ /* @__PURE__ */ jsx5("span", { children: "\u{1F4CE}" }),
14990
+ /* @__PURE__ */ jsxs4("div", { style: { flex: 1, minWidth: 0, overflow: "hidden" }, children: [
14991
+ /* @__PURE__ */ jsx5(
14824
14992
  "div",
14825
14993
  {
14826
14994
  style: {
@@ -14832,7 +15000,7 @@ function FilePlaceholder({ name, size }) {
14832
15000
  children: truncateFilename(name)
14833
15001
  }
14834
15002
  ),
14835
- /* @__PURE__ */ jsx3("div", { style: { fontSize: "11px" }, children: formatFileSize(size) })
15003
+ /* @__PURE__ */ jsx5("div", { style: { fontSize: "11px" }, children: formatFileSize(size) })
14836
15004
  ] })
14837
15005
  ]
14838
15006
  }
@@ -14861,7 +15029,7 @@ function validateCommandName(name) {
14861
15029
 
14862
15030
  // src/components/CommandAutocomplete.tsx
14863
15031
  import { useEffect, useRef } from "react";
14864
- import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
15032
+ import { jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
14865
15033
  var MAX_VISIBLE_ITEMS = 8;
14866
15034
  function CommandAutocomplete({
14867
15035
  commands,
@@ -14892,7 +15060,7 @@ function CommandAutocomplete({
14892
15060
  }
14893
15061
  }, [highlightedIndex]);
14894
15062
  if (filteredCommands.length === 0) {
14895
- return /* @__PURE__ */ jsx4(
15063
+ return /* @__PURE__ */ jsx6(
14896
15064
  "div",
14897
15065
  {
14898
15066
  "data-testid": "command-autocomplete",
@@ -14908,7 +15076,7 @@ function CommandAutocomplete({
14908
15076
  overflow: "hidden",
14909
15077
  zIndex: 1005
14910
15078
  },
14911
- children: /* @__PURE__ */ jsx4(
15079
+ children: /* @__PURE__ */ jsx6(
14912
15080
  "div",
14913
15081
  {
14914
15082
  style: {
@@ -14923,7 +15091,7 @@ function CommandAutocomplete({
14923
15091
  }
14924
15092
  );
14925
15093
  }
14926
- return /* @__PURE__ */ jsx4(
15094
+ return /* @__PURE__ */ jsx6(
14927
15095
  "div",
14928
15096
  {
14929
15097
  "data-testid": "command-autocomplete",
@@ -14942,7 +15110,7 @@ function CommandAutocomplete({
14942
15110
  overflowY: "auto",
14943
15111
  zIndex: 1005
14944
15112
  },
14945
- children: filteredCommands.map((cmd, index2) => /* @__PURE__ */ jsxs3(
15113
+ children: filteredCommands.map((cmd, index2) => /* @__PURE__ */ jsxs5(
14946
15114
  "div",
14947
15115
  {
14948
15116
  ref: (el) => {
@@ -14962,8 +15130,8 @@ function CommandAutocomplete({
14962
15130
  gap: "8px"
14963
15131
  },
14964
15132
  children: [
14965
- /* @__PURE__ */ jsxs3("div", { style: { flex: 1, minWidth: 0 }, children: [
14966
- /* @__PURE__ */ jsxs3(
15133
+ /* @__PURE__ */ jsxs5("div", { style: { flex: 1, minWidth: 0 }, children: [
15134
+ /* @__PURE__ */ jsxs5(
14967
15135
  "div",
14968
15136
  {
14969
15137
  style: {
@@ -14977,7 +15145,7 @@ function CommandAutocomplete({
14977
15145
  ]
14978
15146
  }
14979
15147
  ),
14980
- /* @__PURE__ */ jsx4(
15148
+ /* @__PURE__ */ jsx6(
14981
15149
  "div",
14982
15150
  {
14983
15151
  style: {
@@ -14992,7 +15160,7 @@ function CommandAutocomplete({
14992
15160
  }
14993
15161
  )
14994
15162
  ] }),
14995
- onDelete && /* @__PURE__ */ jsx4(
15163
+ onDelete && /* @__PURE__ */ jsx6(
14996
15164
  "button",
14997
15165
  {
14998
15166
  "data-testid": "command-delete-button",
@@ -15023,7 +15191,7 @@ function CommandAutocomplete({
15023
15191
  e.currentTarget.style.background = "transparent";
15024
15192
  },
15025
15193
  title: strings.commands.deleteCommand,
15026
- children: /* @__PURE__ */ jsx4("svg", { width: "14", height: "14", viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx4("path", { d: "M2 4H14M6.5 7V11M9.5 7V11M3 4L4 13C4 13.5304 4.21071 14.0391 4.58579 14.4142C4.96086 14.7893 5.46957 15 6 15H10C10.5304 15 11.0391 14.7893 11.4142 14.4142C11.7893 14.0391 12 13.5304 12 13L13 4M5.5 4V2.5C5.5 2.23478 5.60536 1.98043 5.79289 1.79289C5.98043 1.60536 6.23478 1.5 6.5 1.5H9.5C9.76522 1.5 10.0196 1.60536 10.2071 1.79289C10.3946 1.98043 10.5 2.23478 10.5 2.5V4" }) })
15194
+ children: /* @__PURE__ */ jsx6("svg", { width: "14", height: "14", viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx6("path", { d: "M2 4H14M6.5 7V11M9.5 7V11M3 4L4 13C4 13.5304 4.21071 14.0391 4.58579 14.4142C4.96086 14.7893 5.46957 15 6 15H10C10.5304 15 11.0391 14.7893 11.4142 14.4142C11.7893 14.0391 12 13.5304 12 13L13 4M5.5 4V2.5C5.5 2.23478 5.60536 1.98043 5.79289 1.79289C5.98043 1.60536 6.23478 1.5 6.5 1.5H9.5C9.76522 1.5 10.0196 1.60536 10.2071 1.79289C10.3946 1.98043 10.5 2.23478 10.5 2.5V4" }) })
15027
15195
  }
15028
15196
  )
15029
15197
  ]
@@ -15041,7 +15209,7 @@ function getFilteredCommandsCount(commands, searchPrefix) {
15041
15209
  }
15042
15210
 
15043
15211
  // src/hooks/useSlashCommands.tsx
15044
- import { jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
15212
+ import { jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
15045
15213
  var MAX_VISIBLE_ITEMS2 = 8;
15046
15214
  function useSlashCommands({
15047
15215
  commands,
@@ -15176,7 +15344,7 @@ function useSlashCommands({
15176
15344
  }
15177
15345
  }
15178
15346
  }, [savingMessageId, savingMessageText, commandNameInput, commands, onRenameCommand, onSaveCommand, cancelInlineSave, strings]);
15179
- const AutocompleteComponent = showAutocomplete && commands.length > 0 ? /* @__PURE__ */ jsx5(
15347
+ const AutocompleteComponent = showAutocomplete && commands.length > 0 ? /* @__PURE__ */ jsx7(
15180
15348
  CommandAutocomplete,
15181
15349
  {
15182
15350
  commands,
@@ -15192,7 +15360,7 @@ function useSlashCommands({
15192
15360
  if (savingMessageId !== messageId) {
15193
15361
  return null;
15194
15362
  }
15195
- return /* @__PURE__ */ jsxs4(
15363
+ return /* @__PURE__ */ jsxs6(
15196
15364
  "div",
15197
15365
  {
15198
15366
  "data-testid": "inline-save-command",
@@ -15206,9 +15374,9 @@ function useSlashCommands({
15206
15374
  gap: "4px"
15207
15375
  },
15208
15376
  children: [
15209
- /* @__PURE__ */ jsxs4("div", { style: { display: "flex", alignItems: "center", gap: "6px" }, children: [
15210
- /* @__PURE__ */ jsx5("span", { style: { color: theme.primaryColor, fontSize: "13px", fontWeight: 500 }, children: "/" }),
15211
- /* @__PURE__ */ jsx5(
15377
+ /* @__PURE__ */ jsxs6("div", { style: { display: "flex", alignItems: "center", gap: "6px" }, children: [
15378
+ /* @__PURE__ */ jsx7("span", { style: { color: theme.primaryColor, fontSize: "13px", fontWeight: 500 }, children: "/" }),
15379
+ /* @__PURE__ */ jsx7(
15212
15380
  "input",
15213
15381
  {
15214
15382
  ref: commandNameInputRef,
@@ -15240,7 +15408,7 @@ function useSlashCommands({
15240
15408
  }
15241
15409
  }
15242
15410
  ),
15243
- /* @__PURE__ */ jsx5(
15411
+ /* @__PURE__ */ jsx7(
15244
15412
  "button",
15245
15413
  {
15246
15414
  "data-testid": "save-command-confirm",
@@ -15258,15 +15426,15 @@ function useSlashCommands({
15258
15426
  justifyContent: "center"
15259
15427
  },
15260
15428
  title: strings.commands.saveCommand,
15261
- children: /* @__PURE__ */ jsxs4("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
15262
- /* @__PURE__ */ jsx5("path", { d: "M19 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11l5 5v11a2 2 0 0 1-2 2z" }),
15263
- /* @__PURE__ */ jsx5("polyline", { points: "17 21 17 13 7 13 7 21" }),
15264
- /* @__PURE__ */ jsx5("polyline", { points: "7 3 7 8 15 8" })
15429
+ children: /* @__PURE__ */ jsxs6("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
15430
+ /* @__PURE__ */ jsx7("path", { d: "M19 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11l5 5v11a2 2 0 0 1-2 2z" }),
15431
+ /* @__PURE__ */ jsx7("polyline", { points: "17 21 17 13 7 13 7 21" }),
15432
+ /* @__PURE__ */ jsx7("polyline", { points: "7 3 7 8 15 8" })
15265
15433
  ] })
15266
15434
  }
15267
15435
  )
15268
15436
  ] }),
15269
- commandSaveError && /* @__PURE__ */ jsx5(
15437
+ commandSaveError && /* @__PURE__ */ jsx7(
15270
15438
  "div",
15271
15439
  {
15272
15440
  "data-testid": "command-save-error",
@@ -15301,6 +15469,147 @@ import { useState as useState2, useRef as useRef3, useCallback as useCallback2,
15301
15469
  // src/fileUpload/types.ts
15302
15470
  var DEFAULT_MAX_FILE_SIZE = 10 * 1024 * 1024;
15303
15471
 
15472
+ // src/fileUpload/mimeTypeMatcher.ts
15473
+ function matchesMimeType(mimeType, pattern) {
15474
+ if (!pattern.includes("*")) {
15475
+ return mimeType === pattern;
15476
+ }
15477
+ const regexPattern = pattern.replace(/[.+?^${}()|[\]\\]/g, "\\$&").replace(/\*/g, ".*");
15478
+ const regex = new RegExp(`^${regexPattern}$`);
15479
+ return regex.test(mimeType);
15480
+ }
15481
+ function findTransformer(mimeType, transformers) {
15482
+ if (!transformers) {
15483
+ return void 0;
15484
+ }
15485
+ let bestMatch;
15486
+ let bestIsExact = false;
15487
+ let bestLength = -1;
15488
+ for (const [pattern, transformer] of Object.entries(transformers)) {
15489
+ if (!matchesMimeType(mimeType, pattern)) {
15490
+ continue;
15491
+ }
15492
+ const isExact = !pattern.includes("*");
15493
+ if (isExact && !bestIsExact) {
15494
+ bestMatch = transformer;
15495
+ bestIsExact = true;
15496
+ bestLength = pattern.length;
15497
+ continue;
15498
+ }
15499
+ if (isExact === bestIsExact && pattern.length > bestLength) {
15500
+ bestMatch = transformer;
15501
+ bestLength = pattern.length;
15502
+ }
15503
+ }
15504
+ return bestMatch;
15505
+ }
15506
+
15507
+ // src/fileUpload/EmbedFileUploadBackend.ts
15508
+ var EmbedFileUploadBackend = class {
15509
+ /**
15510
+ * Converts a File to a base64 data URL.
15511
+ *
15512
+ * @param file - The File object to convert
15513
+ * @returns Promise resolving to a base64 data URL (e.g., "data:image/png;base64,...")
15514
+ * @throws Error if file reading fails
15515
+ */
15516
+ async prepareForSend(file2) {
15517
+ return new Promise((resolve, reject) => {
15518
+ const reader = new FileReader();
15519
+ reader.onload = () => {
15520
+ if (typeof reader.result === "string") {
15521
+ resolve(reader.result);
15522
+ } else {
15523
+ reject(new Error("Failed to read file as data URL"));
15524
+ }
15525
+ };
15526
+ reader.onerror = () => {
15527
+ reject(new Error(`Failed to read file: ${file2.name}`));
15528
+ };
15529
+ reader.readAsDataURL(file2);
15530
+ });
15531
+ }
15532
+ };
15533
+
15534
+ // src/fileUpload/processAttachments.ts
15535
+ var transformationCache = /* @__PURE__ */ new Map();
15536
+ function getFileCacheKey(file2) {
15537
+ return `${file2.name}:${file2.size}:${file2.lastModified}`;
15538
+ }
15539
+ async function getTransformedContent(file2, transformer, context, onProgress) {
15540
+ const cacheKey = getFileCacheKey(file2);
15541
+ const cached2 = transformationCache.get(cacheKey);
15542
+ if (cached2 !== void 0) {
15543
+ return cached2;
15544
+ }
15545
+ const result = await transformer.transform(file2, context, onProgress);
15546
+ transformationCache.set(cacheKey, result);
15547
+ return result;
15548
+ }
15549
+ async function processAttachments(attachments, config2) {
15550
+ const { getCurrentChat, backend = new EmbedFileUploadBackend(), transformers = {}, onFileProgress } = config2;
15551
+ const contentParts = [];
15552
+ const chat = await getCurrentChat();
15553
+ const context = { chat };
15554
+ for (const attachment of attachments) {
15555
+ try {
15556
+ if (attachment.transformedContent !== void 0) {
15557
+ contentParts.push({
15558
+ type: "transformed_file",
15559
+ text: attachment.transformedContent,
15560
+ originalFile: {
15561
+ name: attachment.file.name,
15562
+ mimeType: attachment.file.type,
15563
+ size: attachment.file.size
15564
+ }
15565
+ });
15566
+ continue;
15567
+ }
15568
+ const transformer = findTransformer(attachment.file.type, transformers);
15569
+ if (transformer) {
15570
+ onFileProgress?.(attachment.id, { status: "processing" });
15571
+ const transformedText = await getTransformedContent(
15572
+ attachment.file,
15573
+ transformer,
15574
+ context,
15575
+ (progress) => {
15576
+ onFileProgress?.(attachment.id, { status: "processing", progress });
15577
+ }
15578
+ );
15579
+ contentParts.push({
15580
+ type: "transformed_file",
15581
+ text: transformedText,
15582
+ originalFile: {
15583
+ name: attachment.file.name,
15584
+ mimeType: attachment.file.type,
15585
+ size: attachment.file.size
15586
+ }
15587
+ });
15588
+ onFileProgress?.(attachment.id, { status: "done" });
15589
+ } else {
15590
+ const url3 = await backend.prepareForSend(attachment.file);
15591
+ if (attachment.file.type.startsWith("image/")) {
15592
+ contentParts.push({ type: "image", url: url3 });
15593
+ } else {
15594
+ contentParts.push({
15595
+ type: "file",
15596
+ url: url3,
15597
+ mimeType: attachment.file.type,
15598
+ name: attachment.file.name
15599
+ });
15600
+ }
15601
+ }
15602
+ } catch (error46) {
15603
+ onFileProgress?.(attachment.id, { status: "error" });
15604
+ throw error46;
15605
+ }
15606
+ }
15607
+ return contentParts;
15608
+ }
15609
+ function clearTransformationCache() {
15610
+ transformationCache.clear();
15611
+ }
15612
+
15304
15613
  // ../../node_modules/.bun/uuid@11.1.0/node_modules/uuid/dist/esm-browser/stringify.js
15305
15614
  var byteToHex = [];
15306
15615
  for (let i = 0; i < 256; ++i) {
@@ -15354,7 +15663,7 @@ function v4(options, buf, offset) {
15354
15663
  var v4_default = v4;
15355
15664
 
15356
15665
  // src/hooks/useFileUpload.tsx
15357
- import { jsx as jsx6 } from "react/jsx-runtime";
15666
+ import { jsx as jsx8 } from "react/jsx-runtime";
15358
15667
  async function generateImagePreview(file2) {
15359
15668
  if (!file2.type.startsWith("image/")) {
15360
15669
  return void 0;
@@ -15387,18 +15696,21 @@ function isTypeAccepted(mimeType, acceptedTypes) {
15387
15696
  function useFileUpload({
15388
15697
  config: config2,
15389
15698
  disabled = false,
15390
- resetDependency
15699
+ resetDependency,
15700
+ getCurrentChat
15391
15701
  }) {
15392
15702
  const strings = useStrings();
15393
15703
  const theme = useTheme();
15394
15704
  const [attachments, setAttachments] = useState2([]);
15395
15705
  const [isDragging, setIsDragging] = useState2(false);
15396
15706
  const [fileError, setFileError] = useState2(null);
15707
+ const [processingState, setProcessingState] = useState2(/* @__PURE__ */ new Map());
15397
15708
  const fileInputRef = useRef3(null);
15398
15709
  const dragCounterRef = useRef3(0);
15399
15710
  const enabled = config2 !== void 0;
15400
15711
  const maxFileSize = config2?.maxFileSize ?? DEFAULT_MAX_FILE_SIZE;
15401
15712
  const acceptedTypes = config2?.acceptedTypes;
15713
+ const transformers = config2?.transformers;
15402
15714
  useEffect3(() => {
15403
15715
  if (fileError) {
15404
15716
  const timer = setTimeout(() => setFileError(null), 3e3);
@@ -15408,7 +15720,28 @@ function useFileUpload({
15408
15720
  useEffect3(() => {
15409
15721
  setAttachments([]);
15410
15722
  setFileError(null);
15723
+ setProcessingState(/* @__PURE__ */ new Map());
15411
15724
  }, [resetDependency]);
15725
+ const runTransformer = useCallback2(async (attachmentId, file2, transformer) => {
15726
+ setProcessingState((prev) => new Map(prev).set(attachmentId, { status: "processing" }));
15727
+ try {
15728
+ const chat = await getCurrentChat();
15729
+ const context = { chat };
15730
+ const transformedContent = await getTransformedContent(file2, transformer, context, (progress) => {
15731
+ setProcessingState((prev) => new Map(prev).set(attachmentId, {
15732
+ status: "processing",
15733
+ progress
15734
+ }));
15735
+ });
15736
+ setAttachments((prev) => prev.map(
15737
+ (a) => a.id === attachmentId ? { ...a, transformedContent } : a
15738
+ ));
15739
+ setProcessingState((prev) => new Map(prev).set(attachmentId, { status: "done" }));
15740
+ } catch (error46) {
15741
+ console.error(`[useFileUpload] Transformation failed for ${file2.name}:`, error46);
15742
+ setProcessingState((prev) => new Map(prev).set(attachmentId, { status: "error" }));
15743
+ }
15744
+ }, [getCurrentChat]);
15412
15745
  const handleFiles = useCallback2(async (files) => {
15413
15746
  const fileArray = Array.from(files);
15414
15747
  for (const file2 of fileArray) {
@@ -15423,21 +15756,30 @@ function useFileUpload({
15423
15756
  continue;
15424
15757
  }
15425
15758
  const preview = await generateImagePreview(file2);
15426
- setAttachments((prev) => [
15427
- ...prev,
15428
- {
15429
- id: v4_default(),
15430
- file: file2,
15431
- preview
15432
- }
15433
- ]);
15759
+ const attachmentId = v4_default();
15760
+ const attachment = {
15761
+ id: attachmentId,
15762
+ file: file2,
15763
+ preview
15764
+ };
15765
+ setAttachments((prev) => [...prev, attachment]);
15766
+ const transformer = findTransformer(file2.type, transformers);
15767
+ if (transformer) {
15768
+ runTransformer(attachmentId, file2, transformer);
15769
+ }
15434
15770
  }
15435
- }, [maxFileSize, acceptedTypes, strings]);
15771
+ }, [maxFileSize, acceptedTypes, strings, transformers, runTransformer]);
15436
15772
  const removeAttachment = useCallback2((id) => {
15437
15773
  setAttachments((prev) => prev.filter((a) => a.id !== id));
15774
+ setProcessingState((prev) => {
15775
+ const next = new Map(prev);
15776
+ next.delete(id);
15777
+ return next;
15778
+ });
15438
15779
  }, []);
15439
15780
  const clearAttachments = useCallback2(() => {
15440
15781
  setAttachments([]);
15782
+ setProcessingState(/* @__PURE__ */ new Map());
15441
15783
  }, []);
15442
15784
  const openFilePicker = useCallback2(() => {
15443
15785
  fileInputRef.current?.click();
@@ -15490,7 +15832,7 @@ function useFileUpload({
15490
15832
  }), [handleDragEnter, handleDragOver, handleDragLeave, handleDrop]);
15491
15833
  const DropZoneOverlay = useMemo(() => {
15492
15834
  if (!isDragging || !enabled) return null;
15493
- return /* @__PURE__ */ jsx6(
15835
+ return /* @__PURE__ */ jsx8(
15494
15836
  "div",
15495
15837
  {
15496
15838
  style: {
@@ -15505,7 +15847,7 @@ function useFileUpload({
15505
15847
  zIndex: 1010,
15506
15848
  pointerEvents: "none"
15507
15849
  },
15508
- children: /* @__PURE__ */ jsx6(
15850
+ children: /* @__PURE__ */ jsx8(
15509
15851
  "div",
15510
15852
  {
15511
15853
  style: {
@@ -15514,7 +15856,7 @@ function useFileUpload({
15514
15856
  borderRadius: "12px",
15515
15857
  boxShadow: theme.buttonShadow
15516
15858
  },
15517
- children: /* @__PURE__ */ jsx6("span", { style: { color: theme.primaryColor, fontWeight: 600, fontSize: "16px" }, children: strings.fileUpload.dropFilesHere })
15859
+ children: /* @__PURE__ */ jsx8("span", { style: { color: theme.primaryColor, fontWeight: 600, fontSize: "16px" }, children: strings.fileUpload.dropFilesHere })
15518
15860
  }
15519
15861
  )
15520
15862
  }
@@ -15527,6 +15869,7 @@ function useFileUpload({
15527
15869
  enabled,
15528
15870
  maxFileSize,
15529
15871
  acceptedTypes,
15872
+ processingState,
15530
15873
  fileInputRef,
15531
15874
  handleFiles,
15532
15875
  removeAttachment,
@@ -15544,7 +15887,7 @@ function useFileUpload({
15544
15887
 
15545
15888
  // src/hooks/useDropdownState.tsx
15546
15889
  import { useState as useState3, useCallback as useCallback3, useMemo as useMemo2 } from "react";
15547
- import { jsx as jsx7 } from "react/jsx-runtime";
15890
+ import { jsx as jsx9 } from "react/jsx-runtime";
15548
15891
  function useDropdownState(options = {}) {
15549
15892
  const { backdropZIndex = 1002, initialOpen = false } = options;
15550
15893
  const [isOpen, setIsOpen] = useState3(initialOpen);
@@ -15559,7 +15902,7 @@ function useDropdownState(options = {}) {
15559
15902
  }, []);
15560
15903
  const Backdrop = useMemo2(() => {
15561
15904
  if (!isOpen) return null;
15562
- return /* @__PURE__ */ jsx7(
15905
+ return /* @__PURE__ */ jsx9(
15563
15906
  "div",
15564
15907
  {
15565
15908
  onClick: close,
@@ -15584,7 +15927,7 @@ function useDropdownState(options = {}) {
15584
15927
  }
15585
15928
 
15586
15929
  // src/components/UseAIChatPanel.tsx
15587
- import { Fragment, jsx as jsx8, jsxs as jsxs5 } from "react/jsx-runtime";
15930
+ import { Fragment, jsx as jsx10, jsxs as jsxs7 } from "react/jsx-runtime";
15588
15931
  function getTextContent(content3) {
15589
15932
  if (typeof content3 === "string") {
15590
15933
  return content3;
@@ -15605,12 +15948,14 @@ function UseAIChatPanel({
15605
15948
  onLoadChat,
15606
15949
  onDeleteChat,
15607
15950
  onListChats,
15951
+ onGetChat,
15608
15952
  suggestions,
15609
15953
  availableAgents,
15610
15954
  defaultAgent,
15611
15955
  selectedAgent,
15612
15956
  onAgentChange,
15613
15957
  fileUploadConfig,
15958
+ fileProcessing,
15614
15959
  commands = [],
15615
15960
  onSaveCommand,
15616
15961
  onRenameCommand,
@@ -15632,6 +15977,7 @@ function UseAIChatPanel({
15632
15977
  fileError,
15633
15978
  enabled: fileUploadEnabled,
15634
15979
  acceptedTypes,
15980
+ processingState: fileProcessingState,
15635
15981
  fileInputRef,
15636
15982
  removeAttachment,
15637
15983
  clearAttachments,
@@ -15640,6 +15986,7 @@ function UseAIChatPanel({
15640
15986
  getDropZoneProps,
15641
15987
  DropZoneOverlay
15642
15988
  } = useFileUpload({
15989
+ getCurrentChat: onGetChat ?? (async () => null),
15643
15990
  config: fileUploadConfig,
15644
15991
  disabled: loading,
15645
15992
  resetDependency: currentChatId
@@ -15711,7 +16058,7 @@ function UseAIChatPanel({
15711
16058
  chatHistoryDropdown.close();
15712
16059
  }
15713
16060
  };
15714
- return /* @__PURE__ */ jsxs5(
16061
+ return /* @__PURE__ */ jsxs7(
15715
16062
  "div",
15716
16063
  {
15717
16064
  onClick: () => {
@@ -15729,7 +16076,7 @@ function UseAIChatPanel({
15729
16076
  },
15730
16077
  children: [
15731
16078
  DropZoneOverlay,
15732
- /* @__PURE__ */ jsxs5(
16079
+ /* @__PURE__ */ jsxs7(
15733
16080
  "div",
15734
16081
  {
15735
16082
  style: {
@@ -15742,7 +16089,7 @@ function UseAIChatPanel({
15742
16089
  gap: "12px"
15743
16090
  },
15744
16091
  children: [
15745
- /* @__PURE__ */ jsx8("div", { style: { flex: 1, minWidth: 0, position: "relative" }, children: onListChats ? /* @__PURE__ */ jsxs5(
16092
+ /* @__PURE__ */ jsx10("div", { style: { flex: 1, minWidth: 0, position: "relative" }, children: onListChats ? /* @__PURE__ */ jsxs7(
15746
16093
  "button",
15747
16094
  {
15748
16095
  "data-testid": "chat-history-dropdown-button",
@@ -15775,7 +16122,7 @@ function UseAIChatPanel({
15775
16122
  e.currentTarget.style.background = "transparent";
15776
16123
  },
15777
16124
  children: [
15778
- /* @__PURE__ */ jsx8("span", { style: {
16125
+ /* @__PURE__ */ jsx10("span", { style: {
15779
16126
  overflow: "hidden",
15780
16127
  textOverflow: "ellipsis",
15781
16128
  whiteSpace: "nowrap",
@@ -15792,13 +16139,13 @@ function UseAIChatPanel({
15792
16139
  }
15793
16140
  return strings.header.newChat;
15794
16141
  })() }),
15795
- /* @__PURE__ */ jsx8("svg", { width: "12", height: "12", viewBox: "0 0 12 12", fill: "none", style: { flexShrink: 0 }, children: /* @__PURE__ */ jsx8("path", { d: "M3 4.5L6 7.5L9 4.5", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }) })
16142
+ /* @__PURE__ */ jsx10("svg", { width: "12", height: "12", viewBox: "0 0 12 12", fill: "none", style: { flexShrink: 0 }, children: /* @__PURE__ */ jsx10("path", { d: "M3 4.5L6 7.5L9 4.5", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }) })
15796
16143
  ]
15797
16144
  }
15798
- ) : /* @__PURE__ */ jsx8("div", { style: { fontSize: "14px", fontWeight: "600", color: theme.textColor, padding: "6px 8px" }, children: strings.header.aiAssistant }) }),
15799
- /* @__PURE__ */ jsxs5("div", { style: { display: "flex", alignItems: "center", gap: "4px" }, children: [
15800
- availableAgents && availableAgents.length > 1 && onAgentChange && /* @__PURE__ */ jsxs5("div", { style: { position: "relative" }, children: [
15801
- /* @__PURE__ */ jsxs5(
16145
+ ) : /* @__PURE__ */ jsx10("div", { style: { fontSize: "14px", fontWeight: "600", color: theme.textColor, padding: "6px 8px" }, children: strings.header.aiAssistant }) }),
16146
+ /* @__PURE__ */ jsxs7("div", { style: { display: "flex", alignItems: "center", gap: "4px" }, children: [
16147
+ availableAgents && availableAgents.length > 1 && onAgentChange && /* @__PURE__ */ jsxs7("div", { style: { position: "relative" }, children: [
16148
+ /* @__PURE__ */ jsxs7(
15802
16149
  "button",
15803
16150
  {
15804
16151
  "data-testid": "agent-selector",
@@ -15827,7 +16174,7 @@ function UseAIChatPanel({
15827
16174
  },
15828
16175
  title: "Select AI model",
15829
16176
  children: [
15830
- /* @__PURE__ */ jsx8("span", { style: {
16177
+ /* @__PURE__ */ jsx10("span", { style: {
15831
16178
  overflow: "hidden",
15832
16179
  textOverflow: "ellipsis",
15833
16180
  whiteSpace: "nowrap",
@@ -15836,11 +16183,11 @@ function UseAIChatPanel({
15836
16183
  const agent = availableAgents.find((a) => a.id === (selectedAgent ?? defaultAgent));
15837
16184
  return agent?.name || "AI";
15838
16185
  })() }),
15839
- /* @__PURE__ */ jsx8("svg", { width: "10", height: "10", viewBox: "0 0 12 12", fill: "none", style: { flexShrink: 0 }, children: /* @__PURE__ */ jsx8("path", { d: "M3 4.5L6 7.5L9 4.5", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }) })
16186
+ /* @__PURE__ */ jsx10("svg", { width: "10", height: "10", viewBox: "0 0 12 12", fill: "none", style: { flexShrink: 0 }, children: /* @__PURE__ */ jsx10("path", { d: "M3 4.5L6 7.5L9 4.5", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }) })
15840
16187
  ]
15841
16188
  }
15842
16189
  ),
15843
- agentDropdown.isOpen && /* @__PURE__ */ jsx8(
16190
+ agentDropdown.isOpen && /* @__PURE__ */ jsx10(
15844
16191
  "div",
15845
16192
  {
15846
16193
  style: {
@@ -15860,7 +16207,7 @@ function UseAIChatPanel({
15860
16207
  },
15861
16208
  children: availableAgents.map((agent) => {
15862
16209
  const isSelected = agent.id === (selectedAgent ?? defaultAgent);
15863
- return /* @__PURE__ */ jsxs5(
16210
+ return /* @__PURE__ */ jsxs7(
15864
16211
  "div",
15865
16212
  {
15866
16213
  "data-testid": "agent-option",
@@ -15890,13 +16237,13 @@ function UseAIChatPanel({
15890
16237
  }
15891
16238
  },
15892
16239
  children: [
15893
- /* @__PURE__ */ jsxs5("div", { style: { flex: 1, minWidth: 0 }, children: [
15894
- /* @__PURE__ */ jsx8("div", { style: {
16240
+ /* @__PURE__ */ jsxs7("div", { style: { flex: 1, minWidth: 0 }, children: [
16241
+ /* @__PURE__ */ jsx10("div", { style: {
15895
16242
  fontSize: "13px",
15896
16243
  fontWeight: isSelected ? "600" : "500",
15897
16244
  color: isSelected ? theme.primaryColor : theme.textColor
15898
16245
  }, children: agent.name }),
15899
- agent.annotation && /* @__PURE__ */ jsx8("div", { style: {
16246
+ agent.annotation && /* @__PURE__ */ jsx10("div", { style: {
15900
16247
  fontSize: "11px",
15901
16248
  color: theme.secondaryTextColor,
15902
16249
  marginTop: "2px",
@@ -15905,7 +16252,7 @@ function UseAIChatPanel({
15905
16252
  whiteSpace: "nowrap"
15906
16253
  }, children: agent.annotation })
15907
16254
  ] }),
15908
- isSelected && /* @__PURE__ */ jsx8("svg", { width: "14", height: "14", viewBox: "0 0 14 14", fill: "none", style: { flexShrink: 0 }, children: /* @__PURE__ */ jsx8("path", { d: "M2 7L5.5 10.5L12 4", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }) })
16255
+ isSelected && /* @__PURE__ */ jsx10("svg", { width: "14", height: "14", viewBox: "0 0 14 14", fill: "none", style: { flexShrink: 0 }, children: /* @__PURE__ */ jsx10("path", { d: "M2 7L5.5 10.5L12 4", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }) })
15909
16256
  ]
15910
16257
  },
15911
16258
  agent.id
@@ -15914,7 +16261,7 @@ function UseAIChatPanel({
15914
16261
  }
15915
16262
  )
15916
16263
  ] }),
15917
- onNewChat && /* @__PURE__ */ jsx8(
16264
+ onNewChat && /* @__PURE__ */ jsx10(
15918
16265
  "button",
15919
16266
  {
15920
16267
  "data-testid": "new-chat-button",
@@ -15941,10 +16288,10 @@ function UseAIChatPanel({
15941
16288
  e.currentTarget.style.color = theme.secondaryTextColor;
15942
16289
  },
15943
16290
  title: strings.header.newChat,
15944
- children: /* @__PURE__ */ jsx8("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", children: /* @__PURE__ */ jsx8("path", { d: "M8 3.5V12.5M3.5 8H12.5", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round" }) })
16291
+ children: /* @__PURE__ */ jsx10("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", children: /* @__PURE__ */ jsx10("path", { d: "M8 3.5V12.5M3.5 8H12.5", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round" }) })
15945
16292
  }
15946
16293
  ),
15947
- onDeleteChat && messages.length > 0 && /* @__PURE__ */ jsx8(
16294
+ onDeleteChat && messages.length > 0 && /* @__PURE__ */ jsx10(
15948
16295
  "button",
15949
16296
  {
15950
16297
  "data-testid": "delete-chat-button",
@@ -15968,7 +16315,7 @@ function UseAIChatPanel({
15968
16315
  e.currentTarget.style.color = theme.secondaryTextColor;
15969
16316
  },
15970
16317
  title: strings.header.deleteChat,
15971
- children: /* @__PURE__ */ jsx8("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", children: /* @__PURE__ */ jsx8("path", { d: "M2 4H14M6.5 7V11M9.5 7V11M3 4L4 13C4 13.5304 4.21071 14.0391 4.58579 14.4142C4.96086 14.7893 5.46957 15 6 15H10C10.5304 15 11.0391 14.7893 11.4142 14.4142C11.7893 14.0391 12 13.5304 12 13L13 4M5.5 4V2.5C5.5 2.23478 5.60536 1.98043 5.79289 1.79289C5.98043 1.60536 6.23478 1.5 6.5 1.5H9.5C9.76522 1.5 10.0196 1.60536 10.2071 1.79289C10.3946 1.98043 10.5 2.23478 10.5 2.5V4", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }) })
16318
+ children: /* @__PURE__ */ jsx10("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", children: /* @__PURE__ */ jsx10("path", { d: "M2 4H14M6.5 7V11M9.5 7V11M3 4L4 13C4 13.5304 4.21071 14.0391 4.58579 14.4142C4.96086 14.7893 5.46957 15 6 15H10C10.5304 15 11.0391 14.7893 11.4142 14.4142C11.7893 14.0391 12 13.5304 12 13L13 4M5.5 4V2.5C5.5 2.23478 5.60536 1.98043 5.79289 1.79289C5.98043 1.60536 6.23478 1.5 6.5 1.5H9.5C9.76522 1.5 10.0196 1.60536 10.2071 1.79289C10.3946 1.98043 10.5 2.23478 10.5 2.5V4", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }) })
15972
16319
  }
15973
16320
  ),
15974
16321
  closeButton
@@ -15976,7 +16323,7 @@ function UseAIChatPanel({
15976
16323
  ]
15977
16324
  }
15978
16325
  ),
15979
- chatHistoryDropdown.isOpen && onListChats && /* @__PURE__ */ jsx8(
16326
+ chatHistoryDropdown.isOpen && onListChats && /* @__PURE__ */ jsx10(
15980
16327
  "div",
15981
16328
  {
15982
16329
  style: {
@@ -15993,7 +16340,7 @@ function UseAIChatPanel({
15993
16340
  flexDirection: "column",
15994
16341
  overflow: "hidden"
15995
16342
  },
15996
- children: /* @__PURE__ */ jsx8(
16343
+ children: /* @__PURE__ */ jsx10(
15997
16344
  "div",
15998
16345
  {
15999
16346
  style: {
@@ -16001,7 +16348,7 @@ function UseAIChatPanel({
16001
16348
  overflowY: "auto",
16002
16349
  padding: "8px"
16003
16350
  },
16004
- children: chatHistory.length === 0 ? /* @__PURE__ */ jsx8(
16351
+ children: chatHistory.length === 0 ? /* @__PURE__ */ jsx10(
16005
16352
  "div",
16006
16353
  {
16007
16354
  style: {
@@ -16010,9 +16357,9 @@ function UseAIChatPanel({
16010
16357
  padding: "32px 16px",
16011
16358
  fontSize: "13px"
16012
16359
  },
16013
- children: /* @__PURE__ */ jsx8("p", { style: { margin: 0 }, children: strings.chatHistory.noChatHistory })
16360
+ children: /* @__PURE__ */ jsx10("p", { style: { margin: 0 }, children: strings.chatHistory.noChatHistory })
16014
16361
  }
16015
- ) : chatHistory.map((chat) => /* @__PURE__ */ jsxs5(
16362
+ ) : chatHistory.map((chat) => /* @__PURE__ */ jsxs7(
16016
16363
  "div",
16017
16364
  {
16018
16365
  "data-testid": "chat-history-item",
@@ -16036,10 +16383,10 @@ function UseAIChatPanel({
16036
16383
  }
16037
16384
  },
16038
16385
  children: [
16039
- /* @__PURE__ */ jsx8("div", { style: { fontSize: "13px", fontWeight: "500", color: theme.textColor, marginBottom: "4px", overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }, children: chat.title || strings.header.newChat }),
16040
- /* @__PURE__ */ jsxs5("div", { style: { fontSize: "11px", color: theme.secondaryTextColor }, children: [
16386
+ /* @__PURE__ */ jsx10("div", { style: { fontSize: "13px", fontWeight: "500", color: theme.textColor, marginBottom: "4px", overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }, children: chat.title || strings.header.newChat }),
16387
+ /* @__PURE__ */ jsxs7("div", { style: { fontSize: "11px", color: theme.secondaryTextColor }, children: [
16041
16388
  new Date(chat.updatedAt).toLocaleDateString([], { month: "short", day: "numeric" }),
16042
- currentChatId === chat.id && /* @__PURE__ */ jsxs5("span", { style: {
16389
+ currentChatId === chat.id && /* @__PURE__ */ jsxs7("span", { style: {
16043
16390
  marginLeft: "8px",
16044
16391
  color: theme.primaryColor,
16045
16392
  fontWeight: "600"
@@ -16058,7 +16405,7 @@ function UseAIChatPanel({
16058
16405
  ),
16059
16406
  chatHistoryDropdown.Backdrop,
16060
16407
  agentDropdown.Backdrop,
16061
- /* @__PURE__ */ jsxs5(
16408
+ /* @__PURE__ */ jsxs7(
16062
16409
  "div",
16063
16410
  {
16064
16411
  style: {
@@ -16070,7 +16417,7 @@ function UseAIChatPanel({
16070
16417
  gap: "12px"
16071
16418
  },
16072
16419
  children: [
16073
- messages.length === 0 && /* @__PURE__ */ jsxs5(
16420
+ messages.length === 0 && /* @__PURE__ */ jsxs7(
16074
16421
  "div",
16075
16422
  {
16076
16423
  style: {
@@ -16081,12 +16428,12 @@ function UseAIChatPanel({
16081
16428
  gap: "20px"
16082
16429
  },
16083
16430
  children: [
16084
- /* @__PURE__ */ jsxs5("div", { style: { textAlign: "center", color: theme.secondaryTextColor, fontSize: "14px" }, children: [
16085
- /* @__PURE__ */ jsx8("p", { style: { margin: 0, fontSize: "32px", marginBottom: "12px" }, children: "\u{1F4AC}" }),
16086
- /* @__PURE__ */ jsx8("p", { style: { margin: 0 }, children: strings.emptyChat.startConversation }),
16087
- /* @__PURE__ */ jsx8("p", { style: { margin: "8px 0 0", fontSize: "12px" }, children: strings.emptyChat.askMeToHelp })
16431
+ /* @__PURE__ */ jsxs7("div", { style: { textAlign: "center", color: theme.secondaryTextColor, fontSize: "14px" }, children: [
16432
+ /* @__PURE__ */ jsx10("p", { style: { margin: 0, fontSize: "32px", marginBottom: "12px" }, children: "\u{1F4AC}" }),
16433
+ /* @__PURE__ */ jsx10("p", { style: { margin: 0 }, children: strings.emptyChat.startConversation }),
16434
+ /* @__PURE__ */ jsx10("p", { style: { margin: "8px 0 0", fontSize: "12px" }, children: strings.emptyChat.askMeToHelp })
16088
16435
  ] }),
16089
- displayedSuggestions.length > 0 && /* @__PURE__ */ jsx8(
16436
+ displayedSuggestions.length > 0 && /* @__PURE__ */ jsx10(
16090
16437
  "div",
16091
16438
  {
16092
16439
  style: {
@@ -16096,7 +16443,7 @@ function UseAIChatPanel({
16096
16443
  width: "100%",
16097
16444
  maxWidth: "320px"
16098
16445
  },
16099
- children: displayedSuggestions.map((suggestion, index2) => /* @__PURE__ */ jsx8(
16446
+ children: displayedSuggestions.map((suggestion, index2) => /* @__PURE__ */ jsx10(
16100
16447
  "button",
16101
16448
  {
16102
16449
  "data-testid": "chat-suggestion-button",
@@ -16140,7 +16487,7 @@ function UseAIChatPanel({
16140
16487
  ]
16141
16488
  }
16142
16489
  ),
16143
- messages.map((message) => /* @__PURE__ */ jsxs5(
16490
+ messages.map((message) => /* @__PURE__ */ jsxs7(
16144
16491
  "div",
16145
16492
  {
16146
16493
  "data-testid": `chat-message-${message.role}`,
@@ -16153,7 +16500,7 @@ function UseAIChatPanel({
16153
16500
  onMouseEnter: () => message.role === "user" && setHoveredMessageId(message.id),
16154
16501
  onMouseLeave: () => setHoveredMessageId(null),
16155
16502
  children: [
16156
- /* @__PURE__ */ jsxs5(
16503
+ /* @__PURE__ */ jsxs7(
16157
16504
  "div",
16158
16505
  {
16159
16506
  style: {
@@ -16161,7 +16508,7 @@ function UseAIChatPanel({
16161
16508
  maxWidth: "80%"
16162
16509
  },
16163
16510
  children: [
16164
- message.role === "user" && hoveredMessageId === message.id && onSaveCommand && !slashCommands.isSavingCommand(message.id) && /* @__PURE__ */ jsx8(
16511
+ message.role === "user" && hoveredMessageId === message.id && onSaveCommand && !slashCommands.isSavingCommand(message.id) && /* @__PURE__ */ jsx10(
16165
16512
  "button",
16166
16513
  {
16167
16514
  "data-testid": "save-command-button",
@@ -16197,14 +16544,14 @@ function UseAIChatPanel({
16197
16544
  e.currentTarget.style.transform = "scale(1)";
16198
16545
  e.currentTarget.style.boxShadow = "0 2px 6px rgba(0, 0, 0, 0.15)";
16199
16546
  },
16200
- children: /* @__PURE__ */ jsxs5("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
16201
- /* @__PURE__ */ jsx8("path", { d: "M19 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11l5 5v11a2 2 0 0 1-2 2z" }),
16202
- /* @__PURE__ */ jsx8("polyline", { points: "17 21 17 13 7 13 7 21" }),
16203
- /* @__PURE__ */ jsx8("polyline", { points: "7 3 7 8 15 8" })
16547
+ children: /* @__PURE__ */ jsxs7("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
16548
+ /* @__PURE__ */ jsx10("path", { d: "M19 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11l5 5v11a2 2 0 0 1-2 2z" }),
16549
+ /* @__PURE__ */ jsx10("polyline", { points: "17 21 17 13 7 13 7 21" }),
16550
+ /* @__PURE__ */ jsx10("polyline", { points: "7 3 7 8 15 8" })
16204
16551
  ] })
16205
16552
  }
16206
16553
  ),
16207
- /* @__PURE__ */ jsxs5(
16554
+ /* @__PURE__ */ jsxs7(
16208
16555
  "div",
16209
16556
  {
16210
16557
  "data-testid": "chat-message-content",
@@ -16219,7 +16566,7 @@ function UseAIChatPanel({
16219
16566
  wordWrap: "break-word"
16220
16567
  },
16221
16568
  children: [
16222
- message.role === "user" && hasFileContent(message.content) && /* @__PURE__ */ jsx8("div", { style: { display: "flex", flexWrap: "wrap", gap: "6px", marginBottom: "8px" }, children: message.content.filter((part) => part.type === "file").map((part, idx) => /* @__PURE__ */ jsx8(
16569
+ message.role === "user" && hasFileContent(message.content) && /* @__PURE__ */ jsx10("div", { style: { display: "flex", flexWrap: "wrap", gap: "6px", marginBottom: "8px" }, children: message.content.filter((part) => part.type === "file").map((part, idx) => /* @__PURE__ */ jsx10(
16223
16570
  FilePlaceholder,
16224
16571
  {
16225
16572
  name: part.file.name,
@@ -16227,7 +16574,7 @@ function UseAIChatPanel({
16227
16574
  },
16228
16575
  idx
16229
16576
  )) }),
16230
- message.role === "assistant" ? /* @__PURE__ */ jsx8(MarkdownContent, { content: getTextContent(message.content) }) : getTextContent(message.content)
16577
+ message.role === "assistant" ? /* @__PURE__ */ jsx10(MarkdownContent, { content: getTextContent(message.content) }) : getTextContent(message.content)
16231
16578
  ]
16232
16579
  }
16233
16580
  ),
@@ -16238,7 +16585,7 @@ function UseAIChatPanel({
16238
16585
  ]
16239
16586
  }
16240
16587
  ),
16241
- /* @__PURE__ */ jsx8(
16588
+ /* @__PURE__ */ jsx10(
16242
16589
  "div",
16243
16590
  {
16244
16591
  style: {
@@ -16257,14 +16604,14 @@ function UseAIChatPanel({
16257
16604
  },
16258
16605
  message.id
16259
16606
  )),
16260
- loading && /* @__PURE__ */ jsx8(
16607
+ loading && /* @__PURE__ */ jsx10(
16261
16608
  "div",
16262
16609
  {
16263
16610
  style: {
16264
16611
  display: "flex",
16265
16612
  alignItems: "flex-start"
16266
16613
  },
16267
- children: /* @__PURE__ */ jsx8(
16614
+ children: /* @__PURE__ */ jsx10(
16268
16615
  "div",
16269
16616
  {
16270
16617
  className: "markdown-content",
@@ -16277,19 +16624,41 @@ function UseAIChatPanel({
16277
16624
  color: theme.textColor,
16278
16625
  maxWidth: "80%"
16279
16626
  },
16280
- children: streamingText ? /* @__PURE__ */ jsx8(MarkdownContent, { content: streamingText }) : /* @__PURE__ */ jsxs5(Fragment, { children: [
16281
- /* @__PURE__ */ jsx8("span", { style: { opacity: 0.6 }, children: strings.input.thinking }),
16282
- /* @__PURE__ */ jsx8("span", { className: "dots", style: { marginLeft: "4px" }, children: "..." })
16627
+ children: streamingText ? /* @__PURE__ */ jsx10(MarkdownContent, { content: streamingText }) : fileProcessing && fileProcessing.status === "processing" ? /* @__PURE__ */ jsxs7("div", { children: [
16628
+ /* @__PURE__ */ jsx10("span", { style: { opacity: 0.6 }, children: strings.input.processingFile }),
16629
+ fileProcessing.progress != null && /* @__PURE__ */ jsxs7(Fragment, { children: [
16630
+ /* @__PURE__ */ jsxs7("span", { style: { opacity: 0.6, marginLeft: "4px" }, children: [
16631
+ Math.round(fileProcessing.progress),
16632
+ "%"
16633
+ ] }),
16634
+ /* @__PURE__ */ jsx10("div", { style: {
16635
+ marginTop: "6px",
16636
+ height: "4px",
16637
+ borderRadius: "2px",
16638
+ background: theme.borderColor,
16639
+ overflow: "hidden"
16640
+ }, children: /* @__PURE__ */ jsx10("div", { style: {
16641
+ height: "100%",
16642
+ width: `${fileProcessing.progress}%`,
16643
+ borderRadius: "2px",
16644
+ background: theme.primaryColor,
16645
+ transition: "width 0.3s ease"
16646
+ } }) })
16647
+ ] }),
16648
+ fileProcessing.progress == null && /* @__PURE__ */ jsx10("span", { className: "dots", style: { marginLeft: "4px" }, children: "..." })
16649
+ ] }) : /* @__PURE__ */ jsxs7(Fragment, { children: [
16650
+ /* @__PURE__ */ jsx10("span", { style: { opacity: 0.6 }, children: strings.input.thinking }),
16651
+ /* @__PURE__ */ jsx10("span", { className: "dots", style: { marginLeft: "4px" }, children: "..." })
16283
16652
  ] })
16284
16653
  }
16285
16654
  )
16286
16655
  }
16287
16656
  ),
16288
- /* @__PURE__ */ jsx8("div", { ref: messagesEndRef })
16657
+ /* @__PURE__ */ jsx10("div", { ref: messagesEndRef })
16289
16658
  ]
16290
16659
  }
16291
16660
  ),
16292
- /* @__PURE__ */ jsxs5(
16661
+ /* @__PURE__ */ jsxs7(
16293
16662
  "div",
16294
16663
  {
16295
16664
  style: {
@@ -16297,7 +16666,7 @@ function UseAIChatPanel({
16297
16666
  borderTop: `1px solid ${theme.borderColor}`
16298
16667
  },
16299
16668
  children: [
16300
- fileError && /* @__PURE__ */ jsx8(
16669
+ fileError && /* @__PURE__ */ jsx10(
16301
16670
  "div",
16302
16671
  {
16303
16672
  "data-testid": "file-error",
@@ -16312,7 +16681,7 @@ function UseAIChatPanel({
16312
16681
  children: fileError
16313
16682
  }
16314
16683
  ),
16315
- attachments.length > 0 && /* @__PURE__ */ jsx8(
16684
+ attachments.length > 0 && /* @__PURE__ */ jsx10(
16316
16685
  "div",
16317
16686
  {
16318
16687
  "data-testid": "file-attachments",
@@ -16322,18 +16691,19 @@ function UseAIChatPanel({
16322
16691
  gap: "8px",
16323
16692
  marginBottom: "8px"
16324
16693
  },
16325
- children: attachments.map((attachment) => /* @__PURE__ */ jsx8(
16694
+ children: attachments.map((attachment) => /* @__PURE__ */ jsx10(
16326
16695
  FileChip,
16327
16696
  {
16328
16697
  attachment,
16329
16698
  onRemove: () => removeAttachment(attachment.id),
16330
- disabled: loading
16699
+ disabled: loading,
16700
+ processingState: fileProcessingState.get(attachment.id)
16331
16701
  },
16332
16702
  attachment.id
16333
16703
  ))
16334
16704
  }
16335
16705
  ),
16336
- /* @__PURE__ */ jsxs5(
16706
+ /* @__PURE__ */ jsxs7(
16337
16707
  "div",
16338
16708
  {
16339
16709
  style: {
@@ -16345,18 +16715,19 @@ function UseAIChatPanel({
16345
16715
  },
16346
16716
  children: [
16347
16717
  slashCommands.AutocompleteComponent,
16348
- /* @__PURE__ */ jsx8(
16718
+ /* @__PURE__ */ jsx10(
16349
16719
  "input",
16350
16720
  {
16351
16721
  ref: fileInputRef,
16352
16722
  type: "file",
16353
16723
  multiple: true,
16724
+ "data-testid": "file-input",
16354
16725
  style: { display: "none" },
16355
16726
  onChange: handleFileInputChange,
16356
16727
  accept: acceptedTypes?.join(",")
16357
16728
  }
16358
16729
  ),
16359
- /* @__PURE__ */ jsx8(
16730
+ /* @__PURE__ */ jsx10(
16360
16731
  "textarea",
16361
16732
  {
16362
16733
  ref: textareaRef,
@@ -16384,7 +16755,7 @@ function UseAIChatPanel({
16384
16755
  }
16385
16756
  }
16386
16757
  ),
16387
- /* @__PURE__ */ jsxs5(
16758
+ /* @__PURE__ */ jsxs7(
16388
16759
  "div",
16389
16760
  {
16390
16761
  style: {
@@ -16394,7 +16765,7 @@ function UseAIChatPanel({
16394
16765
  padding: "4px 8px"
16395
16766
  },
16396
16767
  children: [
16397
- /* @__PURE__ */ jsx8("div", { style: { display: "flex", alignItems: "center", gap: "8px" }, children: fileUploadEnabled && /* @__PURE__ */ jsx8(
16768
+ /* @__PURE__ */ jsx10("div", { style: { display: "flex", alignItems: "center", gap: "8px" }, children: fileUploadEnabled && /* @__PURE__ */ jsx10(
16398
16769
  "button",
16399
16770
  {
16400
16771
  "data-testid": "file-picker-button",
@@ -16426,13 +16797,13 @@ function UseAIChatPanel({
16426
16797
  e.currentTarget.style.borderColor = theme.borderColor;
16427
16798
  },
16428
16799
  title: strings.fileUpload.attachFiles,
16429
- children: /* @__PURE__ */ jsxs5("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: [
16430
- /* @__PURE__ */ jsx8("line", { x1: "12", y1: "5", x2: "12", y2: "19" }),
16431
- /* @__PURE__ */ jsx8("line", { x1: "5", y1: "12", x2: "19", y2: "12" })
16800
+ children: /* @__PURE__ */ jsxs7("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: [
16801
+ /* @__PURE__ */ jsx10("line", { x1: "12", y1: "5", x2: "12", y2: "19" }),
16802
+ /* @__PURE__ */ jsx10("line", { x1: "5", y1: "12", x2: "19", y2: "12" })
16432
16803
  ] })
16433
16804
  }
16434
16805
  ) }),
16435
- /* @__PURE__ */ jsx8(
16806
+ /* @__PURE__ */ jsx10(
16436
16807
  "button",
16437
16808
  {
16438
16809
  "data-testid": "chat-send-button",
@@ -16453,9 +16824,9 @@ function UseAIChatPanel({
16453
16824
  height: "32px",
16454
16825
  transition: "all 0.2s"
16455
16826
  },
16456
- children: /* @__PURE__ */ jsxs5("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: [
16457
- /* @__PURE__ */ jsx8("line", { x1: "12", y1: "19", x2: "12", y2: "5" }),
16458
- /* @__PURE__ */ jsx8("polyline", { points: "5 12 12 5 19 12" })
16827
+ children: /* @__PURE__ */ jsxs7("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: [
16828
+ /* @__PURE__ */ jsx10("line", { x1: "12", y1: "19", x2: "12", y2: "5" }),
16829
+ /* @__PURE__ */ jsx10("polyline", { points: "5 12 12 5 19 12" })
16459
16830
  ] })
16460
16831
  }
16461
16832
  )
@@ -16468,7 +16839,7 @@ function UseAIChatPanel({
16468
16839
  ]
16469
16840
  }
16470
16841
  ),
16471
- /* @__PURE__ */ jsx8("style", { children: `
16842
+ /* @__PURE__ */ jsx10("style", { children: `
16472
16843
  /* Markdown content styles */
16473
16844
  .markdown-content > :first-child {
16474
16845
  margin-top: 0 !important;
@@ -16493,7 +16864,7 @@ function UseAIChatPanel({
16493
16864
  }
16494
16865
 
16495
16866
  // src/components/UseAIFloatingChatWrapper.tsx
16496
- import { Fragment as Fragment2, jsx as jsx9, jsxs as jsxs6 } from "react/jsx-runtime";
16867
+ import { Fragment as Fragment2, jsx as jsx11, jsxs as jsxs8 } from "react/jsx-runtime";
16497
16868
  function UseAIFloatingChatWrapper({
16498
16869
  isOpen,
16499
16870
  onClose,
@@ -16501,8 +16872,8 @@ function UseAIFloatingChatWrapper({
16501
16872
  }) {
16502
16873
  const theme = useTheme();
16503
16874
  if (!isOpen) return null;
16504
- return /* @__PURE__ */ jsxs6(Fragment2, { children: [
16505
- /* @__PURE__ */ jsx9(
16875
+ return /* @__PURE__ */ jsxs8(Fragment2, { children: [
16876
+ /* @__PURE__ */ jsx11(
16506
16877
  "div",
16507
16878
  {
16508
16879
  style: {
@@ -16518,7 +16889,7 @@ function UseAIFloatingChatWrapper({
16518
16889
  onClick: onClose
16519
16890
  }
16520
16891
  ),
16521
- /* @__PURE__ */ jsx9(
16892
+ /* @__PURE__ */ jsx11(
16522
16893
  "div",
16523
16894
  {
16524
16895
  style: {
@@ -16537,7 +16908,7 @@ function UseAIFloatingChatWrapper({
16537
16908
  children
16538
16909
  }
16539
16910
  ),
16540
- /* @__PURE__ */ jsx9("style", { children: `
16911
+ /* @__PURE__ */ jsx11("style", { children: `
16541
16912
  @keyframes fadeIn {
16542
16913
  from { opacity: 0; }
16543
16914
  to { opacity: 1; }
@@ -16557,7 +16928,7 @@ function UseAIFloatingChatWrapper({
16557
16928
  }
16558
16929
  function CloseButton({ onClick }) {
16559
16930
  const theme = useTheme();
16560
- return /* @__PURE__ */ jsx9(
16931
+ return /* @__PURE__ */ jsx11(
16561
16932
  "button",
16562
16933
  {
16563
16934
  "data-testid": "chat-close-button",
@@ -16592,7 +16963,7 @@ function CloseButton({ onClick }) {
16592
16963
 
16593
16964
  // src/components/UseAIChat.tsx
16594
16965
  import { createContext as createContext3, useContext as useContext3 } from "react";
16595
- import { jsx as jsx10 } from "react/jsx-runtime";
16966
+ import { jsx as jsx12 } from "react/jsx-runtime";
16596
16967
  var __UseAIChatContext = createContext3(null);
16597
16968
  function useChatUIContext() {
16598
16969
  const context = useContext3(__UseAIChatContext);
@@ -16616,34 +16987,36 @@ function UseAIChat({ floating = false }) {
16616
16987
  onLoadChat: ctx.history.load,
16617
16988
  onDeleteChat: ctx.history.delete,
16618
16989
  onListChats: ctx.history.list,
16990
+ onGetChat: ctx.history.get,
16619
16991
  suggestions: ctx.suggestions,
16620
16992
  availableAgents: ctx.agents.available,
16621
16993
  defaultAgent: ctx.agents.default,
16622
16994
  selectedAgent: ctx.agents.selected,
16623
16995
  onAgentChange: ctx.agents.set,
16624
16996
  fileUploadConfig: ctx.fileUploadConfig,
16997
+ fileProcessing: ctx.fileProcessing,
16625
16998
  commands: ctx.commands.list,
16626
16999
  onSaveCommand: ctx.commands.save,
16627
17000
  onRenameCommand: ctx.commands.rename,
16628
17001
  onDeleteCommand: ctx.commands.delete
16629
17002
  };
16630
17003
  if (floating) {
16631
- return /* @__PURE__ */ jsx10(
17004
+ return /* @__PURE__ */ jsx12(
16632
17005
  UseAIFloatingChatWrapper,
16633
17006
  {
16634
17007
  isOpen: ctx.ui.isOpen,
16635
17008
  onClose: () => ctx.ui.setOpen(false),
16636
- children: /* @__PURE__ */ jsx10(
17009
+ children: /* @__PURE__ */ jsx12(
16637
17010
  UseAIChatPanel,
16638
17011
  {
16639
17012
  ...chatPanelProps,
16640
- closeButton: /* @__PURE__ */ jsx10(CloseButton, { onClick: () => ctx.ui.setOpen(false) })
17013
+ closeButton: /* @__PURE__ */ jsx12(CloseButton, { onClick: () => ctx.ui.setOpen(false) })
16641
17014
  }
16642
17015
  )
16643
17016
  }
16644
17017
  );
16645
17018
  }
16646
- return /* @__PURE__ */ jsx10(UseAIChatPanel, { ...chatPanelProps });
17019
+ return /* @__PURE__ */ jsx12(UseAIChatPanel, { ...chatPanelProps });
16647
17020
  }
16648
17021
 
16649
17022
  // ../../node_modules/.bun/engine.io-parser@5.2.3/node_modules/engine.io-parser/build/esm/commons.js
@@ -20202,12 +20575,18 @@ var UseAIClient = class {
20202
20575
  return { type: "text", text: part.text };
20203
20576
  } else if (part.type === "image") {
20204
20577
  return { type: "image", url: part.url };
20205
- } else {
20578
+ } else if (part.type === "file") {
20206
20579
  return {
20207
20580
  type: "file",
20208
20581
  url: part.url,
20209
20582
  mimeType: part.mimeType
20210
20583
  };
20584
+ } else {
20585
+ return {
20586
+ type: "transformed_file",
20587
+ text: part.text,
20588
+ originalFile: part.originalFile
20589
+ };
20211
20590
  }
20212
20591
  });
20213
20592
  }
@@ -33245,7 +33624,8 @@ var LocalStorageChatRepository = class {
33245
33624
  title: options?.title,
33246
33625
  messages: [],
33247
33626
  createdAt: now,
33248
- updatedAt: now
33627
+ updatedAt: now,
33628
+ metadata: options?.metadata
33249
33629
  };
33250
33630
  await this.enforceMaxChatsLimit();
33251
33631
  await this.saveChat(chat);
@@ -33329,6 +33709,14 @@ var LocalStorageChatRepository = class {
33329
33709
  throw new Error(`Failed to clear all chats: ${error46 instanceof Error ? error46.message : "Unknown error"}`);
33330
33710
  }
33331
33711
  }
33712
+ async updateMetadata(id, metadata, overwrite = false) {
33713
+ const chat = await this.loadChat(id);
33714
+ if (!chat) {
33715
+ throw new Error(`Chat not found: ${id}`);
33716
+ }
33717
+ chat.metadata = overwrite ? metadata : { ...chat.metadata, ...metadata };
33718
+ await this.saveChat(chat);
33719
+ }
33332
33720
  getChatKey(id) {
33333
33721
  return `${STORAGE_KEY_PREFIX}${id}`;
33334
33722
  }
@@ -33367,36 +33755,12 @@ var LocalStorageChatRepository = class {
33367
33755
  }
33368
33756
  };
33369
33757
 
33370
- // src/fileUpload/EmbedFileUploadBackend.ts
33371
- var EmbedFileUploadBackend = class {
33372
- /**
33373
- * Converts a File to a base64 data URL.
33374
- *
33375
- * @param file - The File object to convert
33376
- * @returns Promise resolving to a base64 data URL (e.g., "data:image/png;base64,...")
33377
- * @throws Error if file reading fails
33378
- */
33379
- async prepareForSend(file2) {
33380
- return new Promise((resolve, reject) => {
33381
- const reader = new FileReader();
33382
- reader.onload = () => {
33383
- if (typeof reader.result === "string") {
33384
- resolve(reader.result);
33385
- } else {
33386
- reject(new Error("Failed to read file as data URL"));
33387
- }
33388
- };
33389
- reader.onerror = () => {
33390
- reject(new Error(`Failed to read file: ${file2.name}`));
33391
- };
33392
- reader.readAsDataURL(file2);
33393
- });
33394
- }
33395
- };
33396
-
33397
33758
  // src/hooks/useChatManagement.ts
33398
33759
  import { useState as useState5, useCallback as useCallback4, useRef as useRef5, useEffect as useEffect5 } from "react";
33399
33760
  var CHAT_TITLE_MAX_LENGTH = 50;
33761
+ function deepEquals(a, b) {
33762
+ return JSON.stringify(a) === JSON.stringify(b);
33763
+ }
33400
33764
  function generateChatTitle(message) {
33401
33765
  return message.length > CHAT_TITLE_MAX_LENGTH ? message.substring(0, CHAT_TITLE_MAX_LENGTH) + "..." : message;
33402
33766
  }
@@ -33427,7 +33791,11 @@ function transformMessagesToClientFormat(uiMessages) {
33427
33791
  }
33428
33792
  function useChatManagement({
33429
33793
  repository,
33430
- clientRef
33794
+ clientRef,
33795
+ onSendMessage,
33796
+ setOpen,
33797
+ connected,
33798
+ loading
33431
33799
  }) {
33432
33800
  const [currentChatId, setCurrentChatId] = useState5(null);
33433
33801
  const [pendingChatId, setPendingChatId] = useState5(null);
@@ -33460,18 +33828,18 @@ function useChatManagement({
33460
33828
  const loadedMessages = await loadChatMessages(chatId);
33461
33829
  setMessages(loadedMessages);
33462
33830
  }, [loadChatMessages]);
33463
- const createNewChat = useCallback4(async () => {
33831
+ const createNewChat = useCallback4(async (options) => {
33464
33832
  console.log("[ChatManagement] createNewChat called - currentChatId:", currentChatId, "pendingChatId:", pendingChatId, "messages.length:", messages.length);
33465
33833
  if (pendingChatId && messages.length === 0) {
33466
- console.log("[ChatManagement] Pending chat is already blank, not creating new chat");
33467
- return pendingChatId;
33468
- }
33469
- if (currentChatId && !pendingChatId && messages.length === 0) {
33470
- console.log("[ChatManagement] Current chat is already blank, not creating new chat");
33471
- return currentChatId;
33834
+ const existingChat = await repository.loadChat(pendingChatId);
33835
+ const optionsMatch = existingChat && existingChat.title === options?.title && deepEquals(existingChat.metadata, options?.metadata);
33836
+ if (optionsMatch) {
33837
+ console.log("[ChatManagement] Last created chat has matching options, reusing:", pendingChatId);
33838
+ return pendingChatId;
33839
+ }
33472
33840
  }
33473
33841
  console.log("[ChatManagement] Creating new chat...");
33474
- const chatId = await repository.createChat();
33842
+ const chatId = await repository.createChat(options);
33475
33843
  setPendingChatId(chatId);
33476
33844
  setMessages([]);
33477
33845
  if (clientRef.current) {
@@ -33516,6 +33884,22 @@ function useChatManagement({
33516
33884
  }
33517
33885
  }
33518
33886
  }, [currentChatId, repository]);
33887
+ const getCurrentChat = useCallback4(async () => {
33888
+ const chatId = pendingChatId || currentChatId;
33889
+ if (!chatId) return null;
33890
+ const chat = await repository.loadChat(chatId);
33891
+ if (chat?.metadata) {
33892
+ chat.metadata = Object.freeze({ ...chat.metadata });
33893
+ }
33894
+ return chat;
33895
+ }, [pendingChatId, currentChatId, repository]);
33896
+ const updateMetadata = useCallback4(async (metadata, overwrite = false) => {
33897
+ const chatId = pendingChatId || currentChatId;
33898
+ if (!chatId) {
33899
+ throw new Error("No active chat");
33900
+ }
33901
+ await repository.updateMetadata(chatId, metadata, overwrite);
33902
+ }, [pendingChatId, currentChatId, repository]);
33519
33903
  const activatePendingChat = useCallback4(() => {
33520
33904
  if (!pendingChatId) return null;
33521
33905
  console.log("[ChatManagement] Activating pending chat:", pendingChatId);
@@ -33534,7 +33918,7 @@ function useChatManagement({
33534
33918
  console.error("[ChatManagement] Chat not found:", chatId);
33535
33919
  return false;
33536
33920
  }
33537
- const { generateMessageId: generateMessageId2 } = await import("./types-INERONQV.js");
33921
+ const { generateMessageId: generateMessageId2 } = await import("./types-STDS67SG.js");
33538
33922
  chat.messages.push({
33539
33923
  id: generateMessageId2(),
33540
33924
  role: "user",
@@ -33570,7 +33954,7 @@ function useChatManagement({
33570
33954
  console.error("[ChatManagement] Chat not found:", currentChatIdValue);
33571
33955
  return;
33572
33956
  }
33573
- const { generateMessageId: generateMessageId2 } = await import("./types-INERONQV.js");
33957
+ const { generateMessageId: generateMessageId2 } = await import("./types-STDS67SG.js");
33574
33958
  chat.messages.push({
33575
33959
  id: generateMessageId2(),
33576
33960
  role: "assistant",
@@ -33627,6 +34011,70 @@ function useChatManagement({
33627
34011
  }
33628
34012
  }, [currentChatId, pendingChatId, createNewChat, repository, loadChatMessages, clientRef]);
33629
34013
  const displayedChatId = pendingChatId || currentChatId;
34014
+ const pendingMessagesRef = useRef5([]);
34015
+ const isProcessingQueueRef = useRef5(false);
34016
+ const loadingRef = useRef5(loading);
34017
+ useEffect5(() => {
34018
+ loadingRef.current = loading;
34019
+ }, [loading]);
34020
+ const processMessageQueue = useCallback4(async () => {
34021
+ if (isProcessingQueueRef.current || pendingMessagesRef.current.length === 0 || !onSendMessage) {
34022
+ return;
34023
+ }
34024
+ isProcessingQueueRef.current = true;
34025
+ while (pendingMessagesRef.current.length > 0) {
34026
+ const { message, options } = pendingMessagesRef.current.shift();
34027
+ const { newChat = false, attachments = [], openChat = true, metadata } = options ?? {};
34028
+ if (newChat) {
34029
+ await createNewChat({ metadata });
34030
+ }
34031
+ const fileAttachments = await Promise.all(
34032
+ attachments.map(async (file2) => {
34033
+ let preview;
34034
+ if (file2.type.startsWith("image/")) {
34035
+ preview = await new Promise((resolve) => {
34036
+ const reader = new FileReader();
34037
+ reader.onload = () => resolve(typeof reader.result === "string" ? reader.result : void 0);
34038
+ reader.onerror = () => resolve(void 0);
34039
+ reader.readAsDataURL(file2);
34040
+ });
34041
+ }
34042
+ return {
34043
+ id: crypto.randomUUID(),
34044
+ file: file2,
34045
+ preview
34046
+ };
34047
+ })
34048
+ );
34049
+ await onSendMessage(message, fileAttachments.length > 0 ? fileAttachments : void 0);
34050
+ if (openChat && setOpen) {
34051
+ setOpen(true);
34052
+ }
34053
+ await new Promise((resolve) => {
34054
+ const checkLoading = () => {
34055
+ setTimeout(() => {
34056
+ if (!loadingRef.current) {
34057
+ resolve();
34058
+ } else {
34059
+ checkLoading();
34060
+ }
34061
+ }, 100);
34062
+ };
34063
+ checkLoading();
34064
+ });
34065
+ }
34066
+ isProcessingQueueRef.current = false;
34067
+ }, [onSendMessage, createNewChat, setOpen]);
34068
+ const sendMessage = useCallback4(async (message, options) => {
34069
+ if (!onSendMessage) {
34070
+ throw new Error("sendMessage is not available (onSendMessage callback not provided)");
34071
+ }
34072
+ if (!connected) {
34073
+ throw new Error("Not connected to UseAI server");
34074
+ }
34075
+ pendingMessagesRef.current.push({ message, options });
34076
+ await processMessageQueue();
34077
+ }, [onSendMessage, connected, processMessageQueue]);
33630
34078
  return {
33631
34079
  currentChatId,
33632
34080
  pendingChatId,
@@ -33641,6 +34089,9 @@ function useChatManagement({
33641
34089
  saveUserMessage,
33642
34090
  saveAIResponse,
33643
34091
  reloadMessages,
34092
+ sendMessage,
34093
+ getCurrentChat,
34094
+ updateMetadata,
33644
34095
  currentChatIdSnapshot,
33645
34096
  pendingChatIdSnapshot
33646
34097
  };
@@ -34022,7 +34473,7 @@ function usePromptState({
34022
34473
  }
34023
34474
 
34024
34475
  // src/providers/useAIProvider.tsx
34025
- import { Fragment as Fragment3, jsx as jsx11, jsxs as jsxs7 } from "react/jsx-runtime";
34476
+ import { Fragment as Fragment3, jsx as jsx13, jsxs as jsxs9 } from "react/jsx-runtime";
34026
34477
  var __UseAIContext = createContext4(null);
34027
34478
  var hasWarnedAboutMissingProvider = false;
34028
34479
  var noOpContextValue = {
@@ -34052,6 +34503,11 @@ var noOpContextValue = {
34052
34503
  },
34053
34504
  list: async () => [],
34054
34505
  clear: async () => {
34506
+ },
34507
+ sendMessage: async () => {
34508
+ },
34509
+ get: async () => null,
34510
+ updateMetadata: async () => {
34055
34511
  }
34056
34512
  },
34057
34513
  agents: {
@@ -34091,7 +34547,8 @@ function UseAIProvider({
34091
34547
  renderChat = true,
34092
34548
  theme: customTheme,
34093
34549
  strings: customStrings,
34094
- visibleAgentIds
34550
+ visibleAgentIds,
34551
+ onOpenChange
34095
34552
  }) {
34096
34553
  const fileUploadConfig = fileUploadConfigProp === false ? void 0 : fileUploadConfigProp ?? DEFAULT_FILE_UPLOAD_CONFIG;
34097
34554
  const theme = { ...defaultTheme, ...customTheme };
@@ -34099,12 +34556,18 @@ function UseAIProvider({
34099
34556
  const [connected, setConnected] = useState10(false);
34100
34557
  const [isChatOpen, setIsChatOpen] = useState10(false);
34101
34558
  const [loading, setLoading] = useState10(false);
34559
+ const [fileProcessingState, setFileProcessingState] = useState10(null);
34560
+ const handleSetChatOpen = useCallback9((open) => {
34561
+ setIsChatOpen(open);
34562
+ onOpenChange?.(open);
34563
+ }, [onOpenChange]);
34102
34564
  const [streamingText, setStreamingText] = useState10("");
34103
34565
  const streamingChatIdRef = useRef9(null);
34104
34566
  const clientRef = useRef9(null);
34105
34567
  const repositoryRef = useRef9(
34106
34568
  chatRepository || new LocalStorageChatRepository()
34107
34569
  );
34570
+ const handleSendMessageRef = useRef9(null);
34108
34571
  const {
34109
34572
  registerTools,
34110
34573
  unregisterTools,
@@ -34126,9 +34589,18 @@ function UseAIProvider({
34126
34589
  clientRef,
34127
34590
  connected
34128
34591
  });
34592
+ const stableSendMessage = useCallback9(async (message, attachments) => {
34593
+ if (handleSendMessageRef.current) {
34594
+ await handleSendMessageRef.current(message, attachments);
34595
+ }
34596
+ }, []);
34129
34597
  const chatManagement = useChatManagement({
34130
34598
  repository: repositoryRef.current,
34131
- clientRef
34599
+ clientRef,
34600
+ onSendMessage: stableSendMessage,
34601
+ setOpen: handleSetChatOpen,
34602
+ connected,
34603
+ loading
34132
34604
  });
34133
34605
  const {
34134
34606
  currentChatId,
@@ -34142,7 +34614,10 @@ function UseAIProvider({
34142
34614
  clearCurrentChat,
34143
34615
  activatePendingChat,
34144
34616
  saveUserMessage,
34145
- saveAIResponse
34617
+ saveAIResponse,
34618
+ sendMessage,
34619
+ getCurrentChat,
34620
+ updateMetadata
34146
34621
  } = chatManagement;
34147
34622
  const {
34148
34623
  availableAgents,
@@ -34283,7 +34758,6 @@ function UseAIProvider({
34283
34758
  let persistedContent = message;
34284
34759
  let multimodalContent;
34285
34760
  if (attachments && attachments.length > 0) {
34286
- const backend = fileUploadConfig?.backend ?? new EmbedFileUploadBackend();
34287
34761
  const persistedParts = [];
34288
34762
  if (message.trim()) {
34289
34763
  persistedParts.push({ type: "text", text: message });
@@ -34299,35 +34773,39 @@ function UseAIProvider({
34299
34773
  });
34300
34774
  }
34301
34775
  persistedContent = persistedParts;
34302
- const contentParts = [];
34303
- if (message.trim()) {
34304
- contentParts.push({ type: "text", text: message });
34776
+ if (activeChatId) {
34777
+ await saveUserMessage(activeChatId, persistedContent);
34305
34778
  }
34306
- for (const attachment of attachments) {
34307
- try {
34308
- const url3 = await backend.prepareForSend(attachment.file);
34309
- if (attachment.file.type.startsWith("image/")) {
34310
- contentParts.push({ type: "image", url: url3 });
34311
- } else {
34312
- contentParts.push({
34313
- type: "file",
34314
- url: url3,
34315
- mimeType: attachment.file.type,
34316
- name: attachment.file.name
34317
- });
34779
+ setLoading(true);
34780
+ try {
34781
+ const fileContent = await processAttachments(attachments, {
34782
+ getCurrentChat,
34783
+ backend: fileUploadConfig?.backend,
34784
+ transformers: fileUploadConfig?.transformers,
34785
+ onFileProgress: (_fileId, state) => {
34786
+ setFileProcessingState(state);
34318
34787
  }
34319
- } catch (error46) {
34320
- console.error("[Provider] Failed to prepare file for send:", error46);
34788
+ });
34789
+ multimodalContent = [];
34790
+ if (message.trim()) {
34791
+ multimodalContent.push({ type: "text", text: message });
34321
34792
  }
34793
+ multimodalContent.push(...fileContent);
34794
+ } catch (error46) {
34795
+ setLoading(false);
34796
+ throw error46;
34797
+ } finally {
34798
+ setFileProcessingState(null);
34322
34799
  }
34323
- multimodalContent = contentParts;
34324
- }
34325
- if (activeChatId) {
34326
- await saveUserMessage(activeChatId, persistedContent);
34800
+ } else {
34801
+ if (activeChatId) {
34802
+ await saveUserMessage(activeChatId, persistedContent);
34803
+ }
34804
+ setLoading(true);
34327
34805
  }
34328
- setLoading(true);
34329
34806
  await clientRef.current.sendPrompt(message, multimodalContent);
34330
- }, [activatePendingChat, currentChatId, saveUserMessage, fileUploadConfig]);
34807
+ }, [activatePendingChat, currentChatId, saveUserMessage, fileUploadConfig, getCurrentChat]);
34808
+ handleSendMessageRef.current = handleSendMessage;
34331
34809
  const value2 = {
34332
34810
  serverUrl,
34333
34811
  connected,
@@ -34347,7 +34825,10 @@ function UseAIProvider({
34347
34825
  load: loadChat,
34348
34826
  delete: deleteChat,
34349
34827
  list: listChats,
34350
- clear: clearCurrentChat
34828
+ clear: clearCurrentChat,
34829
+ sendMessage,
34830
+ get: getCurrentChat,
34831
+ updateMetadata
34351
34832
  },
34352
34833
  agents: {
34353
34834
  available: availableAgents,
@@ -34372,12 +34853,14 @@ function UseAIProvider({
34372
34853
  streamingText: effectiveStreamingText,
34373
34854
  suggestions: aggregatedSuggestions,
34374
34855
  fileUploadConfig,
34856
+ fileProcessing: fileProcessingState,
34375
34857
  history: {
34376
34858
  currentId: displayedChatId,
34377
34859
  create: createNewChat,
34378
34860
  load: loadChat,
34379
34861
  delete: deleteChat,
34380
- list: listChats
34862
+ list: listChats,
34863
+ get: getCurrentChat
34381
34864
  },
34382
34865
  agents: {
34383
34866
  available: availableAgents,
@@ -34393,7 +34876,7 @@ function UseAIProvider({
34393
34876
  },
34394
34877
  ui: {
34395
34878
  isOpen: isChatOpen,
34396
- setOpen: setIsChatOpen
34879
+ setOpen: handleSetChatOpen
34397
34880
  }
34398
34881
  };
34399
34882
  const isUIDisabled = CustomButton === null || CustomChat === null;
@@ -34416,6 +34899,7 @@ function UseAIProvider({
34416
34899
  selectedAgent,
34417
34900
  onAgentChange: setAgent,
34418
34901
  fileUploadConfig,
34902
+ fileProcessing: fileProcessingState,
34419
34903
  commands,
34420
34904
  onSaveCommand: saveCommand,
34421
34905
  onRenameCommand: renameCommand,
@@ -34423,21 +34907,21 @@ function UseAIProvider({
34423
34907
  };
34424
34908
  const renderDefaultChat = () => {
34425
34909
  if (isUIDisabled) return null;
34426
- return /* @__PURE__ */ jsx11(UseAIFloatingChatWrapper, { isOpen: isChatOpen, onClose: () => setIsChatOpen(false), children: /* @__PURE__ */ jsx11(
34910
+ return /* @__PURE__ */ jsx13(UseAIFloatingChatWrapper, { isOpen: isChatOpen, onClose: () => handleSetChatOpen(false), children: /* @__PURE__ */ jsx13(
34427
34911
  UseAIChatPanel,
34428
34912
  {
34429
34913
  ...chatPanelProps,
34430
- closeButton: /* @__PURE__ */ jsx11(CloseButton, { onClick: () => setIsChatOpen(false) })
34914
+ closeButton: /* @__PURE__ */ jsx13(CloseButton, { onClick: () => handleSetChatOpen(false) })
34431
34915
  }
34432
34916
  ) });
34433
34917
  };
34434
34918
  const renderCustomChat = () => {
34435
34919
  if (!CustomChat) return null;
34436
- return /* @__PURE__ */ jsx11(
34920
+ return /* @__PURE__ */ jsx13(
34437
34921
  CustomChat,
34438
34922
  {
34439
34923
  isOpen: isChatOpen,
34440
- onClose: () => setIsChatOpen(false),
34924
+ onClose: () => handleSetChatOpen(false),
34441
34925
  onSendMessage: handleSendMessage,
34442
34926
  messages,
34443
34927
  loading,
@@ -34452,18 +34936,18 @@ function UseAIProvider({
34452
34936
  };
34453
34937
  const renderBuiltInChat = () => {
34454
34938
  if (!renderChat) return null;
34455
- return /* @__PURE__ */ jsxs7(Fragment3, { children: [
34456
- ButtonComponent && /* @__PURE__ */ jsx11(
34939
+ return /* @__PURE__ */ jsxs9(Fragment3, { children: [
34940
+ ButtonComponent && /* @__PURE__ */ jsx13(
34457
34941
  ButtonComponent,
34458
34942
  {
34459
- onClick: () => setIsChatOpen(true),
34943
+ onClick: () => handleSetChatOpen(true),
34460
34944
  connected
34461
34945
  }
34462
34946
  ),
34463
34947
  hasCustomChat ? renderCustomChat() : renderDefaultChat()
34464
34948
  ] });
34465
34949
  };
34466
- return /* @__PURE__ */ jsx11(ThemeContext.Provider, { value: theme, children: /* @__PURE__ */ jsx11(StringsContext.Provider, { value: strings, children: /* @__PURE__ */ jsx11(__UseAIContext.Provider, { value: value2, children: /* @__PURE__ */ jsxs7(__UseAIChatContext.Provider, { value: chatUIContextValue, children: [
34950
+ return /* @__PURE__ */ jsx13(ThemeContext.Provider, { value: theme, children: /* @__PURE__ */ jsx13(StringsContext.Provider, { value: strings, children: /* @__PURE__ */ jsx13(__UseAIContext.Provider, { value: value2, children: /* @__PURE__ */ jsxs9(__UseAIChatContext.Provider, { value: chatUIContextValue, children: [
34467
34951
  children,
34468
34952
  renderBuiltInChat()
34469
34953
  ] }) }) }) });
@@ -34861,14 +35345,18 @@ export {
34861
35345
  UseAIFloatingButton,
34862
35346
  UseAIFloatingChatWrapper,
34863
35347
  UseAIProvider,
35348
+ clearTransformationCache,
34864
35349
  convertToolsToDefinitions,
34865
35350
  defaultStrings,
34866
35351
  defaultTheme,
34867
35352
  defineTool,
34868
35353
  executeDefinedTool,
35354
+ findTransformer,
34869
35355
  generateChatId,
34870
35356
  generateCommandId,
34871
35357
  generateMessageId,
35358
+ matchesMimeType,
35359
+ processAttachments,
34872
35360
  useAI,
34873
35361
  useAIContext,
34874
35362
  useAIWorkflow,