@iota-uz/sdk 0.4.9 → 0.4.11

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.
@@ -59,23 +59,25 @@ var init_IotaContext = __esm({
59
59
  IotaContext = React.createContext(null);
60
60
  }
61
61
  });
62
-
63
- // ui/src/bichat/hooks/useTranslation.ts
64
62
  function useTranslation() {
65
63
  const { locale } = useIotaContext();
66
- const t = (key2, params) => {
67
- let text = locale.translations[key2] || key2;
68
- if (params) {
69
- Object.keys(params).forEach((paramKey) => {
70
- const value = params[paramKey];
71
- text = text.replace(new RegExp(`{{${paramKey}}}`, "g"), String(value));
72
- });
73
- }
74
- return text;
75
- };
64
+ const { translations, language } = locale;
65
+ const t = React.useCallback(
66
+ (key2, params) => {
67
+ let text = translations[key2] || key2;
68
+ if (params) {
69
+ Object.keys(params).forEach((paramKey) => {
70
+ const value = params[paramKey];
71
+ text = text.replace(new RegExp(`{{${paramKey}}}`, "g"), String(value));
72
+ });
73
+ }
74
+ return text;
75
+ },
76
+ [translations]
77
+ );
76
78
  return {
77
79
  t,
78
- locale: locale.language
80
+ locale: language
79
81
  };
80
82
  }
81
83
  var init_useTranslation = __esm({
@@ -95,7 +97,7 @@ function ChartCard({ chartData }) {
95
97
  title,
96
98
  ": "
97
99
  ] }),
98
- t("Chart.NoData")
100
+ t("BiChat.Chart.NoData")
99
101
  ] }) });
100
102
  }
101
103
  const apexSeries = chartType === "pie" || chartType === "donut" ? series[0]?.data ?? [] : series.map((s) => ({ name: s.name, data: s.data }));
@@ -171,10 +173,10 @@ function ChartCard({ chartData }) {
171
173
  onClick: handleExportPNG,
172
174
  disabled: isExporting,
173
175
  className: "inline-flex items-center gap-1.5 rounded-lg px-2.5 py-1.5 text-xs font-medium text-gray-400 opacity-0 transition-all duration-150 hover:bg-gray-100 hover:text-gray-600 focus-visible:opacity-100 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500/50 group-hover/chart:opacity-100 disabled:opacity-50 dark:text-gray-500 dark:hover:bg-gray-700 dark:hover:text-gray-300",
174
- title: t("Chart.Download"),
175
- children: isExporting ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-gray-500 dark:text-gray-400", children: t("Chart.Exporting") }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
176
+ title: t("BiChat.Chart.Download"),
177
+ children: isExporting ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-gray-500 dark:text-gray-400", children: t("BiChat.Chart.Exporting") }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
176
178
  /* @__PURE__ */ jsxRuntime.jsx(react.DownloadSimple, { className: "h-3.5 w-3.5", weight: "bold" }),
177
- /* @__PURE__ */ jsxRuntime.jsx("span", { children: t("Chart.DownloadPNG") })
179
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: t("BiChat.Chart.DownloadPNG") })
178
180
  ] })
179
181
  }
180
182
  ) })
@@ -1506,8 +1508,8 @@ function useBranding() {
1506
1508
  appName: customBranding.appName || "BiChat",
1507
1509
  logoUrl: customBranding.logoUrl,
1508
1510
  welcome: {
1509
- title: customBranding.welcome?.title || t("Welcome.Title"),
1510
- description: customBranding.welcome?.description || t("Welcome.Description"),
1511
+ title: customBranding.welcome?.title || t("BiChat.Welcome.Title"),
1512
+ description: customBranding.welcome?.description || t("BiChat.Welcome.Description"),
1511
1513
  examplePrompts
1512
1514
  },
1513
1515
  theme: customBranding.theme
@@ -1523,7 +1525,7 @@ function ChatHeader({ session, onBack, readOnly, logoSlot, actionsSlot }) {
1523
1525
  {
1524
1526
  onClick: onBack,
1525
1527
  className: "cursor-pointer p-2 hover:bg-gray-100 dark:hover:bg-gray-700 active:bg-gray-200 dark:active:bg-gray-600 rounded-lg transition-colors duration-150 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500/50",
1526
- "aria-label": t("Chat.GoBack"),
1528
+ "aria-label": t("BiChat.Chat.GoBack"),
1527
1529
  children: /* @__PURE__ */ jsxRuntime.jsx("svg", { className: "w-5 h-5", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsxRuntime.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M15 19l-7-7 7-7" }) })
1528
1530
  }
1529
1531
  ) : null;
@@ -1533,7 +1535,7 @@ function ChatHeader({ session, onBack, readOnly, logoSlot, actionsSlot }) {
1533
1535
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3", children: [
1534
1536
  BackButton,
1535
1537
  Logo,
1536
- /* @__PURE__ */ jsxRuntime.jsx("h1", { className: "text-lg font-semibold text-[var(--bichat-text)]", children: t("Chat.NewChat") })
1538
+ /* @__PURE__ */ jsxRuntime.jsx("h1", { className: "text-lg font-semibold text-[var(--bichat-text)]", children: t("BiChat.Chat.NewChat") })
1537
1539
  ] }),
1538
1540
  actionsSlot && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-2", children: actionsSlot })
1539
1541
  ] }) });
@@ -1549,14 +1551,14 @@ function ChatHeader({ session, onBack, readOnly, logoSlot, actionsSlot }) {
1549
1551
  className: "w-4 h-4 text-[var(--bichat-primary)]",
1550
1552
  fill: "currentColor",
1551
1553
  viewBox: "0 0 20 20",
1552
- "aria-label": t("Chat.Pinned"),
1554
+ "aria-label": t("BiChat.Chat.Pinned"),
1553
1555
  children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M10 2a1 1 0 011 1v1.323l3.954 1.582 1.599-.8a1 1 0 01.894 1.79l-1.233.616 1.738 5.42a1 1 0 01-.285 1.05A3.989 3.989 0 0115 15a3.989 3.989 0 01-2.667-1.019 1 1 0 01-.285-1.05l1.715-5.349L11 6.477V16h2a1 1 0 110 2H7a1 1 0 110-2h2V6.477L6.237 7.582l1.715 5.349a1 1 0 01-.285 1.05A3.989 3.989 0 015 15a3.989 3.989 0 01-2.667-1.019 1 1 0 01-.285-1.05l1.738-5.42-1.233-.617a1 1 0 01.894-1.788l1.599.799L9 4.323V3a1 1 0 011-1z" })
1554
1556
  }
1555
1557
  )
1556
1558
  ] }),
1557
1559
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
1558
- readOnly && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "px-2 py-1 text-xs bg-amber-100 dark:bg-amber-900/30 text-amber-800 dark:text-amber-200 rounded", children: t("Chat.ReadOnly") }),
1559
- session.status === "archived" && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "px-2 py-1 text-xs bg-gray-200 dark:bg-gray-700 text-gray-700 dark:text-gray-300 rounded", children: t("Chat.Archived") }),
1560
+ readOnly && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "px-2 py-1 text-xs bg-amber-100 dark:bg-amber-900/30 text-amber-800 dark:text-amber-200 rounded", children: t("BiChat.Chat.ReadOnly") }),
1561
+ session.status === "archived" && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "px-2 py-1 text-xs bg-gray-200 dark:bg-gray-700 text-gray-700 dark:text-gray-300 rounded", children: t("BiChat.Chat.Archived") }),
1560
1562
  actionsSlot
1561
1563
  ] })
1562
1564
  ] }) });
@@ -1973,6 +1975,7 @@ function AttachmentGrid({
1973
1975
  var MemoizedAttachmentGrid = React__default.default.memo(AttachmentGrid);
1974
1976
  MemoizedAttachmentGrid.displayName = "AttachmentGrid";
1975
1977
  var AttachmentGrid_default = MemoizedAttachmentGrid;
1978
+ init_useTranslation();
1976
1979
  function ImageModal({
1977
1980
  isOpen,
1978
1981
  onClose,
@@ -1981,6 +1984,7 @@ function ImageModal({
1981
1984
  currentIndex = 0,
1982
1985
  onNavigate
1983
1986
  }) {
1987
+ const { t } = useTranslation();
1984
1988
  const [isImageLoaded, setIsImageLoaded] = React.useState(false);
1985
1989
  const [imageError, setImageError] = React.useState(false);
1986
1990
  const [retryKey, setRetryKey] = React.useState(0);
@@ -2033,7 +2037,7 @@ function ImageModal({
2033
2037
  {
2034
2038
  onClick: onClose,
2035
2039
  className: "cursor-pointer flex items-center justify-center w-8 h-8 rounded-md bg-gray-100 hover:bg-gray-200 dark:bg-gray-800 dark:hover:bg-gray-700 text-gray-500 hover:text-gray-900 dark:text-gray-400 dark:hover:text-white transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-gray-400",
2036
- "aria-label": "Close modal",
2040
+ "aria-label": t("BiChat.Image.Close"),
2037
2041
  type: "button",
2038
2042
  children: /* @__PURE__ */ jsxRuntime.jsx(react.X, { size: 18, weight: "bold" })
2039
2043
  }
@@ -2049,11 +2053,11 @@ function ImageModal({
2049
2053
  children: [
2050
2054
  !isImageLoaded && !imageError && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute inset-0 flex items-center justify-center pointer-events-none", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-center gap-3", children: [
2051
2055
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-8 h-8 border-2 border-gray-300 dark:border-gray-700 border-t-gray-500 dark:border-t-gray-400 rounded-full animate-spin" }),
2052
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs text-gray-400 dark:text-gray-500", children: "Loading" })
2056
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs text-gray-400 dark:text-gray-500", children: t("BiChat.Loading") })
2053
2057
  ] }) }),
2054
2058
  imageError && /* @__PURE__ */ jsxRuntime.jsxs("div", { role: "alert", className: "flex flex-col items-center justify-center text-center max-w-xs", children: [
2055
2059
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-center w-16 h-16 rounded-2xl bg-gray-100 dark:bg-gray-800 border border-gray-200 dark:border-gray-700 mb-5", children: /* @__PURE__ */ jsxRuntime.jsx(react.ImageBroken, { size: 28, className: "text-gray-400 dark:text-gray-500", weight: "duotone" }) }),
2056
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-medium text-gray-700 dark:text-gray-300 mb-1", children: "Failed to load image" }),
2060
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-medium text-gray-700 dark:text-gray-300 mb-1", children: t("BiChat.Image.FailedToLoad") }),
2057
2061
  /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-gray-400 dark:text-gray-500 mb-5 truncate max-w-full", children: attachment.filename }),
2058
2062
  /* @__PURE__ */ jsxRuntime.jsxs(
2059
2063
  "button",
@@ -2061,10 +2065,10 @@ function ImageModal({
2061
2065
  type: "button",
2062
2066
  onClick: handleRetry,
2063
2067
  className: "cursor-pointer inline-flex items-center gap-2 px-4 py-2 text-sm font-medium text-gray-700 dark:text-gray-200 bg-white dark:bg-gray-800 hover:bg-gray-50 dark:hover:bg-gray-700 border border-gray-200 dark:border-gray-700 rounded-lg transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-gray-400",
2064
- "aria-label": "Retry loading image",
2068
+ "aria-label": t("BiChat.Image.Retry"),
2065
2069
  children: [
2066
2070
  /* @__PURE__ */ jsxRuntime.jsx(react.ArrowClockwise, { size: 16, weight: "bold" }),
2067
- "Retry"
2071
+ t("BiChat.Retry.Label")
2068
2072
  ]
2069
2073
  }
2070
2074
  )
@@ -2098,7 +2102,7 @@ function ImageModal({
2098
2102
  "transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-gray-400",
2099
2103
  canNavigatePrev && isImageLoaded && !imageError ? "cursor-pointer bg-white/90 hover:bg-white dark:bg-gray-800/90 dark:hover:bg-gray-700 text-gray-700 hover:text-gray-900 dark:text-gray-300 dark:hover:text-white shadow-sm" : "bg-white/40 dark:bg-gray-800/40 text-gray-300 dark:text-gray-700 cursor-not-allowed"
2100
2104
  ].join(" "),
2101
- "aria-label": "Previous image",
2105
+ "aria-label": t("BiChat.Image.Previous"),
2102
2106
  type: "button",
2103
2107
  children: /* @__PURE__ */ jsxRuntime.jsx(react.CaretLeft, { size: 20, weight: "bold" })
2104
2108
  }
@@ -2114,7 +2118,7 @@ function ImageModal({
2114
2118
  "transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-gray-400",
2115
2119
  canNavigateNext && isImageLoaded && !imageError ? "cursor-pointer bg-white/90 hover:bg-white dark:bg-gray-800/90 dark:hover:bg-gray-700 text-gray-700 hover:text-gray-900 dark:text-gray-300 dark:hover:text-white shadow-sm" : "bg-white/40 dark:bg-gray-800/40 text-gray-300 dark:text-gray-700 cursor-not-allowed"
2116
2120
  ].join(" "),
2117
- "aria-label": "Next image",
2121
+ "aria-label": t("BiChat.Image.Next"),
2118
2122
  type: "button",
2119
2123
  children: /* @__PURE__ */ jsxRuntime.jsx(react.CaretRight, { size: 20, weight: "bold" })
2120
2124
  }
@@ -2361,7 +2365,7 @@ function UserMessage({
2361
2365
  onClick: handleCopyClick,
2362
2366
  className: `cursor-pointer ${classes.actionButton} ${isCopied ? "text-green-600 dark:text-green-400" : ""}`,
2363
2367
  "aria-label": "Copy message",
2364
- title: isCopied ? t("Message.Copied") : t("Message.Copy"),
2368
+ title: isCopied ? t("BiChat.Message.Copied") : t("BiChat.Message.Copy"),
2365
2369
  children: isCopied ? /* @__PURE__ */ jsxRuntime.jsx(react.Check, { size: 14, weight: "bold" }) : /* @__PURE__ */ jsxRuntime.jsx(react.Copy, { size: 14, weight: "regular" })
2366
2370
  }
2367
2371
  ),
@@ -2603,8 +2607,10 @@ function DownloadCard({ artifact }) {
2603
2607
  }
2604
2608
  );
2605
2609
  }
2610
+ init_useTranslation();
2606
2611
  function InlineQuestionForm({ pendingQuestion }) {
2607
2612
  const { handleSubmitQuestionAnswers, handleRejectPendingQuestion, loading } = useChatMessaging();
2613
+ const { t } = useTranslation();
2608
2614
  const [currentStep, setCurrentStep] = React.useState(0);
2609
2615
  const [answers, setAnswers] = React.useState({});
2610
2616
  const [otherTexts, setOtherTexts] = React.useState({});
@@ -2707,11 +2713,11 @@ function InlineQuestionForm({ pendingQuestion }) {
2707
2713
  const options = currentQuestion.options || [];
2708
2714
  const isOtherSelected = currentAnswer?.customText !== void 0;
2709
2715
  const canProceed = isCurrentAnswerValid();
2710
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "animate-slide-up rounded-2xl border border-primary-200 dark:border-primary-800/50 bg-gradient-to-b from-primary-50/80 to-white dark:from-primary-950/30 dark:to-gray-900/80 shadow-sm overflow-hidden", children: /* @__PURE__ */ jsxRuntime.jsxs("form", { onSubmit: handleSubmit, children: [
2716
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "animate-slide-up rounded-2xl border border-gray-200 dark:border-gray-700/50 bg-gradient-to-b from-primary-50/80 to-white dark:from-primary-950/30 dark:to-gray-900/80 shadow-sm overflow-hidden", children: /* @__PURE__ */ jsxRuntime.jsxs("form", { onSubmit: handleSubmit, children: [
2711
2717
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2.5 px-4 pt-4 pb-3", children: [
2712
2718
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-center w-7 h-7 rounded-lg bg-primary-100 dark:bg-primary-900/40", children: /* @__PURE__ */ jsxRuntime.jsx(react.ChatCircleDots, { className: "w-4 h-4 text-primary-600 dark:text-primary-400", weight: "fill" }) }),
2713
2719
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 min-w-0", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
2714
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs font-semibold uppercase tracking-wide text-primary-600 dark:text-primary-400", children: "Input needed" }),
2720
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs font-semibold uppercase tracking-wide text-primary-600 dark:text-primary-400", children: t("BiChat.InlineQuestion.InputNeeded") }),
2715
2721
  totalSteps > 1 && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-[11px] tabular-nums text-gray-400 dark:text-gray-500", children: [
2716
2722
  currentStep + 1,
2717
2723
  "/",
@@ -2725,7 +2731,7 @@ function InlineQuestionForm({ pendingQuestion }) {
2725
2731
  onClick: handleRejectPendingQuestion,
2726
2732
  disabled: loading,
2727
2733
  className: "cursor-pointer p-1 rounded-md text-gray-400 dark:text-gray-500 hover:text-gray-600 dark:hover:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-800 transition-colors disabled:opacity-40",
2728
- "aria-label": "Dismiss",
2734
+ "aria-label": t("BiChat.InlineQuestion.Dismiss"),
2729
2735
  children: /* @__PURE__ */ jsxRuntime.jsx(react.X, { size: 16, weight: "bold" })
2730
2736
  }
2731
2737
  )
@@ -2747,7 +2753,7 @@ function InlineQuestionForm({ pendingQuestion }) {
2747
2753
  }) }),
2748
2754
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "px-4 pb-3", children: [
2749
2755
  /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-[15px] leading-relaxed text-gray-800 dark:text-gray-200", children: currentQuestion.text }),
2750
- isMultiSelect && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-1 text-xs text-gray-400 dark:text-gray-500", children: "Select all that apply" })
2756
+ isMultiSelect && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-1 text-xs text-gray-400 dark:text-gray-500", children: t("BiChat.InlineQuestion.SelectAllThatApply") })
2751
2757
  ] }),
2752
2758
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "px-4 pb-2 space-y-1.5", children: [
2753
2759
  options.map((option) => {
@@ -2826,18 +2832,17 @@ function InlineQuestionForm({ pendingQuestion }) {
2826
2832
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: [
2827
2833
  "text-sm transition-colors duration-150",
2828
2834
  isOtherSelected ? "text-gray-900 dark:text-gray-100 font-medium" : "text-gray-700 dark:text-gray-300"
2829
- ].join(" "), children: "Other" })
2835
+ ].join(" "), children: t("BiChat.InlineQuestion.OtherOption") })
2830
2836
  ]
2831
2837
  }
2832
2838
  ),
2833
- isOtherSelected && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pl-8 pr-1 pb-1 animate-slide-up", children: /* @__PURE__ */ jsxRuntime.jsx(
2839
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pl-8 pr-1 pb-1", children: /* @__PURE__ */ jsxRuntime.jsx(
2834
2840
  "input",
2835
2841
  {
2836
2842
  type: "text",
2837
2843
  value: currentOtherText,
2838
2844
  onChange: (e) => handleOtherTextChange(e.target.value),
2839
- placeholder: "Type your answer...",
2840
- autoFocus: true,
2845
+ placeholder: t("BiChat.InlineQuestion.TypeYourAnswer"),
2841
2846
  className: "w-full px-3 py-2 text-sm border border-gray-200 dark:border-gray-700 rounded-lg bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100 placeholder:text-gray-400 dark:placeholder:text-gray-500 focus:outline-none focus:ring-2 focus:ring-primary-500/40 focus:border-primary-400 dark:focus:border-primary-600 transition-shadow"
2842
2847
  }
2843
2848
  ) })
@@ -2851,7 +2856,7 @@ function InlineQuestionForm({ pendingQuestion }) {
2851
2856
  className: "cursor-pointer flex items-center gap-1 px-2.5 py-1.5 text-sm text-gray-500 dark:text-gray-400 hover:text-gray-700 dark:hover:text-gray-200 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-800 transition-colors",
2852
2857
  children: [
2853
2858
  /* @__PURE__ */ jsxRuntime.jsx(react.ArrowLeft, { size: 14, weight: "bold" }),
2854
- "Back"
2859
+ t("BiChat.InlineQuestion.Back")
2855
2860
  ]
2856
2861
  }
2857
2862
  ) }),
@@ -2866,10 +2871,10 @@ function InlineQuestionForm({ pendingQuestion }) {
2866
2871
  canProceed ? "cursor-pointer bg-primary-600 hover:bg-primary-700 active:bg-primary-800 text-white shadow-sm hover:shadow" : "bg-gray-100 dark:bg-gray-800 text-gray-400 dark:text-gray-600 cursor-not-allowed"
2867
2872
  ].join(" "),
2868
2873
  children: isLastStep ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
2869
- "Submit",
2874
+ t("BiChat.Submit"),
2870
2875
  /* @__PURE__ */ jsxRuntime.jsx(react.PaperPlaneTilt, { size: 14, weight: "fill" })
2871
2876
  ] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
2872
- "Next",
2877
+ t("BiChat.InlineQuestion.Next"),
2873
2878
  /* @__PURE__ */ jsxRuntime.jsx(react.ArrowRight, { size: 14, weight: "bold" })
2874
2879
  ] })
2875
2880
  }
@@ -3038,13 +3043,13 @@ function ToolCard({ tool }) {
3038
3043
  children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "overflow-hidden min-h-0", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "px-3 pb-3 pt-1 space-y-2", children: [
3039
3044
  tool.arguments && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg bg-[#1a1b26] dark:bg-gray-950 overflow-hidden ring-1 ring-gray-800/10 dark:ring-white/5", children: [
3040
3045
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between px-3 py-1.5 bg-[#1e1f2e] dark:bg-gray-900/80 border-b border-white/5", children: [
3041
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px] uppercase tracking-wider font-medium text-gray-500", children: t("Slash.DebugArguments") }),
3046
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px] uppercase tracking-wider font-medium text-gray-500", children: t("BiChat.Slash.DebugArguments") }),
3042
3047
  /* @__PURE__ */ jsxRuntime.jsx(
3043
3048
  CopyPill,
3044
3049
  {
3045
3050
  text: tool.arguments,
3046
- label: t("Slash.DebugCopyTrace"),
3047
- copiedLabel: t("Slash.DebugCopied")
3051
+ label: t("BiChat.Slash.DebugCopyTrace"),
3052
+ copiedLabel: t("BiChat.Slash.DebugCopied")
3048
3053
  }
3049
3054
  )
3050
3055
  ] }),
@@ -3052,20 +3057,20 @@ function ToolCard({ tool }) {
3052
3057
  ] }),
3053
3058
  tool.result && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg bg-[#1a1b26] dark:bg-gray-950 overflow-hidden ring-1 ring-gray-800/10 dark:ring-white/5", children: [
3054
3059
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between px-3 py-1.5 bg-[#1e1f2e] dark:bg-gray-900/80 border-b border-white/5", children: [
3055
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px] uppercase tracking-wider font-medium text-gray-500", children: t("Slash.DebugResult") }),
3060
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px] uppercase tracking-wider font-medium text-gray-500", children: t("BiChat.Slash.DebugResult") }),
3056
3061
  /* @__PURE__ */ jsxRuntime.jsx(
3057
3062
  CopyPill,
3058
3063
  {
3059
3064
  text: tool.result,
3060
- label: t("Slash.DebugCopyTrace"),
3061
- copiedLabel: t("Slash.DebugCopied")
3065
+ label: t("BiChat.Slash.DebugCopyTrace"),
3066
+ copiedLabel: t("BiChat.Slash.DebugCopied")
3062
3067
  }
3063
3068
  )
3064
3069
  ] }),
3065
3070
  /* @__PURE__ */ jsxRuntime.jsx("pre", { className: "p-3 text-[11px] font-mono text-gray-300 overflow-x-auto max-h-60 overflow-y-auto whitespace-pre-wrap break-all leading-relaxed", children: tool.result })
3066
3071
  ] }),
3067
3072
  tool.error && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg bg-red-950/80 dark:bg-red-950/40 overflow-hidden ring-1 ring-red-800/20", children: [
3068
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-3 py-1.5 border-b border-red-800/20", children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px] uppercase tracking-wider font-medium text-red-400", children: t("Slash.DebugError") }) }),
3073
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-3 py-1.5 border-b border-red-800/20", children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px] uppercase tracking-wider font-medium text-red-400", children: t("BiChat.Slash.DebugError") }) }),
3069
3074
  /* @__PURE__ */ jsxRuntime.jsx("pre", { className: "p-3 text-[11px] font-mono text-red-300 overflow-x-auto whitespace-pre-wrap break-all leading-relaxed", children: tool.error })
3070
3075
  ] })
3071
3076
  ] }) })
@@ -3085,7 +3090,7 @@ function DebugPanel({ trace }) {
3085
3090
  metrics.push({
3086
3091
  icon: /* @__PURE__ */ jsxRuntime.jsx(react.Timer, { size: 14, weight: "duotone", className: "text-amber-600 dark:text-amber-400" }),
3087
3092
  value: formatGenerationDuration(trace.generationMs),
3088
- label: t("Slash.DebugGeneration"),
3093
+ label: t("BiChat.Slash.DebugGeneration"),
3089
3094
  accentBorder: "border-l-amber-400 dark:border-l-amber-500",
3090
3095
  accentBg: "bg-amber-50 dark:bg-amber-950/30"
3091
3096
  });
@@ -3094,7 +3099,7 @@ function DebugPanel({ trace }) {
3094
3099
  metrics.push({
3095
3100
  icon: /* @__PURE__ */ jsxRuntime.jsx(react.Lightning, { size: 14, weight: "fill", className: "text-orange-500 dark:text-orange-400" }),
3096
3101
  value: `${tokensPerSecond.toFixed(1)}/s`,
3097
- label: t("Slash.DebugTokensPerSecond"),
3102
+ label: t("BiChat.Slash.DebugTokensPerSecond"),
3098
3103
  accentBorder: "border-l-orange-400 dark:border-l-orange-500",
3099
3104
  accentBg: "bg-orange-50 dark:bg-orange-950/30"
3100
3105
  });
@@ -3104,21 +3109,21 @@ function DebugPanel({ trace }) {
3104
3109
  {
3105
3110
  icon: /* @__PURE__ */ jsxRuntime.jsx(react.Stack, { size: 14, weight: "duotone", className: "text-violet-600 dark:text-violet-400" }),
3106
3111
  value: trace.usage.totalTokens.toLocaleString(),
3107
- label: t("Slash.DebugTotalTokens"),
3112
+ label: t("BiChat.Slash.DebugTotalTokens"),
3108
3113
  accentBorder: "border-l-violet-400 dark:border-l-violet-500",
3109
3114
  accentBg: "bg-violet-50 dark:bg-violet-950/30"
3110
3115
  },
3111
3116
  {
3112
3117
  icon: /* @__PURE__ */ jsxRuntime.jsx(react.ArrowUp, { size: 14, weight: "bold", className: "text-blue-600 dark:text-blue-400" }),
3113
3118
  value: trace.usage.promptTokens.toLocaleString(),
3114
- label: t("Slash.DebugPromptTokens"),
3119
+ label: t("BiChat.Slash.DebugPromptTokens"),
3115
3120
  accentBorder: "border-l-blue-400 dark:border-l-blue-500",
3116
3121
  accentBg: "bg-blue-50 dark:bg-blue-950/30"
3117
3122
  },
3118
3123
  {
3119
3124
  icon: /* @__PURE__ */ jsxRuntime.jsx(react.ArrowDown, { size: 14, weight: "bold", className: "text-indigo-600 dark:text-indigo-400" }),
3120
3125
  value: trace.usage.completionTokens.toLocaleString(),
3121
- label: t("Slash.DebugCompletionTokens"),
3126
+ label: t("BiChat.Slash.DebugCompletionTokens"),
3122
3127
  accentBorder: "border-l-indigo-400 dark:border-l-indigo-500",
3123
3128
  accentBg: "bg-indigo-50 dark:bg-indigo-950/30"
3124
3129
  }
@@ -3127,7 +3132,7 @@ function DebugPanel({ trace }) {
3127
3132
  metrics.push({
3128
3133
  icon: /* @__PURE__ */ jsxRuntime.jsx(react.Database, { size: 14, weight: "duotone", className: "text-pink-600 dark:text-pink-400" }),
3129
3134
  value: trace.usage.cachedTokens.toLocaleString(),
3130
- label: t("Slash.DebugCachedTokens"),
3135
+ label: t("BiChat.Slash.DebugCachedTokens"),
3131
3136
  accentBorder: "border-l-pink-400 dark:border-l-pink-500",
3132
3137
  accentBg: "bg-pink-50 dark:bg-pink-950/30"
3133
3138
  });
@@ -3138,14 +3143,14 @@ function DebugPanel({ trace }) {
3138
3143
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between mb-4", children: [
3139
3144
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2.5", children: [
3140
3145
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-center w-6 h-6 rounded-lg bg-gray-100 dark:bg-gray-800", children: /* @__PURE__ */ jsxRuntime.jsx(react.Bug, { size: 14, weight: "duotone", className: "text-gray-500 dark:text-gray-400" }) }),
3141
- /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-[11px] uppercase tracking-widest font-semibold text-gray-400 dark:text-gray-500", children: t("Slash.DebugPanelTitle") })
3146
+ /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-[11px] uppercase tracking-widest font-semibold text-gray-400 dark:text-gray-500", children: t("BiChat.Slash.DebugPanelTitle") })
3142
3147
  ] }),
3143
3148
  hasData && trace && /* @__PURE__ */ jsxRuntime.jsx(
3144
3149
  CopyPill,
3145
3150
  {
3146
3151
  text: JSON.stringify(trace, null, 2),
3147
- label: t("Slash.DebugCopyTrace"),
3148
- copiedLabel: t("Slash.DebugCopied")
3152
+ label: t("BiChat.Slash.DebugCopyTrace"),
3153
+ copiedLabel: t("BiChat.Slash.DebugCopied")
3149
3154
  }
3150
3155
  )
3151
3156
  ] }),
@@ -3154,12 +3159,12 @@ function DebugPanel({ trace }) {
3154
3159
  trace.tools.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
3155
3160
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 mb-2.5", children: [
3156
3161
  /* @__PURE__ */ jsxRuntime.jsx(react.Wrench, { size: 13, weight: "duotone", className: "text-gray-400 dark:text-gray-500" }),
3157
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[11px] font-medium text-gray-500 dark:text-gray-400", children: t("Slash.DebugToolCalls") }),
3162
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[11px] font-medium text-gray-500 dark:text-gray-400", children: t("BiChat.Slash.DebugToolCalls") }),
3158
3163
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "px-1.5 py-0.5 rounded-full bg-gray-100 dark:bg-gray-800 text-[10px] font-mono font-medium text-gray-500 dark:text-gray-400 tabular-nums", children: trace.tools.length })
3159
3164
  ] }),
3160
3165
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-1.5", children: trace.tools.map((tool, idx) => /* @__PURE__ */ jsxRuntime.jsx(ToolCard, { tool }, `${tool.callId || tool.name}-${idx}`)) })
3161
3166
  ] })
3162
- ] }) : /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-gray-400 dark:text-gray-500 italic", children: t("Slash.DebugUnavailable") })
3167
+ ] }) : /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-gray-400 dark:text-gray-500 italic", children: t("BiChat.Slash.DebugUnavailable") })
3163
3168
  ] });
3164
3169
  }
3165
3170
 
@@ -3365,7 +3370,7 @@ function AssistantMessage({
3365
3370
  )
3366
3371
  }
3367
3372
  ),
3368
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium", children: t("Assistant.Explanation") })
3373
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium", children: t("BiChat.Assistant.Explanation") })
3369
3374
  ]
3370
3375
  }
3371
3376
  ),
@@ -3391,7 +3396,7 @@ function AssistantMessage({
3391
3396
  onClick: handleCopyClick,
3392
3397
  className: `cursor-pointer ${classes.actionButton} ${isCopied ? "text-green-600 dark:text-green-400" : ""}`,
3393
3398
  "aria-label": "Copy message",
3394
- title: isCopied ? t("Message.Copied") : t("Message.Copy"),
3399
+ title: isCopied ? t("BiChat.Message.Copied") : t("BiChat.Message.Copy"),
3395
3400
  children: isCopied ? /* @__PURE__ */ jsxRuntime.jsx(react.Check, { size: 14, weight: "bold" }) : /* @__PURE__ */ jsxRuntime.jsx(react.Copy, { size: 14, weight: "regular" })
3396
3401
  }
3397
3402
  ),
@@ -3485,7 +3490,7 @@ function SystemMessage({
3485
3490
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 px-4 pt-3 pb-2", children: [
3486
3491
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1.5 text-gray-400 dark:text-gray-500", children: [
3487
3492
  /* @__PURE__ */ jsxRuntime.jsx(react.ClockCounterClockwise, { size: 13, weight: "bold" }),
3488
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[11px] font-semibold uppercase tracking-wider", children: t("System.ConversationSummary") })
3493
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[11px] font-semibold uppercase tracking-wider", children: t("BiChat.System.ConversationSummary") })
3489
3494
  ] }),
3490
3495
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1" }),
3491
3496
  !hideActions && !hideTimestamp && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[11px] text-gray-400 dark:text-gray-500 tabular-nums", children: timestamp }),
@@ -3499,7 +3504,7 @@ function SystemMessage({
3499
3504
  ${isCopied ? "text-green-600 dark:text-green-400" : "text-gray-400 dark:text-gray-500 hover:text-gray-600 dark:hover:text-gray-300 hover:bg-gray-200/50 dark:hover:bg-gray-700/40"}
3500
3505
  `,
3501
3506
  "aria-label": "Copy message",
3502
- title: isCopied ? t("Message.Copied") : t("Message.Copy"),
3507
+ title: isCopied ? t("BiChat.Message.Copied") : t("BiChat.Message.Copy"),
3503
3508
  children: isCopied ? /* @__PURE__ */ jsxRuntime.jsx(react.Check, { size: 13, weight: "bold" }) : /* @__PURE__ */ jsxRuntime.jsx(react.Copy, { size: 13, weight: "regular" })
3504
3509
  }
3505
3510
  )
@@ -3517,7 +3522,7 @@ function SystemMessage({
3517
3522
  {
3518
3523
  fallback: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 text-sm text-gray-400 dark:text-gray-500 py-2", children: [
3519
3524
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-3.5 h-3.5 border-[1.5px] border-gray-300 dark:border-gray-600 border-t-transparent rounded-full animate-spin" }),
3520
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs", children: t("System.LoadingSummary") })
3525
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs", children: t("BiChat.System.LoadingSummary") })
3521
3526
  ] }),
3522
3527
  children: /* @__PURE__ */ jsxRuntime.jsx(MarkdownRenderer3, { content, sendDisabled: true })
3523
3528
  }
@@ -3534,7 +3539,7 @@ function SystemMessage({
3534
3539
  "aria-expanded": isExpanded,
3535
3540
  className: "cursor-pointer group/toggle inline-flex items-center gap-1 px-3 py-1 rounded-full text-[11px] font-medium text-gray-500 dark:text-gray-400 hover:text-gray-700 dark:hover:text-gray-200 hover:bg-gray-200/60 dark:hover:bg-gray-700/50 transition-colors duration-150",
3536
3541
  children: [
3537
- /* @__PURE__ */ jsxRuntime.jsx("span", { children: isExpanded ? t("System.ShowLess") : t("System.ShowMore") }),
3542
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: isExpanded ? t("BiChat.System.ShowLess") : t("BiChat.System.ShowMore") }),
3538
3543
  /* @__PURE__ */ jsxRuntime.jsx(
3539
3544
  react.CaretDown,
3540
3545
  {
@@ -3898,13 +3903,16 @@ var errorMessageVariants = {
3898
3903
  }
3899
3904
  }
3900
3905
  };
3901
- var DEFAULT_VERBS = [
3902
- "Thinking",
3903
- "Processing",
3904
- "Analyzing",
3905
- "Synthesizing",
3906
- "Computing",
3907
- "Working on it"
3906
+
3907
+ // ui/src/bichat/components/TypingIndicator.tsx
3908
+ init_useTranslation();
3909
+ var THINKING_KEYS = [
3910
+ "BiChat.Thinking.Thinking",
3911
+ "BiChat.Thinking.Processing",
3912
+ "BiChat.Thinking.Analyzing",
3913
+ "BiChat.Thinking.Synthesizing",
3914
+ "BiChat.Thinking.Computing",
3915
+ "BiChat.Thinking.WorkingOnIt"
3908
3916
  ];
3909
3917
  var prefersReducedMotion2 = () => {
3910
3918
  if (typeof window === "undefined") return false;
@@ -3918,10 +3926,15 @@ var getRandomVerb = (verbs, current) => {
3918
3926
  return available[Math.floor(Math.random() * available.length)];
3919
3927
  };
3920
3928
  function TypingIndicator({
3921
- verbs = DEFAULT_VERBS,
3929
+ verbs: verbsProp,
3922
3930
  rotationInterval = 3e3,
3923
3931
  className = ""
3924
3932
  }) {
3933
+ const { t } = useTranslation();
3934
+ const verbs = React.useMemo(() => {
3935
+ if (verbsProp) return verbsProp;
3936
+ return THINKING_KEYS.map((key2) => t(key2));
3937
+ }, [verbsProp, t]);
3925
3938
  const [verb, setVerb] = React.useState(() => verbs[Math.floor(Math.random() * verbs.length)]);
3926
3939
  React.useEffect(() => {
3927
3940
  if (prefersReducedMotion2()) return;
@@ -4106,8 +4119,8 @@ function MessageList({ renderUserTurn, renderAssistantTurn, thinkingVerbs, readO
4106
4119
  isCompacting && /* @__PURE__ */ jsxRuntime.jsx(
4107
4120
  CompactionDoodle_default,
4108
4121
  {
4109
- title: t("Slash.CompactingTitle"),
4110
- subtitle: t("Slash.CompactingSubtitle")
4122
+ title: t("BiChat.Slash.CompactingTitle"),
4123
+ subtitle: t("BiChat.Slash.CompactingSubtitle")
4111
4124
  }
4112
4125
  ),
4113
4126
  fetching && turns.length === 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-6", "aria-hidden": "true", children: [
@@ -4208,7 +4221,7 @@ var MessageInput = React.forwardRef(
4208
4221
  const [dropSuccess, setDropSuccess] = React.useState(false);
4209
4222
  const [pendingFileCount, setPendingFileCount] = React.useState(0);
4210
4223
  const [viewingImageIndex, setViewingImageIndex] = React.useState(null);
4211
- const placeholder = placeholderOverride || t("Input.Placeholder");
4224
+ const placeholder = placeholderOverride || t("BiChat.Input.Placeholder");
4212
4225
  const textareaRef = React.useRef(null);
4213
4226
  const fileInputRef = React.useRef(null);
4214
4227
  const containerRef = React.useRef(null);
@@ -4219,9 +4232,9 @@ var MessageInput = React.forwardRef(
4219
4232
  const commandQuery = message.trimStart().slice(1).split(/\s+/)[0]?.toLowerCase() || "";
4220
4233
  const slashCommands = React.useMemo(
4221
4234
  () => [
4222
- { name: "/clear", description: t("Slash.ClearDescription") },
4223
- { name: "/debug", description: t("Slash.DebugDescription") },
4224
- { name: "/compact", description: t("Slash.CompactDescription") }
4235
+ { name: "/clear", description: t("BiChat.Slash.ClearDescription") },
4236
+ { name: "/debug", description: t("BiChat.Slash.DebugDescription") },
4237
+ { name: "/compact", description: t("BiChat.Slash.CompactDescription") }
4225
4238
  ],
4226
4239
  [t]
4227
4240
  );
@@ -4511,12 +4524,12 @@ var MessageInput = React.forwardRef(
4511
4524
  onClearCommandError?.();
4512
4525
  },
4513
4526
  className: "cursor-pointer ml-2 p-1 hover:bg-red-100 dark:hover:bg-red-800 rounded transition-colors",
4514
- "aria-label": t("Input.DismissError"),
4527
+ "aria-label": t("BiChat.Input.DismissError"),
4515
4528
  children: /* @__PURE__ */ jsxRuntime.jsx(react.X, { size: 14 })
4516
4529
  }
4517
4530
  )
4518
4531
  ] }),
4519
- messageQueue.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mb-3 text-xs text-gray-500 dark:text-gray-400", children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "px-2.5 py-1 bg-primary-50 dark:bg-primary-900/30 text-primary-600 dark:text-primary-400 rounded font-medium", children: t("Input.MessagesQueued", { count: messageQueue.length }) }) }),
4532
+ messageQueue.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mb-3 text-xs text-gray-500 dark:text-gray-400", children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "px-2.5 py-1 bg-primary-50 dark:bg-primary-900/30 text-primary-600 dark:text-primary-400 rounded font-medium", children: t("BiChat.Input.MessagesQueued", { count: messageQueue.length }) }) }),
4520
4533
  debugMode && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mb-3 space-y-2 text-xs", children: [
4521
4534
  /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "inline-flex items-center gap-1.5 px-2.5 py-1 bg-amber-100 dark:bg-amber-900/40 text-amber-700 dark:text-amber-300 rounded-full font-medium text-[11px]", children: [
4522
4535
  /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "relative flex h-1.5 w-1.5", "aria-hidden": "true", children: [
@@ -4524,49 +4537,49 @@ var MessageInput = React.forwardRef(
4524
4537
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "relative inline-flex rounded-full h-1.5 w-1.5 bg-amber-500" })
4525
4538
  ] }),
4526
4539
  /* @__PURE__ */ jsxRuntime.jsx(react.Bug, { size: 12 }),
4527
- t("Slash.DebugBadge")
4540
+ t("BiChat.Slash.DebugBadge")
4528
4541
  ] }),
4529
4542
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-xl border border-gray-200/60 dark:border-gray-700/40 bg-gray-50/50 dark:bg-gray-800/30 p-3 space-y-3", children: [
4530
4543
  hasUsage ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-3 gap-1.5", children: [
4531
4544
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-center gap-1 py-2 rounded-lg bg-white dark:bg-gray-800/60 border border-gray-100 dark:border-gray-700/30", children: [
4532
4545
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1 text-[10px] text-gray-400 dark:text-gray-500", children: [
4533
4546
  /* @__PURE__ */ jsxRuntime.jsx(react.ArrowUp, { size: 10, weight: "bold", className: "text-blue-500 dark:text-blue-400" }),
4534
- t("Slash.DebugPromptTokens")
4547
+ t("BiChat.Slash.DebugPromptTokens")
4535
4548
  ] }),
4536
4549
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-mono font-semibold text-xs text-gray-900 dark:text-gray-100 tabular-nums", children: formatTokens(sessionPromptTokens) })
4537
4550
  ] }),
4538
4551
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-center gap-1 py-2 rounded-lg bg-white dark:bg-gray-800/60 border border-gray-100 dark:border-gray-700/30", children: [
4539
4552
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1 text-[10px] text-gray-400 dark:text-gray-500", children: [
4540
4553
  /* @__PURE__ */ jsxRuntime.jsx(react.ArrowDown, { size: 10, weight: "bold", className: "text-indigo-500 dark:text-indigo-400" }),
4541
- t("Slash.DebugCompletionTokens")
4554
+ t("BiChat.Slash.DebugCompletionTokens")
4542
4555
  ] }),
4543
4556
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-mono font-semibold text-xs text-gray-900 dark:text-gray-100 tabular-nums", children: formatTokens(sessionCompletionTokens) })
4544
4557
  ] }),
4545
4558
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-center gap-1 py-2 rounded-lg bg-white dark:bg-gray-800/60 border border-gray-100 dark:border-gray-700/30", children: [
4546
4559
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1 text-[10px] text-gray-400 dark:text-gray-500", children: [
4547
4560
  /* @__PURE__ */ jsxRuntime.jsx(react.Stack, { size: 10, weight: "bold", className: "text-violet-500 dark:text-violet-400" }),
4548
- t("Slash.DebugTotalTokens")
4561
+ t("BiChat.Slash.DebugTotalTokens")
4549
4562
  ] }),
4550
4563
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-mono font-semibold text-xs text-gray-900 dark:text-gray-100 tabular-nums", children: formatTokens(sessionTotalTokens) })
4551
4564
  ] })
4552
- ] }) : /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-[11px] text-gray-400 dark:text-gray-500 text-center py-1", children: t("Slash.DebugSessionUsageUnavailable") }),
4565
+ ] }) : /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-[11px] text-gray-400 dark:text-gray-500 text-center py-1", children: t("BiChat.Slash.DebugSessionUsageUnavailable") }),
4553
4566
  debugLimits && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-3 gap-1.5", children: [
4554
4567
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1 py-2 px-2 rounded-lg bg-white dark:bg-gray-800/60 border border-gray-100 dark:border-gray-700/30", children: [
4555
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px] text-gray-400 dark:text-gray-500", children: t("Slash.DebugPolicyMaxContextWindow") }),
4568
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px] text-gray-400 dark:text-gray-500", children: t("BiChat.Slash.DebugPolicyMaxContextWindow") }),
4556
4569
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-mono font-semibold text-xs text-gray-900 dark:text-gray-100 tabular-nums", children: formatTokens(policyMaxTokens) })
4557
4570
  ] }),
4558
4571
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1 py-2 px-2 rounded-lg bg-white dark:bg-gray-800/60 border border-gray-100 dark:border-gray-700/30", children: [
4559
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px] text-gray-400 dark:text-gray-500", children: t("Slash.DebugModelMaxContextWindow") }),
4572
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px] text-gray-400 dark:text-gray-500", children: t("BiChat.Slash.DebugModelMaxContextWindow") }),
4560
4573
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-mono font-semibold text-xs text-gray-900 dark:text-gray-100 tabular-nums", children: formatTokens(modelMaxTokens) })
4561
4574
  ] }),
4562
4575
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1 py-2 px-2 rounded-lg bg-white dark:bg-gray-800/60 border border-gray-100 dark:border-gray-700/30", children: [
4563
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px] text-gray-400 dark:text-gray-500", children: t("Slash.DebugEffectiveContextWindow") }),
4576
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px] text-gray-400 dark:text-gray-500", children: t("BiChat.Slash.DebugEffectiveContextWindow") }),
4564
4577
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-mono font-semibold text-xs text-gray-900 dark:text-gray-100 tabular-nums", children: formatTokens(effectiveMaxTokens) })
4565
4578
  ] })
4566
4579
  ] }),
4567
4580
  effectiveMaxTokens > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1.5", children: [
4568
4581
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between", children: [
4569
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px] text-gray-400 dark:text-gray-500", children: t("Slash.DebugContextUsage") }),
4582
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px] text-gray-400 dark:text-gray-500", children: t("BiChat.Slash.DebugContextUsage") }),
4570
4583
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
4571
4584
  /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "font-mono text-[10px] text-gray-400 dark:text-gray-500 tabular-nums", children: [
4572
4585
  formatTokens(latestPromptTokens),
@@ -4616,9 +4629,9 @@ var MessageInput = React.forwardRef(
4616
4629
  children: [
4617
4630
  isDragging && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute inset-0 z-10 bg-primary-50/95 dark:bg-primary-900/90 border-2 border-dashed border-primary-400 rounded-2xl flex items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-center gap-2", children: [
4618
4631
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-10 h-10 rounded-full bg-primary-100 dark:bg-primary-800 flex items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(react.Paperclip, { size: 20, className: "text-primary-600 dark:text-primary-400" }) }),
4619
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-primary-700 dark:text-primary-300 font-medium", children: t("Input.DropFiles") })
4632
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-primary-700 dark:text-primary-300 font-medium", children: t("BiChat.Input.DropFiles") })
4620
4633
  ] }) }),
4621
- dropSuccess && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute inset-0 z-10 bg-green-50/95 dark:bg-green-900/90 border-2 border-green-400 rounded-2xl flex items-center justify-center animate-pulse pointer-events-none", children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-green-700 dark:text-green-300 font-medium", children: t("Input.FilesAdded") }) }),
4634
+ dropSuccess && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute inset-0 z-10 bg-green-50/95 dark:bg-green-900/90 border-2 border-green-400 rounded-2xl flex items-center justify-center animate-pulse pointer-events-none", children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-green-700 dark:text-green-300 font-medium", children: t("BiChat.Input.FilesAdded") }) }),
4622
4635
  /* @__PURE__ */ jsxRuntime.jsxs(
4623
4636
  "div",
4624
4637
  {
@@ -4631,8 +4644,8 @@ var MessageInput = React.forwardRef(
4631
4644
  onClick: () => fileInputRef.current?.click(),
4632
4645
  disabled: loading || disabled || attachments.length >= maxFiles,
4633
4646
  className: "cursor-pointer flex-shrink-0 self-center p-2 text-gray-500 dark:text-gray-400 hover:text-gray-600 dark:hover:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700 rounded-lg transition-colors disabled:opacity-40 disabled:cursor-not-allowed",
4634
- "aria-label": t("Input.AttachFiles"),
4635
- title: t("Input.AttachFiles"),
4647
+ "aria-label": t("BiChat.Input.AttachFiles"),
4648
+ title: t("BiChat.Input.AttachFiles"),
4636
4649
  children: /* @__PURE__ */ jsxRuntime.jsx(react.Paperclip, { size: 20 })
4637
4650
  }
4638
4651
  ),
@@ -4645,7 +4658,7 @@ var MessageInput = React.forwardRef(
4645
4658
  multiple: true,
4646
4659
  onChange: handleFileInputChange,
4647
4660
  className: "hidden",
4648
- "aria-label": t("Input.FileInput")
4661
+ "aria-label": t("BiChat.Input.FileInput")
4649
4662
  }
4650
4663
  ),
4651
4664
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 self-stretch flex items-center", children: /* @__PURE__ */ jsxRuntime.jsx(
@@ -4675,7 +4688,7 @@ var MessageInput = React.forwardRef(
4675
4688
  rows: 1,
4676
4689
  disabled: loading || disabled,
4677
4690
  "aria-busy": loading,
4678
- "aria-label": t("Input.MessageInput")
4691
+ "aria-label": t("BiChat.Input.MessageInput")
4679
4692
  }
4680
4693
  ) }),
4681
4694
  /* @__PURE__ */ jsxRuntime.jsx(
@@ -4684,15 +4697,15 @@ var MessageInput = React.forwardRef(
4684
4697
  type: "submit",
4685
4698
  disabled: !canSubmit,
4686
4699
  className: "cursor-pointer flex-shrink-0 self-center p-2 rounded-lg bg-primary-600 hover:bg-primary-700 active:bg-primary-800 active:scale-95 text-white shadow-sm transition-all disabled:opacity-40 disabled:cursor-not-allowed disabled:hover:bg-primary-600",
4687
- "aria-label": loading ? t("Input.Processing") : t("Input.SendMessage"),
4700
+ "aria-label": loading ? t("BiChat.Input.Processing") : t("BiChat.Input.SendMessage"),
4688
4701
  children: loading ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-[18px] h-[18px] border-2 border-white/60 border-t-transparent rounded-full animate-spin" }) : /* @__PURE__ */ jsxRuntime.jsx(react.PaperPlaneRight, { size: 18, weight: "fill" })
4689
4702
  }
4690
4703
  )
4691
4704
  ]
4692
4705
  }
4693
4706
  ),
4694
- isFocused && !message && !loading && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "hidden sm:block absolute -bottom-5 left-14 text-[10px] text-gray-400 dark:text-gray-500 select-none animate-fade-in", children: t("Input.ShiftEnterHint") }),
4695
- isCommandListVisible && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute left-0 right-0 bottom-full mb-1.5 z-20 overflow-hidden rounded-lg border border-gray-200/70 bg-white/98 shadow-md backdrop-blur-xl dark:border-gray-700/70 dark:bg-gray-900/98 dark:shadow-black/20", children: filteredCommands.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx("ul", { role: "listbox", "aria-label": t("Slash.CommandsList"), className: "py-1 px-1", children: filteredCommands.map((command, index) => {
4707
+ isFocused && !message && !loading && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "hidden sm:block absolute -bottom-5 left-14 text-[10px] text-gray-400 dark:text-gray-500 select-none animate-fade-in", children: t("BiChat.Input.ShiftEnterHint") }),
4708
+ isCommandListVisible && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute left-0 right-0 bottom-full mb-1.5 z-20 overflow-hidden rounded-lg border border-gray-200/70 bg-white/98 shadow-md backdrop-blur-xl dark:border-gray-700/70 dark:bg-gray-900/98 dark:shadow-black/20", children: filteredCommands.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx("ul", { role: "listbox", "aria-label": t("BiChat.Slash.CommandsList"), className: "py-1 px-1", children: filteredCommands.map((command, index) => {
4696
4709
  const isActive = index === activeCommandIndex;
4697
4710
  return /* @__PURE__ */ jsxRuntime.jsxs(
4698
4711
  "li",
@@ -4718,7 +4731,7 @@ var MessageInput = React.forwardRef(
4718
4731
  },
4719
4732
  command.name
4720
4733
  );
4721
- }) }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-3 py-2.5 text-center", children: /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-[11px] text-gray-400 dark:text-gray-500", children: t("Slash.NoMatches") }) }) })
4734
+ }) }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-3 py-2.5 text-center", children: /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-[11px] text-gray-400 dark:text-gray-500", children: t("BiChat.Slash.NoMatches") }) }) })
4722
4735
  ]
4723
4736
  }
4724
4737
  ),
@@ -4742,37 +4755,25 @@ MessageInput.displayName = "MessageInput";
4742
4755
 
4743
4756
  // ui/src/bichat/components/WelcomeContent.tsx
4744
4757
  init_useTranslation();
4745
- var EXAMPLE_PROMPTS = [
4746
- {
4747
- category: "Data Analysis",
4748
- icon: react.ChartBar,
4749
- text: "Show me sales trends for the last quarter"
4750
- },
4751
- {
4752
- category: "Reports",
4753
- icon: react.FileText,
4754
- text: "Generate a summary of customer feedback"
4755
- },
4756
- {
4757
- category: "Insights",
4758
- icon: react.Lightbulb,
4759
- text: "What are the top performing products?"
4760
- }
4758
+ var PROMPT_DEFS = [
4759
+ { categoryKey: "Welcome.Prompt1Category", textKey: "Welcome.Prompt1Text", icon: react.ChartBar, defaultCategory: "OSAGO Portfolio", defaultText: "What is the total amount of accrued OSAGO premiums for the reporting period?" },
4760
+ { categoryKey: "Welcome.Prompt2Category", textKey: "Welcome.Prompt2Text", icon: react.FileText, defaultCategory: "Regional Analysis", defaultText: "Show me the top 5 regions by collected insurance premiums" },
4761
+ { categoryKey: "Welcome.Prompt3Category", textKey: "Welcome.Prompt3Text", icon: react.Lightbulb, defaultCategory: "Loss Analysis", defaultText: "Calculate the loss ratio across the entire OSAGO portfolio" }
4761
4762
  ];
4762
- var CATEGORY_STYLES = {
4763
- "Data Analysis": {
4763
+ var PROMPT_STYLES = [
4764
+ {
4764
4765
  badge: "bg-sky-50 text-sky-600 ring-sky-600/10 dark:bg-sky-400/10 dark:text-sky-400 dark:ring-sky-400/20",
4765
4766
  icon: "text-sky-500 dark:text-sky-400"
4766
4767
  },
4767
- Reports: {
4768
+ {
4768
4769
  badge: "bg-teal-50 text-teal-600 ring-teal-600/10 dark:bg-teal-400/10 dark:text-teal-400 dark:ring-teal-400/20",
4769
4770
  icon: "text-teal-500 dark:text-teal-400"
4770
4771
  },
4771
- Insights: {
4772
+ {
4772
4773
  badge: "bg-amber-50 text-amber-600 ring-amber-600/10 dark:bg-amber-400/10 dark:text-amber-400 dark:ring-amber-400/20",
4773
4774
  icon: "text-amber-500 dark:text-amber-400"
4774
4775
  }
4775
- };
4776
+ ];
4776
4777
  var containerVariants = {
4777
4778
  hidden: { opacity: 0 },
4778
4779
  visible: {
@@ -4814,6 +4815,10 @@ var reducedItemVariants = {
4814
4815
  }
4815
4816
  }
4816
4817
  };
4818
+ function tOr(t, key2, defaultValue) {
4819
+ const v = t(key2);
4820
+ return v !== key2 ? v : defaultValue;
4821
+ }
4817
4822
  function WelcomeContent({
4818
4823
  onPromptSelect,
4819
4824
  title,
@@ -4822,8 +4827,13 @@ function WelcomeContent({
4822
4827
  }) {
4823
4828
  const { t } = useTranslation();
4824
4829
  const shouldReduceMotion = framerMotion.useReducedMotion();
4825
- const resolvedTitle = title || t("Welcome.Title");
4826
- const resolvedDescription = description || t("Welcome.Description");
4830
+ const resolvedTitle = title || "";
4831
+ const resolvedDescription = description || "";
4832
+ const prompts = PROMPT_DEFS.map((def) => ({
4833
+ category: tOr(t, def.categoryKey, def.defaultCategory),
4834
+ text: tOr(t, def.textKey, def.defaultText),
4835
+ icon: def.icon
4836
+ }));
4827
4837
  const handlePromptClick = (prompt) => {
4828
4838
  if (onPromptSelect && !disabled) {
4829
4839
  onPromptSelect(prompt);
@@ -4839,15 +4849,7 @@ function WelcomeContent({
4839
4849
  initial: "hidden",
4840
4850
  animate: "visible",
4841
4851
  children: [
4842
- /* @__PURE__ */ jsxRuntime.jsx(
4843
- "div",
4844
- {
4845
- className: "pointer-events-none absolute inset-x-0 -top-8 flex justify-center overflow-hidden h-56",
4846
- "aria-hidden": true,
4847
- children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-[420px] h-[260px] -mt-16 rounded-full bg-primary-300/[0.08] blur-[80px] dark:bg-primary-400/[0.05]" })
4848
- }
4849
- ),
4850
- /* @__PURE__ */ jsxRuntime.jsx(
4852
+ resolvedTitle && /* @__PURE__ */ jsxRuntime.jsx(
4851
4853
  framerMotion.motion.h1,
4852
4854
  {
4853
4855
  className: "relative text-2xl sm:text-3xl font-semibold text-gray-900 dark:text-white mb-4",
@@ -4855,7 +4857,7 @@ function WelcomeContent({
4855
4857
  children: resolvedTitle
4856
4858
  }
4857
4859
  ),
4858
- /* @__PURE__ */ jsxRuntime.jsx(
4860
+ resolvedDescription && /* @__PURE__ */ jsxRuntime.jsx(
4859
4861
  framerMotion.motion.p,
4860
4862
  {
4861
4863
  className: "text-base text-gray-500 dark:text-gray-400 mb-10 max-w-2xl mx-auto leading-relaxed",
@@ -4866,11 +4868,11 @@ function WelcomeContent({
4866
4868
  /* @__PURE__ */ jsxRuntime.jsxs(framerMotion.motion.div, { variants: activeItemVariants, children: [
4867
4869
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-4 mb-5", children: [
4868
4870
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-px flex-1 bg-gradient-to-r from-transparent to-gray-200 dark:to-gray-700/70" }),
4869
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[11px] font-semibold uppercase tracking-[0.12em] text-gray-400 dark:text-gray-500 select-none", children: t("Welcome.QuickStart") }),
4871
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[11px] font-semibold uppercase tracking-[0.12em] text-gray-400 dark:text-gray-500 select-none", children: t("BiChat.Welcome.QuickStart") }),
4870
4872
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-px flex-1 bg-gradient-to-l from-transparent to-gray-200 dark:to-gray-700/70" })
4871
4873
  ] }),
4872
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid gap-3 sm:grid-cols-2 lg:grid-cols-3", children: EXAMPLE_PROMPTS.map((prompt, index) => {
4873
- const style = CATEGORY_STYLES[prompt.category];
4874
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid gap-3 sm:grid-cols-2 lg:grid-cols-3", children: prompts.map((prompt, index) => {
4875
+ const style = PROMPT_STYLES[index];
4874
4876
  return /* @__PURE__ */ jsxRuntime.jsxs(
4875
4877
  framerMotion.motion.button,
4876
4878
  {
@@ -5000,8 +5002,8 @@ function SessionArtifactList({
5000
5002
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex h-full flex-col items-center justify-center gap-3 px-4 py-12 text-center", children: [
5001
5003
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex h-12 w-12 items-center justify-center rounded-xl bg-gray-100 dark:bg-gray-800", children: /* @__PURE__ */ jsxRuntime.jsx(react.Package, { className: "h-6 w-6 text-gray-400 dark:text-gray-500", weight: "duotone" }) }),
5002
5004
  /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
5003
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-medium text-gray-500 dark:text-gray-400", children: t("Artifacts.Empty") }),
5004
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-0.5 text-xs text-gray-400 dark:text-gray-500", children: t("Artifacts.EmptySubtitle") })
5005
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-medium text-gray-500 dark:text-gray-400", children: t("BiChat.Artifacts.Empty") }),
5006
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-0.5 text-xs text-gray-400 dark:text-gray-500", children: t("BiChat.Artifacts.EmptySubtitle") })
5005
5007
  ] })
5006
5008
  ] });
5007
5009
  }
@@ -5113,7 +5115,7 @@ function ArtifactActions({ url }) {
5113
5115
  className: "inline-flex items-center gap-2 rounded-lg border border-gray-200 px-3 py-1.5 text-xs font-medium text-gray-700 transition-colors hover:bg-gray-50 dark:border-gray-700 dark:text-gray-200 dark:hover:bg-gray-800",
5114
5116
  children: [
5115
5117
  /* @__PURE__ */ jsxRuntime.jsx(react.ArrowSquareOut, { className: "h-3.5 w-3.5", weight: "bold" }),
5116
- t("Artifacts.OpenInNewTab")
5118
+ t("BiChat.Artifacts.OpenInNewTab")
5117
5119
  ]
5118
5120
  }
5119
5121
  ),
@@ -5127,7 +5129,7 @@ function ArtifactActions({ url }) {
5127
5129
  className: "inline-flex items-center gap-2 rounded-lg bg-primary-600 px-3 py-1.5 text-xs font-medium text-white shadow-sm transition-colors hover:bg-primary-700",
5128
5130
  children: [
5129
5131
  /* @__PURE__ */ jsxRuntime.jsx(react.DownloadSimple, { className: "h-3.5 w-3.5", weight: "bold" }),
5130
- t("Artifacts.Download")
5132
+ t("BiChat.Artifacts.Download")
5131
5133
  ]
5132
5134
  }
5133
5135
  )
@@ -5142,7 +5144,7 @@ function TextArtifactPreview({ artifact }) {
5142
5144
  React.useEffect(() => {
5143
5145
  if (!artifact.url) {
5144
5146
  setLoading(false);
5145
- setError(t("Artifacts.TextPreviewFailed"));
5147
+ setError(t("BiChat.Artifacts.TextPreviewFailed"));
5146
5148
  return;
5147
5149
  }
5148
5150
  const controller = new AbortController();
@@ -5165,7 +5167,7 @@ function TextArtifactPreview({ artifact }) {
5165
5167
  if (err instanceof Error && err.name === "AbortError") {
5166
5168
  return;
5167
5169
  }
5168
- setError(t("Artifacts.TextPreviewFailed"));
5170
+ setError(t("BiChat.Artifacts.TextPreviewFailed"));
5169
5171
  }).finally(() => {
5170
5172
  setLoading(false);
5171
5173
  });
@@ -5176,15 +5178,15 @@ function TextArtifactPreview({ artifact }) {
5176
5178
  if (loading) {
5177
5179
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-h-[320px] items-center justify-center rounded-xl border border-gray-200 bg-gray-50 text-sm text-gray-500 dark:border-gray-700/60 dark:bg-gray-800/30 dark:text-gray-400", children: [
5178
5180
  /* @__PURE__ */ jsxRuntime.jsx(react.SpinnerGap, { className: "mr-2 h-4 w-4 animate-spin" }),
5179
- t("Artifacts.PreviewLoading")
5181
+ t("BiChat.Artifacts.PreviewLoading")
5180
5182
  ] });
5181
5183
  }
5182
5184
  if (error) {
5183
5185
  return /* @__PURE__ */ jsxRuntime.jsx(WarningBox, { message: error });
5184
5186
  }
5185
5187
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
5186
- /* @__PURE__ */ jsxRuntime.jsx("pre", { className: "max-h-[70vh] overflow-auto rounded-xl border border-gray-200 bg-gray-50 p-3 text-xs leading-relaxed text-gray-800 dark:border-gray-700/60 dark:bg-gray-900 dark:text-gray-100", children: content || t("Artifacts.PreviewUnavailable") }),
5187
- truncated && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-gray-500 dark:text-gray-400", children: t("Artifacts.TextPreviewTruncated") })
5188
+ /* @__PURE__ */ jsxRuntime.jsx("pre", { className: "max-h-[70vh] overflow-auto rounded-xl border border-gray-200 bg-gray-50 p-3 text-xs leading-relaxed text-gray-800 dark:border-gray-700/60 dark:bg-gray-900 dark:text-gray-100", children: content || t("BiChat.Artifacts.PreviewUnavailable") }),
5189
+ truncated && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-gray-500 dark:text-gray-400", children: t("BiChat.Artifacts.TextPreviewTruncated") })
5188
5190
  ] });
5189
5191
  }
5190
5192
  function SessionArtifactPreview({ artifact }) {
@@ -5200,11 +5202,11 @@ function SessionArtifactPreview({ artifact }) {
5200
5202
  if (chartData) {
5201
5203
  return /* @__PURE__ */ jsxRuntime.jsx(ChartCard, { chartData });
5202
5204
  }
5203
- return /* @__PURE__ */ jsxRuntime.jsx(WarningBox, { message: t("Artifacts.ChartUnavailable") });
5205
+ return /* @__PURE__ */ jsxRuntime.jsx(WarningBox, { message: t("BiChat.Artifacts.ChartUnavailable") });
5204
5206
  }
5205
5207
  if (isImageArtifact2(artifact)) {
5206
5208
  if (!artifact.url) {
5207
- return /* @__PURE__ */ jsxRuntime.jsx(WarningBox, { message: t("Artifacts.ImageUnavailable") });
5209
+ return /* @__PURE__ */ jsxRuntime.jsx(WarningBox, { message: t("BiChat.Artifacts.ImageUnavailable") });
5208
5210
  }
5209
5211
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-3", children: [
5210
5212
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "overflow-hidden rounded-xl border border-gray-200/80 bg-gray-50/50 dark:border-gray-700/60 dark:bg-gray-800/30", children: /* @__PURE__ */ jsxRuntime.jsx(
@@ -5221,7 +5223,7 @@ function SessionArtifactPreview({ artifact }) {
5221
5223
  }
5222
5224
  if (isPDFArtifact(artifact)) {
5223
5225
  if (!artifact.url) {
5224
- return /* @__PURE__ */ jsxRuntime.jsx(WarningBox, { message: t("Artifacts.DownloadUnavailable") });
5226
+ return /* @__PURE__ */ jsxRuntime.jsx(WarningBox, { message: t("BiChat.Artifacts.DownloadUnavailable") });
5225
5227
  }
5226
5228
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-3", children: [
5227
5229
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "overflow-hidden rounded-xl border border-gray-200/80 bg-gray-50 dark:border-gray-700/60 dark:bg-gray-900", children: /* @__PURE__ */ jsxRuntime.jsx(
@@ -5237,7 +5239,7 @@ function SessionArtifactPreview({ artifact }) {
5237
5239
  }
5238
5240
  if (isOfficeDocumentArtifact(artifact)) {
5239
5241
  if (!artifact.url) {
5240
- return /* @__PURE__ */ jsxRuntime.jsx(WarningBox, { message: t("Artifacts.DownloadUnavailable") });
5242
+ return /* @__PURE__ */ jsxRuntime.jsx(WarningBox, { message: t("BiChat.Artifacts.DownloadUnavailable") });
5241
5243
  }
5242
5244
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-3", children: [
5243
5245
  officeViewerURL ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "overflow-hidden rounded-xl border border-gray-200/80 bg-gray-50 dark:border-gray-700/60 dark:bg-gray-900", children: /* @__PURE__ */ jsxRuntime.jsx(
@@ -5247,7 +5249,7 @@ function SessionArtifactPreview({ artifact }) {
5247
5249
  title: artifact.name,
5248
5250
  className: "h-[72vh] w-full"
5249
5251
  }
5250
- ) }) : /* @__PURE__ */ jsxRuntime.jsx(WarningBox, { message: t("Artifacts.OfficePreviewUnavailable") }),
5252
+ ) }) : /* @__PURE__ */ jsxRuntime.jsx(WarningBox, { message: t("BiChat.Artifacts.OfficePreviewUnavailable") }),
5251
5253
  /* @__PURE__ */ jsxRuntime.jsx(ArtifactActions, { url: artifact.url })
5252
5254
  ] });
5253
5255
  }
@@ -5261,13 +5263,13 @@ function SessionArtifactPreview({ artifact }) {
5261
5263
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-3", children: [
5262
5264
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-h-[240px] flex-col items-center justify-center rounded-xl border border-gray-200/80 bg-gray-50/60 p-6 text-center dark:border-gray-700/60 dark:bg-gray-900", children: [
5263
5265
  /* @__PURE__ */ jsxRuntime.jsx(react.FileText, { className: "h-8 w-8 text-gray-400 dark:text-gray-500", weight: "duotone" }),
5264
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-3 text-sm font-medium text-gray-800 dark:text-gray-100", children: t("Artifacts.PreviewUnavailable") }),
5265
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-1 text-xs text-gray-500 dark:text-gray-400", children: t("Artifacts.PreviewNotSupported") })
5266
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-3 text-sm font-medium text-gray-800 dark:text-gray-100", children: t("BiChat.Artifacts.PreviewUnavailable") }),
5267
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-1 text-xs text-gray-500 dark:text-gray-400", children: t("BiChat.Artifacts.PreviewNotSupported") })
5266
5268
  ] }),
5267
5269
  /* @__PURE__ */ jsxRuntime.jsx(ArtifactActions, { url: artifact.url })
5268
5270
  ] });
5269
5271
  }
5270
- return /* @__PURE__ */ jsxRuntime.jsx(WarningBox, { message: t("Artifacts.DownloadUnavailable") });
5272
+ return /* @__PURE__ */ jsxRuntime.jsx(WarningBox, { message: t("BiChat.Artifacts.DownloadUnavailable") });
5271
5273
  }
5272
5274
  function SessionArtifactPreviewModal({
5273
5275
  isOpen,
@@ -5313,7 +5315,7 @@ function SessionArtifactPreviewModal({
5313
5315
  await onRename(artifact, nextName);
5314
5316
  setIsEditingName(false);
5315
5317
  } catch (err) {
5316
- setError(err instanceof Error ? err.message : t("Artifacts.RenameFailed"));
5318
+ setError(err instanceof Error ? err.message : t("BiChat.Artifacts.RenameFailed"));
5317
5319
  } finally {
5318
5320
  setSubmittingRename(false);
5319
5321
  }
@@ -5322,7 +5324,7 @@ function SessionArtifactPreviewModal({
5322
5324
  if (!artifact || !onDelete) {
5323
5325
  return;
5324
5326
  }
5325
- if (!window.confirm(t("Artifacts.DeleteConfirm"))) {
5327
+ if (!window.confirm(t("BiChat.Artifacts.DeleteConfirm"))) {
5326
5328
  return;
5327
5329
  }
5328
5330
  setSubmittingDelete(true);
@@ -5331,7 +5333,7 @@ function SessionArtifactPreviewModal({
5331
5333
  await onDelete(artifact);
5332
5334
  onClose();
5333
5335
  } catch (err) {
5334
- setError(err instanceof Error ? err.message : t("Artifacts.DeleteFailed"));
5336
+ setError(err instanceof Error ? err.message : t("BiChat.Artifacts.DeleteFailed"));
5335
5337
  } finally {
5336
5338
  setSubmittingDelete(false);
5337
5339
  }
@@ -5362,7 +5364,7 @@ function SessionArtifactPreviewModal({
5362
5364
  }
5363
5365
  },
5364
5366
  className: "w-full rounded-lg border border-gray-300 px-3 py-1.5 text-sm text-gray-900 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500/50 dark:border-gray-600 dark:bg-gray-800 dark:text-gray-100",
5365
- "aria-label": t("Artifacts.Rename"),
5367
+ "aria-label": t("BiChat.Artifacts.Rename"),
5366
5368
  autoFocus: true
5367
5369
  }
5368
5370
  ),
@@ -5377,7 +5379,7 @@ function SessionArtifactPreviewModal({
5377
5379
  className: "cursor-pointer inline-flex items-center gap-1 rounded-lg bg-primary-600 px-2.5 py-1.5 text-xs font-medium text-white transition-colors hover:bg-primary-700 disabled:cursor-not-allowed disabled:opacity-60",
5378
5380
  children: [
5379
5381
  /* @__PURE__ */ jsxRuntime.jsx(react.FloppyDisk, { className: "h-3.5 w-3.5", weight: "bold" }),
5380
- t("Message.Save")
5382
+ t("BiChat.Message.Save")
5381
5383
  ]
5382
5384
  }
5383
5385
  ),
@@ -5391,7 +5393,7 @@ function SessionArtifactPreviewModal({
5391
5393
  },
5392
5394
  disabled: submittingRename,
5393
5395
  className: "cursor-pointer rounded-lg border border-gray-200 px-2.5 py-1.5 text-xs font-medium text-gray-700 transition-colors hover:bg-gray-50 disabled:cursor-not-allowed disabled:opacity-60 dark:border-gray-700 dark:text-gray-200 dark:hover:bg-gray-800",
5394
- children: t("Message.Cancel")
5396
+ children: t("BiChat.Message.Cancel")
5395
5397
  }
5396
5398
  )
5397
5399
  ] }) : /* @__PURE__ */ jsxRuntime.jsx("h2", { className: "truncate text-base font-semibold text-gray-900 dark:text-gray-100", children: artifact.name }),
@@ -5407,8 +5409,8 @@ function SessionArtifactPreviewModal({
5407
5409
  setIsEditingName(true);
5408
5410
  },
5409
5411
  className: "cursor-pointer rounded-lg border border-gray-200 p-2 text-gray-600 transition-colors hover:bg-gray-50 hover:text-gray-900 dark:border-gray-700 dark:text-gray-300 dark:hover:bg-gray-800 dark:hover:text-gray-100",
5410
- "aria-label": t("Artifacts.Rename"),
5411
- title: t("Artifacts.Rename"),
5412
+ "aria-label": t("BiChat.Artifacts.Rename"),
5413
+ title: t("BiChat.Artifacts.Rename"),
5412
5414
  children: /* @__PURE__ */ jsxRuntime.jsx(react.PencilSimple, { className: "h-4 w-4", weight: "regular" })
5413
5415
  }
5414
5416
  ),
@@ -5421,8 +5423,8 @@ function SessionArtifactPreviewModal({
5421
5423
  },
5422
5424
  disabled: submittingDelete,
5423
5425
  className: "cursor-pointer rounded-lg border border-red-200 p-2 text-red-600 transition-colors hover:bg-red-50 hover:text-red-700 disabled:cursor-not-allowed disabled:opacity-60 dark:border-red-900/60 dark:text-red-400 dark:hover:bg-red-950/30 dark:hover:text-red-300",
5424
- "aria-label": t("Artifacts.Delete"),
5425
- title: t("Artifacts.Delete"),
5426
+ "aria-label": t("BiChat.Artifacts.Delete"),
5427
+ title: t("BiChat.Artifacts.Delete"),
5426
5428
  children: /* @__PURE__ */ jsxRuntime.jsx(react.Trash, { className: "h-4 w-4", weight: "regular" })
5427
5429
  }
5428
5430
  ),
@@ -5432,8 +5434,8 @@ function SessionArtifactPreviewModal({
5432
5434
  type: "button",
5433
5435
  onClick: handleClose,
5434
5436
  className: "cursor-pointer rounded-lg border border-gray-200 p-2 text-gray-600 transition-colors hover:bg-gray-50 hover:text-gray-900 dark:border-gray-700 dark:text-gray-300 dark:hover:bg-gray-800 dark:hover:text-gray-100",
5435
- "aria-label": t("Common.Close"),
5436
- title: t("Common.Close"),
5437
+ "aria-label": t("BiChat.Common.Close"),
5438
+ title: t("BiChat.Common.Close"),
5437
5439
  children: /* @__PURE__ */ jsxRuntime.jsx(react.X, { className: "h-4 w-4", weight: "bold" })
5438
5440
  }
5439
5441
  )
@@ -5537,7 +5539,7 @@ function SessionArtifactsPanel({
5537
5539
  if (requestID !== requestSeq.current) {
5538
5540
  return;
5539
5541
  }
5540
- setError(err instanceof Error ? err.message : tRef.current("Artifacts.FailedToLoad"));
5542
+ setError(err instanceof Error ? err.message : tRef.current("BiChat.Artifacts.FailedToLoad"));
5541
5543
  } finally {
5542
5544
  if (requestID === requestSeq.current) {
5543
5545
  setFetching(false);
@@ -5652,7 +5654,7 @@ function SessionArtifactsPanel({
5652
5654
  }
5653
5655
  setError(null);
5654
5656
  } catch (err) {
5655
- setError(err instanceof Error ? err.message : tRef.current("Artifacts.FailedToLoad"));
5657
+ setError(err instanceof Error ? err.message : tRef.current("BiChat.Artifacts.FailedToLoad"));
5656
5658
  }
5657
5659
  }, [canDropFiles, dataSource, fetchArtifacts, hasDragFiles, sessionId, setDropSuccessState]);
5658
5660
  const canRenameArtifacts = typeof dataSource.renameSessionArtifact === "function";
@@ -5701,7 +5703,7 @@ function SessionArtifactsPanel({
5701
5703
  isDragging ? "bg-primary-50/40 dark:bg-primary-950/20" : "",
5702
5704
  className
5703
5705
  ].join(" "),
5704
- "aria-label": t("Artifacts.Title"),
5706
+ "aria-label": t("BiChat.Artifacts.Title"),
5705
5707
  onDragEnter: handleDragEnter,
5706
5708
  onDragOver: handleDragOver,
5707
5709
  onDragLeave: handleDragLeave,
@@ -5716,18 +5718,18 @@ function SessionArtifactsPanel({
5716
5718
  ].join(" "),
5717
5719
  children: [
5718
5720
  /* @__PURE__ */ jsxRuntime.jsx(react.Paperclip, { className: "h-5 w-5", weight: "bold" }),
5719
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm font-medium", children: dropSuccess ? t("Input.FilesAdded") : t("Input.DropFiles") })
5721
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm font-medium", children: dropSuccess ? t("BiChat.Input.FilesAdded") : t("BiChat.Input.DropFiles") })
5720
5722
  ]
5721
5723
  }
5722
5724
  ) }),
5723
5725
  /* @__PURE__ */ jsxRuntime.jsx("header", { className: "flex items-center justify-between border-b border-gray-200 px-3 py-2 dark:border-gray-700/80", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "min-w-0 flex-1", children: /* @__PURE__ */ jsxRuntime.jsxs("h2", { className: "truncate text-sm font-semibold text-gray-900 dark:text-gray-100", children: [
5724
- t("Artifacts.Title"),
5726
+ t("BiChat.Artifacts.Title"),
5725
5727
  " (",
5726
5728
  artifacts.length,
5727
5729
  ")"
5728
5730
  ] }) }) }),
5729
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "min-h-0 flex-1 overflow-y-auto px-3 py-3", children: fetching ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex h-full items-center justify-center text-sm text-gray-500 dark:text-gray-400", children: t("Artifacts.Loading") }) : error ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-3 rounded-lg border border-red-200 bg-red-50 p-3 dark:border-red-900/70 dark:bg-red-950/30", children: [
5730
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-medium text-red-800 dark:text-red-300", children: t("Artifacts.FailedToLoad") }),
5731
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "min-h-0 flex-1 overflow-y-auto px-3 py-3", children: fetching ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex h-full items-center justify-center text-sm text-gray-500 dark:text-gray-400", children: t("BiChat.Artifacts.Loading") }) : error ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-3 rounded-lg border border-red-200 bg-red-50 p-3 dark:border-red-900/70 dark:bg-red-950/30", children: [
5732
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-medium text-red-800 dark:text-red-300", children: t("BiChat.Artifacts.FailedToLoad") }),
5731
5733
  /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-red-700 dark:text-red-400", children: error }),
5732
5734
  /* @__PURE__ */ jsxRuntime.jsx(
5733
5735
  "button",
@@ -5737,10 +5739,10 @@ function SessionArtifactsPanel({
5737
5739
  void fetchArtifacts({ reset: true, manual: true });
5738
5740
  },
5739
5741
  className: "cursor-pointer rounded-md border border-red-300 px-2 py-1 text-xs font-medium text-red-700 hover:bg-red-100 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-red-400/50 dark:border-red-800 dark:text-red-300 dark:hover:bg-red-900/40",
5740
- children: t("Alert.Retry")
5742
+ children: t("BiChat.Alert.Retry")
5741
5743
  }
5742
5744
  )
5743
- ] }) : !canFetchArtifacts ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-lg border border-amber-200 bg-amber-50 p-3 text-sm text-amber-800 dark:border-amber-900/70 dark:bg-amber-950/30 dark:text-amber-200", children: t("Artifacts.Unsupported") }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
5745
+ ] }) : !canFetchArtifacts ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-lg border border-amber-200 bg-amber-50 p-3 text-sm text-amber-800 dark:border-amber-900/70 dark:bg-amber-950/30 dark:text-amber-200", children: t("BiChat.Artifacts.Unsupported") }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
5744
5746
  /* @__PURE__ */ jsxRuntime.jsx(
5745
5747
  SessionArtifactList,
5746
5748
  {
@@ -5758,7 +5760,7 @@ function SessionArtifactsPanel({
5758
5760
  },
5759
5761
  disabled: loadingMore || refreshing || fetching,
5760
5762
  className: "cursor-pointer rounded-md border border-gray-200 px-3 py-1.5 text-xs font-medium text-gray-700 transition-colors hover:bg-gray-50 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500/50 disabled:cursor-not-allowed disabled:opacity-50 dark:border-gray-700 dark:text-gray-200 dark:hover:bg-gray-800",
5761
- children: loadingMore ? t("Artifacts.LoadingMore") : t("Artifacts.LoadMore")
5763
+ children: loadingMore ? t("BiChat.Artifacts.LoadingMore") : t("BiChat.Artifacts.LoadMore")
5762
5764
  }
5763
5765
  ) })
5764
5766
  ] }) }),
@@ -5883,11 +5885,11 @@ function ChatSessionCore({
5883
5885
  };
5884
5886
  }, [isResizingArtifactsPanel, artifactsPanelStorageKey]);
5885
5887
  if (fetching) {
5886
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex h-full items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-gray-500 dark:text-gray-400", children: t("Input.Processing") }) });
5888
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex h-full items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-gray-500 dark:text-gray-400", children: t("BiChat.Input.Processing") }) });
5887
5889
  }
5888
5890
  if (error) {
5889
5891
  return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex h-full items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-red-500 dark:text-red-400", children: [
5890
- t("Error.Generic"),
5892
+ t("BiChat.Error.Generic"),
5891
5893
  ": ",
5892
5894
  error
5893
5895
  ] }) });
@@ -5923,11 +5925,11 @@ function ChatSessionCore({
5923
5925
  "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500/50",
5924
5926
  artifactsPanelExpanded ? "bg-primary-50 text-primary-700 hover:bg-primary-100 dark:bg-primary-950/30 dark:text-primary-300 dark:hover:bg-primary-900/40" : "text-gray-500 hover:bg-gray-100 hover:text-gray-700 dark:text-gray-400 dark:hover:bg-gray-800 dark:hover:text-gray-200"
5925
5927
  ].join(" "),
5926
- "aria-label": artifactsPanelExpanded ? t("Artifacts.ToggleHide") : t("Artifacts.ToggleShow"),
5927
- title: artifactsPanelExpanded ? t("Artifacts.ToggleHide") : t("Artifacts.ToggleShow"),
5928
+ "aria-label": artifactsPanelExpanded ? t("BiChat.Artifacts.ToggleHide") : t("BiChat.Artifacts.ToggleShow"),
5929
+ title: artifactsPanelExpanded ? t("BiChat.Artifacts.ToggleHide") : t("BiChat.Artifacts.ToggleShow"),
5928
5930
  children: [
5929
5931
  /* @__PURE__ */ jsxRuntime.jsx(react.Sidebar, { className: "h-4 w-4", weight: artifactsPanelExpanded ? "duotone" : "regular" }),
5930
- t("Artifacts.Title")
5932
+ t("BiChat.Artifacts.Title")
5931
5933
  ]
5932
5934
  }
5933
5935
  ),
@@ -5975,7 +5977,7 @@ function ChatSessionCore({
5975
5977
  formClassName: "mx-auto"
5976
5978
  }
5977
5979
  ),
5978
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-4 pb-1 text-center text-xs text-gray-500 dark:text-gray-400", children: t("Welcome.Disclaimer") })
5980
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-4 pb-1 text-center text-xs text-gray-500 dark:text-gray-400", children: t("BiChat.Welcome.Disclaimer") })
5979
5981
  ] }) }) }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
5980
5982
  /* @__PURE__ */ jsxRuntime.jsx(
5981
5983
  MessageList,
@@ -6025,7 +6027,7 @@ function ChatSessionCore({
6025
6027
  "div",
6026
6028
  {
6027
6029
  role: "separator",
6028
- "aria-label": t("Artifacts.Resize"),
6030
+ "aria-label": t("BiChat.Artifacts.Resize"),
6029
6031
  onMouseDown: handleArtifactsResizeStart,
6030
6032
  className: "relative flex shrink-0 cursor-col-resize touch-none items-center justify-center w-2 transition-colors lg:flex group/resize after:absolute after:inset-y-0 after:left-0 after:w-0.5 after:bg-gray-300 dark:after:bg-gray-600 after:transition-colors group-hover/resize:after:bg-primary-400 dark:group-hover/resize:after:bg-primary-500",
6031
6033
  children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "absolute h-10 w-1.5 cursor-col-resize rounded-full bg-gray-400 transition-colors group-hover/resize:bg-primary-400 dark:bg-gray-500 dark:group-hover/resize:bg-primary-500" })
@@ -6066,7 +6068,7 @@ function ChatSessionCore({
6066
6068
  animate: { opacity: 1 },
6067
6069
  exit: { opacity: 0 },
6068
6070
  onClick: handleToggleArtifactsPanel,
6069
- "aria-label": t("Common.Close")
6071
+ "aria-label": t("BiChat.Common.Close")
6070
6072
  }
6071
6073
  ),
6072
6074
  /* @__PURE__ */ jsxRuntime.jsx(
@@ -6180,6 +6182,9 @@ function EmptyState({
6180
6182
  }
6181
6183
  var MemoizedEmptyState = React.memo(EmptyState);
6182
6184
  MemoizedEmptyState.displayName = "EmptyState";
6185
+
6186
+ // ui/src/bichat/components/EditableText.tsx
6187
+ init_useTranslation();
6183
6188
  var sizeClasses2 = {
6184
6189
  sm: "text-sm",
6185
6190
  md: "text-base",
@@ -6196,6 +6201,7 @@ var EditableText = React.forwardRef(
6196
6201
  inputClassName = "",
6197
6202
  size = "sm"
6198
6203
  }, ref) => {
6204
+ const { t } = useTranslation();
6199
6205
  const [isEditing, setIsEditing] = React.useState(false);
6200
6206
  const [editValue, setEditValue] = React.useState(value);
6201
6207
  const inputRef = React.useRef(null);
@@ -6271,7 +6277,7 @@ var EditableText = React.forwardRef(
6271
6277
  maxLength,
6272
6278
  placeholder,
6273
6279
  className: `flex-1 px-2 py-1 ${sizeClass} bg-white dark:bg-gray-700 border border-primary-500 dark:border-primary-600 rounded-lg focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500/50 dark:focus-visible:ring-primary-600/30 text-gray-900 dark:text-white ${inputClassName}`,
6274
- "aria-label": "Edit text. Press Enter to save, Escape to cancel"
6280
+ "aria-label": t("BiChat.EditableText.AriaLabel")
6275
6281
  }
6276
6282
  )
6277
6283
  }
@@ -6283,7 +6289,7 @@ var EditableText = React.forwardRef(
6283
6289
  {
6284
6290
  onDoubleClick: handleDoubleClick,
6285
6291
  className: `${sizeClass} font-medium truncate flex-1 cursor-pointer select-none hover:text-primary-600 dark:hover:text-primary-400 transition-colors ${className}`,
6286
- title: "Double-click to edit",
6292
+ title: t("BiChat.EditableText.DoubleClickToEdit"),
6287
6293
  role: "button",
6288
6294
  tabIndex: 0,
6289
6295
  onKeyDown: (e) => {
@@ -6302,6 +6308,9 @@ var EditableText = React.forwardRef(
6302
6308
  );
6303
6309
  EditableText.displayName = "EditableText";
6304
6310
  var MemoizedEditableText = React.memo(EditableText);
6311
+
6312
+ // ui/src/bichat/components/SearchInput.tsx
6313
+ init_useTranslation();
6305
6314
  var sizeClasses3 = {
6306
6315
  sm: {
6307
6316
  container: "py-1.5 pl-8 pr-8 text-xs",
@@ -6331,6 +6340,7 @@ function SearchInput({
6331
6340
  disabled = false,
6332
6341
  ariaLabel = "Search"
6333
6342
  }) {
6343
+ const { t } = useTranslation();
6334
6344
  const inputRef = React.useRef(null);
6335
6345
  const sizes = sizeClasses3[size];
6336
6346
  React.useEffect(() => {
@@ -6385,8 +6395,8 @@ function SearchInput({
6385
6395
  type: "button",
6386
6396
  onClick: handleClear,
6387
6397
  className: `cursor-pointer absolute inset-y-0 right-2 flex items-center ${sizes.clearBtn} rounded-lg hover:bg-gray-200 dark:hover:bg-gray-700 transition-all duration-200 text-gray-400 dark:text-gray-500 hover:text-gray-600 dark:hover:text-gray-300`,
6388
- "aria-label": "Clear search",
6389
- title: "Clear search",
6398
+ "aria-label": t("BiChat.Search.Clear"),
6399
+ title: t("BiChat.Search.Clear"),
6390
6400
  children: /* @__PURE__ */ jsxRuntime.jsx(react.X, { size: sizes.icon - 2, weight: "bold" })
6391
6401
  }
6392
6402
  )
@@ -6921,12 +6931,16 @@ function useLongPress(options) {
6921
6931
  isPressed
6922
6932
  };
6923
6933
  }
6934
+
6935
+ // ui/src/bichat/components/TouchContextMenu.tsx
6936
+ init_useTranslation();
6924
6937
  var TouchContextMenu = ({
6925
6938
  items,
6926
6939
  isOpen,
6927
6940
  onClose,
6928
6941
  anchorRect
6929
6942
  }) => {
6943
+ const { t } = useTranslation();
6930
6944
  const [focusedIndex, setFocusedIndex] = React.useState(-1);
6931
6945
  const menuRef = React.useRef(null);
6932
6946
  const itemRefs = React.useRef([]);
@@ -7010,7 +7024,7 @@ var TouchContextMenu = ({
7010
7024
  {
7011
7025
  ref: menuRef,
7012
7026
  role: "menu",
7013
- "aria-label": "Context menu",
7027
+ "aria-label": t("BiChat.ContextMenu"),
7014
7028
  initial: { opacity: 0, scale: 0.95 },
7015
7029
  animate: { opacity: 1, scale: 1 },
7016
7030
  exit: { opacity: 0, scale: 0.95 },
@@ -7075,11 +7089,24 @@ var SessionItem = React.memo(
7075
7089
  const [menuAnchor, setMenuAnchor] = React.useState(null);
7076
7090
  const [isTouch, setIsTouch] = React.useState(false);
7077
7091
  const { t } = useTranslation();
7092
+ const isDraggingRef = React.useRef(false);
7093
+ const dragX = framerMotion.useMotionValue(0);
7094
+ const archiveOpacity = framerMotion.useTransform(dragX, [-80, -40, 0], [1, 0.5, 0]);
7095
+ const archiveScale = framerMotion.useTransform(dragX, [-80, -40, 0], [1, 0.8, 0.6]);
7096
+ const canDragArchive = !!onArchive;
7097
+ const handleDragEnd = (_, info) => {
7098
+ if (info.offset.x < -80 && onArchive) {
7099
+ onArchive();
7100
+ }
7101
+ requestAnimationFrame(() => {
7102
+ isDraggingRef.current = false;
7103
+ });
7104
+ };
7078
7105
  React.useEffect(() => {
7079
7106
  setIsTouch("ontouchend" in document);
7080
7107
  }, []);
7081
- const isTitleGenerating = !session.title || session.title === t("Chat.NewChat");
7082
- const displayTitle = isTitleGenerating ? t("Common.Generating") : session.title ?? t("Common.Untitled");
7108
+ const isTitleGenerating = !session.title || session.title === t("BiChat.Chat.NewChat");
7109
+ const displayTitle = isTitleGenerating ? t("BiChat.Common.Generating") : session.title ?? t("BiChat.Common.Untitled");
7083
7110
  const { handlers: longPressHandlers } = useLongPress({
7084
7111
  delay: 500,
7085
7112
  onLongPress: (e) => {
@@ -7093,60 +7120,58 @@ var SessionItem = React.memo(
7093
7120
  const element = itemRef.current;
7094
7121
  if (!element) return;
7095
7122
  const isIPad = /iPad|Macintosh/i.test(navigator.userAgent) && "ontouchend" in document;
7096
- if (isIPad) {
7097
- const handleContextMenu = (e) => {
7098
- e.preventDefault();
7099
- const target = e.currentTarget;
7100
- setMenuAnchor(target.getBoundingClientRect());
7101
- setMenuOpen(true);
7102
- };
7103
- element.addEventListener("contextmenu", handleContextMenu);
7104
- return () => element.removeEventListener("contextmenu", handleContextMenu);
7105
- }
7106
- return void 0;
7123
+ if (!isIPad) return;
7124
+ const handleContextMenu = (e) => {
7125
+ e.preventDefault();
7126
+ const target = e.currentTarget;
7127
+ setMenuAnchor(target.getBoundingClientRect());
7128
+ setMenuOpen(true);
7129
+ };
7130
+ element.addEventListener("contextmenu", handleContextMenu);
7131
+ return () => element.removeEventListener("contextmenu", handleContextMenu);
7107
7132
  }, [itemRef]);
7108
7133
  const contextMenuItems = mode === "archived" ? [
7109
7134
  ...onRestore ? [{
7110
7135
  id: "restore",
7111
- label: t("Archived.RestoreButton"),
7136
+ label: t("BiChat.Archived.RestoreButton"),
7112
7137
  icon: /* @__PURE__ */ jsxRuntime.jsx(react.ArrowUUpLeft, { size: 20 }),
7113
7138
  onClick: () => onRestore()
7114
7139
  }] : [],
7115
7140
  ...onRename ? [{
7116
7141
  id: "rename",
7117
- label: t("Sidebar.RenameChat"),
7142
+ label: t("BiChat.Sidebar.RenameChat"),
7118
7143
  icon: /* @__PURE__ */ jsxRuntime.jsx(react.PencilSimple, { size: 20 }),
7119
7144
  onClick: () => editableTitleRef.current?.startEditing()
7120
7145
  }] : []
7121
7146
  ] : [
7122
7147
  ...onPin ? [{
7123
7148
  id: "pin",
7124
- label: session.pinned ? t("Sidebar.UnpinChat") : t("Sidebar.PinChat"),
7149
+ label: session.pinned ? t("BiChat.Sidebar.UnpinChat") : t("BiChat.Sidebar.PinChat"),
7125
7150
  icon: session.pinned ? /* @__PURE__ */ jsxRuntime.jsx(react.Check, { size: 20 }) : /* @__PURE__ */ jsxRuntime.jsx(react.Bookmark, { size: 20 }),
7126
7151
  onClick: () => onPin()
7127
7152
  }] : [],
7128
7153
  ...onRename ? [{
7129
7154
  id: "rename",
7130
- label: t("Sidebar.RenameChat"),
7155
+ label: t("BiChat.Sidebar.RenameChat"),
7131
7156
  icon: /* @__PURE__ */ jsxRuntime.jsx(react.PencilSimple, { size: 20 }),
7132
7157
  onClick: () => editableTitleRef.current?.startEditing()
7133
7158
  }] : [],
7134
7159
  ...onRegenerateTitle ? [{
7135
7160
  id: "regenerate",
7136
- label: t("Sidebar.RegenerateTitle"),
7161
+ label: t("BiChat.Sidebar.RegenerateTitle"),
7137
7162
  icon: /* @__PURE__ */ jsxRuntime.jsx(react.ArrowsClockwise, { size: 20 }),
7138
7163
  onClick: () => onRegenerateTitle()
7139
7164
  }] : [],
7140
7165
  ...onArchive ? [{
7141
7166
  id: "archive",
7142
- label: t("Sidebar.ArchiveChat"),
7167
+ label: t("BiChat.Sidebar.ArchiveChat"),
7143
7168
  icon: /* @__PURE__ */ jsxRuntime.jsx(react.Archive, { size: 20 }),
7144
7169
  onClick: () => onArchive(),
7145
7170
  variant: "danger"
7146
7171
  }] : [],
7147
7172
  ...onDelete ? [{
7148
7173
  id: "delete",
7149
- label: t("Sidebar.DeleteChat"),
7174
+ label: t("BiChat.Sidebar.DeleteChat"),
7150
7175
  icon: /* @__PURE__ */ jsxRuntime.jsx(react.Trash, { size: 20 }),
7151
7176
  onClick: () => onDelete(),
7152
7177
  variant: "danger"
@@ -7154,7 +7179,7 @@ var SessionItem = React.memo(
7154
7179
  ];
7155
7180
  const hasContextMenu = contextMenuItems.length > 0;
7156
7181
  return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
7157
- /* @__PURE__ */ jsxRuntime.jsx(
7182
+ /* @__PURE__ */ jsxRuntime.jsxs(
7158
7183
  framerMotion.motion.div,
7159
7184
  {
7160
7185
  variants: sessionItemVariants,
@@ -7162,158 +7187,196 @@ var SessionItem = React.memo(
7162
7187
  animate: "animate",
7163
7188
  whileHover: "hover",
7164
7189
  exit: "exit",
7165
- children: /* @__PURE__ */ jsxRuntime.jsx(
7166
- "button",
7167
- {
7168
- type: "button",
7169
- ref: itemRef,
7170
- onClick: () => onSelect(session.id),
7171
- className: `block w-full text-left px-3 py-2 rounded-lg transition-smooth group relative touch-tap cursor-pointer focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500/50 ${isActive ? "bg-primary-50/50 dark:bg-primary-900/30 text-primary-700 dark:text-primary-400 border-l-4 border-primary-400 dark:border-primary-600" : "text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-800 border-l-4 border-transparent"} ${className}`,
7172
- "aria-current": isActive ? "page" : void 0,
7173
- "data-session-item": true,
7174
- "data-testid": `${testIdPrefix}-session-${session.id}`,
7175
- ...longPressHandlers,
7176
- children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between gap-2", children: [
7177
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-2 min-w-0 flex-1", children: /* @__PURE__ */ jsxRuntime.jsx(
7178
- MemoizedEditableText,
7190
+ className: "relative overflow-hidden rounded-lg",
7191
+ children: [
7192
+ canDragArchive && /* @__PURE__ */ jsxRuntime.jsx(
7193
+ framerMotion.motion.div,
7194
+ {
7195
+ className: "absolute inset-y-0 right-0 w-20 flex items-center justify-center bg-gray-500 dark:bg-gray-600 rounded-r-lg",
7196
+ style: { opacity: archiveOpacity, scale: archiveScale },
7197
+ "aria-hidden": "true",
7198
+ children: /* @__PURE__ */ jsxRuntime.jsx(react.Archive, { size: 20, className: "text-white" })
7199
+ }
7200
+ ),
7201
+ /* @__PURE__ */ jsxRuntime.jsx(
7202
+ framerMotion.motion.div,
7203
+ {
7204
+ drag: canDragArchive ? "x" : false,
7205
+ dragDirectionLock: true,
7206
+ dragConstraints: { left: -100, right: 0 },
7207
+ dragElastic: { left: 0.2, right: 0.5 },
7208
+ dragSnapToOrigin: true,
7209
+ style: { x: canDragArchive ? dragX : void 0 },
7210
+ onDragStart: () => {
7211
+ isDraggingRef.current = true;
7212
+ },
7213
+ onDragEnd: canDragArchive ? handleDragEnd : void 0,
7214
+ className: "relative",
7215
+ children: /* @__PURE__ */ jsxRuntime.jsx(
7216
+ "div",
7179
7217
  {
7180
- ref: editableTitleRef,
7181
- value: displayTitle,
7182
- onSave: (newTitle) => onRename?.(newTitle),
7183
- isLoading: isTitleGenerating
7184
- }
7185
- ) }),
7186
- !isTouch && hasContextMenu && /* @__PURE__ */ jsxRuntime.jsxs(react$1.Menu, { children: [
7187
- /* @__PURE__ */ jsxRuntime.jsx(
7188
- react$1.MenuButton,
7189
- {
7190
- onClick: (e) => {
7218
+ role: "button",
7219
+ tabIndex: 0,
7220
+ ref: itemRef,
7221
+ onClick: () => {
7222
+ if (isDraggingRef.current) return;
7223
+ onSelect(session.id);
7224
+ },
7225
+ onKeyDown: (e) => {
7226
+ if (e.key === "Enter" || e.key === " ") {
7191
7227
  e.preventDefault();
7192
- e.stopPropagation();
7193
- },
7194
- className: "opacity-0 group-hover:opacity-100 p-1.5 rounded hover:bg-gray-200 dark:hover:bg-gray-700 transition-smooth flex-shrink-0 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500/50",
7195
- "aria-label": t("Sidebar.ChatOptions"),
7196
- "data-testid": `${testIdPrefix}-session-options-${session.id}`,
7197
- children: /* @__PURE__ */ jsxRuntime.jsx(react.DotsThree, { size: 16, className: "w-4 h-4", weight: "bold" })
7198
- }
7199
- ),
7200
- /* @__PURE__ */ jsxRuntime.jsxs(
7201
- react$1.MenuItems,
7202
- {
7203
- anchor: "bottom start",
7204
- className: "w-52 bg-white/95 dark:bg-gray-900/95 backdrop-blur rounded-xl shadow-xl border border-gray-200 dark:border-gray-700 z-30 [--anchor-gap:8px] mt-1 p-2 space-y-1",
7205
- children: [
7206
- mode !== "archived" && onPin && /* @__PURE__ */ jsxRuntime.jsx(react$1.MenuItem, { children: ({ focus }) => /* @__PURE__ */ jsxRuntime.jsxs(
7207
- "button",
7208
- {
7209
- onClick: (e) => {
7210
- e.preventDefault();
7211
- e.stopPropagation();
7212
- onPin();
7213
- },
7214
- className: `cursor-pointer flex w-full items-center gap-2 rounded-lg px-3 py-2 text-sm font-medium text-gray-700 dark:text-gray-200 transition-smooth ${focus ? "bg-gray-100 dark:bg-gray-800/70 ring-1 ring-gray-200/80 dark:ring-gray-700/80" : "hover:bg-gray-50 dark:hover:bg-gray-800"}`,
7215
- "aria-label": session.pinned ? t("Sidebar.UnpinChat") : t("Sidebar.PinChat"),
7216
- "data-testid": `${testIdPrefix}-session-pin-${session.id}`,
7217
- children: [
7218
- session.pinned ? /* @__PURE__ */ jsxRuntime.jsx(react.Check, { size: 16, className: "w-4 h-4" }) : /* @__PURE__ */ jsxRuntime.jsx(react.Bookmark, { size: 16, className: "w-4 h-4" }),
7219
- session.pinned ? t("Sidebar.UnpinChat") : t("Sidebar.PinChat")
7220
- ]
7221
- }
7222
- ) }),
7223
- onRename && /* @__PURE__ */ jsxRuntime.jsx(react$1.MenuItem, { children: ({ focus, close }) => /* @__PURE__ */ jsxRuntime.jsxs(
7224
- "button",
7225
- {
7226
- onClick: (e) => {
7227
- e.preventDefault();
7228
- e.stopPropagation();
7229
- editableTitleRef.current?.startEditing();
7230
- close();
7231
- },
7232
- className: `cursor-pointer flex w-full items-center gap-2 rounded-lg px-3 py-2 text-sm font-medium text-gray-700 dark:text-gray-200 transition-smooth ${focus ? "bg-gray-100 dark:bg-gray-800/70 ring-1 ring-gray-200/80 dark:ring-gray-700/80" : "hover:bg-gray-50 dark:hover:bg-gray-800"}`,
7233
- "aria-label": t("Sidebar.RenameChat"),
7234
- "data-testid": `${testIdPrefix}-session-rename-${session.id}`,
7235
- children: [
7236
- /* @__PURE__ */ jsxRuntime.jsx(react.PencilSimple, { size: 16, className: "w-4 h-4" }),
7237
- t("Sidebar.RenameChat")
7238
- ]
7239
- }
7240
- ) }),
7241
- mode !== "archived" && onRegenerateTitle && /* @__PURE__ */ jsxRuntime.jsx(react$1.MenuItem, { children: ({ focus, close }) => /* @__PURE__ */ jsxRuntime.jsxs(
7242
- "button",
7243
- {
7244
- onClick: (e) => {
7245
- e.preventDefault();
7246
- e.stopPropagation();
7247
- onRegenerateTitle();
7248
- close();
7249
- },
7250
- className: `cursor-pointer flex w-full items-center gap-2 rounded-lg px-3 py-2 text-sm font-medium text-gray-700 dark:text-gray-200 transition-smooth ${focus ? "bg-gray-100 dark:bg-gray-800/70 ring-1 ring-gray-200/80 dark:ring-gray-700/80" : "hover:bg-gray-50 dark:hover:bg-gray-800"}`,
7251
- "aria-label": t("Sidebar.RegenerateTitle"),
7252
- "data-testid": `${testIdPrefix}-session-regenerate-${session.id}`,
7253
- children: [
7254
- /* @__PURE__ */ jsxRuntime.jsx(react.ArrowsClockwise, { size: 16, className: "w-4 h-4" }),
7255
- t("Sidebar.RegenerateTitle")
7256
- ]
7257
- }
7258
- ) }),
7259
- mode === "archived" && onRestore && /* @__PURE__ */ jsxRuntime.jsx(react$1.MenuItem, { children: ({ focus }) => /* @__PURE__ */ jsxRuntime.jsxs(
7260
- "button",
7261
- {
7262
- onClick: (e) => {
7263
- e.preventDefault();
7264
- e.stopPropagation();
7265
- onRestore();
7266
- },
7267
- className: `cursor-pointer flex w-full items-center gap-2 rounded-lg px-3 py-2 text-sm font-medium transition-smooth ${focus ? "text-green-700 dark:text-green-300 bg-green-50 dark:bg-green-900/20 ring-1 ring-green-200/70 dark:ring-green-500/30" : "text-green-700 dark:text-green-300 hover:bg-green-50/70 dark:hover:bg-green-900/10"}`,
7268
- "aria-label": t("Archived.RestoreButton"),
7269
- "data-testid": `${testIdPrefix}-session-restore-${session.id}`,
7270
- children: [
7271
- /* @__PURE__ */ jsxRuntime.jsx(react.ArrowUUpLeft, { size: 16, className: "w-4 h-4" }),
7272
- t("Archived.RestoreButton")
7273
- ]
7274
- }
7275
- ) }),
7276
- mode !== "archived" && onArchive && /* @__PURE__ */ jsxRuntime.jsx(react$1.MenuItem, { children: ({ focus }) => /* @__PURE__ */ jsxRuntime.jsxs(
7277
- "button",
7228
+ onSelect(session.id);
7229
+ }
7230
+ },
7231
+ className: `block w-full text-left px-3 py-2 rounded-lg transition-smooth group relative touch-tap cursor-pointer focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500/50 ${isActive ? "bg-primary-50/50 dark:bg-primary-900/30 text-primary-700 dark:text-primary-400 border-l-4 border-primary-400 dark:border-primary-600" : "text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-800 border-l-4 border-transparent"} ${className}`,
7232
+ "aria-current": isActive ? "page" : void 0,
7233
+ "data-session-item": true,
7234
+ "data-testid": `${testIdPrefix}-session-${session.id}`,
7235
+ ...longPressHandlers,
7236
+ children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between gap-2", children: [
7237
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-2 min-w-0 flex-1", children: /* @__PURE__ */ jsxRuntime.jsx(
7238
+ MemoizedEditableText,
7239
+ {
7240
+ ref: editableTitleRef,
7241
+ value: displayTitle,
7242
+ onSave: (newTitle) => onRename?.(newTitle),
7243
+ isLoading: isTitleGenerating
7244
+ }
7245
+ ) }),
7246
+ !isTouch && hasContextMenu && /* @__PURE__ */ jsxRuntime.jsxs(react$1.Menu, { children: [
7247
+ /* @__PURE__ */ jsxRuntime.jsx(
7248
+ react$1.MenuButton,
7278
7249
  {
7279
7250
  onClick: (e) => {
7280
7251
  e.preventDefault();
7281
7252
  e.stopPropagation();
7282
- onArchive();
7283
7253
  },
7284
- className: `cursor-pointer flex w-full items-center gap-2 rounded-lg px-3 py-2 text-sm font-medium transition-smooth ${focus ? "text-amber-600 dark:text-amber-400 bg-amber-50 dark:bg-amber-900/20 ring-1 ring-amber-200/70 dark:ring-amber-500/30" : "text-amber-600 dark:text-amber-400 hover:bg-amber-50/70 dark:hover:bg-amber-900/10"}`,
7285
- "aria-label": t("Sidebar.ArchiveChat"),
7286
- "data-testid": `${testIdPrefix}-session-archive-${session.id}`,
7287
- children: [
7288
- /* @__PURE__ */ jsxRuntime.jsx(react.Archive, { size: 16, className: "w-4 h-4" }),
7289
- t("Sidebar.ArchiveChat")
7290
- ]
7254
+ className: "opacity-0 group-hover:opacity-100 p-1.5 rounded hover:bg-gray-200 dark:hover:bg-gray-700 transition-smooth flex-shrink-0 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500/50",
7255
+ "aria-label": t("BiChat.Sidebar.ChatOptions"),
7256
+ "data-testid": `${testIdPrefix}-session-options-${session.id}`,
7257
+ children: /* @__PURE__ */ jsxRuntime.jsx(react.DotsThree, { size: 16, className: "w-4 h-4", weight: "bold" })
7291
7258
  }
7292
- ) }),
7293
- onDelete && /* @__PURE__ */ jsxRuntime.jsx(react$1.MenuItem, { children: ({ focus }) => /* @__PURE__ */ jsxRuntime.jsxs(
7294
- "button",
7259
+ ),
7260
+ /* @__PURE__ */ jsxRuntime.jsxs(
7261
+ react$1.MenuItems,
7295
7262
  {
7296
- onClick: (e) => {
7297
- e.preventDefault();
7298
- e.stopPropagation();
7299
- onDelete();
7300
- },
7301
- className: `cursor-pointer flex w-full items-center gap-2 rounded-lg px-3 py-2 text-sm font-medium transition-smooth ${focus ? "text-red-600 dark:text-red-400 bg-red-50 dark:bg-red-900/20 ring-1 ring-red-200/70 dark:ring-red-500/30" : "text-red-600 dark:text-red-400 hover:bg-red-50/70 dark:hover:bg-red-900/10"}`,
7302
- "aria-label": t("Sidebar.DeleteChat"),
7303
- "data-testid": `${testIdPrefix}-session-delete-${session.id}`,
7263
+ anchor: "bottom start",
7264
+ className: "w-52 bg-white/95 dark:bg-gray-900/95 backdrop-blur rounded-xl shadow-xl border border-gray-200 dark:border-gray-700 z-30 [--anchor-gap:8px] mt-1 p-2 space-y-1",
7304
7265
  children: [
7305
- /* @__PURE__ */ jsxRuntime.jsx(react.Trash, { size: 16, className: "w-4 h-4" }),
7306
- t("Sidebar.DeleteChat")
7266
+ mode !== "archived" && onPin && /* @__PURE__ */ jsxRuntime.jsx(react$1.MenuItem, { children: ({ focus }) => /* @__PURE__ */ jsxRuntime.jsxs(
7267
+ "button",
7268
+ {
7269
+ onClick: (e) => {
7270
+ e.preventDefault();
7271
+ e.stopPropagation();
7272
+ onPin();
7273
+ },
7274
+ className: `cursor-pointer flex w-full items-center gap-2 rounded-lg px-3 py-2 text-sm font-medium text-gray-700 dark:text-gray-200 transition-smooth ${focus ? "bg-gray-100 dark:bg-gray-800/70 ring-1 ring-gray-200/80 dark:ring-gray-700/80" : "hover:bg-gray-50 dark:hover:bg-gray-800"}`,
7275
+ "aria-label": session.pinned ? t("BiChat.Sidebar.UnpinChat") : t("BiChat.Sidebar.PinChat"),
7276
+ "data-testid": `${testIdPrefix}-session-pin-${session.id}`,
7277
+ children: [
7278
+ session.pinned ? /* @__PURE__ */ jsxRuntime.jsx(react.Check, { size: 16, className: "w-4 h-4" }) : /* @__PURE__ */ jsxRuntime.jsx(react.Bookmark, { size: 16, className: "w-4 h-4" }),
7279
+ session.pinned ? t("BiChat.Sidebar.UnpinChat") : t("BiChat.Sidebar.PinChat")
7280
+ ]
7281
+ }
7282
+ ) }),
7283
+ onRename && /* @__PURE__ */ jsxRuntime.jsx(react$1.MenuItem, { children: ({ focus, close }) => /* @__PURE__ */ jsxRuntime.jsxs(
7284
+ "button",
7285
+ {
7286
+ onClick: (e) => {
7287
+ e.preventDefault();
7288
+ e.stopPropagation();
7289
+ editableTitleRef.current?.startEditing();
7290
+ close();
7291
+ },
7292
+ className: `cursor-pointer flex w-full items-center gap-2 rounded-lg px-3 py-2 text-sm font-medium text-gray-700 dark:text-gray-200 transition-smooth ${focus ? "bg-gray-100 dark:bg-gray-800/70 ring-1 ring-gray-200/80 dark:ring-gray-700/80" : "hover:bg-gray-50 dark:hover:bg-gray-800"}`,
7293
+ "aria-label": t("BiChat.Sidebar.RenameChat"),
7294
+ "data-testid": `${testIdPrefix}-session-rename-${session.id}`,
7295
+ children: [
7296
+ /* @__PURE__ */ jsxRuntime.jsx(react.PencilSimple, { size: 16, className: "w-4 h-4" }),
7297
+ t("BiChat.Sidebar.RenameChat")
7298
+ ]
7299
+ }
7300
+ ) }),
7301
+ mode !== "archived" && onRegenerateTitle && /* @__PURE__ */ jsxRuntime.jsx(react$1.MenuItem, { children: ({ focus, close }) => /* @__PURE__ */ jsxRuntime.jsxs(
7302
+ "button",
7303
+ {
7304
+ onClick: (e) => {
7305
+ e.preventDefault();
7306
+ e.stopPropagation();
7307
+ onRegenerateTitle();
7308
+ close();
7309
+ },
7310
+ className: `cursor-pointer flex w-full items-center gap-2 rounded-lg px-3 py-2 text-sm font-medium text-gray-700 dark:text-gray-200 transition-smooth ${focus ? "bg-gray-100 dark:bg-gray-800/70 ring-1 ring-gray-200/80 dark:ring-gray-700/80" : "hover:bg-gray-50 dark:hover:bg-gray-800"}`,
7311
+ "aria-label": t("BiChat.Sidebar.RegenerateTitle"),
7312
+ "data-testid": `${testIdPrefix}-session-regenerate-${session.id}`,
7313
+ children: [
7314
+ /* @__PURE__ */ jsxRuntime.jsx(react.ArrowsClockwise, { size: 16, className: "w-4 h-4" }),
7315
+ t("BiChat.Sidebar.RegenerateTitle")
7316
+ ]
7317
+ }
7318
+ ) }),
7319
+ mode === "archived" && onRestore && /* @__PURE__ */ jsxRuntime.jsx(react$1.MenuItem, { children: ({ focus }) => /* @__PURE__ */ jsxRuntime.jsxs(
7320
+ "button",
7321
+ {
7322
+ onClick: (e) => {
7323
+ e.preventDefault();
7324
+ e.stopPropagation();
7325
+ onRestore();
7326
+ },
7327
+ className: `cursor-pointer flex w-full items-center gap-2 rounded-lg px-3 py-2 text-sm font-medium transition-smooth ${focus ? "text-green-700 dark:text-green-300 bg-green-50 dark:bg-green-900/20 ring-1 ring-green-200/70 dark:ring-green-500/30" : "text-green-700 dark:text-green-300 hover:bg-green-50/70 dark:hover:bg-green-900/10"}`,
7328
+ "aria-label": t("BiChat.Archived.RestoreButton"),
7329
+ "data-testid": `${testIdPrefix}-session-restore-${session.id}`,
7330
+ children: [
7331
+ /* @__PURE__ */ jsxRuntime.jsx(react.ArrowUUpLeft, { size: 16, className: "w-4 h-4" }),
7332
+ t("BiChat.Archived.RestoreButton")
7333
+ ]
7334
+ }
7335
+ ) }),
7336
+ mode !== "archived" && onArchive && /* @__PURE__ */ jsxRuntime.jsx(react$1.MenuItem, { children: ({ focus }) => /* @__PURE__ */ jsxRuntime.jsxs(
7337
+ "button",
7338
+ {
7339
+ onClick: (e) => {
7340
+ e.preventDefault();
7341
+ e.stopPropagation();
7342
+ onArchive();
7343
+ },
7344
+ className: `cursor-pointer flex w-full items-center gap-2 rounded-lg px-3 py-2 text-sm font-medium transition-smooth ${focus ? "text-amber-600 dark:text-amber-400 bg-amber-50 dark:bg-amber-900/20 ring-1 ring-amber-200/70 dark:ring-amber-500/30" : "text-amber-600 dark:text-amber-400 hover:bg-amber-50/70 dark:hover:bg-amber-900/10"}`,
7345
+ "aria-label": t("BiChat.Sidebar.ArchiveChat"),
7346
+ "data-testid": `${testIdPrefix}-session-archive-${session.id}`,
7347
+ children: [
7348
+ /* @__PURE__ */ jsxRuntime.jsx(react.Archive, { size: 16, className: "w-4 h-4" }),
7349
+ t("BiChat.Sidebar.ArchiveChat")
7350
+ ]
7351
+ }
7352
+ ) }),
7353
+ onDelete && /* @__PURE__ */ jsxRuntime.jsx(react$1.MenuItem, { children: ({ focus }) => /* @__PURE__ */ jsxRuntime.jsxs(
7354
+ "button",
7355
+ {
7356
+ onClick: (e) => {
7357
+ e.preventDefault();
7358
+ e.stopPropagation();
7359
+ onDelete();
7360
+ },
7361
+ className: `cursor-pointer flex w-full items-center gap-2 rounded-lg px-3 py-2 text-sm font-medium transition-smooth ${focus ? "text-red-600 dark:text-red-400 bg-red-50 dark:bg-red-900/20 ring-1 ring-red-200/70 dark:ring-red-500/30" : "text-red-600 dark:text-red-400 hover:bg-red-50/70 dark:hover:bg-red-900/10"}`,
7362
+ "aria-label": t("BiChat.Sidebar.DeleteChat"),
7363
+ "data-testid": `${testIdPrefix}-session-delete-${session.id}`,
7364
+ children: [
7365
+ /* @__PURE__ */ jsxRuntime.jsx(react.Trash, { size: 16, className: "w-4 h-4" }),
7366
+ t("BiChat.Sidebar.DeleteChat")
7367
+ ]
7368
+ }
7369
+ ) })
7307
7370
  ]
7308
7371
  }
7309
- ) })
7310
- ]
7311
- }
7312
- )
7313
- ] })
7314
- ] })
7315
- }
7316
- )
7372
+ )
7373
+ ] })
7374
+ ] })
7375
+ }
7376
+ )
7377
+ }
7378
+ )
7379
+ ]
7317
7380
  }
7318
7381
  ),
7319
7382
  /* @__PURE__ */ jsxRuntime.jsx(
@@ -7379,7 +7442,7 @@ function TabBar({ tabs, activeTab, onTabChange }) {
7379
7442
  "div",
7380
7443
  {
7381
7444
  ref: tablistRef,
7382
- className: "flex gap-1 px-4 pt-4 pb-2 border-b border-gray-200 dark:border-gray-700",
7445
+ className: "flex justify-center gap-1 px-4 pt-4 pb-2 border-b border-gray-200 dark:border-gray-700",
7383
7446
  role: "tablist",
7384
7447
  onKeyDown: handleKeyDown,
7385
7448
  children: tabs.map((tab) => /* @__PURE__ */ jsxRuntime.jsx(
@@ -7444,7 +7507,7 @@ function UserFilter({ users, selectedUser, onUserChange, loading }) {
7444
7507
  disabled:opacity-50 disabled:cursor-not-allowed
7445
7508
  flex items-center justify-between gap-2
7446
7509
  `,
7447
- "aria-label": t("allChats.allUsers"),
7510
+ "aria-label": t("BiChat.AllChats.AllUsers"),
7448
7511
  children: [
7449
7512
  selectedUser ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 min-w-0 flex-1", children: [
7450
7513
  /* @__PURE__ */ jsxRuntime.jsx(
@@ -7461,7 +7524,7 @@ function UserFilter({ users, selectedUser, onUserChange, loading }) {
7461
7524
  " ",
7462
7525
  selectedUser.lastName
7463
7526
  ] })
7464
- ] }) : /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-gray-500 dark:text-gray-400", children: loading ? t("allChats.loadingUsers") : t("allChats.allUsers") }),
7527
+ ] }) : /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-gray-500 dark:text-gray-400", children: loading ? t("BiChat.AllChats.LoadingUsers") : t("BiChat.AllChats.AllUsers") }),
7465
7528
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1 flex-shrink-0", children: [
7466
7529
  selectedUser && /* @__PURE__ */ jsxRuntime.jsx(
7467
7530
  "button",
@@ -7472,7 +7535,7 @@ function UserFilter({ users, selectedUser, onUserChange, loading }) {
7472
7535
  onUserChange(null);
7473
7536
  },
7474
7537
  className: "cursor-pointer p-1 rounded hover:bg-gray-200 dark:hover:bg-gray-600 transition-smooth",
7475
- "aria-label": t("Common.Clear"),
7538
+ "aria-label": t("BiChat.Common.Clear"),
7476
7539
  children: /* @__PURE__ */ jsxRuntime.jsx(react.X, { size: 14, className: "w-3.5 h-3.5 text-gray-600 dark:text-gray-400" })
7477
7540
  }
7478
7541
  ),
@@ -7503,7 +7566,7 @@ function UserFilter({ users, selectedUser, onUserChange, loading }) {
7503
7566
  ${focus ? "bg-gray-100 dark:bg-gray-700" : "hover:bg-gray-50 dark:hover:bg-gray-750"}
7504
7567
  ${!selectedUser ? "text-primary-700 dark:text-primary-400 font-medium" : "text-gray-900 dark:text-gray-100"}
7505
7568
  `,
7506
- children: t("allChats.allUsers")
7569
+ children: t("BiChat.AllChats.AllUsers")
7507
7570
  }
7508
7571
  ) }),
7509
7572
  users.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "border-t border-gray-200 dark:border-gray-700 my-1" }),
@@ -7536,7 +7599,7 @@ function UserFilter({ users, selectedUser, onUserChange, loading }) {
7536
7599
  ]
7537
7600
  }
7538
7601
  ) }, user.id)),
7539
- users.length === 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-3 py-6 text-center", children: /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-gray-500 dark:text-gray-400", children: t("allChats.noUsersFound") }) })
7602
+ users.length === 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-3 py-6 text-center", children: /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-gray-700 dark:text-gray-300", children: t("BiChat.AllChats.NoUsersFound") }) })
7540
7603
  ]
7541
7604
  }
7542
7605
  )
@@ -7601,7 +7664,7 @@ function AllChatsList({ dataSource, onSessionSelect, activeSessionId }) {
7601
7664
  }
7602
7665
  }).catch(() => {
7603
7666
  if (!cancelled) {
7604
- setError(t("allChats.failedToLoad"));
7667
+ setError(t("BiChat.AllChats.FailedToLoad"));
7605
7668
  setFetching(false);
7606
7669
  }
7607
7670
  });
@@ -7667,12 +7730,12 @@ function AllChatsList({ dataSource, onSessionSelect, activeSessionId }) {
7667
7730
  ),
7668
7731
  /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-sm text-gray-700 dark:text-gray-300 flex items-center gap-1.5", children: [
7669
7732
  /* @__PURE__ */ jsxRuntime.jsx(react.Archive, { size: 16, className: "w-4 h-4" }),
7670
- t("allChats.includeArchived")
7733
+ t("BiChat.AllChats.IncludeArchived")
7671
7734
  ] })
7672
7735
  ] }),
7673
- totalCount > 0 && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-gray-500 dark:text-gray-400", children: totalCount === 1 ? t("allChats.chatFound", { count: totalCount }) : t("allChats.chatsFound", { count: totalCount }) })
7736
+ totalCount > 0 && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-gray-500 dark:text-gray-400", children: totalCount === 1 ? t("BiChat.AllChats.ChatFound", { count: totalCount }) : t("BiChat.AllChats.ChatsFound", { count: totalCount }) })
7674
7737
  ] }),
7675
- /* @__PURE__ */ jsxRuntime.jsxs("nav", { className: "flex-1 overflow-y-auto px-2 pb-4 hide-scrollbar", "aria-label": t("allChats.organizationChats"), children: [
7738
+ /* @__PURE__ */ jsxRuntime.jsxs("nav", { className: "flex-1 overflow-y-auto px-2 pb-4 hide-scrollbar", "aria-label": t("BiChat.AllChats.OrganizationChats"), children: [
7676
7739
  fetching && chats.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx(SessionSkeleton, { count: 5 }) : /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: chats.length > 0 ? /* @__PURE__ */ jsxRuntime.jsxs(
7677
7740
  framerMotion.motion.div,
7678
7741
  {
@@ -7681,7 +7744,7 @@ function AllChatsList({ dataSource, onSessionSelect, activeSessionId }) {
7681
7744
  initial: "hidden",
7682
7745
  animate: "visible",
7683
7746
  role: "list",
7684
- "aria-label": t("allChats.organizationChatSessions"),
7747
+ "aria-label": t("BiChat.AllChats.OrganizationChatSessions"),
7685
7748
  children: [
7686
7749
  chats.map((chat) => /* @__PURE__ */ jsxRuntime.jsx(
7687
7750
  framerMotion.motion.div,
@@ -7717,7 +7780,7 @@ function AllChatsList({ dataSource, onSessionSelect, activeSessionId }) {
7717
7780
  }
7718
7781
  ),
7719
7782
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 min-w-0", children: [
7720
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-medium truncate", children: chat.title || t("Common.Untitled") }),
7783
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-medium truncate", children: chat.title || t("BiChat.Common.Untitled") }),
7721
7784
  /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-xs text-gray-500 dark:text-gray-400 truncate", children: [
7722
7785
  chat.owner.firstName,
7723
7786
  " ",
@@ -7725,7 +7788,7 @@ function AllChatsList({ dataSource, onSessionSelect, activeSessionId }) {
7725
7788
  ] }),
7726
7789
  chat.status === "archived" && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "inline-flex items-center gap-1 mt-1 px-2 py-0.5 bg-gray-100 dark:bg-gray-800 text-gray-600 dark:text-gray-400 rounded-full text-xs", children: [
7727
7790
  /* @__PURE__ */ jsxRuntime.jsx(react.Archive, { size: 12, className: "w-3 h-3" }),
7728
- t("Chat.Archived")
7791
+ t("BiChat.Chat.Archived")
7729
7792
  ] })
7730
7793
  ] })
7731
7794
  ] })
@@ -7739,7 +7802,7 @@ function AllChatsList({ dataSource, onSessionSelect, activeSessionId }) {
7739
7802
  {
7740
7803
  onClick: handleLoadMore,
7741
7804
  className: "text-sm text-primary-600 dark:text-primary-400 hover:underline",
7742
- children: t("allChats.loadMore")
7805
+ children: t("BiChat.AllChats.LoadMore")
7743
7806
  }
7744
7807
  ) })
7745
7808
  ]
@@ -7747,8 +7810,8 @@ function AllChatsList({ dataSource, onSessionSelect, activeSessionId }) {
7747
7810
  ) : /* @__PURE__ */ jsxRuntime.jsx(
7748
7811
  MemoizedEmptyState,
7749
7812
  {
7750
- title: t("allChats.noChatsFound"),
7751
- description: selectedUser ? t("allChats.noChatsFromUser", { firstName: selectedUser.firstName, lastName: selectedUser.lastName }) : includeArchived ? t("allChats.noChatsInOrg") : t("allChats.noActiveChatsInOrg")
7813
+ title: t("BiChat.AllChats.NoChatsFound"),
7814
+ description: selectedUser ? t("BiChat.AllChats.NoChatsFromUser", { firstName: selectedUser.firstName, lastName: selectedUser.lastName }) : includeArchived ? t("BiChat.AllChats.NoChatsInOrg") : t("BiChat.AllChats.NoActiveChatsInOrg")
7752
7815
  }
7753
7816
  ) }),
7754
7817
  error && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mx-2 mt-4 p-3 bg-red-50 dark:bg-red-900/20 border border-red-200 dark:border-red-800 rounded-lg", children: /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-red-600 dark:text-red-400", children: error }) })
@@ -7792,11 +7855,11 @@ function groupSessionsByDate(sessions, t) {
7792
7855
  const today = dateFns.startOfDay(now);
7793
7856
  const translate = t || ((key2) => key2);
7794
7857
  const dateLabels = {
7795
- "Today": translate("DateGroup.Today"),
7796
- "Yesterday": translate("DateGroup.Yesterday"),
7797
- "Last 7 Days": translate("DateGroup.Last7Days"),
7798
- "Last 30 Days": translate("DateGroup.Last30Days"),
7799
- "Older": translate("DateGroup.Older")
7858
+ "Today": translate("BiChat.DateGroup.Today"),
7859
+ "Yesterday": translate("BiChat.DateGroup.Yesterday"),
7860
+ "Last 7 Days": translate("BiChat.DateGroup.Last7Days"),
7861
+ "Last 30 Days": translate("BiChat.DateGroup.Last30Days"),
7862
+ "Older": translate("BiChat.DateGroup.Older")
7800
7863
  };
7801
7864
  const groupMap = /* @__PURE__ */ new Map([
7802
7865
  ["Today", []],
@@ -7833,6 +7896,113 @@ function groupSessionsByDate(sessions, t) {
7833
7896
  });
7834
7897
  return groups;
7835
7898
  }
7899
+
7900
+ // ui/src/bichat/utils/errorDisplay.ts
7901
+ function isPermissionDeniedError(error) {
7902
+ if (!error) return false;
7903
+ if (error instanceof Error) {
7904
+ const msg = error.message.toLowerCase();
7905
+ if (msg.includes("forbidden") || msg.includes("permission denied")) return true;
7906
+ }
7907
+ if (typeof error === "object" && error !== null) {
7908
+ const obj = error;
7909
+ if (obj.code === "forbidden" || obj.code === 403) return true;
7910
+ if (obj.status === 403) return true;
7911
+ if (obj.statusCode === 403) return true;
7912
+ if (typeof obj.response === "object" && obj.response !== null) {
7913
+ const resp = obj.response;
7914
+ if (resp.status === 403) return true;
7915
+ }
7916
+ }
7917
+ if (typeof error === "string") {
7918
+ const lower = error.toLowerCase();
7919
+ if (lower.includes("forbidden") || lower.includes("permission denied")) return true;
7920
+ }
7921
+ return false;
7922
+ }
7923
+ function toErrorDisplay(error, fallbackTitle) {
7924
+ const permDenied = isPermissionDeniedError(error);
7925
+ let title = fallbackTitle;
7926
+ let description = "";
7927
+ if (error instanceof Error) {
7928
+ description = error.message;
7929
+ } else if (typeof error === "object" && error !== null) {
7930
+ const obj = error;
7931
+ if (typeof obj.message === "string" && obj.message) description = obj.message;
7932
+ if (typeof obj.title === "string" && obj.title) title = obj.title;
7933
+ if (typeof obj.detail === "string" && obj.detail) description = obj.detail;
7934
+ } else if (typeof error === "string") {
7935
+ description = error;
7936
+ }
7937
+ if (permDenied && !description) {
7938
+ description = "Your account does not have permission for this action.";
7939
+ }
7940
+ return { title, description, isPermissionDenied: permDenied };
7941
+ }
7942
+ function ErrorAlert({ error }) {
7943
+ const amber = error.isPermissionDenied;
7944
+ return /* @__PURE__ */ jsxRuntime.jsxs(
7945
+ "div",
7946
+ {
7947
+ className: `mx-2 mt-4 p-3 border rounded-xl cursor-default ${amber ? "bg-amber-50 dark:bg-amber-900/20 border-amber-200 dark:border-amber-800" : "bg-red-50 dark:bg-red-900/20 border-red-200 dark:border-red-800"}`,
7948
+ children: [
7949
+ /* @__PURE__ */ jsxRuntime.jsx(
7950
+ "p",
7951
+ {
7952
+ className: `text-xs font-medium ${amber ? "text-amber-700 dark:text-amber-300" : "text-red-600 dark:text-red-400"}`,
7953
+ children: error.title
7954
+ }
7955
+ ),
7956
+ error.description && /* @__PURE__ */ jsxRuntime.jsx(
7957
+ "p",
7958
+ {
7959
+ className: `mt-1 text-xs ${amber ? "text-amber-600 dark:text-amber-400" : "text-red-500 dark:text-red-300"}`,
7960
+ children: error.description
7961
+ }
7962
+ )
7963
+ ]
7964
+ }
7965
+ );
7966
+ }
7967
+ var COLLAPSE_STORAGE_KEY = "bichat-sidebar-collapsed";
7968
+ function useSidebarCollapse() {
7969
+ const [isCollapsed, setIsCollapsed] = React.useState(() => {
7970
+ try {
7971
+ return localStorage.getItem(COLLAPSE_STORAGE_KEY) === "true";
7972
+ } catch {
7973
+ return false;
7974
+ }
7975
+ });
7976
+ const isCollapsedRef = React.useRef(isCollapsed);
7977
+ React.useEffect(() => {
7978
+ isCollapsedRef.current = isCollapsed;
7979
+ }, [isCollapsed]);
7980
+ const toggle = React.useCallback(() => {
7981
+ setIsCollapsed((prev) => {
7982
+ const next = !prev;
7983
+ try {
7984
+ localStorage.setItem(COLLAPSE_STORAGE_KEY, String(next));
7985
+ } catch {
7986
+ }
7987
+ return next;
7988
+ });
7989
+ }, []);
7990
+ const expand = React.useCallback(() => {
7991
+ setIsCollapsed(false);
7992
+ try {
7993
+ localStorage.setItem(COLLAPSE_STORAGE_KEY, "false");
7994
+ } catch {
7995
+ }
7996
+ }, []);
7997
+ const collapse = React.useCallback(() => {
7998
+ setIsCollapsed(true);
7999
+ try {
8000
+ localStorage.setItem(COLLAPSE_STORAGE_KEY, "true");
8001
+ } catch {
8002
+ }
8003
+ }, []);
8004
+ return { isCollapsed, isCollapsedRef, toggle, expand, collapse };
8005
+ }
7836
8006
  function Sidebar2({
7837
8007
  dataSource,
7838
8008
  onSessionSelect,
@@ -7851,30 +8021,84 @@ function Sidebar2({
7851
8021
  const toast = useToast();
7852
8022
  const shouldReduceMotion = framerMotion.useReducedMotion();
7853
8023
  const sessionListRef = React.useRef(null);
8024
+ const searchContainerRef = React.useRef(null);
8025
+ const { isCollapsed, isCollapsedRef, toggle, expand, collapse } = useSidebarCollapse();
8026
+ const collapsible = !onClose;
8027
+ const handleSidebarClick = React.useCallback(
8028
+ (e) => {
8029
+ if (!collapsible) return;
8030
+ const interactive = 'a, button, input, summary, [role="button"]';
8031
+ if (e.target.closest(interactive)) return;
8032
+ toggle();
8033
+ },
8034
+ [collapsible, toggle]
8035
+ );
8036
+ const focusSearch = React.useCallback(() => {
8037
+ if (!collapsible) return;
8038
+ if (isCollapsedRef.current) {
8039
+ expand();
8040
+ setTimeout(() => {
8041
+ searchContainerRef.current?.querySelector("input")?.focus();
8042
+ }, 250);
8043
+ } else {
8044
+ searchContainerRef.current?.querySelector("input")?.focus();
8045
+ }
8046
+ }, [collapsible, expand, isCollapsedRef]);
8047
+ React.useEffect(() => {
8048
+ if (!collapsible) return;
8049
+ const handleKeyDown = (e) => {
8050
+ const isMod = e.metaKey || e.ctrlKey;
8051
+ if (isMod && e.key === "b") {
8052
+ e.preventDefault();
8053
+ toggle();
8054
+ }
8055
+ if (isMod && e.key === "k") {
8056
+ e.preventDefault();
8057
+ focusSearch();
8058
+ }
8059
+ };
8060
+ document.addEventListener("keydown", handleKeyDown);
8061
+ return () => document.removeEventListener("keydown", handleKeyDown);
8062
+ }, [collapsible, toggle, focusSearch]);
8063
+ React.useEffect(() => {
8064
+ if (!collapsible) return;
8065
+ const handler = (e) => {
8066
+ const detail = e.detail;
8067
+ if (detail?.expanded) {
8068
+ collapse();
8069
+ }
8070
+ };
8071
+ window.addEventListener("bichat:artifacts-panel-expanded", handler);
8072
+ return () => window.removeEventListener("bichat:artifacts-panel-expanded", handler);
8073
+ }, [collapsible, collapse]);
8074
+ const showCollapsed = collapsible && isCollapsed;
7854
8075
  const [activeTab, setActiveTab] = React.useState("my-chats");
7855
8076
  const [searchQuery, setSearchQuery] = React.useState("");
7856
8077
  const [sessions, setSessions] = React.useState([]);
7857
8078
  const [loading, setLoading] = React.useState(true);
7858
- const [error, setError] = React.useState(null);
8079
+ const [loadError, setLoadError] = React.useState(null);
8080
+ const [actionError, setActionError] = React.useState(null);
8081
+ const accessDenied = loadError?.isPermissionDenied === true;
7859
8082
  const [refreshKey, setRefreshKey] = React.useState(0);
7860
8083
  const [showConfirm, setShowConfirm] = React.useState(false);
7861
8084
  const [sessionToArchive, setSessionToArchive] = React.useState(null);
7862
8085
  const tabs = React.useMemo(() => {
7863
- const items = [{ id: "my-chats", label: t("Sidebar.MyChats") }];
8086
+ const items = [{ id: "my-chats", label: t("BiChat.Sidebar.MyChats") }];
7864
8087
  if (showAllChatsTab) {
7865
- items.push({ id: "all-chats", label: t("Sidebar.AllChats") });
8088
+ items.push({ id: "all-chats", label: t("BiChat.Sidebar.AllChats") });
7866
8089
  }
7867
8090
  return items;
7868
8091
  }, [showAllChatsTab, t]);
7869
8092
  const fetchSessions = React.useCallback(async () => {
7870
8093
  try {
7871
8094
  setLoading(true);
7872
- setError(null);
8095
+ setLoadError(null);
8096
+ setActionError(null);
7873
8097
  const result = await dataSource.listSessions({ limit: 50 });
7874
8098
  setSessions(result.sessions);
7875
8099
  } catch (err) {
7876
8100
  console.error("Failed to load sessions:", err);
7877
- setError(t("Sidebar.FailedToLoadSessions"));
8101
+ setLoadError(toErrorDisplay(err, t("BiChat.Sidebar.FailedToLoadSessions")));
7878
8102
  } finally {
7879
8103
  setLoading(false);
7880
8104
  }
@@ -7883,7 +8107,7 @@ function Sidebar2({
7883
8107
  fetchSessions();
7884
8108
  }, [fetchSessions, refreshKey]);
7885
8109
  const hasPlaceholderTitles = React.useMemo(() => {
7886
- const newChatLabel = t("Chat.NewChat");
8110
+ const newChatLabel = t("BiChat.Chat.NewChat");
7887
8111
  return Array.isArray(sessions) && sessions.some((s) => s && (!s.title || s.title === newChatLabel));
7888
8112
  }, [sessions, t]);
7889
8113
  React.useEffect(() => {
@@ -7919,7 +8143,9 @@ function Sidebar2({
7919
8143
  }
7920
8144
  } catch (err) {
7921
8145
  console.error("Failed to archive session:", err);
7922
- toast.error(t("Sidebar.FailedToArchiveChat"));
8146
+ const display = toErrorDisplay(err, t("BiChat.Sidebar.FailedToArchiveChat"));
8147
+ setActionError(display);
8148
+ toast.error(display.title);
7923
8149
  } finally {
7924
8150
  setShowConfirm(false);
7925
8151
  setSessionToArchive(null);
@@ -7935,27 +8161,33 @@ function Sidebar2({
7935
8161
  setRefreshKey((k) => k + 1);
7936
8162
  } catch (err) {
7937
8163
  console.error("Failed to toggle pin:", err);
7938
- toast.error(t("Sidebar.FailedToTogglePin"));
8164
+ const display = toErrorDisplay(err, t("BiChat.Sidebar.FailedToTogglePin"));
8165
+ setActionError(display);
8166
+ toast.error(display.title);
7939
8167
  }
7940
8168
  };
7941
8169
  const handleRenameSession = async (sessionId, newTitle) => {
7942
8170
  try {
7943
8171
  await dataSource.renameSession(sessionId, newTitle);
7944
- toast.success(t("Sidebar.ChatRenamedSuccessfully"));
8172
+ toast.success(t("BiChat.Sidebar.ChatRenamedSuccessfully"));
7945
8173
  setRefreshKey((k) => k + 1);
7946
8174
  } catch (err) {
7947
8175
  console.error("Failed to update session title:", err);
7948
- toast.error(t("Sidebar.FailedToRenameChat"));
8176
+ const display = toErrorDisplay(err, t("BiChat.Sidebar.FailedToRenameChat"));
8177
+ setActionError(display);
8178
+ toast.error(display.title);
7949
8179
  }
7950
8180
  };
7951
8181
  const handleRegenerateTitle = async (sessionId) => {
7952
8182
  try {
7953
8183
  await dataSource.regenerateSessionTitle(sessionId);
7954
- toast.success(t("Sidebar.TitleRegenerated"));
8184
+ toast.success(t("BiChat.Sidebar.TitleRegenerated"));
7955
8185
  setRefreshKey((k) => k + 1);
7956
8186
  } catch (err) {
7957
8187
  console.error("Failed to regenerate title:", err);
7958
- toast.error(t("Sidebar.FailedToRegenerateTitle"));
8188
+ const display = toErrorDisplay(err, t("BiChat.Sidebar.FailedToRegenerateTitle"));
8189
+ setActionError(display);
8190
+ toast.error(display.title);
7959
8191
  }
7960
8192
  };
7961
8193
  const filteredSessions = React.useMemo(() => {
@@ -8018,176 +8250,311 @@ function Sidebar2({
8018
8250
  /* @__PURE__ */ jsxRuntime.jsxs(
8019
8251
  "aside",
8020
8252
  {
8021
- className: `w-64 bg-surface-300 dark:bg-gray-900 border-r border-gray-200 dark:border-gray-700 h-full min-h-0 flex flex-col overflow-hidden ${className}`,
8253
+ onClick: collapsible ? handleSidebarClick : void 0,
8254
+ className: `relative bg-surface-300 dark:bg-gray-900 border-r border-gray-200 dark:border-gray-700 h-full min-h-0 flex flex-col overflow-hidden transition-[width] duration-300 ease-in-out ${showCollapsed ? "w-16 cursor-e-resize" : collapsible ? "w-64 cursor-w-resize" : "w-64"} ${className}`,
8255
+ style: { willChange: "width" },
8022
8256
  role: "navigation",
8023
- "aria-label": t("Sidebar.ChatSessions"),
8257
+ "aria-label": t("BiChat.Sidebar.ChatSessions"),
8024
8258
  children: [
8025
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "p-4 border-b border-gray-200 dark:border-gray-700 flex items-center justify-between", children: [
8026
- headerSlot,
8027
- onClose && /* @__PURE__ */ jsxRuntime.jsx(
8028
- framerMotion.motion.button,
8029
- {
8030
- onClick: onClose,
8031
- className: "cursor-pointer p-2 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-800 transition-smooth text-gray-600 dark:text-gray-400",
8032
- title: t("Sidebar.CloseSidebar"),
8033
- "aria-label": t("Sidebar.CloseSidebar"),
8034
- whileHover: "hover",
8035
- whileTap: "tap",
8036
- variants: buttonVariants,
8037
- children: /* @__PURE__ */ jsxRuntime.jsx(react.X, { size: 20, className: "w-5 h-5" })
8038
- }
8039
- )
8040
- ] }),
8041
- showAllChatsTab && /* @__PURE__ */ jsxRuntime.jsx(
8042
- TabBar_default,
8259
+ collapsible && /* @__PURE__ */ jsxRuntime.jsx(
8260
+ "div",
8043
8261
  {
8044
- tabs,
8045
- activeTab,
8046
- onTabChange: (id) => setActiveTab(id)
8262
+ className: `absolute inset-x-0 top-0 bottom-0 z-10 flex flex-col items-center pt-3 gap-3 transition-opacity ${showCollapsed ? "opacity-100 duration-150 delay-100" : "opacity-0 pointer-events-none duration-100"}`,
8263
+ children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "group/tooltip relative", children: [
8264
+ /* @__PURE__ */ jsxRuntime.jsx(
8265
+ framerMotion.motion.button,
8266
+ {
8267
+ onClick: (e) => {
8268
+ e.stopPropagation();
8269
+ onNewChat();
8270
+ },
8271
+ disabled: creating || loading || accessDenied,
8272
+ className: "w-10 h-10 rounded-lg bg-primary-600 hover:bg-primary-700 active:bg-primary-800 text-white shadow-sm flex items-center justify-center disabled:opacity-40 disabled:cursor-not-allowed cursor-pointer transition-colors focus-visible:ring-2 focus-visible:ring-primary-400/50",
8273
+ title: t("BiChat.Chat.NewChat"),
8274
+ "aria-label": t("BiChat.Sidebar.CreateNewChat"),
8275
+ whileTap: { scale: 0.95 },
8276
+ children: creating ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-4 h-4 border-2 border-white/50 border-t-transparent rounded-full animate-spin" }) : /* @__PURE__ */ jsxRuntime.jsx(react.Plus, { size: 18, weight: "bold" })
8277
+ }
8278
+ ),
8279
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "pointer-events-none absolute left-full ml-2 top-1/2 -translate-y-1/2 rounded-md bg-gray-900 dark:bg-gray-100 px-2 py-1 text-xs font-medium text-white dark:text-gray-900 opacity-0 group-hover/tooltip:opacity-100 transition-opacity whitespace-nowrap shadow-lg", children: t("BiChat.Chat.NewChat") })
8280
+ ] })
8047
8281
  }
8048
8282
  ),
8049
- activeTab === "all-chats" && showAllChatsTab ? /* @__PURE__ */ jsxRuntime.jsx(
8050
- AllChatsList,
8283
+ /* @__PURE__ */ jsxRuntime.jsxs(
8284
+ "div",
8051
8285
  {
8052
- dataSource,
8053
- onSessionSelect,
8054
- activeSessionId
8055
- }
8056
- ) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
8057
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-3", children: /* @__PURE__ */ jsxRuntime.jsx(
8058
- SearchInput_default,
8059
- {
8060
- value: searchQuery,
8061
- onChange: setSearchQuery,
8062
- placeholder: t("Sidebar.SearchChats")
8063
- }
8064
- ) }),
8065
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-4", children: /* @__PURE__ */ jsxRuntime.jsx(
8066
- framerMotion.motion.button,
8067
- {
8068
- onClick: onNewChat,
8069
- disabled: creating || loading,
8070
- className: "cursor-pointer w-full px-4 py-3 bg-primary-600 dark:bg-primary-700 text-white rounded-lg hover:bg-primary-700 dark:hover:bg-primary-800 transition-smooth font-medium disabled:opacity-50 disabled:cursor-not-allowed flex items-center justify-center",
8071
- title: t("Chat.NewChat"),
8072
- "aria-label": t("Sidebar.CreateNewChat"),
8073
- whileHover: shouldReduceMotion ? {} : { scale: 1.02 },
8074
- whileTap: shouldReduceMotion ? {} : { scale: 0.95 },
8075
- children: creating ? /* @__PURE__ */ jsxRuntime.jsx(LoadingSpinner_default, { variant: "spinner", size: "sm" }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
8076
- /* @__PURE__ */ jsxRuntime.jsx(react.Plus, { size: 20, className: "w-5 h-5" }),
8077
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ml-2", children: t("Chat.NewChat") })
8078
- ] })
8079
- }
8080
- ) }),
8081
- onArchivedView && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-4 pb-2", children: /* @__PURE__ */ jsxRuntime.jsxs(
8082
- "button",
8083
- {
8084
- onClick: onArchivedView,
8085
- className: "cursor-pointer flex items-center gap-2 px-3 py-2 rounded-lg text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-800 transition-smooth text-sm font-medium w-full",
8086
- title: t("Sidebar.ArchivedChats"),
8087
- children: [
8088
- /* @__PURE__ */ jsxRuntime.jsx(react.Archive, { size: 18, className: "w-4.5 h-4.5" }),
8089
- /* @__PURE__ */ jsxRuntime.jsx("span", { children: t("Sidebar.ArchivedChats") })
8090
- ]
8091
- }
8092
- ) }),
8093
- /* @__PURE__ */ jsxRuntime.jsxs(
8094
- "nav",
8095
- {
8096
- ref: sessionListRef,
8097
- className: "flex-1 overflow-y-auto px-2 pb-4 hide-scrollbar",
8098
- "aria-label": "Chat history",
8099
- onKeyDown: handleSessionListKeyDown,
8100
- children: [
8101
- loading && sessions.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx(SessionSkeleton, { count: 5 }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
8102
- pinnedSessions.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mb-4", children: [
8103
- /* @__PURE__ */ jsxRuntime.jsx(
8104
- DateGroupHeader,
8105
- {
8106
- groupName: t("Common.Pinned"),
8107
- count: pinnedSessions.length
8108
- }
8109
- ),
8110
- /* @__PURE__ */ jsxRuntime.jsx(
8111
- framerMotion.motion.div,
8112
- {
8113
- className: "space-y-1 mt-2",
8114
- variants: staggerContainerVariants,
8115
- initial: "hidden",
8116
- animate: "visible",
8117
- role: "list",
8118
- "aria-label": t("Sidebar.PinnedChats"),
8119
- children: pinnedSessions.map((session) => /* @__PURE__ */ jsxRuntime.jsx(
8120
- SessionItem_default,
8121
- {
8122
- session,
8123
- isActive: session.id === activeSessionId,
8124
- onSelect: () => onSessionSelect(session.id),
8125
- onArchive: () => handleArchiveRequest(session.id),
8126
- onPin: () => handleTogglePin(session.id, session.pinned),
8127
- onRename: (newTitle) => handleRenameSession(session.id, newTitle),
8128
- onRegenerateTitle: () => handleRegenerateTitle(session.id)
8129
- },
8130
- session.id
8131
- ))
8132
- }
8133
- ),
8134
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "border-b border-gray-200 dark:border-gray-700 my-3" })
8135
- ] }),
8136
- sessionGroups.map((group) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mb-4", children: [
8137
- /* @__PURE__ */ jsxRuntime.jsx(
8138
- DateGroupHeader,
8139
- {
8140
- groupName: group.name,
8141
- count: group.sessions.length
8142
- }
8143
- ),
8144
- /* @__PURE__ */ jsxRuntime.jsx(
8145
- framerMotion.motion.div,
8146
- {
8147
- className: "space-y-1 mt-2",
8148
- variants: staggerContainerVariants,
8149
- initial: "hidden",
8150
- animate: "visible",
8151
- role: "list",
8152
- "aria-label": `${group.name} chats`,
8153
- children: group.sessions.map((session) => /* @__PURE__ */ jsxRuntime.jsx(
8154
- SessionItem_default,
8286
+ className: `flex flex-col flex-1 min-h-0 w-64 shrink-0 transition-opacity ${showCollapsed ? "opacity-0 pointer-events-none duration-100" : collapsible ? "opacity-100 duration-150 delay-[200ms]" : ""}`,
8287
+ children: [
8288
+ (headerSlot || onClose) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "p-4 border-b border-gray-200 dark:border-gray-700 flex items-center justify-between", children: [
8289
+ headerSlot,
8290
+ onClose && /* @__PURE__ */ jsxRuntime.jsx(
8291
+ framerMotion.motion.button,
8292
+ {
8293
+ onClick: onClose,
8294
+ className: "cursor-pointer p-2 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-800 transition-smooth text-gray-600 dark:text-gray-400",
8295
+ title: t("BiChat.Sidebar.CloseSidebar"),
8296
+ "aria-label": t("BiChat.Sidebar.CloseSidebar"),
8297
+ whileHover: "hover",
8298
+ whileTap: "tap",
8299
+ variants: buttonVariants,
8300
+ children: /* @__PURE__ */ jsxRuntime.jsx(react.X, { size: 20, className: "w-5 h-5" })
8301
+ }
8302
+ )
8303
+ ] }),
8304
+ showAllChatsTab && /* @__PURE__ */ jsxRuntime.jsx(
8305
+ TabBar_default,
8306
+ {
8307
+ tabs,
8308
+ activeTab,
8309
+ onTabChange: (id) => setActiveTab(id)
8310
+ }
8311
+ ),
8312
+ activeTab === "all-chats" && showAllChatsTab ? /* @__PURE__ */ jsxRuntime.jsx(
8313
+ AllChatsList,
8314
+ {
8315
+ dataSource,
8316
+ onSessionSelect,
8317
+ activeSessionId
8318
+ }
8319
+ ) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
8320
+ /* @__PURE__ */ jsxRuntime.jsx("div", { ref: searchContainerRef, className: "mt-3 px-4", children: /* @__PURE__ */ jsxRuntime.jsx(
8321
+ SearchInput_default,
8322
+ {
8323
+ value: searchQuery,
8324
+ onChange: setSearchQuery,
8325
+ placeholder: t("BiChat.Sidebar.SearchChats")
8326
+ }
8327
+ ) }),
8328
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-4", children: /* @__PURE__ */ jsxRuntime.jsx(
8329
+ framerMotion.motion.button,
8330
+ {
8331
+ onClick: (e) => {
8332
+ e.stopPropagation();
8333
+ onNewChat();
8334
+ },
8335
+ disabled: creating || loading || accessDenied,
8336
+ className: "cursor-pointer w-full px-4 py-2.5 bg-primary-600 dark:bg-primary-700 text-white rounded-lg hover:bg-primary-700 hover:-translate-y-0.5 active:bg-primary-800 transition-all duration-150 font-medium shadow-sm disabled:opacity-40 disabled:cursor-not-allowed flex items-center justify-center gap-2 focus-visible:ring-2 focus-visible:ring-primary-400/50 focus-visible:ring-offset-2 dark:focus-visible:ring-offset-gray-900",
8337
+ title: accessDenied ? t("BiChat.Sidebar.MissingPermission") : t("BiChat.Chat.NewChat"),
8338
+ "aria-label": t("BiChat.Sidebar.CreateNewChat"),
8339
+ whileHover: shouldReduceMotion ? {} : { y: -1 },
8340
+ whileTap: shouldReduceMotion ? {} : { scale: 0.98 },
8341
+ children: creating ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
8342
+ /* @__PURE__ */ jsxRuntime.jsx(LoadingSpinner_default, { variant: "spinner", size: "sm" }),
8343
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: t("BiChat.Common.Creating") })
8344
+ ] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
8345
+ /* @__PURE__ */ jsxRuntime.jsx(react.Plus, { size: 16, weight: "bold" }),
8346
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: t("BiChat.Chat.NewChat") })
8347
+ ] })
8348
+ }
8349
+ ) }),
8350
+ /* @__PURE__ */ jsxRuntime.jsxs(
8351
+ "nav",
8352
+ {
8353
+ ref: sessionListRef,
8354
+ className: "flex-1 overflow-y-auto px-2 pb-4 hide-scrollbar",
8355
+ "aria-label": t("BiChat.Sidebar.ChatHistory"),
8356
+ onKeyDown: handleSessionListKeyDown,
8357
+ children: [
8358
+ loading && sessions.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx(SessionSkeleton, { count: 5 }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
8359
+ pinnedSessions.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mb-4", children: [
8360
+ /* @__PURE__ */ jsxRuntime.jsx(
8361
+ DateGroupHeader,
8362
+ {
8363
+ groupName: t("BiChat.Common.Pinned"),
8364
+ count: pinnedSessions.length
8365
+ }
8366
+ ),
8367
+ /* @__PURE__ */ jsxRuntime.jsx(
8368
+ framerMotion.motion.div,
8369
+ {
8370
+ className: "space-y-1 mt-2",
8371
+ variants: staggerContainerVariants,
8372
+ initial: "hidden",
8373
+ animate: "visible",
8374
+ role: "list",
8375
+ "aria-label": t("BiChat.Sidebar.PinnedChats"),
8376
+ children: pinnedSessions.map((session) => /* @__PURE__ */ jsxRuntime.jsx(
8377
+ SessionItem_default,
8378
+ {
8379
+ session,
8380
+ isActive: session.id === activeSessionId,
8381
+ onSelect: () => onSessionSelect(session.id),
8382
+ onArchive: () => handleArchiveRequest(session.id),
8383
+ onPin: () => handleTogglePin(session.id, session.pinned),
8384
+ onRename: (newTitle) => handleRenameSession(session.id, newTitle),
8385
+ onRegenerateTitle: () => handleRegenerateTitle(session.id)
8386
+ },
8387
+ session.id
8388
+ ))
8389
+ }
8390
+ ),
8391
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "border-b border-gray-200 dark:border-gray-700 my-3" })
8392
+ ] }),
8393
+ sessionGroups.map((group) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mb-4", children: [
8394
+ /* @__PURE__ */ jsxRuntime.jsx(
8395
+ DateGroupHeader,
8396
+ {
8397
+ groupName: group.name,
8398
+ count: group.sessions.length
8399
+ }
8400
+ ),
8401
+ /* @__PURE__ */ jsxRuntime.jsx(
8402
+ framerMotion.motion.div,
8403
+ {
8404
+ className: "space-y-1 mt-2",
8405
+ variants: staggerContainerVariants,
8406
+ initial: "hidden",
8407
+ animate: "visible",
8408
+ role: "list",
8409
+ "aria-label": `${group.name} chats`,
8410
+ children: group.sessions.map((session) => /* @__PURE__ */ jsxRuntime.jsx(
8411
+ SessionItem_default,
8412
+ {
8413
+ session,
8414
+ isActive: session.id === activeSessionId,
8415
+ onSelect: () => onSessionSelect(session.id),
8416
+ onArchive: () => handleArchiveRequest(session.id),
8417
+ onPin: () => handleTogglePin(session.id, session.pinned),
8418
+ onRename: (newTitle) => handleRenameSession(session.id, newTitle),
8419
+ onRegenerateTitle: () => handleRegenerateTitle(session.id)
8420
+ },
8421
+ session.id
8422
+ ))
8423
+ }
8424
+ )
8425
+ ] }, group.name)),
8426
+ filteredSessions.length === 0 && !loading && /* @__PURE__ */ jsxRuntime.jsx(
8427
+ MemoizedEmptyState,
8155
8428
  {
8156
- session,
8157
- isActive: session.id === activeSessionId,
8158
- onSelect: () => onSessionSelect(session.id),
8159
- onArchive: () => handleArchiveRequest(session.id),
8160
- onPin: () => handleTogglePin(session.id, session.pinned),
8161
- onRename: (newTitle) => handleRenameSession(session.id, newTitle),
8162
- onRegenerateTitle: () => handleRegenerateTitle(session.id)
8163
- },
8164
- session.id
8165
- ))
8166
- }
8167
- )
8168
- ] }, group.name)),
8169
- filteredSessions.length === 0 && !loading && /* @__PURE__ */ jsxRuntime.jsx(
8170
- MemoizedEmptyState,
8429
+ title: searchQuery ? t("BiChat.Sidebar.NoChatsFound", { query: searchQuery }) : t("BiChat.Sidebar.NoChatsYet"),
8430
+ description: searchQuery ? void 0 : t("BiChat.Sidebar.CreateOneToGetStarted"),
8431
+ action: searchQuery ? /* @__PURE__ */ jsxRuntime.jsx(
8432
+ "button",
8433
+ {
8434
+ onClick: () => setSearchQuery(""),
8435
+ className: "cursor-pointer text-sm text-primary-600 dark:text-primary-400 hover:underline",
8436
+ children: t("BiChat.Common.Clear")
8437
+ }
8438
+ ) : void 0
8439
+ }
8440
+ )
8441
+ ] }),
8442
+ loadError && /* @__PURE__ */ jsxRuntime.jsx(ErrorAlert, { error: loadError }),
8443
+ actionError && !loadError && /* @__PURE__ */ jsxRuntime.jsx(ErrorAlert, { error: actionError })
8444
+ ]
8445
+ }
8446
+ ),
8447
+ footerSlot
8448
+ ] }),
8449
+ collapsible && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-auto border-t border-gray-100 dark:border-gray-800/80 px-4 py-3 flex items-center justify-between", children: [
8450
+ onArchivedView || showAllChatsTab ? /* @__PURE__ */ jsxRuntime.jsxs(react$1.Menu, { children: [
8451
+ /* @__PURE__ */ jsxRuntime.jsx(
8452
+ react$1.MenuButton,
8171
8453
  {
8172
- title: searchQuery ? t("Sidebar.NoChatsFound", { query: searchQuery }) : t("Sidebar.NoChatsYet"),
8173
- description: searchQuery ? void 0 : t("Sidebar.CreateOneToGetStarted"),
8174
- action: searchQuery ? /* @__PURE__ */ jsxRuntime.jsx(
8175
- "button",
8176
- {
8177
- onClick: () => setSearchQuery(""),
8178
- className: "cursor-pointer text-sm text-primary-600 dark:text-primary-400 hover:underline",
8179
- children: t("Common.Clear")
8180
- }
8181
- ) : void 0
8454
+ onClick: (e) => {
8455
+ e.stopPropagation();
8456
+ },
8457
+ disabled: loading || accessDenied,
8458
+ className: "flex items-center justify-center rounded-lg text-gray-500 dark:text-gray-400 hover:text-gray-700 dark:hover:text-gray-200 hover:bg-gray-100 dark:hover:bg-gray-800 transition-colors disabled:opacity-40 disabled:cursor-not-allowed cursor-pointer focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500/50 p-2",
8459
+ "aria-label": t("BiChat.Sidebar.Settings"),
8460
+ title: t("BiChat.Sidebar.Settings"),
8461
+ children: /* @__PURE__ */ jsxRuntime.jsx(react.Gear, { size: 20 })
8462
+ }
8463
+ ),
8464
+ /* @__PURE__ */ jsxRuntime.jsxs(
8465
+ react$1.MenuItems,
8466
+ {
8467
+ anchor: "top start",
8468
+ className: "w-48 bg-white/95 dark:bg-gray-900/95 backdrop-blur-lg rounded-xl shadow-lg border border-gray-200/80 dark:border-gray-700/60 z-30 [--anchor-gap:8px] mb-1 p-1.5",
8469
+ children: [
8470
+ onArchivedView && /* @__PURE__ */ jsxRuntime.jsx(react$1.MenuItem, { children: ({ focus }) => /* @__PURE__ */ jsxRuntime.jsxs(
8471
+ "button",
8472
+ {
8473
+ onClick: (e) => {
8474
+ e.preventDefault();
8475
+ e.stopPropagation();
8476
+ onArchivedView();
8477
+ },
8478
+ className: `cursor-pointer flex w-full items-center gap-2.5 rounded-lg px-2.5 py-1.5 text-[13px] text-gray-600 dark:text-gray-300 transition-colors ${focus ? "bg-gray-100 dark:bg-gray-800/70" : ""}`,
8479
+ "aria-label": t("BiChat.Sidebar.ArchivedChats"),
8480
+ children: [
8481
+ /* @__PURE__ */ jsxRuntime.jsx(react.Archive, { size: 16, className: "text-gray-400 dark:text-gray-500" }),
8482
+ t("BiChat.Sidebar.ArchivedChats")
8483
+ ]
8484
+ }
8485
+ ) }),
8486
+ showAllChatsTab && activeTab !== "all-chats" && /* @__PURE__ */ jsxRuntime.jsx(react$1.MenuItem, { children: ({ focus }) => /* @__PURE__ */ jsxRuntime.jsxs(
8487
+ "button",
8488
+ {
8489
+ onClick: (e) => {
8490
+ e.preventDefault();
8491
+ e.stopPropagation();
8492
+ setActiveTab("all-chats");
8493
+ },
8494
+ className: `cursor-pointer flex w-full items-center gap-2.5 rounded-lg px-2.5 py-1.5 text-[13px] text-gray-600 dark:text-gray-300 transition-colors ${focus ? "bg-gray-100 dark:bg-gray-800/70" : ""}`,
8495
+ "aria-label": t("BiChat.Sidebar.AllChats"),
8496
+ children: [
8497
+ /* @__PURE__ */ jsxRuntime.jsx(react.Users, { size: 16, className: "text-gray-400 dark:text-gray-500" }),
8498
+ t("BiChat.Sidebar.AllChats")
8499
+ ]
8500
+ }
8501
+ ) }),
8502
+ showAllChatsTab && activeTab === "all-chats" && /* @__PURE__ */ jsxRuntime.jsx(react$1.MenuItem, { children: ({ focus }) => /* @__PURE__ */ jsxRuntime.jsxs(
8503
+ "button",
8504
+ {
8505
+ onClick: (e) => {
8506
+ e.preventDefault();
8507
+ e.stopPropagation();
8508
+ setActiveTab("my-chats");
8509
+ },
8510
+ className: `cursor-pointer flex w-full items-center gap-2.5 rounded-lg px-2.5 py-1.5 text-[13px] text-gray-600 dark:text-gray-300 transition-colors ${focus ? "bg-gray-100 dark:bg-gray-800/70" : ""}`,
8511
+ "aria-label": t("BiChat.Sidebar.MyChats"),
8512
+ children: [
8513
+ /* @__PURE__ */ jsxRuntime.jsx(react.List, { size: 16, className: "text-gray-400 dark:text-gray-500" }),
8514
+ t("BiChat.Sidebar.MyChats")
8515
+ ]
8516
+ }
8517
+ ) })
8518
+ ]
8182
8519
  }
8183
8520
  )
8184
- ] }),
8185
- error && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mx-2 mt-4 p-3 bg-red-50 dark:bg-red-900/20 border border-red-200 dark:border-red-800 rounded-lg", children: /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-red-600 dark:text-red-400", children: error }) })
8186
- ]
8521
+ ] }) : /* @__PURE__ */ jsxRuntime.jsx("div", {}),
8522
+ /* @__PURE__ */ jsxRuntime.jsxs(
8523
+ "button",
8524
+ {
8525
+ onClick: (e) => {
8526
+ e.stopPropagation();
8527
+ toggle();
8528
+ },
8529
+ className: "flex items-center gap-2 rounded-lg px-3 py-2 text-gray-500 dark:text-gray-400 hover:text-gray-700 dark:hover:text-gray-200 hover:bg-gray-100 dark:hover:bg-gray-800 transition-colors cursor-pointer focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500/50",
8530
+ title: t("BiChat.Sidebar.CollapseSidebar"),
8531
+ "aria-label": t("BiChat.Sidebar.CollapseSidebar"),
8532
+ children: [
8533
+ /* @__PURE__ */ jsxRuntime.jsx(react.CaretLineLeft, { size: 16 }),
8534
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs font-medium", children: t("BiChat.Sidebar.Collapse") })
8535
+ ]
8536
+ }
8537
+ )
8538
+ ] })
8539
+ ]
8540
+ }
8541
+ ),
8542
+ collapsible && showCollapsed && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute bottom-0 inset-x-0 z-10 border-t border-gray-100 dark:border-gray-800/80 py-3 flex justify-center", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "group/tooltip relative", children: [
8543
+ /* @__PURE__ */ jsxRuntime.jsx(
8544
+ "button",
8545
+ {
8546
+ onClick: (e) => {
8547
+ e.stopPropagation();
8548
+ toggle();
8549
+ },
8550
+ className: "w-10 h-10 flex items-center justify-center rounded-lg text-gray-500 dark:text-gray-400 hover:text-gray-700 dark:hover:text-gray-200 hover:bg-gray-100 dark:hover:bg-gray-800 transition-colors cursor-pointer focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500/50",
8551
+ title: t("BiChat.Sidebar.ExpandSidebar"),
8552
+ "aria-label": t("BiChat.Sidebar.ExpandSidebar"),
8553
+ children: /* @__PURE__ */ jsxRuntime.jsx(react.CaretLineRight, { size: 16 })
8187
8554
  }
8188
8555
  ),
8189
- footerSlot
8190
- ] })
8556
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "pointer-events-none absolute left-full ml-2 top-1/2 -translate-y-1/2 rounded-md bg-gray-900 dark:bg-gray-100 px-2 py-1 text-xs font-medium text-white dark:text-gray-900 opacity-0 group-hover/tooltip:opacity-100 transition-opacity whitespace-nowrap shadow-lg", children: t("BiChat.Sidebar.Expand") })
8557
+ ] }) })
8191
8558
  ]
8192
8559
  }
8193
8560
  ),
@@ -8195,11 +8562,11 @@ function Sidebar2({
8195
8562
  ConfirmModal_default,
8196
8563
  {
8197
8564
  isOpen: showConfirm,
8198
- title: t("Sidebar.ArchiveChatSession"),
8199
- message: t("Sidebar.ArchiveChatMessage"),
8200
- confirmText: t("Sidebar.ArchiveButton"),
8201
- cancelText: t("Common.Cancel"),
8202
- isDanger: false,
8565
+ title: t("BiChat.Sidebar.ArchiveChatSession"),
8566
+ message: t("BiChat.Sidebar.ArchiveChatMessage"),
8567
+ confirmText: t("BiChat.Sidebar.ArchiveButton"),
8568
+ cancelText: t("BiChat.Common.Cancel"),
8569
+ isDanger: true,
8203
8570
  onConfirm: confirmArchive,
8204
8571
  onCancel: () => {
8205
8572
  setShowConfirm(false);
@@ -8255,10 +8622,10 @@ function ArchivedChatList({
8255
8622
  try {
8256
8623
  await dataSource.unarchiveSession(sessionToRestore);
8257
8624
  setRefreshKey((k) => k + 1);
8258
- toast.success(t("Archived.ChatRestoredSuccessfully"));
8625
+ toast.success(t("BiChat.Archived.ChatRestoredSuccessfully"));
8259
8626
  } catch (err) {
8260
8627
  console.error("Failed to restore session:", err);
8261
- toast.error(t("Archived.FailedToRestoreChat"));
8628
+ toast.error(t("BiChat.Archived.FailedToRestoreChat"));
8262
8629
  } finally {
8263
8630
  setShowConfirm(false);
8264
8631
  setSessionToRestore(null);
@@ -8267,11 +8634,11 @@ function ArchivedChatList({
8267
8634
  const handleRenameSession = async (sessionId, newTitle) => {
8268
8635
  try {
8269
8636
  await dataSource.renameSession(sessionId, newTitle);
8270
- toast.success(t("Sidebar.ChatRenamedSuccessfully"));
8637
+ toast.success(t("BiChat.Sidebar.ChatRenamedSuccessfully"));
8271
8638
  setRefreshKey((k) => k + 1);
8272
8639
  } catch (err) {
8273
8640
  console.error("Failed to update session title:", err);
8274
- toast.error(t("Sidebar.FailedToRenameChat"));
8641
+ toast.error(t("BiChat.Sidebar.FailedToRenameChat"));
8275
8642
  }
8276
8643
  };
8277
8644
  const filteredSessions = React.useMemo(() => {
@@ -8299,10 +8666,10 @@ function ArchivedChatList({
8299
8666
  {
8300
8667
  onClick: onBack,
8301
8668
  className: "inline-flex items-center gap-2 px-3 py-2 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-700 transition-colors text-gray-600 dark:text-gray-400",
8302
- "aria-label": t("Archived.BackToChats"),
8669
+ "aria-label": t("BiChat.Archived.BackToChats"),
8303
8670
  children: [
8304
8671
  /* @__PURE__ */ jsxRuntime.jsx(react.ArrowLeft, { size: 20, className: "w-5 h-5" }),
8305
- t("Common.Back")
8672
+ t("BiChat.Common.Back")
8306
8673
  ]
8307
8674
  }
8308
8675
  ) }),
@@ -8314,14 +8681,14 @@ function ArchivedChatList({
8314
8681
  className: "w-6 h-6 text-gray-600 dark:text-gray-400"
8315
8682
  }
8316
8683
  ),
8317
- /* @__PURE__ */ jsxRuntime.jsx("h1", { className: "text-2xl font-bold text-gray-900 dark:text-white", children: t("Archived.Title") })
8684
+ /* @__PURE__ */ jsxRuntime.jsx("h1", { className: "text-2xl font-bold text-gray-900 dark:text-white", children: t("BiChat.Archived.Title") })
8318
8685
  ] }),
8319
8686
  /* @__PURE__ */ jsxRuntime.jsx(
8320
8687
  SearchInput_default,
8321
8688
  {
8322
8689
  value: searchQuery,
8323
8690
  onChange: setSearchQuery,
8324
- placeholder: t("Archived.SearchArchivedChats")
8691
+ placeholder: t("BiChat.Archived.SearchArchivedChats")
8325
8692
  }
8326
8693
  )
8327
8694
  ] }),
@@ -8335,8 +8702,8 @@ function ArchivedChatList({
8335
8702
  className: "text-gray-400 dark:text-gray-500"
8336
8703
  }
8337
8704
  ),
8338
- title: t("Archived.NoArchivedChats"),
8339
- description: t("Archived.NoArchivedChatsDescription")
8705
+ title: t("BiChat.Archived.NoArchivedChats"),
8706
+ description: t("BiChat.Archived.NoArchivedChatsDescription")
8340
8707
  }
8341
8708
  ) }) : isEmptyAfterSearch ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-center h-full px-6", children: /* @__PURE__ */ jsxRuntime.jsx(
8342
8709
  MemoizedEmptyState,
@@ -8348,8 +8715,8 @@ function ArchivedChatList({
8348
8715
  className: "text-gray-400 dark:text-gray-500"
8349
8716
  }
8350
8717
  ),
8351
- title: t("Archived.NoResults"),
8352
- description: t("Archived.NoResultsDescription", {
8718
+ title: t("BiChat.Archived.NoResults"),
8719
+ description: t("BiChat.Archived.NoResultsDescription", {
8353
8720
  query: searchQuery
8354
8721
  })
8355
8722
  }
@@ -8387,10 +8754,10 @@ function ArchivedChatList({
8387
8754
  ConfirmModal_default,
8388
8755
  {
8389
8756
  isOpen: showConfirm,
8390
- title: t("Archived.RestoreChat"),
8391
- message: t("Archived.RestoreChatMessage"),
8392
- confirmText: t("Archived.RestoreButton"),
8393
- cancelText: t("Common.Cancel"),
8757
+ title: t("BiChat.Archived.RestoreChat"),
8758
+ message: t("BiChat.Archived.RestoreChatMessage"),
8759
+ confirmText: t("BiChat.Archived.RestoreButton"),
8760
+ cancelText: t("BiChat.Common.Cancel"),
8394
8761
  isDanger: false,
8395
8762
  onConfirm: confirmRestore,
8396
8763
  onCancel: () => {
@@ -8404,6 +8771,231 @@ function ArchivedChatList({
8404
8771
  }
8405
8772
  );
8406
8773
  }
8774
+
8775
+ // ui/src/bichat/components/SkipLink.tsx
8776
+ init_useTranslation();
8777
+ function SkipLink() {
8778
+ const { t } = useTranslation();
8779
+ return /* @__PURE__ */ jsxRuntime.jsx(
8780
+ "a",
8781
+ {
8782
+ href: "#main-content",
8783
+ className: "sr-only focus-visible:not-sr-only focus-visible:absolute focus-visible:top-4 focus-visible:left-4 focus-visible:z-50 focus-visible:bg-primary-600 focus-visible:text-white focus-visible:px-4 focus-visible:py-2 focus-visible:rounded-lg focus-visible:shadow-lg",
8784
+ children: t("BiChat.SkipLink.Label")
8785
+ }
8786
+ );
8787
+ }
8788
+ var MOBILE_QUERY = "(max-width: 767px)";
8789
+ function getIsMobile() {
8790
+ if (typeof window === "undefined") return false;
8791
+ return window.matchMedia(MOBILE_QUERY).matches;
8792
+ }
8793
+ function useSidebarState() {
8794
+ const [isMobile, setIsMobile] = React.useState(getIsMobile);
8795
+ const [isMobileOpen, setIsMobileOpen] = React.useState(false);
8796
+ React.useEffect(() => {
8797
+ if (typeof window === "undefined") return;
8798
+ const mql = window.matchMedia(MOBILE_QUERY);
8799
+ const handler = (e) => {
8800
+ setIsMobile(e.matches);
8801
+ if (!e.matches) setIsMobileOpen(false);
8802
+ };
8803
+ if (mql.addEventListener) {
8804
+ mql.addEventListener("change", handler);
8805
+ } else if (mql.addListener) {
8806
+ mql.addListener(handler);
8807
+ }
8808
+ return () => {
8809
+ if (mql.removeEventListener) {
8810
+ mql.removeEventListener("change", handler);
8811
+ } else if (mql.removeListener) {
8812
+ mql.removeListener(handler);
8813
+ }
8814
+ };
8815
+ }, []);
8816
+ const openMobile = React.useCallback(() => setIsMobileOpen(true), []);
8817
+ const closeMobile = React.useCallback(() => setIsMobileOpen(false), []);
8818
+ const toggleMobile = React.useCallback(() => setIsMobileOpen((v) => !v), []);
8819
+ return { isMobile, isMobileOpen, openMobile, closeMobile, toggleMobile };
8820
+ }
8821
+ function useFocusTrap(containerRef, isActive, restoreFocusOnDeactivate) {
8822
+ React.useEffect(() => {
8823
+ if (!isActive || !containerRef.current) return;
8824
+ const container = containerRef.current;
8825
+ const previouslyFocused = document.activeElement;
8826
+ const getFocusableElements = () => {
8827
+ const selector = [
8828
+ "button:not([disabled])",
8829
+ "[href]",
8830
+ "input:not([disabled])",
8831
+ "select:not([disabled])",
8832
+ "textarea:not([disabled])",
8833
+ '[tabindex]:not([tabindex="-1"])'
8834
+ ].join(", ");
8835
+ return Array.from(container.querySelectorAll(selector));
8836
+ };
8837
+ const focusableElements = getFocusableElements();
8838
+ if (focusableElements.length > 0) {
8839
+ focusableElements[0].focus();
8840
+ }
8841
+ const handleTabKey = (e) => {
8842
+ if (e.key !== "Tab") return;
8843
+ const focusableElements2 = getFocusableElements();
8844
+ if (focusableElements2.length === 0) return;
8845
+ const firstElement = focusableElements2[0];
8846
+ const lastElement = focusableElements2[focusableElements2.length - 1];
8847
+ if (e.shiftKey) {
8848
+ if (document.activeElement === firstElement) {
8849
+ e.preventDefault();
8850
+ lastElement.focus();
8851
+ }
8852
+ } else {
8853
+ if (document.activeElement === lastElement) {
8854
+ e.preventDefault();
8855
+ firstElement.focus();
8856
+ }
8857
+ }
8858
+ };
8859
+ container.addEventListener("keydown", handleTabKey);
8860
+ return () => {
8861
+ container.removeEventListener("keydown", handleTabKey);
8862
+ if (restoreFocusOnDeactivate) {
8863
+ restoreFocusOnDeactivate.focus();
8864
+ } else if (previouslyFocused instanceof HTMLElement) {
8865
+ previouslyFocused.focus();
8866
+ }
8867
+ };
8868
+ }, [containerRef, isActive, restoreFocusOnDeactivate]);
8869
+ }
8870
+ function useKeyboardShortcuts(shortcuts) {
8871
+ React.useEffect(() => {
8872
+ const handleKeyDown = (e) => {
8873
+ const target = e.target;
8874
+ if (target instanceof HTMLInputElement || target instanceof HTMLTextAreaElement || target.isContentEditable) {
8875
+ const allowInInput = shortcuts.find(
8876
+ (s) => s.key.toLowerCase() === e.key.toLowerCase() && s.key.toLowerCase() === "escape"
8877
+ );
8878
+ if (!allowInInput) {
8879
+ return;
8880
+ }
8881
+ }
8882
+ const matchingShortcut = shortcuts.find((s) => {
8883
+ const keyMatches = e.key.toLowerCase() === s.key.toLowerCase();
8884
+ const modMatches = s.meta ? e.metaKey && !e.ctrlKey : s.ctrl ? e.ctrlKey || e.metaKey : !e.ctrlKey && !e.metaKey;
8885
+ const shiftMatches = s.shift ? e.shiftKey : !e.shiftKey;
8886
+ const altMatches = s.alt ? e.altKey : !e.altKey;
8887
+ return keyMatches && modMatches && shiftMatches && altMatches;
8888
+ });
8889
+ if (matchingShortcut) {
8890
+ if (matchingShortcut.preventDefault !== false) {
8891
+ e.preventDefault();
8892
+ }
8893
+ matchingShortcut.callback();
8894
+ }
8895
+ };
8896
+ document.addEventListener("keydown", handleKeyDown);
8897
+ return () => document.removeEventListener("keydown", handleKeyDown);
8898
+ }, [shortcuts]);
8899
+ }
8900
+
8901
+ // ui/src/bichat/components/BiChatLayout.tsx
8902
+ init_useTranslation();
8903
+ function BiChatLayout({
8904
+ renderSidebar,
8905
+ children,
8906
+ onNewChat,
8907
+ routeKey,
8908
+ className = ""
8909
+ }) {
8910
+ const { t } = useTranslation();
8911
+ const { isMobile, isMobileOpen, openMobile, closeMobile } = useSidebarState();
8912
+ const drawerRef = React.useRef(null);
8913
+ const menuButtonRef = React.useRef(null);
8914
+ useFocusTrap(drawerRef, isMobile && isMobileOpen, menuButtonRef.current);
8915
+ const shortcuts = React.useMemo(() => {
8916
+ if (!onNewChat) return [];
8917
+ return [{ key: "n", ctrl: true, callback: onNewChat, description: "New chat" }];
8918
+ }, [onNewChat]);
8919
+ useKeyboardShortcuts(shortcuts);
8920
+ React.useEffect(() => {
8921
+ if (!isMobile || !isMobileOpen) return;
8922
+ const onKeyDown = (e) => {
8923
+ if (e.key === "Escape") {
8924
+ e.preventDefault();
8925
+ closeMobile();
8926
+ }
8927
+ };
8928
+ document.addEventListener("keydown", onKeyDown);
8929
+ return () => document.removeEventListener("keydown", onKeyDown);
8930
+ }, [closeMobile, isMobile, isMobileOpen]);
8931
+ const handleDrawerDragEnd = (_, info) => {
8932
+ if (info.offset.x < -80) {
8933
+ closeMobile();
8934
+ }
8935
+ };
8936
+ const content = routeKey ? /* @__PURE__ */ jsxRuntime.jsx(framerMotion.AnimatePresence, { mode: "wait", initial: false, children: /* @__PURE__ */ jsxRuntime.jsx(
8937
+ framerMotion.motion.div,
8938
+ {
8939
+ className: "flex flex-1 min-h-0",
8940
+ initial: { opacity: 0, y: 4 },
8941
+ animate: { opacity: 1, y: 0 },
8942
+ exit: { opacity: 0, y: -4 },
8943
+ transition: { duration: 0.15, ease: "easeOut" },
8944
+ children
8945
+ },
8946
+ routeKey
8947
+ ) }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-1 min-h-0", children });
8948
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `relative flex flex-1 w-full h-full min-h-0 overflow-hidden ${className}`, children: [
8949
+ /* @__PURE__ */ jsxRuntime.jsx(SkipLink, {}),
8950
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "hidden md:block", children: renderSidebar({}) }),
8951
+ /* @__PURE__ */ jsxRuntime.jsx(framerMotion.AnimatePresence, { children: isMobile && isMobileOpen && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
8952
+ /* @__PURE__ */ jsxRuntime.jsx(
8953
+ framerMotion.motion.div,
8954
+ {
8955
+ className: "fixed inset-0 z-40 bg-black/40",
8956
+ initial: { opacity: 0 },
8957
+ animate: { opacity: 1 },
8958
+ exit: { opacity: 0 },
8959
+ onClick: closeMobile,
8960
+ "aria-hidden": "true"
8961
+ },
8962
+ "sidebar-backdrop"
8963
+ ),
8964
+ /* @__PURE__ */ jsxRuntime.jsx(
8965
+ framerMotion.motion.div,
8966
+ {
8967
+ className: "fixed inset-y-0 left-0 z-50 w-[18rem] max-w-[85vw] shadow-2xl",
8968
+ initial: { x: "-100%" },
8969
+ animate: { x: 0 },
8970
+ exit: { x: "-100%" },
8971
+ transition: { type: "spring", stiffness: 320, damping: 32 },
8972
+ drag: "x",
8973
+ dragDirectionLock: true,
8974
+ dragConstraints: { left: -120, right: 0 },
8975
+ dragElastic: { left: 0.2, right: 0 },
8976
+ onDragEnd: handleDrawerDragEnd,
8977
+ onClick: (e) => e.stopPropagation(),
8978
+ children: /* @__PURE__ */ jsxRuntime.jsx("div", { ref: drawerRef, className: "h-full bg-white dark:bg-gray-900", children: renderSidebar({ onClose: closeMobile }) })
8979
+ },
8980
+ "sidebar-drawer"
8981
+ )
8982
+ ] }) }),
8983
+ /* @__PURE__ */ jsxRuntime.jsxs("main", { id: "main-content", className: "relative flex-1 flex flex-col min-h-0 overflow-hidden", children: [
8984
+ isMobile && !isMobileOpen && /* @__PURE__ */ jsxRuntime.jsx(
8985
+ "button",
8986
+ {
8987
+ ref: menuButtonRef,
8988
+ onClick: openMobile,
8989
+ className: "md:hidden absolute top-3 left-3 z-30 w-10 h-10 rounded-xl bg-white/90 dark:bg-gray-900/90 text-gray-700 dark:text-gray-200 border border-gray-200/60 dark:border-gray-800/80 shadow-sm flex items-center justify-center hover:bg-white dark:hover:bg-gray-900 transition-colors cursor-pointer focus-visible:ring-2 focus-visible:ring-primary-400/50",
8990
+ "aria-label": t("BiChat.Layout.OpenSidebar"),
8991
+ title: t("BiChat.Layout.OpenSidebar"),
8992
+ children: /* @__PURE__ */ jsxRuntime.jsx(react.List, { size: 20, weight: "bold" })
8993
+ }
8994
+ ),
8995
+ content
8996
+ ] })
8997
+ ] });
8998
+ }
8407
8999
  init_useTranslation();
8408
9000
  var variantStyles = {
8409
9001
  error: {
@@ -8476,7 +9068,7 @@ function Alert({
8476
9068
  {
8477
9069
  onClick: onRetry,
8478
9070
  className: `mt-2 text-xs px-3 py-1.5 rounded ${styles.retryButton} transition-colors font-medium`,
8479
- children: t("Chat.Retry")
9071
+ children: t("BiChat.Chat.Retry")
8480
9072
  }
8481
9073
  )
8482
9074
  ] })
@@ -8486,7 +9078,7 @@ function Alert({
8486
9078
  {
8487
9079
  onClick: onDismiss,
8488
9080
  className: `${styles.button} transition-colors flex-shrink-0`,
8489
- "aria-label": t("Chat.DismissNotification"),
9081
+ "aria-label": t("BiChat.Chat.DismissNotification"),
8490
9082
  children: /* @__PURE__ */ jsxRuntime.jsx(react.X, { size: 20, className: "w-5 h-5" })
8491
9083
  }
8492
9084
  )
@@ -8495,12 +9087,14 @@ function Alert({
8495
9087
  ) });
8496
9088
  }
8497
9089
  var Alert_default = React.memo(Alert);
9090
+ init_useTranslation();
8498
9091
  function ArchiveBanner({
8499
9092
  show = true,
8500
9093
  onRestore,
8501
9094
  restoring = false,
8502
9095
  onRestoreComplete
8503
9096
  }) {
9097
+ const { t } = useTranslation();
8504
9098
  const [error, setError] = React.useState(null);
8505
9099
  const handleRestore = async () => {
8506
9100
  try {
@@ -8512,7 +9106,7 @@ function ArchiveBanner({
8512
9106
  onRestoreComplete();
8513
9107
  }
8514
9108
  } catch (err) {
8515
- const message = err instanceof Error ? err.message : "Failed to restore session";
9109
+ const message = err instanceof Error ? err.message : t("BiChat.Archive.RestoreFailed");
8516
9110
  setError(message);
8517
9111
  }
8518
9112
  };
@@ -8526,11 +9120,11 @@ function ArchiveBanner({
8526
9120
  exit: "exit",
8527
9121
  className: "border-t border border-blue-200 bg-blue-50 dark:bg-blue-900/20 px-4 py-3",
8528
9122
  role: "region",
8529
- "aria-label": "Archive banner",
9123
+ "aria-label": t("BiChat.Archive.Banner"),
8530
9124
  children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "w-full flex items-start justify-between px-4", children: [
8531
9125
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start gap-3 flex-1", children: [
8532
9126
  /* @__PURE__ */ jsxRuntime.jsx(react.Archive, { size: 20, className: "w-5 h-5 text-blue-600 dark:text-blue-400 flex-shrink-0 mt-0.5" }),
8533
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1", children: /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-blue-700 dark:text-blue-400", children: "This chat session has been archived" }) })
9127
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1", children: /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-blue-700 dark:text-blue-400", children: t("BiChat.Archive.Archived") }) })
8534
9128
  ] }),
8535
9129
  /* @__PURE__ */ jsxRuntime.jsx(
8536
9130
  "button",
@@ -8538,11 +9132,11 @@ function ArchiveBanner({
8538
9132
  onClick: handleRestore,
8539
9133
  disabled: restoring,
8540
9134
  className: "ml-2 flex-shrink-0 px-3 py-1.5 text-xs font-medium bg-blue-600 dark:bg-blue-700 hover:bg-blue-700 dark:hover:bg-blue-800 text-white rounded transition-colors disabled:opacity-50 disabled:cursor-not-allowed flex items-center gap-1.5",
8541
- "aria-label": "Restore session",
9135
+ "aria-label": t("BiChat.Archive.Restore"),
8542
9136
  children: restoring ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
8543
9137
  /* @__PURE__ */ jsxRuntime.jsx(react.Spinner, { size: 16, className: "w-4 h-4 animate-spin" }),
8544
- "Restoring..."
8545
- ] }) : "Restore"
9138
+ t("BiChat.Archive.Restoring")
9139
+ ] }) : t("BiChat.Archive.Restore")
8546
9140
  }
8547
9141
  )
8548
9142
  ] })
@@ -8553,7 +9147,7 @@ function ArchiveBanner({
8553
9147
  {
8554
9148
  variant: "error",
8555
9149
  message: error,
8556
- title: "Restore Failed",
9150
+ title: t("BiChat.Archive.RestoreFailed"),
8557
9151
  onDismiss: () => setError(null),
8558
9152
  dismissible: true
8559
9153
  }
@@ -8593,17 +9187,17 @@ var RetryActionArea = React.memo(function RetryActionArea2({
8593
9187
  weight: "fill"
8594
9188
  }
8595
9189
  ),
8596
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-gray-700 dark:text-gray-300", children: t("Retry.Description") })
9190
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-gray-700 dark:text-gray-300", children: t("BiChat.Retry.Subtitle") })
8597
9191
  ] }),
8598
9192
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-2", children: /* @__PURE__ */ jsxRuntime.jsxs(
8599
9193
  "button",
8600
9194
  {
8601
9195
  onClick: onRetry,
8602
9196
  className: "cursor-pointer inline-flex items-center gap-1.5 px-4 py-2 text-sm font-medium text-white bg-primary-600 hover:bg-primary-700 dark:bg-primary-700 dark:hover:bg-primary-600 rounded-lg transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500/50 focus-visible:ring-offset-2 dark:focus-visible:ring-offset-gray-800",
8603
- "aria-label": t("Retry.Title"),
9197
+ "aria-label": t("BiChat.Retry.Title"),
8604
9198
  children: [
8605
9199
  /* @__PURE__ */ jsxRuntime.jsx(react.ArrowClockwise, { size: 16, className: "w-4 h-4" }),
8606
- t("Retry.Button")
9200
+ t("BiChat.Retry.Button")
8607
9201
  ]
8608
9202
  }
8609
9203
  ) })
@@ -8641,7 +9235,7 @@ function StreamError({
8641
9235
  }
8642
9236
  ),
8643
9237
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 min-w-0", children: [
8644
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-medium text-red-800 dark:text-red-200", children: t("Error.Generic") }),
9238
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-medium text-red-800 dark:text-red-200", children: t("BiChat.Error.Generic") }),
8645
9239
  /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-red-600 dark:text-red-300 break-words", children: error })
8646
9240
  ] }),
8647
9241
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 flex-shrink-0", children: [
@@ -8653,7 +9247,7 @@ function StreamError({
8653
9247
  type: "button",
8654
9248
  children: [
8655
9249
  /* @__PURE__ */ jsxRuntime.jsx(react.ArrowClockwise, { className: "w-4 h-4" }),
8656
- t("streamError.retry")
9250
+ t("BiChat.StreamError.Retry")
8657
9251
  ]
8658
9252
  }
8659
9253
  ),
@@ -8665,7 +9259,7 @@ function StreamError({
8665
9259
  type: "button",
8666
9260
  children: [
8667
9261
  /* @__PURE__ */ jsxRuntime.jsx(react.ArrowsCounterClockwise, { className: "w-4 h-4" }),
8668
- t("streamError.regenerate")
9262
+ t("BiChat.StreamError.Regenerate")
8669
9263
  ]
8670
9264
  }
8671
9265
  )
@@ -8674,6 +9268,7 @@ function StreamError({
8674
9268
  }
8675
9269
  );
8676
9270
  }
9271
+ init_useTranslation();
8677
9272
  function MessageActions({
8678
9273
  message,
8679
9274
  onCopy,
@@ -8683,14 +9278,15 @@ function MessageActions({
8683
9278
  const [copying, setCopying] = React.useState(false);
8684
9279
  const [regenerating, setRegenerating] = React.useState(false);
8685
9280
  const toast = useToast();
9281
+ const { t } = useTranslation();
8686
9282
  const isUser = message.role === "user" /* User */;
8687
9283
  const handleCopy = async () => {
8688
9284
  setCopying(true);
8689
9285
  try {
8690
9286
  await onCopy(message.content);
8691
- toast.success("Copied to clipboard");
9287
+ toast.success(t("BiChat.Message.CopiedToClipboard"));
8692
9288
  } catch {
8693
- toast.error("Failed to copy message");
9289
+ toast.error(t("BiChat.Message.FailedToCopy"));
8694
9290
  } finally {
8695
9291
  setCopying(false);
8696
9292
  }
@@ -8710,9 +9306,9 @@ function MessageActions({
8710
9306
  {
8711
9307
  onClick: handleCopy,
8712
9308
  disabled: copying,
8713
- title: copying ? "Copying..." : "Copy message (Cmd/Ctrl+C on selection)",
9309
+ title: copying ? t("BiChat.Message.Copying") : t("BiChat.Message.CopyMessage"),
8714
9310
  className: "cursor-pointer text-gray-500 dark:text-gray-400 hover:bg-gray-100 dark:hover:bg-gray-700 hover:text-gray-700 dark:hover:text-gray-300 rounded-md transition-colors disabled:opacity-50 p-2 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500/50",
8715
- "aria-label": copying ? "Copying message" : "Copy message",
9311
+ "aria-label": copying ? t("BiChat.Message.Copying") : t("BiChat.Message.CopyMessage"),
8716
9312
  children: copying ? /* @__PURE__ */ jsxRuntime.jsx(LoadingSpinner_default, { variant: "spinner", size: "sm" }) : /* @__PURE__ */ jsxRuntime.jsx(react.Copy, { size: 16, className: "w-4 h-4" })
8717
9313
  }
8718
9314
  ),
@@ -8721,9 +9317,9 @@ function MessageActions({
8721
9317
  {
8722
9318
  onClick: handleRegenerate,
8723
9319
  disabled: regenerating,
8724
- title: regenerating ? "Regenerating..." : "Regenerate response",
9320
+ title: regenerating ? t("BiChat.Message.Regenerating") : t("BiChat.Message.Regenerate"),
8725
9321
  className: "cursor-pointer text-gray-500 dark:text-gray-400 hover:bg-gray-100 dark:hover:bg-gray-700 hover:text-gray-700 dark:hover:text-gray-300 rounded-md transition-colors disabled:opacity-50 p-2 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500/50",
8726
- "aria-label": regenerating ? "Regenerating response" : "Regenerate response",
9322
+ "aria-label": regenerating ? t("BiChat.Message.Regenerating") : t("BiChat.Message.Regenerate"),
8727
9323
  children: regenerating ? /* @__PURE__ */ jsxRuntime.jsx(LoadingSpinner_default, { variant: "spinner", size: "sm" }) : /* @__PURE__ */ jsxRuntime.jsx(react.ArrowClockwise, { size: 16, className: "w-4 h-4" })
8728
9324
  }
8729
9325
  ),
@@ -8731,16 +9327,18 @@ function MessageActions({
8731
9327
  "button",
8732
9328
  {
8733
9329
  onClick: () => onEdit(message),
8734
- title: "Edit message",
9330
+ title: t("BiChat.Message.EditMessage"),
8735
9331
  className: "cursor-pointer text-gray-500 dark:text-gray-400 hover:bg-gray-100 dark:hover:bg-gray-700 hover:text-gray-700 dark:hover:text-gray-300 rounded-md transition-colors p-2 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500/50",
8736
- "aria-label": "Edit message",
9332
+ "aria-label": t("BiChat.Message.EditMessage"),
8737
9333
  children: /* @__PURE__ */ jsxRuntime.jsx(react.PencilSimple, { size: 16, className: "w-4 h-4" })
8738
9334
  }
8739
9335
  )
8740
9336
  ] });
8741
9337
  }
8742
9338
  React.memo(MessageActions);
9339
+ init_useTranslation();
8743
9340
  var AttachmentPreview = React.memo(({ attachment, onRemove, onClick, readonly = false }) => {
9341
+ const { t } = useTranslation();
8744
9342
  const [isImageLoaded, setIsImageLoaded] = React.useState(false);
8745
9343
  const [imageError, setImageError] = React.useState(false);
8746
9344
  const previewUrl = attachment.preview || createDataUrl(attachment.base64Data, attachment.mimeType);
@@ -8772,7 +9370,7 @@ var AttachmentPreview = React.memo(({ attachment, onRemove, onClick, readonly =
8772
9370
  children: [
8773
9371
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative mb-2 overflow-hidden rounded-md bg-gray-100 dark:bg-gray-700 aspect-square", children: [
8774
9372
  !isImageLoaded && !imageError && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute inset-0 animate-pulse bg-gray-200 dark:bg-gray-600" }),
8775
- imageError && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute inset-0 flex items-center justify-center bg-gray-100 dark:bg-gray-700", children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs text-gray-500 dark:text-gray-400", children: "Preview unavailable" }) }),
9373
+ imageError && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute inset-0 flex items-center justify-center bg-gray-100 dark:bg-gray-700", children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs text-gray-500 dark:text-gray-400", children: t("BiChat.Attachment.PreviewUnavailable") }) }),
8776
9374
  /* @__PURE__ */ jsxRuntime.jsx(
8777
9375
  "img",
8778
9376
  {
@@ -8808,7 +9406,7 @@ var AttachmentPreview = React.memo(({ attachment, onRemove, onClick, readonly =
8808
9406
  },
8809
9407
  className: "absolute top-1 right-1 flex items-center justify-center bg-red-500 hover:bg-red-600 dark:bg-red-600 dark:hover:bg-red-700 text-white rounded-full transition-all duration-200 shadow-sm hover:shadow-md active:scale-90 w-6 h-6",
8810
9408
  "aria-label": `Remove ${attachment.filename}`,
8811
- title: "Remove attachment",
9409
+ title: t("BiChat.Attachment.Remove"),
8812
9410
  children: /* @__PURE__ */ jsxRuntime.jsx(react.X, { size: 14, className: "w-3.5 h-3.5", weight: "bold" })
8813
9411
  }
8814
9412
  )
@@ -8837,7 +9435,7 @@ var AttachmentUpload = React.memo(
8837
9435
  setIsLoading(true);
8838
9436
  try {
8839
9437
  if (files.length > maxAttachments) {
8840
- toast.error(t("Error.MaxFiles", { max: maxAttachments, selected: files.length }));
9438
+ toast.error(t("BiChat.Error.MaxFiles", { max: maxAttachments, selected: files.length }));
8841
9439
  setIsLoading(false);
8842
9440
  return;
8843
9441
  }
@@ -8877,10 +9475,10 @@ var AttachmentUpload = React.memo(
8877
9475
  }
8878
9476
  if (attachments.length > 0) {
8879
9477
  onAttachmentsSelected(attachments);
8880
- const message = attachments.length === 1 ? t("Attachment.FileAdded", { size: formatFileSize(attachments[0].sizeBytes) }) : t("Attachment.FileAdded", { size: `${attachments.length} files` });
9478
+ const message = attachments.length === 1 ? t("BiChat.Attachment.FileAdded", { size: formatFileSize(attachments[0].sizeBytes) }) : t("BiChat.Attachment.FileAdded", { size: `${attachments.length} files` });
8881
9479
  toast.success(message);
8882
9480
  } else if (errors.length > 0) {
8883
- toast.error(t("Attachment.InvalidFile"));
9481
+ toast.error(t("BiChat.Attachment.InvalidFile"));
8884
9482
  }
8885
9483
  } finally {
8886
9484
  setIsLoading(false);
@@ -8903,7 +9501,7 @@ var AttachmentUpload = React.memo(
8903
9501
  onChange: handleFileSelect,
8904
9502
  disabled: isDisabled,
8905
9503
  className: "sr-only",
8906
- "aria-label": t("Attachment.SelectFiles")
9504
+ "aria-label": t("BiChat.Attachment.SelectFiles")
8907
9505
  }
8908
9506
  ),
8909
9507
  /* @__PURE__ */ jsxRuntime.jsx(
@@ -8913,7 +9511,7 @@ var AttachmentUpload = React.memo(
8913
9511
  onClick: handleClick,
8914
9512
  disabled: isDisabled,
8915
9513
  className: "\n flex items-center justify-center\n w-8 h-8\n text-gray-600 dark:text-gray-400\n hover:text-gray-800 dark:hover:text-gray-200\n hover:bg-gray-100 dark:hover:bg-gray-700\n disabled:text-gray-400 dark:disabled:text-gray-600\n disabled:opacity-50 disabled:cursor-not-allowed\n rounded-lg\n transition-all\n duration-200\n active:scale-95\n focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500/50\n ",
8916
- "aria-label": t("Attachment.SelectFiles"),
9514
+ "aria-label": t("BiChat.Attachment.SelectFiles"),
8917
9515
  "aria-busy": isLoading,
8918
9516
  children: isLoading ? /* @__PURE__ */ jsxRuntime.jsx(react.CircleNotch, { size: 20, className: "w-5 h-5 animate-spin", weight: "fill" }) : /* @__PURE__ */ jsxRuntime.jsx(react.Paperclip, { size: 20, className: "w-5 h-5", weight: "fill" })
8919
9517
  }
@@ -8951,20 +9549,6 @@ function ScreenReaderAnnouncer({
8951
9549
  );
8952
9550
  }
8953
9551
 
8954
- // ui/src/bichat/components/SkipLink.tsx
8955
- init_useTranslation();
8956
- function SkipLink() {
8957
- const { t } = useTranslation();
8958
- return /* @__PURE__ */ jsxRuntime.jsx(
8959
- "a",
8960
- {
8961
- href: "#main-content",
8962
- className: "sr-only focus-visible:not-sr-only focus-visible:absolute focus-visible:top-4 focus-visible:left-4 focus-visible:z-50 focus-visible:bg-primary-600 focus-visible:text-white focus-visible:px-4 focus-visible:py-2 focus-visible:rounded-lg focus-visible:shadow-lg",
8963
- children: t("skipLink.label")
8964
- }
8965
- );
8966
- }
8967
-
8968
9552
  // ui/src/bichat/components/QuestionForm.tsx
8969
9553
  init_useTranslation();
8970
9554
 
@@ -9001,7 +9585,7 @@ function QuestionStep({
9001
9585
  };
9002
9586
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-6", children: [
9003
9587
  /* @__PURE__ */ jsxRuntime.jsx("div", { children: /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-lg font-semibold text-gray-900 dark:text-white mb-2", children: question.text }) }),
9004
- isMultiSelect && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-gray-500 dark:text-gray-500 italic", children: t("Question.SelectMulti") }),
9588
+ isMultiSelect && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-gray-500 dark:text-gray-500 italic", children: t("BiChat.Question.SelectMulti") }),
9005
9589
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-1 gap-3 sm:grid-cols-2", children: (question.options || []).map((option) => {
9006
9590
  const isSelected = selectedOptions.includes(option.label);
9007
9591
  return /* @__PURE__ */ jsxRuntime.jsx(
@@ -9041,7 +9625,7 @@ function QuestionStep({
9041
9625
  }) }),
9042
9626
  /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
9043
9627
  /* @__PURE__ */ jsxRuntime.jsxs("label", { htmlFor: "other-input", className: "block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2", children: [
9044
- t("Question.SpecifyOther"),
9628
+ t("BiChat.Question.SpecifyOther"),
9045
9629
  ":"
9046
9630
  ] }),
9047
9631
  /* @__PURE__ */ jsxRuntime.jsx(
@@ -9050,7 +9634,7 @@ function QuestionStep({
9050
9634
  id: "other-input",
9051
9635
  value: otherText,
9052
9636
  onChange: (e) => handleOtherTextChange(e.target.value),
9053
- placeholder: t("Question.Other"),
9637
+ placeholder: t("BiChat.Question.OtherOption"),
9054
9638
  rows: 3,
9055
9639
  className: "w-full px-4 py-3 border-2 border-gray-200 dark:border-gray-700 rounded-lg\n bg-white dark:bg-gray-800 text-gray-900 dark:text-white\n placeholder-gray-400 dark:placeholder-gray-500\n focus:outline-none focus:ring-2 focus:ring-primary-500 focus:border-primary-500\n resize-none"
9056
9640
  }
@@ -9068,8 +9652,8 @@ function ConfirmationStep({
9068
9652
  const { t } = useTranslation();
9069
9653
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-6", children: [
9070
9654
  /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
9071
- /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-lg font-semibold text-gray-900 dark:text-white", children: t("questionForm.reviewTitle") }),
9072
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-gray-600 dark:text-gray-400 mt-1", children: t("questionForm.reviewDescription") })
9655
+ /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-lg font-semibold text-gray-900 dark:text-white", children: t("BiChat.QuestionForm.ReviewTitle") }),
9656
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-gray-600 dark:text-gray-400 mt-1", children: t("BiChat.QuestionForm.ReviewDescription") })
9073
9657
  ] }),
9074
9658
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-4", children: questions.map((question) => {
9075
9659
  const answerData = answers[question.id] || { options: [] };
@@ -9093,12 +9677,12 @@ function ConfirmationStep({
9093
9677
  )),
9094
9678
  customText && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "inline-flex items-center px-3 py-1 rounded-lg text-sm font-medium border border-amber-500 bg-amber-500/10 text-amber-600 dark:border-amber-400 dark:bg-amber-400/10 dark:text-amber-400", children: [
9095
9679
  /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "font-semibold mr-1", children: [
9096
- t("Question.Other"),
9680
+ t("BiChat.Question.OtherOption"),
9097
9681
  ":"
9098
9682
  ] }),
9099
9683
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "italic", children: customText })
9100
9684
  ] })
9101
- ] }) : /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-gray-400 dark:text-gray-500 italic", children: t("questionForm.skip") })
9685
+ ] }) : /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-gray-400 dark:text-gray-500 italic", children: t("BiChat.QuestionForm.Skip") })
9102
9686
  ]
9103
9687
  },
9104
9688
  question.id
@@ -9115,12 +9699,12 @@ function isQuestionAnswered(data) {
9115
9699
  function validateAnswers(questions, answers, t) {
9116
9700
  const allAnswered = questions.every((q) => isQuestionAnswered(answers[q.id]));
9117
9701
  if (!allAnswered) {
9118
- return t ? t("Error.AllQuestionsRequired") : "Please answer all questions before submitting";
9702
+ return t ? t("BiChat.Error.AllQuestionsRequired") : "Please answer all questions before submitting";
9119
9703
  }
9120
9704
  for (const q of questions) {
9121
9705
  const data = answers[q.id];
9122
9706
  if (data && (data.options?.length ?? 0) === 0 && data.customText === "") {
9123
- return t ? t("Error.CustomTextRequired", { question: q.text }) : `Please enter custom text for question: ${q.text}`;
9707
+ return t ? t("BiChat.Error.CustomTextRequired", { question: q.text }) : `Please enter custom text for question: ${q.text}`;
9124
9708
  }
9125
9709
  }
9126
9710
  return null;
@@ -9173,24 +9757,24 @@ function QuestionForm({
9173
9757
  try {
9174
9758
  await onSubmit(answers);
9175
9759
  } catch (err) {
9176
- const errorMessage = err instanceof Error ? err.message : t("Error.Generic");
9760
+ const errorMessage = err instanceof Error ? err.message : t("BiChat.Error.Generic");
9177
9761
  setError(errorMessage);
9178
9762
  setIsSubmitting(false);
9179
9763
  }
9180
9764
  };
9181
9765
  const totalSteps = questions.length + 1;
9182
- const progressText = isConfirmationStep ? t("questionForm.step", { current: totalSteps, total: totalSteps }) : t("questionForm.step", { current: currentStep + 1, total: totalSteps });
9766
+ const progressText = isConfirmationStep ? t("BiChat.QuestionForm.Step", { current: totalSteps, total: totalSteps }) : t("BiChat.QuestionForm.Step", { current: currentStep + 1, total: totalSteps });
9183
9767
  return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "fixed inset-0 z-50 flex items-center justify-center bg-black bg-opacity-50 p-4", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bg-white dark:bg-gray-800 rounded-lg shadow-xl max-w-2xl w-full max-h-[90vh] overflow-y-auto", children: [
9184
9768
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "border-b border-gray-200 dark:border-gray-700 p-6", children: [
9185
9769
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between mb-4", children: [
9186
- /* @__PURE__ */ jsxRuntime.jsx("h2", { className: "text-2xl font-bold text-gray-900 dark:text-white", children: t("questionForm.title") }),
9770
+ /* @__PURE__ */ jsxRuntime.jsx("h2", { className: "text-2xl font-bold text-gray-900 dark:text-white", children: t("BiChat.QuestionForm.Title") }),
9187
9771
  /* @__PURE__ */ jsxRuntime.jsx(
9188
9772
  "button",
9189
9773
  {
9190
9774
  onClick: onCancel,
9191
9775
  disabled: isSubmitting,
9192
9776
  className: "cursor-pointer text-gray-400 hover:text-gray-600 dark:hover:text-gray-300 disabled:opacity-50",
9193
- "aria-label": t("Common.Close"),
9777
+ "aria-label": t("BiChat.Common.Close"),
9194
9778
  children: /* @__PURE__ */ jsxRuntime.jsx(react.X, { className: "w-6 h-6" })
9195
9779
  }
9196
9780
  )
@@ -9224,7 +9808,7 @@ function QuestionForm({
9224
9808
  onClick: handleBack,
9225
9809
  disabled: isSubmitting,
9226
9810
  className: "cursor-pointer px-6 py-2 text-gray-700 dark:text-gray-300 bg-gray-100 dark:bg-gray-700 rounded-lg hover:bg-gray-200 dark:hover:bg-gray-600 disabled:opacity-50 font-medium transition-colors",
9227
- children: t("questionForm.back")
9811
+ children: t("BiChat.QuestionForm.Back")
9228
9812
  }
9229
9813
  ),
9230
9814
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1" }),
@@ -9235,7 +9819,7 @@ function QuestionForm({
9235
9819
  onClick: onCancel,
9236
9820
  disabled: isSubmitting,
9237
9821
  className: "cursor-pointer px-6 py-2 text-gray-700 dark:text-gray-300 border border-gray-300 dark:border-gray-600 rounded-lg hover:bg-gray-50 dark:hover:bg-gray-700 disabled:opacity-50 font-medium transition-colors",
9238
- children: t("Message.Cancel")
9822
+ children: t("BiChat.Message.Cancel")
9239
9823
  }
9240
9824
  ),
9241
9825
  /* @__PURE__ */ jsxRuntime.jsxs(
@@ -9246,7 +9830,7 @@ function QuestionForm({
9246
9830
  className: "cursor-pointer px-6 py-2 bg-primary-600 hover:bg-primary-700 disabled:opacity-50 text-white rounded-lg font-medium transition-colors flex items-center gap-2",
9247
9831
  children: [
9248
9832
  isSubmitting && /* @__PURE__ */ jsxRuntime.jsx(MemoizedLoadingSpinner, { size: "sm" }),
9249
- isSubmitting ? t("questionForm.submitting") : t("questionForm.confirm")
9833
+ isSubmitting ? t("BiChat.QuestionForm.Submitting") : t("BiChat.QuestionForm.Confirm")
9250
9834
  ]
9251
9835
  }
9252
9836
  )
@@ -9258,7 +9842,7 @@ function QuestionForm({
9258
9842
  onClick: handleNext,
9259
9843
  disabled: !currentQuestionAnswered || isSubmitting,
9260
9844
  className: "cursor-pointer px-6 py-2 bg-primary-600 hover:bg-primary-700 disabled:opacity-50 text-white rounded-lg font-medium transition-colors",
9261
- children: t("questionForm.next")
9845
+ children: t("BiChat.QuestionForm.Next")
9262
9846
  }
9263
9847
  )
9264
9848
  )
@@ -9663,55 +10247,6 @@ function useModalLock(isOpen) {
9663
10247
  };
9664
10248
  }, [isOpen]);
9665
10249
  }
9666
- function useFocusTrap(containerRef, isActive, restoreFocusOnDeactivate) {
9667
- React.useEffect(() => {
9668
- if (!isActive || !containerRef.current) return;
9669
- const container = containerRef.current;
9670
- const previouslyFocused = document.activeElement;
9671
- const getFocusableElements = () => {
9672
- const selector = [
9673
- "button:not([disabled])",
9674
- "[href]",
9675
- "input:not([disabled])",
9676
- "select:not([disabled])",
9677
- "textarea:not([disabled])",
9678
- '[tabindex]:not([tabindex="-1"])'
9679
- ].join(", ");
9680
- return Array.from(container.querySelectorAll(selector));
9681
- };
9682
- const focusableElements = getFocusableElements();
9683
- if (focusableElements.length > 0) {
9684
- focusableElements[0].focus();
9685
- }
9686
- const handleTabKey = (e) => {
9687
- if (e.key !== "Tab") return;
9688
- const focusableElements2 = getFocusableElements();
9689
- if (focusableElements2.length === 0) return;
9690
- const firstElement = focusableElements2[0];
9691
- const lastElement = focusableElements2[focusableElements2.length - 1];
9692
- if (e.shiftKey) {
9693
- if (document.activeElement === firstElement) {
9694
- e.preventDefault();
9695
- lastElement.focus();
9696
- }
9697
- } else {
9698
- if (document.activeElement === lastElement) {
9699
- e.preventDefault();
9700
- firstElement.focus();
9701
- }
9702
- }
9703
- };
9704
- container.addEventListener("keydown", handleTabKey);
9705
- return () => {
9706
- container.removeEventListener("keydown", handleTabKey);
9707
- if (restoreFocusOnDeactivate) {
9708
- restoreFocusOnDeactivate.focus();
9709
- } else if (previouslyFocused instanceof HTMLElement) {
9710
- previouslyFocused.focus();
9711
- }
9712
- };
9713
- }, [containerRef, isActive, restoreFocusOnDeactivate]);
9714
- }
9715
10250
  function useImageGallery(options = {}) {
9716
10251
  const { images: initialImages = [], wrap = false, onOpen, onClose, onNavigate } = options;
9717
10252
  const [isOpen, setIsOpen] = React.useState(false);
@@ -10247,36 +10782,6 @@ function useScrollToBottom(items) {
10247
10782
  scrollToBottom
10248
10783
  };
10249
10784
  }
10250
- function useKeyboardShortcuts(shortcuts) {
10251
- React.useEffect(() => {
10252
- const handleKeyDown = (e) => {
10253
- const target = e.target;
10254
- if (target instanceof HTMLInputElement || target instanceof HTMLTextAreaElement || target.isContentEditable) {
10255
- const allowInInput = shortcuts.find(
10256
- (s) => s.key.toLowerCase() === e.key.toLowerCase() && s.key.toLowerCase() === "escape"
10257
- );
10258
- if (!allowInInput) {
10259
- return;
10260
- }
10261
- }
10262
- const matchingShortcut = shortcuts.find((s) => {
10263
- const keyMatches = e.key.toLowerCase() === s.key.toLowerCase();
10264
- const modMatches = s.meta ? e.metaKey && !e.ctrlKey : s.ctrl ? e.ctrlKey || e.metaKey : !e.ctrlKey && !e.metaKey;
10265
- const shiftMatches = s.shift ? e.shiftKey : !e.shiftKey;
10266
- const altMatches = s.alt ? e.altKey : !e.altKey;
10267
- return keyMatches && modMatches && shiftMatches && altMatches;
10268
- });
10269
- if (matchingShortcut) {
10270
- if (matchingShortcut.preventDefault !== false) {
10271
- e.preventDefault();
10272
- }
10273
- matchingShortcut.callback();
10274
- }
10275
- };
10276
- document.addEventListener("keydown", handleKeyDown);
10277
- return () => document.removeEventListener("keydown", handleKeyDown);
10278
- }, [shortcuts]);
10279
- }
10280
10785
 
10281
10786
  // ui/src/bichat/index.ts
10282
10787
  init_IotaContext();
@@ -10731,12 +11236,63 @@ function toDownloadArtifact(artifact) {
10731
11236
  description: artifact.description
10732
11237
  };
10733
11238
  }
11239
+ function extractChartDataFromToolCalls(toolCalls) {
11240
+ if (!toolCalls) return void 0;
11241
+ for (const tc of toolCalls) {
11242
+ if (tc.name === "draw_chart" && tc.result) {
11243
+ const parsed = parseChartDataFromJsonString(tc.result);
11244
+ if (parsed) return parsed;
11245
+ }
11246
+ }
11247
+ return void 0;
11248
+ }
11249
+ var EXPORT_TOOL_NAMES = {
11250
+ export_query_to_excel: "excel",
11251
+ export_data_to_excel: "excel",
11252
+ export_to_pdf: "pdf"
11253
+ };
11254
+ function extractDownloadArtifactsFromToolCalls(toolCalls) {
11255
+ if (!toolCalls) return [];
11256
+ const artifacts = [];
11257
+ for (const tc of toolCalls) {
11258
+ const type = EXPORT_TOOL_NAMES[tc.name];
11259
+ if (!type || !tc.result) continue;
11260
+ let parsed;
11261
+ try {
11262
+ parsed = JSON.parse(tc.result);
11263
+ } catch {
11264
+ continue;
11265
+ }
11266
+ if (!isRecord(parsed) || typeof parsed.url !== "string" || !parsed.url) continue;
11267
+ const filename = typeof parsed.filename === "string" && parsed.filename ? parsed.filename : parsed.url.split("/").pop() || "download";
11268
+ const sizeKB = typeof parsed.file_size_kb === "number" ? parsed.file_size_kb : void 0;
11269
+ const sizeBytes = typeof parsed.size === "number" ? parsed.size : sizeKB != null ? sizeKB * 1024 : void 0;
11270
+ artifacts.push({
11271
+ type,
11272
+ filename,
11273
+ url: parsed.url,
11274
+ sizeReadable: sizeBytes != null ? formatSizeReadable(sizeBytes) : void 0,
11275
+ rowCount: parseRowCount(parsed),
11276
+ description: typeof parsed.description === "string" ? parsed.description : void 0
11277
+ });
11278
+ }
11279
+ return artifacts;
11280
+ }
10734
11281
  function normalizeAssistantTurn(turn) {
11282
+ const existingArtifacts = turn.artifacts || [];
11283
+ const fromToolCalls = extractDownloadArtifactsFromToolCalls(turn.toolCalls);
11284
+ const merged = [...existingArtifacts];
11285
+ for (const a of fromToolCalls) {
11286
+ if (!merged.some((e) => e.url === a.url && e.filename === a.filename)) {
11287
+ merged.push(a);
11288
+ }
11289
+ }
10735
11290
  return {
10736
11291
  ...turn,
10737
11292
  role: turn.role || "assistant" /* Assistant */,
11293
+ chartData: turn.chartData || extractChartDataFromToolCalls(turn.toolCalls),
10738
11294
  citations: turn.citations || [],
10739
- artifacts: turn.artifacts || [],
11295
+ artifacts: merged,
10740
11296
  codeOutputs: turn.codeOutputs || []
10741
11297
  };
10742
11298
  }
@@ -11147,6 +11703,7 @@ exports.AttachmentGrid = MemoizedAttachmentGrid;
11147
11703
  exports.AttachmentPreview = AttachmentPreview_default;
11148
11704
  exports.AttachmentUpload = AttachmentUpload_default;
11149
11705
  exports.Avatar = Avatar;
11706
+ exports.BiChatLayout = BiChatLayout;
11150
11707
  exports.Bubble = Bubble;
11151
11708
  exports.CHART_VISUAL = CHART_VISUAL;
11152
11709
  exports.ChartCard = ChartCard;
@@ -11233,6 +11790,7 @@ exports.getValidChildren = getValidChildren;
11233
11790
  exports.groupSessionsByDate = groupSessionsByDate;
11234
11791
  exports.hasPermission = hasPermission;
11235
11792
  exports.isImageMimeType = isImageMimeType;
11793
+ exports.isPermissionDeniedError = isPermissionDeniedError;
11236
11794
  exports.lightTheme = lightTheme;
11237
11795
  exports.listItemVariants = listItemVariants;
11238
11796
  exports.messageContainerVariants = messageContainerVariants;
@@ -11240,6 +11798,7 @@ exports.messageVariants = messageVariants;
11240
11798
  exports.scaleFadeVariants = scaleFadeVariants;
11241
11799
  exports.sessionItemVariants = sessionItemVariants;
11242
11800
  exports.staggerContainerVariants = staggerContainerVariants;
11801
+ exports.toErrorDisplay = toErrorDisplay;
11243
11802
  exports.toastVariants = toastVariants;
11244
11803
  exports.typingDotVariants = typingDotVariants;
11245
11804
  exports.useActionButtonContext = useActionButtonContext;
@@ -11262,6 +11821,7 @@ exports.useModalLock = useModalLock;
11262
11821
  exports.useOptionalChatMessaging = useOptionalChatMessaging;
11263
11822
  exports.useRequiredConfig = useRequiredConfig;
11264
11823
  exports.useScrollToBottom = useScrollToBottom;
11824
+ exports.useSidebarState = useSidebarState;
11265
11825
  exports.useStreaming = useStreaming;
11266
11826
  exports.useTheme = useTheme;
11267
11827
  exports.useToast = useToast;