import { Sparkles, MicroscopeIcon, LightbulbIcon, FileCodeIcon, Loader2, Brain, ChevronDown, Loader } from "lucide-react"; import { PlusCircleIcon, MinusCircleIcon } from "@heroicons/react/24/solid"; import AppButton from "components/ui/app-button"; import { cn } from "lib/utils"; import Card from "@/components/ui/card"; import TooltipText from "./ui/tooltip-text"; import { Fail } from "app/page-optimizer/components/icons/icon-svg"; import FAQSection from "./faq-section"; import Accordion from "components/accordion"; import { useState, useEffect } from "react"; import { experimental_useObject as useObject } from 'ai/react'; import { toast } from "components/ui/use-toast"; import { z } from "zod"; import { Collapsible, CollapsibleContent, CollapsibleTrigger } from "components/ui/collapsible"; // @ts-ignore const AIBaseURL = window.rapidload_optimizer?.ai_root || "https://ai.rapidload.io/api"; const SolutionSchema = z.object({ solutions_reasoning: z.array(z.object({ block_type: z.enum(['observation', 'analysis', 'hypothesis', 'validation', 'conclusion']), thought: z.string(), reasoning: z.string(), confidence_level: z.number().min(0).max(100), supporting_evidence: z.array(z.string()), related_blocks: z.array(z.string()).optional(), })), solutions_list: z.array(z.object({ type: z.enum(['rapidload_fix', 'wordpress_fix', 'theme_fix', 'another_plugin_fix', 'code_fix', 'server_config_fix', 'server_upgrade_fix']), title: z.string(), description: z.string(), steps: z.array(z.object({ step: z.number(), action: z.string(), details: z.string(), verification: z.string().optional() })), })), }); type SolutionType = z.infer; interface AiAuditProps { issue: { issue: string; description: string; solutions: SolutionType; howToFix: Array<{ step: string; description: string; type: string; sub_type?: string[]; rapidload_setting_input?: { name: string; }; }>; pagespeed_insight_metrics?: string[]; how_to_fix_questions?: { question: string; explanation: string; type: 'single_choice' | 'multiple_choice' | 'text' | 'number'; options: { value: string; label: string; description: string; }[]; }[]; }; index: number; openItems: string[]; toggleAccordion: (id: string) => void; input: any; loading?: boolean; isLatestAudit?: number; } export const AiAudit = ({ issue, index, openItems, toggleAccordion, input, loading, isLatestAudit }: AiAuditProps) => { const [solutionError, setSolutionError] = useState(null); const [isThinking, setIsThinking] = useState(false); const [thinkingTime, setThinkingTime] = useState(0); const [showThoughts, setShowThoughts] = useState(index === 0); const [thoughtsComplete, setThoughtsComplete] = useState(false); const [openSteps, setOpenSteps] = useState>({}); const { object: solutionObject, submit, isLoading } = useObject({ api: `${AIBaseURL}/solution`, schema: SolutionSchema, onFinish: () => { setIsThinking(false); setThoughtsComplete(true); } }); useEffect(() => { let interval: NodeJS.Timeout; if (isThinking) { const startTime = Date.now(); interval = setInterval(() => { const elapsed = Math.floor((Date.now() - startTime) / 1000); setThinkingTime(elapsed); }, 1000); } return () => clearInterval(interval); }, [isThinking]); useEffect(() => { setThinkingTime(0); setIsThinking(true); }, []); useEffect(() => { if (issue?.solutions?.solutions_list?.length > 0) { setIsThinking(false); setThoughtsComplete(true); } }, [issue]); const toggleSteps = (solutionTitle: string) => { setOpenSteps(prev => ({ ...prev, [solutionTitle]: !prev[solutionTitle] })); }; return (
{/* {JSON.stringify((isLatestAudit ?? 0) - 1)}{JSON.stringify(index)} */} {(loading && index === (isLatestAudit ?? 0) - 1) ? ( ) : ( )}
{issue?.issue} {issue?.pagespeed_insight_metrics?.map((metric: string) => (
{metric}
))}
toggleAccordion(index.toString())} className={cn( 'min-w-[125px] cursor-pointer flex items-center gap-2 pl-4 pr-2 py-1.5 text-sm rounded-2xl', 'dark:hover:bg-brand-800 hover:bg-brand-100 transition-colors border', openItems.includes(index.toString()) && 'dark:bg-brand-900' )} > {openItems.includes(index.toString()) ? 'Hide Issue' : 'Show Issue'} {openItems.includes(index.toString()) ? : }

Core Issue

{issue?.description}

{/* Solutions section */}

Solutions {/* Thinking UI */} {(issue?.solutions?.solutions_reasoning) && (
{issue?.solutions?.solutions_list?.length > 0 ? ( thinkingTime > 0 ? `Thought for ${thinkingTime}s...` : `Thoughts...` ) : ( <> Thinking . . . )}
{issue?.solutions?.solutions_reasoning && (
{issue?.solutions?.solutions_reasoning.map((item, index) => (
{item?.thought} {item?.block_type}
{item?.reasoning}
))}
)}
)}

{/* Solutions List */} {((issue?.solutions && issue?.solutions?.solutions_list))?.map((solution) => { if (!solution) return null; const steps = solution.steps || []; return (
{/* Solution Header */}
{solution.title} {solution.type}

{solution.description}

{/* Steps */} {steps.length > 0 && ( toggleSteps(solution.title)}>

Implementation Steps

    {steps.map((step) => { if (!step) return null; return (
  • {step.step}

    {step.action}

    {step.details}

    {step.verification && (

    Verification: {step.verification}

    )}
  • ); })}
)}
); })}
); };