export const prerender = false; import type { APIRoute } from "astro"; import { execSync } from "node:child_process"; import { readdirSync, statSync } from "node:fs"; import { resolve, join } from "node:path"; const HEARTBEATS_DIR = resolve("/Users/ace/palacering/palaceplatform/heartbeats"); const LABELS: Record = { "heartbeats": "com.manglasabang.heartbeats", "mail-push": "com.manglasabang.mail-push", "market-report": "com.manglasabang.market-report", "morning-briefing": "com.manglasabang.morning-briefing", "radar": "com.manglasabang.radar", "self-heal": "com.manglasabang.self-heal-palacecode,com.manglasabang.self-heal-palacemail", "trademark-watch": "com.manglasabang.trademark-watch", }; function getLoadedLabels(): Set { try { const out = execSync("launchctl list", { encoding: "utf-8", timeout: 5000 }); const labels = new Set(); for (const line of out.split("\n")) { const parts = line.trim().split(/\s+/); if (parts.length >= 3) labels.add(parts[2]); } return labels; } catch { return new Set(); } } function getLastRun(name: string): string | null { try { const logsDir = join(HEARTBEATS_DIR, name, "logs"); const candidates = ["out.log", "palacecode-out.log", "palacemail-out.log"]; let latest: Date | null = null; for (const f of candidates) { try { const st = statSync(join(logsDir, f)); if (!latest || st.mtime > latest) latest = st.mtime; } catch {} } return latest ? latest.toISOString() : null; } catch { return null; } } export const GET: APIRoute = async () => { const loaded = getLoadedLabels(); const dirs = readdirSync(HEARTBEATS_DIR).filter((d) => { try { return statSync(join(HEARTBEATS_DIR, d)).isDirectory(); } catch { return false; } }); const result: Record = {}; for (const dir of dirs) { const labelStr = LABELS[dir] || null; const labels = labelStr ? labelStr.split(",") : []; result[dir] = { loaded: labels.length > 0 ? labels.every((l) => loaded.has(l)) : false, label: labelStr, lastRun: getLastRun(dir), }; } return new Response(JSON.stringify(result), { status: 200, headers: { "Content-Type": "application/json" }, }); };