import { NextResponse } from 'next/server'; import { FieldValue } from 'firebase-admin/firestore'; import { GeminiLlmClient } from '@/lib/ai/gemini-client'; import { runChatExtraction } from '@/lib/ai/chat-extractor'; import { getKnowledgeItem } from '@/lib/server/knowledge'; import { createChatExtraction } from '@/lib/server/chat-extraction'; import { getAdminDb } from '@/lib/firebase/admin'; import type { ProjectPhaseScores } from '@/lib/types/project-artifacts'; interface ExtractFromChatRequest { knowledgeItemId?: string; } // Increase Vercel/Next timeout for large transcripts export const maxDuration = 60; export async function POST( request: Request, { params }: { params: Promise<{ projectId: string }> }, ) { try { const { projectId } = await params; if (!projectId) { return NextResponse.json({ error: 'Missing projectId' }, { status: 400 }); } const body = (await request.json()) as ExtractFromChatRequest; const knowledgeItemId = body.knowledgeItemId?.trim(); if (!knowledgeItemId) { return NextResponse.json({ error: 'knowledgeItemId is required' }, { status: 400 }); } const knowledgeItem = await getKnowledgeItem(projectId, knowledgeItemId); if (!knowledgeItem) { return NextResponse.json({ error: 'Knowledge item not found' }, { status: 404 }); } console.log(`[extract-from-chat] Starting extraction for knowledgeItemId=${knowledgeItemId}, content length=${knowledgeItem.content.length}`); const llm = new GeminiLlmClient(); const extractionData = await runChatExtraction(knowledgeItem, llm); console.log(`[extract-from-chat] Extraction complete for knowledgeItemId=${knowledgeItemId}`); const overallCompletion = extractionData.summary_scores.overall_completion ?? 0; const overallConfidence = extractionData.summary_scores.overall_confidence ?? 0; const extraction = await createChatExtraction({ projectId, knowledgeItemId, data: extractionData, overallCompletion, overallConfidence, }); const adminDb = getAdminDb(); const projectRef = adminDb.collection('projects').doc(projectId); const snapshot = await projectRef.get(); const docData = snapshot.data() ?? {}; const existingScores = (docData.phaseScores ?? {}) as ProjectPhaseScores; const phaseHistory = Array.isArray(docData.phaseHistory) ? [...docData.phaseHistory] : []; phaseHistory.push({ phase: 'extractor', status: 'completed', knowledgeItemId, timestamp: new Date().toISOString(), }); existingScores.extractor = { knowledgeItemId, overallCompletion, overallConfidence, updatedAt: new Date().toISOString(), }; await projectRef.set( { currentPhase: 'analyzed', phaseScores: existingScores, phaseStatus: 'in_progress', phaseHistory, updatedAt: FieldValue.serverTimestamp(), }, { merge: true }, ); return NextResponse.json({ extraction }); } catch (error) { console.error('[extract-from-chat] Extraction failed', error); return NextResponse.json( { error: 'Failed to extract product signals', details: error instanceof Error ? error.message : String(error), }, { status: 500 }, ); } }