← back to Letsbegin

app/api/prd/clarify/route.ts

152 lines

import { NextRequest, NextResponse } from 'next/server'
import { logGemini } from '@/lib/cost-track'

// Gemini API configuration (FREE - no credits needed!)
const GEMINI_API_KEY = process.env.GEMINI_API_KEY
if (!GEMINI_API_KEY) {
  throw new Error('GEMINI_API_KEY environment variable is required')
}
const GEMINI_ENDPOINT = 'https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent'

async function callGemini(prompt: string): Promise<string> {
  const response = await fetch(`${GEMINI_ENDPOINT}?key=${GEMINI_API_KEY}`, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
      contents: [{ parts: [{ text: prompt }] }],
      generationConfig: { temperature: 0.7, maxOutputTokens: 2000 }
    })
  })

  if (!response.ok) {
    const error = await response.text()
    throw new Error(`Gemini API error: ${error}`)
  }

  const data = await response.json()
  logGemini(data, { note: 'prd-clarify' })
  return data.candidates?.[0]?.content?.parts?.[0]?.text || ''
}

interface PRDInput {
  projectName: string
  featureTitle: string
  problemStatement: string
  targetUser: string
  scope: string
  priority: string
  keyFeatures: string
  nonGoals: string
  successMetrics: string
  components: string[]
  integrations: string
  techStack: string
  additionalAnswers: string
  projectPath?: string
}

const targetUserMap: Record<string, string> = {
  'A': 'New users',
  'B': 'Existing users',
  'C': 'Admin users',
  'D': 'All users'
}

const scopeMap: Record<string, string> = {
  'A': 'Minimal viable implementation',
  'B': 'Full-featured implementation',
  'C': 'Backend/API only',
  'D': 'Frontend/UI only'
}

const priorityMap: Record<string, string> = {
  'A': 'Critical (ASAP)',
  'B': 'High priority',
  'C': 'Medium priority',
  'D': 'Low priority (nice-to-have)'
}

interface ClarifyingQuestion {
  id: string
  question: string
  options: { key: string; label: string }[]
}

export async function POST(request: NextRequest) {
  try {
    let input: PRDInput
    try {
      input = await request.json()
    } catch {
      return NextResponse.json({ error: 'Invalid JSON in request body' }, { status: 400 })
    }

    // Build context from the questionnaire
    const context = `
Project: ${input.projectName}
Feature: ${input.featureTitle}
Problem: ${input.problemStatement}
Target User: ${targetUserMap[input.targetUser] || input.targetUser}
Scope: ${scopeMap[input.scope] || input.scope}
Priority: ${priorityMap[input.priority] || input.priority}
Key Features: ${input.keyFeatures || 'Not specified'}
Non-Goals: ${input.nonGoals || 'Not specified'}
Success Metrics: ${input.successMetrics || 'Not specified'}
Tech Stack: ${input.techStack || 'Not specified'}
Integrations: ${input.integrations || 'None'}
`

    const prompt = `You are a PRD (Product Requirements Document) generation assistant. Based on the following feature information, generate 3-5 clarifying questions that would help create a more specific and actionable PRD.

${context}

Generate questions that:
1. Resolve ambiguities about the problem or solution
2. Clarify technical constraints or requirements
3. Identify edge cases or error handling needs
4. Determine success criteria specifics
5. Understand integration or dependency details

For each question, provide exactly 4 options (A, B, C, D) that represent different approaches or answers.

IMPORTANT: Return ONLY a JSON array with this exact structure:
[
  {
    "id": "q1",
    "question": "How should the system handle users who...",
    "options": [
      {"key": "A", "label": "Option A description"},
      {"key": "B", "label": "Option B description"},
      {"key": "C", "label": "Option C description"},
      {"key": "D", "label": "Option D description"}
    ]
  }
]

Return ONLY the JSON array, no other text or explanation.`

    const responseText = await callGemini(prompt)

    // Parse the JSON response
    let questions: ClarifyingQuestion[] = []
    try {
      // Try to find JSON array in the response
      const jsonMatch = responseText.match(/\[[\s\S]*\]/)
      if (jsonMatch) {
        questions = JSON.parse(jsonMatch[0])
      } else {
        questions = JSON.parse(responseText)
      }
    } catch (parseErr) {
      console.error('Failed to parse clarifying questions:', parseErr, 'Response:', responseText)
      // Return empty array - will skip to generation
      questions = []
    }

    return NextResponse.json({ questions, success: true })
  } catch (error) {
    console.error('Failed to generate clarifying questions:', error)
    return NextResponse.json({ error: 'Failed to generate clarifying questions', questions: [] }, { status: 500 })
  }
}