UNPKG

@openai/agents-core

Version:

The OpenAI Agents SDK is a lightweight yet powerful framework for building multi-agent workflows.

69 lines • 2.63 kB
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