@copilotkit/react-ui 1.9.3 → 1.10.0-next.1
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 +38 -0
- package/dist/{chunk-GVKA7RQQ.mjs → chunk-7CAK2CNK.mjs} +2 -2
- package/dist/{chunk-KN2GCKBE.mjs → chunk-7RNOT3GM.mjs} +9 -9
- package/dist/{chunk-KENCH7RN.mjs → chunk-B5IFB5YJ.mjs} +1 -1
- package/dist/chunk-B5IFB5YJ.mjs.map +1 -0
- package/dist/chunk-DBKRAOH7.mjs +34 -0
- package/dist/chunk-DBKRAOH7.mjs.map +1 -0
- package/dist/{chunk-4HUXYD3B.mjs → chunk-DTRPPNSA.mjs} +2 -2
- package/dist/{chunk-YTXEWDNC.mjs → chunk-E6MQUIZW.mjs} +15 -4
- package/dist/chunk-E6MQUIZW.mjs.map +1 -0
- package/dist/{chunk-Z4XPPVZT.mjs → chunk-EYRKZDP5.mjs} +1 -1
- package/dist/chunk-EYRKZDP5.mjs.map +1 -0
- package/dist/{chunk-SGFUVPDB.mjs → chunk-FOSKS7AI.mjs} +4 -4
- package/dist/{chunk-L3GZ7TXC.mjs → chunk-GCKKSSBU.mjs} +21 -24
- package/dist/chunk-GCKKSSBU.mjs.map +1 -0
- package/dist/{chunk-S5MBUNGN.mjs → chunk-O72ZB5V3.mjs} +4 -4
- package/dist/chunk-O72ZB5V3.mjs.map +1 -0
- package/dist/{chunk-QGSPTXOV.mjs → chunk-O7KTFUAN.mjs} +2 -2
- package/dist/chunk-O7KTFUAN.mjs.map +1 -0
- package/dist/{chunk-HKTWKCPS.mjs → chunk-O7PYQO73.mjs} +127 -92
- package/dist/chunk-O7PYQO73.mjs.map +1 -0
- package/dist/{chunk-32MUWKL3.mjs → chunk-OQM7D3Z3.mjs} +22 -18
- package/dist/chunk-OQM7D3Z3.mjs.map +1 -0
- package/dist/chunk-Q2467VHZ.mjs +30 -0
- package/dist/chunk-Q2467VHZ.mjs.map +1 -0
- package/dist/{chunk-ALIBUJML.mjs → chunk-QELAC6XJ.mjs} +2 -2
- package/dist/chunk-QELAC6XJ.mjs.map +1 -0
- package/dist/{chunk-H3EM63WS.mjs → chunk-TCIZDWPC.mjs} +2 -2
- package/dist/chunk-TCIZDWPC.mjs.map +1 -0
- package/dist/chunk-VVL6JFCJ.mjs +16 -0
- package/dist/chunk-VVL6JFCJ.mjs.map +1 -0
- package/dist/chunk-WHDNKXMP.mjs +135 -0
- package/dist/chunk-WHDNKXMP.mjs.map +1 -0
- package/dist/components/chat/Button.d.ts +1 -1
- package/dist/components/chat/Chat.d.ts +119 -28
- package/dist/components/chat/Chat.js +298 -658
- package/dist/components/chat/Chat.js.map +1 -1
- package/dist/components/chat/Chat.mjs +12 -15
- package/dist/components/chat/CodeBlock.js.map +1 -1
- package/dist/components/chat/CodeBlock.mjs +1 -1
- package/dist/components/chat/Header.d.ts +1 -1
- package/dist/components/chat/Header.mjs +4 -4
- package/dist/components/chat/Input.d.ts +1 -1
- package/dist/components/chat/Input.js +3 -3
- package/dist/components/chat/Input.js.map +1 -1
- package/dist/components/chat/Input.mjs +2 -2
- package/dist/components/chat/Markdown.js +13 -2
- package/dist/components/chat/Markdown.js.map +1 -1
- package/dist/components/chat/Markdown.mjs +2 -2
- package/dist/components/chat/Messages.d.ts +3 -3
- package/dist/components/chat/Messages.js +40 -116
- package/dist/components/chat/Messages.js.map +1 -1
- package/dist/components/chat/Messages.mjs +1 -1
- package/dist/components/chat/Modal.d.ts +7 -2
- package/dist/components/chat/Modal.js +308 -668
- package/dist/components/chat/Modal.js.map +1 -1
- package/dist/components/chat/Modal.mjs +17 -20
- package/dist/components/chat/Popup.d.ts +7 -2
- package/dist/components/chat/Popup.js +310 -670
- package/dist/components/chat/Popup.js.map +1 -1
- package/dist/components/chat/Popup.mjs +18 -21
- package/dist/components/chat/Sidebar.d.ts +7 -2
- package/dist/components/chat/Sidebar.js +312 -672
- package/dist/components/chat/Sidebar.js.map +1 -1
- package/dist/components/chat/Sidebar.mjs +18 -21
- package/dist/components/chat/Suggestion.d.ts +2 -9
- package/dist/components/chat/Suggestion.js +6 -96
- package/dist/components/chat/Suggestion.js.map +1 -1
- package/dist/components/chat/Suggestion.mjs +3 -5
- package/dist/components/chat/Suggestions.d.ts +1 -1
- package/dist/components/chat/Suggestions.js +4 -3
- package/dist/components/chat/Suggestions.js.map +1 -1
- package/dist/components/chat/Suggestions.mjs +2 -2
- package/dist/components/chat/Window.d.ts +1 -1
- package/dist/components/chat/index.d.ts +8 -3
- package/dist/components/chat/index.js +316 -676
- package/dist/components/chat/index.js.map +1 -1
- package/dist/components/chat/index.mjs +22 -25
- package/dist/components/chat/messages/AssistantMessage.d.ts +1 -1
- package/dist/components/chat/messages/AssistantMessage.js +32 -24
- package/dist/components/chat/messages/AssistantMessage.js.map +1 -1
- package/dist/components/chat/messages/AssistantMessage.mjs +3 -3
- package/dist/components/chat/messages/ImageRenderer.d.ts +12 -0
- package/dist/components/chat/messages/ImageRenderer.js +58 -0
- package/dist/components/chat/messages/ImageRenderer.js.map +1 -0
- package/dist/components/chat/messages/ImageRenderer.mjs +8 -0
- package/dist/components/chat/messages/RenderMessage.d.ts +9 -0
- package/dist/components/chat/messages/{RenderTextMessage.js → RenderMessage.js} +92 -47
- package/dist/components/chat/messages/RenderMessage.js.map +1 -0
- package/dist/components/chat/messages/RenderMessage.mjs +16 -0
- package/dist/components/chat/messages/UserMessage.d.ts +1 -1
- package/dist/components/chat/messages/UserMessage.js +7 -1
- package/dist/components/chat/messages/UserMessage.js.map +1 -1
- package/dist/components/chat/messages/UserMessage.mjs +1 -1
- package/dist/components/chat/props.d.ts +32 -27
- package/dist/components/chat/props.js.map +1 -1
- package/dist/components/dev-console/console.mjs +3 -3
- package/dist/components/dev-console/index.mjs +4 -4
- package/dist/components/index.d.ts +8 -3
- package/dist/components/index.js +316 -676
- package/dist/components/index.js.map +1 -1
- package/dist/components/index.mjs +23 -26
- package/dist/hooks/index.js.map +1 -1
- package/dist/hooks/index.mjs +1 -1
- package/dist/hooks/use-copilot-chat-suggestions.d.ts +1 -1
- package/dist/hooks/use-copilot-chat-suggestions.js.map +1 -1
- package/dist/hooks/use-copilot-chat-suggestions.mjs +1 -1
- package/dist/hooks/use-push-to-talk.d.ts +1 -1
- package/dist/hooks/use-push-to-talk.js +3 -3
- package/dist/hooks/use-push-to-talk.js.map +1 -1
- package/dist/hooks/use-push-to-talk.mjs +1 -1
- package/dist/index.css +59 -3
- package/dist/index.css.map +1 -1
- package/dist/index.d.ts +8 -3
- package/dist/index.js +322 -682
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +24 -27
- package/dist/types/css.d.ts +3 -0
- package/dist/types/css.js.map +1 -1
- package/package.json +4 -4
- package/src/components/chat/Chat.tsx +194 -106
- package/src/components/chat/CodeBlock.tsx +1 -1
- package/src/components/chat/Markdown.tsx +12 -2
- package/src/components/chat/Messages.tsx +43 -122
- package/src/components/chat/Popup.tsx +1 -1
- package/src/components/chat/Sidebar.tsx +1 -1
- package/src/components/chat/Suggestion.tsx +5 -108
- package/src/components/chat/Suggestions.tsx +0 -1
- package/src/components/chat/index.tsx +1 -1
- package/src/components/chat/messages/AssistantMessage.tsx +15 -23
- package/src/components/chat/messages/ImageRenderer.tsx +37 -0
- package/src/components/chat/messages/{RenderTextMessage.tsx → RenderMessage.tsx} +10 -9
- package/src/components/chat/messages/UserMessage.tsx +16 -5
- package/src/components/chat/props.ts +36 -28
- package/src/css/colors.css +10 -0
- package/src/css/markdown.css +8 -0
- package/src/css/messages.css +54 -5
- package/src/css/suggestions.css +1 -1
- package/src/hooks/use-copilot-chat-suggestions.tsx +1 -1
- package/src/hooks/use-push-to-talk.tsx +6 -5
- package/src/styles.css +1 -1
- package/src/types/css.ts +3 -0
- package/dist/chunk-2II3Q27P.mjs +0 -112
- package/dist/chunk-2II3Q27P.mjs.map +0 -1
- package/dist/chunk-32MUWKL3.mjs.map +0 -1
- package/dist/chunk-53CVDVS5.mjs +0 -127
- package/dist/chunk-53CVDVS5.mjs.map +0 -1
- package/dist/chunk-ALIBUJML.mjs.map +0 -1
- package/dist/chunk-B3D7U7TJ.mjs +0 -211
- package/dist/chunk-B3D7U7TJ.mjs.map +0 -1
- package/dist/chunk-C7OB63U5.mjs +0 -36
- package/dist/chunk-C7OB63U5.mjs.map +0 -1
- package/dist/chunk-H3EM63WS.mjs.map +0 -1
- package/dist/chunk-HKTWKCPS.mjs.map +0 -1
- package/dist/chunk-HWMFMBJC.mjs +0 -10
- package/dist/chunk-HWMFMBJC.mjs.map +0 -1
- package/dist/chunk-IMBPSLL4.mjs +0 -104
- package/dist/chunk-IMBPSLL4.mjs.map +0 -1
- package/dist/chunk-KENCH7RN.mjs.map +0 -1
- package/dist/chunk-L3GZ7TXC.mjs.map +0 -1
- package/dist/chunk-QGSPTXOV.mjs.map +0 -1
- package/dist/chunk-S5MBUNGN.mjs.map +0 -1
- package/dist/chunk-ULDQXCED.mjs +0 -78
- package/dist/chunk-ULDQXCED.mjs.map +0 -1
- package/dist/chunk-YTXEWDNC.mjs.map +0 -1
- package/dist/chunk-Z4XPPVZT.mjs.map +0 -1
- package/dist/components/chat/messages/RenderActionExecutionMessage.d.ts +0 -9
- package/dist/components/chat/messages/RenderActionExecutionMessage.js +0 -869
- package/dist/components/chat/messages/RenderActionExecutionMessage.js.map +0 -1
- package/dist/components/chat/messages/RenderActionExecutionMessage.mjs +0 -14
- package/dist/components/chat/messages/RenderAgentStateMessage.d.ts +0 -9
- package/dist/components/chat/messages/RenderAgentStateMessage.js +0 -854
- package/dist/components/chat/messages/RenderAgentStateMessage.js.map +0 -1
- package/dist/components/chat/messages/RenderAgentStateMessage.mjs +0 -14
- package/dist/components/chat/messages/RenderImageMessage.d.ts +0 -9
- package/dist/components/chat/messages/RenderImageMessage.js +0 -823
- package/dist/components/chat/messages/RenderImageMessage.js.map +0 -1
- package/dist/components/chat/messages/RenderImageMessage.mjs +0 -15
- package/dist/components/chat/messages/RenderImageMessage.mjs.map +0 -1
- package/dist/components/chat/messages/RenderResultMessage.d.ts +0 -9
- package/dist/components/chat/messages/RenderResultMessage.js +0 -778
- package/dist/components/chat/messages/RenderResultMessage.js.map +0 -1
- package/dist/components/chat/messages/RenderResultMessage.mjs +0 -14
- package/dist/components/chat/messages/RenderResultMessage.mjs.map +0 -1
- package/dist/components/chat/messages/RenderTextMessage.d.ts +0 -9
- package/dist/components/chat/messages/RenderTextMessage.js.map +0 -1
- package/dist/components/chat/messages/RenderTextMessage.mjs +0 -15
- package/dist/components/chat/messages/RenderTextMessage.mjs.map +0 -1
- package/src/components/chat/messages/RenderActionExecutionMessage.tsx +0 -127
- package/src/components/chat/messages/RenderAgentStateMessage.tsx +0 -116
- package/src/components/chat/messages/RenderImageMessage.tsx +0 -64
- package/src/components/chat/messages/RenderResultMessage.tsx +0 -26
- /package/dist/{chunk-GVKA7RQQ.mjs.map → chunk-7CAK2CNK.mjs.map} +0 -0
- /package/dist/{chunk-KN2GCKBE.mjs.map → chunk-7RNOT3GM.mjs.map} +0 -0
- /package/dist/{chunk-4HUXYD3B.mjs.map → chunk-DTRPPNSA.mjs.map} +0 -0
- /package/dist/{chunk-SGFUVPDB.mjs.map → chunk-FOSKS7AI.mjs.map} +0 -0
- /package/dist/components/chat/messages/{RenderActionExecutionMessage.mjs.map → ImageRenderer.mjs.map} +0 -0
- /package/dist/components/chat/messages/{RenderAgentStateMessage.mjs.map → RenderMessage.mjs.map} +0 -0
|
@@ -34,9 +34,19 @@ const defaultComponents: Components = {
|
|
|
34
34
|
|
|
35
35
|
const match = /language-(\w+)/.exec(className || "");
|
|
36
36
|
|
|
37
|
-
|
|
37
|
+
// Detect inline code: if it has a language class or contains newlines, it's likely a code block
|
|
38
|
+
// Otherwise, treat it as inline code
|
|
39
|
+
const hasLanguage = match && match[1];
|
|
40
|
+
const content = String(children);
|
|
41
|
+
const hasNewlines = content.includes("\n");
|
|
42
|
+
const isInline = !hasLanguage && !hasNewlines;
|
|
43
|
+
|
|
44
|
+
if (isInline) {
|
|
38
45
|
return (
|
|
39
|
-
<code
|
|
46
|
+
<code
|
|
47
|
+
className={`copilotKitMarkdownElement copilotKitInlineCode ${className || ""}`}
|
|
48
|
+
{...props}
|
|
49
|
+
>
|
|
40
50
|
{children}
|
|
41
51
|
</code>
|
|
42
52
|
);
|
|
@@ -1,18 +1,13 @@
|
|
|
1
1
|
import { useEffect, useMemo, useRef } from "react";
|
|
2
2
|
import { MessagesProps } from "./props";
|
|
3
3
|
import { useChatContext } from "./ChatContext";
|
|
4
|
-
import { Message,
|
|
5
|
-
import {
|
|
4
|
+
import { Message, Role } from "@copilotkit/shared";
|
|
5
|
+
import { useCopilotChat } from "@copilotkit/react-core";
|
|
6
6
|
|
|
7
7
|
export const Messages = ({
|
|
8
|
-
messages,
|
|
9
8
|
inProgress,
|
|
10
9
|
children,
|
|
11
|
-
|
|
12
|
-
RenderActionExecutionMessage,
|
|
13
|
-
RenderAgentStateMessage,
|
|
14
|
-
RenderResultMessage,
|
|
15
|
-
RenderImageMessage,
|
|
10
|
+
RenderMessage,
|
|
16
11
|
AssistantMessage,
|
|
17
12
|
UserMessage,
|
|
18
13
|
onRegenerate,
|
|
@@ -21,110 +16,33 @@ export const Messages = ({
|
|
|
21
16
|
onThumbsDown,
|
|
22
17
|
markdownTagRenderers,
|
|
23
18
|
}: MessagesProps) => {
|
|
24
|
-
const
|
|
25
|
-
const
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
);
|
|
29
|
-
|
|
30
|
-
messages = [...initialMessages, ...messages];
|
|
31
|
-
|
|
32
|
-
const actionResults: Record<string, string> = {};
|
|
33
|
-
|
|
34
|
-
for (let i = 0; i < messages.length; i++) {
|
|
35
|
-
if (messages[i].isActionExecutionMessage()) {
|
|
36
|
-
const id = messages[i].id;
|
|
37
|
-
const resultMessage: ResultMessage | undefined = messages.find(
|
|
38
|
-
(message) => message.isResultMessage() && message.actionExecutionId === id,
|
|
39
|
-
) as ResultMessage | undefined;
|
|
40
|
-
|
|
41
|
-
if (resultMessage) {
|
|
42
|
-
actionResults[id] = ResultMessage.decodeResult(resultMessage.result || "");
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
|
|
19
|
+
const { labels } = useChatContext();
|
|
20
|
+
const { visibleMessages, interrupt } = useCopilotChat();
|
|
21
|
+
const initialMessages = useMemo(() => makeInitialMessages(labels.initial), [labels.initial]);
|
|
22
|
+
const messages = [...initialMessages, ...visibleMessages];
|
|
47
23
|
const { messagesContainerRef, messagesEndRef } = useScrollToBottom(messages);
|
|
48
24
|
|
|
49
|
-
const interrupt = useLangGraphInterruptRender();
|
|
50
|
-
|
|
51
25
|
return (
|
|
52
26
|
<div className="copilotKitMessages" ref={messagesContainerRef}>
|
|
53
27
|
<div className="copilotKitMessagesContainer">
|
|
54
28
|
{messages.map((message, index) => {
|
|
55
29
|
const isCurrentMessage = index === messages.length - 1;
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
/>
|
|
73
|
-
);
|
|
74
|
-
} else if (message.isActionExecutionMessage()) {
|
|
75
|
-
return (
|
|
76
|
-
<RenderActionExecutionMessage
|
|
77
|
-
key={index}
|
|
78
|
-
message={message}
|
|
79
|
-
inProgress={inProgress}
|
|
80
|
-
index={index}
|
|
81
|
-
isCurrentMessage={isCurrentMessage}
|
|
82
|
-
actionResult={actionResults[message.id]}
|
|
83
|
-
AssistantMessage={AssistantMessage}
|
|
84
|
-
UserMessage={UserMessage}
|
|
85
|
-
/>
|
|
86
|
-
);
|
|
87
|
-
} else if (message.isAgentStateMessage()) {
|
|
88
|
-
return (
|
|
89
|
-
<RenderAgentStateMessage
|
|
90
|
-
key={index}
|
|
91
|
-
message={message}
|
|
92
|
-
inProgress={inProgress}
|
|
93
|
-
index={index}
|
|
94
|
-
isCurrentMessage={isCurrentMessage}
|
|
95
|
-
AssistantMessage={AssistantMessage}
|
|
96
|
-
UserMessage={UserMessage}
|
|
97
|
-
/>
|
|
98
|
-
);
|
|
99
|
-
} else if (message.isResultMessage()) {
|
|
100
|
-
return (
|
|
101
|
-
<RenderResultMessage
|
|
102
|
-
key={index}
|
|
103
|
-
message={message}
|
|
104
|
-
inProgress={inProgress}
|
|
105
|
-
index={index}
|
|
106
|
-
isCurrentMessage={isCurrentMessage}
|
|
107
|
-
AssistantMessage={AssistantMessage}
|
|
108
|
-
UserMessage={UserMessage}
|
|
109
|
-
/>
|
|
110
|
-
);
|
|
111
|
-
} else if (message.isImageMessage && message.isImageMessage()) {
|
|
112
|
-
return (
|
|
113
|
-
<RenderImageMessage
|
|
114
|
-
key={index}
|
|
115
|
-
message={message}
|
|
116
|
-
inProgress={inProgress}
|
|
117
|
-
index={index}
|
|
118
|
-
isCurrentMessage={isCurrentMessage}
|
|
119
|
-
AssistantMessage={AssistantMessage}
|
|
120
|
-
UserMessage={UserMessage}
|
|
121
|
-
onRegenerate={onRegenerate}
|
|
122
|
-
onCopy={onCopy}
|
|
123
|
-
onThumbsUp={onThumbsUp}
|
|
124
|
-
onThumbsDown={onThumbsDown}
|
|
125
|
-
/>
|
|
126
|
-
);
|
|
127
|
-
}
|
|
30
|
+
return (
|
|
31
|
+
<RenderMessage
|
|
32
|
+
key={index}
|
|
33
|
+
message={message}
|
|
34
|
+
inProgress={inProgress}
|
|
35
|
+
index={index}
|
|
36
|
+
isCurrentMessage={isCurrentMessage}
|
|
37
|
+
AssistantMessage={AssistantMessage}
|
|
38
|
+
UserMessage={UserMessage}
|
|
39
|
+
onRegenerate={onRegenerate}
|
|
40
|
+
onCopy={onCopy}
|
|
41
|
+
onThumbsUp={onThumbsUp}
|
|
42
|
+
onThumbsDown={onThumbsDown}
|
|
43
|
+
markdownTagRenderers={markdownTagRenderers}
|
|
44
|
+
/>
|
|
45
|
+
);
|
|
128
46
|
})}
|
|
129
47
|
{interrupt}
|
|
130
48
|
</div>
|
|
@@ -135,26 +53,29 @@ export const Messages = ({
|
|
|
135
53
|
);
|
|
136
54
|
};
|
|
137
55
|
|
|
138
|
-
function makeInitialMessages(initial
|
|
139
|
-
|
|
140
|
-
if (initial) {
|
|
141
|
-
if (Array.isArray(initial)) {
|
|
142
|
-
initialArray.push(...initial);
|
|
143
|
-
} else {
|
|
144
|
-
initialArray.push(initial);
|
|
145
|
-
}
|
|
146
|
-
}
|
|
56
|
+
function makeInitialMessages(initial: string | string[] | undefined): Message[] {
|
|
57
|
+
if (!initial) return [];
|
|
147
58
|
|
|
148
|
-
|
|
149
|
-
(message) =>
|
|
150
|
-
|
|
151
|
-
|
|
59
|
+
if (Array.isArray(initial)) {
|
|
60
|
+
return initial.map((message) => {
|
|
61
|
+
return {
|
|
62
|
+
id: message,
|
|
63
|
+
role: "assistant",
|
|
152
64
|
content: message,
|
|
153
|
-
}
|
|
154
|
-
|
|
65
|
+
};
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
return [
|
|
70
|
+
{
|
|
71
|
+
id: initial,
|
|
72
|
+
role: "system",
|
|
73
|
+
content: initial,
|
|
74
|
+
},
|
|
75
|
+
];
|
|
155
76
|
}
|
|
156
77
|
|
|
157
|
-
export function useScrollToBottom(messages:
|
|
78
|
+
export function useScrollToBottom(messages: Message[]) {
|
|
158
79
|
const messagesEndRef = useRef<HTMLDivElement>(null);
|
|
159
80
|
const messagesContainerRef = useRef<HTMLDivElement | null>(null);
|
|
160
81
|
const isProgrammaticScrollRef = useRef(false);
|
|
@@ -217,7 +138,7 @@ export function useScrollToBottom(messages: any[]) {
|
|
|
217
138
|
useEffect(() => {
|
|
218
139
|
isUserScrollUpRef.current = false;
|
|
219
140
|
scrollToBottom();
|
|
220
|
-
}, [messages.filter((m) => m.
|
|
141
|
+
}, [messages.filter((m) => m.role === "user").length]);
|
|
221
142
|
|
|
222
143
|
return { messagesEndRef, messagesContainerRef };
|
|
223
144
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* <br/>
|
|
3
|
-
* <img src="/images/CopilotPopup.gif" width="500" />
|
|
3
|
+
* <img src="https://cdn.copilotkit.ai/docs/copilotkit/images/CopilotPopup.gif" width="500" />
|
|
4
4
|
*
|
|
5
5
|
* A chatbot popup component for the CopilotKit framework. The component allows for a high degree
|
|
6
6
|
* of customization through various props and custom CSS.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* <br/>
|
|
3
|
-
* <img src="/images/CopilotSidebar.gif" width="500" />
|
|
3
|
+
* <img src="https://cdn.copilotkit.ai/docs/copilotkit/images/CopilotSidebar.gif" width="500" />
|
|
4
4
|
*
|
|
5
5
|
* A chatbot sidebar component for the CopilotKit framework. Highly customizable through various props and custom CSS.
|
|
6
6
|
*
|
|
@@ -1,13 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
CopilotContextParams,
|
|
3
|
-
extract,
|
|
4
|
-
CopilotChatSuggestionConfiguration,
|
|
5
|
-
CopilotMessagesContextParams,
|
|
6
|
-
} from "@copilotkit/react-core";
|
|
1
|
+
import { useCopilotChat } from "@copilotkit/react-core";
|
|
7
2
|
import { SmallSpinnerIcon } from "./Icons";
|
|
8
|
-
import { CopilotChatSuggestion } from "../../types/suggestions";
|
|
9
|
-
import { actionParametersToJsonSchema } from "@copilotkit/shared";
|
|
10
|
-
import { CopilotRequestType } from "@copilotkit/runtime-client-gql";
|
|
11
3
|
|
|
12
4
|
interface SuggestionsProps {
|
|
13
5
|
title: string;
|
|
@@ -18,9 +10,12 @@ interface SuggestionsProps {
|
|
|
18
10
|
}
|
|
19
11
|
|
|
20
12
|
export function Suggestion({ title, onClick, partial, className }: SuggestionsProps) {
|
|
13
|
+
if (!title) return null;
|
|
14
|
+
const { isLoading } = useCopilotChat();
|
|
15
|
+
|
|
21
16
|
return (
|
|
22
17
|
<button
|
|
23
|
-
disabled={partial}
|
|
18
|
+
disabled={partial || isLoading}
|
|
24
19
|
onClick={(e) => {
|
|
25
20
|
e.preventDefault();
|
|
26
21
|
onClick();
|
|
@@ -32,101 +27,3 @@ export function Suggestion({ title, onClick, partial, className }: SuggestionsPr
|
|
|
32
27
|
</button>
|
|
33
28
|
);
|
|
34
29
|
}
|
|
35
|
-
|
|
36
|
-
export const reloadSuggestions = async (
|
|
37
|
-
context: CopilotContextParams & CopilotMessagesContextParams,
|
|
38
|
-
chatSuggestionConfiguration: { [key: string]: CopilotChatSuggestionConfiguration },
|
|
39
|
-
setCurrentSuggestions: (suggestions: { title: string; message: string }[]) => void,
|
|
40
|
-
abortControllerRef: React.MutableRefObject<AbortController | null>,
|
|
41
|
-
) => {
|
|
42
|
-
const abortController = abortControllerRef.current;
|
|
43
|
-
|
|
44
|
-
const tools = JSON.stringify(
|
|
45
|
-
Object.values(context.actions).map((action) => ({
|
|
46
|
-
name: action.name,
|
|
47
|
-
description: action.description,
|
|
48
|
-
jsonSchema: JSON.stringify(actionParametersToJsonSchema(action.parameters)),
|
|
49
|
-
})),
|
|
50
|
-
);
|
|
51
|
-
|
|
52
|
-
const allSuggestions: CopilotChatSuggestion[] = [];
|
|
53
|
-
|
|
54
|
-
for (const config of Object.values(chatSuggestionConfiguration)) {
|
|
55
|
-
try {
|
|
56
|
-
const numOfSuggestionsInstructions =
|
|
57
|
-
config.minSuggestions === 0
|
|
58
|
-
? `Produce up to ${config.maxSuggestions} suggestions. ` +
|
|
59
|
-
`If there are no highly relevant suggestions you can think of, provide an empty array.`
|
|
60
|
-
: `Produce between ${config.minSuggestions} and ${config.maxSuggestions} suggestions.`;
|
|
61
|
-
|
|
62
|
-
const result = await extract({
|
|
63
|
-
context,
|
|
64
|
-
instructions:
|
|
65
|
-
"Suggest what the user could say next. Provide clear, highly relevant suggestions. Do not literally suggest function calls. ",
|
|
66
|
-
data:
|
|
67
|
-
config.instructions +
|
|
68
|
-
"\n\n" +
|
|
69
|
-
numOfSuggestionsInstructions +
|
|
70
|
-
"\n\n" +
|
|
71
|
-
"Available tools: " +
|
|
72
|
-
tools +
|
|
73
|
-
"\n\n",
|
|
74
|
-
requestType: CopilotRequestType.Task,
|
|
75
|
-
parameters: [
|
|
76
|
-
{
|
|
77
|
-
name: "suggestions",
|
|
78
|
-
type: "object[]",
|
|
79
|
-
attributes: [
|
|
80
|
-
{
|
|
81
|
-
name: "title",
|
|
82
|
-
description:
|
|
83
|
-
"The title of the suggestion. This is shown as a button and should be short.",
|
|
84
|
-
type: "string",
|
|
85
|
-
},
|
|
86
|
-
{
|
|
87
|
-
name: "message",
|
|
88
|
-
description:
|
|
89
|
-
"The message to send when the suggestion is clicked. This should be a clear, complete sentence and will be sent as an instruction to the AI.",
|
|
90
|
-
type: "string",
|
|
91
|
-
},
|
|
92
|
-
],
|
|
93
|
-
},
|
|
94
|
-
],
|
|
95
|
-
include: {
|
|
96
|
-
messages: true,
|
|
97
|
-
readable: true,
|
|
98
|
-
},
|
|
99
|
-
abortSignal: abortController?.signal,
|
|
100
|
-
stream: ({ status, args }) => {
|
|
101
|
-
const suggestions = args.suggestions || [];
|
|
102
|
-
const newSuggestions: CopilotChatSuggestion[] = [];
|
|
103
|
-
for (let i = 0; i < suggestions.length; i++) {
|
|
104
|
-
// if GPT provides too many suggestions, limit the number of suggestions
|
|
105
|
-
if (config.maxSuggestions !== undefined && i >= config.maxSuggestions) {
|
|
106
|
-
break;
|
|
107
|
-
}
|
|
108
|
-
const { title, message } = suggestions[i];
|
|
109
|
-
|
|
110
|
-
// If this is the last suggestion and the status is not complete, mark it as partial
|
|
111
|
-
const partial = i == suggestions.length - 1 && status !== "complete";
|
|
112
|
-
|
|
113
|
-
newSuggestions.push({
|
|
114
|
-
title,
|
|
115
|
-
message,
|
|
116
|
-
partial,
|
|
117
|
-
className: config.className,
|
|
118
|
-
});
|
|
119
|
-
}
|
|
120
|
-
setCurrentSuggestions([...allSuggestions, ...newSuggestions]);
|
|
121
|
-
},
|
|
122
|
-
});
|
|
123
|
-
allSuggestions.push(...result.suggestions);
|
|
124
|
-
} catch (error) {
|
|
125
|
-
console.error("Error loading suggestions", error);
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
if (abortControllerRef.current === abortController) {
|
|
130
|
-
abortControllerRef.current = null;
|
|
131
|
-
}
|
|
132
|
-
};
|
|
@@ -5,7 +5,7 @@ export { CopilotChat } from "./Chat";
|
|
|
5
5
|
export { Markdown } from "./Markdown";
|
|
6
6
|
export { AssistantMessage } from "./messages/AssistantMessage";
|
|
7
7
|
export { UserMessage } from "./messages/UserMessage";
|
|
8
|
+
export { ImageRenderer } from "./messages/ImageRenderer";
|
|
8
9
|
export { useChatContext } from "./ChatContext";
|
|
9
|
-
export { RenderImageMessage } from "./messages/RenderImageMessage";
|
|
10
10
|
export { Suggestions as RenderSuggestionsList } from "./Suggestions";
|
|
11
11
|
export { Suggestion as RenderSuggestion } from "./Suggestion";
|
|
@@ -2,67 +2,58 @@ import { AssistantMessageProps } from "../props";
|
|
|
2
2
|
import { useChatContext } from "../ChatContext";
|
|
3
3
|
import { Markdown } from "../Markdown";
|
|
4
4
|
import { useState } from "react";
|
|
5
|
-
import { TextMessage } from "@copilotkit/runtime-client-gql";
|
|
6
5
|
|
|
7
6
|
export const AssistantMessage = (props: AssistantMessageProps) => {
|
|
8
7
|
const { icons, labels } = useChatContext();
|
|
9
8
|
const {
|
|
10
9
|
message,
|
|
11
10
|
isLoading,
|
|
12
|
-
subComponent,
|
|
13
11
|
onRegenerate,
|
|
14
12
|
onCopy,
|
|
15
13
|
onThumbsUp,
|
|
16
14
|
onThumbsDown,
|
|
17
15
|
isCurrentMessage,
|
|
18
|
-
rawData,
|
|
19
16
|
markdownTagRenderers,
|
|
20
17
|
} = props;
|
|
21
18
|
const [copied, setCopied] = useState(false);
|
|
22
19
|
|
|
23
20
|
const handleCopy = () => {
|
|
24
|
-
|
|
25
|
-
|
|
21
|
+
const content = message?.content || "";
|
|
22
|
+
if (content && onCopy) {
|
|
23
|
+
navigator.clipboard.writeText(content);
|
|
26
24
|
setCopied(true);
|
|
27
|
-
onCopy(
|
|
25
|
+
onCopy(content);
|
|
28
26
|
setTimeout(() => setCopied(false), 2000);
|
|
29
|
-
} else if (
|
|
30
|
-
navigator.clipboard.writeText(
|
|
27
|
+
} else if (content) {
|
|
28
|
+
navigator.clipboard.writeText(content);
|
|
31
29
|
setCopied(true);
|
|
32
30
|
setTimeout(() => setCopied(false), 2000);
|
|
33
31
|
}
|
|
34
32
|
};
|
|
35
33
|
|
|
36
34
|
const handleRegenerate = () => {
|
|
37
|
-
if (onRegenerate)
|
|
38
|
-
onRegenerate();
|
|
39
|
-
}
|
|
35
|
+
if (onRegenerate) onRegenerate();
|
|
40
36
|
};
|
|
41
37
|
|
|
42
38
|
const handleThumbsUp = () => {
|
|
43
|
-
|
|
44
|
-
if (onThumbsUp && fullMessage) {
|
|
45
|
-
onThumbsUp(fullMessage);
|
|
46
|
-
}
|
|
39
|
+
if (onThumbsUp && message) onThumbsUp(message);
|
|
47
40
|
};
|
|
48
41
|
|
|
49
42
|
const handleThumbsDown = () => {
|
|
50
|
-
|
|
51
|
-
if (onThumbsDown && fullMessage) {
|
|
52
|
-
onThumbsDown(fullMessage);
|
|
53
|
-
}
|
|
43
|
+
if (onThumbsDown && message) onThumbsDown(message);
|
|
54
44
|
};
|
|
55
45
|
|
|
56
46
|
const LoadingIcon = () => <span>{icons.activityIcon}</span>;
|
|
47
|
+
const content = message?.content || "";
|
|
48
|
+
const subComponent = message?.generativeUI?.();
|
|
57
49
|
|
|
58
50
|
return (
|
|
59
51
|
<>
|
|
60
|
-
{
|
|
52
|
+
{content && (
|
|
61
53
|
<div className="copilotKitMessage copilotKitAssistantMessage">
|
|
62
|
-
{
|
|
63
|
-
{isLoading && <LoadingIcon />}
|
|
54
|
+
{content && <Markdown content={content} components={markdownTagRenderers} />}
|
|
64
55
|
|
|
65
|
-
{
|
|
56
|
+
{content && !isLoading && (
|
|
66
57
|
<div
|
|
67
58
|
className={`copilotKitMessageControls ${isCurrentMessage ? "currentMessage" : ""}`}
|
|
68
59
|
>
|
|
@@ -111,6 +102,7 @@ export const AssistantMessage = (props: AssistantMessageProps) => {
|
|
|
111
102
|
</div>
|
|
112
103
|
)}
|
|
113
104
|
<div style={{ marginBottom: "0.5rem" }}>{subComponent}</div>
|
|
105
|
+
{isLoading && <LoadingIcon />}
|
|
114
106
|
</>
|
|
115
107
|
);
|
|
116
108
|
};
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import React, { useState } from "react";
|
|
2
|
+
import { ImageRendererProps } from "../props";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Default image rendering component that can be customized by users.
|
|
6
|
+
* Uses CSS classes for styling so users can override styles.
|
|
7
|
+
*/
|
|
8
|
+
export const ImageRenderer: React.FC<ImageRendererProps> = ({ image, content, className = "" }) => {
|
|
9
|
+
const [imageError, setImageError] = useState(false);
|
|
10
|
+
const imageSrc = `data:image/${image.format};base64,${image.bytes}`;
|
|
11
|
+
const altText = content || "User uploaded image";
|
|
12
|
+
|
|
13
|
+
const handleImageError = () => {
|
|
14
|
+
setImageError(true);
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
if (imageError) {
|
|
18
|
+
return (
|
|
19
|
+
<div className={`copilotKitImageRendering copilotKitImageRenderingError ${className}`}>
|
|
20
|
+
<div className="copilotKitImageRenderingErrorMessage">Failed to load image</div>
|
|
21
|
+
{content && <div className="copilotKitImageRenderingContent">{content}</div>}
|
|
22
|
+
</div>
|
|
23
|
+
);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
return (
|
|
27
|
+
<div className={`copilotKitImageRendering ${className}`}>
|
|
28
|
+
<img
|
|
29
|
+
src={imageSrc}
|
|
30
|
+
alt={altText}
|
|
31
|
+
className="copilotKitImageRenderingImage"
|
|
32
|
+
onError={handleImageError}
|
|
33
|
+
/>
|
|
34
|
+
{content && <div className="copilotKitImageRenderingContent">{content}</div>}
|
|
35
|
+
</div>
|
|
36
|
+
);
|
|
37
|
+
};
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import { RenderMessageProps } from "../props";
|
|
2
2
|
import { UserMessage as DefaultUserMessage } from "./UserMessage";
|
|
3
3
|
import { AssistantMessage as DefaultAssistantMessage } from "./AssistantMessage";
|
|
4
|
+
import { ImageRenderer as DefaultImageRenderer } from "./ImageRenderer";
|
|
4
5
|
|
|
5
|
-
export function
|
|
6
|
+
export function RenderMessage({
|
|
6
7
|
UserMessage = DefaultUserMessage,
|
|
7
8
|
AssistantMessage = DefaultAssistantMessage,
|
|
9
|
+
ImageRenderer = DefaultImageRenderer,
|
|
8
10
|
...props
|
|
9
11
|
}: RenderMessageProps) {
|
|
10
12
|
const {
|
|
@@ -19,23 +21,22 @@ export function RenderTextMessage({
|
|
|
19
21
|
markdownTagRenderers,
|
|
20
22
|
} = props;
|
|
21
23
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
+
switch (message.role) {
|
|
25
|
+
case "user":
|
|
24
26
|
return (
|
|
25
27
|
<UserMessage
|
|
26
28
|
key={index}
|
|
27
29
|
data-message-role="user"
|
|
28
|
-
message={message
|
|
29
|
-
|
|
30
|
+
message={message}
|
|
31
|
+
ImageRenderer={ImageRenderer}
|
|
30
32
|
/>
|
|
31
33
|
);
|
|
32
|
-
|
|
34
|
+
case "assistant":
|
|
33
35
|
return (
|
|
34
36
|
<AssistantMessage
|
|
35
37
|
key={index}
|
|
36
38
|
data-message-role="assistant"
|
|
37
|
-
message={message
|
|
38
|
-
rawData={message}
|
|
39
|
+
message={message}
|
|
39
40
|
isLoading={inProgress && isCurrentMessage && !message.content}
|
|
40
41
|
isGenerating={inProgress && isCurrentMessage && !!message.content}
|
|
41
42
|
isCurrentMessage={isCurrentMessage}
|
|
@@ -44,8 +45,8 @@ export function RenderTextMessage({
|
|
|
44
45
|
onThumbsUp={onThumbsUp}
|
|
45
46
|
onThumbsDown={onThumbsDown}
|
|
46
47
|
markdownTagRenderers={markdownTagRenderers}
|
|
48
|
+
ImageRenderer={ImageRenderer}
|
|
47
49
|
/>
|
|
48
50
|
);
|
|
49
|
-
}
|
|
50
51
|
}
|
|
51
52
|
}
|
|
@@ -1,9 +1,20 @@
|
|
|
1
1
|
import { UserMessageProps } from "../props";
|
|
2
2
|
|
|
3
3
|
export const UserMessage = (props: UserMessageProps) => {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
)
|
|
4
|
+
const { message, ImageRenderer } = props;
|
|
5
|
+
const isImageMessage = message && "image" in message && message.image;
|
|
6
|
+
|
|
7
|
+
// Image message
|
|
8
|
+
if (isImageMessage) {
|
|
9
|
+
const imageMessage = message;
|
|
10
|
+
|
|
11
|
+
return (
|
|
12
|
+
<div className="copilotKitMessage copilotKitUserMessage">
|
|
13
|
+
<ImageRenderer image={imageMessage.image!} content={imageMessage.content} />
|
|
14
|
+
</div>
|
|
15
|
+
);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
// Regular text message
|
|
19
|
+
return <div className="copilotKitMessage copilotKitUserMessage">{message?.content}</div>;
|
|
9
20
|
};
|