import { NextRequest, NextResponse } from 'next/server' import { prisma } from '@/lib/prisma' import { calculateNextRun } from '@/lib/agents/schedule' export const dynamic = 'force-dynamic' /** * POST /api/cron/agents * * Finds all enabled, non-manual agents whose nextRun <= now, * executes them, and schedules the next run. * * Optional auth: set CRON_SECRET env var, callers must pass * Authorization: Bearer */ export async function POST(request: NextRequest) { const cronSecret = process.env.CRON_SECRET if (!cronSecret) { console.error('[CronAgents] CRON_SECRET env var is required but not set') return NextResponse.json({ error: 'Server misconfiguration' }, { status: 500 }) } const authHeader = request.headers.get('authorization') if (authHeader !== `Bearer ${cronSecret}`) { return NextResponse.json({ error: 'Unauthorized' }, { status: 401 }) } try { const now = new Date() const dueAgents = await prisma.agent.findMany({ where: { isEnabled: true, frequency: { not: 'manual' }, nextRun: { lte: now }, }, select: { id: true, userId: true, frequency: true, scheduledTime: true, scheduledDay: true, timezone: true, }, }) if (dueAgents.length === 0) { return NextResponse.json({ success: true, executed: 0 }) } console.log(`[CronAgents] Found ${dueAgents.length} due agent(s): ${dueAgents.map(a => a.id).join(', ')}`) const results: { id: string; success: boolean; error?: string }[] = [] // Execute agents sequentially (max 3 per cycle) for (const agent of dueAgents.slice(0, 3)) { try { console.log(`[CronAgents] Executing agent ${agent.id} (${agent.frequency})`) const { executeAgent } = await import('@/lib/ai/services/agent-executor.service') const result = await executeAgent(agent.id, agent.userId) // Calculate and set next run const nextRun = calculateNextRun({ frequency: agent.frequency, scheduledTime: agent.scheduledTime, scheduledDay: agent.scheduledDay, timezone: agent.timezone, }) console.log(`[CronAgents] Agent ${agent.id} done. success=${result.success}, nextRun=${nextRun?.toISOString() ?? 'null'}`) await prisma.agent.update({ where: { id: agent.id }, data: { nextRun }, }) results.push({ id: agent.id, success: result.success, error: result.error }) } catch (error) { const msg = error instanceof Error ? error.message : 'Unknown error' console.error(`[CronAgents] Agent ${agent.id} failed:`, msg) // Still schedule next run even on failure const nextRun = calculateNextRun({ frequency: agent.frequency, scheduledTime: agent.scheduledTime, scheduledDay: agent.scheduledDay, timezone: agent.timezone, }) await prisma.agent.update({ where: { id: agent.id }, data: { nextRun }, }) results.push({ id: agent.id, success: false, error: msg }) } } return NextResponse.json({ success: true, executed: results.length, results, }) } catch (error) { console.error('[CronAgents] Error:', error) return NextResponse.json( { success: false, error: 'Internal Server Error' }, { status: 500 } ) } }