import React, { useCallback } from "react";
import { GraphQLError } from "@copilotkit/runtime-client-gql";
import { useToast } from "../toast/toast-provider";
import { ExclamationMarkIcon } from "../toast/exclamation-mark-icon";
import ReactMarkdown from "react-markdown";
interface OriginalError {
message?: string;
stack?: string;
}
export function ErrorToast({ errors }: { errors: (Error | GraphQLError)[] }) {
const errorsToRender = errors.map((error, idx) => {
const originalError =
"extensions" in error
? (error.extensions?.originalError as undefined | OriginalError)
: {};
const message = originalError?.message ?? error.message;
const code =
"extensions" in error ? (error.extensions?.code as string) : null;
return (
{code && (
Copilot Runtime Error:{" "}
{code}
)}
{message}
);
});
return (
{errorsToRender}
NOTE: This error only displays during local development.
);
}
export function useErrorToast() {
const { addToast } = useToast();
return useCallback(
(errors: (Error | GraphQLError)[]) => {
const errorId = errors
.map((err) => {
const message =
"extensions" in err
? (err.extensions?.originalError as any)?.message || err.message
: err.message;
const stack = err.stack || "";
return btoa(message + stack).slice(0, 32); // Create hash from message + stack
})
.join("|");
addToast({
type: "error",
id: errorId, // Toast libraries typically dedupe by id
message: ,
});
},
[addToast],
);
}
export function useAsyncCallback Promise>(
callback: T,
deps: Parameters[1],
) {
const addErrorToast = useErrorToast();
return useCallback(async (...args: Parameters) => {
try {
return await callback(...args);
} catch (error) {
console.error("Error in async callback:", error);
// @ts-ignore
addErrorToast([error]);
throw error;
}
}, deps);
}