feat: add screenshot list and file serving endpoints for debug viewer
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
c93bce1b8b
commit
23cb8c890f
1 changed files with 58 additions and 0 deletions
|
|
@ -1,5 +1,7 @@
|
||||||
import express, { Express, Request, Response } from 'express';
|
import express, { Express, Request, Response } from 'express';
|
||||||
import { Server } from 'http';
|
import { Server } from 'http';
|
||||||
|
import path from 'path';
|
||||||
|
import fs from 'fs';
|
||||||
import { logger } from '../utils/logger';
|
import { logger } from '../utils/logger';
|
||||||
import { config } from '../config';
|
import { config } from '../config';
|
||||||
import { runAuthTests, runSingleVariant, getVariantIds } from '../bot/authTestProcedure';
|
import { runAuthTests, runSingleVariant, getVariantIds } from '../bot/authTestProcedure';
|
||||||
|
|
@ -184,5 +186,61 @@ export class HttpServer {
|
||||||
res.status(500).json({ error: (error as Error).message });
|
res.status(500).json({ error: (error as Error).message });
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// List screenshots for a session
|
||||||
|
// Filename format: {sessionId}-{step}-{timestamp}.png
|
||||||
|
this._app.get('/api/bot/screenshots/:sessionId', (req: Request, res: Response) => {
|
||||||
|
try {
|
||||||
|
const { sessionId } = req.params;
|
||||||
|
const screenshotDir = config.screenshotDir;
|
||||||
|
|
||||||
|
if (!fs.existsSync(screenshotDir)) {
|
||||||
|
res.json({ screenshots: [] });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const files = fs.readdirSync(screenshotDir)
|
||||||
|
.filter(f => f.startsWith(`${sessionId}-`) && f.endsWith('.png'))
|
||||||
|
.sort();
|
||||||
|
|
||||||
|
const screenshots = files.map(name => {
|
||||||
|
const stats = fs.statSync(path.join(screenshotDir, name));
|
||||||
|
const withoutExt = name.replace('.png', '');
|
||||||
|
const parts = withoutExt.split('-');
|
||||||
|
// sessionId is a UUID (5 parts joined by -), step follows, timestamp is last
|
||||||
|
const timestamp = parseInt(parts[parts.length - 1], 10) || 0;
|
||||||
|
const step = parts.slice(5, -1).join('-');
|
||||||
|
return { name, step, timestamp, sizeBytes: stats.size };
|
||||||
|
});
|
||||||
|
|
||||||
|
res.json({ screenshots });
|
||||||
|
} catch (error) {
|
||||||
|
logger.error('Error listing screenshots:', error);
|
||||||
|
res.status(500).json({ error: (error as Error).message });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Serve a single screenshot file
|
||||||
|
this._app.get('/api/bot/screenshots/file/:filename', (req: Request, res: Response) => {
|
||||||
|
try {
|
||||||
|
const { filename } = req.params;
|
||||||
|
|
||||||
|
if (!filename.endsWith('.png') || filename.includes('..') || filename.includes('/') || filename.includes('\\')) {
|
||||||
|
res.status(400).json({ error: 'Invalid filename' });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const filepath = path.join(config.screenshotDir, filename);
|
||||||
|
if (!fs.existsSync(filepath)) {
|
||||||
|
res.status(404).json({ error: 'Screenshot not found' });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
res.type('image/png').sendFile(path.resolve(filepath));
|
||||||
|
} catch (error) {
|
||||||
|
logger.error('Error serving screenshot:', error);
|
||||||
|
res.status(500).json({ error: (error as Error).message });
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue