@openai/agents-core
Version:
The OpenAI Agents SDK is a lightweight yet powerful framework for building multi-agent workflows.
69 lines • 2.63 kB
JavaScript
import { combineAbortSignals, createSiblingCancellationError, isAbortError, } from "../utils/abortSignals.mjs";
export async function runWithSiblingCancellation(tasks, parentSignal, onFirstFailure) {
if (tasks.length <= 1) {
return Promise.all(tasks.map((task) => task(parentSignal)));
}
const siblingController = new AbortController();
const { signal, cleanup } = combineAbortSignals(parentSignal, siblingController.signal);
let firstFailureOwner;
let firstFailureParentWasAborted = false;
let firstFailure;
const siblingFailureReason = createSiblingCancellationError();
const cancelSiblings = () => {
if (!siblingController.signal.aborted) {
siblingController.abort(siblingFailureReason);
}
};
const reserveFailure = (owner, hasFailure, error) => {
const newlyReserved = firstFailureOwner === undefined;
if (firstFailureOwner === undefined) {
firstFailureOwner = owner;
firstFailureParentWasAborted = parentSignal?.aborted ?? false;
}
if (firstFailureOwner === owner &&
hasFailure &&
firstFailure === undefined) {
const parentReason = parentSignal?.reason;
const failure = firstFailureParentWasAborted &&
(error === parentReason || isAbortError(error))
? parentReason
: error;
firstFailure = { value: failure };
}
if (newlyReserved) {
try {
onFirstFailure?.();
}
finally {
cancelSiblings();
}
}
};
const pendingTasks = tasks.map(async (task, index) => {
try {
return await task(signal, (...errors) => reserveFailure(index, errors.length > 0, errors[0]));
}
catch (error) {
reserveFailure(index, true, error);
throw error;
}
});
try {
const settledTasks = await Promise.allSettled(pendingTasks);
if (firstFailureOwner !== undefined) {
if (firstFailure === undefined) {
const ownerResult = settledTasks[firstFailureOwner];
if (ownerResult?.status === 'rejected') {
throw ownerResult.reason;
}
throw new Error('The task that reserved failure ownership completed.');
}
throw firstFailure.value;
}
return settledTasks.map((result) => result.value);
}
finally {
cleanup();
}
}
//# sourceMappingURL=siblingCancellation.mjs.map