Spaces:
Build error
Build error
File size: 6,632 Bytes
333c51a | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 | 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 }
);
}
}
|