Skip to content

Commit 90692bc

Browse files
author
Juan Castaño
committed
Add fix with AI functionality
1 parent 9af56cb commit 90692bc

File tree

5 files changed

+109
-14
lines changed

5 files changed

+109
-14
lines changed

app/api/generate/route.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ const benchify = new Benchify({
1212
apiKey: process.env.BENCHIFY_API_KEY,
1313
});
1414

15-
const debug = false;
15+
const debug = true;
1616
const buggyCode = [
1717
{
1818
path: "src/App.tsx",
@@ -79,7 +79,7 @@ export async function POST(request: NextRequest) {
7979

8080
// Determine if this is an edit request or new generation
8181
if (existingFiles && editInstruction) {
82-
// Edit existing code
82+
// Edit existing code (including error fixes)
8383
console.log('Processing edit request...');
8484
console.log('Existing files:', existingFiles.map(f => ({ path: f.path, contentLength: f.content.length })));
8585

app/chat/page.tsx

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,12 @@ export default function ChatPage() {
8282
}
8383
};
8484

85+
const handleUpdateResult = (updatedResult: GenerationResult) => {
86+
setResult(updatedResult);
87+
// Save updated result to sessionStorage
88+
sessionStorage.setItem('builderResult', JSON.stringify(updatedResult));
89+
};
90+
8591
// Show loading spinner if we don't have prompt yet
8692
if (!initialPrompt) {
8793
return (
@@ -101,11 +107,7 @@ export default function ChatPage() {
101107
<ChatInterface
102108
initialPrompt={initialPrompt}
103109
currentFiles={result?.repairedFiles || result?.originalFiles}
104-
onUpdateResult={(updatedResult) => {
105-
setResult(updatedResult);
106-
// Save updated result to sessionStorage
107-
sessionStorage.setItem('builderResult', JSON.stringify(updatedResult));
108-
}}
110+
onUpdateResult={handleUpdateResult}
109111
/>
110112
</div>
111113

@@ -118,6 +120,7 @@ export default function ChatPage() {
118120
prompt={initialPrompt}
119121
buildErrors={result?.buildErrors}
120122
hasErrors={result?.hasErrors}
123+
onFixComplete={handleUpdateResult}
121124
/>
122125
</div>
123126
</div>

components/ui-builder/error-display.tsx

Lines changed: 91 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
11
'use client';
22

3-
import { AlertCircle, Code, FileX, Terminal } from 'lucide-react';
3+
import { useState } from 'react';
4+
import { AlertCircle, Code, FileX, Terminal, Wand2 } from 'lucide-react';
45
import { Alert, AlertDescription, AlertTitle } from '@/components/ui/alert';
56
import { Badge } from '@/components/ui/badge';
7+
import { Button } from '@/components/ui/button';
68
import { ScrollArea } from '@/components/ui/scroll-area';
9+
import { benchifyFileSchema } from '@/lib/schemas';
10+
import { z } from 'zod';
711

812
interface BuildError {
913
type: 'typescript' | 'build' | 'runtime';
@@ -15,9 +19,13 @@ interface BuildError {
1519

1620
interface ErrorDisplayProps {
1721
errors: BuildError[];
22+
currentFiles?: z.infer<typeof benchifyFileSchema>;
23+
onFixComplete?: (result: any) => void;
1824
}
1925

20-
export function ErrorDisplay({ errors }: ErrorDisplayProps) {
26+
export function ErrorDisplay({ errors, currentFiles, onFixComplete }: ErrorDisplayProps) {
27+
const [isFixing, setIsFixing] = useState(false);
28+
2129
const getErrorIcon = (type: BuildError['type']) => {
2230
switch (type) {
2331
case 'typescript':
@@ -52,15 +60,94 @@ export function ErrorDisplay({ errors }: ErrorDisplayProps) {
5260
return acc;
5361
}, {} as Record<string, BuildError[]>);
5462

63+
const handleFixWithAI = async () => {
64+
if (!currentFiles || errors.length === 0 || isFixing) return;
65+
66+
setIsFixing(true);
67+
68+
try {
69+
// Format errors into an edit instruction
70+
const errorDetails = errors.map(error => {
71+
let errorInfo = `${error.type.toUpperCase()} ERROR: ${error.message}`;
72+
if (error.file) {
73+
errorInfo += ` (in ${error.file}`;
74+
if (error.line) errorInfo += ` at line ${error.line}`;
75+
if (error.column) errorInfo += `, column ${error.column}`;
76+
errorInfo += ')';
77+
}
78+
return errorInfo;
79+
}).join('\n\n');
80+
81+
const fixInstruction = `Fix the following build errors:
82+
83+
${errorDetails}
84+
85+
Please make the minimal changes necessary to resolve these errors while maintaining existing functionality.`;
86+
87+
// Use the existing edit API
88+
const response = await fetch('/api/generate', {
89+
method: 'POST',
90+
headers: {
91+
'Content-Type': 'application/json',
92+
},
93+
body: JSON.stringify({
94+
type: 'component',
95+
description: '',
96+
existingFiles: currentFiles,
97+
editInstruction: fixInstruction,
98+
}),
99+
});
100+
101+
if (!response.ok) {
102+
throw new Error('Failed to fix errors with AI');
103+
}
104+
105+
const fixResult = await response.json();
106+
107+
// Notify parent component of the fix result
108+
if (onFixComplete) {
109+
onFixComplete(fixResult);
110+
}
111+
112+
} catch (error) {
113+
console.error('Error fixing with AI:', error);
114+
// Could add error toast here
115+
} finally {
116+
setIsFixing(false);
117+
}
118+
};
119+
55120
return (
56121
<div className="w-full h-full flex items-center justify-center rounded-md border bg-background p-6">
57122
<div className="w-full max-w-2xl">
58123
<div className="text-center mb-6">
59124
<AlertCircle className="h-12 w-12 text-destructive mx-auto mb-4" />
60125
<h3 className="text-lg font-semibold mb-2">Build Errors Detected</h3>
61-
<p className="text-muted-foreground text-sm">
126+
<p className="text-muted-foreground text-sm mb-4">
62127
Your project has some issues that need to be fixed before it can run properly.
63128
</p>
129+
130+
{/* Fix with AI Button */}
131+
{currentFiles && (
132+
<Button
133+
onClick={handleFixWithAI}
134+
disabled={isFixing}
135+
className="mb-4"
136+
size="sm"
137+
>
138+
{isFixing ? (
139+
<>
140+
<div className="animate-spin rounded-full h-4 w-4 border-b-2 border-current mr-2" />
141+
Fixing with AI...
142+
</>
143+
) : (
144+
<>
145+
<Wand2 className="h-4 w-4 mr-2" />
146+
Fix with AI
147+
</>
148+
)}
149+
</Button>
150+
)}
64151
</div>
65152

66153
<ScrollArea className="max-h-96">
@@ -109,6 +196,7 @@ export function ErrorDisplay({ errors }: ErrorDisplayProps) {
109196
<li>• Verify that all props are properly typed</li>
110197
<li>• Make sure all dependencies are correctly installed</li>
111198
<li>• Try regenerating the component with more specific requirements</li>
199+
{currentFiles && <li>• Use the "Fix with AI" button above for automatic error resolution</li>}
112200
</ul>
113201
</div>
114202
</div>

components/ui-builder/preview-card.tsx

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ interface PreviewCardProps {
5252
prompt?: string;
5353
buildErrors?: BuildError[];
5454
hasErrors?: boolean;
55+
onFixComplete?: (result: any) => void;
5556
}
5657

5758
export function PreviewCard({
@@ -60,7 +61,8 @@ export function PreviewCard({
6061
isGenerating = false,
6162
prompt,
6263
buildErrors = [],
63-
hasErrors = false
64+
hasErrors = false,
65+
onFixComplete
6466
}: PreviewCardProps) {
6567
const files = code || [];
6668
const [currentStep, setCurrentStep] = useState(0);
@@ -147,7 +149,11 @@ export function PreviewCard({
147149
</div>
148150
) : hasErrors && buildErrors.length > 0 ? (
149151
// Show build errors if there are any
150-
<ErrorDisplay errors={buildErrors} />
152+
<ErrorDisplay
153+
errors={buildErrors}
154+
currentFiles={files}
155+
onFixComplete={onFixComplete}
156+
/>
151157
) : previewUrl ? (
152158
// Show the actual preview iframe when ready
153159
<div className="w-full h-full overflow-hidden rounded-md border bg-background">

lib/openai.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,6 @@ const fileSchema = z.object({
1717
content: z.string()
1818
});
1919

20-
21-
2220
// Generate a new application using AI SDK
2321
export async function generateApp(
2422
description: string,

0 commit comments

Comments
 (0)