// 打开预览页 → 跑真实链路 → 依次预览三种控件状态并截图 import { spawn } from 'node:child_process'; import { mkdtempSync, writeFileSync } from 'node:fs'; import { tmpdir } from 'node:os'; import { join } from 'node:path'; const CHROME = 'C:/Users/QunLIn/.agent-browser/browsers/chrome-154.0.8037.92/chrome.exe'; const PORT = 9383; const URL_ = process.argv[2] || 'http://127.0.0.1:8791/'; const OUT = process.argv[3] || 'C:/Users/QunLIn/WorkBuddy/2026-10-02-15-13-24/.workbuddy/human-demo.png'; const sleep = (ms) => new Promise((r) => setTimeout(r, ms)); const userDir = mkdtempSync(join(tmpdir(), 'cdp-demo-')); const chrome = spawn(CHROME, ['--headless=new', `--remote-debugging-port=${PORT}`, `--user-data-dir=${userDir}`, '--no-first-run', '--disable-gpu', '--window-size=820,1400', 'about:blank'], { stdio: 'ignore' }); const PROBE_BOX = 'JSON.stringify((()=>{const w=document.querySelector(".atk-human-box");if(!w)return null;const b=w.getBoundingClientRect();const im=w.querySelector(".atk-human-img");return {cls:w.className,text:w.textContent.trim(),w:Math.round(b.width),h:Math.round(b.height),imgW:im?im.naturalWidth:0};})())'; try { for (let i = 0; i < 40; i++) { try { const r = await fetch(`http://127.0.0.1:${PORT}/json/version`); if (r.ok) break; } catch {} await sleep(300); } const tab = await (await fetch(`http://127.0.0.1:${PORT}/json/new?` + encodeURIComponent(URL_), { method: 'PUT' })).json(); const ws = new WebSocket(tab.webSocketDebuggerUrl); let id = 0; const pending = new Map(); ws.addEventListener('message', (e) => { const m = JSON.parse(e.data); if (m.id && pending.has(m.id)) { pending.get(m.id)(m); pending.delete(m.id); } }); await new Promise((res) => ws.addEventListener('open', res)); const send = (m, p = {}) => new Promise((res) => { const mid = ++id; pending.set(mid, res); ws.send(JSON.stringify({ id: mid, method: m, params: p })); }); const ev = async (expr) => { const r = await send('Runtime.evaluate', { expression: expr, returnByValue: true, awaitPromise: true }); return r.result?.result?.value ?? r.result?.value ?? null; }; await send('Runtime.enable'); await send('Page.enable'); await sleep(1500); console.log('— 页面标题:', await ev('document.title')); // 真实链路(浏览器真的算 PoW) await ev('__demo.runReal()'); await sleep(7000); console.log('— 真实链路日志:\n' + (await ev('document.getElementById("log").innerText'))); await ev('__demo.previewNone()'); await sleep(500); let s = await send('Page.captureScreenshot', { format: 'png' }); writeFileSync(OUT.replace(/\.png$/, '-none.png'), Buffer.from(s.result.data, 'base64')); await ev('__demo.previewClick()'); await sleep(500); console.log('— 点一下控件:', await ev(PROBE_BOX)); s = await send('Page.captureScreenshot', { format: 'png' }); writeFileSync(OUT.replace(/\.png$/, '-click.png'), Buffer.from(s.result.data, 'base64')); await ev('document.querySelector(".atk-human-box").click()'); await sleep(1400); console.log('— 点击后:', await ev(PROBE_BOX)); s = await send('Page.captureScreenshot', { format: 'png' }); writeFileSync(OUT.replace(/\.png$/, '-done.png'), Buffer.from(s.result.data, 'base64')); await ev('__demo.previewCaptcha()'); await sleep(3000); console.log('— 图形验证码:', await ev(PROBE_BOX)); s = await send('Page.captureScreenshot', { format: 'png' }); writeFileSync(OUT, Buffer.from(s.result.data, 'base64')); ws.close(); } catch (e) { console.error('ERROR', e.message); } finally { chrome.kill(); }