Files

76 lines
3.2 KiB
JavaScript
Raw Permalink Normal View History

// 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();
})();