@yourgpt/copilot-sdk 2.1.5-alpha.2 → 2.1.5-alpha.3

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.
package/dist/ui/index.js CHANGED
@@ -18,8 +18,8 @@ import '../chunk-DGUM43GV.js';
18
18
  import { clsx } from 'clsx';
19
19
  import { twMerge } from 'tailwind-merge';
20
20
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
21
- import * as React17 from 'react';
22
- import React17__default, { memo, createContext, useState, useRef, useId, useCallback, useLayoutEffect, useContext, useEffect } from 'react';
21
+ import * as React19 from 'react';
22
+ import React19__default, { memo, createContext, useState, useRef, useId, useCallback, useMemo, useLayoutEffect, useContext, useEffect } from 'react';
23
23
  import { Streamdown } from 'streamdown';
24
24
  import { code } from '@streamdown/code';
25
25
  import { Slot } from '@radix-ui/react-slot';
@@ -384,7 +384,7 @@ var buttonVariants = cva(
384
384
  }
385
385
  }
386
386
  );
387
- var Button = React17.forwardRef(
387
+ var Button = React19.forwardRef(
388
388
  ({ className, variant, size, asChild = false, ...props }, ref) => {
389
389
  const Comp = asChild ? Slot : "button";
390
390
  return /* @__PURE__ */ jsx(
@@ -625,7 +625,7 @@ function TooltipTrigger({
625
625
  disabled,
626
626
  ...props
627
627
  }) {
628
- if (asChild && React17__default.isValidElement(children)) {
628
+ if (asChild && React19__default.isValidElement(children)) {
629
629
  return /* @__PURE__ */ jsx(Tooltip$1.Trigger, { disabled, render: children, ...props });
630
630
  }
631
631
  return /* @__PURE__ */ jsx(Tooltip$1.Trigger, { disabled, ...props, children });
@@ -654,7 +654,7 @@ function TooltipContent({
654
654
  }
655
655
  ) }) });
656
656
  }
657
- var Avatar = React17.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
657
+ var Avatar = React19.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
658
658
  AvatarPrimitive.Root,
659
659
  {
660
660
  ref,
@@ -666,7 +666,7 @@ var Avatar = React17.forwardRef(({ className, ...props }, ref) => /* @__PURE__ *
666
666
  }
667
667
  ));
668
668
  Avatar.displayName = AvatarPrimitive.Root.displayName;
669
- var AvatarImage = React17.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
669
+ var AvatarImage = React19.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
670
670
  AvatarPrimitive.Image,
671
671
  {
672
672
  ref,
@@ -675,7 +675,7 @@ var AvatarImage = React17.forwardRef(({ className, ...props }, ref) => /* @__PUR
675
675
  }
676
676
  ));
677
677
  AvatarImage.displayName = AvatarPrimitive.Image.displayName;
678
- var AvatarFallback = React17.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
678
+ var AvatarFallback = React19.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
679
679
  AvatarPrimitive.Fallback,
680
680
  {
681
681
  ref,
@@ -735,7 +735,34 @@ var MessageContent = ({
735
735
  );
736
736
  return markdown ? /* @__PURE__ */ jsx(Markdown, { className: classNames, ...props, children }) : /* @__PURE__ */ jsx("div", { className: classNames, ...props, children });
737
737
  };
738
- var Textarea = React17.forwardRef(({ className, ...props }, ref) => {
738
+ var MessageActions = ({
739
+ children,
740
+ className,
741
+ ...props
742
+ }) => /* @__PURE__ */ jsx(
743
+ "div",
744
+ {
745
+ className: cn(
746
+ "csdk-message-actions text-muted-foreground flex items-center gap-2",
747
+ className
748
+ ),
749
+ ...props,
750
+ children
751
+ }
752
+ );
753
+ var MessageAction = ({
754
+ tooltip,
755
+ children,
756
+ className,
757
+ side = "top",
758
+ ...props
759
+ }) => {
760
+ return /* @__PURE__ */ jsx(TooltipProvider, { children: /* @__PURE__ */ jsxs(Tooltip, { ...props, children: [
761
+ /* @__PURE__ */ jsx(TooltipTrigger, { asChild: true, children }),
762
+ /* @__PURE__ */ jsx(TooltipContent, { side, className, children: tooltip })
763
+ ] }) });
764
+ };
765
+ var Textarea = React19.forwardRef(({ className, ...props }, ref) => {
739
766
  return /* @__PURE__ */ jsx(
740
767
  "textarea",
741
768
  {
@@ -899,7 +926,7 @@ function PromptInputAction({
899
926
  }
900
927
  var HoverCard = HoverCardPrimitive.Root;
901
928
  var HoverCardTrigger = HoverCardPrimitive.Trigger;
902
- var HoverCardContent = React17.forwardRef(({ className, align = "center", sideOffset = 4, ...props }, ref) => /* @__PURE__ */ jsx(
929
+ var HoverCardContent = React19.forwardRef(({ className, align = "center", sideOffset = 4, ...props }, ref) => /* @__PURE__ */ jsx(
903
930
  HoverCardPrimitive.Content,
904
931
  {
905
932
  ref,
@@ -1442,7 +1469,7 @@ function SourcesCollapsible({
1442
1469
  defaultExpanded = false,
1443
1470
  className
1444
1471
  }) {
1445
- const [expanded, setExpanded] = React17.useState(defaultExpanded);
1472
+ const [expanded, setExpanded] = React19.useState(defaultExpanded);
1446
1473
  if (citations.length === 0) return null;
1447
1474
  return /* @__PURE__ */ jsxs("div", { className: cn("border rounded-lg", className), children: [
1448
1475
  /* @__PURE__ */ jsxs(
@@ -1508,7 +1535,7 @@ function SourcesList({
1508
1535
  if (compact) {
1509
1536
  return /* @__PURE__ */ jsxs("div", { className: cn("text-xs text-muted-foreground", className), children: [
1510
1537
  /* @__PURE__ */ jsx("span", { className: "font-medium", children: "Sources: " }),
1511
- citations.map((c, i) => /* @__PURE__ */ jsxs(React17.Fragment, { children: [
1538
+ citations.map((c, i) => /* @__PURE__ */ jsxs(React19.Fragment, { children: [
1512
1539
  /* @__PURE__ */ jsxs(
1513
1540
  "a",
1514
1541
  {
@@ -1586,11 +1613,11 @@ function resultsToCitations(results) {
1586
1613
  domain: result.domain || getDomain3(result.url)
1587
1614
  }));
1588
1615
  }
1589
- var ReasoningContext = React17.createContext(
1616
+ var ReasoningContext = React19.createContext(
1590
1617
  null
1591
1618
  );
1592
1619
  function useReasoningContext() {
1593
- const context = React17.useContext(ReasoningContext);
1620
+ const context = React19.useContext(ReasoningContext);
1594
1621
  if (!context) {
1595
1622
  throw new Error(
1596
1623
  "Reasoning components must be used within a Reasoning provider"
@@ -1606,11 +1633,11 @@ function Reasoning({
1606
1633
  defaultOpen = false,
1607
1634
  className
1608
1635
  }) {
1609
- const [uncontrolledOpen, setUncontrolledOpen] = React17.useState(defaultOpen);
1610
- const prevStreamingRef = React17.useRef(isStreaming);
1636
+ const [uncontrolledOpen, setUncontrolledOpen] = React19.useState(defaultOpen);
1637
+ const prevStreamingRef = React19.useRef(isStreaming);
1611
1638
  const isControlled = controlledOpen !== void 0;
1612
1639
  const isOpen = isControlled ? controlledOpen : uncontrolledOpen;
1613
- const setIsOpen = React17.useCallback(
1640
+ const setIsOpen = React19.useCallback(
1614
1641
  (open) => {
1615
1642
  if (onOpenChange) {
1616
1643
  onOpenChange(open);
@@ -1621,7 +1648,7 @@ function Reasoning({
1621
1648
  },
1622
1649
  [isControlled, onOpenChange]
1623
1650
  );
1624
- React17.useEffect(() => {
1651
+ React19.useEffect(() => {
1625
1652
  if (isStreaming && !prevStreamingRef.current) {
1626
1653
  setIsOpen(true);
1627
1654
  } else if (!isStreaming && prevStreamingRef.current) {
@@ -1677,9 +1704,9 @@ function ReasoningContent({
1677
1704
  className
1678
1705
  }) {
1679
1706
  const { isOpen } = useReasoningContext();
1680
- const contentRef = React17.useRef(null);
1681
- const [height, setHeight] = React17.useState(0);
1682
- React17.useEffect(() => {
1707
+ const contentRef = React19.useRef(null);
1708
+ const [height, setHeight] = React19.useState(0);
1709
+ React19.useEffect(() => {
1683
1710
  if (contentRef.current) {
1684
1711
  const resizeObserver = new ResizeObserver((entries) => {
1685
1712
  for (const entry of entries) {
@@ -1728,11 +1755,11 @@ function SimpleReasoning({
1728
1755
  /* @__PURE__ */ jsx(ReasoningContent, { markdown, children: content })
1729
1756
  ] });
1730
1757
  }
1731
- var CopilotUIContext = React17.createContext(
1758
+ var CopilotUIContext = React19.createContext(
1732
1759
  null
1733
1760
  );
1734
1761
  function useCopilotUI() {
1735
- const context = React17.useContext(CopilotUIContext);
1762
+ const context = React19.useContext(CopilotUIContext);
1736
1763
  if (!context) {
1737
1764
  return {
1738
1765
  debug: false,
@@ -1747,7 +1774,7 @@ function CopilotUIProvider({
1747
1774
  debug = false,
1748
1775
  defaultDebugExpanded = false
1749
1776
  }) {
1750
- const value = React17.useMemo(
1777
+ const value = React19.useMemo(
1751
1778
  () => ({
1752
1779
  debug,
1753
1780
  defaultDebugExpanded,
@@ -1890,7 +1917,7 @@ function ToolStep({
1890
1917
  }) {
1891
1918
  const { isDebug, defaultDebugExpanded } = useCopilotUI();
1892
1919
  const debug = debugProp ?? isDebug;
1893
- const [expanded, setExpanded] = React17.useState(
1920
+ const [expanded, setExpanded] = React19.useState(
1894
1921
  defaultExpanded ?? defaultDebugExpanded ?? false
1895
1922
  );
1896
1923
  const displayTitle = getDisplayTitle(step);
@@ -2371,9 +2398,9 @@ function ArrowUpRightIcon({ className }) {
2371
2398
  }
2372
2399
  );
2373
2400
  }
2374
- var ConfirmationContext = React17.createContext(null);
2401
+ var ConfirmationContext = React19.createContext(null);
2375
2402
  function useConfirmationContext() {
2376
- const context = React17.useContext(ConfirmationContext);
2403
+ const context = React19.useContext(ConfirmationContext);
2377
2404
  if (!context) {
2378
2405
  throw new Error(
2379
2406
  "Confirmation components must be used within a Confirmation provider"
@@ -3283,9 +3310,9 @@ function ModelSelector({
3283
3310
  showCapabilities = true,
3284
3311
  className
3285
3312
  }) {
3286
- const [isOpen, setIsOpen] = React17.useState(false);
3287
- const containerRef = React17.useRef(null);
3288
- React17.useEffect(() => {
3313
+ const [isOpen, setIsOpen] = React19.useState(false);
3314
+ const containerRef = React19.useRef(null);
3315
+ React19.useEffect(() => {
3289
3316
  function handleClickOutside(event) {
3290
3317
  if (containerRef.current && !containerRef.current.contains(event.target)) {
3291
3318
  setIsOpen(false);
@@ -3294,7 +3321,7 @@ function ModelSelector({
3294
3321
  document.addEventListener("mousedown", handleClickOutside);
3295
3322
  return () => document.removeEventListener("mousedown", handleClickOutside);
3296
3323
  }, []);
3297
- const selectedModel = React17.useMemo(() => {
3324
+ const selectedModel = React19.useMemo(() => {
3298
3325
  if (!value) return null;
3299
3326
  if (providers) {
3300
3327
  for (const provider of providers) {
@@ -3520,7 +3547,7 @@ function PopoverTrigger({
3520
3547
  className,
3521
3548
  ...props
3522
3549
  }) {
3523
- if (asChild && React17.isValidElement(children)) {
3550
+ if (asChild && React19.isValidElement(children)) {
3524
3551
  return /* @__PURE__ */ jsx(Popover$1.Trigger, { render: children, className, ...props });
3525
3552
  }
3526
3553
  return /* @__PURE__ */ jsx(Popover$1.Trigger, { className, ...props, children });
@@ -3655,8 +3682,8 @@ function ThreadPicker({
3655
3682
  itemClassName,
3656
3683
  newButtonClassName
3657
3684
  }) {
3658
- const [isOpen, setIsOpen] = React17.useState(false);
3659
- const selectedThread = React17.useMemo(() => {
3685
+ const [isOpen, setIsOpen] = React19.useState(false);
3686
+ const selectedThread = React19.useMemo(() => {
3660
3687
  if (!value) return null;
3661
3688
  return threads.find((t) => t.id === value) ?? null;
3662
3689
  }, [value, threads]);
@@ -3862,7 +3889,7 @@ function ThreadCard({
3862
3889
  showDelete = true,
3863
3890
  className
3864
3891
  }) {
3865
- const [isHovered, setIsHovered] = React17.useState(false);
3892
+ const [isHovered, setIsHovered] = React19.useState(false);
3866
3893
  const handleDelete = (e) => {
3867
3894
  e.stopPropagation();
3868
3895
  onDelete?.();
@@ -4103,10 +4130,10 @@ function MCPUIFrame({
4103
4130
  showLoading = true,
4104
4131
  testId
4105
4132
  }) {
4106
- const iframeRef = React17.useRef(null);
4107
- const [isLoading, setIsLoading] = React17.useState(true);
4108
- const [error, setError] = React17.useState(null);
4109
- React17.useEffect(() => {
4133
+ const iframeRef = React19.useRef(null);
4134
+ const [isLoading, setIsLoading] = React19.useState(true);
4135
+ const [error, setError] = React19.useState(null);
4136
+ React19.useEffect(() => {
4110
4137
  const handleMessage = (event) => {
4111
4138
  if (event.source !== iframeRef.current?.contentWindow) {
4112
4139
  return;
@@ -4119,17 +4146,17 @@ function MCPUIFrame({
4119
4146
  window.addEventListener("message", handleMessage);
4120
4147
  return () => window.removeEventListener("message", handleMessage);
4121
4148
  }, [onIntent]);
4122
- const handleLoad = React17.useCallback(() => {
4149
+ const handleLoad = React19.useCallback(() => {
4123
4150
  setIsLoading(false);
4124
4151
  onLoad?.();
4125
4152
  }, [onLoad]);
4126
- const handleError = React17.useCallback(() => {
4153
+ const handleError = React19.useCallback(() => {
4127
4154
  const err = new Error("Failed to load MCP UI content");
4128
4155
  setError(err);
4129
4156
  setIsLoading(false);
4130
4157
  onError?.(err);
4131
4158
  }, [onError]);
4132
- const { srcDoc, src } = React17.useMemo(() => {
4159
+ const { srcDoc, src } = React19.useMemo(() => {
4133
4160
  if (resource.mimeType === "text/html") {
4134
4161
  let content = resource.content || "";
4135
4162
  if (resource.blob && !resource.content) {
@@ -4279,6 +4306,284 @@ function MCPUIFrameList({
4279
4306
  `${resource.uri}-${index}`
4280
4307
  )) });
4281
4308
  }
4309
+ var MessageActionsContext = createContext(
4310
+ null
4311
+ );
4312
+ function MessageActionsProvider({
4313
+ children
4314
+ }) {
4315
+ const [registry, setRegistry] = useState(
4316
+ {}
4317
+ );
4318
+ const registerActions = useCallback(
4319
+ (role, actions) => {
4320
+ setRegistry((prev) => ({ ...prev, [role]: actions }));
4321
+ },
4322
+ []
4323
+ );
4324
+ const clearActions = useCallback((role) => {
4325
+ setRegistry((prev) => {
4326
+ const next = { ...prev };
4327
+ delete next[role];
4328
+ return next;
4329
+ });
4330
+ }, []);
4331
+ const getActions = useCallback(
4332
+ (role) => registry[role] ?? [],
4333
+ [registry]
4334
+ );
4335
+ return /* @__PURE__ */ jsx(
4336
+ MessageActionsContext.Provider,
4337
+ {
4338
+ value: { getActions, registerActions, clearActions },
4339
+ children
4340
+ }
4341
+ );
4342
+ }
4343
+ function useMessageActionsContext() {
4344
+ return useContext(MessageActionsContext);
4345
+ }
4346
+ createContext(null);
4347
+ function CopyIcon2() {
4348
+ return /* @__PURE__ */ jsxs(
4349
+ "svg",
4350
+ {
4351
+ width: "13",
4352
+ height: "13",
4353
+ viewBox: "0 0 24 24",
4354
+ fill: "none",
4355
+ stroke: "currentColor",
4356
+ strokeWidth: 2,
4357
+ strokeLinecap: "round",
4358
+ strokeLinejoin: "round",
4359
+ children: [
4360
+ /* @__PURE__ */ jsx("rect", { x: "9", y: "9", width: "13", height: "13", rx: "2", ry: "2" }),
4361
+ /* @__PURE__ */ jsx("path", { d: "M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1" })
4362
+ ]
4363
+ }
4364
+ );
4365
+ }
4366
+ function CheckIcon3() {
4367
+ return /* @__PURE__ */ jsx(
4368
+ "svg",
4369
+ {
4370
+ width: "13",
4371
+ height: "13",
4372
+ viewBox: "0 0 24 24",
4373
+ fill: "none",
4374
+ stroke: "currentColor",
4375
+ strokeWidth: 2.5,
4376
+ strokeLinecap: "round",
4377
+ strokeLinejoin: "round",
4378
+ children: /* @__PURE__ */ jsx("path", { d: "M20 6L9 17l-5-5" })
4379
+ }
4380
+ );
4381
+ }
4382
+ function EditIcon() {
4383
+ return /* @__PURE__ */ jsxs(
4384
+ "svg",
4385
+ {
4386
+ width: "12",
4387
+ height: "12",
4388
+ viewBox: "0 0 24 24",
4389
+ fill: "none",
4390
+ stroke: "currentColor",
4391
+ strokeWidth: 2,
4392
+ strokeLinecap: "round",
4393
+ strokeLinejoin: "round",
4394
+ children: [
4395
+ /* @__PURE__ */ jsx("path", { d: "M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7" }),
4396
+ /* @__PURE__ */ jsx("path", { d: "M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z" })
4397
+ ]
4398
+ }
4399
+ );
4400
+ }
4401
+ function ThumbsUpIcon3() {
4402
+ return /* @__PURE__ */ jsxs(
4403
+ "svg",
4404
+ {
4405
+ width: "13",
4406
+ height: "13",
4407
+ viewBox: "0 0 24 24",
4408
+ fill: "none",
4409
+ stroke: "currentColor",
4410
+ strokeWidth: 2,
4411
+ strokeLinecap: "round",
4412
+ strokeLinejoin: "round",
4413
+ children: [
4414
+ /* @__PURE__ */ jsx("path", { d: "M7 10v12" }),
4415
+ /* @__PURE__ */ jsx("path", { d: "M15 5.88 14 10h5.83a2 2 0 0 1 1.92 2.56l-2.33 8A2 2 0 0 1 17.5 22H4a2 2 0 0 1-2-2v-8a2 2 0 0 1 2-2h2.76a2 2 0 0 0 1.79-1.11L12 2a3.13 3.13 0 0 1 3 3.88Z" })
4416
+ ]
4417
+ }
4418
+ );
4419
+ }
4420
+ function ThumbsDownIcon3() {
4421
+ return /* @__PURE__ */ jsxs(
4422
+ "svg",
4423
+ {
4424
+ width: "13",
4425
+ height: "13",
4426
+ viewBox: "0 0 24 24",
4427
+ fill: "none",
4428
+ stroke: "currentColor",
4429
+ strokeWidth: 2,
4430
+ strokeLinecap: "round",
4431
+ strokeLinejoin: "round",
4432
+ children: [
4433
+ /* @__PURE__ */ jsx("path", { d: "M17 14V2" }),
4434
+ /* @__PURE__ */ jsx("path", { d: "M9 18.12 10 14H4.17a2 2 0 0 1-1.92-2.56l2.33-8A2 2 0 0 1 6.5 2H20a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2h-2.76a2 2 0 0 0-1.79 1.11L12 22a3.13 3.13 0 0 1-3-3.88Z" })
4435
+ ]
4436
+ }
4437
+ );
4438
+ }
4439
+ function CopyAction({ tooltip = "Copy", className }) {
4440
+ return null;
4441
+ }
4442
+ CopyAction.displayName = "CopyAction";
4443
+ function EditAction({ tooltip = "Edit", className }) {
4444
+ return null;
4445
+ }
4446
+ EditAction.displayName = "EditAction";
4447
+ function FeedbackAction({
4448
+ onFeedback,
4449
+ tooltip = "Feedback",
4450
+ className
4451
+ }) {
4452
+ return null;
4453
+ }
4454
+ FeedbackAction.displayName = "FeedbackAction";
4455
+ function Action({
4456
+ icon,
4457
+ tooltip,
4458
+ onClick,
4459
+ hidden,
4460
+ className
4461
+ }) {
4462
+ return null;
4463
+ }
4464
+ Action.displayName = "Action";
4465
+ function MessageActions2({ role, children }) {
4466
+ const ctx = useMessageActionsContext();
4467
+ const actions = useMemo(() => {
4468
+ const result = [];
4469
+ React19__default.Children.forEach(children, (child) => {
4470
+ if (!React19__default.isValidElement(child)) return;
4471
+ const props = child.props;
4472
+ const type = child.type;
4473
+ if (type === CopyAction || child.type?.displayName === "CopyAction") {
4474
+ result.push({
4475
+ id: "copy",
4476
+ icon: /* @__PURE__ */ jsx(CopyIcon2, {}),
4477
+ tooltip: props.tooltip ?? "Copy",
4478
+ onClick: ({ message }) => {
4479
+ navigator.clipboard.writeText(message.content ?? "");
4480
+ },
4481
+ className: props.className
4482
+ });
4483
+ } else if (type === EditAction || child.type?.displayName === "EditAction") {
4484
+ result.push({
4485
+ id: "edit",
4486
+ icon: /* @__PURE__ */ jsx(EditIcon, {}),
4487
+ tooltip: props.tooltip ?? "Edit",
4488
+ onClick: () => {
4489
+ },
4490
+ // handled internally by DefaultMessage via onEditMessage
4491
+ className: props.className
4492
+ });
4493
+ } else if (type === FeedbackAction || child.type?.displayName === "FeedbackAction") {
4494
+ const onFeedback = props.onFeedback;
4495
+ result.push(
4496
+ {
4497
+ id: "feedback-up",
4498
+ icon: /* @__PURE__ */ jsx(ThumbsUpIcon3, {}),
4499
+ tooltip: "Helpful",
4500
+ onClick: ({ message }) => onFeedback?.(message, "helpful"),
4501
+ className: props.className
4502
+ },
4503
+ {
4504
+ id: "feedback-down",
4505
+ icon: /* @__PURE__ */ jsx(ThumbsDownIcon3, {}),
4506
+ tooltip: "Not helpful",
4507
+ onClick: ({ message }) => onFeedback?.(message, "not-helpful"),
4508
+ className: props.className
4509
+ }
4510
+ );
4511
+ } else if (type === Action || child.type?.displayName === "Action") {
4512
+ result.push({
4513
+ id: props.id ?? props.tooltip,
4514
+ icon: props.icon,
4515
+ tooltip: props.tooltip,
4516
+ onClick: props.onClick,
4517
+ hidden: props.hidden,
4518
+ className: props.className
4519
+ });
4520
+ }
4521
+ });
4522
+ return result;
4523
+ }, [children]);
4524
+ useLayoutEffect(() => {
4525
+ if (!ctx) return;
4526
+ ctx.registerActions(role, actions);
4527
+ return () => ctx.clearActions(role);
4528
+ }, [ctx, role, actions]);
4529
+ return null;
4530
+ }
4531
+ function FloatingActions({
4532
+ message,
4533
+ role,
4534
+ align = "left",
4535
+ onEdit
4536
+ }) {
4537
+ const ctx = useMessageActionsContext();
4538
+ const [copiedId, setCopiedId] = React19.useState(null);
4539
+ if (!ctx) return null;
4540
+ const actions = ctx.getActions(role);
4541
+ if (actions.length === 0) return null;
4542
+ return /* @__PURE__ */ jsx(
4543
+ "div",
4544
+ {
4545
+ className: cn(
4546
+ "flex items-center gap-0.5 mt-1",
4547
+ "opacity-0 group-hover/message:opacity-100 transition-opacity duration-150",
4548
+ align === "right" ? "justify-end" : "justify-start"
4549
+ ),
4550
+ children: actions.map((action) => {
4551
+ const isHidden = typeof action.hidden === "function" ? action.hidden({ message }) : action.hidden;
4552
+ if (isHidden) return null;
4553
+ const isCopied = copiedId === action.id;
4554
+ return /* @__PURE__ */ jsx(
4555
+ "button",
4556
+ {
4557
+ type: "button",
4558
+ title: action.tooltip,
4559
+ "aria-label": action.tooltip,
4560
+ className: cn(
4561
+ "flex items-center justify-center size-6 rounded-md",
4562
+ "text-muted-foreground hover:text-foreground hover:bg-muted",
4563
+ "transition-colors",
4564
+ action.className
4565
+ ),
4566
+ onClick: () => {
4567
+ if (action.id === "edit" && onEdit) {
4568
+ onEdit();
4569
+ return;
4570
+ }
4571
+ if (action.id === "copy") {
4572
+ navigator.clipboard.writeText(message.content ?? "");
4573
+ setCopiedId("copy");
4574
+ setTimeout(() => setCopiedId(null), 1500);
4575
+ return;
4576
+ }
4577
+ action.onClick({ message });
4578
+ },
4579
+ children: action.id === "copy" && isCopied ? /* @__PURE__ */ jsx(CheckIcon3, {}) : action.icon
4580
+ },
4581
+ action.id
4582
+ );
4583
+ })
4584
+ }
4585
+ );
4586
+ }
4282
4587
  function DefaultMessage({
4283
4588
  message,
4284
4589
  userAvatar,
@@ -4309,24 +4614,24 @@ function DefaultMessage({
4309
4614
  const isUser = message.role === "user";
4310
4615
  const isCompactionMarker = message.role === "system" && message.metadata?.type === "compaction-marker";
4311
4616
  const isStreaming = isLastMessage && isLoading;
4312
- const [isEditing, setIsEditing] = React17.useState(false);
4313
- const [editValue, setEditValue] = React17.useState(message.content ?? "");
4314
- const editRef = React17.useRef(null);
4315
- const startEdit = React17.useCallback(() => {
4617
+ const [isEditing, setIsEditing] = React19.useState(false);
4618
+ const [editValue, setEditValue] = React19.useState(message.content ?? "");
4619
+ const editRef = React19.useRef(null);
4620
+ const startEdit = React19.useCallback(() => {
4316
4621
  setEditValue(message.content ?? "");
4317
4622
  setIsEditing(true);
4318
4623
  requestAnimationFrame(() => editRef.current?.focus());
4319
4624
  }, [message.content]);
4320
- const cancelEdit = React17.useCallback(() => {
4625
+ const cancelEdit = React19.useCallback(() => {
4321
4626
  setIsEditing(false);
4322
4627
  }, []);
4323
- const submitEdit = React17.useCallback(() => {
4628
+ const submitEdit = React19.useCallback(() => {
4324
4629
  const trimmed = editValue.trim();
4325
4630
  if (!trimmed || !onEditMessage) return;
4326
4631
  onEditMessage(message.id, trimmed);
4327
4632
  setIsEditing(false);
4328
4633
  }, [editValue, message.id, onEditMessage]);
4329
- const handleEditKeyDown = React17.useCallback(
4634
+ const handleEditKeyDown = React19.useCallback(
4330
4635
  (e) => {
4331
4636
  if (e.key === "Enter" && !e.shiftKey) {
4332
4637
  e.preventDefault();
@@ -4368,18 +4673,18 @@ function DefaultMessage({
4368
4673
  /* @__PURE__ */ jsx("div", { className: "flex-1 h-px bg-border" })
4369
4674
  ] });
4370
4675
  }
4371
- const { cleanContent: contentWithoutFollowUps, followUps } = React17.useMemo(() => {
4676
+ const { cleanContent: contentWithoutFollowUps, followUps } = React19.useMemo(() => {
4372
4677
  if (isUser || !message.content) {
4373
4678
  return { cleanContent: message.content, followUps: [] };
4374
4679
  }
4375
4680
  return parseFollowUps(message.content);
4376
4681
  }, [message.content, isUser]);
4377
- const cleanContent = React17.useMemo(() => {
4682
+ const cleanContent = React19.useMemo(() => {
4378
4683
  if (!contentWithoutFollowUps) return contentWithoutFollowUps;
4379
4684
  return contentWithoutFollowUps.replace(/\n*\*{0,2}Sources:?\*{0,2}\s*(\[.+?\]\(.+?\)[,\s]*)+$/gi, "").trim();
4380
4685
  }, [contentWithoutFollowUps]);
4381
4686
  const shouldShowFollowUps = showFollowUps && !isUser && isLastMessage && !isLoading && followUps.length > 0 && onFollowUpClick;
4382
- const sources = React17.useMemo(() => {
4687
+ const sources = React19.useMemo(() => {
4383
4688
  if (isUser || !citations.enabled) return [];
4384
4689
  const extractedSources = [];
4385
4690
  const addSource = (url, title, description) => {
@@ -4433,121 +4738,136 @@ function DefaultMessage({
4433
4738
  const shouldShowSources = citations.enabled && sources.length > 0;
4434
4739
  if (isUser) {
4435
4740
  const hasAttachments = message.attachments && message.attachments.length > 0;
4436
- return /* @__PURE__ */ jsxs(Message, { className: cn("flex gap-2 group/user-msg justify-end"), children: [
4437
- /* @__PURE__ */ jsx("div", { className: "flex flex-col items-end max-w-[80%] min-w-0", children: isEditing ? /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1.5 w-full min-w-[200px]", children: [
4438
- /* @__PURE__ */ jsx(
4439
- "textarea",
4440
- {
4441
- ref: editRef,
4442
- value: editValue,
4443
- onChange: (e) => setEditValue(e.target.value),
4444
- onKeyDown: handleEditKeyDown,
4445
- rows: Math.max(2, (editValue.match(/\n/g) || []).length + 1),
4446
- className: cn(
4447
- "csdk-edit-textarea w-full rounded-lg px-3 py-2 text-sm resize-none",
4448
- "bg-primary text-primary-foreground placeholder:text-primary-foreground/50",
4449
- "focus:outline-none focus:ring-2 focus:ring-primary-foreground/30",
4450
- userMessageClassName
4451
- )
4452
- }
4453
- ),
4454
- /* @__PURE__ */ jsxs("div", { className: "flex gap-1.5 justify-end", children: [
4455
- /* @__PURE__ */ jsx(
4456
- "button",
4457
- {
4458
- type: "button",
4459
- onClick: cancelEdit,
4460
- className: "csdk-edit-cancel px-3 py-1 text-xs rounded-md bg-muted text-muted-foreground hover:bg-muted/80 transition-colors",
4461
- children: "Cancel"
4462
- }
4463
- ),
4464
- /* @__PURE__ */ jsx(
4465
- "button",
4466
- {
4467
- type: "button",
4468
- onClick: submitEdit,
4469
- disabled: !editValue.trim(),
4470
- className: "csdk-edit-submit px-3 py-1 text-xs rounded-md bg-primary text-primary-foreground hover:bg-primary/90 disabled:opacity-50 transition-colors",
4471
- children: "Send"
4472
- }
4473
- )
4474
- ] })
4475
- ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
4476
- message.content && /* @__PURE__ */ jsxs("div", { className: "relative", children: [
4477
- /* @__PURE__ */ jsx(
4478
- MessageContent,
4479
- {
4480
- className: cn(
4481
- "csdk-message-user rounded-lg px-4 py-2 bg-primary text-primary-foreground",
4482
- userMessageClassName
4741
+ return /* @__PURE__ */ jsxs(
4742
+ Message,
4743
+ {
4744
+ className: cn("flex gap-2 group/user-msg group/message justify-end"),
4745
+ children: [
4746
+ /* @__PURE__ */ jsx("div", { className: "flex flex-col items-end max-w-[80%] min-w-0", children: isEditing ? /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1.5 w-full min-w-[200px]", children: [
4747
+ /* @__PURE__ */ jsx(
4748
+ "textarea",
4749
+ {
4750
+ ref: editRef,
4751
+ value: editValue,
4752
+ onChange: (e) => setEditValue(e.target.value),
4753
+ onKeyDown: handleEditKeyDown,
4754
+ rows: Math.max(2, (editValue.match(/\n/g) || []).length + 1),
4755
+ className: cn(
4756
+ "csdk-edit-textarea w-full rounded-lg px-3 py-2 text-sm resize-none",
4757
+ "bg-primary text-primary-foreground placeholder:text-primary-foreground/50",
4758
+ "focus:outline-none focus:ring-2 focus:ring-primary-foreground/30",
4759
+ userMessageClassName
4760
+ )
4761
+ }
4762
+ ),
4763
+ /* @__PURE__ */ jsxs("div", { className: "flex gap-1.5 justify-end", children: [
4764
+ /* @__PURE__ */ jsx(
4765
+ "button",
4766
+ {
4767
+ type: "button",
4768
+ onClick: cancelEdit,
4769
+ className: "csdk-edit-cancel px-3 py-1 text-xs rounded-md bg-muted text-muted-foreground hover:bg-muted/80 transition-colors",
4770
+ children: "Cancel"
4771
+ }
4483
4772
  ),
4484
- markdown: true,
4485
- size,
4486
- children: message.content
4487
- }
4488
- ),
4489
- showEditBtn && /* @__PURE__ */ jsx(
4490
- "button",
4491
- {
4492
- type: "button",
4493
- onClick: startEdit,
4494
- "aria-label": "Edit message",
4495
- className: cn(
4496
- "csdk-edit-btn absolute -left-7 top-1/2 -translate-y-1/2",
4497
- "size-6 flex items-center justify-center rounded-full",
4498
- "text-muted-foreground bg-background border border-border shadow-sm",
4499
- "opacity-0 group-hover/user-msg:opacity-100 transition-opacity",
4500
- "hover:text-foreground hover:bg-muted"
4773
+ /* @__PURE__ */ jsx(
4774
+ "button",
4775
+ {
4776
+ type: "button",
4777
+ onClick: submitEdit,
4778
+ disabled: !editValue.trim(),
4779
+ className: "csdk-edit-submit px-3 py-1 text-xs rounded-md bg-primary text-primary-foreground hover:bg-primary/90 disabled:opacity-50 transition-colors",
4780
+ children: "Send"
4781
+ }
4782
+ )
4783
+ ] })
4784
+ ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
4785
+ message.content && /* @__PURE__ */ jsxs("div", { className: "relative", children: [
4786
+ /* @__PURE__ */ jsx(
4787
+ MessageContent,
4788
+ {
4789
+ className: cn(
4790
+ "csdk-message-user rounded-lg px-4 py-2 bg-primary text-primary-foreground",
4791
+ userMessageClassName
4792
+ ),
4793
+ markdown: true,
4794
+ size,
4795
+ children: message.content
4796
+ }
4501
4797
  ),
4502
- children: /* @__PURE__ */ jsxs(
4503
- "svg",
4798
+ showEditBtn && /* @__PURE__ */ jsx(
4799
+ "button",
4504
4800
  {
4505
- width: "12",
4506
- height: "12",
4507
- viewBox: "0 0 24 24",
4508
- fill: "none",
4509
- stroke: "currentColor",
4510
- strokeWidth: 2,
4511
- strokeLinecap: "round",
4512
- strokeLinejoin: "round",
4513
- children: [
4514
- /* @__PURE__ */ jsx("path", { d: "M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7" }),
4515
- /* @__PURE__ */ jsx("path", { d: "M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z" })
4516
- ]
4801
+ type: "button",
4802
+ onClick: startEdit,
4803
+ "aria-label": "Edit message",
4804
+ className: cn(
4805
+ "csdk-edit-btn absolute -left-7 top-1/2 -translate-y-1/2",
4806
+ "size-6 flex items-center justify-center rounded-full",
4807
+ "text-muted-foreground bg-background border border-border shadow-sm",
4808
+ "opacity-0 group-hover/user-msg:opacity-100 transition-opacity",
4809
+ "hover:text-foreground hover:bg-muted"
4810
+ ),
4811
+ children: /* @__PURE__ */ jsxs(
4812
+ "svg",
4813
+ {
4814
+ width: "12",
4815
+ height: "12",
4816
+ viewBox: "0 0 24 24",
4817
+ fill: "none",
4818
+ stroke: "currentColor",
4819
+ strokeWidth: 2,
4820
+ strokeLinecap: "round",
4821
+ strokeLinejoin: "round",
4822
+ children: [
4823
+ /* @__PURE__ */ jsx("path", { d: "M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7" }),
4824
+ /* @__PURE__ */ jsx("path", { d: "M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z" })
4825
+ ]
4826
+ }
4827
+ )
4517
4828
  }
4518
4829
  )
4830
+ ] }),
4831
+ hasAttachments && /* @__PURE__ */ jsx("div", { className: "mt-2 flex flex-wrap gap-2 justify-end", children: message.attachments.map((attachment, index) => /* @__PURE__ */ jsx(AttachmentPreview, { attachment }, index)) }),
4832
+ showBranchNav && /* @__PURE__ */ jsx(
4833
+ BranchNavigator,
4834
+ {
4835
+ siblingIndex: branchInfo.siblingIndex,
4836
+ totalSiblings: branchInfo.totalSiblings,
4837
+ hasPrevious: branchInfo.hasPrevious,
4838
+ hasNext: branchInfo.hasNext,
4839
+ onPrevious: () => onSwitchBranch(
4840
+ branchInfo.siblingIds[branchInfo.siblingIndex - 1]
4841
+ ),
4842
+ onNext: () => onSwitchBranch(
4843
+ branchInfo.siblingIds[branchInfo.siblingIndex + 1]
4844
+ ),
4845
+ className: "mt-1"
4846
+ }
4847
+ ),
4848
+ /* @__PURE__ */ jsx(
4849
+ FloatingActions,
4850
+ {
4851
+ message,
4852
+ role: "user",
4853
+ align: "right",
4854
+ onEdit: onEditMessage ? startEdit : void 0
4855
+ }
4856
+ )
4857
+ ] }) }),
4858
+ showUserAvatar && /* @__PURE__ */ jsx(
4859
+ MessageAvatar,
4860
+ {
4861
+ src: userAvatar.src,
4862
+ alt: "User",
4863
+ fallback: userAvatar.fallback,
4864
+ className: userAvatar.className,
4865
+ children: userAvatar.component
4519
4866
  }
4520
4867
  )
4521
- ] }),
4522
- hasAttachments && /* @__PURE__ */ jsx("div", { className: "mt-2 flex flex-wrap gap-2 justify-end", children: message.attachments.map((attachment, index) => /* @__PURE__ */ jsx(AttachmentPreview, { attachment }, index)) }),
4523
- showBranchNav && /* @__PURE__ */ jsx(
4524
- BranchNavigator,
4525
- {
4526
- siblingIndex: branchInfo.siblingIndex,
4527
- totalSiblings: branchInfo.totalSiblings,
4528
- hasPrevious: branchInfo.hasPrevious,
4529
- hasNext: branchInfo.hasNext,
4530
- onPrevious: () => onSwitchBranch(
4531
- branchInfo.siblingIds[branchInfo.siblingIndex - 1]
4532
- ),
4533
- onNext: () => onSwitchBranch(
4534
- branchInfo.siblingIds[branchInfo.siblingIndex + 1]
4535
- ),
4536
- className: "mt-1"
4537
- }
4538
- )
4539
- ] }) }),
4540
- showUserAvatar && /* @__PURE__ */ jsx(
4541
- MessageAvatar,
4542
- {
4543
- src: userAvatar.src,
4544
- alt: "User",
4545
- fallback: userAvatar.fallback,
4546
- className: userAvatar.className,
4547
- children: userAvatar.component
4548
- }
4549
- )
4550
- ] });
4868
+ ]
4869
+ }
4870
+ );
4551
4871
  }
4552
4872
  const isToolHidden = (exec) => {
4553
4873
  if (exec.hidden === true) return true;
@@ -4584,7 +4904,7 @@ function DefaultMessage({
4584
4904
  result: exec.result,
4585
4905
  error: exec.error
4586
4906
  }));
4587
- return /* @__PURE__ */ jsxs(Message, { className: "flex gap-2", children: [
4907
+ return /* @__PURE__ */ jsxs(Message, { className: "flex gap-2 group/message", children: [
4588
4908
  /* @__PURE__ */ jsx(
4589
4909
  MessageAvatar,
4590
4910
  {
@@ -4642,7 +4962,7 @@ function DefaultMessage({
4642
4962
  renderProps
4643
4963
  );
4644
4964
  if (output != null) {
4645
- return /* @__PURE__ */ jsx(React17.Fragment, { children: output }, exec.id);
4965
+ return /* @__PURE__ */ jsx(React19.Fragment, { children: output }, exec.id);
4646
4966
  }
4647
4967
  }
4648
4968
  if (mcpToolRenderer && (exec.source === "mcp" || toolDef?.source === "mcp")) {
@@ -4758,7 +5078,7 @@ function DefaultMessage({
4758
5078
  const output = toolDef.render(
4759
5079
  renderProps
4760
5080
  );
4761
- return /* @__PURE__ */ jsx(React17.Fragment, { children: output }, tool.id);
5081
+ return /* @__PURE__ */ jsx(React19.Fragment, { children: output }, tool.id);
4762
5082
  }
4763
5083
  return /* @__PURE__ */ jsx(
4764
5084
  PermissionConfirmation,
@@ -4800,14 +5120,15 @@ function DefaultMessage({
4800
5120
  className: followUpClassName,
4801
5121
  buttonClassName: followUpButtonClassName
4802
5122
  }
4803
- )
5123
+ ),
5124
+ /* @__PURE__ */ jsx(FloatingActions, { message, role: "assistant", align: "left" })
4804
5125
  ] })
4805
5126
  )
4806
5127
  ] })
4807
5128
  ] });
4808
5129
  }
4809
5130
  function AttachmentPreview({ attachment }) {
4810
- const [expanded, setExpanded] = React17.useState(false);
5131
+ const [expanded, setExpanded] = React19.useState(false);
4811
5132
  if (attachment.type !== "image") {
4812
5133
  return /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 rounded-lg border bg-muted/50 px-3 py-2 text-sm", children: [
4813
5134
  /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: attachment.type }),
@@ -5265,10 +5586,10 @@ function ChatView({ children, className }) {
5265
5586
  ChatView.displayName = "ChatView";
5266
5587
  function chatViewHasOnlyLayoutChildren(chatViewElement) {
5267
5588
  if (!chatViewElement?.props?.children) return false;
5268
- const childArray = React17__default.Children.toArray(chatViewElement.props.children);
5589
+ const childArray = React19__default.Children.toArray(chatViewElement.props.children);
5269
5590
  if (childArray.length === 0) return false;
5270
5591
  return childArray.every(
5271
- (child) => React17__default.isValidElement(child) && (child.type === Header || child.type === Footer)
5592
+ (child) => React19__default.isValidElement(child) && (child.type === Header || child.type === Footer)
5272
5593
  );
5273
5594
  }
5274
5595
  function Header({ children, className }) {
@@ -5406,18 +5727,18 @@ function ThreadPickerCompound(props) {
5406
5727
  );
5407
5728
  }
5408
5729
  function hasCompoundChild(children, ...components) {
5409
- return React17__default.Children.toArray(children).some(
5410
- (child) => React17__default.isValidElement(child) && components.includes(child.type)
5730
+ return React19__default.Children.toArray(children).some(
5731
+ (child) => React19__default.isValidElement(child) && components.includes(child.type)
5411
5732
  );
5412
5733
  }
5413
5734
  function findCompoundChild(children, component) {
5414
- return React17__default.Children.toArray(children).find(
5415
- (child) => React17__default.isValidElement(child) && child.type === component
5735
+ return React19__default.Children.toArray(children).find(
5736
+ (child) => React19__default.isValidElement(child) && child.type === component
5416
5737
  );
5417
5738
  }
5418
5739
  function filterCompoundChildren(children, ...components) {
5419
- return React17__default.Children.toArray(children).filter(
5420
- (child) => React17__default.isValidElement(child) && components.includes(child.type)
5740
+ return React19__default.Children.toArray(children).filter(
5741
+ (child) => React19__default.isValidElement(child) && components.includes(child.type)
5421
5742
  );
5422
5743
  }
5423
5744
  var DEFAULT_MAX_FILE_SIZE2 = 5 * 1024 * 1024;
@@ -5695,7 +6016,7 @@ function ChatComponent({
5695
6016
  },
5696
6017
  [onSendMessage]
5697
6018
  );
5698
- const contextValue = React17__default.useMemo(
6019
+ const contextValue = React19__default.useMemo(
5699
6020
  () => ({
5700
6021
  view,
5701
6022
  send,
@@ -5703,6 +6024,9 @@ function ChatComponent({
5703
6024
  onStop,
5704
6025
  attachmentsEnabled,
5705
6026
  placeholder,
6027
+ // Messages for Chat.MessageList primitive
6028
+ messages,
6029
+ registeredTools,
5706
6030
  // Thread management - passed from connected-chat
5707
6031
  onNewChat,
5708
6032
  threads,
@@ -5718,6 +6042,8 @@ function ChatComponent({
5718
6042
  onStop,
5719
6043
  attachmentsEnabled,
5720
6044
  placeholder,
6045
+ messages,
6046
+ registeredTools,
5721
6047
  onNewChat,
5722
6048
  threads,
5723
6049
  currentThreadId,
@@ -5726,7 +6052,7 @@ function ChatComponent({
5726
6052
  isThreadBusy
5727
6053
  ]
5728
6054
  );
5729
- return /* @__PURE__ */ jsx(CopilotChatContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsxs(
6055
+ return /* @__PURE__ */ jsx(MessageActionsProvider, { children: /* @__PURE__ */ jsx(CopilotChatContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsxs(
5730
6056
  "div",
5731
6057
  {
5732
6058
  className: cn(
@@ -5826,7 +6152,10 @@ function ChatComponent({
5826
6152
  }
5827
6153
  const savedExecutions = message.metadata?.toolExecutions;
5828
6154
  const messageToolExecutions = message.toolExecutions || savedExecutions;
5829
- const messageWithExecutions = messageToolExecutions ? { ...message, toolExecutions: messageToolExecutions } : message;
6155
+ const messageWithExecutions = messageToolExecutions ? {
6156
+ ...message,
6157
+ toolExecutions: messageToolExecutions
6158
+ } : message;
5830
6159
  const handleFollowUpClick = (question) => {
5831
6160
  if (onSuggestionClick) {
5832
6161
  onSuggestionClick(question);
@@ -5834,7 +6163,7 @@ function ChatComponent({
5834
6163
  onSendMessage?.(question);
5835
6164
  }
5836
6165
  };
5837
- return renderMessage ? /* @__PURE__ */ jsx(React17__default.Fragment, { children: renderMessage(messageWithExecutions, index) }, message.id) : /* @__PURE__ */ jsx(
6166
+ return renderMessage ? /* @__PURE__ */ jsx(React19__default.Fragment, { children: renderMessage(messageWithExecutions, index) }, message.id) : /* @__PURE__ */ jsx(
5838
6167
  DefaultMessage,
5839
6168
  {
5840
6169
  message: messageWithExecutions,
@@ -6017,7 +6346,7 @@ function ChatComponent({
6017
6346
  rootFooter
6018
6347
  ]
6019
6348
  }
6020
- ) });
6349
+ ) }) });
6021
6350
  }
6022
6351
  var Chat = Object.assign(ChatComponent, {
6023
6352
  Root: ChatComponent,
@@ -6033,9 +6362,34 @@ var Chat = Object.assign(ChatComponent, {
6033
6362
  Suggestions: SuggestionsCompound,
6034
6363
  BackButton,
6035
6364
  // Navigation: start new chat
6036
- ThreadPicker: ThreadPickerCompound
6365
+ ThreadPicker: ThreadPickerCompound,
6037
6366
  // Thread switching
6367
+ // Message actions compound components
6368
+ MessageActions: MessageActions2,
6369
+ CopyAction,
6370
+ EditAction,
6371
+ FeedbackAction,
6372
+ Action
6038
6373
  });
6374
+ function MessageList({ children, className }) {
6375
+ const { messages, registeredTools } = useCopilotChatContext();
6376
+ return /* @__PURE__ */ jsx("div", { className, children: messages.map((message, index) => {
6377
+ if (children) {
6378
+ return /* @__PURE__ */ jsx(React19.Fragment, { children: children(message, index) }, message.id);
6379
+ }
6380
+ return /* @__PURE__ */ jsx(
6381
+ DefaultMessage,
6382
+ {
6383
+ message,
6384
+ userAvatar: { fallback: "U" },
6385
+ assistantAvatar: { fallback: "AI" },
6386
+ registeredTools,
6387
+ isLastMessage: index === messages.length - 1
6388
+ },
6389
+ message.id
6390
+ );
6391
+ }) });
6392
+ }
6039
6393
  function ToolExecutionMessage({
6040
6394
  executions,
6041
6395
  assistantAvatar = { fallback: "AI" },
@@ -6179,7 +6533,8 @@ function useInternalThreadManager(config = {}) {
6179
6533
  adapter,
6180
6534
  saveDebounce = 1e3,
6181
6535
  autoRestoreLastThread = true,
6182
- onThreadChange
6536
+ onThreadChange,
6537
+ enabled = true
6183
6538
  } = config;
6184
6539
  const threadManagerConfig = {
6185
6540
  adapter,
@@ -6268,6 +6623,7 @@ function useInternalThreadManager(config = {}) {
6268
6623
  });
6269
6624
  }, [clearCurrentThread, setMessages, onThreadChange]);
6270
6625
  useEffect(() => {
6626
+ if (!enabled) return;
6271
6627
  if (hasInitializedRef.current || !currentThread) {
6272
6628
  return;
6273
6629
  }
@@ -6299,8 +6655,9 @@ function useInternalThreadManager(config = {}) {
6299
6655
  requestAnimationFrame(() => {
6300
6656
  isLoadingMessagesRef.current = false;
6301
6657
  });
6302
- }, [adapter, currentThread, setMessages, getMessageSnapshot, onThreadChange]);
6658
+ }, [enabled, adapter, currentThread, setMessages, getMessageSnapshot, onThreadChange]);
6303
6659
  useEffect(() => {
6660
+ if (!enabled) return;
6304
6661
  if (isLoadingMessagesRef.current) {
6305
6662
  return;
6306
6663
  }
@@ -6333,6 +6690,7 @@ function useInternalThreadManager(config = {}) {
6333
6690
  updateCurrentThread({ messages: coreMessages });
6334
6691
  lastSavedSnapshotRef.current = currentSnapshot;
6335
6692
  }, [
6693
+ enabled,
6336
6694
  adapter,
6337
6695
  messages,
6338
6696
  currentThreadId,
@@ -6411,7 +6769,7 @@ function CopilotChatBase(props) {
6411
6769
  } = props;
6412
6770
  const persistenceConfig = parsePersistenceConfig(persistence, onThreadChange);
6413
6771
  const threadManagerResult = useInternalThreadManager(
6414
- persistenceConfig ?? { autoRestoreLastThread: false }
6772
+ persistenceConfig ?? { autoRestoreLastThread: false, enabled: false }
6415
6773
  );
6416
6774
  const isPersistenceEnabled = !!persistence;
6417
6775
  const {
@@ -6580,7 +6938,7 @@ function CopilotChatBase(props) {
6580
6938
  footer: classNames.footer
6581
6939
  } : void 0;
6582
6940
  const { threadManager, handleSwitchThread, handleNewThread, isBusy } = threadManagerResult;
6583
- const handleDeleteThread = React17__default.useCallback(
6941
+ const handleDeleteThread = React19__default.useCallback(
6584
6942
  (threadId) => {
6585
6943
  const isCurrentThread = threadManager.currentThreadId === threadId;
6586
6944
  threadManager.deleteThread(threadId);
@@ -6708,6 +7066,38 @@ function PoweredBy({ className, showLogo = true }) {
6708
7066
  );
6709
7067
  }
6710
7068
 
6711
- export { AlertTriangleIcon, BotIcon, BranchNavigator, Button, CapabilityBadge, CapabilityList, Chat, ChatContainerContent, ChatContainerRoot, ChatContainerScrollAnchor, ChatWelcome, CheckIcon, ChevronDownIcon2 as ChevronDownIcon, ChevronLeftIcon, ChevronUpIcon, CitationBadge, CitationSuperscript, CloseIcon, CodeBlock, CompactPermissionConfirmation, Confirmation, ConfirmationActions, ConfirmationApproved, ConfirmationMessage, ConfirmationPending, ConfirmationRejected, ConnectedChat, CopilotChat, CopilotUIProvider, CopyIcon, DEFAULT_PERMISSION_OPTIONS, DevLogger, FeedbackBar, FollowUpQuestions, InlineToolSteps, Loader, MCPUIFrame, MCPUIFrameList, Markdown, MessageAvatar, MessageContent, Message as MessagePrimitive, MessageWithCitations, ModelSelector, PermissionConfirmation, PoweredBy, PromptInput, PromptInputAction, PromptInputActions, PromptInputTextarea, Reasoning, ReasoningContent, ReasoningTrigger, RefreshIcon, ScrollButton, SearchAnswer, SearchResults, SearchResultsWithAnswer, SendIcon, SimpleConfirmation, SimpleModelSelector, SimpleReasoning, SimpleSource, Source, SourceContent, SourceGroup, SourcePill, SourceTrigger, SourcesBar, SourcesCollapsible, SourcesList, StopIcon, ThreadCard, ThreadList, ThreadPicker, ThumbsDownIcon2 as ThumbsDownIcon, ThumbsUpIcon2 as ThumbsUpIcon, ToolExecutionMessage, ToolStep, ToolSteps, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, UserIcon, XIcon2 as XIcon, annotationsToCitations, cn, parseFollowUps, resultsToCitations, useChatContainer, useCopilotChatContext, useCopilotUI };
7069
+ // src/ui/index.ts
7070
+ var ChatPrimitives = {
7071
+ // ── List ──────────────────────────────────────────────
7072
+ /** Renders the message list via render-prop. Falls back to DefaultMessage if no children. */
7073
+ MessageList,
7074
+ // ── Messages ──────────────────────────────────────────
7075
+ /** Full SDK message bubble (user + assistant + tools). Use as fallback inside MessageList. */
7076
+ DefaultMessage,
7077
+ /** Low-level message row wrapper (flex layout + avatar slot) */
7078
+ Message,
7079
+ /** Message avatar — image with fallback text/icon */
7080
+ MessageAvatar,
7081
+ /** Message content bubble — supports markdown */
7082
+ MessageContent,
7083
+ /** Action bar below a message (copy, feedback, etc.) */
7084
+ MessageActions,
7085
+ /** Single action button with tooltip inside MessageActions */
7086
+ MessageAction,
7087
+ // ── Layout ────────────────────────────────────────────
7088
+ /** Chat header bar with title and controls */
7089
+ Header: ChatHeader,
7090
+ /** Welcome screen shown when there are no messages */
7091
+ Welcome: ChatWelcome,
7092
+ /** Chat input / composer */
7093
+ Input: PromptInput,
7094
+ /** Scroll anchor — keeps the view pinned to the latest message */
7095
+ ScrollAnchor: ChatContainerScrollAnchor,
7096
+ // ── Indicators ────────────────────────────────────────
7097
+ /** Loading / streaming indicator (dots, wave, typing variants) */
7098
+ Loader
7099
+ };
7100
+
7101
+ export { AlertTriangleIcon, BotIcon, BranchNavigator, Button, CapabilityBadge, CapabilityList, Chat, ChatContainerContent, ChatContainerRoot, ChatContainerScrollAnchor, ChatPrimitives, 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 };
6712
7102
  //# sourceMappingURL=index.js.map
6713
7103
  //# sourceMappingURL=index.js.map