diff --git a/app/api/generate/route.ts b/app/api/generate/route.ts index fab7ab7..8c8e5bd 100644 --- a/app/api/generate/route.ts +++ b/app/api/generate/route.ts @@ -12,7 +12,7 @@ const benchify = new Benchify({ apiKey: process.env.BENCHIFY_API_KEY, }); -const debug = false; +const debug = true; const buggyCode = [ { path: "src/App.tsx", @@ -79,7 +79,7 @@ export async function POST(request: NextRequest) { // Determine if this is an edit request or new generation if (existingFiles && editInstruction) { - // Edit existing code + // Edit existing code (including error fixes) console.log('Processing edit request...'); console.log('Existing files:', existingFiles.map(f => ({ path: f.path, contentLength: f.content.length }))); diff --git a/app/chat/page.tsx b/app/chat/page.tsx index 2bacf37..e81341d 100644 --- a/app/chat/page.tsx +++ b/app/chat/page.tsx @@ -82,6 +82,12 @@ export default function ChatPage() { } }; + const handleUpdateResult = (updatedResult: GenerationResult) => { + setResult(updatedResult); + // Save updated result to sessionStorage + sessionStorage.setItem('builderResult', JSON.stringify(updatedResult)); + }; + // Show loading spinner if we don't have prompt yet if (!initialPrompt) { return ( @@ -101,11 +107,7 @@ export default function ChatPage() { { - setResult(updatedResult); - // Save updated result to sessionStorage - sessionStorage.setItem('builderResult', JSON.stringify(updatedResult)); - }} + onUpdateResult={handleUpdateResult} /> @@ -118,6 +120,7 @@ export default function ChatPage() { prompt={initialPrompt} buildErrors={result?.buildErrors} hasErrors={result?.hasErrors} + onFixComplete={handleUpdateResult} /> diff --git a/components/ui-builder/error-display.tsx b/components/ui-builder/error-display.tsx index 9e86626..c1f21d9 100644 --- a/components/ui-builder/error-display.tsx +++ b/components/ui-builder/error-display.tsx @@ -1,9 +1,13 @@ 'use client'; -import { AlertCircle, Code, FileX, Terminal } from 'lucide-react'; +import { useState } from 'react'; +import { AlertCircle, Code, FileX, Terminal, Wand2 } from 'lucide-react'; import { Alert, AlertDescription, AlertTitle } from '@/components/ui/alert'; import { Badge } from '@/components/ui/badge'; +import { Button } from '@/components/ui/button'; import { ScrollArea } from '@/components/ui/scroll-area'; +import { benchifyFileSchema } from '@/lib/schemas'; +import { z } from 'zod'; interface BuildError { type: 'typescript' | 'build' | 'runtime'; @@ -15,9 +19,13 @@ interface BuildError { interface ErrorDisplayProps { errors: BuildError[]; + currentFiles?: z.infer; + onFixComplete?: (result: any) => void; } -export function ErrorDisplay({ errors }: ErrorDisplayProps) { +export function ErrorDisplay({ errors, currentFiles, onFixComplete }: ErrorDisplayProps) { + const [isFixing, setIsFixing] = useState(false); + const getErrorIcon = (type: BuildError['type']) => { switch (type) { case 'typescript': @@ -52,15 +60,94 @@ export function ErrorDisplay({ errors }: ErrorDisplayProps) { return acc; }, {} as Record); + const handleFixWithAI = async () => { + if (!currentFiles || errors.length === 0 || isFixing) return; + + setIsFixing(true); + + try { + // Format errors into an edit instruction + const errorDetails = errors.map(error => { + let errorInfo = `${error.type.toUpperCase()} ERROR: ${error.message}`; + if (error.file) { + errorInfo += ` (in ${error.file}`; + if (error.line) errorInfo += ` at line ${error.line}`; + if (error.column) errorInfo += `, column ${error.column}`; + errorInfo += ')'; + } + return errorInfo; + }).join('\n\n'); + + const fixInstruction = `Fix the following build errors: + +${errorDetails} + +Please make the minimal changes necessary to resolve these errors while maintaining existing functionality.`; + + // Use the existing edit API + const response = await fetch('/api/generate', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + type: 'component', + description: '', + existingFiles: currentFiles, + editInstruction: fixInstruction, + }), + }); + + if (!response.ok) { + throw new Error('Failed to fix errors with AI'); + } + + const fixResult = await response.json(); + + // Notify parent component of the fix result + if (onFixComplete) { + onFixComplete(fixResult); + } + + } catch (error) { + console.error('Error fixing with AI:', error); + // Could add error toast here + } finally { + setIsFixing(false); + } + }; + return (

Build Errors Detected

-

+

Your project has some issues that need to be fixed before it can run properly.

+ + {/* Fix with AI Button */} + {currentFiles && ( + + )}
@@ -109,6 +196,7 @@ export function ErrorDisplay({ errors }: ErrorDisplayProps) {
  • • Verify that all props are properly typed
  • • Make sure all dependencies are correctly installed
  • • Try regenerating the component with more specific requirements
  • + {currentFiles &&
  • • Use the "Fix with AI" button above for automatic error resolution
  • }
    diff --git a/components/ui-builder/preview-card.tsx b/components/ui-builder/preview-card.tsx index 6680062..cdb9a5e 100644 --- a/components/ui-builder/preview-card.tsx +++ b/components/ui-builder/preview-card.tsx @@ -52,6 +52,7 @@ interface PreviewCardProps { prompt?: string; buildErrors?: BuildError[]; hasErrors?: boolean; + onFixComplete?: (result: any) => void; } export function PreviewCard({ @@ -60,7 +61,8 @@ export function PreviewCard({ isGenerating = false, prompt, buildErrors = [], - hasErrors = false + hasErrors = false, + onFixComplete }: PreviewCardProps) { const files = code || []; const [currentStep, setCurrentStep] = useState(0); @@ -147,7 +149,11 @@ export function PreviewCard({ ) : hasErrors && buildErrors.length > 0 ? ( // Show build errors if there are any - + ) : previewUrl ? ( // Show the actual preview iframe when ready
    diff --git a/lib/openai.ts b/lib/openai.ts index 938df3c..fa39f06 100644 --- a/lib/openai.ts +++ b/lib/openai.ts @@ -17,8 +17,6 @@ const fileSchema = z.object({ content: z.string() }); - - // Generate a new application using AI SDK export async function generateApp( description: string,