// Read-only verification of YCode's actual IPC and renderer after an offline import. import fs from 'node:fs/promises' import assert from 'node:assert/strict' const endpoint = process.argv[2] || 'http://127.0.0.1:9237' const copy = JSON.parse(await fs.readFile('.tmp/workbuddy-copy-report.json', 'utf8')) assert.equal(copy.applied, true) const pause = ms => new Promise(resolve => setTimeout(resolve, ms)) let targets for (let attempt = 0; attempt < 80; attempt++) { try { targets = await (await fetch(`${endpoint}/json/list`)).json(); break } catch { await pause(200) } } const target = targets?.find(value => value.type === 'page' && (value.title === 'YCode' || value.url.includes('/out/renderer/'))) assert.ok(target, 'YCode renderer must be running') const socket = new WebSocket(target.webSocketDebuggerUrl) await new Promise((resolve, reject) => { socket.onopen = resolve; socket.onerror = reject }) let sequence = 0 const pending = new Map() const exceptions = [] socket.onmessage = event => { const message = JSON.parse(event.data) if (message.method === 'Runtime.exceptionThrown') exceptions.push(message.params.exceptionDetails.text) const request = pending.get(message.id) if (request) { pending.delete(message.id); message.error ? request.reject(new Error(message.error.message)) : request.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 })) }) await send('Runtime.enable') let result try { for (let attempt = 0; attempt < 80; attempt++) { result = await send('Runtime.evaluate', { expression: `(async()=>{ if(!window.ycode?.session)return null; const list=await window.ycode.session.list(); const session=list.find(item=>item.id===${JSON.stringify(copy.sessionId)}); if(!session)return null; const messages=await window.ycode.session.messages(session.id); return {session,sessionCount:list.length,messageCount:messages.length, tools:messages.flatMap(message=>message.tools??[]).length, images:messages.flatMap(message=>message.attachments??[]).filter(item=>item.previewUrl?.startsWith('data:image/')).length, userXmlWrappers:messages.filter(message=>message.role==='user'&&/|message.status==='streaming').length, renderedUserMessages:document.querySelectorAll('.msg--user').length, renderedAssistantMessages:document.querySelectorAll('.msg--assistant').length, titleVisible:[...document.querySelectorAll('.sidebar__item-title')].some(item=>item.textContent===session.title)} })()`, awaitPromise: true, returnByValue: true }) if (result.result?.value?.titleVisible && result.result.value.renderedUserMessages > 0) break if (result.exceptionDetails) throw new Error(result.exceptionDetails.text) await pause(250) } const actual = result.result.value assert.equal(actual.messageCount, copy.stats.importedMessages) assert.equal(actual.tools, copy.stats.toolCalls) assert.equal(actual.images, copy.stats.copiedImages) assert.equal(actual.sessionCount, copy.existingSessionCount + 1) assert.equal(actual.titleVisible, true) assert.equal(actual.userXmlWrappers, 0) assert.equal(actual.streaming, 0) assert.deepEqual(exceptions, []) const image = await send('Page.captureScreenshot', { format: 'png', fromSurface: true }) await fs.writeFile('.tmp/ycode-workbuddy-copy.png', Buffer.from(image.data, 'base64')) await fs.writeFile('.tmp/ycode-workbuddy-copy-ui-report.json', JSON.stringify({ ...actual, exceptions }, null, 2)) console.log(JSON.stringify({ ...actual, exceptions })) } finally { socket.close() }