Files
llm-atlas/scripts/check-deepseek-task-bootstrap-browser.mjs
T
2026-07-30 06:15:45 +08:00

303 lines
13 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { writeFileSync } from "node:fs";
const cdpPort = process.env.CDP_PORT ?? "9231";
const baseUrl = process.env.SITE_URL ?? "http://127.0.0.1:4327";
const pages = await fetch(`http://127.0.0.1:${cdpPort}/json/list`)
.then((response) => response.json());
const page = pages.find((entry) => entry.type === "page");
if (!page) throw new Error(`CDP ${cdpPort} 没有可用页面`);
const socket = new WebSocket(page.webSocketDebuggerUrl);
await new Promise((resolve, reject) => {
socket.addEventListener("open", resolve, { once: true });
socket.addEventListener("error", reject, { once: true });
});
let nextId = 0;
const pending = new Map();
const exceptions = [];
socket.addEventListener("message", (event) => {
const message = JSON.parse(event.data);
if (message.id && pending.has(message.id)) {
const { resolve, reject } = pending.get(message.id);
pending.delete(message.id);
if (message.error) reject(new Error(message.error.message));
else resolve(message.result);
}
if (message.method === "Runtime.exceptionThrown") {
exceptions.push(
message.params.exceptionDetails.exception?.description
?? message.params.exceptionDetails.text,
);
}
});
const command = (method, params = {}) => new Promise((resolve, reject) => {
const id = ++nextId;
pending.set(id, { resolve, reject });
socket.send(JSON.stringify({ id, method, params }));
});
const pause = (milliseconds) => new Promise(
(resolve) => setTimeout(resolve, milliseconds),
);
const evaluate = async (expression) => {
const result = await command("Runtime.evaluate", {
expression,
returnByValue: true,
awaitPromise: true,
});
if (result.exceptionDetails) {
throw new Error(
result.exceptionDetails.exception?.description
?? result.exceptionDetails.text,
);
}
return result.result.value;
};
const screenshot = async (path) => {
const result = await command("Page.captureScreenshot", {
format: "png",
captureBeyondViewport: false,
});
writeFileSync(path, Buffer.from(result.data, "base64"));
};
const assert = (condition, message) => {
if (!condition) throw new Error(message);
};
await command("Page.enable");
await command("Runtime.enable");
await command("Emulation.setDeviceMetricsOverride", {
width: 1440,
height: 1100,
deviceScaleFactor: 1,
mobile: false,
});
await command("Page.navigate", {
url: `${baseUrl}/deepseek/#task-bootstrap-crn`,
});
for (let attempt = 0; attempt < 100; attempt += 1) {
await pause(100);
if (await evaluate("document.readyState === 'complete'")) break;
}
const overview = await evaluate(`(() => {
const root = document.querySelector("[data-task-bootstrap-lab]");
if (!root) return null;
document.documentElement.style.scrollBehavior = "auto";
window.scrollTo(0, root.getBoundingClientRect().top + window.scrollY);
const facts = Object.fromEntries(
[...root.querySelectorAll(".tb-ledger article")].map((node) => [
node.querySelector("span").textContent.trim(),
node.querySelector("b").textContent.trim(),
]),
);
return {
tabs: root.querySelectorAll("[data-tb-tab]").length,
panels: root.querySelectorAll("[data-tb-panel]").length,
active: root.querySelector("[data-tb-panel]:not([hidden])")?.dataset.tbPanel,
bars: root.querySelectorAll(".uniform-bars article").length,
lanes: root.querySelectorAll(".token-lanes article").length,
laneTokens: root.querySelectorAll(".token-lanes article i").length,
facts,
labs: [...document.querySelectorAll(".page-facts > div")]
.find((node) => node.querySelector("dt")?.textContent.trim() === "LABS")
?.querySelector("dd")?.textContent.trim(),
status: [...document.querySelectorAll(".page-facts > div")]
.find((node) => node.querySelector("dt")?.textContent.trim() === "STATUS")
?.querySelector("dd")?.textContent.trim(),
documentOverflow: document.documentElement.scrollWidth
- document.documentElement.clientWidth,
};
})()`);
await pause(250);
await screenshot("/tmp/llm-atlas-task-bootstrap-sampler-desktop.png");
const bootstrap = await evaluate(`(() => {
const root = document.querySelector("[data-task-bootstrap-lab]");
root.querySelector('[data-tb-tab="bootstrap"]').click();
const read = () => ({
active: root.querySelector("[data-tb-panel]:not([hidden])").dataset.tbPanel,
conditionCards: [...root.querySelectorAll("[data-tb-condition-cards] article")]
.map((node) => node.querySelector("b").textContent.trim()),
forest: [...root.querySelectorAll("[data-tb-forest] > article")].map((node) => ({
label: node.querySelector("span").textContent.trim(),
point: node.querySelector(":scope > b").textContent.trim(),
band: node.querySelector("small").textContent.trim(),
clear: node.querySelector("u").classList.contains("clear"),
})),
robust: root.querySelector("[data-tb-robust-count]").textContent.trim(),
});
const codeCorrectness = read();
root.querySelector('[data-tb-metric="generated_tokens"]').click();
const codeLength = read();
root.querySelector('[data-tb-domain="math"]').click();
const mathLength = read();
return { codeCorrectness, codeLength, mathLength };
})()`);
await pause(150);
await screenshot("/tmp/llm-atlas-task-bootstrap-forest-desktop.png");
const taskExplorer = await evaluate(`(() => {
const root = document.querySelector("[data-task-bootstrap-lab]");
root.querySelector('[data-tb-tab="tasks"]').click();
const domain = root.querySelector("[data-tb-task-domain]");
const contrast = root.querySelector("[data-tb-task-contrast]");
domain.value = "math";
domain.dispatchEvent(new Event("change", { bubbles: true }));
contrast.value = "system_at_eos";
contrast.dispatchEvent(new Event("change", { bubbles: true }));
root.querySelector('[data-tb-task-page="2"]').click();
return {
active: root.querySelector("[data-tb-panel]:not([hidden])").dataset.tbPanel,
rows: root.querySelectorAll("[data-tb-task-rows] > article").length,
page: root.querySelector("[data-tb-task-page-label]").textContent.trim(),
selectedPage: root.querySelector('[data-tb-task-page][aria-pressed="true"]')
.dataset.tbTaskPage,
firstTask: root.querySelector("[data-tb-task-rows] > article span b")
.textContent.trim(),
transition: [...root.querySelectorAll("[data-tb-transition-cards] article")]
.map((node) => node.querySelector("b").textContent.trim()),
};
})()`);
const tape = await evaluate(`(() => {
const root = document.querySelector("[data-task-bootstrap-lab]");
root.querySelector('[data-tb-tab="tapes"]').click();
const domain = root.querySelector("[data-tb-tape-domain]");
const contrast = root.querySelector("[data-tb-tape-contrast]");
domain.value = "math";
domain.dispatchEvent(new Event("change", { bubbles: true }));
contrast.value = "system_at_eos";
contrast.dispatchEvent(new Event("change", { bubbles: true }));
return {
active: root.querySelector("[data-tb-panel]:not([hidden])").dataset.tbPanel,
rows: root.querySelectorAll("[data-tb-tape-rows] > article").length,
cells: root.querySelectorAll("[data-tb-tape-rows] > article > b").length,
means: [...root.querySelectorAll("[data-tb-tape-means] > b")]
.map((node) => node.textContent.trim()),
taskRange: root.querySelector("[data-tb-task-range]").textContent.trim(),
tapeRange: root.querySelector("[data-tb-tape-range]").textContent.trim(),
};
})()`);
const audit = await evaluate(`(() => {
const root = document.querySelector("[data-task-bootstrap-lab]");
root.querySelector('[data-tb-tab="audit"]').click();
return {
active: root.querySelector("[data-tb-panel]:not([hidden])").dataset.tbPanel,
fields: [...root.querySelectorAll(".replay-fields article")]
.map((node) => node.querySelector("b").textContent.trim()),
codeOutcomes: root.querySelectorAll(".failure-ledger > article:first-child > div").length,
mathOutcomes: root.querySelectorAll(".failure-ledger > article:last-child > div").length,
deviations: root.querySelectorAll(".deviation-ledger article").length,
artifacts: root.querySelectorAll(".artifact-chain article").length,
};
})()`);
const keyboard = await evaluate(`(() => {
const root = document.querySelector("[data-task-bootstrap-lab]");
const first = root.querySelector('[data-tb-tab="sampler"]');
first.click();
first.focus();
first.dispatchEvent(new KeyboardEvent("keydown", {
key: "ArrowRight",
bubbles: true,
}));
return {
selected: root.querySelector('[data-tb-tab][aria-selected="true"]').dataset.tbTab,
active: root.querySelector("[data-tb-panel]:not([hidden])").dataset.tbPanel,
focused: document.activeElement.dataset.tbTab,
};
})()`);
await command("Emulation.setDeviceMetricsOverride", {
width: 390,
height: 844,
deviceScaleFactor: 1,
mobile: true,
});
await pause(300);
const mobile = await evaluate(`(() => {
const root = document.querySelector("[data-task-bootstrap-lab]");
root.querySelector('[data-tb-tab="tasks"]').click();
root.scrollIntoView();
return {
documentOverflow: document.documentElement.scrollWidth
- document.documentElement.clientWidth,
rootOverflow: root.scrollWidth - root.clientWidth,
tableWidth: root.querySelector(".task-table").getBoundingClientRect().width,
tableScrollWidth: root.querySelector(".task-table").scrollWidth,
viewport: window.innerWidth,
};
})()`);
await screenshot("/tmp/llm-atlas-task-bootstrap-mobile.png");
assert(overview, "找不到任务 bootstrap 实验");
assert(overview.tabs === 5 && overview.panels === 5, "五页签/面板合同异常");
assert(overview.active === "sampler", "初始面板不是 sampler");
assert(overview.bars === 8, "uniform tape 前八步渲染异常");
assert(overview.lanes === 4 && overview.laneTokens === 32, "四条件 token lane 异常");
assert(overview.facts.TASKS === "32 + 32", "任务 headline 异常");
assert(overview.facts["FORMAL GRID"] === "352", "formal headline 异常");
assert(overview.facts["UNIFORM AUDIT"] === "352 / 352", "uniform headline 异常");
assert(overview.facts["FRESH PROCESS"] === "64 / 64", "replay headline 异常");
assert(overview.labs === "22 个可操作实验", "DeepSeek LABS 总账异常");
assert(overview.status === "八轮 · 864 条采样", "DeepSeek STATUS 总账异常");
assert(overview.documentOverflow <= 1, `桌面横向溢出 ${overview.documentOverflow}px`);
assert(bootstrap.codeCorrectness.active === "bootstrap", "bootstrap 面板切换异常");
assert(bootstrap.codeCorrectness.conditionCards.join("|") === "16 / 32 pass|16 / 32 pass|15 / 32 pass|12 / 32 pass", "Code 条件 pass 表异常");
assert(bootstrap.codeCorrectness.forest.length === 4, "forest contrast 数异常");
assert(bootstrap.codeCorrectness.robust === "0 / 4 bands 不跨 0", "Code correctness 带数异常");
assert(bootstrap.codeLength.robust === "2 / 4 bands 不跨 0", "Code length 带数异常");
assert(bootstrap.codeLength.forest.at(-1).point === "-130.9 tok", "Code system-period 长度异常");
assert(bootstrap.mathLength.robust === "1 / 4 bands 不跨 0", "Math length 带数异常");
assert(bootstrap.mathLength.forest.at(-1).point === "+25.1 tok", "Math system-period 长度异常");
assert(taskExplorer.active === "tasks", "逐题面板切换异常");
assert(taskExplorer.rows === 8 && taskExplorer.page === "17–24 / 32", "逐题分页异常");
assert(taskExplorer.selectedPage === "2", "逐题页按钮状态异常");
assert(taskExplorer.firstTask === "gsm8k/test/1050", "逐题页首任务异常");
assert(taskExplorer.transition.join("|") === "3 / 32|3 / 32|16 / 32|10 / 32", "Math system-EOS 转移异常");
assert(tape.active === "tapes", "tape 面板切换异常");
assert(tape.rows === 4 && tape.cells === 16, "4×4 tape matrix 异常");
assert(tape.means.join("|") === "0.00|+0.50|-0.25|+0.25", "Math system-EOS tape means 异常");
assert(tape.taskRange === "1.25" && tape.tapeRange === "1.00", "tape/task range 异常");
assert(audit.active === "audit", "审计面板切换异常");
assert(audit.fields.length === 12, "重放字段数不为 12");
assert(audit.fields.every((value) => value === "64 / 64"), "重放字段未全部 exact");
assert(audit.codeOutcomes === 6 && audit.mathOutcomes === 2, "失败分类数量异常");
assert(audit.deviations === 2, "偏离账数量异常");
assert(audit.artifacts === 4, "工件 hash 数量异常");
assert(
keyboard.selected === "bootstrap"
&& keyboard.active === "bootstrap"
&& keyboard.focused === "bootstrap",
"页签键盘导航异常",
);
assert(mobile.documentOverflow <= 1, `移动端 document 横向溢出 ${mobile.documentOverflow}px`);
assert(mobile.rootOverflow <= 1, `移动端实验横向溢出 ${mobile.rootOverflow}px`);
assert(mobile.tableWidth <= mobile.viewport, "移动端任务表容器超出 viewport");
assert(mobile.tableScrollWidth > mobile.tableWidth, "移动端任务表没有内部横向滚动");
assert(exceptions.length === 0, `浏览器异常:${exceptions.join(" | ")}`);
console.log(JSON.stringify({
overview,
bootstrap,
taskExplorer,
tape,
audit,
keyboard,
mobile,
screenshots: [
"/tmp/llm-atlas-task-bootstrap-sampler-desktop.png",
"/tmp/llm-atlas-task-bootstrap-forest-desktop.png",
"/tmp/llm-atlas-task-bootstrap-mobile.png",
],
}, null, 2));
socket.close();