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