@yourgpt/copilot-sdk 2.1.4 → 2.1.5-alpha.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.
Files changed (103) hide show
  1. package/dist/MessageTree-CoIt_4nB.d.cts +161 -0
  2. package/dist/MessageTree-CzaN9Eul.d.ts +161 -0
  3. package/dist/{ThreadManager-Dkp_eLty.d.ts → ThreadManager-BEAECB7Y.d.ts} +1 -1
  4. package/dist/{ThreadManager-LfFRhr4e.d.cts → ThreadManager-Cw5fwyCN.d.cts} +1 -1
  5. package/dist/{chunk-POZNNKNJ.cjs → chunk-246B6X5D.cjs} +8 -2
  6. package/dist/chunk-246B6X5D.cjs.map +1 -0
  7. package/dist/{chunk-QLH6TSCC.js → chunk-4QXY2PBG.js} +8 -2
  8. package/dist/chunk-4QXY2PBG.js.map +1 -0
  9. package/dist/{chunk-7PKGRYHY.js → chunk-5Q72LZ5H.js} +3107 -357
  10. package/dist/chunk-5Q72LZ5H.js.map +1 -0
  11. package/dist/chunk-BJYA5NDL.cjs +96 -0
  12. package/dist/chunk-BJYA5NDL.cjs.map +1 -0
  13. package/dist/{chunk-LZMBBGWH.js → chunk-ENFWM3EY.js} +4 -4
  14. package/dist/{chunk-LZMBBGWH.js.map → chunk-ENFWM3EY.js.map} +1 -1
  15. package/dist/{chunk-OQPRIB73.cjs → chunk-I3SQUNTT.cjs} +71 -25
  16. package/dist/chunk-I3SQUNTT.cjs.map +1 -0
  17. package/dist/{chunk-N6VZ7FOW.cjs → chunk-IXWNDR7H.cjs} +3290 -522
  18. package/dist/chunk-IXWNDR7H.cjs.map +1 -0
  19. package/dist/{chunk-WAPGTQDR.cjs → chunk-JKGFQUHJ.cjs} +10 -10
  20. package/dist/{chunk-WAPGTQDR.cjs.map → chunk-JKGFQUHJ.cjs.map} +1 -1
  21. package/dist/{chunk-XGITAEXU.js → chunk-LLM7AHMO.js} +2 -2
  22. package/dist/{chunk-XGITAEXU.js.map → chunk-LLM7AHMO.js.map} +1 -1
  23. package/dist/{chunk-ASV6JLYG.cjs → chunk-NUXLAZOE.cjs} +2 -2
  24. package/dist/{chunk-ASV6JLYG.cjs.map → chunk-NUXLAZOE.cjs.map} +1 -1
  25. package/dist/{chunk-37KEHUCE.js → chunk-UXJ6LIZB.js} +51 -7
  26. package/dist/chunk-UXJ6LIZB.js.map +1 -0
  27. package/dist/chunk-VNLLW3ZI.js +94 -0
  28. package/dist/chunk-VNLLW3ZI.js.map +1 -0
  29. package/dist/core/index.cjs +99 -91
  30. package/dist/core/index.d.cts +7 -7
  31. package/dist/core/index.d.ts +7 -7
  32. package/dist/core/index.js +5 -5
  33. package/dist/{index-BHkRA0mM.d.cts → index-CiExk87c.d.cts} +1 -1
  34. package/dist/{index-tB0qI8my.d.ts → index-Dwrcf-CP.d.ts} +1 -1
  35. package/dist/mcp/index.d.cts +3 -3
  36. package/dist/mcp/index.d.ts +3 -3
  37. package/dist/react/index.cjs +113 -52
  38. package/dist/react/index.d.cts +673 -77
  39. package/dist/react/index.d.ts +673 -77
  40. package/dist/react/index.js +7 -6
  41. package/dist/server/index.cjs +339 -0
  42. package/dist/server/index.cjs.map +1 -0
  43. package/dist/server/index.d.cts +171 -0
  44. package/dist/server/index.d.ts +171 -0
  45. package/dist/server/index.js +332 -0
  46. package/dist/server/index.js.map +1 -0
  47. package/dist/tools/anthropic/index.cjs +3 -3
  48. package/dist/tools/anthropic/index.d.cts +1 -1
  49. package/dist/tools/anthropic/index.d.ts +1 -1
  50. package/dist/tools/anthropic/index.js +3 -3
  51. package/dist/tools/brave/index.cjs +6 -6
  52. package/dist/tools/brave/index.d.cts +1 -1
  53. package/dist/tools/brave/index.d.ts +1 -1
  54. package/dist/tools/brave/index.js +3 -3
  55. package/dist/tools/exa/index.cjs +6 -6
  56. package/dist/tools/exa/index.d.cts +1 -1
  57. package/dist/tools/exa/index.d.ts +1 -1
  58. package/dist/tools/exa/index.js +3 -3
  59. package/dist/tools/google/index.cjs +6 -6
  60. package/dist/tools/google/index.d.cts +1 -1
  61. package/dist/tools/google/index.d.ts +1 -1
  62. package/dist/tools/google/index.js +3 -3
  63. package/dist/tools/openai/index.cjs +6 -6
  64. package/dist/tools/openai/index.d.cts +1 -1
  65. package/dist/tools/openai/index.d.ts +1 -1
  66. package/dist/tools/openai/index.js +3 -3
  67. package/dist/tools/searxng/index.cjs +6 -6
  68. package/dist/tools/searxng/index.d.cts +1 -1
  69. package/dist/tools/searxng/index.d.ts +1 -1
  70. package/dist/tools/searxng/index.js +3 -3
  71. package/dist/tools/serper/index.cjs +6 -6
  72. package/dist/tools/serper/index.d.cts +1 -1
  73. package/dist/tools/serper/index.d.ts +1 -1
  74. package/dist/tools/serper/index.js +3 -3
  75. package/dist/tools/tavily/index.cjs +6 -6
  76. package/dist/tools/tavily/index.d.cts +1 -1
  77. package/dist/tools/tavily/index.d.ts +1 -1
  78. package/dist/tools/tavily/index.js +3 -3
  79. package/dist/tools/web-search/index.cjs +7 -7
  80. package/dist/tools/web-search/index.d.cts +2 -2
  81. package/dist/tools/web-search/index.d.ts +2 -2
  82. package/dist/tools/web-search/index.js +4 -4
  83. package/dist/{tools-coIcskZ4.d.ts → tools-DHZhF5km.d.cts} +161 -1
  84. package/dist/{tools-coIcskZ4.d.cts → tools-DHZhF5km.d.ts} +161 -1
  85. package/dist/{types-rjaSVmEF.d.ts → types-BTyJu0WD.d.ts} +1 -1
  86. package/dist/types-BckL3hiw.d.cts +93 -0
  87. package/dist/types-BckL3hiw.d.ts +93 -0
  88. package/dist/{types-C8t4Ut8f.d.cts → types-BdX7uPj0.d.cts} +1 -1
  89. package/dist/{types-DG2ya08y.d.ts → types-BeFBBZ5i.d.cts} +64 -1
  90. package/dist/{types-DG2ya08y.d.cts → types-BeFBBZ5i.d.ts} +64 -1
  91. package/dist/ui/index.cjs +509 -209
  92. package/dist/ui/index.cjs.map +1 -1
  93. package/dist/ui/index.d.cts +81 -4
  94. package/dist/ui/index.d.ts +81 -4
  95. package/dist/ui/index.js +457 -158
  96. package/dist/ui/index.js.map +1 -1
  97. package/package.json +6 -1
  98. package/dist/chunk-37KEHUCE.js.map +0 -1
  99. package/dist/chunk-7PKGRYHY.js.map +0 -1
  100. package/dist/chunk-N6VZ7FOW.cjs.map +0 -1
  101. package/dist/chunk-OQPRIB73.cjs.map +0 -1
  102. package/dist/chunk-POZNNKNJ.cjs.map +0 -1
  103. package/dist/chunk-QLH6TSCC.js.map +0 -1
package/dist/ui/index.cjs CHANGED
@@ -1,12 +1,14 @@
1
1
  'use strict';
2
2
 
3
- var chunkN6VZ7FOW_cjs = require('../chunk-N6VZ7FOW.cjs');
4
- var chunkOQPRIB73_cjs = require('../chunk-OQPRIB73.cjs');
3
+ var chunkIXWNDR7H_cjs = require('../chunk-IXWNDR7H.cjs');
4
+ var chunkI3SQUNTT_cjs = require('../chunk-I3SQUNTT.cjs');
5
5
  var chunkJO4BHPAD_cjs = require('../chunk-JO4BHPAD.cjs');
6
6
  require('../chunk-JGPDQDY4.cjs');
7
- require('../chunk-WAPGTQDR.cjs');
8
- require('../chunk-POZNNKNJ.cjs');
9
- require('../chunk-ASV6JLYG.cjs');
7
+ require('../chunk-BJYA5NDL.cjs');
8
+ require('../chunk-JKGFQUHJ.cjs');
9
+ require('../chunk-246B6X5D.cjs');
10
+ require('../chunk-NUXLAZOE.cjs');
11
+ require('../chunk-TXLIY7GF.cjs');
10
12
  require('../chunk-CBAHCI4R.cjs');
11
13
  require('../chunk-MEBXW75C.cjs');
12
14
  require('../chunk-W73FBYIH.cjs');
@@ -14,12 +16,11 @@ require('../chunk-2FAWEBZS.cjs');
14
16
  require('../chunk-6T5XXJEP.cjs');
15
17
  require('../chunk-GANCV72Z.cjs');
16
18
  require('../chunk-XWOHNY3F.cjs');
17
- require('../chunk-TXLIY7GF.cjs');
18
19
  require('../chunk-JEQ2X3Z6.cjs');
19
20
  var clsx = require('clsx');
20
21
  var tailwindMerge = require('tailwind-merge');
21
22
  var jsxRuntime = require('react/jsx-runtime');
22
- var React20 = require('react');
23
+ var React18 = require('react');
23
24
  var streamdown = require('streamdown');
24
25
  var code = require('@streamdown/code');
25
26
  var reactSlot = require('@radix-ui/react-slot');
@@ -49,7 +50,7 @@ function _interopNamespace(e) {
49
50
  return Object.freeze(n);
50
51
  }
51
52
 
52
- var React20__namespace = /*#__PURE__*/_interopNamespace(React20);
53
+ var React18__namespace = /*#__PURE__*/_interopNamespace(React18);
53
54
  var AvatarPrimitive__namespace = /*#__PURE__*/_interopNamespace(AvatarPrimitive);
54
55
  var HoverCardPrimitive__namespace = /*#__PURE__*/_interopNamespace(HoverCardPrimitive);
55
56
 
@@ -365,7 +366,7 @@ function MarkdownComponent({
365
366
  }
366
367
  ) });
367
368
  }
368
- var Markdown = React20.memo(MarkdownComponent);
369
+ var Markdown = React18.memo(MarkdownComponent);
369
370
  Markdown.displayName = "Markdown";
370
371
  function CodeBlock({ children, className, ...props }) {
371
372
  return /* @__PURE__ */ jsxRuntime.jsx(
@@ -406,7 +407,7 @@ var buttonVariants = classVarianceAuthority.cva(
406
407
  }
407
408
  }
408
409
  );
409
- var Button = React20__namespace.forwardRef(
410
+ var Button = React18__namespace.forwardRef(
410
411
  ({ className, variant, size, asChild = false, ...props }, ref) => {
411
412
  const Comp = asChild ? reactSlot.Slot : "button";
412
413
  return /* @__PURE__ */ jsxRuntime.jsx(
@@ -647,7 +648,7 @@ function TooltipTrigger({
647
648
  disabled,
648
649
  ...props
649
650
  }) {
650
- if (asChild && React20__namespace.default.isValidElement(children)) {
651
+ if (asChild && React18__namespace.default.isValidElement(children)) {
651
652
  return /* @__PURE__ */ jsxRuntime.jsx(tooltip.Tooltip.Trigger, { disabled, render: children, ...props });
652
653
  }
653
654
  return /* @__PURE__ */ jsxRuntime.jsx(tooltip.Tooltip.Trigger, { disabled, ...props, children });
@@ -676,7 +677,7 @@ function TooltipContent({
676
677
  }
677
678
  ) }) });
678
679
  }
679
- var Avatar = React20__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
680
+ var Avatar = React18__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
680
681
  AvatarPrimitive__namespace.Root,
681
682
  {
682
683
  ref,
@@ -688,7 +689,7 @@ var Avatar = React20__namespace.forwardRef(({ className, ...props }, ref) => /*
688
689
  }
689
690
  ));
690
691
  Avatar.displayName = AvatarPrimitive__namespace.Root.displayName;
691
- var AvatarImage = React20__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
692
+ var AvatarImage = React18__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
692
693
  AvatarPrimitive__namespace.Image,
693
694
  {
694
695
  ref,
@@ -697,7 +698,7 @@ var AvatarImage = React20__namespace.forwardRef(({ className, ...props }, ref) =
697
698
  }
698
699
  ));
699
700
  AvatarImage.displayName = AvatarPrimitive__namespace.Image.displayName;
700
- var AvatarFallback = React20__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
701
+ var AvatarFallback = React18__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
701
702
  AvatarPrimitive__namespace.Fallback,
702
703
  {
703
704
  ref,
@@ -757,7 +758,7 @@ var MessageContent = ({
757
758
  );
758
759
  return markdown ? /* @__PURE__ */ jsxRuntime.jsx(Markdown, { className: classNames, ...props, children }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: classNames, ...props, children });
759
760
  };
760
- var Textarea = React20__namespace.forwardRef(({ className, ...props }, ref) => {
761
+ var Textarea = React18__namespace.forwardRef(({ className, ...props }, ref) => {
761
762
  return /* @__PURE__ */ jsxRuntime.jsx(
762
763
  "textarea",
763
764
  {
@@ -771,7 +772,7 @@ var Textarea = React20__namespace.forwardRef(({ className, ...props }, ref) => {
771
772
  );
772
773
  });
773
774
  Textarea.displayName = "Textarea";
774
- var PromptInputContext = React20.createContext({
775
+ var PromptInputContext = React18.createContext({
775
776
  isLoading: false,
776
777
  value: "",
777
778
  setValue: () => {
@@ -782,7 +783,7 @@ var PromptInputContext = React20.createContext({
782
783
  textareaRef: { current: null }
783
784
  });
784
785
  function usePromptInput() {
785
- return React20.useContext(PromptInputContext);
786
+ return React18.useContext(PromptInputContext);
786
787
  }
787
788
  function PromptInput({
788
789
  className,
@@ -796,8 +797,8 @@ function PromptInput({
796
797
  onClick,
797
798
  ...props
798
799
  }) {
799
- const [internalValue, setInternalValue] = React20.useState(value || "");
800
- const textareaRef = React20.useRef(null);
800
+ const [internalValue, setInternalValue] = React18.useState(value || "");
801
+ const textareaRef = React18.useRef(null);
801
802
  const handleChange = (newValue) => {
802
803
  setInternalValue(newValue);
803
804
  onValueChange?.(newValue);
@@ -854,7 +855,7 @@ function PromptInputTextarea({
854
855
  textareaRef.current = el;
855
856
  adjustHeight(el);
856
857
  };
857
- React20.useLayoutEffect(() => {
858
+ React18.useLayoutEffect(() => {
858
859
  if (!textareaRef.current || disableAutosize) return;
859
860
  const el = textareaRef.current;
860
861
  el.style.height = "auto";
@@ -921,7 +922,7 @@ function PromptInputAction({
921
922
  }
922
923
  var HoverCard = HoverCardPrimitive__namespace.Root;
923
924
  var HoverCardTrigger = HoverCardPrimitive__namespace.Trigger;
924
- var HoverCardContent = React20__namespace.forwardRef(({ className, align = "center", sideOffset = 4, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
925
+ var HoverCardContent = React18__namespace.forwardRef(({ className, align = "center", sideOffset = 4, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
925
926
  HoverCardPrimitive__namespace.Content,
926
927
  {
927
928
  ref,
@@ -935,9 +936,9 @@ var HoverCardContent = React20__namespace.forwardRef(({ className, align = "cent
935
936
  }
936
937
  ));
937
938
  HoverCardContent.displayName = HoverCardPrimitive__namespace.Content.displayName;
938
- var SourceContext = React20.createContext(null);
939
+ var SourceContext = React18.createContext(null);
939
940
  function useSourceContext() {
940
- const ctx = React20.useContext(SourceContext);
941
+ const ctx = React18.useContext(SourceContext);
941
942
  if (!ctx) throw new Error("Source.* must be used inside <Source>");
942
943
  return ctx;
943
944
  }
@@ -1464,7 +1465,7 @@ function SourcesCollapsible({
1464
1465
  defaultExpanded = false,
1465
1466
  className
1466
1467
  }) {
1467
- const [expanded, setExpanded] = React20__namespace.useState(defaultExpanded);
1468
+ const [expanded, setExpanded] = React18__namespace.useState(defaultExpanded);
1468
1469
  if (citations.length === 0) return null;
1469
1470
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("border rounded-lg", className), children: [
1470
1471
  /* @__PURE__ */ jsxRuntime.jsxs(
@@ -1530,7 +1531,7 @@ function SourcesList({
1530
1531
  if (compact) {
1531
1532
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("text-xs text-muted-foreground", className), children: [
1532
1533
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium", children: "Sources: " }),
1533
- citations.map((c, i) => /* @__PURE__ */ jsxRuntime.jsxs(React20__namespace.Fragment, { children: [
1534
+ citations.map((c, i) => /* @__PURE__ */ jsxRuntime.jsxs(React18__namespace.Fragment, { children: [
1534
1535
  /* @__PURE__ */ jsxRuntime.jsxs(
1535
1536
  "a",
1536
1537
  {
@@ -1608,11 +1609,11 @@ function resultsToCitations(results) {
1608
1609
  domain: result.domain || getDomain3(result.url)
1609
1610
  }));
1610
1611
  }
1611
- var ReasoningContext = React20__namespace.createContext(
1612
+ var ReasoningContext = React18__namespace.createContext(
1612
1613
  null
1613
1614
  );
1614
1615
  function useReasoningContext() {
1615
- const context = React20__namespace.useContext(ReasoningContext);
1616
+ const context = React18__namespace.useContext(ReasoningContext);
1616
1617
  if (!context) {
1617
1618
  throw new Error(
1618
1619
  "Reasoning components must be used within a Reasoning provider"
@@ -1628,11 +1629,11 @@ function Reasoning({
1628
1629
  defaultOpen = false,
1629
1630
  className
1630
1631
  }) {
1631
- const [uncontrolledOpen, setUncontrolledOpen] = React20__namespace.useState(defaultOpen);
1632
- const prevStreamingRef = React20__namespace.useRef(isStreaming);
1632
+ const [uncontrolledOpen, setUncontrolledOpen] = React18__namespace.useState(defaultOpen);
1633
+ const prevStreamingRef = React18__namespace.useRef(isStreaming);
1633
1634
  const isControlled = controlledOpen !== void 0;
1634
1635
  const isOpen = isControlled ? controlledOpen : uncontrolledOpen;
1635
- const setIsOpen = React20__namespace.useCallback(
1636
+ const setIsOpen = React18__namespace.useCallback(
1636
1637
  (open) => {
1637
1638
  if (onOpenChange) {
1638
1639
  onOpenChange(open);
@@ -1643,7 +1644,7 @@ function Reasoning({
1643
1644
  },
1644
1645
  [isControlled, onOpenChange]
1645
1646
  );
1646
- React20__namespace.useEffect(() => {
1647
+ React18__namespace.useEffect(() => {
1647
1648
  if (isStreaming && !prevStreamingRef.current) {
1648
1649
  setIsOpen(true);
1649
1650
  } else if (!isStreaming && prevStreamingRef.current) {
@@ -1699,9 +1700,9 @@ function ReasoningContent({
1699
1700
  className
1700
1701
  }) {
1701
1702
  const { isOpen } = useReasoningContext();
1702
- const contentRef = React20__namespace.useRef(null);
1703
- const [height, setHeight] = React20__namespace.useState(0);
1704
- React20__namespace.useEffect(() => {
1703
+ const contentRef = React18__namespace.useRef(null);
1704
+ const [height, setHeight] = React18__namespace.useState(0);
1705
+ React18__namespace.useEffect(() => {
1705
1706
  if (contentRef.current) {
1706
1707
  const resizeObserver = new ResizeObserver((entries) => {
1707
1708
  for (const entry of entries) {
@@ -1750,11 +1751,11 @@ function SimpleReasoning({
1750
1751
  /* @__PURE__ */ jsxRuntime.jsx(ReasoningContent, { markdown, children: content })
1751
1752
  ] });
1752
1753
  }
1753
- var CopilotUIContext = React20__namespace.createContext(
1754
+ var CopilotUIContext = React18__namespace.createContext(
1754
1755
  null
1755
1756
  );
1756
1757
  function useCopilotUI() {
1757
- const context = React20__namespace.useContext(CopilotUIContext);
1758
+ const context = React18__namespace.useContext(CopilotUIContext);
1758
1759
  if (!context) {
1759
1760
  return {
1760
1761
  debug: false,
@@ -1769,7 +1770,7 @@ function CopilotUIProvider({
1769
1770
  debug = false,
1770
1771
  defaultDebugExpanded = false
1771
1772
  }) {
1772
- const value = React20__namespace.useMemo(
1773
+ const value = React18__namespace.useMemo(
1773
1774
  () => ({
1774
1775
  debug,
1775
1776
  defaultDebugExpanded,
@@ -1912,7 +1913,7 @@ function ToolStep({
1912
1913
  }) {
1913
1914
  const { isDebug, defaultDebugExpanded } = useCopilotUI();
1914
1915
  const debug = debugProp ?? isDebug;
1915
- const [expanded, setExpanded] = React20__namespace.useState(
1916
+ const [expanded, setExpanded] = React18__namespace.useState(
1916
1917
  defaultExpanded ?? defaultDebugExpanded ?? false
1917
1918
  );
1918
1919
  const displayTitle = getDisplayTitle(step);
@@ -2393,9 +2394,9 @@ function ArrowUpRightIcon({ className }) {
2393
2394
  }
2394
2395
  );
2395
2396
  }
2396
- var ConfirmationContext = React20__namespace.createContext(null);
2397
+ var ConfirmationContext = React18__namespace.createContext(null);
2397
2398
  function useConfirmationContext() {
2398
- const context = React20__namespace.useContext(ConfirmationContext);
2399
+ const context = React18__namespace.useContext(ConfirmationContext);
2399
2400
  if (!context) {
2400
2401
  throw new Error(
2401
2402
  "Confirmation components must be used within a Confirmation provider"
@@ -2567,8 +2568,8 @@ function PermissionConfirmation({
2567
2568
  permissionOptions = DEFAULT_PERMISSION_OPTIONS,
2568
2569
  className
2569
2570
  }) {
2570
- const [selectedPermission, setSelectedPermission] = React20__namespace.useState("ask");
2571
- const [showOptions, setShowOptions] = React20__namespace.useState(false);
2571
+ const [selectedPermission, setSelectedPermission] = React18__namespace.useState("ask");
2572
+ const [showOptions, setShowOptions] = React18__namespace.useState(false);
2572
2573
  const handleApprove = () => {
2573
2574
  onApprove?.(selectedPermission);
2574
2575
  };
@@ -2698,7 +2699,7 @@ function CompactPermissionConfirmation({
2698
2699
  onReject,
2699
2700
  className
2700
2701
  }) {
2701
- const [rememberChoice, setRememberChoice] = React20__namespace.useState(false);
2702
+ const [rememberChoice, setRememberChoice] = React18__namespace.useState(false);
2702
2703
  const handleApprove = () => {
2703
2704
  onApprove?.(rememberChoice ? "allow_always" : "ask");
2704
2705
  };
@@ -2810,13 +2811,93 @@ function FollowUpQuestions({
2810
2811
  index
2811
2812
  )) });
2812
2813
  }
2814
+ function BranchNavigator({
2815
+ siblingIndex,
2816
+ totalSiblings,
2817
+ hasPrevious,
2818
+ hasNext,
2819
+ onPrevious,
2820
+ onNext,
2821
+ className
2822
+ }) {
2823
+ return /* @__PURE__ */ jsxRuntime.jsxs(
2824
+ "div",
2825
+ {
2826
+ className: cn(
2827
+ "csdk-branch-navigator flex items-center gap-1 text-xs text-muted-foreground select-none",
2828
+ className
2829
+ ),
2830
+ children: [
2831
+ /* @__PURE__ */ jsxRuntime.jsx(
2832
+ "button",
2833
+ {
2834
+ type: "button",
2835
+ onClick: onPrevious,
2836
+ disabled: !hasPrevious,
2837
+ "aria-label": "Previous version",
2838
+ className: cn(
2839
+ "p-0.5 rounded transition-colors",
2840
+ hasPrevious ? "hover:text-foreground hover:bg-muted cursor-pointer" : "opacity-30 cursor-default"
2841
+ ),
2842
+ children: /* @__PURE__ */ jsxRuntime.jsx(
2843
+ "svg",
2844
+ {
2845
+ width: "14",
2846
+ height: "14",
2847
+ viewBox: "0 0 24 24",
2848
+ fill: "none",
2849
+ stroke: "currentColor",
2850
+ strokeWidth: 2.5,
2851
+ strokeLinecap: "round",
2852
+ strokeLinejoin: "round",
2853
+ children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M15 18l-6-6 6-6" })
2854
+ }
2855
+ )
2856
+ }
2857
+ ),
2858
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "tabular-nums leading-none", children: [
2859
+ siblingIndex + 1,
2860
+ "\u2009/\u2009",
2861
+ totalSiblings
2862
+ ] }),
2863
+ /* @__PURE__ */ jsxRuntime.jsx(
2864
+ "button",
2865
+ {
2866
+ type: "button",
2867
+ onClick: onNext,
2868
+ disabled: !hasNext,
2869
+ "aria-label": "Next version",
2870
+ className: cn(
2871
+ "p-0.5 rounded transition-colors",
2872
+ hasNext ? "hover:text-foreground hover:bg-muted cursor-pointer" : "opacity-30 cursor-default"
2873
+ ),
2874
+ children: /* @__PURE__ */ jsxRuntime.jsx(
2875
+ "svg",
2876
+ {
2877
+ width: "14",
2878
+ height: "14",
2879
+ viewBox: "0 0 24 24",
2880
+ fill: "none",
2881
+ stroke: "currentColor",
2882
+ strokeWidth: 2.5,
2883
+ strokeLinecap: "round",
2884
+ strokeLinejoin: "round",
2885
+ children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M9 18l6-6-6-6" })
2886
+ }
2887
+ )
2888
+ }
2889
+ )
2890
+ ]
2891
+ }
2892
+ );
2893
+ }
2813
2894
  function DevLogger({
2814
2895
  state,
2815
2896
  position = "bottom-right",
2816
2897
  className
2817
2898
  }) {
2818
- const [isOpen, setIsOpen] = React20.useState(false);
2819
- const [activeTab, setActiveTab] = React20.useState("chat");
2899
+ const [isOpen, setIsOpen] = React18.useState(false);
2900
+ const [activeTab, setActiveTab] = React18.useState("chat");
2820
2901
  const positionClasses = {
2821
2902
  "bottom-left": "bottom-4 left-4",
2822
2903
  "bottom-right": "bottom-4 right-4",
@@ -3241,9 +3322,9 @@ function ModelSelector({
3241
3322
  showCapabilities = true,
3242
3323
  className
3243
3324
  }) {
3244
- const [isOpen, setIsOpen] = React20__namespace.useState(false);
3245
- const containerRef = React20__namespace.useRef(null);
3246
- React20__namespace.useEffect(() => {
3325
+ const [isOpen, setIsOpen] = React18__namespace.useState(false);
3326
+ const containerRef = React18__namespace.useRef(null);
3327
+ React18__namespace.useEffect(() => {
3247
3328
  function handleClickOutside(event) {
3248
3329
  if (containerRef.current && !containerRef.current.contains(event.target)) {
3249
3330
  setIsOpen(false);
@@ -3252,7 +3333,7 @@ function ModelSelector({
3252
3333
  document.addEventListener("mousedown", handleClickOutside);
3253
3334
  return () => document.removeEventListener("mousedown", handleClickOutside);
3254
3335
  }, []);
3255
- const selectedModel = React20__namespace.useMemo(() => {
3336
+ const selectedModel = React18__namespace.useMemo(() => {
3256
3337
  if (!value) return null;
3257
3338
  if (providers) {
3258
3339
  for (const provider of providers) {
@@ -3478,7 +3559,7 @@ function PopoverTrigger({
3478
3559
  className,
3479
3560
  ...props
3480
3561
  }) {
3481
- if (asChild && React20__namespace.isValidElement(children)) {
3562
+ if (asChild && React18__namespace.isValidElement(children)) {
3482
3563
  return /* @__PURE__ */ jsxRuntime.jsx(popover.Popover.Trigger, { render: children, className, ...props });
3483
3564
  }
3484
3565
  return /* @__PURE__ */ jsxRuntime.jsx(popover.Popover.Trigger, { className, ...props, children });
@@ -3613,8 +3694,8 @@ function ThreadPicker({
3613
3694
  itemClassName,
3614
3695
  newButtonClassName
3615
3696
  }) {
3616
- const [isOpen, setIsOpen] = React20__namespace.useState(false);
3617
- const selectedThread = React20__namespace.useMemo(() => {
3697
+ const [isOpen, setIsOpen] = React18__namespace.useState(false);
3698
+ const selectedThread = React18__namespace.useMemo(() => {
3618
3699
  if (!value) return null;
3619
3700
  return threads.find((t) => t.id === value) ?? null;
3620
3701
  }, [value, threads]);
@@ -3820,7 +3901,7 @@ function ThreadCard({
3820
3901
  showDelete = true,
3821
3902
  className
3822
3903
  }) {
3823
- const [isHovered, setIsHovered] = React20__namespace.useState(false);
3904
+ const [isHovered, setIsHovered] = React18__namespace.useState(false);
3824
3905
  const handleDelete = (e) => {
3825
3906
  e.stopPropagation();
3826
3907
  onDelete?.();
@@ -4061,10 +4142,10 @@ function MCPUIFrame({
4061
4142
  showLoading = true,
4062
4143
  testId
4063
4144
  }) {
4064
- const iframeRef = React20__namespace.useRef(null);
4065
- const [isLoading, setIsLoading] = React20__namespace.useState(true);
4066
- const [error, setError] = React20__namespace.useState(null);
4067
- React20__namespace.useEffect(() => {
4145
+ const iframeRef = React18__namespace.useRef(null);
4146
+ const [isLoading, setIsLoading] = React18__namespace.useState(true);
4147
+ const [error, setError] = React18__namespace.useState(null);
4148
+ React18__namespace.useEffect(() => {
4068
4149
  const handleMessage = (event) => {
4069
4150
  if (event.source !== iframeRef.current?.contentWindow) {
4070
4151
  return;
@@ -4077,17 +4158,17 @@ function MCPUIFrame({
4077
4158
  window.addEventListener("message", handleMessage);
4078
4159
  return () => window.removeEventListener("message", handleMessage);
4079
4160
  }, [onIntent]);
4080
- const handleLoad = React20__namespace.useCallback(() => {
4161
+ const handleLoad = React18__namespace.useCallback(() => {
4081
4162
  setIsLoading(false);
4082
4163
  onLoad?.();
4083
4164
  }, [onLoad]);
4084
- const handleError = React20__namespace.useCallback(() => {
4165
+ const handleError = React18__namespace.useCallback(() => {
4085
4166
  const err = new Error("Failed to load MCP UI content");
4086
4167
  setError(err);
4087
4168
  setIsLoading(false);
4088
4169
  onError?.(err);
4089
4170
  }, [onError]);
4090
- const { srcDoc, src } = React20__namespace.useMemo(() => {
4171
+ const { srcDoc, src } = React18__namespace.useMemo(() => {
4091
4172
  if (resource.mimeType === "text/html") {
4092
4173
  let content = resource.content || "";
4093
4174
  if (resource.blob && !resource.content) {
@@ -4252,28 +4333,92 @@ function DefaultMessage({
4252
4333
  registeredTools,
4253
4334
  toolRenderers,
4254
4335
  mcpToolRenderer,
4336
+ fallbackToolRenderer,
4255
4337
  onApproveToolExecution,
4256
4338
  onRejectToolExecution,
4257
4339
  showFollowUps = true,
4258
4340
  onFollowUpClick,
4259
4341
  followUpClassName,
4260
4342
  followUpButtonClassName,
4261
- citations = { enabled: true }
4343
+ citations = { enabled: true },
4344
+ branchInfo,
4345
+ onSwitchBranch,
4346
+ onEditMessage
4262
4347
  }) {
4263
4348
  const isUser = message.role === "user";
4349
+ const isCompactionMarker = message.role === "system" && message.metadata?.type === "compaction-marker";
4264
4350
  const isStreaming = isLastMessage && isLoading;
4265
- const { cleanContent: contentWithoutFollowUps, followUps } = React20__namespace.useMemo(() => {
4351
+ const [isEditing, setIsEditing] = React18__namespace.useState(false);
4352
+ const [editValue, setEditValue] = React18__namespace.useState(message.content ?? "");
4353
+ const editRef = React18__namespace.useRef(null);
4354
+ const startEdit = React18__namespace.useCallback(() => {
4355
+ setEditValue(message.content ?? "");
4356
+ setIsEditing(true);
4357
+ requestAnimationFrame(() => editRef.current?.focus());
4358
+ }, [message.content]);
4359
+ const cancelEdit = React18__namespace.useCallback(() => {
4360
+ setIsEditing(false);
4361
+ }, []);
4362
+ const submitEdit = React18__namespace.useCallback(() => {
4363
+ const trimmed = editValue.trim();
4364
+ if (!trimmed || !onEditMessage) return;
4365
+ onEditMessage(message.id, trimmed);
4366
+ setIsEditing(false);
4367
+ }, [editValue, message.id, onEditMessage]);
4368
+ const handleEditKeyDown = React18__namespace.useCallback(
4369
+ (e) => {
4370
+ if (e.key === "Enter" && !e.shiftKey) {
4371
+ e.preventDefault();
4372
+ submitEdit();
4373
+ }
4374
+ if (e.key === "Escape") {
4375
+ cancelEdit();
4376
+ }
4377
+ },
4378
+ [submitEdit, cancelEdit]
4379
+ );
4380
+ const showBranchNav = isUser && branchInfo && branchInfo.totalSiblings > 1 && onSwitchBranch;
4381
+ const showEditBtn = isUser && !!onEditMessage && !isLoading;
4382
+ if (isCompactionMarker) {
4383
+ const tokensSaved = message.metadata?.tokensSaved;
4384
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3 py-2 px-1 my-1", children: [
4385
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 h-px bg-border" }),
4386
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-[11px] text-muted-foreground whitespace-nowrap flex items-center gap-1.5", children: [
4387
+ /* @__PURE__ */ jsxRuntime.jsx(
4388
+ "svg",
4389
+ {
4390
+ className: "size-3 opacity-60",
4391
+ viewBox: "0 0 24 24",
4392
+ fill: "none",
4393
+ stroke: "currentColor",
4394
+ strokeWidth: 2,
4395
+ children: /* @__PURE__ */ jsxRuntime.jsx(
4396
+ "path",
4397
+ {
4398
+ strokeLinecap: "round",
4399
+ strokeLinejoin: "round",
4400
+ d: "M19 9l-7 7-7-7"
4401
+ }
4402
+ )
4403
+ }
4404
+ ),
4405
+ tokensSaved ? `Earlier conversation summarized \xB7 ~${tokensSaved.toLocaleString()} tokens saved` : "Earlier conversation summarized"
4406
+ ] }),
4407
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 h-px bg-border" })
4408
+ ] });
4409
+ }
4410
+ const { cleanContent: contentWithoutFollowUps, followUps } = React18__namespace.useMemo(() => {
4266
4411
  if (isUser || !message.content) {
4267
4412
  return { cleanContent: message.content, followUps: [] };
4268
4413
  }
4269
4414
  return parseFollowUps(message.content);
4270
4415
  }, [message.content, isUser]);
4271
- const cleanContent = React20__namespace.useMemo(() => {
4416
+ const cleanContent = React18__namespace.useMemo(() => {
4272
4417
  if (!contentWithoutFollowUps) return contentWithoutFollowUps;
4273
4418
  return contentWithoutFollowUps.replace(/\n*\*{0,2}Sources:?\*{0,2}\s*(\[.+?\]\(.+?\)[,\s]*)+$/gi, "").trim();
4274
4419
  }, [contentWithoutFollowUps]);
4275
4420
  const shouldShowFollowUps = showFollowUps && !isUser && isLastMessage && !isLoading && followUps.length > 0 && onFollowUpClick;
4276
- const sources = React20__namespace.useMemo(() => {
4421
+ const sources = React18__namespace.useMemo(() => {
4277
4422
  if (isUser || !citations.enabled) return [];
4278
4423
  const extractedSources = [];
4279
4424
  const addSource = (url, title, description) => {
@@ -4327,41 +4472,121 @@ function DefaultMessage({
4327
4472
  const shouldShowSources = citations.enabled && sources.length > 0;
4328
4473
  if (isUser) {
4329
4474
  const hasAttachments = message.attachments && message.attachments.length > 0;
4330
- return /* @__PURE__ */ jsxRuntime.jsxs(
4331
- Message,
4332
- {
4333
- className: cn(
4334
- "flex gap-2",
4335
- showUserAvatar ? "justify-end" : "justify-end"
4475
+ return /* @__PURE__ */ jsxRuntime.jsxs(Message, { className: cn("flex gap-2 group/user-msg justify-end"), children: [
4476
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-col items-end max-w-[80%] min-w-0", children: isEditing ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1.5 w-full min-w-[200px]", children: [
4477
+ /* @__PURE__ */ jsxRuntime.jsx(
4478
+ "textarea",
4479
+ {
4480
+ ref: editRef,
4481
+ value: editValue,
4482
+ onChange: (e) => setEditValue(e.target.value),
4483
+ onKeyDown: handleEditKeyDown,
4484
+ rows: Math.max(2, (editValue.match(/\n/g) || []).length + 1),
4485
+ className: cn(
4486
+ "csdk-edit-textarea w-full rounded-lg px-3 py-2 text-sm resize-none",
4487
+ "bg-primary text-primary-foreground placeholder:text-primary-foreground/50",
4488
+ "focus:outline-none focus:ring-2 focus:ring-primary-foreground/30",
4489
+ userMessageClassName
4490
+ )
4491
+ }
4336
4492
  ),
4337
- children: [
4338
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-end max-w-[80%] min-w-0", children: [
4339
- message.content && /* @__PURE__ */ jsxRuntime.jsx(
4340
- MessageContent,
4341
- {
4342
- className: cn(
4343
- "csdk-message-user rounded-lg px-4 py-2 bg-primary text-primary-foreground",
4344
- userMessageClassName
4345
- ),
4346
- markdown: true,
4347
- size,
4348
- children: message.content
4349
- }
4350
- ),
4351
- hasAttachments && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-2 flex flex-wrap gap-2 justify-end", children: message.attachments.map((attachment, index) => /* @__PURE__ */ jsxRuntime.jsx(AttachmentPreview, { attachment }, index)) })
4352
- ] }),
4353
- showUserAvatar && /* @__PURE__ */ jsxRuntime.jsx(
4354
- MessageAvatar,
4493
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-1.5 justify-end", children: [
4494
+ /* @__PURE__ */ jsxRuntime.jsx(
4495
+ "button",
4496
+ {
4497
+ type: "button",
4498
+ onClick: cancelEdit,
4499
+ className: "csdk-edit-cancel px-3 py-1 text-xs rounded-md bg-muted text-muted-foreground hover:bg-muted/80 transition-colors",
4500
+ children: "Cancel"
4501
+ }
4502
+ ),
4503
+ /* @__PURE__ */ jsxRuntime.jsx(
4504
+ "button",
4355
4505
  {
4356
- src: userAvatar.src,
4357
- alt: "User",
4358
- fallback: userAvatar.fallback,
4359
- children: userAvatar.component
4506
+ type: "button",
4507
+ onClick: submitEdit,
4508
+ disabled: !editValue.trim(),
4509
+ className: "csdk-edit-submit px-3 py-1 text-xs rounded-md bg-primary text-primary-foreground hover:bg-primary/90 disabled:opacity-50 transition-colors",
4510
+ children: "Send"
4360
4511
  }
4361
4512
  )
4362
- ]
4363
- }
4364
- );
4513
+ ] })
4514
+ ] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
4515
+ message.content && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative", children: [
4516
+ /* @__PURE__ */ jsxRuntime.jsx(
4517
+ MessageContent,
4518
+ {
4519
+ className: cn(
4520
+ "csdk-message-user rounded-lg px-4 py-2 bg-primary text-primary-foreground",
4521
+ userMessageClassName
4522
+ ),
4523
+ markdown: true,
4524
+ size,
4525
+ children: message.content
4526
+ }
4527
+ ),
4528
+ showEditBtn && /* @__PURE__ */ jsxRuntime.jsx(
4529
+ "button",
4530
+ {
4531
+ type: "button",
4532
+ onClick: startEdit,
4533
+ "aria-label": "Edit message",
4534
+ className: cn(
4535
+ "csdk-edit-btn absolute -left-7 top-1/2 -translate-y-1/2",
4536
+ "size-6 flex items-center justify-center rounded-full",
4537
+ "text-muted-foreground bg-background border border-border shadow-sm",
4538
+ "opacity-0 group-hover/user-msg:opacity-100 transition-opacity",
4539
+ "hover:text-foreground hover:bg-muted"
4540
+ ),
4541
+ children: /* @__PURE__ */ jsxRuntime.jsxs(
4542
+ "svg",
4543
+ {
4544
+ width: "12",
4545
+ height: "12",
4546
+ viewBox: "0 0 24 24",
4547
+ fill: "none",
4548
+ stroke: "currentColor",
4549
+ strokeWidth: 2,
4550
+ strokeLinecap: "round",
4551
+ strokeLinejoin: "round",
4552
+ children: [
4553
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7" }),
4554
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z" })
4555
+ ]
4556
+ }
4557
+ )
4558
+ }
4559
+ )
4560
+ ] }),
4561
+ hasAttachments && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-2 flex flex-wrap gap-2 justify-end", children: message.attachments.map((attachment, index) => /* @__PURE__ */ jsxRuntime.jsx(AttachmentPreview, { attachment }, index)) }),
4562
+ showBranchNav && /* @__PURE__ */ jsxRuntime.jsx(
4563
+ BranchNavigator,
4564
+ {
4565
+ siblingIndex: branchInfo.siblingIndex,
4566
+ totalSiblings: branchInfo.totalSiblings,
4567
+ hasPrevious: branchInfo.hasPrevious,
4568
+ hasNext: branchInfo.hasNext,
4569
+ onPrevious: () => onSwitchBranch(
4570
+ branchInfo.siblingIds[branchInfo.siblingIndex - 1]
4571
+ ),
4572
+ onNext: () => onSwitchBranch(
4573
+ branchInfo.siblingIds[branchInfo.siblingIndex + 1]
4574
+ ),
4575
+ className: "mt-1"
4576
+ }
4577
+ )
4578
+ ] }) }),
4579
+ showUserAvatar && /* @__PURE__ */ jsxRuntime.jsx(
4580
+ MessageAvatar,
4581
+ {
4582
+ src: userAvatar.src,
4583
+ alt: "User",
4584
+ fallback: userAvatar.fallback,
4585
+ className: userAvatar.className,
4586
+ children: userAvatar.component
4587
+ }
4588
+ )
4589
+ ] });
4365
4590
  }
4366
4591
  const isToolHidden = (exec) => {
4367
4592
  if (exec.hidden === true) return true;
@@ -4379,6 +4604,7 @@ function DefaultMessage({
4379
4604
  const toolDef = registeredTools?.find((t) => t.name === toolName);
4380
4605
  if (mcpToolRenderer && (execSource === "mcp" || toolDef?.source === "mcp"))
4381
4606
  return true;
4607
+ if (fallbackToolRenderer) return true;
4382
4608
  if (toolDef?.render) return true;
4383
4609
  return false;
4384
4610
  };
@@ -4405,7 +4631,7 @@ function DefaultMessage({
4405
4631
  alt: "Assistant",
4406
4632
  fallback: assistantAvatar.fallback,
4407
4633
  fallbackIcon: !assistantAvatar.src && !assistantAvatar.fallback && !assistantAvatar.component ? /* @__PURE__ */ jsxRuntime.jsx(copilot_sdk_logo_default, { className: "size-5" }) : void 0,
4408
- className: "bg-muted",
4634
+ className: cn("bg-muted", assistantAvatar.className),
4409
4635
  children: assistantAvatar.component
4410
4636
  }
4411
4637
  ),
@@ -4418,10 +4644,7 @@ function DefaultMessage({
4418
4644
  className: "mb-2"
4419
4645
  }
4420
4646
  ),
4421
- isLastMessage && isProcessing ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg bg-muted px-4 py-2 flex items-center gap-2", children: [
4422
- /* @__PURE__ */ jsxRuntime.jsx(Loader, { variant: "dots", size: "sm" }),
4423
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-muted-foreground", children: "Continuing..." })
4424
- ] }) : (
4647
+ isLastMessage && isProcessing && !completedTools?.length && !pendingApprovalTools?.length ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-lg bg-muted px-4 py-2", children: /* @__PURE__ */ jsxRuntime.jsx(Loader, { variant: "dots", size: "sm" }) }) : (
4425
4648
  /* Show streaming loader when loading with no content and no tools */
4426
4649
  isLastMessage && isLoading && !cleanContent?.trim() && !toolsWithCustomRender?.length && !toolsWithoutCustomRender?.length && !pendingApprovalTools?.length ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-lg bg-muted px-4 py-2", children: /* @__PURE__ */ jsxRuntime.jsx(Loader, { variant: loaderVariant, size: "sm" }) }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
4427
4650
  cleanContent?.trim() && /* @__PURE__ */ jsxRuntime.jsx(
@@ -4437,10 +4660,34 @@ function DefaultMessage({
4437
4660
  }
4438
4661
  ),
4439
4662
  toolsWithCustomRender && toolsWithCustomRender.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("space-y-2", cleanContent?.trim() && "mt-2"), children: toolsWithCustomRender.map((exec) => {
4440
- const Renderer = toolRenderers?.[exec.name];
4441
- if (Renderer) {
4663
+ const toolDef = registeredTools?.find(
4664
+ (t) => t.name === exec.name
4665
+ );
4666
+ if (toolDef?.render) {
4667
+ let status = "pending";
4668
+ if (exec.status === "executing") status = "executing";
4669
+ else if (exec.status === "completed") status = "completed";
4670
+ else if (exec.status === "error" || exec.status === "failed" || exec.status === "rejected")
4671
+ status = "error";
4672
+ const renderProps = {
4673
+ status,
4674
+ args: exec.args,
4675
+ result: exec.result,
4676
+ error: exec.error,
4677
+ toolCallId: exec.id,
4678
+ toolName: exec.name
4679
+ };
4680
+ const output = toolDef.render(
4681
+ renderProps
4682
+ );
4683
+ if (output != null) {
4684
+ return /* @__PURE__ */ jsxRuntime.jsx(React18__namespace.Fragment, { children: output }, exec.id);
4685
+ }
4686
+ }
4687
+ if (mcpToolRenderer && (exec.source === "mcp" || toolDef?.source === "mcp")) {
4688
+ const MCPRenderer = mcpToolRenderer;
4442
4689
  return /* @__PURE__ */ jsxRuntime.jsx(
4443
- Renderer,
4690
+ MCPRenderer,
4444
4691
  {
4445
4692
  execution: {
4446
4693
  id: exec.id,
@@ -4449,20 +4696,16 @@ function DefaultMessage({
4449
4696
  status: exec.status,
4450
4697
  result: exec.result,
4451
4698
  error: exec.error,
4452
- approvalStatus: exec.approvalStatus,
4453
- source: exec.source
4699
+ source: exec.source || toolDef?.source
4454
4700
  }
4455
4701
  },
4456
4702
  exec.id
4457
4703
  );
4458
4704
  }
4459
- const toolDef = registeredTools?.find(
4460
- (t) => t.name === exec.name
4461
- );
4462
- if (mcpToolRenderer && (exec.source === "mcp" || toolDef?.source === "mcp")) {
4463
- const MCPRenderer = mcpToolRenderer;
4705
+ if (fallbackToolRenderer) {
4706
+ const FallbackRenderer = fallbackToolRenderer;
4464
4707
  return /* @__PURE__ */ jsxRuntime.jsx(
4465
- MCPRenderer,
4708
+ FallbackRenderer,
4466
4709
  {
4467
4710
  execution: {
4468
4711
  id: exec.id,
@@ -4471,31 +4714,30 @@ function DefaultMessage({
4471
4714
  status: exec.status,
4472
4715
  result: exec.result,
4473
4716
  error: exec.error,
4474
- source: exec.source || toolDef?.source
4717
+ source: exec.source
4475
4718
  }
4476
4719
  },
4477
4720
  exec.id
4478
4721
  );
4479
4722
  }
4480
- const toolDefForRender = toolDef ?? registeredTools?.find((t) => t.name === exec.name);
4481
- if (toolDefForRender?.render) {
4482
- let status = "pending";
4483
- if (exec.status === "executing") status = "executing";
4484
- else if (exec.status === "completed") status = "completed";
4485
- else if (exec.status === "error" || exec.status === "failed" || exec.status === "rejected")
4486
- status = "error";
4487
- const renderProps = {
4488
- status,
4489
- args: exec.args,
4490
- result: exec.result,
4491
- error: exec.error,
4492
- toolCallId: exec.id,
4493
- toolName: exec.name
4494
- };
4495
- const output = toolDefForRender.render(
4496
- renderProps
4723
+ const Renderer = toolRenderers?.[exec.name];
4724
+ if (Renderer) {
4725
+ return /* @__PURE__ */ jsxRuntime.jsx(
4726
+ Renderer,
4727
+ {
4728
+ execution: {
4729
+ id: exec.id,
4730
+ name: exec.name,
4731
+ args: exec.args,
4732
+ status: exec.status,
4733
+ result: exec.result,
4734
+ error: exec.error,
4735
+ approvalStatus: exec.approvalStatus,
4736
+ source: exec.source
4737
+ }
4738
+ },
4739
+ exec.id
4497
4740
  );
4498
- return /* @__PURE__ */ jsxRuntime.jsx(React20__namespace.Fragment, { children: output }, exec.id);
4499
4741
  }
4500
4742
  return null;
4501
4743
  }) }),
@@ -4521,6 +4763,7 @@ function DefaultMessage({
4521
4763
  `${exec.id}-ui`
4522
4764
  );
4523
4765
  }),
4766
+ isLastMessage && isProcessing && completedTools && completedTools.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-2 rounded-lg bg-muted px-4 py-2", children: /* @__PURE__ */ jsxRuntime.jsx(Loader, { variant: "dots", size: "sm" }) }),
4524
4767
  pendingApprovalTools && pendingApprovalTools.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-2 space-y-2", children: pendingApprovalTools.map((tool) => {
4525
4768
  const approvalCallbacks = {
4526
4769
  onApprove: (extraData) => onApproveToolExecution?.(tool.id, extraData),
@@ -4554,7 +4797,7 @@ function DefaultMessage({
4554
4797
  const output = toolDef.render(
4555
4798
  renderProps
4556
4799
  );
4557
- return /* @__PURE__ */ jsxRuntime.jsx(React20__namespace.Fragment, { children: output }, tool.id);
4800
+ return /* @__PURE__ */ jsxRuntime.jsx(React18__namespace.Fragment, { children: output }, tool.id);
4558
4801
  }
4559
4802
  return /* @__PURE__ */ jsxRuntime.jsx(
4560
4803
  PermissionConfirmation,
@@ -4603,7 +4846,7 @@ function DefaultMessage({
4603
4846
  ] });
4604
4847
  }
4605
4848
  function AttachmentPreview({ attachment }) {
4606
- const [expanded, setExpanded] = React20__namespace.useState(false);
4849
+ const [expanded, setExpanded] = React18__namespace.useState(false);
4607
4850
  if (attachment.type !== "image") {
4608
4851
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 rounded-lg border bg-muted/50 px-3 py-2 text-sm", children: [
4609
4852
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground", children: attachment.type }),
@@ -4732,10 +4975,10 @@ function ChatWelcome({
4732
4975
  processAttachment: processAttachmentProp,
4733
4976
  classNames = {}
4734
4977
  }) {
4735
- const [input, setInput] = React20.useState("");
4736
- const [pendingAttachments, setPendingAttachments] = React20.useState([]);
4737
- const fileInputRef = React20.useRef(null);
4738
- const fileInputId = React20.useId();
4978
+ const [input, setInput] = React18.useState("");
4979
+ const [pendingAttachments, setPendingAttachments] = React18.useState([]);
4980
+ const fileInputRef = React18.useRef(null);
4981
+ const fileInputId = React18.useId();
4739
4982
  const title = config?.title ?? DEFAULT_TITLE;
4740
4983
  const subtitle = config?.subtitle ?? DEFAULT_SUBTITLE;
4741
4984
  const logo = config?.logo;
@@ -4744,7 +4987,7 @@ function ChatWelcome({
4744
4987
  config?.recentChatsLabel ?? DEFAULT_RECENT_CHATS_LABEL;
4745
4988
  const maxRecentChats = config?.maxRecentChats ?? DEFAULT_MAX_RECENT_CHATS;
4746
4989
  config?.viewMoreLabel ?? DEFAULT_VIEW_MORE_LABEL;
4747
- const isFileTypeAllowed = React20.useCallback(
4990
+ const isFileTypeAllowed = React18.useCallback(
4748
4991
  (file) => {
4749
4992
  for (const type of allowedFileTypes) {
4750
4993
  if (type.endsWith("/*")) {
@@ -4758,7 +5001,7 @@ function ChatWelcome({
4758
5001
  },
4759
5002
  [allowedFileTypes]
4760
5003
  );
4761
- const handleFileSelect = React20.useCallback(
5004
+ const handleFileSelect = React18.useCallback(
4762
5005
  async (files) => {
4763
5006
  if (!files || !attachmentsEnabled) return;
4764
5007
  for (const file of Array.from(files)) {
@@ -4821,7 +5064,7 @@ function ChatWelcome({
4821
5064
  },
4822
5065
  [attachmentsEnabled, maxFileSize, isFileTypeAllowed, processAttachmentProp]
4823
5066
  );
4824
- const handleInputChange = React20.useCallback(
5067
+ const handleInputChange = React18.useCallback(
4825
5068
  (e) => {
4826
5069
  handleFileSelect(e.target.files);
4827
5070
  if (fileInputRef.current) {
@@ -4830,7 +5073,7 @@ function ChatWelcome({
4830
5073
  },
4831
5074
  [handleFileSelect]
4832
5075
  );
4833
- const removePendingAttachment = React20.useCallback((id) => {
5076
+ const removePendingAttachment = React18.useCallback((id) => {
4834
5077
  setPendingAttachments((prev) => {
4835
5078
  const att = prev.find((a) => a.id === id);
4836
5079
  if (att) {
@@ -4839,7 +5082,7 @@ function ChatWelcome({
4839
5082
  return prev.filter((a) => a.id !== id);
4840
5083
  });
4841
5084
  }, []);
4842
- const handleSubmit = React20.useCallback(() => {
5085
+ const handleSubmit = React18.useCallback(() => {
4843
5086
  const hasContent = input.trim();
4844
5087
  const hasAttachments = pendingAttachments.some(
4845
5088
  (att) => att.status === "ready"
@@ -4851,7 +5094,7 @@ function ChatWelcome({
4851
5094
  setPendingAttachments([]);
4852
5095
  setInput("");
4853
5096
  }, [input, isLoading, onSendMessage, pendingAttachments]);
4854
- const handleSuggestionClick = React20.useCallback(
5097
+ const handleSuggestionClick = React18.useCallback(
4855
5098
  (suggestion) => {
4856
5099
  onSendMessage(suggestion);
4857
5100
  },
@@ -5023,11 +5266,11 @@ function ChatWelcome({
5023
5266
  }
5024
5267
  );
5025
5268
  }
5026
- var CopilotChatContext = React20.createContext(
5269
+ var CopilotChatContext = React18.createContext(
5027
5270
  null
5028
5271
  );
5029
5272
  var useCopilotChatContext = () => {
5030
- const ctx = React20.useContext(CopilotChatContext);
5273
+ const ctx = React18.useContext(CopilotChatContext);
5031
5274
  if (!ctx) {
5032
5275
  throw new Error(
5033
5276
  "useCopilotChatContext must be used within CopilotChat. Make sure you're using CopilotChat.Home, CopilotChat.Input, etc. inside <CopilotChat>"
@@ -5061,10 +5304,10 @@ function ChatView({ children, className }) {
5061
5304
  ChatView.displayName = "ChatView";
5062
5305
  function chatViewHasOnlyLayoutChildren(chatViewElement) {
5063
5306
  if (!chatViewElement?.props?.children) return false;
5064
- const childArray = React20__namespace.default.Children.toArray(chatViewElement.props.children);
5307
+ const childArray = React18__namespace.default.Children.toArray(chatViewElement.props.children);
5065
5308
  if (childArray.length === 0) return false;
5066
5309
  return childArray.every(
5067
- (child) => React20__namespace.default.isValidElement(child) && (child.type === Header || child.type === Footer)
5310
+ (child) => React18__namespace.default.isValidElement(child) && (child.type === Header || child.type === Footer)
5068
5311
  );
5069
5312
  }
5070
5313
  function Header({ children, className }) {
@@ -5080,8 +5323,8 @@ function Input({ placeholder: placeholderProp, className }) {
5080
5323
  onStop,
5081
5324
  placeholder: defaultPlaceholder
5082
5325
  } = useCopilotChatContext();
5083
- const [value, setValue] = React20.useState("");
5084
- const handleSubmit = React20.useCallback(() => {
5326
+ const [value, setValue] = React18.useState("");
5327
+ const handleSubmit = React18.useCallback(() => {
5085
5328
  if (value.trim() && !isLoading) {
5086
5329
  send(value.trim());
5087
5330
  setValue("");
@@ -5202,18 +5445,18 @@ function ThreadPickerCompound(props) {
5202
5445
  );
5203
5446
  }
5204
5447
  function hasCompoundChild(children, ...components) {
5205
- return React20__namespace.default.Children.toArray(children).some(
5206
- (child) => React20__namespace.default.isValidElement(child) && components.includes(child.type)
5448
+ return React18__namespace.default.Children.toArray(children).some(
5449
+ (child) => React18__namespace.default.isValidElement(child) && components.includes(child.type)
5207
5450
  );
5208
5451
  }
5209
5452
  function findCompoundChild(children, component) {
5210
- return React20__namespace.default.Children.toArray(children).find(
5211
- (child) => React20__namespace.default.isValidElement(child) && child.type === component
5453
+ return React18__namespace.default.Children.toArray(children).find(
5454
+ (child) => React18__namespace.default.isValidElement(child) && child.type === component
5212
5455
  );
5213
5456
  }
5214
5457
  function filterCompoundChildren(children, ...components) {
5215
- return React20__namespace.default.Children.toArray(children).filter(
5216
- (child) => React20__namespace.default.isValidElement(child) && components.includes(child.type)
5458
+ return React18__namespace.default.Children.toArray(children).filter(
5459
+ (child) => React18__namespace.default.isValidElement(child) && components.includes(child.type)
5217
5460
  );
5218
5461
  }
5219
5462
  var DEFAULT_MAX_FILE_SIZE2 = 5 * 1024 * 1024;
@@ -5288,6 +5531,7 @@ function ChatComponent({
5288
5531
  registeredTools,
5289
5532
  toolRenderers,
5290
5533
  mcpToolRenderer,
5534
+ fallbackToolRenderer,
5291
5535
  onApproveToolExecution,
5292
5536
  onRejectToolExecution,
5293
5537
  // Follow-up Questions
@@ -5300,6 +5544,8 @@ function ChatComponent({
5300
5544
  renderMessage,
5301
5545
  renderInput,
5302
5546
  renderHeader,
5547
+ // Avatar grouping
5548
+ groupConsecutiveMessages = false,
5303
5549
  // Styling
5304
5550
  className,
5305
5551
  classNames = {},
@@ -5308,16 +5554,20 @@ function ChatComponent({
5308
5554
  threads,
5309
5555
  currentThreadId,
5310
5556
  onSwitchThread,
5311
- isThreadBusy
5557
+ isThreadBusy,
5558
+ // Branching
5559
+ getBranchInfo,
5560
+ onSwitchBranch,
5561
+ onEditMessage
5312
5562
  }) {
5313
5563
  const userAvatar = { fallback: "U", ...userAvatarProp };
5314
5564
  const assistantAvatar = { fallback: "AI", ...assistantAvatarProp };
5315
- const [input, setInput] = React20.useState("");
5316
- const [pendingAttachments, setPendingAttachments] = React20.useState([]);
5317
- const [isDragging, setIsDragging] = React20.useState(false);
5318
- const fileInputRef = React20.useRef(null);
5319
- const fileInputId = React20.useId();
5320
- const isFileTypeAllowed = React20.useCallback(
5565
+ const [input, setInput] = React18.useState("");
5566
+ const [pendingAttachments, setPendingAttachments] = React18.useState([]);
5567
+ const [isDragging, setIsDragging] = React18.useState(false);
5568
+ const fileInputRef = React18.useRef(null);
5569
+ const fileInputId = React18.useId();
5570
+ const isFileTypeAllowed = React18.useCallback(
5321
5571
  (file) => {
5322
5572
  for (const type of allowedFileTypes) {
5323
5573
  if (type.endsWith("/*")) {
@@ -5331,7 +5581,7 @@ function ChatComponent({
5331
5581
  },
5332
5582
  [allowedFileTypes]
5333
5583
  );
5334
- const handleFileSelect = React20.useCallback(
5584
+ const handleFileSelect = React18.useCallback(
5335
5585
  async (files) => {
5336
5586
  if (!files || !attachmentsEnabled) return;
5337
5587
  for (const file of Array.from(files)) {
@@ -5394,7 +5644,7 @@ function ChatComponent({
5394
5644
  },
5395
5645
  [attachmentsEnabled, maxFileSize, isFileTypeAllowed, processAttachmentProp]
5396
5646
  );
5397
- const handleInputChange = React20.useCallback(
5647
+ const handleInputChange = React18.useCallback(
5398
5648
  (e) => {
5399
5649
  handleFileSelect(e.target.files);
5400
5650
  if (fileInputRef.current) {
@@ -5403,7 +5653,7 @@ function ChatComponent({
5403
5653
  },
5404
5654
  [handleFileSelect]
5405
5655
  );
5406
- const removePendingAttachment = React20.useCallback((id) => {
5656
+ const removePendingAttachment = React18.useCallback((id) => {
5407
5657
  setPendingAttachments((prev) => {
5408
5658
  const att = prev.find((a) => a.id === id);
5409
5659
  if (att) {
@@ -5412,7 +5662,7 @@ function ChatComponent({
5412
5662
  return prev.filter((a) => a.id !== id);
5413
5663
  });
5414
5664
  }, []);
5415
- const handleDragOver = React20.useCallback(
5665
+ const handleDragOver = React18.useCallback(
5416
5666
  (e) => {
5417
5667
  e.preventDefault();
5418
5668
  e.stopPropagation();
@@ -5422,12 +5672,12 @@ function ChatComponent({
5422
5672
  },
5423
5673
  [attachmentsEnabled]
5424
5674
  );
5425
- const handleDragLeave = React20.useCallback((e) => {
5675
+ const handleDragLeave = React18.useCallback((e) => {
5426
5676
  e.preventDefault();
5427
5677
  e.stopPropagation();
5428
5678
  setIsDragging(false);
5429
5679
  }, []);
5430
- const handleDrop = React20.useCallback(
5680
+ const handleDrop = React18.useCallback(
5431
5681
  (e) => {
5432
5682
  e.preventDefault();
5433
5683
  e.stopPropagation();
@@ -5438,7 +5688,7 @@ function ChatComponent({
5438
5688
  },
5439
5689
  [attachmentsEnabled, handleFileSelect]
5440
5690
  );
5441
- const handleSubmit = React20.useCallback(() => {
5691
+ const handleSubmit = React18.useCallback(() => {
5442
5692
  const hasContent = input.trim();
5443
5693
  const hasAttachments = pendingAttachments.some(
5444
5694
  (att) => att.status === "ready"
@@ -5450,7 +5700,7 @@ function ChatComponent({
5450
5700
  setPendingAttachments([]);
5451
5701
  setInput("");
5452
5702
  }, [input, isLoading, onSendMessage, pendingAttachments]);
5453
- const handleSuggestionClick = React20.useCallback(
5703
+ const handleSuggestionClick = React18.useCallback(
5454
5704
  (suggestion) => {
5455
5705
  if (onSuggestionClick) {
5456
5706
  onSuggestionClick(suggestion);
@@ -5477,13 +5727,13 @@ function ChatComponent({
5477
5727
  const chatViewNeedsDefault = chatViewElement && (!chatViewElement.props.children || chatViewHasOnlyLayoutChildren(chatViewElement));
5478
5728
  const showDefaultWelcome = view === "home" && !hasCustomHome && welcome !== false;
5479
5729
  const welcomeConfig = typeof welcome === "object" ? welcome : void 0;
5480
- const send = React20.useCallback(
5730
+ const send = React18.useCallback(
5481
5731
  (message, attachments) => {
5482
5732
  onSendMessage?.(message, attachments);
5483
5733
  },
5484
5734
  [onSendMessage]
5485
5735
  );
5486
- const contextValue = React20__namespace.default.useMemo(
5736
+ const contextValue = React18__namespace.default.useMemo(
5487
5737
  () => ({
5488
5738
  view,
5489
5739
  send,
@@ -5577,6 +5827,28 @@ function ChatComponent({
5577
5827
  messages.length === 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "py-8 text-center text-muted-foreground", children: welcomeMessage || "Send a message to start the conversation" }),
5578
5828
  messages.map((message, index) => {
5579
5829
  const isLastMessage = index === messages.length - 1;
5830
+ const GROUP_THRESHOLD_MS = 5 * 60 * 1e3;
5831
+ const shouldHideAvatar = (() => {
5832
+ if (!groupConsecutiveMessages || index === 0)
5833
+ return false;
5834
+ let prevIdx = index - 1;
5835
+ while (prevIdx >= 0) {
5836
+ const prev = messages[prevIdx];
5837
+ const isToolMsg = prev.role === "tool";
5838
+ const isInvisibleSystem = prev.role === "system" && // eslint-disable-next-line @typescript-eslint/no-explicit-any
5839
+ prev.metadata?.type !== "compaction-marker";
5840
+ if (!isToolMsg && !isInvisibleSystem) break;
5841
+ prevIdx--;
5842
+ }
5843
+ if (prevIdx < 0) return false;
5844
+ const prevVisible = messages[prevIdx];
5845
+ if (prevVisible.role !== message.role) return false;
5846
+ const curTs = message.timestamp;
5847
+ const prevTs = prevVisible.timestamp;
5848
+ if (curTs && prevTs && curTs - prevTs > GROUP_THRESHOLD_MS)
5849
+ return false;
5850
+ return true;
5851
+ })();
5580
5852
  const isEmptyAssistant = message.role === "assistant" && !message.content?.trim();
5581
5853
  const hasToolCalls = message.tool_calls && message.tool_calls.length > 0;
5582
5854
  const hasToolExecutions = message.toolExecutions && message.toolExecutions.length > 0;
@@ -5599,12 +5871,12 @@ function ChatComponent({
5599
5871
  onSendMessage?.(question);
5600
5872
  }
5601
5873
  };
5602
- return renderMessage ? /* @__PURE__ */ jsxRuntime.jsx(React20__namespace.default.Fragment, { children: renderMessage(messageWithExecutions, index) }, message.id) : /* @__PURE__ */ jsxRuntime.jsx(
5874
+ return renderMessage ? /* @__PURE__ */ jsxRuntime.jsx(React18__namespace.default.Fragment, { children: renderMessage(messageWithExecutions, index) }, message.id) : /* @__PURE__ */ jsxRuntime.jsx(
5603
5875
  DefaultMessage,
5604
5876
  {
5605
5877
  message: messageWithExecutions,
5606
- userAvatar,
5607
- assistantAvatar,
5878
+ userAvatar: shouldHideAvatar && message.role === "user" ? { ...userAvatar, className: "invisible" } : userAvatar,
5879
+ assistantAvatar: shouldHideAvatar && message.role === "assistant" ? { ...assistantAvatar, className: "invisible" } : assistantAvatar,
5608
5880
  showUserAvatar,
5609
5881
  userMessageClassName: classNames.userMessage,
5610
5882
  assistantMessageClassName: classNames.assistantMessage,
@@ -5616,13 +5888,17 @@ function ChatComponent({
5616
5888
  registeredTools,
5617
5889
  toolRenderers,
5618
5890
  mcpToolRenderer,
5891
+ fallbackToolRenderer,
5619
5892
  onApproveToolExecution,
5620
5893
  onRejectToolExecution,
5621
5894
  showFollowUps,
5622
5895
  onFollowUpClick: handleFollowUpClick,
5623
5896
  followUpClassName,
5624
5897
  followUpButtonClassName,
5625
- citations: citations === false ? { enabled: false } : citations
5898
+ citations: citations === false ? { enabled: false } : citations,
5899
+ branchInfo: message.role === "user" ? getBranchInfo?.(message.id) ?? null : null,
5900
+ onSwitchBranch,
5901
+ onEditMessage
5626
5902
  },
5627
5903
  message.id
5628
5904
  );
@@ -5945,7 +6221,7 @@ function useInternalThreadManager(config = {}) {
5945
6221
  saveDebounce,
5946
6222
  autoRestoreLastThread
5947
6223
  };
5948
- const threadManager = chunkN6VZ7FOW_cjs.useThreadManager(threadManagerConfig);
6224
+ const threadManager = chunkIXWNDR7H_cjs.useThreadManager(threadManagerConfig);
5949
6225
  const {
5950
6226
  currentThread,
5951
6227
  currentThreadId,
@@ -5955,18 +6231,18 @@ function useInternalThreadManager(config = {}) {
5955
6231
  clearCurrentThread,
5956
6232
  refreshThreads
5957
6233
  } = threadManager;
5958
- const { messages, setMessages, status, isLoading } = chunkN6VZ7FOW_cjs.useCopilot();
5959
- const isLoadingMessagesRef = React20.useRef(false);
5960
- const savingToThreadRef = React20.useRef(null);
5961
- const lastSavedSnapshotRef = React20.useRef("");
5962
- const hasInitializedRef = React20.useRef(false);
5963
- const getMessageSnapshot = React20.useCallback((msgs) => {
6234
+ const { messages, setMessages, status, isLoading, getAllMessages } = chunkIXWNDR7H_cjs.useCopilot();
6235
+ const isLoadingMessagesRef = React18.useRef(false);
6236
+ const savingToThreadRef = React18.useRef(null);
6237
+ const lastSavedSnapshotRef = React18.useRef("");
6238
+ const hasInitializedRef = React18.useRef(false);
6239
+ const getMessageSnapshot = React18.useCallback((msgs) => {
5964
6240
  return msgs.map((m) => {
5965
6241
  const contentPreview = (m.content ?? "").slice(0, 20);
5966
6242
  return `${m.id}:${contentPreview}:${m.content?.length ?? 0}`;
5967
6243
  }).join("|");
5968
6244
  }, []);
5969
- const convertToCore = React20.useCallback((msgs) => {
6245
+ const convertToCore = React18.useCallback((msgs) => {
5970
6246
  return msgs.map((m) => ({
5971
6247
  id: m.id,
5972
6248
  role: m.role,
@@ -5974,6 +6250,8 @@ function useInternalThreadManager(config = {}) {
5974
6250
  created_at: m.createdAt,
5975
6251
  tool_calls: m.toolCalls,
5976
6252
  tool_call_id: m.toolCallId,
6253
+ parent_id: m.parentId,
6254
+ children_ids: m.childrenIds,
5977
6255
  // Preserve full metadata including citations, toolExecutions, etc.
5978
6256
  metadata: {
5979
6257
  ...m.metadata,
@@ -5982,7 +6260,7 @@ function useInternalThreadManager(config = {}) {
5982
6260
  }
5983
6261
  }));
5984
6262
  }, []);
5985
- const handleSwitchThread = React20.useCallback(
6263
+ const handleSwitchThread = React18.useCallback(
5986
6264
  async (threadId) => {
5987
6265
  isLoadingMessagesRef.current = true;
5988
6266
  const thread = await switchThread(threadId);
@@ -5994,6 +6272,8 @@ function useInternalThreadManager(config = {}) {
5994
6272
  createdAt: m.created_at ?? /* @__PURE__ */ new Date(),
5995
6273
  toolCalls: m.tool_calls,
5996
6274
  toolCallId: m.tool_call_id,
6275
+ parentId: m.parent_id,
6276
+ childrenIds: m.children_ids,
5997
6277
  attachments: m.metadata?.attachments
5998
6278
  }));
5999
6279
  lastSavedSnapshotRef.current = getMessageSnapshot(uiMessages);
@@ -6011,7 +6291,7 @@ function useInternalThreadManager(config = {}) {
6011
6291
  },
6012
6292
  [switchThread, setMessages, getMessageSnapshot, onThreadChange]
6013
6293
  );
6014
- const handleNewThread = React20.useCallback(async () => {
6294
+ const handleNewThread = React18.useCallback(async () => {
6015
6295
  isLoadingMessagesRef.current = true;
6016
6296
  clearCurrentThread();
6017
6297
  lastSavedSnapshotRef.current = "";
@@ -6022,7 +6302,7 @@ function useInternalThreadManager(config = {}) {
6022
6302
  isLoadingMessagesRef.current = false;
6023
6303
  });
6024
6304
  }, [clearCurrentThread, setMessages, onThreadChange]);
6025
- React20.useEffect(() => {
6305
+ React18.useEffect(() => {
6026
6306
  if (hasInitializedRef.current || !currentThread) {
6027
6307
  return;
6028
6308
  }
@@ -6036,6 +6316,8 @@ function useInternalThreadManager(config = {}) {
6036
6316
  createdAt: m.created_at ?? /* @__PURE__ */ new Date(),
6037
6317
  toolCalls: m.tool_calls,
6038
6318
  toolCallId: m.tool_call_id,
6319
+ parentId: m.parent_id,
6320
+ childrenIds: m.children_ids,
6039
6321
  attachments: m.metadata?.attachments,
6040
6322
  thinking: m.metadata?.thinking,
6041
6323
  // Preserve full metadata including citations, toolExecutions, etc.
@@ -6053,7 +6335,7 @@ function useInternalThreadManager(config = {}) {
6053
6335
  isLoadingMessagesRef.current = false;
6054
6336
  });
6055
6337
  }, [adapter, currentThread, setMessages, getMessageSnapshot, onThreadChange]);
6056
- React20.useEffect(() => {
6338
+ React18.useEffect(() => {
6057
6339
  if (isLoadingMessagesRef.current) {
6058
6340
  return;
6059
6341
  }
@@ -6067,7 +6349,10 @@ function useInternalThreadManager(config = {}) {
6067
6349
  if (currentSnapshot === lastSavedSnapshotRef.current) {
6068
6350
  return;
6069
6351
  }
6070
- const coreMessages = convertToCore(messages);
6352
+ const allUIMessages = getAllMessages();
6353
+ const coreMessages = convertToCore(
6354
+ allUIMessages.length > 0 ? allUIMessages : messages
6355
+ );
6071
6356
  if (!currentThreadId && !savingToThreadRef.current) {
6072
6357
  savingToThreadRef.current = "creating";
6073
6358
  createThread({ messages: coreMessages }).then((thread) => {
@@ -6092,6 +6377,7 @@ function useInternalThreadManager(config = {}) {
6092
6377
  refreshThreads,
6093
6378
  getMessageSnapshot,
6094
6379
  convertToCore,
6380
+ getAllMessages,
6095
6381
  onThreadChange
6096
6382
  ]);
6097
6383
  const isBusy = isLoading || status === "streaming" || status === "submitted";
@@ -6122,7 +6408,7 @@ function parsePersistenceConfig(persistence, onThreadChange) {
6122
6408
  };
6123
6409
  case "server":
6124
6410
  return {
6125
- adapter: chunkOQPRIB73_cjs.createServerAdapter({
6411
+ adapter: chunkI3SQUNTT_cjs.createServerAdapter({
6126
6412
  endpoint: persistence.endpoint,
6127
6413
  headers: persistence.headers
6128
6414
  }),
@@ -6171,8 +6457,11 @@ function CopilotChatBase(props) {
6171
6457
  toolExecutions: rawToolExecutions,
6172
6458
  approveToolExecution,
6173
6459
  rejectToolExecution,
6174
- registeredTools
6175
- } = chunkN6VZ7FOW_cjs.useCopilot();
6460
+ registeredTools,
6461
+ switchBranch,
6462
+ getBranchInfo,
6463
+ editMessage
6464
+ } = chunkIXWNDR7H_cjs.useCopilot();
6176
6465
  const toolExecutions = rawToolExecutions.map(
6177
6466
  (exec) => ({
6178
6467
  id: exec.id,
@@ -6190,7 +6479,9 @@ function CopilotChatBase(props) {
6190
6479
  messages.filter((m) => m.role === "tool" && m.toolCallId).forEach((m) => {
6191
6480
  toolResultsMap.set(m.toolCallId, m.content ?? "");
6192
6481
  });
6193
- const visibleMessages = messages.filter((m) => m.role !== "tool").map((m) => {
6482
+ const visibleMessages = messages.filter(
6483
+ (m) => m.role !== "tool" && (m.role !== "system" || m.metadata?.type === "compaction-marker")
6484
+ ).map((m) => {
6194
6485
  let messageToolExecutions;
6195
6486
  if (m.role === "assistant" && m.toolCalls && m.toolCalls.length > 0) {
6196
6487
  const toolCallIds = new Set(
@@ -6286,24 +6577,29 @@ function CopilotChatBase(props) {
6286
6577
  });
6287
6578
  const suggestions = visibleMessages.length === 0 && chatProps.suggestions?.length ? chatProps.suggestions : [];
6288
6579
  const lastMessage = messages[messages.length - 1];
6289
- const isInToolFlow = lastMessage?.role === "assistant" && lastMessage.toolCalls?.length;
6580
+ const lastAssistantWithTools = [...messages].reverse().find(
6581
+ (m) => m.role === "assistant" && m.toolCalls?.length
6582
+ );
6583
+ const isInToolFlow = lastMessage?.role === "tool" || lastMessage?.role === "assistant" && lastMessage.toolCalls?.length;
6290
6584
  let isProcessingToolResults = false;
6291
6585
  if (isLoading && isInToolFlow) {
6292
- const currentToolCallIds = new Set(
6293
- lastMessage.toolCalls?.map(
6294
- (tc) => tc.id
6295
- ) || []
6296
- );
6297
- const currentExecutions = toolExecutions.filter(
6298
- (exec) => currentToolCallIds.has(exec.id)
6299
- );
6300
- const hasCompletedTools = currentExecutions.some(
6301
- (exec) => exec.status === "completed" || exec.status === "error" || exec.status === "failed"
6302
- );
6303
- const hasExecutingTools = currentExecutions.some(
6304
- (exec) => exec.status === "executing" || exec.status === "pending"
6305
- );
6306
- isProcessingToolResults = hasCompletedTools && !hasExecutingTools;
6586
+ if (lastMessage?.role === "tool") {
6587
+ isProcessingToolResults = true;
6588
+ } else if (lastAssistantWithTools) {
6589
+ const currentToolCallIds = new Set(
6590
+ lastAssistantWithTools.toolCalls?.map((tc) => tc.id) || []
6591
+ );
6592
+ const currentExecutions = toolExecutions.filter(
6593
+ (exec) => currentToolCallIds.has(exec.id)
6594
+ );
6595
+ const hasCompletedTools = currentExecutions.some(
6596
+ (exec) => exec.status === "completed" || exec.status === "error" || exec.status === "failed"
6597
+ );
6598
+ const hasExecutingTools = currentExecutions.some(
6599
+ (exec) => exec.status === "executing" || exec.status === "pending"
6600
+ );
6601
+ isProcessingToolResults = hasCompletedTools && !hasExecutingTools;
6602
+ }
6307
6603
  }
6308
6604
  const chatClassNames = classNames ? {
6309
6605
  root: classNames.root,
@@ -6317,7 +6613,7 @@ function CopilotChatBase(props) {
6317
6613
  footer: classNames.footer
6318
6614
  } : void 0;
6319
6615
  const { threadManager, handleSwitchThread, handleNewThread, isBusy } = threadManagerResult;
6320
- const handleDeleteThread = React20__namespace.default.useCallback(
6616
+ const handleDeleteThread = React18__namespace.default.useCallback(
6321
6617
  (threadId) => {
6322
6618
  const isCurrentThread = threadManager.currentThreadId === threadId;
6323
6619
  threadManager.deleteThread(threadId);
@@ -6374,6 +6670,9 @@ function CopilotChatBase(props) {
6374
6670
  currentThreadId: threadManager.currentThreadId,
6375
6671
  onSwitchThread: isPersistenceEnabled ? handleSwitchThread : void 0,
6376
6672
  isThreadBusy: isBusy,
6673
+ getBranchInfo,
6674
+ onSwitchBranch: switchBranch,
6675
+ onEditMessage: editMessage,
6377
6676
  children
6378
6677
  }
6379
6678
  );
@@ -6444,6 +6743,7 @@ function PoweredBy({ className, showLogo = true }) {
6444
6743
 
6445
6744
  exports.AlertTriangleIcon = AlertTriangleIcon;
6446
6745
  exports.BotIcon = BotIcon;
6746
+ exports.BranchNavigator = BranchNavigator;
6447
6747
  exports.Button = Button;
6448
6748
  exports.CapabilityBadge = CapabilityBadge;
6449
6749
  exports.CapabilityList = CapabilityList;