naisys
Version:
NAISYS - Autonomous AI agent runner with built-in context management and cost tracking
79 lines • 3.02 kB
JavaScript
import { spawn } from "child_process";
/** 75 = EX_TEMPFAIL, reused here as an internal "restart requested" exit code. */
export const RESTART_EXIT_CODE = 75;
export const RESTART_WRAPPER_ACTIVE_ENV = "NAISYS_RESTART_WRAPPER_ACTIVE";
export const RESTART_WRAPPER_CHILD_ENV = "NAISYS_RESTART_WRAPPER_CHILD";
export const DISABLE_RESTART_WRAPPER_ENV = "NAISYS_DISABLE_RESTART_WRAPPER";
/** Flags that should only apply to the first invocation and be dropped on auto-update restarts. */
const ONE_SHOT_FLAGS = ["--setup"];
export function stripOneShotFlags(args) {
return args.filter((arg) => !ONE_SHOT_FLAGS.some((flag) => arg === flag || arg.startsWith(`${flag}=`)));
}
const POSIX_FORWARD_SIGNALS = ["SIGINT", "SIGTERM", "SIGHUP"];
const WINDOWS_FORWARD_SIGNALS = ["SIGINT", "SIGTERM"];
const SIGNAL_EXIT_CODES = {
SIGHUP: 129,
SIGINT: 130,
SIGTERM: 143,
};
export function isRestartWrapperActive(env = process.env) {
return env[RESTART_WRAPPER_ACTIVE_ENV] === "1";
}
export function shouldUseRestartWrapper(argv = process.argv, env = process.env) {
const usesHub = argv.some((arg) => arg === "--hub" || arg.startsWith("--hub=")) ||
argv.includes("--integrated-hub");
const autoUpdateDisabled = argv.includes("--no-auto-update");
return (usesHub &&
!autoUpdateDisabled &&
!env.pm_id &&
env[RESTART_WRAPPER_CHILD_ENV] !== "1" &&
env[DISABLE_RESTART_WRAPPER_ENV] !== "1");
}
export function getRestartWrapperSignals(platform = process.platform) {
return platform === "win32" ? WINDOWS_FORWARD_SIGNALS : POSIX_FORWARD_SIGNALS;
}
export function getExitCodeForSignal(signal) {
if (!signal)
return 1;
return SIGNAL_EXIT_CODES[signal] ?? 1;
}
export async function runWithRestartWrapper() {
let activeChild = null;
const forwardSignal = (signal) => {
if (activeChild && activeChild.exitCode === null) {
activeChild.kill(signal);
}
};
for (const signal of getRestartWrapperSignals()) {
process.on(signal, () => forwardSignal(signal));
}
let childArgs = process.argv.slice(1);
while (true) {
activeChild = spawn(process.argv[0], childArgs, {
cwd: process.cwd(),
stdio: "inherit",
env: {
...process.env,
[RESTART_WRAPPER_ACTIVE_ENV]: "1",
[RESTART_WRAPPER_CHILD_ENV]: "1",
},
});
const exitCode = await waitForExit(activeChild);
activeChild = null;
if (exitCode === RESTART_EXIT_CODE) {
console.log("[NAISYS] Restarting...");
childArgs = stripOneShotFlags(childArgs);
continue;
}
return exitCode;
}
}
function waitForExit(child) {
return new Promise((resolve, reject) => {
child.once("error", reject);
child.once("exit", (code, signal) => {
resolve(code ?? getExitCodeForSignal(signal));
});
});
}
//# sourceMappingURL=restartManager.js.map