@copilotkit/react-ui 1.10.0-next.8 → 1.10.0

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