- control-server.mjs runs chrome-control.mjs LOCALLY on the browser host, so a remote bot's controlBrowser (BROWSER_CONTROL_URL) drives real xdotool input on THIS screen instead of the bot machine. Published on the LAN. - controlBrowser tool posts to BROWSER_CONTROL_URL when set, else runs locally. - Drop hard depends_on ollama so a browser-host doesn't start Ollama. - gitignore .env.bak*/*.bak (a backup with tokens had been left untracked).
49 lines
2.1 KiB
JavaScript
49 lines
2.1 KiB
JavaScript
// Browser-control HTTP endpoint for the BROWSER HOST.
|
|
//
|
|
// The on-screen Chrome, the X display (:1), xdotool (real cursor/keyboard) and
|
|
// the broadcast capture all live on THIS machine. A remote `bot` on another PC
|
|
// therefore cannot drive them directly — it must send a command here, where
|
|
// chrome-control.mjs runs LOCALLY (real input lands on this host's screen,
|
|
// visible on its VNC / Go-Live).
|
|
//
|
|
// POST /control body: {"action":"navigate","url":"naver.com", ...}
|
|
// GET /health
|
|
//
|
|
// Internal-network use only (no auth, per deployment decision). Bind/port:
|
|
// BROWSER_CONTROL_BIND (default 0.0.0.0), BROWSER_CONTROL_PORT (default 8777)
|
|
import http from 'node:http';
|
|
import { execFile } from 'node:child_process';
|
|
import { fileURLToPath } from 'node:url';
|
|
import { dirname, join } from 'node:path';
|
|
|
|
const PORT = parseInt(process.env.BROWSER_CONTROL_PORT || '8777', 10);
|
|
const BIND = process.env.BROWSER_CONTROL_BIND || '0.0.0.0';
|
|
const SCRIPT = join(dirname(fileURLToPath(import.meta.url)), 'chrome-control.mjs');
|
|
|
|
const server = http.createServer((req, res) => {
|
|
if (req.method === 'GET' && req.url === '/health') {
|
|
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
res.end(JSON.stringify({ ok: true, host: 'browser' }));
|
|
return;
|
|
}
|
|
if (req.method !== 'POST') {
|
|
res.writeHead(405); res.end('POST /control');
|
|
return;
|
|
}
|
|
let body = '';
|
|
req.on('data', (c) => { body += c; if (body.length > 1e6) req.destroy(); });
|
|
req.on('end', () => {
|
|
// Run the action LOCALLY: chrome-control.mjs uses CDP + xdotool on this
|
|
// host, so the cursor really moves and text is typed on this screen.
|
|
execFile('node', [SCRIPT, body || '{}'], { timeout: 95_000, env: process.env }, (err, stdout, stderr) => {
|
|
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
const out = (stdout || '').trim();
|
|
res.end(out || JSON.stringify({ ok: false, error: String((stderr || '').trim() || err?.message || 'no output') }));
|
|
});
|
|
});
|
|
});
|
|
|
|
server.listen(PORT, BIND, () => {
|
|
console.log(`[control-server] listening on ${BIND}:${PORT} (browser host)`);
|
|
});
|