"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.createAnomalyRouter = createAnomalyRouter; const express_1 = require("express"); const fs_1 = __importDefault(require("fs")); function createAnomalyRouter(store, enrichmentService) { const router = (0, express_1.Router)(); // GET /api/anomalies — list all anomalies (optionally filtered) router.get('/', (req, res) => { const sessionId = req.query['sessionId']; const severity = req.query['severity']; const anomalies = store.getAllAnomalies(sessionId, severity); const mapped = anomalies.map((a) => ({ id: a.id, sessionId: store.findSessionForAnomaly(a.id), type: a.type, severity: a.severity, description: a.description, timestamp: a.timestamp, screenshotUrl: a.evidence.screenshotPath ? `/api/anomalies/${a.id}/screenshot` : undefined, })); res.json(mapped); }); // GET /api/anomalies/:anomalyId — full anomaly detail router.get('/:anomalyId', (req, res) => { const anomalyId = req.params['anomalyId']; const anomaly = store.getAnomaly(anomalyId); if (!anomaly) { res.status(404).json({ error: 'Anomaly not found' }); return; } res.json({ ...anomaly, sessionId: store.findSessionForAnomaly(anomaly.id), screenshotUrl: anomaly.evidence.screenshotPath ? `/api/anomalies/${anomaly.id}/screenshot` : undefined, }); }); // GET /api/anomalies/:anomalyId/screenshot — serve PNG router.get('/:anomalyId/screenshot', (req, res) => { const anomalyId = req.params['anomalyId']; const filePath = store.screenshotPath(anomalyId); if (!filePath || !fs_1.default.existsSync(filePath)) { res.status(404).json({ error: 'Screenshot not found' }); return; } res.setHeader('Content-Type', 'image/png'); fs_1.default.createReadStream(filePath).pipe(res); }); // POST /api/anomalies/:anomalyId/replay — trigger replay router.post('/:anomalyId/replay', async (req, res) => { const anomalyId = req.params['anomalyId']; try { const replayId = await store.replayAnomaly(anomalyId); res.json({ replayId, status: 'running' }); } catch (err) { const msg = err instanceof Error ? err.message : String(err); res.status(404).json({ error: msg }); } }); // POST /api/anomalies/:anomalyId/enrich — AI enrichment router.post('/:anomalyId/enrich', async (req, res) => { const anomalyId = req.params['anomalyId']; const anomaly = store.getAnomaly(anomalyId); if (!anomaly) { res.status(404).json({ error: 'Anomaly not found' }); return; } if (!enrichmentService?.hasProvider()) { res.status(503).json({ error: 'No AI provider configured (set ABE_AI_PROVIDER)' }); return; } const context = { domSnapshot: '', httpLog: anomaly.evidence.httpLog ?? [], consoleErrors: anomaly.evidence.rawErrors ?? [], actionTrace: anomaly.actionTrace, pageTitle: '', url: anomaly.actionTrace[anomaly.actionTrace.length - 1]?.url ?? '', }; // Run async — emit WS event when done void enrichmentService.enrich(anomaly, context); res.json({ status: 'enriching', anomalyId }); }); return router; }