@copilotkit/react-core 1.9.2-next.7 → 1.9.2-next.9
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 +16 -0
- package/dist/{chunk-CCESTGAM.mjs → chunk-3OQM3NEK.mjs} +2 -2
- package/dist/{chunk-T4ZKC4X4.mjs → chunk-3YHYWAHK.mjs} +2 -2
- package/dist/{chunk-ISYBUDL4.mjs → chunk-55QZ2SVJ.mjs} +4 -5
- package/dist/chunk-55QZ2SVJ.mjs.map +1 -0
- package/dist/chunk-57K2ZJ5F.mjs +348 -0
- package/dist/chunk-57K2ZJ5F.mjs.map +1 -0
- package/dist/{chunk-ZHEEHGLS.mjs → chunk-ADIITPD2.mjs} +8 -5
- package/dist/{chunk-ZHEEHGLS.mjs.map → chunk-ADIITPD2.mjs.map} +1 -1
- package/dist/{chunk-S4BOATBG.mjs → chunk-EF5BNM34.mjs} +2 -2
- package/dist/{chunk-I4JPQECN.mjs → chunk-EXU7GWLC.mjs} +4 -4
- package/dist/{chunk-7G6RR4HE.mjs → chunk-FXK6RQIN.mjs} +2 -2
- package/dist/{chunk-JXF732XG.mjs → chunk-G7LYGERN.mjs} +80 -13
- package/dist/chunk-G7LYGERN.mjs.map +1 -0
- package/dist/{chunk-VJCHRQ7Q.mjs → chunk-JDEWNLNP.mjs} +37 -4
- package/dist/chunk-JDEWNLNP.mjs.map +1 -0
- package/dist/{chunk-JHIZ5HAI.mjs → chunk-NQVCZQ5T.mjs} +3 -3
- package/dist/{chunk-VF6UPRKM.mjs → chunk-OF4SZTLL.mjs} +3 -3
- package/dist/{chunk-QQZLIEXK.mjs → chunk-SJJNFYGQ.mjs} +3 -3
- package/dist/{chunk-RN3ZRHI7.mjs → chunk-WOGURSAL.mjs} +5 -5
- package/dist/chunk-YAF2LATQ.mjs +310 -0
- package/dist/chunk-YAF2LATQ.mjs.map +1 -0
- package/dist/components/copilot-provider/copilot-messages.js +35 -2
- package/dist/components/copilot-provider/copilot-messages.js.map +1 -1
- package/dist/components/copilot-provider/copilot-messages.mjs +2 -2
- package/dist/components/copilot-provider/copilotkit.js +289 -234
- package/dist/components/copilot-provider/copilotkit.js.map +1 -1
- package/dist/components/copilot-provider/copilotkit.mjs +7 -7
- package/dist/components/copilot-provider/index.js +289 -234
- package/dist/components/copilot-provider/index.js.map +1 -1
- package/dist/components/copilot-provider/index.mjs +7 -7
- package/dist/components/error-boundary/error-boundary.js +135 -146
- package/dist/components/error-boundary/error-boundary.js.map +1 -1
- package/dist/components/error-boundary/error-boundary.mjs +4 -4
- package/dist/components/error-boundary/error-utils.js.map +1 -1
- package/dist/components/error-boundary/error-utils.mjs +2 -2
- package/dist/components/index.js +289 -234
- package/dist/components/index.js.map +1 -1
- package/dist/components/index.mjs +7 -7
- package/dist/components/toast/toast-provider.js +118 -85
- package/dist/components/toast/toast-provider.js.map +1 -1
- package/dist/components/toast/toast-provider.mjs +1 -1
- package/dist/components/usage-banner.js +135 -146
- package/dist/components/usage-banner.js.map +1 -1
- package/dist/components/usage-banner.mjs +1 -1
- package/dist/hooks/index.js +75 -10
- package/dist/hooks/index.js.map +1 -1
- package/dist/hooks/index.mjs +14 -14
- package/dist/hooks/use-chat.js +72 -10
- package/dist/hooks/use-chat.js.map +1 -1
- package/dist/hooks/use-chat.mjs +4 -4
- package/dist/hooks/use-coagent-state-render.js.map +1 -1
- package/dist/hooks/use-coagent-state-render.mjs +2 -2
- package/dist/hooks/use-coagent.js +75 -10
- package/dist/hooks/use-coagent.js.map +1 -1
- package/dist/hooks/use-coagent.mjs +10 -10
- package/dist/hooks/use-copilot-action.js.map +1 -1
- package/dist/hooks/use-copilot-action.mjs +3 -3
- package/dist/hooks/use-copilot-authenticated-action.js.map +1 -1
- package/dist/hooks/use-copilot-authenticated-action.mjs +4 -4
- package/dist/hooks/use-copilot-chat.js +72 -10
- package/dist/hooks/use-copilot-chat.js.map +1 -1
- package/dist/hooks/use-copilot-chat.mjs +9 -9
- package/dist/hooks/use-copilot-runtime-client.js +1 -1
- package/dist/hooks/use-copilot-runtime-client.js.map +1 -1
- package/dist/hooks/use-copilot-runtime-client.mjs +2 -2
- package/dist/hooks/use-langgraph-interrupt.js +72 -10
- package/dist/hooks/use-langgraph-interrupt.js.map +1 -1
- package/dist/hooks/use-langgraph-interrupt.mjs +10 -10
- package/dist/index.js +363 -243
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +15 -15
- package/dist/lib/copilot-task.mjs +8 -8
- package/dist/lib/index.mjs +8 -8
- package/dist/utils/extract.mjs +7 -7
- package/dist/utils/index.mjs +7 -7
- package/jest.config.js +7 -3
- package/package.json +4 -3
- package/src/components/copilot-provider/__tests__/copilotkit-trace.test.tsx +1 -0
- package/src/components/copilot-provider/copilot-messages.tsx +42 -3
- package/src/components/toast/toast-provider.tsx +49 -24
- package/src/components/usage-banner.tsx +144 -147
- package/src/hooks/use-chat.ts +106 -6
- package/src/hooks/use-coagent.ts +5 -0
- package/src/hooks/use-copilot-runtime-client.ts +2 -39
- package/tsconfig.json +1 -8
- package/dist/chunk-HD2GE3DK.mjs +0 -359
- package/dist/chunk-HD2GE3DK.mjs.map +0 -1
- package/dist/chunk-ISYBUDL4.mjs.map +0 -1
- package/dist/chunk-JXF732XG.mjs.map +0 -1
- package/dist/chunk-VJCHRQ7Q.mjs.map +0 -1
- package/dist/chunk-VRXANACV.mjs +0 -277
- package/dist/chunk-VRXANACV.mjs.map +0 -1
- /package/dist/{chunk-CCESTGAM.mjs.map → chunk-3OQM3NEK.mjs.map} +0 -0
- /package/dist/{chunk-T4ZKC4X4.mjs.map → chunk-3YHYWAHK.mjs.map} +0 -0
- /package/dist/{chunk-S4BOATBG.mjs.map → chunk-EF5BNM34.mjs.map} +0 -0
- /package/dist/{chunk-I4JPQECN.mjs.map → chunk-EXU7GWLC.mjs.map} +0 -0
- /package/dist/{chunk-7G6RR4HE.mjs.map → chunk-FXK6RQIN.mjs.map} +0 -0
- /package/dist/{chunk-JHIZ5HAI.mjs.map → chunk-NQVCZQ5T.mjs.map} +0 -0
- /package/dist/{chunk-VF6UPRKM.mjs.map → chunk-OF4SZTLL.mjs.map} +0 -0
- /package/dist/{chunk-QQZLIEXK.mjs.map → chunk-SJJNFYGQ.mjs.map} +0 -0
- /package/dist/{chunk-RN3ZRHI7.mjs.map → chunk-WOGURSAL.mjs.map} +0 -0
|
@@ -21,8 +21,8 @@ const defaultIcons: Record<Severity, JSX.Element> = {
|
|
|
21
21
|
[Severity.CRITICAL]: (
|
|
22
22
|
<svg
|
|
23
23
|
viewBox="0 0 24 24"
|
|
24
|
-
width="
|
|
25
|
-
height="
|
|
24
|
+
width="16"
|
|
25
|
+
height="16"
|
|
26
26
|
stroke="currentColor"
|
|
27
27
|
strokeWidth="2.5"
|
|
28
28
|
fill="none"
|
|
@@ -37,8 +37,8 @@ const defaultIcons: Record<Severity, JSX.Element> = {
|
|
|
37
37
|
[Severity.WARNING]: (
|
|
38
38
|
<svg
|
|
39
39
|
viewBox="0 0 24 24"
|
|
40
|
-
width="
|
|
41
|
-
height="
|
|
40
|
+
width="16"
|
|
41
|
+
height="16"
|
|
42
42
|
stroke="currentColor"
|
|
43
43
|
strokeWidth="2.5"
|
|
44
44
|
fill="none"
|
|
@@ -53,8 +53,8 @@ const defaultIcons: Record<Severity, JSX.Element> = {
|
|
|
53
53
|
[Severity.INFO]: (
|
|
54
54
|
<svg
|
|
55
55
|
viewBox="0 0 24 24"
|
|
56
|
-
width="
|
|
57
|
-
height="
|
|
56
|
+
width="16"
|
|
57
|
+
height="16"
|
|
58
58
|
stroke="currentColor"
|
|
59
59
|
strokeWidth="2.5"
|
|
60
60
|
fill="none"
|
|
@@ -79,23 +79,46 @@ export function UsageBanner({
|
|
|
79
79
|
return null;
|
|
80
80
|
}
|
|
81
81
|
|
|
82
|
-
//
|
|
82
|
+
// Enhanced message parsing to clean up technical details
|
|
83
83
|
const parseMessage = (rawMessage: string) => {
|
|
84
|
-
//
|
|
85
|
-
|
|
86
|
-
|
|
84
|
+
// console.log("Raw message:", rawMessage); // Debug
|
|
85
|
+
|
|
86
|
+
// Super aggressive cleaning - handle common error patterns first
|
|
87
|
+
if (
|
|
88
|
+
rawMessage.toLowerCase().includes("authentication") ||
|
|
89
|
+
rawMessage.toLowerCase().includes("api key")
|
|
90
|
+
) {
|
|
91
|
+
return "Authentication failed. Please check your API key.";
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
if (rawMessage.toLowerCase().includes("rate limit")) {
|
|
95
|
+
return "Rate limit exceeded. Please try again later.";
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
if (rawMessage.toLowerCase().includes("checkpointer")) {
|
|
99
|
+
return "Agent configuration error. Please check your setup.";
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// For any other error, extract just the main error type
|
|
103
|
+
let cleanMessage = rawMessage;
|
|
87
104
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
105
|
+
// Remove everything after the first " - " or ":" followed by technical details
|
|
106
|
+
cleanMessage = cleanMessage.split(" - ")[0];
|
|
107
|
+
cleanMessage = cleanMessage.split(": Error code")[0];
|
|
108
|
+
cleanMessage = cleanMessage.split(": 401")[0];
|
|
109
|
+
cleanMessage = cleanMessage.split(": 403")[0];
|
|
110
|
+
cleanMessage = cleanMessage.split(": 404")[0];
|
|
111
|
+
cleanMessage = cleanMessage.split(": 500")[0];
|
|
94
112
|
|
|
95
|
-
|
|
113
|
+
// Remove "See more" links
|
|
114
|
+
cleanMessage = cleanMessage.replace(/See more:.*$/g, "").trim();
|
|
115
|
+
|
|
116
|
+
// If still too technical, just show a generic message
|
|
117
|
+
if (cleanMessage.includes("{") || cleanMessage.includes("'") || cleanMessage.length > 60) {
|
|
118
|
+
return "Configuration error. Please check your setup.";
|
|
96
119
|
}
|
|
97
120
|
|
|
98
|
-
return
|
|
121
|
+
return cleanMessage || "An error occurred. Please check your configuration.";
|
|
99
122
|
};
|
|
100
123
|
|
|
101
124
|
const cleanMessage = parseMessage(message);
|
|
@@ -103,7 +126,7 @@ export function UsageBanner({
|
|
|
103
126
|
|
|
104
127
|
const themeConfigs = {
|
|
105
128
|
[Severity.INFO]: {
|
|
106
|
-
bg: "
|
|
129
|
+
bg: "rgba(239, 246, 255, 0.95)",
|
|
107
130
|
border: "#93c5fd",
|
|
108
131
|
text: "#1e40af",
|
|
109
132
|
icon: "#3b82f6",
|
|
@@ -111,7 +134,7 @@ export function UsageBanner({
|
|
|
111
134
|
primaryBtnHover: "#2563eb",
|
|
112
135
|
},
|
|
113
136
|
[Severity.WARNING]: {
|
|
114
|
-
bg: "
|
|
137
|
+
bg: "rgba(255, 251, 235, 0.95)",
|
|
115
138
|
border: "#fbbf24",
|
|
116
139
|
text: "#92400e",
|
|
117
140
|
icon: "#f59e0b",
|
|
@@ -119,7 +142,7 @@ export function UsageBanner({
|
|
|
119
142
|
primaryBtnHover: "#d97706",
|
|
120
143
|
},
|
|
121
144
|
[Severity.CRITICAL]: {
|
|
122
|
-
bg: "
|
|
145
|
+
bg: "rgba(254, 242, 242, 0.95)",
|
|
123
146
|
border: "#f87171",
|
|
124
147
|
text: "#991b1b",
|
|
125
148
|
icon: "#ef4444",
|
|
@@ -134,13 +157,13 @@ export function UsageBanner({
|
|
|
134
157
|
<div
|
|
135
158
|
style={{
|
|
136
159
|
position: "fixed",
|
|
137
|
-
bottom: "
|
|
160
|
+
bottom: "24px",
|
|
138
161
|
left: "50%",
|
|
139
162
|
transform: "translateX(-50%)",
|
|
140
|
-
|
|
141
|
-
|
|
163
|
+
width: "400px",
|
|
164
|
+
maxWidth: "90vw",
|
|
142
165
|
zIndex: 10000,
|
|
143
|
-
animation: "bannerSlideIn 0.
|
|
166
|
+
animation: "bannerSlideIn 0.3s cubic-bezier(0.16, 1, 0.3, 1)",
|
|
144
167
|
}}
|
|
145
168
|
>
|
|
146
169
|
<style>
|
|
@@ -148,28 +171,29 @@ export function UsageBanner({
|
|
|
148
171
|
@keyframes bannerSlideIn {
|
|
149
172
|
from {
|
|
150
173
|
opacity: 0;
|
|
151
|
-
transform: translateX(-50%) translateY(
|
|
174
|
+
transform: translateX(-50%) translateY(20px);
|
|
175
|
+
scale: 0.95;
|
|
152
176
|
}
|
|
153
177
|
to {
|
|
154
178
|
opacity: 1;
|
|
155
179
|
transform: translateX(-50%) translateY(0);
|
|
180
|
+
scale: 1;
|
|
156
181
|
}
|
|
157
182
|
}
|
|
158
183
|
`}
|
|
159
184
|
</style>
|
|
160
185
|
<div
|
|
161
186
|
style={{
|
|
162
|
-
|
|
163
|
-
alignItems: "flex-start",
|
|
164
|
-
gap: "14px",
|
|
165
|
-
borderRadius: "16px",
|
|
187
|
+
borderRadius: "12px",
|
|
166
188
|
border: `1px solid ${themeConfig.border}`,
|
|
167
189
|
background: themeConfig.bg,
|
|
168
|
-
padding: "
|
|
169
|
-
boxShadow: "0
|
|
190
|
+
padding: "14px",
|
|
191
|
+
boxShadow: "0 8px 32px rgba(0, 0, 0, 0.12), 0 2px 8px rgba(0, 0, 0, 0.08)",
|
|
170
192
|
position: "relative",
|
|
171
|
-
backdropFilter: "blur(
|
|
172
|
-
WebkitBackdropFilter: "blur(
|
|
193
|
+
backdropFilter: "blur(12px)",
|
|
194
|
+
WebkitBackdropFilter: "blur(12px)",
|
|
195
|
+
boxSizing: "border-box",
|
|
196
|
+
overflow: "hidden",
|
|
173
197
|
}}
|
|
174
198
|
>
|
|
175
199
|
{/* Close button */}
|
|
@@ -178,144 +202,117 @@ export function UsageBanner({
|
|
|
178
202
|
onClick={onClose}
|
|
179
203
|
style={{
|
|
180
204
|
position: "absolute",
|
|
181
|
-
top: "
|
|
182
|
-
right: "
|
|
183
|
-
background: "rgba(255, 255, 255, 0.
|
|
205
|
+
top: "8px",
|
|
206
|
+
right: "8px",
|
|
207
|
+
background: "rgba(255, 255, 255, 0.9)",
|
|
184
208
|
border: "none",
|
|
185
209
|
color: themeConfig.text,
|
|
186
210
|
cursor: "pointer",
|
|
187
|
-
fontSize: "
|
|
211
|
+
fontSize: "16px",
|
|
188
212
|
lineHeight: "1",
|
|
189
|
-
padding: "
|
|
190
|
-
borderRadius: "
|
|
191
|
-
|
|
192
|
-
|
|
213
|
+
padding: "4px",
|
|
214
|
+
borderRadius: "4px",
|
|
215
|
+
width: "20px",
|
|
216
|
+
height: "20px",
|
|
193
217
|
display: "flex",
|
|
194
218
|
alignItems: "center",
|
|
195
219
|
justifyContent: "center",
|
|
196
|
-
width: "28px",
|
|
197
|
-
height: "28px",
|
|
198
220
|
}}
|
|
199
221
|
title="Close"
|
|
200
|
-
onMouseOver={(e) => {
|
|
201
|
-
e.currentTarget.style.opacity = "1";
|
|
202
|
-
e.currentTarget.style.background = "rgba(255, 255, 255, 1)";
|
|
203
|
-
e.currentTarget.style.transform = "scale(1.05)";
|
|
204
|
-
}}
|
|
205
|
-
onMouseOut={(e) => {
|
|
206
|
-
e.currentTarget.style.opacity = "0.7";
|
|
207
|
-
e.currentTarget.style.background = "rgba(255, 255, 255, 0.8)";
|
|
208
|
-
e.currentTarget.style.transform = "scale(1)";
|
|
209
|
-
}}
|
|
210
222
|
>
|
|
211
223
|
×
|
|
212
224
|
</button>
|
|
213
225
|
)}
|
|
214
226
|
|
|
215
|
-
{/*
|
|
227
|
+
{/* Message */}
|
|
216
228
|
<div
|
|
217
229
|
style={{
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
230
|
+
fontSize: "14px",
|
|
231
|
+
fontWeight: 500,
|
|
232
|
+
color: themeConfig.text,
|
|
233
|
+
lineHeight: "1.4",
|
|
234
|
+
fontFamily: "-apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif",
|
|
235
|
+
paddingRight: onClose ? "30px" : "0",
|
|
236
|
+
marginBottom: actions ? "12px" : "0",
|
|
237
|
+
wordBreak: "break-word",
|
|
238
|
+
overflow: "hidden",
|
|
239
|
+
textOverflow: "ellipsis",
|
|
240
|
+
display: "-webkit-box",
|
|
241
|
+
WebkitLineClamp: 2,
|
|
242
|
+
WebkitBoxOrient: "vertical",
|
|
227
243
|
}}
|
|
228
244
|
>
|
|
229
|
-
{
|
|
245
|
+
{cleanMessage}
|
|
230
246
|
</div>
|
|
231
247
|
|
|
232
|
-
{/*
|
|
233
|
-
|
|
234
|
-
{/* Message */}
|
|
248
|
+
{/* Actions */}
|
|
249
|
+
{actions && (
|
|
235
250
|
<div
|
|
236
251
|
style={{
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
lineHeight: "1.5",
|
|
241
|
-
marginBottom: actions ? "12px" : "0",
|
|
242
|
-
fontFamily: "-apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif",
|
|
252
|
+
display: "flex",
|
|
253
|
+
gap: "8px",
|
|
254
|
+
flexWrap: "wrap",
|
|
243
255
|
}}
|
|
244
256
|
>
|
|
245
|
-
{
|
|
257
|
+
{actions.secondary && (
|
|
258
|
+
<button
|
|
259
|
+
onClick={actions.secondary.onClick}
|
|
260
|
+
style={{
|
|
261
|
+
borderRadius: "8px",
|
|
262
|
+
padding: "6px 12px",
|
|
263
|
+
fontSize: "13px",
|
|
264
|
+
fontWeight: 500,
|
|
265
|
+
color: themeConfig.text,
|
|
266
|
+
backgroundColor: "rgba(255, 255, 255, 0.9)",
|
|
267
|
+
border: `1px solid ${themeConfig.border}`,
|
|
268
|
+
cursor: "pointer",
|
|
269
|
+
transition: "all 0.2s ease",
|
|
270
|
+
fontFamily: "-apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif",
|
|
271
|
+
}}
|
|
272
|
+
onMouseOver={(e) => {
|
|
273
|
+
e.currentTarget.style.backgroundColor = "rgba(255, 255, 255, 1)";
|
|
274
|
+
e.currentTarget.style.transform = "translateY(-1px)";
|
|
275
|
+
}}
|
|
276
|
+
onMouseOut={(e) => {
|
|
277
|
+
e.currentTarget.style.backgroundColor = "rgba(255, 255, 255, 0.9)";
|
|
278
|
+
e.currentTarget.style.transform = "translateY(0)";
|
|
279
|
+
}}
|
|
280
|
+
>
|
|
281
|
+
{actions.secondary.label}
|
|
282
|
+
</button>
|
|
283
|
+
)}
|
|
284
|
+
{actions.primary && (
|
|
285
|
+
<button
|
|
286
|
+
onClick={actions.primary.onClick}
|
|
287
|
+
style={{
|
|
288
|
+
borderRadius: "8px",
|
|
289
|
+
padding: "6px 12px",
|
|
290
|
+
fontSize: "13px",
|
|
291
|
+
fontWeight: 600,
|
|
292
|
+
color: "#fff",
|
|
293
|
+
backgroundColor: themeConfig.primaryBtn,
|
|
294
|
+
border: "none",
|
|
295
|
+
cursor: "pointer",
|
|
296
|
+
transition: "all 0.2s ease",
|
|
297
|
+
boxShadow: "0 2px 8px rgba(0, 0, 0, 0.15)",
|
|
298
|
+
fontFamily: "-apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif",
|
|
299
|
+
}}
|
|
300
|
+
onMouseOver={(e) => {
|
|
301
|
+
e.currentTarget.style.backgroundColor = themeConfig.primaryBtnHover;
|
|
302
|
+
e.currentTarget.style.transform = "translateY(-1px)";
|
|
303
|
+
e.currentTarget.style.boxShadow = "0 4px 12px rgba(0, 0, 0, 0.2)";
|
|
304
|
+
}}
|
|
305
|
+
onMouseOut={(e) => {
|
|
306
|
+
e.currentTarget.style.backgroundColor = themeConfig.primaryBtn;
|
|
307
|
+
e.currentTarget.style.transform = "translateY(0)";
|
|
308
|
+
e.currentTarget.style.boxShadow = "0 2px 8px rgba(0, 0, 0, 0.15)";
|
|
309
|
+
}}
|
|
310
|
+
>
|
|
311
|
+
{actions.primary.label}
|
|
312
|
+
</button>
|
|
313
|
+
)}
|
|
246
314
|
</div>
|
|
247
|
-
|
|
248
|
-
{/* Actions */}
|
|
249
|
-
{actions && (
|
|
250
|
-
<div
|
|
251
|
-
style={{
|
|
252
|
-
display: "flex",
|
|
253
|
-
gap: "10px",
|
|
254
|
-
flexWrap: "wrap",
|
|
255
|
-
}}
|
|
256
|
-
>
|
|
257
|
-
{actions.secondary && (
|
|
258
|
-
<button
|
|
259
|
-
onClick={actions.secondary.onClick}
|
|
260
|
-
style={{
|
|
261
|
-
borderRadius: "10px",
|
|
262
|
-
padding: "8px 16px",
|
|
263
|
-
fontSize: "14px",
|
|
264
|
-
fontWeight: 500,
|
|
265
|
-
color: themeConfig.text,
|
|
266
|
-
backgroundColor: "rgba(255, 255, 255, 0.8)",
|
|
267
|
-
border: `1.5px solid ${themeConfig.border}`,
|
|
268
|
-
cursor: "pointer",
|
|
269
|
-
transition: "all 0.2s ease",
|
|
270
|
-
fontFamily: "-apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif",
|
|
271
|
-
}}
|
|
272
|
-
onMouseOver={(e) => {
|
|
273
|
-
e.currentTarget.style.backgroundColor = "rgba(255, 255, 255, 1)";
|
|
274
|
-
e.currentTarget.style.transform = "translateY(-1px)";
|
|
275
|
-
e.currentTarget.style.boxShadow = "0 4px 12px rgba(0, 0, 0, 0.15)";
|
|
276
|
-
}}
|
|
277
|
-
onMouseOut={(e) => {
|
|
278
|
-
e.currentTarget.style.backgroundColor = "rgba(255, 255, 255, 0.8)";
|
|
279
|
-
e.currentTarget.style.transform = "translateY(0)";
|
|
280
|
-
e.currentTarget.style.boxShadow = "none";
|
|
281
|
-
}}
|
|
282
|
-
>
|
|
283
|
-
{actions.secondary.label}
|
|
284
|
-
</button>
|
|
285
|
-
)}
|
|
286
|
-
{actions.primary && (
|
|
287
|
-
<button
|
|
288
|
-
onClick={actions.primary.onClick}
|
|
289
|
-
style={{
|
|
290
|
-
borderRadius: "10px",
|
|
291
|
-
padding: "8px 16px",
|
|
292
|
-
fontSize: "14px",
|
|
293
|
-
fontWeight: 600,
|
|
294
|
-
color: "#fff",
|
|
295
|
-
backgroundColor: themeConfig.primaryBtn,
|
|
296
|
-
border: "none",
|
|
297
|
-
cursor: "pointer",
|
|
298
|
-
transition: "all 0.2s ease",
|
|
299
|
-
boxShadow: "0 4px 12px rgba(0, 0, 0, 0.15)",
|
|
300
|
-
fontFamily: "-apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif",
|
|
301
|
-
}}
|
|
302
|
-
onMouseOver={(e) => {
|
|
303
|
-
e.currentTarget.style.backgroundColor = themeConfig.primaryBtnHover;
|
|
304
|
-
e.currentTarget.style.transform = "translateY(-1px)";
|
|
305
|
-
e.currentTarget.style.boxShadow = "0 6px 16px rgba(0, 0, 0, 0.2)";
|
|
306
|
-
}}
|
|
307
|
-
onMouseOut={(e) => {
|
|
308
|
-
e.currentTarget.style.backgroundColor = themeConfig.primaryBtn;
|
|
309
|
-
e.currentTarget.style.transform = "translateY(0)";
|
|
310
|
-
e.currentTarget.style.boxShadow = "0 4px 12px rgba(0, 0, 0, 0.15)";
|
|
311
|
-
}}
|
|
312
|
-
>
|
|
313
|
-
{actions.primary.label}
|
|
314
|
-
</button>
|
|
315
|
-
)}
|
|
316
|
-
</div>
|
|
317
|
-
)}
|
|
318
|
-
</div>
|
|
315
|
+
)}
|
|
319
316
|
</div>
|
|
320
317
|
</div>
|
|
321
318
|
);
|
package/src/hooks/use-chat.ts
CHANGED
|
@@ -5,6 +5,8 @@ import {
|
|
|
5
5
|
CoAgentStateRenderHandler,
|
|
6
6
|
randomId,
|
|
7
7
|
parseJson,
|
|
8
|
+
CopilotKitError,
|
|
9
|
+
CopilotKitErrorCode,
|
|
8
10
|
} from "@copilotkit/shared";
|
|
9
11
|
import {
|
|
10
12
|
Message,
|
|
@@ -39,6 +41,7 @@ import { AgentSession } from "../context/copilot-context";
|
|
|
39
41
|
import { useCopilotRuntimeClient } from "./use-copilot-runtime-client";
|
|
40
42
|
import { useCopilotContext } from "../context/copilot-context";
|
|
41
43
|
import { useAsyncCallback, useErrorToast } from "../components/error-boundary/error-utils";
|
|
44
|
+
import { useToast } from "../components/toast/toast-provider";
|
|
42
45
|
import {
|
|
43
46
|
LangGraphInterruptAction,
|
|
44
47
|
LangGraphInterruptActionSetter,
|
|
@@ -218,6 +221,41 @@ export function useChat(options: UseChatOptions): UseChatHelpers {
|
|
|
218
221
|
} = options;
|
|
219
222
|
const runChatCompletionRef = useRef<(previousMessages: Message[]) => Promise<Message[]>>();
|
|
220
223
|
const addErrorToast = useErrorToast();
|
|
224
|
+
const { setBannerError } = useToast();
|
|
225
|
+
|
|
226
|
+
// Get onTrace from context since it's not part of copilotConfig
|
|
227
|
+
const { onTrace } = useCopilotContext();
|
|
228
|
+
|
|
229
|
+
// Add tracing functionality to use-chat
|
|
230
|
+
const traceUIError = async (error: CopilotKitError, originalError?: any) => {
|
|
231
|
+
// Just check if onTrace and publicApiKey are defined
|
|
232
|
+
if (!onTrace || !copilotConfig?.publicApiKey) return;
|
|
233
|
+
|
|
234
|
+
try {
|
|
235
|
+
const traceEvent = {
|
|
236
|
+
type: "error" as const,
|
|
237
|
+
timestamp: Date.now(),
|
|
238
|
+
context: {
|
|
239
|
+
source: "ui" as const,
|
|
240
|
+
request: {
|
|
241
|
+
operation: "useChatCompletion",
|
|
242
|
+
url: copilotConfig.chatApiEndpoint,
|
|
243
|
+
startTime: Date.now(),
|
|
244
|
+
},
|
|
245
|
+
technical: {
|
|
246
|
+
environment: "browser",
|
|
247
|
+
userAgent: typeof navigator !== "undefined" ? navigator.userAgent : undefined,
|
|
248
|
+
stackTrace: originalError instanceof Error ? originalError.stack : undefined,
|
|
249
|
+
},
|
|
250
|
+
},
|
|
251
|
+
error,
|
|
252
|
+
};
|
|
253
|
+
|
|
254
|
+
await onTrace(traceEvent);
|
|
255
|
+
} catch (traceError) {
|
|
256
|
+
console.error("Error in use-chat onTrace handler:", traceError);
|
|
257
|
+
}
|
|
258
|
+
};
|
|
221
259
|
// We need to keep a ref of coagent states and session because of renderAndWait - making sure
|
|
222
260
|
// the latest state is sent to the API
|
|
223
261
|
// This is a workaround and needs to be addressed in the future
|
|
@@ -453,29 +491,91 @@ export function useChat(options: UseChatOptions): UseChatHelpers {
|
|
|
453
491
|
filterAdjacentAgentStateMessages(rawMessagesResponse),
|
|
454
492
|
);
|
|
455
493
|
|
|
456
|
-
if (messages.length === 0) {
|
|
457
|
-
continue;
|
|
458
|
-
}
|
|
459
|
-
|
|
460
494
|
newMessages = [];
|
|
461
495
|
|
|
496
|
+
// Handle error statuses BEFORE checking if there are messages
|
|
497
|
+
// (errors can come in chunks with no messages)
|
|
498
|
+
|
|
462
499
|
// request failed, display error message and quit
|
|
463
500
|
if (
|
|
464
501
|
value.generateCopilotResponse.status?.__typename === "FailedResponseStatus" &&
|
|
465
502
|
value.generateCopilotResponse.status.reason === "GUARDRAILS_VALIDATION_FAILED"
|
|
466
503
|
) {
|
|
504
|
+
const guardrailsReason =
|
|
505
|
+
value.generateCopilotResponse.status.details?.guardrailsReason || "";
|
|
506
|
+
|
|
467
507
|
newMessages = [
|
|
468
508
|
new TextMessage({
|
|
469
509
|
role: MessageRole.Assistant,
|
|
470
|
-
content:
|
|
510
|
+
content: guardrailsReason,
|
|
471
511
|
}),
|
|
472
512
|
];
|
|
513
|
+
|
|
514
|
+
// Trace guardrails validation failure
|
|
515
|
+
const guardrailsError = new CopilotKitError({
|
|
516
|
+
message: `Guardrails validation failed: ${guardrailsReason}`,
|
|
517
|
+
code: CopilotKitErrorCode.MISUSE,
|
|
518
|
+
});
|
|
519
|
+
await traceUIError(guardrailsError, {
|
|
520
|
+
statusReason: value.generateCopilotResponse.status.reason,
|
|
521
|
+
statusDetails: value.generateCopilotResponse.status.details,
|
|
522
|
+
});
|
|
523
|
+
|
|
473
524
|
setMessages([...previousMessages, ...newMessages]);
|
|
474
525
|
break;
|
|
475
526
|
}
|
|
476
527
|
|
|
528
|
+
// Handle UNKNOWN_ERROR failures (like authentication errors) by routing to banner error system
|
|
529
|
+
if (
|
|
530
|
+
value.generateCopilotResponse.status?.__typename === "FailedResponseStatus" &&
|
|
531
|
+
value.generateCopilotResponse.status.reason === "UNKNOWN_ERROR"
|
|
532
|
+
) {
|
|
533
|
+
const errorMessage =
|
|
534
|
+
value.generateCopilotResponse.status.details?.description ||
|
|
535
|
+
"An unknown error occurred";
|
|
536
|
+
|
|
537
|
+
// Try to extract original error information from the response details
|
|
538
|
+
const statusDetails = value.generateCopilotResponse.status.details;
|
|
539
|
+
const originalError = statusDetails?.originalError || statusDetails?.error;
|
|
540
|
+
|
|
541
|
+
// Extract structured error information if available (prioritize top-level over extensions)
|
|
542
|
+
const originalCode = originalError?.code || originalError?.extensions?.code;
|
|
543
|
+
const originalSeverity = originalError?.severity || originalError?.extensions?.severity;
|
|
544
|
+
const originalVisibility =
|
|
545
|
+
originalError?.visibility || originalError?.extensions?.visibility;
|
|
546
|
+
|
|
547
|
+
// Use the original error code if available, otherwise default to NETWORK_ERROR
|
|
548
|
+
let errorCode = CopilotKitErrorCode.NETWORK_ERROR;
|
|
549
|
+
if (originalCode && Object.values(CopilotKitErrorCode).includes(originalCode)) {
|
|
550
|
+
errorCode = originalCode;
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
// Create a structured CopilotKitError preserving original error information
|
|
554
|
+
const structuredError = new CopilotKitError({
|
|
555
|
+
message: errorMessage,
|
|
556
|
+
code: errorCode,
|
|
557
|
+
severity: originalSeverity,
|
|
558
|
+
visibility: originalVisibility,
|
|
559
|
+
});
|
|
560
|
+
|
|
561
|
+
// Display the error in the banner
|
|
562
|
+
setBannerError(structuredError);
|
|
563
|
+
|
|
564
|
+
// Trace the error for debugging/observability
|
|
565
|
+
await traceUIError(structuredError, {
|
|
566
|
+
statusReason: value.generateCopilotResponse.status.reason,
|
|
567
|
+
statusDetails: value.generateCopilotResponse.status.details,
|
|
568
|
+
originalErrorCode: originalCode,
|
|
569
|
+
preservedStructure: !!originalCode,
|
|
570
|
+
});
|
|
571
|
+
|
|
572
|
+
// Stop processing and break from the loop
|
|
573
|
+
setIsLoading(false);
|
|
574
|
+
break;
|
|
575
|
+
}
|
|
576
|
+
|
|
477
577
|
// add messages to the chat
|
|
478
|
-
else {
|
|
578
|
+
else if (messages.length > 0) {
|
|
479
579
|
newMessages = [...messages];
|
|
480
580
|
|
|
481
581
|
for (const message of messages) {
|
package/src/hooks/use-coagent.ts
CHANGED
|
@@ -278,6 +278,11 @@ export function useCoAgent<T = any>(options: UseCoagentOptions<T>): UseCoagentRe
|
|
|
278
278
|
agentName: name,
|
|
279
279
|
});
|
|
280
280
|
|
|
281
|
+
// Runtime client handles errors automatically via handleGQLErrors
|
|
282
|
+
if (result.error) {
|
|
283
|
+
return; // Don't process data on error
|
|
284
|
+
}
|
|
285
|
+
|
|
281
286
|
const newState = result.data?.loadAgentState?.state;
|
|
282
287
|
if (newState === lastLoadedState.current) return;
|
|
283
288
|
|
|
@@ -32,6 +32,7 @@ export const useCopilotRuntimeClient = (options: CopilotRuntimeClientHookOptions
|
|
|
32
32
|
|
|
33
33
|
// Helper function to trace UI errors
|
|
34
34
|
const traceUIError = async (error: CopilotKitError, originalError?: any) => {
|
|
35
|
+
// Just check if onTrace and publicApiKey are defined
|
|
35
36
|
if (!onTrace || !runtimeOptions.publicApiKey) return;
|
|
36
37
|
|
|
37
38
|
try {
|
|
@@ -46,14 +47,13 @@ export const useCopilotRuntimeClient = (options: CopilotRuntimeClientHookOptions
|
|
|
46
47
|
startTime: Date.now(),
|
|
47
48
|
},
|
|
48
49
|
technical: {
|
|
49
|
-
environment:
|
|
50
|
+
environment: "browser",
|
|
50
51
|
userAgent: typeof navigator !== "undefined" ? navigator.userAgent : undefined,
|
|
51
52
|
stackTrace: originalError instanceof Error ? originalError.stack : undefined,
|
|
52
53
|
},
|
|
53
54
|
},
|
|
54
55
|
error,
|
|
55
56
|
};
|
|
56
|
-
|
|
57
57
|
await onTrace(traceEvent);
|
|
58
58
|
} catch (traceError) {
|
|
59
59
|
console.error("Error in onTrace handler:", traceError);
|
|
@@ -79,7 +79,6 @@ export const useCopilotRuntimeClient = (options: CopilotRuntimeClientHookOptions
|
|
|
79
79
|
return;
|
|
80
80
|
}
|
|
81
81
|
|
|
82
|
-
// Respect showDevConsole setting for ALL errors
|
|
83
82
|
if (!isDev) {
|
|
84
83
|
console.error("CopilotKit Error (hidden in production):", gqlError.message);
|
|
85
84
|
return;
|
|
@@ -148,42 +147,6 @@ export const useCopilotRuntimeClient = (options: CopilotRuntimeClientHookOptions
|
|
|
148
147
|
return runtimeClient;
|
|
149
148
|
};
|
|
150
149
|
|
|
151
|
-
// Helper to determine if error should show as banner based on structured error system
|
|
152
|
-
function shouldShowAsBanner(gqlError: GraphQLError): boolean {
|
|
153
|
-
const extensions = gqlError.extensions;
|
|
154
|
-
if (!extensions) return false;
|
|
155
|
-
|
|
156
|
-
// Primary: Check error code and use structured config
|
|
157
|
-
const code = extensions.code as CopilotKitErrorCode;
|
|
158
|
-
if (code && ERROR_CONFIG[code]?.visibility === ErrorVisibility.BANNER) {
|
|
159
|
-
return true;
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
// Fallback: Check for API key errors which should always be banners
|
|
163
|
-
const errorMessage = gqlError.message.toLowerCase();
|
|
164
|
-
if (
|
|
165
|
-
errorMessage.includes("api key") ||
|
|
166
|
-
errorMessage.includes("401") ||
|
|
167
|
-
errorMessage.includes("unauthorized") ||
|
|
168
|
-
errorMessage.includes("authentication") ||
|
|
169
|
-
errorMessage.includes("incorrect api key")
|
|
170
|
-
) {
|
|
171
|
-
return true;
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
// Legacy: Check by stack trace for discovery errors (for backward compatibility)
|
|
175
|
-
const originalError = extensions.originalError as any;
|
|
176
|
-
if (originalError?.stack) {
|
|
177
|
-
return (
|
|
178
|
-
originalError.stack.includes("CopilotApiDiscoveryError") ||
|
|
179
|
-
originalError.stack.includes("CopilotKitRemoteEndpointDiscoveryError") ||
|
|
180
|
-
originalError.stack.includes("CopilotKitAgentDiscoveryError")
|
|
181
|
-
);
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
return false;
|
|
185
|
-
}
|
|
186
|
-
|
|
187
150
|
// Create appropriate structured error from GraphQL error
|
|
188
151
|
function createStructuredError(gqlError: GraphQLError): CopilotKitError | null {
|
|
189
152
|
const extensions = gqlError.extensions;
|
package/tsconfig.json
CHANGED
|
@@ -1,12 +1,5 @@
|
|
|
1
1
|
{
|
|
2
2
|
"extends": "../../utilities/tsconfig/react-library.json",
|
|
3
3
|
"include": ["."],
|
|
4
|
-
"exclude": [
|
|
5
|
-
"dist",
|
|
6
|
-
"build",
|
|
7
|
-
"node_modules",
|
|
8
|
-
"**/*.test.ts",
|
|
9
|
-
"**/*.test.tsx",
|
|
10
|
-
"**/__tests__/*"
|
|
11
|
-
]
|
|
4
|
+
"exclude": ["dist", "build", "node_modules", "**/*.test.ts", "**/*.test.tsx", "**/__tests__/*"]
|
|
12
5
|
}
|