import { spawnPnpmRunner } from "./pnpm-runner.mjs"; const forwardedArgs = []; let quietOverride; for (const arg of process.argv.slice(2)) { if (arg === "--") { continue; } if (arg === "--quiet" || arg === "--quiet-live") { quietOverride = "1"; continue; } if (arg === "--no-quiet" || arg === "--no-quiet-live") { quietOverride = "0"; continue; } forwardedArgs.push(arg); } const env = { ...process.env, OPENCLAW_LIVE_TEST: process.env.OPENCLAW_LIVE_TEST || "1", OPENCLAW_LIVE_TEST_QUIET: quietOverride ?? process.env.OPENCLAW_LIVE_TEST_QUIET ?? "1", }; function parsePositiveInt(value, fallback) { if (!value) { return fallback; } const parsed = Number.parseInt(value, 10); return Number.isFinite(parsed) && parsed > 0 ? parsed : fallback; } const heartbeatMs = parsePositiveInt(process.env.OPENCLAW_LIVE_WRAPPER_HEARTBEAT_MS, 20_000); const startedAt = Date.now(); let lastOutputAt = startedAt; const child = spawnPnpmRunner({ stdio: ["inherit", "pipe", "pipe"], pnpmArgs: ["exec", "vitest", "run", "--config", "vitest.live.config.ts", ...forwardedArgs], env, }); const noteOutput = () => { lastOutputAt = Date.now(); }; child.stdout?.on("data", (chunk) => { noteOutput(); process.stdout.write(chunk); }); child.stderr?.on("data", (chunk) => { noteOutput(); process.stderr.write(chunk); }); const heartbeat = setInterval(() => { const now = Date.now(); if (now - lastOutputAt < heartbeatMs) { return; } const elapsedSec = Math.max(1, Math.round((now - startedAt) / 1_000)); const quietSec = Math.max(1, Math.round((now - lastOutputAt) / 1_000)); process.stderr.write( `[test:live] still running (${elapsedSec}s elapsed, ${quietSec}s since last output)\n`, ); lastOutputAt = now; }, heartbeatMs); heartbeat.unref?.(); child.on("exit", (code, signal) => { clearInterval(heartbeat); if (signal) { process.kill(process.pid, signal); return; } process.exit(code ?? 1); }); child.on("error", (error) => { clearInterval(heartbeat); console.error(error); process.exit(1); });