Spaces:
Sleeping
Sleeping
| import { NextRequest, NextResponse } from 'next/server'; | |
| import { | |
| intakeMessage, | |
| parseIntent, | |
| retrieveContext, | |
| evaluateTiming, | |
| synthesize, | |
| type Synthesis, | |
| } from '@/lib/defrag/pipeline'; | |
| // Stage 6: Safety and Scope Check | |
| function applySafetyFilter(synthesis: Synthesis): { pass: boolean; reason?: string } { | |
| // Ensure relational focus, non-diagnostic, emotionally safe | |
| if (synthesis.userState.includes('diagnose') || synthesis.userState.includes('disorder')) { | |
| return { pass: false, reason: 'Diagnostic language detected' }; | |
| } | |
| return { pass: true }; | |
| } | |
| // Stage 7: Response Generation (using OpenAI) | |
| async function generateResponse(synthesis: Synthesis): Promise<string> { | |
| const systemPrompt = `You are the DEFRAG AI — a relational intelligence system. | |
| Your role: | |
| - Interpret relational dynamics using structured context | |
| - Translate perception differences between people | |
| - Offer practical, grounded guidance | |
| - Maintain calm, emotionally mature tone | |
| - Never diagnose or use clinical labels | |
| - Focus on relational understanding, not general advice | |
| Current synthesis: | |
| User state: ${synthesis.userState} | |
| Other state: ${synthesis.otherState} | |
| Dynamic: ${synthesis.dynamicBetween} | |
| Timing: ${synthesis.timingSuggestion} | |
| Generate a response that: | |
| 1. Acknowledges the user's experience | |
| 2. Explains the relational dynamic | |
| 3. Translates the other person's likely perspective | |
| 4. Offers 2-3 practical next steps | |
| 5. Returns agency to the user`; | |
| // In production: call OpenAI API | |
| // For prototype: return structured mock based on synthesis | |
| const mockResponse = `That makes sense. ${synthesis.userState} | |
| ${synthesis.otherState} | |
| ${synthesis.dynamicBetween} | |
| ${synthesis.timingSuggestion} | |
| Here are a few approaches you could try: | |
| - Start from what you want more of, rather than what feels frustrating | |
| - Ask for their perspective before sharing your own | |
| - If the moment feels charged, waiting could give the conversation a better chance | |
| The choice is yours.`; | |
| return mockResponse; | |
| } | |
| // Stage 8: Follow-up Actions | |
| function attachFollowUpActions(synthesis: Synthesis) { | |
| return [ | |
| { id: 'why', label: 'What makes you say that?', action: 'explain_reasoning' }, | |
| { id: 'retry', label: 'Try another approach', action: 'regenerate' }, | |
| { id: 'simulate', label: 'Practice the conversation', action: 'start_simulation' }, | |
| { id: 'challenge', label: "That doesn't sound like them", action: 'correct_model' }, | |
| ]; | |
| } | |
| // Full Pipeline Orchestration | |
| export async function POST(request: NextRequest) { | |
| try { | |
| const { message } = await request.json(); | |
| if (!message || typeof message !== 'string') { | |
| return NextResponse.json({ error: 'Invalid message' }, { status: 400 }); | |
| } | |
| // Stage 1: Intake | |
| const intake = intakeMessage(message); | |
| // Stage 2: Parse | |
| const situation = parseIntent(message, intake); | |
| // Stage 3: Retrieve Context | |
| const context = retrieveContext(situation); | |
| // Stage 4: Timing Evaluation | |
| const timing = evaluateTiming(context); | |
| // Stage 5: Synthesis | |
| const synthesis = synthesize(situation, context, timing); | |
| // Stage 6: Safety Check | |
| const safety = applySafetyFilter(synthesis); | |
| if (!safety.pass) { | |
| return NextResponse.json( | |
| { error: 'Safety filter triggered', reason: safety.reason }, | |
| { status: 400 } | |
| ); | |
| } | |
| // Stage 7: Response Generation | |
| const response = await generateResponse(synthesis); | |
| // Stage 8: Attach Follow-up Actions | |
| const actions = attachFollowUpActions(synthesis); | |
| // Return structured response | |
| return NextResponse.json({ | |
| response, | |
| synthesis: { | |
| intent: intake.messageClass, | |
| relationship: situation.primaryRelationship, | |
| dynamic: situation.dynamic, | |
| timing: timing.assessment, | |
| }, | |
| actions, | |
| }); | |
| } catch (error) { | |
| console.error('Pipeline error:', error); | |
| return NextResponse.json({ error: 'Internal pipeline error' }, { status: 500 }); | |
| } | |
| } | |