mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-21 18:08:05 -06:00
60 lines
1.7 KiB
TypeScript
60 lines
1.7 KiB
TypeScript
/**
|
|
* Thin Codex app-server timeout adapter around OpenClaw's shared security
|
|
* runtime timeout helper.
|
|
*/
|
|
import { withTimeout as withSharedTimeout } from "openclaw/plugin-sdk/security-runtime";
|
|
|
|
function resolveAbortError(signal: AbortSignal): Error {
|
|
return signal.reason instanceof Error
|
|
? signal.reason
|
|
: new Error("Codex app-server operation aborted", { cause: signal.reason });
|
|
}
|
|
|
|
/** Awaits a promise with a Codex-specific timeout error message. */
|
|
export async function withTimeout<T>(
|
|
promise: Promise<T>,
|
|
timeoutMs: number,
|
|
timeoutMessage: string,
|
|
createError?: () => Error,
|
|
): Promise<T> {
|
|
return await withSharedTimeout(promise, timeoutMs, {
|
|
message: timeoutMessage,
|
|
...(createError ? { createError } : {}),
|
|
});
|
|
}
|
|
|
|
/** Bounds an operation by both its owner lifecycle and one total wall-clock budget. */
|
|
export async function withAbortableTimeout<T>(params: {
|
|
promise: Promise<T>;
|
|
timeoutMs: number;
|
|
signal?: AbortSignal;
|
|
timeoutMessage: string;
|
|
createTimeoutError?: () => Error;
|
|
}): Promise<T> {
|
|
const signal = params.signal;
|
|
if (signal?.aborted) {
|
|
throw resolveAbortError(signal);
|
|
}
|
|
let removeAbortListener: (() => void) | undefined;
|
|
const operation = signal
|
|
? Promise.race([
|
|
params.promise,
|
|
new Promise<never>((_, reject) => {
|
|
const onAbort = () => reject(resolveAbortError(signal));
|
|
signal.addEventListener("abort", onAbort, { once: true });
|
|
removeAbortListener = () => signal.removeEventListener("abort", onAbort);
|
|
}),
|
|
])
|
|
: params.promise;
|
|
try {
|
|
return await withTimeout(
|
|
operation,
|
|
params.timeoutMs,
|
|
params.timeoutMessage,
|
|
params.createTimeoutError,
|
|
);
|
|
} finally {
|
|
removeAbortListener?.();
|
|
}
|
|
}
|