@copilotkit/react-core 1.9.2-next.2 → 1.9.2-next.21

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 (170) hide show
  1. package/CHANGELOG.md +162 -0
  2. package/dist/{chunk-UHQMV2CE.mjs → chunk-36MGCCPZ.mjs} +2 -2
  3. package/dist/{chunk-CCESTGAM.mjs → chunk-3OQM3NEK.mjs} +2 -2
  4. package/dist/{chunk-OUSWPVDT.mjs → chunk-4URMLOBR.mjs} +4 -4
  5. package/dist/chunk-57K2ZJ5F.mjs +348 -0
  6. package/dist/chunk-57K2ZJ5F.mjs.map +1 -0
  7. package/dist/{chunk-LZDDYZEY.mjs → chunk-5BSUSFHM.mjs} +2 -2
  8. package/dist/{chunk-C6F6EQNA.mjs → chunk-BVK7PLK6.mjs} +2 -2
  9. package/dist/{chunk-CMKIDDQL.mjs → chunk-DDIBJUWK.mjs} +11 -8
  10. package/dist/{chunk-CMKIDDQL.mjs.map → chunk-DDIBJUWK.mjs.map} +1 -1
  11. package/dist/{chunk-NNSXCFQO.mjs → chunk-DGON3GZX.mjs} +42 -8
  12. package/dist/chunk-DGON3GZX.mjs.map +1 -0
  13. package/dist/{chunk-6KGEF242.mjs → chunk-DKZTPL66.mjs} +3 -2
  14. package/dist/chunk-DKZTPL66.mjs.map +1 -0
  15. package/dist/{chunk-LDACFA2B.mjs → chunk-FN3UA2ZE.mjs} +3 -3
  16. package/dist/{chunk-RUY6MLHA.mjs → chunk-JWAXDYOW.mjs} +36 -6
  17. package/dist/chunk-JWAXDYOW.mjs.map +1 -0
  18. package/dist/{chunk-2FW7HH6W.mjs → chunk-KIXKBJUV.mjs} +3 -3
  19. package/dist/{chunk-MGIXEJWG.mjs → chunk-MTAJI7HV.mjs} +181 -68
  20. package/dist/chunk-MTAJI7HV.mjs.map +1 -0
  21. package/dist/{chunk-L6QAOAE4.mjs → chunk-N2M65NJ2.mjs} +69 -25
  22. package/dist/chunk-N2M65NJ2.mjs.map +1 -0
  23. package/dist/{chunk-T42PN5VN.mjs → chunk-NJA5ZLAZ.mjs} +29 -10
  24. package/dist/chunk-NJA5ZLAZ.mjs.map +1 -0
  25. package/dist/{chunk-4I7PLQF7.mjs → chunk-QKEH3O4S.mjs} +5 -5
  26. package/dist/{chunk-FRZZPPIV.mjs → chunk-RAQK4M64.mjs} +2 -2
  27. package/dist/{chunk-QQZLIEXK.mjs → chunk-SJJNFYGQ.mjs} +3 -3
  28. package/dist/{chunk-Q5D5XQFA.mjs → chunk-VDADWRS3.mjs} +2 -2
  29. package/dist/chunk-YAF2LATQ.mjs +310 -0
  30. package/dist/chunk-YAF2LATQ.mjs.map +1 -0
  31. package/dist/components/copilot-provider/copilot-messages.js +40 -5
  32. package/dist/components/copilot-provider/copilot-messages.js.map +1 -1
  33. package/dist/components/copilot-provider/copilot-messages.mjs +3 -3
  34. package/dist/components/copilot-provider/copilotkit-props.d.ts +27 -3
  35. package/dist/components/copilot-provider/copilotkit-props.js.map +1 -1
  36. package/dist/components/copilot-provider/copilotkit.d.ts +1 -1
  37. package/dist/components/copilot-provider/copilotkit.js +385 -254
  38. package/dist/components/copilot-provider/copilotkit.js.map +1 -1
  39. package/dist/components/copilot-provider/copilotkit.mjs +10 -10
  40. package/dist/components/copilot-provider/index.d.ts +1 -1
  41. package/dist/components/copilot-provider/index.js +385 -254
  42. package/dist/components/copilot-provider/index.js.map +1 -1
  43. package/dist/components/copilot-provider/index.mjs +10 -10
  44. package/dist/components/error-boundary/error-boundary.js +135 -146
  45. package/dist/components/error-boundary/error-boundary.js.map +1 -1
  46. package/dist/components/error-boundary/error-boundary.mjs +4 -4
  47. package/dist/components/error-boundary/error-utils.js.map +1 -1
  48. package/dist/components/error-boundary/error-utils.mjs +2 -2
  49. package/dist/components/index.d.ts +1 -1
  50. package/dist/components/index.js +385 -254
  51. package/dist/components/index.js.map +1 -1
  52. package/dist/components/index.mjs +10 -10
  53. package/dist/components/toast/toast-provider.js +118 -85
  54. package/dist/components/toast/toast-provider.js.map +1 -1
  55. package/dist/components/toast/toast-provider.mjs +1 -1
  56. package/dist/components/usage-banner.js +135 -146
  57. package/dist/components/usage-banner.js.map +1 -1
  58. package/dist/components/usage-banner.mjs +1 -1
  59. package/dist/context/copilot-context.d.ts +1 -1
  60. package/dist/context/copilot-context.js +2 -1
  61. package/dist/context/copilot-context.js.map +1 -1
  62. package/dist/context/copilot-context.mjs +1 -1
  63. package/dist/context/index.d.ts +1 -1
  64. package/dist/context/index.js +2 -1
  65. package/dist/context/index.js.map +1 -1
  66. package/dist/context/index.mjs +1 -1
  67. package/dist/{copilot-context-f9b2b4c3.d.ts → copilot-context-3ab4fdf5.d.ts} +6 -2
  68. package/dist/hooks/index.d.ts +1 -1
  69. package/dist/hooks/index.js +232 -71
  70. package/dist/hooks/index.js.map +1 -1
  71. package/dist/hooks/index.mjs +32 -32
  72. package/dist/hooks/use-chat.d.ts +1 -1
  73. package/dist/hooks/use-chat.js +295 -156
  74. package/dist/hooks/use-chat.js.map +1 -1
  75. package/dist/hooks/use-chat.mjs +6 -6
  76. package/dist/hooks/use-coagent-state-render.js +2 -1
  77. package/dist/hooks/use-coagent-state-render.js.map +1 -1
  78. package/dist/hooks/use-coagent-state-render.mjs +3 -3
  79. package/dist/hooks/use-coagent.d.ts +1 -1
  80. package/dist/hooks/use-coagent.js +207 -65
  81. package/dist/hooks/use-coagent.js.map +1 -1
  82. package/dist/hooks/use-coagent.mjs +14 -14
  83. package/dist/hooks/use-copilot-action.js +27 -7
  84. package/dist/hooks/use-copilot-action.js.map +1 -1
  85. package/dist/hooks/use-copilot-action.mjs +4 -4
  86. package/dist/hooks/use-copilot-additional-instructions.js +2 -1
  87. package/dist/hooks/use-copilot-additional-instructions.js.map +1 -1
  88. package/dist/hooks/use-copilot-additional-instructions.mjs +2 -2
  89. package/dist/hooks/use-copilot-authenticated-action.js +27 -7
  90. package/dist/hooks/use-copilot-authenticated-action.js.map +1 -1
  91. package/dist/hooks/use-copilot-authenticated-action.mjs +5 -5
  92. package/dist/hooks/use-copilot-chat.d.ts +1 -1
  93. package/dist/hooks/use-copilot-chat.js +204 -65
  94. package/dist/hooks/use-copilot-chat.js.map +1 -1
  95. package/dist/hooks/use-copilot-chat.mjs +13 -13
  96. package/dist/hooks/use-copilot-readable.js +2 -1
  97. package/dist/hooks/use-copilot-readable.js.map +1 -1
  98. package/dist/hooks/use-copilot-readable.mjs +2 -2
  99. package/dist/hooks/use-copilot-runtime-client.d.ts +2 -0
  100. package/dist/hooks/use-copilot-runtime-client.js +52 -2
  101. package/dist/hooks/use-copilot-runtime-client.js.map +1 -1
  102. package/dist/hooks/use-copilot-runtime-client.mjs +2 -2
  103. package/dist/hooks/use-langgraph-interrupt-render.js +2 -1
  104. package/dist/hooks/use-langgraph-interrupt-render.js.map +1 -1
  105. package/dist/hooks/use-langgraph-interrupt-render.mjs +2 -2
  106. package/dist/hooks/use-langgraph-interrupt.d.ts +1 -1
  107. package/dist/hooks/use-langgraph-interrupt.js +204 -65
  108. package/dist/hooks/use-langgraph-interrupt.js.map +1 -1
  109. package/dist/hooks/use-langgraph-interrupt.mjs +14 -14
  110. package/dist/hooks/use-make-copilot-document-readable.js +2 -1
  111. package/dist/hooks/use-make-copilot-document-readable.js.map +1 -1
  112. package/dist/hooks/use-make-copilot-document-readable.mjs +2 -2
  113. package/dist/index.d.ts +1 -1
  114. package/dist/index.js +582 -321
  115. package/dist/index.js.map +1 -1
  116. package/dist/index.mjs +33 -33
  117. package/dist/lib/copilot-task.d.ts +1 -1
  118. package/dist/lib/copilot-task.js.map +1 -1
  119. package/dist/lib/copilot-task.mjs +11 -11
  120. package/dist/lib/index.d.ts +1 -1
  121. package/dist/lib/index.js.map +1 -1
  122. package/dist/lib/index.mjs +11 -11
  123. package/dist/types/interrupt-action.d.ts +1 -1
  124. package/dist/utils/extract.d.ts +1 -1
  125. package/dist/utils/extract.js.map +1 -1
  126. package/dist/utils/extract.mjs +10 -10
  127. package/dist/utils/index.d.ts +1 -1
  128. package/dist/utils/index.js.map +1 -1
  129. package/dist/utils/index.mjs +10 -10
  130. package/jest.config.js +7 -3
  131. package/package.json +4 -3
  132. package/src/components/copilot-provider/__tests__/copilotkit-error.test.tsx +75 -0
  133. package/src/components/copilot-provider/copilot-messages.tsx +47 -6
  134. package/src/components/copilot-provider/copilotkit-props.tsx +27 -1
  135. package/src/components/copilot-provider/copilotkit.tsx +64 -18
  136. package/src/components/toast/toast-provider.tsx +49 -24
  137. package/src/components/usage-banner.tsx +144 -147
  138. package/src/context/copilot-context.tsx +8 -2
  139. package/src/hooks/use-chat.ts +247 -61
  140. package/src/hooks/use-coagent.ts +5 -0
  141. package/src/hooks/use-copilot-action.ts +51 -9
  142. package/src/hooks/use-copilot-runtime-client.ts +41 -40
  143. package/tsconfig.json +4 -8
  144. package/tsup.config.ts +6 -6
  145. package/dist/chunk-6KGEF242.mjs.map +0 -1
  146. package/dist/chunk-HD2GE3DK.mjs +0 -359
  147. package/dist/chunk-HD2GE3DK.mjs.map +0 -1
  148. package/dist/chunk-L6QAOAE4.mjs.map +0 -1
  149. package/dist/chunk-MGIXEJWG.mjs.map +0 -1
  150. package/dist/chunk-NNSXCFQO.mjs.map +0 -1
  151. package/dist/chunk-RUY6MLHA.mjs.map +0 -1
  152. package/dist/chunk-T42PN5VN.mjs.map +0 -1
  153. package/dist/chunk-VRXANACV.mjs +0 -277
  154. package/dist/chunk-VRXANACV.mjs.map +0 -1
  155. package/dist/utils/utils.test.d.ts +0 -2
  156. package/dist/utils/utils.test.js +0 -9
  157. package/dist/utils/utils.test.js.map +0 -1
  158. package/dist/utils/utils.test.mjs +0 -7
  159. package/dist/utils/utils.test.mjs.map +0 -1
  160. /package/dist/{chunk-UHQMV2CE.mjs.map → chunk-36MGCCPZ.mjs.map} +0 -0
  161. /package/dist/{chunk-CCESTGAM.mjs.map → chunk-3OQM3NEK.mjs.map} +0 -0
  162. /package/dist/{chunk-OUSWPVDT.mjs.map → chunk-4URMLOBR.mjs.map} +0 -0
  163. /package/dist/{chunk-LZDDYZEY.mjs.map → chunk-5BSUSFHM.mjs.map} +0 -0
  164. /package/dist/{chunk-C6F6EQNA.mjs.map → chunk-BVK7PLK6.mjs.map} +0 -0
  165. /package/dist/{chunk-LDACFA2B.mjs.map → chunk-FN3UA2ZE.mjs.map} +0 -0
  166. /package/dist/{chunk-2FW7HH6W.mjs.map → chunk-KIXKBJUV.mjs.map} +0 -0
  167. /package/dist/{chunk-4I7PLQF7.mjs.map → chunk-QKEH3O4S.mjs.map} +0 -0
  168. /package/dist/{chunk-FRZZPPIV.mjs.map → chunk-RAQK4M64.mjs.map} +0 -0
  169. /package/dist/{chunk-QQZLIEXK.mjs.map → chunk-SJJNFYGQ.mjs.map} +0 -0
  170. /package/dist/{chunk-Q5D5XQFA.mjs.map → chunk-VDADWRS3.mjs.map} +0 -0
@@ -272,25 +272,29 @@ export function CopilotKitInternal(cpkProps: CopilotKitProps) {
272
272
  headers,
273
273
  credentials: copilotApiConfig.credentials,
274
274
  showDevConsole: props.showDevConsole ?? false,
275
+ onError: props.onError,
275
276
  });
276
277
 
277
278
  const [chatSuggestionConfiguration, setChatSuggestionConfiguration] = useState<{
278
279
  [key: string]: CopilotChatSuggestionConfiguration;
279
280
  }>({});
280
281
 
281
- const addChatSuggestionConfiguration = (
282
- id: string,
283
- suggestion: CopilotChatSuggestionConfiguration,
284
- ) => {
285
- setChatSuggestionConfiguration((prev) => ({ ...prev, [id]: suggestion }));
286
- };
282
+ const addChatSuggestionConfiguration = useCallback(
283
+ (id: string, suggestion: CopilotChatSuggestionConfiguration) => {
284
+ setChatSuggestionConfiguration((prev) => ({ ...prev, [id]: suggestion }));
285
+ },
286
+ [setChatSuggestionConfiguration],
287
+ );
287
288
 
288
- const removeChatSuggestionConfiguration = (id: string) => {
289
- setChatSuggestionConfiguration((prev) => {
290
- const { [id]: _, ...rest } = prev;
291
- return rest;
292
- });
293
- };
289
+ const removeChatSuggestionConfiguration = useCallback(
290
+ (id: string) => {
291
+ setChatSuggestionConfiguration((prev) => {
292
+ const { [id]: _, ...rest } = prev;
293
+ return rest;
294
+ });
295
+ },
296
+ [setChatSuggestionConfiguration],
297
+ );
294
298
 
295
299
  const [availableAgents, setAvailableAgents] = useState<Agent[]>([]);
296
300
  const [coagentStates, setCoagentStates] = useState<Record<string, CoagentState>>({});
@@ -386,6 +390,47 @@ export function CopilotKitInternal(cpkProps: CopilotKitProps) {
386
390
  setLangGraphInterruptAction(null);
387
391
  }, []);
388
392
 
393
+ const memoizedChildren = useMemo(() => children, [children]);
394
+
395
+ const agentLock = useMemo(() => props.agent ?? null, [props.agent]);
396
+
397
+ const forwardedParameters = useMemo(
398
+ () => props.forwardedParameters ?? {},
399
+ [props.forwardedParameters],
400
+ );
401
+
402
+ const updateExtensions = useCallback(
403
+ (newExtensions: SetStateAction<ExtensionsInput>) => {
404
+ setExtensions((prev: ExtensionsInput) => {
405
+ const resolved = typeof newExtensions === "function" ? newExtensions(prev) : newExtensions;
406
+ const isSameLength = Object.keys(resolved).length === Object.keys(prev).length;
407
+ const isEqual =
408
+ isSameLength &&
409
+ // @ts-ignore
410
+ Object.entries(resolved).every(([key, value]) => prev[key] === value);
411
+
412
+ return isEqual ? prev : resolved;
413
+ });
414
+ },
415
+ [setExtensions],
416
+ );
417
+
418
+ const updateAuthStates = useCallback(
419
+ (newAuthStates: SetStateAction<Record<string, AuthState>>) => {
420
+ setAuthStates((prev) => {
421
+ const resolved = typeof newAuthStates === "function" ? newAuthStates(prev) : newAuthStates;
422
+ const isSameLength = Object.keys(resolved).length === Object.keys(prev).length;
423
+ const isEqual =
424
+ isSameLength &&
425
+ // @ts-ignore
426
+ Object.entries(resolved).every(([key, value]) => prev[key] === value);
427
+
428
+ return isEqual ? prev : resolved;
429
+ });
430
+ },
431
+ [setAuthStates],
432
+ );
433
+
389
434
  return (
390
435
  <CopilotContext.Provider
391
436
  value={{
@@ -422,8 +467,8 @@ export function CopilotKitInternal(cpkProps: CopilotKitProps) {
422
467
  agentSession,
423
468
  setAgentSession,
424
469
  runtimeClient,
425
- forwardedParameters: props.forwardedParameters || {},
426
- agentLock: props.agent || null,
470
+ forwardedParameters,
471
+ agentLock,
427
472
  threadId: internalThreadId,
428
473
  setThreadId,
429
474
  runId,
@@ -432,15 +477,16 @@ export function CopilotKitInternal(cpkProps: CopilotKitProps) {
432
477
  availableAgents,
433
478
  authConfig_c: props.authConfig_c,
434
479
  authStates_c: authStates,
435
- setAuthStates_c: setAuthStates,
480
+ setAuthStates_c: updateAuthStates,
436
481
  extensions,
437
- setExtensions,
482
+ setExtensions: updateExtensions,
438
483
  langGraphInterruptAction,
439
484
  setLangGraphInterruptAction,
440
485
  removeLangGraphInterruptAction,
486
+ onError: props.onError,
441
487
  }}
442
488
  >
443
- <CopilotMessages>{children}</CopilotMessages>
489
+ <CopilotMessages>{memoizedChildren}</CopilotMessages>
444
490
  </CopilotContext.Provider>
445
491
  );
446
492
  }
@@ -448,7 +494,7 @@ export function CopilotKitInternal(cpkProps: CopilotKitProps) {
448
494
  export const defaultCopilotContextCategories = ["global"];
449
495
 
450
496
  function entryPointsToFunctionCallHandler(actions: FrontendAction<any>[]): FunctionCallHandler {
451
- return async ({ name, args }) => {
497
+ return async ({ name, args }: { name: string; args: Record<string, any> }) => {
452
498
  let actionsByFunctionName: Record<string, FrontendAction<any>> = {};
453
499
  for (let action of actions) {
454
500
  actionsByFunctionName[action.name] = action;
@@ -183,12 +183,14 @@ export function ToastProvider({
183
183
  border: `1px solid ${colors.border}`,
184
184
  borderLeft: `4px solid ${colors.border}`,
185
185
  borderRadius: "8px",
186
- padding: "10px 14px",
186
+ padding: "12px 16px",
187
187
  fontSize: "13px",
188
188
  boxShadow: "0 4px 12px rgba(0, 0, 0, 0.15)",
189
189
  backdropFilter: "blur(8px)",
190
- maxWidth: "500px",
191
- minWidth: "350px",
190
+ maxWidth: "min(90vw, 700px)",
191
+ width: "100%",
192
+ boxSizing: "border-box",
193
+ overflow: "hidden",
192
194
  }}
193
195
  >
194
196
  <div
@@ -199,7 +201,15 @@ export function ToastProvider({
199
201
  gap: "10px",
200
202
  }}
201
203
  >
202
- <div style={{ display: "flex", alignItems: "center", gap: "8px", flex: 1 }}>
204
+ <div
205
+ style={{
206
+ display: "flex",
207
+ alignItems: "center",
208
+ gap: "8px",
209
+ flex: 1,
210
+ minWidth: 0,
211
+ }}
212
+ >
203
213
  <div
204
214
  style={{
205
215
  width: "12px",
@@ -209,7 +219,15 @@ export function ToastProvider({
209
219
  flexShrink: 0,
210
220
  }}
211
221
  />
212
- <div style={{ display: "flex", alignItems: "center", gap: "10px", flex: 1 }}>
222
+ <div
223
+ style={{
224
+ display: "flex",
225
+ alignItems: "center",
226
+ gap: "10px",
227
+ flex: 1,
228
+ minWidth: 0,
229
+ }}
230
+ >
213
231
  <div
214
232
  style={{
215
233
  color: colors.text,
@@ -217,30 +235,37 @@ export function ToastProvider({
217
235
  fontWeight: "400",
218
236
  fontSize: "13px",
219
237
  flex: 1,
220
- wordWrap: "break-word",
238
+ wordBreak: "break-all",
221
239
  overflowWrap: "break-word",
222
- hyphens: "auto",
240
+ maxWidth: "550px",
241
+ overflow: "hidden",
242
+ display: "-webkit-box",
243
+ WebkitLineClamp: 10,
244
+ WebkitBoxOrient: "vertical",
223
245
  }}
224
246
  >
225
247
  {(() => {
226
- const message = bannerError.message;
227
- const markdownLinkRegex = /\[([^\]]+)\]\(([^)]+)\)/g;
228
- const plainUrlRegex = /(https?:\/\/[^\s)]+)/g;
229
-
230
- // Remove URLs and markdown links from the message, keep just the text
231
- let cleanMessage = message
232
- .replace(markdownLinkRegex, "") // Remove [text](url)
233
- .replace(plainUrlRegex, "") // Remove plain URLs
234
- .replace(/See more:\s*/g, "") // Remove "See more:" text
235
- .replace(/\s+/g, " ") // Clean up extra spaces
236
- .trim();
237
-
238
- // Truncate very long messages for better display
239
- if (cleanMessage.length > 120) {
240
- cleanMessage = cleanMessage.substring(0, 117) + "...";
248
+ let message = bannerError.message;
249
+
250
+ // Try to extract the useful message from JSON first
251
+ const jsonMatch = message.match(/'message':\s*'([^']+)'/);
252
+ if (jsonMatch) {
253
+ return jsonMatch[1]; // Return the actual error message
241
254
  }
242
255
 
243
- return cleanMessage;
256
+ // Strip technical garbage but keep the meaningful message
257
+ message = message.split(" - ")[0]; // Remove everything after " - {"
258
+ message = message.split(": Error code")[0]; // Remove ": Error code: 401"
259
+ message = message.replace(/:\s*\d{3}$/, ""); // Remove trailing ": 401"
260
+ message = message.replace(/See more:.*$/g, ""); // Remove "See more" links
261
+ message = message.trim();
262
+
263
+ // If it's still garbage (contains { or '), use fallback
264
+ // if (message.includes("{") || message.includes("'")) {
265
+ // return "Configuration error.... Please check your setup.";
266
+ // }
267
+
268
+ return message || "Configuration error occurred.";
244
269
  })()}
245
270
  </div>
246
271
 
@@ -262,7 +287,7 @@ export function ToastProvider({
262
287
  // Check for plain URLs
263
288
  const urlMatch = plainUrlRegex.exec(message);
264
289
  if (urlMatch) {
265
- url = urlMatch[0];
290
+ url = urlMatch[0].replace(/[.,;:'"]*$/, ""); // Remove trailing punctuation
266
291
  buttonText = "See More";
267
292
  }
268
293
  }
@@ -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="18"
25
- height="18"
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="18"
41
- height="18"
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="18"
57
- height="18"
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
- // Parse markdown links from message and clean it up
82
+ // Enhanced message parsing to clean up technical details
83
83
  const parseMessage = (rawMessage: string) => {
84
- // Extract markdown links: [text](url)
85
- const linkRegex = /\[([^\]]+)\]\(([^)]+)\)/g;
86
- const matches = Array.from(rawMessage.matchAll(linkRegex));
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
- if (matches.length > 0) {
89
- // Remove "See more:" and markdown links from the main message
90
- let cleanMessage = rawMessage
91
- .replace(/\.\s*See more:\s*\[([^\]]+)\]\(([^)]+)\)/g, ".")
92
- .replace(/See more:\s*\[([^\]]+)\]\(([^)]+)\)/g, "")
93
- .trim();
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
- return cleanMessage;
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 rawMessage;
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: "linear-gradient(135deg, #eff6ff 0%, #dbeafe 100%)",
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: "linear-gradient(135deg, #fffbeb 0%, #fef3c7 100%)",
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: "linear-gradient(135deg, #fef2f2 0%, #fecaca 100%)",
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: "20px",
160
+ bottom: "24px",
138
161
  left: "50%",
139
162
  transform: "translateX(-50%)",
140
- maxWidth: "min(95vw, 680px)",
141
- width: "100%",
163
+ width: "400px",
164
+ maxWidth: "90vw",
142
165
  zIndex: 10000,
143
- animation: "bannerSlideIn 0.4s cubic-bezier(0.16, 1, 0.3, 1)",
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(10px);
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
- display: "flex",
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: "18px 20px",
169
- boxShadow: "0 10px 25px -5px rgba(0, 0, 0, 0.1), 0 8px 10px -6px rgba(0, 0, 0, 0.1)",
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(10px)",
172
- WebkitBackdropFilter: "blur(10px)",
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: "12px",
182
- right: "12px",
183
- background: "rgba(255, 255, 255, 0.8)",
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: "18px",
211
+ fontSize: "16px",
188
212
  lineHeight: "1",
189
- padding: "6px",
190
- borderRadius: "8px",
191
- opacity: 0.7,
192
- transition: "all 0.2s ease",
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
- {/* Icon */}
227
+ {/* Message */}
216
228
  <div
217
229
  style={{
218
- color: themeConfig.icon,
219
- flexShrink: 0,
220
- marginTop: "1px",
221
- padding: "6px",
222
- borderRadius: "10px",
223
- background: "rgba(255, 255, 255, 0.7)",
224
- display: "flex",
225
- alignItems: "center",
226
- justifyContent: "center",
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
- {Icon}
245
+ {cleanMessage}
230
246
  </div>
231
247
 
232
- {/* Content */}
233
- <div style={{ flex: 1, paddingRight: onClose ? "40px" : "0" }}>
234
- {/* Message */}
248
+ {/* Actions */}
249
+ {actions && (
235
250
  <div
236
251
  style={{
237
- fontSize: "15px",
238
- fontWeight: 600,
239
- color: themeConfig.text,
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
- {cleanMessage}
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
  );