import { db } from '@/lib/db' import { machines, sessionCodes } from '@/lib/db/schema' import { eq, and, isNotNull, gt } from 'drizzle-orm' import { NextRequest, NextResponse } from 'next/server' // Increment this when a new agent binary is published to /downloads/ const CURRENT_AGENT_VERSION = '1.0.0' export async function POST(request: NextRequest) { try { const { accessKey, agentVersion } = await request.json() if (!accessKey) { return NextResponse.json({ error: 'Access key required' }, { status: 400 }) } const result = await db .update(machines) .set({ isOnline: true, lastSeen: new Date(), agentVersion: agentVersion || undefined }) .where(eq(machines.accessKey, accessKey)) .returning({ id: machines.id }) if (!result[0]) { return NextResponse.json({ error: 'Invalid access key' }, { status: 401 }) } const machineId = result[0].id // Check for a pending connection (code used recently) const pending = await db .select() .from(sessionCodes) .where( and( eq(sessionCodes.machineId, machineId), eq(sessionCodes.isActive, true), gt(sessionCodes.expiresAt, new Date()), isNotNull(sessionCodes.usedAt) ) ) .orderBy(sessionCodes.usedAt) .limit(1) const needsUpdate = agentVersion && agentVersion !== CURRENT_AGENT_VERSION const appUrl = process.env.NEXT_PUBLIC_APP_URL || '' const downloadUrl = needsUpdate ? `${appUrl}/downloads/remotelink-agent-${process.platform === 'win32' ? 'windows.exe' : 'linux'}` : null return NextResponse.json({ success: true, pendingConnection: pending[0] ? { sessionCodeId: pending[0].id, usedBy: pending[0].usedBy } : null, updateAvailable: needsUpdate ? { version: CURRENT_AGENT_VERSION, downloadUrl } : null, }) } catch (error) { console.error('[Heartbeat] Error:', error) return NextResponse.json({ error: 'Internal server error' }, { status: 500 }) } }