openclaw
Version:
Multi-channel AI gateway with extensible messaging integrations
108 lines (107 loc) • 3.83 kB
JavaScript
import { a as resolveConnectChallengeTimeoutMs, o as resolveFiniteTimeoutDelayMs } from "./timeouts-D2XMKe-X.js";
//#region packages/gateway-client/src/event-loop-ready.ts
const DEFAULT_MAX_WAIT_MS = 1e4;
const DEFAULT_INTERVAL_MS = 1;
const DEFAULT_DRIFT_THRESHOLD_MS = 200;
const DEFAULT_CONSECUTIVE_READY_CHECKS = 2;
function resolvePositiveInteger(value, fallback) {
return Number.isFinite(value) && value !== void 0 ? Math.max(1, Math.floor(value)) : fallback;
}
/** Waits until timer drift stays low for consecutive checks, or aborts/times out. */
async function waitForEventLoopReady(options = {}) {
const maxWaitMs = resolveFiniteTimeoutDelayMs(options.maxWaitMs, DEFAULT_MAX_WAIT_MS, { minMs: 0 });
const intervalMs = resolveFiniteTimeoutDelayMs(options.intervalMs, DEFAULT_INTERVAL_MS);
const driftThresholdMs = resolvePositiveInteger(options.driftThresholdMs, DEFAULT_DRIFT_THRESHOLD_MS);
const consecutiveReadyChecks = resolvePositiveInteger(options.consecutiveReadyChecks, DEFAULT_CONSECUTIVE_READY_CHECKS);
const signal = options.signal;
const startedAt = Date.now();
let readyChecks = 0;
let checks = 0;
let maxDriftMs = 0;
return await new Promise((resolve) => {
let settled = false;
let timer = null;
const clearTimer = () => {
if (timer) {
clearTimeout(timer);
timer = null;
}
};
const finish = (ready, aborted = false) => {
if (settled) return;
settled = true;
clearTimer();
signal?.removeEventListener("abort", onAbort);
resolve({
ready,
elapsedMs: Math.max(0, Date.now() - startedAt),
maxDriftMs,
checks,
aborted
});
};
const onAbort = () => {
finish(false, true);
};
if (signal?.aborted) {
finish(false, true);
return;
}
signal?.addEventListener("abort", onAbort, { once: true });
const scheduleNext = () => {
if (signal?.aborted) {
finish(false, true);
return;
}
const elapsedMs = Math.max(0, Date.now() - startedAt);
const remainingMs = maxWaitMs - elapsedMs;
if (remainingMs <= 0) {
finish(false);
return;
}
const delayMs = Math.min(intervalMs, remainingMs);
const scheduledAt = Date.now();
timer = setTimeout(() => {
timer = null;
checks += 1;
const driftMs = Math.max(0, Date.now() - scheduledAt - delayMs);
maxDriftMs = Math.max(maxDriftMs, driftMs);
if (driftMs > driftThresholdMs) readyChecks = 0;
else readyChecks += 1;
if (readyChecks >= consecutiveReadyChecks) {
finish(true);
return;
}
scheduleNext();
}, delayMs);
};
scheduleNext();
});
}
//#endregion
//#region packages/gateway-client/src/readiness.ts
function resolveGatewayClientStartReadinessTimeoutMs(options = {}) {
if (typeof options.timeoutMs === "number" && Number.isFinite(options.timeoutMs)) return options.timeoutMs;
const clientOptions = options.clientOptions ?? {};
return resolveConnectChallengeTimeoutMs(clientOptions.connectChallengeTimeoutMs, {
env: clientOptions.env,
configuredTimeoutMs: clientOptions.preauthHandshakeTimeoutMs
});
}
/** Starts a gateway client only after the supplied readiness probe succeeds. */
async function startGatewayClientWithReadinessWait(waitForReady, client, options = {}) {
const readiness = await waitForReady({
maxWaitMs: resolveGatewayClientStartReadinessTimeoutMs(options),
signal: options.signal
});
if (readiness.ready && !readiness.aborted && options.signal?.aborted !== true) client.start();
return readiness;
}
//#endregion
//#region src/gateway/client-start-readiness.ts
/** Starts a gateway client once the shared event-loop readiness check passes. */
function startGatewayClientWhenEventLoopReady(client, options = {}) {
return startGatewayClientWithReadinessWait(waitForEventLoopReady, client, options);
}
//#endregion
export { startGatewayClientWhenEventLoopReady as t };