import { AlertTriangle, X } from "lucide-react";
import { useTranslation } from "react-i18next";
import { Button } from "@/components/ui/button";
import { cn } from "@/lib/utils";
import type { StreamError } from "@/lib/nanobot-client";
interface StreamErrorNoticeProps {
error: StreamError;
onDismiss: () => void;
}
/**
* Fallback banner for transport-level faults that cannot be attached to a
* visible failed message. ``role="alert"`` + ``aria-live="assertive"``
* ensures screen readers announce the failure.
*/
export function StreamErrorNotice({ error, onDismiss }: StreamErrorNoticeProps) {
const { t } = useTranslation();
const { title, body } = resolveCopy(error, t);
return (
);
}
function resolveCopy(
error: StreamError,
t: (key: string) => string,
): { title: string; body: string } {
switch (error.kind) {
case "message_too_big":
return {
title: t("errors.messageTooBig.title"),
body: t("errors.messageTooBig.body"),
};
case "workspace_scope_rejected":
return {
title: t("errors.workspaceScopeRejected.title"),
body: t("errors.workspaceScopeRejected.body"),
};
case "turn_rejected":
return {
title: t("errors.turnRejected.title"),
body: t("errors.turnRejected.body"),
};
default: {
// Exhaustiveness guard: if a new StreamError kind is added, TS will
// complain here until we add a corresponding i18n branch.
const _exhaustive: never = error;
return { title: String(_exhaustive), body: "" };
}
}
}