export const dynamic = 'force-dynamic' import { NextRequest, NextResponse } from 'next/server' import { createClient } from '@/lib/supabase/server' import { getSession } from '@/lib/auth/get-session' import { createDeepSeekClient } from '@/lib/claude/client' import { getApiKey } from '@/lib/settings' export async function POST(request: NextRequest) { const session = await getSession() if (!session) return NextResponse.json({ error: 'Unauthorized' }, { status: 401 }) const supabase = await createClient() const since = new Date(Date.now() - 60_000).toISOString() const { count: recentCount } = await supabase .from('audit_log') .select('id', { count: 'exact', head: true }) .eq('changed_by', session.sub) .eq('action', 'ai_quality_check') .gte('changed_at', since) if ((recentCount ?? 0) > 0) return NextResponse.json({ error: 'Rate limited — please wait 60 seconds' }, { status: 429 }) const deepseekKey = await getApiKey('DEEPSEEK_API_KEY') const client = createDeepSeekClient(deepseekKey) let body: { description?: string; incident_type?: string } try { body = await request.json() } catch { return NextResponse.json({ error: 'Invalid JSON body' }, { status: 400 }) } if (!body.description || !body.incident_type) { return NextResponse.json({ error: 'description and incident_type required' }, { status: 422 }) } let res: Awaited> try { res = await client.chat.completions.create({ model: 'deepseek-chat', max_tokens: 1024, tools: [{ type: 'function', function: { name: 'assess_quality', description: 'Assess HSE incident report description quality', parameters: { type: 'object', properties: { score: { type: 'number', description: '1-10 quality score' }, passes: { type: 'boolean', description: 'True when score is 6 or above' }, feedback: { type: 'string', description: 'One-sentence quality summary' }, suggestions: { type: 'array', items: { type: 'string' }, description: 'Up to 3 concrete suggestions to improve the description', }, }, required: ['score', 'passes', 'feedback', 'suggestions'], }, }, }], tool_choice: { type: 'function', function: { name: 'assess_quality' } }, messages: [{ role: 'user', content: `You are an HSE reporting assistant for a Malaysian 3PL warehouse. Assess this incident report description. Incident type: ${body.incident_type} Description: ${body.description} Score 1–10 based on: specificity (location, time, persons involved), completeness (what happened + immediate actions), and clarity. Score 6 or above passes. If score is below 6, give up to 3 actionable suggestions.`, }], }) } catch { return NextResponse.json({ error: 'AI service unavailable' }, { status: 503 }) } const call = res.choices[0]?.message?.tool_calls?.[0] if (!call || call.type !== 'function') return NextResponse.json({ error: 'AI assessment failed' }, { status: 500 }) let input: { score?: unknown; passes?: unknown; feedback?: unknown; suggestions?: unknown } try { input = JSON.parse(call.function.arguments) } catch { return NextResponse.json({ error: 'AI returned unexpected structure' }, { status: 500 }) } if ( typeof input.score !== 'number' || typeof input.passes !== 'boolean' || typeof input.feedback !== 'string' || !Array.isArray(input.suggestions) ) { return NextResponse.json({ error: 'AI returned unexpected structure' }, { status: 500 }) } await supabase.rpc('write_audit_log', { p_table_name: 'incidents', p_record_id: session.sub, p_action: 'ai_quality_check', p_new_value: { score: input.score, passes: input.passes, model: 'deepseek-chat' } as never, }) return NextResponse.json(input) }