@copilotkit/react-ui 1.55.0-next.9 → 1.55.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 +21 -4
- package/dist/index.cjs +429 -174
- package/dist/index.cjs.map +1 -1
- package/dist/index.css +334 -25
- package/dist/index.css.map +1 -1
- package/dist/index.d.cts +62 -6
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +62 -6
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +430 -176
- package/dist/index.mjs.map +1 -1
- package/dist/index.umd.js +440 -179
- package/dist/index.umd.js.map +1 -1
- package/oxlint-rules/copilotkit-plugin.mjs +10 -0
- package/oxlint-rules/require-cpk-prefix.mjs +547 -0
- package/package.json +33 -34
- package/src/components/chat/AttachmentQueue.tsx +125 -0
- package/src/components/chat/AttachmentRenderer.tsx +133 -0
- package/src/components/chat/Chat.tsx +367 -149
- package/src/components/chat/Modal.tsx +1 -1
- package/src/components/chat/attachment-utils.ts +32 -0
- package/src/components/chat/index.tsx +1 -0
- package/src/components/chat/messages/ImageRenderer.tsx +20 -8
- package/src/components/chat/messages/UserMessage.tsx +42 -8
- package/src/components/chat/props.ts +25 -2
- package/src/css/attachments.css +227 -0
- package/src/css/colors.css +8 -4
- package/src/css/console.css +34 -9
- package/src/css/input.css +5 -2
- package/src/css/markdown.css +1 -1
- package/src/css/messages.css +11 -4
- package/src/css/popup.css +15 -3
- package/src/css/sidebar.css +28 -3
- package/src/css/suggestions.css +4 -2
- package/src/styles.css +2 -1
package/dist/index.mjs
CHANGED
|
@@ -4,7 +4,7 @@ import * as React$1 from "react";
|
|
|
4
4
|
import React, { forwardRef, memo, useCallback, useEffect, useImperativeHandle, useMemo, useRef, useState } from "react";
|
|
5
5
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
6
6
|
import { defaultCopilotContextCategories, shouldShowDevConsole, useCopilotChatInternal, useCopilotChatSuggestions as useCopilotChatSuggestions$1, useCopilotContext, useCopilotMessagesContext } from "@copilotkit/react-core";
|
|
7
|
-
import { COPILOTKIT_VERSION, CopilotKitError, CopilotKitErrorCode, ErrorVisibility, Severity, isMacOS, randomUUID, styledConsole } from "@copilotkit/shared";
|
|
7
|
+
import { COPILOTKIT_VERSION, CopilotKitError, CopilotKitErrorCode, ErrorVisibility, Severity, exceedsMaxSize, formatFileSize, formatFileSize as formatFileSize$1, generateVideoThumbnail, getDocumentIcon, getModalityFromMimeType, getSourceUrl, isMacOS, matchesAcceptFilter, randomUUID, readFileAsBase64, styledConsole } from "@copilotkit/shared";
|
|
8
8
|
import { Menu, MenuButton, MenuItem, MenuItems } from "@headlessui/react";
|
|
9
9
|
import ReactMarkdown from "react-markdown";
|
|
10
10
|
import { Light, Prism } from "react-syntax-highlighter";
|
|
@@ -885,6 +885,89 @@ const Header = ({}) => {
|
|
|
885
885
|
});
|
|
886
886
|
};
|
|
887
887
|
|
|
888
|
+
//#endregion
|
|
889
|
+
//#region src/components/chat/AttachmentRenderer.tsx
|
|
890
|
+
const ImageAttachment = memo(function ImageAttachment({ src, className }) {
|
|
891
|
+
const [error, setError] = useState(false);
|
|
892
|
+
if (error) return /* @__PURE__ */ jsx("div", {
|
|
893
|
+
className: `copilotKitImageRendering copilotKitImageRenderingError ${className ?? ""}`,
|
|
894
|
+
children: /* @__PURE__ */ jsx("div", {
|
|
895
|
+
className: "copilotKitImageRenderingErrorMessage",
|
|
896
|
+
children: "Failed to load image"
|
|
897
|
+
})
|
|
898
|
+
});
|
|
899
|
+
return /* @__PURE__ */ jsx("div", {
|
|
900
|
+
className: `copilotKitImageRendering ${className ?? ""}`,
|
|
901
|
+
children: /* @__PURE__ */ jsx("img", {
|
|
902
|
+
src,
|
|
903
|
+
alt: "Image attachment",
|
|
904
|
+
className: "copilotKitImageRenderingImage",
|
|
905
|
+
onError: () => setError(true)
|
|
906
|
+
})
|
|
907
|
+
});
|
|
908
|
+
});
|
|
909
|
+
const AudioAttachment = memo(function AudioAttachment({ src, filename, className }) {
|
|
910
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
911
|
+
className: `copilotKitAttachment copilotKitAttachmentAudio ${className ?? ""}`,
|
|
912
|
+
children: [/* @__PURE__ */ jsx("audio", {
|
|
913
|
+
src,
|
|
914
|
+
controls: true,
|
|
915
|
+
preload: "metadata"
|
|
916
|
+
}), filename && /* @__PURE__ */ jsx("span", {
|
|
917
|
+
className: "copilotKitAttachmentFilename",
|
|
918
|
+
children: filename
|
|
919
|
+
})]
|
|
920
|
+
});
|
|
921
|
+
});
|
|
922
|
+
const VideoAttachment = memo(function VideoAttachment({ src, className }) {
|
|
923
|
+
return /* @__PURE__ */ jsx("div", {
|
|
924
|
+
className: `copilotKitAttachment copilotKitAttachmentVideo ${className ?? ""}`,
|
|
925
|
+
children: /* @__PURE__ */ jsx("video", {
|
|
926
|
+
src,
|
|
927
|
+
controls: true,
|
|
928
|
+
preload: "metadata"
|
|
929
|
+
})
|
|
930
|
+
});
|
|
931
|
+
});
|
|
932
|
+
const DocumentAttachment = memo(function DocumentAttachment({ source, filename, className }) {
|
|
933
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
934
|
+
className: `copilotKitAttachment copilotKitAttachmentDocument ${className ?? ""}`,
|
|
935
|
+
children: [/* @__PURE__ */ jsx("div", {
|
|
936
|
+
className: "copilotKitAttachmentDocIcon",
|
|
937
|
+
children: getDocumentIcon(source.mimeType ?? "")
|
|
938
|
+
}), /* @__PURE__ */ jsx("div", {
|
|
939
|
+
className: "copilotKitAttachmentDocInfo",
|
|
940
|
+
children: /* @__PURE__ */ jsx("span", {
|
|
941
|
+
className: "copilotKitAttachmentDocName",
|
|
942
|
+
children: filename || source.mimeType || "Unknown type"
|
|
943
|
+
})
|
|
944
|
+
})]
|
|
945
|
+
});
|
|
946
|
+
});
|
|
947
|
+
const AttachmentRenderer = ({ type, source, filename, className }) => {
|
|
948
|
+
const src = getSourceUrl(source);
|
|
949
|
+
switch (type) {
|
|
950
|
+
case "image": return /* @__PURE__ */ jsx(ImageAttachment, {
|
|
951
|
+
src,
|
|
952
|
+
className
|
|
953
|
+
});
|
|
954
|
+
case "audio": return /* @__PURE__ */ jsx(AudioAttachment, {
|
|
955
|
+
src,
|
|
956
|
+
filename,
|
|
957
|
+
className
|
|
958
|
+
});
|
|
959
|
+
case "video": return /* @__PURE__ */ jsx(VideoAttachment, {
|
|
960
|
+
src,
|
|
961
|
+
className
|
|
962
|
+
});
|
|
963
|
+
case "document": return /* @__PURE__ */ jsx(DocumentAttachment, {
|
|
964
|
+
source,
|
|
965
|
+
filename,
|
|
966
|
+
className
|
|
967
|
+
});
|
|
968
|
+
}
|
|
969
|
+
};
|
|
970
|
+
|
|
888
971
|
//#endregion
|
|
889
972
|
//#region src/components/chat/messages/UserMessage.tsx
|
|
890
973
|
const getTextContent = (content) => {
|
|
@@ -894,22 +977,35 @@ const getTextContent = (content) => {
|
|
|
894
977
|
if (part.type === "text") return part.text;
|
|
895
978
|
}).filter((value) => typeof value === "string" && value.length > 0).join(" ").trim() || void 0;
|
|
896
979
|
};
|
|
980
|
+
const getMediaParts = (content) => {
|
|
981
|
+
if (!content || typeof content === "string") return [];
|
|
982
|
+
return content.filter((part) => part.type === "image" || part.type === "audio" || part.type === "video" || part.type === "document");
|
|
983
|
+
};
|
|
897
984
|
const UserMessage = (props) => {
|
|
898
985
|
const { message, ImageRenderer } = props;
|
|
986
|
+
const content = message?.content;
|
|
899
987
|
if (message && "image" in message && Boolean(message.image)) {
|
|
900
|
-
const
|
|
901
|
-
const content = getTextContent(imageMessage?.content);
|
|
988
|
+
const legacyImage = message.image;
|
|
902
989
|
return /* @__PURE__ */ jsx("div", {
|
|
903
990
|
className: "copilotKitMessage copilotKitUserMessage",
|
|
904
991
|
children: /* @__PURE__ */ jsx(ImageRenderer, {
|
|
905
|
-
image:
|
|
906
|
-
content
|
|
992
|
+
image: legacyImage,
|
|
993
|
+
content: getTextContent(content)
|
|
907
994
|
})
|
|
908
995
|
});
|
|
909
996
|
}
|
|
910
|
-
|
|
997
|
+
const textContent = getTextContent(content);
|
|
998
|
+
const mediaParts = getMediaParts(content);
|
|
999
|
+
if (mediaParts.length === 0) return /* @__PURE__ */ jsx("div", {
|
|
1000
|
+
className: "copilotKitMessage copilotKitUserMessage",
|
|
1001
|
+
children: textContent
|
|
1002
|
+
});
|
|
1003
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
911
1004
|
className: "copilotKitMessage copilotKitUserMessage",
|
|
912
|
-
children:
|
|
1005
|
+
children: [textContent && /* @__PURE__ */ jsx("div", { children: textContent }), mediaParts.map((part, index) => /* @__PURE__ */ jsx(AttachmentRenderer, {
|
|
1006
|
+
type: part.type,
|
|
1007
|
+
source: part.source
|
|
1008
|
+
}, index))]
|
|
913
1009
|
});
|
|
914
1010
|
};
|
|
915
1011
|
|
|
@@ -1379,16 +1475,18 @@ const AssistantMessage = (props) => {
|
|
|
1379
1475
|
//#endregion
|
|
1380
1476
|
//#region src/components/chat/messages/ImageRenderer.tsx
|
|
1381
1477
|
/**
|
|
1382
|
-
*
|
|
1383
|
-
*
|
|
1478
|
+
* @deprecated Use `CopilotChatAttachmentRenderer` from `@copilotkit/react-core/v2` instead.
|
|
1479
|
+
* `ImageRenderer` only handles images. The v2 attachment renderer supports images, audio, video, and documents.
|
|
1480
|
+
* See https://docs.copilotkit.ai/migration-guides/migrate-attachments
|
|
1481
|
+
* @since 1.56.0
|
|
1384
1482
|
*/
|
|
1385
|
-
const ImageRenderer = ({ image, content, className = "" }) => {
|
|
1483
|
+
const ImageRenderer = ({ image, source, content, className = "" }) => {
|
|
1386
1484
|
const [imageError, setImageError] = useState(false);
|
|
1387
|
-
|
|
1485
|
+
let imageSrc;
|
|
1486
|
+
if (source) imageSrc = source.type === "url" ? source.value : `data:${source.mimeType};base64,${source.value}`;
|
|
1487
|
+
else if (image) imageSrc = `data:image/${image.format};base64,${image.bytes}`;
|
|
1488
|
+
else return null;
|
|
1388
1489
|
const altText = content || "User uploaded image";
|
|
1389
|
-
const handleImageError = () => {
|
|
1390
|
-
setImageError(true);
|
|
1391
|
-
};
|
|
1392
1490
|
if (imageError) return /* @__PURE__ */ jsxs("div", {
|
|
1393
1491
|
className: `copilotKitImageRendering copilotKitImageRenderingError ${className}`,
|
|
1394
1492
|
children: [/* @__PURE__ */ jsx("div", {
|
|
@@ -1405,7 +1503,7 @@ const ImageRenderer = ({ image, content, className = "" }) => {
|
|
|
1405
1503
|
src: imageSrc,
|
|
1406
1504
|
alt: altText,
|
|
1407
1505
|
className: "copilotKitImageRenderingImage",
|
|
1408
|
-
onError:
|
|
1506
|
+
onError: () => setImageError(true)
|
|
1409
1507
|
}), content && /* @__PURE__ */ jsx("div", {
|
|
1410
1508
|
className: "copilotKitImageRenderingContent",
|
|
1411
1509
|
children: content
|
|
@@ -1923,61 +2021,101 @@ const Input = ({ inProgress, onSend, chatReady = false, onStop, onUpload, hideSt
|
|
|
1923
2021
|
};
|
|
1924
2022
|
|
|
1925
2023
|
//#endregion
|
|
1926
|
-
//#region src/components/chat/
|
|
1927
|
-
const
|
|
1928
|
-
if (
|
|
2024
|
+
//#region src/components/chat/AttachmentQueue.tsx
|
|
2025
|
+
const AttachmentQueue = ({ attachments, onRemoveAttachment, className = "" }) => {
|
|
2026
|
+
if (attachments.length === 0) return null;
|
|
1929
2027
|
return /* @__PURE__ */ jsx("div", {
|
|
1930
|
-
className: `
|
|
1931
|
-
|
|
1932
|
-
|
|
1933
|
-
|
|
1934
|
-
|
|
1935
|
-
|
|
1936
|
-
|
|
1937
|
-
|
|
1938
|
-
|
|
1939
|
-
|
|
1940
|
-
|
|
1941
|
-
|
|
1942
|
-
|
|
1943
|
-
|
|
1944
|
-
|
|
1945
|
-
|
|
1946
|
-
|
|
1947
|
-
},
|
|
1948
|
-
children: [/* @__PURE__ */ jsx("img", {
|
|
1949
|
-
src: `data:${image.contentType};base64,${image.bytes}`,
|
|
1950
|
-
alt: `Selected image ${index + 1}`,
|
|
1951
|
-
style: {
|
|
1952
|
-
width: "100%",
|
|
1953
|
-
height: "100%",
|
|
1954
|
-
objectFit: "cover"
|
|
1955
|
-
}
|
|
1956
|
-
}), /* @__PURE__ */ jsx("button", {
|
|
1957
|
-
onClick: () => onRemoveImage(index),
|
|
1958
|
-
className: "copilotKitImageUploadQueueRemoveButton",
|
|
1959
|
-
style: {
|
|
1960
|
-
position: "absolute",
|
|
1961
|
-
top: "2px",
|
|
1962
|
-
right: "2px",
|
|
1963
|
-
background: "rgba(0,0,0,0.6)",
|
|
1964
|
-
color: "white",
|
|
1965
|
-
border: "none",
|
|
1966
|
-
borderRadius: "50%",
|
|
1967
|
-
width: "18px",
|
|
1968
|
-
height: "18px",
|
|
1969
|
-
display: "flex",
|
|
1970
|
-
alignItems: "center",
|
|
1971
|
-
justifyContent: "center",
|
|
1972
|
-
cursor: "pointer",
|
|
1973
|
-
fontSize: "10px",
|
|
1974
|
-
padding: 0
|
|
1975
|
-
},
|
|
1976
|
-
children: "✕"
|
|
1977
|
-
})]
|
|
1978
|
-
}, index))
|
|
2028
|
+
className: `copilotKitAttachmentQueue ${className}`,
|
|
2029
|
+
children: attachments.map((attachment) => /* @__PURE__ */ jsxs("div", {
|
|
2030
|
+
className: `copilotKitAttachmentQueueItem copilotKitAttachmentQueueItem--${attachment.type}`,
|
|
2031
|
+
children: [
|
|
2032
|
+
attachment.status === "uploading" && /* @__PURE__ */ jsx("div", {
|
|
2033
|
+
className: "copilotKitAttachmentQueueOverlay",
|
|
2034
|
+
children: /* @__PURE__ */ jsx("div", { className: "copilotKitAttachmentQueueSpinner" })
|
|
2035
|
+
}),
|
|
2036
|
+
/* @__PURE__ */ jsx(AttachmentPreview, { attachment }),
|
|
2037
|
+
/* @__PURE__ */ jsx("button", {
|
|
2038
|
+
onClick: () => onRemoveAttachment(attachment.id),
|
|
2039
|
+
className: "copilotKitAttachmentQueueRemoveButton",
|
|
2040
|
+
"aria-label": "Remove attachment",
|
|
2041
|
+
children: "✕"
|
|
2042
|
+
})
|
|
2043
|
+
]
|
|
2044
|
+
}, attachment.id))
|
|
1979
2045
|
});
|
|
1980
2046
|
};
|
|
2047
|
+
function AttachmentPreview({ attachment }) {
|
|
2048
|
+
if (attachment.status === "uploading") return /* @__PURE__ */ jsx("div", { className: "copilotKitAttachmentQueuePreviewPlaceholder" });
|
|
2049
|
+
const src = getSourceUrl(attachment.source);
|
|
2050
|
+
switch (attachment.type) {
|
|
2051
|
+
case "image": return /* @__PURE__ */ jsx("img", {
|
|
2052
|
+
src,
|
|
2053
|
+
alt: attachment.filename || "Image attachment",
|
|
2054
|
+
className: "copilotKitAttachmentQueuePreviewImage"
|
|
2055
|
+
});
|
|
2056
|
+
case "audio": return /* @__PURE__ */ jsxs("div", {
|
|
2057
|
+
className: "copilotKitAttachmentQueuePreviewAudio",
|
|
2058
|
+
children: [/* @__PURE__ */ jsx("audio", {
|
|
2059
|
+
src,
|
|
2060
|
+
controls: true,
|
|
2061
|
+
preload: "metadata"
|
|
2062
|
+
}), attachment.filename && /* @__PURE__ */ jsx("span", {
|
|
2063
|
+
className: "copilotKitAttachmentQueueFilename",
|
|
2064
|
+
children: attachment.filename
|
|
2065
|
+
})]
|
|
2066
|
+
});
|
|
2067
|
+
case "video": return /* @__PURE__ */ jsx("div", {
|
|
2068
|
+
className: "copilotKitAttachmentQueuePreviewVideo",
|
|
2069
|
+
children: attachment.thumbnail ? /* @__PURE__ */ jsx("img", {
|
|
2070
|
+
src: attachment.thumbnail,
|
|
2071
|
+
alt: attachment.filename || "Video thumbnail",
|
|
2072
|
+
className: "copilotKitAttachmentQueuePreviewImage"
|
|
2073
|
+
}) : /* @__PURE__ */ jsx("video", {
|
|
2074
|
+
src,
|
|
2075
|
+
preload: "metadata",
|
|
2076
|
+
muted: true,
|
|
2077
|
+
className: "copilotKitAttachmentQueuePreviewImage"
|
|
2078
|
+
})
|
|
2079
|
+
});
|
|
2080
|
+
case "document": return /* @__PURE__ */ jsxs("div", {
|
|
2081
|
+
className: "copilotKitAttachmentQueuePreviewDocument",
|
|
2082
|
+
children: [/* @__PURE__ */ jsx("div", {
|
|
2083
|
+
className: "copilotKitAttachmentQueueDocIcon",
|
|
2084
|
+
children: getDocumentIcon(attachment.source.mimeType ?? "")
|
|
2085
|
+
}), /* @__PURE__ */ jsxs("div", {
|
|
2086
|
+
className: "copilotKitAttachmentQueueDocInfo",
|
|
2087
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
2088
|
+
className: "copilotKitAttachmentQueueFilename",
|
|
2089
|
+
children: attachment.filename || "Document"
|
|
2090
|
+
}), attachment.size != null && /* @__PURE__ */ jsx("span", {
|
|
2091
|
+
className: "copilotKitAttachmentQueueFileSize",
|
|
2092
|
+
children: formatFileSize(attachment.size)
|
|
2093
|
+
})]
|
|
2094
|
+
})]
|
|
2095
|
+
});
|
|
2096
|
+
}
|
|
2097
|
+
}
|
|
2098
|
+
|
|
2099
|
+
//#endregion
|
|
2100
|
+
//#region src/components/chat/attachment-utils.ts
|
|
2101
|
+
const suppressedWarnings = /* @__PURE__ */ new Set();
|
|
2102
|
+
let globalSuppress = false;
|
|
2103
|
+
/**
|
|
2104
|
+
* Issue a deprecation warning once per key per session.
|
|
2105
|
+
* Suppressed entirely if the user calls suppressDeprecationWarnings().
|
|
2106
|
+
*/
|
|
2107
|
+
function deprecationWarning(key, message) {
|
|
2108
|
+
if (globalSuppress || suppressedWarnings.has(key)) return;
|
|
2109
|
+
if (typeof process !== "undefined" && process.env?.NODE_ENV === "production") return;
|
|
2110
|
+
suppressedWarnings.add(key);
|
|
2111
|
+
console.warn(`[CopilotKit] Deprecation: ${message}`);
|
|
2112
|
+
}
|
|
2113
|
+
/**
|
|
2114
|
+
* Suppress all CopilotKit deprecation warnings.
|
|
2115
|
+
*/
|
|
2116
|
+
function suppressDeprecationWarnings() {
|
|
2117
|
+
globalSuppress = true;
|
|
2118
|
+
}
|
|
1981
2119
|
|
|
1982
2120
|
//#endregion
|
|
1983
2121
|
//#region src/components/chat/Suggestion.tsx
|
|
@@ -2077,10 +2215,25 @@ function Suggestions({ suggestions, onSuggestionClick, isLoading }) {
|
|
|
2077
2215
|
* ```
|
|
2078
2216
|
* For more information about how to customize the styles, check out the [Customize Look & Feel](/guides/custom-look-and-feel/customize-built-in-ui-components) guide.
|
|
2079
2217
|
*/
|
|
2080
|
-
function CopilotChat({ instructions, suggestions = "auto", onSubmitMessage, makeSystemMessage, disableSystemMessage, onInProgress, onStopGeneration, onReloadMessages, onRegenerate, onCopy, onThumbsUp, onThumbsDown, markdownTagRenderers, Messages: Messages$2 = Messages, RenderMessage: RenderMessage$1 = RenderMessage, RenderSuggestionsList = Suggestions, Input: Input$2 = Input, className, icons, labels, AssistantMessage: AssistantMessage$2 = AssistantMessage, UserMessage: UserMessage$3 = UserMessage, ImageRenderer: ImageRenderer$1 = ImageRenderer, ErrorMessage, imageUploadsEnabled, inputFileAccept = "image/*", hideStopButton, observabilityHooks, renderError, onError, RenderTextMessage, RenderActionExecutionMessage, RenderAgentStateMessage, RenderResultMessage, RenderImageMessage }) {
|
|
2218
|
+
function CopilotChat({ instructions, suggestions = "auto", onSubmitMessage, makeSystemMessage, disableSystemMessage, onInProgress, onStopGeneration, onReloadMessages, onRegenerate, onCopy, onThumbsUp, onThumbsDown, markdownTagRenderers, Messages: Messages$2 = Messages, RenderMessage: RenderMessage$1 = RenderMessage, RenderSuggestionsList = Suggestions, Input: Input$2 = Input, className, icons, labels, AssistantMessage: AssistantMessage$2 = AssistantMessage, UserMessage: UserMessage$3 = UserMessage, ImageRenderer: ImageRenderer$1 = ImageRenderer, ErrorMessage, imageUploadsEnabled, inputFileAccept = "image/*", attachments, hideStopButton, observabilityHooks, renderError, onError, RenderTextMessage, RenderActionExecutionMessage, RenderAgentStateMessage, RenderResultMessage, RenderImageMessage }) {
|
|
2081
2219
|
const { additionalInstructions, setChatInstructions, copilotApiConfig, setBannerError, setInternalErrorHandler, removeInternalErrorHandler } = useCopilotContext();
|
|
2082
2220
|
const { publicApiKey, chatApiEndpoint } = copilotApiConfig;
|
|
2083
|
-
const
|
|
2221
|
+
const resolvedAttachments = (() => {
|
|
2222
|
+
if (attachments) return attachments;
|
|
2223
|
+
if (imageUploadsEnabled) {
|
|
2224
|
+
deprecationWarning("imageUploadsEnabled", "imageUploadsEnabled is deprecated. Use attachments={{ enabled: true }} instead. See https://docs.copilotkit.ai/migration-guides/migrate-attachments");
|
|
2225
|
+
return {
|
|
2226
|
+
enabled: true,
|
|
2227
|
+
accept: inputFileAccept || "image/*"
|
|
2228
|
+
};
|
|
2229
|
+
}
|
|
2230
|
+
})();
|
|
2231
|
+
const attachmentsEnabled = resolvedAttachments?.enabled ?? false;
|
|
2232
|
+
const attachmentsAccept = resolvedAttachments?.accept ?? "*/*";
|
|
2233
|
+
const attachmentsMaxSize = resolvedAttachments?.maxSize ?? 20 * 1024 * 1024;
|
|
2234
|
+
const [selectedAttachments, setSelectedAttachments] = useState([]);
|
|
2235
|
+
const [dragOver, setDragOver] = useState(false);
|
|
2236
|
+
const processFilesRef = useRef(async () => {});
|
|
2084
2237
|
const [chatError, setChatError] = useState(null);
|
|
2085
2238
|
const [messageFeedback, setMessageFeedback] = useState({});
|
|
2086
2239
|
const fileInputRef = useRef(null);
|
|
@@ -2101,8 +2254,10 @@ function CopilotChat({ instructions, suggestions = "auto", onSubmitMessage, make
|
|
|
2101
2254
|
setBannerError
|
|
2102
2255
|
]);
|
|
2103
2256
|
const triggerChatError = useCallback((error, operation, originalError) => {
|
|
2257
|
+
const errorMessage = error?.message || error?.toString() || "An error occurred";
|
|
2258
|
+
console.error(`[CopilotKit] ${operation} error:`, errorMessage, originalError ?? error);
|
|
2104
2259
|
setChatError({
|
|
2105
|
-
message:
|
|
2260
|
+
message: errorMessage,
|
|
2106
2261
|
operation,
|
|
2107
2262
|
timestamp: Date.now()
|
|
2108
2263
|
});
|
|
@@ -2156,40 +2311,27 @@ function CopilotChat({ instructions, suggestions = "auto", onSubmitMessage, make
|
|
|
2156
2311
|
removeInternalErrorHandler
|
|
2157
2312
|
]);
|
|
2158
2313
|
useEffect(() => {
|
|
2159
|
-
if (!
|
|
2314
|
+
if (!attachmentsEnabled) return;
|
|
2160
2315
|
const handlePaste = async (e) => {
|
|
2161
2316
|
if (!e.target.parentElement?.classList.contains("copilotKitInput")) return;
|
|
2162
|
-
const
|
|
2163
|
-
if (
|
|
2317
|
+
const fileItems = Array.from(e.clipboardData?.items || []).filter((item) => item.kind === "file" && item.getAsFile() !== null && matchesAcceptFilter(item.getAsFile(), attachmentsAccept));
|
|
2318
|
+
if (fileItems.length === 0) return;
|
|
2164
2319
|
e.preventDefault();
|
|
2165
|
-
const
|
|
2166
|
-
const file = item.getAsFile();
|
|
2167
|
-
if (!file) return Promise.resolve(null);
|
|
2168
|
-
return new Promise((resolve, reject) => {
|
|
2169
|
-
const reader = new FileReader();
|
|
2170
|
-
reader.onload = (e) => {
|
|
2171
|
-
const base64String = (e.target?.result)?.split(",")[1];
|
|
2172
|
-
if (base64String) resolve({
|
|
2173
|
-
contentType: file.type,
|
|
2174
|
-
bytes: base64String
|
|
2175
|
-
});
|
|
2176
|
-
else resolve(null);
|
|
2177
|
-
};
|
|
2178
|
-
reader.onerror = reject;
|
|
2179
|
-
reader.readAsDataURL(file);
|
|
2180
|
-
});
|
|
2181
|
-
});
|
|
2320
|
+
const files = fileItems.map((item) => item.getAsFile()).filter((f) => f !== null);
|
|
2182
2321
|
try {
|
|
2183
|
-
|
|
2184
|
-
setSelectedImages((prev) => [...prev, ...loadedImages]);
|
|
2322
|
+
await processFilesRef.current(files);
|
|
2185
2323
|
} catch (error) {
|
|
2186
|
-
triggerChatError(error, "
|
|
2187
|
-
console.error("Error processing pasted images:", error);
|
|
2324
|
+
triggerChatError(error, "pasteUpload", error);
|
|
2188
2325
|
}
|
|
2189
2326
|
};
|
|
2190
2327
|
document.addEventListener("paste", handlePaste);
|
|
2191
2328
|
return () => document.removeEventListener("paste", handlePaste);
|
|
2192
|
-
}, [
|
|
2329
|
+
}, [
|
|
2330
|
+
attachmentsEnabled,
|
|
2331
|
+
attachmentsAccept,
|
|
2332
|
+
attachmentsMaxSize,
|
|
2333
|
+
triggerChatError
|
|
2334
|
+
]);
|
|
2193
2335
|
useEffect(() => {
|
|
2194
2336
|
if (!additionalInstructions?.length) {
|
|
2195
2337
|
setChatInstructions(instructions || "");
|
|
@@ -2217,9 +2359,38 @@ function CopilotChat({ instructions, suggestions = "auto", onSubmitMessage, make
|
|
|
2217
2359
|
}
|
|
2218
2360
|
}, [isLoading, triggerObservabilityHook]);
|
|
2219
2361
|
const handleSendMessage = (text) => {
|
|
2220
|
-
|
|
2362
|
+
if (selectedAttachments.some((a) => a.status === "uploading")) {
|
|
2363
|
+
triggerChatError(/* @__PURE__ */ new Error("Attachment(s) still uploading. Please wait."), "sendMessage");
|
|
2364
|
+
return Promise.resolve({
|
|
2365
|
+
id: randomUUID(),
|
|
2366
|
+
content: text,
|
|
2367
|
+
role: "user"
|
|
2368
|
+
});
|
|
2369
|
+
}
|
|
2370
|
+
const currentAttachments = selectedAttachments.filter((a) => a.status === "ready");
|
|
2371
|
+
setSelectedAttachments([]);
|
|
2221
2372
|
if (fileInputRef.current) fileInputRef.current.value = "";
|
|
2222
2373
|
triggerObservabilityHook("onMessageSent", text);
|
|
2374
|
+
if (currentAttachments.length > 0) {
|
|
2375
|
+
const contentParts = [];
|
|
2376
|
+
if (text.trim()) contentParts.push({
|
|
2377
|
+
type: "text",
|
|
2378
|
+
text
|
|
2379
|
+
});
|
|
2380
|
+
for (const attachment of currentAttachments) contentParts.push({
|
|
2381
|
+
type: attachment.type,
|
|
2382
|
+
source: attachment.source,
|
|
2383
|
+
metadata: {
|
|
2384
|
+
...attachment.filename ? { filename: attachment.filename } : {},
|
|
2385
|
+
...attachment.metadata
|
|
2386
|
+
}
|
|
2387
|
+
});
|
|
2388
|
+
return sendMessage({
|
|
2389
|
+
id: randomUUID(),
|
|
2390
|
+
content: contentParts,
|
|
2391
|
+
role: "user"
|
|
2392
|
+
});
|
|
2393
|
+
}
|
|
2223
2394
|
return sendMessage({
|
|
2224
2395
|
id: randomUUID(),
|
|
2225
2396
|
content: text,
|
|
@@ -2237,34 +2408,108 @@ function CopilotChat({ instructions, suggestions = "auto", onSubmitMessage, make
|
|
|
2237
2408
|
if (onCopy) onCopy(message);
|
|
2238
2409
|
triggerObservabilityHook("onMessageCopied", message);
|
|
2239
2410
|
};
|
|
2240
|
-
const
|
|
2241
|
-
|
|
2242
|
-
const
|
|
2243
|
-
|
|
2244
|
-
|
|
2245
|
-
|
|
2246
|
-
|
|
2247
|
-
|
|
2248
|
-
|
|
2249
|
-
|
|
2250
|
-
contentType: file.type,
|
|
2251
|
-
bytes: base64String
|
|
2252
|
-
});
|
|
2253
|
-
};
|
|
2254
|
-
reader.onerror = reject;
|
|
2255
|
-
reader.readAsDataURL(file);
|
|
2411
|
+
const processFiles = async (files) => {
|
|
2412
|
+
const validFiles = files.filter((file) => matchesAcceptFilter(file, attachmentsAccept));
|
|
2413
|
+
const rejectedFiles = files.filter((file) => !matchesAcceptFilter(file, attachmentsAccept));
|
|
2414
|
+
for (const file of rejectedFiles) {
|
|
2415
|
+
const message = `File "${file.name}" is not accepted. Supported types: ${attachmentsAccept}`;
|
|
2416
|
+
triggerChatError(new Error(message), "fileUpload");
|
|
2417
|
+
resolvedAttachments?.onUploadFailed?.({
|
|
2418
|
+
reason: "invalid-type",
|
|
2419
|
+
file,
|
|
2420
|
+
message
|
|
2256
2421
|
});
|
|
2257
|
-
}
|
|
2422
|
+
}
|
|
2423
|
+
for (const file of validFiles) {
|
|
2424
|
+
if (exceedsMaxSize(file, attachmentsMaxSize)) {
|
|
2425
|
+
const message = `File "${file.name}" exceeds the maximum size of ${formatFileSize$1(attachmentsMaxSize)}`;
|
|
2426
|
+
triggerChatError(new Error(message), "fileUpload");
|
|
2427
|
+
resolvedAttachments?.onUploadFailed?.({
|
|
2428
|
+
reason: "file-too-large",
|
|
2429
|
+
file,
|
|
2430
|
+
message
|
|
2431
|
+
});
|
|
2432
|
+
continue;
|
|
2433
|
+
}
|
|
2434
|
+
const modality = getModalityFromMimeType(file.type);
|
|
2435
|
+
const placeholderId = randomUUID();
|
|
2436
|
+
const placeholder = {
|
|
2437
|
+
id: placeholderId,
|
|
2438
|
+
type: modality,
|
|
2439
|
+
source: {
|
|
2440
|
+
type: "data",
|
|
2441
|
+
value: "",
|
|
2442
|
+
mimeType: file.type
|
|
2443
|
+
},
|
|
2444
|
+
filename: file.name,
|
|
2445
|
+
size: file.size,
|
|
2446
|
+
status: "uploading"
|
|
2447
|
+
};
|
|
2448
|
+
setSelectedAttachments((prev) => [...prev, placeholder]);
|
|
2449
|
+
try {
|
|
2450
|
+
let source;
|
|
2451
|
+
let uploadMetadata;
|
|
2452
|
+
if (resolvedAttachments?.onUpload) {
|
|
2453
|
+
const { metadata: meta, ...uploadSource } = await resolvedAttachments.onUpload(file);
|
|
2454
|
+
source = uploadSource;
|
|
2455
|
+
uploadMetadata = meta;
|
|
2456
|
+
} else source = {
|
|
2457
|
+
type: "data",
|
|
2458
|
+
value: await readFileAsBase64(file),
|
|
2459
|
+
mimeType: file.type
|
|
2460
|
+
};
|
|
2461
|
+
let thumbnail;
|
|
2462
|
+
if (modality === "video") thumbnail = await generateVideoThumbnail(file);
|
|
2463
|
+
setSelectedAttachments((prev) => prev.map((att) => att.id === placeholderId ? {
|
|
2464
|
+
...att,
|
|
2465
|
+
source,
|
|
2466
|
+
status: "ready",
|
|
2467
|
+
thumbnail,
|
|
2468
|
+
metadata: uploadMetadata
|
|
2469
|
+
} : att));
|
|
2470
|
+
} catch (error) {
|
|
2471
|
+
setSelectedAttachments((prev) => prev.filter((att) => att.id !== placeholderId));
|
|
2472
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
2473
|
+
triggerChatError(/* @__PURE__ */ new Error(`Failed to upload "${file.name}": ${message}`), "fileUpload", error);
|
|
2474
|
+
resolvedAttachments?.onUploadFailed?.({
|
|
2475
|
+
reason: "upload-failed",
|
|
2476
|
+
file,
|
|
2477
|
+
message: `Failed to upload "${file.name}": ${message}`
|
|
2478
|
+
});
|
|
2479
|
+
}
|
|
2480
|
+
}
|
|
2481
|
+
};
|
|
2482
|
+
processFilesRef.current = processFiles;
|
|
2483
|
+
const handleFileUpload = async (event) => {
|
|
2484
|
+
if (!event.target.files || event.target.files.length === 0) return;
|
|
2258
2485
|
try {
|
|
2259
|
-
|
|
2260
|
-
setSelectedImages((prev) => [...prev, ...loadedImages]);
|
|
2486
|
+
await processFiles(Array.from(event.target.files));
|
|
2261
2487
|
} catch (error) {
|
|
2262
|
-
triggerChatError(error, "
|
|
2263
|
-
console.error("Error reading files:", error);
|
|
2488
|
+
triggerChatError(error, "fileUpload", error);
|
|
2264
2489
|
}
|
|
2265
2490
|
};
|
|
2266
|
-
const
|
|
2267
|
-
|
|
2491
|
+
const handleDragOver = (e) => {
|
|
2492
|
+
if (!attachmentsEnabled) return;
|
|
2493
|
+
e.preventDefault();
|
|
2494
|
+
e.stopPropagation();
|
|
2495
|
+
setDragOver(true);
|
|
2496
|
+
};
|
|
2497
|
+
const handleDragLeave = (e) => {
|
|
2498
|
+
e.preventDefault();
|
|
2499
|
+
e.stopPropagation();
|
|
2500
|
+
setDragOver(false);
|
|
2501
|
+
};
|
|
2502
|
+
const handleDrop = async (e) => {
|
|
2503
|
+
e.preventDefault();
|
|
2504
|
+
e.stopPropagation();
|
|
2505
|
+
setDragOver(false);
|
|
2506
|
+
if (!attachmentsEnabled) return;
|
|
2507
|
+
const files = Array.from(e.dataTransfer.files);
|
|
2508
|
+
if (files.length > 0) try {
|
|
2509
|
+
await processFiles(files);
|
|
2510
|
+
} catch (error) {
|
|
2511
|
+
triggerChatError(error, "dropUpload", error);
|
|
2512
|
+
}
|
|
2268
2513
|
};
|
|
2269
2514
|
const handleThumbsUp = (message) => {
|
|
2270
2515
|
if (onThumbsUp) onThumbsUp(message);
|
|
@@ -2282,65 +2527,71 @@ function CopilotChat({ instructions, suggestions = "auto", onSubmitMessage, make
|
|
|
2282
2527
|
}));
|
|
2283
2528
|
triggerObservabilityHook("onFeedbackGiven", message.id, "thumbsDown");
|
|
2284
2529
|
};
|
|
2285
|
-
return /* @__PURE__ */
|
|
2530
|
+
return /* @__PURE__ */ jsx(WrappedCopilotChat, {
|
|
2286
2531
|
icons,
|
|
2287
2532
|
labels,
|
|
2288
2533
|
className,
|
|
2289
|
-
children:
|
|
2290
|
-
|
|
2291
|
-
|
|
2292
|
-
|
|
2293
|
-
|
|
2294
|
-
|
|
2295
|
-
|
|
2296
|
-
|
|
2297
|
-
|
|
2298
|
-
|
|
2299
|
-
|
|
2300
|
-
|
|
2301
|
-
|
|
2302
|
-
|
|
2303
|
-
|
|
2304
|
-
|
|
2305
|
-
|
|
2306
|
-
|
|
2307
|
-
|
|
2308
|
-
|
|
2309
|
-
|
|
2310
|
-
|
|
2311
|
-
|
|
2312
|
-
|
|
2313
|
-
|
|
2314
|
-
|
|
2315
|
-
|
|
2316
|
-
|
|
2317
|
-
|
|
2318
|
-
|
|
2319
|
-
|
|
2320
|
-
|
|
2534
|
+
children: /* @__PURE__ */ jsxs("div", {
|
|
2535
|
+
onDragOver: handleDragOver,
|
|
2536
|
+
onDragLeave: handleDragLeave,
|
|
2537
|
+
onDrop: handleDrop,
|
|
2538
|
+
className: dragOver ? "copilotKitDragOver" : "",
|
|
2539
|
+
children: [
|
|
2540
|
+
chatError && renderError && renderError({
|
|
2541
|
+
...chatError,
|
|
2542
|
+
onDismiss: () => setChatError(null),
|
|
2543
|
+
onRetry: () => {
|
|
2544
|
+
setChatError(null);
|
|
2545
|
+
}
|
|
2546
|
+
}),
|
|
2547
|
+
/* @__PURE__ */ jsx(Messages$2, {
|
|
2548
|
+
AssistantMessage: AssistantMessage$2,
|
|
2549
|
+
UserMessage: UserMessage$3,
|
|
2550
|
+
RenderMessage: RenderMessage$1,
|
|
2551
|
+
messages,
|
|
2552
|
+
inProgress: isLoading,
|
|
2553
|
+
onRegenerate: handleRegenerate,
|
|
2554
|
+
onCopy: handleCopy,
|
|
2555
|
+
onThumbsUp: handleThumbsUp,
|
|
2556
|
+
onThumbsDown: handleThumbsDown,
|
|
2557
|
+
messageFeedback,
|
|
2558
|
+
markdownTagRenderers,
|
|
2559
|
+
ImageRenderer: ImageRenderer$1,
|
|
2560
|
+
ErrorMessage,
|
|
2561
|
+
chatError,
|
|
2562
|
+
RenderTextMessage,
|
|
2563
|
+
RenderActionExecutionMessage,
|
|
2564
|
+
RenderAgentStateMessage,
|
|
2565
|
+
RenderResultMessage,
|
|
2566
|
+
RenderImageMessage,
|
|
2567
|
+
children: currentSuggestions.length > 0 && /* @__PURE__ */ jsx(RenderSuggestionsList, {
|
|
2568
|
+
onSuggestionClick: handleSendMessage,
|
|
2569
|
+
suggestions: currentSuggestions,
|
|
2570
|
+
isLoading: isLoadingSuggestions
|
|
2571
|
+
})
|
|
2572
|
+
}),
|
|
2573
|
+
attachmentsEnabled && /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(AttachmentQueue, {
|
|
2574
|
+
attachments: selectedAttachments,
|
|
2575
|
+
onRemoveAttachment: (id) => setSelectedAttachments((prev) => prev.filter((att) => att.id !== id))
|
|
2576
|
+
}), /* @__PURE__ */ jsx("input", {
|
|
2577
|
+
type: "file",
|
|
2578
|
+
multiple: true,
|
|
2579
|
+
ref: fileInputRef,
|
|
2580
|
+
onChange: handleFileUpload,
|
|
2581
|
+
accept: attachmentsAccept,
|
|
2582
|
+
style: { display: "none" }
|
|
2583
|
+
})] }),
|
|
2584
|
+
/* @__PURE__ */ jsx(Input$2, {
|
|
2585
|
+
inProgress: isLoading,
|
|
2586
|
+
chatReady: Boolean(agent),
|
|
2587
|
+
onSend: handleSendMessage,
|
|
2588
|
+
isVisible,
|
|
2589
|
+
onStop: stopGeneration,
|
|
2590
|
+
onUpload: attachmentsEnabled ? () => fileInputRef.current?.click() : void 0,
|
|
2591
|
+
hideStopButton
|
|
2321
2592
|
})
|
|
2322
|
-
|
|
2323
|
-
|
|
2324
|
-
images: selectedImages,
|
|
2325
|
-
onRemoveImage: removeSelectedImage
|
|
2326
|
-
}), /* @__PURE__ */ jsx("input", {
|
|
2327
|
-
type: "file",
|
|
2328
|
-
multiple: true,
|
|
2329
|
-
ref: fileInputRef,
|
|
2330
|
-
onChange: handleImageUpload,
|
|
2331
|
-
accept: inputFileAccept,
|
|
2332
|
-
style: { display: "none" }
|
|
2333
|
-
})] }),
|
|
2334
|
-
/* @__PURE__ */ jsx(Input$2, {
|
|
2335
|
-
inProgress: isLoading,
|
|
2336
|
-
chatReady: Boolean(agent),
|
|
2337
|
-
onSend: handleSendMessage,
|
|
2338
|
-
isVisible,
|
|
2339
|
-
onStop: stopGeneration,
|
|
2340
|
-
onUpload: imageUploadsEnabled ? () => fileInputRef.current?.click() : void 0,
|
|
2341
|
-
hideStopButton
|
|
2342
|
-
})
|
|
2343
|
-
]
|
|
2593
|
+
]
|
|
2594
|
+
})
|
|
2344
2595
|
});
|
|
2345
2596
|
}
|
|
2346
2597
|
function WrappedCopilotChat({ children, icons, labels, className }) {
|
|
@@ -2393,7 +2644,10 @@ const CopilotModalInner = ({ observabilityHooks, onSetOpen, clickOutsideToClose,
|
|
|
2393
2644
|
triggerObservabilityHook
|
|
2394
2645
|
]);
|
|
2395
2646
|
const memoizedHeader = useMemo(() => /* @__PURE__ */ jsx(Header, {}), [Header]);
|
|
2396
|
-
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
2647
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("div", {
|
|
2648
|
+
className: "copilotKitModalChildrenWrapper",
|
|
2649
|
+
children: useMemo(() => children, [children])
|
|
2650
|
+
}), /* @__PURE__ */ jsxs("div", {
|
|
2397
2651
|
className,
|
|
2398
2652
|
children: [/* @__PURE__ */ jsx(Button, {}), /* @__PURE__ */ jsxs(Window, {
|
|
2399
2653
|
clickOutsideToClose,
|
|
@@ -2684,5 +2938,5 @@ function useCopilotChatSuggestions(config, dependencies = []) {
|
|
|
2684
2938
|
}
|
|
2685
2939
|
|
|
2686
2940
|
//#endregion
|
|
2687
|
-
export { AssistantMessage, CopilotChat, CopilotDevConsole, CopilotPopup, CopilotSidebar, ImageRenderer, Markdown, Suggestion as RenderSuggestion, Suggestions as RenderSuggestionsList, UserMessage, shouldShowDevConsole, useChatContext, useCopilotChatSuggestions };
|
|
2941
|
+
export { AssistantMessage, CopilotChat, CopilotDevConsole, CopilotPopup, CopilotSidebar, ImageRenderer, Markdown, Suggestion as RenderSuggestion, Suggestions as RenderSuggestionsList, UserMessage, shouldShowDevConsole, suppressDeprecationWarnings, useChatContext, useCopilotChatSuggestions };
|
|
2688
2942
|
//# sourceMappingURL=index.mjs.map
|