76 lines
3.2 KiB
JavaScript
76 lines
3.2 KiB
JavaScript
// deploy/m2_probe5.js —— PipelineCard props 与渲染链探针(PM 使用,在远端运行)
|
||||
|
|
// 读组件实例 props(vnode.props.block)并比较与 pinia store 的引用/状态。
|
|||
|
|
const { chromium } = require('playwright');
|
|||
|
|
|
|||
|
|
(async () => {
|
|||
|
|
const browser = await chromium.launch();
|
|||
|
|
const ctx = await browser.newContext({ viewport: { width: 1440, height: 900 } });
|
|||
|
|
const page = await ctx.newPage();
|
|||
|
|
await page.goto('http://127.0.0.1:5180', { waitUntil: 'domcontentloaded' });
|
|||
|
|
await page.waitForSelector('.app-shell', { timeout: 15000 });
|
|||
|
|
await page.click('.new-task-btn');
|
|||
|
|
await page.waitForSelector('.composer textarea', { timeout: 15000 });
|
|||
|
|
await page.fill('.composer textarea', 'SPL gene family in rice');
|
|||
|
|
await page.click('.send-btn');
|
|||
|
|
|
|||
|
|
const t0 = Date.now();
|
|||
|
|
let last = '';
|
|||
|
|
while (Date.now() - t0 < 150000) {
|
|||
|
|
const snap = await page.evaluate(() => {
|
|||
|
|
const cardEl = document.querySelector('.pipeline-card');
|
|||
|
|
if (!cardEl) return { noCard: true };
|
|||
|
|
// 沿 vnode 链找组件实例
|
|||
|
|
let vnode = cardEl.__vueParentComponent;
|
|||
|
|
const found = [];
|
|||
|
|
for (let i = 0; i < 6 && vnode; i++) {
|
|||
|
|
const p = vnode.props;
|
|||
|
|
if (p && p.block) {
|
|||
|
|
const b = p.block;
|
|||
|
|
found.push({
|
|||
|
|
comp: vnode.type?.name || vnode.type?.__name || 'anon',
|
|||
|
|
blockStatus: b.status,
|
|||
|
|
steps: (b.steps || []).map((s) => `${s.phase}:${s.state}`).join(','),
|
|||
|
|
isReactiveProxy: !!b.__v_raw || typeof b.status !== 'string' || false,
|
|||
|
|
});
|
|||
|
|
// 读原始 store 对象比较(raw)
|
|||
|
|
const raw = b.__v_raw || b;
|
|||
|
|
found[found.length - 1].rawStatus = raw.status;
|
|||
|
|
found[found.length - 1].rawSteps = (raw.steps || []).map((s) => s.state).join(',');
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
vnode = vnode.parent;
|
|||
|
|
}
|
|||
|
|
// pinia 直接读
|
|||
|
|
let storeBlock = null;
|
|||
|
|
const rootEl = document.querySelector('#app') || document.querySelector('.app-shell');
|
|||
|
|
let n = rootEl;
|
|||
|
|
let app = null;
|
|||
|
|
while (n && !app) { if (n.__vue_app__) app = n.__vue_app__; n = n.__vueParentComponent?.parent || null; }
|
|||
|
|
if (app) {
|
|||
|
|
const pinia = app.config.globalProperties.$pinia;
|
|||
|
|
const chat = pinia._s.get('chat');
|
|||
|
|
const aMsg = [...chat.messages].reverse().find((m) => m.role === 'assistant');
|
|||
|
|
const sb = aMsg?.blocks?.[0];
|
|||
|
|
if (sb) storeBlock = { status: sb.status, steps: sb.steps.map((s) => s.state).join(',') };
|
|||
|
|
}
|
|||
|
|
return { found, storeBlock, domText: cardEl.textContent.slice(0, 60) };
|
|||
|
|
});
|
|||
|
|
const key = JSON.stringify(snap);
|
|||
|
|
if (key !== last) {
|
|||
|
|
last = key;
|
|||
|
|
console.log(`T+${Math.round((Date.now() - t0) / 1000)}s`, JSON.stringify(snap, null, 1));
|
|||
|
|
}
|
|||
|
|
// 流结束后看最终状态
|
|||
|
|
const doneNow = await page.evaluate(() => {
|
|||
|
|
const rootEl = document.querySelector('#app');
|
|||
|
|
let n = rootEl; let app = null;
|
|||
|
|
while (n && !app) { if (n.__vue_app__) app = n.__vue_app__; n = n.__vueParentComponent?.parent || null; }
|
|||
|
|
if (!app) return false;
|
|||
|
|
return !app.config.globalProperties.$pinia._s.get('chat').busy;
|
|||
|
|
});
|
|||
|
|
if (doneNow && Date.now() - t0 > 30000) break;
|
|||
|
|
await new Promise((r) => setTimeout(r, 2500));
|
|||
|
|
}
|
|||
|
|
await browser.close();
|
|||
|
|
})();
|