chore: establish YCode replication baseline and TODO
This commit is contained in:
commit
6dc59f89ba
1118 files changed
+196002
No files matched your search
@@ -0,0 +1,31 @@
|
||||
// YCode-only live DOM/screenshot inspection. Original WorkBuddy must use REA instead.
|
||||
import fs from 'node:fs/promises'
|
||||
const targets = await (await fetch('http://127.0.0.1:9237/json/list')).json()
|
||||
const setting = process.argv.includes('--settings')
|
||||
const target = targets.find(item => item.type === 'page' && item.url.includes('window=settings') === setting)
|
||||
if (!target) throw new Error('Requested YCode window not found')
|
||||
const socket = new WebSocket(target.webSocketDebuggerUrl)
|
||||
await new Promise(resolve => { socket.onopen = resolve })
|
||||
let sequence = 0
|
||||
const pending = new Map()
|
||||
socket.onmessage = event => { const message = JSON.parse(event.data); const task = pending.get(message.id); if (task) { pending.delete(message.id); message.error ? task.reject(message.error) : task.resolve(message.result) } }
|
||||
const send = (method, params = {}) => new Promise((resolve, reject) => { const id = ++sequence; pending.set(id, { resolve, reject }); socket.send(JSON.stringify({ id, method, params })) })
|
||||
const evaluate = async expression => { const response = await send('Runtime.evaluate', { expression, returnByValue: true, awaitPromise: true }); if (response.exceptionDetails) throw new Error(response.exceptionDetails.text); return response.result.value }
|
||||
const out = '.tmp/ycode-live-' + (setting ? 'settings' : 'main')
|
||||
try {
|
||||
await fs.mkdir(out, { recursive: true })
|
||||
const viewportArgument = process.argv.find(value => value.startsWith('--viewport='))
|
||||
if (viewportArgument) {
|
||||
const match = /^--viewport=(\d+)x(\d+)$/.exec(viewportArgument)
|
||||
if (!match || Number(match[1]) < 160 || Number(match[2]) < 160) throw new Error('Invalid viewport')
|
||||
await send('Emulation.setDeviceMetricsOverride', { width: Number(match[1]), height: Number(match[2]), deviceScaleFactor: 1, mobile: false })
|
||||
}
|
||||
if (process.argv.includes('--home')) await evaluate(`Array.from(document.querySelectorAll('.sidebar__tab')).find(button=>button.textContent.includes('新建任务'))?.click()`)
|
||||
await evaluate('document.fonts.ready.then(()=>true)')
|
||||
await evaluate('new Promise(resolve=>setTimeout(resolve,1200))')
|
||||
const layout = await evaluate(`(()=>{const selectors=['.sidebar','.chat-pane','.source-home','.wb-home-page','.wb-home-page__main-content','.wb-home-header','.wb-scene-tabs','.wb-home-composer','.wb-home-composer__chips','.wb-home-composer__input-slot','.wb-home-composer__below-input','.wb-composer','.cr-input-container','.wb-composer__workspace-footer','.cr-input-toolbar','.cr-permission-setting','.settings-modal','.settings-modal__nav','.settings-modal__content','.models-settings-panel','.models-settings-panel__editor','.sidebar-next'];return{viewport:{width:innerWidth,height:innerHeight},nodes:selectors.flatMap(selector=>Array.from(document.querySelectorAll(selector)).map(node=>{const box=node.getBoundingClientRect(),style=getComputedStyle(node);return{selector,bounds:[box.x,box.y,box.width,box.height],font:style.fontFamily,fontSize:style.fontSize,lineHeight:style.lineHeight,padding:style.padding,margin:style.margin,gap:style.gap,background:style.backgroundColor,display:style.display}}))}})()`)
|
||||
await fs.writeFile(out + '/layout.json', JSON.stringify(layout, null, 2))
|
||||
const screenshot = await send('Page.captureScreenshot', { format: 'png', fromSurface: true })
|
||||
await fs.writeFile(out + '/screen.png', Buffer.from(screenshot.data, 'base64'))
|
||||
console.log(JSON.stringify({ targetId: target.id, output: out, viewport: layout.viewport }))
|
||||
} finally { socket.close() }
|
||||
Reference in new issue
Block a user