@copilotkit/react-ui 1.10.0-next.1 → 1.10.0-next.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (108) hide show
  1. package/CHANGELOG.md +104 -0
  2. package/dist/{chunk-O7KTFUAN.mjs → chunk-226ZMOE3.mjs} +2 -2
  3. package/dist/{chunk-WHDNKXMP.mjs → chunk-BJHJBS5M.mjs} +46 -6
  4. package/dist/chunk-BJHJBS5M.mjs.map +1 -0
  5. package/dist/{chunk-FOSKS7AI.mjs → chunk-FFJHOZX6.mjs} +5 -5
  6. package/dist/{chunk-QELAC6XJ.mjs → chunk-GBP47ONN.mjs} +2 -2
  7. package/dist/chunk-GBP47ONN.mjs.map +1 -0
  8. package/dist/{chunk-7CAK2CNK.mjs → chunk-GDSZGYCE.mjs} +2 -2
  9. package/dist/{chunk-O7PYQO73.mjs → chunk-GJ4SX4JE.mjs} +153 -37
  10. package/dist/chunk-GJ4SX4JE.mjs.map +1 -0
  11. package/dist/{chunk-TCIZDWPC.mjs → chunk-J5ZZR6YB.mjs} +2 -2
  12. package/dist/chunk-J5ZZR6YB.mjs.map +1 -0
  13. package/dist/{chunk-QN7T3GWI.mjs → chunk-JY2CSDKN.mjs} +4 -6
  14. package/dist/chunk-JY2CSDKN.mjs.map +1 -0
  15. package/dist/chunk-MIVUCSGO.mjs +126 -0
  16. package/dist/chunk-MIVUCSGO.mjs.map +1 -0
  17. package/dist/{chunk-OQM7D3Z3.mjs → chunk-T5QU6KSB.mjs} +8 -4
  18. package/dist/chunk-T5QU6KSB.mjs.map +1 -0
  19. package/dist/{chunk-Q2467VHZ.mjs → chunk-W26XFBEG.mjs} +2 -2
  20. package/dist/chunk-W26XFBEG.mjs.map +1 -0
  21. package/dist/chunk-Y44VLEUH.mjs +222 -0
  22. package/dist/chunk-Y44VLEUH.mjs.map +1 -0
  23. package/dist/components/chat/Chat.d.ts +52 -15
  24. package/dist/components/chat/Chat.js +1136 -869
  25. package/dist/components/chat/Chat.js.map +1 -1
  26. package/dist/components/chat/Chat.mjs +9 -8
  27. package/dist/components/chat/Header.js +6 -8
  28. package/dist/components/chat/Header.js.map +1 -1
  29. package/dist/components/chat/Header.mjs +4 -4
  30. package/dist/components/chat/Messages.d.ts +1 -1
  31. package/dist/components/chat/Messages.js +984 -23
  32. package/dist/components/chat/Messages.js.map +1 -1
  33. package/dist/components/chat/Messages.mjs +9 -1
  34. package/dist/components/chat/Modal.d.ts +2 -2
  35. package/dist/components/chat/Modal.js +1267 -931
  36. package/dist/components/chat/Modal.js.map +1 -1
  37. package/dist/components/chat/Modal.mjs +14 -13
  38. package/dist/components/chat/Popup.d.ts +1 -1
  39. package/dist/components/chat/Popup.js +1269 -933
  40. package/dist/components/chat/Popup.js.map +1 -1
  41. package/dist/components/chat/Popup.mjs +15 -14
  42. package/dist/components/chat/Sidebar.d.ts +1 -1
  43. package/dist/components/chat/Sidebar.js +1269 -933
  44. package/dist/components/chat/Sidebar.js.map +1 -1
  45. package/dist/components/chat/Sidebar.mjs +15 -14
  46. package/dist/components/chat/Suggestion.js +1 -1
  47. package/dist/components/chat/Suggestion.js.map +1 -1
  48. package/dist/components/chat/Suggestion.mjs +1 -1
  49. package/dist/components/chat/Suggestions.js +1 -1
  50. package/dist/components/chat/Suggestions.js.map +1 -1
  51. package/dist/components/chat/Suggestions.mjs +2 -2
  52. package/dist/components/chat/index.d.ts +2 -2
  53. package/dist/components/chat/index.js +1271 -935
  54. package/dist/components/chat/index.js.map +1 -1
  55. package/dist/components/chat/index.mjs +22 -21
  56. package/dist/components/chat/messages/LegacyRenderMessage.d.ts +28 -0
  57. package/dist/components/chat/messages/LegacyRenderMessage.js +980 -0
  58. package/dist/components/chat/messages/LegacyRenderMessage.js.map +1 -0
  59. package/dist/components/chat/messages/LegacyRenderMessage.mjs +17 -0
  60. package/dist/components/chat/messages/LegacyRenderMessage.mjs.map +1 -0
  61. package/dist/components/chat/messages/RenderMessage.js +4 -0
  62. package/dist/components/chat/messages/RenderMessage.js.map +1 -1
  63. package/dist/components/chat/messages/RenderMessage.mjs +2 -2
  64. package/dist/components/chat/props.d.ts +94 -2
  65. package/dist/components/chat/props.js.map +1 -1
  66. package/dist/components/dev-console/console.d.ts +1 -0
  67. package/dist/components/dev-console/console.js +6 -8
  68. package/dist/components/dev-console/console.js.map +1 -1
  69. package/dist/components/dev-console/console.mjs +3 -3
  70. package/dist/components/dev-console/index.d.ts +1 -3
  71. package/dist/components/dev-console/index.js +7 -9
  72. package/dist/components/dev-console/index.js.map +1 -1
  73. package/dist/components/dev-console/index.mjs +5 -5
  74. package/dist/components/dev-console/utils.d.ts +2 -2
  75. package/dist/components/dev-console/utils.js +2 -4
  76. package/dist/components/dev-console/utils.js.map +1 -1
  77. package/dist/components/dev-console/utils.mjs +1 -1
  78. package/dist/components/index.d.ts +3 -5
  79. package/dist/components/index.js +1272 -936
  80. package/dist/components/index.js.map +1 -1
  81. package/dist/components/index.mjs +24 -23
  82. package/dist/index.d.ts +3 -5
  83. package/dist/index.js +1303 -967
  84. package/dist/index.js.map +1 -1
  85. package/dist/index.mjs +24 -23
  86. package/package.json +6 -6
  87. package/src/components/chat/Chat.tsx +241 -23
  88. package/src/components/chat/Messages.tsx +58 -5
  89. package/src/components/chat/Modal.tsx +128 -41
  90. package/src/components/chat/Popup.tsx +20 -0
  91. package/src/components/chat/Sidebar.tsx +22 -0
  92. package/src/components/chat/Suggestion.tsx +1 -1
  93. package/src/components/chat/messages/LegacyRenderMessage.tsx +143 -0
  94. package/src/components/chat/messages/RenderMessage.tsx +3 -0
  95. package/src/components/chat/props.ts +110 -1
  96. package/src/components/dev-console/utils.ts +1 -6
  97. package/dist/chunk-7RNOT3GM.mjs +0 -144
  98. package/dist/chunk-7RNOT3GM.mjs.map +0 -1
  99. package/dist/chunk-O7PYQO73.mjs.map +0 -1
  100. package/dist/chunk-OQM7D3Z3.mjs.map +0 -1
  101. package/dist/chunk-Q2467VHZ.mjs.map +0 -1
  102. package/dist/chunk-QELAC6XJ.mjs.map +0 -1
  103. package/dist/chunk-QN7T3GWI.mjs.map +0 -1
  104. package/dist/chunk-TCIZDWPC.mjs.map +0 -1
  105. package/dist/chunk-WHDNKXMP.mjs.map +0 -1
  106. /package/dist/{chunk-O7KTFUAN.mjs.map → chunk-226ZMOE3.mjs.map} +0 -0
  107. /package/dist/{chunk-FOSKS7AI.mjs.map → chunk-FFJHOZX6.mjs.map} +0 -0
  108. /package/dist/{chunk-7CAK2CNK.mjs.map → chunk-GDSZGYCE.mjs.map} +0 -0
@@ -522,9 +522,7 @@ var Button = ({}) => {
522
522
 
523
523
  // src/components/dev-console/utils.ts
524
524
  var import_react_core2 = require("@copilotkit/react-core");
525
- function shouldShowDevConsole(showDevConsole) {
526
- return showDevConsole;
527
- }
525
+ var import_react_core3 = require("@copilotkit/react-core");
528
526
  function getPublishedCopilotKitVersion(current, forceCheck = false) {
529
527
  return __async(this, null, function* () {
530
528
  const LOCAL_STORAGE_KEY = "__copilotkit_version_check__";
@@ -644,7 +642,7 @@ function logMessages(context) {
644
642
  }
645
643
 
646
644
  // src/components/dev-console/console.tsx
647
- var import_react_core3 = require("@copilotkit/react-core");
645
+ var import_react_core4 = require("@copilotkit/react-core");
648
646
  var import_react4 = require("react");
649
647
 
650
648
  // src/components/dev-console/icons.tsx
@@ -834,10 +832,10 @@ function CopilotKitHelpModal() {
834
832
  var import_jsx_runtime8 = require("react/jsx-runtime");
835
833
  function CopilotDevConsole() {
836
834
  const currentVersion = import_shared2.COPILOTKIT_VERSION;
837
- const context = (0, import_react_core3.useCopilotContext)();
835
+ const context = (0, import_react_core4.useCopilotContext)();
838
836
  const [showDevConsole, setShowDevConsole] = (0, import_react4.useState)(false);
839
837
  (0, import_react4.useEffect)(() => {
840
- setShowDevConsole(shouldShowDevConsole(context.showDevConsole));
838
+ setShowDevConsole((0, import_react_core3.shouldShowDevConsole)(context.showDevConsole));
841
839
  }, [context.showDevConsole]);
842
840
  const dontRunTwiceInDevMode = (0, import_react4.useRef)(false);
843
841
  const [versionStatus, setVersionStatus] = (0, import_react4.useState)("unknown");
@@ -963,8 +961,8 @@ function DebugMenuButton({
963
961
  checkForUpdates,
964
962
  mode
965
963
  }) {
966
- const context = (0, import_react_core3.useCopilotContext)();
967
- const messagesContext = (0, import_react_core3.useCopilotMessagesContext)();
964
+ const context = (0, import_react_core4.useCopilotContext)();
965
+ const messagesContext = (0, import_react_core4.useCopilotMessagesContext)();
968
966
  return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_jsx_runtime8.Fragment, { children: /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_react5.Menu, { children: [
969
967
  /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
970
968
  import_react5.MenuButton,
@@ -1025,559 +1023,137 @@ var Header = ({}) => {
1025
1023
  };
1026
1024
 
1027
1025
  // src/components/chat/Messages.tsx
1028
- var import_react6 = require("react");
1029
- var import_react_core4 = require("@copilotkit/react-core");
1026
+ var import_react10 = require("react");
1027
+ var import_react_core5 = require("@copilotkit/react-core");
1028
+
1029
+ // src/components/chat/messages/UserMessage.tsx
1030
1030
  var import_jsx_runtime10 = require("react/jsx-runtime");
1031
- var Messages = ({
1032
- inProgress,
1033
- children,
1034
- RenderMessage: RenderMessage2,
1035
- AssistantMessage: AssistantMessage2,
1036
- UserMessage: UserMessage2,
1037
- onRegenerate,
1038
- onCopy,
1039
- onThumbsUp,
1040
- onThumbsDown,
1041
- markdownTagRenderers
1042
- }) => {
1043
- const { labels } = useChatContext();
1044
- const { visibleMessages, interrupt } = (0, import_react_core4.useCopilotChat)();
1045
- const initialMessages = (0, import_react6.useMemo)(() => makeInitialMessages(labels.initial), [labels.initial]);
1046
- const messages = [...initialMessages, ...visibleMessages];
1047
- const { messagesContainerRef, messagesEndRef } = useScrollToBottom(messages);
1048
- return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "copilotKitMessages", ref: messagesContainerRef, children: [
1049
- /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "copilotKitMessagesContainer", children: [
1050
- messages.map((message, index) => {
1051
- const isCurrentMessage = index === messages.length - 1;
1052
- return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
1053
- RenderMessage2,
1054
- {
1055
- message,
1056
- inProgress,
1057
- index,
1058
- isCurrentMessage,
1059
- AssistantMessage: AssistantMessage2,
1060
- UserMessage: UserMessage2,
1061
- onRegenerate,
1062
- onCopy,
1063
- onThumbsUp,
1064
- onThumbsDown,
1065
- markdownTagRenderers
1066
- },
1067
- index
1068
- );
1069
- }),
1070
- interrupt
1071
- ] }),
1072
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("footer", { className: "copilotKitMessagesFooter", ref: messagesEndRef, children })
1073
- ] });
1074
- };
1075
- function makeInitialMessages(initial) {
1076
- if (!initial)
1077
- return [];
1078
- if (Array.isArray(initial)) {
1079
- return initial.map((message) => {
1080
- return {
1081
- id: message,
1082
- role: "assistant",
1083
- content: message
1084
- };
1085
- });
1031
+ var UserMessage = (props) => {
1032
+ const { message, ImageRenderer: ImageRenderer2 } = props;
1033
+ const isImageMessage = message && "image" in message && message.image;
1034
+ if (isImageMessage) {
1035
+ const imageMessage = message;
1036
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "copilotKitMessage copilotKitUserMessage", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(ImageRenderer2, { image: imageMessage.image, content: imageMessage.content }) });
1086
1037
  }
1087
- return [
1088
- {
1089
- id: initial,
1090
- role: "system",
1091
- content: initial
1092
- }
1093
- ];
1094
- }
1095
- function useScrollToBottom(messages) {
1096
- const messagesEndRef = (0, import_react6.useRef)(null);
1097
- const messagesContainerRef = (0, import_react6.useRef)(null);
1098
- const isProgrammaticScrollRef = (0, import_react6.useRef)(false);
1099
- const isUserScrollUpRef = (0, import_react6.useRef)(false);
1100
- const scrollToBottom = () => {
1101
- if (messagesContainerRef.current && messagesEndRef.current) {
1102
- isProgrammaticScrollRef.current = true;
1103
- messagesContainerRef.current.scrollTop = messagesContainerRef.current.scrollHeight;
1104
- }
1105
- };
1106
- const handleScroll = () => {
1107
- if (isProgrammaticScrollRef.current) {
1108
- isProgrammaticScrollRef.current = false;
1038
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "copilotKitMessage copilotKitUserMessage", children: message == null ? void 0 : message.content });
1039
+ };
1040
+
1041
+ // src/components/chat/Markdown.tsx
1042
+ var import_react7 = require("react");
1043
+ var import_react_markdown = __toESM(require("react-markdown"));
1044
+
1045
+ // src/components/chat/CodeBlock.tsx
1046
+ var import_react6 = require("react");
1047
+ var import_react_syntax_highlighter = require("react-syntax-highlighter");
1048
+
1049
+ // src/hooks/use-copy-to-clipboard.tsx
1050
+ var React5 = __toESM(require("react"));
1051
+ function useCopyToClipboard({ timeout = 2e3 }) {
1052
+ const [isCopied, setIsCopied] = React5.useState(false);
1053
+ const copyToClipboard = (value) => {
1054
+ var _a;
1055
+ if (typeof window === "undefined" || !((_a = navigator.clipboard) == null ? void 0 : _a.writeText)) {
1109
1056
  return;
1110
1057
  }
1111
- if (messagesContainerRef.current) {
1112
- const { scrollTop, scrollHeight, clientHeight } = messagesContainerRef.current;
1113
- isUserScrollUpRef.current = scrollTop + clientHeight < scrollHeight;
1114
- }
1115
- };
1116
- (0, import_react6.useEffect)(() => {
1117
- const container = messagesContainerRef.current;
1118
- if (container) {
1119
- container.addEventListener("scroll", handleScroll);
1120
- }
1121
- return () => {
1122
- if (container) {
1123
- container.removeEventListener("scroll", handleScroll);
1124
- }
1125
- };
1126
- }, []);
1127
- (0, import_react6.useEffect)(() => {
1128
- const container = messagesContainerRef.current;
1129
- if (!container) {
1058
+ if (!value) {
1130
1059
  return;
1131
1060
  }
1132
- const mutationObserver = new MutationObserver(() => {
1133
- if (!isUserScrollUpRef.current) {
1134
- scrollToBottom();
1135
- }
1136
- });
1137
- mutationObserver.observe(container, {
1138
- childList: true,
1139
- subtree: true,
1140
- characterData: true
1061
+ navigator.clipboard.writeText(value).then(() => {
1062
+ setIsCopied(true);
1063
+ setTimeout(() => {
1064
+ setIsCopied(false);
1065
+ }, timeout);
1141
1066
  });
1142
- return () => {
1143
- mutationObserver.disconnect();
1144
- };
1145
- }, []);
1146
- (0, import_react6.useEffect)(() => {
1147
- isUserScrollUpRef.current = false;
1148
- scrollToBottom();
1149
- }, [messages.filter((m) => m.role === "user").length]);
1150
- return { messagesEndRef, messagesContainerRef };
1067
+ };
1068
+ return { isCopied, copyToClipboard };
1151
1069
  }
1152
1070
 
1153
- // src/components/chat/Input.tsx
1154
- var import_react9 = require("react");
1155
-
1156
- // src/components/chat/Textarea.tsx
1157
- var import_react7 = require("react");
1071
+ // src/components/chat/CodeBlock.tsx
1158
1072
  var import_jsx_runtime11 = require("react/jsx-runtime");
1159
- var AutoResizingTextarea = (0, import_react7.forwardRef)(
1160
- ({
1161
- maxRows = 1,
1162
- placeholder,
1163
- value,
1164
- onChange,
1165
- onKeyDown,
1166
- onCompositionStart,
1167
- onCompositionEnd,
1168
- autoFocus
1169
- }, ref) => {
1170
- const internalTextareaRef = (0, import_react7.useRef)(null);
1171
- const [maxHeight, setMaxHeight] = (0, import_react7.useState)(0);
1172
- (0, import_react7.useImperativeHandle)(ref, () => internalTextareaRef.current);
1173
- (0, import_react7.useEffect)(() => {
1174
- const calculateMaxHeight = () => {
1175
- const textarea = internalTextareaRef.current;
1176
- if (textarea) {
1177
- textarea.style.height = "auto";
1178
- const singleRowHeight = textarea.scrollHeight;
1179
- setMaxHeight(singleRowHeight * maxRows);
1180
- if (autoFocus) {
1181
- textarea.focus();
1182
- }
1183
- }
1184
- };
1185
- calculateMaxHeight();
1186
- }, [maxRows]);
1187
- (0, import_react7.useEffect)(() => {
1188
- const textarea = internalTextareaRef.current;
1189
- if (textarea) {
1190
- textarea.style.height = "auto";
1191
- textarea.style.height = `${Math.min(textarea.scrollHeight, maxHeight)}px`;
1192
- }
1193
- }, [value, maxHeight]);
1194
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
1195
- "textarea",
1073
+ var programmingLanguages = {
1074
+ javascript: ".js",
1075
+ python: ".py",
1076
+ java: ".java",
1077
+ c: ".c",
1078
+ cpp: ".cpp",
1079
+ "c++": ".cpp",
1080
+ "c#": ".cs",
1081
+ ruby: ".rb",
1082
+ php: ".php",
1083
+ swift: ".swift",
1084
+ "objective-c": ".m",
1085
+ kotlin: ".kt",
1086
+ typescript: ".ts",
1087
+ go: ".go",
1088
+ perl: ".pl",
1089
+ rust: ".rs",
1090
+ scala: ".scala",
1091
+ haskell: ".hs",
1092
+ lua: ".lua",
1093
+ shell: ".sh",
1094
+ sql: ".sql",
1095
+ html: ".html",
1096
+ css: ".css"
1097
+ // add more file extensions here, make sure the key is same as language prop in CodeBlock.tsx component
1098
+ };
1099
+ var generateRandomString = (length, lowercase = false) => {
1100
+ const chars = "ABCDEFGHJKLMNPQRSTUVWXY3456789";
1101
+ let result = "";
1102
+ for (let i = 0; i < length; i++) {
1103
+ result += chars.charAt(Math.floor(Math.random() * chars.length));
1104
+ }
1105
+ return lowercase ? result.toLowerCase() : result;
1106
+ };
1107
+ var CodeBlock = (0, import_react6.memo)(({ language, value }) => {
1108
+ const { isCopied, copyToClipboard } = useCopyToClipboard({ timeout: 2e3 });
1109
+ const downloadAsFile = () => {
1110
+ if (typeof window === "undefined") {
1111
+ return;
1112
+ }
1113
+ const fileExtension = programmingLanguages[language] || ".file";
1114
+ const suggestedFileName = `file-${generateRandomString(3, true)}${fileExtension}`;
1115
+ const fileName = window.prompt("Enter file name", suggestedFileName);
1116
+ if (!fileName) {
1117
+ return;
1118
+ }
1119
+ const blob = new Blob([value], { type: "text/plain" });
1120
+ const url = URL.createObjectURL(blob);
1121
+ const link = document.createElement("a");
1122
+ link.download = fileName;
1123
+ link.href = url;
1124
+ link.style.display = "none";
1125
+ document.body.appendChild(link);
1126
+ link.click();
1127
+ document.body.removeChild(link);
1128
+ URL.revokeObjectURL(url);
1129
+ };
1130
+ const onCopy = () => {
1131
+ if (isCopied)
1132
+ return;
1133
+ copyToClipboard(value);
1134
+ };
1135
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "copilotKitCodeBlock", children: [
1136
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "copilotKitCodeBlockToolbar", children: [
1137
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: "copilotKitCodeBlockToolbarLanguage", children: language }),
1138
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "copilotKitCodeBlockToolbarButtons", children: [
1139
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("button", { className: "copilotKitCodeBlockToolbarButton", onClick: downloadAsFile, children: DownloadIcon }),
1140
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("button", { className: "copilotKitCodeBlockToolbarButton", onClick: onCopy, children: isCopied ? CheckIcon : CopyIcon })
1141
+ ] })
1142
+ ] }),
1143
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
1144
+ import_react_syntax_highlighter.Prism,
1196
1145
  {
1197
- ref: internalTextareaRef,
1198
- value,
1199
- onChange,
1200
- onKeyDown,
1201
- onCompositionStart,
1202
- onCompositionEnd,
1203
- placeholder,
1204
- style: {
1205
- overflow: "auto",
1206
- resize: "none",
1207
- maxHeight: `${maxHeight}px`
1146
+ language,
1147
+ style: highlightStyle,
1148
+ PreTag: "div",
1149
+ customStyle: {
1150
+ margin: 0,
1151
+ borderBottomLeftRadius: "0.375rem",
1152
+ borderBottomRightRadius: "0.375rem"
1208
1153
  },
1209
- rows: 1
1154
+ children: value
1210
1155
  }
1211
- );
1212
- }
1213
- );
1214
- var Textarea_default = AutoResizingTextarea;
1215
-
1216
- // src/hooks/use-push-to-talk.tsx
1217
- var import_react_core5 = require("@copilotkit/react-core");
1218
- var import_runtime_client_gql = require("@copilotkit/runtime-client-gql");
1219
- var import_react8 = require("react");
1220
- var startRecording = (mediaStreamRef, mediaRecorderRef, audioContextRef, recordedChunks, onStop) => __async(void 0, null, function* () {
1221
- if (!mediaStreamRef.current || !audioContextRef.current) {
1222
- mediaStreamRef.current = yield navigator.mediaDevices.getUserMedia({ audio: true });
1223
- audioContextRef.current = new window.AudioContext();
1224
- yield audioContextRef.current.resume();
1225
- }
1226
- mediaRecorderRef.current = new MediaRecorder(mediaStreamRef.current);
1227
- mediaRecorderRef.current.start(1e3);
1228
- mediaRecorderRef.current.ondataavailable = (event) => {
1229
- recordedChunks.push(event.data);
1230
- };
1231
- mediaRecorderRef.current.onstop = onStop;
1232
- });
1233
- var stopRecording = (mediaRecorderRef) => {
1234
- if (mediaRecorderRef.current && mediaRecorderRef.current.state !== "inactive") {
1235
- mediaRecorderRef.current.stop();
1236
- }
1237
- };
1238
- var transcribeAudio = (recordedChunks, transcribeAudioUrl) => __async(void 0, null, function* () {
1239
- const completeBlob = new Blob(recordedChunks, { type: "audio/mp4" });
1240
- const formData = new FormData();
1241
- formData.append("file", completeBlob, "recording.mp4");
1242
- const response = yield fetch(transcribeAudioUrl, {
1243
- method: "POST",
1244
- body: formData
1245
- });
1246
- if (!response.ok) {
1247
- throw new Error(`Error: ${response.statusText}`);
1248
- }
1249
- const transcription = yield response.json();
1250
- return transcription.text;
1251
- });
1252
- var playAudioResponse = (text, textToSpeechUrl, audioContext) => {
1253
- const encodedText = encodeURIComponent(text);
1254
- const url = `${textToSpeechUrl}?text=${encodedText}`;
1255
- fetch(url).then((response) => response.arrayBuffer()).then((arrayBuffer) => audioContext.decodeAudioData(arrayBuffer)).then((audioBuffer) => {
1256
- const source = audioContext.createBufferSource();
1257
- source.buffer = audioBuffer;
1258
- source.connect(audioContext.destination);
1259
- source.start(0);
1260
- }).catch((error) => {
1261
- console.error("Error with decoding audio data", error);
1262
- });
1263
- };
1264
- var usePushToTalk = ({
1265
- sendFunction,
1266
- inProgress
1267
- }) => {
1268
- const [pushToTalkState, setPushToTalkState] = (0, import_react8.useState)("idle");
1269
- const mediaStreamRef = (0, import_react8.useRef)(null);
1270
- const audioContextRef = (0, import_react8.useRef)(null);
1271
- const mediaRecorderRef = (0, import_react8.useRef)(null);
1272
- const recordedChunks = (0, import_react8.useRef)([]);
1273
- const generalContext = (0, import_react_core5.useCopilotContext)();
1274
- const messagesContext = (0, import_react_core5.useCopilotMessagesContext)();
1275
- const context = __spreadValues(__spreadValues({}, generalContext), messagesContext);
1276
- const [startReadingFromMessageId, setStartReadingFromMessageId] = (0, import_react8.useState)(null);
1277
- (0, import_react8.useEffect)(() => {
1278
- if (pushToTalkState === "recording") {
1279
- startRecording(
1280
- mediaStreamRef,
1281
- mediaRecorderRef,
1282
- audioContextRef,
1283
- recordedChunks.current,
1284
- () => {
1285
- setPushToTalkState("transcribing");
1286
- }
1287
- );
1288
- } else {
1289
- stopRecording(mediaRecorderRef);
1290
- if (pushToTalkState === "transcribing") {
1291
- transcribeAudio(recordedChunks.current, context.copilotApiConfig.transcribeAudioUrl).then(
1292
- (transcription) => __async(void 0, null, function* () {
1293
- recordedChunks.current = [];
1294
- setPushToTalkState("idle");
1295
- const message = yield sendFunction(transcription);
1296
- setStartReadingFromMessageId(message.id);
1297
- })
1298
- );
1299
- }
1300
- }
1301
- return () => {
1302
- stopRecording(mediaRecorderRef);
1303
- };
1304
- }, [pushToTalkState]);
1305
- (0, import_react8.useEffect)(() => {
1306
- if (inProgress === false && startReadingFromMessageId) {
1307
- const lastMessageIndex = context.messages.findIndex(
1308
- (message) => message.id === startReadingFromMessageId
1309
- );
1310
- const aguiMessages = (0, import_runtime_client_gql.gqlToAGUI)(context.messages);
1311
- const messagesAfterLast = aguiMessages.slice(lastMessageIndex + 1).filter((message) => message.role === "assistant");
1312
- const text = messagesAfterLast.map((message) => message.content).join("\n");
1313
- playAudioResponse(text, context.copilotApiConfig.textToSpeechUrl, audioContextRef.current);
1314
- setStartReadingFromMessageId(null);
1315
- }
1316
- }, [startReadingFromMessageId, inProgress]);
1317
- return { pushToTalkState, setPushToTalkState };
1318
- };
1319
-
1320
- // src/components/chat/Input.tsx
1321
- var import_react_core6 = require("@copilotkit/react-core");
1322
-
1323
- // src/hooks/use-dark-mode.ts
1324
- var useDarkMode = () => {
1325
- if (typeof window === "undefined")
1326
- return false;
1327
- return document.documentElement.classList.contains("dark") || document.body.classList.contains("dark") || document.documentElement.getAttribute("data-theme") === "dark" || document.body.getAttribute("data-theme") === "dark" || window.matchMedia("(prefers-color-scheme: dark)").matches;
1328
- };
1329
-
1330
- // src/components/chat/PoweredByTag.tsx
1331
- var import_jsx_runtime12 = require("react/jsx-runtime");
1332
- function PoweredByTag({ showPoweredBy = true }) {
1333
- const isDark = useDarkMode();
1334
- if (!showPoweredBy) {
1335
- return null;
1336
- }
1337
- const poweredByStyle = {
1338
- visibility: "visible",
1339
- display: "block",
1340
- position: "static",
1341
- textAlign: "center",
1342
- fontSize: "12px",
1343
- padding: "3px 0",
1344
- color: isDark ? "rgb(69, 69, 69)" : "rgb(214, 214, 214)"
1345
- };
1346
- return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("p", { className: "poweredBy", style: poweredByStyle, children: "Powered by CopilotKit" }) });
1347
- }
1348
-
1349
- // src/components/chat/Input.tsx
1350
- var import_jsx_runtime13 = require("react/jsx-runtime");
1351
- var MAX_NEWLINES = 6;
1352
- var Input = ({
1353
- inProgress,
1354
- onSend,
1355
- isVisible = false,
1356
- onStop,
1357
- onUpload,
1358
- hideStopButton = false
1359
- }) => {
1360
- var _a, _b;
1361
- const context = useChatContext();
1362
- const copilotContext = (0, import_react_core6.useCopilotContext)();
1363
- const showPoweredBy = !((_a = copilotContext.copilotApiConfig) == null ? void 0 : _a.publicApiKey);
1364
- const pushToTalkConfigured = copilotContext.copilotApiConfig.textToSpeechUrl !== void 0 && copilotContext.copilotApiConfig.transcribeAudioUrl !== void 0;
1365
- const textareaRef = (0, import_react9.useRef)(null);
1366
- const [isComposing, setIsComposing] = (0, import_react9.useState)(false);
1367
- const handleDivClick = (event) => {
1368
- var _a2;
1369
- const target = event.target;
1370
- if (target.closest("button"))
1371
- return;
1372
- if (target.tagName === "TEXTAREA")
1373
- return;
1374
- (_a2 = textareaRef.current) == null ? void 0 : _a2.focus();
1375
- };
1376
- const [text, setText] = (0, import_react9.useState)("");
1377
- const send = () => {
1378
- var _a2;
1379
- if (inProgress)
1380
- return;
1381
- onSend(text);
1382
- setText("");
1383
- (_a2 = textareaRef.current) == null ? void 0 : _a2.focus();
1384
- };
1385
- const { pushToTalkState, setPushToTalkState } = usePushToTalk({
1386
- sendFunction: onSend,
1387
- inProgress
1388
- });
1389
- const isInProgress = inProgress || pushToTalkState === "transcribing";
1390
- const buttonIcon = isInProgress && !hideStopButton ? context.icons.stopIcon : context.icons.sendIcon;
1391
- const showPushToTalk = pushToTalkConfigured && (pushToTalkState === "idle" || pushToTalkState === "recording") && !inProgress;
1392
- const canSend = (0, import_react9.useMemo)(() => {
1393
- var _a2;
1394
- const interruptEvent = (_a2 = copilotContext.langGraphInterruptAction) == null ? void 0 : _a2.event;
1395
- const interruptInProgress = (interruptEvent == null ? void 0 : interruptEvent.name) === "LangGraphInterruptEvent" && !(interruptEvent == null ? void 0 : interruptEvent.response);
1396
- return !isInProgress && text.trim().length > 0 && pushToTalkState === "idle" && !interruptInProgress;
1397
- }, [(_b = copilotContext.langGraphInterruptAction) == null ? void 0 : _b.event, isInProgress, text, pushToTalkState]);
1398
- const canStop = (0, import_react9.useMemo)(() => {
1399
- return isInProgress && !hideStopButton;
1400
- }, [isInProgress, hideStopButton]);
1401
- const sendDisabled = !canSend && !canStop;
1402
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: `copilotKitInputContainer ${showPoweredBy ? "poweredByContainer" : ""}`, children: [
1403
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "copilotKitInput", onClick: handleDivClick, children: [
1404
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
1405
- Textarea_default,
1406
- {
1407
- ref: textareaRef,
1408
- placeholder: context.labels.placeholder,
1409
- autoFocus: false,
1410
- maxRows: MAX_NEWLINES,
1411
- value: text,
1412
- onChange: (event) => setText(event.target.value),
1413
- onCompositionStart: () => setIsComposing(true),
1414
- onCompositionEnd: () => setIsComposing(false),
1415
- onKeyDown: (event) => {
1416
- if (event.key === "Enter" && !event.shiftKey && !isComposing) {
1417
- event.preventDefault();
1418
- if (canSend) {
1419
- send();
1420
- }
1421
- }
1422
- }
1423
- }
1424
- ),
1425
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "copilotKitInputControls", children: [
1426
- onUpload && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("button", { onClick: onUpload, className: "copilotKitInputControlButton", children: context.icons.uploadIcon }),
1427
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { style: { flexGrow: 1 } }),
1428
- showPushToTalk && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
1429
- "button",
1430
- {
1431
- onClick: () => setPushToTalkState(pushToTalkState === "idle" ? "recording" : "transcribing"),
1432
- className: pushToTalkState === "recording" ? "copilotKitInputControlButton copilotKitPushToTalkRecording" : "copilotKitInputControlButton",
1433
- children: context.icons.pushToTalkIcon
1434
- }
1435
- ),
1436
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
1437
- "button",
1438
- {
1439
- disabled: sendDisabled,
1440
- onClick: isInProgress && !hideStopButton ? onStop : send,
1441
- "data-copilotkit-in-progress": inProgress,
1442
- "data-test-id": inProgress ? "copilot-chat-request-in-progress" : "copilot-chat-ready",
1443
- className: "copilotKitInputControlButton",
1444
- children: buttonIcon
1445
- }
1446
- )
1447
- ] })
1448
- ] }),
1449
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(PoweredByTag, { showPoweredBy })
1450
- ] });
1451
- };
1452
-
1453
- // src/components/chat/messages/UserMessage.tsx
1454
- var import_jsx_runtime14 = require("react/jsx-runtime");
1455
- var UserMessage = (props) => {
1456
- const { message, ImageRenderer: ImageRenderer2 } = props;
1457
- const isImageMessage = message && "image" in message && message.image;
1458
- if (isImageMessage) {
1459
- const imageMessage = message;
1460
- return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "copilotKitMessage copilotKitUserMessage", children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(ImageRenderer2, { image: imageMessage.image, content: imageMessage.content }) });
1461
- }
1462
- return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "copilotKitMessage copilotKitUserMessage", children: message == null ? void 0 : message.content });
1463
- };
1464
-
1465
- // src/components/chat/Markdown.tsx
1466
- var import_react11 = require("react");
1467
- var import_react_markdown = __toESM(require("react-markdown"));
1468
-
1469
- // src/components/chat/CodeBlock.tsx
1470
- var import_react10 = require("react");
1471
- var import_react_syntax_highlighter = require("react-syntax-highlighter");
1472
-
1473
- // src/hooks/use-copy-to-clipboard.tsx
1474
- var React7 = __toESM(require("react"));
1475
- function useCopyToClipboard({ timeout = 2e3 }) {
1476
- const [isCopied, setIsCopied] = React7.useState(false);
1477
- const copyToClipboard = (value) => {
1478
- var _a;
1479
- if (typeof window === "undefined" || !((_a = navigator.clipboard) == null ? void 0 : _a.writeText)) {
1480
- return;
1481
- }
1482
- if (!value) {
1483
- return;
1484
- }
1485
- navigator.clipboard.writeText(value).then(() => {
1486
- setIsCopied(true);
1487
- setTimeout(() => {
1488
- setIsCopied(false);
1489
- }, timeout);
1490
- });
1491
- };
1492
- return { isCopied, copyToClipboard };
1493
- }
1494
-
1495
- // src/components/chat/CodeBlock.tsx
1496
- var import_jsx_runtime15 = require("react/jsx-runtime");
1497
- var programmingLanguages = {
1498
- javascript: ".js",
1499
- python: ".py",
1500
- java: ".java",
1501
- c: ".c",
1502
- cpp: ".cpp",
1503
- "c++": ".cpp",
1504
- "c#": ".cs",
1505
- ruby: ".rb",
1506
- php: ".php",
1507
- swift: ".swift",
1508
- "objective-c": ".m",
1509
- kotlin: ".kt",
1510
- typescript: ".ts",
1511
- go: ".go",
1512
- perl: ".pl",
1513
- rust: ".rs",
1514
- scala: ".scala",
1515
- haskell: ".hs",
1516
- lua: ".lua",
1517
- shell: ".sh",
1518
- sql: ".sql",
1519
- html: ".html",
1520
- css: ".css"
1521
- // add more file extensions here, make sure the key is same as language prop in CodeBlock.tsx component
1522
- };
1523
- var generateRandomString = (length, lowercase = false) => {
1524
- const chars = "ABCDEFGHJKLMNPQRSTUVWXY3456789";
1525
- let result = "";
1526
- for (let i = 0; i < length; i++) {
1527
- result += chars.charAt(Math.floor(Math.random() * chars.length));
1528
- }
1529
- return lowercase ? result.toLowerCase() : result;
1530
- };
1531
- var CodeBlock = (0, import_react10.memo)(({ language, value }) => {
1532
- const { isCopied, copyToClipboard } = useCopyToClipboard({ timeout: 2e3 });
1533
- const downloadAsFile = () => {
1534
- if (typeof window === "undefined") {
1535
- return;
1536
- }
1537
- const fileExtension = programmingLanguages[language] || ".file";
1538
- const suggestedFileName = `file-${generateRandomString(3, true)}${fileExtension}`;
1539
- const fileName = window.prompt("Enter file name", suggestedFileName);
1540
- if (!fileName) {
1541
- return;
1542
- }
1543
- const blob = new Blob([value], { type: "text/plain" });
1544
- const url = URL.createObjectURL(blob);
1545
- const link = document.createElement("a");
1546
- link.download = fileName;
1547
- link.href = url;
1548
- link.style.display = "none";
1549
- document.body.appendChild(link);
1550
- link.click();
1551
- document.body.removeChild(link);
1552
- URL.revokeObjectURL(url);
1553
- };
1554
- const onCopy = () => {
1555
- if (isCopied)
1556
- return;
1557
- copyToClipboard(value);
1558
- };
1559
- return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "copilotKitCodeBlock", children: [
1560
- /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "copilotKitCodeBlockToolbar", children: [
1561
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: "copilotKitCodeBlockToolbarLanguage", children: language }),
1562
- /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "copilotKitCodeBlockToolbarButtons", children: [
1563
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("button", { className: "copilotKitCodeBlockToolbarButton", onClick: downloadAsFile, children: DownloadIcon }),
1564
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("button", { className: "copilotKitCodeBlockToolbarButton", onClick: onCopy, children: isCopied ? CheckIcon : CopyIcon })
1565
- ] })
1566
- ] }),
1567
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
1568
- import_react_syntax_highlighter.Prism,
1569
- {
1570
- language,
1571
- style: highlightStyle,
1572
- PreTag: "div",
1573
- customStyle: {
1574
- margin: 0,
1575
- borderBottomLeftRadius: "0.375rem",
1576
- borderBottomRightRadius: "0.375rem"
1577
- },
1578
- children: value
1579
- }
1580
- )
1156
+ )
1581
1157
  ] });
1582
1158
  });
1583
1159
  CodeBlock.displayName = "CodeBlock";
@@ -1863,315 +1439,895 @@ var highlightStyle = {
1863
1439
  zIndex: "0"
1864
1440
  }
1865
1441
  };
1866
-
1867
- // src/components/chat/Markdown.tsx
1868
- var import_remark_gfm = __toESM(require("remark-gfm"));
1869
- var import_remark_math = __toESM(require("remark-math"));
1870
- var import_rehype_raw = __toESM(require("rehype-raw"));
1871
- var import_jsx_runtime16 = require("react/jsx-runtime");
1872
- var defaultComponents = {
1873
- a(_a) {
1874
- var _b = _a, { children } = _b, props = __objRest(_b, ["children"]);
1875
- return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("a", __spreadProps(__spreadValues({ className: "copilotKitMarkdownElement" }, props), { target: "_blank", rel: "noopener noreferrer", children }));
1876
- },
1877
- // @ts-expect-error -- inline
1878
- code(_c) {
1879
- var _d = _c, { children, className, inline } = _d, props = __objRest(_d, ["children", "className", "inline"]);
1880
- if (Array.isArray(children) && children.length) {
1881
- if (children[0] == "\u258D") {
1882
- return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
1883
- "span",
1884
- {
1885
- style: {
1886
- animation: "pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite",
1887
- marginTop: "0.25rem"
1888
- },
1889
- children: "\u258D"
1890
- }
1442
+
1443
+ // src/components/chat/Markdown.tsx
1444
+ var import_remark_gfm = __toESM(require("remark-gfm"));
1445
+ var import_remark_math = __toESM(require("remark-math"));
1446
+ var import_rehype_raw = __toESM(require("rehype-raw"));
1447
+ var import_jsx_runtime12 = require("react/jsx-runtime");
1448
+ var defaultComponents = {
1449
+ a(_a) {
1450
+ var _b = _a, { children } = _b, props = __objRest(_b, ["children"]);
1451
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("a", __spreadProps(__spreadValues({ className: "copilotKitMarkdownElement" }, props), { target: "_blank", rel: "noopener noreferrer", children }));
1452
+ },
1453
+ // @ts-expect-error -- inline
1454
+ code(_c) {
1455
+ var _d = _c, { children, className, inline } = _d, props = __objRest(_d, ["children", "className", "inline"]);
1456
+ if (Array.isArray(children) && children.length) {
1457
+ if (children[0] == "\u258D") {
1458
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
1459
+ "span",
1460
+ {
1461
+ style: {
1462
+ animation: "pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite",
1463
+ marginTop: "0.25rem"
1464
+ },
1465
+ children: "\u258D"
1466
+ }
1467
+ );
1468
+ }
1469
+ children[0] = (children == null ? void 0 : children[0]).replace("`\u258D`", "\u258D");
1470
+ }
1471
+ const match = /language-(\w+)/.exec(className || "");
1472
+ const hasLanguage = match && match[1];
1473
+ const content = String(children);
1474
+ const hasNewlines = content.includes("\n");
1475
+ const isInline = !hasLanguage && !hasNewlines;
1476
+ if (isInline) {
1477
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
1478
+ "code",
1479
+ __spreadProps(__spreadValues({
1480
+ className: `copilotKitMarkdownElement copilotKitInlineCode ${className || ""}`
1481
+ }, props), {
1482
+ children
1483
+ })
1484
+ );
1485
+ }
1486
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
1487
+ CodeBlock,
1488
+ __spreadValues({
1489
+ language: match && match[1] || "",
1490
+ value: String(children).replace(/\n$/, "")
1491
+ }, props),
1492
+ Math.random()
1493
+ );
1494
+ },
1495
+ h1: (_e) => {
1496
+ var _f = _e, { children } = _f, props = __objRest(_f, ["children"]);
1497
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("h1", __spreadProps(__spreadValues({ className: "copilotKitMarkdownElement" }, props), { children }));
1498
+ },
1499
+ h2: (_g) => {
1500
+ var _h = _g, { children } = _h, props = __objRest(_h, ["children"]);
1501
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("h2", __spreadProps(__spreadValues({ className: "copilotKitMarkdownElement" }, props), { children }));
1502
+ },
1503
+ h3: (_i) => {
1504
+ var _j = _i, { children } = _j, props = __objRest(_j, ["children"]);
1505
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("h3", __spreadProps(__spreadValues({ className: "copilotKitMarkdownElement" }, props), { children }));
1506
+ },
1507
+ h4: (_k) => {
1508
+ var _l = _k, { children } = _l, props = __objRest(_l, ["children"]);
1509
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("h4", __spreadProps(__spreadValues({ className: "copilotKitMarkdownElement" }, props), { children }));
1510
+ },
1511
+ h5: (_m) => {
1512
+ var _n = _m, { children } = _n, props = __objRest(_n, ["children"]);
1513
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("h5", __spreadProps(__spreadValues({ className: "copilotKitMarkdownElement" }, props), { children }));
1514
+ },
1515
+ h6: (_o) => {
1516
+ var _p = _o, { children } = _p, props = __objRest(_p, ["children"]);
1517
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("h6", __spreadProps(__spreadValues({ className: "copilotKitMarkdownElement" }, props), { children }));
1518
+ },
1519
+ p: (_q) => {
1520
+ var _r = _q, { children } = _r, props = __objRest(_r, ["children"]);
1521
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("p", __spreadProps(__spreadValues({ className: "copilotKitMarkdownElement" }, props), { children }));
1522
+ },
1523
+ pre: (_s) => {
1524
+ var _t = _s, { children } = _t, props = __objRest(_t, ["children"]);
1525
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("pre", __spreadProps(__spreadValues({ className: "copilotKitMarkdownElement" }, props), { children }));
1526
+ },
1527
+ blockquote: (_u) => {
1528
+ var _v = _u, { children } = _v, props = __objRest(_v, ["children"]);
1529
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("blockquote", __spreadProps(__spreadValues({ className: "copilotKitMarkdownElement" }, props), { children }));
1530
+ },
1531
+ ul: (_w) => {
1532
+ var _x = _w, { children } = _x, props = __objRest(_x, ["children"]);
1533
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("ul", __spreadProps(__spreadValues({ className: "copilotKitMarkdownElement" }, props), { children }));
1534
+ },
1535
+ li: (_y) => {
1536
+ var _z = _y, { children } = _z, props = __objRest(_z, ["children"]);
1537
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("li", __spreadProps(__spreadValues({ className: "copilotKitMarkdownElement" }, props), { children }));
1538
+ }
1539
+ };
1540
+ var MemoizedReactMarkdown = (0, import_react7.memo)(
1541
+ import_react_markdown.default,
1542
+ (prevProps, nextProps) => prevProps.children === nextProps.children && prevProps.components === nextProps.components
1543
+ );
1544
+ var Markdown = ({ content, components }) => {
1545
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "copilotKitMarkdown", children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
1546
+ MemoizedReactMarkdown,
1547
+ {
1548
+ components: __spreadValues(__spreadValues({}, defaultComponents), components),
1549
+ remarkPlugins: [import_remark_gfm.default, import_remark_math.default],
1550
+ rehypePlugins: [import_rehype_raw.default],
1551
+ children: content
1552
+ }
1553
+ ) });
1554
+ };
1555
+
1556
+ // src/components/chat/messages/AssistantMessage.tsx
1557
+ var import_react8 = require("react");
1558
+ var import_jsx_runtime13 = require("react/jsx-runtime");
1559
+ var AssistantMessage = (props) => {
1560
+ var _a;
1561
+ const { icons, labels } = useChatContext();
1562
+ const {
1563
+ message,
1564
+ isLoading,
1565
+ onRegenerate,
1566
+ onCopy,
1567
+ onThumbsUp,
1568
+ onThumbsDown,
1569
+ isCurrentMessage,
1570
+ markdownTagRenderers
1571
+ } = props;
1572
+ const [copied, setCopied] = (0, import_react8.useState)(false);
1573
+ const handleCopy = () => {
1574
+ const content2 = (message == null ? void 0 : message.content) || "";
1575
+ if (content2 && onCopy) {
1576
+ navigator.clipboard.writeText(content2);
1577
+ setCopied(true);
1578
+ onCopy(content2);
1579
+ setTimeout(() => setCopied(false), 2e3);
1580
+ } else if (content2) {
1581
+ navigator.clipboard.writeText(content2);
1582
+ setCopied(true);
1583
+ setTimeout(() => setCopied(false), 2e3);
1584
+ }
1585
+ };
1586
+ const handleRegenerate = () => {
1587
+ if (onRegenerate)
1588
+ onRegenerate();
1589
+ };
1590
+ const handleThumbsUp = () => {
1591
+ if (onThumbsUp && message)
1592
+ onThumbsUp(message);
1593
+ };
1594
+ const handleThumbsDown = () => {
1595
+ if (onThumbsDown && message)
1596
+ onThumbsDown(message);
1597
+ };
1598
+ const LoadingIcon = () => /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { children: icons.activityIcon });
1599
+ const content = (message == null ? void 0 : message.content) || "";
1600
+ const subComponent = (_a = message == null ? void 0 : message.generativeUI) == null ? void 0 : _a.call(message);
1601
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_jsx_runtime13.Fragment, { children: [
1602
+ content && /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "copilotKitMessage copilotKitAssistantMessage", children: [
1603
+ content && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Markdown, { content, components: markdownTagRenderers }),
1604
+ content && !isLoading && /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
1605
+ "div",
1606
+ {
1607
+ className: `copilotKitMessageControls ${isCurrentMessage ? "currentMessage" : ""}`,
1608
+ children: [
1609
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
1610
+ "button",
1611
+ {
1612
+ className: "copilotKitMessageControlButton",
1613
+ onClick: handleRegenerate,
1614
+ "aria-label": labels.regenerateResponse,
1615
+ title: labels.regenerateResponse,
1616
+ children: icons.regenerateIcon
1617
+ }
1618
+ ),
1619
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
1620
+ "button",
1621
+ {
1622
+ className: "copilotKitMessageControlButton",
1623
+ onClick: handleCopy,
1624
+ "aria-label": labels.copyToClipboard,
1625
+ title: labels.copyToClipboard,
1626
+ children: copied ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { style: { fontSize: "10px", fontWeight: "bold" }, children: "\u2713" }) : icons.copyIcon
1627
+ }
1628
+ ),
1629
+ onThumbsUp && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
1630
+ "button",
1631
+ {
1632
+ className: "copilotKitMessageControlButton",
1633
+ onClick: handleThumbsUp,
1634
+ "aria-label": labels.thumbsUp,
1635
+ title: labels.thumbsUp,
1636
+ children: icons.thumbsUpIcon
1637
+ }
1638
+ ),
1639
+ onThumbsDown && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
1640
+ "button",
1641
+ {
1642
+ className: "copilotKitMessageControlButton",
1643
+ onClick: handleThumbsDown,
1644
+ "aria-label": labels.thumbsDown,
1645
+ title: labels.thumbsDown,
1646
+ children: icons.thumbsDownIcon
1647
+ }
1648
+ )
1649
+ ]
1650
+ }
1651
+ )
1652
+ ] }),
1653
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { style: { marginBottom: "0.5rem" }, children: subComponent }),
1654
+ isLoading && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(LoadingIcon, {})
1655
+ ] });
1656
+ };
1657
+
1658
+ // src/components/chat/messages/ImageRenderer.tsx
1659
+ var import_react9 = require("react");
1660
+ var import_jsx_runtime14 = require("react/jsx-runtime");
1661
+ var ImageRenderer = ({ image, content, className = "" }) => {
1662
+ const [imageError, setImageError] = (0, import_react9.useState)(false);
1663
+ const imageSrc = `data:image/${image.format};base64,${image.bytes}`;
1664
+ const altText = content || "User uploaded image";
1665
+ const handleImageError = () => {
1666
+ setImageError(true);
1667
+ };
1668
+ if (imageError) {
1669
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: `copilotKitImageRendering copilotKitImageRenderingError ${className}`, children: [
1670
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "copilotKitImageRenderingErrorMessage", children: "Failed to load image" }),
1671
+ content && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "copilotKitImageRenderingContent", children: content })
1672
+ ] });
1673
+ }
1674
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: `copilotKitImageRendering ${className}`, children: [
1675
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
1676
+ "img",
1677
+ {
1678
+ src: imageSrc,
1679
+ alt: altText,
1680
+ className: "copilotKitImageRenderingImage",
1681
+ onError: handleImageError
1682
+ }
1683
+ ),
1684
+ content && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "copilotKitImageRenderingContent", children: content })
1685
+ ] });
1686
+ };
1687
+
1688
+ // src/components/chat/messages/RenderMessage.tsx
1689
+ var import_jsx_runtime15 = require("react/jsx-runtime");
1690
+ function RenderMessage(_a) {
1691
+ var _b = _a, {
1692
+ UserMessage: UserMessage2 = UserMessage,
1693
+ AssistantMessage: AssistantMessage2 = AssistantMessage,
1694
+ ImageRenderer: ImageRenderer2 = ImageRenderer
1695
+ } = _b, props = __objRest(_b, [
1696
+ "UserMessage",
1697
+ "AssistantMessage",
1698
+ "ImageRenderer"
1699
+ ]);
1700
+ var _a2;
1701
+ const {
1702
+ message,
1703
+ inProgress,
1704
+ index,
1705
+ isCurrentMessage,
1706
+ onRegenerate,
1707
+ onCopy,
1708
+ onThumbsUp,
1709
+ onThumbsDown,
1710
+ markdownTagRenderers
1711
+ } = props;
1712
+ switch (message.role) {
1713
+ case "user":
1714
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
1715
+ UserMessage2,
1716
+ {
1717
+ rawData: message,
1718
+ "data-message-role": "user",
1719
+ message,
1720
+ ImageRenderer: ImageRenderer2
1721
+ },
1722
+ index
1723
+ );
1724
+ case "assistant":
1725
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
1726
+ AssistantMessage2,
1727
+ {
1728
+ "data-message-role": "assistant",
1729
+ subComponent: (_a2 = message.generativeUI) == null ? void 0 : _a2.call(message),
1730
+ rawData: message,
1731
+ message,
1732
+ isLoading: inProgress && isCurrentMessage && !message.content,
1733
+ isGenerating: inProgress && isCurrentMessage && !!message.content,
1734
+ isCurrentMessage,
1735
+ onRegenerate: () => onRegenerate == null ? void 0 : onRegenerate(message.id),
1736
+ onCopy,
1737
+ onThumbsUp,
1738
+ onThumbsDown,
1739
+ markdownTagRenderers,
1740
+ ImageRenderer: ImageRenderer2
1741
+ },
1742
+ index
1743
+ );
1744
+ }
1745
+ }
1746
+
1747
+ // src/components/chat/messages/LegacyRenderMessage.tsx
1748
+ var import_runtime_client_gql = require("@copilotkit/runtime-client-gql");
1749
+ var import_jsx_runtime16 = require("react/jsx-runtime");
1750
+ var LegacyRenderMessage = ({
1751
+ message,
1752
+ inProgress,
1753
+ index,
1754
+ isCurrentMessage,
1755
+ actionResult,
1756
+ AssistantMessage: AssistantMessage2,
1757
+ UserMessage: UserMessage2,
1758
+ ImageRenderer: ImageRenderer2,
1759
+ onRegenerate,
1760
+ onCopy,
1761
+ onThumbsUp,
1762
+ onThumbsDown,
1763
+ markdownTagRenderers,
1764
+ legacyProps
1765
+ }) => {
1766
+ var _a;
1767
+ const {
1768
+ RenderTextMessage,
1769
+ RenderActionExecutionMessage,
1770
+ RenderAgentStateMessage,
1771
+ RenderResultMessage,
1772
+ RenderImageMessage
1773
+ } = legacyProps;
1774
+ const deprecatedMessage = (_a = (0, import_runtime_client_gql.aguiToGQL)(message)[0]) != null ? _a : void 0;
1775
+ if (deprecatedMessage.isTextMessage() && RenderTextMessage) {
1776
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
1777
+ RenderTextMessage,
1778
+ {
1779
+ message,
1780
+ inProgress,
1781
+ index,
1782
+ isCurrentMessage,
1783
+ AssistantMessage: AssistantMessage2,
1784
+ UserMessage: UserMessage2,
1785
+ onRegenerate,
1786
+ onCopy,
1787
+ onThumbsUp,
1788
+ onThumbsDown,
1789
+ markdownTagRenderers
1790
+ }
1791
+ );
1792
+ }
1793
+ if (deprecatedMessage.isActionExecutionMessage() && RenderActionExecutionMessage) {
1794
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
1795
+ RenderActionExecutionMessage,
1796
+ {
1797
+ message,
1798
+ inProgress,
1799
+ index,
1800
+ isCurrentMessage,
1801
+ actionResult,
1802
+ AssistantMessage: AssistantMessage2,
1803
+ UserMessage: UserMessage2
1804
+ }
1805
+ );
1806
+ }
1807
+ if (deprecatedMessage.isAgentStateMessage() && RenderAgentStateMessage) {
1808
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
1809
+ RenderAgentStateMessage,
1810
+ {
1811
+ message,
1812
+ inProgress,
1813
+ index,
1814
+ isCurrentMessage,
1815
+ AssistantMessage: AssistantMessage2,
1816
+ UserMessage: UserMessage2
1817
+ }
1818
+ );
1819
+ }
1820
+ if (deprecatedMessage.isResultMessage() && RenderResultMessage) {
1821
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
1822
+ RenderResultMessage,
1823
+ {
1824
+ message,
1825
+ inProgress,
1826
+ index,
1827
+ isCurrentMessage,
1828
+ AssistantMessage: AssistantMessage2,
1829
+ UserMessage: UserMessage2
1830
+ }
1831
+ );
1832
+ }
1833
+ if (deprecatedMessage.isImageMessage() && RenderImageMessage) {
1834
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
1835
+ RenderImageMessage,
1836
+ {
1837
+ message,
1838
+ inProgress,
1839
+ index,
1840
+ isCurrentMessage,
1841
+ AssistantMessage: AssistantMessage2,
1842
+ UserMessage: UserMessage2
1843
+ }
1844
+ );
1845
+ }
1846
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
1847
+ RenderMessage,
1848
+ {
1849
+ message,
1850
+ inProgress,
1851
+ index,
1852
+ isCurrentMessage,
1853
+ AssistantMessage: AssistantMessage2,
1854
+ UserMessage: UserMessage2,
1855
+ ImageRenderer: ImageRenderer2,
1856
+ onRegenerate,
1857
+ onCopy,
1858
+ onThumbsUp,
1859
+ onThumbsDown,
1860
+ markdownTagRenderers
1861
+ }
1862
+ );
1863
+ };
1864
+
1865
+ // src/components/chat/Messages.tsx
1866
+ var import_jsx_runtime17 = require("react/jsx-runtime");
1867
+ var Messages = ({
1868
+ inProgress,
1869
+ children,
1870
+ RenderMessage: RenderMessage2,
1871
+ AssistantMessage: AssistantMessage2,
1872
+ UserMessage: UserMessage2,
1873
+ ImageRenderer: ImageRenderer2,
1874
+ onRegenerate,
1875
+ onCopy,
1876
+ onThumbsUp,
1877
+ onThumbsDown,
1878
+ markdownTagRenderers,
1879
+ // Legacy props
1880
+ RenderTextMessage,
1881
+ RenderActionExecutionMessage,
1882
+ RenderAgentStateMessage,
1883
+ RenderResultMessage,
1884
+ RenderImageMessage
1885
+ }) => {
1886
+ const { labels } = useChatContext();
1887
+ const { messages: visibleMessages, interrupt } = (0, import_react_core5.useCopilotChatInternal)();
1888
+ const initialMessages = (0, import_react10.useMemo)(() => makeInitialMessages(labels.initial), [labels.initial]);
1889
+ const messages = [...initialMessages, ...visibleMessages];
1890
+ const { messagesContainerRef, messagesEndRef } = useScrollToBottom(messages);
1891
+ const hasLegacyProps = !!(RenderTextMessage || RenderActionExecutionMessage || RenderAgentStateMessage || RenderResultMessage || RenderImageMessage);
1892
+ (0, import_react10.useEffect)(() => {
1893
+ if (hasLegacyProps) {
1894
+ console.warn(
1895
+ "[CopilotKit] Legacy message render props (RenderTextMessage, RenderActionExecutionMessage, etc.) are deprecated. Please use the unified 'RenderMessage' prop instead. See migration guide: https://docs.copilotkit.ai/migration/render-message"
1896
+ );
1897
+ }
1898
+ }, [hasLegacyProps]);
1899
+ const legacyProps = (0, import_react10.useMemo)(
1900
+ () => ({
1901
+ RenderTextMessage,
1902
+ RenderActionExecutionMessage,
1903
+ RenderAgentStateMessage,
1904
+ RenderResultMessage,
1905
+ RenderImageMessage
1906
+ }),
1907
+ [
1908
+ RenderTextMessage,
1909
+ RenderActionExecutionMessage,
1910
+ RenderAgentStateMessage,
1911
+ RenderResultMessage,
1912
+ RenderImageMessage
1913
+ ]
1914
+ );
1915
+ const MessageRenderer = hasLegacyProps ? (props) => /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(LegacyRenderMessage, __spreadProps(__spreadValues({}, props), { legacyProps })) : RenderMessage2;
1916
+ return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "copilotKitMessages", ref: messagesContainerRef, children: [
1917
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "copilotKitMessagesContainer", children: [
1918
+ messages.map((message, index) => {
1919
+ const isCurrentMessage = index === messages.length - 1;
1920
+ return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
1921
+ MessageRenderer,
1922
+ {
1923
+ message,
1924
+ inProgress,
1925
+ index,
1926
+ isCurrentMessage,
1927
+ AssistantMessage: AssistantMessage2,
1928
+ UserMessage: UserMessage2,
1929
+ ImageRenderer: ImageRenderer2,
1930
+ onRegenerate,
1931
+ onCopy,
1932
+ onThumbsUp,
1933
+ onThumbsDown,
1934
+ markdownTagRenderers
1935
+ },
1936
+ index
1937
+ );
1938
+ }),
1939
+ interrupt
1940
+ ] }),
1941
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("footer", { className: "copilotKitMessagesFooter", ref: messagesEndRef, children })
1942
+ ] });
1943
+ };
1944
+ function makeInitialMessages(initial) {
1945
+ if (!initial)
1946
+ return [];
1947
+ if (Array.isArray(initial)) {
1948
+ return initial.map((message) => {
1949
+ return {
1950
+ id: message,
1951
+ role: "assistant",
1952
+ content: message
1953
+ };
1954
+ });
1955
+ }
1956
+ return [
1957
+ {
1958
+ id: initial,
1959
+ role: "assistant",
1960
+ content: initial
1961
+ }
1962
+ ];
1963
+ }
1964
+ function useScrollToBottom(messages) {
1965
+ const messagesEndRef = (0, import_react10.useRef)(null);
1966
+ const messagesContainerRef = (0, import_react10.useRef)(null);
1967
+ const isProgrammaticScrollRef = (0, import_react10.useRef)(false);
1968
+ const isUserScrollUpRef = (0, import_react10.useRef)(false);
1969
+ const scrollToBottom = () => {
1970
+ if (messagesContainerRef.current && messagesEndRef.current) {
1971
+ isProgrammaticScrollRef.current = true;
1972
+ messagesContainerRef.current.scrollTop = messagesContainerRef.current.scrollHeight;
1973
+ }
1974
+ };
1975
+ const handleScroll = () => {
1976
+ if (isProgrammaticScrollRef.current) {
1977
+ isProgrammaticScrollRef.current = false;
1978
+ return;
1979
+ }
1980
+ if (messagesContainerRef.current) {
1981
+ const { scrollTop, scrollHeight, clientHeight } = messagesContainerRef.current;
1982
+ isUserScrollUpRef.current = scrollTop + clientHeight < scrollHeight;
1983
+ }
1984
+ };
1985
+ (0, import_react10.useEffect)(() => {
1986
+ const container = messagesContainerRef.current;
1987
+ if (container) {
1988
+ container.addEventListener("scroll", handleScroll);
1989
+ }
1990
+ return () => {
1991
+ if (container) {
1992
+ container.removeEventListener("scroll", handleScroll);
1993
+ }
1994
+ };
1995
+ }, []);
1996
+ (0, import_react10.useEffect)(() => {
1997
+ const container = messagesContainerRef.current;
1998
+ if (!container) {
1999
+ return;
2000
+ }
2001
+ const mutationObserver = new MutationObserver(() => {
2002
+ if (!isUserScrollUpRef.current) {
2003
+ scrollToBottom();
2004
+ }
2005
+ });
2006
+ mutationObserver.observe(container, {
2007
+ childList: true,
2008
+ subtree: true,
2009
+ characterData: true
2010
+ });
2011
+ return () => {
2012
+ mutationObserver.disconnect();
2013
+ };
2014
+ }, []);
2015
+ (0, import_react10.useEffect)(() => {
2016
+ isUserScrollUpRef.current = false;
2017
+ scrollToBottom();
2018
+ }, [messages.filter((m) => m.role === "user").length]);
2019
+ return { messagesEndRef, messagesContainerRef };
2020
+ }
2021
+
2022
+ // src/components/chat/Input.tsx
2023
+ var import_react13 = require("react");
2024
+
2025
+ // src/components/chat/Textarea.tsx
2026
+ var import_react11 = require("react");
2027
+ var import_jsx_runtime18 = require("react/jsx-runtime");
2028
+ var AutoResizingTextarea = (0, import_react11.forwardRef)(
2029
+ ({
2030
+ maxRows = 1,
2031
+ placeholder,
2032
+ value,
2033
+ onChange,
2034
+ onKeyDown,
2035
+ onCompositionStart,
2036
+ onCompositionEnd,
2037
+ autoFocus
2038
+ }, ref) => {
2039
+ const internalTextareaRef = (0, import_react11.useRef)(null);
2040
+ const [maxHeight, setMaxHeight] = (0, import_react11.useState)(0);
2041
+ (0, import_react11.useImperativeHandle)(ref, () => internalTextareaRef.current);
2042
+ (0, import_react11.useEffect)(() => {
2043
+ const calculateMaxHeight = () => {
2044
+ const textarea = internalTextareaRef.current;
2045
+ if (textarea) {
2046
+ textarea.style.height = "auto";
2047
+ const singleRowHeight = textarea.scrollHeight;
2048
+ setMaxHeight(singleRowHeight * maxRows);
2049
+ if (autoFocus) {
2050
+ textarea.focus();
2051
+ }
2052
+ }
2053
+ };
2054
+ calculateMaxHeight();
2055
+ }, [maxRows]);
2056
+ (0, import_react11.useEffect)(() => {
2057
+ const textarea = internalTextareaRef.current;
2058
+ if (textarea) {
2059
+ textarea.style.height = "auto";
2060
+ textarea.style.height = `${Math.min(textarea.scrollHeight, maxHeight)}px`;
2061
+ }
2062
+ }, [value, maxHeight]);
2063
+ return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
2064
+ "textarea",
2065
+ {
2066
+ ref: internalTextareaRef,
2067
+ value,
2068
+ onChange,
2069
+ onKeyDown,
2070
+ onCompositionStart,
2071
+ onCompositionEnd,
2072
+ placeholder,
2073
+ style: {
2074
+ overflow: "auto",
2075
+ resize: "none",
2076
+ maxHeight: `${maxHeight}px`
2077
+ },
2078
+ rows: 1
2079
+ }
2080
+ );
2081
+ }
2082
+ );
2083
+ var Textarea_default = AutoResizingTextarea;
2084
+
2085
+ // src/hooks/use-push-to-talk.tsx
2086
+ var import_react_core6 = require("@copilotkit/react-core");
2087
+ var import_runtime_client_gql2 = require("@copilotkit/runtime-client-gql");
2088
+ var import_react12 = require("react");
2089
+ var startRecording = (mediaStreamRef, mediaRecorderRef, audioContextRef, recordedChunks, onStop) => __async(void 0, null, function* () {
2090
+ if (!mediaStreamRef.current || !audioContextRef.current) {
2091
+ mediaStreamRef.current = yield navigator.mediaDevices.getUserMedia({ audio: true });
2092
+ audioContextRef.current = new window.AudioContext();
2093
+ yield audioContextRef.current.resume();
2094
+ }
2095
+ mediaRecorderRef.current = new MediaRecorder(mediaStreamRef.current);
2096
+ mediaRecorderRef.current.start(1e3);
2097
+ mediaRecorderRef.current.ondataavailable = (event) => {
2098
+ recordedChunks.push(event.data);
2099
+ };
2100
+ mediaRecorderRef.current.onstop = onStop;
2101
+ });
2102
+ var stopRecording = (mediaRecorderRef) => {
2103
+ if (mediaRecorderRef.current && mediaRecorderRef.current.state !== "inactive") {
2104
+ mediaRecorderRef.current.stop();
2105
+ }
2106
+ };
2107
+ var transcribeAudio = (recordedChunks, transcribeAudioUrl) => __async(void 0, null, function* () {
2108
+ const completeBlob = new Blob(recordedChunks, { type: "audio/mp4" });
2109
+ const formData = new FormData();
2110
+ formData.append("file", completeBlob, "recording.mp4");
2111
+ const response = yield fetch(transcribeAudioUrl, {
2112
+ method: "POST",
2113
+ body: formData
2114
+ });
2115
+ if (!response.ok) {
2116
+ throw new Error(`Error: ${response.statusText}`);
2117
+ }
2118
+ const transcription = yield response.json();
2119
+ return transcription.text;
2120
+ });
2121
+ var playAudioResponse = (text, textToSpeechUrl, audioContext) => {
2122
+ const encodedText = encodeURIComponent(text);
2123
+ const url = `${textToSpeechUrl}?text=${encodedText}`;
2124
+ fetch(url).then((response) => response.arrayBuffer()).then((arrayBuffer) => audioContext.decodeAudioData(arrayBuffer)).then((audioBuffer) => {
2125
+ const source = audioContext.createBufferSource();
2126
+ source.buffer = audioBuffer;
2127
+ source.connect(audioContext.destination);
2128
+ source.start(0);
2129
+ }).catch((error) => {
2130
+ console.error("Error with decoding audio data", error);
2131
+ });
2132
+ };
2133
+ var usePushToTalk = ({
2134
+ sendFunction,
2135
+ inProgress
2136
+ }) => {
2137
+ const [pushToTalkState, setPushToTalkState] = (0, import_react12.useState)("idle");
2138
+ const mediaStreamRef = (0, import_react12.useRef)(null);
2139
+ const audioContextRef = (0, import_react12.useRef)(null);
2140
+ const mediaRecorderRef = (0, import_react12.useRef)(null);
2141
+ const recordedChunks = (0, import_react12.useRef)([]);
2142
+ const generalContext = (0, import_react_core6.useCopilotContext)();
2143
+ const messagesContext = (0, import_react_core6.useCopilotMessagesContext)();
2144
+ const context = __spreadValues(__spreadValues({}, generalContext), messagesContext);
2145
+ const [startReadingFromMessageId, setStartReadingFromMessageId] = (0, import_react12.useState)(null);
2146
+ (0, import_react12.useEffect)(() => {
2147
+ if (pushToTalkState === "recording") {
2148
+ startRecording(
2149
+ mediaStreamRef,
2150
+ mediaRecorderRef,
2151
+ audioContextRef,
2152
+ recordedChunks.current,
2153
+ () => {
2154
+ setPushToTalkState("transcribing");
2155
+ }
2156
+ );
2157
+ } else {
2158
+ stopRecording(mediaRecorderRef);
2159
+ if (pushToTalkState === "transcribing") {
2160
+ transcribeAudio(recordedChunks.current, context.copilotApiConfig.transcribeAudioUrl).then(
2161
+ (transcription) => __async(void 0, null, function* () {
2162
+ recordedChunks.current = [];
2163
+ setPushToTalkState("idle");
2164
+ const message = yield sendFunction(transcription);
2165
+ setStartReadingFromMessageId(message.id);
2166
+ })
1891
2167
  );
1892
2168
  }
1893
- children[0] = (children == null ? void 0 : children[0]).replace("`\u258D`", "\u258D");
1894
2169
  }
1895
- const match = /language-(\w+)/.exec(className || "");
1896
- const hasLanguage = match && match[1];
1897
- const content = String(children);
1898
- const hasNewlines = content.includes("\n");
1899
- const isInline = !hasLanguage && !hasNewlines;
1900
- if (isInline) {
1901
- return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
1902
- "code",
1903
- __spreadProps(__spreadValues({
1904
- className: `copilotKitMarkdownElement copilotKitInlineCode ${className || ""}`
1905
- }, props), {
1906
- children
1907
- })
2170
+ return () => {
2171
+ stopRecording(mediaRecorderRef);
2172
+ };
2173
+ }, [pushToTalkState]);
2174
+ (0, import_react12.useEffect)(() => {
2175
+ if (inProgress === false && startReadingFromMessageId) {
2176
+ const lastMessageIndex = context.messages.findIndex(
2177
+ (message) => message.id === startReadingFromMessageId
1908
2178
  );
2179
+ const aguiMessages = (0, import_runtime_client_gql2.gqlToAGUI)(context.messages);
2180
+ const messagesAfterLast = aguiMessages.slice(lastMessageIndex + 1).filter((message) => message.role === "assistant");
2181
+ const text = messagesAfterLast.map((message) => message.content).join("\n");
2182
+ playAudioResponse(text, context.copilotApiConfig.textToSpeechUrl, audioContextRef.current);
2183
+ setStartReadingFromMessageId(null);
1909
2184
  }
1910
- return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
1911
- CodeBlock,
1912
- __spreadValues({
1913
- language: match && match[1] || "",
1914
- value: String(children).replace(/\n$/, "")
1915
- }, props),
1916
- Math.random()
1917
- );
1918
- },
1919
- h1: (_e) => {
1920
- var _f = _e, { children } = _f, props = __objRest(_f, ["children"]);
1921
- return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("h1", __spreadProps(__spreadValues({ className: "copilotKitMarkdownElement" }, props), { children }));
1922
- },
1923
- h2: (_g) => {
1924
- var _h = _g, { children } = _h, props = __objRest(_h, ["children"]);
1925
- return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("h2", __spreadProps(__spreadValues({ className: "copilotKitMarkdownElement" }, props), { children }));
1926
- },
1927
- h3: (_i) => {
1928
- var _j = _i, { children } = _j, props = __objRest(_j, ["children"]);
1929
- return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("h3", __spreadProps(__spreadValues({ className: "copilotKitMarkdownElement" }, props), { children }));
1930
- },
1931
- h4: (_k) => {
1932
- var _l = _k, { children } = _l, props = __objRest(_l, ["children"]);
1933
- return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("h4", __spreadProps(__spreadValues({ className: "copilotKitMarkdownElement" }, props), { children }));
1934
- },
1935
- h5: (_m) => {
1936
- var _n = _m, { children } = _n, props = __objRest(_n, ["children"]);
1937
- return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("h5", __spreadProps(__spreadValues({ className: "copilotKitMarkdownElement" }, props), { children }));
1938
- },
1939
- h6: (_o) => {
1940
- var _p = _o, { children } = _p, props = __objRest(_p, ["children"]);
1941
- return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("h6", __spreadProps(__spreadValues({ className: "copilotKitMarkdownElement" }, props), { children }));
1942
- },
1943
- p: (_q) => {
1944
- var _r = _q, { children } = _r, props = __objRest(_r, ["children"]);
1945
- return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("p", __spreadProps(__spreadValues({ className: "copilotKitMarkdownElement" }, props), { children }));
1946
- },
1947
- pre: (_s) => {
1948
- var _t = _s, { children } = _t, props = __objRest(_t, ["children"]);
1949
- return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("pre", __spreadProps(__spreadValues({ className: "copilotKitMarkdownElement" }, props), { children }));
1950
- },
1951
- blockquote: (_u) => {
1952
- var _v = _u, { children } = _v, props = __objRest(_v, ["children"]);
1953
- return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("blockquote", __spreadProps(__spreadValues({ className: "copilotKitMarkdownElement" }, props), { children }));
1954
- },
1955
- ul: (_w) => {
1956
- var _x = _w, { children } = _x, props = __objRest(_x, ["children"]);
1957
- return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("ul", __spreadProps(__spreadValues({ className: "copilotKitMarkdownElement" }, props), { children }));
1958
- },
1959
- li: (_y) => {
1960
- var _z = _y, { children } = _z, props = __objRest(_z, ["children"]);
1961
- return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("li", __spreadProps(__spreadValues({ className: "copilotKitMarkdownElement" }, props), { children }));
1962
- }
2185
+ }, [startReadingFromMessageId, inProgress]);
2186
+ return { pushToTalkState, setPushToTalkState };
1963
2187
  };
1964
- var MemoizedReactMarkdown = (0, import_react11.memo)(
1965
- import_react_markdown.default,
1966
- (prevProps, nextProps) => prevProps.children === nextProps.children && prevProps.components === nextProps.components
1967
- );
1968
- var Markdown = ({ content, components }) => {
1969
- return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { className: "copilotKitMarkdown", children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
1970
- MemoizedReactMarkdown,
1971
- {
1972
- components: __spreadValues(__spreadValues({}, defaultComponents), components),
1973
- remarkPlugins: [import_remark_gfm.default, import_remark_math.default],
1974
- rehypePlugins: [import_rehype_raw.default],
1975
- children: content
1976
- }
1977
- ) });
2188
+
2189
+ // src/components/chat/Input.tsx
2190
+ var import_react_core7 = require("@copilotkit/react-core");
2191
+
2192
+ // src/hooks/use-dark-mode.ts
2193
+ var useDarkMode = () => {
2194
+ if (typeof window === "undefined")
2195
+ return false;
2196
+ return document.documentElement.classList.contains("dark") || document.body.classList.contains("dark") || document.documentElement.getAttribute("data-theme") === "dark" || document.body.getAttribute("data-theme") === "dark" || window.matchMedia("(prefers-color-scheme: dark)").matches;
1978
2197
  };
1979
2198
 
1980
- // src/components/chat/messages/AssistantMessage.tsx
1981
- var import_react12 = require("react");
1982
- var import_jsx_runtime17 = require("react/jsx-runtime");
1983
- var AssistantMessage = (props) => {
1984
- var _a;
1985
- const { icons, labels } = useChatContext();
1986
- const {
1987
- message,
1988
- isLoading,
1989
- onRegenerate,
1990
- onCopy,
1991
- onThumbsUp,
1992
- onThumbsDown,
1993
- isCurrentMessage,
1994
- markdownTagRenderers
1995
- } = props;
1996
- const [copied, setCopied] = (0, import_react12.useState)(false);
1997
- const handleCopy = () => {
1998
- const content2 = (message == null ? void 0 : message.content) || "";
1999
- if (content2 && onCopy) {
2000
- navigator.clipboard.writeText(content2);
2001
- setCopied(true);
2002
- onCopy(content2);
2003
- setTimeout(() => setCopied(false), 2e3);
2004
- } else if (content2) {
2005
- navigator.clipboard.writeText(content2);
2006
- setCopied(true);
2007
- setTimeout(() => setCopied(false), 2e3);
2008
- }
2009
- };
2010
- const handleRegenerate = () => {
2011
- if (onRegenerate)
2012
- onRegenerate();
2199
+ // src/components/chat/PoweredByTag.tsx
2200
+ var import_jsx_runtime19 = require("react/jsx-runtime");
2201
+ function PoweredByTag({ showPoweredBy = true }) {
2202
+ const isDark = useDarkMode();
2203
+ if (!showPoweredBy) {
2204
+ return null;
2205
+ }
2206
+ const poweredByStyle = {
2207
+ visibility: "visible",
2208
+ display: "block",
2209
+ position: "static",
2210
+ textAlign: "center",
2211
+ fontSize: "12px",
2212
+ padding: "3px 0",
2213
+ color: isDark ? "rgb(69, 69, 69)" : "rgb(214, 214, 214)"
2013
2214
  };
2014
- const handleThumbsUp = () => {
2015
- if (onThumbsUp && message)
2016
- onThumbsUp(message);
2215
+ return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("p", { className: "poweredBy", style: poweredByStyle, children: "Powered by CopilotKit" }) });
2216
+ }
2217
+
2218
+ // src/components/chat/Input.tsx
2219
+ var import_jsx_runtime20 = require("react/jsx-runtime");
2220
+ var MAX_NEWLINES = 6;
2221
+ var Input = ({
2222
+ inProgress,
2223
+ onSend,
2224
+ isVisible = false,
2225
+ onStop,
2226
+ onUpload,
2227
+ hideStopButton = false
2228
+ }) => {
2229
+ var _a, _b;
2230
+ const context = useChatContext();
2231
+ const copilotContext = (0, import_react_core7.useCopilotContext)();
2232
+ const showPoweredBy = !((_a = copilotContext.copilotApiConfig) == null ? void 0 : _a.publicApiKey);
2233
+ const pushToTalkConfigured = copilotContext.copilotApiConfig.textToSpeechUrl !== void 0 && copilotContext.copilotApiConfig.transcribeAudioUrl !== void 0;
2234
+ const textareaRef = (0, import_react13.useRef)(null);
2235
+ const [isComposing, setIsComposing] = (0, import_react13.useState)(false);
2236
+ const handleDivClick = (event) => {
2237
+ var _a2;
2238
+ const target = event.target;
2239
+ if (target.closest("button"))
2240
+ return;
2241
+ if (target.tagName === "TEXTAREA")
2242
+ return;
2243
+ (_a2 = textareaRef.current) == null ? void 0 : _a2.focus();
2017
2244
  };
2018
- const handleThumbsDown = () => {
2019
- if (onThumbsDown && message)
2020
- onThumbsDown(message);
2245
+ const [text, setText] = (0, import_react13.useState)("");
2246
+ const send = () => {
2247
+ var _a2;
2248
+ if (inProgress)
2249
+ return;
2250
+ onSend(text);
2251
+ setText("");
2252
+ (_a2 = textareaRef.current) == null ? void 0 : _a2.focus();
2021
2253
  };
2022
- const LoadingIcon = () => /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { children: icons.activityIcon });
2023
- const content = (message == null ? void 0 : message.content) || "";
2024
- const subComponent = (_a = message == null ? void 0 : message.generativeUI) == null ? void 0 : _a.call(message);
2025
- return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(import_jsx_runtime17.Fragment, { children: [
2026
- content && /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "copilotKitMessage copilotKitAssistantMessage", children: [
2027
- content && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(Markdown, { content, components: markdownTagRenderers }),
2028
- content && !isLoading && /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
2029
- "div",
2254
+ const { pushToTalkState, setPushToTalkState } = usePushToTalk({
2255
+ sendFunction: onSend,
2256
+ inProgress
2257
+ });
2258
+ const isInProgress = inProgress || pushToTalkState === "transcribing";
2259
+ const buttonIcon = isInProgress && !hideStopButton ? context.icons.stopIcon : context.icons.sendIcon;
2260
+ const showPushToTalk = pushToTalkConfigured && (pushToTalkState === "idle" || pushToTalkState === "recording") && !inProgress;
2261
+ const canSend = (0, import_react13.useMemo)(() => {
2262
+ var _a2;
2263
+ const interruptEvent = (_a2 = copilotContext.langGraphInterruptAction) == null ? void 0 : _a2.event;
2264
+ const interruptInProgress = (interruptEvent == null ? void 0 : interruptEvent.name) === "LangGraphInterruptEvent" && !(interruptEvent == null ? void 0 : interruptEvent.response);
2265
+ return !isInProgress && text.trim().length > 0 && pushToTalkState === "idle" && !interruptInProgress;
2266
+ }, [(_b = copilotContext.langGraphInterruptAction) == null ? void 0 : _b.event, isInProgress, text, pushToTalkState]);
2267
+ const canStop = (0, import_react13.useMemo)(() => {
2268
+ return isInProgress && !hideStopButton;
2269
+ }, [isInProgress, hideStopButton]);
2270
+ const sendDisabled = !canSend && !canStop;
2271
+ return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { className: `copilotKitInputContainer ${showPoweredBy ? "poweredByContainer" : ""}`, children: [
2272
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { className: "copilotKitInput", onClick: handleDivClick, children: [
2273
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
2274
+ Textarea_default,
2030
2275
  {
2031
- className: `copilotKitMessageControls ${isCurrentMessage ? "currentMessage" : ""}`,
2032
- children: [
2033
- /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
2034
- "button",
2035
- {
2036
- className: "copilotKitMessageControlButton",
2037
- onClick: handleRegenerate,
2038
- "aria-label": labels.regenerateResponse,
2039
- title: labels.regenerateResponse,
2040
- children: icons.regenerateIcon
2041
- }
2042
- ),
2043
- /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
2044
- "button",
2045
- {
2046
- className: "copilotKitMessageControlButton",
2047
- onClick: handleCopy,
2048
- "aria-label": labels.copyToClipboard,
2049
- title: labels.copyToClipboard,
2050
- children: copied ? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { style: { fontSize: "10px", fontWeight: "bold" }, children: "\u2713" }) : icons.copyIcon
2051
- }
2052
- ),
2053
- onThumbsUp && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
2054
- "button",
2055
- {
2056
- className: "copilotKitMessageControlButton",
2057
- onClick: handleThumbsUp,
2058
- "aria-label": labels.thumbsUp,
2059
- title: labels.thumbsUp,
2060
- children: icons.thumbsUpIcon
2061
- }
2062
- ),
2063
- onThumbsDown && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
2064
- "button",
2065
- {
2066
- className: "copilotKitMessageControlButton",
2067
- onClick: handleThumbsDown,
2068
- "aria-label": labels.thumbsDown,
2069
- title: labels.thumbsDown,
2070
- children: icons.thumbsDownIcon
2276
+ ref: textareaRef,
2277
+ placeholder: context.labels.placeholder,
2278
+ autoFocus: false,
2279
+ maxRows: MAX_NEWLINES,
2280
+ value: text,
2281
+ onChange: (event) => setText(event.target.value),
2282
+ onCompositionStart: () => setIsComposing(true),
2283
+ onCompositionEnd: () => setIsComposing(false),
2284
+ onKeyDown: (event) => {
2285
+ if (event.key === "Enter" && !event.shiftKey && !isComposing) {
2286
+ event.preventDefault();
2287
+ if (canSend) {
2288
+ send();
2071
2289
  }
2072
- )
2073
- ]
2290
+ }
2291
+ }
2074
2292
  }
2075
- )
2293
+ ),
2294
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { className: "copilotKitInputControls", children: [
2295
+ onUpload && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("button", { onClick: onUpload, className: "copilotKitInputControlButton", children: context.icons.uploadIcon }),
2296
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { style: { flexGrow: 1 } }),
2297
+ showPushToTalk && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
2298
+ "button",
2299
+ {
2300
+ onClick: () => setPushToTalkState(pushToTalkState === "idle" ? "recording" : "transcribing"),
2301
+ className: pushToTalkState === "recording" ? "copilotKitInputControlButton copilotKitPushToTalkRecording" : "copilotKitInputControlButton",
2302
+ children: context.icons.pushToTalkIcon
2303
+ }
2304
+ ),
2305
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
2306
+ "button",
2307
+ {
2308
+ disabled: sendDisabled,
2309
+ onClick: isInProgress && !hideStopButton ? onStop : send,
2310
+ "data-copilotkit-in-progress": inProgress,
2311
+ "data-test-id": inProgress ? "copilot-chat-request-in-progress" : "copilot-chat-ready",
2312
+ className: "copilotKitInputControlButton",
2313
+ children: buttonIcon
2314
+ }
2315
+ )
2316
+ ] })
2076
2317
  ] }),
2077
- /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { style: { marginBottom: "0.5rem" }, children: subComponent }),
2078
- isLoading && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(LoadingIcon, {})
2079
- ] });
2080
- };
2081
-
2082
- // src/components/chat/messages/ImageRenderer.tsx
2083
- var import_react13 = require("react");
2084
- var import_jsx_runtime18 = require("react/jsx-runtime");
2085
- var ImageRenderer = ({ image, content, className = "" }) => {
2086
- const [imageError, setImageError] = (0, import_react13.useState)(false);
2087
- const imageSrc = `data:image/${image.format};base64,${image.bytes}`;
2088
- const altText = content || "User uploaded image";
2089
- const handleImageError = () => {
2090
- setImageError(true);
2091
- };
2092
- if (imageError) {
2093
- return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: `copilotKitImageRendering copilotKitImageRenderingError ${className}`, children: [
2094
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { className: "copilotKitImageRenderingErrorMessage", children: "Failed to load image" }),
2095
- content && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { className: "copilotKitImageRenderingContent", children: content })
2096
- ] });
2097
- }
2098
- return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: `copilotKitImageRendering ${className}`, children: [
2099
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
2100
- "img",
2101
- {
2102
- src: imageSrc,
2103
- alt: altText,
2104
- className: "copilotKitImageRenderingImage",
2105
- onError: handleImageError
2106
- }
2107
- ),
2108
- content && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { className: "copilotKitImageRenderingContent", children: content })
2318
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(PoweredByTag, { showPoweredBy })
2109
2319
  ] });
2110
2320
  };
2111
2321
 
2112
- // src/components/chat/messages/RenderMessage.tsx
2113
- var import_jsx_runtime19 = require("react/jsx-runtime");
2114
- function RenderMessage(_a) {
2115
- var _b = _a, {
2116
- UserMessage: UserMessage2 = UserMessage,
2117
- AssistantMessage: AssistantMessage2 = AssistantMessage,
2118
- ImageRenderer: ImageRenderer2 = ImageRenderer
2119
- } = _b, props = __objRest(_b, [
2120
- "UserMessage",
2121
- "AssistantMessage",
2122
- "ImageRenderer"
2123
- ]);
2124
- const {
2125
- message,
2126
- inProgress,
2127
- index,
2128
- isCurrentMessage,
2129
- onRegenerate,
2130
- onCopy,
2131
- onThumbsUp,
2132
- onThumbsDown,
2133
- markdownTagRenderers
2134
- } = props;
2135
- switch (message.role) {
2136
- case "user":
2137
- return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
2138
- UserMessage2,
2139
- {
2140
- "data-message-role": "user",
2141
- message,
2142
- ImageRenderer: ImageRenderer2
2143
- },
2144
- index
2145
- );
2146
- case "assistant":
2147
- return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
2148
- AssistantMessage2,
2149
- {
2150
- "data-message-role": "assistant",
2151
- message,
2152
- isLoading: inProgress && isCurrentMessage && !message.content,
2153
- isGenerating: inProgress && isCurrentMessage && !!message.content,
2154
- isCurrentMessage,
2155
- onRegenerate: () => onRegenerate == null ? void 0 : onRegenerate(message.id),
2156
- onCopy,
2157
- onThumbsUp,
2158
- onThumbsDown,
2159
- markdownTagRenderers,
2160
- ImageRenderer: ImageRenderer2
2161
- },
2162
- index
2163
- );
2164
- }
2165
- }
2166
-
2167
2322
  // src/components/chat/Chat.tsx
2168
2323
  var import_react14 = __toESM(require("react"));
2169
- var import_react_core8 = require("@copilotkit/react-core");
2170
- var import_shared3 = require("@copilotkit/shared");
2171
2324
  var import_react_core9 = require("@copilotkit/react-core");
2325
+ var import_shared3 = require("@copilotkit/shared");
2326
+ var import_shared4 = require("@copilotkit/shared");
2327
+ var import_react_core10 = require("@copilotkit/react-core");
2172
2328
 
2173
2329
  // src/components/chat/ImageUploadQueue.tsx
2174
- var import_jsx_runtime20 = require("react/jsx-runtime");
2330
+ var import_jsx_runtime21 = require("react/jsx-runtime");
2175
2331
  var ImageUploadQueue = ({
2176
2332
  images,
2177
2333
  onRemoveImage,
@@ -2179,7 +2335,7 @@ var ImageUploadQueue = ({
2179
2335
  }) => {
2180
2336
  if (images.length === 0)
2181
2337
  return null;
2182
- return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
2338
+ return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
2183
2339
  "div",
2184
2340
  {
2185
2341
  className: `copilotKitImageUploadQueue ${className}`,
@@ -2190,7 +2346,7 @@ var ImageUploadQueue = ({
2190
2346
  margin: "8px",
2191
2347
  padding: "8px"
2192
2348
  },
2193
- children: images.map((image, index) => /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
2349
+ children: images.map((image, index) => /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
2194
2350
  "div",
2195
2351
  {
2196
2352
  className: "copilotKitImageUploadQueueItem",
@@ -2203,7 +2359,7 @@ var ImageUploadQueue = ({
2203
2359
  overflow: "hidden"
2204
2360
  },
2205
2361
  children: [
2206
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
2362
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
2207
2363
  "img",
2208
2364
  {
2209
2365
  src: `data:${image.contentType};base64,${image.bytes}`,
@@ -2215,7 +2371,7 @@ var ImageUploadQueue = ({
2215
2371
  }
2216
2372
  }
2217
2373
  ),
2218
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
2374
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
2219
2375
  "button",
2220
2376
  {
2221
2377
  onClick: () => onRemoveImage(index),
@@ -2249,13 +2405,13 @@ var ImageUploadQueue = ({
2249
2405
  };
2250
2406
 
2251
2407
  // src/components/chat/Suggestion.tsx
2252
- var import_react_core7 = require("@copilotkit/react-core");
2253
- var import_jsx_runtime21 = require("react/jsx-runtime");
2408
+ var import_react_core8 = require("@copilotkit/react-core");
2409
+ var import_jsx_runtime22 = require("react/jsx-runtime");
2254
2410
  function Suggestion({ title, onClick, partial, className }) {
2255
2411
  if (!title)
2256
2412
  return null;
2257
- const { isLoading } = (0, import_react_core7.useCopilotChat)();
2258
- return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
2413
+ const { isLoading } = (0, import_react_core8.useCopilotChatInternal)();
2414
+ return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
2259
2415
  "button",
2260
2416
  {
2261
2417
  disabled: partial || isLoading,
@@ -2265,15 +2421,15 @@ function Suggestion({ title, onClick, partial, className }) {
2265
2421
  },
2266
2422
  className: className || (partial ? "suggestion loading" : "suggestion"),
2267
2423
  "data-test-id": "suggestion",
2268
- children: partial ? SmallSpinnerIcon : /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { children: title })
2424
+ children: partial ? SmallSpinnerIcon : /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { children: title })
2269
2425
  }
2270
2426
  );
2271
2427
  }
2272
2428
 
2273
2429
  // src/components/chat/Suggestions.tsx
2274
- var import_jsx_runtime22 = require("react/jsx-runtime");
2430
+ var import_jsx_runtime23 = require("react/jsx-runtime");
2275
2431
  function Suggestions({ suggestions, onSuggestionClick }) {
2276
- return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { className: "suggestions", children: suggestions.map((suggestion, index) => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
2432
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "suggestions", children: suggestions.map((suggestion, index) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
2277
2433
  Suggestion,
2278
2434
  {
2279
2435
  title: suggestion.title,
@@ -2287,7 +2443,7 @@ function Suggestions({ suggestions, onSuggestionClick }) {
2287
2443
  }
2288
2444
 
2289
2445
  // src/components/chat/Chat.tsx
2290
- var import_jsx_runtime23 = require("react/jsx-runtime");
2446
+ var import_jsx_runtime24 = require("react/jsx-runtime");
2291
2447
  function CopilotChat({
2292
2448
  instructions,
2293
2449
  suggestions = "auto",
@@ -2313,11 +2469,83 @@ function CopilotChat({
2313
2469
  ImageRenderer: ImageRenderer2 = ImageRenderer,
2314
2470
  imageUploadsEnabled,
2315
2471
  inputFileAccept = "image/*",
2316
- hideStopButton
2472
+ hideStopButton,
2473
+ observabilityHooks,
2474
+ renderError,
2475
+ // Legacy props - deprecated
2476
+ RenderTextMessage,
2477
+ RenderActionExecutionMessage,
2478
+ RenderAgentStateMessage,
2479
+ RenderResultMessage,
2480
+ RenderImageMessage
2317
2481
  }) {
2318
- const { additionalInstructions, setChatInstructions } = (0, import_react_core8.useCopilotContext)();
2482
+ const { additionalInstructions, setChatInstructions, copilotApiConfig, setBannerError } = (0, import_react_core9.useCopilotContext)();
2483
+ const { publicApiKey, chatApiEndpoint } = copilotApiConfig;
2319
2484
  const [selectedImages, setSelectedImages] = (0, import_react14.useState)([]);
2485
+ const [chatError, setChatError] = (0, import_react14.useState)(null);
2320
2486
  const fileInputRef = (0, import_react14.useRef)(null);
2487
+ const triggerObservabilityHook = (0, import_react14.useCallback)(
2488
+ (hookName, ...args) => {
2489
+ if (publicApiKey && (observabilityHooks == null ? void 0 : observabilityHooks[hookName])) {
2490
+ observabilityHooks[hookName](...args);
2491
+ }
2492
+ if ((observabilityHooks == null ? void 0 : observabilityHooks[hookName]) && !publicApiKey) {
2493
+ setBannerError(
2494
+ new import_shared3.CopilotKitError({
2495
+ message: "observabilityHooks requires a publicApiKey to function.",
2496
+ code: import_shared3.CopilotKitErrorCode.MISSING_PUBLIC_API_KEY_ERROR,
2497
+ severity: import_shared3.Severity.CRITICAL,
2498
+ visibility: import_shared3.ErrorVisibility.BANNER
2499
+ })
2500
+ );
2501
+ import_shared3.styledConsole.publicApiKeyRequired("observabilityHooks");
2502
+ }
2503
+ },
2504
+ [publicApiKey, observabilityHooks, setBannerError]
2505
+ );
2506
+ const triggerChatError = (0, import_react14.useCallback)(
2507
+ (error, operation, originalError) => {
2508
+ const errorMessage = (error == null ? void 0 : error.message) || (error == null ? void 0 : error.toString()) || "An error occurred";
2509
+ setChatError({
2510
+ message: errorMessage,
2511
+ operation,
2512
+ timestamp: Date.now()
2513
+ });
2514
+ if (publicApiKey && (observabilityHooks == null ? void 0 : observabilityHooks.onError)) {
2515
+ const errorEvent = {
2516
+ type: "error",
2517
+ timestamp: Date.now(),
2518
+ context: {
2519
+ source: "ui",
2520
+ request: {
2521
+ operation,
2522
+ url: chatApiEndpoint,
2523
+ startTime: Date.now()
2524
+ },
2525
+ technical: {
2526
+ environment: "browser",
2527
+ userAgent: typeof navigator !== "undefined" ? navigator.userAgent : void 0,
2528
+ stackTrace: originalError instanceof Error ? originalError.stack : void 0
2529
+ }
2530
+ },
2531
+ error
2532
+ };
2533
+ observabilityHooks.onError(errorEvent);
2534
+ }
2535
+ if ((observabilityHooks == null ? void 0 : observabilityHooks.onError) && !publicApiKey) {
2536
+ setBannerError(
2537
+ new import_shared3.CopilotKitError({
2538
+ message: "observabilityHooks.onError requires a publicApiKey to function.",
2539
+ code: import_shared3.CopilotKitErrorCode.MISSING_PUBLIC_API_KEY_ERROR,
2540
+ severity: import_shared3.Severity.CRITICAL,
2541
+ visibility: import_shared3.ErrorVisibility.BANNER
2542
+ })
2543
+ );
2544
+ import_shared3.styledConsole.publicApiKeyRequired("observabilityHooks.onError");
2545
+ }
2546
+ },
2547
+ [publicApiKey, chatApiEndpoint, observabilityHooks, setBannerError]
2548
+ );
2321
2549
  (0, import_react14.useEffect)(() => {
2322
2550
  if (!imageUploadsEnabled)
2323
2551
  return;
@@ -2357,12 +2585,13 @@ function CopilotChat({
2357
2585
  const loadedImages = (yield Promise.all(imagePromises)).filter((img) => img !== null);
2358
2586
  setSelectedImages((prev) => [...prev, ...loadedImages]);
2359
2587
  } catch (error) {
2588
+ triggerChatError(error, "processClipboardImages", error);
2360
2589
  console.error("Error processing pasted images:", error);
2361
2590
  }
2362
2591
  });
2363
2592
  document.addEventListener("paste", handlePaste);
2364
2593
  return () => document.removeEventListener("paste", handlePaste);
2365
- }, [imageUploadsEnabled]);
2594
+ }, [imageUploadsEnabled, triggerChatError]);
2366
2595
  (0, import_react14.useEffect)(() => {
2367
2596
  if (!(additionalInstructions == null ? void 0 : additionalInstructions.length)) {
2368
2597
  setChatInstructions(instructions || "");
@@ -2376,7 +2605,7 @@ function CopilotChat({
2376
2605
  setChatInstructions(combinedAdditionalInstructions.join("\n") || "");
2377
2606
  }, [instructions, additionalInstructions]);
2378
2607
  const {
2379
- visibleMessages,
2608
+ messages,
2380
2609
  isLoading,
2381
2610
  sendMessage,
2382
2611
  stopGeneration,
@@ -2390,12 +2619,24 @@ function CopilotChat({
2390
2619
  onStopGeneration,
2391
2620
  onReloadMessages
2392
2621
  );
2622
+ const prevIsLoading = (0, import_react14.useRef)(isLoading);
2623
+ (0, import_react14.useEffect)(() => {
2624
+ if (prevIsLoading.current !== isLoading) {
2625
+ if (isLoading) {
2626
+ triggerObservabilityHook("onChatStarted");
2627
+ } else {
2628
+ triggerObservabilityHook("onChatStopped");
2629
+ }
2630
+ prevIsLoading.current = isLoading;
2631
+ }
2632
+ }, [isLoading, triggerObservabilityHook]);
2393
2633
  const handleSendMessage = (text) => {
2394
2634
  const images = selectedImages;
2395
2635
  setSelectedImages([]);
2396
2636
  if (fileInputRef.current) {
2397
2637
  fileInputRef.current.value = "";
2398
2638
  }
2639
+ triggerObservabilityHook("onMessageSent", text);
2399
2640
  return sendMessage(text, images);
2400
2641
  };
2401
2642
  const chatContext = import_react14.default.useContext(ChatContext);
@@ -2404,12 +2645,14 @@ function CopilotChat({
2404
2645
  if (onRegenerate) {
2405
2646
  onRegenerate(messageId);
2406
2647
  }
2648
+ triggerObservabilityHook("onMessageRegenerated", messageId);
2407
2649
  reloadMessages(messageId);
2408
2650
  };
2409
2651
  const handleCopy = (message) => {
2410
2652
  if (onCopy) {
2411
2653
  onCopy(message);
2412
2654
  }
2655
+ triggerObservabilityHook("onMessageCopied", message);
2413
2656
  };
2414
2657
  const handleImageUpload = (event) => __async(this, null, function* () {
2415
2658
  if (!event.target.files || event.target.files.length === 0) {
@@ -2439,28 +2682,52 @@ function CopilotChat({
2439
2682
  const loadedImages = yield Promise.all(fileReadPromises);
2440
2683
  setSelectedImages((prev) => [...prev, ...loadedImages]);
2441
2684
  } catch (error) {
2685
+ triggerChatError(error, "processUploadedImages", error);
2442
2686
  console.error("Error reading files:", error);
2443
2687
  }
2444
2688
  });
2445
2689
  const removeSelectedImage = (index) => {
2446
2690
  setSelectedImages((prev) => prev.filter((_, i) => i !== index));
2447
2691
  };
2448
- return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(WrappedCopilotChat, { icons, labels, className, children: [
2449
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
2692
+ const handleThumbsUp = (message) => {
2693
+ if (onThumbsUp) {
2694
+ onThumbsUp(message);
2695
+ }
2696
+ triggerObservabilityHook("onFeedbackGiven", message.id, "thumbsUp");
2697
+ };
2698
+ const handleThumbsDown = (message) => {
2699
+ if (onThumbsDown) {
2700
+ onThumbsDown(message);
2701
+ }
2702
+ triggerObservabilityHook("onFeedbackGiven", message.id, "thumbsDown");
2703
+ };
2704
+ return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(WrappedCopilotChat, { icons, labels, className, children: [
2705
+ chatError && renderError && renderError(__spreadProps(__spreadValues({}, chatError), {
2706
+ onDismiss: () => setChatError(null),
2707
+ onRetry: () => {
2708
+ setChatError(null);
2709
+ }
2710
+ })),
2711
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
2450
2712
  Messages2,
2451
2713
  {
2452
2714
  AssistantMessage: AssistantMessage2,
2453
2715
  UserMessage: UserMessage2,
2454
2716
  RenderMessage: RenderMessage2,
2455
- messages: visibleMessages,
2717
+ messages,
2456
2718
  inProgress: isLoading,
2457
2719
  onRegenerate: handleRegenerate,
2458
2720
  onCopy: handleCopy,
2459
- onThumbsUp,
2460
- onThumbsDown,
2721
+ onThumbsUp: handleThumbsUp,
2722
+ onThumbsDown: handleThumbsDown,
2461
2723
  markdownTagRenderers,
2462
2724
  ImageRenderer: ImageRenderer2,
2463
- children: currentSuggestions.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
2725
+ RenderTextMessage,
2726
+ RenderActionExecutionMessage,
2727
+ RenderAgentStateMessage,
2728
+ RenderResultMessage,
2729
+ RenderImageMessage,
2730
+ children: currentSuggestions.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
2464
2731
  RenderSuggestionsList,
2465
2732
  {
2466
2733
  onSuggestionClick: handleSendMessage,
@@ -2469,9 +2736,9 @@ function CopilotChat({
2469
2736
  )
2470
2737
  }
2471
2738
  ),
2472
- imageUploadsEnabled && /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(import_jsx_runtime23.Fragment, { children: [
2473
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(ImageUploadQueue, { images: selectedImages, onRemoveImage: removeSelectedImage }),
2474
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
2739
+ imageUploadsEnabled && /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(import_jsx_runtime24.Fragment, { children: [
2740
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(ImageUploadQueue, { images: selectedImages, onRemoveImage: removeSelectedImage }),
2741
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
2475
2742
  "input",
2476
2743
  {
2477
2744
  type: "file",
@@ -2483,7 +2750,7 @@ function CopilotChat({
2483
2750
  }
2484
2751
  )
2485
2752
  ] }),
2486
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
2753
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
2487
2754
  Input2,
2488
2755
  {
2489
2756
  inProgress: isLoading,
@@ -2507,16 +2774,16 @@ function WrappedCopilotChat({
2507
2774
  }) {
2508
2775
  const chatContext = import_react14.default.useContext(ChatContext);
2509
2776
  if (!chatContext) {
2510
- return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(ChatContextProvider, { icons, labels, open: true, setOpen: () => {
2511
- }, children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: `copilotKitChat ${className != null ? className : ""}`, children }) });
2777
+ return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(ChatContextProvider, { icons, labels, open: true, setOpen: () => {
2778
+ }, children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: `copilotKitChat ${className != null ? className : ""}`, children }) });
2512
2779
  }
2513
- return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_jsx_runtime23.Fragment, { children });
2780
+ return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_jsx_runtime24.Fragment, { children });
2514
2781
  }
2515
2782
  var useCopilotChatLogic = (chatSuggestions, makeSystemMessage, onInProgress, onSubmitMessage, onStopGeneration, onReloadMessages) => {
2516
2783
  var _a;
2517
2784
  const {
2518
- visibleMessages,
2519
- appendMessage,
2785
+ messages,
2786
+ sendMessage,
2520
2787
  setMessages,
2521
2788
  reloadMessages: defaultReloadMessages,
2522
2789
  stopGeneration: defaultStopGeneration,
@@ -2527,11 +2794,11 @@ var useCopilotChatLogic = (chatSuggestions, makeSystemMessage, onInProgress, onS
2527
2794
  generateSuggestions,
2528
2795
  resetSuggestions: resetSuggestionsFromHook,
2529
2796
  isLoadingSuggestions
2530
- } = (0, import_react_core8.useCopilotChat)({
2797
+ } = (0, import_react_core9.useCopilotChatInternal)({
2531
2798
  makeSystemMessage
2532
2799
  });
2533
- const generalContext = (0, import_react_core8.useCopilotContext)();
2534
- const messagesContext = (0, import_react_core8.useCopilotMessagesContext)();
2800
+ const generalContext = (0, import_react_core9.useCopilotContext)();
2801
+ const messagesContext = (0, import_react_core9.useCopilotMessagesContext)();
2535
2802
  const { actions } = generalContext;
2536
2803
  const [suggestionsFailed, setSuggestionsFailed] = (0, import_react14.useState)(false);
2537
2804
  const hasGeneratedInitialSuggestions = (0, import_react14.useRef)(false);
@@ -2562,12 +2829,12 @@ var useCopilotChatLogic = (chatSuggestions, makeSystemMessage, onInProgress, onS
2562
2829
  if (Object.keys(generalContext.chatSuggestionConfiguration).length === 0) {
2563
2830
  return;
2564
2831
  }
2565
- if (visibleMessages.length === 0 && !hasGeneratedInitialSuggestions.current) {
2832
+ if (messages.length === 0 && !hasGeneratedInitialSuggestions.current) {
2566
2833
  hasGeneratedInitialSuggestions.current = true;
2567
2834
  generateSuggestionsWithErrorHandling("initial");
2568
2835
  return;
2569
2836
  }
2570
- if (visibleMessages.length > 0 && suggestions.length === 0) {
2837
+ if (messages.length > 0 && suggestions.length === 0) {
2571
2838
  generateSuggestionsWithErrorHandling("post-message");
2572
2839
  return;
2573
2840
  }
@@ -2575,7 +2842,7 @@ var useCopilotChatLogic = (chatSuggestions, makeSystemMessage, onInProgress, onS
2575
2842
  chatSuggestions,
2576
2843
  isLoadingSuggestions,
2577
2844
  suggestionsFailed,
2578
- visibleMessages.length,
2845
+ messages.length,
2579
2846
  isLoading,
2580
2847
  suggestions.length,
2581
2848
  Object.keys(generalContext.chatSuggestionConfiguration).join(","),
@@ -2605,7 +2872,7 @@ var useCopilotChatLogic = (chatSuggestions, makeSystemMessage, onInProgress, onS
2605
2872
  (0, import_react14.useEffect)(() => {
2606
2873
  onInProgress == null ? void 0 : onInProgress(isLoading);
2607
2874
  }, [onInProgress, isLoading]);
2608
- const sendMessage = (messageContent, imagesToUse) => __async(void 0, null, function* () {
2875
+ const safelySendMessage = (messageContent, imagesToUse) => __async(void 0, null, function* () {
2609
2876
  const images = imagesToUse || [];
2610
2877
  if (chatSuggestions === "auto" || chatSuggestions === "manual") {
2611
2878
  setSuggestions([]);
@@ -2613,7 +2880,7 @@ var useCopilotChatLogic = (chatSuggestions, makeSystemMessage, onInProgress, onS
2613
2880
  let firstMessage = null;
2614
2881
  if (messageContent.trim().length > 0) {
2615
2882
  const textMessage = {
2616
- id: (0, import_shared3.randomId)(),
2883
+ id: (0, import_shared4.randomId)(),
2617
2884
  role: "user",
2618
2885
  content: messageContent
2619
2886
  };
@@ -2624,7 +2891,7 @@ var useCopilotChatLogic = (chatSuggestions, makeSystemMessage, onInProgress, onS
2624
2891
  console.error("Error in onSubmitMessage:", error);
2625
2892
  }
2626
2893
  }
2627
- yield appendMessage(textMessage, {
2894
+ yield sendMessage(textMessage, {
2628
2895
  followUp: images.length === 0,
2629
2896
  clearSuggestions: chatSuggestions === "auto" || chatSuggestions === "manual"
2630
2897
  });
@@ -2635,25 +2902,24 @@ var useCopilotChatLogic = (chatSuggestions, makeSystemMessage, onInProgress, onS
2635
2902
  if (images.length > 0) {
2636
2903
  for (let i = 0; i < images.length; i++) {
2637
2904
  const imageMessage = {
2638
- id: (0, import_shared3.randomId)(),
2905
+ id: (0, import_shared4.randomId)(),
2639
2906
  role: "user",
2640
2907
  image: {
2641
2908
  format: images[i].contentType.replace("image/", ""),
2642
2909
  bytes: images[i].bytes
2643
2910
  }
2644
2911
  };
2645
- yield appendMessage(imageMessage, { followUp: i === images.length - 1 });
2912
+ yield sendMessage(imageMessage, { followUp: i === images.length - 1 });
2646
2913
  if (!firstMessage) {
2647
2914
  firstMessage = imageMessage;
2648
2915
  }
2649
2916
  }
2650
2917
  }
2651
2918
  if (!firstMessage) {
2652
- return { role: "user", content: "", id: (0, import_shared3.randomId)() };
2919
+ return { role: "user", content: "", id: (0, import_shared4.randomId)() };
2653
2920
  }
2654
2921
  return firstMessage;
2655
2922
  });
2656
- const messages = visibleMessages;
2657
2923
  const currentAgentName = (_a = generalContext.agentSession) == null ? void 0 : _a.agentName;
2658
2924
  const restartCurrentAgent = (hint) => __async(void 0, null, function* () {
2659
2925
  if (generalContext.agentSession) {
@@ -2674,18 +2940,18 @@ var useCopilotChatLogic = (chatSuggestions, makeSystemMessage, onInProgress, onS
2674
2940
  });
2675
2941
  const runCurrentAgent = (hint) => __async(void 0, null, function* () {
2676
2942
  if (generalContext.agentSession) {
2677
- yield (0, import_react_core9.runAgent)(
2943
+ yield (0, import_react_core10.runAgent)(
2678
2944
  generalContext.agentSession.agentName,
2679
2945
  stableContext,
2680
- appendMessage,
2681
- runChatCompletion,
2682
- hint
2946
+ messagesContext.messages,
2947
+ sendMessage,
2948
+ runChatCompletion
2683
2949
  );
2684
2950
  }
2685
2951
  });
2686
2952
  const stopCurrentAgent = () => {
2687
2953
  if (generalContext.agentSession) {
2688
- (0, import_react_core9.stopAgent)(generalContext.agentSession.agentName, stableContext);
2954
+ (0, import_react_core10.stopAgent)(generalContext.agentSession.agentName, stableContext);
2689
2955
  }
2690
2956
  };
2691
2957
  const setCurrentAgentState = (state) => {
@@ -2735,10 +3001,9 @@ var useCopilotChatLogic = (chatSuggestions, makeSystemMessage, onInProgress, onS
2735
3001
  }
2736
3002
  return {
2737
3003
  messages,
2738
- visibleMessages,
2739
3004
  isLoading,
2740
3005
  suggestions,
2741
- sendMessage,
3006
+ sendMessage: safelySendMessage,
2742
3007
  stopGeneration,
2743
3008
  reloadMessages,
2744
3009
  resetSuggestions,
@@ -2748,7 +3013,88 @@ var useCopilotChatLogic = (chatSuggestions, makeSystemMessage, onInProgress, onS
2748
3013
  };
2749
3014
 
2750
3015
  // src/components/chat/Modal.tsx
2751
- var import_jsx_runtime24 = require("react/jsx-runtime");
3016
+ var import_react_core11 = require("@copilotkit/react-core");
3017
+ var import_shared5 = require("@copilotkit/shared");
3018
+ var import_jsx_runtime25 = require("react/jsx-runtime");
3019
+ var CopilotModalInner = (_a) => {
3020
+ var _b = _a, {
3021
+ observabilityHooks,
3022
+ onSetOpen,
3023
+ clickOutsideToClose,
3024
+ hitEscapeToClose,
3025
+ shortcut,
3026
+ className,
3027
+ children,
3028
+ Window: Window2,
3029
+ Button: Button2,
3030
+ Header: Header2
3031
+ } = _b, chatProps = __objRest(_b, [
3032
+ "observabilityHooks",
3033
+ "onSetOpen",
3034
+ "clickOutsideToClose",
3035
+ "hitEscapeToClose",
3036
+ "shortcut",
3037
+ "className",
3038
+ "children",
3039
+ "Window",
3040
+ "Button",
3041
+ "Header"
3042
+ ]);
3043
+ const { copilotApiConfig, setBannerError } = (0, import_react_core11.useCopilotContext)();
3044
+ const { publicApiKey } = copilotApiConfig;
3045
+ const triggerObservabilityHook = (0, import_react15.useCallback)(
3046
+ (hookName, ...args) => {
3047
+ if (publicApiKey && (observabilityHooks == null ? void 0 : observabilityHooks[hookName])) {
3048
+ observabilityHooks[hookName](...args);
3049
+ }
3050
+ if ((observabilityHooks == null ? void 0 : observabilityHooks[hookName]) && !publicApiKey) {
3051
+ setBannerError(
3052
+ new import_shared5.CopilotKitError({
3053
+ message: "observabilityHooks requires a publicApiKey to function.",
3054
+ code: import_shared5.CopilotKitErrorCode.MISSING_PUBLIC_API_KEY_ERROR,
3055
+ severity: import_shared5.Severity.CRITICAL,
3056
+ visibility: import_shared5.ErrorVisibility.BANNER
3057
+ })
3058
+ );
3059
+ import_shared5.styledConsole.publicApiKeyRequired("observabilityHooks");
3060
+ }
3061
+ },
3062
+ [publicApiKey, observabilityHooks, setBannerError]
3063
+ );
3064
+ const { open } = useChatContext();
3065
+ const prevOpen = (0, import_react15.useRef)(open);
3066
+ (0, import_react15.useEffect)(() => {
3067
+ if (prevOpen.current !== open) {
3068
+ onSetOpen == null ? void 0 : onSetOpen(open);
3069
+ if (open) {
3070
+ triggerObservabilityHook("onChatExpanded");
3071
+ } else {
3072
+ triggerObservabilityHook("onChatMinimized");
3073
+ }
3074
+ prevOpen.current = open;
3075
+ }
3076
+ }, [open, onSetOpen, triggerObservabilityHook]);
3077
+ const memoizedHeader = (0, import_react15.useMemo)(() => /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(Header2, {}), [Header2]);
3078
+ const memoizedChildren = (0, import_react15.useMemo)(() => children, [children]);
3079
+ return /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(import_jsx_runtime25.Fragment, { children: [
3080
+ memoizedChildren,
3081
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className, children: [
3082
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(Button2, {}),
3083
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(
3084
+ Window2,
3085
+ {
3086
+ clickOutsideToClose,
3087
+ shortcut,
3088
+ hitEscapeToClose,
3089
+ children: [
3090
+ memoizedHeader,
3091
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(CopilotChat, __spreadProps(__spreadValues({}, chatProps), { observabilityHooks }))
3092
+ ]
3093
+ }
3094
+ )
3095
+ ] })
3096
+ ] });
3097
+ };
2752
3098
  var CopilotModal = (_a) => {
2753
3099
  var _b = _a, {
2754
3100
  instructions,
@@ -2777,7 +3123,8 @@ var CopilotModal = (_a) => {
2777
3123
  onRegenerate,
2778
3124
  markdownTagRenderers,
2779
3125
  className,
2780
- children
3126
+ children,
3127
+ observabilityHooks
2781
3128
  } = _b, props = __objRest(_b, [
2782
3129
  "instructions",
2783
3130
  "defaultOpen",
@@ -2805,52 +3152,41 @@ var CopilotModal = (_a) => {
2805
3152
  "onRegenerate",
2806
3153
  "markdownTagRenderers",
2807
3154
  "className",
2808
- "children"
3155
+ "children",
3156
+ "observabilityHooks"
2809
3157
  ]);
2810
3158
  const [openState, setOpenState] = import_react15.default.useState(defaultOpen);
2811
- const setOpen = (open) => {
2812
- onSetOpen == null ? void 0 : onSetOpen(open);
2813
- setOpenState(open);
2814
- };
2815
- const memoizedHeader = (0, import_react15.useMemo)(() => /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(Header2, {}), [Header2]);
2816
- const memoizedChildren = (0, import_react15.useMemo)(() => children, [children]);
2817
- return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(ChatContextProvider, { icons, labels, open: openState, setOpen, children: [
2818
- memoizedChildren,
2819
- /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className, children: [
2820
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(Button2, {}),
2821
- /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
2822
- Window2,
2823
- {
2824
- clickOutsideToClose,
2825
- shortcut,
2826
- hitEscapeToClose,
2827
- children: [
2828
- memoizedHeader,
2829
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
2830
- CopilotChat,
2831
- __spreadProps(__spreadValues({}, props), {
2832
- instructions,
2833
- onSubmitMessage,
2834
- onStopGeneration,
2835
- onReloadMessages,
2836
- makeSystemMessage,
2837
- onInProgress,
2838
- Messages: Messages2,
2839
- Input: Input2,
2840
- AssistantMessage: AssistantMessage2,
2841
- UserMessage: UserMessage2,
2842
- onThumbsUp,
2843
- onThumbsDown,
2844
- onCopy,
2845
- onRegenerate,
2846
- markdownTagRenderers
2847
- })
2848
- )
2849
- ]
2850
- }
2851
- )
2852
- ] })
2853
- ] });
3159
+ return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(ChatContextProvider, { icons, labels, open: openState, setOpen: setOpenState, children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
3160
+ CopilotModalInner,
3161
+ __spreadProps(__spreadValues({
3162
+ observabilityHooks,
3163
+ onSetOpen,
3164
+ clickOutsideToClose: clickOutsideToClose != null ? clickOutsideToClose : true,
3165
+ hitEscapeToClose: hitEscapeToClose != null ? hitEscapeToClose : true,
3166
+ shortcut: shortcut != null ? shortcut : "/",
3167
+ className,
3168
+ Window: Window2,
3169
+ Button: Button2,
3170
+ Header: Header2,
3171
+ instructions,
3172
+ onSubmitMessage,
3173
+ onStopGeneration,
3174
+ onReloadMessages,
3175
+ makeSystemMessage,
3176
+ onInProgress,
3177
+ Messages: Messages2,
3178
+ Input: Input2,
3179
+ AssistantMessage: AssistantMessage2,
3180
+ UserMessage: UserMessage2,
3181
+ onThumbsUp,
3182
+ onThumbsDown,
3183
+ onCopy,
3184
+ onRegenerate,
3185
+ markdownTagRenderers
3186
+ }, props), {
3187
+ children
3188
+ })
3189
+ ) });
2854
3190
  };
2855
3191
  // Annotate the CommonJS export names for ESM import in node:
2856
3192
  0 && (module.exports = {