@yourgpt/copilot-sdk 2.1.3 → 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-DMBFN7KO.js → chunk-6BMQZIS3.js} +3105 -355
  10. package/dist/chunk-6BMQZIS3.js.map +1 -0
  11. package/dist/{chunk-R6LKHKAI.cjs → chunk-76RE7AJE.cjs} +3277 -509
  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-WQSK3Z4K.cjs → chunk-I3SQUNTT.cjs} +81 -31
  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-VFV5FVVI.js → chunk-UXJ6LIZB.js} +61 -13
  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 +21 -10
  31. package/dist/core/index.d.ts +21 -10
  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 +703 -90
  39. package/dist/react/index.d.ts +703 -90
  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-DMBFN7KO.js.map +0 -1
  99. package/dist/chunk-POZNNKNJ.cjs.map +0 -1
  100. package/dist/chunk-QLH6TSCC.js.map +0 -1
  101. package/dist/chunk-R6LKHKAI.cjs.map +0 -1
  102. package/dist/chunk-VFV5FVVI.js.map +0 -1
  103. package/dist/chunk-WQSK3Z4K.cjs.map +0 -1
package/dist/ui/index.js CHANGED
@@ -1,10 +1,12 @@
1
- import { useCopilot, useThreadManager } from '../chunk-DMBFN7KO.js';
2
- import { createServerAdapter } from '../chunk-VFV5FVVI.js';
1
+ import { useCopilot, useThreadManager } from '../chunk-6BMQZIS3.js';
2
+ import { createServerAdapter } from '../chunk-UXJ6LIZB.js';
3
3
  import { DEFAULT_MCP_UI_SANDBOX, parseMCPUIMessage } from '../chunk-G4SF2PNQ.js';
4
4
  import '../chunk-EWVQWTNV.js';
5
- import '../chunk-LZMBBGWH.js';
6
- import '../chunk-QLH6TSCC.js';
7
- import '../chunk-XGITAEXU.js';
5
+ import '../chunk-VNLLW3ZI.js';
6
+ import '../chunk-ENFWM3EY.js';
7
+ import '../chunk-4QXY2PBG.js';
8
+ import '../chunk-LLM7AHMO.js';
9
+ import '../chunk-RQ74USYU.js';
8
10
  import '../chunk-7W7QLZNC.js';
9
11
  import '../chunk-CEOMTQTP.js';
10
12
  import '../chunk-PPFHA6IL.js';
@@ -12,13 +14,12 @@ import '../chunk-DABZYCVX.js';
12
14
  import '../chunk-MNDGIW47.js';
13
15
  import '../chunk-VD74IPKB.js';
14
16
  import '../chunk-53UGJNHN.js';
15
- import '../chunk-RQ74USYU.js';
16
17
  import '../chunk-DGUM43GV.js';
17
18
  import { clsx } from 'clsx';
18
19
  import { twMerge } from 'tailwind-merge';
19
20
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
20
- import * as React20 from 'react';
21
- import React20__default, { memo, createContext, useState, useRef, useId, useCallback, useLayoutEffect, useContext, useEffect } from 'react';
21
+ import * as React18 from 'react';
22
+ import React18__default, { memo, createContext, useState, useRef, useId, useCallback, useLayoutEffect, useContext, useEffect } from 'react';
22
23
  import { Streamdown } from 'streamdown';
23
24
  import { code } from '@streamdown/code';
24
25
  import { Slot } from '@radix-ui/react-slot';
@@ -383,7 +384,7 @@ var buttonVariants = cva(
383
384
  }
384
385
  }
385
386
  );
386
- var Button = React20.forwardRef(
387
+ var Button = React18.forwardRef(
387
388
  ({ className, variant, size, asChild = false, ...props }, ref) => {
388
389
  const Comp = asChild ? Slot : "button";
389
390
  return /* @__PURE__ */ jsx(
@@ -624,7 +625,7 @@ function TooltipTrigger({
624
625
  disabled,
625
626
  ...props
626
627
  }) {
627
- if (asChild && React20__default.isValidElement(children)) {
628
+ if (asChild && React18__default.isValidElement(children)) {
628
629
  return /* @__PURE__ */ jsx(Tooltip$1.Trigger, { disabled, render: children, ...props });
629
630
  }
630
631
  return /* @__PURE__ */ jsx(Tooltip$1.Trigger, { disabled, ...props, children });
@@ -653,7 +654,7 @@ function TooltipContent({
653
654
  }
654
655
  ) }) });
655
656
  }
656
- var Avatar = React20.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
657
+ var Avatar = React18.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
657
658
  AvatarPrimitive.Root,
658
659
  {
659
660
  ref,
@@ -665,7 +666,7 @@ var Avatar = React20.forwardRef(({ className, ...props }, ref) => /* @__PURE__ *
665
666
  }
666
667
  ));
667
668
  Avatar.displayName = AvatarPrimitive.Root.displayName;
668
- var AvatarImage = React20.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
669
+ var AvatarImage = React18.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
669
670
  AvatarPrimitive.Image,
670
671
  {
671
672
  ref,
@@ -674,7 +675,7 @@ var AvatarImage = React20.forwardRef(({ className, ...props }, ref) => /* @__PUR
674
675
  }
675
676
  ));
676
677
  AvatarImage.displayName = AvatarPrimitive.Image.displayName;
677
- var AvatarFallback = React20.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
678
+ var AvatarFallback = React18.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
678
679
  AvatarPrimitive.Fallback,
679
680
  {
680
681
  ref,
@@ -734,7 +735,7 @@ var MessageContent = ({
734
735
  );
735
736
  return markdown ? /* @__PURE__ */ jsx(Markdown, { className: classNames, ...props, children }) : /* @__PURE__ */ jsx("div", { className: classNames, ...props, children });
736
737
  };
737
- var Textarea = React20.forwardRef(({ className, ...props }, ref) => {
738
+ var Textarea = React18.forwardRef(({ className, ...props }, ref) => {
738
739
  return /* @__PURE__ */ jsx(
739
740
  "textarea",
740
741
  {
@@ -898,7 +899,7 @@ function PromptInputAction({
898
899
  }
899
900
  var HoverCard = HoverCardPrimitive.Root;
900
901
  var HoverCardTrigger = HoverCardPrimitive.Trigger;
901
- var HoverCardContent = React20.forwardRef(({ className, align = "center", sideOffset = 4, ...props }, ref) => /* @__PURE__ */ jsx(
902
+ var HoverCardContent = React18.forwardRef(({ className, align = "center", sideOffset = 4, ...props }, ref) => /* @__PURE__ */ jsx(
902
903
  HoverCardPrimitive.Content,
903
904
  {
904
905
  ref,
@@ -1441,7 +1442,7 @@ function SourcesCollapsible({
1441
1442
  defaultExpanded = false,
1442
1443
  className
1443
1444
  }) {
1444
- const [expanded, setExpanded] = React20.useState(defaultExpanded);
1445
+ const [expanded, setExpanded] = React18.useState(defaultExpanded);
1445
1446
  if (citations.length === 0) return null;
1446
1447
  return /* @__PURE__ */ jsxs("div", { className: cn("border rounded-lg", className), children: [
1447
1448
  /* @__PURE__ */ jsxs(
@@ -1507,7 +1508,7 @@ function SourcesList({
1507
1508
  if (compact) {
1508
1509
  return /* @__PURE__ */ jsxs("div", { className: cn("text-xs text-muted-foreground", className), children: [
1509
1510
  /* @__PURE__ */ jsx("span", { className: "font-medium", children: "Sources: " }),
1510
- citations.map((c, i) => /* @__PURE__ */ jsxs(React20.Fragment, { children: [
1511
+ citations.map((c, i) => /* @__PURE__ */ jsxs(React18.Fragment, { children: [
1511
1512
  /* @__PURE__ */ jsxs(
1512
1513
  "a",
1513
1514
  {
@@ -1585,11 +1586,11 @@ function resultsToCitations(results) {
1585
1586
  domain: result.domain || getDomain3(result.url)
1586
1587
  }));
1587
1588
  }
1588
- var ReasoningContext = React20.createContext(
1589
+ var ReasoningContext = React18.createContext(
1589
1590
  null
1590
1591
  );
1591
1592
  function useReasoningContext() {
1592
- const context = React20.useContext(ReasoningContext);
1593
+ const context = React18.useContext(ReasoningContext);
1593
1594
  if (!context) {
1594
1595
  throw new Error(
1595
1596
  "Reasoning components must be used within a Reasoning provider"
@@ -1605,11 +1606,11 @@ function Reasoning({
1605
1606
  defaultOpen = false,
1606
1607
  className
1607
1608
  }) {
1608
- const [uncontrolledOpen, setUncontrolledOpen] = React20.useState(defaultOpen);
1609
- const prevStreamingRef = React20.useRef(isStreaming);
1609
+ const [uncontrolledOpen, setUncontrolledOpen] = React18.useState(defaultOpen);
1610
+ const prevStreamingRef = React18.useRef(isStreaming);
1610
1611
  const isControlled = controlledOpen !== void 0;
1611
1612
  const isOpen = isControlled ? controlledOpen : uncontrolledOpen;
1612
- const setIsOpen = React20.useCallback(
1613
+ const setIsOpen = React18.useCallback(
1613
1614
  (open) => {
1614
1615
  if (onOpenChange) {
1615
1616
  onOpenChange(open);
@@ -1620,7 +1621,7 @@ function Reasoning({
1620
1621
  },
1621
1622
  [isControlled, onOpenChange]
1622
1623
  );
1623
- React20.useEffect(() => {
1624
+ React18.useEffect(() => {
1624
1625
  if (isStreaming && !prevStreamingRef.current) {
1625
1626
  setIsOpen(true);
1626
1627
  } else if (!isStreaming && prevStreamingRef.current) {
@@ -1676,9 +1677,9 @@ function ReasoningContent({
1676
1677
  className
1677
1678
  }) {
1678
1679
  const { isOpen } = useReasoningContext();
1679
- const contentRef = React20.useRef(null);
1680
- const [height, setHeight] = React20.useState(0);
1681
- React20.useEffect(() => {
1680
+ const contentRef = React18.useRef(null);
1681
+ const [height, setHeight] = React18.useState(0);
1682
+ React18.useEffect(() => {
1682
1683
  if (contentRef.current) {
1683
1684
  const resizeObserver = new ResizeObserver((entries) => {
1684
1685
  for (const entry of entries) {
@@ -1727,11 +1728,11 @@ function SimpleReasoning({
1727
1728
  /* @__PURE__ */ jsx(ReasoningContent, { markdown, children: content })
1728
1729
  ] });
1729
1730
  }
1730
- var CopilotUIContext = React20.createContext(
1731
+ var CopilotUIContext = React18.createContext(
1731
1732
  null
1732
1733
  );
1733
1734
  function useCopilotUI() {
1734
- const context = React20.useContext(CopilotUIContext);
1735
+ const context = React18.useContext(CopilotUIContext);
1735
1736
  if (!context) {
1736
1737
  return {
1737
1738
  debug: false,
@@ -1746,7 +1747,7 @@ function CopilotUIProvider({
1746
1747
  debug = false,
1747
1748
  defaultDebugExpanded = false
1748
1749
  }) {
1749
- const value = React20.useMemo(
1750
+ const value = React18.useMemo(
1750
1751
  () => ({
1751
1752
  debug,
1752
1753
  defaultDebugExpanded,
@@ -1889,7 +1890,7 @@ function ToolStep({
1889
1890
  }) {
1890
1891
  const { isDebug, defaultDebugExpanded } = useCopilotUI();
1891
1892
  const debug = debugProp ?? isDebug;
1892
- const [expanded, setExpanded] = React20.useState(
1893
+ const [expanded, setExpanded] = React18.useState(
1893
1894
  defaultExpanded ?? defaultDebugExpanded ?? false
1894
1895
  );
1895
1896
  const displayTitle = getDisplayTitle(step);
@@ -2370,9 +2371,9 @@ function ArrowUpRightIcon({ className }) {
2370
2371
  }
2371
2372
  );
2372
2373
  }
2373
- var ConfirmationContext = React20.createContext(null);
2374
+ var ConfirmationContext = React18.createContext(null);
2374
2375
  function useConfirmationContext() {
2375
- const context = React20.useContext(ConfirmationContext);
2376
+ const context = React18.useContext(ConfirmationContext);
2376
2377
  if (!context) {
2377
2378
  throw new Error(
2378
2379
  "Confirmation components must be used within a Confirmation provider"
@@ -2544,8 +2545,8 @@ function PermissionConfirmation({
2544
2545
  permissionOptions = DEFAULT_PERMISSION_OPTIONS,
2545
2546
  className
2546
2547
  }) {
2547
- const [selectedPermission, setSelectedPermission] = React20.useState("ask");
2548
- const [showOptions, setShowOptions] = React20.useState(false);
2548
+ const [selectedPermission, setSelectedPermission] = React18.useState("ask");
2549
+ const [showOptions, setShowOptions] = React18.useState(false);
2549
2550
  const handleApprove = () => {
2550
2551
  onApprove?.(selectedPermission);
2551
2552
  };
@@ -2675,7 +2676,7 @@ function CompactPermissionConfirmation({
2675
2676
  onReject,
2676
2677
  className
2677
2678
  }) {
2678
- const [rememberChoice, setRememberChoice] = React20.useState(false);
2679
+ const [rememberChoice, setRememberChoice] = React18.useState(false);
2679
2680
  const handleApprove = () => {
2680
2681
  onApprove?.(rememberChoice ? "allow_always" : "ask");
2681
2682
  };
@@ -2787,6 +2788,86 @@ function FollowUpQuestions({
2787
2788
  index
2788
2789
  )) });
2789
2790
  }
2791
+ function BranchNavigator({
2792
+ siblingIndex,
2793
+ totalSiblings,
2794
+ hasPrevious,
2795
+ hasNext,
2796
+ onPrevious,
2797
+ onNext,
2798
+ className
2799
+ }) {
2800
+ return /* @__PURE__ */ jsxs(
2801
+ "div",
2802
+ {
2803
+ className: cn(
2804
+ "csdk-branch-navigator flex items-center gap-1 text-xs text-muted-foreground select-none",
2805
+ className
2806
+ ),
2807
+ children: [
2808
+ /* @__PURE__ */ jsx(
2809
+ "button",
2810
+ {
2811
+ type: "button",
2812
+ onClick: onPrevious,
2813
+ disabled: !hasPrevious,
2814
+ "aria-label": "Previous version",
2815
+ className: cn(
2816
+ "p-0.5 rounded transition-colors",
2817
+ hasPrevious ? "hover:text-foreground hover:bg-muted cursor-pointer" : "opacity-30 cursor-default"
2818
+ ),
2819
+ children: /* @__PURE__ */ jsx(
2820
+ "svg",
2821
+ {
2822
+ width: "14",
2823
+ height: "14",
2824
+ viewBox: "0 0 24 24",
2825
+ fill: "none",
2826
+ stroke: "currentColor",
2827
+ strokeWidth: 2.5,
2828
+ strokeLinecap: "round",
2829
+ strokeLinejoin: "round",
2830
+ children: /* @__PURE__ */ jsx("path", { d: "M15 18l-6-6 6-6" })
2831
+ }
2832
+ )
2833
+ }
2834
+ ),
2835
+ /* @__PURE__ */ jsxs("span", { className: "tabular-nums leading-none", children: [
2836
+ siblingIndex + 1,
2837
+ "\u2009/\u2009",
2838
+ totalSiblings
2839
+ ] }),
2840
+ /* @__PURE__ */ jsx(
2841
+ "button",
2842
+ {
2843
+ type: "button",
2844
+ onClick: onNext,
2845
+ disabled: !hasNext,
2846
+ "aria-label": "Next version",
2847
+ className: cn(
2848
+ "p-0.5 rounded transition-colors",
2849
+ hasNext ? "hover:text-foreground hover:bg-muted cursor-pointer" : "opacity-30 cursor-default"
2850
+ ),
2851
+ children: /* @__PURE__ */ jsx(
2852
+ "svg",
2853
+ {
2854
+ width: "14",
2855
+ height: "14",
2856
+ viewBox: "0 0 24 24",
2857
+ fill: "none",
2858
+ stroke: "currentColor",
2859
+ strokeWidth: 2.5,
2860
+ strokeLinecap: "round",
2861
+ strokeLinejoin: "round",
2862
+ children: /* @__PURE__ */ jsx("path", { d: "M9 18l6-6-6-6" })
2863
+ }
2864
+ )
2865
+ }
2866
+ )
2867
+ ]
2868
+ }
2869
+ );
2870
+ }
2790
2871
  function DevLogger({
2791
2872
  state,
2792
2873
  position = "bottom-right",
@@ -3218,9 +3299,9 @@ function ModelSelector({
3218
3299
  showCapabilities = true,
3219
3300
  className
3220
3301
  }) {
3221
- const [isOpen, setIsOpen] = React20.useState(false);
3222
- const containerRef = React20.useRef(null);
3223
- React20.useEffect(() => {
3302
+ const [isOpen, setIsOpen] = React18.useState(false);
3303
+ const containerRef = React18.useRef(null);
3304
+ React18.useEffect(() => {
3224
3305
  function handleClickOutside(event) {
3225
3306
  if (containerRef.current && !containerRef.current.contains(event.target)) {
3226
3307
  setIsOpen(false);
@@ -3229,7 +3310,7 @@ function ModelSelector({
3229
3310
  document.addEventListener("mousedown", handleClickOutside);
3230
3311
  return () => document.removeEventListener("mousedown", handleClickOutside);
3231
3312
  }, []);
3232
- const selectedModel = React20.useMemo(() => {
3313
+ const selectedModel = React18.useMemo(() => {
3233
3314
  if (!value) return null;
3234
3315
  if (providers) {
3235
3316
  for (const provider of providers) {
@@ -3455,7 +3536,7 @@ function PopoverTrigger({
3455
3536
  className,
3456
3537
  ...props
3457
3538
  }) {
3458
- if (asChild && React20.isValidElement(children)) {
3539
+ if (asChild && React18.isValidElement(children)) {
3459
3540
  return /* @__PURE__ */ jsx(Popover$1.Trigger, { render: children, className, ...props });
3460
3541
  }
3461
3542
  return /* @__PURE__ */ jsx(Popover$1.Trigger, { className, ...props, children });
@@ -3590,8 +3671,8 @@ function ThreadPicker({
3590
3671
  itemClassName,
3591
3672
  newButtonClassName
3592
3673
  }) {
3593
- const [isOpen, setIsOpen] = React20.useState(false);
3594
- const selectedThread = React20.useMemo(() => {
3674
+ const [isOpen, setIsOpen] = React18.useState(false);
3675
+ const selectedThread = React18.useMemo(() => {
3595
3676
  if (!value) return null;
3596
3677
  return threads.find((t) => t.id === value) ?? null;
3597
3678
  }, [value, threads]);
@@ -3797,7 +3878,7 @@ function ThreadCard({
3797
3878
  showDelete = true,
3798
3879
  className
3799
3880
  }) {
3800
- const [isHovered, setIsHovered] = React20.useState(false);
3881
+ const [isHovered, setIsHovered] = React18.useState(false);
3801
3882
  const handleDelete = (e) => {
3802
3883
  e.stopPropagation();
3803
3884
  onDelete?.();
@@ -4038,10 +4119,10 @@ function MCPUIFrame({
4038
4119
  showLoading = true,
4039
4120
  testId
4040
4121
  }) {
4041
- const iframeRef = React20.useRef(null);
4042
- const [isLoading, setIsLoading] = React20.useState(true);
4043
- const [error, setError] = React20.useState(null);
4044
- React20.useEffect(() => {
4122
+ const iframeRef = React18.useRef(null);
4123
+ const [isLoading, setIsLoading] = React18.useState(true);
4124
+ const [error, setError] = React18.useState(null);
4125
+ React18.useEffect(() => {
4045
4126
  const handleMessage = (event) => {
4046
4127
  if (event.source !== iframeRef.current?.contentWindow) {
4047
4128
  return;
@@ -4054,17 +4135,17 @@ function MCPUIFrame({
4054
4135
  window.addEventListener("message", handleMessage);
4055
4136
  return () => window.removeEventListener("message", handleMessage);
4056
4137
  }, [onIntent]);
4057
- const handleLoad = React20.useCallback(() => {
4138
+ const handleLoad = React18.useCallback(() => {
4058
4139
  setIsLoading(false);
4059
4140
  onLoad?.();
4060
4141
  }, [onLoad]);
4061
- const handleError = React20.useCallback(() => {
4142
+ const handleError = React18.useCallback(() => {
4062
4143
  const err = new Error("Failed to load MCP UI content");
4063
4144
  setError(err);
4064
4145
  setIsLoading(false);
4065
4146
  onError?.(err);
4066
4147
  }, [onError]);
4067
- const { srcDoc, src } = React20.useMemo(() => {
4148
+ const { srcDoc, src } = React18.useMemo(() => {
4068
4149
  if (resource.mimeType === "text/html") {
4069
4150
  let content = resource.content || "";
4070
4151
  if (resource.blob && !resource.content) {
@@ -4229,28 +4310,92 @@ function DefaultMessage({
4229
4310
  registeredTools,
4230
4311
  toolRenderers,
4231
4312
  mcpToolRenderer,
4313
+ fallbackToolRenderer,
4232
4314
  onApproveToolExecution,
4233
4315
  onRejectToolExecution,
4234
4316
  showFollowUps = true,
4235
4317
  onFollowUpClick,
4236
4318
  followUpClassName,
4237
4319
  followUpButtonClassName,
4238
- citations = { enabled: true }
4320
+ citations = { enabled: true },
4321
+ branchInfo,
4322
+ onSwitchBranch,
4323
+ onEditMessage
4239
4324
  }) {
4240
4325
  const isUser = message.role === "user";
4326
+ const isCompactionMarker = message.role === "system" && message.metadata?.type === "compaction-marker";
4241
4327
  const isStreaming = isLastMessage && isLoading;
4242
- const { cleanContent: contentWithoutFollowUps, followUps } = React20.useMemo(() => {
4328
+ const [isEditing, setIsEditing] = React18.useState(false);
4329
+ const [editValue, setEditValue] = React18.useState(message.content ?? "");
4330
+ const editRef = React18.useRef(null);
4331
+ const startEdit = React18.useCallback(() => {
4332
+ setEditValue(message.content ?? "");
4333
+ setIsEditing(true);
4334
+ requestAnimationFrame(() => editRef.current?.focus());
4335
+ }, [message.content]);
4336
+ const cancelEdit = React18.useCallback(() => {
4337
+ setIsEditing(false);
4338
+ }, []);
4339
+ const submitEdit = React18.useCallback(() => {
4340
+ const trimmed = editValue.trim();
4341
+ if (!trimmed || !onEditMessage) return;
4342
+ onEditMessage(message.id, trimmed);
4343
+ setIsEditing(false);
4344
+ }, [editValue, message.id, onEditMessage]);
4345
+ const handleEditKeyDown = React18.useCallback(
4346
+ (e) => {
4347
+ if (e.key === "Enter" && !e.shiftKey) {
4348
+ e.preventDefault();
4349
+ submitEdit();
4350
+ }
4351
+ if (e.key === "Escape") {
4352
+ cancelEdit();
4353
+ }
4354
+ },
4355
+ [submitEdit, cancelEdit]
4356
+ );
4357
+ const showBranchNav = isUser && branchInfo && branchInfo.totalSiblings > 1 && onSwitchBranch;
4358
+ const showEditBtn = isUser && !!onEditMessage && !isLoading;
4359
+ if (isCompactionMarker) {
4360
+ const tokensSaved = message.metadata?.tokensSaved;
4361
+ return /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3 py-2 px-1 my-1", children: [
4362
+ /* @__PURE__ */ jsx("div", { className: "flex-1 h-px bg-border" }),
4363
+ /* @__PURE__ */ jsxs("span", { className: "text-[11px] text-muted-foreground whitespace-nowrap flex items-center gap-1.5", children: [
4364
+ /* @__PURE__ */ jsx(
4365
+ "svg",
4366
+ {
4367
+ className: "size-3 opacity-60",
4368
+ viewBox: "0 0 24 24",
4369
+ fill: "none",
4370
+ stroke: "currentColor",
4371
+ strokeWidth: 2,
4372
+ children: /* @__PURE__ */ jsx(
4373
+ "path",
4374
+ {
4375
+ strokeLinecap: "round",
4376
+ strokeLinejoin: "round",
4377
+ d: "M19 9l-7 7-7-7"
4378
+ }
4379
+ )
4380
+ }
4381
+ ),
4382
+ tokensSaved ? `Earlier conversation summarized \xB7 ~${tokensSaved.toLocaleString()} tokens saved` : "Earlier conversation summarized"
4383
+ ] }),
4384
+ /* @__PURE__ */ jsx("div", { className: "flex-1 h-px bg-border" })
4385
+ ] });
4386
+ }
4387
+ const { cleanContent: contentWithoutFollowUps, followUps } = React18.useMemo(() => {
4243
4388
  if (isUser || !message.content) {
4244
4389
  return { cleanContent: message.content, followUps: [] };
4245
4390
  }
4246
4391
  return parseFollowUps(message.content);
4247
4392
  }, [message.content, isUser]);
4248
- const cleanContent = React20.useMemo(() => {
4393
+ const cleanContent = React18.useMemo(() => {
4249
4394
  if (!contentWithoutFollowUps) return contentWithoutFollowUps;
4250
4395
  return contentWithoutFollowUps.replace(/\n*\*{0,2}Sources:?\*{0,2}\s*(\[.+?\]\(.+?\)[,\s]*)+$/gi, "").trim();
4251
4396
  }, [contentWithoutFollowUps]);
4252
4397
  const shouldShowFollowUps = showFollowUps && !isUser && isLastMessage && !isLoading && followUps.length > 0 && onFollowUpClick;
4253
- const sources = React20.useMemo(() => {
4398
+ const sources = React18.useMemo(() => {
4254
4399
  if (isUser || !citations.enabled) return [];
4255
4400
  const extractedSources = [];
4256
4401
  const addSource = (url, title, description) => {
@@ -4307,32 +4452,118 @@ function DefaultMessage({
4307
4452
  return /* @__PURE__ */ jsxs(
4308
4453
  Message,
4309
4454
  {
4310
- className: cn(
4311
- "flex gap-2",
4312
- showUserAvatar ? "justify-end" : "justify-end"
4313
- ),
4455
+ className: cn("flex gap-2 group/user-msg justify-end"),
4314
4456
  children: [
4315
- /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-end max-w-[80%] min-w-0", children: [
4316
- message.content && /* @__PURE__ */ jsx(
4317
- MessageContent,
4457
+ /* @__PURE__ */ jsx("div", { className: "flex flex-col items-end max-w-[80%] min-w-0", children: isEditing ? /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1.5 w-full min-w-[200px]", children: [
4458
+ /* @__PURE__ */ jsx(
4459
+ "textarea",
4318
4460
  {
4461
+ ref: editRef,
4462
+ value: editValue,
4463
+ onChange: (e) => setEditValue(e.target.value),
4464
+ onKeyDown: handleEditKeyDown,
4465
+ rows: Math.max(2, (editValue.match(/\n/g) || []).length + 1),
4319
4466
  className: cn(
4320
- "csdk-message-user rounded-lg px-4 py-2 bg-primary text-primary-foreground",
4467
+ "csdk-edit-textarea w-full rounded-lg px-3 py-2 text-sm resize-none",
4468
+ "bg-primary text-primary-foreground placeholder:text-primary-foreground/50",
4469
+ "focus:outline-none focus:ring-2 focus:ring-primary-foreground/30",
4321
4470
  userMessageClassName
4322
- ),
4323
- markdown: true,
4324
- size,
4325
- children: message.content
4471
+ )
4326
4472
  }
4327
4473
  ),
4328
- hasAttachments && /* @__PURE__ */ jsx("div", { className: "mt-2 flex flex-wrap gap-2 justify-end", children: message.attachments.map((attachment, index) => /* @__PURE__ */ jsx(AttachmentPreview, { attachment }, index)) })
4329
- ] }),
4474
+ /* @__PURE__ */ jsxs("div", { className: "flex gap-1.5 justify-end", children: [
4475
+ /* @__PURE__ */ jsx(
4476
+ "button",
4477
+ {
4478
+ type: "button",
4479
+ onClick: cancelEdit,
4480
+ className: "csdk-edit-cancel px-3 py-1 text-xs rounded-md bg-muted text-muted-foreground hover:bg-muted/80 transition-colors",
4481
+ children: "Cancel"
4482
+ }
4483
+ ),
4484
+ /* @__PURE__ */ jsx(
4485
+ "button",
4486
+ {
4487
+ type: "button",
4488
+ onClick: submitEdit,
4489
+ disabled: !editValue.trim(),
4490
+ 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",
4491
+ children: "Send"
4492
+ }
4493
+ )
4494
+ ] })
4495
+ ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
4496
+ message.content && /* @__PURE__ */ jsxs("div", { className: "relative", children: [
4497
+ /* @__PURE__ */ jsx(
4498
+ MessageContent,
4499
+ {
4500
+ className: cn(
4501
+ "csdk-message-user rounded-lg px-4 py-2 bg-primary text-primary-foreground",
4502
+ userMessageClassName
4503
+ ),
4504
+ markdown: true,
4505
+ size,
4506
+ children: message.content
4507
+ }
4508
+ ),
4509
+ showEditBtn && /* @__PURE__ */ jsx(
4510
+ "button",
4511
+ {
4512
+ type: "button",
4513
+ onClick: startEdit,
4514
+ "aria-label": "Edit message",
4515
+ className: cn(
4516
+ "csdk-edit-btn absolute -left-7 top-1/2 -translate-y-1/2",
4517
+ "size-6 flex items-center justify-center rounded-full",
4518
+ "text-muted-foreground bg-background border border-border shadow-sm",
4519
+ "opacity-0 group-hover/user-msg:opacity-100 transition-opacity",
4520
+ "hover:text-foreground hover:bg-muted"
4521
+ ),
4522
+ children: /* @__PURE__ */ jsxs(
4523
+ "svg",
4524
+ {
4525
+ width: "12",
4526
+ height: "12",
4527
+ viewBox: "0 0 24 24",
4528
+ fill: "none",
4529
+ stroke: "currentColor",
4530
+ strokeWidth: 2,
4531
+ strokeLinecap: "round",
4532
+ strokeLinejoin: "round",
4533
+ children: [
4534
+ /* @__PURE__ */ jsx("path", { d: "M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7" }),
4535
+ /* @__PURE__ */ jsx("path", { d: "M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z" })
4536
+ ]
4537
+ }
4538
+ )
4539
+ }
4540
+ )
4541
+ ] }),
4542
+ hasAttachments && /* @__PURE__ */ jsx("div", { className: "mt-2 flex flex-wrap gap-2 justify-end", children: message.attachments.map((attachment, index) => /* @__PURE__ */ jsx(AttachmentPreview, { attachment }, index)) }),
4543
+ showBranchNav && /* @__PURE__ */ jsx(
4544
+ BranchNavigator,
4545
+ {
4546
+ siblingIndex: branchInfo.siblingIndex,
4547
+ totalSiblings: branchInfo.totalSiblings,
4548
+ hasPrevious: branchInfo.hasPrevious,
4549
+ hasNext: branchInfo.hasNext,
4550
+ onPrevious: () => onSwitchBranch(
4551
+ branchInfo.siblingIds[branchInfo.siblingIndex - 1]
4552
+ ),
4553
+ onNext: () => onSwitchBranch(
4554
+ branchInfo.siblingIds[branchInfo.siblingIndex + 1]
4555
+ ),
4556
+ className: "mt-1"
4557
+ }
4558
+ )
4559
+ ] }) }),
4330
4560
  showUserAvatar && /* @__PURE__ */ jsx(
4331
4561
  MessageAvatar,
4332
4562
  {
4333
4563
  src: userAvatar.src,
4334
4564
  alt: "User",
4335
4565
  fallback: userAvatar.fallback,
4566
+ className: userAvatar.className,
4336
4567
  children: userAvatar.component
4337
4568
  }
4338
4569
  )
@@ -4356,6 +4587,7 @@ function DefaultMessage({
4356
4587
  const toolDef = registeredTools?.find((t) => t.name === toolName);
4357
4588
  if (mcpToolRenderer && (execSource === "mcp" || toolDef?.source === "mcp"))
4358
4589
  return true;
4590
+ if (fallbackToolRenderer) return true;
4359
4591
  if (toolDef?.render) return true;
4360
4592
  return false;
4361
4593
  };
@@ -4382,7 +4614,7 @@ function DefaultMessage({
4382
4614
  alt: "Assistant",
4383
4615
  fallback: assistantAvatar.fallback,
4384
4616
  fallbackIcon: !assistantAvatar.src && !assistantAvatar.fallback && !assistantAvatar.component ? /* @__PURE__ */ jsx(copilot_sdk_logo_default, { className: "size-5" }) : void 0,
4385
- className: "bg-muted",
4617
+ className: cn("bg-muted", assistantAvatar.className),
4386
4618
  children: assistantAvatar.component
4387
4619
  }
4388
4620
  ),
@@ -4395,10 +4627,7 @@ function DefaultMessage({
4395
4627
  className: "mb-2"
4396
4628
  }
4397
4629
  ),
4398
- isLastMessage && isProcessing ? /* @__PURE__ */ jsxs("div", { className: "rounded-lg bg-muted px-4 py-2 flex items-center gap-2", children: [
4399
- /* @__PURE__ */ jsx(Loader, { variant: "dots", size: "sm" }),
4400
- /* @__PURE__ */ jsx("span", { className: "text-sm text-muted-foreground", children: "Continuing..." })
4401
- ] }) : (
4630
+ isLastMessage && isProcessing && !completedTools?.length && !pendingApprovalTools?.length ? /* @__PURE__ */ jsx("div", { className: "rounded-lg bg-muted px-4 py-2", children: /* @__PURE__ */ jsx(Loader, { variant: "dots", size: "sm" }) }) : (
4402
4631
  /* Show streaming loader when loading with no content and no tools */
4403
4632
  isLastMessage && isLoading && !cleanContent?.trim() && !toolsWithCustomRender?.length && !toolsWithoutCustomRender?.length && !pendingApprovalTools?.length ? /* @__PURE__ */ jsx("div", { className: "rounded-lg bg-muted px-4 py-2", children: /* @__PURE__ */ jsx(Loader, { variant: loaderVariant, size: "sm" }) }) : /* @__PURE__ */ jsxs(Fragment, { children: [
4404
4633
  cleanContent?.trim() && /* @__PURE__ */ jsx(
@@ -4454,6 +4683,24 @@ function DefaultMessage({
4454
4683
  exec.id
4455
4684
  );
4456
4685
  }
4686
+ if (fallbackToolRenderer) {
4687
+ const FallbackRenderer = fallbackToolRenderer;
4688
+ return /* @__PURE__ */ jsx(
4689
+ FallbackRenderer,
4690
+ {
4691
+ execution: {
4692
+ id: exec.id,
4693
+ name: exec.name,
4694
+ args: exec.args,
4695
+ status: exec.status,
4696
+ result: exec.result,
4697
+ error: exec.error,
4698
+ source: exec.source
4699
+ }
4700
+ },
4701
+ exec.id
4702
+ );
4703
+ }
4457
4704
  const toolDefForRender = toolDef ?? registeredTools?.find((t) => t.name === exec.name);
4458
4705
  if (toolDefForRender?.render) {
4459
4706
  let status = "pending";
@@ -4472,7 +4719,7 @@ function DefaultMessage({
4472
4719
  const output = toolDefForRender.render(
4473
4720
  renderProps
4474
4721
  );
4475
- return /* @__PURE__ */ jsx(React20.Fragment, { children: output }, exec.id);
4722
+ return /* @__PURE__ */ jsx(React18.Fragment, { children: output }, exec.id);
4476
4723
  }
4477
4724
  return null;
4478
4725
  }) }),
@@ -4498,6 +4745,7 @@ function DefaultMessage({
4498
4745
  `${exec.id}-ui`
4499
4746
  );
4500
4747
  }),
4748
+ isLastMessage && isProcessing && completedTools && completedTools.length > 0 && /* @__PURE__ */ jsx("div", { className: "mt-2 rounded-lg bg-muted px-4 py-2", children: /* @__PURE__ */ jsx(Loader, { variant: "dots", size: "sm" }) }),
4501
4749
  pendingApprovalTools && pendingApprovalTools.length > 0 && /* @__PURE__ */ jsx("div", { className: "mt-2 space-y-2", children: pendingApprovalTools.map((tool) => {
4502
4750
  const approvalCallbacks = {
4503
4751
  onApprove: (extraData) => onApproveToolExecution?.(tool.id, extraData),
@@ -4531,7 +4779,7 @@ function DefaultMessage({
4531
4779
  const output = toolDef.render(
4532
4780
  renderProps
4533
4781
  );
4534
- return /* @__PURE__ */ jsx(React20.Fragment, { children: output }, tool.id);
4782
+ return /* @__PURE__ */ jsx(React18.Fragment, { children: output }, tool.id);
4535
4783
  }
4536
4784
  return /* @__PURE__ */ jsx(
4537
4785
  PermissionConfirmation,
@@ -4580,7 +4828,7 @@ function DefaultMessage({
4580
4828
  ] });
4581
4829
  }
4582
4830
  function AttachmentPreview({ attachment }) {
4583
- const [expanded, setExpanded] = React20.useState(false);
4831
+ const [expanded, setExpanded] = React18.useState(false);
4584
4832
  if (attachment.type !== "image") {
4585
4833
  return /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 rounded-lg border bg-muted/50 px-3 py-2 text-sm", children: [
4586
4834
  /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: attachment.type }),
@@ -5038,10 +5286,10 @@ function ChatView({ children, className }) {
5038
5286
  ChatView.displayName = "ChatView";
5039
5287
  function chatViewHasOnlyLayoutChildren(chatViewElement) {
5040
5288
  if (!chatViewElement?.props?.children) return false;
5041
- const childArray = React20__default.Children.toArray(chatViewElement.props.children);
5289
+ const childArray = React18__default.Children.toArray(chatViewElement.props.children);
5042
5290
  if (childArray.length === 0) return false;
5043
5291
  return childArray.every(
5044
- (child) => React20__default.isValidElement(child) && (child.type === Header || child.type === Footer)
5292
+ (child) => React18__default.isValidElement(child) && (child.type === Header || child.type === Footer)
5045
5293
  );
5046
5294
  }
5047
5295
  function Header({ children, className }) {
@@ -5179,18 +5427,18 @@ function ThreadPickerCompound(props) {
5179
5427
  );
5180
5428
  }
5181
5429
  function hasCompoundChild(children, ...components) {
5182
- return React20__default.Children.toArray(children).some(
5183
- (child) => React20__default.isValidElement(child) && components.includes(child.type)
5430
+ return React18__default.Children.toArray(children).some(
5431
+ (child) => React18__default.isValidElement(child) && components.includes(child.type)
5184
5432
  );
5185
5433
  }
5186
5434
  function findCompoundChild(children, component) {
5187
- return React20__default.Children.toArray(children).find(
5188
- (child) => React20__default.isValidElement(child) && child.type === component
5435
+ return React18__default.Children.toArray(children).find(
5436
+ (child) => React18__default.isValidElement(child) && child.type === component
5189
5437
  );
5190
5438
  }
5191
5439
  function filterCompoundChildren(children, ...components) {
5192
- return React20__default.Children.toArray(children).filter(
5193
- (child) => React20__default.isValidElement(child) && components.includes(child.type)
5440
+ return React18__default.Children.toArray(children).filter(
5441
+ (child) => React18__default.isValidElement(child) && components.includes(child.type)
5194
5442
  );
5195
5443
  }
5196
5444
  var DEFAULT_MAX_FILE_SIZE2 = 5 * 1024 * 1024;
@@ -5265,6 +5513,7 @@ function ChatComponent({
5265
5513
  registeredTools,
5266
5514
  toolRenderers,
5267
5515
  mcpToolRenderer,
5516
+ fallbackToolRenderer,
5268
5517
  onApproveToolExecution,
5269
5518
  onRejectToolExecution,
5270
5519
  // Follow-up Questions
@@ -5277,6 +5526,8 @@ function ChatComponent({
5277
5526
  renderMessage,
5278
5527
  renderInput,
5279
5528
  renderHeader,
5529
+ // Avatar grouping
5530
+ groupConsecutiveMessages = false,
5280
5531
  // Styling
5281
5532
  className,
5282
5533
  classNames = {},
@@ -5285,7 +5536,11 @@ function ChatComponent({
5285
5536
  threads,
5286
5537
  currentThreadId,
5287
5538
  onSwitchThread,
5288
- isThreadBusy
5539
+ isThreadBusy,
5540
+ // Branching
5541
+ getBranchInfo,
5542
+ onSwitchBranch,
5543
+ onEditMessage
5289
5544
  }) {
5290
5545
  const userAvatar = { fallback: "U", ...userAvatarProp };
5291
5546
  const assistantAvatar = { fallback: "AI", ...assistantAvatarProp };
@@ -5460,7 +5715,7 @@ function ChatComponent({
5460
5715
  },
5461
5716
  [onSendMessage]
5462
5717
  );
5463
- const contextValue = React20__default.useMemo(
5718
+ const contextValue = React18__default.useMemo(
5464
5719
  () => ({
5465
5720
  view,
5466
5721
  send,
@@ -5554,6 +5809,28 @@ function ChatComponent({
5554
5809
  messages.length === 0 && /* @__PURE__ */ jsx("div", { className: "py-8 text-center text-muted-foreground", children: welcomeMessage || "Send a message to start the conversation" }),
5555
5810
  messages.map((message, index) => {
5556
5811
  const isLastMessage = index === messages.length - 1;
5812
+ const GROUP_THRESHOLD_MS = 5 * 60 * 1e3;
5813
+ const shouldHideAvatar = (() => {
5814
+ if (!groupConsecutiveMessages || index === 0)
5815
+ return false;
5816
+ let prevIdx = index - 1;
5817
+ while (prevIdx >= 0) {
5818
+ const prev = messages[prevIdx];
5819
+ const isToolMsg = prev.role === "tool";
5820
+ const isInvisibleSystem = prev.role === "system" && // eslint-disable-next-line @typescript-eslint/no-explicit-any
5821
+ prev.metadata?.type !== "compaction-marker";
5822
+ if (!isToolMsg && !isInvisibleSystem) break;
5823
+ prevIdx--;
5824
+ }
5825
+ if (prevIdx < 0) return false;
5826
+ const prevVisible = messages[prevIdx];
5827
+ if (prevVisible.role !== message.role) return false;
5828
+ const curTs = message.timestamp;
5829
+ const prevTs = prevVisible.timestamp;
5830
+ if (curTs && prevTs && curTs - prevTs > GROUP_THRESHOLD_MS)
5831
+ return false;
5832
+ return true;
5833
+ })();
5557
5834
  const isEmptyAssistant = message.role === "assistant" && !message.content?.trim();
5558
5835
  const hasToolCalls = message.tool_calls && message.tool_calls.length > 0;
5559
5836
  const hasToolExecutions = message.toolExecutions && message.toolExecutions.length > 0;
@@ -5576,12 +5853,12 @@ function ChatComponent({
5576
5853
  onSendMessage?.(question);
5577
5854
  }
5578
5855
  };
5579
- return renderMessage ? /* @__PURE__ */ jsx(React20__default.Fragment, { children: renderMessage(messageWithExecutions, index) }, message.id) : /* @__PURE__ */ jsx(
5856
+ return renderMessage ? /* @__PURE__ */ jsx(React18__default.Fragment, { children: renderMessage(messageWithExecutions, index) }, message.id) : /* @__PURE__ */ jsx(
5580
5857
  DefaultMessage,
5581
5858
  {
5582
5859
  message: messageWithExecutions,
5583
- userAvatar,
5584
- assistantAvatar,
5860
+ userAvatar: shouldHideAvatar && message.role === "user" ? { ...userAvatar, className: "invisible" } : userAvatar,
5861
+ assistantAvatar: shouldHideAvatar && message.role === "assistant" ? { ...assistantAvatar, className: "invisible" } : assistantAvatar,
5585
5862
  showUserAvatar,
5586
5863
  userMessageClassName: classNames.userMessage,
5587
5864
  assistantMessageClassName: classNames.assistantMessage,
@@ -5593,13 +5870,17 @@ function ChatComponent({
5593
5870
  registeredTools,
5594
5871
  toolRenderers,
5595
5872
  mcpToolRenderer,
5873
+ fallbackToolRenderer,
5596
5874
  onApproveToolExecution,
5597
5875
  onRejectToolExecution,
5598
5876
  showFollowUps,
5599
5877
  onFollowUpClick: handleFollowUpClick,
5600
5878
  followUpClassName,
5601
5879
  followUpButtonClassName,
5602
- citations: citations === false ? { enabled: false } : citations
5880
+ citations: citations === false ? { enabled: false } : citations,
5881
+ branchInfo: message.role === "user" ? getBranchInfo?.(message.id) ?? null : null,
5882
+ onSwitchBranch,
5883
+ onEditMessage
5603
5884
  },
5604
5885
  message.id
5605
5886
  );
@@ -5932,7 +6213,7 @@ function useInternalThreadManager(config = {}) {
5932
6213
  clearCurrentThread,
5933
6214
  refreshThreads
5934
6215
  } = threadManager;
5935
- const { messages, setMessages, status, isLoading } = useCopilot();
6216
+ const { messages, setMessages, status, isLoading, getAllMessages } = useCopilot();
5936
6217
  const isLoadingMessagesRef = useRef(false);
5937
6218
  const savingToThreadRef = useRef(null);
5938
6219
  const lastSavedSnapshotRef = useRef("");
@@ -5951,6 +6232,8 @@ function useInternalThreadManager(config = {}) {
5951
6232
  created_at: m.createdAt,
5952
6233
  tool_calls: m.toolCalls,
5953
6234
  tool_call_id: m.toolCallId,
6235
+ parent_id: m.parentId,
6236
+ children_ids: m.childrenIds,
5954
6237
  // Preserve full metadata including citations, toolExecutions, etc.
5955
6238
  metadata: {
5956
6239
  ...m.metadata,
@@ -5971,6 +6254,8 @@ function useInternalThreadManager(config = {}) {
5971
6254
  createdAt: m.created_at ?? /* @__PURE__ */ new Date(),
5972
6255
  toolCalls: m.tool_calls,
5973
6256
  toolCallId: m.tool_call_id,
6257
+ parentId: m.parent_id,
6258
+ childrenIds: m.children_ids,
5974
6259
  attachments: m.metadata?.attachments
5975
6260
  }));
5976
6261
  lastSavedSnapshotRef.current = getMessageSnapshot(uiMessages);
@@ -6013,6 +6298,8 @@ function useInternalThreadManager(config = {}) {
6013
6298
  createdAt: m.created_at ?? /* @__PURE__ */ new Date(),
6014
6299
  toolCalls: m.tool_calls,
6015
6300
  toolCallId: m.tool_call_id,
6301
+ parentId: m.parent_id,
6302
+ childrenIds: m.children_ids,
6016
6303
  attachments: m.metadata?.attachments,
6017
6304
  thinking: m.metadata?.thinking,
6018
6305
  // Preserve full metadata including citations, toolExecutions, etc.
@@ -6044,7 +6331,10 @@ function useInternalThreadManager(config = {}) {
6044
6331
  if (currentSnapshot === lastSavedSnapshotRef.current) {
6045
6332
  return;
6046
6333
  }
6047
- const coreMessages = convertToCore(messages);
6334
+ const allUIMessages = getAllMessages();
6335
+ const coreMessages = convertToCore(
6336
+ allUIMessages.length > 0 ? allUIMessages : messages
6337
+ );
6048
6338
  if (!currentThreadId && !savingToThreadRef.current) {
6049
6339
  savingToThreadRef.current = "creating";
6050
6340
  createThread({ messages: coreMessages }).then((thread) => {
@@ -6069,6 +6359,7 @@ function useInternalThreadManager(config = {}) {
6069
6359
  refreshThreads,
6070
6360
  getMessageSnapshot,
6071
6361
  convertToCore,
6362
+ getAllMessages,
6072
6363
  onThreadChange
6073
6364
  ]);
6074
6365
  const isBusy = isLoading || status === "streaming" || status === "submitted";
@@ -6148,7 +6439,10 @@ function CopilotChatBase(props) {
6148
6439
  toolExecutions: rawToolExecutions,
6149
6440
  approveToolExecution,
6150
6441
  rejectToolExecution,
6151
- registeredTools
6442
+ registeredTools,
6443
+ switchBranch,
6444
+ getBranchInfo,
6445
+ editMessage
6152
6446
  } = useCopilot();
6153
6447
  const toolExecutions = rawToolExecutions.map(
6154
6448
  (exec) => ({
@@ -6167,7 +6461,9 @@ function CopilotChatBase(props) {
6167
6461
  messages.filter((m) => m.role === "tool" && m.toolCallId).forEach((m) => {
6168
6462
  toolResultsMap.set(m.toolCallId, m.content ?? "");
6169
6463
  });
6170
- const visibleMessages = messages.filter((m) => m.role !== "tool").map((m) => {
6464
+ const visibleMessages = messages.filter(
6465
+ (m) => m.role !== "tool" && (m.role !== "system" || m.metadata?.type === "compaction-marker")
6466
+ ).map((m) => {
6171
6467
  let messageToolExecutions;
6172
6468
  if (m.role === "assistant" && m.toolCalls && m.toolCalls.length > 0) {
6173
6469
  const toolCallIds = new Set(
@@ -6263,24 +6559,29 @@ function CopilotChatBase(props) {
6263
6559
  });
6264
6560
  const suggestions = visibleMessages.length === 0 && chatProps.suggestions?.length ? chatProps.suggestions : [];
6265
6561
  const lastMessage = messages[messages.length - 1];
6266
- const isInToolFlow = lastMessage?.role === "assistant" && lastMessage.toolCalls?.length;
6562
+ const lastAssistantWithTools = [...messages].reverse().find(
6563
+ (m) => m.role === "assistant" && m.toolCalls?.length
6564
+ );
6565
+ const isInToolFlow = lastMessage?.role === "tool" || lastMessage?.role === "assistant" && lastMessage.toolCalls?.length;
6267
6566
  let isProcessingToolResults = false;
6268
6567
  if (isLoading && isInToolFlow) {
6269
- const currentToolCallIds = new Set(
6270
- lastMessage.toolCalls?.map(
6271
- (tc) => tc.id
6272
- ) || []
6273
- );
6274
- const currentExecutions = toolExecutions.filter(
6275
- (exec) => currentToolCallIds.has(exec.id)
6276
- );
6277
- const hasCompletedTools = currentExecutions.some(
6278
- (exec) => exec.status === "completed" || exec.status === "error" || exec.status === "failed"
6279
- );
6280
- const hasExecutingTools = currentExecutions.some(
6281
- (exec) => exec.status === "executing" || exec.status === "pending"
6282
- );
6283
- isProcessingToolResults = hasCompletedTools && !hasExecutingTools;
6568
+ if (lastMessage?.role === "tool") {
6569
+ isProcessingToolResults = true;
6570
+ } else if (lastAssistantWithTools) {
6571
+ const currentToolCallIds = new Set(
6572
+ lastAssistantWithTools.toolCalls?.map((tc) => tc.id) || []
6573
+ );
6574
+ const currentExecutions = toolExecutions.filter(
6575
+ (exec) => currentToolCallIds.has(exec.id)
6576
+ );
6577
+ const hasCompletedTools = currentExecutions.some(
6578
+ (exec) => exec.status === "completed" || exec.status === "error" || exec.status === "failed"
6579
+ );
6580
+ const hasExecutingTools = currentExecutions.some(
6581
+ (exec) => exec.status === "executing" || exec.status === "pending"
6582
+ );
6583
+ isProcessingToolResults = hasCompletedTools && !hasExecutingTools;
6584
+ }
6284
6585
  }
6285
6586
  const chatClassNames = classNames ? {
6286
6587
  root: classNames.root,
@@ -6294,7 +6595,7 @@ function CopilotChatBase(props) {
6294
6595
  footer: classNames.footer
6295
6596
  } : void 0;
6296
6597
  const { threadManager, handleSwitchThread, handleNewThread, isBusy } = threadManagerResult;
6297
- const handleDeleteThread = React20__default.useCallback(
6598
+ const handleDeleteThread = React18__default.useCallback(
6298
6599
  (threadId) => {
6299
6600
  const isCurrentThread = threadManager.currentThreadId === threadId;
6300
6601
  threadManager.deleteThread(threadId);
@@ -6351,6 +6652,9 @@ function CopilotChatBase(props) {
6351
6652
  currentThreadId: threadManager.currentThreadId,
6352
6653
  onSwitchThread: isPersistenceEnabled ? handleSwitchThread : void 0,
6353
6654
  isThreadBusy: isBusy,
6655
+ getBranchInfo,
6656
+ onSwitchBranch: switchBranch,
6657
+ onEditMessage: editMessage,
6354
6658
  children
6355
6659
  }
6356
6660
  );
@@ -6419,6 +6723,6 @@ function PoweredBy({ className, showLogo = true }) {
6419
6723
  );
6420
6724
  }
6421
6725
 
6422
- export { AlertTriangleIcon, BotIcon, Button, CapabilityBadge, CapabilityList, Chat, ChatContainerContent, ChatContainerRoot, ChatContainerScrollAnchor, ChatWelcome, CheckIcon, ChevronDownIcon2 as ChevronDownIcon, ChevronLeftIcon, ChevronUpIcon, CitationBadge, CitationSuperscript, CloseIcon, CodeBlock, CompactPermissionConfirmation, Confirmation, ConfirmationActions, ConfirmationApproved, ConfirmationMessage, ConfirmationPending, ConfirmationRejected, ConnectedChat, CopilotChat, CopilotUIProvider, CopyIcon, DEFAULT_PERMISSION_OPTIONS, DevLogger, FeedbackBar, FollowUpQuestions, InlineToolSteps, Loader, MCPUIFrame, MCPUIFrameList, Markdown, MessageAvatar, MessageContent, Message as MessagePrimitive, MessageWithCitations, ModelSelector, PermissionConfirmation, PoweredBy, PromptInput, PromptInputAction, PromptInputActions, PromptInputTextarea, Reasoning, ReasoningContent, ReasoningTrigger, RefreshIcon, ScrollButton, SearchAnswer, SearchResults, SearchResultsWithAnswer, SendIcon, SimpleConfirmation, SimpleModelSelector, SimpleReasoning, SimpleSource, Source, SourceContent, SourceGroup, SourcePill, SourceTrigger, SourcesBar, SourcesCollapsible, SourcesList, StopIcon, ThreadCard, ThreadList, ThreadPicker, ThumbsDownIcon2 as ThumbsDownIcon, ThumbsUpIcon2 as ThumbsUpIcon, ToolExecutionMessage, ToolStep, ToolSteps, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, UserIcon, XIcon2 as XIcon, annotationsToCitations, cn, parseFollowUps, resultsToCitations, useChatContainer, useCopilotChatContext, useCopilotUI };
6726
+ export { AlertTriangleIcon, BotIcon, BranchNavigator, Button, CapabilityBadge, CapabilityList, Chat, ChatContainerContent, ChatContainerRoot, ChatContainerScrollAnchor, ChatWelcome, CheckIcon, ChevronDownIcon2 as ChevronDownIcon, ChevronLeftIcon, ChevronUpIcon, CitationBadge, CitationSuperscript, CloseIcon, CodeBlock, CompactPermissionConfirmation, Confirmation, ConfirmationActions, ConfirmationApproved, ConfirmationMessage, ConfirmationPending, ConfirmationRejected, ConnectedChat, CopilotChat, CopilotUIProvider, CopyIcon, DEFAULT_PERMISSION_OPTIONS, DevLogger, FeedbackBar, FollowUpQuestions, InlineToolSteps, Loader, MCPUIFrame, MCPUIFrameList, Markdown, MessageAvatar, MessageContent, Message as MessagePrimitive, MessageWithCitations, ModelSelector, PermissionConfirmation, PoweredBy, PromptInput, PromptInputAction, PromptInputActions, PromptInputTextarea, Reasoning, ReasoningContent, ReasoningTrigger, RefreshIcon, ScrollButton, SearchAnswer, SearchResults, SearchResultsWithAnswer, SendIcon, SimpleConfirmation, SimpleModelSelector, SimpleReasoning, SimpleSource, Source, SourceContent, SourceGroup, SourcePill, SourceTrigger, SourcesBar, SourcesCollapsible, SourcesList, StopIcon, ThreadCard, ThreadList, ThreadPicker, ThumbsDownIcon2 as ThumbsDownIcon, ThumbsUpIcon2 as ThumbsUpIcon, ToolExecutionMessage, ToolStep, ToolSteps, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, UserIcon, XIcon2 as XIcon, annotationsToCitations, cn, parseFollowUps, resultsToCitations, useChatContainer, useCopilotChatContext, useCopilotUI };
6423
6727
  //# sourceMappingURL=index.js.map
6424
6728
  //# sourceMappingURL=index.js.map