@copilotkit/react-ui
Version:
<img src="https://github.com/user-attachments/assets/0a6b64d9-e193-4940-a3f6-60334ac34084" alt="banner" style="border-radius: 12px; border: 2px solid #d6d4fa;" />
474 lines (472 loc) • 14.7 kB
JavaScript
import {
RenderActionExecutionMessage
} from "./chunk-53CVDVS5.mjs";
import {
RenderAgentStateMessage
} from "./chunk-2II3Q27P.mjs";
import {
RenderImageMessage
} from "./chunk-ULDQXCED.mjs";
import {
RenderResultMessage
} from "./chunk-C7OB63U5.mjs";
import {
RenderTextMessage
} from "./chunk-32MUWKL3.mjs";
import {
AssistantMessage
} from "./chunk-L3GZ7TXC.mjs";
import {
UserMessage
} from "./chunk-HWMFMBJC.mjs";
import {
Suggestions
} from "./chunk-QGSPTXOV.mjs";
import {
reloadSuggestions
} from "./chunk-IMBPSLL4.mjs";
import {
ImageUploadQueue
} from "./chunk-PLHTVHUW.mjs";
import {
Input
} from "./chunk-4HUXYD3B.mjs";
import {
Messages
} from "./chunk-B3D7U7TJ.mjs";
import {
ChatContext,
ChatContextProvider
} from "./chunk-IEMQ2SQW.mjs";
import {
__async,
__spreadProps,
__spreadValues
} from "./chunk-MRXNTQOX.mjs";
// src/components/chat/Chat.tsx
import React, { useEffect, useRef, useState } from "react";
import {
useCopilotChat,
useCopilotContext,
useCopilotMessagesContext
} from "@copilotkit/react-core";
import { Role, TextMessage, ImageMessage } from "@copilotkit/runtime-client-gql";
import { randomId } from "@copilotkit/shared";
import { runAgent, stopAgent } from "@copilotkit/react-core";
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
function CopilotChat({
instructions,
onSubmitMessage,
makeSystemMessage,
onInProgress,
onStopGeneration,
onReloadMessages,
onRegenerate,
onCopy,
onThumbsUp,
onThumbsDown,
markdownTagRenderers,
Messages: Messages2 = Messages,
RenderTextMessage: RenderTextMessage2 = RenderTextMessage,
RenderActionExecutionMessage: RenderActionExecutionMessage2 = RenderActionExecutionMessage,
RenderAgentStateMessage: RenderAgentStateMessage2 = RenderAgentStateMessage,
RenderResultMessage: RenderResultMessage2 = RenderResultMessage,
RenderImageMessage: RenderImageMessage2 = RenderImageMessage,
RenderSuggestionsList = Suggestions,
Input: Input2 = Input,
className,
icons,
labels,
AssistantMessage: AssistantMessage2 = AssistantMessage,
UserMessage: UserMessage2 = UserMessage,
imageUploadsEnabled,
inputFileAccept = "image/*",
hideStopButton
}) {
const { additionalInstructions, setChatInstructions } = useCopilotContext();
const [selectedImages, setSelectedImages] = useState([]);
const fileInputRef = useRef(null);
useEffect(() => {
if (!imageUploadsEnabled)
return;
const handlePaste = (e) => __async(this, null, function* () {
var _a, _b;
const target = e.target;
if (!((_a = target.parentElement) == null ? void 0 : _a.classList.contains("copilotKitInput")))
return;
const items = Array.from(((_b = e.clipboardData) == null ? void 0 : _b.items) || []);
const imageItems = items.filter((item) => item.type.startsWith("image/"));
if (imageItems.length === 0)
return;
e.preventDefault();
const imagePromises = imageItems.map((item) => {
const file = item.getAsFile();
if (!file)
return Promise.resolve(null);
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onload = (e2) => {
var _a2, _b2;
const base64String = (_b2 = (_a2 = e2.target) == null ? void 0 : _a2.result) == null ? void 0 : _b2.split(",")[1];
if (base64String) {
resolve({
contentType: file.type,
bytes: base64String
});
} else {
resolve(null);
}
};
reader.onerror = reject;
reader.readAsDataURL(file);
});
});
try {
const loadedImages = (yield Promise.all(imagePromises)).filter((img) => img !== null);
setSelectedImages((prev) => [...prev, ...loadedImages]);
} catch (error) {
console.error("Error processing pasted images:", error);
}
});
document.addEventListener("paste", handlePaste);
return () => document.removeEventListener("paste", handlePaste);
}, [imageUploadsEnabled]);
useEffect(() => {
if (!(additionalInstructions == null ? void 0 : additionalInstructions.length)) {
setChatInstructions(instructions || "");
return;
}
const combinedAdditionalInstructions = [
instructions,
"Additionally, follow these instructions:",
...additionalInstructions.map((instruction) => `- ${instruction}`)
];
console.log("combinedAdditionalInstructions", combinedAdditionalInstructions);
setChatInstructions(combinedAdditionalInstructions.join("\n") || "");
}, [instructions, additionalInstructions]);
const {
visibleMessages,
isLoading,
currentSuggestions,
sendMessage,
stopGeneration,
reloadMessages
} = useCopilotChatLogic(
makeSystemMessage,
onInProgress,
onSubmitMessage,
onStopGeneration,
onReloadMessages
);
const handleSendMessage = (text) => {
const images = selectedImages;
setSelectedImages([]);
if (fileInputRef.current) {
fileInputRef.current.value = "";
}
return sendMessage(text, images);
};
const chatContext = React.useContext(ChatContext);
const isVisible = chatContext ? chatContext.open : true;
const handleRegenerate = (messageId) => {
if (onRegenerate) {
onRegenerate(messageId);
}
reloadMessages(messageId);
};
const handleCopy = (message) => {
if (onCopy) {
onCopy(message);
}
};
const handleImageUpload = (event) => __async(this, null, function* () {
if (!event.target.files || event.target.files.length === 0) {
return;
}
const files = Array.from(event.target.files).filter((file) => file.type.startsWith("image/"));
if (files.length === 0)
return;
const fileReadPromises = files.map((file) => {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onload = (e) => {
var _a, _b;
const base64String = ((_b = (_a = e.target) == null ? void 0 : _a.result) == null ? void 0 : _b.split(",")[1]) || "";
if (base64String) {
resolve({
contentType: file.type,
bytes: base64String
});
}
};
reader.onerror = reject;
reader.readAsDataURL(file);
});
});
try {
const loadedImages = yield Promise.all(fileReadPromises);
setSelectedImages((prev) => [...prev, ...loadedImages]);
} catch (error) {
console.error("Error reading files:", error);
}
});
const removeSelectedImage = (index) => {
setSelectedImages((prev) => prev.filter((_, i) => i !== index));
};
return /* @__PURE__ */ jsxs(WrappedCopilotChat, { icons, labels, className, children: [
/* @__PURE__ */ jsx(
Messages2,
{
AssistantMessage: AssistantMessage2,
UserMessage: UserMessage2,
RenderTextMessage: RenderTextMessage2,
RenderActionExecutionMessage: RenderActionExecutionMessage2,
RenderAgentStateMessage: RenderAgentStateMessage2,
RenderResultMessage: RenderResultMessage2,
RenderImageMessage: RenderImageMessage2,
messages: visibleMessages,
inProgress: isLoading,
onRegenerate: handleRegenerate,
onCopy: handleCopy,
onThumbsUp,
onThumbsDown,
markdownTagRenderers,
children: currentSuggestions.length > 0 && /* @__PURE__ */ jsx(
RenderSuggestionsList,
{
onSuggestionClick: handleSendMessage,
suggestions: currentSuggestions
}
)
}
),
imageUploadsEnabled && /* @__PURE__ */ jsxs(Fragment, { children: [
/* @__PURE__ */ jsx(ImageUploadQueue, { images: selectedImages, onRemoveImage: removeSelectedImage }),
/* @__PURE__ */ jsx(
"input",
{
type: "file",
multiple: true,
ref: fileInputRef,
onChange: handleImageUpload,
accept: inputFileAccept,
style: { display: "none" }
}
)
] }),
/* @__PURE__ */ jsx(
Input2,
{
inProgress: isLoading,
onSend: handleSendMessage,
isVisible,
onStop: stopGeneration,
onUpload: imageUploadsEnabled ? () => {
var _a;
return (_a = fileInputRef.current) == null ? void 0 : _a.click();
} : void 0,
hideStopButton
}
)
] });
}
function WrappedCopilotChat({
children,
icons,
labels,
className
}) {
const chatContext = React.useContext(ChatContext);
if (!chatContext) {
return /* @__PURE__ */ jsx(ChatContextProvider, { icons, labels, open: true, setOpen: () => {
}, children: /* @__PURE__ */ jsx("div", { className: `copilotKitChat ${className != null ? className : ""}`, children }) });
}
return /* @__PURE__ */ jsx(Fragment, { children });
}
var SUGGESTIONS_DEBOUNCE_TIMEOUT = 1e3;
var useCopilotChatLogic = (makeSystemMessage, onInProgress, onSubmitMessage, onStopGeneration, onReloadMessages) => {
var _a;
const {
visibleMessages,
appendMessage,
reloadMessages: defaultReloadMessages,
stopGeneration: defaultStopGeneration,
runChatCompletion,
isLoading
} = useCopilotChat({
id: randomId(),
makeSystemMessage
});
const [currentSuggestions, setCurrentSuggestions] = useState([]);
const suggestionsAbortControllerRef = useRef(null);
const debounceTimerRef = useRef();
const abortSuggestions = () => {
var _a2;
(_a2 = suggestionsAbortControllerRef.current) == null ? void 0 : _a2.abort();
suggestionsAbortControllerRef.current = null;
};
const generalContext = useCopilotContext();
const messagesContext = useCopilotMessagesContext();
const context = __spreadValues(__spreadValues({}, generalContext), messagesContext);
useEffect(() => {
onInProgress == null ? void 0 : onInProgress(isLoading);
abortSuggestions();
debounceTimerRef.current = setTimeout(
() => {
if (!isLoading && Object.keys(context.chatSuggestionConfiguration).length !== 0) {
suggestionsAbortControllerRef.current = new AbortController();
reloadSuggestions(
context,
context.chatSuggestionConfiguration,
setCurrentSuggestions,
suggestionsAbortControllerRef
);
}
},
currentSuggestions.length == 0 ? 0 : SUGGESTIONS_DEBOUNCE_TIMEOUT
);
return () => {
clearTimeout(debounceTimerRef.current);
};
}, [
isLoading,
context.chatSuggestionConfiguration,
// hackish way to trigger suggestions reload on reset, but better than moving suggestions to the
// global context
visibleMessages.length == 0
]);
const sendMessage = (messageContent, imagesToUse) => __async(void 0, null, function* () {
const images = imagesToUse || [];
abortSuggestions();
setCurrentSuggestions([]);
let firstMessage = null;
if (messageContent.trim().length > 0) {
const textMessage = new TextMessage({
content: messageContent,
role: Role.User
});
if (onSubmitMessage) {
try {
yield onSubmitMessage(messageContent);
} catch (error) {
console.error("Error in onSubmitMessage:", error);
}
}
yield appendMessage(textMessage, { followUp: images.length === 0 });
if (!firstMessage) {
firstMessage = textMessage;
}
}
if (images.length > 0) {
for (let i = 0; i < images.length; i++) {
const imageMessage = new ImageMessage({
format: images[i].contentType.replace("image/", ""),
bytes: images[i].bytes,
role: Role.User
});
yield appendMessage(imageMessage, { followUp: i === images.length - 1 });
if (!firstMessage) {
firstMessage = imageMessage;
}
}
}
if (!firstMessage) {
return new TextMessage({ content: "", role: Role.User });
}
return firstMessage;
});
const messages = visibleMessages;
const { setMessages } = messagesContext;
const currentAgentName = (_a = generalContext.agentSession) == null ? void 0 : _a.agentName;
const restartCurrentAgent = (hint) => __async(void 0, null, function* () {
if (generalContext.agentSession) {
generalContext.setAgentSession(__spreadProps(__spreadValues({}, generalContext.agentSession), {
nodeName: void 0,
threadId: void 0
}));
generalContext.setCoagentStates((prevAgentStates) => {
return __spreadProps(__spreadValues({}, prevAgentStates), {
[generalContext.agentSession.agentName]: __spreadProps(__spreadValues({}, prevAgentStates[generalContext.agentSession.agentName]), {
threadId: void 0,
nodeName: void 0,
runId: void 0
})
});
});
}
});
const runCurrentAgent = (hint) => __async(void 0, null, function* () {
if (generalContext.agentSession) {
yield runAgent(
generalContext.agentSession.agentName,
context,
appendMessage,
runChatCompletion,
hint
);
}
});
const stopCurrentAgent = () => {
if (generalContext.agentSession) {
stopAgent(generalContext.agentSession.agentName, context);
}
};
const setCurrentAgentState = (state) => {
if (generalContext.agentSession) {
generalContext.setCoagentStates((prevAgentStates) => {
return __spreadProps(__spreadValues({}, prevAgentStates), {
[generalContext.agentSession.agentName]: {
state
}
});
});
}
};
function stopGeneration() {
if (onStopGeneration) {
onStopGeneration({
messages,
setMessages,
stopGeneration: defaultStopGeneration,
currentAgentName,
restartCurrentAgent,
stopCurrentAgent,
runCurrentAgent,
setCurrentAgentState
});
} else {
defaultStopGeneration();
}
}
function reloadMessages(messageId) {
if (onReloadMessages) {
onReloadMessages({
messages,
setMessages,
stopGeneration: defaultStopGeneration,
currentAgentName,
restartCurrentAgent,
stopCurrentAgent,
runCurrentAgent,
setCurrentAgentState,
messageId
});
} else {
defaultReloadMessages(messageId);
}
}
return {
visibleMessages,
isLoading,
currentSuggestions,
sendMessage,
stopGeneration,
reloadMessages
};
};
export {
CopilotChat,
WrappedCopilotChat,
useCopilotChatLogic
};
//# sourceMappingURL=chunk-HKTWKCPS.mjs.map