# All files / src/components/error AIErrorHelper.tsx

86.11% Statements 93/108
25% Branches 1/4
50% Functions 1/2
86.11% Lines 93/108

Press n or j to go to the next uncovered block, b, p or k for the previous block.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    1091x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    6x
    6x
    6x
    6x
    6x
    6x
    6x
    6x
    6x

    6x
    6x
    6x
    6x
    6x
    6x
    6x
    6x
    6x
    6x
    6x
    6x
    6x
    6x
    6x
    6x
    6x
    6x
    6x
    6x
    6x
    6x
    6x
    6x
    6x
    6x
    6x
    6x
    6x
    6x
    6x
    6x
    6x
    6x
    6x
    6x
    6x
    6x
    6x
    6x
    6x
    6x
    6x
    6x
    6x
    6x
    6x
    6x
    6x
    6x
    6x
    6x
    6x
    6x
    6x
    6x
    6x
    6x
    6x
    6x
    6x
     import { useState } from 'react'
    import { Button } from '@/components/ui/button'
    import {
      Dialog,
      DialogContent,
      DialogDescription,
      DialogHeader,
      DialogTitle,
    } from '@/components/ui/dialog'
    import { Alert, AlertDescription } from '@/components/ui/alert'
    import { Sparkle } from '@phosphor-icons/react'
    import { motion, AnimatePresence } from 'framer-motion'
    import { analyzeErrorWithAI } from './analyzeError'
    import { MarkdownRenderer } from './MarkdownRenderer'
    import { LoadingAnalysis } from './LoadingAnalysis'

    interface AIErrorHelperProps {
      error: Error | string
      context?: string
      className?: string
    }

    export function AIErrorHelper({ error, context, className }: AIErrorHelperProps) {
      const [open, setOpen] = useState(false)
      const [analysis, setAnalysis] = useState<string>('')
      const [isAnalyzing, setIsAnalyzing] = useState(false)
      const [analysisError, setAnalysisError] = useState<string>('')

      const errorMessage = typeof error === 'string' ? error : error.message
      const errorStack = typeof error === 'string' ? '' : error.stack

      const analyzeError = async () => {
        setOpen(true)
        setIsAnalyzing(true)
        setAnalysisError('')
        setAnalysis('')

        try {
          const result = await analyzeErrorWithAI(errorMessage, errorStack, context)
          setAnalysis(result)
        } catch (err) {
          console.error('AI analysis failed', err)
          setAnalysisError('Unable to analyze error. The AI service may be temporarily unavailable.')
        } finally {
          setIsAnalyzing(false)
        }
      }

      return (
        <>
          <motion.div
            initial={{ scale: 0.9, opacity: 0 }}
            animate={{ scale: 1, opacity: 1 }}
            transition={{ duration: 0.2 }}
            className={className}
          >
            <Button
              onClick={analyzeError}
              variant="outline"
              size="sm"
              className="gap-2 border-accent/50 text-accent hover:bg-accent/10 hover:text-accent hover:border-accent transition-all"
            >
              <motion.div
                animate={{ rotate: [0, 10, -10, 10, 0] }}
                transition={{ duration: 2, repeat: Infinity, repeatDelay: 1 }}
              >
                <Sparkle className="h-4 w-4" weight="fill" />
              </motion.div>
              Ask AI for Help
            </Button>
          </motion.div>

          <Dialog open={open} onOpenChange={setOpen}>
            <DialogContent className="max-w-2xl max-h-[80vh] overflow-hidden flex flex-col">
              <DialogHeader className="pr-8">
                <DialogTitle className="flex items-center gap-2">
                  <Sparkle className="h-5 w-5 text-accent" weight="fill" />
                  AI Error Analysis
                </DialogTitle>
                <DialogDescription>
                  Let me help you understand and fix this error
                </DialogDescription>
              </DialogHeader>

              <div className="flex-1 overflow-y-auto space-y-4">
                <Alert className="bg-destructive/10 border-destructive/30">
                  <AlertDescription className="text-sm font-mono">
                    {errorMessage}
                  </AlertDescription>
                </Alert>

                {isAnalyzing && <LoadingAnalysis />}

                {analysisError && (
                  <Alert variant="destructive">
                    <AlertDescription>{analysisError}</AlertDescription>
                  </Alert>
                )}

                <AnimatePresence>
                  {analysis && <MarkdownRenderer content={analysis} />}
                </AnimatePresence>
              </div>
            </DialogContent>
          </Dialog>
        </>
      )
    }