Files
writing-agent/tools/st-request-diff/run-all.mjs
T

100 lines
4.2 KiB
JavaScript

// 一条命令跑全流程:起两个假上游 -> 逐个预设驱动真酒馆与本仓库 -> 出对比报告。
// 用法: node run-all.mjs [--only all|st|wa|diff] [--headful] [--preset 路径(可多次)] [--message 你好]
import { spawn } from "node:child_process";
import path from "node:path";
import { fileURLToPath } from "node:url";
import { waitFor } from "./cdp.mjs";
const HERE = path.dirname(fileURLToPath(import.meta.url));
const DEFAULT_PRESETS = [
"C:/Users/zed/Downloads/Reborn2.4.json",
"C:/Users/zed/Downloads/linux_1.3.json",
];
function readArgs(argv) {
const out = { only: "all", presets: [], message: "你好", stCapturePort: 8801, waCapturePort: 8802, stPort: 8123, headful: false, card: "tokens", out: path.join(HERE, "captures") };
for (let i = 0; i < argv.length; i++) {
const k = argv[i];
const v = argv[i + 1];
if (k === "--only") { out.only = String(v); i++; }
else if (k === "--preset") { out.presets.push(path.resolve(String(v))); i++; }
else if (k === "--message") { out.message = String(v); i++; }
else if (k === "--st-port") { out.stPort = Number(v); i++; }
else if (k === "--card") { out.card = String(v); i++; }
else if (k === "--headful") out.headful = true;
}
if (out.presets.length === 0) out.presets = DEFAULT_PRESETS.slice();
return out;
}
function run(script, args) {
return new Promise((resolve) => {
const child = spawn(process.execPath, [path.join(HERE, script), ...args], { cwd: HERE, stdio: ["ignore", "pipe", "pipe"] });
let out = "";
const pipe = (chunk) => { const text = String(chunk); out += text; process.stdout.write(text); };
child.stdout.on("data", pipe);
child.stderr.on("data", pipe);
child.on("close", (code) => resolve({ code, out }));
});
}
function lastJson(out) {
const lines = out.split(/\r?\n/).filter((l) => l.trim().startsWith("{") && l.includes("\"capture\""));
if (!lines.length) return null;
try { return JSON.parse(lines[lines.length - 1]); } catch (e) { return null; }
}
async function main() {
const args = readArgs(process.argv.slice(2));
const wantSt = args.only === "all" || args.only === "st";
const wantWa = args.only === "all" || args.only === "wa";
const wantDiff = args.only === "all" || args.only === "diff";
const captures = [];
const startCapture = (label, port) => {
const child = spawn(process.execPath, [path.join(HERE, "capture-server.mjs"), "--label", label, "--port", String(port), "--out", args.out], { cwd: HERE, stdio: "inherit" });
captures.push(child);
};
const waitMock = (port) => waitFor(async () => (await fetch("http://127.0.0.1:" + port + "/v1/models").catch(() => null)) !== null, { timeoutMs: 15000, label: "假上游 " + port });
try {
if (wantSt || wantWa) {
startCapture("st", args.stCapturePort);
startCapture("wa", args.waCapturePort);
await waitMock(args.stCapturePort);
await waitMock(args.waCapturePort);
}
const pairs = [];
for (const preset of args.presets) {
const pair = { preset };
if (wantSt) {
const r = await run("drive-st.mjs", ["--preset", preset, "--message", args.message, "--capture-port", String(args.stCapturePort), "--st-port", String(args.stPort), "--card", args.card, "--out", args.out, ...(args.headful ? ["--headful"] : [])]);
if (r.code !== 0) throw new Error("驱动酒馆失败: " + preset);
const meta = lastJson(r.out);
if (meta) pair.st = meta.capture;
}
if (wantWa) {
const r = await run("drive-wa.mjs", ["--preset", preset, "--message", args.message, "--capture-port", String(args.waCapturePort), "--out", args.out]);
if (r.code !== 0) throw new Error("驱动本仓库失败: " + preset);
const meta = lastJson(r.out);
if (meta) pair.wa = meta.capture;
}
pairs.push(pair);
}
if (wantDiff) {
for (const pair of pairs) {
if (!pair.st || !pair.wa) continue;
const r = await run("diff.mjs", ["--st", pair.st, "--wa", pair.wa, "--preset", pair.preset]);
if (r.code !== 0) throw new Error("对比失败: " + pair.preset);
}
}
} finally {
for (const child of captures) {
try { child.kill(); } catch (e) {}
}
}
}
await main();