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

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