UNPKG

@openai/agents-core

Version:

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

147 lines • 5.85 kB
import { MaxTurnsExceededError, ModelBehaviorError, ModelRefusalError, ModelTimeoutError, ToolCallError, ToolInputGuardrailTripwireTriggered, ToolOutputGuardrailTripwireTriggered, UserError, } from "../errors.mjs"; import { assistant } from "../helpers/message.mjs"; import { RunMessageOutputItem } from "../items.mjs"; import logger from "../logger.mjs"; import { getRunOutput, getTurnInput } from "./items.mjs"; import { streamStepItemsToRunResult } from "./streaming.mjs"; import { createRedactedErrorDetailsError } from "../utils/finalOutputError.mjs"; export async function preserveInvalidFinalOutputRedaction(callback, inheritedRedaction = false) { const redactFromStart = inheritedRedaction || logger.dontLogModelData; try { return await callback(redactFromStart); } catch (error) { if (redactFromStart || logger.dontLogModelData) { throw createRedactedErrorDetailsError(); } throw error; } } /** * Attaches the active run state to errors that need resumable caller context. */ export const attachRunStateToError = (error, state) => { if (error instanceof ModelTimeoutError) { error.state ??= state; return; } if (!(error instanceof ToolCallError)) { return; } if (error.error instanceof ToolInputGuardrailTripwireTriggered || error.error instanceof ToolOutputGuardrailTripwireTriggered) { error.error.state ??= state; } }; const buildRunData = (state) => ({ input: state._originalInput, newItems: state._generatedItems, history: getTurnInput(state._originalInput, state._generatedItems, state._reasoningItemIdPolicy), output: getRunOutput(state._generatedItems, state._reasoningItemIdPolicy), rawResponses: state._modelResponses, lastAgent: state._currentAgent, state, }); const formatFinalOutput = (agent, finalOutput) => { if (agent.outputType === 'text') { return String(finalOutput); } return JSON.stringify(finalOutput); }; const createFinalOutputItem = (agent, outputText) => new RunMessageOutputItem(assistant(outputText), agent); function validateRunErrorFinalOutput(agent, outputText, redactInvalidOutputDetails = false, redactFromStart = false) { try { agent.processFinalOutput(outputText); } catch (error) { if (redactInvalidOutputDetails && (redactFromStart || logger.dontLogModelData)) { throw createRedactedErrorDetailsError(); } const message = error instanceof Error ? error.message : String(error); throw new UserError(`Invalid run error handler finalOutput: ${message}`); } } export const formatRunErrorFinalOutput = formatFinalOutput; export const createRunErrorFinalOutputItem = createFinalOutputItem; export const validateRunErrorHandlerFinalOutput = validateRunErrorFinalOutput; export function invalidateAcceptedResponseReplayEvidence(state) { if (state?._currentStep?.type === 'next_step_interruption' && state._currentStep.data?.responseAccepted === true) { state._lastProcessedResponse = undefined; } } export const resolveRunErrorHandler = async ({ error, errorKind, errorHandlers, context, runData, attemptedErrors, }) => { const kind = errorKind ?? (error instanceof MaxTurnsExceededError ? 'maxTurns' : error instanceof ModelRefusalError ? 'modelRefusal' : undefined); if (!kind) { return undefined; } const typedError = kind === 'maxTurns' && error instanceof MaxTurnsExceededError ? error : kind === 'modelRefusal' && error instanceof ModelRefusalError ? error : kind === 'invalidFinalOutput' && error instanceof ModelBehaviorError ? error : undefined; if (!typedError) { return undefined; } const handler = errorHandlers?.[kind] ?? errorHandlers?.default; if (!handler) { return undefined; } if (attemptedErrors?.has(typedError)) { return undefined; } attemptedErrors?.add(typedError); invalidateAcceptedResponseReplayEvidence(runData.state); const handlerResult = await handler({ error: typedError, context, runData, }); return handlerResult || undefined; }; export const prepareRunErrorFinalOutput = async ({ error, state, errorHandlers, streamResult, responseAccepted, attemptedErrors, }) => { const handlerResult = await resolveRunErrorHandler({ error, errorHandlers, context: state._context, runData: buildRunData(state), attemptedErrors, }); if (!handlerResult) { return undefined; } const includeInHistory = handlerResult.includeInHistory !== false; const outputText = formatFinalOutput(state._currentAgent, handlerResult.finalOutput); validateRunErrorFinalOutput(state._currentAgent, outputText); streamResult?._hideFinalOutput(); state._lastTurnResponse = undefined; state._lastProcessedResponse = undefined; const item = createFinalOutputItem(state._currentAgent, outputText); const deferredItem = error instanceof MaxTurnsExceededError && includeInHistory ? item : undefined; if (includeInHistory && !deferredItem) { state._generatedItems.push(item); } if (streamResult && !deferredItem && (includeInHistory || !(error instanceof MaxTurnsExceededError))) { streamStepItemsToRunResult(streamResult, [item]); } state._currentStep = { type: 'next_step_final_output', output: outputText, ...(responseAccepted ? { responseAccepted: true } : {}), }; state._finalOutputSource = 'error_handler'; return { deferredItem }; }; //# sourceMappingURL=errorHandlers.mjs.map