133 lines
6.1 KiB
JavaScript
133 lines
6.1 KiB
JavaScript
#!/usr/bin/env node
|
|
// HWLAB #803 noise-capture CLI.
|
|
//
|
|
// Captures the rendered Agent workspace (#code-agent-summary, per-message
|
|
// meta/pending/runtime/session/trace cards) from a live or local Cloud Web
|
|
// build and prints a structured JSON dump that can be diffed before/after a
|
|
// Web UI refactor.
|
|
//
|
|
// Usage:
|
|
// CHROMIUM_PATH=/usr/bin/chromium-browser \
|
|
// node tools/capture-issue-803-noise.mjs \
|
|
// --url http://74.48.78.17:17666/ --user admin --pass hwlab2026 \
|
|
// --png /tmp/hwlab-noise.png
|
|
// CHROMIUM_PATH=/usr/bin/chromium-browser \
|
|
// NOISE_USER=admin NOISE_PASS=hwlab2026 \
|
|
// node tools/capture-issue-803-noise.mjs
|
|
|
|
import { setTimeout as sleep } from "node:timers/promises";
|
|
|
|
import { importPlaywright, launchChromium } from "../scripts/src/browser-launcher.mjs";
|
|
|
|
function parseArgs(argv) {
|
|
const args = {
|
|
url: process.env.NOISE_URL ?? "http://74.48.78.17:17666/",
|
|
user: process.env.NOISE_USER ?? "admin",
|
|
pass: process.env.NOISE_PASS ?? "hwlab2026",
|
|
message: process.env.NOISE_MESSAGE ?? null,
|
|
viewport: process.env.NOISE_VIEWPORT ?? "1440x900",
|
|
png: process.env.NOISE_PNG ?? "/tmp/hwlab-noise.png"
|
|
};
|
|
for (let index = 0; index < argv.length; index += 1) {
|
|
const arg = argv[index];
|
|
if (arg === "--url") args.url = argv[++index];
|
|
else if (arg === "--user") args.user = argv[++index];
|
|
else if (arg === "--pass") args.pass = argv[++index];
|
|
else if (arg === "--message") args.message = argv[++index];
|
|
else if (arg === "--png") args.png = argv[++index];
|
|
else if (arg === "--viewport") args.viewport = argv[++index];
|
|
}
|
|
const [w, h] = args.viewport.split("x").map(Number);
|
|
args.viewportWidth = Number.isFinite(w) ? w : 1440;
|
|
args.viewportHeight = Number.isFinite(h) ? h : 900;
|
|
return args;
|
|
}
|
|
|
|
const args = parseArgs(process.argv.slice(2));
|
|
const { chromium } = await importPlaywright();
|
|
const browser = await launchChromium(chromium);
|
|
console.error(`[noise] browser ${JSON.stringify(browser.hwlabLaunchPlan ?? {})}`);
|
|
const ctx = await browser.newContext({ viewport: { width: args.viewportWidth, height: args.viewportHeight } });
|
|
const page = await ctx.newPage();
|
|
await page.goto(args.url, { waitUntil: "networkidle", timeout: 30000 });
|
|
try {
|
|
await page.locator("#login-username").fill(args.user, { timeout: 5000 });
|
|
await page.locator("#login-password").fill(args.pass);
|
|
await page.locator("#login-submit").click();
|
|
await page.locator("#command-input").waitFor({ state: "visible", timeout: 12000 });
|
|
} catch (error) {
|
|
console.error("[noise] login failed:", error instanceof Error ? error.message : String(error));
|
|
}
|
|
await page.waitForTimeout(1500);
|
|
if (args.message) {
|
|
try {
|
|
await page.locator("#command-input").fill(args.message, { timeout: 5000 });
|
|
await page.locator("#command-send").click();
|
|
await sleep(8000);
|
|
} catch (error) {
|
|
console.error("[noise] submit failed:", error instanceof Error ? error.message : String(error));
|
|
}
|
|
}
|
|
|
|
const data = await page.evaluate(() => {
|
|
const summary = document.querySelector("#code-agent-summary");
|
|
const summaryRect = summary?.getBoundingClientRect();
|
|
const summaryText = summary?.textContent?.replace(/\s+/gu, " ").trim().slice(0, 800) ?? null;
|
|
const summaryDetail = document.querySelector("#code-agent-summary-detail");
|
|
const summaryDetailRect = summaryDetail?.getBoundingClientRect();
|
|
const summaryDetailText = summaryDetail?.textContent?.replace(/\s+/gu, " ").trim().slice(0, 1500) ?? null;
|
|
const summaryIsOpen = summary ? summary.open === true : null;
|
|
const summaryDebugBtn = document.querySelector("#code-agent-debug-trigger");
|
|
const convList = document.querySelector("#conversation-list");
|
|
const convListRect = convList?.getBoundingClientRect();
|
|
const messages = [...document.querySelectorAll(".message-card")].map((card) => {
|
|
const rect = card.getBoundingClientRect();
|
|
const role = card.getAttribute("data-message-role")
|
|
?? [...card.classList].find((cls) => cls.startsWith("message-"))?.replace(/^message-/, "")
|
|
?? null;
|
|
const meta = card.querySelector(".message-meta")?.textContent?.replace(/\s+/gu, " ").trim() ?? null;
|
|
const pending = card.querySelector(".message-pending-context")?.textContent?.replace(/\s+/gu, " ").trim().slice(0, 600) ?? null;
|
|
const session = card.querySelector(".message-session-context")?.textContent?.replace(/\s+/gu, " ").trim().slice(0, 600) ?? null;
|
|
const runtime = card.querySelector(".message-runtime-path")?.textContent?.replace(/\s+/gu, " ").trim().slice(0, 600) ?? null;
|
|
const trace = card.querySelector(".message-trace")?.textContent?.replace(/\s+/gu, " ").trim().slice(0, 400) ?? null;
|
|
const traceEventsRect = card.querySelector(".message-trace-events")?.getBoundingClientRect();
|
|
const debugTrigger = card.querySelector(".debug-dialog-trigger");
|
|
const cardWidth = rect.width;
|
|
const tracePct = cardWidth > 0 && traceEventsRect ? Math.round((traceEventsRect.width / cardWidth) * 100) : null;
|
|
return {
|
|
role,
|
|
meta,
|
|
pending,
|
|
session,
|
|
runtime,
|
|
trace,
|
|
debugTriggerText: debugTrigger?.textContent ?? null,
|
|
cardWidth: Math.round(cardWidth),
|
|
traceEventsWidth: traceEventsRect ? Math.round(traceEventsRect.width) : null,
|
|
traceEventsPct: tracePct
|
|
};
|
|
});
|
|
const systemCount = messages.filter((m) => m.role === "system").length;
|
|
const roleCounts = messages.reduce((acc, m) => {
|
|
const key = m.role ?? "unknown";
|
|
acc[key] = (acc[key] ?? 0) + 1;
|
|
return acc;
|
|
}, {});
|
|
return {
|
|
summaryText,
|
|
summaryDetailText,
|
|
summaryIsOpen,
|
|
summaryDebugBtnExists: !!summaryDebugBtn,
|
|
summaryRect: summaryRect ? { width: Math.round(summaryRect.width), height: Math.round(summaryRect.height) } : null,
|
|
summaryDetailRect: summaryDetailRect ? { width: Math.round(summaryDetailRect.width), height: Math.round(summaryDetailRect.height) } : null,
|
|
convListRect: convListRect ? { width: Math.round(convListRect.width), height: Math.round(convListRect.height) } : null,
|
|
messageCount: messages.length,
|
|
systemMessageCount: systemCount,
|
|
roleCounts,
|
|
messages
|
|
};
|
|
});
|
|
console.log(JSON.stringify(data, null, 2));
|
|
await page.screenshot({ path: args.png, fullPage: false });
|
|
await browser.close();
|