import React from 'react'; import { Button } from './ui/button'; import { AlertTriangle } from 'lucide-react'; import { errorMessage } from '../utils/conversionUtils'; import { trackErrorWithContext, trackEvent, getErrorType } from '../utils/analytics'; function getCurrentPage(): string { return window.location.hash.replace('#', '') || '/'; } // Capture unhandled promise rejections window.addEventListener('unhandledrejection', (event) => { window.electron.logInfo(`[UNHANDLED REJECTION] ${event.reason}`); trackErrorWithContext(event.reason, { component: 'global', page: getCurrentPage(), action: 'async_operation', recoverable: false, }); }); // Capture global errors window.addEventListener('error', (event) => { window.electron.logInfo( `[GLOBAL ERROR] ${event.message} at ${event.filename}:${event.lineno}:${event.colno}` ); trackErrorWithContext(event.error || event.message, { component: event.filename ? event.filename.split('/').pop() : 'unknown', page: getCurrentPage(), action: 'script_execution', recoverable: false, }); }); export function ErrorUI({ error }: { error: string }) { const handleReload = () => { trackEvent({ name: 'app_reloaded', properties: { reason: 'error_recovery' }, }); window.electron.reloadApp(); }; return (

Honk!

{window?.appConfig?.get('GOOSE_VERSION') !== undefined ? (

An error occurred in Goose v{window?.appConfig?.get('GOOSE_VERSION') as string}.

) : (

An error occurred.

)}
          {error}
        
); } export class ErrorBoundary extends React.Component< { children: React.ReactNode }, { error: Error | null; hasError: boolean } > { constructor(props: { children: React.ReactNode }) { super(props); this.state = { hasError: false, error: null }; } static getDerivedStateFromError(error: Error) { return { hasError: true, error }; } componentDidCatch(error: Error, errorInfo: React.ErrorInfo) { // Send error to main process window.electron.logInfo(`[ERROR] ${error.toString()}\n${errorInfo.componentStack}`); const componentMatch = errorInfo.componentStack?.match(/^\s*at\s+(\w+)/); const componentName = componentMatch ? componentMatch[1] : undefined; trackEvent({ name: 'app_crashed', properties: { error_type: getErrorType(error), component: componentName, page: getCurrentPage(), }, }); } render() { if (this.state.hasError) { return ; } return this.props.children; } }