@yourgpt/copilot-sdk 2.0.1 → 2.0.2-beta.2

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 (215) hide show
  1. package/README.md +42 -0
  2. package/dist/{ThreadManager-JT0sqSSD.d.ts → ThreadManager-Dkp_eLty.d.ts} +1 -1
  3. package/dist/{ThreadManager-CUq5Ocu2.d.cts → ThreadManager-LfFRhr4e.d.cts} +1 -1
  4. package/dist/anthropic-6F5GRE3B.js +4 -0
  5. package/dist/anthropic-6F5GRE3B.js.map +1 -0
  6. package/dist/anthropic-DGalr_Fw.d.cts +17 -0
  7. package/dist/anthropic-DkCEDYOt.d.ts +17 -0
  8. package/dist/anthropic-NMTRABEH.cjs +21 -0
  9. package/dist/anthropic-NMTRABEH.cjs.map +1 -0
  10. package/dist/brave-DdnWb7Gb.d.cts +17 -0
  11. package/dist/brave-DsI9n7Wr.d.ts +17 -0
  12. package/dist/brave-OYKCOZEM.cjs +21 -0
  13. package/dist/brave-OYKCOZEM.cjs.map +1 -0
  14. package/dist/brave-XSASGGH2.js +4 -0
  15. package/dist/brave-XSASGGH2.js.map +1 -0
  16. package/dist/chunk-2FAWEBZS.cjs +88 -0
  17. package/dist/chunk-2FAWEBZS.cjs.map +1 -0
  18. package/dist/chunk-53UGJNHN.js +92 -0
  19. package/dist/chunk-53UGJNHN.js.map +1 -0
  20. package/dist/chunk-6T5XXJEP.cjs +80 -0
  21. package/dist/chunk-6T5XXJEP.cjs.map +1 -0
  22. package/dist/chunk-7K7HZMP4.cjs +1170 -0
  23. package/dist/chunk-7K7HZMP4.cjs.map +1 -0
  24. package/dist/chunk-7W7QLZNC.js +72 -0
  25. package/dist/chunk-7W7QLZNC.js.map +1 -0
  26. package/dist/{chunk-JM7PB2LP.js → chunk-7XFFRV7D.js} +10 -66
  27. package/dist/chunk-7XFFRV7D.js.map +1 -0
  28. package/dist/chunk-ASV6JLYG.cjs +99 -0
  29. package/dist/chunk-ASV6JLYG.cjs.map +1 -0
  30. package/dist/chunk-BH7MNDWW.js +1152 -0
  31. package/dist/chunk-BH7MNDWW.js.map +1 -0
  32. package/dist/chunk-BKO7DSPU.js +67 -0
  33. package/dist/chunk-BKO7DSPU.js.map +1 -0
  34. package/dist/chunk-CBAHCI4R.cjs +76 -0
  35. package/dist/chunk-CBAHCI4R.cjs.map +1 -0
  36. package/dist/chunk-CEKAYA2Q.cjs +74 -0
  37. package/dist/chunk-CEKAYA2Q.cjs.map +1 -0
  38. package/dist/chunk-CEOMTQTP.js +85 -0
  39. package/dist/chunk-CEOMTQTP.js.map +1 -0
  40. package/dist/chunk-DABZYCVX.js +84 -0
  41. package/dist/chunk-DABZYCVX.js.map +1 -0
  42. package/dist/chunk-DGUM43GV.js +10 -0
  43. package/dist/chunk-DGUM43GV.js.map +1 -0
  44. package/dist/chunk-G4SF2PNQ.js +33 -0
  45. package/dist/chunk-G4SF2PNQ.js.map +1 -0
  46. package/dist/chunk-GANCV72Z.cjs +110 -0
  47. package/dist/chunk-GANCV72Z.cjs.map +1 -0
  48. package/dist/{chunk-BLSI67J6.cjs → chunk-H5XMKBBA.cjs} +425 -30
  49. package/dist/chunk-H5XMKBBA.cjs.map +1 -0
  50. package/dist/{chunk-CJ7UWN2Y.js → chunk-IXFV6AW6.js} +397 -7
  51. package/dist/chunk-IXFV6AW6.js.map +1 -0
  52. package/dist/chunk-JEQ2X3Z6.cjs +12 -0
  53. package/dist/chunk-JEQ2X3Z6.cjs.map +1 -0
  54. package/dist/chunk-JO4BHPAD.cjs +40 -0
  55. package/dist/chunk-JO4BHPAD.cjs.map +1 -0
  56. package/dist/chunk-MEBXW75C.cjs +89 -0
  57. package/dist/chunk-MEBXW75C.cjs.map +1 -0
  58. package/dist/chunk-MNDGIW47.js +76 -0
  59. package/dist/chunk-MNDGIW47.js.map +1 -0
  60. package/dist/chunk-PPFHA6IL.js +83 -0
  61. package/dist/chunk-PPFHA6IL.js.map +1 -0
  62. package/dist/chunk-RQ74USYU.js +128 -0
  63. package/dist/chunk-RQ74USYU.js.map +1 -0
  64. package/dist/chunk-TXLIY7GF.cjs +132 -0
  65. package/dist/chunk-TXLIY7GF.cjs.map +1 -0
  66. package/dist/chunk-UIWFYMAO.cjs +82 -0
  67. package/dist/chunk-UIWFYMAO.cjs.map +1 -0
  68. package/dist/{chunk-4PRWNAXQ.cjs → chunk-UOWLKFXK.cjs} +27 -89
  69. package/dist/chunk-UOWLKFXK.cjs.map +1 -0
  70. package/dist/chunk-VD74IPKB.js +106 -0
  71. package/dist/chunk-VD74IPKB.js.map +1 -0
  72. package/dist/chunk-W73FBYIH.cjs +87 -0
  73. package/dist/chunk-W73FBYIH.cjs.map +1 -0
  74. package/dist/chunk-XGITAEXU.js +93 -0
  75. package/dist/chunk-XGITAEXU.js.map +1 -0
  76. package/dist/chunk-XWOHNY3F.cjs +96 -0
  77. package/dist/chunk-XWOHNY3F.cjs.map +1 -0
  78. package/dist/chunk-ZPYQDMUX.js +79 -0
  79. package/dist/chunk-ZPYQDMUX.js.map +1 -0
  80. package/dist/core/index.cjs +156 -84
  81. package/dist/core/index.d.cts +16 -4
  82. package/dist/core/index.d.ts +16 -4
  83. package/dist/core/index.js +13 -1
  84. package/dist/exa-72KFY5A7.cjs +21 -0
  85. package/dist/exa-72KFY5A7.cjs.map +1 -0
  86. package/dist/exa-Dp9U-WTc.d.ts +17 -0
  87. package/dist/exa-NNVPBC2M.js +4 -0
  88. package/dist/exa-NNVPBC2M.js.map +1 -0
  89. package/dist/exa-jJSPhyUW.d.cts +17 -0
  90. package/dist/google-CHU2yycE.d.cts +17 -0
  91. package/dist/google-CTEK6SV2.js +4 -0
  92. package/dist/google-CTEK6SV2.js.map +1 -0
  93. package/dist/google-Da8IQxaI.d.ts +17 -0
  94. package/dist/google-IIUXFFVF.cjs +21 -0
  95. package/dist/google-IIUXFFVF.cjs.map +1 -0
  96. package/dist/index-2VtgKM8S.d.cts +206 -0
  97. package/dist/index-pWEH7pUE.d.ts +206 -0
  98. package/dist/mcp/index.cjs +670 -0
  99. package/dist/mcp/index.cjs.map +1 -0
  100. package/dist/mcp/index.d.cts +779 -0
  101. package/dist/mcp/index.d.ts +779 -0
  102. package/dist/mcp/index.js +574 -0
  103. package/dist/mcp/index.js.map +1 -0
  104. package/dist/openai-6KTCQ7PZ.cjs +21 -0
  105. package/dist/openai-6KTCQ7PZ.cjs.map +1 -0
  106. package/dist/openai-7W2PCNW5.js +4 -0
  107. package/dist/openai-7W2PCNW5.js.map +1 -0
  108. package/dist/openai-Cam8hF4f.d.ts +17 -0
  109. package/dist/openai-HVSCuXgO.d.cts +17 -0
  110. package/dist/react/index.cjs +75 -42
  111. package/dist/react/index.d.cts +270 -45
  112. package/dist/react/index.d.ts +270 -45
  113. package/dist/react/index.js +15 -2
  114. package/dist/searxng-AXLVGY7Z.js +4 -0
  115. package/dist/searxng-AXLVGY7Z.js.map +1 -0
  116. package/dist/searxng-EJKNY236.cjs +21 -0
  117. package/dist/searxng-EJKNY236.cjs.map +1 -0
  118. package/dist/searxng-K0qtY9vp.d.ts +17 -0
  119. package/dist/searxng-QGOte_Gq.d.cts +17 -0
  120. package/dist/serper-3JYJHJX6.js +4 -0
  121. package/dist/serper-3JYJHJX6.js.map +1 -0
  122. package/dist/serper-63FT4AOL.cjs +21 -0
  123. package/dist/serper-63FT4AOL.cjs.map +1 -0
  124. package/dist/serper-7Czya3PW.d.ts +17 -0
  125. package/dist/serper-JzdaSnS9.d.cts +17 -0
  126. package/dist/styles.css +38 -0
  127. package/dist/tavily-AWFP4RM7.cjs +21 -0
  128. package/dist/tavily-AWFP4RM7.cjs.map +1 -0
  129. package/dist/tavily-C8cXXojE.d.cts +17 -0
  130. package/dist/tavily-CIWAAZPH.js +4 -0
  131. package/dist/tavily-CIWAAZPH.js.map +1 -0
  132. package/dist/tavily-DdSGVgkE.d.ts +17 -0
  133. package/dist/themes/catppuccin.css +2 -0
  134. package/dist/themes/claude.css +2 -0
  135. package/dist/themes/linear.css +2 -0
  136. package/dist/themes/modern-minimal.css +2 -0
  137. package/dist/themes/posthog.css +2 -0
  138. package/dist/themes/supabase.css +2 -0
  139. package/dist/themes/twitter.css +2 -0
  140. package/dist/themes/vercel.css +2 -0
  141. package/dist/tools/anthropic/index.cjs +61 -0
  142. package/dist/tools/anthropic/index.cjs.map +1 -0
  143. package/dist/tools/anthropic/index.d.cts +67 -0
  144. package/dist/tools/anthropic/index.d.ts +67 -0
  145. package/dist/tools/anthropic/index.js +56 -0
  146. package/dist/tools/anthropic/index.js.map +1 -0
  147. package/dist/tools/brave/index.cjs +85 -0
  148. package/dist/tools/brave/index.cjs.map +1 -0
  149. package/dist/tools/brave/index.d.cts +91 -0
  150. package/dist/tools/brave/index.d.ts +91 -0
  151. package/dist/tools/brave/index.js +80 -0
  152. package/dist/tools/brave/index.js.map +1 -0
  153. package/dist/tools/exa/index.cjs +90 -0
  154. package/dist/tools/exa/index.cjs.map +1 -0
  155. package/dist/tools/exa/index.d.cts +92 -0
  156. package/dist/tools/exa/index.d.ts +92 -0
  157. package/dist/tools/exa/index.js +85 -0
  158. package/dist/tools/exa/index.js.map +1 -0
  159. package/dist/tools/google/index.cjs +81 -0
  160. package/dist/tools/google/index.cjs.map +1 -0
  161. package/dist/tools/google/index.d.cts +81 -0
  162. package/dist/tools/google/index.d.ts +81 -0
  163. package/dist/tools/google/index.js +76 -0
  164. package/dist/tools/google/index.js.map +1 -0
  165. package/dist/tools/openai/index.cjs +83 -0
  166. package/dist/tools/openai/index.cjs.map +1 -0
  167. package/dist/tools/openai/index.d.cts +84 -0
  168. package/dist/tools/openai/index.d.ts +84 -0
  169. package/dist/tools/openai/index.js +78 -0
  170. package/dist/tools/openai/index.js.map +1 -0
  171. package/dist/tools/searxng/index.cjs +85 -0
  172. package/dist/tools/searxng/index.cjs.map +1 -0
  173. package/dist/tools/searxng/index.d.cts +91 -0
  174. package/dist/tools/searxng/index.d.ts +91 -0
  175. package/dist/tools/searxng/index.js +80 -0
  176. package/dist/tools/searxng/index.js.map +1 -0
  177. package/dist/tools/serper/index.cjs +85 -0
  178. package/dist/tools/serper/index.cjs.map +1 -0
  179. package/dist/tools/serper/index.d.cts +91 -0
  180. package/dist/tools/serper/index.d.ts +91 -0
  181. package/dist/tools/serper/index.js +80 -0
  182. package/dist/tools/serper/index.js.map +1 -0
  183. package/dist/tools/tavily/index.cjs +91 -0
  184. package/dist/tools/tavily/index.cjs.map +1 -0
  185. package/dist/tools/tavily/index.d.cts +95 -0
  186. package/dist/tools/tavily/index.d.ts +95 -0
  187. package/dist/tools/tavily/index.js +86 -0
  188. package/dist/tools/tavily/index.js.map +1 -0
  189. package/dist/tools/web-search/index.cjs +31 -0
  190. package/dist/tools/web-search/index.cjs.map +1 -0
  191. package/dist/tools/web-search/index.d.cts +3 -0
  192. package/dist/tools/web-search/index.d.ts +3 -0
  193. package/dist/tools/web-search/index.js +14 -0
  194. package/dist/tools/web-search/index.js.map +1 -0
  195. package/dist/{types-BtAaOV07.d.cts → tools-DDWrco4h.d.cts} +43 -367
  196. package/dist/{types-BtAaOV07.d.ts → tools-DDWrco4h.d.ts} +43 -367
  197. package/dist/types-B20VCJXL.d.cts +347 -0
  198. package/dist/types-B20VCJXL.d.ts +347 -0
  199. package/dist/types-Cizh9K_f.d.ts +441 -0
  200. package/dist/types-DG2ya08y.d.cts +367 -0
  201. package/dist/types-DG2ya08y.d.ts +367 -0
  202. package/dist/types-DjSfYNKj.d.cts +441 -0
  203. package/dist/types-ZguuKEs_.d.cts +127 -0
  204. package/dist/types-ZguuKEs_.d.ts +127 -0
  205. package/dist/ui/index.cjs +1075 -148
  206. package/dist/ui/index.cjs.map +1 -1
  207. package/dist/ui/index.d.cts +410 -4
  208. package/dist/ui/index.d.ts +410 -4
  209. package/dist/ui/index.js +1007 -96
  210. package/dist/ui/index.js.map +1 -1
  211. package/package.json +52 -2
  212. package/dist/chunk-4PRWNAXQ.cjs.map +0 -1
  213. package/dist/chunk-BLSI67J6.cjs.map +0 -1
  214. package/dist/chunk-CJ7UWN2Y.js.map +0 -1
  215. package/dist/chunk-JM7PB2LP.js.map +0 -1
package/dist/ui/index.js CHANGED
@@ -1,10 +1,24 @@
1
- import { useCopilot, useThreadManager } from '../chunk-CJ7UWN2Y.js';
2
- import { createServerAdapter } from '../chunk-JM7PB2LP.js';
1
+ import { useCopilot, useThreadManager } from '../chunk-IXFV6AW6.js';
2
+ import { createServerAdapter } from '../chunk-7XFFRV7D.js';
3
+ import { DEFAULT_MCP_UI_SANDBOX, parseMCPUIMessage } from '../chunk-G4SF2PNQ.js';
4
+ import '../chunk-BH7MNDWW.js';
5
+ import '../chunk-ZPYQDMUX.js';
6
+ import '../chunk-BKO7DSPU.js';
7
+ import '../chunk-XGITAEXU.js';
8
+ import '../chunk-7W7QLZNC.js';
9
+ import '../chunk-CEOMTQTP.js';
10
+ import '../chunk-PPFHA6IL.js';
11
+ import '../chunk-DABZYCVX.js';
12
+ import '../chunk-MNDGIW47.js';
13
+ import '../chunk-VD74IPKB.js';
14
+ import '../chunk-53UGJNHN.js';
15
+ import '../chunk-RQ74USYU.js';
16
+ import '../chunk-DGUM43GV.js';
3
17
  import { clsx } from 'clsx';
4
18
  import { twMerge } from 'tailwind-merge';
5
19
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
6
- import * as React18 from 'react';
7
- import React18__default, { memo, createContext, useState, useRef, useId, useCallback, useLayoutEffect, useContext, useEffect } from 'react';
20
+ import * as React20 from 'react';
21
+ import React20__default, { memo, createContext, useState, useRef, useId, useCallback, useLayoutEffect, useContext, useEffect } from 'react';
8
22
  import { Streamdown } from 'streamdown';
9
23
  import { code } from '@streamdown/code';
10
24
  import { Slot } from '@radix-ui/react-slot';
@@ -13,6 +27,7 @@ import { StickToBottom as StickToBottom$1, useStickToBottomContext } from 'use-s
13
27
  import { Tooltip as Tooltip$1 } from '@base-ui/react/tooltip';
14
28
  import * as AvatarPrimitive from '@radix-ui/react-avatar';
15
29
  import * as HoverCardPrimitive from '@radix-ui/react-hover-card';
30
+ import { Globe, ChevronUp, ChevronDown, ExternalLink } from 'lucide-react';
16
31
  import { Popover as Popover$1 } from '@base-ui/react/popover';
17
32
 
18
33
  function cn(...inputs) {
@@ -366,7 +381,7 @@ var buttonVariants = cva(
366
381
  }
367
382
  }
368
383
  );
369
- var Button = React18.forwardRef(
384
+ var Button = React20.forwardRef(
370
385
  ({ className, variant, size, asChild = false, ...props }, ref) => {
371
386
  const Comp = asChild ? Slot : "button";
372
387
  return /* @__PURE__ */ jsx(
@@ -509,7 +524,7 @@ function ChatContainerRoot({
509
524
  return /* @__PURE__ */ jsx(
510
525
  StickToBottom,
511
526
  {
512
- className: cn("flex overflow-y-auto", className),
527
+ className: cn("min-h-0", className),
513
528
  resize: "smooth",
514
529
  initial: "instant",
515
530
  role: "log",
@@ -607,7 +622,7 @@ function TooltipTrigger({
607
622
  disabled,
608
623
  ...props
609
624
  }) {
610
- if (asChild && React18__default.isValidElement(children)) {
625
+ if (asChild && React20__default.isValidElement(children)) {
611
626
  return /* @__PURE__ */ jsx(Tooltip$1.Trigger, { disabled, render: children, ...props });
612
627
  }
613
628
  return /* @__PURE__ */ jsx(Tooltip$1.Trigger, { disabled, ...props, children });
@@ -636,7 +651,7 @@ function TooltipContent({
636
651
  }
637
652
  ) }) });
638
653
  }
639
- var Avatar = React18.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
654
+ var Avatar = React20.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
640
655
  AvatarPrimitive.Root,
641
656
  {
642
657
  ref,
@@ -648,7 +663,7 @@ var Avatar = React18.forwardRef(({ className, ...props }, ref) => /* @__PURE__ *
648
663
  }
649
664
  ));
650
665
  Avatar.displayName = AvatarPrimitive.Root.displayName;
651
- var AvatarImage = React18.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
666
+ var AvatarImage = React20.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
652
667
  AvatarPrimitive.Image,
653
668
  {
654
669
  ref,
@@ -657,7 +672,7 @@ var AvatarImage = React18.forwardRef(({ className, ...props }, ref) => /* @__PUR
657
672
  }
658
673
  ));
659
674
  AvatarImage.displayName = AvatarPrimitive.Image.displayName;
660
- var AvatarFallback = React18.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
675
+ var AvatarFallback = React20.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
661
676
  AvatarPrimitive.Fallback,
662
677
  {
663
678
  ref,
@@ -700,7 +715,7 @@ var MessageContent = ({
700
715
  ...props
701
716
  }) => {
702
717
  const classNames = cn(
703
- "csdk-message-content rounded-lg p-2 break-words whitespace-normal max-w-none leading-relaxed",
718
+ "csdk-message-content rounded-lg p-2 break-words whitespace-normal max-w-full leading-relaxed overflow-x-auto overflow-y-hidden",
704
719
  // Typography - simple Tailwind utilities (no prose)
705
720
  "[&_p]:my-1 [&_p]:leading-relaxed",
706
721
  "[&_ul]:my-1 [&_ul]:pl-4 [&_ul]:list-disc [&_ul]:list-outside",
@@ -708,14 +723,16 @@ var MessageContent = ({
708
723
  "[&_li]:my-0.5 [&_li]:pl-0",
709
724
  "[&_pre]:my-2 [&_blockquote]:my-2 [&_blockquote]:pl-3 [&_blockquote]:border-l-2 [&_blockquote]:border-current/30",
710
725
  "[&_code]:bg-current/10 [&_code]:px-1 [&_code]:rounded [&_code]:text-[0.9em]",
711
- "[&_a]:underline",
726
+ "[&_a]:underline [&_a]:text-[var(--csdk-link-color)] [&_a]:[overflow-wrap:anywhere]",
727
+ "[&_button[data-streamdown='link']]:underline [&_button[data-streamdown='link']]:text-[var(--csdk-link-color)] [&_button[data-streamdown='link']]:[overflow-wrap:anywhere] [&_button[data-streamdown='link']]:font-medium",
728
+ "[&_.text-primary]:text-[var(--csdk-link-color)]",
712
729
  "[&_strong]:font-semibold",
713
730
  textSizeMap[size],
714
731
  className
715
732
  );
716
733
  return markdown ? /* @__PURE__ */ jsx(Markdown, { className: classNames, ...props, children }) : /* @__PURE__ */ jsx("div", { className: classNames, ...props, children });
717
734
  };
718
- var Textarea = React18.forwardRef(({ className, ...props }, ref) => {
735
+ var Textarea = React20.forwardRef(({ className, ...props }, ref) => {
719
736
  return /* @__PURE__ */ jsx(
720
737
  "textarea",
721
738
  {
@@ -879,14 +896,14 @@ function PromptInputAction({
879
896
  }
880
897
  var HoverCard = HoverCardPrimitive.Root;
881
898
  var HoverCardTrigger = HoverCardPrimitive.Trigger;
882
- var HoverCardContent = React18.forwardRef(({ className, align = "center", sideOffset = 4, ...props }, ref) => /* @__PURE__ */ jsx(
899
+ var HoverCardContent = React20.forwardRef(({ className, align = "center", sideOffset = 4, ...props }, ref) => /* @__PURE__ */ jsx(
883
900
  HoverCardPrimitive.Content,
884
901
  {
885
902
  ref,
886
903
  align,
887
904
  sideOffset,
888
905
  className: cn(
889
- "z-50 w-64 rounded-md border bg-popover p-4 text-popover-foreground shadow-md outline-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 origin-[--radix-hover-card-content-transform-origin]",
906
+ "z-50 w-64 rounded-md border bg-popover p-4 text-popover-foreground shadow-md outline-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
890
907
  className
891
908
  ),
892
909
  ...props
@@ -922,8 +939,8 @@ function SourceTrigger({
922
939
  target: "_blank",
923
940
  rel: "noopener noreferrer",
924
941
  className: cn(
925
- "bg-muted text-muted-foreground hover:bg-muted-foreground/30 hover:text-primary inline-flex h-5 max-w-32 items-center gap-1 overflow-hidden rounded-full py-0 text-xs no-underline transition-colors duration-150",
926
- showFavicon ? "pr-2 pl-1" : "px-1",
942
+ "inline-flex h-7 items-center gap-1.5 rounded-full border border-border/50 bg-background px-2.5 text-xs text-foreground/80 no-underline shadow-sm transition-all duration-150",
943
+ "hover:bg-muted hover:border-border hover:shadow-md hover:text-foreground",
927
944
  className
928
945
  ),
929
946
  children: [
@@ -933,13 +950,13 @@ function SourceTrigger({
933
950
  src: `https://www.google.com/s2/favicons?sz=64&domain_url=${encodeURIComponent(
934
951
  href
935
952
  )}`,
936
- alt: "favicon",
937
- width: 14,
938
- height: 14,
939
- className: "size-3.5 rounded-full"
953
+ alt: "",
954
+ width: 16,
955
+ height: 16,
956
+ className: "size-4 rounded-full"
940
957
  }
941
958
  ),
942
- /* @__PURE__ */ jsx("span", { className: "truncate tabular-nums text-center font-normal", children: labelToShow })
959
+ /* @__PURE__ */ jsx("span", { className: "truncate max-w-28 font-medium", children: labelToShow })
943
960
  ]
944
961
  }
945
962
  ) });
@@ -950,40 +967,627 @@ function SourceContent({
950
967
  className
951
968
  }) {
952
969
  const { href, domain } = useSourceContext();
953
- return /* @__PURE__ */ jsx(HoverCardContent, { className: cn("w-80 p-0 shadow-xs", className), children: /* @__PURE__ */ jsxs(
970
+ return /* @__PURE__ */ jsx(
971
+ HoverCardContent,
972
+ {
973
+ className: cn("w-80 p-0 shadow-lg border border-border/50", className),
974
+ sideOffset: 8,
975
+ children: /* @__PURE__ */ jsxs(
976
+ "a",
977
+ {
978
+ href,
979
+ target: "_blank",
980
+ rel: "noopener noreferrer",
981
+ className: "flex flex-col gap-2.5 p-4 hover:bg-muted/50 transition-colors rounded-lg",
982
+ children: [
983
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
984
+ /* @__PURE__ */ jsx(
985
+ "img",
986
+ {
987
+ src: `https://www.google.com/s2/favicons?sz=64&domain_url=${encodeURIComponent(
988
+ href
989
+ )}`,
990
+ alt: "",
991
+ className: "size-5 rounded-full",
992
+ width: 20,
993
+ height: 20
994
+ }
995
+ ),
996
+ /* @__PURE__ */ jsx("div", { className: "text-foreground/70 truncate text-sm", children: domain.replace("www.", "") })
997
+ ] }),
998
+ /* @__PURE__ */ jsx("div", { className: "line-clamp-2 text-sm font-semibold text-foreground", children: title }),
999
+ description && /* @__PURE__ */ jsx("div", { className: "text-muted-foreground line-clamp-3 text-sm leading-relaxed", children: description })
1000
+ ]
1001
+ }
1002
+ )
1003
+ }
1004
+ );
1005
+ }
1006
+ function SourceGroup({
1007
+ sources,
1008
+ label,
1009
+ maxVisible = 5,
1010
+ showFavicon = true,
1011
+ numbered = false,
1012
+ className
1013
+ }) {
1014
+ if (!sources || sources.length === 0) return null;
1015
+ const visibleSources = sources.slice(0, maxVisible);
1016
+ const hiddenCount = sources.length - maxVisible;
1017
+ return /* @__PURE__ */ jsxs("div", { className: cn("flex flex-wrap items-center gap-2", className), children: [
1018
+ label && /* @__PURE__ */ jsx("span", { className: "text-muted-foreground text-xs font-medium", children: label }),
1019
+ visibleSources.map((source, index) => /* @__PURE__ */ jsxs(Source, { href: source.href, children: [
1020
+ /* @__PURE__ */ jsx(
1021
+ SourceTrigger,
1022
+ {
1023
+ label: numbered ? index + 1 : void 0,
1024
+ showFavicon
1025
+ }
1026
+ ),
1027
+ (source.title || source.description) && /* @__PURE__ */ jsx(
1028
+ SourceContent,
1029
+ {
1030
+ title: source.title || getDomain(source.href),
1031
+ description: source.description || source.href
1032
+ }
1033
+ )
1034
+ ] }, index)),
1035
+ hiddenCount > 0 && /* @__PURE__ */ jsxs("span", { className: "text-muted-foreground text-xs font-medium bg-muted px-2 py-1 rounded-full", children: [
1036
+ "+",
1037
+ hiddenCount,
1038
+ " more"
1039
+ ] })
1040
+ ] });
1041
+ }
1042
+ function SimpleSource({
1043
+ href,
1044
+ label,
1045
+ showFavicon = false,
1046
+ className
1047
+ }) {
1048
+ let domain = "";
1049
+ try {
1050
+ domain = new URL(href).hostname.replace("www.", "");
1051
+ } catch {
1052
+ domain = href;
1053
+ }
1054
+ const displayLabel = label ?? domain;
1055
+ return /* @__PURE__ */ jsxs(
954
1056
  "a",
955
1057
  {
956
1058
  href,
957
1059
  target: "_blank",
958
1060
  rel: "noopener noreferrer",
959
- className: "flex flex-col gap-2 p-3",
1061
+ className: cn(
1062
+ "bg-muted text-muted-foreground hover:bg-primary/20 hover:text-primary",
1063
+ "inline-flex h-5 items-center gap-1 rounded-full text-xs no-underline transition-colors",
1064
+ showFavicon ? "pr-2 pl-1" : "px-1.5",
1065
+ className
1066
+ ),
960
1067
  children: [
961
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5", children: [
962
- /* @__PURE__ */ jsx(
963
- "img",
964
- {
965
- src: `https://www.google.com/s2/favicons?sz=64&domain_url=${encodeURIComponent(
966
- href
967
- )}`,
968
- alt: "favicon",
969
- className: "size-4 rounded-full",
970
- width: 16,
971
- height: 16
1068
+ showFavicon && /* @__PURE__ */ jsx(
1069
+ "img",
1070
+ {
1071
+ src: `https://www.google.com/s2/favicons?sz=64&domain_url=${encodeURIComponent(href)}`,
1072
+ alt: "",
1073
+ width: 14,
1074
+ height: 14,
1075
+ className: "size-3.5 rounded-full"
1076
+ }
1077
+ ),
1078
+ /* @__PURE__ */ jsx("span", { className: "truncate tabular-nums font-normal", children: displayLabel })
1079
+ ]
1080
+ }
1081
+ );
1082
+ }
1083
+ function getDomain(url) {
1084
+ try {
1085
+ return new URL(url).hostname.replace("www.", "");
1086
+ } catch {
1087
+ return url;
1088
+ }
1089
+ }
1090
+ function SearchResults({
1091
+ results,
1092
+ className,
1093
+ variant = "cards",
1094
+ maxResults,
1095
+ showScores = false,
1096
+ showDates = false
1097
+ }) {
1098
+ const displayResults = maxResults ? results.slice(0, maxResults) : results;
1099
+ if (displayResults.length === 0) {
1100
+ return /* @__PURE__ */ jsx("div", { className: cn("text-muted-foreground text-sm", className), children: "No results found" });
1101
+ }
1102
+ if (variant === "compact") {
1103
+ return /* @__PURE__ */ jsx("div", { className: cn("flex flex-wrap gap-2", className), children: displayResults.map((result, i) => /* @__PURE__ */ jsx(SearchResultCompact, { result, index: i + 1 }, i)) });
1104
+ }
1105
+ if (variant === "list") {
1106
+ return /* @__PURE__ */ jsx("div", { className: cn("space-y-2", className), children: displayResults.map((result, i) => /* @__PURE__ */ jsx(
1107
+ SearchResultList,
1108
+ {
1109
+ result,
1110
+ index: i + 1,
1111
+ showScore: showScores,
1112
+ showDate: showDates
1113
+ },
1114
+ i
1115
+ )) });
1116
+ }
1117
+ return /* @__PURE__ */ jsx("div", { className: cn("grid gap-2", className), children: displayResults.map((result, i) => /* @__PURE__ */ jsx(
1118
+ SearchResultCard,
1119
+ {
1120
+ result,
1121
+ showScore: showScores,
1122
+ showDate: showDates
1123
+ },
1124
+ i
1125
+ )) });
1126
+ }
1127
+ function SearchResultCard({
1128
+ result,
1129
+ showScore,
1130
+ showDate
1131
+ }) {
1132
+ const domain = result.domain || getDomain2(result.url);
1133
+ return /* @__PURE__ */ jsx(
1134
+ "a",
1135
+ {
1136
+ href: result.url,
1137
+ target: "_blank",
1138
+ rel: "noopener noreferrer",
1139
+ className: "group block p-3 border rounded-lg hover:bg-muted/50 transition-colors",
1140
+ children: /* @__PURE__ */ jsxs("div", { className: "flex items-start gap-3", children: [
1141
+ /* @__PURE__ */ jsx(
1142
+ "img",
1143
+ {
1144
+ src: getFaviconUrl(result.url),
1145
+ alt: "",
1146
+ className: "w-5 h-5 mt-0.5 rounded-sm",
1147
+ width: 20,
1148
+ height: 20
1149
+ }
1150
+ ),
1151
+ /* @__PURE__ */ jsxs("div", { className: "flex-1 min-w-0", children: [
1152
+ /* @__PURE__ */ jsx("h4", { className: "font-medium text-sm group-hover:text-primary truncate", children: result.title }),
1153
+ /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground mt-1 line-clamp-2", children: result.content }),
1154
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 mt-1", children: [
1155
+ /* @__PURE__ */ jsx("span", { className: "text-xs text-muted-foreground/60 truncate", children: domain }),
1156
+ showDate && result.publishedDate && /* @__PURE__ */ jsx("span", { className: "text-xs text-muted-foreground/60", children: formatDate(result.publishedDate) }),
1157
+ showScore && result.score !== void 0 && /* @__PURE__ */ jsxs("span", { className: "text-xs text-muted-foreground/60", children: [
1158
+ (result.score * 100).toFixed(0),
1159
+ "% match"
1160
+ ] })
1161
+ ] })
1162
+ ] })
1163
+ ] })
1164
+ }
1165
+ );
1166
+ }
1167
+ function SearchResultList({
1168
+ result,
1169
+ index,
1170
+ showScore,
1171
+ showDate
1172
+ }) {
1173
+ const domain = result.domain || getDomain2(result.url);
1174
+ return /* @__PURE__ */ jsxs(
1175
+ "a",
1176
+ {
1177
+ href: result.url,
1178
+ target: "_blank",
1179
+ rel: "noopener noreferrer",
1180
+ className: "group flex items-start gap-2 py-1.5 hover:bg-muted/30 rounded px-1 -mx-1 transition-colors",
1181
+ children: [
1182
+ /* @__PURE__ */ jsxs("span", { className: "text-xs text-muted-foreground/60 mt-0.5 w-4 text-right flex-shrink-0", children: [
1183
+ index,
1184
+ "."
1185
+ ] }),
1186
+ /* @__PURE__ */ jsx(
1187
+ "img",
1188
+ {
1189
+ src: getFaviconUrl(result.url),
1190
+ alt: "",
1191
+ className: "w-4 h-4 mt-0.5 rounded-sm flex-shrink-0",
1192
+ width: 16,
1193
+ height: 16
1194
+ }
1195
+ ),
1196
+ /* @__PURE__ */ jsxs("div", { className: "flex-1 min-w-0", children: [
1197
+ /* @__PURE__ */ jsx("span", { className: "text-sm group-hover:text-primary", children: result.title }),
1198
+ /* @__PURE__ */ jsx("span", { className: "text-xs text-muted-foreground ml-2", children: domain }),
1199
+ showDate && result.publishedDate && /* @__PURE__ */ jsx("span", { className: "text-xs text-muted-foreground/60 ml-2", children: formatDate(result.publishedDate) }),
1200
+ showScore && result.score !== void 0 && /* @__PURE__ */ jsxs("span", { className: "text-xs text-muted-foreground/60 ml-2", children: [
1201
+ "(",
1202
+ (result.score * 100).toFixed(0),
1203
+ "%)"
1204
+ ] })
1205
+ ] })
1206
+ ]
1207
+ }
1208
+ );
1209
+ }
1210
+ function SearchResultCompact({ result, index }) {
1211
+ const domain = result.domain || getDomain2(result.url);
1212
+ return /* @__PURE__ */ jsxs(
1213
+ "a",
1214
+ {
1215
+ href: result.url,
1216
+ target: "_blank",
1217
+ rel: "noopener noreferrer",
1218
+ className: "inline-flex items-center gap-1.5 px-2 py-1 text-xs bg-muted hover:bg-muted/80 rounded-md transition-colors",
1219
+ title: result.title,
1220
+ children: [
1221
+ /* @__PURE__ */ jsx(
1222
+ "img",
1223
+ {
1224
+ src: getFaviconUrl(result.url),
1225
+ alt: "",
1226
+ className: "w-3.5 h-3.5 rounded-sm",
1227
+ width: 14,
1228
+ height: 14
1229
+ }
1230
+ ),
1231
+ /* @__PURE__ */ jsx("span", { className: "truncate max-w-[120px]", children: domain })
1232
+ ]
1233
+ }
1234
+ );
1235
+ }
1236
+ function SearchAnswer({ answer, className }) {
1237
+ return /* @__PURE__ */ jsx(
1238
+ "div",
1239
+ {
1240
+ className: cn(
1241
+ "p-3 bg-muted/50 rounded-lg border-l-2 border-primary/50",
1242
+ className
1243
+ ),
1244
+ children: /* @__PURE__ */ jsx("p", { className: "text-sm", children: answer })
1245
+ }
1246
+ );
1247
+ }
1248
+ function SearchResultsWithAnswer({
1249
+ response,
1250
+ className,
1251
+ variant = "cards",
1252
+ showAnswer = true,
1253
+ maxResults
1254
+ }) {
1255
+ return /* @__PURE__ */ jsxs("div", { className: cn("space-y-3", className), children: [
1256
+ showAnswer && response.answer && /* @__PURE__ */ jsx(SearchAnswer, { answer: response.answer }),
1257
+ /* @__PURE__ */ jsx(
1258
+ SearchResults,
1259
+ {
1260
+ results: response.results,
1261
+ variant,
1262
+ maxResults
1263
+ }
1264
+ ),
1265
+ response.searchTime && /* @__PURE__ */ jsxs("p", { className: "text-xs text-muted-foreground", children: [
1266
+ "Found ",
1267
+ response.results.length,
1268
+ " results in ",
1269
+ response.searchTime,
1270
+ "ms"
1271
+ ] })
1272
+ ] });
1273
+ }
1274
+ function getDomain2(url) {
1275
+ try {
1276
+ return new URL(url).hostname.replace("www.", "");
1277
+ } catch {
1278
+ return url;
1279
+ }
1280
+ }
1281
+ function getFaviconUrl(url) {
1282
+ try {
1283
+ const domain = new URL(url).hostname;
1284
+ return `https://www.google.com/s2/favicons?domain=${domain}&sz=32`;
1285
+ } catch {
1286
+ return "";
1287
+ }
1288
+ }
1289
+ function formatDate(dateStr) {
1290
+ try {
1291
+ const date = new Date(dateStr);
1292
+ const now = /* @__PURE__ */ new Date();
1293
+ const diffMs = now.getTime() - date.getTime();
1294
+ const diffDays = Math.floor(diffMs / (1e3 * 60 * 60 * 24));
1295
+ if (diffDays === 0) return "Today";
1296
+ if (diffDays === 1) return "Yesterday";
1297
+ if (diffDays < 7) return `${diffDays} days ago`;
1298
+ if (diffDays < 30) return `${Math.floor(diffDays / 7)} weeks ago`;
1299
+ if (diffDays < 365) return `${Math.floor(diffDays / 30)} months ago`;
1300
+ return `${Math.floor(diffDays / 365)} years ago`;
1301
+ } catch {
1302
+ return dateStr;
1303
+ }
1304
+ }
1305
+ function CitationBadge({
1306
+ index,
1307
+ url,
1308
+ title,
1309
+ size = "sm",
1310
+ className,
1311
+ onClick
1312
+ }) {
1313
+ const sizeClasses = {
1314
+ sm: "text-[10px] min-w-[16px] h-4 px-1",
1315
+ md: "text-xs min-w-[20px] h-5 px-1.5"
1316
+ };
1317
+ const badge = /* @__PURE__ */ jsx(
1318
+ "span",
1319
+ {
1320
+ className: cn(
1321
+ "inline-flex items-center justify-center rounded font-medium",
1322
+ "bg-primary/10 text-primary hover:bg-primary/20",
1323
+ "cursor-pointer transition-colors",
1324
+ sizeClasses[size],
1325
+ className
1326
+ ),
1327
+ title,
1328
+ onClick,
1329
+ children: index
1330
+ }
1331
+ );
1332
+ if (url) {
1333
+ return /* @__PURE__ */ jsx(
1334
+ "a",
1335
+ {
1336
+ href: url,
1337
+ target: "_blank",
1338
+ rel: "noopener noreferrer",
1339
+ className: "inline-flex",
1340
+ children: badge
1341
+ }
1342
+ );
1343
+ }
1344
+ return badge;
1345
+ }
1346
+ function CitationSuperscript({
1347
+ index,
1348
+ url,
1349
+ title,
1350
+ className
1351
+ }) {
1352
+ const sup = /* @__PURE__ */ jsxs(
1353
+ "sup",
1354
+ {
1355
+ className: cn(
1356
+ "text-[10px] text-primary hover:underline cursor-pointer ml-0.5",
1357
+ className
1358
+ ),
1359
+ title,
1360
+ children: [
1361
+ "[",
1362
+ index,
1363
+ "]"
1364
+ ]
1365
+ }
1366
+ );
1367
+ if (url) {
1368
+ return /* @__PURE__ */ jsx("a", { href: url, target: "_blank", rel: "noopener noreferrer", children: sup });
1369
+ }
1370
+ return sup;
1371
+ }
1372
+ function SourcePill({
1373
+ citation,
1374
+ showIndex = true,
1375
+ className
1376
+ }) {
1377
+ const domain = citation.domain || getDomain3(citation.url);
1378
+ const favicon = citation.favicon || getFaviconUrl2(citation.url);
1379
+ return /* @__PURE__ */ jsxs(
1380
+ "a",
1381
+ {
1382
+ href: citation.url,
1383
+ target: "_blank",
1384
+ rel: "noopener noreferrer",
1385
+ title: citation.title,
1386
+ className: cn(
1387
+ "inline-flex items-center gap-1.5 px-2 py-1 text-xs rounded-full",
1388
+ "bg-muted hover:bg-muted/80 transition-colors",
1389
+ "text-muted-foreground hover:text-foreground",
1390
+ className
1391
+ ),
1392
+ children: [
1393
+ showIndex && /* @__PURE__ */ jsx("span", { className: "text-[10px] font-medium text-primary", children: citation.index }),
1394
+ /* @__PURE__ */ jsx(
1395
+ "img",
1396
+ {
1397
+ src: favicon,
1398
+ alt: "",
1399
+ className: "w-3.5 h-3.5 rounded-sm",
1400
+ width: 14,
1401
+ height: 14,
1402
+ onError: (e) => {
1403
+ e.target.style.display = "none";
972
1404
  }
973
- ),
974
- /* @__PURE__ */ jsx("div", { className: "text-primary truncate text-sm", children: domain.replace("www.", "") })
1405
+ }
1406
+ ),
1407
+ /* @__PURE__ */ jsx("span", { className: "truncate max-w-[100px]", children: domain })
1408
+ ]
1409
+ }
1410
+ );
1411
+ }
1412
+ function SourcesBar({
1413
+ citations,
1414
+ label = "Sources",
1415
+ maxVisible = 5,
1416
+ className
1417
+ }) {
1418
+ const visibleCitations = citations.slice(0, maxVisible);
1419
+ const hiddenCount = citations.length - maxVisible;
1420
+ if (citations.length === 0) return null;
1421
+ return /* @__PURE__ */ jsxs("div", { className: cn("flex items-center gap-2", className), children: [
1422
+ /* @__PURE__ */ jsxs("span", { className: "text-xs text-muted-foreground flex items-center gap-1", children: [
1423
+ /* @__PURE__ */ jsx(Globe, { className: "w-3 h-3" }),
1424
+ label
1425
+ ] }),
1426
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5 overflow-x-auto", children: [
1427
+ visibleCitations.map((citation) => /* @__PURE__ */ jsx(SourcePill, { citation }, citation.index)),
1428
+ hiddenCount > 0 && /* @__PURE__ */ jsxs("span", { className: "text-xs text-muted-foreground px-2", children: [
1429
+ "+",
1430
+ hiddenCount,
1431
+ " more"
1432
+ ] })
1433
+ ] })
1434
+ ] });
1435
+ }
1436
+ function SourcesCollapsible({
1437
+ citations,
1438
+ label = "Sources",
1439
+ defaultExpanded = false,
1440
+ className
1441
+ }) {
1442
+ const [expanded, setExpanded] = React20.useState(defaultExpanded);
1443
+ if (citations.length === 0) return null;
1444
+ return /* @__PURE__ */ jsxs("div", { className: cn("border rounded-lg", className), children: [
1445
+ /* @__PURE__ */ jsxs(
1446
+ "button",
1447
+ {
1448
+ onClick: () => setExpanded(!expanded),
1449
+ className: "w-full flex items-center justify-between px-3 py-2 text-sm hover:bg-muted/50 transition-colors",
1450
+ children: [
1451
+ /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-2 text-muted-foreground", children: [
1452
+ /* @__PURE__ */ jsx(Globe, { className: "w-4 h-4" }),
1453
+ label,
1454
+ " (",
1455
+ citations.length,
1456
+ ")"
1457
+ ] }),
1458
+ expanded ? /* @__PURE__ */ jsx(ChevronUp, { className: "w-4 h-4 text-muted-foreground" }) : /* @__PURE__ */ jsx(ChevronDown, { className: "w-4 h-4 text-muted-foreground" })
1459
+ ]
1460
+ }
1461
+ ),
1462
+ expanded && /* @__PURE__ */ jsx("div", { className: "px-3 pb-3 space-y-2", children: citations.map((citation) => /* @__PURE__ */ jsx(SourceItem, { citation }, citation.index)) })
1463
+ ] });
1464
+ }
1465
+ function SourceItem({ citation }) {
1466
+ const domain = citation.domain || getDomain3(citation.url);
1467
+ const favicon = citation.favicon || getFaviconUrl2(citation.url);
1468
+ return /* @__PURE__ */ jsxs(
1469
+ "a",
1470
+ {
1471
+ href: citation.url,
1472
+ target: "_blank",
1473
+ rel: "noopener noreferrer",
1474
+ className: "flex items-start gap-3 p-2 rounded-md hover:bg-muted/50 transition-colors group",
1475
+ children: [
1476
+ /* @__PURE__ */ jsx("span", { className: "flex items-center justify-center w-5 h-5 rounded bg-primary/10 text-primary text-xs font-medium flex-shrink-0", children: citation.index }),
1477
+ /* @__PURE__ */ jsx(
1478
+ "img",
1479
+ {
1480
+ src: favicon,
1481
+ alt: "",
1482
+ className: "w-4 h-4 mt-0.5 rounded-sm flex-shrink-0",
1483
+ width: 16,
1484
+ height: 16,
1485
+ onError: (e) => {
1486
+ e.target.style.display = "none";
1487
+ }
1488
+ }
1489
+ ),
1490
+ /* @__PURE__ */ jsxs("div", { className: "flex-1 min-w-0", children: [
1491
+ /* @__PURE__ */ jsx("p", { className: "text-sm font-medium group-hover:text-primary truncate", children: citation.title }),
1492
+ /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground truncate", children: domain })
975
1493
  ] }),
976
- /* @__PURE__ */ jsx("div", { className: "line-clamp-2 text-sm font-medium", children: title }),
977
- /* @__PURE__ */ jsx("div", { className: "text-muted-foreground line-clamp-2 text-sm", children: description })
1494
+ /* @__PURE__ */ jsx(ExternalLink, { className: "w-3.5 h-3.5 text-muted-foreground opacity-0 group-hover:opacity-100 transition-opacity flex-shrink-0" })
978
1495
  ]
979
1496
  }
980
- ) });
1497
+ );
1498
+ }
1499
+ function SourcesList({
1500
+ citations,
1501
+ className,
1502
+ compact = false
1503
+ }) {
1504
+ if (citations.length === 0) return null;
1505
+ if (compact) {
1506
+ return /* @__PURE__ */ jsxs("div", { className: cn("text-xs text-muted-foreground", className), children: [
1507
+ /* @__PURE__ */ jsx("span", { className: "font-medium", children: "Sources: " }),
1508
+ citations.map((c, i) => /* @__PURE__ */ jsxs(React20.Fragment, { children: [
1509
+ /* @__PURE__ */ jsxs(
1510
+ "a",
1511
+ {
1512
+ href: c.url,
1513
+ target: "_blank",
1514
+ rel: "noopener noreferrer",
1515
+ className: "hover:text-primary hover:underline",
1516
+ children: [
1517
+ "[",
1518
+ c.index,
1519
+ "]"
1520
+ ]
1521
+ }
1522
+ ),
1523
+ i < citations.length - 1 && " "
1524
+ ] }, c.index))
1525
+ ] });
1526
+ }
1527
+ return /* @__PURE__ */ jsx("div", { className: cn("space-y-1", className), children: citations.map((citation) => /* @__PURE__ */ jsx(SourceItem, { citation }, citation.index)) });
981
1528
  }
982
- var ReasoningContext = React18.createContext(
1529
+ function MessageWithCitations({
1530
+ children,
1531
+ citations,
1532
+ config = {},
1533
+ className
1534
+ }) {
1535
+ const { enabled = true, sourcesPosition = "bottom", maxVisible = 5 } = config;
1536
+ if (!enabled || citations.length === 0) {
1537
+ return /* @__PURE__ */ jsx("div", { className, children });
1538
+ }
1539
+ return /* @__PURE__ */ jsxs("div", { className: cn("space-y-3", className), children: [
1540
+ /* @__PURE__ */ jsx("div", { children }),
1541
+ sourcesPosition === "bottom" && /* @__PURE__ */ jsx(SourcesBar, { citations, maxVisible }),
1542
+ sourcesPosition === "collapsible" && /* @__PURE__ */ jsx(SourcesCollapsible, { citations })
1543
+ ] });
1544
+ }
1545
+ function getDomain3(url) {
1546
+ try {
1547
+ return new URL(url).hostname.replace("www.", "");
1548
+ } catch {
1549
+ return url;
1550
+ }
1551
+ }
1552
+ function getFaviconUrl2(url) {
1553
+ try {
1554
+ const domain = new URL(url).hostname;
1555
+ return `https://www.google.com/s2/favicons?domain=${domain}&sz=32`;
1556
+ } catch {
1557
+ return "";
1558
+ }
1559
+ }
1560
+ function annotationsToCitations(annotations) {
1561
+ const seen = /* @__PURE__ */ new Set();
1562
+ const citations = [];
1563
+ for (const annotation of annotations) {
1564
+ if (annotation.type === "url_citation" && annotation.url) {
1565
+ if (!seen.has(annotation.url)) {
1566
+ seen.add(annotation.url);
1567
+ citations.push({
1568
+ index: citations.length + 1,
1569
+ url: annotation.url,
1570
+ title: annotation.title || getDomain3(annotation.url),
1571
+ domain: getDomain3(annotation.url)
1572
+ });
1573
+ }
1574
+ }
1575
+ }
1576
+ return citations;
1577
+ }
1578
+ function resultsToCitations(results) {
1579
+ return results.map((result, index) => ({
1580
+ index: index + 1,
1581
+ url: result.url,
1582
+ title: result.title,
1583
+ domain: result.domain || getDomain3(result.url)
1584
+ }));
1585
+ }
1586
+ var ReasoningContext = React20.createContext(
983
1587
  null
984
1588
  );
985
1589
  function useReasoningContext() {
986
- const context = React18.useContext(ReasoningContext);
1590
+ const context = React20.useContext(ReasoningContext);
987
1591
  if (!context) {
988
1592
  throw new Error(
989
1593
  "Reasoning components must be used within a Reasoning provider"
@@ -999,11 +1603,11 @@ function Reasoning({
999
1603
  defaultOpen = false,
1000
1604
  className
1001
1605
  }) {
1002
- const [uncontrolledOpen, setUncontrolledOpen] = React18.useState(defaultOpen);
1003
- const prevStreamingRef = React18.useRef(isStreaming);
1606
+ const [uncontrolledOpen, setUncontrolledOpen] = React20.useState(defaultOpen);
1607
+ const prevStreamingRef = React20.useRef(isStreaming);
1004
1608
  const isControlled = controlledOpen !== void 0;
1005
1609
  const isOpen = isControlled ? controlledOpen : uncontrolledOpen;
1006
- const setIsOpen = React18.useCallback(
1610
+ const setIsOpen = React20.useCallback(
1007
1611
  (open) => {
1008
1612
  if (onOpenChange) {
1009
1613
  onOpenChange(open);
@@ -1014,7 +1618,7 @@ function Reasoning({
1014
1618
  },
1015
1619
  [isControlled, onOpenChange]
1016
1620
  );
1017
- React18.useEffect(() => {
1621
+ React20.useEffect(() => {
1018
1622
  if (isStreaming && !prevStreamingRef.current) {
1019
1623
  setIsOpen(true);
1020
1624
  } else if (!isStreaming && prevStreamingRef.current) {
@@ -1070,9 +1674,9 @@ function ReasoningContent({
1070
1674
  className
1071
1675
  }) {
1072
1676
  const { isOpen } = useReasoningContext();
1073
- const contentRef = React18.useRef(null);
1074
- const [height, setHeight] = React18.useState(0);
1075
- React18.useEffect(() => {
1677
+ const contentRef = React20.useRef(null);
1678
+ const [height, setHeight] = React20.useState(0);
1679
+ React20.useEffect(() => {
1076
1680
  if (contentRef.current) {
1077
1681
  const resizeObserver = new ResizeObserver((entries) => {
1078
1682
  for (const entry of entries) {
@@ -1121,11 +1725,11 @@ function SimpleReasoning({
1121
1725
  /* @__PURE__ */ jsx(ReasoningContent, { markdown, children: content })
1122
1726
  ] });
1123
1727
  }
1124
- var CopilotUIContext = React18.createContext(
1728
+ var CopilotUIContext = React20.createContext(
1125
1729
  null
1126
1730
  );
1127
1731
  function useCopilotUI() {
1128
- const context = React18.useContext(CopilotUIContext);
1732
+ const context = React20.useContext(CopilotUIContext);
1129
1733
  if (!context) {
1130
1734
  return {
1131
1735
  debug: false,
@@ -1140,7 +1744,7 @@ function CopilotUIProvider({
1140
1744
  debug = false,
1141
1745
  defaultDebugExpanded = false
1142
1746
  }) {
1143
- const value = React18.useMemo(
1747
+ const value = React20.useMemo(
1144
1748
  () => ({
1145
1749
  debug,
1146
1750
  defaultDebugExpanded,
@@ -1151,6 +1755,7 @@ function CopilotUIProvider({
1151
1755
  return /* @__PURE__ */ jsx(CopilotUIContext.Provider, { value, children });
1152
1756
  }
1153
1757
  function toolNameToTitle(name) {
1758
+ if (!name) return "Tool";
1154
1759
  let result = name.replace(/_/g, " ");
1155
1760
  result = result.replace(/([a-z])([A-Z])/g, "$1 $2");
1156
1761
  return result.charAt(0).toUpperCase() + result.slice(1).toLowerCase();
@@ -1282,7 +1887,7 @@ function ToolStep({
1282
1887
  }) {
1283
1888
  const { isDebug, defaultDebugExpanded } = useCopilotUI();
1284
1889
  const debug = debugProp ?? isDebug;
1285
- const [expanded, setExpanded] = React18.useState(
1890
+ const [expanded, setExpanded] = React20.useState(
1286
1891
  defaultExpanded ?? defaultDebugExpanded ?? false
1287
1892
  );
1288
1893
  const displayTitle = getDisplayTitle(step);
@@ -1763,9 +2368,9 @@ function ArrowUpRightIcon({ className }) {
1763
2368
  }
1764
2369
  );
1765
2370
  }
1766
- var ConfirmationContext = React18.createContext(null);
2371
+ var ConfirmationContext = React20.createContext(null);
1767
2372
  function useConfirmationContext() {
1768
- const context = React18.useContext(ConfirmationContext);
2373
+ const context = React20.useContext(ConfirmationContext);
1769
2374
  if (!context) {
1770
2375
  throw new Error(
1771
2376
  "Confirmation components must be used within a Confirmation provider"
@@ -1937,8 +2542,8 @@ function PermissionConfirmation({
1937
2542
  permissionOptions = DEFAULT_PERMISSION_OPTIONS,
1938
2543
  className
1939
2544
  }) {
1940
- const [selectedPermission, setSelectedPermission] = React18.useState("ask");
1941
- const [showOptions, setShowOptions] = React18.useState(false);
2545
+ const [selectedPermission, setSelectedPermission] = React20.useState("ask");
2546
+ const [showOptions, setShowOptions] = React20.useState(false);
1942
2547
  const handleApprove = () => {
1943
2548
  onApprove?.(selectedPermission);
1944
2549
  };
@@ -2068,7 +2673,7 @@ function CompactPermissionConfirmation({
2068
2673
  onReject,
2069
2674
  className
2070
2675
  }) {
2071
- const [rememberChoice, setRememberChoice] = React18.useState(false);
2676
+ const [rememberChoice, setRememberChoice] = React20.useState(false);
2072
2677
  const handleApprove = () => {
2073
2678
  onApprove?.(rememberChoice ? "allow_always" : "ask");
2074
2679
  };
@@ -2611,9 +3216,9 @@ function ModelSelector({
2611
3216
  showCapabilities = true,
2612
3217
  className
2613
3218
  }) {
2614
- const [isOpen, setIsOpen] = React18.useState(false);
2615
- const containerRef = React18.useRef(null);
2616
- React18.useEffect(() => {
3219
+ const [isOpen, setIsOpen] = React20.useState(false);
3220
+ const containerRef = React20.useRef(null);
3221
+ React20.useEffect(() => {
2617
3222
  function handleClickOutside(event) {
2618
3223
  if (containerRef.current && !containerRef.current.contains(event.target)) {
2619
3224
  setIsOpen(false);
@@ -2622,7 +3227,7 @@ function ModelSelector({
2622
3227
  document.addEventListener("mousedown", handleClickOutside);
2623
3228
  return () => document.removeEventListener("mousedown", handleClickOutside);
2624
3229
  }, []);
2625
- const selectedModel = React18.useMemo(() => {
3230
+ const selectedModel = React20.useMemo(() => {
2626
3231
  if (!value) return null;
2627
3232
  if (providers) {
2628
3233
  for (const provider of providers) {
@@ -2848,7 +3453,7 @@ function PopoverTrigger({
2848
3453
  className,
2849
3454
  ...props
2850
3455
  }) {
2851
- if (asChild && React18.isValidElement(children)) {
3456
+ if (asChild && React20.isValidElement(children)) {
2852
3457
  return /* @__PURE__ */ jsx(Popover$1.Trigger, { render: children, className, ...props });
2853
3458
  }
2854
3459
  return /* @__PURE__ */ jsx(Popover$1.Trigger, { className, ...props, children });
@@ -2876,7 +3481,7 @@ function PopoverContent({
2876
3481
  }
2877
3482
  ) }) });
2878
3483
  }
2879
- function formatDate(date) {
3484
+ function formatDate2(date) {
2880
3485
  const now = /* @__PURE__ */ new Date();
2881
3486
  const diff = now.getTime() - date.getTime();
2882
3487
  if (diff < 60 * 1e3) {
@@ -2983,8 +3588,8 @@ function ThreadPicker({
2983
3588
  itemClassName,
2984
3589
  newButtonClassName
2985
3590
  }) {
2986
- const [isOpen, setIsOpen] = React18.useState(false);
2987
- const selectedThread = React18.useMemo(() => {
3591
+ const [isOpen, setIsOpen] = React20.useState(false);
3592
+ const selectedThread = React20.useMemo(() => {
2988
3593
  if (!value) return null;
2989
3594
  return threads.find((t) => t.id === value) ?? null;
2990
3595
  }, [value, threads]);
@@ -3073,7 +3678,7 @@ function ThreadPicker({
3073
3678
  /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5 text-[11px] text-muted-foreground", children: [
3074
3679
  thread.preview && /* @__PURE__ */ jsx("span", { className: "truncate max-w-[180px]", children: thread.preview }),
3075
3680
  thread.preview && thread.updatedAt && /* @__PURE__ */ jsx("span", { className: "flex-shrink-0", children: "\xB7" }),
3076
- thread.updatedAt && /* @__PURE__ */ jsx("span", { className: "flex-shrink-0", children: formatDate(thread.updatedAt) })
3681
+ thread.updatedAt && /* @__PURE__ */ jsx("span", { className: "flex-shrink-0", children: formatDate2(thread.updatedAt) })
3077
3682
  ] })
3078
3683
  ]
3079
3684
  }
@@ -3100,7 +3705,7 @@ function ThreadPicker({
3100
3705
  )
3101
3706
  ] });
3102
3707
  }
3103
- function formatDate2(date) {
3708
+ function formatDate3(date) {
3104
3709
  const now = /* @__PURE__ */ new Date();
3105
3710
  const diff = now.getTime() - date.getTime();
3106
3711
  if (diff < 60 * 1e3) {
@@ -3190,7 +3795,7 @@ function ThreadCard({
3190
3795
  showDelete = true,
3191
3796
  className
3192
3797
  }) {
3193
- const [isHovered, setIsHovered] = React18.useState(false);
3798
+ const [isHovered, setIsHovered] = React20.useState(false);
3194
3799
  const handleDelete = (e) => {
3195
3800
  e.stopPropagation();
3196
3801
  onDelete?.();
@@ -3245,7 +3850,7 @@ function ThreadCard({
3245
3850
  " messages"
3246
3851
  ] }),
3247
3852
  thread.messageCount !== void 0 && thread.messageCount > 0 && thread.updatedAt && /* @__PURE__ */ jsx("span", { children: "\xB7" }),
3248
- thread.updatedAt && /* @__PURE__ */ jsx("span", { children: formatDate2(thread.updatedAt) })
3853
+ thread.updatedAt && /* @__PURE__ */ jsx("span", { children: formatDate3(thread.updatedAt) })
3249
3854
  ] })
3250
3855
  ] })
3251
3856
  ] })
@@ -3420,6 +4025,193 @@ function Suggestions({
3420
4025
  index
3421
4026
  )) });
3422
4027
  }
4028
+ function MCPUIFrame({
4029
+ resource,
4030
+ onIntent,
4031
+ onError,
4032
+ onLoad,
4033
+ className,
4034
+ style,
4035
+ sandbox = DEFAULT_MCP_UI_SANDBOX,
4036
+ showLoading = true,
4037
+ testId
4038
+ }) {
4039
+ const iframeRef = React20.useRef(null);
4040
+ const [isLoading, setIsLoading] = React20.useState(true);
4041
+ const [error, setError] = React20.useState(null);
4042
+ React20.useEffect(() => {
4043
+ const handleMessage = (event) => {
4044
+ if (event.source !== iframeRef.current?.contentWindow) {
4045
+ return;
4046
+ }
4047
+ const intent = parseMCPUIMessage(event.data);
4048
+ if (intent && onIntent) {
4049
+ onIntent(intent);
4050
+ }
4051
+ };
4052
+ window.addEventListener("message", handleMessage);
4053
+ return () => window.removeEventListener("message", handleMessage);
4054
+ }, [onIntent]);
4055
+ const handleLoad = React20.useCallback(() => {
4056
+ setIsLoading(false);
4057
+ onLoad?.();
4058
+ }, [onLoad]);
4059
+ const handleError = React20.useCallback(() => {
4060
+ const err = new Error("Failed to load MCP UI content");
4061
+ setError(err);
4062
+ setIsLoading(false);
4063
+ onError?.(err);
4064
+ }, [onError]);
4065
+ const { srcDoc, src } = React20.useMemo(() => {
4066
+ if (resource.mimeType === "text/html") {
4067
+ let content = resource.content || "";
4068
+ if (resource.blob && !resource.content) {
4069
+ try {
4070
+ content = atob(resource.blob);
4071
+ } catch {
4072
+ setError(new Error("Failed to decode MCP UI blob content"));
4073
+ }
4074
+ }
4075
+ const wrappedContent = `
4076
+ <!DOCTYPE html>
4077
+ <html>
4078
+ <head>
4079
+ <meta charset="utf-8">
4080
+ <meta name="viewport" content="width=device-width, initial-scale=1">
4081
+ <style>
4082
+ *, *::before, *::after { box-sizing: border-box; }
4083
+ body { margin: 0; padding: 8px; font-family: system-ui, -apple-system, sans-serif; }
4084
+ </style>
4085
+ </head>
4086
+ <body>
4087
+ ${content}
4088
+ <script>
4089
+ // Helper for sending intents to parent
4090
+ window.mcpUI = {
4091
+ sendIntent: function(intent) {
4092
+ window.parent.postMessage({ source: 'mcp-ui', intent: intent }, '*');
4093
+ },
4094
+ callTool: function(name, args) {
4095
+ this.sendIntent({ type: 'tool', name: name, arguments: args });
4096
+ },
4097
+ sendAction: function(action, data) {
4098
+ this.sendIntent({ type: 'intent', action: action, data: data });
4099
+ },
4100
+ prompt: function(text) {
4101
+ this.sendIntent({ type: 'prompt', text: text });
4102
+ },
4103
+ notify: function(message, level) {
4104
+ this.sendIntent({ type: 'notify', message: message, level: level || 'info' });
4105
+ },
4106
+ openLink: function(url, newTab) {
4107
+ this.sendIntent({ type: 'link', url: url, newTab: newTab !== false });
4108
+ }
4109
+ };
4110
+ </script>
4111
+ </body>
4112
+ </html>
4113
+ `;
4114
+ return { srcDoc: wrappedContent, src: void 0 };
4115
+ }
4116
+ if (resource.mimeType === "text/uri-list") {
4117
+ return { srcDoc: void 0, src: resource.content };
4118
+ }
4119
+ return { srcDoc: void 0, src: resource.content };
4120
+ }, [resource]);
4121
+ const frameStyle = {
4122
+ width: resource.metadata?.width || "100%",
4123
+ minHeight: resource.metadata?.height || "200px",
4124
+ ...style
4125
+ };
4126
+ if (error) {
4127
+ return /* @__PURE__ */ jsx(
4128
+ "div",
4129
+ {
4130
+ className: cn(
4131
+ "flex items-center justify-center rounded-lg border border-destructive/50 bg-destructive/10 p-4 text-sm text-destructive",
4132
+ className
4133
+ ),
4134
+ style: frameStyle,
4135
+ "data-testid": testId ? `${testId}-error` : void 0,
4136
+ children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
4137
+ /* @__PURE__ */ jsx(
4138
+ "svg",
4139
+ {
4140
+ className: "size-4",
4141
+ fill: "none",
4142
+ viewBox: "0 0 24 24",
4143
+ stroke: "currentColor",
4144
+ strokeWidth: 2,
4145
+ children: /* @__PURE__ */ jsx(
4146
+ "path",
4147
+ {
4148
+ strokeLinecap: "round",
4149
+ strokeLinejoin: "round",
4150
+ d: "M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z"
4151
+ }
4152
+ )
4153
+ }
4154
+ ),
4155
+ /* @__PURE__ */ jsx("span", { children: "Failed to load interactive content" })
4156
+ ] })
4157
+ }
4158
+ );
4159
+ }
4160
+ return /* @__PURE__ */ jsxs(
4161
+ "div",
4162
+ {
4163
+ className: cn("relative overflow-hidden rounded-lg border", className),
4164
+ "data-testid": testId,
4165
+ children: [
4166
+ resource.metadata?.title && /* @__PURE__ */ jsx("div", { className: "border-b bg-muted/50 px-3 py-1.5 text-xs font-medium text-muted-foreground", children: resource.metadata.title }),
4167
+ showLoading && isLoading && /* @__PURE__ */ jsx("div", { className: "absolute inset-0 z-10 flex items-center justify-center bg-background/80", children: /* @__PURE__ */ jsx(Loader, { variant: "dots", size: "md" }) }),
4168
+ /* @__PURE__ */ jsx(
4169
+ "iframe",
4170
+ {
4171
+ ref: iframeRef,
4172
+ srcDoc,
4173
+ src,
4174
+ sandbox,
4175
+ onLoad: handleLoad,
4176
+ onError: handleError,
4177
+ className: "block w-full border-0",
4178
+ style: frameStyle,
4179
+ title: resource.metadata?.title || "MCP UI Content",
4180
+ "data-testid": testId ? `${testId}-iframe` : void 0
4181
+ }
4182
+ )
4183
+ ]
4184
+ }
4185
+ );
4186
+ }
4187
+ function MCPUIFrameList({
4188
+ resources,
4189
+ onIntent,
4190
+ onError,
4191
+ className,
4192
+ frameClassName,
4193
+ gap = "md"
4194
+ }) {
4195
+ if (!resources || resources.length === 0) {
4196
+ return null;
4197
+ }
4198
+ const gapClasses = {
4199
+ sm: "space-y-1",
4200
+ md: "space-y-2",
4201
+ lg: "space-y-4"
4202
+ };
4203
+ return /* @__PURE__ */ jsx("div", { className: cn(gapClasses[gap], className), children: resources.map((resource, index) => /* @__PURE__ */ jsx(
4204
+ MCPUIFrame,
4205
+ {
4206
+ resource,
4207
+ onIntent: (intent) => onIntent?.(intent, index),
4208
+ onError: (error) => onError?.(error, index),
4209
+ className: frameClassName,
4210
+ testId: `mcp-ui-frame-${index}`
4211
+ },
4212
+ `${resource.uri}-${index}`
4213
+ )) });
4214
+ }
3423
4215
  function DefaultMessage({
3424
4216
  message,
3425
4217
  userAvatar,
@@ -3439,17 +4231,74 @@ function DefaultMessage({
3439
4231
  showFollowUps = true,
3440
4232
  onFollowUpClick,
3441
4233
  followUpClassName,
3442
- followUpButtonClassName
4234
+ followUpButtonClassName,
4235
+ citations = { enabled: true }
3443
4236
  }) {
3444
4237
  const isUser = message.role === "user";
3445
4238
  const isStreaming = isLastMessage && isLoading;
3446
- const { cleanContent, followUps } = React18.useMemo(() => {
4239
+ const { cleanContent: contentWithoutFollowUps, followUps } = React20.useMemo(() => {
3447
4240
  if (isUser || !message.content) {
3448
4241
  return { cleanContent: message.content, followUps: [] };
3449
4242
  }
3450
4243
  return parseFollowUps(message.content);
3451
4244
  }, [message.content, isUser]);
4245
+ const cleanContent = React20.useMemo(() => {
4246
+ if (!contentWithoutFollowUps) return contentWithoutFollowUps;
4247
+ return contentWithoutFollowUps.replace(/\n*\*{0,2}Sources:?\*{0,2}\s*(\[.+?\]\(.+?\)[,\s]*)+$/gi, "").trim();
4248
+ }, [contentWithoutFollowUps]);
3452
4249
  const shouldShowFollowUps = showFollowUps && !isUser && isLastMessage && !isLoading && followUps.length > 0 && onFollowUpClick;
4250
+ const sources = React20.useMemo(() => {
4251
+ if (isUser || !citations.enabled) return [];
4252
+ const extractedSources = [];
4253
+ const addSource = (url, title, description) => {
4254
+ if (url && !extractedSources.find((s) => s.href === url)) {
4255
+ extractedSources.push({
4256
+ href: url,
4257
+ title: title || getDomainFromUrl(url),
4258
+ description
4259
+ });
4260
+ }
4261
+ };
4262
+ const nativeCitations = message.metadata?.citations;
4263
+ if (nativeCitations && Array.isArray(nativeCitations)) {
4264
+ nativeCitations.forEach((citation) => {
4265
+ addSource(citation.url, citation.title, citation.citedText);
4266
+ });
4267
+ }
4268
+ message.toolExecutions?.forEach((exec) => {
4269
+ if (exec.name === "web_search" && exec.status === "completed" && exec.result) {
4270
+ const result = exec.result;
4271
+ const dataObj = result.data;
4272
+ if (dataObj?.results && Array.isArray(dataObj.results)) {
4273
+ dataObj.results.forEach((r) => {
4274
+ addSource(r.url, r.title, r.content);
4275
+ });
4276
+ }
4277
+ if (result.results && Array.isArray(result.results)) {
4278
+ result.results.forEach((r) => {
4279
+ addSource(r.url, r.title, r.content);
4280
+ });
4281
+ }
4282
+ if (dataObj && !dataObj.results && dataObj.query) {
4283
+ const response = dataObj;
4284
+ if (response.results && Array.isArray(response.results)) {
4285
+ response.results.forEach((r) => {
4286
+ addSource(r.url, r.title, r.content);
4287
+ });
4288
+ }
4289
+ }
4290
+ }
4291
+ });
4292
+ return extractedSources;
4293
+ }, [message.metadata, message.toolExecutions, isUser, citations.enabled]);
4294
+ function getDomainFromUrl(url) {
4295
+ try {
4296
+ return new URL(url).hostname.replace("www.", "");
4297
+ } catch {
4298
+ return url;
4299
+ }
4300
+ }
4301
+ const shouldShowSources = citations.enabled && sources.length > 0;
3453
4302
  if (isUser) {
3454
4303
  const hasAttachments = message.attachments && message.attachments.length > 0;
3455
4304
  return /* @__PURE__ */ jsxs(
@@ -3460,7 +4309,7 @@ function DefaultMessage({
3460
4309
  showUserAvatar ? "justify-end" : "justify-end"
3461
4310
  ),
3462
4311
  children: [
3463
- /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-end max-w-[80%]", children: [
4312
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-end max-w-[80%] min-w-0", children: [
3464
4313
  message.content && /* @__PURE__ */ jsx(
3465
4314
  MessageContent,
3466
4315
  {
@@ -3488,11 +4337,15 @@ function DefaultMessage({
3488
4337
  }
3489
4338
  );
3490
4339
  }
4340
+ const isToolHidden = (toolName) => {
4341
+ const toolDef = registeredTools?.find((t) => t.name === toolName);
4342
+ return toolDef?.hidden === true;
4343
+ };
3491
4344
  const pendingApprovalTools = message.toolExecutions?.filter(
3492
- (exec) => exec.approvalStatus === "required"
4345
+ (exec) => exec.approvalStatus === "required" && !isToolHidden(exec.name)
3493
4346
  );
3494
4347
  const completedTools = message.toolExecutions?.filter(
3495
- (exec) => exec.approvalStatus !== "required"
4348
+ (exec) => exec.approvalStatus !== "required" && !isToolHidden(exec.name)
3496
4349
  );
3497
4350
  const hasCustomRender = (toolName) => {
3498
4351
  if (toolRenderers?.[toolName]) return true;
@@ -3506,7 +4359,8 @@ function DefaultMessage({
3506
4359
  const toolsWithoutCustomRender = completedTools?.filter(
3507
4360
  (exec) => !hasCustomRender(exec.name)
3508
4361
  );
3509
- const toolSteps = toolsWithoutCustomRender?.map((exec) => ({
4362
+ const hasNativeCitations = !!message.metadata?.citations?.length;
4363
+ const toolSteps = toolsWithoutCustomRender?.filter((exec) => !(exec.name === "web_search" && hasNativeCitations)).map((exec) => ({
3510
4364
  id: exec.id,
3511
4365
  name: exec.name,
3512
4366
  args: exec.args,
@@ -3592,11 +4446,23 @@ function DefaultMessage({
3592
4446
  const output = toolDef.render(
3593
4447
  renderProps
3594
4448
  );
3595
- return /* @__PURE__ */ jsx(React18.Fragment, { children: output }, exec.id);
4449
+ return /* @__PURE__ */ jsx(React20.Fragment, { children: output }, exec.id);
3596
4450
  }
3597
4451
  return null;
3598
4452
  }) }),
3599
4453
  toolSteps && toolSteps.length > 0 && /* @__PURE__ */ jsx("div", { className: "mt-2 rounded-lg bg-muted/50 px-3 py-2", children: /* @__PURE__ */ jsx(ToolSteps, { steps: toolSteps }) }),
4454
+ message.toolExecutions?.filter((exec) => !isToolHidden(exec.name)).map((exec) => {
4455
+ const uiResources = exec.result?._uiResources;
4456
+ if (!uiResources || uiResources.length === 0) return null;
4457
+ return /* @__PURE__ */ jsx(
4458
+ MCPUIFrameList,
4459
+ {
4460
+ resources: uiResources,
4461
+ className: "mt-2"
4462
+ },
4463
+ `${exec.id}-ui`
4464
+ );
4465
+ }),
3600
4466
  pendingApprovalTools && pendingApprovalTools.length > 0 && /* @__PURE__ */ jsx("div", { className: "mt-2 space-y-2", children: pendingApprovalTools.map((tool) => {
3601
4467
  const approvalCallbacks = {
3602
4468
  onApprove: (extraData) => onApproveToolExecution?.(tool.id, extraData),
@@ -3630,7 +4496,7 @@ function DefaultMessage({
3630
4496
  const output = toolDef.render(
3631
4497
  renderProps
3632
4498
  );
3633
- return /* @__PURE__ */ jsx(React18.Fragment, { children: output }, tool.id);
4499
+ return /* @__PURE__ */ jsx(React20.Fragment, { children: output }, tool.id);
3634
4500
  }
3635
4501
  return /* @__PURE__ */ jsx(
3636
4502
  PermissionConfirmation,
@@ -3653,6 +4519,17 @@ function DefaultMessage({
3653
4519
  );
3654
4520
  }) }),
3655
4521
  message.attachments && message.attachments.length > 0 && /* @__PURE__ */ jsx("div", { className: "mt-2 flex flex-wrap gap-2", children: message.attachments.map((attachment, index) => /* @__PURE__ */ jsx(AttachmentPreview, { attachment }, index)) }),
4522
+ shouldShowSources && /* @__PURE__ */ jsx(
4523
+ SourceGroup,
4524
+ {
4525
+ sources,
4526
+ label: citations.label,
4527
+ showFavicon: citations.showFavicon ?? true,
4528
+ numbered: citations.numbered ?? false,
4529
+ maxVisible: citations.maxVisible ?? 6,
4530
+ className: cn("mt-2", citations.className)
4531
+ }
4532
+ ),
3656
4533
  shouldShowFollowUps && /* @__PURE__ */ jsx(
3657
4534
  FollowUpQuestions,
3658
4535
  {
@@ -3668,7 +4545,7 @@ function DefaultMessage({
3668
4545
  ] });
3669
4546
  }
3670
4547
  function AttachmentPreview({ attachment }) {
3671
- const [expanded, setExpanded] = React18.useState(false);
4548
+ const [expanded, setExpanded] = React20.useState(false);
3672
4549
  if (attachment.type !== "image") {
3673
4550
  return /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 rounded-lg border bg-muted/50 px-3 py-2 text-sm", children: [
3674
4551
  /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: attachment.type }),
@@ -4126,10 +5003,10 @@ function ChatView({ children, className }) {
4126
5003
  ChatView.displayName = "ChatView";
4127
5004
  function chatViewHasOnlyLayoutChildren(chatViewElement) {
4128
5005
  if (!chatViewElement?.props?.children) return false;
4129
- const childArray = React18__default.Children.toArray(chatViewElement.props.children);
5006
+ const childArray = React20__default.Children.toArray(chatViewElement.props.children);
4130
5007
  if (childArray.length === 0) return false;
4131
5008
  return childArray.every(
4132
- (child) => React18__default.isValidElement(child) && (child.type === Header || child.type === Footer)
5009
+ (child) => React20__default.isValidElement(child) && (child.type === Header || child.type === Footer)
4133
5010
  );
4134
5011
  }
4135
5012
  function Header({ children, className }) {
@@ -4267,18 +5144,18 @@ function ThreadPickerCompound(props) {
4267
5144
  );
4268
5145
  }
4269
5146
  function hasCompoundChild(children, ...components) {
4270
- return React18__default.Children.toArray(children).some(
4271
- (child) => React18__default.isValidElement(child) && components.includes(child.type)
5147
+ return React20__default.Children.toArray(children).some(
5148
+ (child) => React20__default.isValidElement(child) && components.includes(child.type)
4272
5149
  );
4273
5150
  }
4274
5151
  function findCompoundChild(children, component) {
4275
- return React18__default.Children.toArray(children).find(
4276
- (child) => React18__default.isValidElement(child) && child.type === component
5152
+ return React20__default.Children.toArray(children).find(
5153
+ (child) => React20__default.isValidElement(child) && child.type === component
4277
5154
  );
4278
5155
  }
4279
5156
  function filterCompoundChildren(children, ...components) {
4280
- return React18__default.Children.toArray(children).filter(
4281
- (child) => React18__default.isValidElement(child) && components.includes(child.type)
5157
+ return React20__default.Children.toArray(children).filter(
5158
+ (child) => React20__default.isValidElement(child) && components.includes(child.type)
4282
5159
  );
4283
5160
  }
4284
5161
  var DEFAULT_MAX_FILE_SIZE2 = 5 * 1024 * 1024;
@@ -4358,6 +5235,8 @@ function ChatComponent({
4358
5235
  showFollowUps = true,
4359
5236
  followUpClassName,
4360
5237
  followUpButtonClassName,
5238
+ // Citations/Sources
5239
+ citations,
4361
5240
  // Custom rendering
4362
5241
  renderMessage,
4363
5242
  renderInput,
@@ -4545,7 +5424,7 @@ function ChatComponent({
4545
5424
  },
4546
5425
  [onSendMessage]
4547
5426
  );
4548
- const contextValue = React18__default.useMemo(
5427
+ const contextValue = React20__default.useMemo(
4549
5428
  () => ({
4550
5429
  view,
4551
5430
  send,
@@ -4661,7 +5540,7 @@ function ChatComponent({
4661
5540
  onSendMessage?.(question);
4662
5541
  }
4663
5542
  };
4664
- return renderMessage ? /* @__PURE__ */ jsx(React18__default.Fragment, { children: renderMessage(messageWithExecutions, index) }, message.id) : /* @__PURE__ */ jsx(
5543
+ return renderMessage ? /* @__PURE__ */ jsx(React20__default.Fragment, { children: renderMessage(messageWithExecutions, index) }, message.id) : /* @__PURE__ */ jsx(
4665
5544
  DefaultMessage,
4666
5545
  {
4667
5546
  message: messageWithExecutions,
@@ -4682,7 +5561,8 @@ function ChatComponent({
4682
5561
  showFollowUps,
4683
5562
  onFollowUpClick: handleFollowUpClick,
4684
5563
  followUpClassName,
4685
- followUpButtonClassName
5564
+ followUpButtonClassName,
5565
+ citations: citations === false ? { enabled: false } : citations
4686
5566
  },
4687
5567
  message.id
4688
5568
  );
@@ -4861,6 +5741,7 @@ function ToolExecutionMessage({
4861
5741
  onApprove,
4862
5742
  onReject,
4863
5743
  toolRenderers,
5744
+ onUIIntent,
4864
5745
  className
4865
5746
  }) {
4866
5747
  if (!executions || executions.length === 0) return null;
@@ -4972,7 +5853,23 @@ function ToolExecutionMessage({
4972
5853
  tool.id
4973
5854
  );
4974
5855
  }) }),
4975
- toolSteps.length > 0 && /* @__PURE__ */ jsx("div", { className: "rounded-lg border bg-card px-3 py-2.5 shadow-sm", children: /* @__PURE__ */ jsx(ToolSteps, { steps: toolSteps }) })
5856
+ toolSteps.length > 0 && /* @__PURE__ */ jsx("div", { className: "rounded-lg border bg-card px-3 py-2.5 shadow-sm", children: /* @__PURE__ */ jsx(ToolSteps, { steps: toolSteps }) }),
5857
+ otherExecutions.map((exec) => {
5858
+ const uiResources = exec.result?._uiResources;
5859
+ if (!uiResources || uiResources.length === 0) return null;
5860
+ return /* @__PURE__ */ jsx(
5861
+ MCPUIFrameList,
5862
+ {
5863
+ resources: uiResources,
5864
+ onIntent: (intent) => onUIIntent?.(intent, {
5865
+ toolName: exec.name,
5866
+ toolCallId: exec.id
5867
+ }),
5868
+ className: "mt-2"
5869
+ },
5870
+ `${exec.id}-ui`
5871
+ );
5872
+ })
4976
5873
  ] })
4977
5874
  ] });
4978
5875
  }
@@ -5017,7 +5914,9 @@ function useInternalThreadManager(config = {}) {
5017
5914
  created_at: m.createdAt,
5018
5915
  tool_calls: m.toolCalls,
5019
5916
  tool_call_id: m.toolCallId,
5917
+ // Preserve full metadata including citations, toolExecutions, etc.
5020
5918
  metadata: {
5919
+ ...m.metadata,
5021
5920
  attachments: m.attachments,
5022
5921
  thinking: m.thinking
5023
5922
  }
@@ -5064,6 +5963,9 @@ function useInternalThreadManager(config = {}) {
5064
5963
  });
5065
5964
  }, [clearCurrentThread, setMessages, onThreadChange]);
5066
5965
  useEffect(() => {
5966
+ if (!adapter) {
5967
+ return;
5968
+ }
5067
5969
  if (hasInitializedRef.current || !currentThread) {
5068
5970
  return;
5069
5971
  }
@@ -5077,7 +5979,10 @@ function useInternalThreadManager(config = {}) {
5077
5979
  createdAt: m.created_at ?? /* @__PURE__ */ new Date(),
5078
5980
  toolCalls: m.tool_calls,
5079
5981
  toolCallId: m.tool_call_id,
5080
- attachments: m.metadata?.attachments
5982
+ attachments: m.metadata?.attachments,
5983
+ thinking: m.metadata?.thinking,
5984
+ // Preserve full metadata including citations, toolExecutions, etc.
5985
+ metadata: m.metadata
5081
5986
  }));
5082
5987
  lastSavedSnapshotRef.current = getMessageSnapshot(uiMessages);
5083
5988
  savingToThreadRef.current = currentThread.id;
@@ -5090,8 +5995,11 @@ function useInternalThreadManager(config = {}) {
5090
5995
  requestAnimationFrame(() => {
5091
5996
  isLoadingMessagesRef.current = false;
5092
5997
  });
5093
- }, [currentThread, setMessages, getMessageSnapshot, onThreadChange]);
5998
+ }, [adapter, currentThread, setMessages, getMessageSnapshot, onThreadChange]);
5094
5999
  useEffect(() => {
6000
+ if (!adapter) {
6001
+ return;
6002
+ }
5095
6003
  if (isLoadingMessagesRef.current) {
5096
6004
  return;
5097
6005
  }
@@ -5121,6 +6029,7 @@ function useInternalThreadManager(config = {}) {
5121
6029
  updateCurrentThread({ messages: coreMessages });
5122
6030
  lastSavedSnapshotRef.current = currentSnapshot;
5123
6031
  }, [
6032
+ adapter,
5124
6033
  messages,
5125
6034
  currentThreadId,
5126
6035
  status,
@@ -5296,7 +6205,9 @@ function CopilotChatBase(props) {
5296
6205
  // Include tool_calls for assistant messages
5297
6206
  tool_calls: m.toolCalls,
5298
6207
  // Attach matched tool executions to assistant messages
5299
- toolExecutions: messageToolExecutions
6208
+ toolExecutions: messageToolExecutions,
6209
+ // Include metadata (citations from native web search, etc.)
6210
+ metadata: m.metadata
5300
6211
  };
5301
6212
  });
5302
6213
  const suggestions = visibleMessages.length === 0 && chatProps.suggestions?.length ? chatProps.suggestions : [];
@@ -5332,7 +6243,7 @@ function CopilotChatBase(props) {
5332
6243
  footer: classNames.footer
5333
6244
  } : void 0;
5334
6245
  const { threadManager, handleSwitchThread, handleNewThread, isBusy } = threadManagerResult;
5335
- const handleDeleteThread = React18__default.useCallback(
6246
+ const handleDeleteThread = React20__default.useCallback(
5336
6247
  (threadId) => {
5337
6248
  const isCurrentThread = threadManager.currentThreadId === threadId;
5338
6249
  threadManager.deleteThread(threadId);
@@ -5457,6 +6368,6 @@ function PoweredBy({ className, showLogo = true }) {
5457
6368
  );
5458
6369
  }
5459
6370
 
5460
- export { AlertTriangleIcon, BotIcon, Button, CapabilityBadge, CapabilityList, Chat, ChatContainerContent, ChatContainerRoot, ChatContainerScrollAnchor, ChatWelcome, CheckIcon, ChevronDownIcon2 as ChevronDownIcon, ChevronLeftIcon, ChevronUpIcon, CloseIcon, CodeBlock, CompactPermissionConfirmation, Confirmation, ConfirmationActions, ConfirmationApproved, ConfirmationMessage, ConfirmationPending, ConfirmationRejected, ConnectedChat, CopilotChat, CopilotUIProvider, CopyIcon, DEFAULT_PERMISSION_OPTIONS, DevLogger, FeedbackBar, FollowUpQuestions, InlineToolSteps, Loader, Markdown, MessageAvatar, MessageContent, Message as MessagePrimitive, ModelSelector, PermissionConfirmation, PoweredBy, PromptInput, PromptInputAction, PromptInputActions, PromptInputTextarea, Reasoning, ReasoningContent, ReasoningTrigger, RefreshIcon, ScrollButton, SendIcon, SimpleConfirmation, SimpleModelSelector, SimpleReasoning, Source, SourceContent, SourceTrigger, StopIcon, ThreadCard, ThreadList, ThreadPicker, ThumbsDownIcon2 as ThumbsDownIcon, ThumbsUpIcon2 as ThumbsUpIcon, ToolExecutionMessage, ToolStep, ToolSteps, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, UserIcon, XIcon2 as XIcon, cn, parseFollowUps, useChatContainer, useCopilotChatContext, useCopilotUI };
6371
+ 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 };
5461
6372
  //# sourceMappingURL=index.js.map
5462
6373
  //# sourceMappingURL=index.js.map