@copilotkit/react-ui 1.3.2 → 1.3.3-pre.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (84) hide show
  1. package/CHANGELOG.md +10 -0
  2. package/dist/{chunk-PGJGIYRW.mjs → chunk-3YESXHJH.mjs} +3 -3
  3. package/dist/{chunk-I454U2HM.mjs → chunk-BTOVRBBW.mjs} +52 -25
  4. package/dist/chunk-BTOVRBBW.mjs.map +1 -0
  5. package/dist/chunk-GDNJRSD4.mjs +126 -0
  6. package/dist/chunk-GDNJRSD4.mjs.map +1 -0
  7. package/dist/{chunk-N6GQ4WV4.mjs → chunk-GHMYWL42.mjs} +2 -2
  8. package/dist/{chunk-N6GQ4WV4.mjs.map → chunk-GHMYWL42.mjs.map} +1 -1
  9. package/dist/chunk-GOTHQ665.mjs +19 -0
  10. package/dist/chunk-GOTHQ665.mjs.map +1 -0
  11. package/dist/chunk-MA5B5ELM.mjs +26 -0
  12. package/dist/chunk-MA5B5ELM.mjs.map +1 -0
  13. package/dist/chunk-U42OB2S3.mjs +61 -0
  14. package/dist/chunk-U42OB2S3.mjs.map +1 -0
  15. package/dist/{chunk-KJQVEUVB.mjs → chunk-UUHCZZZV.mjs} +2 -2
  16. package/dist/chunk-UUHCZZZV.mjs.map +1 -0
  17. package/dist/chunk-YH2STM73.mjs +76 -0
  18. package/dist/chunk-YH2STM73.mjs.map +1 -0
  19. package/dist/components/chat/Chat.d.ts +18 -2
  20. package/dist/components/chat/Chat.js +664 -556
  21. package/dist/components/chat/Chat.js.map +1 -1
  22. package/dist/components/chat/Chat.mjs +6 -2
  23. package/dist/components/chat/Messages.d.ts +1 -1
  24. package/dist/components/chat/Messages.js +61 -662
  25. package/dist/components/chat/Messages.js.map +1 -1
  26. package/dist/components/chat/Messages.mjs +1 -4
  27. package/dist/components/chat/Modal.js +669 -561
  28. package/dist/components/chat/Modal.js.map +1 -1
  29. package/dist/components/chat/Modal.mjs +7 -3
  30. package/dist/components/chat/Popup.js +669 -561
  31. package/dist/components/chat/Popup.js.map +1 -1
  32. package/dist/components/chat/Popup.mjs +8 -4
  33. package/dist/components/chat/Sidebar.js +669 -561
  34. package/dist/components/chat/Sidebar.js.map +1 -1
  35. package/dist/components/chat/Sidebar.mjs +8 -4
  36. package/dist/components/chat/index.d.ts +1 -1
  37. package/dist/components/chat/index.js +669 -561
  38. package/dist/components/chat/index.js.map +1 -1
  39. package/dist/components/chat/index.mjs +9 -5
  40. package/dist/components/chat/messages/RenderActionExecutionMessage.d.ts +7 -0
  41. package/dist/components/chat/messages/RenderActionExecutionMessage.js +122 -0
  42. package/dist/components/chat/messages/RenderActionExecutionMessage.js.map +1 -0
  43. package/dist/components/chat/messages/RenderActionExecutionMessage.mjs +10 -0
  44. package/dist/components/chat/messages/RenderActionExecutionMessage.mjs.map +1 -0
  45. package/dist/components/chat/messages/RenderAgentStateMessage.d.ts +7 -0
  46. package/dist/components/chat/messages/RenderAgentStateMessage.js +107 -0
  47. package/dist/components/chat/messages/RenderAgentStateMessage.js.map +1 -0
  48. package/dist/components/chat/messages/RenderAgentStateMessage.mjs +10 -0
  49. package/dist/components/chat/messages/RenderAgentStateMessage.mjs.map +1 -0
  50. package/dist/components/chat/messages/RenderResultMessage.d.ts +7 -0
  51. package/dist/components/chat/messages/RenderResultMessage.js +65 -0
  52. package/dist/components/chat/messages/RenderResultMessage.js.map +1 -0
  53. package/dist/components/chat/messages/RenderResultMessage.mjs +10 -0
  54. package/dist/components/chat/messages/RenderResultMessage.mjs.map +1 -0
  55. package/dist/components/chat/messages/RenderTextMessage.d.ts +7 -0
  56. package/dist/components/chat/messages/RenderTextMessage.js +614 -0
  57. package/dist/components/chat/messages/RenderTextMessage.js.map +1 -0
  58. package/dist/components/chat/messages/RenderTextMessage.mjs +13 -0
  59. package/dist/components/chat/messages/RenderTextMessage.mjs.map +1 -0
  60. package/dist/components/chat/props.d.ts +12 -1
  61. package/dist/components/chat/props.js.map +1 -1
  62. package/dist/components/index.d.ts +1 -1
  63. package/dist/components/index.js +669 -561
  64. package/dist/components/index.js.map +1 -1
  65. package/dist/components/index.mjs +9 -5
  66. package/dist/index.d.ts +1 -1
  67. package/dist/index.js +677 -569
  68. package/dist/index.js.map +1 -1
  69. package/dist/index.mjs +9 -5
  70. package/package.json +7 -7
  71. package/src/components/chat/Chat.tsx +39 -4
  72. package/src/components/chat/Messages.tsx +45 -175
  73. package/src/components/chat/Popup.tsx +2 -2
  74. package/src/components/chat/Sidebar.tsx +2 -2
  75. package/src/components/chat/messages/RenderActionExecutionMessage.tsx +90 -0
  76. package/src/components/chat/messages/RenderAgentStateMessage.tsx +81 -0
  77. package/src/components/chat/messages/RenderResultMessage.tsx +15 -0
  78. package/src/components/chat/messages/RenderTextMessage.tsx +28 -0
  79. package/src/components/chat/props.ts +12 -0
  80. package/dist/chunk-4K36ATCD.mjs +0 -184
  81. package/dist/chunk-4K36ATCD.mjs.map +0 -1
  82. package/dist/chunk-I454U2HM.mjs.map +0 -1
  83. package/dist/chunk-KJQVEUVB.mjs.map +0 -1
  84. /package/dist/{chunk-PGJGIYRW.mjs.map → chunk-3YESXHJH.mjs.map} +0 -0
package/dist/index.mjs CHANGED
@@ -4,27 +4,31 @@ import "./chunk-JD7BAH7U.mjs";
4
4
  import "./chunk-MRFF7GSQ.mjs";
5
5
  import {
6
6
  CopilotSidebar
7
- } from "./chunk-KJQVEUVB.mjs";
7
+ } from "./chunk-UUHCZZZV.mjs";
8
8
  import "./chunk-WB3YULQ4.mjs";
9
9
  import {
10
10
  CopilotPopup
11
- } from "./chunk-N6GQ4WV4.mjs";
12
- import "./chunk-PGJGIYRW.mjs";
11
+ } from "./chunk-GHMYWL42.mjs";
12
+ import "./chunk-3YESXHJH.mjs";
13
13
  import "./chunk-FO7Z5LAL.mjs";
14
14
  import "./chunk-FLV3J3VX.mjs";
15
15
  import "./chunk-YOH25I6N.mjs";
16
16
  import {
17
17
  CopilotChat
18
- } from "./chunk-I454U2HM.mjs";
18
+ } from "./chunk-BTOVRBBW.mjs";
19
19
  import "./chunk-V7W6IM2V.mjs";
20
+ import "./chunk-YH2STM73.mjs";
21
+ import "./chunk-U42OB2S3.mjs";
22
+ import "./chunk-GOTHQ665.mjs";
23
+ import "./chunk-MA5B5ELM.mjs";
20
24
  import "./chunk-WCPLXRZX.mjs";
21
25
  import "./chunk-I4QG2ZZU.mjs";
22
26
  import "./chunk-H7TM5JE6.mjs";
23
27
  import "./chunk-OTPAZXVR.mjs";
24
28
  import "./chunk-U6J5DGOE.mjs";
25
29
  import "./chunk-YQFVRDNC.mjs";
26
- import "./chunk-4K36ATCD.mjs";
27
30
  import "./chunk-YQ3D5IQV.mjs";
31
+ import "./chunk-GDNJRSD4.mjs";
28
32
  import "./chunk-XSUSSWDS.mjs";
29
33
  import {
30
34
  useChatContext
package/package.json CHANGED
@@ -9,7 +9,7 @@
9
9
  "publishConfig": {
10
10
  "access": "public"
11
11
  },
12
- "version": "1.3.2",
12
+ "version": "1.3.3-pre.0",
13
13
  "sideEffects": [
14
14
  "**/*.css"
15
15
  ],
@@ -40,9 +40,9 @@
40
40
  "ts-jest": "^29.1.1",
41
41
  "tsup": "^6.7.0",
42
42
  "typescript": "^5.2.3",
43
- "eslint-config-custom": "1.3.2",
44
- "tailwind-config": "1.3.2",
45
- "tsconfig": "1.3.2"
43
+ "eslint-config-custom": "1.3.3-pre.0",
44
+ "tailwind-config": "1.3.3-pre.0",
45
+ "tsconfig": "1.3.3-pre.0"
46
46
  },
47
47
  "dependencies": {
48
48
  "@headlessui/react": "^2.1.3",
@@ -50,9 +50,9 @@
50
50
  "react-syntax-highlighter": "^15.5.0",
51
51
  "remark-gfm": "^3.0.1",
52
52
  "remark-math": "^5.1.1",
53
- "@copilotkit/react-core": "1.3.2",
54
- "@copilotkit/runtime-client-gql": "1.3.2",
55
- "@copilotkit/shared": "1.3.2"
53
+ "@copilotkit/react-core": "1.3.3-pre.0",
54
+ "@copilotkit/runtime-client-gql": "1.3.3-pre.0",
55
+ "@copilotkit/shared": "1.3.3-pre.0"
56
56
  },
57
57
  "keywords": [
58
58
  "copilotkit",
@@ -30,9 +30,9 @@
30
30
  * ### Look & Feel
31
31
  *
32
32
  * By default, CopilotKit components do not have any styles. You can import CopilotKit's stylesheet at the root of your project:
33
- * ```tsx fileName="YourRootComponent.tsx" {2}
33
+ * ```tsx title="YourRootComponent.tsx"
34
34
  * ...
35
- * import "@copilotkit/react-ui/styles.css";
35
+ * import "@copilotkit/react-ui/styles.css"; // [!code highlight]
36
36
  *
37
37
  * export function YourRootComponent() {
38
38
  * return (
@@ -54,13 +54,17 @@ import {
54
54
  import { Messages as DefaultMessages } from "./Messages";
55
55
  import { Input as DefaultInput } from "./Input";
56
56
  import { ResponseButton as DefaultResponseButton } from "./Response";
57
+ import { RenderTextMessage as DefaultRenderTextMessage } from "./messages/RenderTextMessage";
58
+ import { RenderActionExecutionMessage as DefaultRenderActionExecutionMessage } from "./messages/RenderActionExecutionMessage";
59
+ import { RenderResultMessage as DefaultRenderResultMessage } from "./messages/RenderResultMessage";
60
+ import { RenderAgentStateMessage as DefaultRenderAgentStateMessage } from "./messages/RenderAgentStateMessage";
57
61
  import { Suggestion } from "./Suggestion";
58
62
  import React, { useEffect, useRef, useState } from "react";
59
63
  import { SystemMessageFunction, useCopilotChat, useCopilotContext } from "@copilotkit/react-core";
60
64
  import { reloadSuggestions } from "./Suggestion";
61
65
  import { CopilotChatSuggestion } from "../../types/suggestions";
62
66
  import { Message, Role, TextMessage } from "@copilotkit/runtime-client-gql";
63
- import { InputProps, MessagesProps, ResponseButtonProps } from "./props";
67
+ import { InputProps, MessagesProps, RenderMessageProps, ResponseButtonProps } from "./props";
64
68
  import { randomId } from "@copilotkit/shared";
65
69
 
66
70
  import { CopilotDevConsole } from "../dev-console";
@@ -118,6 +122,26 @@ export interface CopilotChatProps {
118
122
  */
119
123
  Messages?: React.ComponentType<MessagesProps>;
120
124
 
125
+ /**
126
+ * A custom RenderTextMessage component to use instead of the default.
127
+ */
128
+ RenderTextMessage?: React.ComponentType<RenderMessageProps>;
129
+
130
+ /**
131
+ * A custom RenderActionExecutionMessage component to use instead of the default.
132
+ */
133
+ RenderActionExecutionMessage?: React.ComponentType<RenderMessageProps>;
134
+
135
+ /**
136
+ * A custom RenderAgentStateMessage component to use instead of the default.
137
+ */
138
+ RenderAgentStateMessage?: React.ComponentType<RenderMessageProps>;
139
+
140
+ /**
141
+ * A custom RenderResultMessage component to use instead of the default.
142
+ */
143
+ RenderResultMessage?: React.ComponentType<RenderMessageProps>;
144
+
121
145
  /**
122
146
  * A custom Input component to use instead of the default.
123
147
  */
@@ -146,6 +170,10 @@ export function CopilotChat({
146
170
  showResponseButton = true,
147
171
  onInProgress,
148
172
  Messages = DefaultMessages,
173
+ RenderTextMessage = DefaultRenderTextMessage,
174
+ RenderActionExecutionMessage = DefaultRenderActionExecutionMessage,
175
+ RenderAgentStateMessage = DefaultRenderAgentStateMessage,
176
+ RenderResultMessage = DefaultRenderResultMessage,
149
177
  Input = DefaultInput,
150
178
  ResponseButton = DefaultResponseButton,
151
179
  className,
@@ -173,7 +201,14 @@ export function CopilotChat({
173
201
  return (
174
202
  <WrappedCopilotChat icons={icons} labels={labels} className={className}>
175
203
  <CopilotDevConsole />
176
- <Messages messages={visibleMessages} inProgress={isLoading}>
204
+ <Messages
205
+ RenderTextMessage={RenderTextMessage}
206
+ RenderActionExecutionMessage={RenderActionExecutionMessage}
207
+ RenderAgentStateMessage={RenderAgentStateMessage}
208
+ RenderResultMessage={RenderResultMessage}
209
+ messages={visibleMessages}
210
+ inProgress={isLoading}
211
+ >
177
212
  {currentSuggestions.length > 0 && (
178
213
  <div>
179
214
  <h6>Suggested:</h6>
@@ -1,10 +1,7 @@
1
1
  import React, { useEffect, useMemo } from "react";
2
2
  import { MessagesProps } from "./props";
3
3
  import { useChatContext } from "./ChatContext";
4
- import { Markdown } from "./Markdown";
5
- import { RenderFunctionStatus, useCopilotContext } from "@copilotkit/react-core";
6
4
  import {
7
- MessageStatusCode,
8
5
  ActionExecutionMessage,
9
6
  Message,
10
7
  ResultMessage,
@@ -12,11 +9,16 @@ import {
12
9
  Role,
13
10
  AgentStateMessage,
14
11
  } from "@copilotkit/runtime-client-gql";
15
- import { CoagentInChatRenderFunction } from "@copilotkit/react-core/dist/context/copilot-context";
16
-
17
- export const Messages = ({ messages, inProgress, children }: MessagesProps) => {
18
- const { chatComponentsCache } = useCopilotContext();
19
12
 
13
+ export const Messages = ({
14
+ messages,
15
+ inProgress,
16
+ children,
17
+ RenderTextMessage,
18
+ RenderActionExecutionMessage,
19
+ RenderAgentStateMessage,
20
+ RenderResultMessage,
21
+ }: MessagesProps) => {
20
22
  const context = useChatContext();
21
23
  const initialMessages = useMemo(
22
24
  () => makeInitialMessages(context.labels.initial),
@@ -24,7 +26,7 @@ export const Messages = ({ messages, inProgress, children }: MessagesProps) => {
24
26
  );
25
27
  messages = [...initialMessages, ...messages];
26
28
 
27
- const functionResults: Record<string, string> = {};
29
+ const actionResults: Record<string, string> = {};
28
30
 
29
31
  for (let i = 0; i < messages.length; i++) {
30
32
  if (messages[i] instanceof ActionExecutionMessage) {
@@ -34,7 +36,7 @@ export const Messages = ({ messages, inProgress, children }: MessagesProps) => {
34
36
  ) as ResultMessage | undefined;
35
37
 
36
38
  if (resultMessage) {
37
- functionResults[id] = ResultMessage.decodeResult(resultMessage.result || "");
39
+ actionResults[id] = ResultMessage.decodeResult(resultMessage.result || "");
38
40
  }
39
41
  }
40
42
  }
@@ -58,178 +60,46 @@ export const Messages = ({ messages, inProgress, children }: MessagesProps) => {
58
60
  {messages.map((message, index) => {
59
61
  const isCurrentMessage = index === messages.length - 1;
60
62
 
61
- if (message instanceof TextMessage && message.role === "user") {
63
+ if (message instanceof TextMessage) {
62
64
  return (
63
- <div key={index} className="copilotKitMessage copilotKitUserMessage">
64
- {message.content}
65
- </div>
65
+ <RenderTextMessage
66
+ key={index}
67
+ message={message}
68
+ inProgress={inProgress}
69
+ index={index}
70
+ isCurrentMessage={isCurrentMessage}
71
+ />
66
72
  );
67
- } else if (message instanceof TextMessage && message.role == "assistant") {
73
+ } else if (message instanceof ActionExecutionMessage) {
68
74
  return (
69
- <div key={index} className={`copilotKitMessage copilotKitAssistantMessage`}>
70
- {isCurrentMessage && inProgress && !message.content ? (
71
- context.icons.spinnerIcon
72
- ) : (
73
- <Markdown content={message.content} />
74
- )}
75
- </div>
75
+ <RenderActionExecutionMessage
76
+ key={index}
77
+ message={message}
78
+ inProgress={inProgress}
79
+ index={index}
80
+ isCurrentMessage={isCurrentMessage}
81
+ actionResult={actionResults[message.id]}
82
+ />
76
83
  );
77
- } else if (message instanceof ActionExecutionMessage) {
78
- if (
79
- chatComponentsCache.current !== null &&
80
- chatComponentsCache.current.actions[message.name]
81
- ) {
82
- const render = chatComponentsCache.current.actions[message.name];
83
- // render a static string
84
- if (typeof render === "string") {
85
- // when render is static, we show it only when in progress
86
- if (isCurrentMessage && inProgress) {
87
- return (
88
- <div key={index} className={`copilotKitMessage copilotKitAssistantMessage`}>
89
- {context.icons.spinnerIcon} <span className="inProgressLabel">{render}</span>
90
- </div>
91
- );
92
- }
93
- // Done - silent by default to avoid a series of "done" messages
94
- else {
95
- return null;
96
- }
97
- }
98
- // render is a function
99
- else {
100
- const args = message.arguments;
101
-
102
- let status: RenderFunctionStatus = "inProgress";
103
-
104
- if (functionResults[message.id] !== undefined) {
105
- status = "complete";
106
- } else if (message.status.code !== MessageStatusCode.Pending) {
107
- status = "executing";
108
- }
109
-
110
- try {
111
- const toRender = render({
112
- status: status as any,
113
- args,
114
- result: functionResults[message.id],
115
- });
116
- // No result and complete: stay silent
117
- if (!toRender && status === "complete") {
118
- return null;
119
- }
120
- if (typeof toRender === "string") {
121
- return (
122
- <div key={index} className={`copilotKitMessage copilotKitAssistantMessage`}>
123
- {isCurrentMessage && inProgress && context.icons.spinnerIcon} {toRender}
124
- </div>
125
- );
126
- } else {
127
- return (
128
- <div key={index} className="copilotKitCustomAssistantMessage">
129
- {toRender}
130
- </div>
131
- );
132
- }
133
- } catch (e) {
134
- console.error(`Error executing render function for action ${message.name}: ${e}`);
135
- return (
136
- <div key={index} className={`copilotKitMessage copilotKitAssistantMessage`}>
137
- {isCurrentMessage && inProgress && context.icons.spinnerIcon}
138
- <b>❌ Error executing render: {message.name}</b>
139
- <br />
140
- {e instanceof Error ? e.message : String(e)}
141
- </div>
142
- );
143
- }
144
- }
145
- }
146
- // No render function found- show the default message
147
- else if (!inProgress || !isCurrentMessage) {
148
- // Done - silent by default to avoid a series of "done" messages
149
- return null;
150
- } else {
151
- // In progress
152
- return (
153
- <div key={index} className={`copilotKitMessage copilotKitAssistantMessage`}>
154
- {context.icons.spinnerIcon}
155
- </div>
156
- );
157
- }
158
84
  } else if (message instanceof AgentStateMessage) {
159
- let render: string | CoagentInChatRenderFunction | undefined;
160
-
161
- if (chatComponentsCache.current !== null) {
162
- render =
163
- chatComponentsCache.current.coagentActions[
164
- `${message.agentName}-${message.nodeName}`
165
- ] || chatComponentsCache.current.coagentActions[`${message.agentName}-global`];
166
- }
167
-
168
- if (render) {
169
- // render a static string
170
- if (typeof render === "string") {
171
- // when render is static, we show it only when in progress
172
- if (isCurrentMessage && inProgress) {
173
- return (
174
- <div key={index} className={`copilotKitMessage copilotKitAssistantMessage`}>
175
- {context.icons.spinnerIcon} <span className="inProgressLabel">{render}</span>
176
- </div>
177
- );
178
- }
179
- // Done - silent by default to avoid a series of "done" messages
180
- else {
181
- return null;
182
- }
183
- }
184
- // render is a function
185
- else {
186
- const state = message.state;
187
-
188
- let status = message.active ? "inProgress" : "complete";
189
-
190
- const toRender = render({
191
- status: status as any,
192
- state,
193
- nodeName: message.nodeName,
194
- });
195
-
196
- // No result and complete: stay silent
197
- if (!toRender && status === "complete") {
198
- return null;
199
- }
200
-
201
- if (typeof toRender === "string") {
202
- return (
203
- <div key={index} className={`copilotKitMessage copilotKitAssistantMessage`}>
204
- {isCurrentMessage && inProgress && context.icons.spinnerIcon} {toRender}
205
- </div>
206
- );
207
- } else {
208
- return (
209
- <div key={index} className="copilotKitCustomAssistantMessage">
210
- {toRender}
211
- </div>
212
- );
213
- }
214
- }
215
- }
216
- // No render function found- show the default message
217
- else if (!inProgress || !isCurrentMessage) {
218
- // Done - silent by default to avoid a series of "done" messages
219
- return null;
220
- } else {
221
- // In progress
222
- return (
223
- <div key={index} className={`copilotKitMessage copilotKitAssistantMessage`}>
224
- {context.icons.spinnerIcon}
225
- </div>
226
- );
227
- }
228
- } else if (message instanceof ResultMessage && inProgress && isCurrentMessage) {
229
85
  return (
230
- <div key={index} className={`copilotKitMessage copilotKitAssistantMessage`}>
231
- {context.icons.spinnerIcon}
232
- </div>
86
+ <RenderAgentStateMessage
87
+ key={index}
88
+ message={message}
89
+ inProgress={inProgress}
90
+ index={index}
91
+ isCurrentMessage={isCurrentMessage}
92
+ />
93
+ );
94
+ } else if (message instanceof ResultMessage) {
95
+ return (
96
+ <RenderResultMessage
97
+ key={index}
98
+ message={message}
99
+ inProgress={inProgress}
100
+ index={index}
101
+ isCurrentMessage={isCurrentMessage}
102
+ />
233
103
  );
234
104
  }
235
105
  })}
@@ -31,9 +31,9 @@
31
31
  * ### Look & Feel
32
32
  *
33
33
  * By default, CopilotKit components do not have any styles. You can import CopilotKit's stylesheet at the root of your project:
34
- * ```tsx fileName="YourRootComponent.tsx" {2}
34
+ * ```tsx title="YourRootComponent.tsx"
35
35
  * ...
36
- * import "@copilotkit/react-ui/styles.css";
36
+ * import "@copilotkit/react-ui/styles.css"; // [!code highlight]
37
37
  *
38
38
  * export function YourRootComponent() {
39
39
  * return (
@@ -33,9 +33,9 @@
33
33
  * ### Look & Feel
34
34
  *
35
35
  * By default, CopilotKit components do not have any styles. You can import CopilotKit's stylesheet at the root of your project:
36
- * ```tsx fileName="YourRootComponent.tsx" {2}
36
+ * ```tsx title="YourRootComponent.tsx"
37
37
  * ...
38
- * import "@copilotkit/react-ui/styles.css";
38
+ * import "@copilotkit/react-ui/styles.css"; // [!code highlight]
39
39
  *
40
40
  * export function YourRootComponent() {
41
41
  * return (
@@ -0,0 +1,90 @@
1
+ import { ActionExecutionMessage, MessageStatusCode } from "@copilotkit/runtime-client-gql";
2
+ import { RenderMessageProps } from "../props";
3
+ import { useChatContext } from "../ChatContext";
4
+ import { RenderFunctionStatus, useCopilotContext } from "@copilotkit/react-core";
5
+
6
+ export function RenderActionExecutionMessage(props: RenderMessageProps) {
7
+ const { message, inProgress, index, isCurrentMessage, actionResult } = props;
8
+ const { chatComponentsCache } = useCopilotContext();
9
+ const { icons } = useChatContext();
10
+
11
+ if (message instanceof ActionExecutionMessage) {
12
+ if (chatComponentsCache.current !== null && chatComponentsCache.current.actions[message.name]) {
13
+ const render = chatComponentsCache.current.actions[message.name];
14
+ // render a static string
15
+ if (typeof render === "string") {
16
+ // when render is static, we show it only when in progress
17
+ if (isCurrentMessage && inProgress) {
18
+ return (
19
+ <div key={index} className={`copilotKitMessage copilotKitAssistantMessage`}>
20
+ {icons.spinnerIcon} <span className="inProgressLabel">{render}</span>
21
+ </div>
22
+ );
23
+ }
24
+ // Done - silent by default to avoid a series of "done" messages
25
+ else {
26
+ return null;
27
+ }
28
+ }
29
+ // render is a function
30
+ else {
31
+ const args = message.arguments;
32
+
33
+ let status: RenderFunctionStatus = "inProgress";
34
+
35
+ if (actionResult !== undefined) {
36
+ status = "complete";
37
+ } else if (message.status.code !== MessageStatusCode.Pending) {
38
+ status = "executing";
39
+ }
40
+
41
+ try {
42
+ const toRender = render({
43
+ status: status as any,
44
+ args,
45
+ result: actionResult,
46
+ });
47
+ // No result and complete: stay silent
48
+ if (!toRender && status === "complete") {
49
+ return null;
50
+ }
51
+ if (typeof toRender === "string") {
52
+ return (
53
+ <div key={index} className={`copilotKitMessage copilotKitAssistantMessage`}>
54
+ {isCurrentMessage && inProgress && icons.spinnerIcon} {toRender}
55
+ </div>
56
+ );
57
+ } else {
58
+ return (
59
+ <div key={index} className="copilotKitCustomAssistantMessage">
60
+ {toRender}
61
+ </div>
62
+ );
63
+ }
64
+ } catch (e) {
65
+ console.error(`Error executing render function for action ${message.name}: ${e}`);
66
+ return (
67
+ <div key={index} className={`copilotKitMessage copilotKitAssistantMessage`}>
68
+ {isCurrentMessage && inProgress && icons.spinnerIcon}
69
+ <b>❌ Error executing render: {message.name}</b>
70
+ <br />
71
+ {e instanceof Error ? e.message : String(e)}
72
+ </div>
73
+ );
74
+ }
75
+ }
76
+ }
77
+ // No render function found- show the default message
78
+ else if (!inProgress || !isCurrentMessage) {
79
+ // Done - silent by default to avoid a series of "done" messages
80
+ return null;
81
+ } else {
82
+ // In progress
83
+ return (
84
+ <div key={index} className={`copilotKitMessage copilotKitAssistantMessage`}>
85
+ {icons.spinnerIcon}
86
+ </div>
87
+ );
88
+ }
89
+ }
90
+ }
@@ -0,0 +1,81 @@
1
+ import { AgentStateMessage } from "@copilotkit/runtime-client-gql";
2
+ import { RenderMessageProps } from "../props";
3
+ import { useChatContext } from "../ChatContext";
4
+ import { CoagentInChatRenderFunction, useCopilotContext } from "@copilotkit/react-core";
5
+
6
+ export function RenderAgentStateMessage(props: RenderMessageProps) {
7
+ const { message, inProgress, index, isCurrentMessage } = props;
8
+ const { chatComponentsCache } = useCopilotContext();
9
+ const { icons } = useChatContext();
10
+
11
+ if (message instanceof AgentStateMessage) {
12
+ let render: string | CoagentInChatRenderFunction | undefined;
13
+
14
+ if (chatComponentsCache.current !== null) {
15
+ render =
16
+ chatComponentsCache.current.coagentActions[`${message.agentName}-${message.nodeName}`] ||
17
+ chatComponentsCache.current.coagentActions[`${message.agentName}-global`];
18
+ }
19
+
20
+ if (render) {
21
+ // render a static string
22
+ if (typeof render === "string") {
23
+ // when render is static, we show it only when in progress
24
+ if (isCurrentMessage && inProgress) {
25
+ return (
26
+ <div key={index} className={`copilotKitMessage copilotKitAssistantMessage`}>
27
+ {icons.spinnerIcon} <span className="inProgressLabel">{render}</span>
28
+ </div>
29
+ );
30
+ }
31
+ // Done - silent by default to avoid a series of "done" messages
32
+ else {
33
+ return null;
34
+ }
35
+ }
36
+ // render is a function
37
+ else {
38
+ const state = message.state;
39
+
40
+ let status = message.active ? "inProgress" : "complete";
41
+
42
+ const toRender = render({
43
+ status: status as any,
44
+ state,
45
+ nodeName: message.nodeName,
46
+ });
47
+
48
+ // No result and complete: stay silent
49
+ if (!toRender && status === "complete") {
50
+ return null;
51
+ }
52
+
53
+ if (typeof toRender === "string") {
54
+ return (
55
+ <div key={index} className={`copilotKitMessage copilotKitAssistantMessage`}>
56
+ {isCurrentMessage && inProgress && icons.spinnerIcon} {toRender}
57
+ </div>
58
+ );
59
+ } else {
60
+ return (
61
+ <div key={index} className="copilotKitCustomAssistantMessage">
62
+ {toRender}
63
+ </div>
64
+ );
65
+ }
66
+ }
67
+ }
68
+ // No render function found- show the default message
69
+ else if (!inProgress || !isCurrentMessage) {
70
+ // Done - silent by default to avoid a series of "done" messages
71
+ return null;
72
+ } else {
73
+ // In progress
74
+ return (
75
+ <div key={index} className={`copilotKitMessage copilotKitAssistantMessage`}>
76
+ {icons.spinnerIcon}
77
+ </div>
78
+ );
79
+ }
80
+ }
81
+ }
@@ -0,0 +1,15 @@
1
+ import { ResultMessage } from "@copilotkit/runtime-client-gql";
2
+ import { RenderMessageProps } from "../props";
3
+ import { useChatContext } from "../ChatContext";
4
+
5
+ export function RenderResultMessage(props: RenderMessageProps) {
6
+ const { message, inProgress, index, isCurrentMessage } = props;
7
+ const { icons } = useChatContext();
8
+ if (message instanceof ResultMessage && inProgress && isCurrentMessage) {
9
+ return (
10
+ <div key={index} className={`copilotKitMessage copilotKitAssistantMessage`}>
11
+ {icons.spinnerIcon}
12
+ </div>
13
+ );
14
+ }
15
+ }
@@ -0,0 +1,28 @@
1
+ import { TextMessage } from "@copilotkit/runtime-client-gql";
2
+ import { RenderMessageProps } from "../props";
3
+ import { Markdown } from "../Markdown";
4
+ import { useChatContext } from "../ChatContext";
5
+
6
+ export function RenderTextMessage(props: RenderMessageProps) {
7
+ const { message, inProgress, index, isCurrentMessage } = props;
8
+ const { icons } = useChatContext();
9
+ if (message instanceof TextMessage) {
10
+ if (message.role === "user") {
11
+ return (
12
+ <div key={index} className="copilotKitMessage copilotKitUserMessage">
13
+ {message.content}
14
+ </div>
15
+ );
16
+ } else if (message.role == "assistant") {
17
+ return (
18
+ <div key={index} className={`copilotKitMessage copilotKitAssistantMessage`}>
19
+ {isCurrentMessage && inProgress && !message.content ? (
20
+ icons.spinnerIcon
21
+ ) : (
22
+ <Markdown content={message.content} />
23
+ )}
24
+ </div>
25
+ );
26
+ }
27
+ }
28
+ }
@@ -23,6 +23,18 @@ export interface MessagesProps {
23
23
  messages: Message[];
24
24
  inProgress: boolean;
25
25
  children?: React.ReactNode;
26
+ RenderTextMessage: React.ComponentType<RenderMessageProps>;
27
+ RenderActionExecutionMessage: React.ComponentType<RenderMessageProps>;
28
+ RenderAgentStateMessage: React.ComponentType<RenderMessageProps>;
29
+ RenderResultMessage: React.ComponentType<RenderMessageProps>;
30
+ }
31
+
32
+ export interface RenderMessageProps {
33
+ message: Message;
34
+ inProgress: boolean;
35
+ index: number;
36
+ isCurrentMessage: boolean;
37
+ actionResult?: string;
26
38
  }
27
39
 
28
40
  export interface InputProps {