@yourgpt/copilot-sdk 2.1.4 → 2.1.5-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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-6BMQZIS3.js} +3094 -355
  10. package/dist/chunk-6BMQZIS3.js.map +1 -0
  11. package/dist/{chunk-N6VZ7FOW.cjs → chunk-76RE7AJE.cjs} +3277 -520
  12. package/dist/chunk-76RE7AJE.cjs.map +1 -0
  13. package/dist/chunk-BJYA5NDL.cjs +96 -0
  14. package/dist/chunk-BJYA5NDL.cjs.map +1 -0
  15. package/dist/{chunk-LZMBBGWH.js → chunk-ENFWM3EY.js} +4 -4
  16. package/dist/{chunk-LZMBBGWH.js.map → chunk-ENFWM3EY.js.map} +1 -1
  17. package/dist/{chunk-OQPRIB73.cjs → chunk-I3SQUNTT.cjs} +71 -25
  18. package/dist/chunk-I3SQUNTT.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 +468 -163
  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 +416 -112
  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 chunk76RE7AJE_cjs = require('../chunk-76RE7AJE.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) => {
@@ -4330,32 +4475,118 @@ function DefaultMessage({
4330
4475
  return /* @__PURE__ */ jsxRuntime.jsxs(
4331
4476
  Message,
4332
4477
  {
4333
- className: cn(
4334
- "flex gap-2",
4335
- showUserAvatar ? "justify-end" : "justify-end"
4336
- ),
4478
+ className: cn("flex gap-2 group/user-msg justify-end"),
4337
4479
  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,
4480
+ /* @__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: [
4481
+ /* @__PURE__ */ jsxRuntime.jsx(
4482
+ "textarea",
4341
4483
  {
4484
+ ref: editRef,
4485
+ value: editValue,
4486
+ onChange: (e) => setEditValue(e.target.value),
4487
+ onKeyDown: handleEditKeyDown,
4488
+ rows: Math.max(2, (editValue.match(/\n/g) || []).length + 1),
4342
4489
  className: cn(
4343
- "csdk-message-user rounded-lg px-4 py-2 bg-primary text-primary-foreground",
4490
+ "csdk-edit-textarea w-full rounded-lg px-3 py-2 text-sm resize-none",
4491
+ "bg-primary text-primary-foreground placeholder:text-primary-foreground/50",
4492
+ "focus:outline-none focus:ring-2 focus:ring-primary-foreground/30",
4344
4493
  userMessageClassName
4345
- ),
4346
- markdown: true,
4347
- size,
4348
- children: message.content
4494
+ )
4349
4495
  }
4350
4496
  ),
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
- ] }),
4497
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-1.5 justify-end", children: [
4498
+ /* @__PURE__ */ jsxRuntime.jsx(
4499
+ "button",
4500
+ {
4501
+ type: "button",
4502
+ onClick: cancelEdit,
4503
+ className: "csdk-edit-cancel px-3 py-1 text-xs rounded-md bg-muted text-muted-foreground hover:bg-muted/80 transition-colors",
4504
+ children: "Cancel"
4505
+ }
4506
+ ),
4507
+ /* @__PURE__ */ jsxRuntime.jsx(
4508
+ "button",
4509
+ {
4510
+ type: "button",
4511
+ onClick: submitEdit,
4512
+ disabled: !editValue.trim(),
4513
+ 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",
4514
+ children: "Send"
4515
+ }
4516
+ )
4517
+ ] })
4518
+ ] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
4519
+ message.content && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative", children: [
4520
+ /* @__PURE__ */ jsxRuntime.jsx(
4521
+ MessageContent,
4522
+ {
4523
+ className: cn(
4524
+ "csdk-message-user rounded-lg px-4 py-2 bg-primary text-primary-foreground",
4525
+ userMessageClassName
4526
+ ),
4527
+ markdown: true,
4528
+ size,
4529
+ children: message.content
4530
+ }
4531
+ ),
4532
+ showEditBtn && /* @__PURE__ */ jsxRuntime.jsx(
4533
+ "button",
4534
+ {
4535
+ type: "button",
4536
+ onClick: startEdit,
4537
+ "aria-label": "Edit message",
4538
+ className: cn(
4539
+ "csdk-edit-btn absolute -left-7 top-1/2 -translate-y-1/2",
4540
+ "size-6 flex items-center justify-center rounded-full",
4541
+ "text-muted-foreground bg-background border border-border shadow-sm",
4542
+ "opacity-0 group-hover/user-msg:opacity-100 transition-opacity",
4543
+ "hover:text-foreground hover:bg-muted"
4544
+ ),
4545
+ children: /* @__PURE__ */ jsxRuntime.jsxs(
4546
+ "svg",
4547
+ {
4548
+ width: "12",
4549
+ height: "12",
4550
+ viewBox: "0 0 24 24",
4551
+ fill: "none",
4552
+ stroke: "currentColor",
4553
+ strokeWidth: 2,
4554
+ strokeLinecap: "round",
4555
+ strokeLinejoin: "round",
4556
+ children: [
4557
+ /* @__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" }),
4558
+ /* @__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" })
4559
+ ]
4560
+ }
4561
+ )
4562
+ }
4563
+ )
4564
+ ] }),
4565
+ 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)) }),
4566
+ showBranchNav && /* @__PURE__ */ jsxRuntime.jsx(
4567
+ BranchNavigator,
4568
+ {
4569
+ siblingIndex: branchInfo.siblingIndex,
4570
+ totalSiblings: branchInfo.totalSiblings,
4571
+ hasPrevious: branchInfo.hasPrevious,
4572
+ hasNext: branchInfo.hasNext,
4573
+ onPrevious: () => onSwitchBranch(
4574
+ branchInfo.siblingIds[branchInfo.siblingIndex - 1]
4575
+ ),
4576
+ onNext: () => onSwitchBranch(
4577
+ branchInfo.siblingIds[branchInfo.siblingIndex + 1]
4578
+ ),
4579
+ className: "mt-1"
4580
+ }
4581
+ )
4582
+ ] }) }),
4353
4583
  showUserAvatar && /* @__PURE__ */ jsxRuntime.jsx(
4354
4584
  MessageAvatar,
4355
4585
  {
4356
4586
  src: userAvatar.src,
4357
4587
  alt: "User",
4358
4588
  fallback: userAvatar.fallback,
4589
+ className: userAvatar.className,
4359
4590
  children: userAvatar.component
4360
4591
  }
4361
4592
  )
@@ -4379,6 +4610,7 @@ function DefaultMessage({
4379
4610
  const toolDef = registeredTools?.find((t) => t.name === toolName);
4380
4611
  if (mcpToolRenderer && (execSource === "mcp" || toolDef?.source === "mcp"))
4381
4612
  return true;
4613
+ if (fallbackToolRenderer) return true;
4382
4614
  if (toolDef?.render) return true;
4383
4615
  return false;
4384
4616
  };
@@ -4405,7 +4637,7 @@ function DefaultMessage({
4405
4637
  alt: "Assistant",
4406
4638
  fallback: assistantAvatar.fallback,
4407
4639
  fallbackIcon: !assistantAvatar.src && !assistantAvatar.fallback && !assistantAvatar.component ? /* @__PURE__ */ jsxRuntime.jsx(copilot_sdk_logo_default, { className: "size-5" }) : void 0,
4408
- className: "bg-muted",
4640
+ className: cn("bg-muted", assistantAvatar.className),
4409
4641
  children: assistantAvatar.component
4410
4642
  }
4411
4643
  ),
@@ -4418,10 +4650,7 @@ function DefaultMessage({
4418
4650
  className: "mb-2"
4419
4651
  }
4420
4652
  ),
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
- ] }) : (
4653
+ 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
4654
  /* Show streaming loader when loading with no content and no tools */
4426
4655
  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
4656
  cleanContent?.trim() && /* @__PURE__ */ jsxRuntime.jsx(
@@ -4477,6 +4706,24 @@ function DefaultMessage({
4477
4706
  exec.id
4478
4707
  );
4479
4708
  }
4709
+ if (fallbackToolRenderer) {
4710
+ const FallbackRenderer = fallbackToolRenderer;
4711
+ return /* @__PURE__ */ jsxRuntime.jsx(
4712
+ FallbackRenderer,
4713
+ {
4714
+ execution: {
4715
+ id: exec.id,
4716
+ name: exec.name,
4717
+ args: exec.args,
4718
+ status: exec.status,
4719
+ result: exec.result,
4720
+ error: exec.error,
4721
+ source: exec.source
4722
+ }
4723
+ },
4724
+ exec.id
4725
+ );
4726
+ }
4480
4727
  const toolDefForRender = toolDef ?? registeredTools?.find((t) => t.name === exec.name);
4481
4728
  if (toolDefForRender?.render) {
4482
4729
  let status = "pending";
@@ -4495,7 +4742,7 @@ function DefaultMessage({
4495
4742
  const output = toolDefForRender.render(
4496
4743
  renderProps
4497
4744
  );
4498
- return /* @__PURE__ */ jsxRuntime.jsx(React20__namespace.Fragment, { children: output }, exec.id);
4745
+ return /* @__PURE__ */ jsxRuntime.jsx(React18__namespace.Fragment, { children: output }, exec.id);
4499
4746
  }
4500
4747
  return null;
4501
4748
  }) }),
@@ -4521,6 +4768,7 @@ function DefaultMessage({
4521
4768
  `${exec.id}-ui`
4522
4769
  );
4523
4770
  }),
4771
+ 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
4772
  pendingApprovalTools && pendingApprovalTools.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-2 space-y-2", children: pendingApprovalTools.map((tool) => {
4525
4773
  const approvalCallbacks = {
4526
4774
  onApprove: (extraData) => onApproveToolExecution?.(tool.id, extraData),
@@ -4554,7 +4802,7 @@ function DefaultMessage({
4554
4802
  const output = toolDef.render(
4555
4803
  renderProps
4556
4804
  );
4557
- return /* @__PURE__ */ jsxRuntime.jsx(React20__namespace.Fragment, { children: output }, tool.id);
4805
+ return /* @__PURE__ */ jsxRuntime.jsx(React18__namespace.Fragment, { children: output }, tool.id);
4558
4806
  }
4559
4807
  return /* @__PURE__ */ jsxRuntime.jsx(
4560
4808
  PermissionConfirmation,
@@ -4603,7 +4851,7 @@ function DefaultMessage({
4603
4851
  ] });
4604
4852
  }
4605
4853
  function AttachmentPreview({ attachment }) {
4606
- const [expanded, setExpanded] = React20__namespace.useState(false);
4854
+ const [expanded, setExpanded] = React18__namespace.useState(false);
4607
4855
  if (attachment.type !== "image") {
4608
4856
  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
4857
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground", children: attachment.type }),
@@ -4732,10 +4980,10 @@ function ChatWelcome({
4732
4980
  processAttachment: processAttachmentProp,
4733
4981
  classNames = {}
4734
4982
  }) {
4735
- const [input, setInput] = React20.useState("");
4736
- const [pendingAttachments, setPendingAttachments] = React20.useState([]);
4737
- const fileInputRef = React20.useRef(null);
4738
- const fileInputId = React20.useId();
4983
+ const [input, setInput] = React18.useState("");
4984
+ const [pendingAttachments, setPendingAttachments] = React18.useState([]);
4985
+ const fileInputRef = React18.useRef(null);
4986
+ const fileInputId = React18.useId();
4739
4987
  const title = config?.title ?? DEFAULT_TITLE;
4740
4988
  const subtitle = config?.subtitle ?? DEFAULT_SUBTITLE;
4741
4989
  const logo = config?.logo;
@@ -4744,7 +4992,7 @@ function ChatWelcome({
4744
4992
  config?.recentChatsLabel ?? DEFAULT_RECENT_CHATS_LABEL;
4745
4993
  const maxRecentChats = config?.maxRecentChats ?? DEFAULT_MAX_RECENT_CHATS;
4746
4994
  config?.viewMoreLabel ?? DEFAULT_VIEW_MORE_LABEL;
4747
- const isFileTypeAllowed = React20.useCallback(
4995
+ const isFileTypeAllowed = React18.useCallback(
4748
4996
  (file) => {
4749
4997
  for (const type of allowedFileTypes) {
4750
4998
  if (type.endsWith("/*")) {
@@ -4758,7 +5006,7 @@ function ChatWelcome({
4758
5006
  },
4759
5007
  [allowedFileTypes]
4760
5008
  );
4761
- const handleFileSelect = React20.useCallback(
5009
+ const handleFileSelect = React18.useCallback(
4762
5010
  async (files) => {
4763
5011
  if (!files || !attachmentsEnabled) return;
4764
5012
  for (const file of Array.from(files)) {
@@ -4821,7 +5069,7 @@ function ChatWelcome({
4821
5069
  },
4822
5070
  [attachmentsEnabled, maxFileSize, isFileTypeAllowed, processAttachmentProp]
4823
5071
  );
4824
- const handleInputChange = React20.useCallback(
5072
+ const handleInputChange = React18.useCallback(
4825
5073
  (e) => {
4826
5074
  handleFileSelect(e.target.files);
4827
5075
  if (fileInputRef.current) {
@@ -4830,7 +5078,7 @@ function ChatWelcome({
4830
5078
  },
4831
5079
  [handleFileSelect]
4832
5080
  );
4833
- const removePendingAttachment = React20.useCallback((id) => {
5081
+ const removePendingAttachment = React18.useCallback((id) => {
4834
5082
  setPendingAttachments((prev) => {
4835
5083
  const att = prev.find((a) => a.id === id);
4836
5084
  if (att) {
@@ -4839,7 +5087,7 @@ function ChatWelcome({
4839
5087
  return prev.filter((a) => a.id !== id);
4840
5088
  });
4841
5089
  }, []);
4842
- const handleSubmit = React20.useCallback(() => {
5090
+ const handleSubmit = React18.useCallback(() => {
4843
5091
  const hasContent = input.trim();
4844
5092
  const hasAttachments = pendingAttachments.some(
4845
5093
  (att) => att.status === "ready"
@@ -4851,7 +5099,7 @@ function ChatWelcome({
4851
5099
  setPendingAttachments([]);
4852
5100
  setInput("");
4853
5101
  }, [input, isLoading, onSendMessage, pendingAttachments]);
4854
- const handleSuggestionClick = React20.useCallback(
5102
+ const handleSuggestionClick = React18.useCallback(
4855
5103
  (suggestion) => {
4856
5104
  onSendMessage(suggestion);
4857
5105
  },
@@ -5023,11 +5271,11 @@ function ChatWelcome({
5023
5271
  }
5024
5272
  );
5025
5273
  }
5026
- var CopilotChatContext = React20.createContext(
5274
+ var CopilotChatContext = React18.createContext(
5027
5275
  null
5028
5276
  );
5029
5277
  var useCopilotChatContext = () => {
5030
- const ctx = React20.useContext(CopilotChatContext);
5278
+ const ctx = React18.useContext(CopilotChatContext);
5031
5279
  if (!ctx) {
5032
5280
  throw new Error(
5033
5281
  "useCopilotChatContext must be used within CopilotChat. Make sure you're using CopilotChat.Home, CopilotChat.Input, etc. inside <CopilotChat>"
@@ -5061,10 +5309,10 @@ function ChatView({ children, className }) {
5061
5309
  ChatView.displayName = "ChatView";
5062
5310
  function chatViewHasOnlyLayoutChildren(chatViewElement) {
5063
5311
  if (!chatViewElement?.props?.children) return false;
5064
- const childArray = React20__namespace.default.Children.toArray(chatViewElement.props.children);
5312
+ const childArray = React18__namespace.default.Children.toArray(chatViewElement.props.children);
5065
5313
  if (childArray.length === 0) return false;
5066
5314
  return childArray.every(
5067
- (child) => React20__namespace.default.isValidElement(child) && (child.type === Header || child.type === Footer)
5315
+ (child) => React18__namespace.default.isValidElement(child) && (child.type === Header || child.type === Footer)
5068
5316
  );
5069
5317
  }
5070
5318
  function Header({ children, className }) {
@@ -5080,8 +5328,8 @@ function Input({ placeholder: placeholderProp, className }) {
5080
5328
  onStop,
5081
5329
  placeholder: defaultPlaceholder
5082
5330
  } = useCopilotChatContext();
5083
- const [value, setValue] = React20.useState("");
5084
- const handleSubmit = React20.useCallback(() => {
5331
+ const [value, setValue] = React18.useState("");
5332
+ const handleSubmit = React18.useCallback(() => {
5085
5333
  if (value.trim() && !isLoading) {
5086
5334
  send(value.trim());
5087
5335
  setValue("");
@@ -5202,18 +5450,18 @@ function ThreadPickerCompound(props) {
5202
5450
  );
5203
5451
  }
5204
5452
  function hasCompoundChild(children, ...components) {
5205
- return React20__namespace.default.Children.toArray(children).some(
5206
- (child) => React20__namespace.default.isValidElement(child) && components.includes(child.type)
5453
+ return React18__namespace.default.Children.toArray(children).some(
5454
+ (child) => React18__namespace.default.isValidElement(child) && components.includes(child.type)
5207
5455
  );
5208
5456
  }
5209
5457
  function findCompoundChild(children, component) {
5210
- return React20__namespace.default.Children.toArray(children).find(
5211
- (child) => React20__namespace.default.isValidElement(child) && child.type === component
5458
+ return React18__namespace.default.Children.toArray(children).find(
5459
+ (child) => React18__namespace.default.isValidElement(child) && child.type === component
5212
5460
  );
5213
5461
  }
5214
5462
  function filterCompoundChildren(children, ...components) {
5215
- return React20__namespace.default.Children.toArray(children).filter(
5216
- (child) => React20__namespace.default.isValidElement(child) && components.includes(child.type)
5463
+ return React18__namespace.default.Children.toArray(children).filter(
5464
+ (child) => React18__namespace.default.isValidElement(child) && components.includes(child.type)
5217
5465
  );
5218
5466
  }
5219
5467
  var DEFAULT_MAX_FILE_SIZE2 = 5 * 1024 * 1024;
@@ -5288,6 +5536,7 @@ function ChatComponent({
5288
5536
  registeredTools,
5289
5537
  toolRenderers,
5290
5538
  mcpToolRenderer,
5539
+ fallbackToolRenderer,
5291
5540
  onApproveToolExecution,
5292
5541
  onRejectToolExecution,
5293
5542
  // Follow-up Questions
@@ -5300,6 +5549,8 @@ function ChatComponent({
5300
5549
  renderMessage,
5301
5550
  renderInput,
5302
5551
  renderHeader,
5552
+ // Avatar grouping
5553
+ groupConsecutiveMessages = false,
5303
5554
  // Styling
5304
5555
  className,
5305
5556
  classNames = {},
@@ -5308,16 +5559,20 @@ function ChatComponent({
5308
5559
  threads,
5309
5560
  currentThreadId,
5310
5561
  onSwitchThread,
5311
- isThreadBusy
5562
+ isThreadBusy,
5563
+ // Branching
5564
+ getBranchInfo,
5565
+ onSwitchBranch,
5566
+ onEditMessage
5312
5567
  }) {
5313
5568
  const userAvatar = { fallback: "U", ...userAvatarProp };
5314
5569
  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(
5570
+ const [input, setInput] = React18.useState("");
5571
+ const [pendingAttachments, setPendingAttachments] = React18.useState([]);
5572
+ const [isDragging, setIsDragging] = React18.useState(false);
5573
+ const fileInputRef = React18.useRef(null);
5574
+ const fileInputId = React18.useId();
5575
+ const isFileTypeAllowed = React18.useCallback(
5321
5576
  (file) => {
5322
5577
  for (const type of allowedFileTypes) {
5323
5578
  if (type.endsWith("/*")) {
@@ -5331,7 +5586,7 @@ function ChatComponent({
5331
5586
  },
5332
5587
  [allowedFileTypes]
5333
5588
  );
5334
- const handleFileSelect = React20.useCallback(
5589
+ const handleFileSelect = React18.useCallback(
5335
5590
  async (files) => {
5336
5591
  if (!files || !attachmentsEnabled) return;
5337
5592
  for (const file of Array.from(files)) {
@@ -5394,7 +5649,7 @@ function ChatComponent({
5394
5649
  },
5395
5650
  [attachmentsEnabled, maxFileSize, isFileTypeAllowed, processAttachmentProp]
5396
5651
  );
5397
- const handleInputChange = React20.useCallback(
5652
+ const handleInputChange = React18.useCallback(
5398
5653
  (e) => {
5399
5654
  handleFileSelect(e.target.files);
5400
5655
  if (fileInputRef.current) {
@@ -5403,7 +5658,7 @@ function ChatComponent({
5403
5658
  },
5404
5659
  [handleFileSelect]
5405
5660
  );
5406
- const removePendingAttachment = React20.useCallback((id) => {
5661
+ const removePendingAttachment = React18.useCallback((id) => {
5407
5662
  setPendingAttachments((prev) => {
5408
5663
  const att = prev.find((a) => a.id === id);
5409
5664
  if (att) {
@@ -5412,7 +5667,7 @@ function ChatComponent({
5412
5667
  return prev.filter((a) => a.id !== id);
5413
5668
  });
5414
5669
  }, []);
5415
- const handleDragOver = React20.useCallback(
5670
+ const handleDragOver = React18.useCallback(
5416
5671
  (e) => {
5417
5672
  e.preventDefault();
5418
5673
  e.stopPropagation();
@@ -5422,12 +5677,12 @@ function ChatComponent({
5422
5677
  },
5423
5678
  [attachmentsEnabled]
5424
5679
  );
5425
- const handleDragLeave = React20.useCallback((e) => {
5680
+ const handleDragLeave = React18.useCallback((e) => {
5426
5681
  e.preventDefault();
5427
5682
  e.stopPropagation();
5428
5683
  setIsDragging(false);
5429
5684
  }, []);
5430
- const handleDrop = React20.useCallback(
5685
+ const handleDrop = React18.useCallback(
5431
5686
  (e) => {
5432
5687
  e.preventDefault();
5433
5688
  e.stopPropagation();
@@ -5438,7 +5693,7 @@ function ChatComponent({
5438
5693
  },
5439
5694
  [attachmentsEnabled, handleFileSelect]
5440
5695
  );
5441
- const handleSubmit = React20.useCallback(() => {
5696
+ const handleSubmit = React18.useCallback(() => {
5442
5697
  const hasContent = input.trim();
5443
5698
  const hasAttachments = pendingAttachments.some(
5444
5699
  (att) => att.status === "ready"
@@ -5450,7 +5705,7 @@ function ChatComponent({
5450
5705
  setPendingAttachments([]);
5451
5706
  setInput("");
5452
5707
  }, [input, isLoading, onSendMessage, pendingAttachments]);
5453
- const handleSuggestionClick = React20.useCallback(
5708
+ const handleSuggestionClick = React18.useCallback(
5454
5709
  (suggestion) => {
5455
5710
  if (onSuggestionClick) {
5456
5711
  onSuggestionClick(suggestion);
@@ -5477,13 +5732,13 @@ function ChatComponent({
5477
5732
  const chatViewNeedsDefault = chatViewElement && (!chatViewElement.props.children || chatViewHasOnlyLayoutChildren(chatViewElement));
5478
5733
  const showDefaultWelcome = view === "home" && !hasCustomHome && welcome !== false;
5479
5734
  const welcomeConfig = typeof welcome === "object" ? welcome : void 0;
5480
- const send = React20.useCallback(
5735
+ const send = React18.useCallback(
5481
5736
  (message, attachments) => {
5482
5737
  onSendMessage?.(message, attachments);
5483
5738
  },
5484
5739
  [onSendMessage]
5485
5740
  );
5486
- const contextValue = React20__namespace.default.useMemo(
5741
+ const contextValue = React18__namespace.default.useMemo(
5487
5742
  () => ({
5488
5743
  view,
5489
5744
  send,
@@ -5577,6 +5832,28 @@ function ChatComponent({
5577
5832
  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
5833
  messages.map((message, index) => {
5579
5834
  const isLastMessage = index === messages.length - 1;
5835
+ const GROUP_THRESHOLD_MS = 5 * 60 * 1e3;
5836
+ const shouldHideAvatar = (() => {
5837
+ if (!groupConsecutiveMessages || index === 0)
5838
+ return false;
5839
+ let prevIdx = index - 1;
5840
+ while (prevIdx >= 0) {
5841
+ const prev = messages[prevIdx];
5842
+ const isToolMsg = prev.role === "tool";
5843
+ const isInvisibleSystem = prev.role === "system" && // eslint-disable-next-line @typescript-eslint/no-explicit-any
5844
+ prev.metadata?.type !== "compaction-marker";
5845
+ if (!isToolMsg && !isInvisibleSystem) break;
5846
+ prevIdx--;
5847
+ }
5848
+ if (prevIdx < 0) return false;
5849
+ const prevVisible = messages[prevIdx];
5850
+ if (prevVisible.role !== message.role) return false;
5851
+ const curTs = message.timestamp;
5852
+ const prevTs = prevVisible.timestamp;
5853
+ if (curTs && prevTs && curTs - prevTs > GROUP_THRESHOLD_MS)
5854
+ return false;
5855
+ return true;
5856
+ })();
5580
5857
  const isEmptyAssistant = message.role === "assistant" && !message.content?.trim();
5581
5858
  const hasToolCalls = message.tool_calls && message.tool_calls.length > 0;
5582
5859
  const hasToolExecutions = message.toolExecutions && message.toolExecutions.length > 0;
@@ -5599,12 +5876,12 @@ function ChatComponent({
5599
5876
  onSendMessage?.(question);
5600
5877
  }
5601
5878
  };
5602
- return renderMessage ? /* @__PURE__ */ jsxRuntime.jsx(React20__namespace.default.Fragment, { children: renderMessage(messageWithExecutions, index) }, message.id) : /* @__PURE__ */ jsxRuntime.jsx(
5879
+ return renderMessage ? /* @__PURE__ */ jsxRuntime.jsx(React18__namespace.default.Fragment, { children: renderMessage(messageWithExecutions, index) }, message.id) : /* @__PURE__ */ jsxRuntime.jsx(
5603
5880
  DefaultMessage,
5604
5881
  {
5605
5882
  message: messageWithExecutions,
5606
- userAvatar,
5607
- assistantAvatar,
5883
+ userAvatar: shouldHideAvatar && message.role === "user" ? { ...userAvatar, className: "invisible" } : userAvatar,
5884
+ assistantAvatar: shouldHideAvatar && message.role === "assistant" ? { ...assistantAvatar, className: "invisible" } : assistantAvatar,
5608
5885
  showUserAvatar,
5609
5886
  userMessageClassName: classNames.userMessage,
5610
5887
  assistantMessageClassName: classNames.assistantMessage,
@@ -5616,13 +5893,17 @@ function ChatComponent({
5616
5893
  registeredTools,
5617
5894
  toolRenderers,
5618
5895
  mcpToolRenderer,
5896
+ fallbackToolRenderer,
5619
5897
  onApproveToolExecution,
5620
5898
  onRejectToolExecution,
5621
5899
  showFollowUps,
5622
5900
  onFollowUpClick: handleFollowUpClick,
5623
5901
  followUpClassName,
5624
5902
  followUpButtonClassName,
5625
- citations: citations === false ? { enabled: false } : citations
5903
+ citations: citations === false ? { enabled: false } : citations,
5904
+ branchInfo: message.role === "user" ? getBranchInfo?.(message.id) ?? null : null,
5905
+ onSwitchBranch,
5906
+ onEditMessage
5626
5907
  },
5627
5908
  message.id
5628
5909
  );
@@ -5945,7 +6226,7 @@ function useInternalThreadManager(config = {}) {
5945
6226
  saveDebounce,
5946
6227
  autoRestoreLastThread
5947
6228
  };
5948
- const threadManager = chunkN6VZ7FOW_cjs.useThreadManager(threadManagerConfig);
6229
+ const threadManager = chunk76RE7AJE_cjs.useThreadManager(threadManagerConfig);
5949
6230
  const {
5950
6231
  currentThread,
5951
6232
  currentThreadId,
@@ -5955,18 +6236,18 @@ function useInternalThreadManager(config = {}) {
5955
6236
  clearCurrentThread,
5956
6237
  refreshThreads
5957
6238
  } = 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) => {
6239
+ const { messages, setMessages, status, isLoading, getAllMessages } = chunk76RE7AJE_cjs.useCopilot();
6240
+ const isLoadingMessagesRef = React18.useRef(false);
6241
+ const savingToThreadRef = React18.useRef(null);
6242
+ const lastSavedSnapshotRef = React18.useRef("");
6243
+ const hasInitializedRef = React18.useRef(false);
6244
+ const getMessageSnapshot = React18.useCallback((msgs) => {
5964
6245
  return msgs.map((m) => {
5965
6246
  const contentPreview = (m.content ?? "").slice(0, 20);
5966
6247
  return `${m.id}:${contentPreview}:${m.content?.length ?? 0}`;
5967
6248
  }).join("|");
5968
6249
  }, []);
5969
- const convertToCore = React20.useCallback((msgs) => {
6250
+ const convertToCore = React18.useCallback((msgs) => {
5970
6251
  return msgs.map((m) => ({
5971
6252
  id: m.id,
5972
6253
  role: m.role,
@@ -5974,6 +6255,8 @@ function useInternalThreadManager(config = {}) {
5974
6255
  created_at: m.createdAt,
5975
6256
  tool_calls: m.toolCalls,
5976
6257
  tool_call_id: m.toolCallId,
6258
+ parent_id: m.parentId,
6259
+ children_ids: m.childrenIds,
5977
6260
  // Preserve full metadata including citations, toolExecutions, etc.
5978
6261
  metadata: {
5979
6262
  ...m.metadata,
@@ -5982,7 +6265,7 @@ function useInternalThreadManager(config = {}) {
5982
6265
  }
5983
6266
  }));
5984
6267
  }, []);
5985
- const handleSwitchThread = React20.useCallback(
6268
+ const handleSwitchThread = React18.useCallback(
5986
6269
  async (threadId) => {
5987
6270
  isLoadingMessagesRef.current = true;
5988
6271
  const thread = await switchThread(threadId);
@@ -5994,6 +6277,8 @@ function useInternalThreadManager(config = {}) {
5994
6277
  createdAt: m.created_at ?? /* @__PURE__ */ new Date(),
5995
6278
  toolCalls: m.tool_calls,
5996
6279
  toolCallId: m.tool_call_id,
6280
+ parentId: m.parent_id,
6281
+ childrenIds: m.children_ids,
5997
6282
  attachments: m.metadata?.attachments
5998
6283
  }));
5999
6284
  lastSavedSnapshotRef.current = getMessageSnapshot(uiMessages);
@@ -6011,7 +6296,7 @@ function useInternalThreadManager(config = {}) {
6011
6296
  },
6012
6297
  [switchThread, setMessages, getMessageSnapshot, onThreadChange]
6013
6298
  );
6014
- const handleNewThread = React20.useCallback(async () => {
6299
+ const handleNewThread = React18.useCallback(async () => {
6015
6300
  isLoadingMessagesRef.current = true;
6016
6301
  clearCurrentThread();
6017
6302
  lastSavedSnapshotRef.current = "";
@@ -6022,7 +6307,7 @@ function useInternalThreadManager(config = {}) {
6022
6307
  isLoadingMessagesRef.current = false;
6023
6308
  });
6024
6309
  }, [clearCurrentThread, setMessages, onThreadChange]);
6025
- React20.useEffect(() => {
6310
+ React18.useEffect(() => {
6026
6311
  if (hasInitializedRef.current || !currentThread) {
6027
6312
  return;
6028
6313
  }
@@ -6036,6 +6321,8 @@ function useInternalThreadManager(config = {}) {
6036
6321
  createdAt: m.created_at ?? /* @__PURE__ */ new Date(),
6037
6322
  toolCalls: m.tool_calls,
6038
6323
  toolCallId: m.tool_call_id,
6324
+ parentId: m.parent_id,
6325
+ childrenIds: m.children_ids,
6039
6326
  attachments: m.metadata?.attachments,
6040
6327
  thinking: m.metadata?.thinking,
6041
6328
  // Preserve full metadata including citations, toolExecutions, etc.
@@ -6053,7 +6340,7 @@ function useInternalThreadManager(config = {}) {
6053
6340
  isLoadingMessagesRef.current = false;
6054
6341
  });
6055
6342
  }, [adapter, currentThread, setMessages, getMessageSnapshot, onThreadChange]);
6056
- React20.useEffect(() => {
6343
+ React18.useEffect(() => {
6057
6344
  if (isLoadingMessagesRef.current) {
6058
6345
  return;
6059
6346
  }
@@ -6067,7 +6354,10 @@ function useInternalThreadManager(config = {}) {
6067
6354
  if (currentSnapshot === lastSavedSnapshotRef.current) {
6068
6355
  return;
6069
6356
  }
6070
- const coreMessages = convertToCore(messages);
6357
+ const allUIMessages = getAllMessages();
6358
+ const coreMessages = convertToCore(
6359
+ allUIMessages.length > 0 ? allUIMessages : messages
6360
+ );
6071
6361
  if (!currentThreadId && !savingToThreadRef.current) {
6072
6362
  savingToThreadRef.current = "creating";
6073
6363
  createThread({ messages: coreMessages }).then((thread) => {
@@ -6092,6 +6382,7 @@ function useInternalThreadManager(config = {}) {
6092
6382
  refreshThreads,
6093
6383
  getMessageSnapshot,
6094
6384
  convertToCore,
6385
+ getAllMessages,
6095
6386
  onThreadChange
6096
6387
  ]);
6097
6388
  const isBusy = isLoading || status === "streaming" || status === "submitted";
@@ -6122,7 +6413,7 @@ function parsePersistenceConfig(persistence, onThreadChange) {
6122
6413
  };
6123
6414
  case "server":
6124
6415
  return {
6125
- adapter: chunkOQPRIB73_cjs.createServerAdapter({
6416
+ adapter: chunkI3SQUNTT_cjs.createServerAdapter({
6126
6417
  endpoint: persistence.endpoint,
6127
6418
  headers: persistence.headers
6128
6419
  }),
@@ -6171,8 +6462,11 @@ function CopilotChatBase(props) {
6171
6462
  toolExecutions: rawToolExecutions,
6172
6463
  approveToolExecution,
6173
6464
  rejectToolExecution,
6174
- registeredTools
6175
- } = chunkN6VZ7FOW_cjs.useCopilot();
6465
+ registeredTools,
6466
+ switchBranch,
6467
+ getBranchInfo,
6468
+ editMessage
6469
+ } = chunk76RE7AJE_cjs.useCopilot();
6176
6470
  const toolExecutions = rawToolExecutions.map(
6177
6471
  (exec) => ({
6178
6472
  id: exec.id,
@@ -6190,7 +6484,9 @@ function CopilotChatBase(props) {
6190
6484
  messages.filter((m) => m.role === "tool" && m.toolCallId).forEach((m) => {
6191
6485
  toolResultsMap.set(m.toolCallId, m.content ?? "");
6192
6486
  });
6193
- const visibleMessages = messages.filter((m) => m.role !== "tool").map((m) => {
6487
+ const visibleMessages = messages.filter(
6488
+ (m) => m.role !== "tool" && (m.role !== "system" || m.metadata?.type === "compaction-marker")
6489
+ ).map((m) => {
6194
6490
  let messageToolExecutions;
6195
6491
  if (m.role === "assistant" && m.toolCalls && m.toolCalls.length > 0) {
6196
6492
  const toolCallIds = new Set(
@@ -6286,24 +6582,29 @@ function CopilotChatBase(props) {
6286
6582
  });
6287
6583
  const suggestions = visibleMessages.length === 0 && chatProps.suggestions?.length ? chatProps.suggestions : [];
6288
6584
  const lastMessage = messages[messages.length - 1];
6289
- const isInToolFlow = lastMessage?.role === "assistant" && lastMessage.toolCalls?.length;
6585
+ const lastAssistantWithTools = [...messages].reverse().find(
6586
+ (m) => m.role === "assistant" && m.toolCalls?.length
6587
+ );
6588
+ const isInToolFlow = lastMessage?.role === "tool" || lastMessage?.role === "assistant" && lastMessage.toolCalls?.length;
6290
6589
  let isProcessingToolResults = false;
6291
6590
  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;
6591
+ if (lastMessage?.role === "tool") {
6592
+ isProcessingToolResults = true;
6593
+ } else if (lastAssistantWithTools) {
6594
+ const currentToolCallIds = new Set(
6595
+ lastAssistantWithTools.toolCalls?.map((tc) => tc.id) || []
6596
+ );
6597
+ const currentExecutions = toolExecutions.filter(
6598
+ (exec) => currentToolCallIds.has(exec.id)
6599
+ );
6600
+ const hasCompletedTools = currentExecutions.some(
6601
+ (exec) => exec.status === "completed" || exec.status === "error" || exec.status === "failed"
6602
+ );
6603
+ const hasExecutingTools = currentExecutions.some(
6604
+ (exec) => exec.status === "executing" || exec.status === "pending"
6605
+ );
6606
+ isProcessingToolResults = hasCompletedTools && !hasExecutingTools;
6607
+ }
6307
6608
  }
6308
6609
  const chatClassNames = classNames ? {
6309
6610
  root: classNames.root,
@@ -6317,7 +6618,7 @@ function CopilotChatBase(props) {
6317
6618
  footer: classNames.footer
6318
6619
  } : void 0;
6319
6620
  const { threadManager, handleSwitchThread, handleNewThread, isBusy } = threadManagerResult;
6320
- const handleDeleteThread = React20__namespace.default.useCallback(
6621
+ const handleDeleteThread = React18__namespace.default.useCallback(
6321
6622
  (threadId) => {
6322
6623
  const isCurrentThread = threadManager.currentThreadId === threadId;
6323
6624
  threadManager.deleteThread(threadId);
@@ -6374,6 +6675,9 @@ function CopilotChatBase(props) {
6374
6675
  currentThreadId: threadManager.currentThreadId,
6375
6676
  onSwitchThread: isPersistenceEnabled ? handleSwitchThread : void 0,
6376
6677
  isThreadBusy: isBusy,
6678
+ getBranchInfo,
6679
+ onSwitchBranch: switchBranch,
6680
+ onEditMessage: editMessage,
6377
6681
  children
6378
6682
  }
6379
6683
  );
@@ -6444,6 +6748,7 @@ function PoweredBy({ className, showLogo = true }) {
6444
6748
 
6445
6749
  exports.AlertTriangleIcon = AlertTriangleIcon;
6446
6750
  exports.BotIcon = BotIcon;
6751
+ exports.BranchNavigator = BranchNavigator;
6447
6752
  exports.Button = Button;
6448
6753
  exports.CapabilityBadge = CapabilityBadge;
6449
6754
  exports.CapabilityList = CapabilityList;