openclaw
Version:
Multi-channel AI gateway with extensible messaging integrations
61 lines (60 loc) • 1.91 kB
JavaScript
import "./src-vebZIeLe.js";
import { l as toErrorObject } from "./error-coercion-D_-xJ90S.js";
import { t as expectDefined } from "./expect-CyE8FADM.js";
import "./errors-Db3Ymjlb.js";
import { spawn } from "node:child_process";
import { once } from "node:events";
//#region src/process/spawn-utils.ts
const DEFAULT_RETRY_CODES = ["EBADF"];
function resolveCommandStdio(params) {
return [
params.hasInput ? "pipe" : params.preferInherit ? "inherit" : "pipe",
"pipe",
"pipe"
];
}
function shouldRetry(err, codes) {
const code = err && typeof err === "object" && "code" in err ? String(err.code) : "";
return code.length > 0 && codes.includes(code);
}
async function spawnAndWaitForSpawn(spawnImpl, argv, options) {
const child = spawnImpl(expectDefined(argv[0], "argv entry at 0"), argv.slice(1), options);
try {
await once(child, "spawn");
} catch (err) {
throw toErrorObject(err, "Non-Error rejection");
}
return child;
}
async function spawnWithFallback(params) {
const spawnImpl = params.spawnImpl ?? spawn;
const retryCodes = params.retryCodes ?? DEFAULT_RETRY_CODES;
const baseOptions = { ...params.options };
const fallbacks = params.fallbacks ?? [];
const attempts = [{ options: baseOptions }, ...fallbacks.map((fallback) => ({
label: fallback.label,
options: {
...baseOptions,
...fallback.options
}
}))];
let lastError;
for (const [index, attempt] of attempts.entries()) {
params.assertCurrent?.();
try {
return {
child: await spawnAndWaitForSpawn(spawnImpl, params.argv, attempt.options),
usedFallback: index > 0,
fallbackLabel: attempt.label
};
} catch (err) {
lastError = err;
const nextFallback = fallbacks[index];
if (!nextFallback || !shouldRetry(err, retryCodes)) throw err;
params.onFallback?.(err, nextFallback);
}
}
throw lastError;
}
//#endregion
export { spawnWithFallback as n, resolveCommandStdio as t };