#!/usr/bin/env tsx /** * 按 canonical 路径 id 启动 Playwright codegen 录制 * * npm run record:priority1-path -- F04-ftl-open-deck-flatbed * npm run record:priority1-path -- list */ import { spawn } from "node:child_process"; import fs from "node:fs"; import path from "node:path"; import { PRIORITY1_CANONICAL_PATHS, formatPriority1InputSummary, } from "@/workers/rpa/priority1/demo-input"; import { buildPriority1FormPlan } from "@/workers/rpa/priority1/form-logic-map"; import { DEFAULT_PRIORITY1_QUOTE_URL, isForbiddenPriority1QuoteUrl, } from "./record-priority1"; const ROOT = process.cwd(); const OUTPUT_DIR = path.join(ROOT, ".rpa", "recordings"); const STORAGE_PATH = process.env.PRIORITY1_STORAGE_STATE_PATH?.trim() || path.join(ROOT, ".rpa", "priority1-storage.json"); function formatTimestamp(): string { const d = new Date(); const pad = (n: number) => String(n).padStart(2, "0"); return `${d.getFullYear()}${pad(d.getMonth() + 1)}${pad(d.getDate())}-${pad(d.getHours())}${pad(d.getMinutes())}${pad(d.getSeconds())}`; } function listPaths(): void { console.log("\nPriority1 canonical 录制清单(24 条):\n"); for (const p of PRIORITY1_CANONICAL_PATHS) { console.log(` ${p.id.padEnd(32)} ${p.title} [${p.verified}]`); } console.log("\n用法: npm run record:priority1-path -- \n"); } function main(): void { const pathId = process.argv[2]?.trim(); if (!pathId || pathId === "-h" || pathId === "--help") { console.log("用法: npm run record:priority1-path -- "); listPaths(); process.exit(0); } if (pathId === "list") { listPaths(); process.exit(0); } const canonical = PRIORITY1_CANONICAL_PATHS.find( (p) => p.id === pathId || p.id.startsWith(pathId), ); if (!canonical) { console.error(`未找到路径: ${pathId}`); listPaths(); process.exit(1); } const startUrl = DEFAULT_PRIORITY1_QUOTE_URL; if (isForbiddenPriority1QuoteUrl(startUrl)) { console.error("禁止入口 URL"); process.exit(1); } fs.mkdirSync(OUTPUT_DIR, { recursive: true }); fs.mkdirSync(path.dirname(STORAGE_PATH), { recursive: true }); const outputFile = path.join( OUTPUT_DIR, `priority1-${canonical.id}-${formatTimestamp()}.js`, ); console.log("\n=== Priority1 单路径录制 ==="); console.log(`路径: ${canonical.id} — ${canonical.title}`); console.log(`画像: ${canonical.persona}`); console.log("─".repeat(50)); console.log(formatPriority1InputSummary(canonical.input)); console.log("─".repeat(50)); console.log("[form-logic-map] Step 2 关键步骤:"); for (const row of buildPriority1FormPlan(canonical.input).filter((p) => p.step === "step2")) { console.log(` ${row.order}. ${row.field.label} ← ${row.value}`); } console.log("─".repeat(50)); console.log(`产出: ${outputFile}`); console.log("录到报价页出现后再关闭 codegen\n"); const args = [ "playwright", "codegen", "--target=javascript", "-o", outputFile, `--save-storage=${STORAGE_PATH}`, ]; if (fs.existsSync(STORAGE_PATH)) { args.push(`--load-storage=${STORAGE_PATH}`); } args.push(startUrl); const child = spawn("npx", args, { stdio: "inherit", shell: true, cwd: ROOT, env: { ...process.env, RPA_HEADLESS: "false" }, }); child.on("exit", (code) => process.exit(code ?? 0)); } main();