UNPKG

@openai/agents-core

Version:

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

354 lines • 12.7 kB
import { UserError } from "./errors.mjs"; import { toolDisplayName, toolQualifiedName } from "./tooling.mjs"; export { toolDisplayName, toolQualifiedName } from "./tooling.mjs"; // Key by the invocation function so supported namespace/preparation copies retain identity. const mcpToolBindings = new WeakMap(); /** @internal */ export function bindMcpTool(tool, binding) { mcpToolBindings.set(tool.invoke, Object.freeze({ ...binding })); return tool; } /** @internal */ export function getMcpToolBinding(tool) { return mcpToolBindings.get(tool.invoke) ?? null; } /** @internal */ export function matchesFunctionToolRecipient(original, tool) { const current = getMcpToolBinding(tool); if (original === 'unknown') return false; if (original === null || current === null) return original === current; return (original.serverName === current.serverName && original.toolName === current.toolName && original.serverIndex === current.serverIndex); } export const FUNCTION_TOOL_NAMESPACE = Symbol('functionToolNamespace'); export const FUNCTION_TOOL_NAMESPACE_DESCRIPTION = Symbol('functionToolNamespaceDescription'); function isNonEmptyString(value) { return typeof value === 'string' && value.length > 0; } /** @internal */ export function getHostedMcpApprovalRequestIdentity(value) { const candidate = value; const rawItem = candidate?.rawItem && typeof candidate.rawItem === 'object' ? candidate.rawItem : candidate; if (rawItem?.type !== 'hosted_tool_call') { return undefined; } const providerData = rawItem.providerData; if (!providerData) { return undefined; } if (providerData.type !== undefined && providerData.type !== 'mcp_approval_request') { return undefined; } if (providerData.type === undefined && !isNonEmptyString(providerData.server_label) && !(isNonEmptyString(providerData.serverLabel) && isNonEmptyString(providerData.itemId))) { return undefined; } return { ...(isNonEmptyString(providerData.id) ? { requestId: providerData.id } : isNonEmptyString(providerData.itemId) ? { requestId: providerData.itemId } : isNonEmptyString(rawItem.id) ? { requestId: rawItem.id } : {}), ...(isNonEmptyString(providerData.server_label) ? { serverLabel: providerData.server_label } : isNonEmptyString(providerData.serverLabel) ? { serverLabel: providerData.serverLabel } : {}), ...(isNonEmptyString(providerData.name) ? { toolName: providerData.name } : isNonEmptyString(rawItem.name) && rawItem.name !== 'mcp_approval_request' ? { toolName: rawItem.name } : {}), }; } /** @internal */ export function getHostedMcpApprovalStateKey(identity) { if (identity.serverLabel && identity.toolName) { return JSON.stringify([ 'hosted_mcp', identity.serverLabel, identity.toolName, ]); } return undefined; } /** @internal */ export function getHostedMcpApprovalRequestKey(identity) { if (identity.serverLabel && identity.toolName && identity.requestId) { return JSON.stringify([ 'hosted_mcp_request', identity.serverLabel, identity.toolName, identity.requestId, ]); } return undefined; } /** @internal */ export function getHostedMcpApprovalIdentityFromStateKey(stateKey) { try { const value = JSON.parse(stateKey); if (Array.isArray(value) && value.length === 3 && value[0] === 'hosted_mcp' && isNonEmptyString(value[1]) && isNonEmptyString(value[2])) { return { serverLabel: value[1], toolName: value[2] }; } } catch { // Non-JSON keys are not hosted MCP approval identities. } return undefined; } function encodeFunctionToolLookupKey(parts) { return JSON.stringify(parts); } export function getToolCallNamespace(toolCall) { return isNonEmptyString(toolCall.namespace) ? toolCall.namespace : undefined; } export function getToolCallName(toolCall) { return isNonEmptyString(toolCall.name) ? toolCall.name : undefined; } export function getToolCallQualifiedName(toolCall) { return toolQualifiedName(getToolCallName(toolCall), getToolCallNamespace(toolCall)); } export function getToolCallDisplayName(toolCall) { return toolDisplayName(getToolCallName(toolCall), getToolCallNamespace(toolCall)); } /** @internal */ export function getFunctionToolLookupKey(name, namespace) { if (!isNonEmptyString(name)) { return undefined; } if (namespace === name) { return encodeFunctionToolLookupKey(['deferred_top_level', name]); } if (isNonEmptyString(namespace)) { return encodeFunctionToolLookupKey(['namespaced', namespace, name]); } return encodeFunctionToolLookupKey(['bare', name]); } /** @internal */ export function getFunctionToolLookupKeyForCall(toolCall) { return getFunctionToolLookupKey(getToolCallName(toolCall), getToolCallNamespace(toolCall)); } /** @internal */ export function isDeferredTopLevelFunctionTool(tool) { const candidate = tool; return (candidate?.deferLoading === true && !getExplicitFunctionToolNamespace(tool) && isNonEmptyString(candidate?.name)); } /** @internal */ export function getBareTopLevelFunctionToolName(tool) { const name = getFunctionToolName(tool); if (!name || getExplicitFunctionToolNamespace(tool) || isDeferredTopLevelFunctionTool(tool)) { return undefined; } return name; } /** @internal */ export function getFunctionToolLookupKeyForTool(tool) { const name = getFunctionToolName(tool); if (isDeferredTopLevelFunctionTool(tool)) { return encodeFunctionToolLookupKey(['deferred_top_level', name]); } return getFunctionToolLookupKey(name, getExplicitFunctionToolNamespace(tool)); } /** @internal */ export function assertFunctionToolLookupConfiguration(tools) { const strictOwners = new Map(); for (const tool of tools) { const name = getFunctionToolName(tool); const namespace = getExplicitFunctionToolNamespace(tool); if (name && namespace === name) { 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.'); } if (!namespace && !isDeferredTopLevelFunctionTool(tool)) { continue; } const key = getFunctionToolLookupKeyForTool(tool); if (!key) { continue; } if (strictOwners.has(key)) { throw new UserError('Ambiguous function tool configuration. Assign unique names within each namespace and for deferred top-level tools.'); } strictOwners.set(key, tool); } } /** @internal */ export function buildFunctionToolLookupMap(tools) { assertFunctionToolLookupConfiguration(tools); const lookup = new Map(); for (const tool of tools) { const key = getFunctionToolLookupKeyForTool(tool); if (key) { lookup.set(key, tool); } } return lookup; } /** @internal */ export function resolveFunctionToolCall(toolCall, availableTools) { const key = getFunctionToolLookupKeyForCall(toolCall); const directMatch = key ? availableTools.get(key) : undefined; if (directMatch || getToolCallNamespace(toolCall)) { return directMatch; } const name = getToolCallName(toolCall); const deferredKey = name ? encodeFunctionToolLookupKey(['deferred_top_level', name]) : undefined; const deferredMatch = deferredKey ? availableTools.get(deferredKey) : undefined; if (deferredMatch || !name) { return deferredMatch; } let flattenedNamespaceMatch; for (const tool of availableTools.values()) { if (!getExplicitFunctionToolNamespace(tool) || getFunctionToolQualifiedName(tool) !== name) { continue; } if (flattenedNamespaceMatch && flattenedNamespaceMatch !== tool) { return undefined; } flattenedNamespaceMatch = tool; } return flattenedNamespaceMatch; } /** @internal */ export function getFunctionToolStateKey(tool) { const name = getFunctionToolName(tool); if (!name) { return undefined; } return getFunctionToolLookupKeyForTool(tool); } /** @internal */ export function getFunctionToolLegacyStateKeyFromStateKey(stateKey) { let parts; try { parts = JSON.parse(stateKey); } catch { return undefined; } if (!Array.isArray(parts)) { return undefined; } if ((parts[0] === 'bare' || parts[0] === 'deferred_top_level') && parts.length === 2 && isNonEmptyString(parts[1])) { return parts[1]; } if (parts[0] === 'namespaced' && parts.length === 3 && isNonEmptyString(parts[1]) && isNonEmptyString(parts[2])) { return toolQualifiedName(parts[2], parts[1]); } return undefined; } /** @internal */ export function getFunctionToolStateKeyForCall(toolCall, fallbackName) { const name = getToolCallName(toolCall); const namespace = getToolCallNamespace(toolCall); return (getFunctionToolLookupKey(name ?? fallbackName, namespace) ?? fallbackName); } /** @internal */ export function getFunctionToolStateKeyForResolvedCall(toolCall, tool, resolvedToolStateKey = getFunctionToolStateKey(tool)) { const callStateKey = getFunctionToolStateKeyForCall(toolCall); if (!callStateKey || !resolvedToolStateKey) { return undefined; } if (callStateKey === resolvedToolStateKey) { return resolvedToolStateKey; } return !getToolCallNamespace(toolCall) && isDeferredTopLevelFunctionTool(tool) && getToolCallName(toolCall) === getFunctionToolName(tool) ? resolvedToolStateKey : undefined; } /** @internal */ export function getFunctionToolStateKeys(tool, availableTools = []) { const primary = getFunctionToolStateKey(tool); if (!primary) { return []; } const name = getFunctionToolName(tool); if (!name) { return [primary]; } const legacyKey = getFunctionToolLegacyStateKey(tool); if (!legacyKey || legacyKey === primary) { return [primary]; } const hasLegacyCollision = availableTools.some((candidate) => candidate !== tool && getFunctionToolLegacyStateKey(candidate) === legacyKey && getFunctionToolStateKey(candidate) !== primary); return hasLegacyCollision ? [primary] : [primary, legacyKey]; } function getFunctionToolLegacyStateKey(tool) { const name = getFunctionToolName(tool); if (!name) { return undefined; } const namespace = getExplicitFunctionToolNamespace(tool); return namespace ? toolQualifiedName(name, namespace) : name; } export function getExplicitFunctionToolNamespace(tool) { const candidate = tool; return isNonEmptyString(candidate?.[FUNCTION_TOOL_NAMESPACE]) ? candidate[FUNCTION_TOOL_NAMESPACE] : undefined; } export function getFunctionToolNamespace(tool) { return getExplicitFunctionToolNamespace(tool); } export function getFunctionToolNamespaceDescription(tool) { const candidate = tool; return isNonEmptyString(candidate?.[FUNCTION_TOOL_NAMESPACE_DESCRIPTION]) ? candidate[FUNCTION_TOOL_NAMESPACE_DESCRIPTION] : undefined; } export function getFunctionToolQualifiedName(tool) { const candidate = tool; return toolQualifiedName(isNonEmptyString(candidate?.name) ? candidate.name : undefined, getFunctionToolNamespace(tool)); } export function getFunctionToolDisplayName(tool) { const candidate = tool; return toolDisplayName(isNonEmptyString(candidate?.name) ? candidate.name : undefined, getFunctionToolNamespace(tool)); } export function matchesFunctionToolName(tool, candidate) { if (!isNonEmptyString(candidate)) { return false; } const bareName = getFunctionToolName(tool); if (bareName === candidate) { return true; } return getFunctionToolQualifiedName(tool) === candidate; } function getFunctionToolName(tool) { const candidate = tool; return isNonEmptyString(candidate?.name) ? candidate.name : undefined; } //# sourceMappingURL=toolIdentity.mjs.map