@copilotz/chat-ui 0.1.0 → 0.1.1

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
@@ -64,6 +64,11 @@ var defaultChatConfig = {
64
64
  title: "Chat Assistant",
65
65
  subtitle: "How can I help you today?"
66
66
  },
67
+ agentSelector: {
68
+ enabled: false,
69
+ label: "Select agent",
70
+ hideIfSingle: true
71
+ },
67
72
  labels: {
68
73
  inputPlaceholder: "Type your message...",
69
74
  sendButton: "Send",
@@ -156,6 +161,10 @@ function mergeConfig(_baseConfig, userConfig) {
156
161
  ...defaultChatConfig.ui,
157
162
  ...userConfig.ui
158
163
  },
164
+ agentSelector: {
165
+ ...defaultChatConfig.agentSelector,
166
+ ...userConfig.agentSelector
167
+ },
159
168
  customComponent: userConfig.customComponent || defaultChatConfig.customComponent,
160
169
  headerActions: userConfig.headerActions || defaultChatConfig.headerActions
161
170
  };
@@ -566,7 +575,7 @@ function TooltipContent({
566
575
  // src/components/chat/Message.tsx
567
576
  var import_lucide_react = require("lucide-react");
568
577
  var import_jsx_runtime7 = require("react/jsx-runtime");
569
- var ThinkingIndicator = ({ label = "Thinking..." }) => {
578
+ var ThinkingIndicator = (0, import_react.memo)(function ThinkingIndicator2({ label = "Thinking..." }) {
570
579
  return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex items-center gap-2 py-2", children: [
571
580
  /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex gap-1", children: [
572
581
  /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
@@ -593,26 +602,30 @@ var ThinkingIndicator = ({ label = "Thinking..." }) => {
593
602
  ] }),
594
603
  /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "text-sm text-muted-foreground animate-pulse", children: label })
595
604
  ] });
605
+ });
606
+ var markdownComponents = {
607
+ code: ({ node, className, children, ...props }) => {
608
+ const inline = props.inline;
609
+ const match = /language-(\w+)/.exec(className || "");
610
+ return !inline && match ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("pre", { className: "relative", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("code", { className, ...props, children }) }) : /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("code", { className: "bg-muted px-1 py-0.5 rounded text-sm", ...props, children });
611
+ }
596
612
  };
597
- var StreamingText = ({
613
+ var remarkPluginsDefault = [import_remark_gfm.default];
614
+ var rehypePluginsDefault = [import_rehype_highlight.default];
615
+ var rehypePluginsEmpty = [];
616
+ var StreamingText = (0, import_react.memo)(function StreamingText2({
598
617
  content,
599
618
  isStreaming = false,
600
619
  thinkingLabel = "Thinking..."
601
- }) => {
620
+ }) {
602
621
  const hasContent = content.trim().length > 0;
603
622
  return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "prose prose-sm max-w-none dark:prose-invert", children: [
604
623
  hasContent ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
605
624
  import_react_markdown.default,
606
625
  {
607
- remarkPlugins: [import_remark_gfm.default],
608
- rehypePlugins: isStreaming ? [] : [import_rehype_highlight.default],
609
- components: {
610
- code: ({ node, className, children, ...props }) => {
611
- const inline = props.inline;
612
- const match = /language-(\w+)/.exec(className || "");
613
- return !inline && match ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("pre", { className: "relative", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("code", { className, ...props, children }) }) : /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("code", { className: "bg-muted px-1 py-0.5 rounded text-sm", ...props, children });
614
- }
615
- },
626
+ remarkPlugins: remarkPluginsDefault,
627
+ rehypePlugins: isStreaming ? rehypePluginsEmpty : rehypePluginsDefault,
628
+ components: markdownComponents,
616
629
  children: content
617
630
  }
618
631
  ) : isStreaming ? (
@@ -621,8 +634,8 @@ var StreamingText = ({
621
634
  ) : null,
622
635
  isStreaming && hasContent && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "inline-block w-2 h-4 bg-primary animate-pulse ml-1" })
623
636
  ] });
624
- };
625
- var MediaRenderer = ({ attachment }) => {
637
+ });
638
+ var MediaRenderer = (0, import_react.memo)(function MediaRenderer2({ attachment }) {
626
639
  const [isPlaying, setIsPlaying] = (0, import_react.useState)(false);
627
640
  const audioRef = (0, import_react.useRef)(null);
628
641
  const videoRef = (0, import_react.useRef)(null);
@@ -696,8 +709,8 @@ var MediaRenderer = ({ attachment }) => {
696
709
  default:
697
710
  return null;
698
711
  }
699
- };
700
- var ToolCallsDisplay = ({ toolCalls, label }) => {
712
+ });
713
+ var ToolCallsDisplay = (0, import_react.memo)(function ToolCallsDisplay2({ toolCalls, label }) {
701
714
  const [expandedCall, setExpandedCall] = (0, import_react.useState)(null);
702
715
  const getStatusIcon = (status) => {
703
716
  switch (status) {
@@ -766,8 +779,48 @@ var ToolCallsDisplay = ({ toolCalls, label }) => {
766
779
  ] }, call.id);
767
780
  })
768
781
  ] });
782
+ });
783
+ var arePropsEqual = (prevProps, nextProps) => {
784
+ if (prevProps.message.id !== nextProps.message.id) return false;
785
+ if (prevProps.message.content !== nextProps.message.content) return false;
786
+ if (prevProps.message.isStreaming !== nextProps.message.isStreaming) return false;
787
+ if (prevProps.message.isComplete !== nextProps.message.isComplete) return false;
788
+ if (prevProps.message.isEdited !== nextProps.message.isEdited) return false;
789
+ if (prevProps.message.timestamp !== nextProps.message.timestamp) return false;
790
+ if (prevProps.message.toolCalls !== nextProps.message.toolCalls) {
791
+ const prevCalls = prevProps.message.toolCalls;
792
+ const nextCalls = nextProps.message.toolCalls;
793
+ if (!prevCalls || !nextCalls || prevCalls.length !== nextCalls.length) return false;
794
+ for (let i = 0; i < prevCalls.length; i++) {
795
+ if (prevCalls[i].id !== nextCalls[i].id || prevCalls[i].status !== nextCalls[i].status || prevCalls[i].result !== nextCalls[i].result) {
796
+ return false;
797
+ }
798
+ }
799
+ }
800
+ if (prevProps.message.attachments !== nextProps.message.attachments) {
801
+ const prevAtt = prevProps.message.attachments;
802
+ const nextAtt = nextProps.message.attachments;
803
+ if (!prevAtt || !nextAtt || prevAtt.length !== nextAtt.length) return false;
804
+ }
805
+ if (prevProps.isUser !== nextProps.isUser) return false;
806
+ if (prevProps.userAvatar !== nextProps.userAvatar) return false;
807
+ if (prevProps.userName !== nextProps.userName) return false;
808
+ if (prevProps.assistantName !== nextProps.assistantName) return false;
809
+ if (prevProps.showTimestamp !== nextProps.showTimestamp) return false;
810
+ if (prevProps.showAvatar !== nextProps.showAvatar) return false;
811
+ if (prevProps.enableCopy !== nextProps.enableCopy) return false;
812
+ if (prevProps.enableEdit !== nextProps.enableEdit) return false;
813
+ if (prevProps.enableRegenerate !== nextProps.enableRegenerate) return false;
814
+ if (prevProps.enableToolCallsDisplay !== nextProps.enableToolCallsDisplay) return false;
815
+ if (prevProps.compactMode !== nextProps.compactMode) return false;
816
+ if (prevProps.className !== nextProps.className) return false;
817
+ if (prevProps.toolUsedLabel !== nextProps.toolUsedLabel) return false;
818
+ if (prevProps.thinkingLabel !== nextProps.thinkingLabel) return false;
819
+ if (prevProps.isGrouped !== nextProps.isGrouped) return false;
820
+ if (prevProps.assistantAvatar !== nextProps.assistantAvatar) return false;
821
+ return true;
769
822
  };
770
- var Message = ({
823
+ var Message = (0, import_react.memo)(({
771
824
  message,
772
825
  isUser,
773
826
  userAvatar,
@@ -784,7 +837,8 @@ var Message = ({
784
837
  onAction,
785
838
  className = "",
786
839
  toolUsedLabel,
787
- thinkingLabel = "Thinking..."
840
+ thinkingLabel = "Thinking...",
841
+ isGrouped = false
788
842
  }) => {
789
843
  const [isEditing, setIsEditing] = (0, import_react.useState)(false);
790
844
  const [editContent, setEditContent] = (0, import_react.useState)(message.content);
@@ -834,7 +888,7 @@ var Message = ({
834
888
  onMouseEnter: () => setShowActions(true),
835
889
  onMouseLeave: () => setShowActions(false),
836
890
  children: [
837
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: `flex gap-3 ${messageIsUser ? "flex-row-reverse" : "flex-row"} w-full mb-1`, children: [
891
+ !isGrouped && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: `flex gap-3 ${messageIsUser ? "flex-row-reverse" : "flex-row"} w-full mb-1`, children: [
838
892
  showAvatar && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: `flex-shrink-0 ${compactMode ? "mt-1" : "mt-0"}`, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Avatar, { className: compactMode ? "h-6 w-6" : "h-8 w-8", children: messageIsUser ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_jsx_runtime7.Fragment, { children: [
839
893
  /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(AvatarImage, { src: userAvatar, alt: userName }),
840
894
  /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(AvatarFallback, { className: "bg-primary text-primary-foreground", children: userName.charAt(0).toUpperCase() })
@@ -845,7 +899,7 @@ var Message = ({
845
899
  message.isEdited && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Badge, { variant: "outline", className: "text-xs", children: "editado" })
846
900
  ] })
847
901
  ] }),
848
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: `flex-1 min-w-0 ${messageIsUser ? "text-right" : "text-left"}`, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: `relative inline-flex flex-col ${messageIsUser ? "rounded-lg p-3 bg-primary text-primary-foreground ml-auto max-w-[85%]" : "max-w-[85%]"}`, children: [
902
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: `flex-1 min-w-0 ${messageIsUser ? "text-right" : "text-left"} ${isGrouped && showAvatar && !messageIsUser ? compactMode ? "ml-9" : "ml-11" : ""} ${isGrouped && showAvatar && messageIsUser ? compactMode ? "mr-9" : "mr-11" : ""}`, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: `relative inline-flex flex-col ${messageIsUser ? "rounded-lg p-3 bg-primary text-primary-foreground ml-auto max-w-[85%]" : "max-w-[85%]"}`, children: [
849
903
  isEditing ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "space-y-2", children: [
850
904
  /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
851
905
  Textarea,
@@ -923,7 +977,7 @@ var Message = ({
923
977
  ]
924
978
  }
925
979
  ) });
926
- };
980
+ }, arePropsEqual);
927
981
 
928
982
  // src/components/chat/Sidebar.tsx
929
983
  var import_react2 = require("react");
@@ -948,7 +1002,7 @@ function Input({ className, type, ...props }) {
948
1002
  }
949
1003
 
950
1004
  // src/components/ui/sidebar.tsx
951
- var React3 = __toESM(require("react"), 1);
1005
+ var React4 = __toESM(require("react"), 1);
952
1006
  var import_react_slot3 = require("@radix-ui/react-slot");
953
1007
  var import_class_variance_authority3 = require("class-variance-authority");
954
1008
  var import_lucide_react3 = require("lucide-react");
@@ -995,11 +1049,30 @@ function Separator({
995
1049
  }
996
1050
 
997
1051
  // src/components/ui/sheet.tsx
1052
+ var React3 = __toESM(require("react"), 1);
998
1053
  var SheetPrimitive = __toESM(require("@radix-ui/react-dialog"), 1);
999
1054
  var import_lucide_react2 = require("lucide-react");
1000
1055
  var import_jsx_runtime10 = require("react/jsx-runtime");
1001
- function Sheet({ ...props }) {
1002
- return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(SheetPrimitive.Root, { "data-slot": "sheet", ...props });
1056
+ function cleanupBodyStyles() {
1057
+ if (typeof document !== "undefined" && document.body.style.pointerEvents === "none") {
1058
+ document.body.style.pointerEvents = "";
1059
+ }
1060
+ }
1061
+ function Sheet({ open, onOpenChange, ...props }) {
1062
+ const prevOpenRef = React3.useRef(open);
1063
+ React3.useEffect(() => {
1064
+ if (prevOpenRef.current === true && open === false) {
1065
+ const timeout = setTimeout(cleanupBodyStyles, 350);
1066
+ return () => clearTimeout(timeout);
1067
+ }
1068
+ prevOpenRef.current = open;
1069
+ }, [open]);
1070
+ React3.useEffect(() => {
1071
+ return () => {
1072
+ cleanupBodyStyles();
1073
+ };
1074
+ }, []);
1075
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(SheetPrimitive.Root, { "data-slot": "sheet", open, onOpenChange, ...props });
1003
1076
  }
1004
1077
  function SheetPortal({
1005
1078
  ...props
@@ -1015,7 +1088,10 @@ function SheetOverlay({
1015
1088
  {
1016
1089
  "data-slot": "sheet-overlay",
1017
1090
  className: cn(
1018
- "data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black/50",
1091
+ "fixed inset-0 z-50 bg-black/50",
1092
+ "data-[state=open]:animate-in data-[state=closed]:animate-out",
1093
+ "data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
1094
+ "data-[state=closed]:pointer-events-none",
1019
1095
  className
1020
1096
  ),
1021
1097
  ...props
@@ -1034,6 +1110,7 @@ function SheetContent({
1034
1110
  SheetPrimitive.Content,
1035
1111
  {
1036
1112
  "data-slot": "sheet-content",
1113
+ "aria-describedby": void 0,
1037
1114
  className: cn(
1038
1115
  "bg-background data-[state=open]:animate-in data-[state=closed]:animate-out fixed z-50 flex flex-col gap-4 shadow-lg transition ease-in-out data-[state=closed]:duration-300 data-[state=open]:duration-500",
1039
1116
  side === "right" && "data-[state=closed]:slide-out-to-right data-[state=open]:slide-in-from-right inset-y-0 right-0 h-full w-3/4 border-l sm:max-w-sm",
@@ -1099,9 +1176,9 @@ var SIDEBAR_WIDTH = "16rem";
1099
1176
  var SIDEBAR_WIDTH_MOBILE = "18rem";
1100
1177
  var SIDEBAR_WIDTH_ICON = "3rem";
1101
1178
  var SIDEBAR_KEYBOARD_SHORTCUT = "b";
1102
- var SidebarContext = React3.createContext(null);
1179
+ var SidebarContext = React4.createContext(null);
1103
1180
  function useSidebar() {
1104
- const context = React3.useContext(SidebarContext);
1181
+ const context = React4.useContext(SidebarContext);
1105
1182
  if (!context) {
1106
1183
  throw new Error("useSidebar must be used within a SidebarProvider.");
1107
1184
  }
@@ -1117,10 +1194,10 @@ function SidebarProvider({
1117
1194
  ...props
1118
1195
  }) {
1119
1196
  const isMobile = useIsMobile();
1120
- const [openMobile, setOpenMobile] = React3.useState(false);
1121
- const [_open, _setOpen] = React3.useState(defaultOpen);
1197
+ const [openMobile, setOpenMobile] = React4.useState(false);
1198
+ const [_open, _setOpen] = React4.useState(defaultOpen);
1122
1199
  const open = openProp ?? _open;
1123
- const setOpen = React3.useCallback(
1200
+ const setOpen = React4.useCallback(
1124
1201
  (value) => {
1125
1202
  const openState = typeof value === "function" ? value(open) : value;
1126
1203
  if (setOpenProp) {
@@ -1132,10 +1209,10 @@ function SidebarProvider({
1132
1209
  },
1133
1210
  [setOpenProp, open]
1134
1211
  );
1135
- const toggleSidebar = React3.useCallback(() => {
1212
+ const toggleSidebar = React4.useCallback(() => {
1136
1213
  return isMobile ? setOpenMobile((open2) => !open2) : setOpen((open2) => !open2);
1137
1214
  }, [isMobile, setOpen, setOpenMobile]);
1138
- React3.useEffect(() => {
1215
+ React4.useEffect(() => {
1139
1216
  const handleKeyDown = (event) => {
1140
1217
  if (event.key === SIDEBAR_KEYBOARD_SHORTCUT && (event.metaKey || event.ctrlKey)) {
1141
1218
  event.preventDefault();
@@ -1146,7 +1223,7 @@ function SidebarProvider({
1146
1223
  return () => window.removeEventListener("keydown", handleKeyDown);
1147
1224
  }, [toggleSidebar]);
1148
1225
  const state = open ? "expanded" : "collapsed";
1149
- const contextValue = React3.useMemo(
1226
+ const contextValue = React4.useMemo(
1150
1227
  () => ({
1151
1228
  state,
1152
1229
  open,
@@ -1529,13 +1606,34 @@ function SidebarMenuAction({
1529
1606
  }
1530
1607
 
1531
1608
  // src/components/ui/dialog.tsx
1609
+ var React5 = __toESM(require("react"), 1);
1532
1610
  var DialogPrimitive = __toESM(require("@radix-ui/react-dialog"), 1);
1533
1611
  var import_lucide_react4 = require("lucide-react");
1534
1612
  var import_jsx_runtime12 = require("react/jsx-runtime");
1613
+ function cleanupBodyStyles2() {
1614
+ if (typeof document !== "undefined" && document.body.style.pointerEvents === "none") {
1615
+ document.body.style.pointerEvents = "";
1616
+ }
1617
+ }
1535
1618
  function Dialog({
1619
+ open,
1620
+ onOpenChange,
1536
1621
  ...props
1537
1622
  }) {
1538
- return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(DialogPrimitive.Root, { "data-slot": "dialog", ...props });
1623
+ const prevOpenRef = React5.useRef(open);
1624
+ React5.useEffect(() => {
1625
+ if (prevOpenRef.current === true && open === false) {
1626
+ const timeout = setTimeout(cleanupBodyStyles2, 250);
1627
+ return () => clearTimeout(timeout);
1628
+ }
1629
+ prevOpenRef.current = open;
1630
+ }, [open]);
1631
+ React5.useEffect(() => {
1632
+ return () => {
1633
+ cleanupBodyStyles2();
1634
+ };
1635
+ }, []);
1636
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(DialogPrimitive.Root, { "data-slot": "dialog", open, onOpenChange, ...props });
1539
1637
  }
1540
1638
  function DialogTrigger({
1541
1639
  ...props
@@ -1556,7 +1654,10 @@ function DialogOverlay({
1556
1654
  {
1557
1655
  "data-slot": "dialog-overlay",
1558
1656
  className: cn(
1559
- "data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black/50",
1657
+ "fixed inset-0 z-50 bg-black/50",
1658
+ "data-[state=open]:animate-in data-[state=closed]:animate-out",
1659
+ "data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
1660
+ "data-[state=closed]:pointer-events-none",
1560
1661
  className
1561
1662
  ),
1562
1663
  ...props
@@ -1575,6 +1676,7 @@ function DialogContent({
1575
1676
  DialogPrimitive.Content,
1576
1677
  {
1577
1678
  "data-slot": "dialog-content",
1679
+ "aria-describedby": void 0,
1578
1680
  className: cn(
1579
1681
  "bg-background data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 fixed top-[50%] left-[50%] z-50 grid w-full max-w-[calc(100%-2rem)] translate-x-[-50%] translate-y-[-50%] gap-4 rounded-lg border p-6 shadow-lg duration-200 sm:max-w-lg",
1580
1682
  className
@@ -1649,12 +1751,33 @@ function DialogDescription({
1649
1751
  }
1650
1752
 
1651
1753
  // src/components/ui/alert-dialog.tsx
1754
+ var React6 = __toESM(require("react"), 1);
1652
1755
  var AlertDialogPrimitive = __toESM(require("@radix-ui/react-alert-dialog"), 1);
1653
1756
  var import_jsx_runtime13 = require("react/jsx-runtime");
1757
+ function cleanupBodyStyles3() {
1758
+ if (typeof document !== "undefined" && document.body.style.pointerEvents === "none") {
1759
+ document.body.style.pointerEvents = "";
1760
+ }
1761
+ }
1654
1762
  function AlertDialog({
1763
+ open,
1764
+ onOpenChange,
1655
1765
  ...props
1656
1766
  }) {
1657
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(AlertDialogPrimitive.Root, { "data-slot": "alert-dialog", ...props });
1767
+ const prevOpenRef = React6.useRef(open);
1768
+ React6.useEffect(() => {
1769
+ if (prevOpenRef.current === true && open === false) {
1770
+ const timeout = setTimeout(cleanupBodyStyles3, 250);
1771
+ return () => clearTimeout(timeout);
1772
+ }
1773
+ prevOpenRef.current = open;
1774
+ }, [open]);
1775
+ React6.useEffect(() => {
1776
+ return () => {
1777
+ cleanupBodyStyles3();
1778
+ };
1779
+ }, []);
1780
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(AlertDialogPrimitive.Root, { "data-slot": "alert-dialog", open, onOpenChange, ...props });
1658
1781
  }
1659
1782
  function AlertDialogPortal({
1660
1783
  ...props
@@ -1670,7 +1793,10 @@ function AlertDialogOverlay({
1670
1793
  {
1671
1794
  "data-slot": "alert-dialog-overlay",
1672
1795
  className: cn(
1673
- "data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black/50",
1796
+ "fixed inset-0 z-50 bg-black/50",
1797
+ "data-[state=open]:animate-in data-[state=closed]:animate-out",
1798
+ "data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
1799
+ "data-[state=closed]:pointer-events-none",
1674
1800
  className
1675
1801
  ),
1676
1802
  ...props
@@ -2128,6 +2254,13 @@ var Sidebar2 = ({
2128
2254
  };
2129
2255
  return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(Sidebar, { collapsible: "icon", ...props, children: [
2130
2256
  /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(SidebarHeader, { children: [
2257
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "flex items-center gap-3 px-2 py-3", children: [
2258
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { className: "flex items-center justify-center shrink-0", children: config.branding?.logo || /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(Avatar, { className: "h-8 w-8", children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(AvatarFallback, { className: "bg-primary text-primary-foreground", children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_lucide_react7.Bot, { className: "h-4 w-4" }) }) }) }),
2259
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "flex flex-col min-w-0 group-data-[collapsible=icon]:hidden", children: [
2260
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { className: "text-sm font-semibold truncate", children: config.branding?.title || "Chat" }),
2261
+ config.branding?.subtitle && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { className: "text-xs text-muted-foreground truncate", children: config.branding.subtitle })
2262
+ ] })
2263
+ ] }),
2131
2264
  onCreateThread && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
2132
2265
  CreateThreadDialog,
2133
2266
  {
@@ -2147,7 +2280,7 @@ var Sidebar2 = ({
2147
2280
  ) }) })
2148
2281
  }
2149
2282
  ),
2150
- /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "px-2 py-1 mt-6", children: [
2283
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "px-2 py-1 mt-4", children: [
2151
2284
  /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "relative group-data-[collapsible=icon]:hidden", children: [
2152
2285
  /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_lucide_react7.Search, { className: "pointer-events-none absolute left-2 top-1/2 size-4 -translate-y-1/2 select-none opacity-50" }),
2153
2286
  /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
@@ -2262,7 +2395,7 @@ var Sidebar2 = ({
2262
2395
  }
2263
2396
  ) }),
2264
2397
  /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(SidebarRail, {}),
2265
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(AlertDialog, { open: !!deleteThreadId, onOpenChange: () => setDeleteThreadId(null), children: /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(AlertDialogContent, { children: [
2398
+ deleteThreadId && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(AlertDialog, { open: !!deleteThreadId, onOpenChange: () => setDeleteThreadId(null), children: /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(AlertDialogContent, { children: [
2266
2399
  /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(AlertDialogHeader, { children: [
2267
2400
  /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(AlertDialogTitle, { children: config.labels?.deleteConfirmTitle || "Delete Conversation" }),
2268
2401
  /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(AlertDialogDescription, { children: config.labels?.deleteConfirmDescription || "Are you sure you want to delete this conversation? This action cannot be undone." })
@@ -2297,6 +2430,10 @@ var ChatHeader = ({
2297
2430
  onClearAll,
2298
2431
  showCustomComponentButton,
2299
2432
  isMobile,
2433
+ showAgentSelector = false,
2434
+ agentOptions = [],
2435
+ selectedAgentId = null,
2436
+ onSelectAgent,
2300
2437
  className = ""
2301
2438
  }) => {
2302
2439
  const [isDarkMode, setIsDarkMode] = import_react3.default.useState(() => {
@@ -2347,22 +2484,64 @@ var ChatHeader = ({
2347
2484
  };
2348
2485
  input.click();
2349
2486
  };
2487
+ const selectedAgent = agentOptions.find((agent) => agent.id === selectedAgentId) || null;
2488
+ const agentPlaceholder = config.agentSelector?.label || "Select agent";
2350
2489
  return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
2351
2490
  Card,
2352
2491
  {
2353
2492
  "data-chat-header": true,
2354
2493
  className: `py-0 border-b rounded-none relative z-10 bg-background/95 backdrop-blur supports-[backdrop-filter]:bg-background/80 ${className}`,
2355
2494
  style: isMobile ? { paddingTop: "env(safe-area-inset-top)" } : void 0,
2356
- children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(CardHeader, { className: "p-2", children: /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "flex items-center justify-between", children: [
2357
- /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { className: "flex items-center gap-3", children: /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(Tooltip, { children: [
2358
- /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(SidebarTrigger, { className: "-ml-1" }) }),
2359
- /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(TooltipContent, { children: config.labels?.sidebarToggle || "Toggle Sidebar" })
2360
- ] }) }),
2361
- /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "flex items-center gap-3 flex-1 justify-center", children: [
2362
- config.branding?.logo || /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(Avatar, { className: "h-8 w-8", children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(AvatarFallback, { children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(import_lucide_react8.Bot, { className: "h-4 w-4" }) }) }),
2363
- /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { className: "text-center hidden md:block", children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(CardTitle, { className: "text-sm font-medium", children: config.branding?.title || "Chat Assistant" }) }),
2364
- /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { className: "md:hidden text-sm font-medium truncate max-w-[150px]", children: currentThreadTitle || config.branding?.title || "Chat" })
2495
+ children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(CardHeader, { className: "p-2", children: /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "flex items-center justify-between gap-2", children: [
2496
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "flex items-center gap-1", children: [
2497
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(Tooltip, { children: [
2498
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(SidebarTrigger, { className: "-ml-1" }) }),
2499
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(TooltipContent, { children: config.labels?.sidebarToggle || "Toggle Sidebar" })
2500
+ ] }),
2501
+ showAgentSelector && /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(DropdownMenu, { children: [
2502
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
2503
+ Button,
2504
+ {
2505
+ variant: "ghost",
2506
+ className: "h-9 px-3 gap-1.5 font-medium text-base hover:bg-accent/50",
2507
+ children: [
2508
+ selectedAgent?.avatarUrl ? /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(Avatar, { className: "h-5 w-5", children: [
2509
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(AvatarImage, { src: selectedAgent.avatarUrl, alt: selectedAgent.name }),
2510
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(AvatarFallback, { className: "text-[10px]", children: selectedAgent.name.charAt(0).toUpperCase() })
2511
+ ] }) : null,
2512
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "max-w-[200px] truncate", children: selectedAgent?.name || agentPlaceholder }),
2513
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(import_lucide_react8.ChevronDown, { className: "h-4 w-4 opacity-50" })
2514
+ ]
2515
+ }
2516
+ ) }),
2517
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(DropdownMenuContent, { align: "start", className: "w-[280px]", children: agentOptions.map((agent) => {
2518
+ const isSelected = agent.id === selectedAgentId;
2519
+ return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
2520
+ DropdownMenuItem,
2521
+ {
2522
+ onClick: () => onSelectAgent?.(agent.id),
2523
+ className: "flex items-start gap-3 p-3 cursor-pointer",
2524
+ children: [
2525
+ agent.avatarUrl ? /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(Avatar, { className: "h-6 w-6 mt-0.5 shrink-0", children: [
2526
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(AvatarImage, { src: agent.avatarUrl, alt: agent.name }),
2527
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(AvatarFallback, { className: "text-[10px]", children: agent.name.charAt(0).toUpperCase() })
2528
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { className: "h-6 w-6 mt-0.5 shrink-0 flex items-center justify-center rounded-full bg-primary/10", children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(import_lucide_react8.Bot, { className: "h-3.5 w-3.5 text-primary" }) }),
2529
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "flex-1 min-w-0", children: [
2530
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "flex items-center gap-2", children: [
2531
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "font-medium text-sm", children: agent.name }),
2532
+ isSelected && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(import_lucide_react8.Check, { className: "h-4 w-4 text-primary shrink-0" })
2533
+ ] }),
2534
+ agent.description && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("p", { className: "text-xs text-muted-foreground mt-0.5 line-clamp-2", children: agent.description })
2535
+ ] })
2536
+ ]
2537
+ },
2538
+ agent.id
2539
+ );
2540
+ }) })
2541
+ ] }),
2542
+ !showAgentSelector && isMobile && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "text-sm font-medium truncate max-w-[150px] ml-2", children: currentThreadTitle || config.branding?.title || "Chat" })
2365
2543
  ] }),
2544
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { className: "flex-1" }),
2366
2545
  /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "flex items-center gap-1", children: [
2367
2546
  showCustomComponentButton && config.customComponent && /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(Tooltip, { children: [
2368
2547
  /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
@@ -2497,7 +2676,7 @@ function Progress({
2497
2676
  // src/components/chat/ChatInput.tsx
2498
2677
  var import_lucide_react9 = require("lucide-react");
2499
2678
  var import_jsx_runtime20 = require("react/jsx-runtime");
2500
- var FileUploadItem = ({ file, progress, onCancel }) => {
2679
+ var FileUploadItem = (0, import_react5.memo)(function FileUploadItem2({ file, progress, onCancel }) {
2501
2680
  const guessTypeFromName = (name) => {
2502
2681
  const ext = (name || "").split(".").pop()?.toLowerCase();
2503
2682
  switch (ext) {
@@ -2555,8 +2734,8 @@ var FileUploadItem = ({ file, progress, onCancel }) => {
2555
2734
  }
2556
2735
  )
2557
2736
  ] }) }) });
2558
- };
2559
- var AttachmentPreview = ({ attachment, onRemove }) => {
2737
+ });
2738
+ var AttachmentPreview = (0, import_react5.memo)(function AttachmentPreview2({ attachment, onRemove }) {
2560
2739
  const [isPlaying, setIsPlaying] = (0, import_react5.useState)(false);
2561
2740
  const audioRef = (0, import_react5.useRef)(null);
2562
2741
  const handlePlayPause = () => {
@@ -2656,8 +2835,8 @@ var AttachmentPreview = ({ attachment, onRemove }) => {
2656
2835
  ] }),
2657
2836
  attachment.fileName && attachment.kind !== "audio" && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { className: "absolute bottom-0 left-0 right-0 bg-black/70 text-white text-xs p-1 rounded-b", children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("p", { className: "truncate", children: attachment.fileName }) })
2658
2837
  ] }) });
2659
- };
2660
- var AudioRecorder = ({ isRecording, onStartRecording, onStopRecording, onCancel, recordingDuration, config }) => {
2838
+ });
2839
+ var AudioRecorder = (0, import_react5.memo)(function AudioRecorder2({ isRecording, onStartRecording, onStopRecording, onCancel, recordingDuration, config }) {
2661
2840
  const formatTime = (seconds) => {
2662
2841
  const mins = Math.floor(seconds / 60);
2663
2842
  const secs = seconds % 60;
@@ -2711,8 +2890,8 @@ var AudioRecorder = ({ isRecording, onStartRecording, onStopRecording, onCancel,
2711
2890
  )
2712
2891
  ] })
2713
2892
  ] }) }) });
2714
- };
2715
- var ChatInput = ({
2893
+ });
2894
+ var ChatInput = (0, import_react5.memo)(function ChatInput2({
2716
2895
  value,
2717
2896
  onChange,
2718
2897
  onSubmit,
@@ -2730,7 +2909,7 @@ var ChatInput = ({
2730
2909
  acceptedFileTypes = ["image/*", "video/*", "audio/*"],
2731
2910
  className = "",
2732
2911
  config
2733
- }) => {
2912
+ }) {
2734
2913
  const [isRecording, setIsRecording] = (0, import_react5.useState)(false);
2735
2914
  const { setContext } = useChatUserContext();
2736
2915
  const [recordingDuration, setRecordingDuration] = (0, import_react5.useState)(0);
@@ -3072,16 +3251,16 @@ var ChatInput = ({
3072
3251
  ] })
3073
3252
  ] })
3074
3253
  ] }) }) });
3075
- };
3254
+ });
3076
3255
 
3077
3256
  // src/components/chat/UserProfile.tsx
3078
3257
  var import_react6 = require("react");
3079
3258
 
3080
3259
  // src/components/ui/scroll-area.tsx
3081
- var React8 = __toESM(require("react"), 1);
3260
+ var React11 = __toESM(require("react"), 1);
3082
3261
  var ScrollAreaPrimitive = __toESM(require("@radix-ui/react-scroll-area"), 1);
3083
3262
  var import_jsx_runtime21 = require("react/jsx-runtime");
3084
- var ScrollArea = React8.forwardRef(({ className, children, viewportClassName, onScroll, onScrollCapture, ...props }, ref) => {
3263
+ var ScrollArea = React11.forwardRef(({ className, children, viewportClassName, onScroll, onScrollCapture, ...props }, ref) => {
3085
3264
  return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
3086
3265
  ScrollAreaPrimitive.Root,
3087
3266
  {
@@ -3527,10 +3706,16 @@ var ChatUI = ({
3527
3706
  user,
3528
3707
  assistant,
3529
3708
  suggestions = [],
3709
+ messageSuggestions = {},
3710
+ agentOptions = [],
3711
+ selectedAgentId = null,
3712
+ onSelectAgent,
3530
3713
  className = "",
3531
3714
  onAddMemory,
3532
3715
  onUpdateMemory,
3533
- onDeleteMemory
3716
+ onDeleteMemory,
3717
+ initialInput,
3718
+ onInitialInputConsumed
3534
3719
  }) => {
3535
3720
  const config = mergeConfig(defaultChatConfig, userConfig);
3536
3721
  const [isMobile, setIsMobile] = (0, import_react7.useState)(false);
@@ -3548,9 +3733,9 @@ var ChatUI = ({
3548
3733
  }
3549
3734
  return false;
3550
3735
  };
3736
+ const [inputValue, setInputValue] = (0, import_react7.useState)("");
3737
+ const [attachments, setAttachments] = (0, import_react7.useState)([]);
3551
3738
  const [state, setState] = (0, import_react7.useState)({
3552
- input: "",
3553
- attachments: [],
3554
3739
  isRecording: false,
3555
3740
  selectedThreadId: currentThreadId,
3556
3741
  isAtBottom: true,
@@ -3567,16 +3752,41 @@ var ChatUI = ({
3567
3752
  setState((prev) => ({ ...prev, selectedThreadId: currentThreadId }));
3568
3753
  }
3569
3754
  }, [currentThreadId]);
3755
+ const initialInputApplied = (0, import_react7.useRef)(false);
3756
+ const initialInputConsumedRef = (0, import_react7.useRef)(false);
3757
+ (0, import_react7.useEffect)(() => {
3758
+ if (initialInput && !initialInputApplied.current) {
3759
+ setInputValue(initialInput);
3760
+ initialInputApplied.current = true;
3761
+ }
3762
+ }, [initialInput]);
3570
3763
  const messagesEndRef = (0, import_react7.useRef)(null);
3571
3764
  const scrollAreaRef = (0, import_react7.useRef)(null);
3765
+ const stateRef = (0, import_react7.useRef)(state);
3766
+ const inputValueRef = (0, import_react7.useRef)(inputValue);
3767
+ const attachmentsRef = (0, import_react7.useRef)(attachments);
3768
+ (0, import_react7.useEffect)(() => {
3769
+ stateRef.current = state;
3770
+ }, [state]);
3771
+ (0, import_react7.useEffect)(() => {
3772
+ inputValueRef.current = inputValue;
3773
+ }, [inputValue]);
3774
+ (0, import_react7.useEffect)(() => {
3775
+ attachmentsRef.current = attachments;
3776
+ }, [attachments]);
3572
3777
  const [isCustomMounted, setIsCustomMounted] = (0, import_react7.useState)(false);
3573
3778
  const [isCustomVisible, setIsCustomVisible] = (0, import_react7.useState)(false);
3574
3779
  const createStateCallback = (0, import_react7.useCallback)(
3575
3780
  (setter) => ({
3576
3781
  setState: (newState) => setter?.(newState),
3577
- getState: () => state
3782
+ getState: () => ({
3783
+ ...stateRef.current,
3784
+ input: inputValueRef.current,
3785
+ attachments: attachmentsRef.current
3786
+ })
3578
3787
  }),
3579
- [state]
3788
+ []
3789
+ // No dependencies - uses refs for latest state
3580
3790
  );
3581
3791
  (0, import_react7.useEffect)(() => {
3582
3792
  const checkMobile = () => {
@@ -3613,15 +3823,16 @@ var ChatUI = ({
3613
3823
  const isAtBottom = scrollHeight - scrollTop - clientHeight < 50;
3614
3824
  setState((prev) => ({ ...prev, isAtBottom }));
3615
3825
  }, []);
3616
- const handleSendMessage = (0, import_react7.useCallback)((content, attachments = []) => {
3617
- if (!content.trim() && attachments.length === 0) return;
3618
- callbacks.onSendMessage?.(content, attachments, createStateCallback());
3619
- setState((prev) => ({
3620
- ...prev,
3621
- input: "",
3622
- attachments: []
3623
- }));
3624
- }, [callbacks, createStateCallback]);
3826
+ const handleSendMessage = (0, import_react7.useCallback)((content, messageAttachments = []) => {
3827
+ if (!content.trim() && messageAttachments.length === 0) return;
3828
+ callbacks.onSendMessage?.(content, messageAttachments, createStateCallback());
3829
+ if (initialInputApplied.current && !initialInputConsumedRef.current) {
3830
+ initialInputConsumedRef.current = true;
3831
+ onInitialInputConsumed?.();
3832
+ }
3833
+ setInputValue("");
3834
+ setAttachments([]);
3835
+ }, [callbacks, createStateCallback, onInitialInputConsumed]);
3625
3836
  const handleMessageAction = (0, import_react7.useCallback)((event) => {
3626
3837
  const { action, messageId, content } = event;
3627
3838
  switch (action) {
@@ -3642,7 +3853,7 @@ var ChatUI = ({
3642
3853
  }
3643
3854
  }, [callbacks, createStateCallback]);
3644
3855
  const handleCreateThread = (0, import_react7.useCallback)((title) => {
3645
- callbacks.onCreateThread?.(title, createStateCallback(setState));
3856
+ callbacks.onCreateThread?.(title, createStateCallback());
3646
3857
  }, [callbacks, createStateCallback]);
3647
3858
  const handleSelectThread = (0, import_react7.useCallback)((threadId) => {
3648
3859
  callbacks.onSelectThread?.(threadId, createStateCallback());
@@ -3667,23 +3878,54 @@ var ChatUI = ({
3667
3878
  }
3668
3879
  return component;
3669
3880
  }, [config?.customComponent?.component, closeSidebar, isMobile]);
3881
+ const SuggestionIconComponents = [import_lucide_react11.MessageSquare, import_lucide_react11.Lightbulb, import_lucide_react11.Zap, import_lucide_react11.HelpCircle];
3670
3882
  const renderSuggestions = () => {
3671
3883
  if (messages.length > 0 || !suggestions.length) return null;
3672
- return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "text-center py-8", children: [
3673
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "inline-flex items-center justify-center w-16 h-16 rounded-full bg-primary/10 mb-4", children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_lucide_react11.Sparkles, { className: "w-8 h-8 text-primary" }) }),
3674
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("h3", { className: "text-lg font-semibold mb-2", children: config.branding.title }),
3675
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("p", { className: "text-muted-foreground mb-6", children: config.branding.subtitle }),
3676
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-3 max-w-2xl mx-auto", children: suggestions.map((suggestion, index) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
3677
- Card,
3884
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "flex flex-col items-center justify-center min-h-[60vh] py-8 px-4", children: [
3885
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "text-center mb-8", children: [
3886
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "inline-flex items-center justify-center w-14 h-14 rounded-2xl bg-gradient-to-br from-primary/20 to-primary/5 mb-4 shadow-sm", children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_lucide_react11.Sparkles, { className: "w-7 h-7 text-primary" }) }),
3887
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("h2", { className: "text-xl font-semibold mb-2", children: config.branding.title }),
3888
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("p", { className: "text-muted-foreground text-sm max-w-md", children: config.branding.subtitle })
3889
+ ] }),
3890
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "grid grid-cols-1 sm:grid-cols-2 gap-3 w-full max-w-2xl", children: suggestions.map((suggestion, index) => /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(
3891
+ "button",
3678
3892
  {
3679
- className: "cursor-pointer hover:bg-muted/50 transition-colors",
3893
+ type: "button",
3680
3894
  onClick: () => handleSendMessage(suggestion),
3681
- children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(CardContent, { className: "p-4 text-left", children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("p", { className: "text-sm", children: suggestion }) })
3895
+ className: "group relative flex items-start gap-3 p-4 text-left rounded-xl border bg-card hover:bg-accent/50 hover:border-accent transition-all duration-200 hover:shadow-sm",
3896
+ children: [
3897
+ (() => {
3898
+ const IconComponent = SuggestionIconComponents[index % SuggestionIconComponents.length];
3899
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "flex items-center justify-center w-8 h-8 rounded-lg bg-primary/10 text-primary shrink-0 group-hover:bg-primary/15 transition-colors", children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(IconComponent, { className: "h-4 w-4" }) });
3900
+ })(),
3901
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "flex-1 min-w-0 pr-6", children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("p", { className: "text-sm font-medium leading-snug line-clamp-2", children: suggestion }) }),
3902
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_lucide_react11.ArrowRight, { className: "absolute right-4 top-1/2 -translate-y-1/2 h-4 w-4 text-muted-foreground opacity-0 group-hover:opacity-100 transition-opacity" })
3903
+ ]
3682
3904
  },
3683
3905
  index
3684
3906
  )) })
3685
3907
  ] });
3686
3908
  };
3909
+ const renderInlineSuggestions = (messageId) => {
3910
+ const items = messageSuggestions?.[messageId];
3911
+ if (!items || items.length === 0) return null;
3912
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "flex flex-wrap gap-2 mt-2 ml-11", children: items.map((suggestion, index) => /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(
3913
+ "button",
3914
+ {
3915
+ type: "button",
3916
+ onClick: () => handleSendMessage(suggestion),
3917
+ 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",
3918
+ children: [
3919
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_lucide_react11.Sparkles, { className: "h-3 w-3 text-primary opacity-70 group-hover:opacity-100" }),
3920
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "max-w-[200px] truncate", children: suggestion })
3921
+ ]
3922
+ },
3923
+ `${messageId}-suggestion-${index}`
3924
+ )) });
3925
+ };
3926
+ const shouldShowAgentSelector = Boolean(
3927
+ config.agentSelector?.enabled && onSelectAgent && agentOptions.length > 0 && (!config.agentSelector?.hideIfSingle || agentOptions.length > 1)
3928
+ );
3687
3929
  return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(TooltipProvider, { children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(SidebarProvider, { defaultOpen: true, children: /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: `flex h-[100svh] md:h-screen bg-background w-full overflow-hidden ${className}`, children: [
3688
3930
  /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
3689
3931
  Sidebar2,
@@ -3724,7 +3966,11 @@ var ChatUI = ({
3724
3966
  isMobile,
3725
3967
  onCustomComponentToggle: () => setState((prev) => ({ ...prev, showSidebar: !prev.showSidebar })),
3726
3968
  onNewThread: handleCreateThread,
3727
- showCustomComponentButton: !!config?.customComponent?.component
3969
+ showCustomComponentButton: !!config?.customComponent?.component,
3970
+ showAgentSelector: shouldShowAgentSelector,
3971
+ agentOptions,
3972
+ selectedAgentId,
3973
+ onSelectAgent
3728
3974
  }
3729
3975
  ),
3730
3976
  /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "flex flex-1 flex-row min-h-0 overflow-hidden", children: [
@@ -3738,27 +3984,34 @@ var ChatUI = ({
3738
3984
  onScrollCapture: handleScroll,
3739
3985
  children: /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "max-w-4xl mx-auto space-y-4 pb-4", children: [
3740
3986
  renderSuggestions(),
3741
- messages.map((message) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
3742
- Message,
3743
- {
3744
- message,
3745
- userAvatar: user?.avatar,
3746
- userName: user?.name,
3747
- assistantAvatar: assistant?.avatar,
3748
- assistantName: assistant?.name,
3749
- showTimestamp: config.ui.showTimestamps,
3750
- showAvatar: config.ui.showAvatars,
3751
- enableCopy: config.features.enableMessageCopy,
3752
- enableEdit: config.features.enableMessageEditing,
3753
- enableRegenerate: config.features.enableRegeneration,
3754
- enableToolCallsDisplay: config.features.enableToolCallsDisplay,
3755
- compactMode: config.ui.compactMode,
3756
- onAction: handleMessageAction,
3757
- toolUsedLabel: config.labels.toolUsed,
3758
- thinkingLabel: config.labels.thinking
3759
- },
3760
- message.id
3761
- )),
3987
+ messages.map((message, index) => {
3988
+ const prevMessage = index > 0 ? messages[index - 1] : null;
3989
+ const isGrouped = prevMessage !== null && prevMessage.role === message.role;
3990
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: isGrouped ? "space-y-1 -mt-2" : "space-y-2", children: [
3991
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
3992
+ Message,
3993
+ {
3994
+ message,
3995
+ userAvatar: user?.avatar,
3996
+ userName: user?.name,
3997
+ assistantAvatar: assistant?.avatar,
3998
+ assistantName: assistant?.name,
3999
+ showTimestamp: config.ui.showTimestamps,
4000
+ showAvatar: config.ui.showAvatars,
4001
+ enableCopy: config.features.enableMessageCopy,
4002
+ enableEdit: config.features.enableMessageEditing,
4003
+ enableRegenerate: config.features.enableRegeneration,
4004
+ enableToolCallsDisplay: config.features.enableToolCallsDisplay,
4005
+ compactMode: config.ui.compactMode,
4006
+ onAction: handleMessageAction,
4007
+ toolUsedLabel: config.labels.toolUsed,
4008
+ thinkingLabel: config.labels.thinking,
4009
+ isGrouped
4010
+ }
4011
+ ),
4012
+ message.role === "assistant" && renderInlineSuggestions(message.id)
4013
+ ] }, message.id);
4014
+ }),
3762
4015
  /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { ref: messagesEndRef })
3763
4016
  ] })
3764
4017
  }
@@ -3766,11 +4019,17 @@ var ChatUI = ({
3766
4019
  /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "bg-background pb-[env(safe-area-inset-bottom)]", children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
3767
4020
  ChatInput,
3768
4021
  {
3769
- value: state.input,
3770
- onChange: (value) => setState((prev) => ({ ...prev, input: value })),
4022
+ value: inputValue,
4023
+ onChange: (value) => {
4024
+ setInputValue(value);
4025
+ if (initialInputApplied.current && !initialInputConsumedRef.current) {
4026
+ initialInputConsumedRef.current = true;
4027
+ onInitialInputConsumed?.();
4028
+ }
4029
+ },
3771
4030
  onSubmit: handleSendMessage,
3772
- attachments: state.attachments,
3773
- onAttachmentsChange: (attachments) => setState((prev) => ({ ...prev, attachments })),
4031
+ attachments,
4032
+ onAttachmentsChange: setAttachments,
3774
4033
  placeholder: config.labels.inputPlaceholder,
3775
4034
  disabled: false,
3776
4035
  isGenerating,
@@ -3810,7 +4069,7 @@ var ChatUI = ({
3810
4069
  }
3811
4070
  )
3812
4071
  ] }),
3813
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
4072
+ isUserProfileOpen && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
3814
4073
  UserProfile,
3815
4074
  {
3816
4075
  isOpen: isUserProfileOpen,
@@ -4074,7 +4333,7 @@ var ThreadManager = ({
4074
4333
  ] }, group)) }) })
4075
4334
  ] })
4076
4335
  ] }) }),
4077
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(AlertDialog, { open: !!deleteThreadId, onOpenChange: () => setDeleteThreadId(null), children: /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(AlertDialogContent, { children: [
4336
+ deleteThreadId && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(AlertDialog, { open: !!deleteThreadId, onOpenChange: () => setDeleteThreadId(null), children: /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(AlertDialogContent, { children: [
4078
4337
  /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(AlertDialogHeader, { children: [
4079
4338
  /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(AlertDialogTitle, { children: config?.labels?.deleteConfirmTitle || "Delete Conversation" }),
4080
4339
  /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(AlertDialogDescription, { children: config?.labels?.deleteConfirmDescription || "Are you sure you want to delete this conversation? This action cannot be undone." })