Files
openclaw/src/cli/one-shot-exit.ts
T
dorukardahan 9344bb8b48 fix(cli): exit after model inspection output (#77904)
* fix(cli): exit after model inspection output

* fix(cli): drain stderr before one-shot exit

* fix(cli): exit after model inspection output

* fix(clownfish): address review for live-pr-inventory-20260706T090631-001 (1)

* fix(cli): defer model command exit until teardown

* test(cli): isolate one-shot exit spies

* fix(cli): defer models status check exit

* fix(cli): satisfy lint for Vitest markers

* fix(cli): always wait for stream flush callbacks

* test(cli): wait for deferred exit callback

---------

Co-authored-by: openclaw-clownfish[bot] <280122609+openclaw-clownfish[bot]@users.noreply.github.com>
Co-authored-by: Vincent Koc <25068+vincentkoc@users.noreply.github.com>
2026-07-06 06:16:59 -07:00

71 lines
1.9 KiB
TypeScript

import type { RuntimeEnv } from "../runtime.js";
import { defaultRuntime } from "../runtime.js";
type VitestWorkerMarkers = {
tinypoolState?: unknown;
vitestWorker?: unknown;
};
let requestedExitCode: number | undefined;
function resolveVitestWorkerMarkers(): VitestWorkerMarkers {
const processMarkers = process as NodeJS.Process & Record<string, unknown>;
const globalMarkers = globalThis as typeof globalThis & Record<string, unknown>;
return {
tinypoolState: processMarkers["__tinypool_state__"],
vitestWorker: globalMarkers["__vitest_worker__"],
};
}
function isVitestWorker(
env: NodeJS.ProcessEnv,
markers: VitestWorkerMarkers = resolveVitestWorkerMarkers(),
): boolean {
const hasVitestEnv =
env.VITEST === "true" ||
env.VITEST === "1" ||
env.VITEST_POOL_ID !== undefined ||
env.VITEST_WORKER_ID !== undefined;
return (
hasVitestEnv && (markers.tinypoolState !== undefined || markers.vitestWorker !== undefined)
);
}
export function requestExitAfterOneShotOutput(
runtime: RuntimeEnv = defaultRuntime,
exitCode = 0,
): boolean {
if (runtime !== defaultRuntime) {
return false;
}
requestedExitCode = exitCode;
return true;
}
export function flushExitAfterOneShotOutput(
runtime: RuntimeEnv = defaultRuntime,
env: NodeJS.ProcessEnv = process.env,
markers: VitestWorkerMarkers = resolveVitestWorkerMarkers(),
): void {
const exitCode = requestedExitCode;
requestedExitCode = undefined;
if (exitCode === undefined || runtime !== defaultRuntime || isVitestWorker(env, markers)) {
return;
}
const exit = () => runtime.exit(exitCode);
let pendingStreams = 2;
const drain = (stream: NodeJS.WriteStream) => {
stream.write("", () => {
pendingStreams -= 1;
if (pendingStreams === 0) {
setImmediate(exit);
}
});
};
drain(process.stdout);
drain(process.stderr);
}