{"repo": "adhaghani/antiturnitin", "files": {"app/api/analyze/route.ts": {"d7f3b5e5cbc37599bfd8d6f4af1b9284be7ef008": {"t": 1785745574.7405577, "n": 3857, "h": "757a0cdb53f29d1a", "c": "import { NextRequest, NextResponse } from \"next/server\";\n\nconst SYSTEM_PROMPT = `You are an expert linguistic analyzer. Evaluate the following text for 'Perplexity' and 'Burstiness'.\n- Perplexity measures the randomness and unpredictability of word choices. AI-generated text tends to have low perplexity (predictable, formulaic patterns). Human text has higher, more natural variability.\n- Burstiness measures variation in sentence structure and length. Human writing typically has high burstiness (mixing long complex sentences with short punchy ones). AI text tends toward uniform sentence patterns.\n\nReturn ONLY a valid JSON object (no markdown formatting, no code fences) with exactly this structure:\n{\n \"human_score\": ,\n \"burstiness_analysis\": \"\",\n \"perplexity_analysis\": \"\",\n \"improvement_tips\": [\"\", \"\", \"\"]\n}`;\n\nexport async function POST(request: NextRequest) {\n try {\n const { text } = await request.json();\n\n if (!text || typeof text !== \"string\" || text.trim().length === 0) {\n return NextResponse.json({ error: \"Text is required\" }, { status: 400 });\n }\n\n if (text.trim().length < 50) {\n return NextResponse.json(\n {\n error:\n \"Text must be at least 50 characters for a meaningful analysis\",\n },\n { status: 400 },\n );\n }\n\n const apiKey = process.env.DEEPSEEK_API_KEY;\n if (!apiKey) {\n return NextResponse.json(\n { error: \"Server configuration error\" },\n { status: 500 },\n );\n }\n\n const response = await fetch(\n \"https://api.deepseek.com/v1/chat/completions\",\n {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${apiKey}`,\n },\n body: JSON.stringify({\n model: \"deepseek-v4-pro\",\n messages: [\n { role: \"system\", content: SYSTEM_PROMPT },\n { role: \"user\", content: text.trim() },\n ],\n temperature: 0.1,\n max_tokens: 4000,\n }),\n },\n );\n\n if (!response.ok) {\n const errorBody = await response.text().catch(() => \"\");\n console.error(`DeepSeek API error ${response.status}:`, errorBody);\n return NextResponse.json(\n { error: `Analysis service returned an error (${response.status})` },\n { status: response.status },\n );\n }\n\n const data = await response.json();\n const content: string | undefined = data.choices?.[0]?.message?.content;\n\n if (!content) {\n console.error(\"DeepSeek returned empty content:\", data);\n return NextResponse.json(\n { error: \"No analysis returned from the service\" },\n { status: 500 },\n );\n }\n\n // DeepSeek may wrap JSON in markdown code fences — extract the raw JSON\n const jsonMatch = content.match(/\\{[\\s\\S]*\\}/);\n if (!jsonMatch) {\n console.error(\"Failed to extract JSON from DeepSeek response:\", content);\n return NextResponse.json(\n { error: \"Failed to parse analysis result\" },\n { status: 500 },\n );\n }\n\n const analysis = JSON.parse(jsonMatch[0]) as {\n human_score: number;\n burstiness_analysis: string;\n perplexity_analysis: string;\n improvement_tips: string[];\n };\n\n // Clamp human_score to 0–100 range as a safety net\n analysis.human_score = Math.max(\n 0,\n Math.min(100, Math.round(analysis.human_score)),\n );\n\n return NextResponse.json(analysis);\n } catch (error) {\n console.error(\"Analyze route error:\", error);\n return NextResponse.json(\n { error: \"Internal server error\" },\n { status: 500 },\n );\n }\n}\n"}, "ddd38f4b7ec20e30cb29e8ac632ffb45cdef613e": {"t": 1785754384.9115207, "n": 3857, "h": "8ee5dabf188722aa", "c": "import { NextRequest, NextResponse } from \"next/server\";\n\nconst SYSTEM_PROMPT = `You are an expert linguistic analyzer. Evaluate the following text for 'Perplexity' and 'Burstiness'.\n- Perplexity measures the randomness and unpredictability of word choices. AI-generated text tends to have low perplexity (predictable, formulaic patterns). Human text has higher, more natural variability.\n- Burstiness measures variation in sentence structure and length. Human writing typically has high burstiness (mixing long complex sentences with short punchy ones). AI text tends toward uniform sentence patterns.\n\nReturn ONLY a valid JSON object (no markdown formatting, no code fences) with exactly this structure:\n{\n \"human_score\": ,\n \"burstiness_analysis\": \"\",\n \"perplexity_analysis\": \"\",\n \"improvement_tips\": [\"\", \"\", \"\"]\n}`;\n\nexport async function POST(request: NextRequest) {\n try {\n const { text } = await request.json();\n\n if (!text || typeof text !== \"string\" || text.trim().length === 0) {\n return NextResponse.json({ error: \"Text is required\" }, { status: 400 });\n }\n\n if (text.trim().length < 50) {\n return NextResponse.json(\n {\n error:\n \"Text must be at least 50 characters for a meaningful analysis\",\n },\n { status: 400 },\n );\n }\n\n const apiKey = process.env.DEEPSEEK_API_KEY;\n if (!apiKey) {\n return NextResponse.json(\n { error: \"Server configuration error\" },\n { status: 500 },\n );\n }\n\n const response = await fetch(\n \"https://api.deepseek.com/v1/chat/completions\",\n {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${apiKey}`,\n },\n body: JSON.stringify({\n model: \"deepseek-v4-pro\",\n messages: [\n { role: \"system\", content: SYSTEM_PROMPT },\n { role: \"user\", content: text.trim() },\n ],\n temperature: 0.1,\n max_tokens: 1000,\n }),\n },\n );\n\n if (!response.ok) {\n const errorBody = await response.text().catch(() => \"\");\n console.error(`DeepSeek API error ${response.status}:`, errorBody);\n return NextResponse.json(\n { error: `Analysis service returned an error (${response.status})` },\n { status: response.status },\n );\n }\n\n const data = await response.json();\n const content: string | undefined = data.choices?.[0]?.message?.content;\n\n if (!content) {\n console.error(\"DeepSeek returned empty content:\", data);\n return NextResponse.json(\n { error: \"No analysis returned from the service\" },\n { status: 500 },\n );\n }\n\n // DeepSeek may wrap JSON in markdown code fences — extract the raw JSON\n const jsonMatch = content.match(/\\{[\\s\\S]*\\}/);\n if (!jsonMatch) {\n console.error(\"Failed to extract JSON from DeepSeek response:\", content);\n return NextResponse.json(\n { error: \"Failed to parse analysis result\" },\n { status: 500 },\n );\n }\n\n const analysis = JSON.parse(jsonMatch[0]) as {\n human_score: number;\n burstiness_analysis: string;\n perplexity_analysis: string;\n improvement_tips: string[];\n };\n\n // Clamp human_score to 0–100 range as a safety net\n analysis.human_score = Math.max(\n 0,\n Math.min(100, Math.round(analysis.human_score)),\n );\n\n return NextResponse.json(analysis);\n } catch (error) {\n console.error(\"Analyze route error:\", error);\n return NextResponse.json(\n { error: \"Internal server error\" },\n { status: 500 },\n );\n }\n}\n"}}}}