@yourgpt/copilot-sdk 2.0.0 → 2.0.2-beta.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 (215) hide show
  1. package/README.md +68 -27
  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-CJ7UWN2Y.js → chunk-3YKHVLNP.js} +397 -7
  19. package/dist/chunk-3YKHVLNP.js.map +1 -0
  20. package/dist/chunk-4WWWMNUA.js +1142 -0
  21. package/dist/chunk-4WWWMNUA.js.map +1 -0
  22. package/dist/chunk-53UGJNHN.js +92 -0
  23. package/dist/chunk-53UGJNHN.js.map +1 -0
  24. package/dist/chunk-6BXQFCK3.js +79 -0
  25. package/dist/chunk-6BXQFCK3.js.map +1 -0
  26. package/dist/chunk-6T5XXJEP.cjs +80 -0
  27. package/dist/chunk-6T5XXJEP.cjs.map +1 -0
  28. package/dist/chunk-7W7QLZNC.js +72 -0
  29. package/dist/chunk-7W7QLZNC.js.map +1 -0
  30. package/dist/chunk-ASV6JLYG.cjs +99 -0
  31. package/dist/chunk-ASV6JLYG.cjs.map +1 -0
  32. package/dist/chunk-CBAHCI4R.cjs +76 -0
  33. package/dist/chunk-CBAHCI4R.cjs.map +1 -0
  34. package/dist/chunk-CEOMTQTP.js +85 -0
  35. package/dist/chunk-CEOMTQTP.js.map +1 -0
  36. package/dist/chunk-DABZYCVX.js +84 -0
  37. package/dist/chunk-DABZYCVX.js.map +1 -0
  38. package/dist/chunk-DGUM43GV.js +10 -0
  39. package/dist/chunk-DGUM43GV.js.map +1 -0
  40. package/dist/{chunk-4PRWNAXQ.cjs → chunk-DUPNYVBP.cjs} +27 -89
  41. package/dist/chunk-DUPNYVBP.cjs.map +1 -0
  42. package/dist/chunk-DVC63PGD.cjs +1160 -0
  43. package/dist/chunk-DVC63PGD.cjs.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-J4OMGO5O.js +66 -0
  49. package/dist/chunk-J4OMGO5O.js.map +1 -0
  50. package/dist/chunk-JEQ2X3Z6.cjs +12 -0
  51. package/dist/chunk-JEQ2X3Z6.cjs.map +1 -0
  52. package/dist/chunk-JO4BHPAD.cjs +40 -0
  53. package/dist/chunk-JO4BHPAD.cjs.map +1 -0
  54. package/dist/chunk-MEBXW75C.cjs +89 -0
  55. package/dist/chunk-MEBXW75C.cjs.map +1 -0
  56. package/dist/chunk-MNDGIW47.js +76 -0
  57. package/dist/chunk-MNDGIW47.js.map +1 -0
  58. package/dist/chunk-PPFHA6IL.js +83 -0
  59. package/dist/chunk-PPFHA6IL.js.map +1 -0
  60. package/dist/{chunk-BLSI67J6.cjs → chunk-RBZXLBGI.cjs} +425 -30
  61. package/dist/chunk-RBZXLBGI.cjs.map +1 -0
  62. package/dist/chunk-RQ74USYU.js +128 -0
  63. package/dist/chunk-RQ74USYU.js.map +1 -0
  64. package/dist/chunk-TX7CGITI.cjs +82 -0
  65. package/dist/chunk-TX7CGITI.cjs.map +1 -0
  66. package/dist/chunk-TXLIY7GF.cjs +132 -0
  67. package/dist/chunk-TXLIY7GF.cjs.map +1 -0
  68. package/dist/chunk-VD74IPKB.js +106 -0
  69. package/dist/chunk-VD74IPKB.js.map +1 -0
  70. package/dist/chunk-W73FBYIH.cjs +87 -0
  71. package/dist/chunk-W73FBYIH.cjs.map +1 -0
  72. package/dist/chunk-W74OTXXX.cjs +73 -0
  73. package/dist/chunk-W74OTXXX.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-JM7PB2LP.js → chunk-Z7PHGSJT.js} +10 -66
  79. package/dist/chunk-Z7PHGSJT.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-DBNh0jhE.d.ts +206 -0
  97. package/dist/index-DOlhSb79.d.cts +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-EiPWA9Ay.d.cts} +34 -367
  196. package/dist/{types-BtAaOV07.d.ts → tools-EiPWA9Ay.d.ts} +34 -367
  197. package/dist/types-B20VCJXL.d.cts +347 -0
  198. package/dist/types-B20VCJXL.d.ts +347 -0
  199. package/dist/types-CKA6U74u.d.cts +441 -0
  200. package/dist/types-DG2ya08y.d.cts +367 -0
  201. package/dist/types-DG2ya08y.d.ts +367 -0
  202. package/dist/types-ZguuKEs_.d.cts +127 -0
  203. package/dist/types-ZguuKEs_.d.ts +127 -0
  204. package/dist/types-iBkPICvQ.d.ts +441 -0
  205. package/dist/ui/index.cjs +1069 -146
  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 +1001 -94
  210. package/dist/ui/index.js.map +1 -1
  211. package/package.json +53 -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-3YKHVLNP.js';
2
+ import { createServerAdapter } from '../chunk-Z7PHGSJT.js';
3
+ import { DEFAULT_MCP_UI_SANDBOX, parseMCPUIMessage } from '../chunk-G4SF2PNQ.js';
4
+ import '../chunk-4WWWMNUA.js';
5
+ import '../chunk-6BXQFCK3.js';
6
+ import '../chunk-J4OMGO5O.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)) });
1528
+ }
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
+ }));
981
1585
  }
982
- var ReasoningContext = React18.createContext(
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
  {
@@ -3506,7 +4355,8 @@ function DefaultMessage({
3506
4355
  const toolsWithoutCustomRender = completedTools?.filter(
3507
4356
  (exec) => !hasCustomRender(exec.name)
3508
4357
  );
3509
- const toolSteps = toolsWithoutCustomRender?.map((exec) => ({
4358
+ const hasNativeCitations = !!message.metadata?.citations?.length;
4359
+ const toolSteps = toolsWithoutCustomRender?.filter((exec) => !(exec.name === "web_search" && hasNativeCitations)).map((exec) => ({
3510
4360
  id: exec.id,
3511
4361
  name: exec.name,
3512
4362
  args: exec.args,
@@ -3592,11 +4442,23 @@ function DefaultMessage({
3592
4442
  const output = toolDef.render(
3593
4443
  renderProps
3594
4444
  );
3595
- return /* @__PURE__ */ jsx(React18.Fragment, { children: output }, exec.id);
4445
+ return /* @__PURE__ */ jsx(React20.Fragment, { children: output }, exec.id);
3596
4446
  }
3597
4447
  return null;
3598
4448
  }) }),
3599
4449
  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 }) }),
4450
+ message.toolExecutions?.map((exec) => {
4451
+ const uiResources = exec.result?._uiResources;
4452
+ if (!uiResources || uiResources.length === 0) return null;
4453
+ return /* @__PURE__ */ jsx(
4454
+ MCPUIFrameList,
4455
+ {
4456
+ resources: uiResources,
4457
+ className: "mt-2"
4458
+ },
4459
+ `${exec.id}-ui`
4460
+ );
4461
+ }),
3600
4462
  pendingApprovalTools && pendingApprovalTools.length > 0 && /* @__PURE__ */ jsx("div", { className: "mt-2 space-y-2", children: pendingApprovalTools.map((tool) => {
3601
4463
  const approvalCallbacks = {
3602
4464
  onApprove: (extraData) => onApproveToolExecution?.(tool.id, extraData),
@@ -3630,7 +4492,7 @@ function DefaultMessage({
3630
4492
  const output = toolDef.render(
3631
4493
  renderProps
3632
4494
  );
3633
- return /* @__PURE__ */ jsx(React18.Fragment, { children: output }, tool.id);
4495
+ return /* @__PURE__ */ jsx(React20.Fragment, { children: output }, tool.id);
3634
4496
  }
3635
4497
  return /* @__PURE__ */ jsx(
3636
4498
  PermissionConfirmation,
@@ -3653,6 +4515,17 @@ function DefaultMessage({
3653
4515
  );
3654
4516
  }) }),
3655
4517
  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)) }),
4518
+ shouldShowSources && /* @__PURE__ */ jsx(
4519
+ SourceGroup,
4520
+ {
4521
+ sources,
4522
+ label: citations.label,
4523
+ showFavicon: citations.showFavicon ?? true,
4524
+ numbered: citations.numbered ?? false,
4525
+ maxVisible: citations.maxVisible ?? 6,
4526
+ className: cn("mt-2", citations.className)
4527
+ }
4528
+ ),
3656
4529
  shouldShowFollowUps && /* @__PURE__ */ jsx(
3657
4530
  FollowUpQuestions,
3658
4531
  {
@@ -3668,7 +4541,7 @@ function DefaultMessage({
3668
4541
  ] });
3669
4542
  }
3670
4543
  function AttachmentPreview({ attachment }) {
3671
- const [expanded, setExpanded] = React18.useState(false);
4544
+ const [expanded, setExpanded] = React20.useState(false);
3672
4545
  if (attachment.type !== "image") {
3673
4546
  return /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 rounded-lg border bg-muted/50 px-3 py-2 text-sm", children: [
3674
4547
  /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: attachment.type }),
@@ -4126,10 +4999,10 @@ function ChatView({ children, className }) {
4126
4999
  ChatView.displayName = "ChatView";
4127
5000
  function chatViewHasOnlyLayoutChildren(chatViewElement) {
4128
5001
  if (!chatViewElement?.props?.children) return false;
4129
- const childArray = React18__default.Children.toArray(chatViewElement.props.children);
5002
+ const childArray = React20__default.Children.toArray(chatViewElement.props.children);
4130
5003
  if (childArray.length === 0) return false;
4131
5004
  return childArray.every(
4132
- (child) => React18__default.isValidElement(child) && (child.type === Header || child.type === Footer)
5005
+ (child) => React20__default.isValidElement(child) && (child.type === Header || child.type === Footer)
4133
5006
  );
4134
5007
  }
4135
5008
  function Header({ children, className }) {
@@ -4267,18 +5140,18 @@ function ThreadPickerCompound(props) {
4267
5140
  );
4268
5141
  }
4269
5142
  function hasCompoundChild(children, ...components) {
4270
- return React18__default.Children.toArray(children).some(
4271
- (child) => React18__default.isValidElement(child) && components.includes(child.type)
5143
+ return React20__default.Children.toArray(children).some(
5144
+ (child) => React20__default.isValidElement(child) && components.includes(child.type)
4272
5145
  );
4273
5146
  }
4274
5147
  function findCompoundChild(children, component) {
4275
- return React18__default.Children.toArray(children).find(
4276
- (child) => React18__default.isValidElement(child) && child.type === component
5148
+ return React20__default.Children.toArray(children).find(
5149
+ (child) => React20__default.isValidElement(child) && child.type === component
4277
5150
  );
4278
5151
  }
4279
5152
  function filterCompoundChildren(children, ...components) {
4280
- return React18__default.Children.toArray(children).filter(
4281
- (child) => React18__default.isValidElement(child) && components.includes(child.type)
5153
+ return React20__default.Children.toArray(children).filter(
5154
+ (child) => React20__default.isValidElement(child) && components.includes(child.type)
4282
5155
  );
4283
5156
  }
4284
5157
  var DEFAULT_MAX_FILE_SIZE2 = 5 * 1024 * 1024;
@@ -4358,6 +5231,8 @@ function ChatComponent({
4358
5231
  showFollowUps = true,
4359
5232
  followUpClassName,
4360
5233
  followUpButtonClassName,
5234
+ // Citations/Sources
5235
+ citations,
4361
5236
  // Custom rendering
4362
5237
  renderMessage,
4363
5238
  renderInput,
@@ -4545,7 +5420,7 @@ function ChatComponent({
4545
5420
  },
4546
5421
  [onSendMessage]
4547
5422
  );
4548
- const contextValue = React18__default.useMemo(
5423
+ const contextValue = React20__default.useMemo(
4549
5424
  () => ({
4550
5425
  view,
4551
5426
  send,
@@ -4661,7 +5536,7 @@ function ChatComponent({
4661
5536
  onSendMessage?.(question);
4662
5537
  }
4663
5538
  };
4664
- return renderMessage ? /* @__PURE__ */ jsx(React18__default.Fragment, { children: renderMessage(messageWithExecutions, index) }, message.id) : /* @__PURE__ */ jsx(
5539
+ return renderMessage ? /* @__PURE__ */ jsx(React20__default.Fragment, { children: renderMessage(messageWithExecutions, index) }, message.id) : /* @__PURE__ */ jsx(
4665
5540
  DefaultMessage,
4666
5541
  {
4667
5542
  message: messageWithExecutions,
@@ -4682,7 +5557,8 @@ function ChatComponent({
4682
5557
  showFollowUps,
4683
5558
  onFollowUpClick: handleFollowUpClick,
4684
5559
  followUpClassName,
4685
- followUpButtonClassName
5560
+ followUpButtonClassName,
5561
+ citations: citations === false ? { enabled: false } : citations
4686
5562
  },
4687
5563
  message.id
4688
5564
  );
@@ -4861,6 +5737,7 @@ function ToolExecutionMessage({
4861
5737
  onApprove,
4862
5738
  onReject,
4863
5739
  toolRenderers,
5740
+ onUIIntent,
4864
5741
  className
4865
5742
  }) {
4866
5743
  if (!executions || executions.length === 0) return null;
@@ -4972,7 +5849,23 @@ function ToolExecutionMessage({
4972
5849
  tool.id
4973
5850
  );
4974
5851
  }) }),
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 }) })
5852
+ 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 }) }),
5853
+ otherExecutions.map((exec) => {
5854
+ const uiResources = exec.result?._uiResources;
5855
+ if (!uiResources || uiResources.length === 0) return null;
5856
+ return /* @__PURE__ */ jsx(
5857
+ MCPUIFrameList,
5858
+ {
5859
+ resources: uiResources,
5860
+ onIntent: (intent) => onUIIntent?.(intent, {
5861
+ toolName: exec.name,
5862
+ toolCallId: exec.id
5863
+ }),
5864
+ className: "mt-2"
5865
+ },
5866
+ `${exec.id}-ui`
5867
+ );
5868
+ })
4976
5869
  ] })
4977
5870
  ] });
4978
5871
  }
@@ -5017,7 +5910,9 @@ function useInternalThreadManager(config = {}) {
5017
5910
  created_at: m.createdAt,
5018
5911
  tool_calls: m.toolCalls,
5019
5912
  tool_call_id: m.toolCallId,
5913
+ // Preserve full metadata including citations, toolExecutions, etc.
5020
5914
  metadata: {
5915
+ ...m.metadata,
5021
5916
  attachments: m.attachments,
5022
5917
  thinking: m.thinking
5023
5918
  }
@@ -5064,6 +5959,9 @@ function useInternalThreadManager(config = {}) {
5064
5959
  });
5065
5960
  }, [clearCurrentThread, setMessages, onThreadChange]);
5066
5961
  useEffect(() => {
5962
+ if (!adapter) {
5963
+ return;
5964
+ }
5067
5965
  if (hasInitializedRef.current || !currentThread) {
5068
5966
  return;
5069
5967
  }
@@ -5077,7 +5975,10 @@ function useInternalThreadManager(config = {}) {
5077
5975
  createdAt: m.created_at ?? /* @__PURE__ */ new Date(),
5078
5976
  toolCalls: m.tool_calls,
5079
5977
  toolCallId: m.tool_call_id,
5080
- attachments: m.metadata?.attachments
5978
+ attachments: m.metadata?.attachments,
5979
+ thinking: m.metadata?.thinking,
5980
+ // Preserve full metadata including citations, toolExecutions, etc.
5981
+ metadata: m.metadata
5081
5982
  }));
5082
5983
  lastSavedSnapshotRef.current = getMessageSnapshot(uiMessages);
5083
5984
  savingToThreadRef.current = currentThread.id;
@@ -5090,8 +5991,11 @@ function useInternalThreadManager(config = {}) {
5090
5991
  requestAnimationFrame(() => {
5091
5992
  isLoadingMessagesRef.current = false;
5092
5993
  });
5093
- }, [currentThread, setMessages, getMessageSnapshot, onThreadChange]);
5994
+ }, [adapter, currentThread, setMessages, getMessageSnapshot, onThreadChange]);
5094
5995
  useEffect(() => {
5996
+ if (!adapter) {
5997
+ return;
5998
+ }
5095
5999
  if (isLoadingMessagesRef.current) {
5096
6000
  return;
5097
6001
  }
@@ -5121,6 +6025,7 @@ function useInternalThreadManager(config = {}) {
5121
6025
  updateCurrentThread({ messages: coreMessages });
5122
6026
  lastSavedSnapshotRef.current = currentSnapshot;
5123
6027
  }, [
6028
+ adapter,
5124
6029
  messages,
5125
6030
  currentThreadId,
5126
6031
  status,
@@ -5296,7 +6201,9 @@ function CopilotChatBase(props) {
5296
6201
  // Include tool_calls for assistant messages
5297
6202
  tool_calls: m.toolCalls,
5298
6203
  // Attach matched tool executions to assistant messages
5299
- toolExecutions: messageToolExecutions
6204
+ toolExecutions: messageToolExecutions,
6205
+ // Include metadata (citations from native web search, etc.)
6206
+ metadata: m.metadata
5300
6207
  };
5301
6208
  });
5302
6209
  const suggestions = visibleMessages.length === 0 && chatProps.suggestions?.length ? chatProps.suggestions : [];
@@ -5332,7 +6239,7 @@ function CopilotChatBase(props) {
5332
6239
  footer: classNames.footer
5333
6240
  } : void 0;
5334
6241
  const { threadManager, handleSwitchThread, handleNewThread, isBusy } = threadManagerResult;
5335
- const handleDeleteThread = React18__default.useCallback(
6242
+ const handleDeleteThread = React20__default.useCallback(
5336
6243
  (threadId) => {
5337
6244
  const isCurrentThread = threadManager.currentThreadId === threadId;
5338
6245
  threadManager.deleteThread(threadId);
@@ -5457,6 +6364,6 @@ function PoweredBy({ className, showLogo = true }) {
5457
6364
  );
5458
6365
  }
5459
6366
 
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 };
6367
+ 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
6368
  //# sourceMappingURL=index.js.map
5462
6369
  //# sourceMappingURL=index.js.map