import { useEffect, useMemo, useRef, useState } from 'react'; import { formatOpenCodeRuntimeDeliveryDebugDetails, type OpenCodeRuntimeDeliveryDebugDetails, } from '@renderer/utils/openCodeRuntimeDeliveryDiagnostics'; import { AlertCircle } from 'lucide-react'; import type { JSX } from 'react'; interface OpenCodeDeliveryWarningProps { warning: string | null; debugDetails?: OpenCodeRuntimeDeliveryDebugDetails | null; pendingDelayMs?: number; } export const OpenCodeDeliveryWarning = ({ warning, debugDetails, pendingDelayMs = 10_000, }: OpenCodeDeliveryWarningProps): JSX.Element | null => { const detailsKey = `${warning ?? ''}:${debugDetails?.messageId ?? ''}:${debugDetails?.statusMessageId ?? ''}:${debugDetails?.userVisibleState ?? ''}`; const delayPendingWarning = debugDetails?.userVisibleState === 'checking' || (!debugDetails?.userVisibleState && debugDetails?.responsePending === true && debugDetails.delivered !== false); const [expandedKey, setExpandedKey] = useState(null); const [copiedKey, setCopiedKey] = useState(null); const [pendingVisibleKey, setPendingVisibleKey] = useState(() => delayPendingWarning ? null : detailsKey ); const mountedRef = useRef(true); const copiedResetTimerRef = useRef(null); const pendingTimerRef = useRef(null); const expanded = expandedKey === detailsKey; const copied = copiedKey === detailsKey; const copyText = useMemo( () => (debugDetails ? formatOpenCodeRuntimeDeliveryDebugDetails(debugDetails) : ''), [debugDetails] ); useEffect(() => { mountedRef.current = true; return () => { mountedRef.current = false; if (copiedResetTimerRef.current !== null) { window.clearTimeout(copiedResetTimerRef.current); } if (pendingTimerRef.current !== null) { window.clearTimeout(pendingTimerRef.current); } }; }, []); useEffect(() => { if (pendingTimerRef.current !== null) { window.clearTimeout(pendingTimerRef.current); pendingTimerRef.current = null; } if (!warning) { setPendingVisibleKey(null); return; } if (!delayPendingWarning || pendingDelayMs <= 0) { setPendingVisibleKey(detailsKey); return; } setPendingVisibleKey(null); pendingTimerRef.current = window.setTimeout(() => { pendingTimerRef.current = null; if (mountedRef.current) { setPendingVisibleKey(detailsKey); } }, pendingDelayMs); }, [delayPendingWarning, detailsKey, pendingDelayMs, warning]); if (!warning) return null; if (delayPendingWarning && pendingVisibleKey !== detailsKey) return null; const handleCopy = async (): Promise => { if (!copyText || !navigator.clipboard?.writeText) return; try { await navigator.clipboard.writeText(copyText); } catch { return; } if (!mountedRef.current) return; setCopiedKey(detailsKey); if (copiedResetTimerRef.current !== null) { window.clearTimeout(copiedResetTimerRef.current); } copiedResetTimerRef.current = window.setTimeout(() => { copiedResetTimerRef.current = null; if (mountedRef.current) { setCopiedKey(null); } }, 1500); }; return ( {warning} {debugDetails ? ( ) : null} {expanded && debugDetails ? ( messageId {debugDetails.messageId} statusMessageId {debugDetails.statusMessageId} providerId {debugDetails.providerId} delivered {String(debugDetails.delivered)} responsePending {String(debugDetails.responsePending)} responseState {debugDetails.responseState ?? 'null'} ledgerStatus {debugDetails.ledgerStatus ?? 'null'} visibleReplyMessageId {debugDetails.visibleReplyMessageId ?? 'null'} visibleReplyCorrelation {debugDetails.visibleReplyCorrelation ?? 'null'} queuedBehindMessageId {debugDetails.queuedBehindMessageId ?? 'null'} acceptanceUnknown {String(debugDetails.acceptanceUnknown)} userVisibleState {debugDetails.userVisibleState ?? 'null'} userVisibleReasonCode {debugDetails.userVisibleReasonCode ?? 'null'} userVisibleNextReviewAt {debugDetails.userVisibleNextReviewAt ?? 'null'} userVisibleMessage {debugDetails.userVisibleMessage ?? 'null'} reason {debugDetails.reason ?? 'null'} diagnostics {debugDetails.diagnostics.length ? debugDetails.diagnostics.join('; ') : '[]'} ) : null} ); };