added fast apply
if isEdit === true & Morph API Key is in .env: - Morph Fast Apply is activated.
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
import { NextRequest, NextResponse } from 'next/server';
|
||||
import { parseMorphEdits, applyMorphEditToFile } from '@/lib/morph-fast-apply';
|
||||
import type { SandboxState } from '@/types/sandbox';
|
||||
import type { ConversationState } from '@/types/conversation';
|
||||
|
||||
@@ -144,6 +145,12 @@ export async function POST(request: NextRequest) {
|
||||
|
||||
// Parse the AI response
|
||||
const parsed = parseAIResponse(response);
|
||||
const morphEnabled = Boolean(isEdit && process.env.MORPH_API_KEY);
|
||||
const morphEdits = morphEnabled ? parseMorphEdits(response) : [];
|
||||
console.log('[apply-ai-code] Morph Fast Apply mode:', morphEnabled);
|
||||
if (morphEnabled) {
|
||||
console.log('[apply-ai-code] Morph edits found:', morphEdits.length);
|
||||
}
|
||||
|
||||
// Initialize existingFiles if not already
|
||||
if (!global.existingFiles) {
|
||||
@@ -172,6 +179,14 @@ export async function POST(request: NextRequest) {
|
||||
console.log('[apply-ai-code] Is edit mode:', isEdit);
|
||||
console.log('[apply-ai-code] Files to write:', parsed.files.map(f => f.path));
|
||||
console.log('[apply-ai-code] Existing files:', Array.from(global.existingFiles));
|
||||
if (morphEnabled) {
|
||||
console.log('[apply-ai-code] Morph Fast Apply enabled');
|
||||
if (morphEdits.length > 0) {
|
||||
console.log('[apply-ai-code] Parsed Morph edits:', morphEdits.map(e => e.targetFile));
|
||||
} else {
|
||||
console.log('[apply-ai-code] No <edit> blocks found in response');
|
||||
}
|
||||
}
|
||||
|
||||
const results = {
|
||||
filesCreated: [] as string[],
|
||||
@@ -296,9 +311,46 @@ export async function POST(request: NextRequest) {
|
||||
}
|
||||
}
|
||||
|
||||
// Attempt Morph Fast Apply for edits before file creation
|
||||
const morphUpdatedPaths = new Set<string>();
|
||||
|
||||
if (morphEnabled && morphEdits.length > 0) {
|
||||
if (!global.activeSandbox) {
|
||||
console.warn('[apply-ai-code] Morph edits found but no active sandbox; skipping Morph application');
|
||||
} else {
|
||||
console.log(`[apply-ai-code] Applying ${morphEdits.length} fast edits via Morph...`);
|
||||
for (const edit of morphEdits) {
|
||||
try {
|
||||
const result = await applyMorphEditToFile({
|
||||
sandbox: global.activeSandbox,
|
||||
targetPath: edit.targetFile,
|
||||
instructions: edit.instructions,
|
||||
updateSnippet: edit.update
|
||||
});
|
||||
|
||||
if (result.success && result.normalizedPath) {
|
||||
morphUpdatedPaths.add(result.normalizedPath);
|
||||
results.filesUpdated.push(result.normalizedPath);
|
||||
console.log('[apply-ai-code] Morph applied to', result.normalizedPath);
|
||||
} else {
|
||||
const msg = result.error || 'Unknown Morph error';
|
||||
console.error('[apply-ai-code] Morph apply failed:', msg);
|
||||
results.errors.push(`Morph apply failed for ${edit.targetFile}: ${msg}`);
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('[apply-ai-code] Morph apply exception:', e);
|
||||
results.errors.push(`Morph apply exception for ${edit.targetFile}: ${(e as Error).message}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (morphEnabled && morphEdits.length === 0) {
|
||||
console.warn('[apply-ai-code] Morph enabled but no <edit> blocks found; falling back to full-file flow');
|
||||
}
|
||||
|
||||
// Filter out config files that shouldn't be created
|
||||
const configFiles = ['tailwind.config.js', 'vite.config.js', 'package.json', 'package-lock.json', 'tsconfig.json', 'postcss.config.js'];
|
||||
const filteredFiles = parsed.files.filter(file => {
|
||||
let filteredFiles = parsed.files.filter(file => {
|
||||
const fileName = file.path.split('/').pop() || '';
|
||||
if (configFiles.includes(fileName)) {
|
||||
console.warn(`[apply-ai-code] Skipping config file: ${file.path} - already exists in template`);
|
||||
@@ -306,6 +358,21 @@ export async function POST(request: NextRequest) {
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
// Avoid overwriting files already updated by Morph
|
||||
if (morphUpdatedPaths.size > 0) {
|
||||
filteredFiles = filteredFiles.filter(file => {
|
||||
let normalizedPath = file.path.startsWith('/') ? file.path.slice(1) : file.path;
|
||||
const fileName = normalizedPath.split('/').pop() || '';
|
||||
if (!normalizedPath.startsWith('src/') &&
|
||||
!normalizedPath.startsWith('public/') &&
|
||||
normalizedPath !== 'index.html' &&
|
||||
!configFiles.includes(fileName)) {
|
||||
normalizedPath = 'src/' + normalizedPath;
|
||||
}
|
||||
return !morphUpdatedPaths.has(normalizedPath);
|
||||
});
|
||||
}
|
||||
|
||||
// Create or update files AFTER package installation
|
||||
for (const file of filteredFiles) {
|
||||
@@ -354,7 +421,7 @@ export async function POST(request: NextRequest) {
|
||||
|
||||
} catch (writeError) {
|
||||
console.error(`[apply-ai-code] E2B file write error:`, writeError);
|
||||
throw writeError;
|
||||
throw writeError as Error;
|
||||
}
|
||||
|
||||
|
||||
@@ -491,7 +558,7 @@ with open(file_path, 'w') as f:
|
||||
print(f"Auto-generated: {file_path}")
|
||||
`);
|
||||
results.filesCreated.push('src/index.css (with Tailwind)');
|
||||
} catch (error) {
|
||||
} catch {
|
||||
results.errors.push('Failed to create index.css with Tailwind');
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user