Files
Momento/memento-note/app/api/cron/agents/route.ts
sepehr f0999263a0
All checks were successful
Deploy to Production / Build and Deploy (push) Successful in 42s
fix: remove nextRun recalculation from getAgents() that blocked cron
The getAgents() function was recalculating nextRun to future dates when
it found past values. This prevented the cron scheduler from ever
finding due agents (nextRun <= now was always false since getAgents
had already pushed it to the future).

Also fix toast polling: use null sentinel for agents without initial
actions so first execution is still detected. Limit cron to 3 agents
per cycle and add logging.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-26 13:00:55 +02:00

105 lines
3.0 KiB
TypeScript

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 <CRON_SECRET>
*/
export async function POST(request: NextRequest) {
// Optional auth
const cronSecret = process.env.CRON_SECRET
if (cronSecret) {
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)`)
const results: { id: string; success: boolean; error?: string }[] = []
// Execute agents sequentially (max 3 per cycle) to avoid overwhelming the AI provider
for (const agent of dueAgents.slice(0, 3)) {
try {
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,
})
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)
results.push({ id: agent.id, success: false, error: 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 },
})
}
}
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 }
)
}
}