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