@copilotz/chat-ui 0.6.6 → 0.6.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -40,7 +40,7 @@ __export(index_exports, {
40
40
  module.exports = __toCommonJS(index_exports);
41
41
 
42
42
  // src/components/chat/ChatUI.tsx
43
- var import_react9 = require("react");
43
+ var import_react10 = require("react");
44
44
  var import_react_virtual = require("@tanstack/react-virtual");
45
45
 
46
46
  // src/config/chatConfig.ts
@@ -786,8 +786,7 @@ var StreamingText = (0, import_react2.memo)(function StreamingText2({
786
786
  className = "",
787
787
  renderMarkdown = true,
788
788
  markdown,
789
- plainTextChunkChars = 12e3,
790
- contentStyle
789
+ plainTextChunkChars = 12e3
791
790
  }) {
792
791
  const hasContent = content.trim().length > 0;
793
792
  const enableSyntaxHighlight = renderMarkdown && !isStreaming && hasCodeBlocks(content);
@@ -817,7 +816,6 @@ var StreamingText = (0, import_react2.memo)(function StreamingText2({
817
816
  LongContentShell,
818
817
  {
819
818
  className: `prose prose-sm max-w-none dark:prose-invert break-words ${className}`.trim(),
820
- style: contentStyle,
821
819
  children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
822
820
  import_react_markdown.default,
823
821
  {
@@ -833,8 +831,7 @@ var StreamingText = (0, import_react2.memo)(function StreamingText2({
833
831
  {
834
832
  content,
835
833
  className,
836
- chunkSize: plainTextChunkChars,
837
- style: contentStyle
834
+ chunkSize: plainTextChunkChars
838
835
  }
839
836
  ) : null,
840
837
  isStreaming && hasContent && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "inline-block w-2 h-4 bg-primary animate-pulse ml-1" })
@@ -984,11 +981,6 @@ var Message = (0, import_react2.memo)(({
984
981
  const isCollapsed = canCollapseMessage && !isExpanded;
985
982
  const contentToRender = isCollapsed ? getCollapsedPreview(message.content, normalizedPreviewChars, previewOverride) : message.content;
986
983
  const shouldRenderMarkdown = !isCollapsed && (!messageIsUser || renderUserMarkdown);
987
- const shouldApplyLargeContentContainment = !isCollapsed && message.content.length > normalizedChunkChars;
988
- const contentStyle = shouldApplyLargeContentContainment ? {
989
- contentVisibility: "auto",
990
- containIntrinsicSize: "1px 400px"
991
- } : void 0;
992
984
  const horizontalOffsetClass = showAvatar ? messageIsUser ? compactMode ? "mr-9" : "mr-11" : compactMode ? "ml-9" : "ml-11" : "";
993
985
  const handleCopy = async () => {
994
986
  try {
@@ -1099,8 +1091,7 @@ var Message = (0, import_react2.memo)(({
1099
1091
  isStreaming: message.isStreaming,
1100
1092
  renderMarkdown: shouldRenderMarkdown,
1101
1093
  markdown,
1102
- plainTextChunkChars: normalizedChunkChars,
1103
- contentStyle
1094
+ plainTextChunkChars: normalizedChunkChars
1104
1095
  }
1105
1096
  ),
1106
1097
  canCollapseMessage && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "mt-3", children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
@@ -1165,7 +1156,7 @@ var Message = (0, import_react2.memo)(({
1165
1156
  }, arePropsEqual);
1166
1157
 
1167
1158
  // src/components/chat/Sidebar.tsx
1168
- var import_react3 = require("react");
1159
+ var import_react4 = require("react");
1169
1160
 
1170
1161
  // src/components/ui/input.tsx
1171
1162
  var import_jsx_runtime9 = require("react/jsx-runtime");
@@ -2194,6 +2185,7 @@ function DropdownMenuSeparator({
2194
2185
  var import_lucide_react8 = require("lucide-react");
2195
2186
 
2196
2187
  // src/components/chat/UserMenu.tsx
2188
+ var import_react3 = __toESM(require("react"), 1);
2197
2189
  var import_lucide_react7 = require("lucide-react");
2198
2190
  var import_jsx_runtime17 = require("react/jsx-runtime");
2199
2191
  var getInitials = (name, email) => {
@@ -2215,6 +2207,7 @@ var UserMenu = ({
2215
2207
  callbacks,
2216
2208
  currentTheme = "system",
2217
2209
  showThemeOptions = true,
2210
+ sections = [],
2218
2211
  additionalItems
2219
2212
  }) => {
2220
2213
  const { isMobile } = useSidebar();
@@ -2278,6 +2271,27 @@ var UserMenu = ({
2278
2271
  /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { children: labels.settings })
2279
2272
  ] }),
2280
2273
  additionalItems,
2274
+ sections.map((section) => /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(import_react3.default.Fragment, { children: [
2275
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(DropdownMenuSeparator, {}),
2276
+ section.label && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(DropdownMenuLabel, { className: "px-2 py-2", children: section.label }),
2277
+ section.items.map((item) => /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
2278
+ DropdownMenuItem,
2279
+ {
2280
+ onClick: item.onSelect,
2281
+ disabled: item.disabled,
2282
+ className: [
2283
+ item.checked ? "bg-accent/60" : "",
2284
+ item.variant === "destructive" ? "text-destructive focus:text-destructive focus:bg-destructive/10" : ""
2285
+ ].filter(Boolean).join(" "),
2286
+ children: [
2287
+ item.icon && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "mr-2 h-4 w-4 shrink-0", children: item.icon }),
2288
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "flex-1", children: item.label }),
2289
+ item.checked && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(import_lucide_react7.Check, { className: "ml-2 h-4 w-4 text-primary" })
2290
+ ]
2291
+ },
2292
+ item.id
2293
+ ))
2294
+ ] }, section.id)),
2281
2295
  showThemeOptions && callbacks?.onThemeChange && /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(import_jsx_runtime17.Fragment, { children: [
2282
2296
  /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(DropdownMenuSeparator, {}),
2283
2297
  /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
@@ -2337,8 +2351,8 @@ var UserMenu = ({
2337
2351
  // src/components/chat/Sidebar.tsx
2338
2352
  var import_jsx_runtime18 = require("react/jsx-runtime");
2339
2353
  var CreateThreadDialog = ({ config, onCreateThread, trigger }) => {
2340
- const [title, setTitle] = (0, import_react3.useState)("");
2341
- const [isOpen, setIsOpen] = (0, import_react3.useState)(false);
2354
+ const [title, setTitle] = (0, import_react4.useState)("");
2355
+ const [isOpen, setIsOpen] = (0, import_react4.useState)(false);
2342
2356
  const handleCreate = () => {
2343
2357
  onCreateThread(title.trim() || void 0);
2344
2358
  setTitle("");
@@ -2389,17 +2403,18 @@ var Sidebar2 = ({
2389
2403
  userMenuCallbacks,
2390
2404
  currentTheme,
2391
2405
  showThemeOptions = true,
2406
+ userMenuSections,
2392
2407
  userMenuAdditionalItems,
2393
2408
  ...props
2394
2409
  }) => {
2395
- const [searchQuery, setSearchQuery] = (0, import_react3.useState)("");
2396
- const [showArchived, setShowArchived] = (0, import_react3.useState)(false);
2397
- const [deleteThreadId, setDeleteThreadId] = (0, import_react3.useState)(null);
2398
- const [editingThreadId, setEditingThreadId] = (0, import_react3.useState)(null);
2399
- const [editTitle, setEditTitle] = (0, import_react3.useState)("");
2400
- const inputRef = (0, import_react3.useRef)(null);
2410
+ const [searchQuery, setSearchQuery] = (0, import_react4.useState)("");
2411
+ const [showArchived, setShowArchived] = (0, import_react4.useState)(false);
2412
+ const [deleteThreadId, setDeleteThreadId] = (0, import_react4.useState)(null);
2413
+ const [editingThreadId, setEditingThreadId] = (0, import_react4.useState)(null);
2414
+ const [editTitle, setEditTitle] = (0, import_react4.useState)("");
2415
+ const inputRef = (0, import_react4.useRef)(null);
2401
2416
  const { setOpen } = useSidebar();
2402
- (0, import_react3.useEffect)(() => {
2417
+ (0, import_react4.useEffect)(() => {
2403
2418
  if (editingThreadId && inputRef.current) {
2404
2419
  inputRef.current.focus();
2405
2420
  inputRef.current.select();
@@ -2407,7 +2422,9 @@ var Sidebar2 = ({
2407
2422
  }, [editingThreadId]);
2408
2423
  const filteredThreads = threads.filter((thread) => {
2409
2424
  const title = (thread.title ?? "").toString();
2410
- const matchesSearch = title.toLowerCase().includes(searchQuery.toLowerCase());
2425
+ const matchesSearch = title.toLowerCase().includes(
2426
+ searchQuery.toLowerCase()
2427
+ );
2411
2428
  const matchesArchiveFilter = showArchived || !thread.isArchived;
2412
2429
  return matchesSearch && matchesArchiveFilter;
2413
2430
  });
@@ -2531,8 +2548,12 @@ var Sidebar2 = ({
2531
2548
  value: editTitle,
2532
2549
  onChange: (e) => setEditTitle(e.target.value),
2533
2550
  onKeyDown: (e) => {
2534
- if (e.key === "Enter") saveEdit();
2535
- if (e.key === "Escape") cancelEdit();
2551
+ if (e.key === "Enter") {
2552
+ saveEdit();
2553
+ }
2554
+ if (e.key === "Escape") {
2555
+ cancelEdit();
2556
+ }
2536
2557
  },
2537
2558
  onBlur: saveEdit,
2538
2559
  className: "h-7 text-sm"
@@ -2555,28 +2576,48 @@ var Sidebar2 = ({
2555
2576
  /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_lucide_react8.MoreHorizontal, {}),
2556
2577
  /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { className: "sr-only", children: "More" })
2557
2578
  ] }) }),
2558
- /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(DropdownMenuContent, { className: "w-48", side: "right", align: "start", children: [
2559
- /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(DropdownMenuItem, { onClick: () => startEditing(thread), children: [
2560
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_lucide_react8.Edit2, { className: "mr-2 h-4 w-4" }),
2561
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { children: config.labels?.renameThread || "Rename" })
2562
- ] }),
2563
- /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(DropdownMenuItem, { onClick: () => onArchiveThread?.(thread.id), children: [
2564
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_lucide_react8.Archive, { className: "mr-2 h-4 w-4" }),
2565
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { children: thread.isArchived ? config.labels?.unarchiveThread || "Unarchive" : config.labels?.archiveThread || "Archive" })
2566
- ] }),
2567
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(DropdownMenuSeparator, {}),
2568
- /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(
2569
- DropdownMenuItem,
2570
- {
2571
- onClick: () => setDeleteThreadId(thread.id),
2572
- className: "text-destructive focus:text-destructive",
2573
- children: [
2574
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_lucide_react8.Trash2, { className: "mr-2 h-4 w-4" }),
2575
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { children: config.labels?.deleteThread || "Delete" })
2576
- ]
2577
- }
2578
- )
2579
- ] })
2579
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(
2580
+ DropdownMenuContent,
2581
+ {
2582
+ className: "w-48",
2583
+ side: "right",
2584
+ align: "start",
2585
+ children: [
2586
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(
2587
+ DropdownMenuItem,
2588
+ {
2589
+ onClick: () => startEditing(thread),
2590
+ children: [
2591
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_lucide_react8.Edit2, { className: "mr-2 h-4 w-4" }),
2592
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { children: config.labels?.renameThread || "Rename" })
2593
+ ]
2594
+ }
2595
+ ),
2596
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(
2597
+ DropdownMenuItem,
2598
+ {
2599
+ onClick: () => onArchiveThread?.(thread.id),
2600
+ children: [
2601
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_lucide_react8.Archive, { className: "mr-2 h-4 w-4" }),
2602
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { children: thread.isArchived ? config.labels?.unarchiveThread || "Unarchive" : config.labels?.archiveThread || "Archive" })
2603
+ ]
2604
+ }
2605
+ ),
2606
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(DropdownMenuSeparator, {}),
2607
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(
2608
+ DropdownMenuItem,
2609
+ {
2610
+ onClick: () => setDeleteThreadId(thread.id),
2611
+ className: "text-destructive focus:text-destructive",
2612
+ children: [
2613
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_lucide_react8.Trash2, { className: "mr-2 h-4 w-4" }),
2614
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { children: config.labels?.deleteThread || "Delete" })
2615
+ ]
2616
+ }
2617
+ )
2618
+ ]
2619
+ }
2620
+ )
2580
2621
  ] })
2581
2622
  ] }, thread.id)) }) })
2582
2623
  ] }, group))
@@ -2589,39 +2630,47 @@ var Sidebar2 = ({
2589
2630
  callbacks: userMenuCallbacks,
2590
2631
  currentTheme,
2591
2632
  showThemeOptions,
2633
+ sections: userMenuSections,
2592
2634
  additionalItems: userMenuAdditionalItems
2593
2635
  }
2594
2636
  ) }),
2595
2637
  /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(SidebarRail, {}),
2596
- deleteThreadId && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(AlertDialog, { open: !!deleteThreadId, onOpenChange: () => setDeleteThreadId(null), children: /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(AlertDialogContent, { children: [
2597
- /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(AlertDialogHeader, { children: [
2598
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(AlertDialogTitle, { children: config.labels?.deleteConfirmTitle || "Delete Conversation" }),
2599
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(AlertDialogDescription, { children: config.labels?.deleteConfirmDescription || "Are you sure you want to delete this conversation? This action cannot be undone." })
2600
- ] }),
2601
- /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(AlertDialogFooter, { children: [
2602
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(AlertDialogCancel, { children: config.labels?.cancel || "Cancel" }),
2603
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
2604
- AlertDialogAction,
2605
- {
2606
- onClick: () => deleteThreadId && handleDeleteThread(deleteThreadId),
2607
- className: "bg-destructive text-destructive-foreground hover:bg-destructive/90",
2608
- children: config.labels?.deleteThread || "Delete"
2609
- }
2610
- )
2611
- ] })
2612
- ] }) })
2638
+ deleteThreadId && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
2639
+ AlertDialog,
2640
+ {
2641
+ open: !!deleteThreadId,
2642
+ onOpenChange: () => setDeleteThreadId(null),
2643
+ children: /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(AlertDialogContent, { children: [
2644
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(AlertDialogHeader, { children: [
2645
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(AlertDialogTitle, { children: config.labels?.deleteConfirmTitle || "Delete Conversation" }),
2646
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(AlertDialogDescription, { children: config.labels?.deleteConfirmDescription || "Are you sure you want to delete this conversation? This action cannot be undone." })
2647
+ ] }),
2648
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(AlertDialogFooter, { children: [
2649
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(AlertDialogCancel, { children: config.labels?.cancel || "Cancel" }),
2650
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
2651
+ AlertDialogAction,
2652
+ {
2653
+ onClick: () => deleteThreadId && handleDeleteThread(deleteThreadId),
2654
+ className: "bg-destructive text-destructive-foreground hover:bg-destructive/90",
2655
+ children: config.labels?.deleteThread || "Delete"
2656
+ }
2657
+ )
2658
+ ] })
2659
+ ] })
2660
+ }
2661
+ )
2613
2662
  ] });
2614
2663
  };
2615
2664
 
2616
2665
  // src/components/chat/ChatHeader.tsx
2617
- var import_react5 = __toESM(require("react"), 1);
2666
+ var import_react6 = __toESM(require("react"), 1);
2618
2667
  var import_lucide_react10 = require("lucide-react");
2619
2668
 
2620
2669
  // src/components/chat/AgentSelectors.tsx
2621
- var import_react4 = require("react");
2670
+ var import_react5 = require("react");
2622
2671
  var import_lucide_react9 = require("lucide-react");
2623
2672
  var import_jsx_runtime19 = require("react/jsx-runtime");
2624
- var ParticipantsSelector = (0, import_react4.memo)(({
2673
+ var ParticipantsSelector = (0, import_react5.memo)(({
2625
2674
  agents,
2626
2675
  participantIds,
2627
2676
  onParticipantsChange,
@@ -2629,8 +2678,8 @@ var ParticipantsSelector = (0, import_react4.memo)(({
2629
2678
  maxVisible = 3,
2630
2679
  disabled = false
2631
2680
  }) => {
2632
- const agentsWithColors = (0, import_react4.useMemo)(() => assignAgentColors(agents), [agents]);
2633
- const selectedAgents = (0, import_react4.useMemo)(
2681
+ const agentsWithColors = (0, import_react5.useMemo)(() => assignAgentColors(agents), [agents]);
2682
+ const selectedAgents = (0, import_react5.useMemo)(
2634
2683
  () => agentsWithColors.filter((a) => participantIds.includes(a.id)),
2635
2684
  [agentsWithColors, participantIds]
2636
2685
  );
@@ -2719,7 +2768,7 @@ var ParticipantsSelector = (0, import_react4.memo)(({
2719
2768
  ] });
2720
2769
  });
2721
2770
  ParticipantsSelector.displayName = "ParticipantsSelector";
2722
- var TargetAgentSelector = (0, import_react4.memo)(({
2771
+ var TargetAgentSelector = (0, import_react5.memo)(({
2723
2772
  agents,
2724
2773
  targetAgentId,
2725
2774
  onTargetChange,
@@ -2727,8 +2776,8 @@ var TargetAgentSelector = (0, import_react4.memo)(({
2727
2776
  placeholder = "Select agent",
2728
2777
  disabled = false
2729
2778
  }) => {
2730
- const agentsWithColors = (0, import_react4.useMemo)(() => assignAgentColors(agents), [agents]);
2731
- const selectedAgent = (0, import_react4.useMemo)(
2779
+ const agentsWithColors = (0, import_react5.useMemo)(() => assignAgentColors(agents), [agents]);
2780
+ const selectedAgent = (0, import_react5.useMemo)(
2732
2781
  () => agentsWithColors.find((a) => a.id === targetAgentId),
2733
2782
  [agentsWithColors, targetAgentId]
2734
2783
  );
@@ -2797,7 +2846,7 @@ var TargetAgentSelector = (0, import_react4.memo)(({
2797
2846
  ] });
2798
2847
  });
2799
2848
  TargetAgentSelector.displayName = "TargetAgentSelector";
2800
- var AgentBadge = (0, import_react4.memo)(({
2849
+ var AgentBadge = (0, import_react5.memo)(({
2801
2850
  agent,
2802
2851
  onRemove,
2803
2852
  showRemove = false,
@@ -2866,11 +2915,11 @@ var ChatHeader = ({
2866
2915
  onParticipantsChange,
2867
2916
  className = ""
2868
2917
  }) => {
2869
- const [isDarkMode, setIsDarkMode] = import_react5.default.useState(() => {
2918
+ const [isDarkMode, setIsDarkMode] = import_react6.default.useState(() => {
2870
2919
  if (typeof window === "undefined") return false;
2871
2920
  return document.documentElement.classList.contains("dark");
2872
2921
  });
2873
- import_react5.default.useEffect(() => {
2922
+ import_react6.default.useEffect(() => {
2874
2923
  const observer = new MutationObserver(() => {
2875
2924
  setIsDarkMode(document.documentElement.classList.contains("dark"));
2876
2925
  });
@@ -3044,18 +3093,18 @@ var ChatHeader = ({
3044
3093
  };
3045
3094
 
3046
3095
  // src/components/chat/ChatInput.tsx
3047
- var import_react7 = __toESM(require("react"), 1);
3096
+ var import_react8 = __toESM(require("react"), 1);
3048
3097
 
3049
3098
  // src/components/chat/UserContext.tsx
3050
- var import_react6 = require("react");
3099
+ var import_react7 = require("react");
3051
3100
  var import_jsx_runtime21 = require("react/jsx-runtime");
3052
- var Ctx = (0, import_react6.createContext)(void 0);
3101
+ var Ctx = (0, import_react7.createContext)(void 0);
3053
3102
  var ChatUserContextProvider = ({ children, initial }) => {
3054
- const [ctx, setCtx] = (0, import_react6.useState)(() => ({
3103
+ const [ctx, setCtx] = (0, import_react7.useState)(() => ({
3055
3104
  updatedAt: Date.now(),
3056
3105
  ...initial ?? {}
3057
3106
  }));
3058
- (0, import_react6.useEffect)(() => {
3107
+ (0, import_react7.useEffect)(() => {
3059
3108
  if (!initial) return;
3060
3109
  setCtx((prev) => {
3061
3110
  const keys = Object.keys(initial);
@@ -3064,13 +3113,13 @@ var ChatUserContextProvider = ({ children, initial }) => {
3064
3113
  return { ...prev, ...initial, updatedAt: Date.now() };
3065
3114
  });
3066
3115
  }, [initial]);
3067
- const setPartial = (0, import_react6.useCallback)((next) => {
3116
+ const setPartial = (0, import_react7.useCallback)((next) => {
3068
3117
  setCtx((prev) => {
3069
3118
  const partial = typeof next === "function" ? next(prev) : next;
3070
3119
  return { ...prev, ...partial, updatedAt: Date.now() };
3071
3120
  });
3072
3121
  }, []);
3073
- const value = (0, import_react6.useMemo)(() => ({
3122
+ const value = (0, import_react7.useMemo)(() => ({
3074
3123
  context: ctx,
3075
3124
  setContext: setPartial,
3076
3125
  resetContext: () => setCtx({ updatedAt: Date.now() })
@@ -3078,7 +3127,7 @@ var ChatUserContextProvider = ({ children, initial }) => {
3078
3127
  return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(Ctx.Provider, { value, children });
3079
3128
  };
3080
3129
  function useChatUserContext() {
3081
- const v = (0, import_react6.useContext)(Ctx);
3130
+ const v = (0, import_react7.useContext)(Ctx);
3082
3131
  if (!v) throw new Error("useChatUserContext must be used within ChatUserContextProvider");
3083
3132
  return v;
3084
3133
  }
@@ -3662,7 +3711,7 @@ function resolveTargetFromMentions(value, agents) {
3662
3711
  }
3663
3712
  return null;
3664
3713
  }
3665
- var FileUploadItem = (0, import_react7.memo)(function FileUploadItem2({ file, progress, onCancel }) {
3714
+ var FileUploadItem = (0, import_react8.memo)(function FileUploadItem2({ file, progress, onCancel }) {
3666
3715
  const guessTypeFromName = (name) => {
3667
3716
  const ext = (name || "").split(".").pop()?.toLowerCase();
3668
3717
  switch (ext) {
@@ -3721,11 +3770,11 @@ var FileUploadItem = (0, import_react7.memo)(function FileUploadItem2({ file, pr
3721
3770
  )
3722
3771
  ] }) }) });
3723
3772
  });
3724
- var AttachmentPreview = (0, import_react7.memo)(function AttachmentPreview2({ attachment, onRemove }) {
3725
- const [isPlaying, setIsPlaying] = (0, import_react7.useState)(false);
3726
- const [audioPlaybackSrc, setAudioPlaybackSrc] = (0, import_react7.useState)(attachment.dataUrl);
3727
- const audioRef = (0, import_react7.useRef)(null);
3728
- (0, import_react7.useEffect)(() => {
3773
+ var AttachmentPreview = (0, import_react8.memo)(function AttachmentPreview2({ attachment, onRemove }) {
3774
+ const [isPlaying, setIsPlaying] = (0, import_react8.useState)(false);
3775
+ const [audioPlaybackSrc, setAudioPlaybackSrc] = (0, import_react8.useState)(attachment.dataUrl);
3776
+ const audioRef = (0, import_react8.useRef)(null);
3777
+ (0, import_react8.useEffect)(() => {
3729
3778
  if (attachment.kind !== "audio" || !attachment.dataUrl.startsWith("data:")) {
3730
3779
  setAudioPlaybackSrc(attachment.dataUrl);
3731
3780
  return;
@@ -3850,7 +3899,7 @@ var resolveVoiceErrorMessage = (error, config) => {
3850
3899
  };
3851
3900
  var clearVoiceTranscript = () => ({});
3852
3901
  var resolveVoiceSegmentDuration = (segment) => segment.attachment.durationMs ?? 0;
3853
- var ChatInput = (0, import_react7.memo)(function ChatInput2({
3902
+ var ChatInput = (0, import_react8.memo)(function ChatInput2({
3854
3903
  value,
3855
3904
  onChange,
3856
3905
  onSubmit,
@@ -3879,27 +3928,27 @@ var ChatInput = (0, import_react7.memo)(function ChatInput2({
3879
3928
  const voiceTranscriptMode = config?.voiceCompose?.transcriptMode ?? "final-only";
3880
3929
  const voiceMaxRecordingMs = config?.voiceCompose?.maxRecordingMs;
3881
3930
  const { setContext } = useChatUserContext();
3882
- const [uploadProgress, setUploadProgress] = (0, import_react7.useState)(/* @__PURE__ */ new Map());
3883
- const [isVoiceComposerOpen, setIsVoiceComposerOpen] = (0, import_react7.useState)(
3931
+ const [uploadProgress, setUploadProgress] = (0, import_react8.useState)(/* @__PURE__ */ new Map());
3932
+ const [isVoiceComposerOpen, setIsVoiceComposerOpen] = (0, import_react8.useState)(
3884
3933
  () => enableAudioRecording && voiceDefaultMode === "voice"
3885
3934
  );
3886
- const [voiceState, setVoiceState] = (0, import_react7.useState)("idle");
3887
- const [voiceDraft, setVoiceDraft] = (0, import_react7.useState)(null);
3888
- const [voiceTranscript, setVoiceTranscript] = (0, import_react7.useState)(clearVoiceTranscript);
3889
- const [voiceDurationMs, setVoiceDurationMs] = (0, import_react7.useState)(0);
3890
- const [voiceAudioLevel, setVoiceAudioLevel] = (0, import_react7.useState)(0);
3891
- const [voiceCountdownMs, setVoiceCountdownMs] = (0, import_react7.useState)(0);
3892
- const [isVoiceAutoSendActive, setIsVoiceAutoSendActive] = (0, import_react7.useState)(false);
3893
- const [voiceError, setVoiceError] = (0, import_react7.useState)(null);
3894
- const [activeMention, setActiveMention] = (0, import_react7.useState)(null);
3895
- const [activeMentionIndex, setActiveMentionIndex] = (0, import_react7.useState)(0);
3896
- const textareaRef = (0, import_react7.useRef)(null);
3897
- const fileInputRef = (0, import_react7.useRef)(null);
3898
- const voiceProviderRef = (0, import_react7.useRef)(null);
3899
- const voiceDraftRef = (0, import_react7.useRef)(null);
3900
- const voiceAppendBaseRef = (0, import_react7.useRef)(null);
3901
- const voiceAppendBaseDurationRef = (0, import_react7.useRef)(0);
3902
- const filteredMentionAgents = import_react7.default.useMemo(() => {
3935
+ const [voiceState, setVoiceState] = (0, import_react8.useState)("idle");
3936
+ const [voiceDraft, setVoiceDraft] = (0, import_react8.useState)(null);
3937
+ const [voiceTranscript, setVoiceTranscript] = (0, import_react8.useState)(clearVoiceTranscript);
3938
+ const [voiceDurationMs, setVoiceDurationMs] = (0, import_react8.useState)(0);
3939
+ const [voiceAudioLevel, setVoiceAudioLevel] = (0, import_react8.useState)(0);
3940
+ const [voiceCountdownMs, setVoiceCountdownMs] = (0, import_react8.useState)(0);
3941
+ const [isVoiceAutoSendActive, setIsVoiceAutoSendActive] = (0, import_react8.useState)(false);
3942
+ const [voiceError, setVoiceError] = (0, import_react8.useState)(null);
3943
+ const [activeMention, setActiveMention] = (0, import_react8.useState)(null);
3944
+ const [activeMentionIndex, setActiveMentionIndex] = (0, import_react8.useState)(0);
3945
+ const textareaRef = (0, import_react8.useRef)(null);
3946
+ const fileInputRef = (0, import_react8.useRef)(null);
3947
+ const voiceProviderRef = (0, import_react8.useRef)(null);
3948
+ const voiceDraftRef = (0, import_react8.useRef)(null);
3949
+ const voiceAppendBaseRef = (0, import_react8.useRef)(null);
3950
+ const voiceAppendBaseDurationRef = (0, import_react8.useRef)(0);
3951
+ const filteredMentionAgents = import_react8.default.useMemo(() => {
3903
3952
  if (!activeMention || mentionAgents.length === 0) return [];
3904
3953
  const query = activeMention.query.trim().toLowerCase();
3905
3954
  const rank = (agent) => {
@@ -3917,7 +3966,7 @@ var ChatInput = (0, import_react7.memo)(function ChatInput2({
3917
3966
  }).slice(0, 6);
3918
3967
  }, [activeMention, mentionAgents]);
3919
3968
  const isMentionMenuOpen = filteredMentionAgents.length > 0;
3920
- const syncMentionState = (0, import_react7.useCallback)((nextValue, nextCaret) => {
3969
+ const syncMentionState = (0, import_react8.useCallback)((nextValue, nextCaret) => {
3921
3970
  const caret = typeof nextCaret === "number" ? nextCaret : textareaRef.current?.selectionStart ?? nextValue.length;
3922
3971
  const nextMatch = getActiveMentionMatch(nextValue, caret);
3923
3972
  setActiveMention((prev) => {
@@ -3928,7 +3977,7 @@ var ChatInput = (0, import_react7.memo)(function ChatInput2({
3928
3977
  });
3929
3978
  setActiveMentionIndex(0);
3930
3979
  }, []);
3931
- (0, import_react7.useEffect)(() => {
3980
+ (0, import_react8.useEffect)(() => {
3932
3981
  return () => {
3933
3982
  if (voiceProviderRef.current) {
3934
3983
  void voiceProviderRef.current.destroy();
@@ -3936,10 +3985,10 @@ var ChatInput = (0, import_react7.memo)(function ChatInput2({
3936
3985
  }
3937
3986
  };
3938
3987
  }, []);
3939
- (0, import_react7.useEffect)(() => {
3988
+ (0, import_react8.useEffect)(() => {
3940
3989
  voiceDraftRef.current = voiceDraft;
3941
3990
  }, [voiceDraft]);
3942
- (0, import_react7.useEffect)(() => {
3991
+ (0, import_react8.useEffect)(() => {
3943
3992
  if (!isMentionMenuOpen) {
3944
3993
  setActiveMentionIndex(0);
3945
3994
  return;
@@ -3948,7 +3997,7 @@ var ChatInput = (0, import_react7.memo)(function ChatInput2({
3948
3997
  (prev) => prev >= filteredMentionAgents.length ? 0 : prev
3949
3998
  );
3950
3999
  }, [filteredMentionAgents.length, isMentionMenuOpen]);
3951
- const selectMentionAgent = (0, import_react7.useCallback)((agent) => {
4000
+ const selectMentionAgent = (0, import_react8.useCallback)((agent) => {
3952
4001
  if (!activeMention) return;
3953
4002
  const replacement = `@${agent.name} `;
3954
4003
  const nextValue = value.slice(0, activeMention.start) + replacement + value.slice(activeMention.end);
@@ -4086,7 +4135,7 @@ var ChatInput = (0, import_react7.memo)(function ChatInput2({
4086
4135
  }
4087
4136
  e.target.value = "";
4088
4137
  };
4089
- const handleDrop = (0, import_react7.useCallback)(async (e) => {
4138
+ const handleDrop = (0, import_react8.useCallback)(async (e) => {
4090
4139
  e.preventDefault();
4091
4140
  if (!enableFileUpload) return;
4092
4141
  const files = Array.from(e.dataTransfer.files);
@@ -4099,10 +4148,10 @@ var ChatInput = (0, import_react7.memo)(function ChatInput2({
4099
4148
  }
4100
4149
  }
4101
4150
  }, [attachments, enableFileUpload, maxAttachments, onAttachmentsChange]);
4102
- const handleDragOver = (0, import_react7.useCallback)((e) => {
4151
+ const handleDragOver = (0, import_react8.useCallback)((e) => {
4103
4152
  e.preventDefault();
4104
4153
  }, []);
4105
- const resetVoiceComposerState = (0, import_react7.useCallback)((nextState = "idle") => {
4154
+ const resetVoiceComposerState = (0, import_react8.useCallback)((nextState = "idle") => {
4106
4155
  setVoiceState(nextState);
4107
4156
  setVoiceDraft(null);
4108
4157
  voiceDraftRef.current = null;
@@ -4115,11 +4164,11 @@ var ChatInput = (0, import_react7.memo)(function ChatInput2({
4115
4164
  setIsVoiceAutoSendActive(false);
4116
4165
  setVoiceError(null);
4117
4166
  }, []);
4118
- const armVoiceDraftForAppend = (0, import_react7.useCallback)((segment) => {
4167
+ const armVoiceDraftForAppend = (0, import_react8.useCallback)((segment) => {
4119
4168
  voiceAppendBaseRef.current = segment;
4120
4169
  voiceAppendBaseDurationRef.current = segment ? resolveVoiceSegmentDuration(segment) : 0;
4121
4170
  }, []);
4122
- const handleVoiceProviderStateChange = (0, import_react7.useCallback)((nextState) => {
4171
+ const handleVoiceProviderStateChange = (0, import_react8.useCallback)((nextState) => {
4123
4172
  if (voiceReviewMode === "armed" && (nextState === "waiting_for_speech" || nextState === "listening")) {
4124
4173
  const currentDraft = voiceDraftRef.current;
4125
4174
  if (currentDraft) {
@@ -4132,7 +4181,7 @@ var ChatInput = (0, import_react7.memo)(function ChatInput2({
4132
4181
  }
4133
4182
  setVoiceState(nextState);
4134
4183
  }, [armVoiceDraftForAppend, voiceAutoSendDelayMs, voiceReviewMode]);
4135
- const ensureVoiceProvider = (0, import_react7.useCallback)(async () => {
4184
+ const ensureVoiceProvider = (0, import_react8.useCallback)(async () => {
4136
4185
  if (voiceProviderRef.current) {
4137
4186
  return voiceProviderRef.current;
4138
4187
  }
@@ -4219,7 +4268,7 @@ var ChatInput = (0, import_react7.memo)(function ChatInput2({
4219
4268
  voiceProviderRef.current = provider;
4220
4269
  return provider;
4221
4270
  }, [armVoiceDraftForAppend, config, handleVoiceProviderStateChange, voiceAutoSendDelayMs, voiceMaxRecordingMs, voiceReviewMode]);
4222
- const closeVoiceComposer = (0, import_react7.useCallback)(async () => {
4271
+ const closeVoiceComposer = (0, import_react8.useCallback)(async () => {
4223
4272
  voiceAppendBaseRef.current = null;
4224
4273
  voiceAppendBaseDurationRef.current = 0;
4225
4274
  setIsVoiceComposerOpen(false);
@@ -4235,7 +4284,7 @@ var ChatInput = (0, import_react7.memo)(function ChatInput2({
4235
4284
  await voiceProviderRef.current.cancel();
4236
4285
  }
4237
4286
  }, []);
4238
- const startVoiceCapture = (0, import_react7.useCallback)(async (appendToDraft = false) => {
4287
+ const startVoiceCapture = (0, import_react8.useCallback)(async (appendToDraft = false) => {
4239
4288
  if (disabled || isGenerating) {
4240
4289
  return;
4241
4290
  }
@@ -4284,7 +4333,7 @@ var ChatInput = (0, import_react7.memo)(function ChatInput2({
4284
4333
  setVoiceState("error");
4285
4334
  }
4286
4335
  }, [disabled, isGenerating, ensureVoiceProvider, config]);
4287
- const stopVoiceCapture = (0, import_react7.useCallback)(async () => {
4336
+ const stopVoiceCapture = (0, import_react8.useCallback)(async () => {
4288
4337
  if (!voiceProviderRef.current) return;
4289
4338
  try {
4290
4339
  await voiceProviderRef.current.stop();
@@ -4293,7 +4342,7 @@ var ChatInput = (0, import_react7.memo)(function ChatInput2({
4293
4342
  setVoiceState("error");
4294
4343
  }
4295
4344
  }, [config]);
4296
- const cancelVoiceCapture = (0, import_react7.useCallback)(async () => {
4345
+ const cancelVoiceCapture = (0, import_react8.useCallback)(async () => {
4297
4346
  voiceAppendBaseRef.current = null;
4298
4347
  voiceAppendBaseDurationRef.current = 0;
4299
4348
  if (voiceProviderRef.current) {
@@ -4301,7 +4350,7 @@ var ChatInput = (0, import_react7.memo)(function ChatInput2({
4301
4350
  }
4302
4351
  resetVoiceComposerState("idle");
4303
4352
  }, [resetVoiceComposerState]);
4304
- const finalizeVoiceComposerAfterSend = (0, import_react7.useCallback)(() => {
4353
+ const finalizeVoiceComposerAfterSend = (0, import_react8.useCallback)(() => {
4305
4354
  if (voicePersistComposer) {
4306
4355
  resetVoiceComposerState("idle");
4307
4356
  setIsVoiceComposerOpen(true);
@@ -4309,7 +4358,7 @@ var ChatInput = (0, import_react7.memo)(function ChatInput2({
4309
4358
  }
4310
4359
  void closeVoiceComposer();
4311
4360
  }, [voicePersistComposer, resetVoiceComposerState, closeVoiceComposer]);
4312
- const sendVoiceDraft = (0, import_react7.useCallback)(() => {
4361
+ const sendVoiceDraft = (0, import_react8.useCallback)(() => {
4313
4362
  void (async () => {
4314
4363
  if (!voiceDraft || disabled || isGenerating) {
4315
4364
  return;
@@ -4335,7 +4384,7 @@ var ChatInput = (0, import_react7.memo)(function ChatInput2({
4335
4384
  onAttachmentsChange,
4336
4385
  finalizeVoiceComposerAfterSend
4337
4386
  ]);
4338
- const cancelVoiceAutoSend = (0, import_react7.useCallback)(() => {
4387
+ const cancelVoiceAutoSend = (0, import_react8.useCallback)(() => {
4339
4388
  void (async () => {
4340
4389
  if (voiceReviewMode === "armed" && voiceProviderRef.current) {
4341
4390
  await voiceProviderRef.current.cancel();
@@ -4347,7 +4396,7 @@ var ChatInput = (0, import_react7.memo)(function ChatInput2({
4347
4396
  setVoiceCountdownMs(0);
4348
4397
  setIsVoiceAutoSendActive(false);
4349
4398
  }, [armVoiceDraftForAppend, voiceReviewMode]);
4350
- const pauseVoiceReview = (0, import_react7.useCallback)(async () => {
4399
+ const pauseVoiceReview = (0, import_react8.useCallback)(async () => {
4351
4400
  if (voiceState === "listening") {
4352
4401
  await stopVoiceCapture();
4353
4402
  return;
@@ -4359,7 +4408,7 @@ var ChatInput = (0, import_react7.memo)(function ChatInput2({
4359
4408
  setVoiceAudioLevel(0);
4360
4409
  setVoiceState("review");
4361
4410
  }, [armVoiceDraftForAppend, stopVoiceCapture, voiceReviewMode, voiceState]);
4362
- (0, import_react7.useEffect)(() => {
4411
+ (0, import_react8.useEffect)(() => {
4363
4412
  if (!voiceDraft || voiceAutoSendDelayMs <= 0 || !isVoiceAutoSendActive) {
4364
4413
  return;
4365
4414
  }
@@ -4596,13 +4645,13 @@ var ChatInput = (0, import_react7.memo)(function ChatInput2({
4596
4645
  });
4597
4646
 
4598
4647
  // src/components/chat/UserProfile.tsx
4599
- var import_react8 = require("react");
4648
+ var import_react9 = require("react");
4600
4649
 
4601
4650
  // src/components/ui/scroll-area.tsx
4602
- var React13 = __toESM(require("react"), 1);
4651
+ var React14 = __toESM(require("react"), 1);
4603
4652
  var ScrollAreaPrimitive = __toESM(require("@radix-ui/react-scroll-area"), 1);
4604
4653
  var import_jsx_runtime25 = require("react/jsx-runtime");
4605
- var ScrollArea = React13.forwardRef(({ className, children, viewportClassName, onScroll, onScrollCapture, ...props }, ref) => {
4654
+ var ScrollArea = React14.forwardRef(({ className, children, viewportClassName, onScroll, onScrollCapture, ...props }, ref) => {
4606
4655
  return /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(
4607
4656
  ScrollAreaPrimitive.Root,
4608
4657
  {
@@ -4770,10 +4819,10 @@ var UserProfile = ({
4770
4819
  onDeleteMemory,
4771
4820
  className
4772
4821
  }) => {
4773
- const [newMemoryContent, setNewMemoryContent] = (0, import_react8.useState)("");
4774
- const [isAddingMemory, setIsAddingMemory] = (0, import_react8.useState)(false);
4775
- const [editingMemoryId, setEditingMemoryId] = (0, import_react8.useState)(null);
4776
- const [editingMemoryContent, setEditingMemoryContent] = (0, import_react8.useState)("");
4822
+ const [newMemoryContent, setNewMemoryContent] = (0, import_react9.useState)("");
4823
+ const [isAddingMemory, setIsAddingMemory] = (0, import_react9.useState)(false);
4824
+ const [editingMemoryId, setEditingMemoryId] = (0, import_react9.useState)(null);
4825
+ const [editingMemoryContent, setEditingMemoryContent] = (0, import_react9.useState)("");
4777
4826
  const handleAddMemory = () => {
4778
4827
  if (newMemoryContent.trim() && onAddMemory) {
4779
4828
  onAddMemory(newMemoryContent.trim(), "other");
@@ -5049,7 +5098,9 @@ function getMessageSpeakerKey(message) {
5049
5098
  }
5050
5099
  function getAssistantSpeakerTokens(message) {
5051
5100
  if (!message || message.role !== "assistant") return [];
5052
- const rawTokens = [message.senderAgentId, message.senderName].filter((value) => typeof value === "string" && value.trim().length > 0).map((value) => value.trim().toLowerCase());
5101
+ const rawTokens = [message.senderAgentId, message.senderName].filter(
5102
+ (value) => typeof value === "string" && value.trim().length > 0
5103
+ ).map((value) => value.trim().toLowerCase());
5053
5104
  if (rawTokens.length > 0) {
5054
5105
  return Array.from(new Set(rawTokens));
5055
5106
  }
@@ -5083,7 +5134,9 @@ var mergeReasoning = (activities) => {
5083
5134
  return segments.filter((segment, index) => index === 0 || segment !== segments[index - 1]).join("\n\n");
5084
5135
  };
5085
5136
  var mergeGroupActivity = (messages) => {
5086
- const activities = messages.map((message) => message.activity).filter((activity) => Boolean(activity));
5137
+ const activities = messages.map((message) => message.activity).filter(
5138
+ (activity) => Boolean(activity)
5139
+ );
5087
5140
  if (activities.length === 0) return void 0;
5088
5141
  const lastActivity = activities[activities.length - 1];
5089
5142
  const mergedReasoning = mergeReasoning(activities);
@@ -5147,6 +5200,7 @@ var ChatUI = ({
5147
5200
  currentThreadId = null,
5148
5201
  config: userConfig,
5149
5202
  sidebar: _sidebar,
5203
+ userMenuSections,
5150
5204
  userMenuAdditionalItems,
5151
5205
  isGenerating = false,
5152
5206
  isMessagesLoading = false,
@@ -5172,12 +5226,12 @@ var ChatUI = ({
5172
5226
  initialInput,
5173
5227
  onInitialInputConsumed
5174
5228
  }) => {
5175
- const config = (0, import_react9.useMemo)(
5229
+ const config = (0, import_react10.useMemo)(
5176
5230
  () => mergeConfig(defaultChatConfig, userConfig),
5177
5231
  [userConfig]
5178
5232
  );
5179
- const [isMobile, setIsMobile] = (0, import_react9.useState)(false);
5180
- const [isUserProfileOpen, setIsUserProfileOpen] = (0, import_react9.useState)(false);
5233
+ const [isMobile, setIsMobile] = (0, import_react10.useState)(false);
5234
+ const [isUserProfileOpen, setIsUserProfileOpen] = (0, import_react10.useState)(false);
5181
5235
  let userContext;
5182
5236
  try {
5183
5237
  const contextValue = useChatUserContext();
@@ -5191,10 +5245,10 @@ var ChatUI = ({
5191
5245
  }
5192
5246
  return false;
5193
5247
  };
5194
- const [inputValue, setInputValue] = (0, import_react9.useState)("");
5195
- const [attachments, setAttachments] = (0, import_react9.useState)([]);
5196
- const [expandedMessageIds, setExpandedMessageIds] = (0, import_react9.useState)({});
5197
- const [state, setState] = (0, import_react9.useState)({
5248
+ const [inputValue, setInputValue] = (0, import_react10.useState)("");
5249
+ const [attachments, setAttachments] = (0, import_react10.useState)([]);
5250
+ const [expandedMessageIds, setExpandedMessageIds] = (0, import_react10.useState)({});
5251
+ const [state, setState] = (0, import_react10.useState)({
5198
5252
  isRecording: false,
5199
5253
  selectedThreadId: currentThreadId,
5200
5254
  isAtBottom: true,
@@ -5206,43 +5260,46 @@ var ChatUI = ({
5206
5260
  isSidebarCollapsed: false
5207
5261
  // No longer used for main sidebar
5208
5262
  });
5209
- (0, import_react9.useEffect)(() => {
5263
+ (0, import_react10.useEffect)(() => {
5210
5264
  if (currentThreadId !== state.selectedThreadId) {
5211
5265
  setState((prev) => ({ ...prev, selectedThreadId: currentThreadId }));
5212
5266
  }
5213
5267
  }, [currentThreadId]);
5214
- const initialInputApplied = (0, import_react9.useRef)(false);
5215
- const initialInputConsumedRef = (0, import_react9.useRef)(false);
5216
- (0, import_react9.useEffect)(() => {
5268
+ const initialInputApplied = (0, import_react10.useRef)(false);
5269
+ const initialInputConsumedRef = (0, import_react10.useRef)(false);
5270
+ (0, import_react10.useEffect)(() => {
5217
5271
  if (initialInput && !initialInputApplied.current) {
5218
5272
  setInputValue(initialInput);
5219
5273
  initialInputApplied.current = true;
5220
5274
  }
5221
5275
  }, [initialInput]);
5222
- const scrollAreaRef = (0, import_react9.useRef)(null);
5223
- const prependSnapshotRef = (0, import_react9.useRef)(null);
5224
- const stateRef = (0, import_react9.useRef)(state);
5225
- const inputValueRef = (0, import_react9.useRef)(inputValue);
5226
- const attachmentsRef = (0, import_react9.useRef)(attachments);
5227
- (0, import_react9.useEffect)(() => {
5276
+ const scrollAreaRef = (0, import_react10.useRef)(null);
5277
+ const prependSnapshotRef = (0, import_react10.useRef)(null);
5278
+ const stateRef = (0, import_react10.useRef)(state);
5279
+ const inputValueRef = (0, import_react10.useRef)(inputValue);
5280
+ const attachmentsRef = (0, import_react10.useRef)(attachments);
5281
+ (0, import_react10.useEffect)(() => {
5228
5282
  stateRef.current = state;
5229
5283
  }, [state]);
5230
- (0, import_react9.useEffect)(() => {
5284
+ (0, import_react10.useEffect)(() => {
5231
5285
  inputValueRef.current = inputValue;
5232
5286
  }, [inputValue]);
5233
- (0, import_react9.useEffect)(() => {
5287
+ (0, import_react10.useEffect)(() => {
5234
5288
  attachmentsRef.current = attachments;
5235
5289
  }, [attachments]);
5236
- const [isCustomMounted, setIsCustomMounted] = (0, import_react9.useState)(false);
5237
- const [isCustomVisible, setIsCustomVisible] = (0, import_react9.useState)(false);
5238
- const groupedMessages = (0, import_react9.useMemo)(() => groupMessagesForRender(messages), [messages]);
5290
+ const [isCustomMounted, setIsCustomMounted] = (0, import_react10.useState)(false);
5291
+ const [isCustomVisible, setIsCustomVisible] = (0, import_react10.useState)(false);
5292
+ const groupedMessages = (0, import_react10.useMemo)(() => groupMessagesForRender(messages), [
5293
+ messages
5294
+ ]);
5239
5295
  const virtualizer = (0, import_react_virtual.useVirtualizer)({
5240
5296
  count: groupedMessages.length,
5241
5297
  getScrollElement: () => scrollAreaRef.current,
5298
+ getItemKey: (index) => groupedMessages[index]?.id ?? index,
5242
5299
  estimateSize: () => 100,
5243
5300
  overscan: 5
5244
5301
  });
5245
- const createStateCallback = (0, import_react9.useCallback)(
5302
+ const createStateCallback = (0, import_react10.useCallback)(
5246
5303
  (setter) => ({
5247
5304
  setState: (newState) => setter?.(newState),
5248
5305
  getState: () => ({
@@ -5254,7 +5311,7 @@ var ChatUI = ({
5254
5311
  []
5255
5312
  // No dependencies - uses refs for latest state
5256
5313
  );
5257
- (0, import_react9.useEffect)(() => {
5314
+ (0, import_react10.useEffect)(() => {
5258
5315
  const checkMobile = () => {
5259
5316
  setIsMobile(globalThis.innerWidth < 1024);
5260
5317
  };
@@ -5262,7 +5319,7 @@ var ChatUI = ({
5262
5319
  globalThis.addEventListener("resize", checkMobile);
5263
5320
  return () => globalThis.removeEventListener("resize", checkMobile);
5264
5321
  }, []);
5265
- (0, import_react9.useEffect)(() => {
5322
+ (0, import_react10.useEffect)(() => {
5266
5323
  if (!isMobile || !config.customComponent?.component) return;
5267
5324
  if (state.showSidebar) {
5268
5325
  setIsCustomMounted(true);
@@ -5273,8 +5330,8 @@ var ChatUI = ({
5273
5330
  return () => clearTimeout(t);
5274
5331
  }
5275
5332
  }, [state.showSidebar, isMobile, config.customComponent]);
5276
- const prevMessageCountRef = (0, import_react9.useRef)(0);
5277
- (0, import_react9.useEffect)(() => {
5333
+ const prevMessageCountRef = (0, import_react10.useRef)(0);
5334
+ (0, import_react10.useEffect)(() => {
5278
5335
  if (groupedMessages.length === 0) {
5279
5336
  prevMessageCountRef.current = 0;
5280
5337
  return;
@@ -5288,7 +5345,9 @@ var ChatUI = ({
5288
5345
  if (wasEmpty) {
5289
5346
  requestAnimationFrame(() => {
5290
5347
  requestAnimationFrame(() => {
5291
- virtualizer.scrollToIndex(groupedMessages.length - 1, { align: "end" });
5348
+ virtualizer.scrollToIndex(groupedMessages.length - 1, {
5349
+ align: "end"
5350
+ });
5292
5351
  });
5293
5352
  });
5294
5353
  return;
@@ -5304,13 +5363,34 @@ var ChatUI = ({
5304
5363
  }
5305
5364
  });
5306
5365
  }, [groupedMessages, state.isAtBottom, virtualizer]);
5307
- (0, import_react9.useEffect)(() => {
5308
- virtualizer.measure();
5309
- }, [expandedMessageIds, virtualizer]);
5310
- (0, import_react9.useEffect)(() => {
5366
+ (0, import_react10.useEffect)(() => {
5367
+ const viewport = scrollAreaRef.current;
5368
+ if (!viewport) return;
5369
+ let rafId;
5370
+ const ro = new ResizeObserver(() => {
5371
+ cancelAnimationFrame(rafId);
5372
+ rafId = requestAnimationFrame(() => {
5373
+ const elements = virtualizer.elementsCache;
5374
+ if (elements) {
5375
+ elements.forEach((node) => {
5376
+ if (node.isConnected) {
5377
+ virtualizer.observer?.unobserve(node);
5378
+ virtualizer.observer?.observe(node);
5379
+ }
5380
+ });
5381
+ }
5382
+ });
5383
+ });
5384
+ ro.observe(viewport);
5385
+ return () => {
5386
+ cancelAnimationFrame(rafId);
5387
+ ro.disconnect();
5388
+ };
5389
+ }, [virtualizer]);
5390
+ (0, import_react10.useEffect)(() => {
5311
5391
  prependSnapshotRef.current = null;
5312
5392
  }, [currentThreadId]);
5313
- (0, import_react9.useEffect)(() => {
5393
+ (0, import_react10.useEffect)(() => {
5314
5394
  const snapshot = prependSnapshotRef.current;
5315
5395
  if (!snapshot) return;
5316
5396
  if (groupedMessages.length <= snapshot.messageCount) {
@@ -5336,7 +5416,7 @@ var ChatUI = ({
5336
5416
  });
5337
5417
  });
5338
5418
  }, [groupedMessages, isLoadingOlderMessages, virtualizer]);
5339
- const requestOlderMessages = (0, import_react9.useCallback)(() => {
5419
+ const requestOlderMessages = (0, import_react10.useCallback)(() => {
5340
5420
  if (!onLoadOlderMessages || !hasMoreMessagesBefore || isLoadingOlderMessages) return;
5341
5421
  const viewport = scrollAreaRef.current;
5342
5422
  prependSnapshotRef.current = viewport ? {
@@ -5346,12 +5426,19 @@ var ChatUI = ({
5346
5426
  messageCount: groupedMessages.length
5347
5427
  } : null;
5348
5428
  onLoadOlderMessages();
5349
- }, [groupedMessages, hasMoreMessagesBefore, isLoadingOlderMessages, onLoadOlderMessages]);
5350
- (0, import_react9.useEffect)(() => {
5429
+ }, [
5430
+ groupedMessages,
5431
+ hasMoreMessagesBefore,
5432
+ isLoadingOlderMessages,
5433
+ onLoadOlderMessages
5434
+ ]);
5435
+ (0, import_react10.useEffect)(() => {
5351
5436
  const validMessageIds = new Set(groupedMessages.map((group) => group.id));
5352
5437
  setExpandedMessageIds((prev) => {
5353
5438
  const activeIds = Object.keys(prev);
5354
- const staleIds = activeIds.filter((messageId) => !validMessageIds.has(messageId));
5439
+ const staleIds = activeIds.filter(
5440
+ (messageId) => !validMessageIds.has(messageId)
5441
+ );
5355
5442
  if (staleIds.length === 0) {
5356
5443
  return prev;
5357
5444
  }
@@ -5362,7 +5449,7 @@ var ChatUI = ({
5362
5449
  return next;
5363
5450
  });
5364
5451
  }, [groupedMessages]);
5365
- const handleScroll = (0, import_react9.useCallback)((e) => {
5452
+ const handleScroll = (0, import_react10.useCallback)((e) => {
5366
5453
  const { scrollTop, scrollHeight, clientHeight } = e.currentTarget;
5367
5454
  const isAtBottom = scrollHeight - scrollTop - clientHeight < 50;
5368
5455
  const isNearTop = scrollTop < 120;
@@ -5374,9 +5461,13 @@ var ChatUI = ({
5374
5461
  return { ...prev, isAtBottom };
5375
5462
  });
5376
5463
  }, [hasMoreMessagesBefore, isLoadingOlderMessages, requestOlderMessages]);
5377
- const handleSendMessage = (0, import_react9.useCallback)((content, messageAttachments = []) => {
5464
+ const handleSendMessage = (0, import_react10.useCallback)((content, messageAttachments = []) => {
5378
5465
  if (!content.trim() && messageAttachments.length === 0) return;
5379
- callbacks.onSendMessage?.(content, messageAttachments, createStateCallback());
5466
+ callbacks.onSendMessage?.(
5467
+ content,
5468
+ messageAttachments,
5469
+ createStateCallback()
5470
+ );
5380
5471
  if (initialInputApplied.current && !initialInputConsumedRef.current) {
5381
5472
  initialInputConsumedRef.current = true;
5382
5473
  onInitialInputConsumed?.();
@@ -5384,11 +5475,15 @@ var ChatUI = ({
5384
5475
  setInputValue("");
5385
5476
  setAttachments([]);
5386
5477
  }, [callbacks, createStateCallback, onInitialInputConsumed]);
5387
- const handleMessageAction = (0, import_react9.useCallback)((event) => {
5478
+ const handleMessageAction = (0, import_react10.useCallback)((event) => {
5388
5479
  const { action, messageId, content } = event;
5389
5480
  switch (action) {
5390
5481
  case "copy":
5391
- callbacks.onCopyMessage?.(messageId, content || "", createStateCallback());
5482
+ callbacks.onCopyMessage?.(
5483
+ messageId,
5484
+ content || "",
5485
+ createStateCallback()
5486
+ );
5392
5487
  break;
5393
5488
  case "edit":
5394
5489
  if (content) {
@@ -5403,7 +5498,7 @@ var ChatUI = ({
5403
5498
  break;
5404
5499
  }
5405
5500
  }, [callbacks, createStateCallback]);
5406
- const handleToggleMessageExpansion = (0, import_react9.useCallback)((messageId) => {
5501
+ const handleToggleMessageExpansion = (0, import_react10.useCallback)((messageId) => {
5407
5502
  setExpandedMessageIds((prev) => {
5408
5503
  if (prev[messageId]) {
5409
5504
  const next = { ...prev };
@@ -5416,44 +5511,52 @@ var ChatUI = ({
5416
5511
  };
5417
5512
  });
5418
5513
  }, []);
5419
- const handleCreateThread = (0, import_react9.useCallback)((title) => {
5514
+ const handleCreateThread = (0, import_react10.useCallback)((title) => {
5420
5515
  callbacks.onCreateThread?.(title, createStateCallback());
5421
5516
  }, [callbacks, createStateCallback]);
5422
- const handleSelectThread = (0, import_react9.useCallback)((threadId) => {
5517
+ const handleSelectThread = (0, import_react10.useCallback)((threadId) => {
5423
5518
  callbacks.onSelectThread?.(threadId, createStateCallback());
5424
5519
  }, [callbacks, createStateCallback]);
5425
- const handleRenameThread = (0, import_react9.useCallback)((threadId, newTitle) => {
5426
- callbacks.onRenameThread?.(threadId, newTitle, createStateCallback());
5427
- }, [callbacks, createStateCallback]);
5428
- const handleDeleteThread = (0, import_react9.useCallback)((threadId) => {
5520
+ const handleRenameThread = (0, import_react10.useCallback)(
5521
+ (threadId, newTitle) => {
5522
+ callbacks.onRenameThread?.(threadId, newTitle, createStateCallback());
5523
+ },
5524
+ [callbacks, createStateCallback]
5525
+ );
5526
+ const handleDeleteThread = (0, import_react10.useCallback)((threadId) => {
5429
5527
  callbacks.onDeleteThread?.(threadId, createStateCallback());
5430
5528
  }, [callbacks, createStateCallback]);
5431
- const handleArchiveThread = (0, import_react9.useCallback)((threadId) => {
5529
+ const handleArchiveThread = (0, import_react10.useCallback)((threadId) => {
5432
5530
  callbacks.onArchiveThread?.(threadId, createStateCallback());
5433
5531
  }, [callbacks, createStateCallback]);
5434
- const closeSidebar = (0, import_react9.useCallback)(() => {
5532
+ const closeSidebar = (0, import_react10.useCallback)(() => {
5435
5533
  setState((prev) => ({ ...prev, showSidebar: false }));
5436
5534
  }, []);
5437
- const handleCustomComponentToggle = (0, import_react9.useCallback)(() => {
5535
+ const handleCustomComponentToggle = (0, import_react10.useCallback)(() => {
5438
5536
  setState((prev) => ({ ...prev, showSidebar: !prev.showSidebar }));
5439
5537
  }, []);
5440
- const sidebarUser = (0, import_react9.useMemo)(() => user ? {
5538
+ const sidebarUser = (0, import_react10.useMemo)(() => user ? {
5441
5539
  id: user.id,
5442
5540
  name: user.name,
5443
5541
  email: user.email,
5444
5542
  avatar: user.avatar
5445
5543
  } : null, [user?.id, user?.name, user?.email, user?.avatar]);
5446
- const handleViewProfile = (0, import_react9.useCallback)(() => {
5544
+ const handleViewProfile = (0, import_react10.useCallback)(() => {
5447
5545
  setIsUserProfileOpen(true);
5448
5546
  callbacks.onViewProfile?.();
5449
5547
  }, [callbacks.onViewProfile]);
5450
- const sidebarUserMenuCallbacks = (0, import_react9.useMemo)(() => ({
5548
+ const sidebarUserMenuCallbacks = (0, import_react10.useMemo)(() => ({
5451
5549
  onViewProfile: handleViewProfile,
5452
5550
  onOpenSettings: callbacks.onOpenSettings,
5453
5551
  onThemeChange: callbacks.onThemeChange,
5454
5552
  onLogout: callbacks.onLogout
5455
- }), [handleViewProfile, callbacks.onOpenSettings, callbacks.onThemeChange, callbacks.onLogout]);
5456
- const renderCustomComponent = (0, import_react9.useCallback)(() => {
5553
+ }), [
5554
+ handleViewProfile,
5555
+ callbacks.onOpenSettings,
5556
+ callbacks.onThemeChange,
5557
+ callbacks.onLogout
5558
+ ]);
5559
+ const renderCustomComponent = (0, import_react10.useCallback)(() => {
5457
5560
  const component = config?.customComponent?.component;
5458
5561
  if (!component) return null;
5459
5562
  if (typeof component === "function") {
@@ -5493,19 +5596,25 @@ var ChatUI = ({
5493
5596
  const items = messageSuggestions?.[messageId];
5494
5597
  if (!items || items.length === 0) return null;
5495
5598
  const inlineSuggestionOffsetClass = config.ui.showAvatars ? config.ui.compactMode ? "ml-9" : "ml-11" : "";
5496
- return /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("div", { className: `flex flex-wrap gap-2 mt-2 ${inlineSuggestionOffsetClass}`, children: items.map((suggestion, index) => /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(
5497
- "button",
5599
+ return /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
5600
+ "div",
5498
5601
  {
5499
- type: "button",
5500
- onClick: () => handleSendMessage(suggestion),
5501
- className: "group inline-flex items-center gap-1.5 px-3 py-1.5 text-sm rounded-full border border-border bg-background hover:bg-accent hover:border-accent-foreground/20 transition-all duration-150 text-foreground/80 hover:text-foreground",
5502
- children: [
5503
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_lucide_react14.Sparkles, { className: "h-3 w-3 text-primary opacity-70 group-hover:opacity-100" }),
5504
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { className: "max-w-[200px] truncate", children: suggestion })
5505
- ]
5506
- },
5507
- `${messageId}-suggestion-${index}`
5508
- )) });
5602
+ className: `flex flex-wrap gap-2 mt-2 ${inlineSuggestionOffsetClass}`,
5603
+ children: items.map((suggestion, index) => /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(
5604
+ "button",
5605
+ {
5606
+ type: "button",
5607
+ onClick: () => handleSendMessage(suggestion),
5608
+ className: "group inline-flex items-center gap-1.5 px-3 py-1.5 text-sm rounded-full border border-border bg-background hover:bg-accent hover:border-accent-foreground/20 transition-all duration-150 text-foreground/80 hover:text-foreground",
5609
+ children: [
5610
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_lucide_react14.Sparkles, { className: "h-3 w-3 text-primary opacity-70 group-hover:opacity-100" }),
5611
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { className: "max-w-[200px] truncate", children: suggestion })
5612
+ ]
5613
+ },
5614
+ `${messageId}-suggestion-${index}`
5615
+ ))
5616
+ }
5617
+ );
5509
5618
  };
5510
5619
  const renderMessageLoadingSkeleton = () => /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("div", { className: "space-y-6 py-2", children: [0, 1, 2, 3].map((index) => {
5511
5620
  const isUserRow = index % 2 === 1;
@@ -5527,7 +5636,7 @@ var ChatUI = ({
5527
5636
  );
5528
5637
  }) });
5529
5638
  const isMultiAgentMode = config.agentSelector?.mode === "multi";
5530
- const messageProps = (0, import_react9.useMemo)(() => ({
5639
+ const messageProps = (0, import_react10.useMemo)(() => ({
5531
5640
  userAvatar: user?.avatar,
5532
5641
  userName: user?.name,
5533
5642
  assistantAvatar: assistant?.avatar,
@@ -5580,202 +5689,229 @@ var ChatUI = ({
5580
5689
  const shouldShowAgentSelector = Boolean(
5581
5690
  config.agentSelector?.enabled && agentOptions.length > 0 && (!config.agentSelector?.hideIfSingle || agentOptions.length > 1) && (isMultiAgentMode ? onParticipantsChange : onSelectAgent)
5582
5691
  );
5583
- return /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(TooltipProvider, { children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(SidebarProvider, { defaultOpen: true, children: /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: `flex h-[100svh] md:h-screen bg-background w-full overflow-hidden ${className}`, children: [
5584
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
5585
- Sidebar2,
5586
- {
5587
- threads,
5588
- currentThreadId: state.selectedThreadId,
5589
- config,
5590
- onCreateThread: handleCreateThread,
5591
- onSelectThread: handleSelectThread,
5592
- onRenameThread: handleRenameThread,
5593
- onDeleteThread: handleDeleteThread,
5594
- onArchiveThread: handleArchiveThread,
5595
- user: sidebarUser,
5596
- userMenuCallbacks: sidebarUserMenuCallbacks,
5597
- currentTheme: config.ui.theme === "auto" ? "system" : config.ui.theme,
5598
- showThemeOptions: !!callbacks.onThemeChange,
5599
- userMenuAdditionalItems
5600
- }
5601
- ),
5602
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(SidebarInset, { children: /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "flex flex-col h-full min-h-0", children: [
5603
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
5604
- ChatHeader,
5605
- {
5606
- config,
5607
- currentThreadTitle: threads.find((t) => t.id === state.selectedThreadId)?.title,
5608
- isMobile,
5609
- onCustomComponentToggle: handleCustomComponentToggle,
5610
- onNewThread: handleCreateThread,
5611
- showCustomComponentButton: !!config?.customComponent?.component,
5612
- showAgentSelector: shouldShowAgentSelector,
5613
- isMultiAgentMode,
5614
- agentOptions,
5615
- selectedAgentId,
5616
- onSelectAgent,
5617
- participantIds,
5618
- onParticipantsChange
5619
- }
5620
- ),
5621
- /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "flex flex-1 flex-row min-h-0 overflow-hidden", children: [
5622
- /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "flex-1 flex flex-col min-h-0", children: [
5692
+ return /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(TooltipProvider, { children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(SidebarProvider, { defaultOpen: true, children: /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(
5693
+ "div",
5694
+ {
5695
+ className: `flex h-[100svh] md:h-screen bg-background w-full overflow-hidden ${className}`,
5696
+ children: [
5697
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
5698
+ Sidebar2,
5699
+ {
5700
+ threads,
5701
+ currentThreadId: state.selectedThreadId,
5702
+ config,
5703
+ onCreateThread: handleCreateThread,
5704
+ onSelectThread: handleSelectThread,
5705
+ onRenameThread: handleRenameThread,
5706
+ onDeleteThread: handleDeleteThread,
5707
+ onArchiveThread: handleArchiveThread,
5708
+ user: sidebarUser,
5709
+ userMenuCallbacks: sidebarUserMenuCallbacks,
5710
+ currentTheme: config.ui.theme === "auto" ? "system" : config.ui.theme,
5711
+ showThemeOptions: !!callbacks.onThemeChange,
5712
+ userMenuSections,
5713
+ userMenuAdditionalItems
5714
+ }
5715
+ ),
5716
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(SidebarInset, { children: /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "flex flex-col h-full min-h-0", children: [
5623
5717
  /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
5624
- ScrollArea,
5718
+ ChatHeader,
5625
5719
  {
5626
- ref: scrollAreaRef,
5627
- className: "flex-1 min-h-0",
5628
- viewportClassName: "p-4 overscroll-contain",
5629
- onScrollCapture: handleScroll,
5630
- style: { contain: "strict" },
5631
- children: /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "max-w-4xl mx-auto pb-4", children: [
5632
- groupedMessages.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("div", { className: "flex justify-center py-2", children: isLoadingOlderMessages ? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { className: "text-xs text-muted-foreground", children: config.labels.loadingOlderMessages }) : hasMoreMessagesBefore ? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
5633
- "button",
5720
+ config,
5721
+ currentThreadTitle: threads.find(
5722
+ (t) => t.id === state.selectedThreadId
5723
+ )?.title,
5724
+ isMobile,
5725
+ onCustomComponentToggle: handleCustomComponentToggle,
5726
+ onNewThread: handleCreateThread,
5727
+ showCustomComponentButton: !!config?.customComponent?.component,
5728
+ showAgentSelector: shouldShowAgentSelector,
5729
+ isMultiAgentMode,
5730
+ agentOptions,
5731
+ selectedAgentId,
5732
+ onSelectAgent,
5733
+ participantIds,
5734
+ onParticipantsChange
5735
+ }
5736
+ ),
5737
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "flex flex-1 flex-row min-h-0 overflow-hidden", children: [
5738
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "flex-1 flex flex-col min-h-0", children: [
5739
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
5740
+ ScrollArea,
5741
+ {
5742
+ ref: scrollAreaRef,
5743
+ className: "flex-1 min-h-0",
5744
+ viewportClassName: "p-4 overscroll-contain",
5745
+ onScrollCapture: handleScroll,
5746
+ style: { contain: "content" },
5747
+ children: /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "max-w-4xl mx-auto pb-4", children: [
5748
+ groupedMessages.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("div", { className: "flex justify-center py-2", children: isLoadingOlderMessages ? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { className: "text-xs text-muted-foreground", children: config.labels.loadingOlderMessages }) : hasMoreMessagesBefore ? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
5749
+ "button",
5750
+ {
5751
+ type: "button",
5752
+ onClick: requestOlderMessages,
5753
+ className: "text-xs text-muted-foreground transition-colors hover:text-foreground",
5754
+ children: config.labels.loadOlderMessages
5755
+ }
5756
+ ) : null }),
5757
+ isMessagesLoading ? renderMessageLoadingSkeleton() : groupedMessages.length === 0 ? renderSuggestions() : /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
5758
+ "div",
5759
+ {
5760
+ style: {
5761
+ height: `${virtualizer.getTotalSize()}px`,
5762
+ width: "100%",
5763
+ position: "relative"
5764
+ },
5765
+ children: virtualizer.getVirtualItems().map((virtualRow) => {
5766
+ const group = groupedMessages[virtualRow.index];
5767
+ const message = group.message;
5768
+ return /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
5769
+ "div",
5770
+ {
5771
+ "data-index": virtualRow.index,
5772
+ ref: virtualizer.measureElement,
5773
+ style: {
5774
+ position: "absolute",
5775
+ top: 0,
5776
+ left: 0,
5777
+ width: "100%",
5778
+ transform: `translateY(${virtualRow.start}px)`
5779
+ },
5780
+ children: /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(
5781
+ "div",
5782
+ {
5783
+ className: virtualRow.index === 0 ? "" : "pt-4",
5784
+ children: [
5785
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
5786
+ Message,
5787
+ {
5788
+ message,
5789
+ ...messageProps,
5790
+ isExpanded: Boolean(
5791
+ expandedMessageIds[message.id]
5792
+ )
5793
+ }
5794
+ ),
5795
+ message.role === "assistant" && renderInlineSuggestions(
5796
+ group.suggestionMessageId
5797
+ )
5798
+ ]
5799
+ }
5800
+ )
5801
+ },
5802
+ group.id
5803
+ );
5804
+ })
5805
+ }
5806
+ )
5807
+ ] })
5808
+ }
5809
+ ),
5810
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "bg-background pb-[env(safe-area-inset-bottom)]", children: [
5811
+ isMultiAgentMode && shouldShowAgentSelector && onTargetAgentChange && /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("div", { className: "px-4 pt-1", children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
5812
+ TargetAgentSelector,
5634
5813
  {
5635
- type: "button",
5636
- onClick: requestOlderMessages,
5637
- className: "text-xs text-muted-foreground transition-colors hover:text-foreground",
5638
- children: config.labels.loadOlderMessages
5814
+ agents: participantIds && participantIds.length > 0 ? agentOptions.filter(
5815
+ (a) => participantIds.includes(a.id)
5816
+ ) : agentOptions,
5817
+ targetAgentId,
5818
+ onTargetChange: onTargetAgentChange,
5819
+ placeholder: config.agentSelector?.label || "Select agent",
5820
+ disabled: isGenerating
5639
5821
  }
5640
- ) : null }),
5641
- isMessagesLoading ? renderMessageLoadingSkeleton() : groupedMessages.length === 0 ? renderSuggestions() : /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
5642
- "div",
5822
+ ) }),
5823
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
5824
+ ChatInput,
5643
5825
  {
5644
- style: {
5645
- height: `${virtualizer.getTotalSize()}px`,
5646
- width: "100%",
5647
- position: "relative"
5826
+ value: inputValue,
5827
+ onChange: (value) => {
5828
+ setInputValue(value);
5829
+ if (initialInputApplied.current && !initialInputConsumedRef.current) {
5830
+ initialInputConsumedRef.current = true;
5831
+ onInitialInputConsumed?.();
5832
+ }
5648
5833
  },
5649
- children: virtualizer.getVirtualItems().map((virtualRow) => {
5650
- const group = groupedMessages[virtualRow.index];
5651
- const message = group.message;
5652
- return /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
5653
- "div",
5654
- {
5655
- "data-index": virtualRow.index,
5656
- ref: virtualizer.measureElement,
5657
- style: {
5658
- position: "absolute",
5659
- top: 0,
5660
- left: 0,
5661
- width: "100%",
5662
- transform: `translateY(${virtualRow.start}px)`
5663
- },
5664
- children: /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: virtualRow.index === 0 ? "" : "pt-4", children: [
5665
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
5666
- Message,
5667
- {
5668
- message,
5669
- ...messageProps,
5670
- isExpanded: Boolean(expandedMessageIds[message.id])
5671
- }
5672
- ),
5673
- message.role === "assistant" && renderInlineSuggestions(group.suggestionMessageId)
5674
- ] })
5675
- },
5676
- group.id
5677
- );
5678
- })
5834
+ onSubmit: handleSendMessage,
5835
+ attachments,
5836
+ onAttachmentsChange: setAttachments,
5837
+ placeholder: config.labels.inputPlaceholder,
5838
+ disabled: false,
5839
+ isGenerating,
5840
+ onStopGeneration: callbacks.onStopGeneration,
5841
+ enableFileUpload: config.features.enableFileUpload,
5842
+ enableAudioRecording: config.features.enableAudioRecording,
5843
+ maxAttachments: config.features.maxAttachments,
5844
+ maxFileSize: config.features.maxFileSize,
5845
+ config,
5846
+ mentionAgents: participantIds && participantIds.length > 0 ? agentOptions.filter(
5847
+ (a) => participantIds.includes(a.id)
5848
+ ) : agentOptions,
5849
+ onTargetAgentChange
5679
5850
  }
5680
5851
  )
5681
5852
  ] })
5682
- }
5683
- ),
5684
- /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "bg-background pb-[env(safe-area-inset-bottom)]", children: [
5685
- isMultiAgentMode && shouldShowAgentSelector && onTargetAgentChange && /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("div", { className: "px-4 pt-1", children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
5686
- TargetAgentSelector,
5687
- {
5688
- agents: participantIds && participantIds.length > 0 ? agentOptions.filter((a) => participantIds.includes(a.id)) : agentOptions,
5689
- targetAgentId,
5690
- onTargetChange: onTargetAgentChange,
5691
- placeholder: config.agentSelector?.label || "Select agent",
5692
- disabled: isGenerating
5693
- }
5694
- ) }),
5695
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
5696
- ChatInput,
5853
+ ] }),
5854
+ config?.customComponent?.component && !isMobile && /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
5855
+ "div",
5697
5856
  {
5698
- value: inputValue,
5699
- onChange: (value) => {
5700
- setInputValue(value);
5701
- if (initialInputApplied.current && !initialInputConsumedRef.current) {
5702
- initialInputConsumedRef.current = true;
5703
- onInitialInputConsumed?.();
5704
- }
5857
+ className: "h-full transition-all duration-300 ease-in-out overflow-hidden",
5858
+ style: {
5859
+ width: state.showSidebar ? config.customComponent.panelWidth ?? 320 : 0
5705
5860
  },
5706
- onSubmit: handleSendMessage,
5707
- attachments,
5708
- onAttachmentsChange: setAttachments,
5709
- placeholder: config.labels.inputPlaceholder,
5710
- disabled: false,
5711
- isGenerating,
5712
- onStopGeneration: callbacks.onStopGeneration,
5713
- enableFileUpload: config.features.enableFileUpload,
5714
- enableAudioRecording: config.features.enableAudioRecording,
5715
- maxAttachments: config.features.maxAttachments,
5716
- maxFileSize: config.features.maxFileSize,
5717
- config,
5718
- mentionAgents: participantIds && participantIds.length > 0 ? agentOptions.filter((a) => participantIds.includes(a.id)) : agentOptions,
5719
- onTargetAgentChange
5861
+ children: state.showSidebar && /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
5862
+ "div",
5863
+ {
5864
+ className: "h-full overflow-hidden border-l bg-background animate-in slide-in-from-right-4 duration-300",
5865
+ style: {
5866
+ width: config.customComponent.panelWidth ?? 320
5867
+ },
5868
+ children: renderCustomComponent()
5869
+ }
5870
+ )
5720
5871
  }
5721
5872
  )
5722
5873
  ] })
5874
+ ] }) }),
5875
+ isCustomMounted && config.customComponent?.component && isMobile && /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "fixed inset-0 z-50", children: [
5876
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
5877
+ "div",
5878
+ {
5879
+ className: `absolute inset-0 bg-background/80 backdrop-blur-sm transition-opacity duration-200 ease-out ${isCustomVisible ? "opacity-100" : "opacity-0"}`,
5880
+ style: { willChange: "opacity" },
5881
+ onClick: closeSidebar
5882
+ }
5883
+ ),
5884
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
5885
+ "div",
5886
+ {
5887
+ className: `absolute top-0 right-0 h-full w-full bg-background transform-gpu transition-transform duration-200 ease-out ${isCustomVisible ? "translate-x-0" : "translate-x-full"}`,
5888
+ style: { willChange: "transform" },
5889
+ children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("div", { className: "h-full overflow-hidden", children: renderCustomComponent() })
5890
+ }
5891
+ )
5723
5892
  ] }),
5724
- config?.customComponent?.component && !isMobile && /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
5725
- "div",
5893
+ isUserProfileOpen && /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
5894
+ UserProfile,
5726
5895
  {
5727
- className: "h-full transition-all duration-300 ease-in-out overflow-hidden",
5728
- style: { width: state.showSidebar ? config.customComponent.panelWidth ?? 320 : 0 },
5729
- children: state.showSidebar && /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
5730
- "div",
5731
- {
5732
- className: "h-full overflow-hidden border-l bg-background animate-in slide-in-from-right-4 duration-300",
5733
- style: { width: config.customComponent.panelWidth ?? 320 },
5734
- children: renderCustomComponent()
5735
- }
5736
- )
5896
+ isOpen: isUserProfileOpen,
5897
+ onClose: () => setIsUserProfileOpen(false),
5898
+ user: user ? {
5899
+ id: user.id,
5900
+ name: user.name,
5901
+ email: user.email,
5902
+ avatar: user.avatar
5903
+ } : null,
5904
+ customFields: userContext?.customFields,
5905
+ memories: userContext?.memories?.items,
5906
+ onLogout: callbacks.onLogout,
5907
+ onAddMemory,
5908
+ onUpdateMemory,
5909
+ onDeleteMemory
5737
5910
  }
5738
5911
  )
5739
- ] })
5740
- ] }) }),
5741
- isCustomMounted && config.customComponent?.component && isMobile && /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "fixed inset-0 z-50", children: [
5742
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
5743
- "div",
5744
- {
5745
- className: `absolute inset-0 bg-background/80 backdrop-blur-sm transition-opacity duration-200 ease-out ${isCustomVisible ? "opacity-100" : "opacity-0"}`,
5746
- style: { willChange: "opacity" },
5747
- onClick: closeSidebar
5748
- }
5749
- ),
5750
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
5751
- "div",
5752
- {
5753
- className: `absolute top-0 right-0 h-full w-full bg-background transform-gpu transition-transform duration-200 ease-out ${isCustomVisible ? "translate-x-0" : "translate-x-full"}`,
5754
- style: { willChange: "transform" },
5755
- children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("div", { className: "h-full overflow-hidden", children: renderCustomComponent() })
5756
- }
5757
- )
5758
- ] }),
5759
- isUserProfileOpen && /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
5760
- UserProfile,
5761
- {
5762
- isOpen: isUserProfileOpen,
5763
- onClose: () => setIsUserProfileOpen(false),
5764
- user: user ? {
5765
- id: user.id,
5766
- name: user.name,
5767
- email: user.email,
5768
- avatar: user.avatar
5769
- } : null,
5770
- customFields: userContext?.customFields,
5771
- memories: userContext?.memories?.items,
5772
- onLogout: callbacks.onLogout,
5773
- onAddMemory,
5774
- onUpdateMemory,
5775
- onDeleteMemory
5776
- }
5777
- )
5778
- ] }) }) });
5912
+ ]
5913
+ }
5914
+ ) }) });
5779
5915
  };
5780
5916
  // Annotate the CommonJS export names for ESM import in node:
5781
5917
  0 && (module.exports = {