@copilotkit/react-core 1.9.1 → 1.9.2-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.
Files changed (180) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/dist/{chunk-B5UA5G3E.mjs → chunk-2FW7HH6W.mjs} +12 -8
  3. package/dist/chunk-2FW7HH6W.mjs.map +1 -0
  4. package/dist/{chunk-ERFA53MG.mjs → chunk-6KGEF242.mjs} +2 -2
  5. package/dist/chunk-6KGEF242.mjs.map +1 -0
  6. package/dist/{chunk-2J3SMMGW.mjs → chunk-C6F6EQNA.mjs} +2 -2
  7. package/dist/chunk-CCESTGAM.mjs +102 -0
  8. package/dist/chunk-CCESTGAM.mjs.map +1 -0
  9. package/dist/chunk-GFJW4RIM.mjs +9 -0
  10. package/dist/chunk-GFJW4RIM.mjs.map +1 -0
  11. package/dist/chunk-HD2GE3DK.mjs +359 -0
  12. package/dist/chunk-HD2GE3DK.mjs.map +1 -0
  13. package/dist/{chunk-74AJEJTV.mjs → chunk-HJP2RX5R.mjs} +11 -6
  14. package/dist/chunk-HJP2RX5R.mjs.map +1 -0
  15. package/dist/{chunk-EQ4XLLT4.mjs → chunk-LDACFA2B.mjs} +3 -3
  16. package/dist/{chunk-FGBRHBRR.mjs → chunk-LZDDYZEY.mjs} +2 -2
  17. package/dist/chunk-NNSXCFQO.mjs +154 -0
  18. package/dist/chunk-NNSXCFQO.mjs.map +1 -0
  19. package/dist/{chunk-WZAEVHLK.mjs → chunk-Q5D5XQFA.mjs} +2 -2
  20. package/dist/{chunk-534J55RX.mjs → chunk-QQZLIEXK.mjs} +9 -7
  21. package/dist/chunk-QQZLIEXK.mjs.map +1 -0
  22. package/dist/chunk-RUY6MLHA.mjs +119 -0
  23. package/dist/chunk-RUY6MLHA.mjs.map +1 -0
  24. package/dist/{chunk-MDIIRGJD.mjs → chunk-SGLWMQ2J.mjs} +25 -17
  25. package/dist/chunk-SGLWMQ2J.mjs.map +1 -0
  26. package/dist/{chunk-G27C5EFO.mjs → chunk-T42PN5VN.mjs} +7 -5
  27. package/dist/{chunk-G27C5EFO.mjs.map → chunk-T42PN5VN.mjs.map} +1 -1
  28. package/dist/{chunk-VQ3VTO26.mjs → chunk-UHQMV2CE.mjs} +2 -2
  29. package/dist/{chunk-4DVPRMVH.mjs → chunk-UIT6QMUJ.mjs} +7 -7
  30. package/dist/chunk-VRXANACV.mjs +277 -0
  31. package/dist/chunk-VRXANACV.mjs.map +1 -0
  32. package/dist/{chunk-2FLZLANO.mjs → chunk-XY5BN4HZ.mjs} +19 -12
  33. package/dist/chunk-XY5BN4HZ.mjs.map +1 -0
  34. package/dist/{chunk-7HDYPEWS.mjs → chunk-YDENFEKA.mjs} +2 -2
  35. package/dist/{chunk-4VWM6JNK.mjs → chunk-YZDRMIOM.mjs} +6 -6
  36. package/dist/components/copilot-provider/copilot-messages.js +105 -11
  37. package/dist/components/copilot-provider/copilot-messages.js.map +1 -1
  38. package/dist/components/copilot-provider/copilot-messages.mjs +4 -2
  39. package/dist/components/copilot-provider/copilotkit-props.d.ts +4 -3
  40. package/dist/components/copilot-provider/copilotkit-props.js.map +1 -1
  41. package/dist/components/copilot-provider/copilotkit.d.ts +1 -1
  42. package/dist/components/copilot-provider/copilotkit.js +863 -441
  43. package/dist/components/copilot-provider/copilotkit.js.map +1 -1
  44. package/dist/components/copilot-provider/copilotkit.mjs +10 -9
  45. package/dist/components/copilot-provider/index.d.ts +1 -1
  46. package/dist/components/copilot-provider/index.js +863 -441
  47. package/dist/components/copilot-provider/index.js.map +1 -1
  48. package/dist/components/copilot-provider/index.mjs +10 -9
  49. package/dist/components/error-boundary/error-boundary.js +320 -159
  50. package/dist/components/error-boundary/error-boundary.js.map +1 -1
  51. package/dist/components/error-boundary/error-boundary.mjs +4 -3
  52. package/dist/components/error-boundary/error-utils.js +2 -1
  53. package/dist/components/error-boundary/error-utils.js.map +1 -1
  54. package/dist/components/error-boundary/error-utils.mjs +2 -1
  55. package/dist/components/index.d.ts +1 -1
  56. package/dist/components/index.js +863 -441
  57. package/dist/components/index.js.map +1 -1
  58. package/dist/components/index.mjs +10 -9
  59. package/dist/components/toast/toast-provider.d.ts +9 -12
  60. package/dist/components/toast/toast-provider.js +218 -191
  61. package/dist/components/toast/toast-provider.js.map +1 -1
  62. package/dist/components/toast/toast-provider.mjs +1 -2
  63. package/dist/components/usage-banner.d.ts +3 -2
  64. package/dist/components/usage-banner.js +311 -153
  65. package/dist/components/usage-banner.js.map +1 -1
  66. package/dist/components/usage-banner.mjs +1 -1
  67. package/dist/context/copilot-context.d.ts +1 -1
  68. package/dist/context/copilot-context.js +1 -1
  69. package/dist/context/copilot-context.js.map +1 -1
  70. package/dist/context/copilot-context.mjs +1 -1
  71. package/dist/context/index.d.ts +1 -1
  72. package/dist/context/index.js +1 -1
  73. package/dist/context/index.js.map +1 -1
  74. package/dist/context/index.mjs +1 -1
  75. package/dist/{copilot-context-309906bb.d.ts → copilot-context-f9b2b4c3.d.ts} +1 -1
  76. package/dist/hooks/index.d.ts +1 -1
  77. package/dist/hooks/index.js +160 -75
  78. package/dist/hooks/index.js.map +1 -1
  79. package/dist/hooks/index.mjs +33 -32
  80. package/dist/hooks/use-chat.d.ts +1 -1
  81. package/dist/hooks/use-chat.js +243 -68
  82. package/dist/hooks/use-chat.js.map +1 -1
  83. package/dist/hooks/use-chat.mjs +6 -3
  84. package/dist/hooks/use-coagent-state-render.js +10 -5
  85. package/dist/hooks/use-coagent-state-render.js.map +1 -1
  86. package/dist/hooks/use-coagent-state-render.mjs +3 -4
  87. package/dist/hooks/use-coagent.d.ts +1 -1
  88. package/dist/hooks/use-coagent.js +148 -67
  89. package/dist/hooks/use-coagent.js.map +1 -1
  90. package/dist/hooks/use-coagent.mjs +14 -13
  91. package/dist/hooks/use-copilot-action.js +5 -4
  92. package/dist/hooks/use-copilot-action.js.map +1 -1
  93. package/dist/hooks/use-copilot-action.mjs +4 -3
  94. package/dist/hooks/use-copilot-additional-instructions.js +1 -1
  95. package/dist/hooks/use-copilot-additional-instructions.js.map +1 -1
  96. package/dist/hooks/use-copilot-additional-instructions.mjs +2 -2
  97. package/dist/hooks/use-copilot-authenticated-action.js +5 -4
  98. package/dist/hooks/use-copilot-authenticated-action.js.map +1 -1
  99. package/dist/hooks/use-copilot-authenticated-action.mjs +5 -4
  100. package/dist/hooks/use-copilot-chat.d.ts +1 -1
  101. package/dist/hooks/use-copilot-chat.js +138 -62
  102. package/dist/hooks/use-copilot-chat.js.map +1 -1
  103. package/dist/hooks/use-copilot-chat.mjs +13 -12
  104. package/dist/hooks/use-copilot-readable.js +1 -1
  105. package/dist/hooks/use-copilot-readable.js.map +1 -1
  106. package/dist/hooks/use-copilot-readable.mjs +2 -2
  107. package/dist/hooks/use-copilot-runtime-client.d.ts +5 -2
  108. package/dist/hooks/use-copilot-runtime-client.js +101 -128
  109. package/dist/hooks/use-copilot-runtime-client.js.map +1 -1
  110. package/dist/hooks/use-copilot-runtime-client.mjs +3 -3
  111. package/dist/hooks/use-langgraph-interrupt-render.js +1 -1
  112. package/dist/hooks/use-langgraph-interrupt-render.js.map +1 -1
  113. package/dist/hooks/use-langgraph-interrupt-render.mjs +2 -2
  114. package/dist/hooks/use-langgraph-interrupt.d.ts +1 -1
  115. package/dist/hooks/use-langgraph-interrupt.js +140 -64
  116. package/dist/hooks/use-langgraph-interrupt.js.map +1 -1
  117. package/dist/hooks/use-langgraph-interrupt.mjs +14 -13
  118. package/dist/hooks/use-make-copilot-document-readable.js +1 -1
  119. package/dist/hooks/use-make-copilot-document-readable.js.map +1 -1
  120. package/dist/hooks/use-make-copilot-document-readable.mjs +2 -2
  121. package/dist/index.d.ts +1 -1
  122. package/dist/index.js +913 -480
  123. package/dist/index.js.map +1 -1
  124. package/dist/index.mjs +35 -34
  125. package/dist/lib/copilot-task.d.ts +1 -1
  126. package/dist/lib/copilot-task.js.map +1 -1
  127. package/dist/lib/copilot-task.mjs +11 -10
  128. package/dist/lib/index.d.ts +1 -1
  129. package/dist/lib/index.js.map +1 -1
  130. package/dist/lib/index.mjs +11 -10
  131. package/dist/types/interrupt-action.d.ts +1 -1
  132. package/dist/utils/dev-console.d.ts +1 -1
  133. package/dist/utils/dev-console.js +1 -10
  134. package/dist/utils/dev-console.js.map +1 -1
  135. package/dist/utils/dev-console.mjs +1 -1
  136. package/dist/utils/extract.d.ts +1 -1
  137. package/dist/utils/extract.js.map +1 -1
  138. package/dist/utils/extract.mjs +10 -9
  139. package/dist/utils/index.d.ts +1 -1
  140. package/dist/utils/index.js +7 -14
  141. package/dist/utils/index.js.map +1 -1
  142. package/dist/utils/index.mjs +12 -11
  143. package/package.json +3 -3
  144. package/src/components/copilot-provider/copilot-messages.tsx +163 -4
  145. package/src/components/copilot-provider/copilotkit-props.tsx +3 -2
  146. package/src/components/copilot-provider/copilotkit.tsx +8 -2
  147. package/src/components/error-boundary/error-boundary.tsx +6 -5
  148. package/src/components/error-boundary/error-utils.tsx +1 -1
  149. package/src/components/toast/toast-provider.tsx +260 -93
  150. package/src/components/usage-banner.tsx +311 -131
  151. package/src/context/copilot-context.tsx +2 -2
  152. package/src/hooks/use-chat.ts +4 -0
  153. package/src/hooks/use-coagent-state-render.ts +9 -3
  154. package/src/hooks/use-coagent.ts +10 -3
  155. package/src/hooks/use-copilot-runtime-client.ts +153 -12
  156. package/src/utils/dev-console.ts +2 -17
  157. package/dist/chunk-22ENANUU.mjs +0 -250
  158. package/dist/chunk-22ENANUU.mjs.map +0 -1
  159. package/dist/chunk-2FLZLANO.mjs.map +0 -1
  160. package/dist/chunk-534J55RX.mjs.map +0 -1
  161. package/dist/chunk-6PK72HMH.mjs +0 -63
  162. package/dist/chunk-6PK72HMH.mjs.map +0 -1
  163. package/dist/chunk-74AJEJTV.mjs.map +0 -1
  164. package/dist/chunk-B5UA5G3E.mjs.map +0 -1
  165. package/dist/chunk-BKTARDXX.mjs +0 -40
  166. package/dist/chunk-BKTARDXX.mjs.map +0 -1
  167. package/dist/chunk-D34OH4VN.mjs +0 -201
  168. package/dist/chunk-D34OH4VN.mjs.map +0 -1
  169. package/dist/chunk-ERFA53MG.mjs.map +0 -1
  170. package/dist/chunk-MDIIRGJD.mjs.map +0 -1
  171. package/dist/chunk-MLAS4QUR.mjs +0 -18
  172. package/dist/chunk-MLAS4QUR.mjs.map +0 -1
  173. /package/dist/{chunk-2J3SMMGW.mjs.map → chunk-C6F6EQNA.mjs.map} +0 -0
  174. /package/dist/{chunk-EQ4XLLT4.mjs.map → chunk-LDACFA2B.mjs.map} +0 -0
  175. /package/dist/{chunk-FGBRHBRR.mjs.map → chunk-LZDDYZEY.mjs.map} +0 -0
  176. /package/dist/{chunk-WZAEVHLK.mjs.map → chunk-Q5D5XQFA.mjs.map} +0 -0
  177. /package/dist/{chunk-VQ3VTO26.mjs.map → chunk-UHQMV2CE.mjs.map} +0 -0
  178. /package/dist/{chunk-4DVPRMVH.mjs.map → chunk-UIT6QMUJ.mjs.map} +0 -0
  179. /package/dist/{chunk-7HDYPEWS.mjs.map → chunk-YDENFEKA.mjs.map} +0 -0
  180. /package/dist/{chunk-4VWM6JNK.mjs.map → chunk-YZDRMIOM.mjs.map} +0 -0
@@ -1,9 +1,8 @@
1
1
  import React, { useEffect } from "react";
2
- import { Severity, CopilotKitError } from "@copilotkit/shared";
2
+ import { Severity, CopilotKitError, ErrorVisibility } from "@copilotkit/shared";
3
3
  import { StatusChecker } from "../../lib/status-checker";
4
4
  import { renderCopilotKitUsage, UsageBanner } from "../usage-banner";
5
5
  import { useErrorToast } from "./error-utils";
6
- import { COPILOT_CLOUD_ERROR_NAMES } from "@copilotkit/shared";
7
6
 
8
7
  const statusChecker = new StatusChecker();
9
8
 
@@ -58,11 +57,13 @@ export class CopilotErrorBoundary extends React.Component<Props, State> {
58
57
  render() {
59
58
  if (this.state.hasError) {
60
59
  if (this.state.error instanceof CopilotKitError) {
61
- // @ts-expect-error -- It's a copilotkit error at this state. Name is valid
62
- if (COPILOT_CLOUD_ERROR_NAMES.includes(this.state.error.name)) {
60
+ // Check if error should be shown as banner based on visibility
61
+ if (this.state.error.visibility === ErrorVisibility.BANNER) {
63
62
  return (
64
63
  <ErrorToast error={this.state.error}>
65
- {renderCopilotKitUsage(this.state.error)}
64
+ {renderCopilotKitUsage(this.state.error, () =>
65
+ this.setState({ hasError: false, error: undefined }),
66
+ )}
66
67
  </ErrorToast>
67
68
  );
68
69
  }
@@ -33,7 +33,7 @@ export function ErrorToast({ errors }: { errors: (Error | GraphQLError)[] }) {
33
33
  marginBottom: 4,
34
34
  }}
35
35
  >
36
- Copilot Cloud Error:{" "}
36
+ Copilot Runtime Error:{" "}
37
37
  <span style={{ fontFamily: "monospace", fontWeight: "normal" }}>{code}</span>
38
38
  </div>
39
39
  )}
@@ -1,7 +1,8 @@
1
1
  import { GraphQLError } from "@copilotkit/runtime-client-gql";
2
2
  import React, { createContext, useContext, useState, useCallback } from "react";
3
3
  import { ErrorToast } from "../error-boundary/error-utils";
4
- import { PartialBy } from "@copilotkit/shared";
4
+ import { PartialBy, CopilotKitError, CopilotKitErrorCode, Severity } from "@copilotkit/shared";
5
+ import { renderCopilotKitUsage } from "../usage-banner";
5
6
 
6
7
  interface Toast {
7
8
  id: string;
@@ -16,10 +17,80 @@ interface ToastContextValue {
16
17
  addGraphQLErrorsToast: (errors: GraphQLError[]) => void;
17
18
  removeToast: (id: string) => void;
18
19
  enabled: boolean;
20
+ // Banner management
21
+ bannerError: CopilotKitError | null;
22
+ setBannerError: (error: CopilotKitError | null) => void;
19
23
  }
20
24
 
21
25
  const ToastContext = createContext<ToastContextValue | undefined>(undefined);
22
26
 
27
+ // Helper functions for error banner styling
28
+ type ErrorSeverity = "critical" | "warning" | "info";
29
+
30
+ interface ErrorColors {
31
+ background: string;
32
+ border: string;
33
+ text: string;
34
+ icon: string;
35
+ }
36
+
37
+ function getErrorSeverity(error: CopilotKitError): ErrorSeverity {
38
+ // Use structured error severity if available
39
+ if (error.severity) {
40
+ switch (error.severity) {
41
+ case Severity.CRITICAL:
42
+ return "critical";
43
+ case Severity.WARNING:
44
+ return "warning";
45
+ case Severity.INFO:
46
+ return "info";
47
+ default:
48
+ return "info";
49
+ }
50
+ }
51
+
52
+ // Fallback: Check for API key errors which should always be critical
53
+ const message = error.message.toLowerCase();
54
+ if (
55
+ message.includes("api key") ||
56
+ message.includes("401") ||
57
+ message.includes("unauthorized") ||
58
+ message.includes("authentication") ||
59
+ message.includes("incorrect api key")
60
+ ) {
61
+ return "critical";
62
+ }
63
+
64
+ // Default to info level
65
+ return "info";
66
+ }
67
+
68
+ function getErrorColors(severity: ErrorSeverity): ErrorColors {
69
+ switch (severity) {
70
+ case "critical":
71
+ return {
72
+ background: "#fee2e2",
73
+ border: "#dc2626",
74
+ text: "#7f1d1d",
75
+ icon: "#dc2626",
76
+ };
77
+ case "warning":
78
+ return {
79
+ background: "#fef3c7",
80
+ border: "#d97706",
81
+ text: "#78350f",
82
+ icon: "#d97706",
83
+ };
84
+ case "info":
85
+ return {
86
+ background: "#dbeafe",
87
+ border: "#2563eb",
88
+ text: "#1e3a8a",
89
+ icon: "#2563eb",
90
+ };
91
+ }
92
+ }
93
+
23
94
  export function useToast() {
24
95
  const context = useContext(ToastContext);
25
96
  if (!context) {
@@ -36,9 +107,15 @@ export function ToastProvider({
36
107
  children: React.ReactNode;
37
108
  }) {
38
109
  const [toasts, setToasts] = useState<Toast[]>([]);
110
+ const [bannerError, setBannerErrorState] = useState<CopilotKitError | null>(null);
111
+
112
+ const removeToast = useCallback((id: string) => {
113
+ setToasts((prev) => prev.filter((toast) => toast.id !== id));
114
+ }, []);
115
+
39
116
  const addToast = useCallback(
40
117
  (toast: PartialBy<Toast, "id">) => {
41
- // We do not display these errors unless we are in dev mode.
118
+ // Respect the enabled flag for ALL toasts
42
119
  if (!enabled) {
43
120
  return;
44
121
  }
@@ -56,18 +133,24 @@ export function ToastProvider({
56
133
  }, toast.duration);
57
134
  }
58
135
  },
136
+ [enabled, removeToast],
137
+ );
138
+
139
+ const setBannerError = useCallback(
140
+ (error: CopilotKitError | null) => {
141
+ // Respect the enabled flag for ALL errors
142
+ if (!enabled && error !== null) {
143
+ return;
144
+ }
145
+ setBannerErrorState(error);
146
+ },
59
147
  [enabled],
60
148
  );
61
149
 
62
150
  const addGraphQLErrorsToast = useCallback((errors: GraphQLError[]) => {
63
- addToast({
64
- type: "error",
65
- message: <ErrorToast errors={errors} />,
66
- });
67
- }, []);
68
-
69
- const removeToast = useCallback((id: string) => {
70
- setToasts((currentToasts) => currentToasts.filter((toast) => toast.id !== id));
151
+ // DEPRECATED: All errors now route to banners for consistency
152
+ console.warn("addGraphQLErrorsToast is deprecated. All errors now show as banners.");
153
+ // Function kept for backward compatibility - does nothing
71
154
  }, []);
72
155
 
73
156
  const value = {
@@ -76,98 +159,182 @@ export function ToastProvider({
76
159
  addGraphQLErrorsToast,
77
160
  removeToast,
78
161
  enabled,
162
+ bannerError,
163
+ setBannerError,
79
164
  };
80
165
 
81
166
  return (
82
167
  <ToastContext.Provider value={value}>
83
- <div
84
- style={{
85
- position: "fixed",
86
- bottom: "1rem",
87
- left: "50%",
88
- transform: "translateX(-50%)",
89
- zIndex: 50,
90
- display: "flex",
91
- flexDirection: "column",
92
- gap: "0.5rem",
93
- }}
94
- >
95
- {toasts.length > 1 && (
96
- <div style={{ textAlign: "right" }}>
97
- <button
98
- onClick={() => setToasts([])}
168
+ {/* Banner Error Display */}
169
+ {bannerError &&
170
+ (() => {
171
+ const severity = getErrorSeverity(bannerError);
172
+ const colors = getErrorColors(severity);
173
+
174
+ return (
175
+ <div
99
176
  style={{
100
- padding: "4px 8px",
101
- fontSize: "12px",
102
- cursor: "pointer",
103
- background: "white",
104
- border: "1px solid rgba(0,0,0,0.2)",
105
- borderRadius: "4px",
177
+ position: "fixed",
178
+ bottom: "20px",
179
+ left: "50%",
180
+ transform: "translateX(-50%)",
181
+ zIndex: 9999,
182
+ backgroundColor: colors.background,
183
+ border: `1px solid ${colors.border}`,
184
+ borderLeft: `4px solid ${colors.border}`,
185
+ borderRadius: "8px",
186
+ padding: "10px 14px",
187
+ fontSize: "13px",
188
+ boxShadow: "0 4px 12px rgba(0, 0, 0, 0.15)",
189
+ backdropFilter: "blur(8px)",
190
+ maxWidth: "500px",
191
+ minWidth: "350px",
106
192
  }}
107
193
  >
108
- Close All
109
- </button>
110
- </div>
111
- )}
112
- {toasts.map((toast) => (
113
- <Toast
114
- key={toast.id}
115
- message={toast.message}
116
- type={toast.type}
117
- onClose={() => removeToast(toast.id)}
118
- />
119
- ))}
120
- </div>
194
+ <div
195
+ style={{
196
+ display: "flex",
197
+ justifyContent: "space-between",
198
+ alignItems: "center",
199
+ gap: "10px",
200
+ }}
201
+ >
202
+ <div style={{ display: "flex", alignItems: "center", gap: "8px", flex: 1 }}>
203
+ <div
204
+ style={{
205
+ width: "12px",
206
+ height: "12px",
207
+ borderRadius: "50%",
208
+ backgroundColor: colors.border,
209
+ flexShrink: 0,
210
+ }}
211
+ />
212
+ <div style={{ display: "flex", alignItems: "center", gap: "10px", flex: 1 }}>
213
+ <div
214
+ style={{
215
+ color: colors.text,
216
+ lineHeight: "1.4",
217
+ fontWeight: "400",
218
+ fontSize: "13px",
219
+ flex: 1,
220
+ wordWrap: "break-word",
221
+ overflowWrap: "break-word",
222
+ hyphens: "auto",
223
+ }}
224
+ >
225
+ {(() => {
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) + "...";
241
+ }
242
+
243
+ return cleanMessage;
244
+ })()}
245
+ </div>
246
+
247
+ {(() => {
248
+ const message = bannerError.message;
249
+ const markdownLinkRegex = /\[([^\]]+)\]\(([^)]+)\)/g;
250
+ const plainUrlRegex = /(https?:\/\/[^\s)]+)/g;
251
+
252
+ // Extract the first URL found
253
+ let url = null;
254
+ let buttonText = "See More";
255
+
256
+ // Check for markdown links first
257
+ const markdownMatch = markdownLinkRegex.exec(message);
258
+ if (markdownMatch) {
259
+ url = markdownMatch[2];
260
+ buttonText = "See More";
261
+ } else {
262
+ // Check for plain URLs
263
+ const urlMatch = plainUrlRegex.exec(message);
264
+ if (urlMatch) {
265
+ url = urlMatch[0];
266
+ buttonText = "See More";
267
+ }
268
+ }
269
+
270
+ if (!url) return null;
271
+
272
+ return (
273
+ <button
274
+ onClick={() => window.open(url, "_blank", "noopener,noreferrer")}
275
+ style={{
276
+ background: colors.border,
277
+ color: "white",
278
+ border: "none",
279
+ borderRadius: "5px",
280
+ padding: "4px 10px",
281
+ fontSize: "11px",
282
+ fontWeight: "500",
283
+ cursor: "pointer",
284
+ transition: "all 0.2s ease",
285
+ flexShrink: 0,
286
+ }}
287
+ onMouseEnter={(e) => {
288
+ e.currentTarget.style.opacity = "0.9";
289
+ e.currentTarget.style.transform = "translateY(-1px)";
290
+ }}
291
+ onMouseLeave={(e) => {
292
+ e.currentTarget.style.opacity = "1";
293
+ e.currentTarget.style.transform = "translateY(0)";
294
+ }}
295
+ >
296
+ {buttonText}
297
+ </button>
298
+ );
299
+ })()}
300
+ </div>
301
+ </div>
302
+ <button
303
+ onClick={() => setBannerError(null)}
304
+ style={{
305
+ background: "transparent",
306
+ border: "none",
307
+ color: colors.text,
308
+ cursor: "pointer",
309
+ padding: "2px",
310
+ borderRadius: "3px",
311
+ fontSize: "14px",
312
+ lineHeight: "1",
313
+ opacity: 0.6,
314
+ transition: "all 0.2s ease",
315
+ flexShrink: 0,
316
+ }}
317
+ title="Dismiss"
318
+ onMouseEnter={(e) => {
319
+ e.currentTarget.style.opacity = "1";
320
+ e.currentTarget.style.background = "rgba(0, 0, 0, 0.05)";
321
+ }}
322
+ onMouseLeave={(e) => {
323
+ e.currentTarget.style.opacity = "0.6";
324
+ e.currentTarget.style.background = "transparent";
325
+ }}
326
+ >
327
+ ×
328
+ </button>
329
+ </div>
330
+ </div>
331
+ );
332
+ })()}
333
+
334
+ {/* Toast Display - Deprecated: All errors now show as banners */}
121
335
  {children}
122
336
  </ToastContext.Provider>
123
337
  );
124
338
  }
125
339
 
126
- function Toast({
127
- message,
128
- type = "info",
129
- onClose,
130
- }: {
131
- message: string | React.ReactNode;
132
- type: "info" | "success" | "warning" | "error";
133
- onClose: () => void;
134
- }) {
135
- const bgColors = {
136
- info: "#3b82f6",
137
- success: "#22c55e",
138
- warning: "#eab308",
139
- error: "#ef4444",
140
- };
141
-
142
- return (
143
- <div
144
- style={{
145
- backgroundColor: bgColors[type],
146
- color: "white",
147
- padding: "0.5rem 1.5rem",
148
- borderRadius: "0.25rem",
149
- boxShadow: "0 2px 4px rgba(0,0,0,0.1)",
150
- position: "relative",
151
- minWidth: "200px",
152
- }}
153
- >
154
- <div>{message}</div>
155
- <button
156
- onClick={onClose}
157
- style={{
158
- position: "absolute",
159
- top: "0",
160
- right: "0",
161
- background: "none",
162
- border: "none",
163
- color: "white",
164
- cursor: "pointer",
165
- padding: "0.5rem",
166
- fontSize: "1rem",
167
- }}
168
- >
169
-
170
- </button>
171
- </div>
172
- );
173
- }
340
+ // Toast component removed - all errors now show as banners for consistency