@copilotkitnext/react 0.0.12 → 0.0.13-alpha.1

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