@copilotkit/react-ui 0.22.0 → 0.36.0-mme-push-to-talk.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (152) hide show
  1. package/.turbo/turbo-build.log +204 -178
  2. package/CHANGELOG.md +12 -0
  3. package/dist/chunk-5ASYNEHX.mjs +53 -0
  4. package/dist/chunk-5ASYNEHX.mjs.map +1 -0
  5. package/dist/{chunk-MBYUBR3F.mjs → chunk-A7J4KGLP.mjs} +2 -2
  6. package/dist/chunk-DMAQBCTX.mjs +95 -0
  7. package/dist/chunk-DMAQBCTX.mjs.map +1 -0
  8. package/dist/{chunk-KE3N45ZY.mjs → chunk-DRNCOXZO.mjs} +3 -4
  9. package/dist/chunk-DRNCOXZO.mjs.map +1 -0
  10. package/dist/{chunk-7YXG7D47.mjs → chunk-FWTPMPSN.mjs} +37 -2
  11. package/dist/chunk-FWTPMPSN.mjs.map +1 -0
  12. package/dist/chunk-JPX5ODUX.mjs +266 -0
  13. package/dist/chunk-JPX5ODUX.mjs.map +1 -0
  14. package/dist/chunk-KZME7C5S.mjs +76 -0
  15. package/dist/chunk-KZME7C5S.mjs.map +1 -0
  16. package/dist/{chunk-7JYUCW7H.mjs → chunk-MWFHYCQB.mjs} +2 -2
  17. package/dist/chunk-PEDSZYHE.mjs +36 -0
  18. package/dist/chunk-PEDSZYHE.mjs.map +1 -0
  19. package/dist/{chunk-YEHO5VMA.mjs → chunk-PGZDQT74.mjs} +2 -2
  20. package/dist/{chunk-MRXNTQOX.mjs → chunk-SKC7AJIV.mjs} +3 -1
  21. package/dist/chunk-T26KLXLH.mjs +1 -0
  22. package/dist/{chunk-T3WYKWNC.mjs → chunk-UVMROYDT.mjs} +5 -5
  23. package/dist/chunk-UVMROYDT.mjs.map +1 -0
  24. package/dist/{chunk-YAORLSQ3.mjs → chunk-XWWMYJJF.mjs} +5 -5
  25. package/dist/chunk-XWWMYJJF.mjs.map +1 -0
  26. package/dist/{chunk-73EBDGYK.mjs → chunk-XYM43AHP.mjs} +5 -5
  27. package/dist/chunk-XYM43AHP.mjs.map +1 -0
  28. package/dist/chunk-Z45ZEXJW.mjs +32 -0
  29. package/dist/chunk-Z45ZEXJW.mjs.map +1 -0
  30. package/dist/{chunk-WDHLWSSU.mjs → chunk-ZKLK3M77.mjs} +3 -3
  31. package/dist/components/chat/Button.d.ts +1 -1
  32. package/dist/components/chat/Button.js +30 -2
  33. package/dist/components/chat/Button.js.map +1 -1
  34. package/dist/components/chat/Button.mjs +4 -4
  35. package/dist/components/chat/Chat.d.ts +3 -2
  36. package/dist/components/chat/Chat.js +397 -86
  37. package/dist/components/chat/Chat.js.map +1 -1
  38. package/dist/components/chat/Chat.mjs +13 -11
  39. package/dist/components/chat/ChatContext.d.ts +6 -1
  40. package/dist/components/chat/ChatContext.js +29 -28
  41. package/dist/components/chat/ChatContext.js.map +1 -1
  42. package/dist/components/chat/ChatContext.mjs +3 -3
  43. package/dist/components/chat/CodeBlock.js.map +1 -1
  44. package/dist/components/chat/CodeBlock.mjs +3 -3
  45. package/dist/components/chat/Header.js.map +1 -1
  46. package/dist/components/chat/Header.mjs +4 -4
  47. package/dist/components/chat/Icons.d.ts +2 -1
  48. package/dist/components/chat/Icons.js +36 -0
  49. package/dist/components/chat/Icons.js.map +1 -1
  50. package/dist/components/chat/Icons.mjs +4 -2
  51. package/dist/components/chat/Input.d.ts +1 -1
  52. package/dist/components/chat/Input.js +1 -2
  53. package/dist/components/chat/Input.js.map +1 -1
  54. package/dist/components/chat/Input.mjs +4 -4
  55. package/dist/components/chat/Markdown.js.map +1 -1
  56. package/dist/components/chat/Markdown.mjs +4 -4
  57. package/dist/components/chat/Messages.d.ts +1 -1
  58. package/dist/components/chat/Messages.js +2 -2
  59. package/dist/components/chat/Messages.js.map +1 -1
  60. package/dist/components/chat/Messages.mjs +6 -6
  61. package/dist/components/chat/Popup.d.ts +52 -1
  62. package/dist/components/chat/Popup.js +401 -90
  63. package/dist/components/chat/Popup.js.map +1 -1
  64. package/dist/components/chat/Popup.mjs +14 -12
  65. package/dist/components/chat/Response.js.map +1 -1
  66. package/dist/components/chat/Response.mjs +4 -4
  67. package/dist/components/chat/Sidebar.d.ts +3 -5
  68. package/dist/components/chat/Sidebar.js +403 -92
  69. package/dist/components/chat/Sidebar.js.map +1 -1
  70. package/dist/components/chat/Sidebar.mjs +14 -12
  71. package/dist/components/chat/Suggestion.d.ts +14 -0
  72. package/dist/components/chat/Suggestion.js +172 -0
  73. package/dist/components/chat/Suggestion.js.map +1 -0
  74. package/dist/components/chat/Suggestion.mjs +11 -0
  75. package/dist/components/chat/Suggestion.mjs.map +1 -0
  76. package/dist/components/chat/Textarea.mjs +1 -1
  77. package/dist/components/chat/Window.mjs +1 -1
  78. package/dist/components/chat/audio.d.ts +7 -0
  79. package/dist/components/chat/audio.js +77 -0
  80. package/dist/components/chat/audio.js.map +1 -0
  81. package/dist/components/chat/audio.mjs +10 -0
  82. package/dist/components/chat/audio.mjs.map +1 -0
  83. package/dist/components/chat/index.d.ts +2 -1
  84. package/dist/components/chat/index.js +407 -96
  85. package/dist/components/chat/index.js.map +1 -1
  86. package/dist/components/chat/index.mjs +15 -13
  87. package/dist/components/chat/props.d.ts +11 -2
  88. package/dist/components/chat/props.js.map +1 -1
  89. package/dist/components/index.d.ts +2 -1
  90. package/dist/components/index.js +407 -96
  91. package/dist/components/index.js.map +1 -1
  92. package/dist/components/index.mjs +15 -13
  93. package/dist/hooks/index.d.ts +2 -2
  94. package/dist/hooks/index.js +61 -0
  95. package/dist/hooks/index.js.map +1 -1
  96. package/dist/hooks/index.mjs +28 -1
  97. package/dist/hooks/use-copilot-chat-suggestions.d.ts +65 -0
  98. package/dist/hooks/use-copilot-chat-suggestions.js +78 -0
  99. package/dist/hooks/use-copilot-chat-suggestions.js.map +1 -0
  100. package/dist/hooks/use-copilot-chat-suggestions.mjs +28 -0
  101. package/dist/hooks/use-copilot-chat-suggestions.mjs.map +1 -0
  102. package/dist/hooks/use-copy-to-clipboard.mjs +1 -1
  103. package/dist/index.css +41 -5
  104. package/dist/index.css.map +1 -1
  105. package/dist/index.d.ts +3 -1
  106. package/dist/index.js +435 -98
  107. package/dist/index.js.map +1 -1
  108. package/dist/index.mjs +23 -17
  109. package/dist/lib/utils.mjs +1 -1
  110. package/dist/types/suggestions.d.ts +28 -0
  111. package/dist/types/suggestions.js +19 -0
  112. package/dist/types/suggestions.js.map +1 -0
  113. package/dist/types/suggestions.mjs +1 -0
  114. package/dist/types/suggestions.mjs.map +1 -0
  115. package/package.json +6 -6
  116. package/src/components/chat/Button.tsx +36 -4
  117. package/src/components/chat/Chat.tsx +204 -16
  118. package/src/components/chat/ChatContext.tsx +44 -32
  119. package/src/components/chat/Icons.tsx +27 -0
  120. package/src/components/chat/Input.tsx +1 -2
  121. package/src/components/chat/Messages.tsx +3 -3
  122. package/src/components/chat/Popup.tsx +52 -6
  123. package/src/components/chat/Sidebar.tsx +59 -6
  124. package/src/components/chat/Suggestion.tsx +105 -0
  125. package/src/components/chat/audio.ts +26 -0
  126. package/src/components/chat/props.ts +11 -1
  127. package/src/css/messages.css +7 -1
  128. package/src/css/response.css +1 -4
  129. package/src/css/suggestions.css +35 -0
  130. package/src/hooks/index.ts +1 -1
  131. package/src/hooks/use-copilot-chat-suggestions.tsx +91 -0
  132. package/src/styles.css +1 -0
  133. package/src/types/suggestions.ts +30 -0
  134. package/typedoc.json +4 -0
  135. package/dist/chunk-6U3O2JZP.mjs +0 -100
  136. package/dist/chunk-6U3O2JZP.mjs.map +0 -1
  137. package/dist/chunk-73EBDGYK.mjs.map +0 -1
  138. package/dist/chunk-7LMXXGJT.mjs +0 -75
  139. package/dist/chunk-7LMXXGJT.mjs.map +0 -1
  140. package/dist/chunk-7YXG7D47.mjs.map +0 -1
  141. package/dist/chunk-H4VKQGVU.mjs +0 -1
  142. package/dist/chunk-KE3N45ZY.mjs.map +0 -1
  143. package/dist/chunk-T3WYKWNC.mjs.map +0 -1
  144. package/dist/chunk-YAORLSQ3.mjs.map +0 -1
  145. package/dist/chunk-YTIGBBTC.mjs +0 -25
  146. package/dist/chunk-YTIGBBTC.mjs.map +0 -1
  147. /package/dist/{chunk-MBYUBR3F.mjs.map → chunk-A7J4KGLP.mjs.map} +0 -0
  148. /package/dist/{chunk-7JYUCW7H.mjs.map → chunk-MWFHYCQB.mjs.map} +0 -0
  149. /package/dist/{chunk-YEHO5VMA.mjs.map → chunk-PGZDQT74.mjs.map} +0 -0
  150. /package/dist/{chunk-H4VKQGVU.mjs.map → chunk-SKC7AJIV.mjs.map} +0 -0
  151. /package/dist/{chunk-MRXNTQOX.mjs.map → chunk-T26KLXLH.mjs.map} +0 -0
  152. /package/dist/{chunk-WDHLWSSU.mjs.map → chunk-ZKLK3M77.mjs.map} +0 -0
@@ -22,6 +22,7 @@ var __spreadValues = (a, b) => {
22
22
  return a;
23
23
  };
24
24
  var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
25
+ var __restKey = (key) => typeof key === "symbol" ? key : key + "";
25
26
  var __objRest = (source, exclude) => {
26
27
  var target = {};
27
28
  for (var prop in source)
@@ -84,7 +85,7 @@ __export(Popup_exports, {
84
85
  module.exports = __toCommonJS(Popup_exports);
85
86
 
86
87
  // src/components/chat/Chat.tsx
87
- var import_react8 = __toESM(require("react"));
88
+ var import_react9 = __toESM(require("react"));
88
89
 
89
90
  // src/components/chat/ChatContext.tsx
90
91
  var import_react = __toESM(require("react"));
@@ -190,6 +191,40 @@ var SpinnerIcon = /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
190
191
  ]
191
192
  }
192
193
  );
194
+ var SmallSpinnerIcon = /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
195
+ "svg",
196
+ {
197
+ style: {
198
+ animation: "copilotKitSpinAnimation 1s linear infinite"
199
+ },
200
+ width: "13",
201
+ height: "13",
202
+ xmlns: "http://www.w3.org/2000/svg",
203
+ fill: "none",
204
+ viewBox: "0 0 24 24",
205
+ children: [
206
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
207
+ "circle",
208
+ {
209
+ style: { opacity: 0.25 },
210
+ cx: "12",
211
+ cy: "12",
212
+ r: "10",
213
+ stroke: "currentColor",
214
+ strokeWidth: "4"
215
+ }
216
+ ),
217
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
218
+ "path",
219
+ {
220
+ style: { opacity: 0.75 },
221
+ fill: "currentColor",
222
+ d: "M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
223
+ }
224
+ )
225
+ ]
226
+ }
227
+ );
193
228
  var ActivityIcon = /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
194
229
  "svg",
195
230
  {
@@ -296,41 +331,42 @@ var ChatContextProvider = ({
296
331
  icons,
297
332
  children,
298
333
  open,
299
- setOpen
334
+ setOpen,
335
+ addChatSuggestionConfiguration,
336
+ removeChatSuggestionConfiguration
300
337
  }) => {
301
- const context = (0, import_react.useMemo)(
302
- () => ({
303
- labels: __spreadValues(__spreadValues({}, {
304
- initial: "",
305
- title: "CopilotKit",
306
- placeholder: "Type a message...",
307
- thinking: "Thinking...",
308
- error: "\u274C An error occurred. Please try again.",
309
- stopGenerating: "Stop generating",
310
- regenerateResponse: "Regenerate response"
311
- }), labels),
312
- icons: __spreadProps(__spreadValues({}, {
313
- openIcon: OpenIcon,
314
- closeIcon: CloseIcon,
315
- headerCloseIcon: HeaderCloseIcon,
316
- sendIcon: SendIcon,
317
- activityIcon: ActivityIcon,
318
- spinnerIcon: SpinnerIcon,
319
- stopIcon: StopIcon,
320
- regenerateIcon: RegenerateIcon
321
- }), {
322
- icons
323
- }),
324
- open,
325
- setOpen
338
+ const context = {
339
+ labels: __spreadValues(__spreadValues({}, {
340
+ initial: "",
341
+ title: "CopilotKit",
342
+ placeholder: "Type a message...",
343
+ thinking: "Thinking...",
344
+ error: "\u274C An error occurred. Please try again.",
345
+ stopGenerating: "Stop generating",
346
+ regenerateResponse: "Regenerate response"
347
+ }), labels),
348
+ icons: __spreadProps(__spreadValues({}, {
349
+ openIcon: OpenIcon,
350
+ closeIcon: CloseIcon,
351
+ headerCloseIcon: HeaderCloseIcon,
352
+ sendIcon: SendIcon,
353
+ activityIcon: ActivityIcon,
354
+ spinnerIcon: SpinnerIcon,
355
+ stopIcon: StopIcon,
356
+ regenerateIcon: RegenerateIcon
357
+ }), {
358
+ icons
326
359
  }),
327
- [labels, icons, open, setOpen]
328
- );
360
+ open,
361
+ setOpen,
362
+ addChatSuggestionConfiguration,
363
+ removeChatSuggestionConfiguration
364
+ };
329
365
  return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(ChatContext.Provider, { value: context, children });
330
366
  };
331
367
 
332
368
  // src/components/chat/Chat.tsx
333
- var import_react_core2 = require("@copilotkit/react-core");
369
+ var import_react_core3 = require("@copilotkit/react-core");
334
370
 
335
371
  // src/components/chat/Window.tsx
336
372
  var import_react2 = __toESM(require("react"));
@@ -439,10 +475,38 @@ function isMacOS() {
439
475
  }
440
476
 
441
477
  // src/components/chat/Button.tsx
478
+ var import_react3 = require("react");
442
479
  var import_jsx_runtime4 = require("react/jsx-runtime");
443
- var Button = ({ open, setOpen }) => {
480
+ var Button = ({ open, setOpen, pushToTalk, setPushToTalk }) => {
444
481
  const context = useChatContext();
445
- return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { onClick: () => setOpen(!open), children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
482
+ const timerRef = (0, import_react3.useRef)(null);
483
+ const [isLongPress, setIsLongPress] = (0, import_react3.useState)(false);
484
+ const handleMouseDown = () => {
485
+ timerRef.current = setTimeout(() => {
486
+ setPushToTalk(true);
487
+ setIsLongPress(true);
488
+ }, 500);
489
+ };
490
+ const handleMouseUp = () => {
491
+ if (timerRef.current) {
492
+ clearTimeout(timerRef.current);
493
+ setPushToTalk(false);
494
+ }
495
+ };
496
+ const handleClick = () => {
497
+ if (!isLongPress) {
498
+ setOpen(!open);
499
+ } else {
500
+ setIsLongPress(false);
501
+ }
502
+ };
503
+ (0, import_react3.useEffect)(() => {
504
+ document.addEventListener("mouseup", handleMouseUp);
505
+ return () => {
506
+ document.removeEventListener("mouseup", handleMouseUp);
507
+ };
508
+ }, []);
509
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { onClick: handleClick, onMouseDown: handleMouseDown, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
446
510
  "button",
447
511
  {
448
512
  className: `copilotKitButton ${open ? "open" : ""}`,
@@ -466,16 +530,16 @@ var Header = ({ setOpen }) => {
466
530
  };
467
531
 
468
532
  // src/components/chat/Messages.tsx
469
- var import_react5 = __toESM(require("react"));
533
+ var import_react6 = __toESM(require("react"));
470
534
  var import_nanoid = require("nanoid");
471
535
  var import_shared = require("@copilotkit/shared");
472
536
 
473
537
  // src/components/chat/Markdown.tsx
474
- var import_react4 = require("react");
538
+ var import_react5 = require("react");
475
539
  var import_react_markdown = __toESM(require("react-markdown"));
476
540
 
477
541
  // src/components/chat/CodeBlock.tsx
478
- var import_react3 = require("react");
542
+ var import_react4 = require("react");
479
543
  var import_react_syntax_highlighter = require("react-syntax-highlighter");
480
544
 
481
545
  // src/hooks/use-copy-to-clipboard.tsx
@@ -536,7 +600,7 @@ var generateRandomString = (length, lowercase = false) => {
536
600
  }
537
601
  return lowercase ? result.toLowerCase() : result;
538
602
  };
539
- var CodeBlock = (0, import_react3.memo)(({ language, value }) => {
603
+ var CodeBlock = (0, import_react4.memo)(({ language, value }) => {
540
604
  const { isCopied, copyToClipboard } = useCopyToClipboard({ timeout: 2e3 });
541
605
  const downloadAsFile = () => {
542
606
  if (typeof window === "undefined") {
@@ -882,7 +946,7 @@ var highlightStyle = {
882
946
  var import_remark_gfm = __toESM(require("remark-gfm"));
883
947
  var import_remark_math = __toESM(require("remark-math"));
884
948
  var import_jsx_runtime7 = require("react/jsx-runtime");
885
- var MemoizedReactMarkdown = (0, import_react4.memo)(
949
+ var MemoizedReactMarkdown = (0, import_react5.memo)(
886
950
  import_react_markdown.default,
887
951
  (prevProps, nextProps) => prevProps.children === nextProps.children && prevProps.className === nextProps.className
888
952
  );
@@ -941,10 +1005,10 @@ var components = {
941
1005
  // src/components/chat/Messages.tsx
942
1006
  var import_react_core = require("@copilotkit/react-core");
943
1007
  var import_jsx_runtime8 = require("react/jsx-runtime");
944
- var Messages = ({ messages, inProgress }) => {
1008
+ var Messages = ({ messages, inProgress, children }) => {
945
1009
  const { chatComponentsCache } = (0, import_react_core.useCopilotContext)();
946
1010
  const context = useChatContext();
947
- const initialMessages = (0, import_react5.useMemo)(
1011
+ const initialMessages = (0, import_react6.useMemo)(
948
1012
  () => makeInitialMessages(context.labels.initial),
949
1013
  [context.labels.initial]
950
1014
  );
@@ -958,7 +1022,7 @@ var Messages = ({ messages, inProgress }) => {
958
1022
  }
959
1023
  }
960
1024
  }
961
- const messagesEndRef = import_react5.default.useRef(null);
1025
+ const messagesEndRef = import_react6.default.useRef(null);
962
1026
  const scrollToBottom = () => {
963
1027
  if (messagesEndRef.current) {
964
1028
  messagesEndRef.current.scrollIntoView({
@@ -966,7 +1030,7 @@ var Messages = ({ messages, inProgress }) => {
966
1030
  });
967
1031
  }
968
1032
  };
969
- (0, import_react5.useEffect)(() => {
1033
+ (0, import_react6.useEffect)(() => {
970
1034
  scrollToBottom();
971
1035
  }, [messages]);
972
1036
  return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "copilotKitMessages", children: [
@@ -1027,7 +1091,7 @@ var Messages = ({ messages, inProgress }) => {
1027
1091
  return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: `copilotKitMessage copilotKitAssistantMessage`, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Markdown, { content: message.content }) }, index);
1028
1092
  }
1029
1093
  }),
1030
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { ref: messagesEndRef })
1094
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("footer", { ref: messagesEndRef, children })
1031
1095
  ] });
1032
1096
  };
1033
1097
  function makeInitialMessages(initial) {
@@ -1047,17 +1111,17 @@ function makeInitialMessages(initial) {
1047
1111
  }
1048
1112
 
1049
1113
  // src/components/chat/Input.tsx
1050
- var import_react7 = require("react");
1114
+ var import_react8 = require("react");
1051
1115
 
1052
1116
  // src/components/chat/Textarea.tsx
1053
- var import_react6 = require("react");
1117
+ var import_react7 = require("react");
1054
1118
  var import_jsx_runtime9 = require("react/jsx-runtime");
1055
- var AutoResizingTextarea = (0, import_react6.forwardRef)(
1119
+ var AutoResizingTextarea = (0, import_react7.forwardRef)(
1056
1120
  ({ maxRows = 1, placeholder, value, onChange, onKeyDown, autoFocus }, ref) => {
1057
- const internalTextareaRef = (0, import_react6.useRef)(null);
1058
- const [maxHeight, setMaxHeight] = (0, import_react6.useState)(0);
1059
- (0, import_react6.useImperativeHandle)(ref, () => internalTextareaRef.current);
1060
- (0, import_react6.useEffect)(() => {
1121
+ const internalTextareaRef = (0, import_react7.useRef)(null);
1122
+ const [maxHeight, setMaxHeight] = (0, import_react7.useState)(0);
1123
+ (0, import_react7.useImperativeHandle)(ref, () => internalTextareaRef.current);
1124
+ (0, import_react7.useEffect)(() => {
1061
1125
  const calculateMaxHeight = () => {
1062
1126
  const textarea = internalTextareaRef.current;
1063
1127
  if (textarea) {
@@ -1071,7 +1135,7 @@ var AutoResizingTextarea = (0, import_react6.forwardRef)(
1071
1135
  };
1072
1136
  calculateMaxHeight();
1073
1137
  }, [maxRows]);
1074
- (0, import_react6.useEffect)(() => {
1138
+ (0, import_react7.useEffect)(() => {
1075
1139
  const textarea = internalTextareaRef.current;
1076
1140
  if (textarea) {
1077
1141
  textarea.style.height = "auto";
@@ -1100,16 +1164,16 @@ var Textarea_default = AutoResizingTextarea;
1100
1164
 
1101
1165
  // src/components/chat/Input.tsx
1102
1166
  var import_jsx_runtime10 = require("react/jsx-runtime");
1103
- var Input = ({ inProgress, onSend, children, isVisible = false }) => {
1167
+ var Input = ({ inProgress, onSend, isVisible = false }) => {
1104
1168
  const context = useChatContext();
1105
- const textareaRef = (0, import_react7.useRef)(null);
1169
+ const textareaRef = (0, import_react8.useRef)(null);
1106
1170
  const handleDivClick = (event) => {
1107
1171
  var _a;
1108
1172
  if (event.target !== event.currentTarget)
1109
1173
  return;
1110
1174
  (_a = textareaRef.current) == null ? void 0 : _a.focus();
1111
1175
  };
1112
- const [text, setText] = (0, import_react7.useState)("");
1176
+ const [text, setText] = (0, import_react8.useState)("");
1113
1177
  const send = () => {
1114
1178
  var _a;
1115
1179
  if (inProgress)
@@ -1118,7 +1182,7 @@ var Input = ({ inProgress, onSend, children, isVisible = false }) => {
1118
1182
  setText("");
1119
1183
  (_a = textareaRef.current) == null ? void 0 : _a.focus();
1120
1184
  };
1121
- (0, import_react7.useEffect)(() => {
1185
+ (0, import_react8.useEffect)(() => {
1122
1186
  var _a;
1123
1187
  if (isVisible) {
1124
1188
  (_a = textareaRef.current) == null ? void 0 : _a.focus();
@@ -1127,7 +1191,6 @@ var Input = ({ inProgress, onSend, children, isVisible = false }) => {
1127
1191
  const icon = inProgress ? context.icons.activityIcon : context.icons.sendIcon;
1128
1192
  const disabled = inProgress || text.length === 0;
1129
1193
  return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "copilotKitInput", onClick: handleDivClick, children: [
1130
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { children }),
1131
1194
  /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("button", { className: "copilotKitSendButton", disabled, onClick: send, children: icon }),
1132
1195
  /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
1133
1196
  Textarea_default,
@@ -1162,8 +1225,105 @@ var ResponseButton = ({ onClick, inProgress }) => {
1162
1225
  ] });
1163
1226
  };
1164
1227
 
1165
- // src/components/chat/Chat.tsx
1228
+ // src/components/chat/Suggestion.tsx
1229
+ var import_react_core2 = require("@copilotkit/react-core");
1166
1230
  var import_jsx_runtime12 = require("react/jsx-runtime");
1231
+ function Suggestion({ title, message, onClick, partial, className }) {
1232
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
1233
+ "button",
1234
+ {
1235
+ disabled: partial,
1236
+ onClick: (e) => {
1237
+ e.preventDefault();
1238
+ onClick(message);
1239
+ },
1240
+ className: className || "suggestion",
1241
+ children: [
1242
+ partial && SmallSpinnerIcon,
1243
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { children: title })
1244
+ ]
1245
+ }
1246
+ );
1247
+ }
1248
+ var reloadSuggestions = (context, chatSuggestionConfiguration, setCurrentSuggestions, abortControllerRef) => __async(void 0, null, function* () {
1249
+ const abortController = abortControllerRef.current;
1250
+ const tools = JSON.stringify(context.getChatCompletionFunctionDescriptions(context.entryPoints));
1251
+ const allSuggestions = [];
1252
+ for (const config of Object.values(chatSuggestionConfiguration)) {
1253
+ try {
1254
+ const numOfSuggestionsInstructions = config.minSuggestions === 0 ? `Produce up to ${config.maxSuggestions} suggestions. If there are no highly relevant suggestions you can think of, provide an empty array.` : `Produce between ${config.minSuggestions} and ${config.maxSuggestions} suggestions.`;
1255
+ const result = yield (0, import_react_core2.extract)({
1256
+ context,
1257
+ instructions: "Suggest what the user could say next. Provide clear, highly relevant suggestions. Do not literally suggest function calls. " + config.instructions + "\n\n" + numOfSuggestionsInstructions,
1258
+ data: "Available tools: " + tools + "\n\n",
1259
+ parameters: [
1260
+ {
1261
+ name: "suggestions",
1262
+ type: "object[]",
1263
+ attributes: [
1264
+ {
1265
+ name: "title",
1266
+ description: "The title of the suggestion. This is shown as a button and should be short.",
1267
+ type: "string"
1268
+ },
1269
+ {
1270
+ name: "message",
1271
+ description: "The message to send when the suggestion is clicked. This should be a clear, complete sentence and will be sent as an instruction to the AI.",
1272
+ type: "string"
1273
+ }
1274
+ ]
1275
+ }
1276
+ ],
1277
+ include: {
1278
+ messages: true,
1279
+ readable: true
1280
+ },
1281
+ abortSignal: abortController == null ? void 0 : abortController.signal,
1282
+ stream: ({ status, args }) => {
1283
+ const suggestions = args.suggestions || [];
1284
+ const newSuggestions = [];
1285
+ for (let i = 0; i < suggestions.length; i++) {
1286
+ if (config.maxSuggestions !== void 0 && i >= config.maxSuggestions) {
1287
+ break;
1288
+ }
1289
+ const { title, message } = suggestions[i];
1290
+ const partial = i == suggestions.length - 1 && status !== "complete";
1291
+ newSuggestions.push({
1292
+ title,
1293
+ message,
1294
+ partial,
1295
+ className: config.className
1296
+ });
1297
+ }
1298
+ setCurrentSuggestions([...allSuggestions, ...newSuggestions]);
1299
+ }
1300
+ });
1301
+ allSuggestions.push(...result.suggestions);
1302
+ } catch (error) {
1303
+ console.error("Error loading suggestions", error);
1304
+ }
1305
+ }
1306
+ if (abortControllerRef.current === abortController) {
1307
+ abortControllerRef.current = null;
1308
+ }
1309
+ });
1310
+
1311
+ // src/components/chat/audio.ts
1312
+ var requestMicAndPlaybackPermission = () => __async(void 0, null, function* () {
1313
+ try {
1314
+ const stream = yield navigator.mediaDevices.getUserMedia({ audio: true });
1315
+ const audioContext = new window.AudioContext();
1316
+ yield audioContext.resume();
1317
+ return { stream, audioContext };
1318
+ } catch (err) {
1319
+ console.error("Error requesting microphone and playback permissions", err);
1320
+ return null;
1321
+ }
1322
+ });
1323
+
1324
+ // src/components/chat/Chat.tsx
1325
+ var import_jsx_runtime13 = require("react/jsx-runtime");
1326
+ var SUGGESTIONS_DEBOUNCE_TIMEOUT = 1e3;
1167
1327
  var CopilotChat = ({
1168
1328
  instructions,
1169
1329
  defaultOpen = false,
@@ -1186,58 +1346,209 @@ var CopilotChat = ({
1186
1346
  className,
1187
1347
  children
1188
1348
  }) => {
1189
- const { visibleMessages, append, reload, stop, isLoading, input, setInput } = (0, import_react_core2.useCopilotChat)({
1349
+ const { visibleMessages, append, reload, stop, isLoading, input, setInput } = (0, import_react_core3.useCopilotChat)({
1190
1350
  id: (0, import_nanoid2.nanoid)(),
1191
1351
  makeSystemMessage,
1192
1352
  additionalInstructions: instructions
1193
1353
  });
1194
- (0, import_react8.useEffect)(() => {
1354
+ const [currentSuggestions, setCurrentSuggestions] = import_react9.default.useState([]);
1355
+ const suggestionsAbortControllerRef = (0, import_react9.useRef)(null);
1356
+ const debounceTimerRef = (0, import_react9.useRef)();
1357
+ const abortSuggestions = () => {
1358
+ var _a;
1359
+ (_a = suggestionsAbortControllerRef.current) == null ? void 0 : _a.abort();
1360
+ suggestionsAbortControllerRef.current = null;
1361
+ };
1362
+ const context = (0, import_react_core3.useCopilotContext)();
1363
+ const [chatSuggestionConfiguration, setChatSuggestionConfiguration] = (0, import_react9.useState)({});
1364
+ const addChatSuggestionConfiguration = (id, suggestion) => {
1365
+ setChatSuggestionConfiguration((prev) => __spreadProps(__spreadValues({}, prev), { [id]: suggestion }));
1366
+ };
1367
+ const removeChatSuggestion = (id) => {
1368
+ setChatSuggestionConfiguration((prev) => {
1369
+ const _a = prev, { [id]: _ } = _a, rest = __objRest(_a, [__restKey(id)]);
1370
+ return rest;
1371
+ });
1372
+ };
1373
+ (0, import_react9.useEffect)(() => {
1195
1374
  onInProgress == null ? void 0 : onInProgress(isLoading);
1196
- }, [isLoading]);
1197
- const [openState, setOpenState] = import_react8.default.useState(defaultOpen);
1375
+ abortSuggestions();
1376
+ debounceTimerRef.current = setTimeout(
1377
+ () => {
1378
+ if (!isLoading && Object.keys(chatSuggestionConfiguration).length !== 0) {
1379
+ suggestionsAbortControllerRef.current = new AbortController();
1380
+ reloadSuggestions(
1381
+ context,
1382
+ chatSuggestionConfiguration,
1383
+ setCurrentSuggestions,
1384
+ suggestionsAbortControllerRef
1385
+ );
1386
+ }
1387
+ },
1388
+ currentSuggestions.length == 0 ? 0 : SUGGESTIONS_DEBOUNCE_TIMEOUT
1389
+ );
1390
+ return () => {
1391
+ clearTimeout(debounceTimerRef.current);
1392
+ };
1393
+ }, [isLoading, chatSuggestionConfiguration]);
1198
1394
  const setOpen = (open) => {
1199
1395
  onSetOpen == null ? void 0 : onSetOpen(open);
1200
1396
  setOpenState(open);
1201
1397
  };
1202
- const sendMessage = (message) => __async(void 0, null, function* () {
1203
- onSubmitMessage == null ? void 0 : onSubmitMessage(message);
1204
- append({
1398
+ const sendMessage = (messageContent) => __async(void 0, null, function* () {
1399
+ abortSuggestions();
1400
+ setCurrentSuggestions([]);
1401
+ onSubmitMessage == null ? void 0 : onSubmitMessage(messageContent);
1402
+ const message = {
1205
1403
  id: (0, import_nanoid2.nanoid)(),
1206
- content: message,
1404
+ content: messageContent,
1207
1405
  role: "user"
1208
- });
1406
+ };
1407
+ append(message);
1408
+ return message;
1209
1409
  });
1210
- return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(ChatContextProvider, { icons, labels, open: openState, setOpen: setOpenState, children: [
1211
- children,
1212
- /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className, children: [
1213
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Button2, { open: openState, setOpen }),
1214
- /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
1215
- Window2,
1216
- {
1217
- open: openState,
1218
- setOpen,
1219
- clickOutsideToClose,
1220
- shortcut,
1221
- hitEscapeToClose,
1222
- children: [
1223
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Header2, { open: openState, setOpen }),
1224
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Messages2, { messages: visibleMessages, inProgress: isLoading }),
1225
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Input2, { inProgress: isLoading, onSend: sendMessage, isVisible: openState, children: showResponseButton && visibleMessages.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(ResponseButton2, { onClick: isLoading ? stop : reload, inProgress: isLoading }) })
1226
- ]
1227
- }
1228
- )
1229
- ] })
1230
- ] });
1410
+ const [openState, setOpenState] = import_react9.default.useState(defaultOpen);
1411
+ const [pushToTalkState, setPushToTalkState] = import_react9.default.useState(false);
1412
+ const mediaStreamRef = (0, import_react9.useRef)(null);
1413
+ const audioContextRef = (0, import_react9.useRef)(null);
1414
+ const mediaRecorderRef = (0, import_react9.useRef)(null);
1415
+ const [lastMessageIdBeforeAudio, setLastMessageIdBeforeAudio] = (0, import_react9.useState)(null);
1416
+ (0, import_react9.useEffect)(() => {
1417
+ if (pushToTalkState) {
1418
+ console.log("HERE");
1419
+ if (!mediaStreamRef.current || !audioContextRef.current) {
1420
+ setPushToTalkState(false);
1421
+ requestMicAndPlaybackPermission().then((res) => {
1422
+ if (res) {
1423
+ mediaStreamRef.current = res.stream;
1424
+ audioContextRef.current = res.audioContext;
1425
+ }
1426
+ });
1427
+ } else {
1428
+ console.log("Recording started");
1429
+ const recordedChunks = [];
1430
+ mediaRecorderRef.current = new MediaRecorder(mediaStreamRef.current);
1431
+ mediaRecorderRef.current.start(1e3);
1432
+ mediaRecorderRef.current.ondataavailable = (event) => __async(void 0, null, function* () {
1433
+ console.log("Recorded audio: ", event.data);
1434
+ recordedChunks.push(event.data);
1435
+ });
1436
+ mediaRecorderRef.current.onstop = () => __async(void 0, null, function* () {
1437
+ console.log("Recording stopped");
1438
+ const completeBlob = new Blob(recordedChunks, { type: "audio/mp4" });
1439
+ const formData = new FormData();
1440
+ formData.append("file", completeBlob, "recording.mp4");
1441
+ const response = yield fetch(context.copilotApiConfig.transcribeAudioUrl, {
1442
+ method: "POST",
1443
+ body: formData
1444
+ });
1445
+ if (!response.ok) {
1446
+ throw new Error(`Error: ${response.statusText}`);
1447
+ }
1448
+ const transcription = yield response.json();
1449
+ const message = yield sendMessage(transcription.text);
1450
+ setLastMessageIdBeforeAudio(message.id);
1451
+ });
1452
+ }
1453
+ } else {
1454
+ if (mediaRecorderRef.current && mediaRecorderRef.current.state !== "inactive") {
1455
+ mediaRecorderRef.current.stop();
1456
+ }
1457
+ }
1458
+ return () => {
1459
+ if (mediaRecorderRef.current && mediaRecorderRef.current.state !== "inactive") {
1460
+ mediaRecorderRef.current.stop();
1461
+ }
1462
+ };
1463
+ }, [pushToTalkState]);
1464
+ (0, import_react9.useEffect)(() => {
1465
+ if (lastMessageIdBeforeAudio && !isLoading) {
1466
+ if (audioContextRef.current) {
1467
+ const lastMessageIndex = context.messages.findIndex(
1468
+ (message) => message.id === lastMessageIdBeforeAudio
1469
+ );
1470
+ const messagesAfterLast = context.messages.slice(lastMessageIndex + 1).filter((message) => message.role === "assistant" && message.content);
1471
+ const text = messagesAfterLast.map((message) => message.content).join("\n");
1472
+ const encodedText = encodeURIComponent(text);
1473
+ const url = `${context.copilotApiConfig.textToSpeechUrl}?text=${encodedText}`;
1474
+ fetch(url).then((response) => response.arrayBuffer()).then((arrayBuffer) => audioContextRef.current.decodeAudioData(arrayBuffer)).then((audioBuffer) => {
1475
+ const source = audioContextRef.current.createBufferSource();
1476
+ source.buffer = audioBuffer;
1477
+ source.connect(audioContextRef.current.destination);
1478
+ source.start(0);
1479
+ }).catch((error) => {
1480
+ console.error("Error with decoding audio data", error);
1481
+ });
1482
+ setLastMessageIdBeforeAudio(null);
1483
+ }
1484
+ }
1485
+ }, [isLoading]);
1486
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
1487
+ ChatContextProvider,
1488
+ {
1489
+ icons,
1490
+ labels,
1491
+ open: openState,
1492
+ setOpen: setOpenState,
1493
+ addChatSuggestionConfiguration,
1494
+ removeChatSuggestionConfiguration: removeChatSuggestion,
1495
+ children: [
1496
+ children,
1497
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className, children: [
1498
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
1499
+ Button2,
1500
+ {
1501
+ open: openState,
1502
+ setOpen,
1503
+ pushToTalk: pushToTalkState,
1504
+ setPushToTalk: setPushToTalkState
1505
+ }
1506
+ ),
1507
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
1508
+ Window2,
1509
+ {
1510
+ open: openState,
1511
+ setOpen,
1512
+ clickOutsideToClose,
1513
+ shortcut,
1514
+ hitEscapeToClose,
1515
+ children: [
1516
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Header2, { open: openState, setOpen }),
1517
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(Messages2, { messages: visibleMessages, inProgress: isLoading, children: [
1518
+ currentSuggestions.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { children: [
1519
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("h6", { children: "Suggested:" }),
1520
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "suggestions", children: currentSuggestions.map((suggestion, index) => /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
1521
+ Suggestion,
1522
+ {
1523
+ title: suggestion.title,
1524
+ message: suggestion.message,
1525
+ partial: suggestion.partial,
1526
+ className: suggestion.className,
1527
+ onClick: (message) => sendMessage(message)
1528
+ },
1529
+ index
1530
+ )) })
1531
+ ] }),
1532
+ showResponseButton && visibleMessages.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(ResponseButton2, { onClick: isLoading ? stop : reload, inProgress: isLoading })
1533
+ ] }),
1534
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Input2, { inProgress: isLoading, onSend: sendMessage, isVisible: openState })
1535
+ ]
1536
+ }
1537
+ )
1538
+ ] })
1539
+ ]
1540
+ }
1541
+ );
1231
1542
  };
1232
1543
 
1233
1544
  // src/components/chat/Popup.tsx
1234
- var import_jsx_runtime13 = require("react/jsx-runtime");
1235
- var CopilotPopup = (props) => {
1545
+ var import_jsx_runtime14 = require("react/jsx-runtime");
1546
+ function CopilotPopup(props) {
1236
1547
  props = __spreadProps(__spreadValues({}, props), {
1237
1548
  className: props.className ? props.className + " copilotKitPopup" : "copilotKitPopup"
1238
1549
  });
1239
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(CopilotChat, __spreadProps(__spreadValues({}, props), { children: props.children }));
1240
- };
1550
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(CopilotChat, __spreadProps(__spreadValues({}, props), { children: props.children }));
1551
+ }
1241
1552
  // Annotate the CommonJS export names for ESM import in node:
1242
1553
  0 && (module.exports = {
1243
1554
  CopilotPopup