Spaces:
Build error
Build error
| import { NextRequest, NextResponse } from "next/server"; | |
| import { db } from "@/lib/db"; | |
| import ZAI from "z-ai-web-dev-sdk"; | |
| import fs from "fs/promises"; | |
| import path from "path"; | |
| const REPOS_DIR = path.join(process.cwd(), "repos"); | |
| async function readRepoFiles(repoName: string, maxFiles: number = 10): Promise<string> { | |
| const repoPath = path.join(REPOS_DIR, repoName); | |
| let content = ""; | |
| let fileCount = 0; | |
| async function readDir(dir: string, depth: number = 0): Promise<void> { | |
| if (fileCount >= maxFiles || depth > 3) return; | |
| try { | |
| const entries = await fs.readdir(dir, { withFileTypes: true }); | |
| for (const entry of entries) { | |
| if (fileCount >= maxFiles) break; | |
| const fullPath = path.join(dir, entry.name); | |
| // Ignorar carpetas comunes | |
| if (entry.isDirectory()) { | |
| if (["node_modules", ".git", "dist", "build", "__pycache__", "venv", ".next"].includes(entry.name)) { | |
| continue; | |
| } | |
| await readDir(fullPath, depth + 1); | |
| } else if (entry.isFile()) { | |
| // Solo archivos de c贸digo relevantes | |
| const ext = path.extname(entry.name); | |
| const codeExtensions = [".ts", ".tsx", ".js", ".jsx", ".py", ".java", ".go", ".rs", ".c", ".cpp", ".h", ".css", ".scss", ".html", ".json", ".yaml", ".yml", ".md"]; | |
| if (codeExtensions.includes(ext) && !entry.name.startsWith(".")) { | |
| try { | |
| const fileContent = await fs.readFile(fullPath, "utf-8"); | |
| const relativePath = path.relative(repoPath, fullPath); | |
| content += `\n--- ${relativePath} ---\n${fileContent.slice(0, 2000)}\n`; | |
| fileCount++; | |
| } catch { | |
| // Archivo no legible | |
| } | |
| } | |
| } | |
| } | |
| } catch { | |
| // Directorio no accesible | |
| } | |
| } | |
| await readDir(repoPath); | |
| return content; | |
| } | |
| // POST - Analizar c贸digo con IA | |
| export async function POST(request: NextRequest) { | |
| try { | |
| const body = await request.json(); | |
| const { repoId, projectId, type, code } = body; | |
| let analysisContent = code || ""; | |
| let repoName = ""; | |
| // Si hay repoId, leer archivos del repositorio | |
| if (repoId) { | |
| const repo = await db.repo.findUnique({ | |
| where: { id: repoId }, | |
| }); | |
| if (repo) { | |
| repoName = repo.name; | |
| analysisContent = await readRepoFiles(repo.name); | |
| } | |
| } | |
| if (!analysisContent) { | |
| return NextResponse.json( | |
| { success: false, error: "No hay c贸digo para analizar" }, | |
| { status: 400 } | |
| ); | |
| } | |
| const analysisType = type || "code"; | |
| // Crear an谩lisis inicial | |
| const analysis = await db.analysis.create({ | |
| data: { | |
| type: analysisType, | |
| result: "Analizando...", | |
| repoId: repoId || null, | |
| projectId: projectId || null, | |
| }, | |
| }); | |
| try { | |
| const zai = await ZAI.create(); | |
| const prompts: Record<string, string> = { | |
| code: `Analiza el siguiente c贸digo y proporciona: | |
| 1. Resumen general del proyecto | |
| 2. Estructura y organizaci贸n | |
| 3. Calidad del c贸digo (0-10) | |
| 4. Posibles mejoras | |
| 5. Bugs o problemas potenciales | |
| 6. Sugerencias de seguridad | |
| C贸digo a analizar: | |
| ${analysisContent.slice(0, 10000)}`, | |
| security: `Realiza un an谩lisis de seguridad del siguiente c贸digo. Identifica: | |
| 1. Vulnerabilidades potenciales (SQL injection, XSS, etc.) | |
| 2. Exposici贸n de datos sensibles | |
| 3. Dependencias inseguras | |
| 4. Configuraciones peligrosas | |
| 5. Recomendaciones de mitigaci贸n | |
| C贸digo: | |
| ${analysisContent.slice(0, 10000)}`, | |
| performance: `Analiza el rendimiento del siguiente c贸digo: | |
| 1. Cuellos de botella potenciales | |
| 2. Complejidad algor铆tmica | |
| 3. Uso de memoria | |
| 4. Operaciones bloqueantes | |
| 5. Optimizaciones sugeridas | |
| C贸digo: | |
| ${analysisContent.slice(0, 10000)}`, | |
| }; | |
| const completion = await zai.chat.completions.create({ | |
| messages: [ | |
| { | |
| role: "system", | |
| content: "Eres un experto en an谩lisis de c贸digo. Proporciona an谩lisis detallados y accionables.", | |
| }, | |
| { | |
| role: "user", | |
| content: prompts[analysisType] || prompts.code, | |
| }, | |
| ], | |
| temperature: 0.3, | |
| max_tokens: 4000, | |
| }); | |
| const result = completion.choices[0]?.message?.content || "No se pudo generar an谩lisis"; | |
| // Extraer resumen (primeras 200 caracteres) | |
| const summary = result.slice(0, 200) + "..."; | |
| // Actualizar an谩lisis | |
| const updatedAnalysis = await db.analysis.update({ | |
| where: { id: analysis.id }, | |
| data: { | |
| result, | |
| summary, | |
| }, | |
| }); | |
| // Crear tarea de agente | |
| await db.agentTask.create({ | |
| data: { | |
| type: "analyze", | |
| status: "completed", | |
| input: `Analizar ${repoName || "c贸digo"} (${analysisType})`, | |
| output: summary, | |
| completedAt: new Date(), | |
| }, | |
| }); | |
| return NextResponse.json({ | |
| success: true, | |
| analysis: updatedAnalysis, | |
| message: "An谩lisis completado", | |
| }); | |
| } catch (aiError) { | |
| console.error("AI Analysis Error:", aiError); | |
| await db.analysis.update({ | |
| where: { id: analysis.id }, | |
| data: { | |
| result: "Error en el an谩lisis: " + (aiError instanceof Error ? aiError.message : "Error desconocido"), | |
| }, | |
| }); | |
| return NextResponse.json( | |
| { success: false, error: "Error en el an谩lisis de IA" }, | |
| { status: 500 } | |
| ); | |
| } | |
| } catch (error) { | |
| console.error("Error in analyze route:", error); | |
| return NextResponse.json( | |
| { success: false, error: "Error interno del servidor" }, | |
| { status: 500 } | |
| ); | |
| } | |
| } | |
| // GET - Obtener an谩lisis | |
| export async function GET(request: NextRequest) { | |
| try { | |
| const { searchParams } = new URL(request.url); | |
| const repoId = searchParams.get("repoId"); | |
| const projectId = searchParams.get("projectId"); | |
| const where: Record<string, string> = {}; | |
| if (repoId) where.repoId = repoId; | |
| if (projectId) where.projectId = projectId; | |
| const analyses = await db.analysis.findMany({ | |
| where: Object.keys(where).length > 0 ? where : undefined, | |
| include: { | |
| repo: true, | |
| project: true, | |
| }, | |
| orderBy: { createdAt: "desc" }, | |
| take: 20, | |
| }); | |
| return NextResponse.json({ | |
| success: true, | |
| analyses, | |
| }); | |
| } catch (error) { | |
| console.error("Error fetching analyses:", error); | |
| return NextResponse.json( | |
| { success: false, error: "Error al obtener an谩lisis" }, | |
| { status: 500 } | |
| ); | |
| } | |
| } | |