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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (103) hide show
  1. package/dist/MessageTree-CoIt_4nB.d.cts +161 -0
  2. package/dist/MessageTree-CzaN9Eul.d.ts +161 -0
  3. package/dist/{ThreadManager-Dkp_eLty.d.ts → ThreadManager-BEAECB7Y.d.ts} +1 -1
  4. package/dist/{ThreadManager-LfFRhr4e.d.cts → ThreadManager-Cw5fwyCN.d.cts} +1 -1
  5. package/dist/{chunk-POZNNKNJ.cjs → chunk-246B6X5D.cjs} +8 -2
  6. package/dist/chunk-246B6X5D.cjs.map +1 -0
  7. package/dist/{chunk-QLH6TSCC.js → chunk-4QXY2PBG.js} +8 -2
  8. package/dist/chunk-4QXY2PBG.js.map +1 -0
  9. package/dist/{chunk-7PKGRYHY.js → chunk-5Q72LZ5H.js} +3107 -357
  10. package/dist/chunk-5Q72LZ5H.js.map +1 -0
  11. package/dist/chunk-BJYA5NDL.cjs +96 -0
  12. package/dist/chunk-BJYA5NDL.cjs.map +1 -0
  13. package/dist/{chunk-LZMBBGWH.js → chunk-ENFWM3EY.js} +4 -4
  14. package/dist/{chunk-LZMBBGWH.js.map → chunk-ENFWM3EY.js.map} +1 -1
  15. package/dist/{chunk-OQPRIB73.cjs → chunk-I3SQUNTT.cjs} +71 -25
  16. package/dist/chunk-I3SQUNTT.cjs.map +1 -0
  17. package/dist/{chunk-N6VZ7FOW.cjs → chunk-IXWNDR7H.cjs} +3290 -522
  18. package/dist/chunk-IXWNDR7H.cjs.map +1 -0
  19. package/dist/{chunk-WAPGTQDR.cjs → chunk-JKGFQUHJ.cjs} +10 -10
  20. package/dist/{chunk-WAPGTQDR.cjs.map → chunk-JKGFQUHJ.cjs.map} +1 -1
  21. package/dist/{chunk-XGITAEXU.js → chunk-LLM7AHMO.js} +2 -2
  22. package/dist/{chunk-XGITAEXU.js.map → chunk-LLM7AHMO.js.map} +1 -1
  23. package/dist/{chunk-ASV6JLYG.cjs → chunk-NUXLAZOE.cjs} +2 -2
  24. package/dist/{chunk-ASV6JLYG.cjs.map → chunk-NUXLAZOE.cjs.map} +1 -1
  25. package/dist/{chunk-37KEHUCE.js → chunk-UXJ6LIZB.js} +51 -7
  26. package/dist/chunk-UXJ6LIZB.js.map +1 -0
  27. package/dist/chunk-VNLLW3ZI.js +94 -0
  28. package/dist/chunk-VNLLW3ZI.js.map +1 -0
  29. package/dist/core/index.cjs +99 -91
  30. package/dist/core/index.d.cts +7 -7
  31. package/dist/core/index.d.ts +7 -7
  32. package/dist/core/index.js +5 -5
  33. package/dist/{index-BHkRA0mM.d.cts → index-CiExk87c.d.cts} +1 -1
  34. package/dist/{index-tB0qI8my.d.ts → index-Dwrcf-CP.d.ts} +1 -1
  35. package/dist/mcp/index.d.cts +3 -3
  36. package/dist/mcp/index.d.ts +3 -3
  37. package/dist/react/index.cjs +113 -52
  38. package/dist/react/index.d.cts +673 -77
  39. package/dist/react/index.d.ts +673 -77
  40. package/dist/react/index.js +7 -6
  41. package/dist/server/index.cjs +339 -0
  42. package/dist/server/index.cjs.map +1 -0
  43. package/dist/server/index.d.cts +171 -0
  44. package/dist/server/index.d.ts +171 -0
  45. package/dist/server/index.js +332 -0
  46. package/dist/server/index.js.map +1 -0
  47. package/dist/tools/anthropic/index.cjs +3 -3
  48. package/dist/tools/anthropic/index.d.cts +1 -1
  49. package/dist/tools/anthropic/index.d.ts +1 -1
  50. package/dist/tools/anthropic/index.js +3 -3
  51. package/dist/tools/brave/index.cjs +6 -6
  52. package/dist/tools/brave/index.d.cts +1 -1
  53. package/dist/tools/brave/index.d.ts +1 -1
  54. package/dist/tools/brave/index.js +3 -3
  55. package/dist/tools/exa/index.cjs +6 -6
  56. package/dist/tools/exa/index.d.cts +1 -1
  57. package/dist/tools/exa/index.d.ts +1 -1
  58. package/dist/tools/exa/index.js +3 -3
  59. package/dist/tools/google/index.cjs +6 -6
  60. package/dist/tools/google/index.d.cts +1 -1
  61. package/dist/tools/google/index.d.ts +1 -1
  62. package/dist/tools/google/index.js +3 -3
  63. package/dist/tools/openai/index.cjs +6 -6
  64. package/dist/tools/openai/index.d.cts +1 -1
  65. package/dist/tools/openai/index.d.ts +1 -1
  66. package/dist/tools/openai/index.js +3 -3
  67. package/dist/tools/searxng/index.cjs +6 -6
  68. package/dist/tools/searxng/index.d.cts +1 -1
  69. package/dist/tools/searxng/index.d.ts +1 -1
  70. package/dist/tools/searxng/index.js +3 -3
  71. package/dist/tools/serper/index.cjs +6 -6
  72. package/dist/tools/serper/index.d.cts +1 -1
  73. package/dist/tools/serper/index.d.ts +1 -1
  74. package/dist/tools/serper/index.js +3 -3
  75. package/dist/tools/tavily/index.cjs +6 -6
  76. package/dist/tools/tavily/index.d.cts +1 -1
  77. package/dist/tools/tavily/index.d.ts +1 -1
  78. package/dist/tools/tavily/index.js +3 -3
  79. package/dist/tools/web-search/index.cjs +7 -7
  80. package/dist/tools/web-search/index.d.cts +2 -2
  81. package/dist/tools/web-search/index.d.ts +2 -2
  82. package/dist/tools/web-search/index.js +4 -4
  83. package/dist/{tools-coIcskZ4.d.ts → tools-DHZhF5km.d.cts} +161 -1
  84. package/dist/{tools-coIcskZ4.d.cts → tools-DHZhF5km.d.ts} +161 -1
  85. package/dist/{types-rjaSVmEF.d.ts → types-BTyJu0WD.d.ts} +1 -1
  86. package/dist/types-BckL3hiw.d.cts +93 -0
  87. package/dist/types-BckL3hiw.d.ts +93 -0
  88. package/dist/{types-C8t4Ut8f.d.cts → types-BdX7uPj0.d.cts} +1 -1
  89. package/dist/{types-DG2ya08y.d.ts → types-BeFBBZ5i.d.cts} +64 -1
  90. package/dist/{types-DG2ya08y.d.cts → types-BeFBBZ5i.d.ts} +64 -1
  91. package/dist/ui/index.cjs +509 -209
  92. package/dist/ui/index.cjs.map +1 -1
  93. package/dist/ui/index.d.cts +81 -4
  94. package/dist/ui/index.d.ts +81 -4
  95. package/dist/ui/index.js +457 -158
  96. package/dist/ui/index.js.map +1 -1
  97. package/package.json +6 -1
  98. package/dist/chunk-37KEHUCE.js.map +0 -1
  99. package/dist/chunk-7PKGRYHY.js.map +0 -1
  100. package/dist/chunk-N6VZ7FOW.cjs.map +0 -1
  101. package/dist/chunk-OQPRIB73.cjs.map +0 -1
  102. package/dist/chunk-POZNNKNJ.cjs.map +0 -1
  103. package/dist/chunk-QLH6TSCC.js.map +0 -1
package/dist/ui/index.js CHANGED
@@ -1,10 +1,12 @@
1
- import { useCopilot, useThreadManager } from '../chunk-7PKGRYHY.js';
2
- import { createServerAdapter } from '../chunk-37KEHUCE.js';
1
+ import { useCopilot, useThreadManager } from '../chunk-5Q72LZ5H.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) => {
@@ -4304,41 +4449,121 @@ function DefaultMessage({
4304
4449
  const shouldShowSources = citations.enabled && sources.length > 0;
4305
4450
  if (isUser) {
4306
4451
  const hasAttachments = message.attachments && message.attachments.length > 0;
4307
- return /* @__PURE__ */ jsxs(
4308
- Message,
4309
- {
4310
- className: cn(
4311
- "flex gap-2",
4312
- showUserAvatar ? "justify-end" : "justify-end"
4452
+ return /* @__PURE__ */ jsxs(Message, { className: cn("flex gap-2 group/user-msg justify-end"), children: [
4453
+ /* @__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: [
4454
+ /* @__PURE__ */ jsx(
4455
+ "textarea",
4456
+ {
4457
+ ref: editRef,
4458
+ value: editValue,
4459
+ onChange: (e) => setEditValue(e.target.value),
4460
+ onKeyDown: handleEditKeyDown,
4461
+ rows: Math.max(2, (editValue.match(/\n/g) || []).length + 1),
4462
+ className: cn(
4463
+ "csdk-edit-textarea w-full rounded-lg px-3 py-2 text-sm resize-none",
4464
+ "bg-primary text-primary-foreground placeholder:text-primary-foreground/50",
4465
+ "focus:outline-none focus:ring-2 focus:ring-primary-foreground/30",
4466
+ userMessageClassName
4467
+ )
4468
+ }
4313
4469
  ),
4314
- 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,
4318
- {
4319
- className: cn(
4320
- "csdk-message-user rounded-lg px-4 py-2 bg-primary text-primary-foreground",
4321
- userMessageClassName
4322
- ),
4323
- markdown: true,
4324
- size,
4325
- children: message.content
4326
- }
4327
- ),
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
- ] }),
4330
- showUserAvatar && /* @__PURE__ */ jsx(
4331
- MessageAvatar,
4470
+ /* @__PURE__ */ jsxs("div", { className: "flex gap-1.5 justify-end", children: [
4471
+ /* @__PURE__ */ jsx(
4472
+ "button",
4473
+ {
4474
+ type: "button",
4475
+ onClick: cancelEdit,
4476
+ className: "csdk-edit-cancel px-3 py-1 text-xs rounded-md bg-muted text-muted-foreground hover:bg-muted/80 transition-colors",
4477
+ children: "Cancel"
4478
+ }
4479
+ ),
4480
+ /* @__PURE__ */ jsx(
4481
+ "button",
4332
4482
  {
4333
- src: userAvatar.src,
4334
- alt: "User",
4335
- fallback: userAvatar.fallback,
4336
- children: userAvatar.component
4483
+ type: "button",
4484
+ onClick: submitEdit,
4485
+ disabled: !editValue.trim(),
4486
+ 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",
4487
+ children: "Send"
4337
4488
  }
4338
4489
  )
4339
- ]
4340
- }
4341
- );
4490
+ ] })
4491
+ ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
4492
+ message.content && /* @__PURE__ */ jsxs("div", { className: "relative", children: [
4493
+ /* @__PURE__ */ jsx(
4494
+ MessageContent,
4495
+ {
4496
+ className: cn(
4497
+ "csdk-message-user rounded-lg px-4 py-2 bg-primary text-primary-foreground",
4498
+ userMessageClassName
4499
+ ),
4500
+ markdown: true,
4501
+ size,
4502
+ children: message.content
4503
+ }
4504
+ ),
4505
+ showEditBtn && /* @__PURE__ */ jsx(
4506
+ "button",
4507
+ {
4508
+ type: "button",
4509
+ onClick: startEdit,
4510
+ "aria-label": "Edit message",
4511
+ className: cn(
4512
+ "csdk-edit-btn absolute -left-7 top-1/2 -translate-y-1/2",
4513
+ "size-6 flex items-center justify-center rounded-full",
4514
+ "text-muted-foreground bg-background border border-border shadow-sm",
4515
+ "opacity-0 group-hover/user-msg:opacity-100 transition-opacity",
4516
+ "hover:text-foreground hover:bg-muted"
4517
+ ),
4518
+ children: /* @__PURE__ */ jsxs(
4519
+ "svg",
4520
+ {
4521
+ width: "12",
4522
+ height: "12",
4523
+ viewBox: "0 0 24 24",
4524
+ fill: "none",
4525
+ stroke: "currentColor",
4526
+ strokeWidth: 2,
4527
+ strokeLinecap: "round",
4528
+ strokeLinejoin: "round",
4529
+ children: [
4530
+ /* @__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" }),
4531
+ /* @__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" })
4532
+ ]
4533
+ }
4534
+ )
4535
+ }
4536
+ )
4537
+ ] }),
4538
+ 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)) }),
4539
+ showBranchNav && /* @__PURE__ */ jsx(
4540
+ BranchNavigator,
4541
+ {
4542
+ siblingIndex: branchInfo.siblingIndex,
4543
+ totalSiblings: branchInfo.totalSiblings,
4544
+ hasPrevious: branchInfo.hasPrevious,
4545
+ hasNext: branchInfo.hasNext,
4546
+ onPrevious: () => onSwitchBranch(
4547
+ branchInfo.siblingIds[branchInfo.siblingIndex - 1]
4548
+ ),
4549
+ onNext: () => onSwitchBranch(
4550
+ branchInfo.siblingIds[branchInfo.siblingIndex + 1]
4551
+ ),
4552
+ className: "mt-1"
4553
+ }
4554
+ )
4555
+ ] }) }),
4556
+ showUserAvatar && /* @__PURE__ */ jsx(
4557
+ MessageAvatar,
4558
+ {
4559
+ src: userAvatar.src,
4560
+ alt: "User",
4561
+ fallback: userAvatar.fallback,
4562
+ className: userAvatar.className,
4563
+ children: userAvatar.component
4564
+ }
4565
+ )
4566
+ ] });
4342
4567
  }
4343
4568
  const isToolHidden = (exec) => {
4344
4569
  if (exec.hidden === true) return true;
@@ -4356,6 +4581,7 @@ function DefaultMessage({
4356
4581
  const toolDef = registeredTools?.find((t) => t.name === toolName);
4357
4582
  if (mcpToolRenderer && (execSource === "mcp" || toolDef?.source === "mcp"))
4358
4583
  return true;
4584
+ if (fallbackToolRenderer) return true;
4359
4585
  if (toolDef?.render) return true;
4360
4586
  return false;
4361
4587
  };
@@ -4382,7 +4608,7 @@ function DefaultMessage({
4382
4608
  alt: "Assistant",
4383
4609
  fallback: assistantAvatar.fallback,
4384
4610
  fallbackIcon: !assistantAvatar.src && !assistantAvatar.fallback && !assistantAvatar.component ? /* @__PURE__ */ jsx(copilot_sdk_logo_default, { className: "size-5" }) : void 0,
4385
- className: "bg-muted",
4611
+ className: cn("bg-muted", assistantAvatar.className),
4386
4612
  children: assistantAvatar.component
4387
4613
  }
4388
4614
  ),
@@ -4395,10 +4621,7 @@ function DefaultMessage({
4395
4621
  className: "mb-2"
4396
4622
  }
4397
4623
  ),
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
- ] }) : (
4624
+ 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
4625
  /* Show streaming loader when loading with no content and no tools */
4403
4626
  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
4627
  cleanContent?.trim() && /* @__PURE__ */ jsx(
@@ -4414,10 +4637,34 @@ function DefaultMessage({
4414
4637
  }
4415
4638
  ),
4416
4639
  toolsWithCustomRender && toolsWithCustomRender.length > 0 && /* @__PURE__ */ jsx("div", { className: cn("space-y-2", cleanContent?.trim() && "mt-2"), children: toolsWithCustomRender.map((exec) => {
4417
- const Renderer = toolRenderers?.[exec.name];
4418
- if (Renderer) {
4640
+ const toolDef = registeredTools?.find(
4641
+ (t) => t.name === exec.name
4642
+ );
4643
+ if (toolDef?.render) {
4644
+ let status = "pending";
4645
+ if (exec.status === "executing") status = "executing";
4646
+ else if (exec.status === "completed") status = "completed";
4647
+ else if (exec.status === "error" || exec.status === "failed" || exec.status === "rejected")
4648
+ status = "error";
4649
+ const renderProps = {
4650
+ status,
4651
+ args: exec.args,
4652
+ result: exec.result,
4653
+ error: exec.error,
4654
+ toolCallId: exec.id,
4655
+ toolName: exec.name
4656
+ };
4657
+ const output = toolDef.render(
4658
+ renderProps
4659
+ );
4660
+ if (output != null) {
4661
+ return /* @__PURE__ */ jsx(React18.Fragment, { children: output }, exec.id);
4662
+ }
4663
+ }
4664
+ if (mcpToolRenderer && (exec.source === "mcp" || toolDef?.source === "mcp")) {
4665
+ const MCPRenderer = mcpToolRenderer;
4419
4666
  return /* @__PURE__ */ jsx(
4420
- Renderer,
4667
+ MCPRenderer,
4421
4668
  {
4422
4669
  execution: {
4423
4670
  id: exec.id,
@@ -4426,20 +4673,16 @@ function DefaultMessage({
4426
4673
  status: exec.status,
4427
4674
  result: exec.result,
4428
4675
  error: exec.error,
4429
- approvalStatus: exec.approvalStatus,
4430
- source: exec.source
4676
+ source: exec.source || toolDef?.source
4431
4677
  }
4432
4678
  },
4433
4679
  exec.id
4434
4680
  );
4435
4681
  }
4436
- const toolDef = registeredTools?.find(
4437
- (t) => t.name === exec.name
4438
- );
4439
- if (mcpToolRenderer && (exec.source === "mcp" || toolDef?.source === "mcp")) {
4440
- const MCPRenderer = mcpToolRenderer;
4682
+ if (fallbackToolRenderer) {
4683
+ const FallbackRenderer = fallbackToolRenderer;
4441
4684
  return /* @__PURE__ */ jsx(
4442
- MCPRenderer,
4685
+ FallbackRenderer,
4443
4686
  {
4444
4687
  execution: {
4445
4688
  id: exec.id,
@@ -4448,31 +4691,30 @@ function DefaultMessage({
4448
4691
  status: exec.status,
4449
4692
  result: exec.result,
4450
4693
  error: exec.error,
4451
- source: exec.source || toolDef?.source
4694
+ source: exec.source
4452
4695
  }
4453
4696
  },
4454
4697
  exec.id
4455
4698
  );
4456
4699
  }
4457
- const toolDefForRender = toolDef ?? registeredTools?.find((t) => t.name === exec.name);
4458
- if (toolDefForRender?.render) {
4459
- let status = "pending";
4460
- if (exec.status === "executing") status = "executing";
4461
- else if (exec.status === "completed") status = "completed";
4462
- else if (exec.status === "error" || exec.status === "failed" || exec.status === "rejected")
4463
- status = "error";
4464
- const renderProps = {
4465
- status,
4466
- args: exec.args,
4467
- result: exec.result,
4468
- error: exec.error,
4469
- toolCallId: exec.id,
4470
- toolName: exec.name
4471
- };
4472
- const output = toolDefForRender.render(
4473
- renderProps
4700
+ const Renderer = toolRenderers?.[exec.name];
4701
+ if (Renderer) {
4702
+ return /* @__PURE__ */ jsx(
4703
+ Renderer,
4704
+ {
4705
+ execution: {
4706
+ id: exec.id,
4707
+ name: exec.name,
4708
+ args: exec.args,
4709
+ status: exec.status,
4710
+ result: exec.result,
4711
+ error: exec.error,
4712
+ approvalStatus: exec.approvalStatus,
4713
+ source: exec.source
4714
+ }
4715
+ },
4716
+ exec.id
4474
4717
  );
4475
- return /* @__PURE__ */ jsx(React20.Fragment, { children: output }, exec.id);
4476
4718
  }
4477
4719
  return null;
4478
4720
  }) }),
@@ -4498,6 +4740,7 @@ function DefaultMessage({
4498
4740
  `${exec.id}-ui`
4499
4741
  );
4500
4742
  }),
4743
+ 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
4744
  pendingApprovalTools && pendingApprovalTools.length > 0 && /* @__PURE__ */ jsx("div", { className: "mt-2 space-y-2", children: pendingApprovalTools.map((tool) => {
4502
4745
  const approvalCallbacks = {
4503
4746
  onApprove: (extraData) => onApproveToolExecution?.(tool.id, extraData),
@@ -4531,7 +4774,7 @@ function DefaultMessage({
4531
4774
  const output = toolDef.render(
4532
4775
  renderProps
4533
4776
  );
4534
- return /* @__PURE__ */ jsx(React20.Fragment, { children: output }, tool.id);
4777
+ return /* @__PURE__ */ jsx(React18.Fragment, { children: output }, tool.id);
4535
4778
  }
4536
4779
  return /* @__PURE__ */ jsx(
4537
4780
  PermissionConfirmation,
@@ -4580,7 +4823,7 @@ function DefaultMessage({
4580
4823
  ] });
4581
4824
  }
4582
4825
  function AttachmentPreview({ attachment }) {
4583
- const [expanded, setExpanded] = React20.useState(false);
4826
+ const [expanded, setExpanded] = React18.useState(false);
4584
4827
  if (attachment.type !== "image") {
4585
4828
  return /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 rounded-lg border bg-muted/50 px-3 py-2 text-sm", children: [
4586
4829
  /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: attachment.type }),
@@ -5038,10 +5281,10 @@ function ChatView({ children, className }) {
5038
5281
  ChatView.displayName = "ChatView";
5039
5282
  function chatViewHasOnlyLayoutChildren(chatViewElement) {
5040
5283
  if (!chatViewElement?.props?.children) return false;
5041
- const childArray = React20__default.Children.toArray(chatViewElement.props.children);
5284
+ const childArray = React18__default.Children.toArray(chatViewElement.props.children);
5042
5285
  if (childArray.length === 0) return false;
5043
5286
  return childArray.every(
5044
- (child) => React20__default.isValidElement(child) && (child.type === Header || child.type === Footer)
5287
+ (child) => React18__default.isValidElement(child) && (child.type === Header || child.type === Footer)
5045
5288
  );
5046
5289
  }
5047
5290
  function Header({ children, className }) {
@@ -5179,18 +5422,18 @@ function ThreadPickerCompound(props) {
5179
5422
  );
5180
5423
  }
5181
5424
  function hasCompoundChild(children, ...components) {
5182
- return React20__default.Children.toArray(children).some(
5183
- (child) => React20__default.isValidElement(child) && components.includes(child.type)
5425
+ return React18__default.Children.toArray(children).some(
5426
+ (child) => React18__default.isValidElement(child) && components.includes(child.type)
5184
5427
  );
5185
5428
  }
5186
5429
  function findCompoundChild(children, component) {
5187
- return React20__default.Children.toArray(children).find(
5188
- (child) => React20__default.isValidElement(child) && child.type === component
5430
+ return React18__default.Children.toArray(children).find(
5431
+ (child) => React18__default.isValidElement(child) && child.type === component
5189
5432
  );
5190
5433
  }
5191
5434
  function filterCompoundChildren(children, ...components) {
5192
- return React20__default.Children.toArray(children).filter(
5193
- (child) => React20__default.isValidElement(child) && components.includes(child.type)
5435
+ return React18__default.Children.toArray(children).filter(
5436
+ (child) => React18__default.isValidElement(child) && components.includes(child.type)
5194
5437
  );
5195
5438
  }
5196
5439
  var DEFAULT_MAX_FILE_SIZE2 = 5 * 1024 * 1024;
@@ -5265,6 +5508,7 @@ function ChatComponent({
5265
5508
  registeredTools,
5266
5509
  toolRenderers,
5267
5510
  mcpToolRenderer,
5511
+ fallbackToolRenderer,
5268
5512
  onApproveToolExecution,
5269
5513
  onRejectToolExecution,
5270
5514
  // Follow-up Questions
@@ -5277,6 +5521,8 @@ function ChatComponent({
5277
5521
  renderMessage,
5278
5522
  renderInput,
5279
5523
  renderHeader,
5524
+ // Avatar grouping
5525
+ groupConsecutiveMessages = false,
5280
5526
  // Styling
5281
5527
  className,
5282
5528
  classNames = {},
@@ -5285,7 +5531,11 @@ function ChatComponent({
5285
5531
  threads,
5286
5532
  currentThreadId,
5287
5533
  onSwitchThread,
5288
- isThreadBusy
5534
+ isThreadBusy,
5535
+ // Branching
5536
+ getBranchInfo,
5537
+ onSwitchBranch,
5538
+ onEditMessage
5289
5539
  }) {
5290
5540
  const userAvatar = { fallback: "U", ...userAvatarProp };
5291
5541
  const assistantAvatar = { fallback: "AI", ...assistantAvatarProp };
@@ -5460,7 +5710,7 @@ function ChatComponent({
5460
5710
  },
5461
5711
  [onSendMessage]
5462
5712
  );
5463
- const contextValue = React20__default.useMemo(
5713
+ const contextValue = React18__default.useMemo(
5464
5714
  () => ({
5465
5715
  view,
5466
5716
  send,
@@ -5554,6 +5804,28 @@ function ChatComponent({
5554
5804
  messages.length === 0 && /* @__PURE__ */ jsx("div", { className: "py-8 text-center text-muted-foreground", children: welcomeMessage || "Send a message to start the conversation" }),
5555
5805
  messages.map((message, index) => {
5556
5806
  const isLastMessage = index === messages.length - 1;
5807
+ const GROUP_THRESHOLD_MS = 5 * 60 * 1e3;
5808
+ const shouldHideAvatar = (() => {
5809
+ if (!groupConsecutiveMessages || index === 0)
5810
+ return false;
5811
+ let prevIdx = index - 1;
5812
+ while (prevIdx >= 0) {
5813
+ const prev = messages[prevIdx];
5814
+ const isToolMsg = prev.role === "tool";
5815
+ const isInvisibleSystem = prev.role === "system" && // eslint-disable-next-line @typescript-eslint/no-explicit-any
5816
+ prev.metadata?.type !== "compaction-marker";
5817
+ if (!isToolMsg && !isInvisibleSystem) break;
5818
+ prevIdx--;
5819
+ }
5820
+ if (prevIdx < 0) return false;
5821
+ const prevVisible = messages[prevIdx];
5822
+ if (prevVisible.role !== message.role) return false;
5823
+ const curTs = message.timestamp;
5824
+ const prevTs = prevVisible.timestamp;
5825
+ if (curTs && prevTs && curTs - prevTs > GROUP_THRESHOLD_MS)
5826
+ return false;
5827
+ return true;
5828
+ })();
5557
5829
  const isEmptyAssistant = message.role === "assistant" && !message.content?.trim();
5558
5830
  const hasToolCalls = message.tool_calls && message.tool_calls.length > 0;
5559
5831
  const hasToolExecutions = message.toolExecutions && message.toolExecutions.length > 0;
@@ -5576,12 +5848,12 @@ function ChatComponent({
5576
5848
  onSendMessage?.(question);
5577
5849
  }
5578
5850
  };
5579
- return renderMessage ? /* @__PURE__ */ jsx(React20__default.Fragment, { children: renderMessage(messageWithExecutions, index) }, message.id) : /* @__PURE__ */ jsx(
5851
+ return renderMessage ? /* @__PURE__ */ jsx(React18__default.Fragment, { children: renderMessage(messageWithExecutions, index) }, message.id) : /* @__PURE__ */ jsx(
5580
5852
  DefaultMessage,
5581
5853
  {
5582
5854
  message: messageWithExecutions,
5583
- userAvatar,
5584
- assistantAvatar,
5855
+ userAvatar: shouldHideAvatar && message.role === "user" ? { ...userAvatar, className: "invisible" } : userAvatar,
5856
+ assistantAvatar: shouldHideAvatar && message.role === "assistant" ? { ...assistantAvatar, className: "invisible" } : assistantAvatar,
5585
5857
  showUserAvatar,
5586
5858
  userMessageClassName: classNames.userMessage,
5587
5859
  assistantMessageClassName: classNames.assistantMessage,
@@ -5593,13 +5865,17 @@ function ChatComponent({
5593
5865
  registeredTools,
5594
5866
  toolRenderers,
5595
5867
  mcpToolRenderer,
5868
+ fallbackToolRenderer,
5596
5869
  onApproveToolExecution,
5597
5870
  onRejectToolExecution,
5598
5871
  showFollowUps,
5599
5872
  onFollowUpClick: handleFollowUpClick,
5600
5873
  followUpClassName,
5601
5874
  followUpButtonClassName,
5602
- citations: citations === false ? { enabled: false } : citations
5875
+ citations: citations === false ? { enabled: false } : citations,
5876
+ branchInfo: message.role === "user" ? getBranchInfo?.(message.id) ?? null : null,
5877
+ onSwitchBranch,
5878
+ onEditMessage
5603
5879
  },
5604
5880
  message.id
5605
5881
  );
@@ -5932,7 +6208,7 @@ function useInternalThreadManager(config = {}) {
5932
6208
  clearCurrentThread,
5933
6209
  refreshThreads
5934
6210
  } = threadManager;
5935
- const { messages, setMessages, status, isLoading } = useCopilot();
6211
+ const { messages, setMessages, status, isLoading, getAllMessages } = useCopilot();
5936
6212
  const isLoadingMessagesRef = useRef(false);
5937
6213
  const savingToThreadRef = useRef(null);
5938
6214
  const lastSavedSnapshotRef = useRef("");
@@ -5951,6 +6227,8 @@ function useInternalThreadManager(config = {}) {
5951
6227
  created_at: m.createdAt,
5952
6228
  tool_calls: m.toolCalls,
5953
6229
  tool_call_id: m.toolCallId,
6230
+ parent_id: m.parentId,
6231
+ children_ids: m.childrenIds,
5954
6232
  // Preserve full metadata including citations, toolExecutions, etc.
5955
6233
  metadata: {
5956
6234
  ...m.metadata,
@@ -5971,6 +6249,8 @@ function useInternalThreadManager(config = {}) {
5971
6249
  createdAt: m.created_at ?? /* @__PURE__ */ new Date(),
5972
6250
  toolCalls: m.tool_calls,
5973
6251
  toolCallId: m.tool_call_id,
6252
+ parentId: m.parent_id,
6253
+ childrenIds: m.children_ids,
5974
6254
  attachments: m.metadata?.attachments
5975
6255
  }));
5976
6256
  lastSavedSnapshotRef.current = getMessageSnapshot(uiMessages);
@@ -6013,6 +6293,8 @@ function useInternalThreadManager(config = {}) {
6013
6293
  createdAt: m.created_at ?? /* @__PURE__ */ new Date(),
6014
6294
  toolCalls: m.tool_calls,
6015
6295
  toolCallId: m.tool_call_id,
6296
+ parentId: m.parent_id,
6297
+ childrenIds: m.children_ids,
6016
6298
  attachments: m.metadata?.attachments,
6017
6299
  thinking: m.metadata?.thinking,
6018
6300
  // Preserve full metadata including citations, toolExecutions, etc.
@@ -6044,7 +6326,10 @@ function useInternalThreadManager(config = {}) {
6044
6326
  if (currentSnapshot === lastSavedSnapshotRef.current) {
6045
6327
  return;
6046
6328
  }
6047
- const coreMessages = convertToCore(messages);
6329
+ const allUIMessages = getAllMessages();
6330
+ const coreMessages = convertToCore(
6331
+ allUIMessages.length > 0 ? allUIMessages : messages
6332
+ );
6048
6333
  if (!currentThreadId && !savingToThreadRef.current) {
6049
6334
  savingToThreadRef.current = "creating";
6050
6335
  createThread({ messages: coreMessages }).then((thread) => {
@@ -6069,6 +6354,7 @@ function useInternalThreadManager(config = {}) {
6069
6354
  refreshThreads,
6070
6355
  getMessageSnapshot,
6071
6356
  convertToCore,
6357
+ getAllMessages,
6072
6358
  onThreadChange
6073
6359
  ]);
6074
6360
  const isBusy = isLoading || status === "streaming" || status === "submitted";
@@ -6148,7 +6434,10 @@ function CopilotChatBase(props) {
6148
6434
  toolExecutions: rawToolExecutions,
6149
6435
  approveToolExecution,
6150
6436
  rejectToolExecution,
6151
- registeredTools
6437
+ registeredTools,
6438
+ switchBranch,
6439
+ getBranchInfo,
6440
+ editMessage
6152
6441
  } = useCopilot();
6153
6442
  const toolExecutions = rawToolExecutions.map(
6154
6443
  (exec) => ({
@@ -6167,7 +6456,9 @@ function CopilotChatBase(props) {
6167
6456
  messages.filter((m) => m.role === "tool" && m.toolCallId).forEach((m) => {
6168
6457
  toolResultsMap.set(m.toolCallId, m.content ?? "");
6169
6458
  });
6170
- const visibleMessages = messages.filter((m) => m.role !== "tool").map((m) => {
6459
+ const visibleMessages = messages.filter(
6460
+ (m) => m.role !== "tool" && (m.role !== "system" || m.metadata?.type === "compaction-marker")
6461
+ ).map((m) => {
6171
6462
  let messageToolExecutions;
6172
6463
  if (m.role === "assistant" && m.toolCalls && m.toolCalls.length > 0) {
6173
6464
  const toolCallIds = new Set(
@@ -6263,24 +6554,29 @@ function CopilotChatBase(props) {
6263
6554
  });
6264
6555
  const suggestions = visibleMessages.length === 0 && chatProps.suggestions?.length ? chatProps.suggestions : [];
6265
6556
  const lastMessage = messages[messages.length - 1];
6266
- const isInToolFlow = lastMessage?.role === "assistant" && lastMessage.toolCalls?.length;
6557
+ const lastAssistantWithTools = [...messages].reverse().find(
6558
+ (m) => m.role === "assistant" && m.toolCalls?.length
6559
+ );
6560
+ const isInToolFlow = lastMessage?.role === "tool" || lastMessage?.role === "assistant" && lastMessage.toolCalls?.length;
6267
6561
  let isProcessingToolResults = false;
6268
6562
  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;
6563
+ if (lastMessage?.role === "tool") {
6564
+ isProcessingToolResults = true;
6565
+ } else if (lastAssistantWithTools) {
6566
+ const currentToolCallIds = new Set(
6567
+ lastAssistantWithTools.toolCalls?.map((tc) => tc.id) || []
6568
+ );
6569
+ const currentExecutions = toolExecutions.filter(
6570
+ (exec) => currentToolCallIds.has(exec.id)
6571
+ );
6572
+ const hasCompletedTools = currentExecutions.some(
6573
+ (exec) => exec.status === "completed" || exec.status === "error" || exec.status === "failed"
6574
+ );
6575
+ const hasExecutingTools = currentExecutions.some(
6576
+ (exec) => exec.status === "executing" || exec.status === "pending"
6577
+ );
6578
+ isProcessingToolResults = hasCompletedTools && !hasExecutingTools;
6579
+ }
6284
6580
  }
6285
6581
  const chatClassNames = classNames ? {
6286
6582
  root: classNames.root,
@@ -6294,7 +6590,7 @@ function CopilotChatBase(props) {
6294
6590
  footer: classNames.footer
6295
6591
  } : void 0;
6296
6592
  const { threadManager, handleSwitchThread, handleNewThread, isBusy } = threadManagerResult;
6297
- const handleDeleteThread = React20__default.useCallback(
6593
+ const handleDeleteThread = React18__default.useCallback(
6298
6594
  (threadId) => {
6299
6595
  const isCurrentThread = threadManager.currentThreadId === threadId;
6300
6596
  threadManager.deleteThread(threadId);
@@ -6351,6 +6647,9 @@ function CopilotChatBase(props) {
6351
6647
  currentThreadId: threadManager.currentThreadId,
6352
6648
  onSwitchThread: isPersistenceEnabled ? handleSwitchThread : void 0,
6353
6649
  isThreadBusy: isBusy,
6650
+ getBranchInfo,
6651
+ onSwitchBranch: switchBranch,
6652
+ onEditMessage: editMessage,
6354
6653
  children
6355
6654
  }
6356
6655
  );
@@ -6419,6 +6718,6 @@ function PoweredBy({ className, showLogo = true }) {
6419
6718
  );
6420
6719
  }
6421
6720
 
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 };
6721
+ 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
6722
  //# sourceMappingURL=index.js.map
6424
6723
  //# sourceMappingURL=index.js.map