From b03c25e70ea9788a4b2c4034f7fb7f36e8a0ea10 Mon Sep 17 00:00:00 2001 From: Harshit-Mishra2212 Date: Tue, 26 May 2026 02:46:19 +0530 Subject: [PATCH] fix: return structured JSON from AI routes so insights actually populate --- src/app/api/ai/route.ts | 44 +++++++++++++++++------------------ src/app/api/insights/route.ts | 44 ++++++++++++++++++++++------------- 2 files changed, 50 insertions(+), 38 deletions(-) diff --git a/src/app/api/ai/route.ts b/src/app/api/ai/route.ts index 0f2fe47..e46c06a 100644 --- a/src/app/api/ai/route.ts +++ b/src/app/api/ai/route.ts @@ -8,49 +8,49 @@ const anthropic = new Anthropic({ export async function POST(request: Request) { try { const data = await request.json(); - + const response = await anthropic.messages.create({ model: 'claude-3-5-haiku-20241022', max_tokens: 1000, messages: [{ role: 'user', content: `You are analyzing the Protocol Labs Developer Guild (PLDG) engagement data. - + Context: - PLDG is a program designed to drive open source contributors into Filecoin ecosystems - We track engagement through weekly surveys and GitHub contributions - Tech partners include Fil-Oz, Libp2p, IPFS, and others - + Data: ${JSON.stringify(data, null, 2)} - Please provide: - 1. Key Performance Indicators - 2. Risk Factors & Areas for Improvement - 3. Strategic Recommendations - 4. Success Stories & Notable Achievements - - Format the response in markdown.` + Respond ONLY with a valid JSON object in exactly this shape, no markdown, no extra text: + { + "riskFactors": ["risk 1", "risk 2"], + "strategicRecommendations": ["recommendation 1", "recommendation 2"], + "successStories": ["story 1", "story 2"] + }` }] }); - // Type guard to check if the content is text const textContent = response.content[0]; if (!('text' in textContent)) { throw new Error('Unexpected response format from Claude'); } - return NextResponse.json({ - insights: textContent.text, - success: true - }); + let insights; + try { + insights = JSON.parse(textContent.text); + } catch { + throw new Error('Claude returned non-JSON response'); + } + + return NextResponse.json({ insights, success: true }); } catch (error) { console.error('Error generating AI insights:', error); - return NextResponse.json({ - error: 'Failed to generate insights', - success: false - }, { - status: 500 - }); + return NextResponse.json( + { error: 'Failed to generate insights', success: false }, + { status: 500 } + ); } -} \ No newline at end of file +} \ No newline at end of file diff --git a/src/app/api/insights/route.ts b/src/app/api/insights/route.ts index e32857e..54718cc 100644 --- a/src/app/api/insights/route.ts +++ b/src/app/api/insights/route.ts @@ -8,14 +8,14 @@ const anthropic = new Anthropic({ export async function POST(request: Request) { try { const data = await request.json(); - + const response = await anthropic.messages.create({ model: 'claude-3-5-haiku-20241022', max_tokens: 1000, messages: [{ role: 'user', - content: `You are analyzing PLDG (Protocol Labs Developer Guild) engagement data. - Please provide insights and recommendations based on the following metrics: + content: `You are analyzing PLDG (Protocol Labs Developer Guild) engagement data. + Please provide insights based on the following metrics: Engagement Trends: ${JSON.stringify(data.engagementMetrics.trends, null, 2)} @@ -29,22 +29,34 @@ export async function POST(request: Request) { GitHub Activity: ${JSON.stringify(data.githubMetrics, null, 2)} - Please structure your analysis into these sections: - 1. Key Trends - 2. Areas of Concern - 3. Specific Recommendations - 4. Notable Achievements - - Format the response in markdown.` + Respond ONLY with a valid JSON object in exactly this shape, no markdown, no extra text: + { + "keyTrends": ["trend 1", "trend 2", "trend 3"], + "areasOfConcern": ["concern 1", "concern 2"], + "recommendations": ["recommendation 1", "recommendation 2"], + "achievements": ["achievement 1", "achievement 2"] + }` }] }); - return NextResponse.json({ - insights: response.content, - success: true - }); + const textContent = response.content[0]; + if (!('text' in textContent)) { + throw new Error('Unexpected response format from Claude'); + } + + let insights; + try { + insights = JSON.parse(textContent.text); + } catch { + throw new Error('Claude returned non-JSON response for insights'); + } + + return NextResponse.json({ insights, success: true }); } catch (error) { console.error('Error generating insights:', error); - return NextResponse.json({ error: 'Failed to generate insights', success: false }, { status: 500 }); + return NextResponse.json( + { error: 'Failed to generate insights', success: false }, + { status: 500 } + ); } -} \ No newline at end of file +} \ No newline at end of file