import { NextResponse } from 'next/server'; import { getServerSession } from 'next-auth'; import { authOptions } from '@/lib/auth/authOptions'; import { query } from '@/lib/db-postgres'; const AGENT_RUNNER_URL = process.env.AGENT_RUNNER_URL ?? 'http://localhost:3333'; // GET — check the current analysis status for a project export async function GET( _req: Request, { params }: { params: Promise<{ projectId: string }> } ) { const session = await getServerSession(authOptions); if (!session?.user?.email) { return NextResponse.json({ error: 'Unauthorized' }, { status: 401 }); } const { projectId } = await params; const rows = await query<{ data: any }>( `SELECT data FROM fs_projects WHERE id = $1 LIMIT 1`, [projectId] ); if (!rows.length) return NextResponse.json({ error: 'Project not found' }, { status: 404 }); const project = rows[0].data; if (!project.isImport) { return NextResponse.json({ isImport: false }); } const jobId = project.importAnalysisJobId; let jobStatus: Record | null = null; // Fetch live job status from agent runner if we have a job ID if (jobId) { try { const jobRes = await fetch(`${AGENT_RUNNER_URL}/api/jobs/${jobId}`); if (jobRes.ok) { jobStatus = await jobRes.json() as Record; // Sync terminal status back to the project record const runnerStatus = jobStatus.status as string | undefined; if (runnerStatus && runnerStatus !== project.importAnalysisStatus) { await query( `UPDATE fs_projects SET data = jsonb_set(data, '{importAnalysisStatus}', $1::jsonb) WHERE id = $2`, [JSON.stringify(runnerStatus), projectId] ); } } } catch { // Agent runner unreachable — return last known status } } return NextResponse.json({ isImport: true, status: project.importAnalysisStatus ?? 'pending', jobId, job: jobStatus, githubRepoUrl: project.githubRepoUrl, giteaRepo: project.giteaRepo, }); } // POST — (re-)trigger an analysis job for a project export async function POST( _req: Request, { params }: { params: Promise<{ projectId: string }> } ) { const session = await getServerSession(authOptions); if (!session?.user?.email) { return NextResponse.json({ error: 'Unauthorized' }, { status: 401 }); } const { projectId } = await params; const rows = await query<{ data: any }>( `SELECT data FROM fs_projects WHERE id = $1 LIMIT 1`, [projectId] ); if (!rows.length) return NextResponse.json({ error: 'Project not found' }, { status: 404 }); const project = rows[0].data; if (!project.giteaRepo) { return NextResponse.json({ error: 'Project has no Gitea repo' }, { status: 400 }); } try { const jobRes = await fetch(`${AGENT_RUNNER_URL}/api/agent/run`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ agent: 'ImportAnalyzer', task: `Analyze this codebase${project.githubRepoUrl ? ` (originally from ${project.githubRepoUrl})` : ''} and produce CODEBASE_MAP.md and MIGRATION_PLAN.md as described in your instructions.`, repo: project.giteaRepo, }), }); if (!jobRes.ok) { const detail = await jobRes.text(); return NextResponse.json({ error: 'Failed to start analysis', details: detail }, { status: 500 }); } const jobData = await jobRes.json() as { jobId?: string }; const jobId = jobData.jobId ?? null; await query( `UPDATE fs_projects SET data = jsonb_set(jsonb_set(data, '{importAnalysisJobId}', $1::jsonb), '{importAnalysisStatus}', '"running"') WHERE id = $2`, [JSON.stringify(jobId), projectId] ); return NextResponse.json({ success: true, jobId, status: 'running' }); } catch (err) { return NextResponse.json( { error: 'Failed to start analysis', details: err instanceof Error ? err.message : String(err) }, { status: 500 } ); } }