#!/usr/bin/env node import { createServer } from "node:http"; import { existsSync, readdirSync, readFileSync, statSync, } from "node:fs"; import path from "node:path"; import { fileURLToPath } from "node:url"; const scriptDir = path.dirname(fileURLToPath(import.meta.url)); const workspace = path.resolve(scriptDir, "../.."); const agentsDir = path.join(workspace, ".agents"); const runsDir = path.join(agentsDir, "runs"); const checkpointPath = path.join(agentsDir, "checkpoint.json"); const staticDir = path.join(agentsDir, "observability"); const port = parsePort(process.argv) || 4317; const server = createServer((req, res) => { const url = new URL(req.url || "/", `http://${req.headers.host || "localhost"}`); if (url.pathname === "/api/status") { const tail = parseTail(url.searchParams.get("tail")); sendJson(res, buildStatus(tail)); return; } serveStatic(res, url.pathname); }); server.listen(port, "127.0.0.1", () => { console.log(`Agent observability dashboard: http://127.0.0.1:${port}`); }); server.on("error", (error) => { console.error(`Could not start observability dashboard on 127.0.0.1:${port}`); console.error(error.message); process.exit(1); }); function parsePort(argv) { const index = argv.findIndex((arg) => arg === "--port" || arg === "-p"); if (index === -1) return null; const value = Number(argv[index + 1]); if (!Number.isInteger(value) || value < 1 || value > 65535) return null; return value; } function parseTail(value) { const parsed = Number(value); if (!Number.isInteger(parsed) || parsed < 0) return 80; return Math.min(parsed, 500); } function buildStatus(tailLines) { const checkpoint = readJsonIfExists(checkpointPath); const runs = listRuns(); const activeRunId = checkpoint?.active_run_id || findLatestRunId(runs); const activeRun = runs.find((run) => run.id === activeRunId) || null; return { generated_at: new Date().toISOString(), workspace, checkpoint, summary: { run_count: runs.length, active_run_id: activeRunId, current_phase: checkpoint?.current_phase || null, active_branch: checkpoint?.active_branch || null, blocker_count: Array.isArray(checkpoint?.blockers) ? checkpoint.blockers.length : 0, next_action: checkpoint?.next_action || null, }, runs, active_progress: activeRun ? readProgress(activeRun, tailLines) : null, }; } function listRuns() { if (!existsSync(runsDir)) return []; return readdirSync(runsDir) .map((name) => path.join(runsDir, name)) .filter((runPath) => statSync(runPath).isDirectory()) .map((runPath) => { const id = path.basename(runPath); const state = readJsonIfExists(path.join(runPath, "state.json")); const agents = normalizeAgents(readJsonIfExists(path.join(runPath, "agents.json"))); return { id, path: path.relative(workspace, runPath), state, agents: agents.map((agent) => ({ ...agent, lease_expired: isExpired(agent.lease_expires_at), })), mtime_ms: statSync(runPath).mtimeMs, }; }) .sort((a, b) => b.mtime_ms - a.mtime_ms); } function normalizeAgents(value) { if (!value) return []; if (Array.isArray(value)) return value; if (Array.isArray(value.agents)) return value.agents; return Object.entries(value).map(([role, agent]) => ({ role, ...(typeof agent === "object" && agent ? agent : { status: String(agent) }), })); } function findLatestRunId(runs) { if (runs.length === 0) return null; return runs.reduce((latest, run) => (run.mtime_ms > latest.mtime_ms ? run : latest)).id; } function readProgress(run, tailLines) { const runPath = path.join(workspace, run.path); const candidateNames = [ "progress.log", "implementation-log.md", "validation.md", "opus-proposal.md", "snarky-review.md", ]; const filePath = candidateNames .map((name) => path.join(runPath, name)) .find((candidate) => existsSync(candidate) && statSync(candidate).isFile()); if (!filePath) { return { run_id: run.id, path: null, lines: [], }; } const lines = readFileSync(filePath, "utf8").split(/\r?\n/); if (lines.length > 0 && lines[lines.length - 1] === "") { lines.pop(); } return { run_id: run.id, path: path.relative(workspace, filePath), lines: lines.slice(Math.max(0, lines.length - tailLines)), }; } function isExpired(value) { if (!value) return false; const time = Date.parse(value); if (!Number.isFinite(time)) return false; return time < Date.now(); } function readJsonIfExists(filePath) { if (!existsSync(filePath)) return null; try { return JSON.parse(readFileSync(filePath, "utf8")); } catch (error) { return { parse_error: error.message, }; } } function sendJson(res, value) { const body = JSON.stringify(value); res.writeHead(200, { "Content-Type": "application/json", "Content-Length": Buffer.byteLength(body), }); res.end(body); } function serveStatic(res, pathname) { const relative = pathname === "/" ? "index.html" : pathname.slice(1); const filePath = path.resolve(staticDir, relative); if (filePath !== staticDir && !filePath.startsWith(`${staticDir}${path.sep}`)) { sendNotFound(res); return; } if (!existsSync(filePath) || !statSync(filePath).isFile()) { sendNotFound(res); return; } const body = readFileSync(filePath); res.writeHead(200, { "Content-Type": contentType(filePath), "Content-Length": body.length, }); res.end(body); } function sendNotFound(res) { res.writeHead(404, { "Content-Type": "text/plain" }); res.end("Not found"); } function contentType(filePath) { const extension = path.extname(filePath); switch (extension) { case ".html": return "text/html; charset=utf-8"; case ".css": return "text/css; charset=utf-8"; case ".js": return "text/javascript; charset=utf-8"; case ".json": return "application/json"; default: return "application/octet-stream"; } }