@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)
@@ -82,10 +83,10 @@ __export(Sidebar_exports, {
82
83
  CopilotSidebar: () => CopilotSidebar
83
84
  });
84
85
  module.exports = __toCommonJS(Sidebar_exports);
85
- var import_react9 = require("react");
86
+ var import_react10 = require("react");
86
87
 
87
88
  // src/components/chat/Chat.tsx
88
- var import_react8 = __toESM(require("react"));
89
+ var import_react9 = __toESM(require("react"));
89
90
 
90
91
  // src/components/chat/ChatContext.tsx
91
92
  var import_react = __toESM(require("react"));
@@ -191,6 +192,40 @@ var SpinnerIcon = /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
191
192
  ]
192
193
  }
193
194
  );
195
+ var SmallSpinnerIcon = /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
196
+ "svg",
197
+ {
198
+ style: {
199
+ animation: "copilotKitSpinAnimation 1s linear infinite"
200
+ },
201
+ width: "13",
202
+ height: "13",
203
+ xmlns: "http://www.w3.org/2000/svg",
204
+ fill: "none",
205
+ viewBox: "0 0 24 24",
206
+ children: [
207
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
208
+ "circle",
209
+ {
210
+ style: { opacity: 0.25 },
211
+ cx: "12",
212
+ cy: "12",
213
+ r: "10",
214
+ stroke: "currentColor",
215
+ strokeWidth: "4"
216
+ }
217
+ ),
218
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
219
+ "path",
220
+ {
221
+ style: { opacity: 0.75 },
222
+ fill: "currentColor",
223
+ 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"
224
+ }
225
+ )
226
+ ]
227
+ }
228
+ );
194
229
  var ActivityIcon = /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
195
230
  "svg",
196
231
  {
@@ -297,41 +332,42 @@ var ChatContextProvider = ({
297
332
  icons,
298
333
  children,
299
334
  open,
300
- setOpen
335
+ setOpen,
336
+ addChatSuggestionConfiguration,
337
+ removeChatSuggestionConfiguration
301
338
  }) => {
302
- const context = (0, import_react.useMemo)(
303
- () => ({
304
- labels: __spreadValues(__spreadValues({}, {
305
- initial: "",
306
- title: "CopilotKit",
307
- placeholder: "Type a message...",
308
- thinking: "Thinking...",
309
- error: "\u274C An error occurred. Please try again.",
310
- stopGenerating: "Stop generating",
311
- regenerateResponse: "Regenerate response"
312
- }), labels),
313
- icons: __spreadProps(__spreadValues({}, {
314
- openIcon: OpenIcon,
315
- closeIcon: CloseIcon,
316
- headerCloseIcon: HeaderCloseIcon,
317
- sendIcon: SendIcon,
318
- activityIcon: ActivityIcon,
319
- spinnerIcon: SpinnerIcon,
320
- stopIcon: StopIcon,
321
- regenerateIcon: RegenerateIcon
322
- }), {
323
- icons
324
- }),
325
- open,
326
- setOpen
339
+ const context = {
340
+ labels: __spreadValues(__spreadValues({}, {
341
+ initial: "",
342
+ title: "CopilotKit",
343
+ placeholder: "Type a message...",
344
+ thinking: "Thinking...",
345
+ error: "\u274C An error occurred. Please try again.",
346
+ stopGenerating: "Stop generating",
347
+ regenerateResponse: "Regenerate response"
348
+ }), labels),
349
+ icons: __spreadProps(__spreadValues({}, {
350
+ openIcon: OpenIcon,
351
+ closeIcon: CloseIcon,
352
+ headerCloseIcon: HeaderCloseIcon,
353
+ sendIcon: SendIcon,
354
+ activityIcon: ActivityIcon,
355
+ spinnerIcon: SpinnerIcon,
356
+ stopIcon: StopIcon,
357
+ regenerateIcon: RegenerateIcon
358
+ }), {
359
+ icons
327
360
  }),
328
- [labels, icons, open, setOpen]
329
- );
361
+ open,
362
+ setOpen,
363
+ addChatSuggestionConfiguration,
364
+ removeChatSuggestionConfiguration
365
+ };
330
366
  return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(ChatContext.Provider, { value: context, children });
331
367
  };
332
368
 
333
369
  // src/components/chat/Chat.tsx
334
- var import_react_core2 = require("@copilotkit/react-core");
370
+ var import_react_core3 = require("@copilotkit/react-core");
335
371
 
336
372
  // src/components/chat/Window.tsx
337
373
  var import_react2 = __toESM(require("react"));
@@ -440,10 +476,38 @@ function isMacOS() {
440
476
  }
441
477
 
442
478
  // src/components/chat/Button.tsx
479
+ var import_react3 = require("react");
443
480
  var import_jsx_runtime4 = require("react/jsx-runtime");
444
- var Button = ({ open, setOpen }) => {
481
+ var Button = ({ open, setOpen, pushToTalk, setPushToTalk }) => {
445
482
  const context = useChatContext();
446
- return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { onClick: () => setOpen(!open), children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
483
+ const timerRef = (0, import_react3.useRef)(null);
484
+ const [isLongPress, setIsLongPress] = (0, import_react3.useState)(false);
485
+ const handleMouseDown = () => {
486
+ timerRef.current = setTimeout(() => {
487
+ setPushToTalk(true);
488
+ setIsLongPress(true);
489
+ }, 500);
490
+ };
491
+ const handleMouseUp = () => {
492
+ if (timerRef.current) {
493
+ clearTimeout(timerRef.current);
494
+ setPushToTalk(false);
495
+ }
496
+ };
497
+ const handleClick = () => {
498
+ if (!isLongPress) {
499
+ setOpen(!open);
500
+ } else {
501
+ setIsLongPress(false);
502
+ }
503
+ };
504
+ (0, import_react3.useEffect)(() => {
505
+ document.addEventListener("mouseup", handleMouseUp);
506
+ return () => {
507
+ document.removeEventListener("mouseup", handleMouseUp);
508
+ };
509
+ }, []);
510
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { onClick: handleClick, onMouseDown: handleMouseDown, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
447
511
  "button",
448
512
  {
449
513
  className: `copilotKitButton ${open ? "open" : ""}`,
@@ -467,16 +531,16 @@ var Header = ({ setOpen }) => {
467
531
  };
468
532
 
469
533
  // src/components/chat/Messages.tsx
470
- var import_react5 = __toESM(require("react"));
534
+ var import_react6 = __toESM(require("react"));
471
535
  var import_nanoid = require("nanoid");
472
536
  var import_shared = require("@copilotkit/shared");
473
537
 
474
538
  // src/components/chat/Markdown.tsx
475
- var import_react4 = require("react");
539
+ var import_react5 = require("react");
476
540
  var import_react_markdown = __toESM(require("react-markdown"));
477
541
 
478
542
  // src/components/chat/CodeBlock.tsx
479
- var import_react3 = require("react");
543
+ var import_react4 = require("react");
480
544
  var import_react_syntax_highlighter = require("react-syntax-highlighter");
481
545
 
482
546
  // src/hooks/use-copy-to-clipboard.tsx
@@ -537,7 +601,7 @@ var generateRandomString = (length, lowercase = false) => {
537
601
  }
538
602
  return lowercase ? result.toLowerCase() : result;
539
603
  };
540
- var CodeBlock = (0, import_react3.memo)(({ language, value }) => {
604
+ var CodeBlock = (0, import_react4.memo)(({ language, value }) => {
541
605
  const { isCopied, copyToClipboard } = useCopyToClipboard({ timeout: 2e3 });
542
606
  const downloadAsFile = () => {
543
607
  if (typeof window === "undefined") {
@@ -883,7 +947,7 @@ var highlightStyle = {
883
947
  var import_remark_gfm = __toESM(require("remark-gfm"));
884
948
  var import_remark_math = __toESM(require("remark-math"));
885
949
  var import_jsx_runtime7 = require("react/jsx-runtime");
886
- var MemoizedReactMarkdown = (0, import_react4.memo)(
950
+ var MemoizedReactMarkdown = (0, import_react5.memo)(
887
951
  import_react_markdown.default,
888
952
  (prevProps, nextProps) => prevProps.children === nextProps.children && prevProps.className === nextProps.className
889
953
  );
@@ -942,10 +1006,10 @@ var components = {
942
1006
  // src/components/chat/Messages.tsx
943
1007
  var import_react_core = require("@copilotkit/react-core");
944
1008
  var import_jsx_runtime8 = require("react/jsx-runtime");
945
- var Messages = ({ messages, inProgress }) => {
1009
+ var Messages = ({ messages, inProgress, children }) => {
946
1010
  const { chatComponentsCache } = (0, import_react_core.useCopilotContext)();
947
1011
  const context = useChatContext();
948
- const initialMessages = (0, import_react5.useMemo)(
1012
+ const initialMessages = (0, import_react6.useMemo)(
949
1013
  () => makeInitialMessages(context.labels.initial),
950
1014
  [context.labels.initial]
951
1015
  );
@@ -959,7 +1023,7 @@ var Messages = ({ messages, inProgress }) => {
959
1023
  }
960
1024
  }
961
1025
  }
962
- const messagesEndRef = import_react5.default.useRef(null);
1026
+ const messagesEndRef = import_react6.default.useRef(null);
963
1027
  const scrollToBottom = () => {
964
1028
  if (messagesEndRef.current) {
965
1029
  messagesEndRef.current.scrollIntoView({
@@ -967,7 +1031,7 @@ var Messages = ({ messages, inProgress }) => {
967
1031
  });
968
1032
  }
969
1033
  };
970
- (0, import_react5.useEffect)(() => {
1034
+ (0, import_react6.useEffect)(() => {
971
1035
  scrollToBottom();
972
1036
  }, [messages]);
973
1037
  return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "copilotKitMessages", children: [
@@ -1028,7 +1092,7 @@ var Messages = ({ messages, inProgress }) => {
1028
1092
  return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: `copilotKitMessage copilotKitAssistantMessage`, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Markdown, { content: message.content }) }, index);
1029
1093
  }
1030
1094
  }),
1031
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { ref: messagesEndRef })
1095
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("footer", { ref: messagesEndRef, children })
1032
1096
  ] });
1033
1097
  };
1034
1098
  function makeInitialMessages(initial) {
@@ -1048,17 +1112,17 @@ function makeInitialMessages(initial) {
1048
1112
  }
1049
1113
 
1050
1114
  // src/components/chat/Input.tsx
1051
- var import_react7 = require("react");
1115
+ var import_react8 = require("react");
1052
1116
 
1053
1117
  // src/components/chat/Textarea.tsx
1054
- var import_react6 = require("react");
1118
+ var import_react7 = require("react");
1055
1119
  var import_jsx_runtime9 = require("react/jsx-runtime");
1056
- var AutoResizingTextarea = (0, import_react6.forwardRef)(
1120
+ var AutoResizingTextarea = (0, import_react7.forwardRef)(
1057
1121
  ({ maxRows = 1, placeholder, value, onChange, onKeyDown, autoFocus }, ref) => {
1058
- const internalTextareaRef = (0, import_react6.useRef)(null);
1059
- const [maxHeight, setMaxHeight] = (0, import_react6.useState)(0);
1060
- (0, import_react6.useImperativeHandle)(ref, () => internalTextareaRef.current);
1061
- (0, import_react6.useEffect)(() => {
1122
+ const internalTextareaRef = (0, import_react7.useRef)(null);
1123
+ const [maxHeight, setMaxHeight] = (0, import_react7.useState)(0);
1124
+ (0, import_react7.useImperativeHandle)(ref, () => internalTextareaRef.current);
1125
+ (0, import_react7.useEffect)(() => {
1062
1126
  const calculateMaxHeight = () => {
1063
1127
  const textarea = internalTextareaRef.current;
1064
1128
  if (textarea) {
@@ -1072,7 +1136,7 @@ var AutoResizingTextarea = (0, import_react6.forwardRef)(
1072
1136
  };
1073
1137
  calculateMaxHeight();
1074
1138
  }, [maxRows]);
1075
- (0, import_react6.useEffect)(() => {
1139
+ (0, import_react7.useEffect)(() => {
1076
1140
  const textarea = internalTextareaRef.current;
1077
1141
  if (textarea) {
1078
1142
  textarea.style.height = "auto";
@@ -1101,16 +1165,16 @@ var Textarea_default = AutoResizingTextarea;
1101
1165
 
1102
1166
  // src/components/chat/Input.tsx
1103
1167
  var import_jsx_runtime10 = require("react/jsx-runtime");
1104
- var Input = ({ inProgress, onSend, children, isVisible = false }) => {
1168
+ var Input = ({ inProgress, onSend, isVisible = false }) => {
1105
1169
  const context = useChatContext();
1106
- const textareaRef = (0, import_react7.useRef)(null);
1170
+ const textareaRef = (0, import_react8.useRef)(null);
1107
1171
  const handleDivClick = (event) => {
1108
1172
  var _a;
1109
1173
  if (event.target !== event.currentTarget)
1110
1174
  return;
1111
1175
  (_a = textareaRef.current) == null ? void 0 : _a.focus();
1112
1176
  };
1113
- const [text, setText] = (0, import_react7.useState)("");
1177
+ const [text, setText] = (0, import_react8.useState)("");
1114
1178
  const send = () => {
1115
1179
  var _a;
1116
1180
  if (inProgress)
@@ -1119,7 +1183,7 @@ var Input = ({ inProgress, onSend, children, isVisible = false }) => {
1119
1183
  setText("");
1120
1184
  (_a = textareaRef.current) == null ? void 0 : _a.focus();
1121
1185
  };
1122
- (0, import_react7.useEffect)(() => {
1186
+ (0, import_react8.useEffect)(() => {
1123
1187
  var _a;
1124
1188
  if (isVisible) {
1125
1189
  (_a = textareaRef.current) == null ? void 0 : _a.focus();
@@ -1128,7 +1192,6 @@ var Input = ({ inProgress, onSend, children, isVisible = false }) => {
1128
1192
  const icon = inProgress ? context.icons.activityIcon : context.icons.sendIcon;
1129
1193
  const disabled = inProgress || text.length === 0;
1130
1194
  return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "copilotKitInput", onClick: handleDivClick, children: [
1131
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { children }),
1132
1195
  /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("button", { className: "copilotKitSendButton", disabled, onClick: send, children: icon }),
1133
1196
  /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
1134
1197
  Textarea_default,
@@ -1163,8 +1226,105 @@ var ResponseButton = ({ onClick, inProgress }) => {
1163
1226
  ] });
1164
1227
  };
1165
1228
 
1166
- // src/components/chat/Chat.tsx
1229
+ // src/components/chat/Suggestion.tsx
1230
+ var import_react_core2 = require("@copilotkit/react-core");
1167
1231
  var import_jsx_runtime12 = require("react/jsx-runtime");
1232
+ function Suggestion({ title, message, onClick, partial, className }) {
1233
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
1234
+ "button",
1235
+ {
1236
+ disabled: partial,
1237
+ onClick: (e) => {
1238
+ e.preventDefault();
1239
+ onClick(message);
1240
+ },
1241
+ className: className || "suggestion",
1242
+ children: [
1243
+ partial && SmallSpinnerIcon,
1244
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { children: title })
1245
+ ]
1246
+ }
1247
+ );
1248
+ }
1249
+ var reloadSuggestions = (context, chatSuggestionConfiguration, setCurrentSuggestions, abortControllerRef) => __async(void 0, null, function* () {
1250
+ const abortController = abortControllerRef.current;
1251
+ const tools = JSON.stringify(context.getChatCompletionFunctionDescriptions(context.entryPoints));
1252
+ const allSuggestions = [];
1253
+ for (const config of Object.values(chatSuggestionConfiguration)) {
1254
+ try {
1255
+ 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.`;
1256
+ const result = yield (0, import_react_core2.extract)({
1257
+ context,
1258
+ instructions: "Suggest what the user could say next. Provide clear, highly relevant suggestions. Do not literally suggest function calls. " + config.instructions + "\n\n" + numOfSuggestionsInstructions,
1259
+ data: "Available tools: " + tools + "\n\n",
1260
+ parameters: [
1261
+ {
1262
+ name: "suggestions",
1263
+ type: "object[]",
1264
+ attributes: [
1265
+ {
1266
+ name: "title",
1267
+ description: "The title of the suggestion. This is shown as a button and should be short.",
1268
+ type: "string"
1269
+ },
1270
+ {
1271
+ name: "message",
1272
+ 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.",
1273
+ type: "string"
1274
+ }
1275
+ ]
1276
+ }
1277
+ ],
1278
+ include: {
1279
+ messages: true,
1280
+ readable: true
1281
+ },
1282
+ abortSignal: abortController == null ? void 0 : abortController.signal,
1283
+ stream: ({ status, args }) => {
1284
+ const suggestions = args.suggestions || [];
1285
+ const newSuggestions = [];
1286
+ for (let i = 0; i < suggestions.length; i++) {
1287
+ if (config.maxSuggestions !== void 0 && i >= config.maxSuggestions) {
1288
+ break;
1289
+ }
1290
+ const { title, message } = suggestions[i];
1291
+ const partial = i == suggestions.length - 1 && status !== "complete";
1292
+ newSuggestions.push({
1293
+ title,
1294
+ message,
1295
+ partial,
1296
+ className: config.className
1297
+ });
1298
+ }
1299
+ setCurrentSuggestions([...allSuggestions, ...newSuggestions]);
1300
+ }
1301
+ });
1302
+ allSuggestions.push(...result.suggestions);
1303
+ } catch (error) {
1304
+ console.error("Error loading suggestions", error);
1305
+ }
1306
+ }
1307
+ if (abortControllerRef.current === abortController) {
1308
+ abortControllerRef.current = null;
1309
+ }
1310
+ });
1311
+
1312
+ // src/components/chat/audio.ts
1313
+ var requestMicAndPlaybackPermission = () => __async(void 0, null, function* () {
1314
+ try {
1315
+ const stream = yield navigator.mediaDevices.getUserMedia({ audio: true });
1316
+ const audioContext = new window.AudioContext();
1317
+ yield audioContext.resume();
1318
+ return { stream, audioContext };
1319
+ } catch (err) {
1320
+ console.error("Error requesting microphone and playback permissions", err);
1321
+ return null;
1322
+ }
1323
+ });
1324
+
1325
+ // src/components/chat/Chat.tsx
1326
+ var import_jsx_runtime13 = require("react/jsx-runtime");
1327
+ var SUGGESTIONS_DEBOUNCE_TIMEOUT = 1e3;
1168
1328
  var CopilotChat = ({
1169
1329
  instructions,
1170
1330
  defaultOpen = false,
@@ -1187,57 +1347,208 @@ var CopilotChat = ({
1187
1347
  className,
1188
1348
  children
1189
1349
  }) => {
1190
- const { visibleMessages, append, reload, stop, isLoading, input, setInput } = (0, import_react_core2.useCopilotChat)({
1350
+ const { visibleMessages, append, reload, stop, isLoading, input, setInput } = (0, import_react_core3.useCopilotChat)({
1191
1351
  id: (0, import_nanoid2.nanoid)(),
1192
1352
  makeSystemMessage,
1193
1353
  additionalInstructions: instructions
1194
1354
  });
1195
- (0, import_react8.useEffect)(() => {
1355
+ const [currentSuggestions, setCurrentSuggestions] = import_react9.default.useState([]);
1356
+ const suggestionsAbortControllerRef = (0, import_react9.useRef)(null);
1357
+ const debounceTimerRef = (0, import_react9.useRef)();
1358
+ const abortSuggestions = () => {
1359
+ var _a;
1360
+ (_a = suggestionsAbortControllerRef.current) == null ? void 0 : _a.abort();
1361
+ suggestionsAbortControllerRef.current = null;
1362
+ };
1363
+ const context = (0, import_react_core3.useCopilotContext)();
1364
+ const [chatSuggestionConfiguration, setChatSuggestionConfiguration] = (0, import_react9.useState)({});
1365
+ const addChatSuggestionConfiguration = (id, suggestion) => {
1366
+ setChatSuggestionConfiguration((prev) => __spreadProps(__spreadValues({}, prev), { [id]: suggestion }));
1367
+ };
1368
+ const removeChatSuggestion = (id) => {
1369
+ setChatSuggestionConfiguration((prev) => {
1370
+ const _a = prev, { [id]: _ } = _a, rest = __objRest(_a, [__restKey(id)]);
1371
+ return rest;
1372
+ });
1373
+ };
1374
+ (0, import_react9.useEffect)(() => {
1196
1375
  onInProgress == null ? void 0 : onInProgress(isLoading);
1197
- }, [isLoading]);
1198
- const [openState, setOpenState] = import_react8.default.useState(defaultOpen);
1376
+ abortSuggestions();
1377
+ debounceTimerRef.current = setTimeout(
1378
+ () => {
1379
+ if (!isLoading && Object.keys(chatSuggestionConfiguration).length !== 0) {
1380
+ suggestionsAbortControllerRef.current = new AbortController();
1381
+ reloadSuggestions(
1382
+ context,
1383
+ chatSuggestionConfiguration,
1384
+ setCurrentSuggestions,
1385
+ suggestionsAbortControllerRef
1386
+ );
1387
+ }
1388
+ },
1389
+ currentSuggestions.length == 0 ? 0 : SUGGESTIONS_DEBOUNCE_TIMEOUT
1390
+ );
1391
+ return () => {
1392
+ clearTimeout(debounceTimerRef.current);
1393
+ };
1394
+ }, [isLoading, chatSuggestionConfiguration]);
1199
1395
  const setOpen = (open) => {
1200
1396
  onSetOpen == null ? void 0 : onSetOpen(open);
1201
1397
  setOpenState(open);
1202
1398
  };
1203
- const sendMessage = (message) => __async(void 0, null, function* () {
1204
- onSubmitMessage == null ? void 0 : onSubmitMessage(message);
1205
- append({
1399
+ const sendMessage = (messageContent) => __async(void 0, null, function* () {
1400
+ abortSuggestions();
1401
+ setCurrentSuggestions([]);
1402
+ onSubmitMessage == null ? void 0 : onSubmitMessage(messageContent);
1403
+ const message = {
1206
1404
  id: (0, import_nanoid2.nanoid)(),
1207
- content: message,
1405
+ content: messageContent,
1208
1406
  role: "user"
1209
- });
1407
+ };
1408
+ append(message);
1409
+ return message;
1210
1410
  });
1211
- return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(ChatContextProvider, { icons, labels, open: openState, setOpen: setOpenState, children: [
1212
- children,
1213
- /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className, children: [
1214
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Button2, { open: openState, setOpen }),
1215
- /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
1216
- Window2,
1217
- {
1218
- open: openState,
1219
- setOpen,
1220
- clickOutsideToClose,
1221
- shortcut,
1222
- hitEscapeToClose,
1223
- children: [
1224
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Header2, { open: openState, setOpen }),
1225
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Messages2, { messages: visibleMessages, inProgress: isLoading }),
1226
- /* @__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 }) })
1227
- ]
1228
- }
1229
- )
1230
- ] })
1231
- ] });
1411
+ const [openState, setOpenState] = import_react9.default.useState(defaultOpen);
1412
+ const [pushToTalkState, setPushToTalkState] = import_react9.default.useState(false);
1413
+ const mediaStreamRef = (0, import_react9.useRef)(null);
1414
+ const audioContextRef = (0, import_react9.useRef)(null);
1415
+ const mediaRecorderRef = (0, import_react9.useRef)(null);
1416
+ const [lastMessageIdBeforeAudio, setLastMessageIdBeforeAudio] = (0, import_react9.useState)(null);
1417
+ (0, import_react9.useEffect)(() => {
1418
+ if (pushToTalkState) {
1419
+ console.log("HERE");
1420
+ if (!mediaStreamRef.current || !audioContextRef.current) {
1421
+ setPushToTalkState(false);
1422
+ requestMicAndPlaybackPermission().then((res) => {
1423
+ if (res) {
1424
+ mediaStreamRef.current = res.stream;
1425
+ audioContextRef.current = res.audioContext;
1426
+ }
1427
+ });
1428
+ } else {
1429
+ console.log("Recording started");
1430
+ const recordedChunks = [];
1431
+ mediaRecorderRef.current = new MediaRecorder(mediaStreamRef.current);
1432
+ mediaRecorderRef.current.start(1e3);
1433
+ mediaRecorderRef.current.ondataavailable = (event) => __async(void 0, null, function* () {
1434
+ console.log("Recorded audio: ", event.data);
1435
+ recordedChunks.push(event.data);
1436
+ });
1437
+ mediaRecorderRef.current.onstop = () => __async(void 0, null, function* () {
1438
+ console.log("Recording stopped");
1439
+ const completeBlob = new Blob(recordedChunks, { type: "audio/mp4" });
1440
+ const formData = new FormData();
1441
+ formData.append("file", completeBlob, "recording.mp4");
1442
+ const response = yield fetch(context.copilotApiConfig.transcribeAudioUrl, {
1443
+ method: "POST",
1444
+ body: formData
1445
+ });
1446
+ if (!response.ok) {
1447
+ throw new Error(`Error: ${response.statusText}`);
1448
+ }
1449
+ const transcription = yield response.json();
1450
+ const message = yield sendMessage(transcription.text);
1451
+ setLastMessageIdBeforeAudio(message.id);
1452
+ });
1453
+ }
1454
+ } else {
1455
+ if (mediaRecorderRef.current && mediaRecorderRef.current.state !== "inactive") {
1456
+ mediaRecorderRef.current.stop();
1457
+ }
1458
+ }
1459
+ return () => {
1460
+ if (mediaRecorderRef.current && mediaRecorderRef.current.state !== "inactive") {
1461
+ mediaRecorderRef.current.stop();
1462
+ }
1463
+ };
1464
+ }, [pushToTalkState]);
1465
+ (0, import_react9.useEffect)(() => {
1466
+ if (lastMessageIdBeforeAudio && !isLoading) {
1467
+ if (audioContextRef.current) {
1468
+ const lastMessageIndex = context.messages.findIndex(
1469
+ (message) => message.id === lastMessageIdBeforeAudio
1470
+ );
1471
+ const messagesAfterLast = context.messages.slice(lastMessageIndex + 1).filter((message) => message.role === "assistant" && message.content);
1472
+ const text = messagesAfterLast.map((message) => message.content).join("\n");
1473
+ const encodedText = encodeURIComponent(text);
1474
+ const url = `${context.copilotApiConfig.textToSpeechUrl}?text=${encodedText}`;
1475
+ fetch(url).then((response) => response.arrayBuffer()).then((arrayBuffer) => audioContextRef.current.decodeAudioData(arrayBuffer)).then((audioBuffer) => {
1476
+ const source = audioContextRef.current.createBufferSource();
1477
+ source.buffer = audioBuffer;
1478
+ source.connect(audioContextRef.current.destination);
1479
+ source.start(0);
1480
+ }).catch((error) => {
1481
+ console.error("Error with decoding audio data", error);
1482
+ });
1483
+ setLastMessageIdBeforeAudio(null);
1484
+ }
1485
+ }
1486
+ }, [isLoading]);
1487
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
1488
+ ChatContextProvider,
1489
+ {
1490
+ icons,
1491
+ labels,
1492
+ open: openState,
1493
+ setOpen: setOpenState,
1494
+ addChatSuggestionConfiguration,
1495
+ removeChatSuggestionConfiguration: removeChatSuggestion,
1496
+ children: [
1497
+ children,
1498
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className, children: [
1499
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
1500
+ Button2,
1501
+ {
1502
+ open: openState,
1503
+ setOpen,
1504
+ pushToTalk: pushToTalkState,
1505
+ setPushToTalk: setPushToTalkState
1506
+ }
1507
+ ),
1508
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
1509
+ Window2,
1510
+ {
1511
+ open: openState,
1512
+ setOpen,
1513
+ clickOutsideToClose,
1514
+ shortcut,
1515
+ hitEscapeToClose,
1516
+ children: [
1517
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Header2, { open: openState, setOpen }),
1518
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(Messages2, { messages: visibleMessages, inProgress: isLoading, children: [
1519
+ currentSuggestions.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { children: [
1520
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("h6", { children: "Suggested:" }),
1521
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "suggestions", children: currentSuggestions.map((suggestion, index) => /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
1522
+ Suggestion,
1523
+ {
1524
+ title: suggestion.title,
1525
+ message: suggestion.message,
1526
+ partial: suggestion.partial,
1527
+ className: suggestion.className,
1528
+ onClick: (message) => sendMessage(message)
1529
+ },
1530
+ index
1531
+ )) })
1532
+ ] }),
1533
+ showResponseButton && visibleMessages.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(ResponseButton2, { onClick: isLoading ? stop : reload, inProgress: isLoading })
1534
+ ] }),
1535
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Input2, { inProgress: isLoading, onSend: sendMessage, isVisible: openState })
1536
+ ]
1537
+ }
1538
+ )
1539
+ ] })
1540
+ ]
1541
+ }
1542
+ );
1232
1543
  };
1233
1544
 
1234
1545
  // src/components/chat/Sidebar.tsx
1235
- var import_jsx_runtime13 = require("react/jsx-runtime");
1236
- var CopilotSidebar = (props) => {
1546
+ var import_jsx_runtime14 = require("react/jsx-runtime");
1547
+ function CopilotSidebar(props) {
1237
1548
  props = __spreadProps(__spreadValues({}, props), {
1238
1549
  className: props.className ? props.className + " copilotKitSidebar" : "copilotKitSidebar"
1239
1550
  });
1240
- const [expandedClassName, setExpandedClassName] = (0, import_react9.useState)(
1551
+ const [expandedClassName, setExpandedClassName] = (0, import_react10.useState)(
1241
1552
  props.defaultOpen ? "sidebarExpanded" : ""
1242
1553
  );
1243
1554
  const onSetOpen = (open) => {
@@ -1245,8 +1556,8 @@ var CopilotSidebar = (props) => {
1245
1556
  (_a = props.onSetOpen) == null ? void 0 : _a.call(props, open);
1246
1557
  setExpandedClassName(open ? "sidebarExpanded" : "");
1247
1558
  };
1248
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: `copilotKitSidebarContentWrapper ${expandedClassName}`, children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(CopilotChat, __spreadProps(__spreadValues(__spreadValues({}, props), { onSetOpen }), { children: props.children })) });
1249
- };
1559
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: `copilotKitSidebarContentWrapper ${expandedClassName}`, children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(CopilotChat, __spreadProps(__spreadValues(__spreadValues({}, props), { onSetOpen }), { children: props.children })) });
1560
+ }
1250
1561
  // Annotate the CommonJS export names for ESM import in node:
1251
1562
  0 && (module.exports = {
1252
1563
  CopilotSidebar