import { WebSocketServer } from 'ws'; import { chromium } from 'playwright'; const PORT = 7702; const wss = new WebSocketServer({ port: PORT }); console.log(`Browser WS server on ws://localhost:${PORT}`); let browser = null; async function getBrowser() { if (!browser) browser = await chromium.launch({ headless: true, args: ['--no-sandbox','--disable-setuid-sandbox'] }); return browser; } wss.on('connection', async (ws) => { let context = null; let page = null; async function screenshot() { if (!page) return; try { const buf = await page.screenshot({ type: 'jpeg', quality: 70, fullPage: false }); ws.send(JSON.stringify({ type: 'screenshot', data: buf.toString('base64'), url: page.url() })); } catch(e) { ws.send(JSON.stringify({ type: 'error', msg: String(e) })); } } async function navigate(url) { try { if (!context) { const b = await getBrowser(); context = await b.newContext({ viewport: { width: 1280, height: 800 } }); page = await context.newPage(); } if (!url.startsWith('http')) url = 'https://' + url; ws.send(JSON.stringify({ type: 'loading' })); await page.goto(url, { timeout: 30000, waitUntil: 'domcontentloaded' }); await screenshot(); } catch(e) { ws.send(JSON.stringify({ type: 'error', msg: String(e) })); } } ws.on('message', async (msg) => { try { const m = JSON.parse(msg.toString()); if (m.type === 'navigate') await navigate(m.url); if (m.type === 'screenshot') await screenshot(); if (m.type === 'click') { if (page) { await page.mouse.click(m.x, m.y); await screenshot(); } } if (m.type === 'scroll') { if (page) { await page.mouse.wheel(0, m.dy); await screenshot(); } } if (m.type === 'type') { if (page) { await page.keyboard.type(m.text); await screenshot(); } } if (m.type === 'back') { if (page) { await page.goBack(); await screenshot(); } } if (m.type === 'fwd') { if (page) { await page.goForward(); await screenshot(); } } if (m.type === 'reload'){ if (page) { await page.reload(); await screenshot(); } } } catch(e) { ws.send(JSON.stringify({ type: 'error', msg: String(e) })); } }); ws.on('close', async () => { if (context) await context.close().catch(()=>{}); context = null; page = null; }); // Send welcome screenshot placeholder ws.send(JSON.stringify({ type: 'ready' })); });