@openai/agents-core 0.9.0 → 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agent.d.ts +25 -2
- package/dist/agent.js +45 -2
- package/dist/agent.js.map +1 -1
- package/dist/agent.mjs +46 -3
- package/dist/agent.mjs.map +1 -1
- package/dist/agentToolRunConfig.js +3 -0
- package/dist/agentToolRunConfig.js.map +1 -1
- package/dist/agentToolRunConfig.mjs +3 -0
- package/dist/agentToolRunConfig.mjs.map +1 -1
- package/dist/defaultModel.js +2 -1
- package/dist/defaultModel.js.map +1 -1
- package/dist/defaultModel.mjs +2 -1
- package/dist/defaultModel.mjs.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js.map +1 -1
- package/dist/index.mjs.map +1 -1
- package/dist/mcp.d.ts +9 -3
- package/dist/mcp.js +238 -16
- package/dist/mcp.js.map +1 -1
- package/dist/mcp.mjs +238 -16
- package/dist/mcp.mjs.map +1 -1
- package/dist/memory/session.d.ts +7 -0
- package/dist/memory/session.js.map +1 -1
- package/dist/memory/session.mjs.map +1 -1
- package/dist/metadata.js +2 -2
- package/dist/metadata.js.map +1 -1
- package/dist/metadata.mjs +2 -2
- package/dist/metadata.mjs.map +1 -1
- package/dist/result.d.ts +1 -1
- package/dist/result.js.map +1 -1
- package/dist/result.mjs.map +1 -1
- package/dist/run.d.ts +17 -1
- package/dist/run.js +95 -11
- package/dist/run.js.map +1 -1
- package/dist/run.mjs +96 -12
- package/dist/run.mjs.map +1 -1
- package/dist/runState.d.ts +33 -6
- package/dist/runState.js +326 -46
- package/dist/runState.js.map +1 -1
- package/dist/runState.mjs +325 -46
- package/dist/runState.mjs.map +1 -1
- package/dist/runner/sessionPersistence.js +33 -12
- package/dist/runner/sessionPersistence.js.map +1 -1
- package/dist/runner/sessionPersistence.mjs +33 -12
- package/dist/runner/sessionPersistence.mjs.map +1 -1
- package/dist/runner/streamReconciliation.d.ts +14 -0
- package/dist/runner/streamReconciliation.js +80 -0
- package/dist/runner/streamReconciliation.js.map +1 -0
- package/dist/runner/streamReconciliation.mjs +72 -0
- package/dist/runner/streamReconciliation.mjs.map +1 -0
- package/dist/runner/toolExecution.js +45 -12
- package/dist/runner/toolExecution.js.map +1 -1
- package/dist/runner/toolExecution.mjs +45 -12
- package/dist/runner/toolExecution.mjs.map +1 -1
- package/dist/runner/toolUseTracker.d.ts +3 -1
- package/dist/runner/toolUseTracker.js +2 -2
- package/dist/runner/toolUseTracker.js.map +1 -1
- package/dist/runner/toolUseTracker.mjs +2 -2
- package/dist/runner/toolUseTracker.mjs.map +1 -1
- package/dist/runner/turnPreparation.js +1 -1
- package/dist/runner/turnPreparation.js.map +1 -1
- package/dist/runner/turnPreparation.mjs +1 -1
- package/dist/runner/turnPreparation.mjs.map +1 -1
- package/dist/sandbox/agent.d.ts +2 -2
- package/dist/sandbox/agent.js +1 -0
- package/dist/sandbox/agent.js.map +1 -1
- package/dist/sandbox/agent.mjs +1 -0
- package/dist/sandbox/agent.mjs.map +1 -1
- package/dist/sandbox/client.d.ts +3 -3
- package/dist/sandbox/client.js +6 -1
- package/dist/sandbox/client.js.map +1 -1
- package/dist/sandbox/client.mjs +7 -2
- package/dist/sandbox/client.mjs.map +1 -1
- package/dist/sandbox/manifest.d.ts +6 -5
- package/dist/sandbox/manifest.js +7 -0
- package/dist/sandbox/manifest.js.map +1 -1
- package/dist/sandbox/manifest.mjs +7 -0
- package/dist/sandbox/manifest.mjs.map +1 -1
- package/dist/sandbox/users.d.ts +7 -2
- package/dist/sandbox/users.js +1 -1
- package/dist/sandbox/users.js.map +1 -1
- package/dist/sandbox/users.mjs +1 -1
- package/dist/sandbox/users.mjs.map +1 -1
- package/package.json +1 -1
package/dist/runState.mjs
CHANGED
|
@@ -40,8 +40,11 @@ import { getSerializedApplyPatchToolPlaceholder, getSerializedComputerToolPlaceh
|
|
|
40
40
|
* aliasing to serialized run state payloads.
|
|
41
41
|
* - 1.9: Adds optional sandbox session persistence with a versioned session-state
|
|
42
42
|
* envelope for sandbox-agent resume.
|
|
43
|
+
* - 1.10: Adds optional stable agent identity keys so duplicate-name agent graphs can
|
|
44
|
+
* serialize and resume without ambiguous name resolution.
|
|
45
|
+
* - 1.11: Allows null maxTurns to persist runs without a turn limit.
|
|
43
46
|
*/
|
|
44
|
-
export const CURRENT_SCHEMA_VERSION = '1.
|
|
47
|
+
export const CURRENT_SCHEMA_VERSION = '1.11';
|
|
45
48
|
const SUPPORTED_SCHEMA_VERSIONS = [
|
|
46
49
|
'1.0',
|
|
47
50
|
'1.1',
|
|
@@ -52,11 +55,14 @@ const SUPPORTED_SCHEMA_VERSIONS = [
|
|
|
52
55
|
'1.6',
|
|
53
56
|
'1.7',
|
|
54
57
|
'1.8',
|
|
58
|
+
'1.9',
|
|
59
|
+
'1.10',
|
|
55
60
|
CURRENT_SCHEMA_VERSION,
|
|
56
61
|
];
|
|
57
62
|
const $schemaVersion = z.enum(SUPPORTED_SCHEMA_VERSIONS);
|
|
58
63
|
const serializedAgentSchema = z.object({
|
|
59
64
|
name: z.string(),
|
|
65
|
+
identity: z.string().optional(),
|
|
60
66
|
});
|
|
61
67
|
const serializedSpanBase = z.object({
|
|
62
68
|
object: z.literal('trace.span'),
|
|
@@ -307,7 +313,7 @@ export const SerializedRunState = z.object({
|
|
|
307
313
|
toolInput: z.any().optional(),
|
|
308
314
|
}),
|
|
309
315
|
toolUseTracker: z.record(z.string(), z.array(z.string())),
|
|
310
|
-
maxTurns: z.number(),
|
|
316
|
+
maxTurns: z.number().nullable(),
|
|
311
317
|
currentAgentSpan: SerializedSpan.nullable().optional(),
|
|
312
318
|
noActiveAgentRun: z.boolean(),
|
|
313
319
|
inputGuardrailResults: z.array(inputGuardrailResultSchema),
|
|
@@ -470,10 +476,10 @@ export class RunState {
|
|
|
470
476
|
*/
|
|
471
477
|
_trace = null;
|
|
472
478
|
/**
|
|
473
|
-
* Runtime-only tool_search-loaded tools, scoped by agent
|
|
479
|
+
* Runtime-only tool_search-loaded tools, scoped by agent object and preserved across turns for
|
|
474
480
|
* the lifetime of this in-memory run.
|
|
475
481
|
*/
|
|
476
|
-
|
|
482
|
+
_toolSearchRuntimeToolsByAgent = new Map();
|
|
477
483
|
/**
|
|
478
484
|
* Persisted sandbox session metadata for sandbox-agent resume.
|
|
479
485
|
*/
|
|
@@ -517,20 +523,20 @@ export class RunState {
|
|
|
517
523
|
setCurrentAgentSpan(span) {
|
|
518
524
|
this._currentAgentSpan = span;
|
|
519
525
|
}
|
|
520
|
-
getOrCreateToolSearchRuntimeToolState(
|
|
521
|
-
let state = this.
|
|
526
|
+
getOrCreateToolSearchRuntimeToolState(agent) {
|
|
527
|
+
let state = this._toolSearchRuntimeToolsByAgent.get(agent);
|
|
522
528
|
if (!state) {
|
|
523
529
|
state = {
|
|
524
530
|
anonymousEntries: [],
|
|
525
531
|
keyedEntries: new Map(),
|
|
526
532
|
nextOrder: 0,
|
|
527
533
|
};
|
|
528
|
-
this.
|
|
534
|
+
this._toolSearchRuntimeToolsByAgent.set(agent, state);
|
|
529
535
|
}
|
|
530
536
|
return state;
|
|
531
537
|
}
|
|
532
538
|
recordToolSearchRuntimeTools(agent, toolSearchOutput, tools) {
|
|
533
|
-
const runtimeState = this.getOrCreateToolSearchRuntimeToolState(agent
|
|
539
|
+
const runtimeState = this.getOrCreateToolSearchRuntimeToolState(agent);
|
|
534
540
|
const entry = {
|
|
535
541
|
order: runtimeState.nextOrder++,
|
|
536
542
|
tools,
|
|
@@ -543,7 +549,7 @@ export class RunState {
|
|
|
543
549
|
runtimeState.anonymousEntries.push(entry);
|
|
544
550
|
}
|
|
545
551
|
getToolSearchRuntimeTools(agent) {
|
|
546
|
-
const runtimeState = this.
|
|
552
|
+
const runtimeState = this._toolSearchRuntimeToolsByAgent.get(agent);
|
|
547
553
|
if (!runtimeState) {
|
|
548
554
|
return [];
|
|
549
555
|
}
|
|
@@ -680,15 +686,13 @@ export class RunState {
|
|
|
680
686
|
* rehydrate in a separate process that lacks the original environment variables).
|
|
681
687
|
*/
|
|
682
688
|
toJSON(options = {}) {
|
|
683
|
-
|
|
689
|
+
const agentIdentity = buildAgentIdentityMap(this.#startingAgent);
|
|
684
690
|
const includeTracingApiKey = options.includeTracingApiKey === true;
|
|
685
691
|
const contextJson = this._context.toJSON();
|
|
686
692
|
const output = {
|
|
687
693
|
$schemaVersion: CURRENT_SCHEMA_VERSION,
|
|
688
694
|
currentTurn: this._currentTurn,
|
|
689
|
-
currentAgent:
|
|
690
|
-
name: this._currentAgent.name,
|
|
691
|
-
},
|
|
695
|
+
currentAgent: serializeAgentReference(this._currentAgent, agentIdentity.byAgent),
|
|
692
696
|
originalInput: this._originalInput,
|
|
693
697
|
modelResponses: this._modelResponses.map((response) => {
|
|
694
698
|
return {
|
|
@@ -720,7 +724,9 @@ export class RunState {
|
|
|
720
724
|
};
|
|
721
725
|
}),
|
|
722
726
|
context: contextJson,
|
|
723
|
-
toolUseTracker: this._toolUseTracker.toJSON(
|
|
727
|
+
toolUseTracker: this._toolUseTracker.toJSON({
|
|
728
|
+
agentIdentityKeys: agentIdentity.byAgent,
|
|
729
|
+
}),
|
|
724
730
|
maxTurns: this._maxTurns,
|
|
725
731
|
currentAgentSpan: this._currentAgentSpan?.toJSON(),
|
|
726
732
|
noActiveAgentRun: this._noActiveAgentRun,
|
|
@@ -728,16 +734,18 @@ export class RunState {
|
|
|
728
734
|
inputGuardrailResults: this._inputGuardrailResults,
|
|
729
735
|
outputGuardrailResults: this._outputGuardrailResults.map((r) => ({
|
|
730
736
|
...r,
|
|
731
|
-
agent: r.agent.
|
|
737
|
+
agent: serializeAgentReference(r.agent, agentIdentity.byAgent),
|
|
732
738
|
})),
|
|
733
739
|
toolInputGuardrailResults: this._toolInputGuardrailResults,
|
|
734
740
|
toolOutputGuardrailResults: this._toolOutputGuardrailResults,
|
|
735
|
-
currentStep: this._currentStep,
|
|
741
|
+
currentStep: serializeCurrentStep(this._currentStep, agentIdentity.byAgent),
|
|
736
742
|
lastModelResponse: this._lastTurnResponse,
|
|
737
|
-
generatedItems: this._generatedItems.map((item) => item.
|
|
743
|
+
generatedItems: this._generatedItems.map((item) => serializeRunItem(item, agentIdentity.byAgent)),
|
|
738
744
|
pendingAgentToolRuns: Object.fromEntries(this._pendingAgentToolRuns.entries()),
|
|
739
745
|
currentTurnPersistedItemCount: this._currentTurnPersistedItemCount,
|
|
740
|
-
lastProcessedResponse: this._lastProcessedResponse
|
|
746
|
+
lastProcessedResponse: this._lastProcessedResponse
|
|
747
|
+
? serializeProcessedResponse(this._lastProcessedResponse, agentIdentity.byAgent)
|
|
748
|
+
: undefined,
|
|
741
749
|
conversationId: this._conversationId,
|
|
742
750
|
previousResponseId: this._previousResponseId,
|
|
743
751
|
reasoningItemIdPolicy: this._reasoningItemIdPolicy,
|
|
@@ -797,7 +805,10 @@ async function buildRunStateFromString(initialAgent, str, options = {}) {
|
|
|
797
805
|
return buildRunStateFromJson(initialAgent, stateJson, options);
|
|
798
806
|
}
|
|
799
807
|
function assertSchemaVersionSupportsToolSearch(schemaVersion, stateJson) {
|
|
800
|
-
if (schemaVersion === '1.8' ||
|
|
808
|
+
if (schemaVersion === '1.8' ||
|
|
809
|
+
schemaVersion === '1.9' ||
|
|
810
|
+
schemaVersion === '1.10' ||
|
|
811
|
+
schemaVersion === CURRENT_SCHEMA_VERSION) {
|
|
801
812
|
return;
|
|
802
813
|
}
|
|
803
814
|
if (!containsSerializedToolSearchState(stateJson)) {
|
|
@@ -805,6 +816,9 @@ function assertSchemaVersionSupportsToolSearch(schemaVersion, stateJson) {
|
|
|
805
816
|
}
|
|
806
817
|
throw new UserError(`Run state schema version ${schemaVersion} does not support tool_search items. Please reserialize the run state with schema ${CURRENT_SCHEMA_VERSION}.`);
|
|
807
818
|
}
|
|
819
|
+
function schemaVersionSupportsAgentIdentity(schemaVersion) {
|
|
820
|
+
return schemaVersion === '1.10' || schemaVersion === CURRENT_SCHEMA_VERSION;
|
|
821
|
+
}
|
|
808
822
|
function containsSerializedToolSearchState(stateJson) {
|
|
809
823
|
return (containsToolSearchProtocolItems(stateJson.originalInput) ||
|
|
810
824
|
containsToolSearchInModelResponses(stateJson.modelResponses) ||
|
|
@@ -908,17 +922,17 @@ function assertRuntimeToolKeysMatch(args) {
|
|
|
908
922
|
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)}].`);
|
|
909
923
|
}
|
|
910
924
|
async function getConfiguredAgentTools(args) {
|
|
911
|
-
const { agent, context,
|
|
912
|
-
const existing =
|
|
925
|
+
const { agent, context, configuredToolsByAgent } = args;
|
|
926
|
+
const existing = configuredToolsByAgent.get(agent);
|
|
913
927
|
if (existing) {
|
|
914
928
|
return existing;
|
|
915
929
|
}
|
|
916
930
|
const configuredTools = (await agent.getAllTools(context));
|
|
917
|
-
|
|
931
|
+
configuredToolsByAgent.set(agent, configuredTools);
|
|
918
932
|
return configuredTools;
|
|
919
933
|
}
|
|
920
934
|
async function rehydrateToolSearchRuntimeTools(state) {
|
|
921
|
-
const
|
|
935
|
+
const configuredToolsByAgent = new Map();
|
|
922
936
|
const pendingToolSearchCalls = new Map();
|
|
923
937
|
for (const item of state._generatedItems) {
|
|
924
938
|
if (item instanceof RunToolSearchCallItem) {
|
|
@@ -926,10 +940,14 @@ async function rehydrateToolSearchRuntimeTools(state) {
|
|
|
926
940
|
continue;
|
|
927
941
|
}
|
|
928
942
|
const callId = resolveToolSearchCallId(item.rawItem);
|
|
929
|
-
|
|
943
|
+
const agent = item.agent;
|
|
944
|
+
const pendingCallsById = pendingToolSearchCalls.get(agent) ??
|
|
945
|
+
new Map();
|
|
946
|
+
pendingCallsById.set(callId, {
|
|
930
947
|
agent: item.agent,
|
|
931
948
|
toolSearchCall: item.rawItem,
|
|
932
949
|
});
|
|
950
|
+
pendingToolSearchCalls.set(agent, pendingCallsById);
|
|
933
951
|
continue;
|
|
934
952
|
}
|
|
935
953
|
if (!(item instanceof RunToolSearchOutputItem)) {
|
|
@@ -941,7 +959,7 @@ async function rehydrateToolSearchRuntimeTools(state) {
|
|
|
941
959
|
const configuredTools = await getConfiguredAgentTools({
|
|
942
960
|
agent: item.agent,
|
|
943
961
|
context: state._context,
|
|
944
|
-
|
|
962
|
+
configuredToolsByAgent,
|
|
945
963
|
});
|
|
946
964
|
const configuredToolKeys = getRuntimeToolKeys(configuredTools, {
|
|
947
965
|
allowUnsupported: true,
|
|
@@ -951,7 +969,9 @@ async function rehydrateToolSearchRuntimeTools(state) {
|
|
|
951
969
|
continue;
|
|
952
970
|
}
|
|
953
971
|
const callId = resolveToolSearchCallId(item.rawItem);
|
|
954
|
-
const pendingCall = pendingToolSearchCalls
|
|
972
|
+
const pendingCall = pendingToolSearchCalls
|
|
973
|
+
.get(item.agent)
|
|
974
|
+
?.get(callId);
|
|
955
975
|
if (!pendingCall) {
|
|
956
976
|
throw new UserError(`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.`);
|
|
957
977
|
}
|
|
@@ -994,7 +1014,9 @@ async function rehydrateToolSearchRuntimeTools(state) {
|
|
|
994
1014
|
}
|
|
995
1015
|
}
|
|
996
1016
|
async function buildRunStateFromJson(initialAgent, stateJson, options = {}) {
|
|
997
|
-
const agentMap =
|
|
1017
|
+
const agentMap = schemaVersionSupportsAgentIdentity(stateJson.$schemaVersion)
|
|
1018
|
+
? buildAgentIdentityMap(initialAgent).byIdentity
|
|
1019
|
+
: buildAgentMap(initialAgent);
|
|
998
1020
|
const contextOverride = options.contextOverride;
|
|
999
1021
|
const contextStrategy = options.contextStrategy ?? 'merge';
|
|
1000
1022
|
//
|
|
@@ -1019,10 +1041,7 @@ async function buildRunStateFromJson(initialAgent, stateJson, options = {}) {
|
|
|
1019
1041
|
//
|
|
1020
1042
|
// Find the current agent from the initial agent
|
|
1021
1043
|
//
|
|
1022
|
-
const currentAgent =
|
|
1023
|
-
if (!currentAgent) {
|
|
1024
|
-
throw new UserError(`Agent ${stateJson.currentAgent.name} not found`);
|
|
1025
|
-
}
|
|
1044
|
+
const currentAgent = resolveSerializedAgent(stateJson.currentAgent, agentMap);
|
|
1026
1045
|
const state = new RunState(context, '', initialAgent, stateJson.maxTurns);
|
|
1027
1046
|
state._currentAgent = currentAgent;
|
|
1028
1047
|
state._currentTurn = stateJson.currentTurn;
|
|
@@ -1033,7 +1052,13 @@ async function buildRunStateFromJson(initialAgent, stateJson, options = {}) {
|
|
|
1033
1052
|
// rebuild tool use tracker
|
|
1034
1053
|
state._toolUseTracker = new AgentToolUseTracker();
|
|
1035
1054
|
for (const [agentName, toolNames] of Object.entries(stateJson.toolUseTracker)) {
|
|
1036
|
-
|
|
1055
|
+
const agent = agentMap.get(agentName);
|
|
1056
|
+
if (!agent) {
|
|
1057
|
+
throw new UserError(`Agent ${agentName} not found`);
|
|
1058
|
+
}
|
|
1059
|
+
state._toolUseTracker.addToolUse(agent, toolNames, {
|
|
1060
|
+
allowEmpty: true,
|
|
1061
|
+
});
|
|
1037
1062
|
}
|
|
1038
1063
|
state._pendingAgentToolRuns = new Map(Object.entries(stateJson.pendingAgentToolRuns ?? {}));
|
|
1039
1064
|
// rebuild current agent span
|
|
@@ -1056,7 +1081,7 @@ async function buildRunStateFromJson(initialAgent, stateJson, options = {}) {
|
|
|
1056
1081
|
stateJson.inputGuardrailResults;
|
|
1057
1082
|
state._outputGuardrailResults = stateJson.outputGuardrailResults.map((r) => ({
|
|
1058
1083
|
...r,
|
|
1059
|
-
agent:
|
|
1084
|
+
agent: resolveSerializedAgent(r.agent, agentMap),
|
|
1060
1085
|
}));
|
|
1061
1086
|
state._toolInputGuardrailResults =
|
|
1062
1087
|
stateJson.toolInputGuardrailResults;
|
|
@@ -1079,7 +1104,7 @@ async function buildRunStateFromJson(initialAgent, stateJson, options = {}) {
|
|
|
1079
1104
|
if (stateJson.currentStep?.type === 'next_step_handoff') {
|
|
1080
1105
|
state._currentStep = {
|
|
1081
1106
|
type: 'next_step_handoff',
|
|
1082
|
-
newAgent:
|
|
1107
|
+
newAgent: resolveSerializedAgent(stateJson.currentStep.newAgent, agentMap),
|
|
1083
1108
|
};
|
|
1084
1109
|
}
|
|
1085
1110
|
else if (stateJson.currentStep?.type === 'next_step_interruption') {
|
|
@@ -1100,7 +1125,9 @@ export async function rehydrateProcessedResponseTools(initialAgent, state, execu
|
|
|
1100
1125
|
if (!state._lastProcessedResponse) {
|
|
1101
1126
|
return;
|
|
1102
1127
|
}
|
|
1103
|
-
|
|
1128
|
+
const agentIdentity = buildAgentIdentityMap(initialAgent);
|
|
1129
|
+
const serializedProcessedResponse = serializeProcessedResponse(state._lastProcessedResponse, agentIdentity.byAgent);
|
|
1130
|
+
state._lastProcessedResponse = await deserializeProcessedResponse(agentIdentity.byIdentity, state, serializedProcessedResponse, {
|
|
1104
1131
|
executionTools,
|
|
1105
1132
|
allowSerializedExecutionToolPlaceholder: false,
|
|
1106
1133
|
});
|
|
@@ -1140,6 +1167,250 @@ export function buildAgentMap(initialAgent) {
|
|
|
1140
1167
|
}
|
|
1141
1168
|
return map;
|
|
1142
1169
|
}
|
|
1170
|
+
/**
|
|
1171
|
+
* @internal
|
|
1172
|
+
*/
|
|
1173
|
+
export function buildAgentIdentityMap(initialAgent) {
|
|
1174
|
+
const agents = collectAgentGraph(initialAgent);
|
|
1175
|
+
const groups = new Map();
|
|
1176
|
+
const literalNames = new Set();
|
|
1177
|
+
for (const entry of agents) {
|
|
1178
|
+
literalNames.add(entry.agent.name);
|
|
1179
|
+
const group = groups.get(entry.agent.name) ?? [];
|
|
1180
|
+
group.push(entry);
|
|
1181
|
+
groups.set(entry.agent.name, group);
|
|
1182
|
+
}
|
|
1183
|
+
const byIdentity = new Map();
|
|
1184
|
+
const byAgent = new Map();
|
|
1185
|
+
const usedIdentities = new Set();
|
|
1186
|
+
for (const [agentName, group] of groups) {
|
|
1187
|
+
const sortedGroup = group.length === 1
|
|
1188
|
+
? group
|
|
1189
|
+
: [...group].sort((left, right) => {
|
|
1190
|
+
if (left.agent === initialAgent) {
|
|
1191
|
+
return -1;
|
|
1192
|
+
}
|
|
1193
|
+
if (right.agent === initialAgent) {
|
|
1194
|
+
return 1;
|
|
1195
|
+
}
|
|
1196
|
+
const leftSignature = getAgentIdentitySignature(left.agent);
|
|
1197
|
+
const rightSignature = getAgentIdentitySignature(right.agent);
|
|
1198
|
+
if (leftSignature !== rightSignature) {
|
|
1199
|
+
return leftSignature < rightSignature ? -1 : 1;
|
|
1200
|
+
}
|
|
1201
|
+
return left.index - right.index;
|
|
1202
|
+
});
|
|
1203
|
+
let nextSuffix = 0;
|
|
1204
|
+
for (const { agent } of sortedGroup) {
|
|
1205
|
+
let identity;
|
|
1206
|
+
do {
|
|
1207
|
+
identity =
|
|
1208
|
+
nextSuffix === 0 ? agentName : `${agentName}#${nextSuffix + 1}`;
|
|
1209
|
+
nextSuffix += 1;
|
|
1210
|
+
} while (usedIdentities.has(identity) ||
|
|
1211
|
+
(identity !== agent.name && literalNames.has(identity)));
|
|
1212
|
+
usedIdentities.add(identity);
|
|
1213
|
+
byIdentity.set(identity, agent);
|
|
1214
|
+
byAgent.set(agent, identity);
|
|
1215
|
+
}
|
|
1216
|
+
}
|
|
1217
|
+
return { byIdentity, byAgent };
|
|
1218
|
+
}
|
|
1219
|
+
function collectAgentGraph(initialAgent) {
|
|
1220
|
+
const agents = [];
|
|
1221
|
+
const visitedAgents = new Set();
|
|
1222
|
+
const queue = [initialAgent];
|
|
1223
|
+
while (queue.length > 0) {
|
|
1224
|
+
const currentAgent = queue.shift();
|
|
1225
|
+
if (visitedAgents.has(currentAgent)) {
|
|
1226
|
+
continue;
|
|
1227
|
+
}
|
|
1228
|
+
visitedAgents.add(currentAgent);
|
|
1229
|
+
agents.push({ agent: currentAgent, index: agents.length });
|
|
1230
|
+
for (const handoff of currentAgent.handoffs) {
|
|
1231
|
+
if (handoff instanceof Agent) {
|
|
1232
|
+
queue.push(handoff);
|
|
1233
|
+
}
|
|
1234
|
+
else if (handoff.agent) {
|
|
1235
|
+
queue.push(handoff.agent);
|
|
1236
|
+
}
|
|
1237
|
+
}
|
|
1238
|
+
for (const tool of currentAgent.tools) {
|
|
1239
|
+
const sourceAgent = getAgentToolSourceAgent(tool);
|
|
1240
|
+
if (sourceAgent) {
|
|
1241
|
+
queue.push(sourceAgent);
|
|
1242
|
+
}
|
|
1243
|
+
}
|
|
1244
|
+
}
|
|
1245
|
+
return agents;
|
|
1246
|
+
}
|
|
1247
|
+
function getAgentIdentitySignature(agent) {
|
|
1248
|
+
const sandboxAgent = agent;
|
|
1249
|
+
const signature = {
|
|
1250
|
+
type: agent.constructor?.name,
|
|
1251
|
+
name: agent.name,
|
|
1252
|
+
handoffDescription: agent.handoffDescription,
|
|
1253
|
+
instructions: summarizeIdentityValue(agent.instructions),
|
|
1254
|
+
prompt: summarizeIdentityValue(agent.prompt),
|
|
1255
|
+
model: summarizeIdentityValue(agent.model),
|
|
1256
|
+
modelSettings: summarizeIdentityValue(agent.modelSettings),
|
|
1257
|
+
tools: agent.tools.map(summarizeToolIdentity),
|
|
1258
|
+
handoffs: agent.handoffs.map((entry) => entry instanceof Agent
|
|
1259
|
+
? { type: 'agent', name: entry.name }
|
|
1260
|
+
: {
|
|
1261
|
+
type: 'handoff',
|
|
1262
|
+
toolName: entry.toolName,
|
|
1263
|
+
agentName: entry.agentName,
|
|
1264
|
+
targetName: entry.agent?.name,
|
|
1265
|
+
}),
|
|
1266
|
+
mcpServers: agent.mcpServers.map(summarizeIdentityValue),
|
|
1267
|
+
mcpConfig: summarizeIdentityValue(agent.mcpConfig),
|
|
1268
|
+
inputGuardrails: agent.inputGuardrails.map(summarizeIdentityValue),
|
|
1269
|
+
outputGuardrails: agent.outputGuardrails.map(summarizeIdentityValue),
|
|
1270
|
+
outputType: summarizeIdentityValue(agent.outputType),
|
|
1271
|
+
toolUseBehavior: summarizeIdentityValue(agent.toolUseBehavior),
|
|
1272
|
+
resetToolChoice: agent.resetToolChoice,
|
|
1273
|
+
defaultManifest: summarizeIdentityValue(sandboxAgent.defaultManifest),
|
|
1274
|
+
baseInstructions: summarizeIdentityValue(sandboxAgent.baseInstructions),
|
|
1275
|
+
capabilities: sandboxAgent.capabilities?.map(summarizeIdentityValue),
|
|
1276
|
+
runAs: summarizeIdentityValue(sandboxAgent.runAs),
|
|
1277
|
+
};
|
|
1278
|
+
return stableStringify(signature);
|
|
1279
|
+
}
|
|
1280
|
+
function summarizeToolIdentity(tool) {
|
|
1281
|
+
return {
|
|
1282
|
+
type: tool.type,
|
|
1283
|
+
name: tool.name,
|
|
1284
|
+
namespace: tool.namespace,
|
|
1285
|
+
strict: tool.strict,
|
|
1286
|
+
parameters: summarizeIdentityValue(tool.parameters),
|
|
1287
|
+
};
|
|
1288
|
+
}
|
|
1289
|
+
function summarizeIdentityValue(value) {
|
|
1290
|
+
return normalizeForIdentity(value, new WeakSet(), 0);
|
|
1291
|
+
}
|
|
1292
|
+
function normalizeForIdentity(value, seen, depth) {
|
|
1293
|
+
if (value === null || typeof value === 'undefined') {
|
|
1294
|
+
return value;
|
|
1295
|
+
}
|
|
1296
|
+
if (typeof value === 'string' ||
|
|
1297
|
+
typeof value === 'number' ||
|
|
1298
|
+
typeof value === 'boolean') {
|
|
1299
|
+
return value;
|
|
1300
|
+
}
|
|
1301
|
+
if (typeof value === 'function') {
|
|
1302
|
+
return `[function:${value.name || 'anonymous'}]`;
|
|
1303
|
+
}
|
|
1304
|
+
if (typeof value !== 'object') {
|
|
1305
|
+
return String(value);
|
|
1306
|
+
}
|
|
1307
|
+
if (seen.has(value)) {
|
|
1308
|
+
return '[circular]';
|
|
1309
|
+
}
|
|
1310
|
+
if (depth >= 4) {
|
|
1311
|
+
return `[${value.constructor?.name ?? 'Object'}]`;
|
|
1312
|
+
}
|
|
1313
|
+
seen.add(value);
|
|
1314
|
+
if (Array.isArray(value)) {
|
|
1315
|
+
return value.map((item) => normalizeForIdentity(item, seen, depth + 1));
|
|
1316
|
+
}
|
|
1317
|
+
if (value instanceof Map) {
|
|
1318
|
+
return [...value.entries()]
|
|
1319
|
+
.map(([key, entryValue]) => [
|
|
1320
|
+
normalizeForIdentity(key, seen, depth + 1),
|
|
1321
|
+
normalizeForIdentity(entryValue, seen, depth + 1),
|
|
1322
|
+
])
|
|
1323
|
+
.sort((left, right) => stableStringify(left).localeCompare(stableStringify(right)));
|
|
1324
|
+
}
|
|
1325
|
+
if (value instanceof Set) {
|
|
1326
|
+
return [...value.values()]
|
|
1327
|
+
.map((entry) => normalizeForIdentity(entry, seen, depth + 1))
|
|
1328
|
+
.sort((left, right) => stableStringify(left).localeCompare(stableStringify(right)));
|
|
1329
|
+
}
|
|
1330
|
+
const record = value;
|
|
1331
|
+
const normalized = {
|
|
1332
|
+
constructor: value.constructor?.name,
|
|
1333
|
+
};
|
|
1334
|
+
for (const key of Object.keys(record).sort()) {
|
|
1335
|
+
normalized[key] = normalizeForIdentity(record[key], seen, depth + 1);
|
|
1336
|
+
}
|
|
1337
|
+
return normalized;
|
|
1338
|
+
}
|
|
1339
|
+
function stableStringify(value) {
|
|
1340
|
+
return JSON.stringify(value, (_key, currentValue) => {
|
|
1341
|
+
if (!currentValue ||
|
|
1342
|
+
typeof currentValue !== 'object' ||
|
|
1343
|
+
Array.isArray(currentValue)) {
|
|
1344
|
+
return currentValue;
|
|
1345
|
+
}
|
|
1346
|
+
return Object.fromEntries(Object.entries(currentValue).sort(([left], [right]) => left.localeCompare(right)));
|
|
1347
|
+
});
|
|
1348
|
+
}
|
|
1349
|
+
function serializeAgentReference(agent, agentIdentityKeys) {
|
|
1350
|
+
const identity = agentIdentityKeys.get(agent);
|
|
1351
|
+
if (!identity || identity === agent.name) {
|
|
1352
|
+
return { name: agent.name };
|
|
1353
|
+
}
|
|
1354
|
+
return { name: agent.name, identity };
|
|
1355
|
+
}
|
|
1356
|
+
function resolveSerializedAgent(serializedAgent, agentMap, fallbackAgent) {
|
|
1357
|
+
const identity = serializedAgent.identity ?? serializedAgent.name;
|
|
1358
|
+
const agent = agentMap.get(identity);
|
|
1359
|
+
if (agent) {
|
|
1360
|
+
return agent;
|
|
1361
|
+
}
|
|
1362
|
+
if (!serializedAgent.identity && fallbackAgent) {
|
|
1363
|
+
return fallbackAgent;
|
|
1364
|
+
}
|
|
1365
|
+
if (serializedAgent.identity) {
|
|
1366
|
+
throw new UserError(`Agent identity ${serializedAgent.identity} not found`);
|
|
1367
|
+
}
|
|
1368
|
+
throw new UserError(`Agent ${serializedAgent.name} not found`);
|
|
1369
|
+
}
|
|
1370
|
+
function serializeRunItem(item, agentIdentityKeys) {
|
|
1371
|
+
const serialized = item.toJSON();
|
|
1372
|
+
switch (item.type) {
|
|
1373
|
+
case 'handoff_output_item':
|
|
1374
|
+
serialized.sourceAgent = serializeAgentReference(item.sourceAgent, agentIdentityKeys);
|
|
1375
|
+
serialized.targetAgent = serializeAgentReference(item.targetAgent, agentIdentityKeys);
|
|
1376
|
+
return serialized;
|
|
1377
|
+
default:
|
|
1378
|
+
serialized.agent = serializeAgentReference(item.agent, agentIdentityKeys);
|
|
1379
|
+
return serialized;
|
|
1380
|
+
}
|
|
1381
|
+
}
|
|
1382
|
+
function serializeCurrentStep(currentStep, agentIdentityKeys) {
|
|
1383
|
+
if (!currentStep) {
|
|
1384
|
+
return undefined;
|
|
1385
|
+
}
|
|
1386
|
+
if (currentStep.type === 'next_step_handoff') {
|
|
1387
|
+
return {
|
|
1388
|
+
...currentStep,
|
|
1389
|
+
newAgent: serializeAgentReference(currentStep.newAgent, agentIdentityKeys),
|
|
1390
|
+
};
|
|
1391
|
+
}
|
|
1392
|
+
if (currentStep.type === 'next_step_interruption') {
|
|
1393
|
+
const interruptions = Array.isArray(currentStep.data?.interruptions)
|
|
1394
|
+
? currentStep.data.interruptions.map((item) => item instanceof RunToolApprovalItem
|
|
1395
|
+
? serializeRunItem(item, agentIdentityKeys)
|
|
1396
|
+
: item)
|
|
1397
|
+
: currentStep.data?.interruptions;
|
|
1398
|
+
return {
|
|
1399
|
+
...currentStep,
|
|
1400
|
+
data: {
|
|
1401
|
+
...currentStep.data,
|
|
1402
|
+
interruptions,
|
|
1403
|
+
},
|
|
1404
|
+
};
|
|
1405
|
+
}
|
|
1406
|
+
return currentStep;
|
|
1407
|
+
}
|
|
1408
|
+
function serializeProcessedResponse(processedResponse, agentIdentityKeys) {
|
|
1409
|
+
return {
|
|
1410
|
+
...processedResponse,
|
|
1411
|
+
newItems: processedResponse.newItems.map((item) => serializeRunItem(item, agentIdentityKeys)),
|
|
1412
|
+
};
|
|
1413
|
+
}
|
|
1143
1414
|
/**
|
|
1144
1415
|
* @internal
|
|
1145
1416
|
*/
|
|
@@ -1178,23 +1449,23 @@ export function deserializeModelResponse(serializedModelResponse) {
|
|
|
1178
1449
|
export function deserializeItem(serializedItem, agentMap) {
|
|
1179
1450
|
switch (serializedItem.type) {
|
|
1180
1451
|
case 'message_output_item':
|
|
1181
|
-
return new RunMessageOutputItem(serializedItem.rawItem,
|
|
1452
|
+
return new RunMessageOutputItem(serializedItem.rawItem, resolveSerializedAgent(serializedItem.agent, agentMap));
|
|
1182
1453
|
case 'tool_search_call_item':
|
|
1183
|
-
return new RunToolSearchCallItem(serializedItem.rawItem,
|
|
1454
|
+
return new RunToolSearchCallItem(serializedItem.rawItem, resolveSerializedAgent(serializedItem.agent, agentMap));
|
|
1184
1455
|
case 'tool_search_output_item':
|
|
1185
|
-
return new RunToolSearchOutputItem(serializedItem.rawItem,
|
|
1456
|
+
return new RunToolSearchOutputItem(serializedItem.rawItem, resolveSerializedAgent(serializedItem.agent, agentMap));
|
|
1186
1457
|
case 'tool_call_item':
|
|
1187
|
-
return new RunToolCallItem(serializedItem.rawItem,
|
|
1458
|
+
return new RunToolCallItem(serializedItem.rawItem, resolveSerializedAgent(serializedItem.agent, agentMap));
|
|
1188
1459
|
case 'tool_call_output_item':
|
|
1189
|
-
return new RunToolCallOutputItem(serializedItem.rawItem,
|
|
1460
|
+
return new RunToolCallOutputItem(serializedItem.rawItem, resolveSerializedAgent(serializedItem.agent, agentMap), serializedItem.output);
|
|
1190
1461
|
case 'reasoning_item':
|
|
1191
|
-
return new RunReasoningItem(serializedItem.rawItem,
|
|
1462
|
+
return new RunReasoningItem(serializedItem.rawItem, resolveSerializedAgent(serializedItem.agent, agentMap));
|
|
1192
1463
|
case 'handoff_call_item':
|
|
1193
|
-
return new RunHandoffCallItem(serializedItem.rawItem,
|
|
1464
|
+
return new RunHandoffCallItem(serializedItem.rawItem, resolveSerializedAgent(serializedItem.agent, agentMap));
|
|
1194
1465
|
case 'handoff_output_item':
|
|
1195
|
-
return new RunHandoffOutputItem(serializedItem.rawItem,
|
|
1466
|
+
return new RunHandoffOutputItem(serializedItem.rawItem, resolveSerializedAgent(serializedItem.sourceAgent, agentMap), resolveSerializedAgent(serializedItem.targetAgent, agentMap));
|
|
1196
1467
|
case 'tool_approval_item':
|
|
1197
|
-
return new RunToolApprovalItem(serializedItem.rawItem,
|
|
1468
|
+
return new RunToolApprovalItem(serializedItem.rawItem, resolveSerializedAgent(serializedItem.agent, agentMap), serializedItem.toolName);
|
|
1198
1469
|
}
|
|
1199
1470
|
}
|
|
1200
1471
|
function deserializeInterruptionItem(serializedItem, agentMap, currentAgent) {
|
|
@@ -1204,7 +1475,7 @@ function deserializeInterruptionItem(serializedItem, agentMap, currentAgent) {
|
|
|
1204
1475
|
const parsed = itemSchema.safeParse(serializedItem);
|
|
1205
1476
|
if (parsed.success) {
|
|
1206
1477
|
if (parsed.data.type === 'tool_approval_item') {
|
|
1207
|
-
const mappedAgent =
|
|
1478
|
+
const mappedAgent = resolveSerializedAgent(parsed.data.agent, agentMap, currentAgent);
|
|
1208
1479
|
return new RunToolApprovalItem(parsed.data.rawItem, mappedAgent, parsed.data.toolName);
|
|
1209
1480
|
}
|
|
1210
1481
|
const item = deserializeItem(parsed.data, agentMap);
|
|
@@ -1228,7 +1499,15 @@ function deserializeInterruptionItem(serializedItem, agentMap, currentAgent) {
|
|
|
1228
1499
|
const agentName = value.agent && typeof value.agent.name === 'string'
|
|
1229
1500
|
? value.agent.name
|
|
1230
1501
|
: undefined;
|
|
1231
|
-
const
|
|
1502
|
+
const agentIdentity = value.agent && typeof value.agent.identity === 'string'
|
|
1503
|
+
? value.agent.identity
|
|
1504
|
+
: undefined;
|
|
1505
|
+
const mappedAgent = agentName || agentIdentity
|
|
1506
|
+
? resolveSerializedAgent({
|
|
1507
|
+
name: agentName ?? currentAgent.name,
|
|
1508
|
+
identity: agentIdentity,
|
|
1509
|
+
}, agentMap, currentAgent)
|
|
1510
|
+
: currentAgent;
|
|
1232
1511
|
const toolName = typeof value.toolName === 'string'
|
|
1233
1512
|
? value.toolName
|
|
1234
1513
|
: typeof rawItem.name === 'string'
|