@copilotkit/react-ui 1.10.5 → 1.10.6-next.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.
- package/CHANGELOG.md +12 -0
- package/dist/{chunk-QPONDGDJ.mjs → chunk-5HQD6ZPA.mjs} +2 -2
- package/dist/{chunk-DSNTTAJX.mjs → chunk-7HAFY2YK.mjs} +3 -3
- package/dist/{chunk-CGEAG65D.mjs → chunk-ELGRNEAO.mjs} +7 -2
- package/dist/chunk-ELGRNEAO.mjs.map +1 -0
- package/dist/{chunk-K2FLPUR5.mjs → chunk-G7VB7A4O.mjs} +2 -2
- package/dist/{chunk-SDQTGCT2.mjs → chunk-SNGWNZNH.mjs} +2 -2
- package/dist/{chunk-DTRPPNSA.mjs → chunk-ZJCHKHE4.mjs} +2 -2
- package/dist/components/chat/Chat.js +36 -29
- package/dist/components/chat/Chat.js.map +1 -1
- package/dist/components/chat/Chat.mjs +3 -3
- package/dist/components/chat/Input.js +14 -7
- package/dist/components/chat/Input.js.map +1 -1
- package/dist/components/chat/Input.mjs +2 -2
- package/dist/components/chat/Modal.js +43 -36
- package/dist/components/chat/Modal.js.map +1 -1
- package/dist/components/chat/Modal.mjs +4 -4
- package/dist/components/chat/Popup.js +43 -36
- package/dist/components/chat/Popup.js.map +1 -1
- package/dist/components/chat/Popup.mjs +5 -5
- package/dist/components/chat/PoweredByTag.js +6 -1
- package/dist/components/chat/PoweredByTag.js.map +1 -1
- package/dist/components/chat/PoweredByTag.mjs +1 -1
- package/dist/components/chat/Sidebar.js +45 -38
- package/dist/components/chat/Sidebar.js.map +1 -1
- package/dist/components/chat/Sidebar.mjs +5 -5
- package/dist/components/chat/index.js +45 -38
- package/dist/components/chat/index.js.map +1 -1
- package/dist/components/chat/index.mjs +6 -6
- package/dist/components/index.js +45 -38
- package/dist/components/index.js.map +1 -1
- package/dist/components/index.mjs +6 -6
- package/dist/index.js +47 -40
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +11 -11
- package/package.json +4 -4
- package/src/components/chat/PoweredByTag.tsx +15 -2
- package/dist/chunk-CGEAG65D.mjs.map +0 -1
- /package/dist/{chunk-QPONDGDJ.mjs.map → chunk-5HQD6ZPA.mjs.map} +0 -0
- /package/dist/{chunk-DSNTTAJX.mjs.map → chunk-7HAFY2YK.mjs.map} +0 -0
- /package/dist/{chunk-K2FLPUR5.mjs.map → chunk-G7VB7A4O.mjs.map} +0 -0
- /package/dist/{chunk-SDQTGCT2.mjs.map → chunk-SNGWNZNH.mjs.map} +0 -0
- /package/dist/{chunk-DTRPPNSA.mjs.map → chunk-ZJCHKHE4.mjs.map} +0 -0
|
@@ -2,12 +2,12 @@ import {
|
|
|
2
2
|
CopilotChat,
|
|
3
3
|
WrappedCopilotChat,
|
|
4
4
|
useCopilotChatLogic
|
|
5
|
-
} from "../../chunk-
|
|
5
|
+
} from "../../chunk-G7VB7A4O.mjs";
|
|
6
6
|
import "../../chunk-226ZMOE3.mjs";
|
|
7
7
|
import "../../chunk-W26XFBEG.mjs";
|
|
8
8
|
import "../../chunk-PLHTVHUW.mjs";
|
|
9
|
-
import "../../chunk-
|
|
10
|
-
import "../../chunk-
|
|
9
|
+
import "../../chunk-ZJCHKHE4.mjs";
|
|
10
|
+
import "../../chunk-ELGRNEAO.mjs";
|
|
11
11
|
import "../../chunk-QIOJXTIQ.mjs";
|
|
12
12
|
import "../../chunk-W7ONZTSW.mjs";
|
|
13
13
|
import "../../chunk-2LIO4Z3E.mjs";
|
|
@@ -67,7 +67,7 @@ __export(Input_exports, {
|
|
|
67
67
|
Input: () => Input
|
|
68
68
|
});
|
|
69
69
|
module.exports = __toCommonJS(Input_exports);
|
|
70
|
-
var
|
|
70
|
+
var import_react5 = require("react");
|
|
71
71
|
|
|
72
72
|
// src/components/chat/ChatContext.tsx
|
|
73
73
|
var import_react = __toESM(require("react"));
|
|
@@ -250,6 +250,9 @@ var usePushToTalk = ({
|
|
|
250
250
|
// src/components/chat/Input.tsx
|
|
251
251
|
var import_react_core2 = require("@copilotkit/react-core");
|
|
252
252
|
|
|
253
|
+
// src/components/chat/PoweredByTag.tsx
|
|
254
|
+
var import_react4 = require("react");
|
|
255
|
+
|
|
253
256
|
// src/hooks/use-dark-mode.ts
|
|
254
257
|
var useDarkMode = () => {
|
|
255
258
|
if (typeof window === "undefined")
|
|
@@ -260,7 +263,11 @@ var useDarkMode = () => {
|
|
|
260
263
|
// src/components/chat/PoweredByTag.tsx
|
|
261
264
|
var import_jsx_runtime3 = require("react/jsx-runtime");
|
|
262
265
|
function PoweredByTag({ showPoweredBy = true }) {
|
|
266
|
+
const [mounted, setMounted] = (0, import_react4.useState)(false);
|
|
263
267
|
const isDark = useDarkMode();
|
|
268
|
+
(0, import_react4.useEffect)(() => {
|
|
269
|
+
setMounted(true);
|
|
270
|
+
}, []);
|
|
264
271
|
if (!showPoweredBy) {
|
|
265
272
|
return null;
|
|
266
273
|
}
|
|
@@ -271,7 +278,7 @@ function PoweredByTag({ showPoweredBy = true }) {
|
|
|
271
278
|
textAlign: "center",
|
|
272
279
|
fontSize: "12px",
|
|
273
280
|
padding: "3px 0",
|
|
274
|
-
color: isDark ? "rgb(69, 69, 69)" : "rgb(214, 214, 214)"
|
|
281
|
+
color: mounted && isDark ? "rgb(69, 69, 69)" : "rgb(214, 214, 214)"
|
|
275
282
|
};
|
|
276
283
|
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: "poweredBy", style: poweredByStyle, children: "Powered by CopilotKit" }) });
|
|
277
284
|
}
|
|
@@ -292,8 +299,8 @@ var Input = ({
|
|
|
292
299
|
const copilotContext = (0, import_react_core2.useCopilotContext)();
|
|
293
300
|
const showPoweredBy = !((_a = copilotContext.copilotApiConfig) == null ? void 0 : _a.publicApiKey);
|
|
294
301
|
const pushToTalkConfigured = copilotContext.copilotApiConfig.textToSpeechUrl !== void 0 && copilotContext.copilotApiConfig.transcribeAudioUrl !== void 0;
|
|
295
|
-
const textareaRef = (0,
|
|
296
|
-
const [isComposing, setIsComposing] = (0,
|
|
302
|
+
const textareaRef = (0, import_react5.useRef)(null);
|
|
303
|
+
const [isComposing, setIsComposing] = (0, import_react5.useState)(false);
|
|
297
304
|
const handleDivClick = (event) => {
|
|
298
305
|
var _a2;
|
|
299
306
|
const target = event.target;
|
|
@@ -303,7 +310,7 @@ var Input = ({
|
|
|
303
310
|
return;
|
|
304
311
|
(_a2 = textareaRef.current) == null ? void 0 : _a2.focus();
|
|
305
312
|
};
|
|
306
|
-
const [text, setText] = (0,
|
|
313
|
+
const [text, setText] = (0, import_react5.useState)("");
|
|
307
314
|
const send = () => {
|
|
308
315
|
var _a2;
|
|
309
316
|
if (inProgress)
|
|
@@ -319,13 +326,13 @@ var Input = ({
|
|
|
319
326
|
const isInProgress = inProgress || pushToTalkState === "transcribing";
|
|
320
327
|
const buttonIcon = isInProgress && !hideStopButton ? context.icons.stopIcon : context.icons.sendIcon;
|
|
321
328
|
const showPushToTalk = pushToTalkConfigured && (pushToTalkState === "idle" || pushToTalkState === "recording") && !inProgress;
|
|
322
|
-
const canSend = (0,
|
|
329
|
+
const canSend = (0, import_react5.useMemo)(() => {
|
|
323
330
|
var _a2;
|
|
324
331
|
const interruptEvent = (_a2 = copilotContext.langGraphInterruptAction) == null ? void 0 : _a2.event;
|
|
325
332
|
const interruptInProgress = (interruptEvent == null ? void 0 : interruptEvent.name) === "LangGraphInterruptEvent" && !(interruptEvent == null ? void 0 : interruptEvent.response);
|
|
326
333
|
return !isInProgress && text.trim().length > 0 && pushToTalkState === "idle" && !interruptInProgress;
|
|
327
334
|
}, [(_b = copilotContext.langGraphInterruptAction) == null ? void 0 : _b.event, isInProgress, text, pushToTalkState]);
|
|
328
|
-
const canStop = (0,
|
|
335
|
+
const canStop = (0, import_react5.useMemo)(() => {
|
|
329
336
|
return isInProgress && !hideStopButton;
|
|
330
337
|
}, [isInProgress, hideStopButton]);
|
|
331
338
|
const sendDisabled = !canSend && !canStop;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/components/chat/Input.tsx","../../../src/components/chat/ChatContext.tsx","../../../src/components/chat/Textarea.tsx","../../../src/hooks/use-push-to-talk.tsx","../../../src/hooks/use-dark-mode.ts","../../../src/components/chat/PoweredByTag.tsx"],"sourcesContent":["import React, { useMemo, useRef, useState } from \"react\";\nimport { InputProps } from \"./props\";\nimport { useChatContext } from \"./ChatContext\";\nimport AutoResizingTextarea from \"./Textarea\";\nimport { usePushToTalk } from \"../../hooks/use-push-to-talk\";\nimport { useCopilotContext } from \"@copilotkit/react-core\";\nimport { PoweredByTag } from \"./PoweredByTag\";\n\nconst MAX_NEWLINES = 6;\n\nexport const Input = ({\n inProgress,\n onSend,\n isVisible = false,\n onStop,\n onUpload,\n hideStopButton = false,\n}: InputProps) => {\n const context = useChatContext();\n const copilotContext = useCopilotContext();\n\n const showPoweredBy = !copilotContext.copilotApiConfig?.publicApiKey;\n\n const pushToTalkConfigured =\n copilotContext.copilotApiConfig.textToSpeechUrl !== undefined &&\n copilotContext.copilotApiConfig.transcribeAudioUrl !== undefined;\n\n const textareaRef = useRef<HTMLTextAreaElement>(null);\n const [isComposing, setIsComposing] = useState(false);\n\n const handleDivClick = (event: React.MouseEvent<HTMLDivElement>) => {\n const target = event.target as HTMLElement;\n\n // If the user clicked a button or inside a button, don't focus the textarea\n if (target.closest(\"button\")) return;\n\n // If the user clicked the textarea, do nothing (it's already focused)\n if (target.tagName === \"TEXTAREA\") return;\n\n // Otherwise, focus the textarea\n textareaRef.current?.focus();\n };\n\n const [text, setText] = useState(\"\");\n const send = () => {\n if (inProgress) return;\n onSend(text);\n setText(\"\");\n\n textareaRef.current?.focus();\n };\n\n // tylerslaton:\n //\n // This scrolls CopilotKit into view always. Reading the commit history, it was likely\n // added to fix a bug but it is causing issues now.\n //\n // For the future, if we want this behavior again, we will need to find a way to do it without\n // forcing CopilotKit to always be in view. This code causes this because focusing an element\n // in most browsers will scroll that element into view.\n //\n // useEffect(() => {\n // if (isVisible) {\n // textareaRef.current?.focus();\n // }\n // }, [isVisible]);\n\n const { pushToTalkState, setPushToTalkState } = usePushToTalk({\n sendFunction: onSend,\n inProgress,\n });\n\n const isInProgress = inProgress || pushToTalkState === \"transcribing\";\n const buttonIcon =\n isInProgress && !hideStopButton ? context.icons.stopIcon : context.icons.sendIcon;\n const showPushToTalk =\n pushToTalkConfigured &&\n (pushToTalkState === \"idle\" || pushToTalkState === \"recording\") &&\n !inProgress;\n\n const canSend = useMemo(() => {\n const interruptEvent = copilotContext.langGraphInterruptAction?.event;\n const interruptInProgress =\n interruptEvent?.name === \"LangGraphInterruptEvent\" && !interruptEvent?.response;\n\n return (\n !isInProgress && text.trim().length > 0 && pushToTalkState === \"idle\" && !interruptInProgress\n );\n }, [copilotContext.langGraphInterruptAction?.event, isInProgress, text, pushToTalkState]);\n\n const canStop = useMemo(() => {\n return isInProgress && !hideStopButton;\n }, [isInProgress, hideStopButton]);\n\n const sendDisabled = !canSend && !canStop;\n\n return (\n <div className={`copilotKitInputContainer ${showPoweredBy ? \"poweredByContainer\" : \"\"}`}>\n <div className=\"copilotKitInput\" onClick={handleDivClick}>\n <AutoResizingTextarea\n ref={textareaRef}\n placeholder={context.labels.placeholder}\n autoFocus={false}\n maxRows={MAX_NEWLINES}\n value={text}\n onChange={(event) => setText(event.target.value)}\n onCompositionStart={() => setIsComposing(true)}\n onCompositionEnd={() => setIsComposing(false)}\n onKeyDown={(event) => {\n if (event.key === \"Enter\" && !event.shiftKey && !isComposing) {\n event.preventDefault();\n if (canSend) {\n send();\n }\n }\n }}\n />\n <div className=\"copilotKitInputControls\">\n {onUpload && (\n <button onClick={onUpload} className=\"copilotKitInputControlButton\">\n {context.icons.uploadIcon}\n </button>\n )}\n\n <div style={{ flexGrow: 1 }} />\n\n {showPushToTalk && (\n <button\n onClick={() =>\n setPushToTalkState(pushToTalkState === \"idle\" ? \"recording\" : \"transcribing\")\n }\n className={\n pushToTalkState === \"recording\"\n ? \"copilotKitInputControlButton copilotKitPushToTalkRecording\"\n : \"copilotKitInputControlButton\"\n }\n >\n {context.icons.pushToTalkIcon}\n </button>\n )}\n <button\n disabled={sendDisabled}\n onClick={isInProgress && !hideStopButton ? onStop : send}\n data-copilotkit-in-progress={inProgress}\n data-test-id={inProgress ? \"copilot-chat-request-in-progress\" : \"copilot-chat-ready\"}\n className=\"copilotKitInputControlButton\"\n >\n {buttonIcon}\n </button>\n </div>\n </div>\n <PoweredByTag showPoweredBy={showPoweredBy} />\n </div>\n );\n};\n","import React, { useMemo, useState } from \"react\";\nimport * as DefaultIcons from \"./Icons\";\nimport { ThumbsDownIcon, ThumbsUpIcon } from \"./Icons\";\n\n/**\n * Icons for CopilotChat component.\n */\nexport interface CopilotChatIcons {\n /**\n * The icon to use for the open chat button.\n * @default <OpenIcon />\n */\n openIcon?: React.ReactNode;\n\n /**\n * The icon to use for the close chat button.\n * @default <CloseIcon />\n */\n closeIcon?: React.ReactNode;\n\n /**\n * The icon to use for the close chat button in the header.\n * @default <HeaderCloseIcon />\n */\n headerCloseIcon?: React.ReactNode;\n\n /**\n * The icon to use for the send button.\n * @default <SendIcon />\n */\n sendIcon?: React.ReactNode;\n\n /**\n * The icon to use for the activity indicator.\n * @default <ActivityIcon />\n */\n activityIcon?: React.ReactNode;\n\n /**\n * The icon to use for the spinner.\n * @default <SpinnerIcon />\n */\n spinnerIcon?: React.ReactNode;\n\n /**\n * The icon to use for the stop button.\n * @default <StopIcon />\n */\n stopIcon?: React.ReactNode;\n\n /**\n * The icon to use for the regenerate button.\n * @default <RegenerateIcon />\n */\n regenerateIcon?: React.ReactNode;\n\n /**\n * The icons to use for push to talk.\n * @default <PushToTalkIcon />\n */\n\n pushToTalkIcon?: React.ReactNode;\n\n /**\n * The icons to use for copy assistant response\n * @default <CopyIcon />\n */\n\n copyIcon?: React.ReactNode;\n\n /**\n * The icon to use for thumbs up/response approval.\n * @default <ThumbsUpIcon />\n */\n\n thumbsUpIcon?: React.ReactNode;\n\n /**\n * The icon to use for thumbs down/response rejection.\n * @default <ThumbsDownIcon />\n */\n\n thumbsDownIcon?: React.ReactNode;\n\n /**\n * The icon to use for the upload button.\n * @default <UploadIcon />\n */\n uploadIcon?: React.ReactNode;\n}\n\n/**\n * Labels for CopilotChat component.\n */\nexport interface CopilotChatLabels {\n /**\n * The initial message(s) to display in the chat window.\n */\n initial?: string | string[];\n\n /**\n * The title to display in the header.\n * @default \"CopilotKit\"\n */\n title?: string;\n\n /**\n * The placeholder to display in the input.\n * @default \"Type a message...\"\n */\n placeholder?: string;\n\n /**\n * The message to display when an error occurs.\n * @default \"❌ An error occurred. Please try again.\"\n */\n error?: string;\n\n /**\n * The label to display on the stop button.\n * @default \"Stop generating\"\n */\n stopGenerating?: string;\n\n /**\n * The label to display on the regenerate button.\n * @default \"Regenerate response\"\n */\n regenerateResponse?: string;\n\n /**\n * The label for the copy button.\n * @default \"Copy to clipboard\"\n */\n copyToClipboard?: string;\n\n /**\n * The label for the thumbs up button.\n * @default \"Thumbs up\"\n */\n thumbsUp?: string;\n\n /**\n * The label for the thumbs down button.\n * @default \"Thumbs down\"\n */\n thumbsDown?: string;\n\n /**\n * The text to display when content is copied.\n * @default \"Copied!\"\n */\n copied?: string;\n}\n\ninterface ChatContext {\n labels: Required<CopilotChatLabels>;\n icons: Required<CopilotChatIcons>;\n open: boolean;\n setOpen: (open: boolean) => void;\n}\n\nexport const ChatContext = React.createContext<ChatContext | undefined>(undefined);\n\nexport function useChatContext(): ChatContext {\n const context = React.useContext(ChatContext);\n if (context === undefined) {\n throw new Error(\n \"Context not found. Did you forget to wrap your app in a <ChatContextProvider> component?\",\n );\n }\n return context;\n}\n\ninterface ChatContextProps {\n // temperature?: number;\n // instructions?: string;\n // maxFeedback?: number;\n labels?: CopilotChatLabels;\n icons?: CopilotChatIcons;\n children?: React.ReactNode;\n open: boolean;\n setOpen: (open: boolean) => void;\n}\n\nexport const ChatContextProvider = ({\n // temperature,\n // instructions,\n // maxFeedback,\n labels,\n icons,\n children,\n open,\n setOpen,\n}: ChatContextProps) => {\n const memoizedLabels = useMemo(\n () => ({\n ...{\n initial: \"\",\n title: \"CopilotKit\",\n placeholder: \"Type a message...\",\n error: \"❌ An error occurred. Please try again.\",\n stopGenerating: \"Stop generating\",\n regenerateResponse: \"Regenerate response\",\n copyToClipboard: \"Copy to clipboard\",\n thumbsUp: \"Thumbs up\",\n thumbsDown: \"Thumbs down\",\n copied: \"Copied!\",\n },\n ...labels,\n }),\n [labels],\n );\n\n const memoizedIcons = useMemo(\n () => ({\n ...{\n openIcon: DefaultIcons.OpenIcon,\n closeIcon: DefaultIcons.CloseIcon,\n headerCloseIcon: DefaultIcons.HeaderCloseIcon,\n sendIcon: DefaultIcons.SendIcon,\n activityIcon: DefaultIcons.ActivityIcon,\n spinnerIcon: DefaultIcons.SpinnerIcon,\n stopIcon: DefaultIcons.StopIcon,\n regenerateIcon: DefaultIcons.RegenerateIcon,\n pushToTalkIcon: DefaultIcons.MicrophoneIcon,\n copyIcon: DefaultIcons.CopyIcon,\n thumbsUpIcon: DefaultIcons.ThumbsUpIcon,\n thumbsDownIcon: DefaultIcons.ThumbsDownIcon,\n uploadIcon: DefaultIcons.UploadIcon,\n },\n ...icons,\n }),\n [icons],\n );\n\n const context = useMemo(\n () => ({\n labels: memoizedLabels,\n icons: memoizedIcons,\n open,\n setOpen,\n }),\n [memoizedLabels, memoizedIcons, open, setOpen],\n );\n\n return <ChatContext.Provider value={context}>{children}</ChatContext.Provider>;\n};\n","import React, { useState, useRef, useEffect, forwardRef, useImperativeHandle } from \"react\";\n\ninterface AutoResizingTextareaProps {\n maxRows?: number;\n placeholder?: string;\n value: string;\n onChange: (event: React.ChangeEvent<HTMLTextAreaElement>) => void;\n onKeyDown?: (event: React.KeyboardEvent<HTMLTextAreaElement>) => void;\n onCompositionStart?: () => void;\n onCompositionEnd?: () => void;\n autoFocus?: boolean;\n}\n\nconst AutoResizingTextarea = forwardRef<HTMLTextAreaElement, AutoResizingTextareaProps>(\n (\n {\n maxRows = 1,\n placeholder,\n value,\n onChange,\n onKeyDown,\n onCompositionStart,\n onCompositionEnd,\n autoFocus,\n },\n ref,\n ) => {\n const internalTextareaRef = useRef<HTMLTextAreaElement>(null);\n const [maxHeight, setMaxHeight] = useState<number>(0);\n\n useImperativeHandle(ref, () => internalTextareaRef.current as HTMLTextAreaElement);\n\n useEffect(() => {\n const calculateMaxHeight = () => {\n const textarea = internalTextareaRef.current;\n if (textarea) {\n textarea.style.height = \"auto\";\n const singleRowHeight = textarea.scrollHeight;\n setMaxHeight(singleRowHeight * maxRows);\n if (autoFocus) {\n textarea.focus();\n }\n }\n };\n\n calculateMaxHeight();\n }, [maxRows]);\n\n useEffect(() => {\n const textarea = internalTextareaRef.current;\n if (textarea) {\n textarea.style.height = \"auto\";\n textarea.style.height = `${Math.min(textarea.scrollHeight, maxHeight)}px`;\n }\n }, [value, maxHeight]);\n\n return (\n <textarea\n ref={internalTextareaRef}\n value={value}\n onChange={onChange}\n onKeyDown={onKeyDown}\n onCompositionStart={onCompositionStart}\n onCompositionEnd={onCompositionEnd}\n placeholder={placeholder}\n style={{\n overflow: \"auto\",\n resize: \"none\",\n maxHeight: `${maxHeight}px`,\n }}\n rows={1}\n />\n );\n },\n);\n\nexport default AutoResizingTextarea;\n","import { useCopilotContext, useCopilotMessagesContext } from \"@copilotkit/react-core\";\nimport { gqlToAGUI } from \"@copilotkit/runtime-client-gql\";\nimport { Message } from \"@copilotkit/shared\";\nimport { MutableRefObject, useEffect, useRef, useState } from \"react\";\n\nexport const checkMicrophonePermission = async () => {\n try {\n const permissionStatus = await navigator.permissions.query({\n name: \"microphone\" as PermissionName,\n });\n if (permissionStatus.state === \"granted\") {\n return true;\n } else {\n return false;\n }\n } catch (err) {\n console.error(\"Error checking microphone permission\", err);\n }\n};\n\nexport const requestMicAndPlaybackPermission = async () => {\n try {\n const stream = await navigator.mediaDevices.getUserMedia({ audio: true });\n const audioContext = new window.AudioContext();\n await audioContext.resume();\n return { stream, audioContext };\n } catch (err) {\n console.error(\"Error requesting microphone and playback permissions\", err);\n return null;\n }\n};\n\nconst startRecording = async (\n mediaStreamRef: MutableRefObject<MediaStream | null>,\n mediaRecorderRef: MutableRefObject<MediaRecorder | null>,\n audioContextRef: MutableRefObject<AudioContext | null>,\n recordedChunks: Blob[],\n onStop: () => void,\n) => {\n if (!mediaStreamRef.current || !audioContextRef.current) {\n mediaStreamRef.current = await navigator.mediaDevices.getUserMedia({ audio: true });\n audioContextRef.current = new window.AudioContext();\n await audioContextRef.current.resume();\n }\n\n mediaRecorderRef.current = new MediaRecorder(mediaStreamRef.current!);\n mediaRecorderRef.current.start(1000);\n mediaRecorderRef.current.ondataavailable = (event) => {\n recordedChunks.push(event.data);\n };\n mediaRecorderRef.current.onstop = onStop;\n};\n\nconst stopRecording = (mediaRecorderRef: MutableRefObject<MediaRecorder | null>) => {\n if (mediaRecorderRef.current && mediaRecorderRef.current.state !== \"inactive\") {\n mediaRecorderRef.current.stop();\n }\n};\n\nconst transcribeAudio = async (recordedChunks: Blob[], transcribeAudioUrl: string) => {\n const completeBlob = new Blob(recordedChunks, { type: \"audio/mp4\" });\n const formData = new FormData();\n formData.append(\"file\", completeBlob, \"recording.mp4\");\n\n const response = await fetch(transcribeAudioUrl, {\n method: \"POST\",\n body: formData,\n });\n\n if (!response.ok) {\n throw new Error(`Error: ${response.statusText}`);\n }\n\n const transcription = await response.json();\n return transcription.text;\n};\n\nconst playAudioResponse = (text: string, textToSpeechUrl: string, audioContext: AudioContext) => {\n const encodedText = encodeURIComponent(text);\n const url = `${textToSpeechUrl}?text=${encodedText}`;\n\n fetch(url)\n .then((response) => response.arrayBuffer())\n .then((arrayBuffer) => audioContext.decodeAudioData(arrayBuffer))\n .then((audioBuffer) => {\n const source = audioContext.createBufferSource();\n source.buffer = audioBuffer;\n source.connect(audioContext.destination);\n source.start(0);\n })\n .catch((error) => {\n console.error(\"Error with decoding audio data\", error);\n });\n};\n\nexport type PushToTalkState = \"idle\" | \"recording\" | \"transcribing\";\n\nexport type SendFunction = (text: string) => Promise<Message>;\n\nexport const usePushToTalk = ({\n sendFunction,\n inProgress,\n}: {\n sendFunction: SendFunction;\n inProgress: boolean;\n}) => {\n const [pushToTalkState, setPushToTalkState] = useState<PushToTalkState>(\"idle\");\n const mediaStreamRef = useRef<MediaStream | null>(null);\n const audioContextRef = useRef<AudioContext | null>(null);\n const mediaRecorderRef = useRef<MediaRecorder | null>(null);\n const recordedChunks = useRef<Blob[]>([]);\n const generalContext = useCopilotContext();\n const messagesContext = useCopilotMessagesContext();\n const context = { ...generalContext, ...messagesContext };\n const [startReadingFromMessageId, setStartReadingFromMessageId] = useState<string | null>(null);\n\n useEffect(() => {\n if (pushToTalkState === \"recording\") {\n startRecording(\n mediaStreamRef,\n mediaRecorderRef,\n audioContextRef,\n recordedChunks.current,\n () => {\n setPushToTalkState(\"transcribing\");\n },\n );\n } else {\n stopRecording(mediaRecorderRef);\n if (pushToTalkState === \"transcribing\") {\n transcribeAudio(recordedChunks.current, context.copilotApiConfig.transcribeAudioUrl!).then(\n async (transcription) => {\n recordedChunks.current = [];\n setPushToTalkState(\"idle\");\n const message = await sendFunction(transcription);\n setStartReadingFromMessageId(message.id);\n },\n );\n }\n }\n\n return () => {\n stopRecording(mediaRecorderRef);\n };\n }, [pushToTalkState]);\n\n useEffect(() => {\n if (inProgress === false && startReadingFromMessageId) {\n const lastMessageIndex = context.messages.findIndex(\n (message) => message.id === startReadingFromMessageId,\n );\n\n const aguiMessages = gqlToAGUI(context.messages);\n\n const messagesAfterLast = aguiMessages\n .slice(lastMessageIndex + 1)\n .filter((message) => message.role === \"assistant\");\n\n const text = messagesAfterLast.map((message) => message.content).join(\"\\n\");\n playAudioResponse(text, context.copilotApiConfig.textToSpeechUrl!, audioContextRef.current!);\n\n setStartReadingFromMessageId(null);\n }\n }, [startReadingFromMessageId, inProgress]);\n\n return { pushToTalkState, setPushToTalkState };\n};\n","export const useDarkMode = () => {\n if (typeof window === \"undefined\") return false;\n return (\n document.documentElement.classList.contains(\"dark\") ||\n document.body.classList.contains(\"dark\") ||\n document.documentElement.getAttribute(\"data-theme\") === \"dark\" ||\n document.body.getAttribute(\"data-theme\") === \"dark\" ||\n window.matchMedia(\"(prefers-color-scheme: dark)\").matches\n );\n};\n","import React from \"react\";\nimport { useDarkMode } from \"../../hooks/use-dark-mode\";\n\nexport function PoweredByTag({ showPoweredBy = true }: { showPoweredBy?: boolean }) {\n const isDark = useDarkMode();\n\n if (!showPoweredBy) {\n return null;\n }\n\n const poweredByStyle = {\n visibility: \"visible\",\n display: \"block\",\n position: \"static\",\n textAlign: \"center\",\n fontSize: \"12px\",\n padding: \"3px 0\",\n color: isDark ? \"rgb(69, 69, 69)\" : \"rgb(214, 214, 214)\",\n };\n\n return (\n <div>\n {/*@ts-expect-error -- expecting position not to be a string, but it can be.*/}\n <p className=\"poweredBy\" style={poweredByStyle}>\n Powered by CopilotKit\n </p>\n </div>\n );\n}\n"],"mappings":"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","names":["import_react","React","import_react","import_jsx_runtime","import_react","import_react_core","import_jsx_runtime","import_jsx_runtime","_a"]}
|
|
1
|
+
{"version":3,"sources":["../../../src/components/chat/Input.tsx","../../../src/components/chat/ChatContext.tsx","../../../src/components/chat/Textarea.tsx","../../../src/hooks/use-push-to-talk.tsx","../../../src/components/chat/PoweredByTag.tsx","../../../src/hooks/use-dark-mode.ts"],"sourcesContent":["import React, { useMemo, useRef, useState } from \"react\";\nimport { InputProps } from \"./props\";\nimport { useChatContext } from \"./ChatContext\";\nimport AutoResizingTextarea from \"./Textarea\";\nimport { usePushToTalk } from \"../../hooks/use-push-to-talk\";\nimport { useCopilotContext } from \"@copilotkit/react-core\";\nimport { PoweredByTag } from \"./PoweredByTag\";\n\nconst MAX_NEWLINES = 6;\n\nexport const Input = ({\n inProgress,\n onSend,\n isVisible = false,\n onStop,\n onUpload,\n hideStopButton = false,\n}: InputProps) => {\n const context = useChatContext();\n const copilotContext = useCopilotContext();\n\n const showPoweredBy = !copilotContext.copilotApiConfig?.publicApiKey;\n\n const pushToTalkConfigured =\n copilotContext.copilotApiConfig.textToSpeechUrl !== undefined &&\n copilotContext.copilotApiConfig.transcribeAudioUrl !== undefined;\n\n const textareaRef = useRef<HTMLTextAreaElement>(null);\n const [isComposing, setIsComposing] = useState(false);\n\n const handleDivClick = (event: React.MouseEvent<HTMLDivElement>) => {\n const target = event.target as HTMLElement;\n\n // If the user clicked a button or inside a button, don't focus the textarea\n if (target.closest(\"button\")) return;\n\n // If the user clicked the textarea, do nothing (it's already focused)\n if (target.tagName === \"TEXTAREA\") return;\n\n // Otherwise, focus the textarea\n textareaRef.current?.focus();\n };\n\n const [text, setText] = useState(\"\");\n const send = () => {\n if (inProgress) return;\n onSend(text);\n setText(\"\");\n\n textareaRef.current?.focus();\n };\n\n // tylerslaton:\n //\n // This scrolls CopilotKit into view always. Reading the commit history, it was likely\n // added to fix a bug but it is causing issues now.\n //\n // For the future, if we want this behavior again, we will need to find a way to do it without\n // forcing CopilotKit to always be in view. This code causes this because focusing an element\n // in most browsers will scroll that element into view.\n //\n // useEffect(() => {\n // if (isVisible) {\n // textareaRef.current?.focus();\n // }\n // }, [isVisible]);\n\n const { pushToTalkState, setPushToTalkState } = usePushToTalk({\n sendFunction: onSend,\n inProgress,\n });\n\n const isInProgress = inProgress || pushToTalkState === \"transcribing\";\n const buttonIcon =\n isInProgress && !hideStopButton ? context.icons.stopIcon : context.icons.sendIcon;\n const showPushToTalk =\n pushToTalkConfigured &&\n (pushToTalkState === \"idle\" || pushToTalkState === \"recording\") &&\n !inProgress;\n\n const canSend = useMemo(() => {\n const interruptEvent = copilotContext.langGraphInterruptAction?.event;\n const interruptInProgress =\n interruptEvent?.name === \"LangGraphInterruptEvent\" && !interruptEvent?.response;\n\n return (\n !isInProgress && text.trim().length > 0 && pushToTalkState === \"idle\" && !interruptInProgress\n );\n }, [copilotContext.langGraphInterruptAction?.event, isInProgress, text, pushToTalkState]);\n\n const canStop = useMemo(() => {\n return isInProgress && !hideStopButton;\n }, [isInProgress, hideStopButton]);\n\n const sendDisabled = !canSend && !canStop;\n\n return (\n <div className={`copilotKitInputContainer ${showPoweredBy ? \"poweredByContainer\" : \"\"}`}>\n <div className=\"copilotKitInput\" onClick={handleDivClick}>\n <AutoResizingTextarea\n ref={textareaRef}\n placeholder={context.labels.placeholder}\n autoFocus={false}\n maxRows={MAX_NEWLINES}\n value={text}\n onChange={(event) => setText(event.target.value)}\n onCompositionStart={() => setIsComposing(true)}\n onCompositionEnd={() => setIsComposing(false)}\n onKeyDown={(event) => {\n if (event.key === \"Enter\" && !event.shiftKey && !isComposing) {\n event.preventDefault();\n if (canSend) {\n send();\n }\n }\n }}\n />\n <div className=\"copilotKitInputControls\">\n {onUpload && (\n <button onClick={onUpload} className=\"copilotKitInputControlButton\">\n {context.icons.uploadIcon}\n </button>\n )}\n\n <div style={{ flexGrow: 1 }} />\n\n {showPushToTalk && (\n <button\n onClick={() =>\n setPushToTalkState(pushToTalkState === \"idle\" ? \"recording\" : \"transcribing\")\n }\n className={\n pushToTalkState === \"recording\"\n ? \"copilotKitInputControlButton copilotKitPushToTalkRecording\"\n : \"copilotKitInputControlButton\"\n }\n >\n {context.icons.pushToTalkIcon}\n </button>\n )}\n <button\n disabled={sendDisabled}\n onClick={isInProgress && !hideStopButton ? onStop : send}\n data-copilotkit-in-progress={inProgress}\n data-test-id={inProgress ? \"copilot-chat-request-in-progress\" : \"copilot-chat-ready\"}\n className=\"copilotKitInputControlButton\"\n >\n {buttonIcon}\n </button>\n </div>\n </div>\n <PoweredByTag showPoweredBy={showPoweredBy} />\n </div>\n );\n};\n","import React, { useMemo, useState } from \"react\";\nimport * as DefaultIcons from \"./Icons\";\nimport { ThumbsDownIcon, ThumbsUpIcon } from \"./Icons\";\n\n/**\n * Icons for CopilotChat component.\n */\nexport interface CopilotChatIcons {\n /**\n * The icon to use for the open chat button.\n * @default <OpenIcon />\n */\n openIcon?: React.ReactNode;\n\n /**\n * The icon to use for the close chat button.\n * @default <CloseIcon />\n */\n closeIcon?: React.ReactNode;\n\n /**\n * The icon to use for the close chat button in the header.\n * @default <HeaderCloseIcon />\n */\n headerCloseIcon?: React.ReactNode;\n\n /**\n * The icon to use for the send button.\n * @default <SendIcon />\n */\n sendIcon?: React.ReactNode;\n\n /**\n * The icon to use for the activity indicator.\n * @default <ActivityIcon />\n */\n activityIcon?: React.ReactNode;\n\n /**\n * The icon to use for the spinner.\n * @default <SpinnerIcon />\n */\n spinnerIcon?: React.ReactNode;\n\n /**\n * The icon to use for the stop button.\n * @default <StopIcon />\n */\n stopIcon?: React.ReactNode;\n\n /**\n * The icon to use for the regenerate button.\n * @default <RegenerateIcon />\n */\n regenerateIcon?: React.ReactNode;\n\n /**\n * The icons to use for push to talk.\n * @default <PushToTalkIcon />\n */\n\n pushToTalkIcon?: React.ReactNode;\n\n /**\n * The icons to use for copy assistant response\n * @default <CopyIcon />\n */\n\n copyIcon?: React.ReactNode;\n\n /**\n * The icon to use for thumbs up/response approval.\n * @default <ThumbsUpIcon />\n */\n\n thumbsUpIcon?: React.ReactNode;\n\n /**\n * The icon to use for thumbs down/response rejection.\n * @default <ThumbsDownIcon />\n */\n\n thumbsDownIcon?: React.ReactNode;\n\n /**\n * The icon to use for the upload button.\n * @default <UploadIcon />\n */\n uploadIcon?: React.ReactNode;\n}\n\n/**\n * Labels for CopilotChat component.\n */\nexport interface CopilotChatLabels {\n /**\n * The initial message(s) to display in the chat window.\n */\n initial?: string | string[];\n\n /**\n * The title to display in the header.\n * @default \"CopilotKit\"\n */\n title?: string;\n\n /**\n * The placeholder to display in the input.\n * @default \"Type a message...\"\n */\n placeholder?: string;\n\n /**\n * The message to display when an error occurs.\n * @default \"❌ An error occurred. Please try again.\"\n */\n error?: string;\n\n /**\n * The label to display on the stop button.\n * @default \"Stop generating\"\n */\n stopGenerating?: string;\n\n /**\n * The label to display on the regenerate button.\n * @default \"Regenerate response\"\n */\n regenerateResponse?: string;\n\n /**\n * The label for the copy button.\n * @default \"Copy to clipboard\"\n */\n copyToClipboard?: string;\n\n /**\n * The label for the thumbs up button.\n * @default \"Thumbs up\"\n */\n thumbsUp?: string;\n\n /**\n * The label for the thumbs down button.\n * @default \"Thumbs down\"\n */\n thumbsDown?: string;\n\n /**\n * The text to display when content is copied.\n * @default \"Copied!\"\n */\n copied?: string;\n}\n\ninterface ChatContext {\n labels: Required<CopilotChatLabels>;\n icons: Required<CopilotChatIcons>;\n open: boolean;\n setOpen: (open: boolean) => void;\n}\n\nexport const ChatContext = React.createContext<ChatContext | undefined>(undefined);\n\nexport function useChatContext(): ChatContext {\n const context = React.useContext(ChatContext);\n if (context === undefined) {\n throw new Error(\n \"Context not found. Did you forget to wrap your app in a <ChatContextProvider> component?\",\n );\n }\n return context;\n}\n\ninterface ChatContextProps {\n // temperature?: number;\n // instructions?: string;\n // maxFeedback?: number;\n labels?: CopilotChatLabels;\n icons?: CopilotChatIcons;\n children?: React.ReactNode;\n open: boolean;\n setOpen: (open: boolean) => void;\n}\n\nexport const ChatContextProvider = ({\n // temperature,\n // instructions,\n // maxFeedback,\n labels,\n icons,\n children,\n open,\n setOpen,\n}: ChatContextProps) => {\n const memoizedLabels = useMemo(\n () => ({\n ...{\n initial: \"\",\n title: \"CopilotKit\",\n placeholder: \"Type a message...\",\n error: \"❌ An error occurred. Please try again.\",\n stopGenerating: \"Stop generating\",\n regenerateResponse: \"Regenerate response\",\n copyToClipboard: \"Copy to clipboard\",\n thumbsUp: \"Thumbs up\",\n thumbsDown: \"Thumbs down\",\n copied: \"Copied!\",\n },\n ...labels,\n }),\n [labels],\n );\n\n const memoizedIcons = useMemo(\n () => ({\n ...{\n openIcon: DefaultIcons.OpenIcon,\n closeIcon: DefaultIcons.CloseIcon,\n headerCloseIcon: DefaultIcons.HeaderCloseIcon,\n sendIcon: DefaultIcons.SendIcon,\n activityIcon: DefaultIcons.ActivityIcon,\n spinnerIcon: DefaultIcons.SpinnerIcon,\n stopIcon: DefaultIcons.StopIcon,\n regenerateIcon: DefaultIcons.RegenerateIcon,\n pushToTalkIcon: DefaultIcons.MicrophoneIcon,\n copyIcon: DefaultIcons.CopyIcon,\n thumbsUpIcon: DefaultIcons.ThumbsUpIcon,\n thumbsDownIcon: DefaultIcons.ThumbsDownIcon,\n uploadIcon: DefaultIcons.UploadIcon,\n },\n ...icons,\n }),\n [icons],\n );\n\n const context = useMemo(\n () => ({\n labels: memoizedLabels,\n icons: memoizedIcons,\n open,\n setOpen,\n }),\n [memoizedLabels, memoizedIcons, open, setOpen],\n );\n\n return <ChatContext.Provider value={context}>{children}</ChatContext.Provider>;\n};\n","import React, { useState, useRef, useEffect, forwardRef, useImperativeHandle } from \"react\";\n\ninterface AutoResizingTextareaProps {\n maxRows?: number;\n placeholder?: string;\n value: string;\n onChange: (event: React.ChangeEvent<HTMLTextAreaElement>) => void;\n onKeyDown?: (event: React.KeyboardEvent<HTMLTextAreaElement>) => void;\n onCompositionStart?: () => void;\n onCompositionEnd?: () => void;\n autoFocus?: boolean;\n}\n\nconst AutoResizingTextarea = forwardRef<HTMLTextAreaElement, AutoResizingTextareaProps>(\n (\n {\n maxRows = 1,\n placeholder,\n value,\n onChange,\n onKeyDown,\n onCompositionStart,\n onCompositionEnd,\n autoFocus,\n },\n ref,\n ) => {\n const internalTextareaRef = useRef<HTMLTextAreaElement>(null);\n const [maxHeight, setMaxHeight] = useState<number>(0);\n\n useImperativeHandle(ref, () => internalTextareaRef.current as HTMLTextAreaElement);\n\n useEffect(() => {\n const calculateMaxHeight = () => {\n const textarea = internalTextareaRef.current;\n if (textarea) {\n textarea.style.height = \"auto\";\n const singleRowHeight = textarea.scrollHeight;\n setMaxHeight(singleRowHeight * maxRows);\n if (autoFocus) {\n textarea.focus();\n }\n }\n };\n\n calculateMaxHeight();\n }, [maxRows]);\n\n useEffect(() => {\n const textarea = internalTextareaRef.current;\n if (textarea) {\n textarea.style.height = \"auto\";\n textarea.style.height = `${Math.min(textarea.scrollHeight, maxHeight)}px`;\n }\n }, [value, maxHeight]);\n\n return (\n <textarea\n ref={internalTextareaRef}\n value={value}\n onChange={onChange}\n onKeyDown={onKeyDown}\n onCompositionStart={onCompositionStart}\n onCompositionEnd={onCompositionEnd}\n placeholder={placeholder}\n style={{\n overflow: \"auto\",\n resize: \"none\",\n maxHeight: `${maxHeight}px`,\n }}\n rows={1}\n />\n );\n },\n);\n\nexport default AutoResizingTextarea;\n","import { useCopilotContext, useCopilotMessagesContext } from \"@copilotkit/react-core\";\nimport { gqlToAGUI } from \"@copilotkit/runtime-client-gql\";\nimport { Message } from \"@copilotkit/shared\";\nimport { MutableRefObject, useEffect, useRef, useState } from \"react\";\n\nexport const checkMicrophonePermission = async () => {\n try {\n const permissionStatus = await navigator.permissions.query({\n name: \"microphone\" as PermissionName,\n });\n if (permissionStatus.state === \"granted\") {\n return true;\n } else {\n return false;\n }\n } catch (err) {\n console.error(\"Error checking microphone permission\", err);\n }\n};\n\nexport const requestMicAndPlaybackPermission = async () => {\n try {\n const stream = await navigator.mediaDevices.getUserMedia({ audio: true });\n const audioContext = new window.AudioContext();\n await audioContext.resume();\n return { stream, audioContext };\n } catch (err) {\n console.error(\"Error requesting microphone and playback permissions\", err);\n return null;\n }\n};\n\nconst startRecording = async (\n mediaStreamRef: MutableRefObject<MediaStream | null>,\n mediaRecorderRef: MutableRefObject<MediaRecorder | null>,\n audioContextRef: MutableRefObject<AudioContext | null>,\n recordedChunks: Blob[],\n onStop: () => void,\n) => {\n if (!mediaStreamRef.current || !audioContextRef.current) {\n mediaStreamRef.current = await navigator.mediaDevices.getUserMedia({ audio: true });\n audioContextRef.current = new window.AudioContext();\n await audioContextRef.current.resume();\n }\n\n mediaRecorderRef.current = new MediaRecorder(mediaStreamRef.current!);\n mediaRecorderRef.current.start(1000);\n mediaRecorderRef.current.ondataavailable = (event) => {\n recordedChunks.push(event.data);\n };\n mediaRecorderRef.current.onstop = onStop;\n};\n\nconst stopRecording = (mediaRecorderRef: MutableRefObject<MediaRecorder | null>) => {\n if (mediaRecorderRef.current && mediaRecorderRef.current.state !== \"inactive\") {\n mediaRecorderRef.current.stop();\n }\n};\n\nconst transcribeAudio = async (recordedChunks: Blob[], transcribeAudioUrl: string) => {\n const completeBlob = new Blob(recordedChunks, { type: \"audio/mp4\" });\n const formData = new FormData();\n formData.append(\"file\", completeBlob, \"recording.mp4\");\n\n const response = await fetch(transcribeAudioUrl, {\n method: \"POST\",\n body: formData,\n });\n\n if (!response.ok) {\n throw new Error(`Error: ${response.statusText}`);\n }\n\n const transcription = await response.json();\n return transcription.text;\n};\n\nconst playAudioResponse = (text: string, textToSpeechUrl: string, audioContext: AudioContext) => {\n const encodedText = encodeURIComponent(text);\n const url = `${textToSpeechUrl}?text=${encodedText}`;\n\n fetch(url)\n .then((response) => response.arrayBuffer())\n .then((arrayBuffer) => audioContext.decodeAudioData(arrayBuffer))\n .then((audioBuffer) => {\n const source = audioContext.createBufferSource();\n source.buffer = audioBuffer;\n source.connect(audioContext.destination);\n source.start(0);\n })\n .catch((error) => {\n console.error(\"Error with decoding audio data\", error);\n });\n};\n\nexport type PushToTalkState = \"idle\" | \"recording\" | \"transcribing\";\n\nexport type SendFunction = (text: string) => Promise<Message>;\n\nexport const usePushToTalk = ({\n sendFunction,\n inProgress,\n}: {\n sendFunction: SendFunction;\n inProgress: boolean;\n}) => {\n const [pushToTalkState, setPushToTalkState] = useState<PushToTalkState>(\"idle\");\n const mediaStreamRef = useRef<MediaStream | null>(null);\n const audioContextRef = useRef<AudioContext | null>(null);\n const mediaRecorderRef = useRef<MediaRecorder | null>(null);\n const recordedChunks = useRef<Blob[]>([]);\n const generalContext = useCopilotContext();\n const messagesContext = useCopilotMessagesContext();\n const context = { ...generalContext, ...messagesContext };\n const [startReadingFromMessageId, setStartReadingFromMessageId] = useState<string | null>(null);\n\n useEffect(() => {\n if (pushToTalkState === \"recording\") {\n startRecording(\n mediaStreamRef,\n mediaRecorderRef,\n audioContextRef,\n recordedChunks.current,\n () => {\n setPushToTalkState(\"transcribing\");\n },\n );\n } else {\n stopRecording(mediaRecorderRef);\n if (pushToTalkState === \"transcribing\") {\n transcribeAudio(recordedChunks.current, context.copilotApiConfig.transcribeAudioUrl!).then(\n async (transcription) => {\n recordedChunks.current = [];\n setPushToTalkState(\"idle\");\n const message = await sendFunction(transcription);\n setStartReadingFromMessageId(message.id);\n },\n );\n }\n }\n\n return () => {\n stopRecording(mediaRecorderRef);\n };\n }, [pushToTalkState]);\n\n useEffect(() => {\n if (inProgress === false && startReadingFromMessageId) {\n const lastMessageIndex = context.messages.findIndex(\n (message) => message.id === startReadingFromMessageId,\n );\n\n const aguiMessages = gqlToAGUI(context.messages);\n\n const messagesAfterLast = aguiMessages\n .slice(lastMessageIndex + 1)\n .filter((message) => message.role === \"assistant\");\n\n const text = messagesAfterLast.map((message) => message.content).join(\"\\n\");\n playAudioResponse(text, context.copilotApiConfig.textToSpeechUrl!, audioContextRef.current!);\n\n setStartReadingFromMessageId(null);\n }\n }, [startReadingFromMessageId, inProgress]);\n\n return { pushToTalkState, setPushToTalkState };\n};\n","import React, { useState, useEffect } from \"react\";\nimport { useDarkMode } from \"../../hooks/use-dark-mode\";\n\nexport function PoweredByTag({ showPoweredBy = true }: { showPoweredBy?: boolean }) {\n const [mounted, setMounted] = useState(false);\n const isDark = useDarkMode();\n\n /*\n note(tylerslaton):\n\n Ensure we only use the isDark computed value after client-side mount.\n This prevents hydration mismatches by using a default color on the\n server and initial client render, then updating to the correct\n dark mode color after hydration is complete.\n */\n useEffect(() => {\n setMounted(true);\n }, []);\n\n if (!showPoweredBy) {\n return null;\n }\n\n const poweredByStyle = {\n visibility: \"visible\",\n display: \"block\",\n position: \"static\",\n textAlign: \"center\",\n fontSize: \"12px\",\n padding: \"3px 0\",\n color: mounted && isDark ? \"rgb(69, 69, 69)\" : \"rgb(214, 214, 214)\",\n };\n\n return (\n <div>\n {/*@ts-expect-error -- expecting position not to be a string, but it can be.*/}\n <p className=\"poweredBy\" style={poweredByStyle}>\n Powered by CopilotKit\n </p>\n </div>\n );\n}\n","export const useDarkMode = () => {\n if (typeof window === \"undefined\") return false;\n return (\n document.documentElement.classList.contains(\"dark\") ||\n document.body.classList.contains(\"dark\") ||\n document.documentElement.getAttribute(\"data-theme\") === \"dark\" ||\n document.body.getAttribute(\"data-theme\") === \"dark\" ||\n window.matchMedia(\"(prefers-color-scheme: dark)\").matches\n );\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAAAA,gBAAiD;;;ACAjD,mBAAyC;AAsPhC;AApFF,IAAM,cAAc,aAAAC,QAAM,cAAuC,MAAS;AAE1E,SAAS,iBAA8B;AAC5C,QAAM,UAAU,aAAAA,QAAM,WAAW,WAAW;AAC5C,MAAI,YAAY,QAAW;AACzB,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;;;AC5KA,IAAAC,gBAAoF;AAyD9E,IAAAC,sBAAA;AA5CN,IAAM,2BAAuB;AAAA,EAC3B,CACE;AAAA,IACE,UAAU;AAAA,IACV;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,GACA,QACG;AACH,UAAM,0BAAsB,sBAA4B,IAAI;AAC5D,UAAM,CAAC,WAAW,YAAY,QAAI,wBAAiB,CAAC;AAEpD,2CAAoB,KAAK,MAAM,oBAAoB,OAA8B;AAEjF,iCAAU,MAAM;AACd,YAAM,qBAAqB,MAAM;AAC/B,cAAM,WAAW,oBAAoB;AACrC,YAAI,UAAU;AACZ,mBAAS,MAAM,SAAS;AACxB,gBAAM,kBAAkB,SAAS;AACjC,uBAAa,kBAAkB,OAAO;AACtC,cAAI,WAAW;AACb,qBAAS,MAAM;AAAA,UACjB;AAAA,QACF;AAAA,MACF;AAEA,yBAAmB;AAAA,IACrB,GAAG,CAAC,OAAO,CAAC;AAEZ,iCAAU,MAAM;AACd,YAAM,WAAW,oBAAoB;AACrC,UAAI,UAAU;AACZ,iBAAS,MAAM,SAAS;AACxB,iBAAS,MAAM,SAAS,GAAG,KAAK,IAAI,SAAS,cAAc,SAAS;AAAA,MACtE;AAAA,IACF,GAAG,CAAC,OAAO,SAAS,CAAC;AAErB,WACE;AAAA,MAAC;AAAA;AAAA,QACC,KAAK;AAAA,QACL;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA,OAAO;AAAA,UACL,UAAU;AAAA,UACV,QAAQ;AAAA,UACR,WAAW,GAAG;AAAA,QAChB;AAAA,QACA,MAAM;AAAA;AAAA,IACR;AAAA,EAEJ;AACF;AAEA,IAAO,mBAAQ;;;AC5Ef,wBAA6D;AAC7D,gCAA0B;AAE1B,IAAAC,gBAA8D;AA6B9D,IAAM,iBAAiB,CACrB,gBACA,kBACA,iBACA,gBACA,WACG;AACH,MAAI,CAAC,eAAe,WAAW,CAAC,gBAAgB,SAAS;AACvD,mBAAe,UAAU,MAAM,UAAU,aAAa,aAAa,EAAE,OAAO,KAAK,CAAC;AAClF,oBAAgB,UAAU,IAAI,OAAO,aAAa;AAClD,UAAM,gBAAgB,QAAQ,OAAO;AAAA,EACvC;AAEA,mBAAiB,UAAU,IAAI,cAAc,eAAe,OAAQ;AACpE,mBAAiB,QAAQ,MAAM,GAAI;AACnC,mBAAiB,QAAQ,kBAAkB,CAAC,UAAU;AACpD,mBAAe,KAAK,MAAM,IAAI;AAAA,EAChC;AACA,mBAAiB,QAAQ,SAAS;AACpC;AAEA,IAAM,gBAAgB,CAAC,qBAA6D;AAClF,MAAI,iBAAiB,WAAW,iBAAiB,QAAQ,UAAU,YAAY;AAC7E,qBAAiB,QAAQ,KAAK;AAAA,EAChC;AACF;AAEA,IAAM,kBAAkB,CAAO,gBAAwB,uBAA+B;AACpF,QAAM,eAAe,IAAI,KAAK,gBAAgB,EAAE,MAAM,YAAY,CAAC;AACnE,QAAM,WAAW,IAAI,SAAS;AAC9B,WAAS,OAAO,QAAQ,cAAc,eAAe;AAErD,QAAM,WAAW,MAAM,MAAM,oBAAoB;AAAA,IAC/C,QAAQ;AAAA,IACR,MAAM;AAAA,EACR,CAAC;AAED,MAAI,CAAC,SAAS,IAAI;AAChB,UAAM,IAAI,MAAM,UAAU,SAAS,YAAY;AAAA,EACjD;AAEA,QAAM,gBAAgB,MAAM,SAAS,KAAK;AAC1C,SAAO,cAAc;AACvB;AAEA,IAAM,oBAAoB,CAAC,MAAc,iBAAyB,iBAA+B;AAC/F,QAAM,cAAc,mBAAmB,IAAI;AAC3C,QAAM,MAAM,GAAG,wBAAwB;AAEvC,QAAM,GAAG,EACN,KAAK,CAAC,aAAa,SAAS,YAAY,CAAC,EACzC,KAAK,CAAC,gBAAgB,aAAa,gBAAgB,WAAW,CAAC,EAC/D,KAAK,CAAC,gBAAgB;AACrB,UAAM,SAAS,aAAa,mBAAmB;AAC/C,WAAO,SAAS;AAChB,WAAO,QAAQ,aAAa,WAAW;AACvC,WAAO,MAAM,CAAC;AAAA,EAChB,CAAC,EACA,MAAM,CAAC,UAAU;AAChB,YAAQ,MAAM,kCAAkC,KAAK;AAAA,EACvD,CAAC;AACL;AAMO,IAAM,gBAAgB,CAAC;AAAA,EAC5B;AAAA,EACA;AACF,MAGM;AACJ,QAAM,CAAC,iBAAiB,kBAAkB,QAAI,wBAA0B,MAAM;AAC9E,QAAM,qBAAiB,sBAA2B,IAAI;AACtD,QAAM,sBAAkB,sBAA4B,IAAI;AACxD,QAAM,uBAAmB,sBAA6B,IAAI;AAC1D,QAAM,qBAAiB,sBAAe,CAAC,CAAC;AACxC,QAAM,qBAAiB,qCAAkB;AACzC,QAAM,sBAAkB,6CAA0B;AAClD,QAAM,UAAU,kCAAK,iBAAmB;AACxC,QAAM,CAAC,2BAA2B,4BAA4B,QAAI,wBAAwB,IAAI;AAE9F,+BAAU,MAAM;AACd,QAAI,oBAAoB,aAAa;AACnC;AAAA,QACE;AAAA,QACA;AAAA,QACA;AAAA,QACA,eAAe;AAAA,QACf,MAAM;AACJ,6BAAmB,cAAc;AAAA,QACnC;AAAA,MACF;AAAA,IACF,OAAO;AACL,oBAAc,gBAAgB;AAC9B,UAAI,oBAAoB,gBAAgB;AACtC,wBAAgB,eAAe,SAAS,QAAQ,iBAAiB,kBAAmB,EAAE;AAAA,UACpF,CAAO,kBAAkB;AACvB,2BAAe,UAAU,CAAC;AAC1B,+BAAmB,MAAM;AACzB,kBAAM,UAAU,MAAM,aAAa,aAAa;AAChD,yCAA6B,QAAQ,EAAE;AAAA,UACzC;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAEA,WAAO,MAAM;AACX,oBAAc,gBAAgB;AAAA,IAChC;AAAA,EACF,GAAG,CAAC,eAAe,CAAC;AAEpB,+BAAU,MAAM;AACd,QAAI,eAAe,SAAS,2BAA2B;AACrD,YAAM,mBAAmB,QAAQ,SAAS;AAAA,QACxC,CAAC,YAAY,QAAQ,OAAO;AAAA,MAC9B;AAEA,YAAM,mBAAe,qCAAU,QAAQ,QAAQ;AAE/C,YAAM,oBAAoB,aACvB,MAAM,mBAAmB,CAAC,EAC1B,OAAO,CAAC,YAAY,QAAQ,SAAS,WAAW;AAEnD,YAAM,OAAO,kBAAkB,IAAI,CAAC,YAAY,QAAQ,OAAO,EAAE,KAAK,IAAI;AAC1E,wBAAkB,MAAM,QAAQ,iBAAiB,iBAAkB,gBAAgB,OAAQ;AAE3F,mCAA6B,IAAI;AAAA,IACnC;AAAA,EACF,GAAG,CAAC,2BAA2B,UAAU,CAAC;AAE1C,SAAO,EAAE,iBAAiB,mBAAmB;AAC/C;;;AHjKA,IAAAC,qBAAkC;;;AILlC,IAAAC,gBAA2C;;;ACApC,IAAM,cAAc,MAAM;AAC/B,MAAI,OAAO,WAAW;AAAa,WAAO;AAC1C,SACE,SAAS,gBAAgB,UAAU,SAAS,MAAM,KAClD,SAAS,KAAK,UAAU,SAAS,MAAM,KACvC,SAAS,gBAAgB,aAAa,YAAY,MAAM,UACxD,SAAS,KAAK,aAAa,YAAY,MAAM,UAC7C,OAAO,WAAW,8BAA8B,EAAE;AAEtD;;;AD2BM,IAAAC,sBAAA;AAjCC,SAAS,aAAa,EAAE,gBAAgB,KAAK,GAAgC;AAClF,QAAM,CAAC,SAAS,UAAU,QAAI,wBAAS,KAAK;AAC5C,QAAM,SAAS,YAAY;AAU3B,+BAAU,MAAM;AACd,eAAW,IAAI;AAAA,EACjB,GAAG,CAAC,CAAC;AAEL,MAAI,CAAC,eAAe;AAClB,WAAO;AAAA,EACT;AAEA,QAAM,iBAAiB;AAAA,IACrB,YAAY;AAAA,IACZ,SAAS;AAAA,IACT,UAAU;AAAA,IACV,WAAW;AAAA,IACX,UAAU;AAAA,IACV,SAAS;AAAA,IACT,OAAO,WAAW,SAAS,oBAAoB;AAAA,EACjD;AAEA,SACE,6CAAC,SAEC,uDAAC,OAAE,WAAU,aAAY,OAAO,gBAAgB,mCAEhD,GACF;AAEJ;;;AJ0DQ,IAAAC,sBAAA;AA3FR,IAAM,eAAe;AAEd,IAAM,QAAQ,CAAC;AAAA,EACpB;AAAA,EACA;AAAA,EACA,YAAY;AAAA,EACZ;AAAA,EACA;AAAA,EACA,iBAAiB;AACnB,MAAkB;AAjBlB;AAkBE,QAAM,UAAU,eAAe;AAC/B,QAAM,qBAAiB,sCAAkB;AAEzC,QAAM,gBAAgB,GAAC,oBAAe,qBAAf,mBAAiC;AAExD,QAAM,uBACJ,eAAe,iBAAiB,oBAAoB,UACpD,eAAe,iBAAiB,uBAAuB;AAEzD,QAAM,kBAAc,sBAA4B,IAAI;AACpD,QAAM,CAAC,aAAa,cAAc,QAAI,wBAAS,KAAK;AAEpD,QAAM,iBAAiB,CAAC,UAA4C;AA9BtE,QAAAC;AA+BI,UAAM,SAAS,MAAM;AAGrB,QAAI,OAAO,QAAQ,QAAQ;AAAG;AAG9B,QAAI,OAAO,YAAY;AAAY;AAGnC,KAAAA,MAAA,YAAY,YAAZ,gBAAAA,IAAqB;AAAA,EACvB;AAEA,QAAM,CAAC,MAAM,OAAO,QAAI,wBAAS,EAAE;AACnC,QAAM,OAAO,MAAM;AA5CrB,QAAAA;AA6CI,QAAI;AAAY;AAChB,WAAO,IAAI;AACX,YAAQ,EAAE;AAEV,KAAAA,MAAA,YAAY,YAAZ,gBAAAA,IAAqB;AAAA,EACvB;AAiBA,QAAM,EAAE,iBAAiB,mBAAmB,IAAI,cAAc;AAAA,IAC5D,cAAc;AAAA,IACd;AAAA,EACF,CAAC;AAED,QAAM,eAAe,cAAc,oBAAoB;AACvD,QAAM,aACJ,gBAAgB,CAAC,iBAAiB,QAAQ,MAAM,WAAW,QAAQ,MAAM;AAC3E,QAAM,iBACJ,yBACC,oBAAoB,UAAU,oBAAoB,gBACnD,CAAC;AAEH,QAAM,cAAU,uBAAQ,MAAM;AAhFhC,QAAAA;AAiFI,UAAM,kBAAiBA,MAAA,eAAe,6BAAf,gBAAAA,IAAyC;AAChE,UAAM,uBACJ,iDAAgB,UAAS,6BAA6B,EAAC,iDAAgB;AAEzE,WACE,CAAC,gBAAgB,KAAK,KAAK,EAAE,SAAS,KAAK,oBAAoB,UAAU,CAAC;AAAA,EAE9E,GAAG,EAAC,oBAAe,6BAAf,mBAAyC,OAAO,cAAc,MAAM,eAAe,CAAC;AAExF,QAAM,cAAU,uBAAQ,MAAM;AAC5B,WAAO,gBAAgB,CAAC;AAAA,EAC1B,GAAG,CAAC,cAAc,cAAc,CAAC;AAEjC,QAAM,eAAe,CAAC,WAAW,CAAC;AAElC,SACE,8CAAC,SAAI,WAAW,4BAA4B,gBAAgB,uBAAuB,MACjF;AAAA,kDAAC,SAAI,WAAU,mBAAkB,SAAS,gBACxC;AAAA;AAAA,QAAC;AAAA;AAAA,UACC,KAAK;AAAA,UACL,aAAa,QAAQ,OAAO;AAAA,UAC5B,WAAW;AAAA,UACX,SAAS;AAAA,UACT,OAAO;AAAA,UACP,UAAU,CAAC,UAAU,QAAQ,MAAM,OAAO,KAAK;AAAA,UAC/C,oBAAoB,MAAM,eAAe,IAAI;AAAA,UAC7C,kBAAkB,MAAM,eAAe,KAAK;AAAA,UAC5C,WAAW,CAAC,UAAU;AACpB,gBAAI,MAAM,QAAQ,WAAW,CAAC,MAAM,YAAY,CAAC,aAAa;AAC5D,oBAAM,eAAe;AACrB,kBAAI,SAAS;AACX,qBAAK;AAAA,cACP;AAAA,YACF;AAAA,UACF;AAAA;AAAA,MACF;AAAA,MACA,8CAAC,SAAI,WAAU,2BACZ;AAAA,oBACC,6CAAC,YAAO,SAAS,UAAU,WAAU,gCAClC,kBAAQ,MAAM,YACjB;AAAA,QAGF,6CAAC,SAAI,OAAO,EAAE,UAAU,EAAE,GAAG;AAAA,QAE5B,kBACC;AAAA,UAAC;AAAA;AAAA,YACC,SAAS,MACP,mBAAmB,oBAAoB,SAAS,cAAc,cAAc;AAAA,YAE9E,WACE,oBAAoB,cAChB,+DACA;AAAA,YAGL,kBAAQ,MAAM;AAAA;AAAA,QACjB;AAAA,QAEF;AAAA,UAAC;AAAA;AAAA,YACC,UAAU;AAAA,YACV,SAAS,gBAAgB,CAAC,iBAAiB,SAAS;AAAA,YACpD,+BAA6B;AAAA,YAC7B,gBAAc,aAAa,qCAAqC;AAAA,YAChE,WAAU;AAAA,YAET;AAAA;AAAA,QACH;AAAA,SACF;AAAA,OACF;AAAA,IACA,6CAAC,gBAAa,eAA8B;AAAA,KAC9C;AAEJ;","names":["import_react","React","import_react","import_jsx_runtime","import_react","import_react_core","import_react","import_jsx_runtime","import_jsx_runtime","_a"]}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
Input
|
|
3
|
-
} from "../../chunk-
|
|
4
|
-
import "../../chunk-
|
|
3
|
+
} from "../../chunk-ZJCHKHE4.mjs";
|
|
4
|
+
import "../../chunk-ELGRNEAO.mjs";
|
|
5
5
|
import "../../chunk-QIOJXTIQ.mjs";
|
|
6
6
|
import "../../chunk-IEMQ2SQW.mjs";
|
|
7
7
|
import "../../chunk-XWG3L6QC.mjs";
|
|
@@ -82,7 +82,7 @@ __export(Modal_exports, {
|
|
|
82
82
|
CopilotModal: () => CopilotModal
|
|
83
83
|
});
|
|
84
84
|
module.exports = __toCommonJS(Modal_exports);
|
|
85
|
-
var
|
|
85
|
+
var import_react16 = __toESM(require("react"));
|
|
86
86
|
|
|
87
87
|
// src/components/chat/ChatContext.tsx
|
|
88
88
|
var import_react = __toESM(require("react"));
|
|
@@ -2034,7 +2034,7 @@ function useScrollToBottom(messages) {
|
|
|
2034
2034
|
}
|
|
2035
2035
|
|
|
2036
2036
|
// src/components/chat/Input.tsx
|
|
2037
|
-
var
|
|
2037
|
+
var import_react14 = require("react");
|
|
2038
2038
|
|
|
2039
2039
|
// src/components/chat/Textarea.tsx
|
|
2040
2040
|
var import_react11 = require("react");
|
|
@@ -2203,6 +2203,9 @@ var usePushToTalk = ({
|
|
|
2203
2203
|
// src/components/chat/Input.tsx
|
|
2204
2204
|
var import_react_core7 = require("@copilotkit/react-core");
|
|
2205
2205
|
|
|
2206
|
+
// src/components/chat/PoweredByTag.tsx
|
|
2207
|
+
var import_react13 = require("react");
|
|
2208
|
+
|
|
2206
2209
|
// src/hooks/use-dark-mode.ts
|
|
2207
2210
|
var useDarkMode = () => {
|
|
2208
2211
|
if (typeof window === "undefined")
|
|
@@ -2213,7 +2216,11 @@ var useDarkMode = () => {
|
|
|
2213
2216
|
// src/components/chat/PoweredByTag.tsx
|
|
2214
2217
|
var import_jsx_runtime19 = require("react/jsx-runtime");
|
|
2215
2218
|
function PoweredByTag({ showPoweredBy = true }) {
|
|
2219
|
+
const [mounted, setMounted] = (0, import_react13.useState)(false);
|
|
2216
2220
|
const isDark = useDarkMode();
|
|
2221
|
+
(0, import_react13.useEffect)(() => {
|
|
2222
|
+
setMounted(true);
|
|
2223
|
+
}, []);
|
|
2217
2224
|
if (!showPoweredBy) {
|
|
2218
2225
|
return null;
|
|
2219
2226
|
}
|
|
@@ -2224,7 +2231,7 @@ function PoweredByTag({ showPoweredBy = true }) {
|
|
|
2224
2231
|
textAlign: "center",
|
|
2225
2232
|
fontSize: "12px",
|
|
2226
2233
|
padding: "3px 0",
|
|
2227
|
-
color: isDark ? "rgb(69, 69, 69)" : "rgb(214, 214, 214)"
|
|
2234
|
+
color: mounted && isDark ? "rgb(69, 69, 69)" : "rgb(214, 214, 214)"
|
|
2228
2235
|
};
|
|
2229
2236
|
return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("p", { className: "poweredBy", style: poweredByStyle, children: "Powered by CopilotKit" }) });
|
|
2230
2237
|
}
|
|
@@ -2245,8 +2252,8 @@ var Input = ({
|
|
|
2245
2252
|
const copilotContext = (0, import_react_core7.useCopilotContext)();
|
|
2246
2253
|
const showPoweredBy = !((_a = copilotContext.copilotApiConfig) == null ? void 0 : _a.publicApiKey);
|
|
2247
2254
|
const pushToTalkConfigured = copilotContext.copilotApiConfig.textToSpeechUrl !== void 0 && copilotContext.copilotApiConfig.transcribeAudioUrl !== void 0;
|
|
2248
|
-
const textareaRef = (0,
|
|
2249
|
-
const [isComposing, setIsComposing] = (0,
|
|
2255
|
+
const textareaRef = (0, import_react14.useRef)(null);
|
|
2256
|
+
const [isComposing, setIsComposing] = (0, import_react14.useState)(false);
|
|
2250
2257
|
const handleDivClick = (event) => {
|
|
2251
2258
|
var _a2;
|
|
2252
2259
|
const target = event.target;
|
|
@@ -2256,7 +2263,7 @@ var Input = ({
|
|
|
2256
2263
|
return;
|
|
2257
2264
|
(_a2 = textareaRef.current) == null ? void 0 : _a2.focus();
|
|
2258
2265
|
};
|
|
2259
|
-
const [text, setText] = (0,
|
|
2266
|
+
const [text, setText] = (0, import_react14.useState)("");
|
|
2260
2267
|
const send = () => {
|
|
2261
2268
|
var _a2;
|
|
2262
2269
|
if (inProgress)
|
|
@@ -2272,13 +2279,13 @@ var Input = ({
|
|
|
2272
2279
|
const isInProgress = inProgress || pushToTalkState === "transcribing";
|
|
2273
2280
|
const buttonIcon = isInProgress && !hideStopButton ? context.icons.stopIcon : context.icons.sendIcon;
|
|
2274
2281
|
const showPushToTalk = pushToTalkConfigured && (pushToTalkState === "idle" || pushToTalkState === "recording") && !inProgress;
|
|
2275
|
-
const canSend = (0,
|
|
2282
|
+
const canSend = (0, import_react14.useMemo)(() => {
|
|
2276
2283
|
var _a2;
|
|
2277
2284
|
const interruptEvent = (_a2 = copilotContext.langGraphInterruptAction) == null ? void 0 : _a2.event;
|
|
2278
2285
|
const interruptInProgress = (interruptEvent == null ? void 0 : interruptEvent.name) === "LangGraphInterruptEvent" && !(interruptEvent == null ? void 0 : interruptEvent.response);
|
|
2279
2286
|
return !isInProgress && text.trim().length > 0 && pushToTalkState === "idle" && !interruptInProgress;
|
|
2280
2287
|
}, [(_b = copilotContext.langGraphInterruptAction) == null ? void 0 : _b.event, isInProgress, text, pushToTalkState]);
|
|
2281
|
-
const canStop = (0,
|
|
2288
|
+
const canStop = (0, import_react14.useMemo)(() => {
|
|
2282
2289
|
return isInProgress && !hideStopButton;
|
|
2283
2290
|
}, [isInProgress, hideStopButton]);
|
|
2284
2291
|
const sendDisabled = !canSend && !canStop;
|
|
@@ -2334,7 +2341,7 @@ var Input = ({
|
|
|
2334
2341
|
};
|
|
2335
2342
|
|
|
2336
2343
|
// src/components/chat/Chat.tsx
|
|
2337
|
-
var
|
|
2344
|
+
var import_react15 = __toESM(require("react"));
|
|
2338
2345
|
var import_react_core9 = require("@copilotkit/react-core");
|
|
2339
2346
|
var import_shared3 = require("@copilotkit/shared");
|
|
2340
2347
|
var import_shared4 = require("@copilotkit/shared");
|
|
@@ -2505,10 +2512,10 @@ function CopilotChat({
|
|
|
2505
2512
|
removeInternalErrorHandler
|
|
2506
2513
|
} = (0, import_react_core9.useCopilotContext)();
|
|
2507
2514
|
const { publicApiKey, chatApiEndpoint } = copilotApiConfig;
|
|
2508
|
-
const [selectedImages, setSelectedImages] = (0,
|
|
2509
|
-
const [chatError, setChatError] = (0,
|
|
2510
|
-
const fileInputRef = (0,
|
|
2511
|
-
const triggerObservabilityHook = (0,
|
|
2515
|
+
const [selectedImages, setSelectedImages] = (0, import_react15.useState)([]);
|
|
2516
|
+
const [chatError, setChatError] = (0, import_react15.useState)(null);
|
|
2517
|
+
const fileInputRef = (0, import_react15.useRef)(null);
|
|
2518
|
+
const triggerObservabilityHook = (0, import_react15.useCallback)(
|
|
2512
2519
|
(hookName, ...args) => {
|
|
2513
2520
|
if (publicApiKey && (observabilityHooks == null ? void 0 : observabilityHooks[hookName])) {
|
|
2514
2521
|
observabilityHooks[hookName](...args);
|
|
@@ -2527,7 +2534,7 @@ function CopilotChat({
|
|
|
2527
2534
|
},
|
|
2528
2535
|
[publicApiKey, observabilityHooks, setBannerError]
|
|
2529
2536
|
);
|
|
2530
|
-
const triggerChatError = (0,
|
|
2537
|
+
const triggerChatError = (0, import_react15.useCallback)(
|
|
2531
2538
|
(error, operation, originalError) => {
|
|
2532
2539
|
const errorMessage = (error == null ? void 0 : error.message) || (error == null ? void 0 : error.toString()) || "An error occurred";
|
|
2533
2540
|
setChatError({
|
|
@@ -2573,7 +2580,7 @@ function CopilotChat({
|
|
|
2573
2580
|
},
|
|
2574
2581
|
[publicApiKey, chatApiEndpoint, observabilityHooks, setBannerError]
|
|
2575
2582
|
);
|
|
2576
|
-
(0,
|
|
2583
|
+
(0, import_react15.useEffect)(() => {
|
|
2577
2584
|
const id = "chat-component";
|
|
2578
2585
|
setInternalErrorHandler({
|
|
2579
2586
|
[id]: (error) => {
|
|
@@ -2586,7 +2593,7 @@ function CopilotChat({
|
|
|
2586
2593
|
removeInternalErrorHandler == null ? void 0 : removeInternalErrorHandler(id);
|
|
2587
2594
|
};
|
|
2588
2595
|
}, [triggerChatError, setInternalErrorHandler, removeInternalErrorHandler]);
|
|
2589
|
-
(0,
|
|
2596
|
+
(0, import_react15.useEffect)(() => {
|
|
2590
2597
|
if (!imageUploadsEnabled)
|
|
2591
2598
|
return;
|
|
2592
2599
|
const handlePaste = (e) => __async(this, null, function* () {
|
|
@@ -2632,7 +2639,7 @@ function CopilotChat({
|
|
|
2632
2639
|
document.addEventListener("paste", handlePaste);
|
|
2633
2640
|
return () => document.removeEventListener("paste", handlePaste);
|
|
2634
2641
|
}, [imageUploadsEnabled, triggerChatError]);
|
|
2635
|
-
(0,
|
|
2642
|
+
(0, import_react15.useEffect)(() => {
|
|
2636
2643
|
if (!(additionalInstructions == null ? void 0 : additionalInstructions.length)) {
|
|
2637
2644
|
setChatInstructions(instructions || "");
|
|
2638
2645
|
return;
|
|
@@ -2660,8 +2667,8 @@ function CopilotChat({
|
|
|
2660
2667
|
onStopGeneration,
|
|
2661
2668
|
onReloadMessages
|
|
2662
2669
|
);
|
|
2663
|
-
const prevIsLoading = (0,
|
|
2664
|
-
(0,
|
|
2670
|
+
const prevIsLoading = (0, import_react15.useRef)(isLoading);
|
|
2671
|
+
(0, import_react15.useEffect)(() => {
|
|
2665
2672
|
if (prevIsLoading.current !== isLoading) {
|
|
2666
2673
|
if (isLoading) {
|
|
2667
2674
|
triggerObservabilityHook("onChatStarted");
|
|
@@ -2680,7 +2687,7 @@ function CopilotChat({
|
|
|
2680
2687
|
triggerObservabilityHook("onMessageSent", text);
|
|
2681
2688
|
return sendMessage(text, images);
|
|
2682
2689
|
};
|
|
2683
|
-
const chatContext =
|
|
2690
|
+
const chatContext = import_react15.default.useContext(ChatContext);
|
|
2684
2691
|
const isVisible = chatContext ? chatContext.open : true;
|
|
2685
2692
|
const handleRegenerate = (messageId) => {
|
|
2686
2693
|
if (onRegenerate) {
|
|
@@ -2815,7 +2822,7 @@ function WrappedCopilotChat({
|
|
|
2815
2822
|
labels,
|
|
2816
2823
|
className
|
|
2817
2824
|
}) {
|
|
2818
|
-
const chatContext =
|
|
2825
|
+
const chatContext = import_react15.default.useContext(ChatContext);
|
|
2819
2826
|
if (!chatContext) {
|
|
2820
2827
|
return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(ChatContextProvider, { icons, labels, open: true, setOpen: () => {
|
|
2821
2828
|
}, children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: `copilotKitChat ${className != null ? className : ""}`, children }) });
|
|
@@ -2844,15 +2851,15 @@ var useCopilotChatLogic = (chatSuggestions, makeSystemMessage, disableSystemMess
|
|
|
2844
2851
|
const generalContext = (0, import_react_core9.useCopilotContext)();
|
|
2845
2852
|
const messagesContext = (0, import_react_core9.useCopilotMessagesContext)();
|
|
2846
2853
|
const { actions } = generalContext;
|
|
2847
|
-
const [suggestionsFailed, setSuggestionsFailed] = (0,
|
|
2848
|
-
const hasGeneratedInitialSuggestions = (0,
|
|
2849
|
-
(0,
|
|
2854
|
+
const [suggestionsFailed, setSuggestionsFailed] = (0, import_react15.useState)(false);
|
|
2855
|
+
const hasGeneratedInitialSuggestions = (0, import_react15.useRef)(false);
|
|
2856
|
+
(0, import_react15.useEffect)(() => {
|
|
2850
2857
|
if (Array.isArray(chatSuggestions)) {
|
|
2851
2858
|
setSuggestions(chatSuggestions);
|
|
2852
2859
|
hasGeneratedInitialSuggestions.current = true;
|
|
2853
2860
|
}
|
|
2854
2861
|
}, [JSON.stringify(chatSuggestions), setSuggestions]);
|
|
2855
|
-
const generateSuggestionsWithErrorHandling = (0,
|
|
2862
|
+
const generateSuggestionsWithErrorHandling = (0, import_react15.useCallback)(
|
|
2856
2863
|
(context) => __async(void 0, null, function* () {
|
|
2857
2864
|
try {
|
|
2858
2865
|
yield generateSuggestions();
|
|
@@ -2863,7 +2870,7 @@ var useCopilotChatLogic = (chatSuggestions, makeSystemMessage, disableSystemMess
|
|
|
2863
2870
|
}),
|
|
2864
2871
|
[generateSuggestions]
|
|
2865
2872
|
);
|
|
2866
|
-
(0,
|
|
2873
|
+
(0, import_react15.useEffect)(() => {
|
|
2867
2874
|
if (chatSuggestions !== "auto" || isLoadingSuggestions || suggestionsFailed) {
|
|
2868
2875
|
return;
|
|
2869
2876
|
}
|
|
@@ -2893,13 +2900,13 @@ var useCopilotChatLogic = (chatSuggestions, makeSystemMessage, disableSystemMess
|
|
|
2893
2900
|
// Use stable string instead of object reference
|
|
2894
2901
|
generateSuggestionsWithErrorHandling
|
|
2895
2902
|
]);
|
|
2896
|
-
(0,
|
|
2903
|
+
(0, import_react15.useEffect)(() => {
|
|
2897
2904
|
if (chatSuggestions !== "auto") {
|
|
2898
2905
|
hasGeneratedInitialSuggestions.current = false;
|
|
2899
2906
|
setSuggestionsFailed(false);
|
|
2900
2907
|
}
|
|
2901
2908
|
}, [chatSuggestions]);
|
|
2902
|
-
const stableContext = (0,
|
|
2909
|
+
const stableContext = (0, import_react15.useMemo)(
|
|
2903
2910
|
() => __spreadValues(__spreadValues({}, generalContext), messagesContext),
|
|
2904
2911
|
[
|
|
2905
2912
|
// Only include stable dependencies
|
|
@@ -2908,12 +2915,12 @@ var useCopilotChatLogic = (chatSuggestions, makeSystemMessage, disableSystemMess
|
|
|
2908
2915
|
generalContext.isLoading
|
|
2909
2916
|
]
|
|
2910
2917
|
);
|
|
2911
|
-
const resetSuggestions = (0,
|
|
2918
|
+
const resetSuggestions = (0, import_react15.useCallback)(() => {
|
|
2912
2919
|
resetSuggestionsFromHook();
|
|
2913
2920
|
setSuggestionsFailed(false);
|
|
2914
2921
|
hasGeneratedInitialSuggestions.current = false;
|
|
2915
2922
|
}, [resetSuggestionsFromHook]);
|
|
2916
|
-
(0,
|
|
2923
|
+
(0, import_react15.useEffect)(() => {
|
|
2917
2924
|
onInProgress == null ? void 0 : onInProgress(isLoading);
|
|
2918
2925
|
}, [onInProgress, isLoading]);
|
|
2919
2926
|
const safelySendMessage = (messageContent, imagesToUse) => __async(void 0, null, function* () {
|
|
@@ -3086,7 +3093,7 @@ var CopilotModalInner = (_a) => {
|
|
|
3086
3093
|
]);
|
|
3087
3094
|
const { copilotApiConfig, setBannerError } = (0, import_react_core11.useCopilotContext)();
|
|
3088
3095
|
const { publicApiKey } = copilotApiConfig;
|
|
3089
|
-
const triggerObservabilityHook = (0,
|
|
3096
|
+
const triggerObservabilityHook = (0, import_react16.useCallback)(
|
|
3090
3097
|
(hookName, ...args) => {
|
|
3091
3098
|
if (publicApiKey && (observabilityHooks == null ? void 0 : observabilityHooks[hookName])) {
|
|
3092
3099
|
observabilityHooks[hookName](...args);
|
|
@@ -3106,8 +3113,8 @@ var CopilotModalInner = (_a) => {
|
|
|
3106
3113
|
[publicApiKey, observabilityHooks, setBannerError]
|
|
3107
3114
|
);
|
|
3108
3115
|
const { open } = useChatContext();
|
|
3109
|
-
const prevOpen = (0,
|
|
3110
|
-
(0,
|
|
3116
|
+
const prevOpen = (0, import_react16.useRef)(open);
|
|
3117
|
+
(0, import_react16.useEffect)(() => {
|
|
3111
3118
|
if (prevOpen.current !== open) {
|
|
3112
3119
|
onSetOpen == null ? void 0 : onSetOpen(open);
|
|
3113
3120
|
if (open) {
|
|
@@ -3118,8 +3125,8 @@ var CopilotModalInner = (_a) => {
|
|
|
3118
3125
|
prevOpen.current = open;
|
|
3119
3126
|
}
|
|
3120
3127
|
}, [open, onSetOpen, triggerObservabilityHook]);
|
|
3121
|
-
const memoizedHeader = (0,
|
|
3122
|
-
const memoizedChildren = (0,
|
|
3128
|
+
const memoizedHeader = (0, import_react16.useMemo)(() => /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(Header2, {}), [Header2]);
|
|
3129
|
+
const memoizedChildren = (0, import_react16.useMemo)(() => children, [children]);
|
|
3123
3130
|
return /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(import_jsx_runtime25.Fragment, { children: [
|
|
3124
3131
|
memoizedChildren,
|
|
3125
3132
|
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className, children: [
|
|
@@ -3199,7 +3206,7 @@ var CopilotModal = (_a) => {
|
|
|
3199
3206
|
"children",
|
|
3200
3207
|
"observabilityHooks"
|
|
3201
3208
|
]);
|
|
3202
|
-
const [openState, setOpenState] =
|
|
3209
|
+
const [openState, setOpenState] = import_react16.default.useState(defaultOpen);
|
|
3203
3210
|
return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(ChatContextProvider, { icons, labels, open: openState, setOpen: setOpenState, children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
3204
3211
|
CopilotModalInner,
|
|
3205
3212
|
__spreadProps(__spreadValues({
|