You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
69 lines
1.7 KiB
69 lines
1.7 KiB
import fs from "node:fs";
|
|
import readline from "node:readline";
|
|
import { stdin as input, stdout as output } from "node:process";
|
|
|
|
const POLL_MS = 400;
|
|
|
|
function sleep(ms: number): Promise<void> {
|
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
}
|
|
|
|
function consumeTrigger(triggerPath: string): void {
|
|
if (fs.existsSync(triggerPath)) {
|
|
fs.rmSync(triggerPath, { force: true });
|
|
}
|
|
}
|
|
|
|
async function waitForTriggerFile(
|
|
triggerPath: string,
|
|
label: string,
|
|
): Promise<void> {
|
|
consumeTrigger(triggerPath);
|
|
const rel = triggerPath.replace(/\\/g, "/");
|
|
console.log(`
|
|
[录证] ${label} — 文件触发
|
|
PowerShell: New-Item -ItemType File -Force -Path "${rel}"
|
|
或 CMD: type nul > "${rel}"
|
|
`);
|
|
|
|
while (!fs.existsSync(triggerPath)) {
|
|
await sleep(POLL_MS);
|
|
}
|
|
consumeTrigger(triggerPath);
|
|
console.log(`[录证] ${label} 已触发`);
|
|
}
|
|
|
|
export async function waitForHumanCheckpoint(options: {
|
|
label: string;
|
|
message: string;
|
|
triggerPath: string;
|
|
rl?: readline.Interface | null;
|
|
}): Promise<void> {
|
|
const useFileTrigger =
|
|
process.env.HUMAN_RECORD_FILE_TRIGGER === "1" || !process.stdin.isTTY;
|
|
|
|
console.log(`\n[录证] ── ${options.label} ──`);
|
|
console.log(options.message);
|
|
|
|
if (useFileTrigger) {
|
|
await waitForTriggerFile(options.triggerPath, options.label);
|
|
return;
|
|
}
|
|
|
|
const rl =
|
|
options.rl ??
|
|
readline.createInterface({ input, output, terminal: true });
|
|
|
|
await new Promise<void>((resolve) => {
|
|
rl.question("\n操作完成后按 Enter 继续… ", () => resolve());
|
|
});
|
|
|
|
if (!options.rl) {
|
|
rl.close();
|
|
}
|
|
}
|
|
|
|
export function createSharedReadline(): readline.Interface {
|
|
return readline.createInterface({ input, output, terminal: true });
|
|
}
|