UNPKG

@openai/agents-core

Version:

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

109 lines • 5.08 kB
import { UserError } from "../errors.mjs"; import { RunInputItem } from "../items.mjs"; import { getAgentInputItemKey } from "./items.mjs"; import { mapOwnedInputItemsAfterContextProcessing } from "./sessionPersistence.mjs"; /** * Resolves which staged occurrences reached the model after filtering. */ export function selectPendingInputForAdmission(pendingItems, preparation) { if (pendingItems.length === 0) { return []; } const pendingByRawItem = new Map(); for (const item of pendingItems) { pendingByRawItem.set(item.rawItem, item); } for (const [index, sourceItem] of preparation.sourceItems.entries()) { if (sourceItem && pendingByRawItem.has(sourceItem) && preparation.sourceMatchKinds[index] === 'fallback') { throw new UserError('callModelInputFilter cannot safely associate a reconstructed item with pending RunState input. Preserve the input item object, return an unchanged copy, or omit the pending item.'); } } const pendingKeys = new Set(pendingItems.map((item) => getAgentInputItemKey(item.rawItem))); for (const key of pendingKeys) { const candidates = preparation.turnInput.filter((item) => getAgentInputItemKey(item) === key); const reconstructedMatches = preparation.sourceItems.flatMap((sourceItem, index) => sourceItem && getAgentInputItemKey(sourceItem) === key && preparation.sourceMatchKinds[index] === 'content' ? [sourceItem] : []); const hasPendingCandidate = candidates.some((candidate) => pendingByRawItem.has(candidate)); const hasNonPendingCandidate = candidates.some((candidate) => !pendingByRawItem.has(candidate)); if (reconstructedMatches.length > 0 && reconstructedMatches.length < candidates.length && hasPendingCandidate && hasNonPendingCandidate) { throw new UserError('callModelInputFilter cannot safely associate a reconstructed item with pending RunState input. Preserve the input item object, return an unchanged copy, or omit the pending item.'); } } const admitted = []; const acceptedIds = new Set(); for (const [index, sourceItem] of preparation.sourceItems.entries()) { if (!sourceItem) { continue; } const pendingItem = pendingByRawItem.get(sourceItem); if (!pendingItem || acceptedIds.has(pendingItem.inputId)) { continue; } const persistedItem = preparation.persistedItems[index]; if (!persistedItem) { continue; } acceptedIds.add(pendingItem.inputId); const preservesPreparedItem = preparation.preserveInputIdentity && preparation.sourceMatchKinds[index] === 'identity' && getAgentInputItemKey(pendingItem.rawItem) === getAgentInputItemKey(persistedItem); admitted.push(preservesPreparedItem ? pendingItem : new RunInputItem(structuredClone(persistedItem), pendingItem.agent, pendingItem.inputId)); } return admitted; } /** * Preserves staged occurrence identity through sandbox capability processing. */ export function mapPendingInputAfterContextProcessing(pendingItems, preparedItems, processedItems) { if (pendingItems.length === 0 || preparedItems === processedItems) { return pendingItems; } return mapOwnedInputItemsAfterContextProcessing(preparedItems, processedItems, pendingItems.map((item) => item.rawItem)).map(({ item, ownerIndex }) => { const pendingItem = pendingItems[ownerIndex]; return new RunInputItem(item, pendingItem.agent, pendingItem.inputId); }); } /** * Commits accepted occurrences to RunState and leaves omitted occurrences pending. */ export function commitPendingInput(state, preparedItems, admittedItems, sourceItems) { if (preparedItems.length === 0) { return; } const admittedIds = new Set(admittedItems.map((item) => item.inputId)); const sourceItemSet = new Set(sourceItems); const preparedQueueIsIntact = sourceItems.every((item, index) => state._pendingInput[index] === item); const newlyStagedItems = preparedQueueIsIntact ? state._pendingInput.slice(sourceItems.length) : state._pendingInput.filter((item) => !sourceItemSet.has(item)); state._generatedItems.push(...admittedItems); state._pendingInput = [ ...(preparedQueueIsIntact ? preparedItems .filter((item) => !admittedIds.has(item.inputId)) .map((item) => item.rawItem) : []), ...structuredClone(newlyStagedItems), ]; } /** * Returns whether a committed input occurrence still belongs to the unpersisted * suffix for the current local-session turn. */ export function hasUnpersistedRunInput(state) { return state._generatedItems .slice(state._currentTurnPersistedItemCount) .some((item) => item instanceof RunInputItem); } //# sourceMappingURL=pendingInput.mjs.map