import { useEffect, useMemo, useState } from 'react'; import { Alert, AlertTitle, Box, Button, Link, Typography } from '@mui/material'; import { useAgentStore } from '@/store/agentStore'; import { apiFetch } from '@/utils/api'; import { inferenceCreditCta, isInferenceCreditError } from '@/utils/inferenceBilling'; interface ChatErrorBannerProps { error: string; sessionId: string; model?: string | null; onDismiss: () => void; } const DISCUSSIONS_URL = 'https://huggingface.co/spaces/smolagents/ml-intern/discussions'; export default function ChatErrorBanner({ error, sessionId, model, onDismiss }: ChatErrorBannerProps) { const [copied, setCopied] = useState(false); const [reportedAt, setReportedAt] = useState(() => new Date().toISOString()); const userPlan = useAgentStore((s) => s.user?.plan); const isCreditError = isInferenceCreditError(error); const creditCta = isCreditError ? inferenceCreditCta(userPlan) : null; useEffect(() => { setReportedAt(new Date().toISOString()); setCopied(false); }, [error]); const details = useMemo( () => [ 'ML Intern message failure', `time: ${reportedAt}`, `session: ${sessionId}`, `model: ${model || 'unknown'}`, `error: ${error}`, ].join('\n'), [error, model, reportedAt, sessionId], ); const copyDetails = async () => { try { await navigator.clipboard.writeText(details); setCopied(true); } catch { setCopied(false); } }; const trackProClick = () => { if (userPlan === 'pro') return; void apiFetch(`/api/pro-click/${sessionId}`, { method: 'POST', body: JSON.stringify({ source: 'inference_credit_error', target: 'hf_pro' }), }).catch(() => {}); }; return ( } > {creditCta?.title ?? 'Message failed'} {creditCta ? ( creditCta.message ) : ( <> The backend could not process the last message. Retry after a moment. If it keeps happening,{' '} open a discussion {' '} with the copied details. )} {creditCta && ( {creditCta.secondaryHref && creditCta.secondaryLabel && ( )} )} {error} ); }