@copilotkitnext/react 0.0.12 → 0.0.13-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -37,19 +37,29 @@ __export(index_exports, {
37
37
  CopilotChatConfigurationProvider: () => CopilotChatConfigurationProvider,
38
38
  CopilotChatInput: () => CopilotChatInput_default,
39
39
  CopilotChatMessageView: () => CopilotChatMessageView_default,
40
+ CopilotChatSuggestionPill: () => CopilotChatSuggestionPill_default,
41
+ CopilotChatSuggestionView: () => CopilotChatSuggestionView_default,
42
+ CopilotChatToggleButton: () => CopilotChatToggleButton,
43
+ CopilotChatToggleButtonCloseIcon: () => DefaultCloseIcon,
44
+ CopilotChatToggleButtonOpenIcon: () => DefaultOpenIcon,
40
45
  CopilotChatToolCallsView: () => CopilotChatToolCallsView_default,
41
46
  CopilotChatUserMessage: () => CopilotChatUserMessage_default,
42
47
  CopilotChatView: () => CopilotChatView_default,
43
48
  CopilotKitProvider: () => CopilotKitProvider,
49
+ CopilotModalHeader: () => CopilotModalHeader,
50
+ CopilotSidebar: () => CopilotSidebar,
51
+ CopilotSidebarView: () => CopilotSidebarView,
44
52
  WildcardToolCallRender: () => WildcardToolCallRender,
45
53
  defineToolCallRender: () => defineToolCallRender,
46
54
  useAgent: () => useAgent,
47
55
  useAgentContext: () => useAgentContext,
56
+ useConfigureSuggestions: () => useConfigureSuggestions,
48
57
  useCopilotChatConfiguration: () => useCopilotChatConfiguration,
49
58
  useCopilotKit: () => useCopilotKit,
50
59
  useFrontendTool: () => useFrontendTool,
51
60
  useHumanInTheLoop: () => useHumanInTheLoop,
52
- useRenderToolCall: () => useRenderToolCall
61
+ useRenderToolCall: () => useRenderToolCall,
62
+ useSuggestions: () => useSuggestions
53
63
  });
54
64
  module.exports = __toCommonJS(index_exports);
55
65
 
@@ -78,24 +88,56 @@ var CopilotChatDefaultLabels = {
78
88
  assistantMessageToolbarRegenerateLabel: "Regenerate",
79
89
  userMessageToolbarCopyMessageLabel: "Copy",
80
90
  userMessageToolbarEditMessageLabel: "Edit",
81
- chatDisclaimerText: "AI can make mistakes. Please verify important information."
91
+ chatDisclaimerText: "AI can make mistakes. Please verify important information.",
92
+ chatToggleOpenLabel: "Open chat",
93
+ chatToggleCloseLabel: "Close chat",
94
+ modalHeaderTitle: "CopilotKit Chat"
82
95
  };
83
96
  var CopilotChatConfiguration = (0, import_react.createContext)(null);
84
- var CopilotChatConfigurationProvider = ({
85
- children,
86
- labels = {},
87
- agentId,
88
- threadId
89
- }) => {
90
- const mergedLabels = {
91
- ...CopilotChatDefaultLabels,
92
- ...labels
93
- };
94
- const configurationValue = {
95
- labels: mergedLabels,
96
- agentId: agentId ?? import_shared.DEFAULT_AGENT_ID,
97
- threadId
98
- };
97
+ var CopilotChatConfigurationProvider = ({ children, labels, agentId, threadId, isModalDefaultOpen }) => {
98
+ const parentConfig = (0, import_react.useContext)(CopilotChatConfiguration);
99
+ const mergedLabels = (0, import_react.useMemo)(
100
+ () => ({
101
+ ...CopilotChatDefaultLabels,
102
+ ...parentConfig?.labels ?? {},
103
+ ...labels ?? {}
104
+ }),
105
+ [labels, parentConfig?.labels]
106
+ );
107
+ const resolvedAgentId = agentId ?? parentConfig?.agentId ?? import_shared.DEFAULT_AGENT_ID;
108
+ const resolvedThreadId = (0, import_react.useMemo)(() => {
109
+ if (threadId) {
110
+ return threadId;
111
+ }
112
+ if (parentConfig?.threadId) {
113
+ return parentConfig.threadId;
114
+ }
115
+ return (0, import_shared.randomUUID)();
116
+ }, [threadId, parentConfig?.threadId]);
117
+ const resolvedDefaultOpen = isModalDefaultOpen ?? parentConfig?.isModalDefaultOpen ?? true;
118
+ const [internalModalOpen, setInternalModalOpen] = (0, import_react.useState)(
119
+ parentConfig?.isModalOpen ?? resolvedDefaultOpen
120
+ );
121
+ const resolvedIsModalOpen = parentConfig?.isModalOpen ?? internalModalOpen;
122
+ const resolvedSetModalOpen = parentConfig?.setModalOpen ?? setInternalModalOpen;
123
+ const configurationValue = (0, import_react.useMemo)(
124
+ () => ({
125
+ labels: mergedLabels,
126
+ agentId: resolvedAgentId,
127
+ threadId: resolvedThreadId,
128
+ isModalOpen: resolvedIsModalOpen,
129
+ setModalOpen: resolvedSetModalOpen,
130
+ isModalDefaultOpen: resolvedDefaultOpen
131
+ }),
132
+ [
133
+ mergedLabels,
134
+ resolvedAgentId,
135
+ resolvedThreadId,
136
+ resolvedIsModalOpen,
137
+ resolvedSetModalOpen,
138
+ resolvedDefaultOpen
139
+ ]
140
+ );
99
141
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CopilotChatConfiguration.Provider, { value: configurationValue, children });
100
142
  };
101
143
  var useCopilotChatConfiguration = () => {
@@ -549,6 +591,18 @@ function CopilotChatInput({
549
591
  const resolvedValue = isControlled ? value ?? "" : internalValue;
550
592
  const inputRef = (0, import_react4.useRef)(null);
551
593
  const audioRecorderRef = (0, import_react4.useRef)(null);
594
+ const config = useCopilotChatConfiguration();
595
+ const previousModalStateRef = (0, import_react4.useRef)(void 0);
596
+ (0, import_react4.useEffect)(() => {
597
+ if (!autoFocus) {
598
+ previousModalStateRef.current = config?.isModalOpen;
599
+ return;
600
+ }
601
+ if (config?.isModalOpen && !previousModalStateRef.current) {
602
+ inputRef.current?.focus();
603
+ }
604
+ previousModalStateRef.current = config?.isModalOpen;
605
+ }, [config?.isModalOpen, autoFocus]);
552
606
  (0, import_react4.useEffect)(() => {
553
607
  const recorder = audioRecorderRef.current;
554
608
  if (!recorder) {
@@ -599,59 +653,32 @@ function CopilotChatInput({
599
653
  onKeyDown: handleKeyDown,
600
654
  autoFocus
601
655
  });
602
- const BoundAudioRecorder = renderSlot(
603
- audioRecorder,
604
- CopilotChatAudioRecorder,
605
- {
606
- ref: audioRecorderRef
607
- }
608
- );
656
+ const BoundAudioRecorder = renderSlot(audioRecorder, CopilotChatAudioRecorder, {
657
+ ref: audioRecorderRef
658
+ });
609
659
  const BoundSendButton = renderSlot(sendButton, CopilotChatInput.SendButton, {
610
660
  onClick: send,
611
661
  disabled: !resolvedValue.trim() || !onSubmitMessage
612
662
  });
613
- const BoundStartTranscribeButton = renderSlot(
614
- startTranscribeButton,
615
- CopilotChatInput.StartTranscribeButton,
616
- {
617
- onClick: onStartTranscribe
618
- }
619
- );
620
- const BoundCancelTranscribeButton = renderSlot(
621
- cancelTranscribeButton,
622
- CopilotChatInput.CancelTranscribeButton,
623
- {
624
- onClick: onCancelTranscribe
625
- }
626
- );
627
- const BoundFinishTranscribeButton = renderSlot(
628
- finishTranscribeButton,
629
- CopilotChatInput.FinishTranscribeButton,
630
- {
631
- onClick: onFinishTranscribe
632
- }
633
- );
634
- const BoundAddFileButton = renderSlot(
635
- addFileButton,
636
- CopilotChatInput.AddFileButton,
637
- {
638
- onClick: onAddFile,
639
- disabled: mode === "transcribe"
640
- }
641
- );
642
- const BoundToolsButton = renderSlot(
643
- toolsButton,
644
- CopilotChatInput.ToolsButton,
645
- {
646
- disabled: mode === "transcribe",
647
- toolsMenu
648
- }
649
- );
663
+ const BoundStartTranscribeButton = renderSlot(startTranscribeButton, CopilotChatInput.StartTranscribeButton, {
664
+ onClick: onStartTranscribe
665
+ });
666
+ const BoundCancelTranscribeButton = renderSlot(cancelTranscribeButton, CopilotChatInput.CancelTranscribeButton, {
667
+ onClick: onCancelTranscribe
668
+ });
669
+ const BoundFinishTranscribeButton = renderSlot(finishTranscribeButton, CopilotChatInput.FinishTranscribeButton, {
670
+ onClick: onFinishTranscribe
671
+ });
672
+ const BoundAddFileButton = renderSlot(addFileButton, CopilotChatInput.AddFileButton, {
673
+ onClick: onAddFile,
674
+ disabled: mode === "transcribe"
675
+ });
676
+ const BoundToolsButton = renderSlot(toolsButton, CopilotChatInput.ToolsButton, {
677
+ disabled: mode === "transcribe",
678
+ toolsMenu
679
+ });
650
680
  const BoundToolbar = renderSlot(
651
- typeof toolbar === "string" || toolbar === void 0 ? (0, import_tailwind_merge3.twMerge)(
652
- toolbar,
653
- "w-full h-[60px] bg-transparent flex items-center justify-between"
654
- ) : toolbar,
681
+ typeof toolbar === "string" || toolbar === void 0 ? (0, import_tailwind_merge3.twMerge)(toolbar, "w-full h-[60px] bg-transparent flex items-center justify-between") : toolbar,
655
682
  CopilotChatInput.Toolbar,
656
683
  {
657
684
  children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
@@ -692,6 +719,12 @@ function CopilotChatInput({
692
719
  additionalToolbarItems
693
720
  }) });
694
721
  }
722
+ const handleContainerClick = (e) => {
723
+ const target = e.target;
724
+ if (target.tagName !== "BUTTON" && !target.closest("button") && inputRef.current && mode === "input") {
725
+ inputRef.current.focus();
726
+ }
727
+ };
695
728
  return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
696
729
  "div",
697
730
  {
@@ -708,6 +741,7 @@ function CopilotChatInput({
708
741
  "shadow-[0_4px_4px_0_#0000000a,0_0_1px_0_#0000009e] rounded-[28px]",
709
742
  className
710
743
  ),
744
+ onClick: handleContainerClick,
711
745
  ...props,
712
746
  children: [
713
747
  mode === "transcribe" ? BoundAudioRecorder : BoundTextArea,
@@ -820,100 +854,83 @@ function CopilotChatInput({
820
854
  /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(DropdownMenuContent, { side: "top", align: "end", children: renderMenuItems(toolsMenu) })
821
855
  ] });
822
856
  };
823
- CopilotChatInput2.Toolbar = ({
824
- className,
825
- ...props
826
- }) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
827
- "div",
828
- {
829
- className: (0, import_tailwind_merge3.twMerge)(
830
- "w-full h-[60px] bg-transparent flex items-center",
831
- className
832
- ),
833
- ...props
834
- }
835
- );
836
- CopilotChatInput2.TextArea = (0, import_react4.forwardRef)(
837
- function TextArea2({ maxRows = 5, style, className, ...props }, ref) {
838
- const internalTextareaRef = (0, import_react4.useRef)(null);
839
- const [maxHeight, setMaxHeight] = (0, import_react4.useState)(0);
840
- const config = useCopilotChatConfiguration();
841
- const labels = config?.labels ?? CopilotChatDefaultLabels;
842
- (0, import_react4.useImperativeHandle)(
843
- ref,
844
- () => internalTextareaRef.current
845
- );
846
- const adjustHeight = () => {
857
+ CopilotChatInput2.Toolbar = ({ className, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: (0, import_tailwind_merge3.twMerge)("w-full h-[60px] bg-transparent flex items-center", className), ...props });
858
+ CopilotChatInput2.TextArea = (0, import_react4.forwardRef)(function TextArea2({ maxRows = 5, style, className, ...props }, ref) {
859
+ const internalTextareaRef = (0, import_react4.useRef)(null);
860
+ const [maxHeight, setMaxHeight] = (0, import_react4.useState)(0);
861
+ const config = useCopilotChatConfiguration();
862
+ const labels = config?.labels ?? CopilotChatDefaultLabels;
863
+ (0, import_react4.useImperativeHandle)(ref, () => internalTextareaRef.current);
864
+ const adjustHeight = () => {
865
+ const textarea = internalTextareaRef.current;
866
+ if (textarea && maxHeight > 0) {
867
+ textarea.style.height = "auto";
868
+ textarea.style.height = `${Math.min(textarea.scrollHeight, maxHeight)}px`;
869
+ }
870
+ };
871
+ (0, import_react4.useEffect)(() => {
872
+ const calculateMaxHeight = () => {
847
873
  const textarea = internalTextareaRef.current;
848
- if (textarea && maxHeight > 0) {
874
+ if (textarea) {
875
+ const currentValue = textarea.value;
876
+ textarea.value = "";
849
877
  textarea.style.height = "auto";
850
- textarea.style.height = `${Math.min(textarea.scrollHeight, maxHeight)}px`;
851
- }
852
- };
853
- (0, import_react4.useEffect)(() => {
854
- const calculateMaxHeight = () => {
855
- const textarea = internalTextareaRef.current;
856
- if (textarea) {
857
- const currentValue = textarea.value;
858
- textarea.value = "";
878
+ const computedStyle = window.getComputedStyle(textarea);
879
+ const paddingTop = parseFloat(computedStyle.paddingTop);
880
+ const paddingBottom = parseFloat(computedStyle.paddingBottom);
881
+ const contentHeight = textarea.scrollHeight - paddingTop - paddingBottom;
882
+ setMaxHeight(contentHeight * maxRows + paddingTop + paddingBottom);
883
+ textarea.value = currentValue;
884
+ if (currentValue) {
859
885
  textarea.style.height = "auto";
860
- const computedStyle = window.getComputedStyle(textarea);
861
- const paddingTop = parseFloat(computedStyle.paddingTop);
862
- const paddingBottom = parseFloat(computedStyle.paddingBottom);
863
- const contentHeight = textarea.scrollHeight - paddingTop - paddingBottom;
864
- setMaxHeight(contentHeight * maxRows + paddingTop + paddingBottom);
865
- textarea.value = currentValue;
866
- if (currentValue) {
867
- textarea.style.height = "auto";
868
- textarea.style.height = `${Math.min(textarea.scrollHeight, contentHeight * maxRows + paddingTop + paddingBottom)}px`;
869
- }
870
- if (props.autoFocus) {
871
- textarea.focus();
872
- }
886
+ textarea.style.height = `${Math.min(textarea.scrollHeight, contentHeight * maxRows + paddingTop + paddingBottom)}px`;
887
+ }
888
+ if (props.autoFocus) {
889
+ textarea.focus();
873
890
  }
874
- };
875
- calculateMaxHeight();
876
- }, [maxRows, props.autoFocus]);
877
- (0, import_react4.useEffect)(() => {
878
- adjustHeight();
879
- }, [props.value, maxHeight]);
880
- const handleInput = (e) => {
881
- adjustHeight();
882
- if (props.onChange) {
883
- props.onChange(e);
884
891
  }
885
892
  };
886
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
887
- "textarea",
888
- {
889
- ref: internalTextareaRef,
890
- ...props,
891
- onChange: handleInput,
892
- style: {
893
- overflow: "auto",
894
- resize: "none",
895
- maxHeight: `${maxHeight}px`,
896
- ...style
897
- },
898
- placeholder: labels.chatInputPlaceholder,
899
- className: (0, import_tailwind_merge3.twMerge)(
900
- // Layout and sizing
901
- "w-full p-5 pb-0",
902
- // Behavior
903
- "outline-none resize-none",
904
- // Background
905
- "bg-transparent",
906
- // Typography
907
- "antialiased font-regular leading-relaxed text-[16px]",
908
- // Placeholder styles
909
- "placeholder:text-[#00000077] dark:placeholder:text-[#fffc]",
910
- className
911
- ),
912
- rows: 1
913
- }
914
- );
915
- }
916
- );
893
+ calculateMaxHeight();
894
+ }, [maxRows, props.autoFocus]);
895
+ (0, import_react4.useEffect)(() => {
896
+ adjustHeight();
897
+ }, [props.value, maxHeight]);
898
+ const handleInput = (e) => {
899
+ adjustHeight();
900
+ if (props.onChange) {
901
+ props.onChange(e);
902
+ }
903
+ };
904
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
905
+ "textarea",
906
+ {
907
+ ref: internalTextareaRef,
908
+ ...props,
909
+ onChange: handleInput,
910
+ style: {
911
+ overflow: "auto",
912
+ resize: "none",
913
+ maxHeight: `${maxHeight}px`,
914
+ ...style
915
+ },
916
+ placeholder: labels.chatInputPlaceholder,
917
+ className: (0, import_tailwind_merge3.twMerge)(
918
+ // Layout and sizing
919
+ "w-full p-5 pb-0",
920
+ // Behavior
921
+ "outline-none resize-none",
922
+ // Background
923
+ "bg-transparent",
924
+ // Typography
925
+ "antialiased font-regular leading-relaxed text-[16px]",
926
+ // Placeholder styles
927
+ "placeholder:text-[#00000077] dark:placeholder:text-[#fffc]",
928
+ className
929
+ ),
930
+ rows: 1
931
+ }
932
+ );
933
+ });
917
934
  CopilotChatInput2.AudioRecorder = CopilotChatAudioRecorder;
918
935
  })(CopilotChatInput || (CopilotChatInput = {}));
919
936
  CopilotChatInput.TextArea.displayName = "CopilotChatInput.TextArea";
@@ -933,7 +950,7 @@ var import_remark_gfm = __toESM(require("remark-gfm"));
933
950
  var import_remark_math = __toESM(require("remark-math"));
934
951
  var import_rehype_pretty_code = __toESM(require("rehype-pretty-code"));
935
952
  var import_rehype_katex = __toESM(require("rehype-katex"));
936
- var import_react13 = require("react");
953
+ var import_react15 = require("react");
937
954
  var import_lucide_react3 = require("lucide-react");
938
955
  var import_tailwind_merge4 = require("tailwind-merge");
939
956
  var import_katex_min = require("katex/dist/katex.min.css");
@@ -1053,8 +1070,7 @@ var CopilotKitProvider = ({
1053
1070
  }, [renderToolCallsList, frontendToolsList, processedHumanInTheLoopTools]);
1054
1071
  const copilotkit = (0, import_react5.useMemo)(() => {
1055
1072
  const config = {
1056
- // Don't set runtimeUrl during initialization to prevent server-side fetching
1057
- runtimeUrl: void 0,
1073
+ runtimeUrl,
1058
1074
  headers,
1059
1075
  properties,
1060
1076
  agents__unsafe_dev_only: agents,
@@ -1396,8 +1412,192 @@ function useAgentContext(context) {
1396
1412
  }, [description, value, copilotkit]);
1397
1413
  }
1398
1414
 
1415
+ // src/hooks/use-suggestions.tsx
1416
+ var import_react12 = require("react");
1417
+ var import_shared5 = require("@copilotkitnext/shared");
1418
+ function useSuggestions({ agentId } = {}) {
1419
+ const { copilotkit } = useCopilotKit();
1420
+ const config = useCopilotChatConfiguration();
1421
+ const resolvedAgentId = (0, import_react12.useMemo)(() => agentId ?? config?.agentId ?? import_shared5.DEFAULT_AGENT_ID, [agentId, config?.agentId]);
1422
+ const [suggestions, setSuggestions] = (0, import_react12.useState)(() => {
1423
+ const result = copilotkit.getSuggestions(resolvedAgentId);
1424
+ return result.suggestions;
1425
+ });
1426
+ const [isLoading, setIsLoading] = (0, import_react12.useState)(() => {
1427
+ const result = copilotkit.getSuggestions(resolvedAgentId);
1428
+ return result.isLoading;
1429
+ });
1430
+ (0, import_react12.useEffect)(() => {
1431
+ const result = copilotkit.getSuggestions(resolvedAgentId);
1432
+ setSuggestions(result.suggestions);
1433
+ setIsLoading(result.isLoading);
1434
+ }, [copilotkit, resolvedAgentId]);
1435
+ (0, import_react12.useEffect)(() => {
1436
+ const unsubscribe = copilotkit.subscribe({
1437
+ onSuggestionsChanged: ({ agentId: changedAgentId, suggestions: suggestions2 }) => {
1438
+ if (changedAgentId !== resolvedAgentId) {
1439
+ return;
1440
+ }
1441
+ setSuggestions(suggestions2);
1442
+ },
1443
+ onSuggestionsStartedLoading: ({ agentId: changedAgentId }) => {
1444
+ if (changedAgentId !== resolvedAgentId) {
1445
+ return;
1446
+ }
1447
+ setIsLoading(true);
1448
+ },
1449
+ onSuggestionsFinishedLoading: ({ agentId: changedAgentId }) => {
1450
+ if (changedAgentId !== resolvedAgentId) {
1451
+ return;
1452
+ }
1453
+ setIsLoading(false);
1454
+ },
1455
+ onSuggestionsConfigChanged: () => {
1456
+ const result = copilotkit.getSuggestions(resolvedAgentId);
1457
+ setSuggestions(result.suggestions);
1458
+ setIsLoading(result.isLoading);
1459
+ }
1460
+ });
1461
+ return () => {
1462
+ unsubscribe();
1463
+ };
1464
+ }, [copilotkit, resolvedAgentId]);
1465
+ const reloadSuggestions = (0, import_react12.useCallback)(() => {
1466
+ copilotkit.reloadSuggestions(resolvedAgentId);
1467
+ }, [copilotkit, resolvedAgentId]);
1468
+ const clearSuggestions = (0, import_react12.useCallback)(() => {
1469
+ copilotkit.clearSuggestions(resolvedAgentId);
1470
+ }, [copilotkit, resolvedAgentId]);
1471
+ return {
1472
+ suggestions,
1473
+ reloadSuggestions,
1474
+ clearSuggestions,
1475
+ isLoading
1476
+ };
1477
+ }
1478
+
1479
+ // src/hooks/use-configure-suggestions.tsx
1480
+ var import_react13 = require("react");
1481
+ var import_shared6 = require("@copilotkitnext/shared");
1482
+ var EMPTY_DEPS = [];
1483
+ function useConfigureSuggestions(config, options) {
1484
+ const { copilotkit } = useCopilotKit();
1485
+ const chatConfig = useCopilotChatConfiguration();
1486
+ const extraDeps = options?.deps ?? EMPTY_DEPS;
1487
+ const resolvedConsumerAgentId = (0, import_react13.useMemo)(() => chatConfig?.agentId ?? import_shared6.DEFAULT_AGENT_ID, [chatConfig?.agentId]);
1488
+ const rawConsumerAgentId = (0, import_react13.useMemo)(() => config ? config.consumerAgentId : void 0, [config]);
1489
+ const normalizationCacheRef = (0, import_react13.useRef)({
1490
+ serialized: null,
1491
+ config: null
1492
+ });
1493
+ const { normalizedConfig, serializedConfig } = (0, import_react13.useMemo)(() => {
1494
+ if (!config) {
1495
+ normalizationCacheRef.current = { serialized: null, config: null };
1496
+ return { normalizedConfig: null, serializedConfig: null };
1497
+ }
1498
+ if (config.available === "disabled") {
1499
+ normalizationCacheRef.current = { serialized: null, config: null };
1500
+ return { normalizedConfig: null, serializedConfig: null };
1501
+ }
1502
+ let built;
1503
+ if (isDynamicConfig(config)) {
1504
+ built = {
1505
+ ...config
1506
+ };
1507
+ } else {
1508
+ const normalizedSuggestions = normalizeStaticSuggestions(config.suggestions);
1509
+ const baseConfig = {
1510
+ ...config,
1511
+ suggestions: normalizedSuggestions
1512
+ };
1513
+ built = baseConfig;
1514
+ }
1515
+ const serialized = JSON.stringify(built);
1516
+ const cache = normalizationCacheRef.current;
1517
+ if (cache.serialized === serialized && cache.config) {
1518
+ return { normalizedConfig: cache.config, serializedConfig: serialized };
1519
+ }
1520
+ normalizationCacheRef.current = { serialized, config: built };
1521
+ return { normalizedConfig: built, serializedConfig: serialized };
1522
+ }, [config, resolvedConsumerAgentId, ...extraDeps]);
1523
+ const latestConfigRef = (0, import_react13.useRef)(null);
1524
+ latestConfigRef.current = normalizedConfig;
1525
+ const previousSerializedConfigRef = (0, import_react13.useRef)(null);
1526
+ const targetAgentId = (0, import_react13.useMemo)(() => {
1527
+ if (!normalizedConfig) {
1528
+ return resolvedConsumerAgentId;
1529
+ }
1530
+ const consumer = normalizedConfig.consumerAgentId;
1531
+ if (!consumer || consumer === "*") {
1532
+ return resolvedConsumerAgentId;
1533
+ }
1534
+ return consumer;
1535
+ }, [normalizedConfig, resolvedConsumerAgentId]);
1536
+ const isGlobalConfig = rawConsumerAgentId === void 0 || rawConsumerAgentId === "*";
1537
+ const requestReload = (0, import_react13.useCallback)(() => {
1538
+ if (!normalizedConfig) {
1539
+ return;
1540
+ }
1541
+ if (isGlobalConfig) {
1542
+ const agents = Object.values(copilotkit.agents ?? {});
1543
+ for (const entry of agents) {
1544
+ const agentId = entry.agentId;
1545
+ if (!agentId) {
1546
+ continue;
1547
+ }
1548
+ if (!entry.isRunning) {
1549
+ copilotkit.reloadSuggestions(agentId);
1550
+ }
1551
+ }
1552
+ return;
1553
+ }
1554
+ if (!targetAgentId) {
1555
+ return;
1556
+ }
1557
+ copilotkit.reloadSuggestions(targetAgentId);
1558
+ }, [copilotkit, isGlobalConfig, normalizedConfig, targetAgentId]);
1559
+ (0, import_react13.useEffect)(() => {
1560
+ if (!serializedConfig || !latestConfigRef.current) {
1561
+ return;
1562
+ }
1563
+ const id = copilotkit.addSuggestionsConfig(latestConfigRef.current);
1564
+ requestReload();
1565
+ return () => {
1566
+ copilotkit.removeSuggestionsConfig(id);
1567
+ };
1568
+ }, [copilotkit, serializedConfig, requestReload]);
1569
+ (0, import_react13.useEffect)(() => {
1570
+ if (!normalizedConfig) {
1571
+ previousSerializedConfigRef.current = null;
1572
+ return;
1573
+ }
1574
+ if (serializedConfig && previousSerializedConfigRef.current === serializedConfig) {
1575
+ return;
1576
+ }
1577
+ if (serializedConfig) {
1578
+ previousSerializedConfigRef.current = serializedConfig;
1579
+ }
1580
+ requestReload();
1581
+ }, [normalizedConfig, requestReload, serializedConfig]);
1582
+ (0, import_react13.useEffect)(() => {
1583
+ if (!normalizedConfig || extraDeps.length === 0) {
1584
+ return;
1585
+ }
1586
+ requestReload();
1587
+ }, [extraDeps.length, normalizedConfig, requestReload, ...extraDeps]);
1588
+ }
1589
+ function isDynamicConfig(config) {
1590
+ return "instructions" in config;
1591
+ }
1592
+ function normalizeStaticSuggestions(suggestions) {
1593
+ return suggestions.map((suggestion) => ({
1594
+ ...suggestion,
1595
+ isLoading: suggestion.isLoading ?? false
1596
+ }));
1597
+ }
1598
+
1399
1599
  // src/components/chat/CopilotChatToolCallsView.tsx
1400
- var import_react12 = __toESM(require("react"));
1600
+ var import_react14 = __toESM(require("react"));
1401
1601
  var import_jsx_runtime9 = require("react/jsx-runtime");
1402
1602
  function CopilotChatToolCallsView({
1403
1603
  message,
@@ -1411,7 +1611,7 @@ function CopilotChatToolCallsView({
1411
1611
  const toolMessage = messages.find(
1412
1612
  (m) => m.role === "tool" && m.toolCallId === toolCall.id
1413
1613
  );
1414
- return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_react12.default.Fragment, { children: renderToolCall({
1614
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_react14.default.Fragment, { children: renderToolCall({
1415
1615
  toolCall,
1416
1616
  toolMessage
1417
1617
  }) }, toolCall.id);
@@ -1572,7 +1772,7 @@ function CopilotChatAssistantMessage({
1572
1772
  const CodeBlock = ({ children, className, onClick, ...props }) => {
1573
1773
  const config = useCopilotChatConfiguration();
1574
1774
  const labels = config?.labels ?? CopilotChatDefaultLabels;
1575
- const [copied, setCopied] = (0, import_react13.useState)(false);
1775
+ const [copied, setCopied] = (0, import_react15.useState)(false);
1576
1776
  const getCodeContent = (node) => {
1577
1777
  if (typeof node === "string") return node;
1578
1778
  if (Array.isArray(node)) return node.map(getCodeContent).join("");
@@ -1686,7 +1886,7 @@ function CopilotChatAssistantMessage({
1686
1886
  CopilotChatAssistantMessage2.CopyButton = ({ className, title, onClick, ...props }) => {
1687
1887
  const config = useCopilotChatConfiguration();
1688
1888
  const labels = config?.labels ?? CopilotChatDefaultLabels;
1689
- const [copied, setCopied] = (0, import_react13.useState)(false);
1889
+ const [copied, setCopied] = (0, import_react15.useState)(false);
1690
1890
  const handleClick = (event) => {
1691
1891
  setCopied(true);
1692
1892
  setTimeout(() => setCopied(false), 2e3);
@@ -1764,7 +1964,7 @@ CopilotChatAssistantMessage.RegenerateButton.displayName = "CopilotChatAssistant
1764
1964
  var CopilotChatAssistantMessage_default = CopilotChatAssistantMessage;
1765
1965
 
1766
1966
  // src/components/chat/CopilotChatUserMessage.tsx
1767
- var import_react14 = require("react");
1967
+ var import_react16 = require("react");
1768
1968
  var import_lucide_react4 = require("lucide-react");
1769
1969
  var import_tailwind_merge5 = require("tailwind-merge");
1770
1970
  var import_jsx_runtime11 = require("react/jsx-runtime");
@@ -1909,7 +2109,7 @@ function CopilotChatUserMessage({
1909
2109
  CopilotChatUserMessage2.CopyButton = ({ className, title, onClick, ...props }) => {
1910
2110
  const config = useCopilotChatConfiguration();
1911
2111
  const labels = config?.labels ?? CopilotChatDefaultLabels;
1912
- const [copied, setCopied] = (0, import_react14.useState)(false);
2112
+ const [copied, setCopied] = (0, import_react16.useState)(false);
1913
2113
  const handleClick = (event) => {
1914
2114
  setCopied(true);
1915
2115
  setTimeout(() => setCopied(false), 2e3);
@@ -2002,9 +2202,118 @@ CopilotChatUserMessage.EditButton.displayName = "CopilotChatUserMessage.EditButt
2002
2202
  CopilotChatUserMessage.BranchNavigation.displayName = "CopilotChatUserMessage.BranchNavigation";
2003
2203
  var CopilotChatUserMessage_default = CopilotChatUserMessage;
2004
2204
 
2205
+ // src/components/chat/CopilotChatSuggestionPill.tsx
2206
+ var import_react17 = __toESM(require("react"));
2207
+ var import_lucide_react5 = require("lucide-react");
2208
+ var import_jsx_runtime12 = require("react/jsx-runtime");
2209
+ var baseClasses = "group inline-flex h-8 items-center gap-1.5 rounded-full border border-border/60 bg-background px-3 text-xs leading-none text-foreground transition-colors cursor-pointer hover:bg-accent/60 hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background disabled:cursor-not-allowed disabled:text-muted-foreground disabled:hover:bg-background disabled:hover:text-muted-foreground pointer-events-auto";
2210
+ var labelClasses = "whitespace-nowrap font-medium leading-none";
2211
+ var CopilotChatSuggestionPill = import_react17.default.forwardRef(function CopilotChatSuggestionPill2({ className, children, icon, isLoading, type, ...props }, ref) {
2212
+ const showIcon = !isLoading && icon;
2213
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
2214
+ "button",
2215
+ {
2216
+ ref,
2217
+ "data-slot": "suggestion-pill",
2218
+ className: cn(baseClasses, className),
2219
+ type: type ?? "button",
2220
+ "aria-busy": isLoading || void 0,
2221
+ disabled: isLoading || props.disabled,
2222
+ ...props,
2223
+ children: [
2224
+ isLoading ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "flex h-4 w-4 items-center justify-center text-muted-foreground", children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_lucide_react5.Loader2, { className: "h-4 w-4 animate-spin", "aria-hidden": "true" }) }) : showIcon && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "flex h-4 w-4 items-center justify-center text-muted-foreground", children: icon }),
2225
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: labelClasses, children })
2226
+ ]
2227
+ }
2228
+ );
2229
+ });
2230
+ CopilotChatSuggestionPill.displayName = "CopilotChatSuggestionPill";
2231
+ var CopilotChatSuggestionPill_default = CopilotChatSuggestionPill;
2232
+
2233
+ // src/components/chat/CopilotChatSuggestionView.tsx
2234
+ var import_react18 = __toESM(require("react"));
2235
+ var import_jsx_runtime13 = require("react/jsx-runtime");
2236
+ var DefaultContainer = import_react18.default.forwardRef(function DefaultContainer2({ className, ...props }, ref) {
2237
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2238
+ "div",
2239
+ {
2240
+ ref,
2241
+ className: cn(
2242
+ "flex flex-wrap items-center gap-2 px-4 sm:px-0 pointer-events-none",
2243
+ className
2244
+ ),
2245
+ ...props
2246
+ }
2247
+ );
2248
+ });
2249
+ var CopilotChatSuggestionView = import_react18.default.forwardRef(function CopilotChatSuggestionView2({
2250
+ suggestions,
2251
+ onSelectSuggestion,
2252
+ loadingIndexes,
2253
+ container,
2254
+ suggestion: suggestionSlot,
2255
+ className,
2256
+ children,
2257
+ ...restProps
2258
+ }, ref) {
2259
+ const loadingSet = import_react18.default.useMemo(() => {
2260
+ if (!loadingIndexes || loadingIndexes.length === 0) {
2261
+ return /* @__PURE__ */ new Set();
2262
+ }
2263
+ return new Set(loadingIndexes);
2264
+ }, [loadingIndexes]);
2265
+ const ContainerElement = renderSlot(container, DefaultContainer, {
2266
+ ref,
2267
+ className,
2268
+ ...restProps
2269
+ });
2270
+ const suggestionElements = suggestions.map((suggestion, index) => {
2271
+ const isLoading = loadingSet.has(index) || suggestion.isLoading === true;
2272
+ const pill = renderSlot(suggestionSlot, CopilotChatSuggestionPill_default, {
2273
+ children: suggestion.title,
2274
+ isLoading,
2275
+ type: "button",
2276
+ onClick: () => onSelectSuggestion?.(suggestion, index)
2277
+ });
2278
+ return import_react18.default.cloneElement(pill, {
2279
+ key: `${suggestion.title}-${index}`
2280
+ });
2281
+ });
2282
+ const boundContainer = import_react18.default.cloneElement(
2283
+ ContainerElement,
2284
+ void 0,
2285
+ suggestionElements
2286
+ );
2287
+ if (typeof children === "function") {
2288
+ const sampleSuggestion = renderSlot(suggestionSlot, CopilotChatSuggestionPill_default, {
2289
+ children: suggestions[0]?.title ?? "",
2290
+ isLoading: suggestions.length > 0 ? loadingSet.has(0) || suggestions[0]?.isLoading === true : false,
2291
+ type: "button"
2292
+ });
2293
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_jsx_runtime13.Fragment, { children: children({
2294
+ container: boundContainer,
2295
+ suggestion: sampleSuggestion,
2296
+ suggestions,
2297
+ onSelectSuggestion,
2298
+ loadingIndexes,
2299
+ className,
2300
+ ...restProps
2301
+ }) });
2302
+ }
2303
+ if (children) {
2304
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_jsx_runtime13.Fragment, { children: [
2305
+ boundContainer,
2306
+ children
2307
+ ] });
2308
+ }
2309
+ return boundContainer;
2310
+ });
2311
+ CopilotChatSuggestionView.displayName = "CopilotChatSuggestionView";
2312
+ var CopilotChatSuggestionView_default = CopilotChatSuggestionView;
2313
+
2005
2314
  // src/components/chat/CopilotChatMessageView.tsx
2006
2315
  var import_tailwind_merge6 = require("tailwind-merge");
2007
- var import_jsx_runtime12 = require("react/jsx-runtime");
2316
+ var import_jsx_runtime14 = require("react/jsx-runtime");
2008
2317
  function CopilotChatMessageView({
2009
2318
  messages = [],
2010
2319
  assistantMessage,
@@ -2034,7 +2343,7 @@ function CopilotChatMessageView({
2034
2343
  if (children) {
2035
2344
  return children({ messageElements, messages, isRunning });
2036
2345
  }
2037
- return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: (0, import_tailwind_merge6.twMerge)("flex flex-col", className), ...props, children: [
2346
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: (0, import_tailwind_merge6.twMerge)("flex flex-col", className), ...props, children: [
2038
2347
  messageElements,
2039
2348
  isRunning && renderSlot(cursor, CopilotChatMessageView.Cursor, {})
2040
2349
  ] });
@@ -2043,7 +2352,7 @@ CopilotChatMessageView.Cursor = function Cursor({
2043
2352
  className,
2044
2353
  ...props
2045
2354
  }) {
2046
- return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
2355
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
2047
2356
  "div",
2048
2357
  {
2049
2358
  className: (0, import_tailwind_merge6.twMerge)(
@@ -2057,11 +2366,11 @@ CopilotChatMessageView.Cursor = function Cursor({
2057
2366
  var CopilotChatMessageView_default = CopilotChatMessageView;
2058
2367
 
2059
2368
  // src/components/chat/CopilotChatView.tsx
2060
- var import_react15 = __toESM(require("react"));
2369
+ var import_react19 = __toESM(require("react"));
2061
2370
  var import_tailwind_merge7 = require("tailwind-merge");
2062
2371
  var import_use_stick_to_bottom = require("use-stick-to-bottom");
2063
- var import_lucide_react5 = require("lucide-react");
2064
- var import_jsx_runtime13 = require("react/jsx-runtime");
2372
+ var import_lucide_react6 = require("lucide-react");
2373
+ var import_jsx_runtime15 = require("react/jsx-runtime");
2065
2374
  function CopilotChatView({
2066
2375
  messageView,
2067
2376
  input,
@@ -2070,19 +2379,23 @@ function CopilotChatView({
2070
2379
  feather,
2071
2380
  inputContainer,
2072
2381
  disclaimer,
2382
+ suggestionView,
2073
2383
  messages = [],
2074
2384
  autoScroll = true,
2075
2385
  inputProps,
2076
2386
  isRunning = false,
2387
+ suggestions,
2388
+ suggestionLoadingIndexes,
2389
+ onSelectSuggestion,
2077
2390
  children,
2078
2391
  className,
2079
2392
  ...props
2080
2393
  }) {
2081
- const inputContainerRef = (0, import_react15.useRef)(null);
2082
- const [inputContainerHeight, setInputContainerHeight] = (0, import_react15.useState)(0);
2083
- const [isResizing, setIsResizing] = (0, import_react15.useState)(false);
2084
- const resizeTimeoutRef = (0, import_react15.useRef)(null);
2085
- (0, import_react15.useEffect)(() => {
2394
+ const inputContainerRef = (0, import_react19.useRef)(null);
2395
+ const [inputContainerHeight, setInputContainerHeight] = (0, import_react19.useState)(0);
2396
+ const [isResizing, setIsResizing] = (0, import_react19.useState)(false);
2397
+ const resizeTimeoutRef = (0, import_react19.useRef)(null);
2398
+ (0, import_react19.useEffect)(() => {
2086
2399
  const element = inputContainerRef.current;
2087
2400
  if (!element) return;
2088
2401
  const resizeObserver = new ResizeObserver((entries) => {
@@ -2116,40 +2429,38 @@ function CopilotChatView({
2116
2429
  messages,
2117
2430
  isRunning
2118
2431
  });
2119
- const BoundInput = renderSlot(
2120
- input,
2121
- CopilotChatInput_default,
2122
- inputProps ?? {}
2123
- );
2432
+ const BoundInput = renderSlot(input, CopilotChatInput_default, inputProps ?? {});
2433
+ const hasSuggestions = Array.isArray(suggestions) && suggestions.length > 0;
2434
+ const BoundSuggestionView = hasSuggestions ? renderSlot(
2435
+ suggestionView,
2436
+ CopilotChatSuggestionView_default,
2437
+ {
2438
+ suggestions,
2439
+ loadingIndexes: suggestionLoadingIndexes,
2440
+ onSelectSuggestion,
2441
+ className: "mb-3 lg:ml-4 lg:mr-4 ml-0 mr-0"
2442
+ }
2443
+ ) : null;
2124
2444
  const BoundFeather = renderSlot(feather, CopilotChatView.Feather, {});
2125
2445
  const BoundScrollView = renderSlot(scrollView, CopilotChatView.ScrollView, {
2126
2446
  autoScroll,
2127
2447
  scrollToBottomButton,
2128
2448
  inputContainerHeight,
2129
2449
  isResizing,
2130
- children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { style: { paddingBottom: `${inputContainerHeight + 32}px` }, children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "max-w-3xl mx-auto", children: BoundMessageView }) })
2450
+ children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { style: { paddingBottom: `${inputContainerHeight + (hasSuggestions ? 4 : 32)}px` }, children: /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "max-w-3xl mx-auto", children: [
2451
+ BoundMessageView,
2452
+ hasSuggestions ? /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { className: "px-4 sm:px-0 mt-4", children: BoundSuggestionView }) : null
2453
+ ] }) })
2454
+ });
2455
+ const BoundScrollToBottomButton = renderSlot(scrollToBottomButton, CopilotChatView.ScrollToBottomButton, {});
2456
+ const BoundDisclaimer = renderSlot(disclaimer, CopilotChatView.Disclaimer, {});
2457
+ const BoundInputContainer = renderSlot(inputContainer, CopilotChatView.InputContainer, {
2458
+ ref: inputContainerRef,
2459
+ children: /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(import_jsx_runtime15.Fragment, { children: [
2460
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { className: "max-w-3xl mx-auto py-0 px-4 sm:px-0 [div[data-sidebar-chat]_&]:px-8 pointer-events-auto", children: BoundInput }),
2461
+ BoundDisclaimer
2462
+ ] })
2131
2463
  });
2132
- const BoundScrollToBottomButton = renderSlot(
2133
- scrollToBottomButton,
2134
- CopilotChatView.ScrollToBottomButton,
2135
- {}
2136
- );
2137
- const BoundDisclaimer = renderSlot(
2138
- disclaimer,
2139
- CopilotChatView.Disclaimer,
2140
- {}
2141
- );
2142
- const BoundInputContainer = renderSlot(
2143
- inputContainer,
2144
- CopilotChatView.InputContainer,
2145
- {
2146
- ref: inputContainerRef,
2147
- children: /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_jsx_runtime13.Fragment, { children: [
2148
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "max-w-3xl mx-auto py-0 px-4 sm:px-0", children: BoundInput }),
2149
- BoundDisclaimer
2150
- ] })
2151
- }
2152
- );
2153
2464
  if (children) {
2154
2465
  return children({
2155
2466
  messageView: BoundMessageView,
@@ -2158,10 +2469,11 @@ function CopilotChatView({
2158
2469
  scrollToBottomButton: BoundScrollToBottomButton,
2159
2470
  feather: BoundFeather,
2160
2471
  inputContainer: BoundInputContainer,
2161
- disclaimer: BoundDisclaimer
2472
+ disclaimer: BoundDisclaimer,
2473
+ suggestionView: BoundSuggestionView ?? /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_jsx_runtime15.Fragment, {})
2162
2474
  });
2163
2475
  }
2164
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: (0, import_tailwind_merge7.twMerge)("relative h-full", className), ...props, children: [
2476
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: (0, import_tailwind_merge7.twMerge)("relative h-full", className), ...props, children: [
2165
2477
  BoundScrollView,
2166
2478
  BoundFeather,
2167
2479
  BoundInputContainer
@@ -2170,22 +2482,18 @@ function CopilotChatView({
2170
2482
  ((CopilotChatView2) => {
2171
2483
  const ScrollContent = ({ children, scrollToBottomButton, inputContainerHeight, isResizing }) => {
2172
2484
  const { isAtBottom, scrollToBottom } = (0, import_use_stick_to_bottom.useStickToBottomContext)();
2173
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_jsx_runtime13.Fragment, { children: [
2174
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_use_stick_to_bottom.StickToBottom.Content, { className: "overflow-y-scroll overflow-x-hidden", children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "px-4 sm:px-0", children }) }),
2175
- !isAtBottom && !isResizing && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2485
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(import_jsx_runtime15.Fragment, { children: [
2486
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_use_stick_to_bottom.StickToBottom.Content, { className: "overflow-y-scroll overflow-x-hidden", children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { className: "px-4 sm:px-0 [div[data-sidebar-chat]_&]:px-8", children }) }),
2487
+ !isAtBottom && !isResizing && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
2176
2488
  "div",
2177
2489
  {
2178
- className: "absolute inset-x-0 flex justify-center z-10",
2490
+ className: "absolute inset-x-0 flex justify-center z-10 pointer-events-none",
2179
2491
  style: {
2180
2492
  bottom: `${inputContainerHeight + 16}px`
2181
2493
  },
2182
- children: renderSlot(
2183
- scrollToBottomButton,
2184
- CopilotChatView2.ScrollToBottomButton,
2185
- {
2186
- onClick: () => scrollToBottom()
2187
- }
2188
- )
2494
+ children: renderSlot(scrollToBottomButton, CopilotChatView2.ScrollToBottomButton, {
2495
+ onClick: () => scrollToBottom()
2496
+ })
2189
2497
  }
2190
2498
  )
2191
2499
  ] });
@@ -2199,13 +2507,13 @@ function CopilotChatView({
2199
2507
  className,
2200
2508
  ...props
2201
2509
  }) => {
2202
- const [hasMounted, setHasMounted] = (0, import_react15.useState)(false);
2510
+ const [hasMounted, setHasMounted] = (0, import_react19.useState)(false);
2203
2511
  const { scrollRef, contentRef, scrollToBottom } = (0, import_use_stick_to_bottom.useStickToBottom)();
2204
- const [showScrollButton, setShowScrollButton] = (0, import_react15.useState)(false);
2205
- (0, import_react15.useEffect)(() => {
2512
+ const [showScrollButton, setShowScrollButton] = (0, import_react19.useState)(false);
2513
+ (0, import_react19.useEffect)(() => {
2206
2514
  setHasMounted(true);
2207
2515
  }, []);
2208
- (0, import_react15.useEffect)(() => {
2516
+ (0, import_react19.useEffect)(() => {
2209
2517
  if (autoScroll) return;
2210
2518
  const scrollElement = scrollRef.current;
2211
2519
  if (!scrollElement) return;
@@ -2223,45 +2531,44 @@ function CopilotChatView({
2223
2531
  };
2224
2532
  }, [scrollRef, autoScroll]);
2225
2533
  if (!hasMounted) {
2226
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "h-full max-h-full flex flex-col min-h-0 overflow-y-scroll overflow-x-hidden", children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "px-4 sm:px-0", children }) });
2534
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { className: "h-full max-h-full flex flex-col min-h-0 overflow-y-scroll overflow-x-hidden", children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { className: "px-4 sm:px-0 [div[data-sidebar-chat]_&]:px-8", children }) });
2227
2535
  }
2228
2536
  if (!autoScroll) {
2229
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
2537
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
2230
2538
  "div",
2231
2539
  {
2232
2540
  ref: scrollRef,
2233
- className: cn("h-full max-h-full flex flex-col min-h-0 overflow-y-scroll overflow-x-hidden relative", className),
2541
+ className: cn(
2542
+ "h-full max-h-full flex flex-col min-h-0 overflow-y-scroll overflow-x-hidden relative",
2543
+ className
2544
+ ),
2234
2545
  ...props,
2235
2546
  children: [
2236
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { ref: contentRef, className: "px-4 sm:px-0", children }),
2237
- showScrollButton && !isResizing && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2547
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { ref: contentRef, className: "px-4 sm:px-0 [div[data-sidebar-chat]_&]:px-8", children }),
2548
+ showScrollButton && !isResizing && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
2238
2549
  "div",
2239
2550
  {
2240
- className: "absolute inset-x-0 flex justify-center z-10",
2551
+ className: "absolute inset-x-0 flex justify-center z-10 pointer-events-none",
2241
2552
  style: {
2242
2553
  bottom: `${inputContainerHeight + 16}px`
2243
2554
  },
2244
- children: renderSlot(
2245
- scrollToBottomButton,
2246
- CopilotChatView2.ScrollToBottomButton,
2247
- {
2248
- onClick: () => scrollToBottom()
2249
- }
2250
- )
2555
+ children: renderSlot(scrollToBottomButton, CopilotChatView2.ScrollToBottomButton, {
2556
+ onClick: () => scrollToBottom()
2557
+ })
2251
2558
  }
2252
2559
  )
2253
2560
  ]
2254
2561
  }
2255
2562
  );
2256
2563
  }
2257
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2564
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
2258
2565
  import_use_stick_to_bottom.StickToBottom,
2259
2566
  {
2260
2567
  className: cn("h-full max-h-full flex flex-col min-h-0 relative", className),
2261
2568
  resize: "smooth",
2262
2569
  initial: "smooth",
2263
2570
  ...props,
2264
- children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2571
+ children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
2265
2572
  ScrollContent,
2266
2573
  {
2267
2574
  scrollToBottomButton,
@@ -2273,13 +2580,16 @@ function CopilotChatView({
2273
2580
  }
2274
2581
  );
2275
2582
  };
2276
- CopilotChatView2.ScrollToBottomButton = ({ className, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2583
+ CopilotChatView2.ScrollToBottomButton = ({
2584
+ className,
2585
+ ...props
2586
+ }) => /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
2277
2587
  Button,
2278
2588
  {
2279
2589
  variant: "outline",
2280
2590
  size: "sm",
2281
2591
  className: (0, import_tailwind_merge7.twMerge)(
2282
- "rounded-full w-10 h-10 p-0",
2592
+ "rounded-full w-10 h-10 p-0 pointer-events-auto",
2283
2593
  "bg-white dark:bg-gray-900",
2284
2594
  "shadow-lg border border-gray-200 dark:border-gray-700",
2285
2595
  "hover:bg-gray-50 dark:hover:bg-gray-800",
@@ -2287,14 +2597,10 @@ function CopilotChatView({
2287
2597
  className
2288
2598
  ),
2289
2599
  ...props,
2290
- children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_lucide_react5.ChevronDown, { className: "w-4 h-4 text-gray-600 dark:text-white" })
2600
+ children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_lucide_react6.ChevronDown, { className: "w-4 h-4 text-gray-600 dark:text-white" })
2291
2601
  }
2292
2602
  );
2293
- CopilotChatView2.Feather = ({
2294
- className,
2295
- style,
2296
- ...props
2297
- }) => /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2603
+ CopilotChatView2.Feather = ({ className, style, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
2298
2604
  "div",
2299
2605
  {
2300
2606
  className: cn(
@@ -2307,29 +2613,15 @@ function CopilotChatView({
2307
2613
  ...props
2308
2614
  }
2309
2615
  );
2310
- CopilotChatView2.InputContainer = import_react15.default.forwardRef(({ children, className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2311
- "div",
2312
- {
2313
- ref,
2314
- className: cn("absolute bottom-0 left-0 right-0 z-20", className),
2315
- ...props,
2316
- children
2317
- }
2318
- ));
2616
+ CopilotChatView2.InputContainer = import_react19.default.forwardRef(({ children, className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { ref, className: cn("absolute bottom-0 left-0 right-0 z-20 pointer-events-none", className), ...props, children }));
2319
2617
  CopilotChatView2.InputContainer.displayName = "CopilotChatView.InputContainer";
2320
- CopilotChatView2.Disclaimer = ({
2321
- className,
2322
- ...props
2323
- }) => {
2618
+ CopilotChatView2.Disclaimer = ({ className, ...props }) => {
2324
2619
  const config = useCopilotChatConfiguration();
2325
2620
  const labels = config?.labels ?? CopilotChatDefaultLabels;
2326
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2621
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
2327
2622
  "div",
2328
2623
  {
2329
- className: cn(
2330
- "text-center text-xs text-muted-foreground py-3 px-4 max-w-3xl mx-auto",
2331
- className
2332
- ),
2624
+ className: cn("text-center text-xs text-muted-foreground py-3 px-4 max-w-3xl mx-auto", className),
2333
2625
  ...props,
2334
2626
  children: labels.chatDisclaimerText
2335
2627
  }
@@ -2339,32 +2631,31 @@ function CopilotChatView({
2339
2631
  var CopilotChatView_default = CopilotChatView;
2340
2632
 
2341
2633
  // src/components/chat/CopilotChat.tsx
2342
- var import_shared5 = require("@copilotkitnext/shared");
2343
- var import_react16 = require("react");
2634
+ var import_shared7 = require("@copilotkitnext/shared");
2635
+ var import_react20 = require("react");
2344
2636
  var import_ts_deepmerge = require("ts-deepmerge");
2345
2637
  var import_client = require("@ag-ui/client");
2346
- var import_jsx_runtime14 = require("react/jsx-runtime");
2347
- function CopilotChat({ agentId, threadId, labels, ...props }) {
2638
+ var import_jsx_runtime16 = require("react/jsx-runtime");
2639
+ function CopilotChat({ agentId, threadId, labels, chatView, isModalDefaultOpen, ...props }) {
2348
2640
  const existingConfig = useCopilotChatConfiguration();
2349
- const resolvedAgentId = agentId ?? existingConfig?.agentId ?? import_shared5.DEFAULT_AGENT_ID;
2350
- const resolvedThreadId = (0, import_react16.useMemo)(
2351
- () => threadId ?? existingConfig?.threadId ?? (0, import_shared5.randomUUID)(),
2641
+ const resolvedAgentId = agentId ?? existingConfig?.agentId ?? import_shared7.DEFAULT_AGENT_ID;
2642
+ const resolvedThreadId = (0, import_react20.useMemo)(
2643
+ () => threadId ?? existingConfig?.threadId ?? (0, import_shared7.randomUUID)(),
2352
2644
  [threadId, existingConfig?.threadId]
2353
2645
  );
2354
- const resolvedLabels = (0, import_react16.useMemo)(
2355
- () => ({
2356
- ...CopilotChatDefaultLabels,
2357
- ...existingConfig?.labels || {},
2358
- ...labels || {}
2359
- }),
2360
- [existingConfig?.labels, labels]
2361
- );
2362
2646
  const { agent } = useAgent({ agentId: resolvedAgentId });
2363
2647
  const { copilotkit } = useCopilotKit();
2364
- (0, import_react16.useEffect)(() => {
2648
+ const { suggestions: autoSuggestions } = useSuggestions({ agentId: resolvedAgentId });
2649
+ const {
2650
+ inputProps: providedInputProps,
2651
+ messageView: providedMessageView,
2652
+ suggestionView: providedSuggestionView,
2653
+ ...restProps
2654
+ } = props;
2655
+ (0, import_react20.useEffect)(() => {
2365
2656
  const connect = async (agent2) => {
2366
2657
  try {
2367
- await copilotkit.connectAgent({ agent: agent2, agentId: resolvedAgentId });
2658
+ await copilotkit.connectAgent({ agent: agent2 });
2368
2659
  } catch (error) {
2369
2660
  if (error instanceof import_client.AGUIConnectNotImplementedError) {
2370
2661
  } else {
@@ -2379,47 +2670,391 @@ function CopilotChat({ agentId, threadId, labels, ...props }) {
2379
2670
  return () => {
2380
2671
  };
2381
2672
  }, [resolvedThreadId, agent, copilotkit, resolvedAgentId]);
2382
- const onSubmitInput = (0, import_react16.useCallback)(
2673
+ const onSubmitInput = (0, import_react20.useCallback)(
2383
2674
  async (value) => {
2384
2675
  agent?.addMessage({
2385
- id: (0, import_shared5.randomUUID)(),
2676
+ id: (0, import_shared7.randomUUID)(),
2386
2677
  role: "user",
2387
2678
  content: value
2388
2679
  });
2389
2680
  if (agent) {
2390
2681
  try {
2391
- await copilotkit.runAgent({ agent, agentId: resolvedAgentId });
2682
+ await copilotkit.runAgent({ agent });
2392
2683
  } catch (error) {
2393
2684
  console.error("CopilotChat: runAgent failed", error);
2394
2685
  }
2395
2686
  }
2396
2687
  },
2397
- [agent, copilotkit, resolvedAgentId]
2688
+ [agent, copilotkit]
2689
+ );
2690
+ const handleSelectSuggestion = (0, import_react20.useCallback)(
2691
+ async (suggestion) => {
2692
+ if (!agent) {
2693
+ return;
2694
+ }
2695
+ agent.addMessage({
2696
+ id: (0, import_shared7.randomUUID)(),
2697
+ role: "user",
2698
+ content: suggestion.message
2699
+ });
2700
+ try {
2701
+ await copilotkit.runAgent({ agent });
2702
+ } catch (error) {
2703
+ console.error("CopilotChat: runAgent failed after selecting suggestion", error);
2704
+ }
2705
+ },
2706
+ [agent, copilotkit]
2398
2707
  );
2399
- const { inputProps: providedInputProps, messageView: providedMessageView, ...restProps } = props;
2400
2708
  const mergedProps = (0, import_ts_deepmerge.merge)(
2401
2709
  {
2402
- isRunning: agent?.isRunning ?? false
2710
+ isRunning: agent?.isRunning ?? false,
2711
+ suggestions: autoSuggestions,
2712
+ onSelectSuggestion: handleSelectSuggestion,
2713
+ suggestionView: providedSuggestionView
2403
2714
  },
2404
2715
  {
2405
2716
  ...restProps,
2406
2717
  ...typeof providedMessageView === "string" ? { messageView: { className: providedMessageView } } : providedMessageView !== void 0 ? { messageView: providedMessageView } : {}
2407
2718
  }
2408
2719
  );
2409
- return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(CopilotChatConfigurationProvider, { agentId: resolvedAgentId, threadId: resolvedThreadId, labels: resolvedLabels, children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
2410
- CopilotChatView,
2720
+ const finalProps = (0, import_ts_deepmerge.merge)(mergedProps, {
2721
+ messages: agent?.messages ?? [],
2722
+ inputProps: {
2723
+ onSubmitMessage: onSubmitInput,
2724
+ ...providedInputProps
2725
+ }
2726
+ });
2727
+ const RenderedChatView = renderSlot(chatView, CopilotChatView, finalProps);
2728
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
2729
+ CopilotChatConfigurationProvider,
2411
2730
  {
2412
- ...{
2413
- messages: agent?.messages ?? [],
2414
- inputProps: {
2415
- onSubmitMessage: onSubmitInput,
2416
- ...providedInputProps
2417
- },
2418
- ...mergedProps
2731
+ agentId: resolvedAgentId,
2732
+ threadId: resolvedThreadId,
2733
+ labels,
2734
+ isModalDefaultOpen,
2735
+ children: RenderedChatView
2736
+ }
2737
+ );
2738
+ }
2739
+ ((CopilotChat2) => {
2740
+ CopilotChat2.View = CopilotChatView;
2741
+ })(CopilotChat || (CopilotChat = {}));
2742
+
2743
+ // src/components/chat/CopilotChatToggleButton.tsx
2744
+ var import_react21 = __toESM(require("react"));
2745
+ var import_lucide_react7 = require("lucide-react");
2746
+ var import_jsx_runtime17 = require("react/jsx-runtime");
2747
+ var DefaultOpenIcon = ({
2748
+ className,
2749
+ ...props
2750
+ }) => /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(import_lucide_react7.MessageCircle, { className: cn("h-6 w-6", className), strokeWidth: 1.75, fill: "currentColor", ...props });
2751
+ var DefaultCloseIcon = ({
2752
+ className,
2753
+ ...props
2754
+ }) => /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(import_lucide_react7.X, { className: cn("h-6 w-6", className), strokeWidth: 1.75, ...props });
2755
+ DefaultOpenIcon.displayName = "CopilotChatToggleButton.OpenIcon";
2756
+ DefaultCloseIcon.displayName = "CopilotChatToggleButton.CloseIcon";
2757
+ var ICON_TRANSITION_STYLE = Object.freeze({
2758
+ transition: "opacity 120ms ease-out, transform 260ms cubic-bezier(0.22, 1, 0.36, 1)"
2759
+ });
2760
+ var ICON_WRAPPER_BASE = "pointer-events-none absolute inset-0 flex items-center justify-center will-change-transform";
2761
+ var BUTTON_BASE_CLASSES = cn(
2762
+ "fixed bottom-6 right-6 z-[1100] flex h-14 w-14 items-center justify-center",
2763
+ "rounded-full border border-primary bg-primary text-primary-foreground",
2764
+ "shadow-sm transition-all duration-200 ease-out",
2765
+ "hover:scale-[1.04] hover:shadow-md",
2766
+ "cursor-pointer",
2767
+ "active:scale-[0.96]",
2768
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/50 focus-visible:ring-offset-2 focus-visible:ring-offset-background",
2769
+ "disabled:pointer-events-none disabled:opacity-60"
2770
+ );
2771
+ var CopilotChatToggleButton = import_react21.default.forwardRef(function CopilotChatToggleButton2({ openIcon, closeIcon, className, ...buttonProps }, ref) {
2772
+ const { onClick, type, disabled, ...restProps } = buttonProps;
2773
+ const configuration = useCopilotChatConfiguration();
2774
+ const labels = configuration?.labels ?? CopilotChatDefaultLabels;
2775
+ const [fallbackOpen, setFallbackOpen] = (0, import_react21.useState)(false);
2776
+ const isOpen = configuration?.isModalOpen ?? fallbackOpen;
2777
+ const setModalOpen = configuration?.setModalOpen ?? setFallbackOpen;
2778
+ const handleClick = (event) => {
2779
+ if (disabled) {
2780
+ return;
2781
+ }
2782
+ if (onClick) {
2783
+ onClick(event);
2784
+ }
2785
+ if (event.defaultPrevented) {
2786
+ return;
2787
+ }
2788
+ const nextOpen = !isOpen;
2789
+ setModalOpen(nextOpen);
2790
+ };
2791
+ const renderedOpenIcon = renderSlot(
2792
+ openIcon,
2793
+ DefaultOpenIcon,
2794
+ {
2795
+ className: "h-6 w-6",
2796
+ "aria-hidden": true,
2797
+ focusable: false
2798
+ }
2799
+ );
2800
+ const renderedCloseIcon = renderSlot(
2801
+ closeIcon,
2802
+ DefaultCloseIcon,
2803
+ {
2804
+ className: "h-6 w-6",
2805
+ "aria-hidden": true,
2806
+ focusable: false
2807
+ }
2808
+ );
2809
+ const openIconElement = /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
2810
+ "span",
2811
+ {
2812
+ "aria-hidden": "true",
2813
+ "data-slot": "chat-toggle-button-open-icon",
2814
+ className: ICON_WRAPPER_BASE,
2815
+ style: {
2816
+ ...ICON_TRANSITION_STYLE,
2817
+ opacity: isOpen ? 0 : 1,
2818
+ transform: `scale(${isOpen ? 0.75 : 1}) rotate(${isOpen ? 90 : 0}deg)`
2819
+ },
2820
+ children: renderedOpenIcon
2821
+ }
2822
+ );
2823
+ const closeIconElement = /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
2824
+ "span",
2825
+ {
2826
+ "aria-hidden": "true",
2827
+ "data-slot": "chat-toggle-button-close-icon",
2828
+ className: ICON_WRAPPER_BASE,
2829
+ style: {
2830
+ ...ICON_TRANSITION_STYLE,
2831
+ opacity: isOpen ? 1 : 0,
2832
+ transform: `scale(${isOpen ? 1 : 0.75}) rotate(${isOpen ? 0 : -90}deg)`
2833
+ },
2834
+ children: renderedCloseIcon
2835
+ }
2836
+ );
2837
+ return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
2838
+ "button",
2839
+ {
2840
+ ref,
2841
+ type: type ?? "button",
2842
+ "data-slot": "chat-toggle-button",
2843
+ "data-state": isOpen ? "open" : "closed",
2844
+ className: cn(BUTTON_BASE_CLASSES, className),
2845
+ "aria-label": isOpen ? labels.chatToggleCloseLabel : labels.chatToggleOpenLabel,
2846
+ "aria-pressed": isOpen,
2847
+ disabled,
2848
+ onClick: handleClick,
2849
+ ...restProps,
2850
+ children: [
2851
+ openIconElement,
2852
+ closeIconElement
2853
+ ]
2854
+ }
2855
+ );
2856
+ });
2857
+ CopilotChatToggleButton.displayName = "CopilotChatToggleButton";
2858
+ var CopilotChatToggleButton_default = CopilotChatToggleButton;
2859
+
2860
+ // src/components/chat/CopilotSidebarView.tsx
2861
+ var import_react23 = require("react");
2862
+
2863
+ // src/components/chat/CopilotModalHeader.tsx
2864
+ var import_react22 = require("react");
2865
+ var import_lucide_react8 = require("lucide-react");
2866
+ var import_jsx_runtime18 = require("react/jsx-runtime");
2867
+ function CopilotModalHeader({
2868
+ title,
2869
+ titleContent,
2870
+ closeButton,
2871
+ children,
2872
+ className,
2873
+ ...rest
2874
+ }) {
2875
+ const configuration = useCopilotChatConfiguration();
2876
+ const fallbackTitle = configuration?.labels.modalHeaderTitle ?? CopilotChatDefaultLabels.modalHeaderTitle;
2877
+ const resolvedTitle = title ?? fallbackTitle;
2878
+ const handleClose = (0, import_react22.useCallback)(() => {
2879
+ configuration?.setModalOpen(false);
2880
+ }, [configuration]);
2881
+ const BoundTitle = renderSlot(titleContent, CopilotModalHeader.Title, {
2882
+ children: resolvedTitle
2883
+ });
2884
+ const BoundCloseButton = renderSlot(closeButton, CopilotModalHeader.CloseButton, {
2885
+ onClick: handleClose
2886
+ });
2887
+ if (children) {
2888
+ return children({
2889
+ titleContent: BoundTitle,
2890
+ closeButton: BoundCloseButton,
2891
+ title: resolvedTitle,
2892
+ ...rest
2893
+ });
2894
+ }
2895
+ return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
2896
+ "header",
2897
+ {
2898
+ "data-slot": "copilot-modal-header",
2899
+ className: cn(
2900
+ "flex items-center justify-between border-b border-border px-4 py-4",
2901
+ "bg-background/95 backdrop-blur supports-[backdrop-filter]:bg-background/80",
2902
+ className
2903
+ ),
2904
+ ...rest,
2905
+ children: /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "flex w-full items-center gap-2", children: [
2906
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { className: "flex-1", "aria-hidden": "true" }),
2907
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { className: "flex flex-1 justify-center text-center", children: BoundTitle }),
2908
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { className: "flex flex-1 justify-end", children: BoundCloseButton })
2909
+ ] })
2910
+ }
2911
+ );
2912
+ }
2913
+ CopilotModalHeader.displayName = "CopilotModalHeader";
2914
+ ((CopilotModalHeader2) => {
2915
+ CopilotModalHeader2.Title = ({ children, className, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
2916
+ "div",
2917
+ {
2918
+ className: cn(
2919
+ "w-full text-base font-medium leading-none tracking-tight text-foreground",
2920
+ className
2921
+ ),
2922
+ ...props,
2923
+ children
2924
+ }
2925
+ );
2926
+ CopilotModalHeader2.CloseButton = ({
2927
+ className,
2928
+ ...props
2929
+ }) => /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
2930
+ "button",
2931
+ {
2932
+ type: "button",
2933
+ className: cn(
2934
+ "inline-flex size-8 items-center justify-center rounded-full text-muted-foreground transition cursor-pointer",
2935
+ "hover:bg-muted hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
2936
+ className
2937
+ ),
2938
+ "aria-label": "Close",
2939
+ ...props,
2940
+ children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_lucide_react8.X, { className: "h-4 w-4", "aria-hidden": "true" })
2941
+ }
2942
+ );
2943
+ })(CopilotModalHeader || (CopilotModalHeader = {}));
2944
+ CopilotModalHeader.Title.displayName = "CopilotModalHeader.Title";
2945
+ CopilotModalHeader.CloseButton.displayName = "CopilotModalHeader.CloseButton";
2946
+
2947
+ // src/components/chat/CopilotSidebarView.tsx
2948
+ var import_jsx_runtime19 = require("react/jsx-runtime");
2949
+ var DEFAULT_SIDEBAR_WIDTH = 480;
2950
+ var SIDEBAR_TRANSITION_MS = 260;
2951
+ function CopilotSidebarView({ header, width, ...props }) {
2952
+ const configuration = useCopilotChatConfiguration();
2953
+ const isSidebarOpen = configuration?.isModalOpen ?? false;
2954
+ const sidebarRef = (0, import_react23.useRef)(null);
2955
+ const [sidebarWidth, setSidebarWidth] = (0, import_react23.useState)(width ?? DEFAULT_SIDEBAR_WIDTH);
2956
+ const widthToCss = (w) => {
2957
+ return typeof w === "number" ? `${w}px` : w;
2958
+ };
2959
+ const widthToMargin = (w) => {
2960
+ if (typeof w === "number") {
2961
+ return `${w}px`;
2962
+ }
2963
+ return w;
2964
+ };
2965
+ (0, import_react23.useEffect)(() => {
2966
+ if (width !== void 0) {
2967
+ return;
2968
+ }
2969
+ if (typeof window === "undefined") {
2970
+ return;
2971
+ }
2972
+ const element = sidebarRef.current;
2973
+ if (!element) {
2974
+ return;
2975
+ }
2976
+ const updateWidth = () => {
2977
+ const rect = element.getBoundingClientRect();
2978
+ if (rect.width > 0) {
2979
+ setSidebarWidth(rect.width);
2980
+ }
2981
+ };
2982
+ updateWidth();
2983
+ if (typeof ResizeObserver !== "undefined") {
2984
+ const observer = new ResizeObserver(() => updateWidth());
2985
+ observer.observe(element);
2986
+ return () => observer.disconnect();
2987
+ }
2988
+ window.addEventListener("resize", updateWidth);
2989
+ return () => window.removeEventListener("resize", updateWidth);
2990
+ }, [width]);
2991
+ const headerElement = renderSlot(header, CopilotModalHeader, {});
2992
+ return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(import_jsx_runtime19.Fragment, { children: [
2993
+ isSidebarOpen && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
2994
+ "style",
2995
+ {
2996
+ dangerouslySetInnerHTML: {
2997
+ __html: `body {
2998
+ margin-inline-end: ${widthToMargin(sidebarWidth)};
2999
+ transition: margin-inline-end ${SIDEBAR_TRANSITION_MS}ms ease;
3000
+ }`
3001
+ }
2419
3002
  }
3003
+ ),
3004
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(CopilotChatToggleButton_default, {}),
3005
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
3006
+ "aside",
3007
+ {
3008
+ ref: sidebarRef,
3009
+ "data-copilot-sidebar": true,
3010
+ className: cn(
3011
+ "fixed right-0 top-0 z-[1200] flex h-dvh max-h-screen",
3012
+ "border-l border-border bg-background text-foreground shadow-xl",
3013
+ "transition-transform duration-300 ease-out",
3014
+ isSidebarOpen ? "translate-x-0" : "translate-x-full pointer-events-none"
3015
+ ),
3016
+ style: { width: widthToCss(sidebarWidth) },
3017
+ "aria-hidden": !isSidebarOpen,
3018
+ "aria-label": "Copilot chat sidebar",
3019
+ role: "complementary",
3020
+ children: /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: "flex h-full w-full flex-col overflow-hidden", children: [
3021
+ headerElement,
3022
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { className: "flex-1 overflow-hidden", "data-sidebar-chat": true, children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(CopilotChatView_default, { ...props }) })
3023
+ ] })
3024
+ }
3025
+ )
3026
+ ] });
3027
+ }
3028
+ CopilotSidebarView.displayName = "CopilotSidebarView";
3029
+
3030
+ // src/components/chat/CopilotSidebar.tsx
3031
+ var import_react24 = require("react");
3032
+ var import_jsx_runtime20 = require("react/jsx-runtime");
3033
+ function CopilotSidebar({ header, defaultOpen, width, ...chatProps }) {
3034
+ const SidebarViewOverride = (0, import_react24.useMemo)(() => {
3035
+ const Component = (viewProps) => {
3036
+ const { header: viewHeader, width: viewWidth, ...restProps } = viewProps;
3037
+ return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
3038
+ CopilotSidebarView,
3039
+ {
3040
+ ...restProps,
3041
+ header: header ?? viewHeader,
3042
+ width: width ?? viewWidth
3043
+ }
3044
+ );
3045
+ };
3046
+ return Object.assign(Component, CopilotChatView_default);
3047
+ }, [header, width]);
3048
+ return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
3049
+ CopilotChat,
3050
+ {
3051
+ ...chatProps,
3052
+ chatView: SidebarViewOverride,
3053
+ isModalDefaultOpen: defaultOpen
2420
3054
  }
2421
- ) });
3055
+ );
2422
3056
  }
3057
+ CopilotSidebar.displayName = "CopilotSidebar";
2423
3058
 
2424
3059
  // src/types/defineToolCallRender.ts
2425
3060
  var import_zod2 = require("zod");
@@ -2434,25 +3069,25 @@ function defineToolCallRender(def) {
2434
3069
  }
2435
3070
 
2436
3071
  // src/components/WildcardToolCallRender.tsx
2437
- var import_react17 = require("react");
2438
- var import_jsx_runtime15 = require("react/jsx-runtime");
3072
+ var import_react25 = require("react");
3073
+ var import_jsx_runtime21 = require("react/jsx-runtime");
2439
3074
  var WildcardToolCallRender = defineToolCallRender({
2440
3075
  name: "*",
2441
3076
  render: ({ args, result, name, status }) => {
2442
- const [isExpanded, setIsExpanded] = (0, import_react17.useState)(false);
3077
+ const [isExpanded, setIsExpanded] = (0, import_react25.useState)(false);
2443
3078
  const statusString = String(status);
2444
3079
  const isActive = statusString === "inProgress" || statusString === "executing";
2445
3080
  const isComplete = statusString === "complete";
2446
3081
  const statusStyles = isActive ? "bg-amber-100 text-amber-800 dark:bg-amber-500/15 dark:text-amber-400" : isComplete ? "bg-emerald-100 text-emerald-800 dark:bg-emerald-500/15 dark:text-emerald-400" : "bg-zinc-100 text-zinc-800 dark:bg-zinc-700/40 dark:text-zinc-300";
2447
- return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { className: "mt-2 pb-2", children: /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "rounded-xl border border-zinc-200/60 dark:border-zinc-800/60 bg-white/70 dark:bg-zinc-900/50 shadow-sm backdrop-blur p-4", children: [
2448
- /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
3082
+ return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "mt-2 pb-2", children: /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "rounded-xl border border-zinc-200/60 dark:border-zinc-800/60 bg-white/70 dark:bg-zinc-900/50 shadow-sm backdrop-blur p-4", children: [
3083
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
2449
3084
  "div",
2450
3085
  {
2451
3086
  className: "flex items-center justify-between gap-3 cursor-pointer",
2452
3087
  onClick: () => setIsExpanded(!isExpanded),
2453
3088
  children: [
2454
- /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "flex items-center gap-2 min-w-0", children: [
2455
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
3089
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "flex items-center gap-2 min-w-0", children: [
3090
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
2456
3091
  "svg",
2457
3092
  {
2458
3093
  className: `h-4 w-4 text-zinc-500 dark:text-zinc-400 transition-transform ${isExpanded ? "rotate-90" : ""}`,
@@ -2460,7 +3095,7 @@ var WildcardToolCallRender = defineToolCallRender({
2460
3095
  viewBox: "0 0 24 24",
2461
3096
  strokeWidth: 2,
2462
3097
  stroke: "currentColor",
2463
- children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
3098
+ children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
2464
3099
  "path",
2465
3100
  {
2466
3101
  strokeLinecap: "round",
@@ -2470,10 +3105,10 @@ var WildcardToolCallRender = defineToolCallRender({
2470
3105
  )
2471
3106
  }
2472
3107
  ),
2473
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: "inline-block h-2 w-2 rounded-full bg-blue-500" }),
2474
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: "truncate text-sm font-medium text-zinc-900 dark:text-zinc-100", children: name })
3108
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "inline-block h-2 w-2 rounded-full bg-blue-500" }),
3109
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "truncate text-sm font-medium text-zinc-900 dark:text-zinc-100", children: name })
2475
3110
  ] }),
2476
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
3111
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
2477
3112
  "span",
2478
3113
  {
2479
3114
  className: `inline-flex items-center rounded-full px-2 py-1 text-xs font-medium ${statusStyles}`,
@@ -2483,14 +3118,14 @@ var WildcardToolCallRender = defineToolCallRender({
2483
3118
  ]
2484
3119
  }
2485
3120
  ),
2486
- isExpanded && /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "mt-3 grid gap-4", children: [
2487
- /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { children: [
2488
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { className: "text-xs uppercase tracking-wide text-zinc-500 dark:text-zinc-400", children: "Arguments" }),
2489
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("pre", { className: "mt-2 max-h-64 overflow-auto rounded-md bg-zinc-50 dark:bg-zinc-800/60 p-3 text-xs leading-relaxed text-zinc-800 dark:text-zinc-200 whitespace-pre-wrap break-words", children: JSON.stringify(args ?? {}, null, 2) })
3121
+ isExpanded && /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "mt-3 grid gap-4", children: [
3122
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { children: [
3123
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "text-xs uppercase tracking-wide text-zinc-500 dark:text-zinc-400", children: "Arguments" }),
3124
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("pre", { className: "mt-2 max-h-64 overflow-auto rounded-md bg-zinc-50 dark:bg-zinc-800/60 p-3 text-xs leading-relaxed text-zinc-800 dark:text-zinc-200 whitespace-pre-wrap break-words", children: JSON.stringify(args ?? {}, null, 2) })
2490
3125
  ] }),
2491
- result !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { children: [
2492
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { className: "text-xs uppercase tracking-wide text-zinc-500 dark:text-zinc-400", children: "Result" }),
2493
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("pre", { className: "mt-2 max-h-64 overflow-auto rounded-md bg-zinc-50 dark:bg-zinc-800/60 p-3 text-xs leading-relaxed text-zinc-800 dark:text-zinc-200 whitespace-pre-wrap break-words", children: typeof result === "string" ? result : JSON.stringify(result, null, 2) })
3126
+ result !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { children: [
3127
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "text-xs uppercase tracking-wide text-zinc-500 dark:text-zinc-400", children: "Result" }),
3128
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("pre", { className: "mt-2 max-h-64 overflow-auto rounded-md bg-zinc-50 dark:bg-zinc-800/60 p-3 text-xs leading-relaxed text-zinc-800 dark:text-zinc-200 whitespace-pre-wrap break-words", children: typeof result === "string" ? result : JSON.stringify(result, null, 2) })
2494
3129
  ] })
2495
3130
  ] })
2496
3131
  ] }) });
@@ -2505,18 +3140,28 @@ var WildcardToolCallRender = defineToolCallRender({
2505
3140
  CopilotChatConfigurationProvider,
2506
3141
  CopilotChatInput,
2507
3142
  CopilotChatMessageView,
3143
+ CopilotChatSuggestionPill,
3144
+ CopilotChatSuggestionView,
3145
+ CopilotChatToggleButton,
3146
+ CopilotChatToggleButtonCloseIcon,
3147
+ CopilotChatToggleButtonOpenIcon,
2508
3148
  CopilotChatToolCallsView,
2509
3149
  CopilotChatUserMessage,
2510
3150
  CopilotChatView,
2511
3151
  CopilotKitProvider,
3152
+ CopilotModalHeader,
3153
+ CopilotSidebar,
3154
+ CopilotSidebarView,
2512
3155
  WildcardToolCallRender,
2513
3156
  defineToolCallRender,
2514
3157
  useAgent,
2515
3158
  useAgentContext,
3159
+ useConfigureSuggestions,
2516
3160
  useCopilotChatConfiguration,
2517
3161
  useCopilotKit,
2518
3162
  useFrontendTool,
2519
3163
  useHumanInTheLoop,
2520
- useRenderToolCall
3164
+ useRenderToolCall,
3165
+ useSuggestions
2521
3166
  });
2522
3167
  //# sourceMappingURL=index.js.map