UNPKG

@openai/agents-core

Version:

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

5,130 lines • 241 kB
import { z } from 'zod';
import { randomUUID } from '@openai/agents-core/_shims';
import { Agent } from "./agent.mjs";
import { getAgentToolSourceAgent } from "./agentToolSourceRegistry.mjs";
import { buildAgentIdentityMap } from "./runStateIdentity.mjs";
import { getToolSearchAgentName } from "./runner/toolSearchAttribution.mjs";
import { rehydrateLegacyCompactionRunItems } from "./runStateLegacyCompaction.mjs";
export { buildAgentIdentityMap } from "./runStateIdentity.mjs";
import { RunMessageOutputItem, RunInputItem, RunToolApprovalItem, RunToolCallItem, RunToolCallOutputItem, RunToolSearchCallItem, RunToolSearchOutputItem, RunReasoningItem, RunCompactionItem, RunHandoffCallItem, RunHandoffOutputItem, } from "./items.mjs";
import { RunContext } from "./runContext.mjs";
import { extractOutputItemsFromRunItems, getTurnInput, toAgentInputList, } from "./runner/items.mjs";
import { normalizeItemsForSessionPersistence } from "./runner/sessionItems.mjs";
import { getServerConversationOwner } from "./runner/conversation.mjs";
import { AgentToolUseTracker } from "./runner/toolUseTracker.mjs";
import { nextStepSchema } from "./runner/steps.mjs";
import { createToolRunFunction } from "./runner/types.mjs";
import { getCurrentResponseToolOutputGuardrailResultStart, needsNestedApprovalOwnership, hasBlockedOutputExecutionEffect, hasDeterministicTerminalToolOutputSource, hasPendingApprovedToolInputCompaction, hasTerminalToolOutputSource, restoreCurrentResponseToolOutputGuardrailResultStart, } from "./runner/blockedOutputPersistence.mjs";
import { ModelBehaviorError, SystemError, UserError } from "./errors.mjs";
import { getGlobalTraceProvider } from "./tracing/provider.mjs";
import { Usage } from "./usage.mjs";
import { getCurrentTrace } from "./tracing/index.mjs";
import logger from "./logger.mjs";
import * as protocol from "./types/protocol.mjs";
import { SANDBOX_SESSION_STATE_VERSION, SUPPORTED_SANDBOX_SESSION_STATE_VERSIONS, } from "./sandbox/session.mjs";
import { safeExecute } from "./utils/safeExecute.mjs";
import { toSmartString } from "./utils/smartString.mjs";
import { getClientToolSearchExecutor, getToolSearchRuntimeRoutingKey, hasDynamicFunctionToolApprovalPolicy, } from "./tool.mjs";
import { buildFunctionToolLookupMap, getFunctionToolLookupKey, getFunctionToolLegacyStateKeyFromStateKey, getFunctionToolQualifiedName, getFunctionToolStateKey, getFunctionToolStateKeyForCall, getFunctionToolStateKeyForResolvedCall, getFunctionToolStateKeys, FUNCTION_TOOL_NAMESPACE, getMcpToolBinding, getHostedMcpApprovalRequestIdentity, getHostedMcpApprovalRequestKey, getToolCallName, getToolCallNamespace, getToolCallDisplayName, resolveFunctionToolCall, } from "./toolIdentity.mjs";
import { getToolSearchExecution, getToolSearchOutputReplacementKey, getToolSearchProviderCallId, resolveToolSearchCallId, } from "./utils/toolSearch.mjs";
import { executeCustomClientToolSearch, filterEnabledToolSearchRuntimeTools, getClientToolSearchHelper, registerRuntimeToolSearchTools, validateClientToolSearchSupport, } from "./runner/toolSearch.mjs";
import { resolveModelVisibleToolNameCollisions } from "./runner/modelPreparation.mjs";
import { ensureToolCallerAllowed } from "./runner/toolCaller.mjs";
import { getSerializedApplyPatchToolPlaceholder, getSerializedComputerToolPlaceholder, getSerializedFunctionToolPlaceholder, getSerializedShellToolPlaceholder, } from "./sandbox/runtime/toolRehydration.mjs";
import { getToolResultCorrelationForCall, getToolResultCorrelationForResult, getToolResultCorrelationKey, } from "./runner/toolResultCorrelation.mjs";
import { getCanonicalToolCaller, getHandoffToolInvocationName, getHostedMcpApprovalToolName, getToolInvocationCallId, getToolInvocationFingerprint, getToolInvocationNameFromFingerprint, } from "./toolInvocation.mjs";
import { sanitizeSerializedSandboxState, } from "./sandbox/runtime/sessionState.mjs";
/**
 * The schema version of the serialized run state. This is used to ensure that the serialized
 * run state is compatible with the current version of the SDK.
 * If anything in this schema changes, the version will have to be incremented.
 *
 * Version history.
 * - 1.0: Initial serialized RunState schema.
 * - 1.1: Adds optional currentTurnInProgress, conversationId, and previousResponseId fields,
 *   plus broader tool_call_output_item rawItem variants for non-function tools. Older 1.0
 *   payloads remain readable but resumes may lack mid-turn or server-managed context precision.
 * - 1.2: Adds pendingAgentToolRuns for nested agent tool resumption.
 * - 1.3: Adds computer tool approval items to serialized tool_approval_item unions.
 * - 1.4: Adds optional toolInput to serialized run context.
 * - 1.5: Adds optional reasoningItemIdPolicy to preserve reasoning input policy across resume.
 * - 1.6: Adds optional requestId to serialized model responses.
 * - 1.7: Adds optional approval rejection messages.
 * - 1.8: Adds tool search item variants, batched computer actions, and GA computer tool
 *   aliasing to serialized run state payloads.
 * - 1.9: Adds optional sandbox session persistence with a versioned session-state
 *   envelope for sandbox-agent resume.
 * - 1.10: Adds optional stable agent identity keys so duplicate-name agent graphs can
 *   serialize and resume without ambiguous name resolution.
 * - 1.11: Allows null maxTurns to persist runs without a turn limit.
 * - 1.12: Adds optional missing function tool calls to processed responses.
 * - 1.13: Adds optional SDK-only customData on tool output run items.
 * - 1.14: Adds Programmatic Tool Calling program items, outputs, caller linkage,
 *   and optional assistant message phases.
 * - 1.15: Adds reconstructable sandbox environment value references and sandbox
 *   session-state envelope version 2.
 * - 1.16: Adds compaction items, category-aware function tool keys, and agent-scoped
 *   function approvals, including aliases for legacy pending-run accessors.
 * - 1.17: Adds durable local tool execution provenance and blocked-output session
 *   persistence bookkeeping.
 * - 1.18: Adds sandbox session-state envelope version 3 so credential-redacted
 *   mount authority cannot be consumed by older SDKs, and binds per-call approvals
 *   and committed local tool results to canonical invocation fingerprints. It also
 *   scopes persistent hosted MCP approvals by server label and tool name, preserves
 *   JSON-compatible tool outputs as structured data, and adds durable pending input
 *   and accepted-response resume state.
 * - 1.19: Lets an exact call approval decision override a sticky decision for the
 *   same canonical approval identity, and adds sandbox session-state envelope version 4
 *   so Docker network-isolation state cannot be consumed by older SDKs that would drop it
 *   during container replacement.
 * - 1.20: Preserves resolved function identities on tool call items and adds sandbox
 *   session-state envelope version 5 so Docker labels cannot be
 *   consumed by older SDKs that would drop them during container replacement, preserves
 *   exact current-response ownership for serialized approval resumes, and checkpoints
 *   unacknowledged ordinary Session appends completed during approval resume, including
 *   filtered handoff input held until its source append settles.
 * - 1.21: Re-evaluates conditional policies against refreshed normalized input
 *   on approval resume. Normalized values and comparison evidence are never serialized.
 *   Also preserves original local MCP recipients. Historical function calls without
 *   recipient provenance may be rejected or retained as completed, but cannot execute.
 *   Records completion of initial input guardrails. Started snapshots without this
 *   evidence require a fresh run rather than resuming unvalidated input.
 * - 1.22: Records hosted MCP namespace discovery provenance. Older namespace-only
 *   search outputs require rediscovery; explicit MCP descriptors remain usable.
 * - 1.23: Preserves nested numeric token usage breakdowns.
 * - 1.24: Preserves arbitrary JSON token usage metadata, child-owned approval slots,
 *   and completion evidence for handoff failures returned to the source agent.
 *   Adds sandbox session-state envelope version 6 so client-owned
 *   unresolved environment references cannot be consumed by older SDKs that
 *   would resolve them in the runner process.
 */
export const CURRENT_SCHEMA_VERSION = '1.24';
export const SUPPORTED_SCHEMA_VERSIONS = [
    '1.0',
    '1.1',
    '1.2',
    '1.3',
    '1.4',
    '1.5',
    '1.6',
    '1.7',
    '1.8',
    '1.9',
    '1.10',
    '1.11',
    '1.12',
    '1.13',
    '1.14',
    '1.15',
    '1.16',
    '1.17',
    '1.18',
    '1.19',
    '1.20',
    '1.21',
    '1.22',
    '1.23',
    CURRENT_SCHEMA_VERSION,
];
const $schemaVersion = z.enum(SUPPORTED_SCHEMA_VERSIONS);
function schemaVersionSupportsV118State(schemaVersion) {
    return (schemaVersion === '1.18' || schemaVersionSupportsV119State(schemaVersion));
}
function schemaVersionSupportsV119State(schemaVersion) {
    return (schemaVersion === '1.19' || schemaVersionSupportsV120State(schemaVersion));
}
function schemaVersionSupportsV120State(schemaVersion) {
    return (schemaVersion === '1.20' ||
        schemaVersion === '1.21' ||
        schemaVersion === '1.22' ||
        schemaVersion === '1.23' ||
        schemaVersion === CURRENT_SCHEMA_VERSION);
}
function schemaVersionSupportsV116State(schemaVersion) {
    return (schemaVersion === '1.16' ||
        schemaVersion === '1.17' ||
        schemaVersionSupportsV118State(schemaVersion));
}
function schemaVersionSupportsV117State(schemaVersion) {
    return (schemaVersion === '1.17' || schemaVersionSupportsV118State(schemaVersion));
}
const pendingSessionHistoryTransactionSchema = z
    .object({
    operationId: z.string().min(1),
    transactionKind: z.enum(['blocked_append', 'accepted_replace']),
    runItemIndexes: z.array(z.number().int().min(0)),
    replaceRunItemIndexes: z.array(z.number().int().min(0)),
    alreadyPersistedCount: z.number().int().min(0),
    persistedItemCount: z.number().int().min(0),
    deferredItemIndexes: z.array(z.number().int().min(0)),
})
    .strict();
const pendingSessionWriteBaseSchema = {
    sessionId: z.string().min(1),
    alreadyPersistedCount: z.number().int().min(0),
    persistedItemCount: z.number().int().min(1),
    reasoningItemIdPolicy: z.enum(['preserve', 'omit']),
    // Kept separately from canonical append items until the source turn is durable.
    handoffInput: z.lazy(() => handoffInputSnapshotSchema).optional(),
    terminalToolFinalization: z
        .object({
        behavior: z.enum([
            'stop_on_first_tool',
            'stop_at_tool_names',
            'function',
        ]),
        selectedCallId: z.string().min(1).optional(),
        selectedGeneratedItemIndex: z.number().int().min(0).optional(),
        finalOutput: z.string(),
    })
        .strict()
        .optional(),
};
const pendingSessionWriteSchema = z.discriminatedUnion('phase', [
    z
        .object({
        ...pendingSessionWriteBaseSchema,
        phase: z.literal('prepared'),
    })
        .strict(),
    z
        .object({
        ...pendingSessionWriteBaseSchema,
        phase: z.literal('append_ready'),
        beforeItems: z.array(protocol.ModelItem),
        comparableAppendItems: z.array(protocol.ModelItem).min(1),
    })
        .strict(),
    z
        .object({
        ...pendingSessionWriteBaseSchema,
        phase: z.literal('compaction_pending'),
    })
        .strict(),
]);
export function getPendingSessionWriteAppendItems(state, pending) {
    const ownedItems = normalizeItemsForSessionPersistence(extractOutputItemsFromRunItems(state._generatedItems.slice(pending.alreadyPersistedCount, pending.persistedItemCount), pending.reasoningItemIdPolicy));
    if (ownedItems.length === 0) {
        throw new UserError('RunState pending Session write does not own a persistable generated item.');
    }
    const inputPrefix = state._currentTurnSessionHistoryTransactionInputItems ?? [];
    if ((inputPrefix.length > 0 &&
        state._currentTurnSessionHistoryTransactionSessionId === undefined) ||
        (state._currentTurnSessionHistoryTransactionSessionId !== undefined &&
            state._currentTurnSessionHistoryTransactionSessionId !==
                pending.sessionId)) {
        throw new UserError('RunState pending Session write input is missing its transaction-aware Session binding.');
    }
    return normalizeItemsForSessionPersistence([...inputPrefix, ...ownedItems]);
}
const pendingSessionWriteTerminalProducers = new WeakMap();
export function recordPendingSessionWriteTerminalProducer(state, producer) {
    if (producer) {
        pendingSessionWriteTerminalProducers.set(state, producer);
    }
    else {
        pendingSessionWriteTerminalProducers.delete(state);
    }
}
export function clearPendingSessionWriteTerminalProducer(state) {
    pendingSessionWriteTerminalProducers.delete(state);
}
function getLocalToolResultCallId(rawItem) {
    switch (rawItem.type) {
        case 'function_call_result':
        case 'computer_call_result':
        case 'shell_call_output':
        case 'apply_patch_call_output':
            return rawItem.callId;
        default:
            return undefined;
    }
}
function isTrackedLocalToolResult(rawItem) {
    return (rawItem.type === 'function_call_result' ||
        rawItem.type === 'computer_call_result' ||
        rawItem.type === 'shell_call_output' ||
        rawItem.type === 'apply_patch_call_output');
}
function getSerializedLocalToolIdentity(toolCall, approvalNames, agent, functionToolStateKey) {
    if (toolCall.type === 'function_call') {
        const callIdentity = getFunctionToolStateKeyForCall(toolCall, toolCall.name);
        if (functionToolStateKey !== undefined) {
            if (functionToolStateKey !== callIdentity &&
                (getToolCallNamespace(toolCall) ||
                    functionToolStateKey !==
                        getFunctionToolLookupKey(toolCall.name, toolCall.name))) {
                throw new UserError('RunState function tool identity does not match its call.');
            }
            return functionToolStateKey;
        }
        return callIdentity;
    }
    const callId = getToolInvocationCallId(toolCall);
    if (callId) {
        const approvalName = approvalNames.get(callId);
        if (approvalName) {
            return approvalName;
        }
    }
    const expectedType = toolCall.type === 'computer_call'
        ? 'computer'
        : toolCall.type === 'shell_call'
            ? 'shell'
            : 'apply_patch';
    return agent.tools.find((tool) => tool.type === expectedType)?.name;
}
function toolResultMatchesCall(toolCall, result) {
    const callCorrelation = getToolResultCorrelationForCall(toolCall);
    const resultCorrelation = getToolResultCorrelationForResult(result);
    if (!callCorrelation ||
        !resultCorrelation ||
        getToolResultCorrelationKey(callCorrelation) !==
            getToolResultCorrelationKey(resultCorrelation)) {
        return false;
    }
    const callCaller = getCanonicalToolCaller(toolCall);
    const resultCaller = getCanonicalToolCaller(result);
    if (callCaller.type !== resultCaller.type ||
        (callCaller.type === 'program' &&
            (resultCaller.type !== 'program' ||
                callCaller.callerId !== resultCaller.callerId))) {
        return false;
    }
    if (toolCall.type !== 'function_call') {
        return true;
    }
    return (result.type === 'function_call_result' &&
        result.name === toolCall.name &&
        result.namespace === toolCall.namespace);
}
function toolItemsHaveSameCaller(left, right) {
    const leftCaller = getCanonicalToolCaller(left);
    const rightCaller = getCanonicalToolCaller(right);
    return (leftCaller.type === rightCaller.type &&
        (leftCaller.type !== 'program' ||
            (rightCaller.type === 'program' &&
                leftCaller.callerId === rightCaller.callerId)));
}
function getAgentInvocationMap(records, agent) {
    const existing = records.get(agent);
    if (existing) {
        return existing;
    }
    const byCallId = new Map();
    records.set(agent, byCallId);
    return byCallId;
}
function getAgentAmbiguousCallIds(records, agent) {
    const existing = records.get(agent);
    if (existing) {
        return existing;
    }
    const callIds = new Set();
    records.set(agent, callIds);
    return callIds;
}
function recordObservedToolInvocation(observed, ambiguous, agent, callId, fingerprint) {
    const agentObserved = getAgentInvocationMap(observed, agent);
    const previous = agentObserved.get(callId);
    if (previous !== undefined && previous !== fingerprint) {
        getAgentAmbiguousCallIds(ambiguous, agent).add(callId);
        agentObserved.delete(callId);
    }
    else if (!ambiguous.get(agent)?.has(callId)) {
        agentObserved.set(callId, fingerprint);
    }
}
function serializeAgentInvocationRecords(records, agentIdentityKeys) {
    const serialized = [];
    for (const [agent, invocations] of records) {
        const agentIdentity = agentIdentityKeys.get(agent);
        if (agentIdentity && invocations.size > 0) {
            serialized.push({
                agentIdentity,
                invocations: Object.fromEntries(invocations),
            });
        }
    }
    return serialized;
}
function serializeAgentCallIdSets(records, agentIdentityKeys) {
    const serialized = [];
    for (const [agent, callIds] of records) {
        const agentIdentity = agentIdentityKeys.get(agent);
        if (agentIdentity && callIds.size > 0) {
            serialized.push({ agentIdentity, callIds: [...callIds].sort() });
        }
    }
    return serialized;
}
function deserializeAgentInvocationRecords(records, agentsByIdentity) {
    const deserialized = new Map();
    const seenAgentIdentities = new Set();
    for (const { agentIdentity, invocations } of records) {
        const agent = agentsByIdentity.get(agentIdentity);
        if (!agent || seenAgentIdentities.has(agentIdentity)) {
            throw new UserError('RunState contains invalid completed tool invocation ownership for the current agent graph.');
        }
        seenAgentIdentities.add(agentIdentity);
        deserialized.set(agent, new Map(Object.entries(invocations)));
    }
    return deserialized;
}
function deserializeAgentCallIdSets(records, agentsByIdentity) {
    const deserialized = new Map();
    const seenAgentIdentities = new Set();
    for (const { agentIdentity, callIds } of records) {
        const agent = agentsByIdentity.get(agentIdentity);
        if (!agent || seenAgentIdentities.has(agentIdentity)) {
            throw new UserError('RunState contains invalid ambiguous tool invocation ownership for the current agent graph.');
        }
        seenAgentIdentities.add(agentIdentity);
        deserialized.set(agent, new Set(callIds));
    }
    return deserialized;
}
function inferCompletedToolInvocations(generatedItems) {
    const approvalNames = new Map();
    const pendingLocalCalls = new Map();
    const pendingHostedMcpCalls = new Map();
    const observed = new Map();
    const completed = new Map();
    const ambiguous = new Map();
    const evidence = new Map();
    // Completed calls retain their execution-time identity even when a handoff
    // filter removes discovery history. Completion evidence is checked separately.
    for (const item of generatedItems) {
        if (item instanceof RunToolApprovalItem) {
            const callId = getToolInvocationCallId(item.rawItem);
            if (!callId || !item.name) {
                throw new UserError('RunState contains a tool approval request without a canonical invocation identity.');
            }
            const toolName = item.functionToolStateKey ?? item.name;
            getAgentInvocationMap(approvalNames, item.agent).set(callId, toolName);
            const pending = pendingLocalCalls.get(item.agent)?.get(callId);
            if (pending) {
                if (getToolInvocationFingerprint('', pending.toolCall) !==
                    getToolInvocationFingerprint('', item.rawItem)) {
                    getAgentAmbiguousCallIds(ambiguous, item.agent).add(callId);
                    observed.get(item.agent)?.delete(callId);
                }
                else if (!completed.get(item.agent)?.has(callId)) {
                    observed.get(item.agent)?.delete(callId);
                    recordObservedToolInvocation(observed, ambiguous, item.agent, callId, getToolInvocationFingerprint(toolName, pending.toolCall));
                }
            }
            recordObservedToolInvocation(observed, ambiguous, item.agent, callId, getToolInvocationFingerprint(toolName, item.rawItem));
            if (item.rawItem.type === 'function_call' ||
                item.rawItem.type === 'computer_call' ||
                item.rawItem.type === 'shell_call' ||
                item.rawItem.type === 'apply_patch_call') {
                getAgentInvocationMap(pendingLocalCalls, item.agent).set(callId, {
                    toolCall: item.rawItem,
                    identityResolved: true,
                    evidence: pending ? [...pending.evidence, item] : [item],
                });
            }
            continue;
        }
        if (item instanceof RunHandoffCallItem) {
            const rawItem = item.rawItem;
            const callId = getToolInvocationCallId(rawItem);
            if (!callId) {
                throw new UserError('RunState contains a handoff call without a non-empty call ID.');
            }
            const fingerprint = getToolInvocationFingerprint(getHandoffToolInvocationName(rawItem.name), rawItem);
            recordObservedToolInvocation(observed, ambiguous, item.agent, callId, fingerprint);
            getAgentInvocationMap(pendingLocalCalls, item.agent).set(callId, {
                toolCall: rawItem,
                identityResolved: true,
                evidence: [item],
            });
            continue;
        }
        if (item instanceof RunToolCallItem) {
            const rawItem = item.rawItem;
            if (rawItem.type === 'hosted_tool_call' &&
                (rawItem.providerData?.type === 'mcp_approval_request' ||
                    rawItem.name === 'mcp_approval_request')) {
                const providerData = rawItem.providerData;
                if (typeof providerData?.id !== 'string' ||
                    providerData.id.length === 0 ||
                    typeof providerData.name !== 'string' ||
                    providerData.name.length === 0) {
                    throw new UserError('RunState contains a hosted MCP approval request without a canonical invocation identity.');
                }
                recordObservedToolInvocation(observed, ambiguous, item.agent, providerData.id, getToolInvocationFingerprint(providerData.name, rawItem));
                getAgentInvocationMap(pendingHostedMcpCalls, item.agent).set(providerData.id, { toolCall: rawItem, evidence: [item] });
                continue;
            }
            if (rawItem.type === 'hosted_tool_call' &&
                rawItem.name === 'mcp_approval_response') {
                const providerData = rawItem.providerData;
                const callId = providerData?.approval_request_id;
                if (typeof callId !== 'string' || callId.length === 0) {
                    throw new UserError('RunState contains a hosted MCP approval response without a non-empty approval request ID.');
                }
                const pending = pendingHostedMcpCalls.get(item.agent)?.get(callId);
                if (!pending || !toolItemsHaveSameCaller(pending.toolCall, rawItem)) {
                    getAgentAmbiguousCallIds(ambiguous, item.agent).add(callId);
                    observed.get(item.agent)?.delete(callId);
                }
                pendingHostedMcpCalls.get(item.agent)?.delete(callId);
                const fingerprint = observed.get(item.agent)?.get(callId);
                if (fingerprint !== undefined &&
                    !ambiguous.get(item.agent)?.has(callId)) {
                    getAgentInvocationMap(completed, item.agent).set(callId, fingerprint);
                    getAgentInvocationMap(evidence, item.agent).set(callId, [
                        ...(pending?.evidence ?? []),
                        item,
                    ]);
                }
                continue;
            }
            if (rawItem.type !== 'function_call' &&
                rawItem.type !== 'computer_call' &&
                rawItem.type !== 'shell_call' &&
                rawItem.type !== 'apply_patch_call') {
                continue;
            }
            const callId = getToolInvocationCallId(rawItem);
            if (!callId) {
                throw new UserError('RunState contains a local tool call without a non-empty call ID.');
            }
            const toolName = getSerializedLocalToolIdentity(rawItem, approvalNames.get(item.agent) ?? new Map(), item.agent, item.functionToolStateKey);
            const agentPending = getAgentInvocationMap(pendingLocalCalls, item.agent);
            const previousPending = agentPending.get(callId);
            if (previousPending &&
                getToolInvocationFingerprint('', previousPending.toolCall) !==
                    getToolInvocationFingerprint('', rawItem)) {
                getAgentAmbiguousCallIds(ambiguous, item.agent).add(callId);
                agentPending.delete(callId);
                observed.get(item.agent)?.delete(callId);
                continue;
            }
            if (!ambiguous.get(item.agent)?.has(callId)) {
                agentPending.set(callId, {
                    toolCall: rawItem,
                    identityResolved: toolName !== undefined,
                    evidence: [item],
                });
            }
            if (!toolName) {
                continue;
            }
            const fingerprint = getToolInvocationFingerprint(toolName, rawItem);
            recordObservedToolInvocation(observed, ambiguous, item.agent, callId, fingerprint);
            continue;
        }
        if (item instanceof RunToolCallOutputItem ||
            item instanceof RunHandoffOutputItem) {
            if (item instanceof RunHandoffOutputItem) {
                const callId = item.rawItem.callId;
                if (!callId) {
                    throw new UserError('RunState contains a handoff output without a non-empty call ID.');
                }
                const pending = pendingLocalCalls.get(item.sourceAgent)?.get(callId);
                if (!pending ||
                    !toolResultMatchesCall(pending.toolCall, item.rawItem)) {
                    getAgentAmbiguousCallIds(ambiguous, item.sourceAgent).add(callId);
                    observed.get(item.sourceAgent)?.delete(callId);
                }
                pendingLocalCalls.get(item.sourceAgent)?.delete(callId);
                const fingerprint = observed.get(item.sourceAgent)?.get(callId);
                if (fingerprint !== undefined &&
                    !ambiguous.get(item.sourceAgent)?.has(callId)) {
                    getAgentInvocationMap(completed, item.sourceAgent).set(callId, fingerprint);
                    getAgentInvocationMap(evidence, item.sourceAgent).set(callId, [
                        ...(pending?.evidence ?? []),
                        item,
                    ]);
                }
                continue;
            }
            if (!isTrackedLocalToolResult(item.rawItem)) {
                continue;
            }
            const callId = getLocalToolResultCallId(item.rawItem);
            if (!callId) {
                throw new UserError('RunState contains a local tool output without a non-empty call ID.');
            }
            const pending = pendingLocalCalls.get(item.agent)?.get(callId);
            if (!pending ||
                !pending.identityResolved ||
                !toolResultMatchesCall(pending.toolCall, item.rawItem)) {
                getAgentAmbiguousCallIds(ambiguous, item.agent).add(callId);
                observed.get(item.agent)?.delete(callId);
            }
            pendingLocalCalls.get(item.agent)?.delete(callId);
            const fingerprint = callId
                ? observed.get(item.agent)?.get(callId)
                : undefined;
            if (callId &&
                fingerprint !== undefined &&
                !ambiguous.get(item.agent)?.has(callId)) {
                getAgentInvocationMap(completed, item.agent).set(callId, fingerprint);
                getAgentInvocationMap(evidence, item.agent).set(callId, [
                    ...(pending?.evidence ?? []),
                    item,
                ]);
            }
        }
    }
    return { completed, ambiguous, evidence };
}
function rebuildLegacyCompletedToolInvocations(state, generatedItems) {
    const inferred = inferCompletedToolInvocations(generatedItems);
    state._completedToolInvocations = inferred.completed;
    state._ambiguousToolInvocationCallIds = inferred.ambiguous;
}
function getPerCallApprovalIds(record) {
    return new Set([
        ...(Array.isArray(record.approved) ? record.approved : []),
        ...(Array.isArray(record.rejected) ? record.rejected : []),
    ]);
}
function validateCurrentApprovalInvocationRecords(context) {
    const invocationRecords = new Map((context.approvalInvocations ?? []).map((record) => [
        record.agentIdentity,
        record.invocations,
    ]));
    for (const record of context.functionApprovals ?? []) {
        const invocations = invocationRecords.get(record.agentIdentity);
        for (const approval of Object.values(record.approvals)) {
            for (const callId of getPerCallApprovalIds(approval)) {
                if (invocations?.[callId] === undefined) {
                    throw new UserError('RunState contains a per-call function approval without its canonical invocation binding.');
                }
            }
        }
    }
    for (const record of context.approvalInvocations ?? []) {
        for (const approval of Object.values(record.approvals)) {
            for (const callId of getPerCallApprovalIds(approval)) {
                if (record.invocations[callId] === undefined) {
                    throw new UserError('RunState contains a per-call tool approval without its canonical invocation binding.');
                }
            }
        }
    }
}
function isRecoveredHandoffEvidence(evidence) {
    return (evidence.items[0] instanceof RunHandoffCallItem &&
        evidence.items[1] instanceof RunToolCallOutputItem);
}
function validateToolInvocationCompletionEvidence(agent, callId, evidence) {
    const [callItem, outputItem] = evidence.items;
    const toolName = getToolInvocationNameFromFingerprint(evidence.fingerprint);
    let toolCall;
    let expectedToolName;
    let evidenceCallId;
    let correlated = false;
    if (callItem instanceof RunHandoffCallItem) {
        toolCall = callItem.rawItem;
        expectedToolName = getHandoffToolInvocationName(toolCall.name);
        evidenceCallId = toolCall.callId;
        correlated =
            callItem.agent === agent &&
                ((outputItem instanceof RunHandoffOutputItem &&
                    outputItem.sourceAgent === agent) ||
                    (outputItem instanceof RunToolCallOutputItem &&
                        outputItem.agent === agent &&
                        outputItem.executionStatus === 'executed' &&
                        outputItem.rawItem.type === 'function_call_result' &&
                        outputItem.rawItem.status === 'completed')) &&
                toolResultMatchesCall(toolCall, outputItem.rawItem);
    }
    else if (callItem instanceof RunToolCallItem ||
        callItem instanceof RunToolApprovalItem) {
        const rawToolCall = callItem.rawItem;
        if (rawToolCall.type === 'hosted_tool_call') {
            toolCall = rawToolCall;
            const providerData = toolCall.providerData;
            const hostedToolName = typeof providerData?.name === 'string'
                ? providerData.name
                : callItem instanceof RunToolApprovalItem
                    ? callItem.name
                    : undefined;
            expectedToolName = hostedToolName
                ? getHostedMcpApprovalToolName(hostedToolName, toolCall)
                : undefined;
            evidenceCallId =
                typeof providerData?.id === 'string'
                    ? providerData.id
                    : getToolInvocationCallId(toolCall);
            const outputProviderData = outputItem instanceof RunToolCallItem &&
                outputItem.rawItem.type === 'hosted_tool_call'
                ? outputItem.rawItem.providerData
                : undefined;
            correlated =
                callItem.agent === agent &&
                    outputItem instanceof RunToolCallItem &&
                    outputItem.agent === agent &&
                    outputItem.rawItem.type === 'hosted_tool_call' &&
                    outputItem.rawItem.name === 'mcp_approval_response' &&
                    outputProviderData?.approval_request_id === callId &&
                    toolItemsHaveSameCaller(toolCall, outputItem.rawItem);
        }
        else if (rawToolCall.type === 'function_call' ||
            rawToolCall.type === 'computer_call' ||
            rawToolCall.type === 'shell_call' ||
            rawToolCall.type === 'apply_patch_call') {
            toolCall = rawToolCall;
            expectedToolName =
                toolCall.type === 'function_call'
                    ? callItem instanceof RunToolApprovalItem
                        ? (callItem.functionToolStateKey ?? callItem.name)
                        : callItem.functionToolStateKey !== undefined
                            ? getSerializedLocalToolIdentity(toolCall, new Map(), agent, callItem.functionToolStateKey)
                            : getFunctionToolLegacyStateKeyFromStateKey(toolName ?? '') ===
                                getFunctionToolLegacyStateKeyFromStateKey(getFunctionToolStateKeyForCall(toolCall, toolCall.name) ??
                                    '')
                                ? toolName
                                : undefined
                    : callItem instanceof RunToolApprovalItem
                        ? callItem.name
                        : toolName;
            evidenceCallId = getToolInvocationCallId(toolCall);
            correlated =
                callItem.agent === agent &&
                    outputItem instanceof RunToolCallOutputItem &&
                    outputItem.agent === agent &&
                    isTrackedLocalToolResult(outputItem.rawItem) &&
                    toolResultMatchesCall(toolCall, outputItem.rawItem);
        }
        else {
            throw new UserError('RunState completed tool invocation evidence contains an unsupported call item.');
        }
    }
    else {
        throw new UserError('RunState completed tool invocation evidence is missing its canonical call item.');
    }
    if (!toolName ||
        !expectedToolName ||
        expectedToolName !== toolName ||
        evidenceCallId !== callId ||
        getToolInvocationFingerprint(toolName, toolCall) !== evidence.fingerprint ||
        !correlated) {
        throw new UserError('RunState completed tool invocation evidence is not a correlated canonical completion.');
    }
    return evidence.fingerprint;
}
function findToolInvocationCompletionEvidence(agent, callId, fingerprint, outputItem, candidates) {
    for (let index = candidates.length - 1; index >= 0; index -= 1) {
        const candidate = candidates[index];
        if (candidate === outputItem) {
            continue;
        }
        const evidence = {
            fingerprint,
            items: [candidate, outputItem],
        };
        try {
            validateToolInvocationCompletionEvidence(agent, callId, evidence);
            return evidence;
        }
        catch (error) {
            if (!(error instanceof UserError)) {
                throw error;
            }
        }
    }
    return undefined;
}
function getCompletionOutputCallId(item, agent) {
    if (item instanceof RunHandoffOutputItem) {
        return item.sourceAgent === agent ? item.rawItem.callId : undefined;
    }
    if (item instanceof RunToolCallOutputItem) {
        return item.agent === agent && isTrackedLocalToolResult(item.rawItem)
            ? getLocalToolResultCallId(item.rawItem)
            : undefined;
    }
    if (item instanceof RunToolCallItem &&
        item.agent === agent &&
        item.rawItem.type === 'hosted_tool_call' &&
        item.rawItem.name === 'mcp_approval_response') {
        const providerData = item.rawItem.providerData;
        return typeof providerData?.approval_request_id === 'string'
            ? providerData.approval_request_id
            : undefined;
    }
    return undefined;
}
function validateGeneratedHistoryForCompletionEvidence(generatedItems, agent, callId, evidence) {
    const outputItems = generatedItems.filter((item) => getCompletionOutputCallId(item, agent) === callId);
    for (const outputItem of outputItems) {
        if (!findToolInvocationCompletionEvidence(agent, callId, evidence.fingerprint, outputItem, [evidence.items[0], ...generatedItems])) {
            throw new UserError('RunState generated item history conflicts with completed tool invocation evidence.');
        }
    }
}
function validateCurrentCompletedToolInvocations(state, generatedItems, schemaVersion) {
    const serializedCompleted = state._completedToolInvocations;
    const inferred = inferCompletedToolInvocations(generatedItems);
    const inferredCompleted = inferred.completed;
    const evidenceCompleted = new Map();
    for (const [agent, invocations] of state._completedToolInvocationEvidence) {
        for (const [callId, evidence] of invocations) {
            if (schemaVersion !== CURRENT_SCHEMA_VERSION &&
                isRecoveredHandoffEvidence(evidence)) {
                throw new UserError(`Run state schema version ${schemaVersion} does not support recovered handoff evidence.`);
            }
            validateGeneratedHistoryForCompletionEvidence(generatedItems, agent, callId, evidence);
            getAgentInvocationMap(evidenceCompleted, agent).set(callId, validateToolInvocationCompletionEvidence(agent, callId, evidence));
        }
    }
    for (const [agent, invocations] of inferredCompleted) {
        const serializedInvocations = serializedCompleted.get(agent);
        for (const [callId, fingerprint] of invocations) {
            if (serializedInvocations?.get(callId) !== fingerprint) {
                throw new UserError('RunState completed tool invocation records do not match the generated item history.');
            }
        }
    }
    for (const [agent, invocations] of serializedCompleted) {
        const evidenceInvocations = evidenceCompleted.get(agent);
        for (const [callId, fingerprint] of invocations) {
            if (evidenceInvocations?.get(callId) !== fingerprint) {
                throw new UserError('RunState completed tool invocation records do not match correlated completion evidence.');
            }
        }
    }
    for (const [agent, invocations] of evidenceCompleted) {
        const serializedInvocations = serializedCompleted.get(agent);
        for (const [callId, fingerprint] of invocations) {
            if (serializedInvocations?.get(callId) !== fingerprint) {
                throw new UserError('RunState completed tool invocation evidence does not match completed invocation authority.');
            }
        }
    }
    const inferredAmbiguous = inferred.ambiguous;
    for (const [agent, callIds] of inferredAmbiguous) {
        const serializedCallIds = state._ambiguousToolInvocationCallIds.get(agent);
        for (const callId of callIds) {
            if (evidenceCompleted.get(agent)?.has(callId)) {
                continue;
            }
            if (!serializedCallIds?.has(callId)) {
                throw new UserError('RunState ambiguous tool invocation records do not match the generated item history.');
            }
        }
    }
}
const serializedAgentSchema = z.object({
    name: z.string(),
    identity: z.string().optional(),
});
const serializedSpanBase = z.object({
    object: z.literal('trace.span'),
    id: z.string(),
    trace_id: z.string(),
    parent_id: z.string().nullable(),
    started_at: z.string().nullable(),
    ended_at: z.string().nullable(),
    error: z
        .object({
        message: z.string(),
        data: z.record(z.string(), z.any()).optional(),
    })
        .nullable(),
    span_data: z.record(z.string(), z.any()),
});
const SerializedSpan = serializedSpanBase.extend({
    previous_span: z.lazy(() => SerializedSpan).optional(),
});
const requestUsageSchema = z.object({
    inputTokens: z.number(),
    outputTokens: z.number(),
    totalTokens: z.number(),
    inputTokensDetails: protocol.TokenDetails.optional(),
    outputTokensDetails: protocol.TokenDetails.optional(),
    endpoint: z.string().optional(),
});
const usageSchema = z.object({
    requests: z.number(),
    inputTokens: z.number(),
    outputTokens: z.number(),
    totalTokens: z.number(),
    inputTokensDetails: z.array(protocol.TokenDetails).optional(),
    outputTokensDetails: z.array(protocol.TokenDetails).optional(),
    requestUsageEntries: z.array(requestUsageSchema).optional(),
});
// Called only after SerializedRunState validates and bounds every details tree.
// Arrays and nonnumeric leaves need the JSON metadata format introduced in 1.24.
function isNumericTokenDetails(value) {
    return (typeof value === 'number' ||
        (value !== null &&
            typeof value === 'object' &&
            !Array.isArray(value) &&
            Object.values(value).every(isNumericTokenDetails)));
}
function usageSupportsV123(usage) {
    return ((usage.inputTokensDetails ?? []).every(isNumericTokenDetails) &&
        (usage.outputTokensDetails ?? []).every(isNumericTokenDetails) &&
        (usage.requestUsageEntries ?? []).every((entry) => isNumericTokenDetails(entry.inputTokensDetails ?? {}) &&
            isNumericTokenDetails(entry.outputTokensDetails ?? {})));
}
const modelResponseSchema = z.object({
    usage: usageSchema,
    output: z.array(protocol.OutputModelItem),
    responseId: z.string().optional(),
    requestId: z.string().optional(),
    providerData: z.record(z.string(), z.any()).optional(),
});
const INVALID_JSON_COMPATIBLE_VALUE = Symbol('invalidJsonCompatibleValue');
function normalizeJsonCompatibleValue(value) {
    try {
        return normalizeJsonCompatibleValueInternal(value, new Set());
    }
    catch {
        return INVALID_JSON_COMPATIBLE_VALUE;
    }
}
function normalizeJsonCompatibleValueInternal(value, ancestors) {
    if (value === null) {
        return null;
    }
    if (typeof value === 'string' || typeof value === 'boolean') {
        return value;
    }
    if (typeof value === 'number') {
        if (!Number.isFinite(value)) {
            return INVALID_JSON_COMPATIBLE_VALUE;
        }
        return Object.is(value, -0) ? 0 : value;
    }
    if (typeof value !== 'object' || ancestors.has(value)) {
        return INVALID_JSON_COMPATIBLE_VALUE;
    }
    if (hasUnsupportedToJsonProtocol(value)) {
        return INVALID_JSON_COMPATIBLE_VALUE;
    }
    ancestors.add(value);
    try {
        if (Array.isArray(value)) {
            if (Object.getOwnPropertySymbols(value).length > 0) {
                return INVALID_JSON_COMPATIBLE_VALUE;
            }
            const lengthDescriptor = Object.getOwnPropertyDescriptor(value, 'length');
            if (!lengthDescriptor || !('value' in lengthDescriptor)) {
                return INVALID_JSON_COMPATIBLE_VALUE;
            }
            const normalized = [];
            for (let index = 0; index < lengthDescriptor.value; index += 1) {
                const descriptor = Object.getOwnPropertyDescriptor(value, index);
                if (!descriptor || !('value' in descriptor)) {
                    return INVALID_JSON_COMPATIBLE_VALUE;
                }
                const entry = normalizeJsonCompatibleValueInternal(descriptor.value, ancestors);
                if (entry === INVALID_JSON_COMPATIBLE_VALUE) {
                    return INVALID_JSON_COMPATIBLE_VALUE;
                }
                normalized.push(entry);
            }
            return normalized;
        }
        const prototype = Object.getPrototypeOf(value);
        if (prototype !== Object.prototype && prototype !== null) {
            return INVALID_JSON_COMPATIBLE_VALUE;
        }
        const entries = [];
        for (const key of Reflect.ownKeys(value)) {
            if (typeof key !== 'string') {
                return INVALID_JSON_COMPATIBLE_VALUE;
            }
            const descriptor = Object.getOwnPropertyDescriptor(value, key);
            if (!descriptor) {
                return INVALID_JSON_COMPATIBLE_VALUE;
            }
            if (!descriptor.enumerable) {
                continue;
            }
            if (!('value' in descriptor)) {
                return INVALID_JSON_COMPATIBLE_VALUE;
            }
            const entry = normalizeJsonCompatibleValueInternal(descriptor.value, ancestors);
            if (entry === INVALID_JSON_COMPATIBLE_VALUE) {
                return INVALID_JSON_COMPATIBLE_VALUE;
            }
            entries.push([key, entry]);
        }
        return Object.fromEntries(entries);
    }
    finally {
        ancestors.delete(value);
    }
}
function hasUnsupportedToJsonProtocol(value) {
    let current = value;
    while (current !== null) {
        const descriptor = Object.getOwnPropertyDescriptor(current, 'toJSON');
        if (descriptor) {
            return !('value' in descriptor) || typeof descriptor.value === 'function';
        }
        current = Object.getPrototypeOf(current);
    }
    return false;
}
const jsonCompatibleValueSchema = z.preprocess(normalizeJsonCompatibleValue, z.custom((value) => value !== INVALID_JSON_COMPATIBLE_VALUE, { message: 'Expected JSON-compatible data.' }));
const itemSchema = z.discriminatedUnion('type', [
    z.object({
        type: z.literal('input_item'),
        rawItem: protocol.ModelItem,
        agent: serializedAgentSchema,
        inputId: z.string().min(1),
    }),
    z.object({
        type: z.literal('message_output_item'),
        rawItem: protocol.AssistantMessageItem,
        agent: serializedAgentSchema,
    }),
    z.object({
        type: z.literal('tool_search_call_item'),
        rawItem: protocol.ToolSearchCallItem,
        agent: serializedAgentSchema,
    }),
    z.object({
        type: z.literal('tool_search_output_item'),
        rawItem: protocol.ToolSearchOutputItem,
        agent: serializedAgentSchema,
    }),
    z.object({
        type: z.literal('tool_call_item'),
        rawItem: protocol.ToolCallItem.or(protocol.HostedToolCallItem),
        agent: serializedAgentSchema,
        functionToolStateKey: z.string().optional(),
    }),
    z.object({
        type: z.literal('tool_call_output_item'),
        rawItem: protocol.FunctionCallResultItem.or(protocol.ComputerCallResultItem)
            .or(protocol.ShellCallResultItem)
            .or(protocol.ApplyPatchCallResultItem)
            .or(protocol.ProgramCallResultItem),
        agent: serializedAgentSchema,
        output: jsonCompatibleValueSchema,
        customData: z.record(z.string(), z.any()).optional(),
        executionStatus: z.literal('executed').optional(),
    }),
    z.object({
        type: z.literal('reasoning_item'),
        rawItem: protocol.ReasoningItem,
        agent: serializedAgentSchema,
    }),
    z.object({
        type: z.literal('compaction_item'),
        rawItem: protocol.CompactionItem,
        agent: serializedAgentSchema,
    }),
    z.object({
        type: z.literal('handoff_call_item'),
        rawItem: protocol.FunctionCallItem,
        agent: serializedAgentSchema,
    }),
    z.object({
        type: z.literal('handoff_output_item'),
        rawItem: protocol.FunctionCallResultItem,
        sourceAgent: serializedAgentSchema,
        targetAgent: serializedAgentSchema,
    }),
    z.object({
        type: z.literal('tool_approval_item'),
        rawItem: protocol.FunctionCallItem.or(protocol.HostedToolCallItem)
            .or(protocol.ComputerUseCallItem)
            .or(protocol.ShellCallItem)
            .or(protocol.ApplyPatchCallItem),
        agent: serializedAgentSchema,
        toolName: z.string().optional(),
        functionToolStateKey: z.string().optional(),
    }),
]);
const serializedToolInvocationCompletionEvidenceItemSchema = z.union([
    z
        .object({
        generatedItemIndex: z.number().int().min(0),
    })
        .strict(),
    z
        .object({
        item: itemSchema,
    })
        .strict(),
]);
const serializedToolInvocationCompletionEvidenceSchema = z
    .object({
    fingerprint: z.string(),
    items: z.tuple([
        serializedToolInvocationCompletionEvidenceItemSchema,
        serializedToolInvocationCompletionEvidenceItemSchema,
    ]),
})
    .strict();
function serializeAgentInvocationEvidence(records, agentIdentityKeys, generatedItems) {
    const serialized = [];
    const generatedItemIndexes = new Map(generatedItems.map((item, index) => [item, index]));
    for (const [agent, invocations] of records) {
        const agentIdentity = agentIdentityKeys.get(agent);
        if (!agentIdentity || invocations.size === 0) {
            continue;
        }
        serialized.push({
            agentIdentity,
            invocations: Object.fromEntries([...invocations].map(([callId, evidence]) => [
                callId,
                {
                    fingerprint: evidence.fingerprint,
                    items: evidence.items.map((item) => {
                        const generatedItemIndex = generatedItemIndexes.get(item);
                        return generatedItemIndex === undefined
                            ? { item: serializeRunItem(item, agentIdentityKeys) }
                            : { generatedItemIndex };
                    }),
                },
            ])),
        });
    }
    return serialized;
}
function deserializeAgentInvocationEvidence(records, agentsByIdentity, generatedItems) {
    const deserialized = new Map();
    const seenAgentIdentities = new Set();
    for (const { agentIdentity, invocations } of records) {
        const agent = agentsByIdentity.get(agentIdentity);
        if (!agent || seenAgentIdentities.has(agentIdentity)) {
            throw new UserError('RunState contains invalid completed tool invocation evidence ownership for the current agent graph.');
        }
        seenAgentIdentities.add(agentIdentity);
        deserialized.set(agent, new Map(Object.entries(invocations).map(([callId, evidence]) => [
            callId,
            {
                fingerprint: evidence.fingerprint,
                items: evidence.items.map((reference) => {
                    if ('generatedItemIndex' in reference) {
                        const generatedItem = generatedItems[reference.generatedItemIndex];
                        if (!generatedItem) {
                            throw new UserError('RunState completed tool invocation evidence references a missing generated item.');
                        }
                        return generatedItem;
                    }
                    return deserializeItem(reference.item, agentsByIdentity);
                }),
            },
        ])));
    }
    return deserialized;
}
const serializedTraceSchema = z.object({
    object: z.literal('trace'),
    id: z.string(),
    workflow_name: z.string(),
    group_id: z.string().nullable(),
    metadata: z.record(z.string(), z.any()),
    // Populated only if the trace was created with a per-run tracingApiKey (e.g., Runner.run({ tracing: { apiKey } }))
    // and serialization opts in to include it. By default this is omitted to avoid persisting secrets.
    tracing_api_key: z.string().optional().nullable(),
});
const sandboxSessionStateEnvelopeSchema = z
    .object({
    version: z.union(SUPPORTED_SANDBOX_SESSION_STATE_VERSIONS.map((version) => z.literal(version))),
    backendId: z.string(),
    environmentPreparation: z.literal('client').optional(),
    manifest: z.record(z.string(), z.any()),
    snapshot: z.record(z.string(), z.any()).nullable().optional(),
    snapshotFingerprint: z.string().nullable().optional(),
    snapshotFingerprintVersion: z.string().nullable().optional(),
    workspaceReady: z.boolean(),
    exposedPorts: z.record(z.string(), z.any()).optional(),
    providerState: z.record(z.string(), z.any()),
})
    .superRefine((envelope, context) => {
    if (envelope.environmentPreparation === 'client' &&
        envelope.version !== SANDBOX_SESSION_STATE_VERSION) {
        context.addIssue({
            code: 'custom',
            message: 'Client-owned environment preparation requires the current sandbox session envelope version.',
        });
    }
});
const sandboxSessionEntrySchema = z.object({
    backendId: z.string(),
    currentAgentKey: z.string(),
    currentAgentName: z.string(),
    sessionState: sandboxSessionStateEnvelopeSchema,
    preservedOwnedSession: z.boolean().optional(),
    reuseLiveSession: z.boolean().optional(),
    requiresFreshCreation: z.boolean().optional(),
});
const sandboxStateSchema = z.object({
    backendId: z.string(),
    currentAgentKey: z.string(),
    currentAgentName: z.string(),
    sessionState: sandboxSessionStateEnvelopeSchema,
    sessionsByAgent: z.record(z.string(), sandboxSessionEntrySchema),
});
const handoffInputSnapshotSchema = z.object({
    originalInput: z.string().or(z.array(protocol.ModelItem)),
    generatedItems: z.array(itemSchema),
});
const serializedProcessedResponseSchema = z.object({
    newItems: z.array(itemSchema),
    toolsUsed: z.array(z.string()),
    handoffs: z.array(z.object({
        toolCall: z.any(),
        handoff: z.any(),
        targetAgent: serializedAgentSchema.optional(),
    })),
    functions: z.array(z.object({
        toolCall: z.any(),
        tool: z.any(),
        mcpToolBinding: z
            .union([
            z.object({
                serverName: z.string(),
                toolName: z.string(),
                serverIndex: z.number().int().nonnegative().nullable(),
            }),
            z.null(),
            z.literal('unknown'),
        ])
            .optional(),
    })),
    functionToolsNotFound: z
        .array(z.object({
        toolCall: z.any(),
        toolName: z.string(),
        // Describes the error only; persisted input cannot select search execution.
        reason: z.literal('not_loaded').optional(),
    }))
        .optional(),
    computerActions: z.array(z.object({
        toolCall: z.any(),
        computer: z.any(),
    })),
    shellActions: z
        .array(z.object({
        toolCall: z.any(),
        shell: z.any(),
    }))
        .optional(),
    applyPatchActions: z
        .array(z.object({
        toolCall: z.any(),
        applyPatch: z.any(),
    }))
        .optional(),
    mcpApprovalRequests: z
        .array(z.object({
        requestItem: z.object({
            // protocol.HostedToolCallItem
            rawItem: z.object({
                type: z.literal('hosted_tool_call'),
                name: z.string(),
                arguments: z.string().optional(),
                status: z.string().optional(),
                output: z.string().optional(),
                caller: protocol.ToolCaller.optional(),
                // this always exists but marked as optional for early version compatibility; when releasing 1.0, we can remove the nullable and optional
                providerData: z.record(z.string(), z.any()).nullable().optional(),
            }),
        }),
        // HostedMCPTool
        mcpTool: z.object({
            type: z.literal('hosted_tool'),
            name: z.literal('hosted_mcp'),
            providerData: z.record(z.string(), z.any()),
        }),
    }))
        .optional(),
});
const currentResponseGeneratedItemOwnershipSchema = z
    .object({
    generatedItemStartIndex: z.number().int().min(0),
    generatedItemEndIndexExclusive: z.number().int().min(0),
    interruptionGeneratedItemIndexes: z.array(z.number().int().min(0).nullable()),
    toolOutputGuardrailResultStartIndex: z.number().int().min(0),
})
    .strict();
const guardrailFunctionOutputSchema = z.object({
    tripwireTriggered: z.boolean(),
    outputInfo: z.any().optional(),
});
const toolGuardrailBehaviorSchema = z.discriminatedUnion('type', [
    z.object({ type: z.literal('allow') }),
    z.object({
        type: z.literal('rejectContent'),
        message: z.string(),
    }),
    z.object({ type: z.literal('throwException') }),
]);
const toolGuardrailFunctionOutputSchema = z.object({
    outputInfo: z.any().optional(),
    behavior: toolGuardrailBehaviorSchema,
});
const toolGuardrailMetadataSchema = z.object({
    type: z.union([z.literal('tool_input'), z.literal('tool_output')]),
    name: z.string(),
});
const inputGuardrailResultSchema = z.object({
    guardrail: z.object({
        type: z.literal('input'),
        name: z.string(),
    }),
    output: guardrailFunctionOutputSchema,
});
const outputGuardrailResultSchema = z.object({
    guardrail: z.object({
        type: z.literal('output'),
        name: z.string(),
    }),
    agentOutput: z.any(),
    agent: serializedAgentSchema,
    output: guardrailFunctionOutputSchema,
});
const toolInputGuardrailResultSchema = z.object({
    guardrail: toolGuardrailMetadataSchema.extend({
        type: z.literal('tool_input'),
    }),
    output: toolGuardrailFunctionOutputSchema,
});
const toolOutputGuardrailResultSchema = z.object({
    guardrail: toolGuardrailMetadataSchema.extend({
        type: z.literal('tool_output'),
    }),
    output: toolGuardrailFunctionOutputSchema,
});
const approvalRecordSchema = z.object({
    approved: z.array(z.string()).or(z.boolean()),
    rejected: z.array(z.string()).or(z.boolean()),
    messages: z.record(z.string(), z.string()).optional(),
    stickyRejectMessage: z.string().optional(),
});
const canonicalFunctionToolStateKeySchema = z
    .string()
    .refine((value) => getFunctionToolLegacyStateKeyFromStateKey(value) !== undefined, 'Function approval keys must use a canonical category-aware identity.');
const functionApprovalsSchema = z.array(z.object({
    agentIdentity: z.string(),
    approvals: z.record(canonicalFunctionToolStateKeySchema, approvalRecordSchema),
}));
const functionApprovalContextSchema = z.object({
    functionApprovals: functionApprovalsSchema.optional(),
    legacyFunctionApprovals: z
        .record(z.string(), approvalRecordSchema)
        .optional(),
    approvalInvocations: z
        .array(z.object({
        agentIdentity: z.string(),
        invocations: z.record(z.string(), z.string()),
        approvals: z.record(z.string(), approvalRecordSchema),
    }))
        .optional(),
});
export const SerializedRunState = z.object({
    $schemaVersion,
    currentTurn: z.number(),
    currentAgent: serializedAgentSchema,
    originalInput: z.string().or(z.array(protocol.ModelItem)),
    pendingInput: z.array(protocol.ModelItem).optional(),
    modelResponses: z.array(modelResponseSchema),
    context: z.object({
        usage: usageSchema,
        approvals: z.record(z.string(), approvalRecordSchema),
        hostedMcpApprovals: z.record(z.string(), approvalRecordSchema).optional(),
        functionApprovals: functionApprovalsSchema.optional(),
        legacyFunctionApprovals: z
            .record(z.string(), approvalRecordSchema)
            .optional(),
        approvalInvocations: z
            .array(z.object({
            agentIdentity: z.string(),
            invocations: z.record(z.string(), z.string()),
            approvals: z.record(z.string(), approvalRecordSchema),
        }))
            .optional(),
        context: z.record(z.string(), z.any()),
        toolInput: z.any().optional(),
    }),
    toolUseTracker: z.record(z.string(), z.array(z.string())),
    maxTurns: z.number().nullable(),
    currentAgentSpan: SerializedSpan.nullable().optional(),
    noActiveAgentRun: z.boolean(),
    inputGuardrailResults: z.array(inputGuardrailResultSchema),
    initialInputGuardrailsCompleted: z.boolean().optional(),
    outputGuardrailResults: z.array(outputGuardrailResultSchema),
    toolInputGuardrailResults: z
        .array(toolInputGuardrailResultSchema)
        .optional()
        .default([]),
    toolOutputGuardrailResults: z
        .array(toolOutputGuardrailResultSchema)
        .optional()
        .default([]),
    currentTurnInProgress: z.boolean().optional(),
    currentStep: nextStepSchema.optional(),
    lastModelResponse: modelResponseSchema.optional(),
    generatedItems: z.array(itemSchema),
    currentResponseGeneratedItemOwnership: currentResponseGeneratedItemOwnershipSchema.optional(),
    pendingAgentToolRuns: z.record(z.string(), z.string()).optional().default({}),
    pendingAgentToolRunAliases: z
        .record(z.string(), z.string())
        .optional()
        .default({}),
    lastProcessedResponse: serializedProcessedResponseSchema.optional(),
    currentTurnPersistedItemCount: z.number().int().min(0).optional(),
    currentTurnSessionWriteCompactedItemCount: z.number().int().min(0).optional(),
    currentTurnDeferredSessionItemIndexes: z
        .array(z.number().int().min(0))
        .optional(),
    currentTurnBlockedSessionStartIndex: z.number().int().min(0).optional(),
    currentTurnExecutedWithSessionBinding: z.literal(true).optional(),
    currentTurnSessionInputItems: z.array(protocol.ModelItem).optional(),
    pendingSessionHistoryTransaction: pendingSessionHistoryTransactionSchema.optional(),
    pendingSessionWrite: pendingSessionWriteSchema.optional(),
    completedToolInvocations: z
        .array(z.object({
        agentIdentity: z.string(),
        invocations: z.record(z.string(), z.string()),
    }))
        .optional(),
    completedToolInvocationEvidence: z
        .array(z.object({
        agentIdentity: z.string(),
        invocations: z.record(z.string(), serializedToolInvocationCompletionEvidenceSchema),
    }))
        .optional(),
    ambiguousToolInvocationCallIds: z
        .array(z.object({
        agentIdentity: z.string(),
        callIds: z.array(z.string()),
    }))
        .optional(),
    pendingLegacyCompactionSessionItems: z.array(protocol.ModelItem).optional(),
    conversationId: z.string().optional(),
    previousResponseId: z.string().optional(),
    reasoningItemIdPolicy: z.enum(['preserve', 'omit']).optional(),
    trace: serializedTraceSchema.nullable(),
    sandbox: sandboxStateSchema.optional(),
});
function findUniqueContiguousIdentityStart(items, sequence) {
    if (sequence.length === 0 || sequence.length > items.length) {
        return undefined;
    }
    let match;
    for (let start = 0; start <= items.length - sequence.length; start += 1) {
        if (!sequence.every((item, offset) => {
            const candidate = items[start + offset];
            if (candidate === item) {
                return true;
            }
            try {
                return (candidate !== undefined &&
                    candidate.type === item.type &&
                    'rawItem' in candidate &&
                    'rawItem' in item &&
                    candidate.rawItem === item.rawItem);
            }
            catch {
                return false;
            }
        })) {
            continue;
        }
        if (match !== undefined) {
            return undefined;
        }
        match = start;
    }
    return match;
}
function responseOwnsFunctionCall(response, call) {
    const matches = response?.output.filter((item) => item.type === 'function_call' && item.callId === call.callId);
    if (matches?.length !== 1)
        return false;
    const candidate = matches[0];
    return (getToolInvocationFingerprint(getFunctionToolStateKeyForCall(candidate) ?? candidate.name, candidate) ===
        getToolInvocationFingerprint(getFunctionToolStateKeyForCall(call) ?? call.name, call));
}
function captureCurrentResponseGeneratedItemOwnership(state) {
    if (state._currentStep?.type !== 'next_step_interruption') {
        return undefined;
    }
    const processedItems = state._lastProcessedResponse?.newItems ?? [];
    const interruptions = state._currentStep.data.interruptions;
    if (processedItems.length === 0 || interruptions.length === 0) {
        return undefined;
    }
    const generatedItemStartIndex = findUniqueContiguousIdentityStart(state._generatedItems, processedItems);
    if (generatedItemStartIndex === undefined) {
        return undefined;
    }
    const processedEndIndex = generatedItemStartIndex + processedItems.length;
    const interruptionGeneratedItemIndexes = [];
    let previousParentIndex = processedEndIndex - 1;
    let captureNestedOwnership;
    for (const interruption of interruptions) {
        const matchingIndexes = state._generatedItems.flatMap((item, index) => {
            if (index < processedEndIndex) {
                return [];
            }
            if (item === interruption) {
                return [index];
            }
            try {
                if ('rawItem' in item && item.rawItem === interruption.rawItem) {
                    return [index];
                }
                // A partial live resume can recreate the remaining approval wrapper. In that case,
                // use the existing canonical invocation identity, but only inside the already-proven
                // terminal current-response range and only when it selects one candidate.
                return item instanceof RunToolApprovalItem &&
                    item.agent === interruption.agent &&
                    getToolInvocationCallId(item.rawItem) ===
                        getToolInvocationCallId(interruption.rawItem) &&
                    getToolInvocationFingerprint(item.functionToolStateKey ?? item.name ?? '', item.rawItem) ===
                        getToolInvocationFingerprint(interruption.functionToolStateKey ?? interruption.name ?? '', interruption.rawItem)
                    ? [index]
                    : [];
            }
            catch {
                return [];
            }
        });
        if (matchingIndexes.length === 0 &&
            (captureNestedOwnership ??= needsNestedApprovalOwnership(state, generatedItemStartIndex)) &&
            state._ownsNestedApproval(interruption, interruptions)) {
            interruptionGeneratedItemIndexes.push(null);
            continue;
        }
        if (matchingIndexes.length !== 1 ||
            matchingIndexes[0] <= previousParentIndex) {
            return undefined;
        }
        previousParentIndex = matchingIndexes[0];
        interruptionGeneratedItemIndexes.push(previousParentIndex);
    }
    const lastModelResponseIndex = state._modelResponses.lastIndexOf(state._lastTurnResponse);
    if (state._lastTurnResponse === undefined ||
        lastModelResponseIndex !== state._modelResponses.length - 1 ||
        state._modelResponses.indexOf(state._lastTurnResponse) !==
            lastModelResponseIndex) {
        return undefined;
    }
    const toolOutputGuardrailResultStartIndex = getCurrentResponseToolOutputGuardrailResultStart(state);
    if (toolOutputGuardrailResultStartIndex === undefined ||
        toolOutputGuardrailResultStartIndex >
            state._toolOutputGuardrailResults.length) {
        return undefined;
    }
    return {
        generatedItemStartIndex,
        generatedItemEndIndexExclusive: state._generatedItems.length,
        interruptionGeneratedItemIndexes,
        toolOutputGuardrailResultStartIndex,
    };
}
function serializedValuesEqual(left, right) {
    try {
        return JSON.stringify(left) === JSON.stringify(right);
    }
    catch {
        return false;
    }
}
function throwCurrentResponseOwnershipError(reason = 'invalid boundary') {
    throw new UserError(`RunState current-response generated-item ownership has an ${reason}. Start a new run from safe input.`);
}
function validateCurrentResponseGeneratedItemOwnership(stateJson, ownership) {
    // Validate only serialized values here, before tool rehydration or caller-owned context work.
    // Deserialized object identity is restored only after the complete terminal boundary is proven.
    const processedItems = stateJson.lastProcessedResponse?.newItems;
    const serializedInterruptions = stateJson.currentStep?.type === 'next_step_interruption' &&
        Array.isArray(stateJson.currentStep.data?.interruptions)
        ? stateJson.currentStep.data.interruptions
        : undefined;
    const generatedEnd = ownership.generatedItemEndIndexExclusive;
    const processedEnd = ownership.generatedItemStartIndex + (processedItems?.length ?? 0);
    if (!processedItems ||
        processedItems.length === 0 ||
        !serializedInterruptions ||
        serializedInterruptions.length === 0 ||
        !stateJson.lastModelResponse ||
        stateJson.modelResponses.length === 0 ||
        generatedEnd !== stateJson.generatedItems.length ||
        ownership.generatedItemStartIndex >= generatedEnd ||
        processedEnd > generatedEnd ||
        ownership.interruptionGeneratedItemIndexes.length !==
            serializedInterruptions.length ||
        ownership.toolOutputGuardrailResultStartIndex >
            stateJson.toolOutputGuardrailResults.length ||
        !serializedValuesEqual(stateJson.lastModelResponse, stateJson.modelResponses.at(-1))) {
        throwCurrentResponseOwnershipError();
    }
    for (const [offset, processedItem] of processedItems.entries()) {
        if (!serializedValuesEqual(processedItem, stateJson.generatedItems[ownership.generatedItemStartIndex + offset])) {
            throwCurrentResponseOwnershipError();
        }
    }
    const interruptionIndexes = new Set();
    let previousParentIndex = processedEnd - 1;
    for (const [offset, interruptionIndex,] of ownership.interruptionGeneratedItemIndexes.entries()) {
        const parsedInterruption = itemSchema.safeParse(serializedInterruptions[offset]);
        if (interruptionIndex === null) {
            if (stateJson.$schemaVersion !== CURRENT_SCHEMA_VERSION ||
                !parsedInterruption.success ||
                parsedInterruption.data.type !== 'tool_approval_item' ||
                parsedInterruption.data.rawItem.type !== 'function_call') {
                throwCurrentResponseOwnershipError('invalid child approval');
            }
            // The pending invocation is checked against the configured asTool source after rehydration.
            continue;
        }
        const mismatch = !serializedValuesEqual(parsedInterruption.success ? parsedInterruption.data : undefined, stateJson.generatedItems[interruptionIndex]);
        if (!parsedInterruption.success ||
            parsedInterruption.data.type !== 'tool_approval_item' ||
            interruptionIndex <= previousParentIndex ||
            interruptionIndex >= generatedEnd ||
            mismatch) {
            throwCurrentResponseOwnershipError(mismatch ? 'interruption content mismatch' : 'interruption index error');
        }
        previousParentIndex = interruptionIndex;
        interruptionIndexes.add(interruptionIndex);
    }
    const unownedApproval = stateJson.generatedItems
        .slice(processedEnd, generatedEnd)
        .some((item, offset) => item.type === 'tool_approval_item' &&
        !interruptionIndexes.has(processedEnd + offset));
    if (unownedApproval) {
        throwCurrentResponseOwnershipError();
    }
}
function cloneInterruptionSnapshot(interruption) {
    let rawItem;
    try {
        rawItem = structuredClone(interruption.rawItem);
    }
    catch {
        throw new UserError('Cannot read RunState interruptions because an interruption raw item is not cloneable.');
    }
    if (containsSharedArrayBuffer(rawItem)) {
        throw new UserError('Cannot read RunState interruptions because an interruption raw item contains shared memory.');
    }
    return new RunToolApprovalItem(rawItem, interruption.agent, interruption.toolName, interruption.functionToolStateKey);
}
function containsSharedArrayBuffer(value) {
    if (typeof SharedArrayBuffer === 'undefined') {
        return false;
    }
    const visited = new Set();
    const pending = [value];
    while (pending.length > 0) {
        const current = pending.pop();
        if (!current || typeof current !== 'object') {
            continue;
        }
        if (current instanceof SharedArrayBuffer) {
            return true;
        }
        if (ArrayBuffer.isView(current) &&
            current.buffer instanceof SharedArrayBuffer) {
            return true;
        }
        if (typeof WebAssembly !== 'undefined' &&
            current instanceof WebAssembly.Memory &&
            current.buffer instanceof SharedArrayBuffer) {
            return true;
        }
        if (visited.has(current)) {
            continue;
        }
        visited.add(current);
        if (current instanceof Map) {
            for (const [key, entry] of current) {
                pending.push(key, entry);
            }
            continue;
        }
        if (current instanceof Set) {
            for (const entry of current) {
                pending.push(entry);
            }
            continue;
        }
        for (const key of Reflect.ownKeys(current)) {
            const descriptor = Object.getOwnPropertyDescriptor(current, key);
            if (descriptor && 'value' in descriptor) {
                pending.push(descriptor.value);
            }
        }
    }
    return false;
}
/**
 * Serializable snapshot of an agent's run, including context, usage and trace.
 * While this class has publicly writable properties (prefixed with `_`), they are not meant to be
 * used directly. To read these properties, use the `RunResult` instead.
 *
 * Manipulation of the state directly can lead to unexpected behavior and should be avoided.
 * Instead, use the `approve` and `reject` methods to interact with the state.
 */
export class RunState {
    /**
     * Current turn number in the conversation.
     */
    _currentTurn = 0;
    /**
     * Whether the current turn has already been counted (useful when resuming mid-turn).
     */
    _currentTurnInProgress = false;
    /** Whether the complete initial input guardrail batch passed, including an empty batch. */
    _initialInputGuardrailsCompleted = false;
    /**
     * The agent currently handling the conversation.
     */
    _currentAgent;
    /**
     * The root agent that started the run.
     */
    #startingAgent;
    /**
     * Original user input prior to any processing.
     */
    _originalInput;
    /**
     * Input staged for admission immediately before the next resumed model call.
     */
    _pendingInput;
    /**
     * Responses from the model so far.
     */
    _modelResponses;
    /**
     * Conversation identifier when the server manages conversation history.
     */
    _conversationId;
    /**
     * Latest response identifier returned by the server for server-managed conversations.
     */
    _previousResponseId;
    /**
     * Runtime options that control how run items are converted into model turn input.
     * This value is serialized so resumed runs keep the same turn-input behavior.
     */
    _reasoningItemIdPolicy;
    /**
     * Effective model settings used for the most recent model call.
     */
    _lastModelSettings;
    /**
     * Active tracing span for the current agent if tracing is enabled.
     */
    _currentAgentSpan;
    /**
     * Run context tracking approvals, usage, and other metadata.
     */
    _context;
    /**
     * Runtime-only metadata for the current nested agent-tool invocation.
     */
    _agentToolInvocation;
    /**
     * The usage aggregated for this run. This includes per-request breakdowns when available.
     */
    get usage() {
        return this._context.usage;
    }
    /**
     * Tracks what tools each agent has used.
     */
    _toolUseTracker;
    /**
     * Serialized pending nested agent runs keyed by tool name and call id.
     */
    _pendingAgentToolRuns;
    /**
     * Pending conditional approval input lives only in the owning RunState.
     * Neither normalized values nor comparison evidence are serialized.
     * @internal
     */
    _pendingFunctionToolApprovals = new Map();
    /**
     * Legacy pending-run keys mapped to their canonical category-aware keys.
     */
    _pendingAgentToolRunAliases;
    /**
     * Canonical invocation fingerprints whose local tool outputs are committed to run history.
     */
    _completedToolInvocations;
    /**
     * Completed invocations whose supporting run items were removed by a
     * supported history replacement.
     */
    _completedToolInvocationEvidence;
    /**
     * Canonical invocations observed in the active run before their outputs are committed.
     */
    _observedToolInvocations;
    /**
     * Legacy call IDs whose serialized history cannot identify one canonical invocation.
     */
    _ambiguousToolInvocationCallIds;
    /**
     * Items generated by the agent during the run.
     */
    _generatedItems;
    /**
     * Number of `_generatedItems` already flushed to session storage for the current turn.
     *
     * Persisting the entire turn on every save would duplicate responses and tool outputs.
     * Instead, `saveToSession` appends only the delta since the previous write. This counter
     * tracks how many generated run items from *this turn* were already written so the next
     * save can slice off only the new entries. When a turn is interrupted (e.g., awaiting tool
     * approval) and later resumed, we rewind the counter before continuing so the pending tool
     * output still gets stored.
     */
    _currentTurnPersistedItemCount;
    /**
     * Persisted-item count whose resumed-write recovery input compaction has settled.
     */
    _currentTurnSessionWriteCompactedItemCount;
    /**
     * Current-turn item indexes intentionally deferred when a blocked output persisted only a
     * replay-safe subset. A later accepted resume replaces the sparse suffix in original order.
     */
    _currentTurnDeferredSessionItemIndexes;
    /**
     * First current-turn index governed by the sparse blocked-output session suffix.
     */
    _currentTurnBlockedSessionStartIndex;
    /**
     * Logical session bound to the current turn before a transaction-aware tool effect can occur.
     */
    _currentTurnSessionHistoryTransactionSessionId;
    /**
     * Effective reasoning-item ID policy frozen for the current transaction-aware session turn.
     */
    _currentTurnSessionReasoningItemIdPolicy;
    /**
     * Normalized session input frozen before the current transaction-aware model request.
     */
    _currentTurnSessionHistoryTransactionInputItems;
    /**
     * Whether the current live batch may later replace its sparse suffix with accepted output.
     */
    _currentTurnSessionHistoryTransactionCanReplaceAcceptedOutput;
    /**
     * Current step reconstructed from serialized state. This reference is not serialized and is
     * cleared implicitly when the live runner installs another step.
     */
    _serializedCurrentStep;
    /**
     * Stable per-run identifier used to derive idempotent session history transaction IDs.
     */
    _sessionHistoryTransactionId;
    /**
     * Transaction reconstruction data awaiting confirmation from the session backend. Its
     * generated-item indexes, operation identity, and post-commit bookkeeping remain stable across
     * retries on the same live RunState; input stays in the separately frozen current-turn snapshot.
     */
    _pendingSessionHistoryTransaction;
    /**
     * Ordinary Session append whose outcome must be reconciled before another resumed model call.
     */
    _pendingSessionWrite;
    /**
     * Prevents two live resume attempts from executing or reconciling the same resumed Session
     * append concurrently.
     */
    _resumedSessionWriteInProgress;
    /**
     * Compaction marker and persisted suffix that an ordinary session must reconcile once after a
     * pre-1.16 snapshot is restored. The field remains serialized until reconciliation succeeds.
     */
    _pendingLegacyCompactionSessionItems;
    /**
     * Maximum allowed turns before forcing termination.
     */
    _maxTurns;
    /**
     * Whether the run has an active agent step in progress.
     */
    _noActiveAgentRun = true;
    /**
     * Last model response for the previous turn.
     */
    _lastTurnResponse;
    /**
     * Results from input guardrails applied to the run.
     */
    _inputGuardrailResults;
    /**
     * Results from output guardrails applied to the run.
     */
    _outputGuardrailResults;
    /**
     * Results from tool input guardrails applied during tool execution.
     */
    _toolInputGuardrailResults;
    /**
     * Results from tool output guardrails applied during tool execution.
     */
    _toolOutputGuardrailResults;
    /**
     * Next step computed for the agent to take.
     */
    _currentStep = undefined;
    /**
     * Indicates how the final output was produced for the current run.
     * This value is not serialized.
     */
    _finalOutputSource;
    /**
     * Parsed model response after applying guardrails and tools.
     */
    _lastProcessedResponse = undefined;
    /**
     * Trace associated with this run if tracing is enabled.
     */
    _trace = null;
    /**
     * Runtime-only tool_search-loaded tools, scoped by agent object and preserved across turns for
     * the lifetime of this in-memory run.
     */
    _toolSearchRuntimeToolsByAgent = new Map();
    /**
     * Persisted sandbox session metadata for sandbox-agent resume.
     */
    _sandbox = undefined;
    constructor(context, originalInput, startingAgent, maxTurns) {
        this._context = context;
        this._agentToolInvocation = undefined;
        this._originalInput = structuredClone(originalInput);
        this._pendingInput = [];
        this._modelResponses = [];
        this._currentAgentSpan = undefined;
        this._currentAgent = startingAgent;
        this.#startingAgent = startingAgent;
        this._reasoningItemIdPolicy = undefined;
        this._toolUseTracker = new AgentToolUseTracker();
        this._pendingAgentToolRuns = new Map();
        this._pendingAgentToolRunAliases = new Map();
        this._completedToolInvocations = new Map();
        this._completedToolInvocationEvidence = new Map();
        this._observedToolInvocations = new Map();
        this._ambiguousToolInvocationCallIds = new Map();
        this._generatedItems = [];
        this._currentTurnPersistedItemCount = 0;
        this._currentTurnSessionWriteCompactedItemCount = undefined;
        this._currentTurnDeferredSessionItemIndexes = new Set();
        this._currentTurnBlockedSessionStartIndex = undefined;
        this._currentTurnSessionHistoryTransactionSessionId = undefined;
        this._currentTurnSessionReasoningItemIdPolicy = undefined;
        this._currentTurnSessionHistoryTransactionInputItems = undefined;
        this._currentTurnSessionHistoryTransactionCanReplaceAcceptedOutput =
            undefined;
        this._serializedCurrentStep = undefined;
        this._sessionHistoryTransactionId = randomUUID();
        this._pendingSessionHistoryTransaction = undefined;
        this._pendingSessionWrite = undefined;
        this._resumedSessionWriteInProgress = false;
        this._pendingLegacyCompactionSessionItems = undefined;
        this._maxTurns = maxTurns;
        this._inputGuardrailResults = [];
        this._outputGuardrailResults = [];
        this._toolInputGuardrailResults = [];
        this._toolOutputGuardrailResults = [];
        this._trace = getCurrentTrace();
    }
    /**
     * Updates server-managed conversation identifiers as a single operation.
     */
    setConversationContext(conversationId, previousResponseId) {
        this._conversationId = conversationId;
        this._previousResponseId = previousResponseId;
    }
    /**
     * Updates runtime options for converting run items into turn input.
     */
    setReasoningItemIdPolicy(policy) {
        this._reasoningItemIdPolicy = policy;
    }
    /**
     * Updates the agent span associated with the current run.
     */
    setCurrentAgentSpan(span) {
        this._currentAgentSpan = span;
    }
    /**
     * Clears the restored trace and current agent span from this run state.
     *
     * Use this before resuming a serialized state when the resumed run should attach
     * to the current ambient trace instead of the trace persisted in the state.
     */
    clearTrace() {
        this._trace = null;
        this._currentAgentSpan = undefined;
    }
    /**
     * Validate and observe a canonical local tool invocation before side effects.
     * @internal
     * @returns Whether the exact invocation already has a committed output.
     */
    _observeToolInvocation(agent, callId, fingerprint) {
        const completed = this._preflightToolInvocation(agent, callId, fingerprint);
        if (!completed) {
            getAgentInvocationMap(this._observedToolInvocations, agent).set(callId, fingerprint);
        }
        return completed;
    }
    /**
     * Validate a canonical local tool invocation without recording it.
     * @internal
     */
    _preflightToolInvocation(agent, callId, fingerprint) {
        this._context._validateAgentApprovalInvocation(agent, callId, fingerprint);
        const ambiguous = this._ambiguousToolInvocationCallIds.get(agent);
        if (ambiguous?.has(callId)) {
            throw new ModelBehaviorError(`Tool call ID ${callId} has ambiguous invocation history and cannot be executed safely.`, this);
        }
        const completed = this._completedToolInvocations.get(agent)?.get(callId);
        if (completed !== undefined) {
            if (completed !== fingerprint) {
                throw new ModelBehaviorError(`Tool call ID ${callId} was reused for a different invocation after its output was committed.`, this);
            }
            return true;
        }
        const observed = this._observedToolInvocations.get(agent)?.get(callId);
        if (observed !== undefined && observed !== fingerprint) {
            throw new ModelBehaviorError(`Tool call ID ${callId} was reused for different tool invocations in the same run.`, this);
        }
        return false;
    }
    /**
     * Commit fingerprints for local tool output items added to run history.
     * @internal
     */
    _commitToolInvocations(items) {
        const evidenceCandidates = [...this._generatedItems, ...items];
        const commit = (agent, callId, outputItem) => {
            const fingerprint = this._observedToolInvocations.get(agent)?.get(callId);
            if (fingerprint === undefined) {
                return;
            }
            const evidence = findToolInvocationCompletionEvidence(agent, callId, fingerprint, outputItem, evidenceCandidates);
            if (!evidence) {
                return;
            }
            // Preserve the execution-time owner when resuming older pending calls that
            // predate call-item identity metadata. Observed invocations are runtime-only.
            const toolName = getToolInvocationNameFromFingerprint(fingerprint);
            for (const candidate of evidenceCandidates) {
                if (toolName !== undefined &&
                    candidate instanceof RunToolCallItem &&
                    candidate.functionToolStateKey === undefined &&
                    candidate.agent === agent &&
                    candidate.rawItem.type === 'function_call' &&
                    candidate.rawItem.callId === callId &&
                    !getToolCallNamespace(candidate.rawItem) &&
                    toolName ===
                        getFunctionToolLookupKey(candidate.rawItem.name, candidate.rawItem.name) &&
                    getToolInvocationFingerprint(toolName, candidate.rawItem) ===
                        fingerprint) {
                    candidate.functionToolStateKey = toolName;
                }
            }
            getAgentInvocationMap(this._completedToolInvocations, agent).set(callId, fingerprint);
            getAgentInvocationMap(this._completedToolInvocationEvidence, agent).set(callId, evidence);
        };
        for (const item of items) {
            if (item instanceof RunToolCallItem &&
                item.rawItem.type === 'hosted_tool_call' &&
                item.rawItem.name === 'mcp_approval_response') {
                const providerData = item.rawItem.providerData;
                const callId = providerData?.approval_request_id;
                if (typeof callId !== 'string' || callId.length === 0) {
                    throw new ModelBehaviorError('Hosted MCP approval response is missing a non-empty approval request ID.', this);
                }
                commit(item.agent, callId, item);
                continue;
            }
            if (item instanceof RunHandoffOutputItem) {
                const callId = item.rawItem.callId;
                if (!callId) {
                    throw new ModelBehaviorError('Handoff output is missing a non-empty call ID.', this);
                }
                commit(item.sourceAgent, callId, item);
                continue;
            }
            if (!(item instanceof RunToolCallOutputItem)) {
                continue;
            }
            if (!isTrackedLocalToolResult(item.rawItem)) {
                continue;
            }
            const callId = getLocalToolResultCallId(item.rawItem);
            if (!callId) {
                throw new ModelBehaviorError('Tool output is missing a non-empty call ID.', this);
            }
            commit(item.agent, callId, item);
        }
    }
    /**
     * Replaces generated history after completion evidence has been committed.
     * @internal
     */
    _replaceGeneratedItems(generatedItems) {
        this._generatedItems = generatedItems;
    }
    /** @internal Captures an input view without retaining mutable filter-owned items. */
    _captureHandoffInput(originalInput, generatedItems) {
        const identities = buildAgentIdentityMap(this.#startingAgent);
        return structuredClone(handoffInputSnapshotSchema.parse({
            originalInput,
            generatedItems: generatedItems.map((item) => serializeRunItem(item, identities.byAgent)),
        }));
    }
    /** @internal Reuses ordinary RunState item reconstruction for the accepted input view. */
    _deserializeHandoffInput(input) {
        const identities = buildAgentIdentityMap(this.#startingAgent);
        return {
            originalInput: structuredClone(input.originalInput),
            generatedItems: input.generatedItems.map((item) => deserializeItem(item, identities.byIdentity)),
        };
    }
    /** @internal Resolves discovery ownership within the complete starting Agent graph. */
    _getToolSearchAgentName(agent) {
        return getToolSearchAgentName(agent, buildAgentIdentityMap(this.#startingAgent).byAgent.keys());
    }
    getOrCreateToolSearchRuntimeToolState(agent) {
        let state = this._toolSearchRuntimeToolsByAgent.get(agent);
        if (!state) {
            state = {
                keyedEntries: new Map(),
                routedOwners: new Map(),
                nextOrder: 0,
            };
            this._toolSearchRuntimeToolsByAgent.set(agent, state);
        }
        return state;
    }
    recordToolSearchRuntimeTools(agent, toolSearchOutput, tools) {
        const runtimeState = this.getOrCreateToolSearchRuntimeToolState(agent);
        const entry = {
            order: runtimeState.nextOrder++,
            tools,
        };
        const replacementKey = getToolSearchOutputReplacementKey(toolSearchOutput);
        if (replacementKey) {
            const previousEntry = runtimeState.keyedEntries.get(replacementKey);
            if (previousEntry) {
                for (const [routingKey, owner] of runtimeState.routedOwners) {
                    if (owner.entry === previousEntry) {
                        runtimeState.routedOwners.delete(routingKey);
                    }
                }
            }
            runtimeState.keyedEntries.set(replacementKey, entry);
        }
        for (const [toolIndex, tool] of tools.entries()) {
            const routingKey = getToolSearchRuntimeRoutingKey(tool);
            if (!routingKey) {
                continue;
            }
            runtimeState.routedOwners.set(routingKey, {
                entry,
                tool,
                toolIndex,
            });
        }
    }
    getToolSearchRuntimeToolsForOutput(agent, toolSearchOutput) {
        const replacementKey = getToolSearchOutputReplacementKey(toolSearchOutput);
        if (!replacementKey) {
            return [];
        }
        const runtimeState = this._toolSearchRuntimeToolsByAgent.get(agent);
        const entry = runtimeState?.keyedEntries.get(replacementKey);
        if (!runtimeState || !entry) {
            return [];
        }
        return entry.tools.filter((tool) => {
            const routingKey = getToolSearchRuntimeRoutingKey(tool);
            return (typeof routingKey === 'string' &&
                runtimeState.routedOwners.get(routingKey)?.entry === entry);
        });
    }
    getToolSearchRuntimeTools(agent) {
        const runtimeState = this._toolSearchRuntimeToolsByAgent.get(agent);
        if (!runtimeState) {
            return [];
        }
        return [...runtimeState.routedOwners.values()]
            .sort((left, right) => left.entry.order - right.entry.order ||
            left.toolIndex - right.toolIndex)
            .map((owner) => owner.tool);
    }
    /**
     * Switches the active agent handling the run.
     */
    setCurrentAgent(agent) {
        this._currentAgent = agent;
    }
    /**
     * Returns the agent currently handling the run.
     */
    get currentAgent() {
        return this._currentAgent;
    }
    /**
     * Resets the counter that tracks how many items were persisted for the current turn.
     */
    resetTurnPersistence() {
        this._currentTurnPersistedItemCount = 0;
        this._currentTurnSessionWriteCompactedItemCount = undefined;
        this._currentTurnDeferredSessionItemIndexes.clear();
    }
    /**
     * Rewinds the persisted item counter when pending approvals require re-writing outputs.
     */
    rewindTurnPersistence(count) {
        if (count <= 0) {
            return;
        }
        this._currentTurnPersistedItemCount = Math.max(0, this._currentTurnPersistedItemCount - count);
        if (this._currentTurnSessionWriteCompactedItemCount !==
            this._currentTurnPersistedItemCount) {
            this._currentTurnSessionWriteCompactedItemCount = undefined;
        }
    }
    /**
     * The history of the agent run. This includes the input items and the new items generated during the run.
     *
     * This can be used as inputs for the next agent run.
     */
    get history() {
        return getTurnInput(this._originalInput, this._generatedItems, this._reasoningItemIdPolicy);
    }
    /**
     * Returns a copy of input staged for the next resumed model call.
     */
    get pendingInput() {
        return structuredClone(this._pendingInput);
    }
    /**
     * Stages input for admission immediately before the next resumed model call.
     */
    addInput(input) {
        const currentStep = this._currentStep;
        if (currentStep?.type !== 'next_step_interruption' &&
            currentStep?.type !== 'next_step_run_again') {
            throw new UserError('Cannot add input to a terminal RunState', this);
        }
        if (this._maxTurns !== null &&
            this._currentTurn >= this._maxTurns &&
            !this._currentTurnInProgress) {
            throw new UserError('Cannot add input to a RunState with no remaining model turns', this);
        }
        if (currentStep.type === 'next_step_interruption') {
            if (currentStep.data?.responseAccepted === true) {
                throw new UserError('Cannot add input while an accepted model response is awaiting local processing', this);
            }
            const toolUseBehavior = this._currentAgent.toolUseBehavior;
            const interruptions = this.getInterruptions();
            const stopsBeforeNextModel = toolUseBehavior === 'stop_on_first_tool' ||
                (typeof toolUseBehavior === 'object' &&
                    toolUseBehavior.stopAtToolNames.some((toolName) => interruptions.some((item) => item.name === toolName ||
                        (item.rawItem.type === 'function_call' &&
                            getToolCallName(item.rawItem) === toolName))));
            if (stopsBeforeNextModel || typeof toolUseBehavior === 'function') {
                throw new UserError('Cannot add input to an interrupted RunState whose tool result may end the run', this);
            }
        }
        const normalized = toAgentInputList(input).map((item) => protocol.ModelItem.parse(item));
        this._pendingInput.push(...structuredClone(normalized));
    }
    /**
     * Removes all input staged for the next resumed model call.
     */
    clearPendingInput() {
        this._pendingInput = [];
    }
    /**
     * Returns all interruptions if the current step is an interruption otherwise returns an empty array.
     */
    getInterruptions() {
        if (this._currentStep?.type !== 'next_step_interruption') {
            return [];
        }
        const interruptions = this._currentStep.data.interruptions;
        return Array.isArray(interruptions)
            ? interruptions.map(cloneInterruptionSnapshot)
            : [];
    }
    /** @internal Proves a propagated approval belongs to exactly one pending child invocation. */
    _ownsNestedApproval(interruption, interruptions) {
        const { agent, rawItem } = interruption;
        if (agent === this._currentAgent ||
            rawItem.type !== 'function_call' ||
            interruptions.filter((item) => item.agent === agent &&
                getToolInvocationCallId(item.rawItem) === rawItem.callId).length !== 1) {
            return false;
        }
        // Child snapshots use identities relative to their own starting agent.
        // An asTool source is the root of its own identity map, including when names collide.
        const expected = itemSchema.safeParse({
            ...interruption.toJSON(),
            agent: { name: agent.name },
        });
        if (!expected.success)
            return false;
        let found = false;
        for (const run of this._lastProcessedResponse?.functions ?? []) {
            if (getAgentToolSourceAgent(run.tool) !== agent)
                continue;
            const [key] = getFunctionToolStateKeys(run.tool, run.availableFunctionTools ?? [run.tool]);
            if (!key)
                continue;
            const pending = this.getPendingAgentToolRun(key, run.toolCall.callId);
            if (!pending)
                continue;
            try {
                const child = SerializedRunState.parse(JSON.parse(pending));
                if (child.currentStep?.type !== 'next_step_interruption' ||
                    !Array.isArray(child.currentStep.data?.interruptions))
                    return false;
                for (const [offset, entry,] of child.currentStep.data.interruptions.entries()) {
                    const candidate = itemSchema.parse(entry);
                    if (candidate.type !== 'tool_approval_item' ||
                        candidate.rawItem.type !== 'function_call' ||
                        candidate.rawItem.callId !== rawItem.callId)
                        continue;
                    if (found ||
                        !serializedValuesEqual(candidate, expected.data) ||
                        !serializedValuesEqual(candidate.agent, child.currentAgent) ||
                        !responseOwnsFunctionCall(this._lastTurnResponse, run.toolCall) ||
                        !responseOwnsFunctionCall(child.lastModelResponse, rawItem))
                        return false;
                    const ownership = child.currentResponseGeneratedItemOwnership;
                    if (!ownership ||
                        typeof ownership.interruptionGeneratedItemIndexes[offset] !==
                            'number')
                        return false;
                    assertSchemaVersionSupportsCurrentResponseGeneratedItemOwnership(child.$schemaVersion, child);
                    found = true;
                }
            }
            catch {
                return false;
            }
        }
        return found;
    }
    getPendingAgentToolRunKey(toolName, callId) {
        return `${toolName}:${callId}`;
    }
    resolvePendingAgentToolRunKey(toolName, callId) {
        const key = this.getPendingAgentToolRunKey(toolName, callId);
        return this._pendingAgentToolRunAliases.get(key) ?? key;
    }
    getPendingAgentToolRun(toolName, callId) {
        return this._pendingAgentToolRuns.get(this.resolvePendingAgentToolRunKey(toolName, callId));
    }
    hasPendingAgentToolRun(toolName, callId) {
        return this._pendingAgentToolRuns.has(this.resolvePendingAgentToolRunKey(toolName, callId));
    }
    setPendingAgentToolRun(toolName, callId, serializedState, aliases = []) {
        const canonicalKey = this.resolvePendingAgentToolRunKey(toolName, callId);
        this._pendingAgentToolRuns.set(canonicalKey, serializedState);
        for (const alias of aliases) {
            const aliasKey = this.getPendingAgentToolRunKey(alias, callId);
            if (aliasKey === canonicalKey) {
                continue;
            }
            this._pendingAgentToolRuns.delete(aliasKey);
            this._pendingAgentToolRunAliases.set(aliasKey, canonicalKey);
        }
    }
    clearPendingAgentToolRun(toolName, callId) {
        const requestedKey = this.getPendingAgentToolRunKey(toolName, callId);
        const canonicalKey = this.resolvePendingAgentToolRunKey(toolName, callId);
        this._pendingAgentToolRuns.delete(canonicalKey);
        this._pendingAgentToolRuns.delete(requestedKey);
        for (const [aliasKey, targetKey] of this._pendingAgentToolRunAliases) {
            if (aliasKey === requestedKey || targetKey === canonicalKey) {
                this._pendingAgentToolRuns.delete(aliasKey);
                this._pendingAgentToolRunAliases.delete(aliasKey);
            }
        }
    }
    /**
     * Approves a tool call requested by the agent through an interruption and approval item request.
     *
     * To approve the request use this method and then run the agent again with the same state object
     * to continue the execution.
     *
     * By default it will only approve the current tool call. To allow the tool to be used multiple
     * times throughout the run, set the `alwaysApprove` option to `true`.
     *
     * @param approvalItem - The tool call approval item to approve.
     * @param options - Options for the approval.
     * @param options.alwaysApprove - Approve this tool for all future calls in this run.
     */
    approve(approvalItem, options = {
        alwaysApprove: false,
    }) {
        this._context.approveTool(approvalItem, options);
    }
    /**
     * Rejects a tool call requested by the agent through an interruption and approval item request.
     *
     * To reject the request use this method and then run the agent again with the same state object
     * to continue the execution.
     *
     * By default it will only reject the current tool call. To reject the tool for all future
     * calls throughout the run, set the `alwaysReject` option to `true`.
     *
     * When `message` is provided, it is used as the rejection text sent to the model.
     * Otherwise, `toolErrorFormatter` (if configured) or the SDK default is used.
     *
     * @param approvalItem - The tool call approval item to reject.
     * @param options - Options for the rejection.
     * @param options.alwaysReject - Reject this tool for all future calls in this run.
     * @param options.message - The rejection text sent to the model.
     *   If not provided, `toolErrorFormatter` (if configured) or the SDK default is used.
     */
    reject(approvalItem, options = {
        alwaysReject: false,
    }) {
        this._context.rejectTool(approvalItem, options);
    }
    /**
     * Serializes the run state to a JSON object.
     *
     * This method is used to serialize the run state to a JSON object that can be used to
     * resume the run later.
     *
     * @returns The serialized run state.
     */
    /**
     * Serializes the run state. By default, tracing API keys are omitted to prevent
     * accidental persistence of secrets. Pass `includeTracingApiKey: true` only when you
     * intentionally need to migrate a run along with its tracing credentials (e.g., to
     * rehydrate in a separate process that lacks the original environment variables).
     */
    toJSON(options = {}) {
        assertSandboxStateUsesCurrentSessionEnvelope(this._sandbox);
        const agentIdentity = buildAgentIdentityMap(this.#startingAgent);
        const completedToolInvocations = new Map([...this._completedToolInvocations].map(([agent, invocations]) => [
            agent,
            new Map(invocations),
        ]));
        const inferredInvocations = inferCompletedToolInvocations(this._generatedItems);
        for (const [agent, invocations] of inferredInvocations.completed) {
            const completedByAgent = getAgentInvocationMap(completedToolInvocations, agent);
            for (const [callId, fingerprint] of invocations) {
                const existing = completedByAgent.get(callId);
                if (existing !== undefined && existing !== fingerprint) {
                    throw new UserError('RunState completed tool invocation records conflict with the generated item history.');
                }
                completedByAgent.set(callId, fingerprint);
            }
        }
        const completedToolInvocationEvidence = new Map([...this._completedToolInvocationEvidence].map(([agent, invocations]) => [
            agent,
            new Map(invocations),
        ]));
        for (const [agent, invocations] of inferredInvocations.completed) {
            for (const [callId, fingerprint] of invocations) {
                const evidenceByAgent = getAgentInvocationMap(completedToolInvocationEvidence, agent);
                if (!evidenceByAgent.has(callId)) {
                    const inferredEvidence = inferredInvocations.evidence
                        .get(agent)
                        ?.get(callId);
                    const outputItem = inferredEvidence?.at(-1);
                    const evidence = outputItem && inferredEvidence
                        ? findToolInvocationCompletionEvidence(agent, callId, fingerprint, outputItem, inferredEvidence)
                        : undefined;
                    if (evidence) {
                        evidenceByAgent.set(callId, evidence);
                    }
                }
            }
        }
        let hasRecoveredHandoff = false;
        for (const [agent, invocations] of completedToolInvocationEvidence) {
            const completedByAgent = completedToolInvocations.get(agent);
            for (const [callId, evidence] of invocations) {
                hasRecoveredHandoff ||= isRecoveredHandoffEvidence(evidence);
                validateGeneratedHistoryForCompletionEvidence(this._generatedItems, agent, callId, evidence);
                const fingerprint = validateToolInvocationCompletionEvidence(agent, callId, evidence);
                if (completedByAgent?.get(callId) !== fingerprint) {
                    throw new UserError('RunState completed tool invocation evidence lacks completed invocation authority.');
                }
            }
        }
        for (const [agent, invocations] of completedToolInvocations) {
            const evidenceByAgent = completedToolInvocationEvidence.get(agent);
            for (const [callId, fingerprint] of invocations) {
                if (evidenceByAgent?.get(callId)?.fingerprint !== fingerprint) {
                    throw new UserError('RunState completed tool invocation records lack correlated completion evidence.');
                }
            }
        }
        const ambiguousToolInvocationCallIds = new Map([...this._ambiguousToolInvocationCallIds].map(([agent, callIds]) => [
            agent,
            new Set(callIds),
        ]));
        for (const [agent, callIds] of inferredInvocations.ambiguous) {
            const ambiguousByAgent = getAgentAmbiguousCallIds(ambiguousToolInvocationCallIds, agent);
            for (const callId of callIds) {
                if (completedToolInvocationEvidence.get(agent)?.has(callId)) {
                    continue;
                }
                ambiguousByAgent.add(callId);
            }
        }
        const includeTracingApiKey = options.includeTracingApiKey === true;
        const contextJson = this._context._toJSONForRunState(agentIdentity.byAgent);
        const currentResponseGeneratedItemOwnership = captureCurrentResponseGeneratedItemOwnership(this);
        const output = {
            $schemaVersion: CURRENT_SCHEMA_VERSION,
            currentTurn: this._currentTurn,
            currentAgent: serializeAgentReference(this._currentAgent, agentIdentity.byAgent),
            originalInput: this._originalInput,
            pendingInput: this._pendingInput.length > 0 ? this._pendingInput : undefined,
            modelResponses: this._modelResponses.map((response) => {
                return {
                    usage: {
                        requests: response.usage.requests,
                        inputTokens: response.usage.inputTokens,
                        outputTokens: response.usage.outputTokens,
                        totalTokens: response.usage.totalTokens,
                        inputTokensDetails: response.usage.inputTokensDetails,
                        outputTokensDetails: response.usage.outputTokensDetails,
                        ...(response.usage.requestUsageEntries &&
                            response.usage.requestUsageEntries.length > 0
                            ? {
                                requestUsageEntries: response.usage.requestUsageEntries.map((entry) => ({
                                    inputTokens: entry.inputTokens,
                                    outputTokens: entry.outputTokens,
                                    totalTokens: entry.totalTokens,
                                    inputTokensDetails: entry.inputTokensDetails,
                                    outputTokensDetails: entry.outputTokensDetails,
                                    ...(entry.endpoint ? { endpoint: entry.endpoint } : {}),
                                })),
                            }
                            : {}),
                    },
                    output: response.output,
                    responseId: response.responseId,
                    requestId: response.requestId,
                    providerData: response.providerData,
                };
            }),
            context: contextJson,
            toolUseTracker: this._toolUseTracker.toJSON({
                agentIdentityKeys: agentIdentity.byAgent,
            }),
            maxTurns: this._maxTurns,
            currentAgentSpan: this._currentAgentSpan?.toJSON(),
            noActiveAgentRun: this._noActiveAgentRun,
            currentTurnInProgress: this._currentTurnInProgress,
            inputGuardrailResults: this._inputGuardrailResults,
            initialInputGuardrailsCompleted: this._initialInputGuardrailsCompleted,
            outputGuardrailResults: this._outputGuardrailResults.map((r) => ({
                ...r,
                agent: serializeAgentReference(r.agent, agentIdentity.byAgent),
            })),
            toolInputGuardrailResults: this._toolInputGuardrailResults,
            toolOutputGuardrailResults: this._toolOutputGuardrailResults,
            currentStep: serializeCurrentStep(this._currentStep, agentIdentity.byAgent),
            lastModelResponse: this._lastTurnResponse,
            generatedItems: this._generatedItems.map((item) => serializeRunItem(item, agentIdentity.byAgent)),
            currentResponseGeneratedItemOwnership,
            pendingAgentToolRuns: Object.fromEntries(this._pendingAgentToolRuns.entries()),
            pendingAgentToolRunAliases: Object.fromEntries(this._pendingAgentToolRunAliases.entries()),
            completedToolInvocations: serializeAgentInvocationRecords(completedToolInvocations, agentIdentity.byAgent),
            completedToolInvocationEvidence: serializeAgentInvocationEvidence(completedToolInvocationEvidence, agentIdentity.byAgent, this._generatedItems),
            ambiguousToolInvocationCallIds: serializeAgentCallIdSets(ambiguousToolInvocationCallIds, agentIdentity.byAgent),
            currentTurnPersistedItemCount: this._currentTurnPersistedItemCount,
            currentTurnSessionWriteCompactedItemCount: this._currentTurnSessionWriteCompactedItemCount,
            currentTurnDeferredSessionItemIndexes: this._currentTurnDeferredSessionItemIndexes.size > 0
                ? [...this._currentTurnDeferredSessionItemIndexes].sort((left, right) => left - right)
                : undefined,
            currentTurnBlockedSessionStartIndex: this._currentTurnBlockedSessionStartIndex,
            currentTurnExecutedWithSessionBinding: this._currentTurnSessionHistoryTransactionSessionId !== undefined &&
                hasBlockedOutputExecutionEffect(this._generatedItems, this._currentTurnPersistedItemCount)
                ? true
                : undefined,
            currentTurnSessionInputItems: (this._pendingSessionWrite !== undefined ||
                this._currentTurnSessionHistoryTransactionSessionId === undefined) &&
                this._currentTurnSessionHistoryTransactionInputItems !== undefined &&
                this._currentTurnSessionHistoryTransactionInputItems.length > 0 &&
                hasBlockedOutputExecutionEffect(this._generatedItems, this._currentTurnPersistedItemCount)
                ? this._currentTurnSessionHistoryTransactionInputItems
                : undefined,
            pendingSessionHistoryTransaction: this._pendingSessionHistoryTransaction,
            pendingSessionWrite: this._pendingSessionWrite
                ? structuredClone(this._pendingSessionWrite)
                : undefined,
            pendingLegacyCompactionSessionItems: this._pendingLegacyCompactionSessionItems,
            lastProcessedResponse: this._lastProcessedResponse
                ? serializeProcessedResponse(this._lastProcessedResponse, agentIdentity.byAgent)
                : undefined,
            conversationId: this._conversationId,
            previousResponseId: this._previousResponseId,
            reasoningItemIdPolicy: this._reasoningItemIdPolicy,
            trace: this._trace
                ? this._trace.toJSON({ includeTracingApiKey })
                : null,
            sandbox: this._sandbox,
        };
        // parsing the schema to ensure the output is valid for reparsing
        const parsed = SerializedRunState.safeParse(output);
        if (!parsed.success) {
            throw new SystemError(`Failed to serialize run state. ${parsed.error.message}`);
        }
        // Keep ordinary snapshots readable by 0.21.0. Rich metadata is preserved,
        // never filtered to force an older format. Each nested writer selects its
        // own version; do not downgrade an envelope containing a newer child.
        const state = parsed.data;
        const usages = [
            state.context.usage,
            ...state.modelResponses.map((response) => response.usage),
            ...(state.lastModelResponse ? [state.lastModelResponse.usage] : []),
        ];
        const nestedRunsSupportV123 = Object.values(state.pendingAgentToolRuns).every((serialized) => {
            try {
                const nested = JSON.parse(serialized);
                return (nested !== null &&
                    typeof nested === 'object' &&
                    '$schemaVersion' in nested &&
                    nested.$schemaVersion !== CURRENT_SCHEMA_VERSION &&
                    $schemaVersion.safeParse(nested.$schemaVersion).success);
            }
            catch {
                return false;
            }
        });
        const sandboxSupportsV123 = !state.sandbox ||
            [
                state.sandbox.sessionState,
                ...Object.values(state.sandbox.sessionsByAgent).map((entry) => entry.sessionState),
            ].every((envelope) => envelope.version <= 5);
        if (!hasRecoveredHandoff &&
            !state.currentResponseGeneratedItemOwnership?.interruptionGeneratedItemIndexes.includes(null) &&
            usages.every(usageSupportsV123) &&
            nestedRunsSupportV123 &&
            sandboxSupportsV123) {
            state.$schemaVersion = '1.23';
        }
        return state;
    }
    /**
     * Serializes the run state to a string.
     *
     * This method is used to serialize the run state to a string that can be used to
     * resume the run later.
     *
     * @returns The serialized run state.
     */
    toString(options = {}) {
        return JSON.stringify(this.toJSON(options));
    }
    /**
     * Deserializes a run state from a string.
     *
     * This method is used to deserialize a run state from a string that was serialized using the
     * `toString` method.
     * Pending function calls from snapshots without recipient provenance cannot execute;
     * start a new run instead. Rejected and completed calls remain non-executing.
     * MCP calls require the original server names, list positions, and raw tool names.
     * These bindings detect routing changes, not snapshot tampering or changed transport
     * settings or credentials under the same identity.
     */
    static async fromString(initialAgent, str) {
        return buildRunStateFromString(initialAgent, str);
    }
    static async fromStringWithContext(initialAgent, str, context, options = {}) {
        return buildRunStateFromString(initialAgent, str, {
            contextOverride: context,
            contextStrategy: options.contextStrategy,
        });
    }
}
async function buildRunStateFromString(initialAgent, str, options = {}) {
    const [parsingError, jsonResult] = await safeExecute(() => JSON.parse(str));
    if (parsingError) {
        throw new UserError(`Failed to parse run state. ${parsingError instanceof Error ? parsingError.message : String(parsingError)}`);
    }
    const currentSchemaVersion = jsonResult.$schemaVersion;
    if (!currentSchemaVersion) {
        throw new UserError('Run state is missing schema version');
    }
    if (!SUPPORTED_SCHEMA_VERSIONS.includes(currentSchemaVersion)) {
        throw new UserError(`Run state schema version ${currentSchemaVersion} is not supported. Please use version ${CURRENT_SCHEMA_VERSION}.`);
    }
    validateFunctionApprovalEnvelope(currentSchemaVersion, jsonResult);
    const hasPendingInputField = jsonResult !== null &&
        typeof jsonResult === 'object' &&
        hasOwnProperty(jsonResult, 'pendingInput');
    const hasPendingSessionWriteField = jsonResult !== null &&
        typeof jsonResult === 'object' &&
        hasOwnProperty(jsonResult, 'pendingSessionWrite');
    const hasSessionWriteCompactedItemCountField = jsonResult !== null &&
        typeof jsonResult === 'object' &&
        hasOwnProperty(jsonResult, 'currentTurnSessionWriteCompactedItemCount');
    const stateJson = SerializedRunState.parse(jsonResult);
    assertSchemaVersionSupportsStructuredToolOutputs(currentSchemaVersion, stateJson);
    assertSchemaVersionSupportsToolSearch(currentSchemaVersion, stateJson);
    assertSchemaVersionSupportsCustomData(currentSchemaVersion, stateJson);
    assertSchemaVersionSupportsProgrammaticToolCalling(currentSchemaVersion, stateJson);
    assertSchemaVersionSupportsSandboxSessionEnvelope(currentSchemaVersion, stateJson);
    assertSchemaVersionSupportsCompactionItems(currentSchemaVersion, stateJson);
    assertSchemaVersionSupportsOutputGuardrailSessionPersistence(currentSchemaVersion, stateJson);
    assertSchemaVersionSupportsCurrentResponseGeneratedItemOwnership(currentSchemaVersion, stateJson);
    assertSchemaVersionSupportsPendingSessionWrite(currentSchemaVersion, stateJson, hasPendingSessionWriteField, hasSessionWriteCompactedItemCountField);
    assertSchemaVersionSupportsPendingInput(currentSchemaVersion, stateJson, hasPendingInputField);
    const normalizedState = schemaVersionSupportsV116State(currentSchemaVersion)
        ? { stateJson }
        : rehydrateLegacyCompactionRunItems(stateJson);
    const state = await buildRunStateFromJson(initialAgent, normalizedState.stateJson, options);
    if (normalizedState.sessionReconciliation) {
        const { generatedInsertionIndex, previousPersistedItemCount } = normalizedState.sessionReconciliation;
        state._pendingLegacyCompactionSessionItems = extractOutputItemsFromRunItems(state._generatedItems.slice(generatedInsertionIndex, previousPersistedItemCount + 1));
        state._currentTurnPersistedItemCount = previousPersistedItemCount + 1;
    }
    return state;
}
function validateFunctionApprovalEnvelope(schemaVersion, stateJson) {
    if (!stateJson || typeof stateJson !== 'object') {
        return;
    }
    const context = stateJson.context;
    if (!context || typeof context !== 'object') {
        return;
    }
    const hasFunctionApprovals = Object.prototype.hasOwnProperty.call(context, 'functionApprovals');
    const hasLegacyFunctionApprovals = Object.prototype.hasOwnProperty.call(context, 'legacyFunctionApprovals');
    if (!hasFunctionApprovals && !hasLegacyFunctionApprovals) {
        return;
    }
    if (!schemaVersionSupportsV116State(schemaVersion)) {
        throw new UserError(`Run state schema version ${schemaVersion} does not support owner-scoped function approvals. Please reserialize the run state with schema ${CURRENT_SCHEMA_VERSION}.`);
    }
    if (!functionApprovalContextSchema.safeParse(context).success) {
        throw new UserError('Failed to parse owner-scoped function approvals because their structure does not match the supported schema.');
    }
}
function assertSchemaVersionSupportsToolSearch(schemaVersion, stateJson) {
    if (schemaVersion === '1.8' ||
        schemaVersion === '1.9' ||
        schemaVersion === '1.10' ||
        schemaVersion === '1.11' ||
        schemaVersion === '1.12' ||
        schemaVersion === '1.13' ||
        schemaVersion === '1.14' ||
        schemaVersion === '1.15' ||
        schemaVersion === '1.16' ||
        schemaVersion === '1.17' ||
        schemaVersionSupportsV118State(schemaVersion)) {
        return;
    }
    if (!containsSerializedToolSearchState(stateJson)) {
        return;
    }
    throw new UserError(`Run state schema version ${schemaVersion} does not support tool_search items. Please reserialize the run state with schema ${CURRENT_SCHEMA_VERSION}.`);
}
function assertSchemaVersionSupportsCustomData(schemaVersion, stateJson) {
    if (schemaVersion === '1.13' ||
        schemaVersion === '1.14' ||
        schemaVersion === '1.15' ||
        schemaVersion === '1.16' ||
        schemaVersion === '1.17' ||
        schemaVersionSupportsV118State(schemaVersion)) {
        return;
    }
    if (!containsSerializedToolOutputCustomData(stateJson)) {
        return;
    }
    throw new UserError(`Run state schema version ${schemaVersion} does not support tool output customData. Please reserialize the run state with schema ${CURRENT_SCHEMA_VERSION}.`);
}
function assertSchemaVersionSupportsStructuredToolOutputs(schemaVersion, stateJson) {
    if (schemaVersionSupportsV118State(schemaVersion) ||
        !containsStructuredToolOutputState(stateJson)) {
        return;
    }
    throw new UserError(`Run state schema version ${schemaVersion} does not support structured tool output values. Please reserialize the run state with schema ${CURRENT_SCHEMA_VERSION}.`);
}
function schemaVersionSupportsAgentIdentity(schemaVersion) {
    return (schemaVersion === '1.10' ||
        schemaVersion === '1.11' ||
        schemaVersion === '1.12' ||
        schemaVersion === '1.13' ||
        schemaVersion === '1.14' ||
        schemaVersion === '1.15' ||
        schemaVersion === '1.16' ||
        schemaVersion === '1.17' ||
        schemaVersionSupportsV118State(schemaVersion));
}
function assertSchemaVersionSupportsProgrammaticToolCalling(schemaVersion, stateJson) {
    if (schemaVersion === '1.14' ||
        schemaVersion === '1.15' ||
        schemaVersion === '1.16' ||
        schemaVersion === '1.17' ||
        schemaVersionSupportsV118State(schemaVersion)) {
        return;
    }
    if (!containsProgrammaticToolCallingState(stateJson)) {
        return;
    }
    throw new UserError(`Run state schema version ${schemaVersion} does not support Programmatic Tool Calling items. Please reserialize the run state with schema ${CURRENT_SCHEMA_VERSION}.`);
}
function assertSchemaVersionSupportsSandboxSessionEnvelope(schemaVersion, stateJson) {
    if (!stateJson.sandbox) {
        return;
    }
    const envelopes = [
        stateJson.sandbox.sessionState,
        ...Object.values(stateJson.sandbox.sessionsByAgent).map((entry) => entry.sessionState),
    ];
    const supportsVersion2 = schemaVersion === '1.15' ||
        schemaVersion === '1.16' ||
        schemaVersion === '1.17' ||
        schemaVersionSupportsV118State(schemaVersion);
    const supportsVersion3 = schemaVersionSupportsV118State(schemaVersion);
    const supportsVersion4 = schemaVersionSupportsV119State(schemaVersion);
    const supportsVersion5 = schemaVersionSupportsV120State(schemaVersion);
    if (envelopes.every((envelope) => envelope.version === 1 ||
        (envelope.version === 2 && supportsVersion2) ||
        (envelope.version === 3 && supportsVersion3) ||
        (envelope.version === 4 && supportsVersion4) ||
        (envelope.version === 5 && supportsVersion5) ||
        (envelope.version === SANDBOX_SESSION_STATE_VERSION &&
            schemaVersion === CURRENT_SCHEMA_VERSION))) {
        return;
    }
    const rejectedVersion = envelopes.find((envelope) => envelope.version !== 1 &&
        !(envelope.version === 2 && supportsVersion2) &&
        !(envelope.version === 3 && supportsVersion3) &&
        !(envelope.version === 4 && supportsVersion4) &&
        !(envelope.version === 5 && supportsVersion5) &&
        !(envelope.version === SANDBOX_SESSION_STATE_VERSION &&
            schemaVersion === CURRENT_SCHEMA_VERSION))?.version;
    throw new UserError(`Run state schema version ${schemaVersion} does not support sandbox session state version ${rejectedVersion}. Please reserialize the run state with schema ${CURRENT_SCHEMA_VERSION}.`);
}
function assertSandboxStateUsesCurrentSessionEnvelope(sandbox) {
    if (!sandbox) {
        return;
    }
    const legacyVersions = [
        sandbox.sessionState.version,
        ...Object.values(sandbox.sessionsByAgent).map((entry) => entry.sessionState.version),
    ].filter((version) => version !== 5 && version !== SANDBOX_SESSION_STATE_VERSION);
    if (legacyVersions.length === 0) {
        return;
    }
    throw new UserError('Legacy sandbox session state must be resumed through the Runner before it can be serialized with the current RunState schema.');
}
/**
 * Rejects older schemas that carry the new wrapper. Current snapshots treat generated items as
 * the replay authority because a supported handoff input filter may remove or replace raw model
 * output before it becomes history.
 */
function assertSchemaVersionSupportsCompactionItems(schemaVersion, stateJson) {
    if (schemaVersionSupportsV116State(schemaVersion)) {
        return;
    }
    if (!containsSerializedCompactionRunItems(stateJson) &&
        stateJson.pendingLegacyCompactionSessionItems === undefined) {
        return;
    }
    throw new UserError(`Run state schema version ${schemaVersion} does not support compaction items. Please reserialize the run state with schema ${CURRENT_SCHEMA_VERSION}.`);
}
function assertSchemaVersionSupportsOutputGuardrailSessionPersistence(schemaVersion, stateJson) {
    if (schemaVersionSupportsV117State(schemaVersion)) {
        validateOutputGuardrailSessionPersistenceState(stateJson);
        return;
    }
    const hasExecutionProvenance = [
        ...stateJson.generatedItems,
        ...(stateJson.lastProcessedResponse?.newItems ?? []),
    ].some((item) => item.type === 'tool_call_output_item' &&
        item.executionStatus !== undefined);
    const hasV117PersistenceEnvelope = stateJson.currentTurnDeferredSessionItemIndexes !== undefined ||
        stateJson.currentTurnBlockedSessionStartIndex !== undefined ||
        stateJson.currentTurnExecutedWithSessionBinding !== undefined ||
        stateJson.currentTurnSessionInputItems !== undefined ||
        stateJson.pendingSessionHistoryTransaction !== undefined;
    if (!hasV117PersistenceEnvelope && !hasExecutionProvenance) {
        return;
    }
    throw new UserError(`Run state schema version ${schemaVersion} does not support output guardrail session persistence state. Please reserialize the run state with schema ${CURRENT_SCHEMA_VERSION}.`);
}
function assertSchemaVersionSupportsCurrentResponseGeneratedItemOwnership(schemaVersion, stateJson) {
    const ownership = stateJson.currentResponseGeneratedItemOwnership;
    if (ownership === undefined) {
        return;
    }
    if (!schemaVersionSupportsV120State(schemaVersion)) {
        throw new UserError(`Run state schema version ${schemaVersion} does not support current-response generated-item ownership. Please reserialize the run state with schema ${CURRENT_SCHEMA_VERSION}.`);
    }
    validateCurrentResponseGeneratedItemOwnership(stateJson, ownership);
}
function assertSchemaVersionSupportsPendingSessionWrite(schemaVersion, stateJson, hasPendingSessionWriteField, hasSessionWriteCompactedItemCountField) {
    if (!schemaVersionSupportsV120State(schemaVersion)) {
        if (!hasPendingSessionWriteField &&
            !hasSessionWriteCompactedItemCountField) {
            return;
        }
        throw new UserError(`Run state schema version ${schemaVersion} does not support pending Session writes. Please reserialize the run state with schema ${CURRENT_SCHEMA_VERSION}.`);
    }
    const pending = stateJson.pendingSessionWrite;
    const compactedItemCount = stateJson.currentTurnSessionWriteCompactedItemCount;
    const persistedItemCount = stateJson.currentTurnPersistedItemCount ?? 0;
    if (compactedItemCount !== undefined &&
        (pending !== undefined ||
            compactedItemCount !== persistedItemCount ||
            (stateJson.currentStep?.type !== 'next_step_run_again' &&
                stateJson.currentStep?.type !== 'next_step_interruption' &&
                stateJson.currentStep?.type !== 'next_step_final_output'))) {
        throw new UserError('RunState resumed Session write compaction marker is invalid.');
    }
    if (pending === undefined) {
        return;
    }
    const alreadyPersistedCount = persistedItemCount;
    const terminalFinalization = pending.terminalToolFinalization;
    const terminalStep = stateJson.currentStep?.type === 'next_step_final_output';
    const terminalFinalizationShapeIsInvalid = terminalFinalization
        ? terminalFinalization.behavior === 'function'
            ? terminalFinalization.selectedCallId !== undefined ||
                terminalFinalization.selectedGeneratedItemIndex !== undefined
            : terminalFinalization.selectedCallId === undefined ||
                terminalFinalization.selectedGeneratedItemIndex === undefined
        : terminalStep;
    const pendingCompaction = pending.phase === 'compaction_pending';
    const expectedPersistedItemCount = pendingCompaction
        ? pending.persistedItemCount
        : pending.alreadyPersistedCount;
    if ((stateJson.currentStep?.type !== 'next_step_run_again' &&
        stateJson.currentStep?.type !== 'next_step_interruption' &&
        stateJson.currentStep?.type !== 'next_step_final_output') ||
        terminalStep !== (terminalFinalization !== undefined) ||
        terminalFinalizationShapeIsInvalid ||
        expectedPersistedItemCount !== alreadyPersistedCount ||
        pending.persistedItemCount <= pending.alreadyPersistedCount ||
        pending.persistedItemCount !== stateJson.generatedItems.length ||
        stateJson.pendingSessionHistoryTransaction !== undefined ||
        stateJson.pendingLegacyCompactionSessionItems !== undefined ||
        (stateJson.currentTurnDeferredSessionItemIndexes?.length ?? 0) > 0 ||
        stateJson.currentTurnBlockedSessionStartIndex !== undefined ||
        (pendingCompaction &&
            (stateJson.currentTurnExecutedWithSessionBinding !== undefined ||
                stateJson.currentTurnSessionInputItems !== undefined)) ||
        (stateJson.currentTurnSessionInputItems !== undefined &&
            stateJson.currentTurnExecutedWithSessionBinding !== true) ||
        stateJson.conversationId !== undefined ||
        stateJson.previousResponseId !== undefined) {
        throw new UserError('RunState pending Session write is invalid.');
    }
}
export function assertPendingSessionWriteOwnership(state, pending, options = {}) {
    const pendingCompaction = pending.phase === 'compaction_pending';
    const ownsTerminalToolFinalization = state._currentStep?.type === 'next_step_final_output' &&
        ownsPendingTerminalToolFinalization(state, pending, options);
    if ((state._currentStep?.type !== 'next_step_run_again' &&
        state._currentStep?.type !== 'next_step_interruption' &&
        !ownsTerminalToolFinalization) ||
        state._currentTurnPersistedItemCount !==
            (pendingCompaction
                ? pending.persistedItemCount
                : pending.alreadyPersistedCount) ||
        pending.persistedItemCount <= pending.alreadyPersistedCount ||
        pending.persistedItemCount !== state._generatedItems.length ||
        state._currentTurnSessionWriteCompactedItemCount !== undefined ||
        state._pendingSessionHistoryTransaction !== undefined ||
        state._pendingLegacyCompactionSessionItems !== undefined ||
        state._currentTurnDeferredSessionItemIndexes.size > 0 ||
        state._currentTurnBlockedSessionStartIndex !== undefined ||
        (pendingCompaction &&
            (state._currentTurnSessionHistoryTransactionSessionId !== undefined ||
                state._currentTurnSessionHistoryTransactionInputItems !== undefined)) ||
        state._conversationId !== undefined ||
        state._previousResponseId !== undefined) {
        throw new UserError('RunState pending Session write is invalid.');
    }
    getPendingSessionWriteAppendItems(state, pending);
    if (pending.handoffInput) {
        if (state._currentStep?.type !== 'next_step_run_again' ||
            !state._noActiveAgentRun ||
            state._currentTurnInProgress ||
            !state._generatedItems.some((item) => item instanceof RunHandoffOutputItem &&
                item.targetAgent === state._currentAgent)) {
            throw new UserError('RunState pending handoff input is invalid.');
        }
        state._deserializeHandoffInput(pending.handoffInput);
    }
}
function getPendingSessionWriteBehaviorKind(behavior) {
    if (behavior === 'stop_on_first_tool') {
        return 'stop_on_first_tool';
    }
    if (typeof behavior === 'object') {
        return 'stop_at_tool_names';
    }
    if (typeof behavior === 'function') {
        return 'function';
    }
    return undefined;
}
/** @internal */
export function assertPendingSessionCompactionTerminalAuthority(state) {
    const currentStep = state._currentStep;
    if (currentStep?.type !== 'next_step_final_output') {
        return;
    }
    const behavior = state._currentAgent.toolUseBehavior;
    const producer = pendingSessionWriteTerminalProducers.get(state);
    if (producer !== undefined &&
        getPendingSessionWriteBehaviorKind(producer.behavior) !==
            getPendingSessionWriteBehaviorKind(behavior)) {
        throw new UserError('RunState pending Session compaction terminal output is invalid.');
    }
    if (typeof behavior !== 'function') {
        if (!hasDeterministicTerminalToolOutputSource(state)) {
            throw new UserError('RunState pending Session compaction terminal output is invalid.');
        }
        return;
    }
    const completedInvocations = state._completedToolInvocationEvidence.get(state._currentAgent);
    const validProducer = producer !== undefined &&
        producer.behavior === behavior &&
        producer.finalOutput === currentStep.output &&
        producer.selectedCallId === undefined &&
        producer.resultItems.length > 0 &&
        producer.resultItems.length === producer.resultCallIds.length &&
        producer.resultItems.every((item, index) => {
            const callId = producer.resultCallIds[index];
            const generatedItemIndex = state._generatedItems.indexOf(item);
            return (callId !== undefined &&
                generatedItemIndex >= 0 &&
                generatedItemIndex < state._currentTurnPersistedItemCount &&
                getCompletionOutputCallId(item, state._currentAgent) === callId &&
                completedInvocations?.get(callId)?.items[1] === item);
        });
    if (!validProducer) {
        throw new UserError('RunState pending Session compaction terminal output is invalid.');
    }
}
export function capturePendingSessionWriteTerminalFinalization(state) {
    const producer = pendingSessionWriteTerminalProducers.get(state);
    if (!producer || state._currentStep?.type !== 'next_step_final_output') {
        return undefined;
    }
    const behavior = getPendingSessionWriteBehaviorKind(producer.behavior);
    if (!behavior) {
        return undefined;
    }
    const selectedResultIndex = producer.selectedCallId
        ? producer.resultCallIds.indexOf(producer.selectedCallId)
        : -1;
    const selectedGeneratedItemIndex = selectedResultIndex >= 0
        ? state._generatedItems.indexOf(producer.resultItems[selectedResultIndex])
        : undefined;
    if (behavior !== 'function' &&
        (selectedGeneratedItemIndex === undefined || selectedGeneratedItemIndex < 0)) {
        return undefined;
    }
    return {
        behavior,
        selectedCallId: producer.selectedCallId,
        selectedGeneratedItemIndex,
        finalOutput: producer.finalOutput,
    };
}
function getPendingDeclarativeTerminalCandidate(state, item, completedInvocations) {
    if (!(item instanceof RunToolCallOutputItem) ||
        item.agent !== state._currentAgent ||
        item.rawItem.type !== 'function_call_result' ||
        item.rawItem.status === 'incomplete' ||
        getCanonicalToolCaller(item.rawItem).type === 'program') {
        return undefined;
    }
    const callId = getCompletionOutputCallId(item, state._currentAgent);
    const completionEvidence = callId
        ? completedInvocations?.get(callId)
        : undefined;
    if (!callId ||
        !completionEvidence ||
        completionEvidence.items[0] instanceof RunHandoffCallItem ||
        completionEvidence.items[1] !== item) {
        return undefined;
    }
    return { callId, completionEvidence, outputItem: item };
}
function selectPendingDeclarativeTerminalCandidate(behavior, candidates) {
    if (behavior === 'stop_on_first_tool') {
        return candidates[0];
    }
    if (typeof behavior !== 'object') {
        return undefined;
    }
    return candidates.find(({ completionEvidence }) => {
        const callItem = completionEvidence.items[0];
        if ((!(callItem instanceof RunToolCallItem) &&
            !(callItem instanceof RunToolApprovalItem)) ||
            callItem.rawItem.type !== 'function_call') {
            return false;
        }
        const invocationName = getToolInvocationNameFromFingerprint(completionEvidence.fingerprint);
        const qualifiedName = invocationName
            ? getFunctionToolLegacyStateKeyFromStateKey(invocationName)
            : undefined;
        const callName = getToolCallName(callItem.rawItem);
        return behavior.stopAtToolNames.some((toolName) => toolName === callName || toolName === qualifiedName);
    });
}
function ownsPendingTerminalToolFinalization(state, pending, options) {
    const provenance = pending.terminalToolFinalization;
    const currentStep = state._currentStep;
    if (!provenance ||
        (provenance.behavior === 'function' &&
            options.allowUnhydratedTerminalToolStep === true) ||
        currentStep?.type !== 'next_step_final_output' ||
        currentStep.output !== provenance.finalOutput ||
        getPendingSessionWriteBehaviorKind(state._currentAgent.toolUseBehavior) !==
            provenance.behavior ||
        (options.allowUnhydratedTerminalToolStep !== true &&
            !hasTerminalToolOutputSource(state))) {
        return false;
    }
    const completedInvocations = state._completedToolInvocationEvidence.get(state._currentAgent);
    const pendingGeneratedItems = state._generatedItems.slice(pending.alreadyPersistedCount, pending.persistedItemCount);
    if (pendingGeneratedItems.some((item) => {
        const callId = getCompletionOutputCallId(item, state._currentAgent);
        const completionEvidence = callId
            ? completedInvocations?.get(callId)
            : undefined;
        return (completionEvidence !== undefined && completionEvidence.items[1] !== item);
    })) {
        return false;
    }
    const liveProducer = options.allowUnhydratedTerminalToolStep === true
        ? undefined
        : pendingSessionWriteTerminalProducers.get(state);
    if (provenance.behavior === 'function') {
        return Boolean(liveProducer &&
            liveProducer.behavior === state._currentAgent.toolUseBehavior &&
            liveProducer.finalOutput === provenance.finalOutput &&
            liveProducer.selectedCallId === undefined &&
            liveProducer.resultItems.length > 0 &&
            liveProducer.resultItems.every((item, index) => {
                const generatedItemIndex = state._generatedItems.indexOf(item);
                const callId = liveProducer.resultCallIds[index];
                return (callId !== undefined &&
                    generatedItemIndex >= pending.alreadyPersistedCount &&
                    generatedItemIndex < pending.persistedItemCount &&
                    completedInvocations?.has(callId));
            }));
    }
    const selectedCallId = provenance.selectedCallId;
    const selectedGeneratedItemIndex = provenance.selectedGeneratedItemIndex;
    if (!selectedCallId ||
        selectedGeneratedItemIndex === undefined ||
        selectedGeneratedItemIndex < pending.alreadyPersistedCount ||
        selectedGeneratedItemIndex >= pending.persistedItemCount) {
        return false;
    }
    const selectedOutput = state._generatedItems[selectedGeneratedItemIndex];
    const completionEvidence = completedInvocations?.get(selectedCallId);
    if (!(selectedOutput instanceof RunToolCallOutputItem) ||
        getCompletionOutputCallId(selectedOutput, state._currentAgent) !==
            selectedCallId ||
        !completionEvidence ||
        toSmartString(selectedOutput.output) !== provenance.finalOutput) {
        return false;
    }
    const currentBehavior = state._currentAgent.toolUseBehavior;
    if (liveProducer &&
        liveProducer.finalOutput === provenance.finalOutput &&
        liveProducer.selectedCallId === selectedCallId) {
        const liveCandidates = liveProducer.resultItems.map((item, index) => {
            const candidate = getPendingDeclarativeTerminalCandidate(state, item, completedInvocations);
            const generatedItemIndex = state._generatedItems.indexOf(item);
            return candidate &&
                liveProducer.resultCallIds[index] === candidate.callId &&
                generatedItemIndex >= pending.alreadyPersistedCount &&
                generatedItemIndex < pending.persistedItemCount
                ? candidate
                : undefined;
        });
        if (liveCandidates.every((candidate) => candidate !== undefined)) {
            return (selectPendingDeclarativeTerminalCandidate(currentBehavior, liveCandidates)?.outputItem === selectedOutput);
        }
    }
    const restoredCandidates = pendingGeneratedItems.flatMap((item) => {
        const candidate = getPendingDeclarativeTerminalCandidate(state, item, completedInvocations);
        return candidate ? [candidate] : [];
    });
    return (selectPendingDeclarativeTerminalCandidate(currentBehavior, restoredCandidates)?.outputItem === selectedOutput);
}
function assertSchemaVersionSupportsPendingInput(schemaVersion, stateJson, hasPendingInputField) {
    if (schemaVersionSupportsV118State(schemaVersion)) {
        validateAcceptedResponseState(stateJson);
        return;
    }
    const hasInputItems = [
        ...stateJson.generatedItems,
        ...(stateJson.lastProcessedResponse?.newItems ?? []),
    ].some((item) => item.type === 'input_item');
    const hasAcceptedResponseState = hasAcceptedResponseStepFields(stateJson.currentStep);
    if (!hasPendingInputField &&
        (stateJson.pendingInput?.length ?? 0) === 0 &&
        !hasInputItems &&
        !hasAcceptedResponseState) {
        return;
    }
    throw new UserError(`Run state schema version ${schemaVersion} does not support pending input. Please reserialize the run state with schema ${CURRENT_SCHEMA_VERSION}.`);
}
function hasAcceptedResponseStepFields(currentStep) {
    if (currentStep?.type === 'next_step_interruption') {
        return (hasOwnProperty(currentStep.data, 'responseAccepted') ||
            hasOwnProperty(currentStep.data, 'localProcessingStarted'));
    }
    return (currentStep?.type === 'next_step_final_output' &&
        (currentStep.responseAccepted !== undefined ||
            currentStep.localFinalizationStarted !== undefined));
}
function hasOwnProperty(record, key) {
    return Object.prototype.hasOwnProperty.call(record, key);
}
function validateAcceptedResponseState(stateJson) {
    const currentStep = stateJson.currentStep;
    let responseAccepted = false;
    let invalidProgress = false;
    if (currentStep?.type === 'next_step_interruption') {
        const hasAccepted = hasOwnProperty(currentStep.data, 'responseAccepted');
        const hasStarted = hasOwnProperty(currentStep.data, 'localProcessingStarted');
        responseAccepted = currentStep.data.responseAccepted === true;
        invalidProgress =
            (hasAccepted && !responseAccepted) ||
                (hasStarted && currentStep.data.localProcessingStarted !== true) ||
                (hasStarted && !responseAccepted);
    }
    else if (currentStep?.type === 'next_step_final_output') {
        responseAccepted = currentStep.responseAccepted === true;
        invalidProgress =
            currentStep.localFinalizationStarted === true && !responseAccepted;
    }
    if (invalidProgress) {
        throw new UserError('RunState accepted response progress is invalid.');
    }
    if (responseAccepted &&
        !getServerConversationOwner(stateJson.conversationId, stateJson.previousResponseId)) {
        throw new UserError('Accepted model response state requires exactly one server-managed conversation owner.');
    }
}
function validateOutputGuardrailSessionPersistenceState(stateJson) {
    const persistedItemCount = stateJson.currentTurnPersistedItemCount ?? 0;
    const deferredIndexes = stateJson.currentTurnDeferredSessionItemIndexes ?? [];
    if (deferredIndexes.length > 0 ||
        stateJson.currentTurnBlockedSessionStartIndex !== undefined ||
        (stateJson.currentTurnExecutedWithSessionBinding === true &&
            stateJson.pendingSessionWrite === undefined) ||
        stateJson.pendingSessionHistoryTransaction !== undefined) {
        throw new UserError('Serialized output guardrail session transaction authority cannot be resumed safely. Start a new run from the persisted session history.');
    }
    if (persistedItemCount > stateJson.generatedItems.length) {
        throw new UserError('Run state contains unsupported serialized output guardrail session transaction state.');
    }
    const hasUnsupportedExecutionProvenance = [
        ...stateJson.generatedItems,
        ...(stateJson.lastProcessedResponse?.newItems ?? []),
    ].some((item) => item.type === 'tool_call_output_item' &&
        item.executionStatus === 'executed' &&
        item.rawItem.type !== 'function_call_result' &&
        item.rawItem.type !== 'shell_call_output' &&
        item.rawItem.type !== 'computer_call_result' &&
        item.rawItem.type !== 'apply_patch_call_output');
    if (hasUnsupportedExecutionProvenance) {
        throw new UserError('Run state contains execution provenance for an unsupported tool output type.');
    }
}
function containsSerializedCompactionRunItems(stateJson) {
    return (containsCompactionRunItems(stateJson.generatedItems) ||
        containsCompactionRunItems(stateJson.lastProcessedResponse?.newItems));
}
function containsCompactionRunItems(items) {
    return Boolean(items?.some((item) => item.type === 'compaction_item'));
}
function containsProgrammaticToolCallingState(stateJson) {
    return (containsProgrammaticToolCallingProtocolItems(stateJson.originalInput) ||
        stateJson.modelResponses.some(containsProgrammaticToolCallingInModelResponse) ||
        containsProgrammaticToolCallingInModelResponse(stateJson.lastModelResponse) ||
        containsProgrammaticToolCallingRunItems(stateJson.generatedItems) ||
        containsProgrammaticToolCallingInProcessedResponse(stateJson.lastProcessedResponse));
}
function containsProgrammaticToolCallingInModelResponse(modelResponse) {
    return Boolean(modelResponse?.output.some(isProgrammaticToolCallingProtocolItem));
}
function containsProgrammaticToolCallingRunItems(items) {
    return Boolean(items?.some((item) => isProgrammaticToolCallingProtocolItem(item.rawItem)));
}
function containsProgrammaticToolCallingProtocolItems(items) {
    return Array.isArray(items)
        ? items.some(isProgrammaticToolCallingProtocolItem)
        : false;
}
function containsProgrammaticToolCallingInProcessedResponse(processedResponse) {
    if (!processedResponse) {
        return false;
    }
    return (containsProgrammaticToolCallingRunItems(processedResponse.newItems) ||
        processedResponse.functions.some(({ toolCall }) => isProgrammaticToolCallingProtocolItem(toolCall)) ||
        (processedResponse.functionToolsNotFound ?? []).some(({ toolCall }) => isProgrammaticToolCallingProtocolItem(toolCall)) ||
        (processedResponse.shellActions ?? []).some(({ toolCall }) => isProgrammaticToolCallingProtocolItem(toolCall)) ||
        (processedResponse.applyPatchActions ?? []).some(({ toolCall }) => isProgrammaticToolCallingProtocolItem(toolCall)));
}
function isProgrammaticToolCallingProtocolItem(value) {
    if (!value || typeof value !== 'object') {
        return false;
    }
    const item = value;
    if (item.type === 'program' || item.type === 'program_output') {
        return true;
    }
    if (item.type !== 'function_call' &&
        item.type !== 'function_call_result' &&
        item.type !== 'shell_call' &&
        item.type !== 'shell_call_output' &&
        item.type !== 'apply_patch_call' &&
        item.type !== 'apply_patch_call_output' &&
        item.type !== 'hosted_tool_call') {
        return false;
    }
    return (item.caller?.type === 'program' && typeof item.caller.callerId === 'string');
}
function containsSerializedToolSearchState(stateJson) {
    return (containsToolSearchProtocolItems(stateJson.originalInput) ||
        containsToolSearchInModelResponses(stateJson.modelResponses) ||
        containsToolSearchInModelResponse(stateJson.lastModelResponse) ||
        containsToolSearchRunItems(stateJson.generatedItems) ||
        containsToolSearchInProcessedResponse(stateJson.lastProcessedResponse));
}
function containsToolSearchInModelResponses(modelResponses) {
    return modelResponses.some(containsToolSearchInModelResponse);
}
function containsToolSearchInModelResponse(modelResponse) {
    return Boolean(modelResponse?.output.some((item) => isToolSearchProtocolType(item.type)));
}
function containsToolSearchRunItems(items) {
    return Boolean(items?.some((item) => item.type === 'tool_search_call_item' ||
        item.type === 'tool_search_output_item' ||
        isToolSearchProtocolType(item.rawItem?.type)));
}
function containsToolSearchProtocolItems(items) {
    return Array.isArray(items)
        ? items.some((item) => isToolSearchProtocolType(item.type))
        : false;
}
function containsToolSearchInProcessedResponse(processedResponse) {
    return containsToolSearchRunItems(processedResponse?.newItems);
}
function containsSerializedToolOutputCustomData(stateJson) {
    return (containsToolOutputCustomDataRunItems(stateJson.generatedItems) ||
        containsToolOutputCustomDataRunItems(stateJson.lastProcessedResponse?.newItems));
}
function containsStructuredToolOutputState(stateJson) {
    if (containsStructuredToolOutputRunItems(stateJson.generatedItems) ||
        containsStructuredToolOutputRunItems(stateJson.lastProcessedResponse?.newItems)) {
        return true;
    }
    return Boolean(stateJson.completedToolInvocationEvidence?.some(({ invocations }) => Object.values(invocations).some(({ items }) => items.some((reference) => 'item' in reference &&
        reference.item.type === 'tool_call_output_item' &&
        typeof reference.item.output !== 'string'))));
}
function containsStructuredToolOutputRunItems(items) {
    return Boolean(items?.some((item) => item.type === 'tool_call_output_item' &&
        typeof item.output !== 'string'));
}
function containsToolOutputCustomDataRunItems(items) {
    return Boolean(items?.some((item) => item.type === 'tool_call_output_item' &&
        Object.prototype.hasOwnProperty.call(item, 'customData')));
}
function isToolSearchProtocolType(type) {
    return type === 'tool_search_call' || type === 'tool_search_output';
}
function addSerializedRuntimeToolKey(runtimeToolKeys, runtimeToolKey) {
    if (runtimeToolKeys.has(runtimeToolKey)) {
        throw new UserError('Serialized client tool_search output contains multiple tools with the same routed identity. Assign unique tool names or namespaces before resuming RunState.');
    }
    runtimeToolKeys.add(runtimeToolKey);
}
function collectSerializedRuntimeToolKeys(value, runtimeToolKeys, namespace, validateRecognizedShape = false) {
    if (!value || typeof value !== 'object') {
        return;
    }
    const candidate = value;
    if (candidate.type === 'namespace') {
        if (typeof candidate.name !== 'string' ||
            candidate.name.length === 0 ||
            !Array.isArray(candidate.tools)) {
            if (validateRecognizedShape) {
                throw new UserError('Serialized client tool_search output contains a namespace without a valid routed identity.');
            }
            return;
        }
        const nestedNamespace = typeof candidate.name === 'string' ? candidate.name : namespace;
        for (const nestedTool of candidate.tools) {
            collectSerializedRuntimeToolKeys(nestedTool, runtimeToolKeys, nestedNamespace, true);
        }
        return;
    }
    const explicitNamespace = typeof candidate.namespace === 'string' && candidate.namespace.length > 0
        ? candidate.namespace
        : namespace;
    if (candidate.type === 'function') {
        if (typeof candidate.name !== 'string' || candidate.name.length === 0) {
            if (validateRecognizedShape) {
                throw new UserError('Serialized client tool_search output contains a function without a valid routed identity.');
            }
            return;
        }
        const directNamespace = typeof candidate.namespace === 'string' && candidate.namespace.length > 0
            ? candidate.namespace
            : undefined;
        if (candidate.name === namespace || candidate.name === directNamespace) {
            throw new UserError('Responses tool search reserves same-name namespaces for deferred top-level function tools. Rename the namespace or tool name to avoid ambiguous dispatch.');
        }
        const lookupKey = getFunctionToolLookupKey(candidate.name, explicitNamespace ??
            (candidate.deferLoading === true || candidate.defer_loading === true
                ? candidate.name
                : undefined));
        if (lookupKey) {
            addSerializedRuntimeToolKey(runtimeToolKeys, lookupKey);
        }
        return;
    }
    if (candidate.type === 'mcp') {
        if (typeof candidate.server_label !== 'string' ||
            candidate.server_label.length === 0) {
            if (validateRecognizedShape) {
                throw new UserError('Serialized client tool_search output contains an MCP tool without a valid routed identity.');
            }
            return;
        }
        addSerializedRuntimeToolKey(runtimeToolKeys, `mcp:${candidate.server_label}`);
        return;
    }
    if (!candidate.providerData || typeof candidate.providerData !== 'object') {
        return;
    }
    collectSerializedRuntimeToolKeys(candidate.providerData, runtimeToolKeys, explicitNamespace, false);
}
function getSerializedRuntimeToolKeys(toolSearchOutput) {
    const runtimeToolKeys = new Set();
    for (const tool of toolSearchOutput.tools) {
        collectSerializedRuntimeToolKeys(tool, runtimeToolKeys, undefined, true);
    }
    return runtimeToolKeys;
}
function getRuntimeToolKeys(runtimeTools, options = {}) {
    const runtimeToolKeys = new Set();
    const runtimeToolsByKey = new Map();
    for (const tool of runtimeTools) {
        const runtimeToolKey = getToolSearchRuntimeRoutingKey(tool);
        if (!runtimeToolKey) {
            if (options.allowUnsupported) {
                continue;
            }
            throw new UserError('Client tool_search execute() returned an unsupported runtime tool during RunState rehydration.');
        }
        if (options.rejectDuplicateKeys && runtimeToolsByKey.has(runtimeToolKey)) {
            throw new UserError('Client tool_search execute() returned multiple tools with the same routed identity during RunState rehydration.');
        }
        runtimeToolsByKey.set(runtimeToolKey, tool);
        runtimeToolKeys.add(runtimeToolKey);
    }
    return runtimeToolKeys;
}
function formatRuntimeToolKeys(runtimeToolKeys) {
    return [...runtimeToolKeys].sort().join(', ');
}
function selectSerializedRuntimeTools(args) {
    const { agent, toolSearchCall, expectedRuntimeToolKeys, enabledRuntimeTools, } = args;
    const actualRuntimeToolKeys = getRuntimeToolKeys(enabledRuntimeTools, {
        rejectDuplicateKeys: true,
    });
    const hasExpectedKeys = [...expectedRuntimeToolKeys].every((runtimeToolKey) => actualRuntimeToolKeys.has(runtimeToolKey));
    const hasActualKeys = [...actualRuntimeToolKeys].every((runtimeToolKey) => expectedRuntimeToolKeys.has(runtimeToolKey));
    if (hasExpectedKeys && hasActualKeys) {
        return enabledRuntimeTools.filter((runtimeTool) => {
            const runtimeToolKey = getToolSearchRuntimeRoutingKey(runtimeTool);
            return (runtimeToolKey != null && expectedRuntimeToolKeys.has(runtimeToolKey));
        });
    }
    if (logger.dontLogToolData) {
        throw new UserError('RunState cannot resume custom client tool_search because the registered execute callback returned different runtime tools than the serialized state.');
    }
    const callId = resolveToolSearchCallId(toolSearchCall);
    throw new UserError(`RunState cannot resume custom client tool_search call ${callId} for agent ${agent.name} because the registered execute callback returned runtime tools [${formatRuntimeToolKeys(actualRuntimeToolKeys)}] but the serialized state expects [${formatRuntimeToolKeys(expectedRuntimeToolKeys)}].`);
}
async function getConfiguredAgentTools(args) {
    const { agent, context, configuredToolsByAgent } = args;
    const existing = configuredToolsByAgent.get(agent);
    if (existing) {
        return existing;
    }
    const configuredTools = (await agent.getAllTools(context));
    configuredToolsByAgent.set(agent, configuredTools);
    return configuredTools;
}
function throwAmbiguousFunctionCallId(agent, callId, routedToolKeys) {
    if (logger.dontLogToolData) {
        throw new UserError('RunState cannot resume because a function call ID is associated with multiple routed tool identities.');
    }
    throw new UserError(`RunState cannot resume function call ${callId} for agent ${agent.name} because the call ID is reused across routed tool identities [${[
        ...routedToolKeys,
    ].join(', ')}]. Use a unique call ID for each function call.`);
}
function assertUnambiguousFunctionCallIds(state, agentMap, serializedProcessedResponse) {
    const deferredFunctionCallExpectations = [];
    const generatedCallsByAgent = new Map();
    for (const item of state._generatedItems) {
        if (!(item instanceof RunToolCallItem) ||
            item.rawItem.type !== 'function_call') {
            continue;
        }
        const agent = item.agent;
        const routedToolKey = getFunctionToolStateKeyForCall(item.rawItem);
        if (!routedToolKey) {
            continue;
        }
        const callsById = generatedCallsByAgent.get(agent) ?? new Map();
        const previousRoutedToolKey = callsById.get(item.rawItem.callId);
        if (previousRoutedToolKey && previousRoutedToolKey !== routedToolKey) {
            throwAmbiguousFunctionCallId(agent, item.rawItem.callId, [
                previousRoutedToolKey,
                routedToolKey,
            ]);
        }
        callsById.set(item.rawItem.callId, routedToolKey);
        generatedCallsByAgent.set(agent, callsById);
    }
    const processedCallsByAgent = new Map();
    if (serializedProcessedResponse) {
        const agent = state._currentAgent;
        const processedCallsById = new Map();
        for (const functionCall of serializedProcessedResponse.functions) {
            const toolCall = functionCall.toolCall;
            const rawRoutedToolKey = getFunctionToolStateKeyForCall(toolCall);
            if (!rawRoutedToolKey) {
                continue;
            }
            const serializedToolStateKey = getToolCallNamespace(toolCall)
                ? rawRoutedToolKey
                : getFunctionToolStateKey(functionCall.tool);
            const resolvedRoutedToolKey = serializedToolStateKey
                ? getFunctionToolStateKeyForResolvedCall(toolCall, functionCall.tool, serializedToolStateKey)
                : rawRoutedToolKey;
            if (!resolvedRoutedToolKey) {
                throwAmbiguousFunctionCallId(agent, toolCall.callId, [
                    rawRoutedToolKey,
                    serializedToolStateKey,
                ]);
            }
            if (resolvedRoutedToolKey !== rawRoutedToolKey) {
                deferredFunctionCallExpectations.push({
                    agent,
                    toolCall,
                    resolvedRoutedToolKey,
                });
            }
            const callId = toolCall.callId;
            const previousProcessedIdentity = processedCallsById.get(callId);
            if (previousProcessedIdentity &&
                previousProcessedIdentity.resolvedRoutedToolKey !==
                    resolvedRoutedToolKey) {
                throwAmbiguousFunctionCallId(agent, callId, [
                    previousProcessedIdentity.resolvedRoutedToolKey,
                    resolvedRoutedToolKey,
                ]);
            }
            const generatedRoutedToolKey = generatedCallsByAgent
                .get(agent)
                ?.get(callId);
            if (generatedRoutedToolKey &&
                generatedRoutedToolKey !== rawRoutedToolKey) {
                throwAmbiguousFunctionCallId(agent, callId, [
                    generatedRoutedToolKey,
                    rawRoutedToolKey,
                ]);
            }
            processedCallsById.set(callId, {
                rawRoutedToolKey,
                resolvedRoutedToolKey,
            });
        }
        processedCallsByAgent.set(agent, processedCallsById);
    }
    if (state._currentStep?.type !== 'next_step_interruption') {
        return deferredFunctionCallExpectations;
    }
    for (const value of state._currentStep.data?.interruptions ?? []) {
        if (!value || typeof value !== 'object') {
            continue;
        }
        const interruption = value;
        if (!interruption.rawItem ||
            typeof interruption.rawItem !== 'object' ||
            interruption.rawItem.type !== 'function_call') {
            continue;
        }
        const rawItem = interruption.rawItem;
        const rawItemRoutedToolKey = getFunctionToolStateKeyForCall(rawItem);
        if (!rawItemRoutedToolKey) {
            continue;
        }
        const interruptionAgent = interruption.agent && typeof interruption.agent === 'object'
            ? resolveSerializedAgent(interruption.agent, agentMap, state._currentAgent)
            : state._currentAgent;
        const generatedRoutedToolKey = generatedCallsByAgent
            .get(interruptionAgent)
            ?.get(rawItem.callId);
        if (generatedRoutedToolKey &&
            generatedRoutedToolKey !== rawItemRoutedToolKey) {
            throwAmbiguousFunctionCallId(interruptionAgent, rawItem.callId, [
                generatedRoutedToolKey,
                rawItemRoutedToolKey,
            ]);
        }
        const processedIdentity = processedCallsByAgent
            .get(interruptionAgent)
            ?.get(rawItem.callId);
        if (processedIdentity &&
            processedIdentity.rawRoutedToolKey !== rawItemRoutedToolKey) {
            throwAmbiguousFunctionCallId(interruptionAgent, rawItem.callId, [
                processedIdentity.rawRoutedToolKey,
                rawItemRoutedToolKey,
            ]);
        }
        const expectedRoutedToolKey = processedIdentity?.resolvedRoutedToolKey ?? rawItemRoutedToolKey;
        if (typeof interruption.functionToolStateKey === 'string') {
            const validationRequiresPendingNestedState = interruptionAgent !== state._currentAgent && !processedIdentity;
            if (!validationRequiresPendingNestedState &&
                interruption.functionToolStateKey !== expectedRoutedToolKey) {
                throwAmbiguousFunctionCallId(interruptionAgent, rawItem.callId, [
                    expectedRoutedToolKey,
                    interruption.functionToolStateKey,
                ]);
            }
        }
    }
    return deferredFunctionCallExpectations;
}
function collectDeferredToolSearchProvenanceByCallId(args) {
    const { state, effectiveToolSearchOutputs, serializedRuntimeToolKeysByOutput, } = args;
    const effectiveOutputs = new Set(effectiveToolSearchOutputs);
    const routedOwnersByAgent = new Map();
    const entriesByReplacementKeyByAgent = new Map();
    const deferredKeysByCallIdByAgent = new Map();
    for (const item of state._generatedItems) {
        if (item instanceof RunToolSearchOutputItem && effectiveOutputs.has(item)) {
            const agent = item.agent;
            const routedOwners = routedOwnersByAgent.get(agent) ?? new Map();
            const entriesByReplacementKey = entriesByReplacementKeyByAgent.get(agent) ?? new Map();
            const replacementKey = getToolSearchOutputReplacementKey(item.rawItem);
            if (replacementKey) {
                const previousEntry = entriesByReplacementKey.get(replacementKey);
                if (previousEntry) {
                    for (const [routedKey, owner] of routedOwners) {
                        if (owner === previousEntry) {
                            routedOwners.delete(routedKey);
                        }
                    }
                }
                entriesByReplacementKey.set(replacementKey, item);
            }
            for (const routedKey of serializedRuntimeToolKeysByOutput.get(item) ??
                []) {
                routedOwners.set(routedKey, item);
            }
            routedOwnersByAgent.set(agent, routedOwners);
            entriesByReplacementKeyByAgent.set(agent, entriesByReplacementKey);
            continue;
        }
        if (!(item instanceof RunToolCallItem) ||
            item.rawItem.type !== 'function_call' ||
            getToolCallNamespace(item.rawItem)) {
            continue;
        }
        const name = item.rawItem.name;
        const bareKey = getFunctionToolLookupKey(name);
        const deferredKey = getFunctionToolLookupKey(name, name);
        const routedOwners = routedOwnersByAgent.get(item.agent);
        if (!bareKey ||
            !deferredKey ||
            routedOwners?.has(bareKey) ||
            !routedOwners?.has(deferredKey)) {
            continue;
        }
        const keysByCallId = deferredKeysByCallIdByAgent.get(item.agent) ?? new Map();
        keysByCallId.set(item.rawItem.callId, deferredKey);
        deferredKeysByCallIdByAgent.set(item.agent, keysByCallId);
    }
    return deferredKeysByCallIdByAgent;
}
function assertDeferredFunctionCallProvenance(args) {
    const { expectations, capabilitySnapshotsByAgent, deferredToolSearchKeysByCallIdByAgent, } = args;
    for (const expectation of expectations) {
        const snapshot = capabilitySnapshotsByAgent.get(expectation.agent);
        if (snapshot?.handoffMap.has(expectation.toolCall.name)) {
            throwAmbiguousFunctionCallId(expectation.agent, expectation.toolCall.callId, [expectation.toolCall.name, expectation.resolvedRoutedToolKey]);
        }
        const configuredOwner = snapshot
            ? resolveFunctionToolCall(expectation.toolCall, snapshot.functionMap)
            : undefined;
        if (configuredOwner) {
            if (getFunctionToolStateKey(configuredOwner) ===
                expectation.resolvedRoutedToolKey) {
                continue;
            }
            throwAmbiguousFunctionCallId(expectation.agent, expectation.toolCall.callId, [
                getFunctionToolStateKey(configuredOwner) ?? configuredOwner.name,
                expectation.resolvedRoutedToolKey,
            ]);
        }
        if (deferredToolSearchKeysByCallIdByAgent
            .get(expectation.agent)
            ?.get(expectation.toolCall.callId) !== expectation.resolvedRoutedToolKey) {
            throwAmbiguousFunctionCallId(expectation.agent, expectation.toolCall.callId, [
                getFunctionToolStateKeyForCall(expectation.toolCall) ??
                    expectation.toolCall.name,
                expectation.resolvedRoutedToolKey,
            ]);
        }
    }
}
async function rehydrateToolSearchRuntimeTools(state, options) {
    const deferredFunctionCallExpectations = assertUnambiguousFunctionCallIds(state, options.agentMap, options.serializedProcessedResponse);
    const configuredToolsByAgent = new Map();
    const capabilitySnapshotsByAgent = new Map();
    const toolSearchCallOccurrences = [];
    const latestOccurrenceByAgentAndCallId = new Map();
    const pendingOccurrencesByAgent = new Map();
    for (const item of state._generatedItems) {
        if (item instanceof RunToolSearchCallItem) {
            if (getToolSearchExecution(item.rawItem) === 'server') {
                continue;
            }
            const callId = resolveToolSearchCallId(item.rawItem);
            const agent = item.agent;
            const occurrence = {
                pendingCall: {
                    agent,
                    toolSearchCall: item.rawItem,
                },
            };
            toolSearchCallOccurrences.push(occurrence);
            const pendingOccurrences = pendingOccurrencesByAgent.get(agent) ?? [];
            pendingOccurrences.push(occurrence);
            pendingOccurrencesByAgent.set(agent, pendingOccurrences);
            const occurrencesByCallId = latestOccurrenceByAgentAndCallId.get(agent) ?? new Map();
            occurrencesByCallId.set(callId, occurrence);
            latestOccurrenceByAgentAndCallId.set(agent, occurrencesByCallId);
            continue;
        }
        if (!(item instanceof RunToolSearchOutputItem) ||
            getToolSearchExecution(item.rawItem) === 'server') {
            continue;
        }
        const agent = item.agent;
        const explicitCallId = getToolSearchProviderCallId(item.rawItem);
        const pendingOccurrences = pendingOccurrencesByAgent.get(agent) ?? [];
        const occurrence = explicitCallId
            ? latestOccurrenceByAgentAndCallId.get(agent)?.get(explicitCallId)
            : pendingOccurrences.shift();
        if (!occurrence) {
            const callId = resolveToolSearchCallId(item.rawItem);
            throw new UserError(logger.dontLogToolData
                ? 'RunState cannot resume custom client tool_search because the serialized state is missing the matching tool_search call item.'
                : `RunState cannot resume custom client tool_search output ${callId} for agent ${item.agent.name} because the serialized state is missing the matching tool_search call item.`);
        }
        if (explicitCallId) {
            const pendingIndex = pendingOccurrences.indexOf(occurrence);
            if (pendingIndex >= 0) {
                pendingOccurrences.splice(pendingIndex, 1);
            }
        }
        occurrence.output = item;
    }
    const effectiveToolSearchOutputs = toolSearchCallOccurrences
        .map((occurrence) => occurrence.output)
        .filter((item) => Boolean(item));
    const occurrencesByOutput = new Map(toolSearchCallOccurrences.flatMap((occurrence) => occurrence.output ? [[occurrence.output, occurrence]] : []));
    const serializedRuntimeToolKeysByOutput = new Map();
    for (const item of effectiveToolSearchOutputs) {
        serializedRuntimeToolKeysByOutput.set(item, getSerializedRuntimeToolKeys(item.rawItem));
    }
    const agentsToPrepare = new Set(effectiveToolSearchOutputs.map((item) => item.agent));
    if (options.serializedProcessedResponse) {
        agentsToPrepare.add(state._currentAgent);
    }
    if (options.prepareCurrentAgentForLegacyApprovals) {
        agentsToPrepare.add(state._currentAgent);
    }
    for (const agent of agentsToPrepare) {
        const configuredTools = await getConfiguredAgentTools({
            agent,
            context: state._context,
            configuredToolsByAgent,
        });
        const existingRuntimeTools = state.getToolSearchRuntimeTools(agent);
        const enabledRuntimeTools = await getEnabledToolSearchRuntimeTools(state, agent);
        const capabilities = resolveModelVisibleToolNameCollisions([...configuredTools, ...enabledRuntimeTools], await agent.getEnabledHandoffs(state._context), 'warn');
        const availableTools = [...capabilities.tools];
        capabilitySnapshotsByAgent.set(agent, {
            availableTools,
            callbackTools: [...availableTools],
            handoffs: capabilities.handoffs,
            functionMap: buildFunctionToolLookupMap(availableTools.filter((tool) => tool.type === 'function')),
            functionToolsByCallId: new Map(),
            runtimeFunctionTools: new Set(existingRuntimeTools.filter((tool) => tool.type === 'function')),
            handoffMap: new Map(capabilities.handoffs.map((handoff) => [handoff.toolName, handoff])),
            mcpToolMap: new Map(availableTools
                .filter((tool) => tool.type === 'hosted_tool' && tool.providerData?.type === 'mcp')
                .map((tool) => [tool.providerData.server_label, tool])),
            replaceableRuntimeToolKeys: new Set(existingRuntimeTools
                .map((tool) => getToolSearchRuntimeRoutingKey(tool))
                .filter((key) => typeof key === 'string')),
        });
    }
    assertDeferredFunctionCallProvenance({
        expectations: deferredFunctionCallExpectations,
        capabilitySnapshotsByAgent,
        deferredToolSearchKeysByCallIdByAgent: collectDeferredToolSearchProvenanceByCallId({
            state: state,
            effectiveToolSearchOutputs,
            serializedRuntimeToolKeysByOutput,
        }),
    });
    if (schemaVersionSupportsV116State(options.schemaVersion) &&
        options.serializedProcessedResponse) {
        const currentAgent = state._currentAgent;
        const currentSnapshot = capabilitySnapshotsByAgent.get(currentAgent);
        for (const serializedHandoff of options.serializedProcessedResponse
            .handoffs) {
            if (!serializedHandoff.targetAgent) {
                throw new UserError('Run state handoff is missing its required target agent identity.');
            }
            const targetAgent = resolveSerializedAgent(serializedHandoff.targetAgent, options.agentMap);
            const handoff = currentSnapshot.handoffMap.get(serializedHandoff.handoff.toolName);
            if (!handoff || handoff.agent !== targetAgent) {
                throw new UserError(`Handoff ${serializedHandoff.handoff.toolName} not found`);
            }
        }
    }
    for (const agent of new Set(effectiveToolSearchOutputs.map((item) => item.agent))) {
        validateClientToolSearchSupport(capabilitySnapshotsByAgent.get(agent).availableTools);
    }
    const rehydrationRecords = new Map();
    for (const item of effectiveToolSearchOutputs) {
        const callId = resolveToolSearchCallId(item.rawItem);
        const agent = item.agent;
        const snapshot = capabilitySnapshotsByAgent.get(agent);
        const expectedRuntimeToolKeys = serializedRuntimeToolKeysByOutput.get(item);
        const pendingCall = occurrencesByOutput.get(item).pendingCall;
        const toolSearchTool = getClientToolSearchHelper(snapshot.availableTools);
        const hasCustomExecutor = Boolean(toolSearchTool && getClientToolSearchExecutor(toolSearchTool));
        if (expectedRuntimeToolKeys.size === 0) {
            rehydrationRecords.set(item, {
                pendingCall,
                expectedRuntimeToolKeys,
                ...(hasCustomExecutor ? { toolSearchTool } : {}),
            });
            continue;
        }
        if (!hasCustomExecutor) {
            const availableRuntimeToolKeys = getRuntimeToolKeys(snapshot.availableTools, { allowUnsupported: true });
            if ([...expectedRuntimeToolKeys].every((runtimeToolKey) => availableRuntimeToolKeys.has(runtimeToolKey))) {
                rehydrationRecords.set(item, {
                    pendingCall,
                    expectedRuntimeToolKeys,
                });
                continue;
            }
            if (logger.dontLogToolData) {
                throw new UserError('RunState cannot resume custom client tool_search because the agent no longer provides toolSearchTool({ execution: "client", execute }).');
            }
            throw new UserError(`RunState cannot resume custom client tool_search call ${callId} for agent ${pendingCall.agent.name} because the agent no longer provides toolSearchTool({ execution: "client", execute }).`);
        }
        rehydrationRecords.set(item, {
            pendingCall,
            expectedRuntimeToolKeys,
            toolSearchTool,
        });
    }
    for (const generatedItem of state._generatedItems) {
        if (!(generatedItem instanceof RunToolSearchOutputItem)) {
            continue;
        }
        const record = rehydrationRecords.get(generatedItem);
        if (!record?.toolSearchTool) {
            continue;
        }
        const agent = record.pendingCall.agent;
        const snapshot = capabilitySnapshotsByAgent.get(agent);
        const { runtimeTools, callbackRuntimeTools } = await executeCustomClientToolSearch({
            agent,
            runContext: state._context,
            toolSearchCall: record.pendingCall.toolSearchCall,
            toolSearchTool: record.toolSearchTool,
            tools: snapshot.callbackTools,
        });
        const serializedRuntimeTools = selectSerializedRuntimeTools({
            agent,
            toolSearchCall: record.pendingCall.toolSearchCall,
            expectedRuntimeToolKeys: record.expectedRuntimeToolKeys,
            enabledRuntimeTools: runtimeTools,
        });
        record.runtimeTools = serializedRuntimeTools;
        snapshot.callbackTools.push(...callbackRuntimeTools);
    }
    for (const generatedItem of state._generatedItems) {
        if (generatedItem instanceof RunToolSearchOutputItem) {
            const record = rehydrationRecords.get(generatedItem);
            if (!record?.runtimeTools) {
                continue;
            }
            const agent = record.pendingCall.agent;
            const snapshot = capabilitySnapshotsByAgent.get(agent);
            const replacedRuntimeTools = state.getToolSearchRuntimeToolsForOutput(agent, generatedItem.rawItem);
            const registeredRuntimeTools = registerRuntimeToolSearchTools({
                availableTools: snapshot.availableTools,
                functionMap: snapshot.functionMap,
                handoffMap: snapshot.handoffMap,
                mcpToolMap: snapshot.mcpToolMap,
                replaceableRuntimeToolKeys: snapshot.replaceableRuntimeToolKeys,
                replacedRuntimeTools,
                runtimeTools: record.runtimeTools,
            });
            for (const runtimeTool of registeredRuntimeTools) {
                if (runtimeTool.type === 'function') {
                    snapshot.runtimeFunctionTools.add(runtimeTool);
                }
            }
            state.recordToolSearchRuntimeTools(agent, generatedItem.rawItem, registeredRuntimeTools);
            continue;
        }
        if (generatedItem instanceof RunToolCallItem &&
            generatedItem.rawItem.type === 'function_call') {
            const agent = generatedItem.agent;
            const snapshot = capabilitySnapshotsByAgent.get(agent);
            if (!snapshot) {
                continue;
            }
            const functionTool = resolveFunctionToolCall(generatedItem.rawItem, snapshot.functionMap);
            if (functionTool) {
                if (snapshot.runtimeFunctionTools.has(functionTool)) {
                    snapshot.functionToolsByCallId.set(generatedItem.rawItem.callId, functionTool);
                }
            }
        }
    }
    return capabilitySnapshotsByAgent;
}
function restoreCurrentResponseProcessedOwnership(state, stateJson) {
    const ownership = stateJson.currentResponseGeneratedItemOwnership;
    if (!ownership || !state._lastProcessedResponse) {
        return;
    }
    const processedItemCount = stateJson.lastProcessedResponse?.newItems.length ?? 0;
    state._lastProcessedResponse.newItems = state._generatedItems.slice(ownership.generatedItemStartIndex, ownership.generatedItemStartIndex + processedItemCount);
    state._lastTurnResponse = state._modelResponses.at(-1);
    restoreCurrentResponseToolOutputGuardrailResultStart(state, ownership.toolOutputGuardrailResultStartIndex, ownership.interruptionGeneratedItemIndexes.includes(null));
}
function restoreCurrentResponseInterruptionOwnership(stateJson, state, interruptions) {
    const ownership = stateJson.currentResponseGeneratedItemOwnership;
    if (!ownership) {
        return interruptions;
    }
    return ownership.interruptionGeneratedItemIndexes.map((index, offset) => {
        if (index === null) {
            const interruption = interruptions[offset];
            if (!interruption ||
                !state._ownsNestedApproval(interruption, interruptions)) {
                throwCurrentResponseOwnershipError('unproven child approval');
            }
            return interruption;
        }
        const interruption = state._generatedItems[index];
        if (!(interruption instanceof RunToolApprovalItem)) {
            throwCurrentResponseOwnershipError();
        }
        return interruption;
    });
}
async function buildRunStateFromJson(initialAgent, stateJson, options = {}) {
    const schemaVersion = stateJson.$schemaVersion;
    const serializedApprovals = stateJson.context.approvals;
    if (schemaVersionSupportsV118State(schemaVersion) &&
        (stateJson.context.approvalInvocations === undefined ||
            stateJson.completedToolInvocations === undefined ||
            stateJson.completedToolInvocationEvidence === undefined ||
            stateJson.ambiguousToolInvocationCallIds === undefined)) {
        throw new UserError(`RunState schema ${schemaVersion} requires explicit approval, completed, completion-evidence, and ambiguous invocation records.`);
    }
    if (schemaVersionSupportsV118State(schemaVersion)) {
        validateCurrentApprovalInvocationRecords(stateJson.context);
    }
    const agentMap = schemaVersionSupportsAgentIdentity(schemaVersion)
        ? buildAgentIdentityMap(initialAgent).byIdentity
        : buildAgentMap(initialAgent);
    const generatedItems = stateJson.generatedItems.map((item) => deserializeItem(item, agentMap));
    const contextOverride = options.contextOverride;
    const contextStrategy = options.contextStrategy ?? 'merge';
    let deferredLegacyApprovalContext;
    //
    // Rebuild the context
    //
    const context = contextOverride
        ? contextOverride._cloneForRunStateDeserialization()
        : new RunContext(stateJson.context.context);
    context._validateFunctionApprovalOwners(stateJson.context.functionApprovals ?? [], agentMap);
    if (schemaVersionSupportsV118State(schemaVersion)) {
        context._validateApprovalInvocations(stateJson.context.approvalInvocations ?? [], agentMap);
    }
    if (contextOverride) {
        if (contextStrategy === 'merge') {
            if (schemaVersionSupportsV116State(schemaVersion)) {
                context._mergeApprovals(serializedApprovals);
                if (schemaVersionSupportsV118State(schemaVersion)) {
                    context._mergeHostedMcpApprovals(stateJson.context.hostedMcpApprovals ?? {});
                }
                context._mergeFunctionApprovals(stateJson.context.functionApprovals ?? [], agentMap);
                context._mergeLegacyFunctionApprovals(stateJson.context.legacyFunctionApprovals ?? {});
                if (schemaVersionSupportsV118State(schemaVersion)) {
                    context._mergeApprovalInvocations(stateJson.context.approvalInvocations ?? [], agentMap);
                }
            }
            else {
                deferredLegacyApprovalContext = new RunContext(stateJson.context.context);
                deferredLegacyApprovalContext._rebuildApprovals(serializedApprovals);
                deferredLegacyApprovalContext._rebuildLegacyFunctionApprovals(serializedApprovals);
            }
        }
    }
    else {
        context._rebuildApprovals(serializedApprovals);
        context._rebuildHostedMcpApprovals(schemaVersionSupportsV118State(schemaVersion)
            ? (stateJson.context.hostedMcpApprovals ?? {})
            : {});
        context._rebuildFunctionApprovals(stateJson.context.functionApprovals ?? [], agentMap);
        context._rebuildLegacyFunctionApprovals(schemaVersionSupportsV116State(schemaVersion)
            ? (stateJson.context.legacyFunctionApprovals ?? {})
            : serializedApprovals);
        context._rebuildApprovalInvocations(schemaVersionSupportsV118State(schemaVersion)
            ? (stateJson.context.approvalInvocations ?? [])
            : [], agentMap);
    }
    const shouldRestoreSerializedContext = !contextOverride || contextStrategy === 'merge';
    if (shouldRestoreSerializedContext &&
        typeof stateJson.context.toolInput !== 'undefined' &&
        typeof context.toolInput === 'undefined') {
        context.toolInput = stateJson.context.toolInput;
    }
    // Restore the aggregated run usage. toJSON serializes context.usage, but a
    // freshly constructed RunContext starts with an empty Usage, so without this
    // a resumed run reports zero token usage.
    //
    // Only restore on the no-override path. A caller-supplied RunContext is
    // authoritative and owns its usage accounting: its counters do not reveal
    // whether its Usage is newly owned or shared with another run (for example a
    // nested agent-tool resume passes a context whose usage aggregate is shared
    // with the outer run), so it is left untouched.
    if (!contextOverride) {
        context.usage = new Usage(stateJson.context.usage);
    }
    //
    // Find the current agent from the initial agent
    //
    const currentAgent = resolveSerializedAgent(stateJson.currentAgent, agentMap);
    const state = new RunState(context, '', initialAgent, stateJson.maxTurns);
    state._currentAgent = currentAgent;
    state._currentTurn = stateJson.currentTurn;
    state._currentTurnInProgress = stateJson.currentTurnInProgress ?? false;
    state._initialInputGuardrailsCompleted =
        stateJson.initialInputGuardrailsCompleted ?? false;
    state._conversationId = stateJson.conversationId ?? undefined;
    state._previousResponseId = stateJson.previousResponseId ?? undefined;
    state._reasoningItemIdPolicy = stateJson.reasoningItemIdPolicy ?? undefined;
    // rebuild tool use tracker
    state._toolUseTracker = new AgentToolUseTracker();
    for (const [agentName, toolNames] of Object.entries(stateJson.toolUseTracker)) {
        const agent = agentMap.get(agentName);
        if (!agent) {
            throw new UserError(`Agent ${agentName} not found`);
        }
        state._toolUseTracker.addToolUse(agent, toolNames, {
            allowEmpty: true,
        });
    }
    state._pendingAgentToolRuns = new Map(Object.entries(stateJson.pendingAgentToolRuns ?? {}));
    state._pendingAgentToolRunAliases = new Map();
    state._completedToolInvocations = schemaVersionSupportsV118State(schemaVersion)
        ? deserializeAgentInvocationRecords(stateJson.completedToolInvocations ?? [], agentMap)
        : new Map();
    state._completedToolInvocationEvidence = schemaVersionSupportsV118State(schemaVersion)
        ? deserializeAgentInvocationEvidence(stateJson.completedToolInvocationEvidence ?? [], agentMap, generatedItems)
        : new Map();
    state._observedToolInvocations = new Map();
    state._ambiguousToolInvocationCallIds = schemaVersionSupportsV118State(schemaVersion)
        ? deserializeAgentCallIdSets(stateJson.ambiguousToolInvocationCallIds ?? [], agentMap)
        : new Map();
    if (schemaVersionSupportsV118State(schemaVersion)) {
        validateCurrentCompletedToolInvocations(state, generatedItems, schemaVersion);
    }
    // rebuild current agent span
    if (stateJson.currentAgentSpan) {
        if (!stateJson.trace) {
            logger.warn('Trace is not set, skipping tracing setup');
        }
        const trace = getGlobalTraceProvider().createTrace({
            traceId: stateJson.trace?.id,
            name: stateJson.trace?.workflow_name,
            groupId: stateJson.trace?.group_id ?? undefined,
            metadata: stateJson.trace?.metadata,
            tracingApiKey: stateJson.trace?.tracing_api_key ?? undefined,
        });
        state._currentAgentSpan = deserializeSpan(trace, stateJson.currentAgentSpan);
        state._trace = trace;
    }
    state._noActiveAgentRun = stateJson.noActiveAgentRun;
    state._inputGuardrailResults =
        stateJson.inputGuardrailResults;
    state._outputGuardrailResults = stateJson.outputGuardrailResults.map((r) => ({
        ...r,
        agent: resolveSerializedAgent(r.agent, agentMap),
    }));
    state._toolInputGuardrailResults =
        stateJson.toolInputGuardrailResults;
    state._toolOutputGuardrailResults =
        stateJson.toolOutputGuardrailResults;
    state._currentStep = stateJson.currentStep;
    state._originalInput = stateJson.originalInput;
    state._pendingInput = structuredClone(stateJson.pendingInput ?? []);
    state._modelResponses = stateJson.modelResponses.map(deserializeModelResponse);
    state._lastTurnResponse = stateJson.lastModelResponse
        ? deserializeModelResponse(stateJson.lastModelResponse)
        : undefined;
    state._generatedItems = generatedItems;
    state._currentTurnPersistedItemCount =
        stateJson.currentTurnPersistedItemCount ?? 0;
    state._currentTurnSessionWriteCompactedItemCount =
        schemaVersionSupportsV120State(schemaVersion)
            ? stateJson.currentTurnSessionWriteCompactedItemCount
            : undefined;
    const supportsOutputGuardrailSessionPersistence = schemaVersionSupportsV117State(schemaVersion);
    const deferredSessionItemIndexes = supportsOutputGuardrailSessionPersistence
        ? (stateJson.currentTurnDeferredSessionItemIndexes ?? [])
        : [];
    state._currentTurnDeferredSessionItemIndexes = new Set(deferredSessionItemIndexes);
    state._currentTurnBlockedSessionStartIndex = undefined;
    const restoredPendingSessionBinding = stateJson.currentTurnExecutedWithSessionBinding === true &&
        stateJson.pendingSessionWrite !== undefined
        ? stateJson.pendingSessionWrite.sessionId
        : undefined;
    state._currentTurnSessionHistoryTransactionSessionId =
        restoredPendingSessionBinding;
    state._currentTurnSessionReasoningItemIdPolicy = restoredPendingSessionBinding
        ? stateJson.pendingSessionWrite?.reasoningItemIdPolicy
        : undefined;
    state._currentTurnSessionHistoryTransactionInputItems =
        schemaVersionSupportsV117State(schemaVersion)
            ? stateJson.currentTurnSessionInputItems
            : undefined;
    state._currentTurnSessionHistoryTransactionCanReplaceAcceptedOutput =
        undefined;
    state._sessionHistoryTransactionId = randomUUID();
    state._pendingSessionHistoryTransaction = undefined;
    state._pendingSessionWrite = stateJson.pendingSessionWrite
        ? structuredClone(stateJson.pendingSessionWrite)
        : undefined;
    state._resumedSessionWriteInProgress = false;
    state._pendingLegacyCompactionSessionItems =
        stateJson.pendingLegacyCompactionSessionItems;
    if (state._pendingSessionWrite?.phase === 'compaction_pending' &&
        state._currentStep?.type === 'next_step_final_output' &&
        typeof state._currentAgent.toolUseBehavior === 'function') {
        throw new UserError('RunState pending Session compaction terminal output is invalid.');
    }
    if (state._pendingSessionWrite) {
        assertPendingSessionWriteOwnership(state, state._pendingSessionWrite, {
            allowUnhydratedTerminalToolStep: true,
        });
    }
    state._sandbox = stateJson.sandbox
        ? sanitizeSerializedSandboxState(stateJson.sandbox)
        : undefined;
    const capabilitySnapshotsByAgent = await rehydrateToolSearchRuntimeTools(state, {
        agentMap,
        schemaVersion,
        serializedProcessedResponse: stateJson.lastProcessedResponse,
        prepareCurrentAgentForLegacyApprovals: !schemaVersionSupportsV116State(schemaVersion) &&
            shouldRestoreSerializedContext &&
            Object.keys(stateJson.context.approvals).length > 0,
    });
    const currentCapabilitySnapshot = capabilitySnapshotsByAgent.get(state._currentAgent);
    state._lastProcessedResponse = stateJson.lastProcessedResponse
        ? await deserializeProcessedResponse(agentMap, state, stateJson.lastProcessedResponse, {
            executionTools: currentCapabilitySnapshot.availableTools,
            executionHandoffs: currentCapabilitySnapshot.handoffs,
            executionFunctionToolsByCallId: currentCapabilitySnapshot.functionToolsByCallId,
        })
        : undefined;
    restoreCurrentResponseProcessedOwnership(state, stateJson);
    restorePendingAgentToolRunAliases(state, stateJson.pendingAgentToolRunAliases ?? {});
    if (stateJson.currentStep?.type === 'next_step_handoff') {
        state._currentStep = {
            type: 'next_step_handoff',
            newAgent: resolveSerializedAgent(stateJson.currentStep.newAgent, agentMap),
        };
    }
    else if (stateJson.currentStep?.type === 'next_step_interruption') {
        const interruptions = restoreCurrentResponseInterruptionOwnership(stateJson, state, deserializeInterruptions(stateJson.currentStep.data?.interruptions, agentMap, state._currentAgent));
        rebindInterruptionFunctionToolStateKeys(interruptions, state._lastProcessedResponse, state._currentAgent, state, schemaVersion);
        if (!schemaVersionSupportsV118State(schemaVersion) &&
            shouldRestoreSerializedContext) {
            restoreLegacyHostedMcpApprovalsForPendingRequests(context, stateJson.context.approvals, interruptions, schemaVersion === '1.17');
        }
        state._currentStep = {
            type: 'next_step_interruption',
            data: {
                ...stateJson.currentStep.data,
                interruptions,
            },
        };
    }
    const legacyAvailableToolsByAgent = new Map();
    for (const agent of new Set(agentMap.values())) {
        legacyAvailableToolsByAgent.set(agent, [
            ...agent.tools,
        ]);
    }
    for (const [agent, snapshot] of capabilitySnapshotsByAgent) {
        const configuredTools = legacyAvailableToolsByAgent.get(agent) ?? [];
        legacyAvailableToolsByAgent.set(agent, [
            ...new Set([...configuredTools, ...snapshot.availableTools]),
        ]);
    }
    const legacyFunctionApprovalKeys = migrateLegacyFunctionToolState(state, schemaVersion, shouldRestoreSerializedContext, deferredLegacyApprovalContext, legacyAvailableToolsByAgent);
    const legacyApprovalContext = deferredLegacyApprovalContext ?? context;
    if (!schemaVersionSupportsV116State(schemaVersion)) {
        legacyApprovalContext._retainLegacyFunctionApprovals(legacyFunctionApprovalKeys);
        legacyApprovalContext._removeMigratedFunctionApprovalsFromAggregate(legacyFunctionApprovalKeys, new Set([...legacyAvailableToolsByAgent.values()].flatMap((tools) => tools.flatMap((tool) => tool.type !== 'function' && typeof tool.name === 'string'
            ? [tool.name]
            : []))));
    }
    if (deferredLegacyApprovalContext) {
        context._mergeApprovalStatePreservingExactKeys(deferredLegacyApprovalContext, legacyFunctionApprovalKeys);
    }
    if (!schemaVersionSupportsV118State(schemaVersion)) {
        rebuildLegacyCompletedToolInvocations(state, generatedItems);
        for (const run of state._lastProcessedResponse?.functions ?? []) {
            const owner = state._lastProcessedResponse?.newItems.find((item) => item instanceof RunToolCallItem && item.rawItem === run.toolCall)?.agent;
            context._bindLegacyApprovalInvocation(new RunToolApprovalItem(run.toolCall, owner ?? state._currentAgent, run.tool.name, getFunctionToolStateKey(run.tool) ??
                getFunctionToolStateKeyForCall(run.toolCall, run.tool.name)));
        }
        for (const interruption of state.getInterruptions()) {
            context._bindLegacyApprovalInvocation(interruption);
        }
    }
    const interruptions = state.getInterruptions();
    for (const toolRun of state._lastProcessedResponse?.functions ?? []) {
        const call = toolRun.toolCall;
        const owner = state._lastProcessedResponse?.newItems.find((item) => item instanceof RunToolCallItem && item.rawItem === call)?.agent ?? state._currentAgent;
        const isPending = interruptions.some((item) => item.agent === owner &&
            item.rawItem.type === 'function_call' &&
            item.rawItem.callId === call.callId) ||
            getFunctionToolStateKeys(toolRun.tool, toolRun.availableFunctionTools ?? [toolRun.tool]).some((key) => state.hasPendingAgentToolRun(key, call.callId));
        if (!isPending)
            continue;
        const invocation = getToolInvocationFingerprint(getFunctionToolQualifiedName(toolRun.tool) ?? toolRun.tool.name, call);
        if (!hasDynamicFunctionToolApprovalPolicy(toolRun.tool))
            continue;
        // Restored calls have no retained normalized input. Re-evaluate the current
        // policy before honoring a decision for refreshed successful input.
        let records = state._pendingFunctionToolApprovals.get(owner);
        if (!records)
            state._pendingFunctionToolApprovals.set(owner, (records = new Map()));
        records.set(call.callId, { invocation });
    }
    if (contextOverride) {
        const commitCandidate = contextOverride._cloneForRunStateDeserialization();
        commitCandidate._mergeApprovalState(context);
        contextOverride._replaceApprovalState(commitCandidate);
        if (contextStrategy === 'merge' &&
            contextOverride.toolInput === undefined &&
            context.toolInput !== undefined) {
            contextOverride.toolInput = context.toolInput;
        }
        state._context = contextOverride;
    }
    state._serializedCurrentStep = state._currentStep;
    if (hasPendingApprovedToolInputCompaction(state)) {
        assertPendingSessionCompactionTerminalAuthority(state);
    }
    return state;
}
/**
 * @internal
 */
export async function rehydrateProcessedResponseTools(initialAgent, state, executionTools) {
    if (!state._lastProcessedResponse) {
        return;
    }
    const agentIdentity = buildAgentIdentityMap(initialAgent);
    const serializedProcessedResponse = serializeProcessedResponse(state._lastProcessedResponse, agentIdentity.byAgent);
    const executionFunctionToolsByCallId = new Map(state._lastProcessedResponse.functions.flatMap((functionCall) => functionCall.preserveToolOnExecutionRehydration
        ? [[functionCall.toolCall.callId, functionCall.tool]]
        : []));
    state._lastProcessedResponse = await deserializeProcessedResponse(agentIdentity.byIdentity, state, serializedProcessedResponse, {
        executionTools,
        executionFunctionToolsByCallId,
        allowSerializedExecutionToolPlaceholder: false,
    });
}
/**
 * @internal
 */
export function buildAgentMap(initialAgent) {
    const map = new Map();
    const visitedAgents = new Set();
    const queue = [initialAgent];
    while (queue.length > 0) {
        const currentAgent = queue.shift();
        if (visitedAgents.has(currentAgent)) {
            continue;
        }
        visitedAgents.add(currentAgent);
        const existingAgent = map.get(currentAgent.name);
        if (existingAgent && existingAgent !== currentAgent) {
            throw new UserError(`Duplicate agent name "${currentAgent.name}" detected. Use unique agent names when serializing RunState.`);
        }
        map.set(currentAgent.name, currentAgent);
        for (const handoff of currentAgent.handoffs) {
            if (handoff instanceof Agent) {
                queue.push(handoff);
            }
            else if (handoff.agent) {
                queue.push(handoff.agent);
            }
        }
        for (const tool of currentAgent.tools) {
            const sourceAgent = getAgentToolSourceAgent(tool);
            if (sourceAgent) {
                queue.push(sourceAgent);
            }
        }
    }
    return map;
}
function serializeAgentReference(agent, agentIdentityKeys) {
    const identity = agentIdentityKeys.get(agent);
    if (!identity || identity === agent.name) {
        return { name: agent.name };
    }
    return { name: agent.name, identity };
}
function resolveSerializedAgent(serializedAgent, agentMap, fallbackAgent) {
    const identity = serializedAgent.identity ?? serializedAgent.name;
    const agent = agentMap.get(identity);
    if (agent) {
        return agent;
    }
    if (!serializedAgent.identity && fallbackAgent) {
        return fallbackAgent;
    }
    if (serializedAgent.identity) {
        throw new UserError(`Agent identity ${serializedAgent.identity} not found`);
    }
    throw new UserError(`Agent ${serializedAgent.name} not found`);
}
function serializeRunItem(item, agentIdentityKeys) {
    const serialized = item.toJSON();
    if (item instanceof RunToolCallOutputItem) {
        const normalizedOutput = jsonCompatibleValueSchema.safeParse(item.output);
        if (normalizedOutput.success) {
            serialized.output = normalizedOutput.data;
        }
    }
    switch (item.type) {
        case 'handoff_output_item':
            serialized.sourceAgent = serializeAgentReference(item.sourceAgent, agentIdentityKeys);
            serialized.targetAgent = serializeAgentReference(item.targetAgent, agentIdentityKeys);
            return serialized;
        default:
            serialized.agent = serializeAgentReference(item.agent, agentIdentityKeys);
            return serialized;
    }
}
function serializeCurrentStep(currentStep, agentIdentityKeys) {
    if (!currentStep) {
        return undefined;
    }
    if (currentStep.type === 'next_step_handoff') {
        return {
            ...currentStep,
            newAgent: serializeAgentReference(currentStep.newAgent, agentIdentityKeys),
        };
    }
    if (currentStep.type === 'next_step_interruption') {
        const interruptions = Array.isArray(currentStep.data?.interruptions)
            ? currentStep.data.interruptions.map((item) => item instanceof RunToolApprovalItem
                ? serializeRunItem(item, agentIdentityKeys)
                : item)
            : currentStep.data?.interruptions;
        return {
            ...currentStep,
            data: {
                ...currentStep.data,
                interruptions,
            },
        };
    }
    return currentStep;
}
function serializeProcessedResponse(processedResponse, agentIdentityKeys) {
    return {
        ...processedResponse,
        newItems: processedResponse.newItems.map((item) => serializeRunItem(item, agentIdentityKeys)),
        mcpApprovalRequests: processedResponse.mcpApprovalRequests.map(({ requestItem, mcpTool }) => ({
            requestItem: { rawItem: requestItem.rawItem },
            // Resume resolves the live tool from current agent configuration.
            mcpTool: {
                type: mcpTool.type,
                name: mcpTool.name,
                providerData: {
                    type: 'mcp',
                    server_label: mcpTool.providerData.server_label,
                },
            },
        })),
        functions: processedResponse.functions.map(({ toolCall, tool, mcpToolBinding }) => ({
            toolCall,
            tool,
            mcpToolBinding: mcpToolBinding === undefined
                ? getMcpToolBinding(tool)
                : mcpToolBinding,
        })),
        handoffs: processedResponse.handoffs.map(({ toolCall, handoff: processedHandoff }) => ({
            toolCall,
            handoff: processedHandoff,
            targetAgent: serializeAgentReference(processedHandoff.agent, agentIdentityKeys),
        })),
    };
}
/**
 * @internal
 */
export function deserializeSpan(trace, serializedSpan) {
    const spanData = serializedSpan.span_data;
    const previousSpan = serializedSpan.previous_span
        ? deserializeSpan(trace, serializedSpan.previous_span)
        : undefined;
    const span = getGlobalTraceProvider().createSpan({
        spanId: serializedSpan.id,
        traceId: serializedSpan.trace_id,
        parentId: serializedSpan.parent_id ?? undefined,
        startedAt: serializedSpan.started_at ?? undefined,
        endedAt: serializedSpan.ended_at ?? undefined,
        data: spanData,
    }, trace);
    span.previousSpan = previousSpan;
    return span;
}
/**
 * @internal
 */
export function deserializeModelResponse(serializedModelResponse) {
    const usage = new Usage(serializedModelResponse.usage);
    return {
        usage,
        output: serializedModelResponse.output.map((item) => protocol.OutputModelItem.parse(item)),
        responseId: serializedModelResponse.responseId,
        requestId: serializedModelResponse.requestId,
        providerData: serializedModelResponse.providerData,
    };
}
/**
 * @internal
 */
export function deserializeItem(serializedItem, agentMap) {
    switch (serializedItem.type) {
        case 'input_item':
            return new RunInputItem(serializedItem.rawItem, resolveSerializedAgent(serializedItem.agent, agentMap), serializedItem.inputId);
        case 'message_output_item':
            return new RunMessageOutputItem(serializedItem.rawItem, resolveSerializedAgent(serializedItem.agent, agentMap));
        case 'tool_search_call_item':
            return new RunToolSearchCallItem(serializedItem.rawItem, resolveSerializedAgent(serializedItem.agent, agentMap));
        case 'tool_search_output_item':
            return new RunToolSearchOutputItem(serializedItem.rawItem, resolveSerializedAgent(serializedItem.agent, agentMap));
        case 'tool_call_item':
            return new RunToolCallItem(serializedItem.rawItem, resolveSerializedAgent(serializedItem.agent, agentMap), serializedItem.functionToolStateKey);
        case 'tool_call_output_item':
            return new RunToolCallOutputItem(serializedItem.rawItem, resolveSerializedAgent(serializedItem.agent, agentMap), serializedItem.output, serializedItem.customData, serializedItem.executionStatus);
        case 'reasoning_item':
            return new RunReasoningItem(serializedItem.rawItem, resolveSerializedAgent(serializedItem.agent, agentMap));
        case 'compaction_item':
            return new RunCompactionItem(serializedItem.rawItem, resolveSerializedAgent(serializedItem.agent, agentMap));
        case 'handoff_call_item':
            return new RunHandoffCallItem(serializedItem.rawItem, resolveSerializedAgent(serializedItem.agent, agentMap));
        case 'handoff_output_item':
            return new RunHandoffOutputItem(serializedItem.rawItem, resolveSerializedAgent(serializedItem.sourceAgent, agentMap), resolveSerializedAgent(serializedItem.targetAgent, agentMap));
        case 'tool_approval_item':
            return new RunToolApprovalItem(serializedItem.rawItem, resolveSerializedAgent(serializedItem.agent, agentMap), serializedItem.toolName, serializedItem.functionToolStateKey);
    }
}
function deserializeInterruptionItem(serializedItem, agentMap, currentAgent) {
    if (serializedItem instanceof RunToolApprovalItem) {
        return serializedItem;
    }
    const parsed = itemSchema.safeParse(serializedItem);
    if (parsed.success) {
        if (parsed.data.type === 'tool_approval_item') {
            const mappedAgent = resolveSerializedAgent(parsed.data.agent, agentMap, currentAgent);
            return new RunToolApprovalItem(parsed.data.rawItem, mappedAgent, parsed.data.toolName, parsed.data.functionToolStateKey);
        }
        const item = deserializeItem(parsed.data, agentMap);
        return item instanceof RunToolApprovalItem ? item : undefined;
    }
    if (!serializedItem || typeof serializedItem !== 'object') {
        return undefined;
    }
    const value = serializedItem;
    if (!value.rawItem || typeof value.rawItem !== 'object') {
        return undefined;
    }
    const rawItem = value.rawItem;
    if (rawItem.type !== 'function_call' &&
        rawItem.type !== 'hosted_tool_call' &&
        rawItem.type !== 'computer_call' &&
        rawItem.type !== 'shell_call' &&
        rawItem.type !== 'apply_patch_call') {
        return undefined;
    }
    const agentName = value.agent && typeof value.agent.name === 'string'
        ? value.agent.name
        : undefined;
    const agentIdentity = value.agent && typeof value.agent.identity === 'string'
        ? value.agent.identity
        : undefined;
    const mappedAgent = agentName || agentIdentity
        ? resolveSerializedAgent({
            name: agentName ?? currentAgent.name,
            identity: agentIdentity,
        }, agentMap, currentAgent)
        : currentAgent;
    const toolName = typeof value.toolName === 'string'
        ? value.toolName
        : typeof rawItem.name === 'string'
            ? rawItem.name
            : undefined;
    const functionToolStateKey = typeof value.functionToolStateKey === 'string'
        ? value.functionToolStateKey
        : undefined;
    return new RunToolApprovalItem(value.rawItem, mappedAgent, toolName, functionToolStateKey);
}
function deserializeInterruptions(serializedInterruptions, agentMap, currentAgent) {
    if (!Array.isArray(serializedInterruptions)) {
        return [];
    }
    return serializedInterruptions
        .map((item) => deserializeInterruptionItem(item, agentMap, currentAgent))
        .filter((item) => item instanceof RunToolApprovalItem);
}
function restoreLegacyHostedMcpApprovalsForPendingRequests(context, legacyApprovals, approvalItems, restoreStickyDecisions) {
    const pendingByTool = new Map();
    const stickyClaimantsByTool = new Map();
    for (const [index, approvalItem] of approvalItems.entries()) {
        const identity = getHostedMcpApprovalRequestIdentity(approvalItem);
        const requestKey = identity
            ? getHostedMcpApprovalRequestKey(identity)
            : undefined;
        const rawItem = approvalItem.rawItem;
        const providerData = rawItem.providerData;
        const toolName = identity?.toolName ?? approvalItem.name;
        const requestId = identity?.requestId ??
            (typeof rawItem.callId === 'string'
                ? rawItem.callId
                : typeof rawItem.id === 'string'
                    ? rawItem.id
                    : typeof providerData?.itemId === 'string'
                        ? providerData.itemId
                        : typeof providerData?.id === 'string'
                            ? providerData.id
                            : undefined);
        if (!toolName) {
            continue;
        }
        const claimantKey = requestKey ?? JSON.stringify(['legacy_pending_claim', index]);
        const stickyClaimants = stickyClaimantsByTool.get(toolName) ?? new Map();
        stickyClaimants.set(claimantKey, requestKey ? approvalItem : undefined);
        stickyClaimantsByTool.set(toolName, stickyClaimants);
        if (!requestId) {
            continue;
        }
        const pendingByRequestId = pendingByTool.get(toolName) ?? new Map();
        const claimants = pendingByRequestId.get(requestId) ?? new Map();
        claimants.set(claimantKey, requestKey ? approvalItem : undefined);
        pendingByRequestId.set(requestId, claimants);
        pendingByTool.set(toolName, pendingByRequestId);
    }
    for (const [toolName, pendingByRequestId] of pendingByTool) {
        const legacy = legacyApprovals[toolName];
        if (!legacy) {
            continue;
        }
        const hasStickyDecision = restoreStickyDecisions &&
            (legacy.approved === true || legacy.rejected === true);
        if (hasStickyDecision) {
            const claimants = stickyClaimantsByTool.get(toolName) ?? new Map();
            if (claimants.size === 1) {
                const approvalItem = claimants.values().next().value;
                const requestId = approvalItem
                    ? getHostedMcpApprovalRequestIdentity(approvalItem)?.requestId
                    : undefined;
                if (approvalItem && requestId) {
                    restoreLegacyHostedMcpApprovalDecision(context, approvalItem, legacy, requestId, true);
                }
            }
            continue;
        }
        for (const [requestId, claimants] of pendingByRequestId) {
            if (claimants.size !== 1) {
                continue;
            }
            const approvalItem = claimants.values().next().value;
            if (approvalItem) {
                restoreLegacyHostedMcpApprovalDecision(context, approvalItem, legacy, requestId, false);
            }
        }
    }
}
function restoreLegacyHostedMcpApprovalDecision(context, approvalItem, legacy, requestId, restoreStickyDecisions) {
    const decision = resolveLegacyHostedMcpApproval(legacy, requestId, restoreStickyDecisions);
    if (decision === true) {
        context.approveTool(approvalItem);
    }
    else if (decision === false) {
        context.rejectTool(approvalItem, {
            message: legacy.messages?.[requestId] ??
                (restoreStickyDecisions && legacy.rejected === true
                    ? legacy.stickyRejectMessage
                    : undefined),
        });
    }
}
function resolveLegacyHostedMcpApproval(legacy, requestId, restoreStickyDecisions) {
    const stickyApproval = restoreStickyDecisions && legacy.approved === true;
    const stickyRejection = restoreStickyDecisions && legacy.rejected === true;
    if (stickyApproval || stickyRejection) {
        return stickyApproval;
    }
    const exactApproval = Array.isArray(legacy.approved) && legacy.approved.includes(requestId);
    const exactRejection = Array.isArray(legacy.rejected) && legacy.rejected.includes(requestId);
    if (exactApproval || exactRejection) {
        return exactApproval;
    }
    return undefined;
}
function rebindInterruptionFunctionToolStateKeys(interruptions, processedResponse, processedAgent, state, schemaVersion) {
    if (!processedResponse) {
        for (const interruption of interruptions) {
            if (interruption.rawItem.type !== 'function_call' ||
                !interruption.functionToolStateKey) {
                continue;
            }
            const rawStateKey = getFunctionToolStateKeyForCall(interruption.rawItem);
            if (rawStateKey && interruption.functionToolStateKey !== rawStateKey) {
                throwAmbiguousFunctionCallId(interruption.agent, interruption.rawItem.callId, [rawStateKey, interruption.functionToolStateKey]);
            }
        }
        return;
    }
    const functionsByCallId = new Map(processedResponse.functions.map((functionCall) => [
        functionCall.toolCall.callId,
        functionCall,
    ]));
    for (const interruption of interruptions) {
        if (interruption.rawItem.type !== 'function_call') {
            continue;
        }
        let stateKey;
        if (interruption.agent === processedAgent) {
            stateKey = getFunctionToolStateKey(functionsByCallId.get(interruption.rawItem.callId)?.tool);
        }
        else {
            stateKey = findNestedInterruptionFunctionToolStateKey(state, interruption);
            if (schemaVersionSupportsV116State(schemaVersion)) {
                const rawStateKey = getFunctionToolStateKeyForCall(interruption.rawItem);
                const serializedStateKey = interruption.functionToolStateKey;
                const expectedStateKey = stateKey ?? rawStateKey;
                if (serializedStateKey &&
                    expectedStateKey &&
                    serializedStateKey !== expectedStateKey) {
                    throwAmbiguousFunctionCallId(interruption.agent, interruption.rawItem.callId, [expectedStateKey, serializedStateKey]);
                }
            }
        }
        if (stateKey) {
            interruption.functionToolStateKey = stateKey;
        }
    }
}
function findNestedInterruptionFunctionToolStateKey(state, interruption) {
    if (interruption.rawItem.type !== 'function_call') {
        return undefined;
    }
    const serializedPendingStates = new Set();
    for (const functionCall of state._lastProcessedResponse?.functions ?? []) {
        if (getAgentToolSourceAgent(functionCall.tool) !== interruption.agent) {
            continue;
        }
        const stateKeys = getFunctionToolStateKeys(functionCall.tool, functionCall.availableFunctionTools ?? [functionCall.tool]);
        for (const stateKey of stateKeys) {
            const serializedState = state.getPendingAgentToolRun(stateKey, functionCall.toolCall.callId);
            if (serializedState) {
                serializedPendingStates.add(serializedState);
            }
        }
    }
    const resolvedStateKeys = new Set();
    for (const serializedState of serializedPendingStates) {
        const resolvedStateKey = getSerializedNestedInterruptionFunctionToolStateKey(serializedState, interruption.rawItem);
        if (resolvedStateKey) {
            resolvedStateKeys.add(resolvedStateKey);
        }
    }
    if (resolvedStateKeys.size > 1) {
        throwAmbiguousFunctionCallId(interruption.agent, interruption.rawItem.callId, [...resolvedStateKeys]);
    }
    return resolvedStateKeys.values().next().value;
}
function getSerializedNestedInterruptionFunctionToolStateKey(serializedState, interruptionRawItem) {
    let nestedState;
    try {
        nestedState = JSON.parse(serializedState);
    }
    catch {
        return undefined;
    }
    if (!nestedState || typeof nestedState !== 'object') {
        return undefined;
    }
    const candidate = nestedState;
    if (candidate.currentStep?.type !== 'next_step_interruption' ||
        !Array.isArray(candidate.currentStep.data?.interruptions) ||
        !candidate.currentStep.data.interruptions.some((value) => {
            if (!value || typeof value !== 'object') {
                return false;
            }
            const rawItem = value.rawItem;
            return (rawItem != null &&
                typeof rawItem === 'object' &&
                rawItem.type === 'function_call' &&
                rawItem.callId ===
                    interruptionRawItem.callId &&
                getFunctionToolStateKeyForCall(rawItem) ===
                    getFunctionToolStateKeyForCall(interruptionRawItem));
        }) ||
        !Array.isArray(candidate.lastProcessedResponse?.functions)) {
        return undefined;
    }
    const stateKeys = new Set();
    for (const value of candidate.lastProcessedResponse.functions) {
        if (!value || typeof value !== 'object') {
            continue;
        }
        const functionCall = value;
        if (!functionCall.toolCall ||
            typeof functionCall.toolCall !== 'object' ||
            functionCall.toolCall.callId !==
                interruptionRawItem.callId) {
            continue;
        }
        const stateKey = getFunctionToolStateKey(functionCall.tool);
        if (stateKey &&
            getFunctionToolStateKeyForResolvedCall(interruptionRawItem, functionCall.tool, stateKey) === stateKey) {
            stateKeys.add(stateKey);
        }
    }
    if (stateKeys.size !== 1) {
        return undefined;
    }
    return stateKeys.values().next().value;
}
function restorePendingAgentToolRunAliases(state, serializedAliases) {
    const aliasEntries = Object.entries(serializedAliases);
    if (aliasEntries.length === 0) {
        return;
    }
    const validAliases = new Map();
    for (const functionCall of state._lastProcessedResponse?.functions ?? []) {
        const [canonicalToolName, ...aliases] = getFunctionToolStateKeys(functionCall.tool, functionCall.availableFunctionTools ?? [functionCall.tool]);
        if (!canonicalToolName) {
            continue;
        }
        const callId = functionCall.toolCall.callId;
        const canonicalKey = `${canonicalToolName}:${callId}`;
        for (const alias of aliases) {
            validAliases.set(`${alias}:${callId}`, canonicalKey);
        }
    }
    for (const [aliasKey, canonicalKey] of aliasEntries) {
        if (validAliases.get(aliasKey) !== canonicalKey ||
            !state._pendingAgentToolRuns.has(canonicalKey)) {
            throw new UserError('Run state pending agent tool aliases do not match the reconstructed pending function calls.');
        }
    }
    state._pendingAgentToolRunAliases = new Map(aliasEntries);
}
function migrateLegacyFunctionToolState(state, schemaVersion, migrateApprovals, approvalContext = state._context, availableToolsByAgent = new Map()) {
    if (schemaVersionSupportsV116State(schemaVersion)) {
        return new Set();
    }
    const approvalCallsByLegacyKey = new Map();
    const approvalOwnersByLegacyKey = new Map();
    const addApprovalOwner = (legacyKey, agent, canonicalKey) => {
        const ownersByAgent = approvalOwnersByLegacyKey.get(legacyKey) ??
            new Map();
        const ownerKeys = ownersByAgent.get(agent) ?? new Set();
        ownerKeys.add(canonicalKey);
        ownersByAgent.set(agent, ownerKeys);
        approvalOwnersByLegacyKey.set(legacyKey, ownersByAgent);
    };
    const addApprovalCall = (legacyKey, agent, canonicalKey, callId) => {
        addApprovalOwner(legacyKey, agent, canonicalKey);
        const callsByAgent = approvalCallsByLegacyKey.get(legacyKey) ??
            new Map();
        const callsByCanonicalKey = callsByAgent.get(agent) ?? new Map();
        const callIds = callsByCanonicalKey.get(canonicalKey) ?? new Set();
        callIds.add(callId);
        callsByCanonicalKey.set(canonicalKey, callIds);
        callsByAgent.set(agent, callsByCanonicalKey);
        approvalCallsByLegacyKey.set(legacyKey, callsByAgent);
    };
    for (const [agent, availableTools] of availableToolsByAgent) {
        for (const tool of availableTools) {
            if (tool.type !== 'function') {
                continue;
            }
            const canonicalKey = getFunctionToolStateKey(tool);
            const legacyKey = getFunctionToolQualifiedName(tool) ?? tool.name;
            if (!canonicalKey || canonicalKey === legacyKey) {
                continue;
            }
            addApprovalOwner(legacyKey, agent, canonicalKey);
        }
    }
    for (const functionCall of state._lastProcessedResponse?.functions ?? []) {
        const canonicalKey = getFunctionToolStateKey(functionCall.tool);
        const legacyKey = getFunctionToolQualifiedName(functionCall.tool) ?? functionCall.tool.name;
        if (!canonicalKey || canonicalKey === legacyKey) {
            continue;
        }
        const callId = functionCall.toolCall.callId;
        const pendingState = state.getPendingAgentToolRun(legacyKey, callId);
        if (pendingState !== undefined) {
            state.setPendingAgentToolRun(canonicalKey, callId, pendingState, [
                legacyKey,
            ]);
        }
        if (!migrateApprovals) {
            continue;
        }
        addApprovalCall(legacyKey, state._currentAgent, canonicalKey, callId);
    }
    if (state._currentStep?.type === 'next_step_interruption') {
        for (const interruption of state._currentStep.data.interruptions) {
            if (interruption.rawItem.type !== 'function_call' ||
                !interruption.functionToolStateKey) {
                continue;
            }
            const legacyKey = getFunctionToolLegacyStateKeyFromStateKey(interruption.functionToolStateKey);
            if (!legacyKey) {
                continue;
            }
            addApprovalCall(legacyKey, interruption.agent, interruption.functionToolStateKey, interruption.rawItem.callId);
        }
    }
    if (migrateApprovals) {
        for (const [legacyKey, ownersByAgent] of approvalOwnersByLegacyKey) {
            const ownerEntries = [...ownersByAgent].flatMap(([agent, canonicalKeys]) => [...canonicalKeys].map((canonicalKey) => ({ agent, canonicalKey })));
            if (ownerEntries.length !== 1) {
                continue;
            }
            const [{ agent, canonicalKey }] = ownerEntries;
            approvalContext._migrateToolApproval(agent, legacyKey, canonicalKey, [], true);
        }
    }
    for (const [legacyKey, callsByAgent] of approvalCallsByLegacyKey) {
        const callOwners = new Map();
        for (const callsByCanonicalKey of callsByAgent.values()) {
            for (const callIds of callsByCanonicalKey.values()) {
                for (const callId of callIds) {
                    callOwners.set(callId, (callOwners.get(callId) ?? 0) + 1);
                }
            }
        }
        for (const [agent, callsByCanonicalKey] of callsByAgent) {
            for (const [canonicalKey, callIds] of callsByCanonicalKey) {
                for (const callId of callIds) {
                    const remainingOwners = (callOwners.get(callId) ?? 1) - 1;
                    callOwners.set(callId, remainingOwners);
                    approvalContext._migrateToolApproval(agent, legacyKey, canonicalKey, [callId], false, remainingOwners > 0);
                }
            }
        }
    }
    return new Set(approvalOwnersByLegacyKey.keys());
}
/**
 * @internal
 */
function unresolvedFunctionTool(call, serialized) {
    const name = serialized.name ?? call.name;
    // This placeholder preserves history/rejection identity and can never execute.
    return {
        type: 'function',
        name,
        description: '',
        parameters: {
            type: 'object',
            properties: {},
            required: [],
            additionalProperties: false,
        },
        strict: true,
        deferLoading: serialized.deferLoading,
        ...(call.namespace && call.namespace !== name
            ? { [FUNCTION_TOOL_NAMESPACE]: call.namespace }
            : {}),
        needsApproval: async () => true,
        isEnabled: async () => false,
        invoke: async () => {
            throw new UserError('Original function tool is unavailable; restore its configuration or start a new run.');
        },
    };
}
async function deserializeProcessedResponse(agentMap, state, serializedProcessedResponse, options = {}) {
    const currentAgent = state._currentAgent;
    const allTools = options.executionTools
        ? options.executionTools
        : [
            ...(await currentAgent.getAllTools(state._context)),
            ...(await getEnabledToolSearchRuntimeTools(state, currentAgent)),
        ];
    const baseAgentTools = currentAgent.tools;
    const allowSerializedExecutionToolPlaceholder = options.allowSerializedExecutionToolPlaceholder ?? true;
    const tools = buildFunctionToolLookupMap(allTools.filter((tool) => tool.type === 'function'));
    const computerTools = new Map(allTools
        .filter((tool) => tool.type === 'computer')
        .map((tool) => [tool.name, tool]));
    const resolveComputerTool = (toolName) => {
        const exactMatch = computerTools.get(toolName);
        if (exactMatch) {
            return exactMatch;
        }
        if (toolName === 'computer') {
            return computerTools.get('computer_use_preview');
        }
        if (toolName === 'computer_use_preview') {
            return computerTools.get('computer');
        }
        return undefined;
    };
    const shellTools = new Map(allTools
        .filter((tool) => tool.type === 'shell')
        .map((tool) => [tool.name, tool]));
    const applyPatchTools = new Map(allTools
        .filter((tool) => tool.type === 'apply_patch')
        .map((tool) => [tool.name, tool]));
    const mcpTools = new Map(allTools
        .filter((tool) => tool.type === 'hosted_tool' &&
        tool.name === 'hosted_mcp' &&
        tool.providerData?.type === 'mcp')
        .map((tool) => [tool.providerData.server_label, tool]));
    const enabledHandoffs = options.executionHandoffs
        ? options.executionHandoffs
        : await currentAgent.getEnabledHandoffs(state._context);
    const handoffs = new Map(enabledHandoffs.map((entry) => [entry.toolName, entry]));
    const result = {
        newItems: serializedProcessedResponse.newItems.map((item) => deserializeItem(item, agentMap)),
        toolsUsed: serializedProcessedResponse.toolsUsed,
        handoffs: serializedProcessedResponse.handoffs.map((serializedHandoff) => {
            const toolName = serializedHandoff.handoff.toolName;
            const resolvedHandoff = handoffs.get(toolName);
            const serializedTargetAgent = serializedHandoff.targetAgent
                ? resolveSerializedAgent(serializedHandoff.targetAgent, agentMap)
                : undefined;
            const targetMatches = serializedTargetAgent
                ? resolvedHandoff?.agent === serializedTargetAgent
                : resolvedHandoff?.agentName === serializedHandoff.handoff.agentName;
            if (!resolvedHandoff || !targetMatches) {
                throw new UserError(`Handoff ${toolName} not found`);
            }
            ensureToolCallerAllowed(serializedHandoff.toolCall, undefined, resolvedHandoff.toolName, currentAgent);
            return {
                toolCall: serializedHandoff.toolCall,
                handoff: resolvedHandoff,
            };
        }),
        functions: await Promise.all(serializedProcessedResponse.functions.map(async (functionCall) => {
            const toolIdentity = getToolCallDisplayName(functionCall.toolCall) ??
                functionCall.tool.name;
            const exactRuntimeTool = options.executionFunctionToolsByCallId?.get(functionCall.toolCall.callId);
            if (exactRuntimeTool &&
                !getFunctionToolStateKeyForResolvedCall(functionCall.toolCall, exactRuntimeTool)) {
                throwAmbiguousFunctionCallId(currentAgent, functionCall.toolCall.callId, [
                    getFunctionToolStateKey(exactRuntimeTool) ??
                        exactRuntimeTool.name,
                    getFunctionToolStateKeyForCall(functionCall.toolCall) ?? functionCall.tool.name,
                ]);
            }
            // Missing provenance must survive every rewrite, including sandbox rebinding.
            const mcpToolBinding = functionCall.mcpToolBinding === undefined
                ? 'unknown'
                : functionCall.mcpToolBinding;
            const resolvedTool = exactRuntimeTool ??
                resolveFunctionToolCall(functionCall.toolCall, tools) ??
                getSerializedFunctionToolPlaceholder({
                    agent: currentAgent,
                    baseAgentTools,
                    serializedTool: functionCall.tool,
                    toolCall: functionCall.toolCall,
                    toolIdentity,
                    allowSerializedExecutionToolPlaceholder,
                }) ??
                (mcpToolBinding !== null ||
                    state._completedToolInvocations
                        .get(currentAgent)
                        ?.has(functionCall.toolCall.callId)
                    ? unresolvedFunctionTool(functionCall.toolCall, functionCall.tool)
                    : undefined);
            if (!resolvedTool) {
                throw new UserError(`Tool ${toolIdentity} not found`);
            }
            ensureToolCallerAllowed(functionCall.toolCall, resolvedTool.allowedCallers, getFunctionToolQualifiedName(resolvedTool) ?? resolvedTool.name, currentAgent);
            return createToolRunFunction({
                toolCall: functionCall.toolCall,
                tool: resolvedTool,
                availableFunctionTools: [
                    ...new Set([...tools.values(), resolvedTool]),
                ],
                preserveToolOnExecutionRehydration: Boolean(exactRuntimeTool),
                mcpToolBinding,
            });
        })),
        functionToolsNotFound: serializedProcessedResponse.functionToolsNotFound ?? [],
        computerActions: serializedProcessedResponse.computerActions.map((computerAction) => {
            const toolName = computerAction.computer.name;
            const computerTool = resolveComputerTool(toolName) ??
                getSerializedComputerToolPlaceholder({
                    agent: currentAgent,
                    baseAgentTools,
                    serializedTool: computerAction.computer,
                    toolName,
                    allowSerializedExecutionToolPlaceholder,
                });
            if (!computerTool) {
                throw new UserError(`Computer tool ${toolName} not found`);
            }
            return {
                toolCall: computerAction.toolCall,
                computer: computerTool,
            };
        }),
        shellActions: (serializedProcessedResponse.shellActions ?? []).map((shellAction) => {
            const toolName = shellAction.shell.name;
            const shellTool = shellTools.get(toolName) ??
                getSerializedShellToolPlaceholder({
                    agent: currentAgent,
                    baseAgentTools,
                    serializedTool: shellAction.shell,
                    toolName,
                    allowSerializedExecutionToolPlaceholder,
                });
            if (!shellTool) {
                throw new UserError(`Shell tool ${toolName} not found`);
            }
            ensureToolCallerAllowed(shellAction.toolCall, shellTool.allowedCallers, shellTool.name, currentAgent);
            return {
                toolCall: shellAction.toolCall,
                shell: shellTool,
            };
        }),
        applyPatchActions: (serializedProcessedResponse.applyPatchActions ?? []).map((applyPatchAction) => {
            const toolName = applyPatchAction.applyPatch.name;
            const applyPatchTool = applyPatchTools.get(toolName) ??
                getSerializedApplyPatchToolPlaceholder({
                    agent: currentAgent,
                    baseAgentTools,
                    serializedTool: applyPatchAction.applyPatch,
                    toolName,
                    allowSerializedExecutionToolPlaceholder,
                });
            if (!applyPatchTool) {
                throw new UserError(`Apply patch tool ${toolName} not found`);
            }
            ensureToolCallerAllowed(applyPatchAction.toolCall, applyPatchTool.allowedCallers, applyPatchTool.name, currentAgent);
            return {
                toolCall: applyPatchAction.toolCall,
                applyPatch: applyPatchTool,
            };
        }),
        mcpApprovalRequests: (serializedProcessedResponse.mcpApprovalRequests ?? []).map((approvalRequest) => {
            const rawItem = approvalRequest.requestItem
                .rawItem;
            const rawServerLabel = rawItem.providerData?.server_label;
            const serializedServerLabel = approvalRequest.mcpTool.providerData.server_label;
            const serverLabel = typeof rawServerLabel === 'string'
                ? rawServerLabel
                : typeof serializedServerLabel === 'string'
                    ? serializedServerLabel
                    : undefined;
            if (!serverLabel) {
                throw new UserError('MCP approval request is missing a server label');
            }
            const mcpTool = mcpTools.get(serverLabel);
            if (!mcpTool) {
                throw new UserError(`MCP tool ${serverLabel} not found`);
            }
            ensureToolCallerAllowed(rawItem, mcpTool.providerData.allowed_callers, serverLabel, currentAgent);
            return {
                requestItem: new RunToolApprovalItem(rawItem, currentAgent),
                mcpTool,
            };
        }),
    };
    return {
        ...result,
        hasToolsOrApprovalsToRun() {
            return (result.handoffs.length > 0 ||
                result.functions.length > 0 ||
                result.functionToolsNotFound.length > 0 ||
                result.mcpApprovalRequests.length > 0 ||
                result.computerActions.length > 0 ||
                result.shellActions.length > 0 ||
                result.applyPatchActions.length > 0);
        },
    };
}
async function getEnabledToolSearchRuntimeTools(state, agent) {
    return filterEnabledToolSearchRuntimeTools({
        runtimeTools: state.getToolSearchRuntimeTools(agent),
        runContext: state._context,
        agent,
    });
}
//# sourceMappingURL=runState.mjs.map