// chat 子面板 DOM 结构判据(2026-10-05)。
//
// ## 要判的是什么
//
// 实测故障:对话页里「终端 / 运行中命令 / 记忆 / 上下文 / 知识」五个页签
// 点进去全是空白,只有「对话」和「星图」正常。
//
// 根因是 **HTML 少一个 **:构造星图面板的那段 HTML 里有 4 个
//
`,
);
if (startIdx < 0) {
console.error("定位不到 chat 面板段落 —— app.js 结构可能已变");
process.exit(1);
}
const lastIdx = src.indexOf("chat-panel-knowledge");
const seg = src.slice(startIdx, lastIdx + 4000);
// 把跨行拼接的字符串还原成一段连续 HTML:
// '...' + \n '...' → '...'
const html = seg
.replace(/'\s*\+\s*\n\s*'/g, "")
.replace(/'\s*\+\s*'/g, "")
.replace(/"/g, "'");
const opens = (html.match(/
/g) || []).length;
check(
"chat 面板段落 div 标签配平",
opens === closes,
`开 ${opens} / 闭 ${closes},差 ${opens - closes} —— ` +
"少一个
会让后面所有面板被塞进前一个面板内部(表现为空白)",
);
// ── 2) 每个 chat-panel 自身也必须配平 ─────────────────────────────
//
// 总数配平还不够:某处多一个
、另一处少一个,总数仍为 0。
// 逐面板断言能定位到具体是哪个。
const PANELS = ["chat", "starmap", "terminal", "cmd", "memory", "context", "knowledge"];
const unbalanced = [];
for (const name of PANELS) {
const marker = `id='chat-panel-${name}'`;
const at = html.indexOf(marker);
if (at < 0) {
unbalanced.push(`${name}(未找到)`);
continue;
}
// 从该面板的 /g) || []).length;
if (o !== c) unbalanced.push(`${name}(开${o}/闭${c})`);
}
check(
"各子面板独立配平",
unbalanced.length === 0,
unbalanced.length ? "不配平:" + unbalanced.join("、") : "",
);
// ── 3) 所有 chat-panel 必须同属一个父容器 ─────────────────────────
//
// 形态判据:源码里每个面板片段的起始处都应是独立的
'(一个字符串字面量的结束)或 +(拼接)。
const nested = [];
for (const name of PANELS) {
const marker = `id='chat-panel-${name}'`;
const at = html.indexOf(marker);
if (at < 0) continue;
const from = html.lastIndexOf("
${opens} /
${closes}`);
console.log(` 面板数: ${PANELS.length}`);
console.log("");
if (failures > 0) {
console.log(`失败 ${failures} 条`);
process.exit(1);
}
console.log("全部通过");