@openai/agents-core
Version:
The OpenAI Agents SDK is a lightweight yet powerful framework for building multi-agent workflows.
171 lines • 6.8 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.buildAgentIdentityMap = buildAgentIdentityMap;
const agent_1 = require("./agent.js");
const agentToolSourceRegistry_1 = require("./agentToolSourceRegistry.js");
function buildAgentIdentityMap(initialAgent) {
const agents = collectAgentGraph(initialAgent);
const groups = new Map();
const literalNames = new Set();
for (const entry of agents) {
literalNames.add(entry.agent.name);
const group = groups.get(entry.agent.name) ?? [];
group.push(entry);
groups.set(entry.agent.name, group);
}
const byIdentity = new Map();
const byAgent = new Map();
const usedIdentities = new Set();
for (const [agentName, group] of groups) {
const sortedGroup = group.length === 1
? group
: [...group].sort((left, right) => {
if (left.agent === initialAgent)
return -1;
if (right.agent === initialAgent)
return 1;
const leftSignature = getAgentIdentitySignature(left.agent);
const rightSignature = getAgentIdentitySignature(right.agent);
if (leftSignature !== rightSignature) {
return leftSignature < rightSignature ? -1 : 1;
}
return left.index - right.index;
});
let nextSuffix = 0;
for (const { agent } of sortedGroup) {
let identity;
do {
identity =
nextSuffix === 0 ? agentName : `${agentName}#${nextSuffix + 1}`;
nextSuffix += 1;
} while (usedIdentities.has(identity) ||
(identity !== agent.name && literalNames.has(identity)));
usedIdentities.add(identity);
byIdentity.set(identity, agent);
byAgent.set(agent, identity);
}
}
return { byIdentity, byAgent };
}
function collectAgentGraph(initialAgent) {
const agents = [];
const visitedAgents = new Set();
const queue = [initialAgent];
while (queue.length > 0) {
const currentAgent = queue.shift();
if (visitedAgents.has(currentAgent))
continue;
visitedAgents.add(currentAgent);
agents.push({ agent: currentAgent, index: agents.length });
for (const handoff of currentAgent.handoffs) {
if (handoff instanceof agent_1.Agent)
queue.push(handoff);
else if (handoff.agent)
queue.push(handoff.agent);
}
for (const tool of currentAgent.tools) {
const sourceAgent = (0, agentToolSourceRegistry_1.getAgentToolSourceAgent)(tool);
if (sourceAgent)
queue.push(sourceAgent);
}
}
return agents;
}
function getAgentIdentitySignature(agent) {
const sandboxAgent = agent;
return stableStringify({
type: agent.constructor?.name,
name: agent.name,
handoffDescription: agent.handoffDescription,
instructions: summarizeIdentityValue(agent.instructions),
prompt: summarizeIdentityValue(agent.prompt),
model: summarizeIdentityValue(agent.model),
modelSettings: summarizeIdentityValue(agent.modelSettings),
tools: agent.tools.map(summarizeToolIdentity),
handoffs: agent.handoffs.map((entry) => entry instanceof agent_1.Agent
? { type: 'agent', name: entry.name }
: {
type: 'handoff',
toolName: entry.toolName,
agentName: entry.agentName,
targetName: entry.agent?.name,
}),
mcpServers: agent.mcpServers.map(summarizeIdentityValue),
mcpConfig: summarizeIdentityValue(agent.mcpConfig),
inputGuardrails: agent.inputGuardrails.map(summarizeIdentityValue),
outputGuardrails: agent.outputGuardrails.map(summarizeIdentityValue),
outputType: summarizeIdentityValue(agent.outputType),
toolUseBehavior: summarizeIdentityValue(agent.toolUseBehavior),
resetToolChoice: agent.resetToolChoice,
defaultManifest: summarizeIdentityValue(sandboxAgent.defaultManifest),
baseInstructions: summarizeIdentityValue(sandboxAgent.baseInstructions),
capabilities: sandboxAgent.capabilities?.map(summarizeIdentityValue),
runAs: summarizeIdentityValue(sandboxAgent.runAs),
});
}
function summarizeToolIdentity(tool) {
return {
type: tool.type,
name: tool.name,
namespace: tool.namespace,
strict: tool.strict,
parameters: summarizeIdentityValue(tool.parameters),
};
}
function summarizeIdentityValue(value) {
return normalizeForIdentity(value, new WeakSet(), 0);
}
function normalizeForIdentity(value, seen, depth) {
if (value === null || typeof value === 'undefined')
return value;
if (typeof value === 'string' ||
typeof value === 'number' ||
typeof value === 'boolean') {
return value;
}
if (typeof value === 'function') {
return `[function:${value.name || 'anonymous'}]`;
}
if (typeof value !== 'object')
return String(value);
if (seen.has(value))
return '[circular]';
if (depth >= 4)
return `[${value.constructor?.name ?? 'Object'}]`;
seen.add(value);
if (Array.isArray(value)) {
return value.map((item) => normalizeForIdentity(item, seen, depth + 1));
}
if (value instanceof Map) {
return [...value.entries()]
.map(([key, entryValue]) => [
normalizeForIdentity(key, seen, depth + 1),
normalizeForIdentity(entryValue, seen, depth + 1),
])
.sort((left, right) => stableStringify(left).localeCompare(stableStringify(right)));
}
if (value instanceof Set) {
return [...value.values()]
.map((entry) => normalizeForIdentity(entry, seen, depth + 1))
.sort((left, right) => stableStringify(left).localeCompare(stableStringify(right)));
}
const record = value;
const normalized = {
constructor: value.constructor?.name,
};
for (const key of Object.keys(record).sort()) {
normalized[key] = normalizeForIdentity(record[key], seen, depth + 1);
}
return normalized;
}
function stableStringify(value) {
return JSON.stringify(value, (_key, currentValue) => {
if (!currentValue ||
typeof currentValue !== 'object' ||
Array.isArray(currentValue)) {
return currentValue;
}
return Object.fromEntries(Object.entries(currentValue).sort(([left], [right]) => left.localeCompare(right)));
});
}
//# sourceMappingURL=runStateIdentity.js.map