@librechat/agents 3.4.0 → 3.4.2
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/cjs/agents/AgentContext.cjs.map +1 -1
- package/dist/cjs/graphs/Graph.cjs +165 -57
- package/dist/cjs/graphs/Graph.cjs.map +1 -1
- package/dist/cjs/graphs/MultiAgentGraph.cjs +81 -33
- package/dist/cjs/graphs/MultiAgentGraph.cjs.map +1 -1
- package/dist/cjs/graphs/applyGraphRuntimeConfig.cjs +14 -0
- package/dist/cjs/graphs/applyGraphRuntimeConfig.cjs.map +1 -0
- package/dist/cjs/graphs/createGraph.cjs +15 -0
- package/dist/cjs/graphs/createGraph.cjs.map +1 -0
- package/dist/cjs/graphs/index.cjs +1 -0
- package/dist/cjs/hooks/HookRegistry.cjs +83 -0
- package/dist/cjs/hooks/HookRegistry.cjs.map +1 -1
- package/dist/cjs/hooks/createWorkspacePolicyHook.cjs +1 -1
- package/dist/cjs/hooks/executeHooks.cjs +60 -14
- package/dist/cjs/hooks/executeHooks.cjs.map +1 -1
- package/dist/cjs/hooks/index.cjs.map +1 -1
- package/dist/cjs/hooks/types.cjs +2 -0
- package/dist/cjs/hooks/types.cjs.map +1 -1
- package/dist/cjs/llm/init.cjs +3 -3
- package/dist/cjs/llm/invoke.cjs +2 -2
- package/dist/cjs/main.cjs +34 -24
- package/dist/cjs/messages/format.cjs +40 -23
- package/dist/cjs/messages/format.cjs.map +1 -1
- package/dist/cjs/run.cjs +130 -53
- package/dist/cjs/run.cjs.map +1 -1
- package/dist/cjs/session/AgentSession.cjs +37 -2
- package/dist/cjs/session/AgentSession.cjs.map +1 -1
- package/dist/cjs/session/JsonlSessionStore.cjs +2 -2
- package/dist/cjs/stream.cjs +1 -1
- package/dist/cjs/summarization/node.cjs +6 -3
- package/dist/cjs/summarization/node.cjs.map +1 -1
- package/dist/cjs/tools/BashExecutor.cjs +1 -1
- package/dist/cjs/tools/CodeExecutor.cjs +1 -1
- package/dist/cjs/tools/ProgrammaticToolCalling.cjs +1 -1
- package/dist/cjs/tools/SubagentTool.cjs +4 -4
- package/dist/cjs/tools/SubagentTool.cjs.map +1 -1
- package/dist/cjs/tools/ToolNode.cjs +321 -95
- package/dist/cjs/tools/ToolNode.cjs.map +1 -1
- package/dist/cjs/tools/ToolSearch.cjs +1 -1
- package/dist/cjs/tools/eagerEventExecution.cjs +1 -0
- package/dist/cjs/tools/local/LocalExecutionEngine.cjs +3 -3
- package/dist/cjs/tools/local/LocalProgrammaticToolCalling.cjs +2 -2
- package/dist/cjs/tools/search/rerankers.cjs +154 -1
- package/dist/cjs/tools/search/rerankers.cjs.map +1 -1
- package/dist/cjs/tools/search/tool.cjs +4 -1
- package/dist/cjs/tools/search/tool.cjs.map +1 -1
- package/dist/cjs/tools/subagent/SubagentExecutionRegistry.cjs +601 -0
- package/dist/cjs/tools/subagent/SubagentExecutionRegistry.cjs.map +1 -0
- package/dist/cjs/tools/subagent/SubagentExecutor.cjs +1114 -233
- package/dist/cjs/tools/subagent/SubagentExecutor.cjs.map +1 -1
- package/dist/cjs/tools/subagent/SubagentReplay.cjs +177 -0
- package/dist/cjs/tools/subagent/SubagentReplay.cjs.map +1 -0
- package/dist/cjs/tools/subagent/childGraphConfig.cjs +278 -0
- package/dist/cjs/tools/subagent/childGraphConfig.cjs.map +1 -0
- package/dist/cjs/tools/subagent/index.cjs +1 -0
- package/dist/cjs/tools/subagent/runtimeLimits.cjs +5 -0
- package/dist/cjs/tools/subagent/runtimeLimits.cjs.map +1 -0
- package/dist/cjs/tools/toolOutputReferences.cjs +20 -0
- package/dist/cjs/tools/toolOutputReferences.cjs.map +1 -1
- package/dist/cjs/utils/index.cjs +2 -2
- package/dist/esm/agents/AgentContext.mjs.map +1 -1
- package/dist/esm/graphs/Graph.mjs +165 -57
- package/dist/esm/graphs/Graph.mjs.map +1 -1
- package/dist/esm/graphs/MultiAgentGraph.mjs +81 -33
- package/dist/esm/graphs/MultiAgentGraph.mjs.map +1 -1
- package/dist/esm/graphs/applyGraphRuntimeConfig.mjs +14 -0
- package/dist/esm/graphs/applyGraphRuntimeConfig.mjs.map +1 -0
- package/dist/esm/graphs/createGraph.mjs +15 -0
- package/dist/esm/graphs/createGraph.mjs.map +1 -0
- package/dist/esm/graphs/index.mjs +1 -0
- package/dist/esm/hooks/HookRegistry.mjs +83 -0
- package/dist/esm/hooks/HookRegistry.mjs.map +1 -1
- package/dist/esm/hooks/createWorkspacePolicyHook.mjs +1 -1
- package/dist/esm/hooks/executeHooks.mjs +60 -14
- package/dist/esm/hooks/executeHooks.mjs.map +1 -1
- package/dist/esm/hooks/index.mjs.map +1 -1
- package/dist/esm/hooks/types.mjs +2 -1
- package/dist/esm/hooks/types.mjs.map +1 -1
- package/dist/esm/llm/init.mjs +1 -1
- package/dist/esm/llm/invoke.mjs +2 -2
- package/dist/esm/main.mjs +21 -19
- package/dist/esm/messages/format.mjs +40 -23
- package/dist/esm/messages/format.mjs.map +1 -1
- package/dist/esm/run.mjs +131 -54
- package/dist/esm/run.mjs.map +1 -1
- package/dist/esm/session/AgentSession.mjs +37 -2
- package/dist/esm/session/AgentSession.mjs.map +1 -1
- package/dist/esm/session/JsonlSessionStore.mjs +2 -2
- package/dist/esm/stream.mjs +1 -1
- package/dist/esm/summarization/node.mjs +6 -3
- package/dist/esm/summarization/node.mjs.map +1 -1
- package/dist/esm/tools/BashExecutor.mjs +1 -1
- package/dist/esm/tools/CodeExecutor.mjs +1 -1
- package/dist/esm/tools/ProgrammaticToolCalling.mjs +1 -1
- package/dist/esm/tools/SubagentTool.mjs +4 -4
- package/dist/esm/tools/SubagentTool.mjs.map +1 -1
- package/dist/esm/tools/ToolNode.mjs +322 -96
- package/dist/esm/tools/ToolNode.mjs.map +1 -1
- package/dist/esm/tools/ToolSearch.mjs +1 -1
- package/dist/esm/tools/eagerEventExecution.mjs +1 -1
- package/dist/esm/tools/local/LocalExecutionEngine.mjs +3 -3
- package/dist/esm/tools/local/LocalProgrammaticToolCalling.mjs +2 -2
- package/dist/esm/tools/search/rerankers.mjs +154 -1
- package/dist/esm/tools/search/rerankers.mjs.map +1 -1
- package/dist/esm/tools/search/tool.mjs +4 -1
- package/dist/esm/tools/search/tool.mjs.map +1 -1
- package/dist/esm/tools/subagent/SubagentExecutionRegistry.mjs +597 -0
- package/dist/esm/tools/subagent/SubagentExecutionRegistry.mjs.map +1 -0
- package/dist/esm/tools/subagent/SubagentExecutor.mjs +1114 -233
- package/dist/esm/tools/subagent/SubagentExecutor.mjs.map +1 -1
- package/dist/esm/tools/subagent/SubagentReplay.mjs +170 -0
- package/dist/esm/tools/subagent/SubagentReplay.mjs.map +1 -0
- package/dist/esm/tools/subagent/childGraphConfig.mjs +272 -0
- package/dist/esm/tools/subagent/childGraphConfig.mjs.map +1 -0
- package/dist/esm/tools/subagent/index.mjs +1 -0
- package/dist/esm/tools/subagent/runtimeLimits.mjs +5 -0
- package/dist/esm/tools/subagent/runtimeLimits.mjs.map +1 -0
- package/dist/esm/tools/toolOutputReferences.mjs +20 -0
- package/dist/esm/tools/toolOutputReferences.mjs.map +1 -1
- package/dist/esm/utils/index.mjs +2 -2
- package/dist/types/agents/AgentContext.d.ts +1 -1
- package/dist/types/graphs/Graph.d.ts +22 -2
- package/dist/types/graphs/MultiAgentGraph.d.ts +7 -1
- package/dist/types/graphs/applyGraphRuntimeConfig.d.ts +3 -0
- package/dist/types/graphs/createGraph.d.ts +13 -0
- package/dist/types/graphs/graphFactory.d.ts +13 -0
- package/dist/types/graphs/index.d.ts +2 -0
- package/dist/types/hooks/HookRegistry.d.ts +10 -1
- package/dist/types/hooks/executeHooks.d.ts +5 -1
- package/dist/types/hooks/index.d.ts +2 -2
- package/dist/types/hooks/types.d.ts +12 -0
- package/dist/types/run.d.ts +6 -3
- package/dist/types/session/AgentSession.d.ts +1 -0
- package/dist/types/tools/SubagentTool.d.ts +1 -1
- package/dist/types/tools/ToolNode.d.ts +23 -15
- package/dist/types/tools/search/rerankers.d.ts +28 -0
- package/dist/types/tools/search/types.d.ts +38 -1
- package/dist/types/tools/subagent/SubagentExecutionRegistry.d.ts +171 -0
- package/dist/types/tools/subagent/SubagentExecutor.d.ts +70 -36
- package/dist/types/tools/subagent/SubagentReplay.d.ts +85 -0
- package/dist/types/tools/subagent/childGraphConfig.d.ts +37 -0
- package/dist/types/tools/subagent/index.d.ts +1 -1
- package/dist/types/tools/subagent/runtimeLimits.d.ts +4 -0
- package/dist/types/tools/toolOutputReferences.d.ts +12 -0
- package/dist/types/types/graph.d.ts +189 -24
- package/dist/types/types/hitl.d.ts +15 -0
- package/package.json +8 -2
- package/src/agents/AgentContext.ts +1 -1
- package/src/graphs/Graph.ts +349 -104
- package/src/graphs/MultiAgentGraph.ts +149 -47
- package/src/graphs/__tests__/Graph.breakerLifecycle.test.ts +48 -9
- package/src/graphs/__tests__/Graph.contextOverflow.test.ts +1 -1
- package/src/graphs/__tests__/Graph.subagentResumeState.test.ts +80 -0
- package/src/graphs/__tests__/MultiAgentGraph.test.ts +86 -0
- package/src/graphs/__tests__/composition.smoke.test.ts +152 -0
- package/src/graphs/__tests__/createGraph.test.ts +206 -0
- package/src/graphs/applyGraphRuntimeConfig.ts +25 -0
- package/src/graphs/createGraph.ts +32 -0
- package/src/graphs/graphFactory.ts +12 -0
- package/src/graphs/index.ts +2 -0
- package/src/hooks/HookRegistry.ts +151 -1
- package/src/hooks/__tests__/HookRegistry.test.ts +96 -0
- package/src/hooks/__tests__/executeHooks.test.ts +160 -0
- package/src/hooks/executeHooks.ts +133 -15
- package/src/hooks/index.ts +3 -1
- package/src/hooks/types.ts +16 -0
- package/src/messages/format.ts +54 -26
- package/src/messages/formatAgentMessages.reducer.test.ts +162 -0
- package/src/messages/formatAgentMessages.steer.test.ts +16 -11
- package/src/messages/formatAgentMessages.test.ts +7 -2
- package/src/run.ts +214 -56
- package/src/session/AgentSession.ts +52 -2
- package/src/session/__tests__/JsonlSessionStore.test.ts +53 -0
- package/src/specs/graph-subagent.live.test.ts +242 -0
- package/src/specs/graph-subagent.test.ts +322 -0
- package/src/specs/langfuse-routing.integration.test.ts +120 -1
- package/src/specs/subagent.test.ts +130 -4
- package/src/summarization/__tests__/node.test.ts +32 -14
- package/src/summarization/node.ts +15 -11
- package/src/tools/SubagentTool.ts +4 -4
- package/src/tools/ToolNode.ts +643 -157
- package/src/tools/__tests__/SubagentExecutor.test.ts +740 -15
- package/src/tools/__tests__/SubagentReplay.test.ts +329 -0
- package/src/tools/__tests__/ToolNode.breakerSignal.test.ts +208 -2
- package/src/tools/__tests__/directToolHITLResumeScope.test.ts +512 -2
- package/src/tools/__tests__/hitl.test.ts +234 -5
- package/src/tools/__tests__/subagentHooks.test.ts +1126 -61
- package/src/tools/__tests__/toolOutputReferences.test.ts +19 -2
- package/src/tools/search/rag-api-reranker.test.ts +891 -0
- package/src/tools/search/rerankers.ts +260 -0
- package/src/tools/search/tool.ts +6 -0
- package/src/tools/search/types.ts +45 -1
- package/src/tools/subagent/SubagentExecutionRegistry.ts +1159 -0
- package/src/tools/subagent/SubagentExecutor.ts +2232 -312
- package/src/tools/subagent/SubagentReplay.ts +584 -0
- package/src/tools/subagent/__tests__/SubagentExecutionRegistry.test.ts +637 -0
- package/src/tools/subagent/__tests__/SubagentExecutor.lazy.test.ts +3054 -0
- package/src/tools/subagent/__tests__/childGraphConfig.test.ts +521 -0
- package/src/tools/subagent/childGraphConfig.ts +694 -0
- package/src/tools/subagent/index.ts +6 -0
- package/src/tools/subagent/runtimeLimits.ts +7 -0
- package/src/tools/toolOutputReferences.ts +40 -1
- package/src/types/graph.ts +222 -24
- package/src/types/hitl.ts +16 -0
package/src/graphs/Graph.ts
CHANGED
|
@@ -17,12 +17,23 @@ import type {
|
|
|
17
17
|
MessageContent,
|
|
18
18
|
} from '@langchain/core/messages';
|
|
19
19
|
import type { ToolCall } from '@langchain/core/messages/tool';
|
|
20
|
+
import type {
|
|
21
|
+
ReplayableSubagentTool,
|
|
22
|
+
SubagentGraphResumeState,
|
|
23
|
+
SubagentResumeManifest,
|
|
24
|
+
SubagentToolNodeResumeState,
|
|
25
|
+
SettledSubagentToolOutput,
|
|
26
|
+
} from '@/tools/subagent/SubagentReplay';
|
|
20
27
|
import type {
|
|
21
28
|
ResolvedStreamLimits,
|
|
22
29
|
RunBreakerScope,
|
|
23
30
|
StreamedToolCallArgTally,
|
|
24
31
|
StreamDeltaEventTally,
|
|
25
32
|
} from '@/llm/streamLimits';
|
|
33
|
+
import type {
|
|
34
|
+
GraphFactory,
|
|
35
|
+
GraphFactoryDependencies,
|
|
36
|
+
} from '@/graphs/graphFactory';
|
|
26
37
|
import type { OverflowRecoveryPlan } from '@/llm/contextOverflowRecovery';
|
|
27
38
|
import type { FallbackErrorContext } from '@/llm/invoke';
|
|
28
39
|
import type { HookRegistry } from '@/hooks';
|
|
@@ -60,14 +71,6 @@ import {
|
|
|
60
71
|
appendPredecessorHandoffCue,
|
|
61
72
|
removePredecessorHandoffCue,
|
|
62
73
|
} from '@/messages';
|
|
63
|
-
import {
|
|
64
|
-
attemptInvoke,
|
|
65
|
-
tryFallbackProviders,
|
|
66
|
-
getFallbackErrorContext,
|
|
67
|
-
getFallbackOverflowCandidates,
|
|
68
|
-
projectMessagesForProvider,
|
|
69
|
-
resolveServingModelId,
|
|
70
|
-
} from '@/llm/invoke';
|
|
71
74
|
import {
|
|
72
75
|
resetIfNotEmpty,
|
|
73
76
|
isAnthropicLike,
|
|
@@ -79,6 +82,27 @@ import {
|
|
|
79
82
|
joinKeys,
|
|
80
83
|
sleep,
|
|
81
84
|
} from '@/utils';
|
|
85
|
+
import {
|
|
86
|
+
attemptInvoke,
|
|
87
|
+
tryFallbackProviders,
|
|
88
|
+
getFallbackErrorContext,
|
|
89
|
+
getFallbackOverflowCandidates,
|
|
90
|
+
projectMessagesForProvider,
|
|
91
|
+
resolveServingModelId,
|
|
92
|
+
} from '@/llm/invoke';
|
|
93
|
+
import {
|
|
94
|
+
resolveStreamLimits,
|
|
95
|
+
StreamLimitExceededError,
|
|
96
|
+
sweepStaleStreamLimitEntries,
|
|
97
|
+
STREAM_LIMIT_EPOCH_KEY,
|
|
98
|
+
RUN_BREAKER_SCOPE_CONFIG_KEY,
|
|
99
|
+
} from '@/llm/streamLimits';
|
|
100
|
+
import {
|
|
101
|
+
DEFAULT_SUBAGENT_DESCRIPTION,
|
|
102
|
+
SubagentExecutor,
|
|
103
|
+
isGraphSubagentConfig,
|
|
104
|
+
normalizeSubagentConfigEntries,
|
|
105
|
+
} from '@/tools/subagent';
|
|
82
106
|
import {
|
|
83
107
|
Constants,
|
|
84
108
|
GraphNodeKeys,
|
|
@@ -122,18 +146,12 @@ import {
|
|
|
122
146
|
findCallback,
|
|
123
147
|
type CallbackEntry,
|
|
124
148
|
} from '@/utils/callbacks';
|
|
125
|
-
import {
|
|
126
|
-
resolveStreamLimits,
|
|
127
|
-
StreamLimitExceededError,
|
|
128
|
-
sweepStaleStreamLimitEntries,
|
|
129
|
-
STREAM_LIMIT_EPOCH_KEY,
|
|
130
|
-
RUN_BREAKER_SCOPE_CONFIG_KEY,
|
|
131
|
-
} from '@/llm/streamLimits';
|
|
132
149
|
import { partitionAndMarkOpenRouterToolCache } from '@/llm/openrouter/toolCache';
|
|
133
150
|
import { ToolNode as CustomToolNode, toolsCondition } from '@/tools/ToolNode';
|
|
134
151
|
import { shouldTraceToolNodeForLangfuse } from '@/langfuseToolOutputTracing';
|
|
135
152
|
import { createLocalCodingToolBundle } from '@/tools/local/LocalCodingTools';
|
|
136
|
-
import {
|
|
153
|
+
import { SUBAGENT_REPLAY_CONTROLLER } from '@/tools/subagent/SubagentReplay';
|
|
154
|
+
import { applyGraphRuntimeConfig } from '@/graphs/applyGraphRuntimeConfig';
|
|
137
155
|
import { partitionAndMarkBedrockToolCache } from '@/llm/bedrock/toolCache';
|
|
138
156
|
import { safeDispatchCustomEvent, emitAgentLog } from '@/utils/events';
|
|
139
157
|
import { createCloudflareCodingToolBundle } from '@/tools/cloudflare';
|
|
@@ -171,15 +189,21 @@ const EMPTY_PREEMPT_BOUNDARY: PreemptBoundaryResult = {
|
|
|
171
189
|
/** Minimum relative variance before calibrated toolSchemaTokens overrides current value. */
|
|
172
190
|
const CALIBRATION_VARIANCE_THRESHOLD = 0.15;
|
|
173
191
|
|
|
174
|
-
function
|
|
192
|
+
function createChildHandlerRegistry(
|
|
175
193
|
source: HandlerRegistry | undefined
|
|
176
194
|
): HandlerRegistry | undefined {
|
|
177
195
|
const toolHandler = source?.getHandler(GraphEvents.ON_TOOL_EXECUTE);
|
|
178
|
-
|
|
196
|
+
const updateHandler = source?.getHandler(GraphEvents.ON_SUBAGENT_UPDATE);
|
|
197
|
+
if (toolHandler == null && updateHandler == null) {
|
|
179
198
|
return undefined;
|
|
180
199
|
}
|
|
181
200
|
const registry = new HandlerRegistry();
|
|
182
|
-
|
|
201
|
+
if (toolHandler != null) {
|
|
202
|
+
registry.register(GraphEvents.ON_TOOL_EXECUTE, toolHandler);
|
|
203
|
+
}
|
|
204
|
+
if (updateHandler != null) {
|
|
205
|
+
registry.register(GraphEvents.ON_SUBAGENT_UPDATE, updateHandler);
|
|
206
|
+
}
|
|
183
207
|
return registry;
|
|
184
208
|
}
|
|
185
209
|
|
|
@@ -630,6 +654,10 @@ export abstract class Graph<
|
|
|
630
654
|
_TNodeName extends string = string,
|
|
631
655
|
> {
|
|
632
656
|
abstract resetValues(keepContent?: boolean, checkpointScope?: string): void;
|
|
657
|
+
restoreCheckpointMessages(
|
|
658
|
+
_messages: BaseMessage[],
|
|
659
|
+
_pendingMessages?: BaseMessage[]
|
|
660
|
+
): void {}
|
|
633
661
|
abstract initializeTools({
|
|
634
662
|
currentTools,
|
|
635
663
|
currentToolMap,
|
|
@@ -848,11 +876,18 @@ export abstract class Graph<
|
|
|
848
876
|
// Flush each compiled ToolNode's direct-path turn cache so it
|
|
849
877
|
// doesn't leak across Runs (Codex P2 #33). The cache survives
|
|
850
878
|
// `run()` re-entry by design (resume-stable), but end-of-Run
|
|
851
|
-
// is the right point to reset it.
|
|
879
|
+
// is the right point to reset it. Retain the registrations because
|
|
880
|
+
// the compiled workflow can be reused for later Runs; compilation
|
|
881
|
+
// will not register these instances again.
|
|
852
882
|
for (const node of this._compiledToolNodes) {
|
|
853
883
|
node.clearDirectPathTurns();
|
|
854
884
|
}
|
|
855
|
-
|
|
885
|
+
// Subagent executors are likewise compiled once and reused. Clear
|
|
886
|
+
// their per-Run state without dropping the registrations needed by
|
|
887
|
+
// subsequent cleanup cycles.
|
|
888
|
+
for (const executor of this._subagentExecutors) {
|
|
889
|
+
executor.clearHeavyState();
|
|
890
|
+
}
|
|
856
891
|
this.sessions.clear();
|
|
857
892
|
}
|
|
858
893
|
|
|
@@ -904,10 +939,137 @@ export abstract class Graph<
|
|
|
904
939
|
*/
|
|
905
940
|
protected registerCompiledToolNode(node: {
|
|
906
941
|
clearDirectPathTurns(): void;
|
|
942
|
+
createSubagentResumeState(): SubagentToolNodeResumeState;
|
|
943
|
+
restoreSubagentResumeState(state: SubagentToolNodeResumeState): void;
|
|
907
944
|
}): void {
|
|
908
945
|
this._compiledToolNodes.add(node);
|
|
909
946
|
}
|
|
910
947
|
|
|
948
|
+
protected registerSubagentExecutor(executor: SubagentExecutor): void {
|
|
949
|
+
this._subagentExecutors.add(executor);
|
|
950
|
+
}
|
|
951
|
+
|
|
952
|
+
protected resetSubagentCheckpointThreadIds(): void {
|
|
953
|
+
for (const executor of this._subagentExecutors) {
|
|
954
|
+
executor.resetCheckpointThreadIds();
|
|
955
|
+
}
|
|
956
|
+
}
|
|
957
|
+
|
|
958
|
+
getChildCheckpointThreadIds(): string[] {
|
|
959
|
+
const threadIds = new Set<string>();
|
|
960
|
+
for (const executor of this._subagentExecutors) {
|
|
961
|
+
for (const threadId of executor.getChildCheckpointThreadIds()) {
|
|
962
|
+
threadIds.add(threadId);
|
|
963
|
+
}
|
|
964
|
+
}
|
|
965
|
+
return [...threadIds];
|
|
966
|
+
}
|
|
967
|
+
|
|
968
|
+
createSubagentResumeState(runId: string): SubagentGraphResumeState {
|
|
969
|
+
return {
|
|
970
|
+
toolCallSteps: [...this.toolCallStepIds].map(([toolCallId, stepId]) => ({
|
|
971
|
+
toolCallId,
|
|
972
|
+
stepId,
|
|
973
|
+
})),
|
|
974
|
+
toolSessions: [...this.sessions].map(([toolName, context]) => ({
|
|
975
|
+
toolName,
|
|
976
|
+
context: {
|
|
977
|
+
...context,
|
|
978
|
+
...(context.files == null
|
|
979
|
+
? {}
|
|
980
|
+
: { files: context.files.map((file) => ({ ...file })) }),
|
|
981
|
+
},
|
|
982
|
+
})),
|
|
983
|
+
toolNodes: [...this._compiledToolNodes].map((node) =>
|
|
984
|
+
node.createSubagentResumeState()
|
|
985
|
+
),
|
|
986
|
+
eagerToolUsage: [
|
|
987
|
+
{
|
|
988
|
+
agentId: '',
|
|
989
|
+
toolUsageCounts: [...this.eagerEventToolUsageCount].map(
|
|
990
|
+
([toolName, count]) => ({ toolName, count })
|
|
991
|
+
),
|
|
992
|
+
},
|
|
993
|
+
...[...this.eagerEventToolUsageCountsByAgentId].map(
|
|
994
|
+
([agentId, usageCounts]) => ({
|
|
995
|
+
agentId,
|
|
996
|
+
toolUsageCounts: [...usageCounts].map(([toolName, count]) => ({
|
|
997
|
+
toolName,
|
|
998
|
+
count,
|
|
999
|
+
})),
|
|
1000
|
+
})
|
|
1001
|
+
),
|
|
1002
|
+
],
|
|
1003
|
+
eagerToolSuppressions: [...this.eagerEventToolSuppressions],
|
|
1004
|
+
...(this._toolOutputRegistry == null
|
|
1005
|
+
? {}
|
|
1006
|
+
: {
|
|
1007
|
+
toolOutputReferences: this._toolOutputRegistry.snapshotState(runId),
|
|
1008
|
+
}),
|
|
1009
|
+
};
|
|
1010
|
+
}
|
|
1011
|
+
|
|
1012
|
+
restoreSubagentResumeState(
|
|
1013
|
+
state: SubagentGraphResumeState,
|
|
1014
|
+
runId: string
|
|
1015
|
+
): void {
|
|
1016
|
+
const toolNodesByKey = new Map(
|
|
1017
|
+
[...this._compiledToolNodes].map((node) => {
|
|
1018
|
+
const nodeState = node.createSubagentResumeState();
|
|
1019
|
+
return [nodeState.stateKey, node] as const;
|
|
1020
|
+
})
|
|
1021
|
+
);
|
|
1022
|
+
if (toolNodesByKey.size !== state.toolNodes.length) {
|
|
1023
|
+
throw new Error('Cannot restore changed subagent tool topology.');
|
|
1024
|
+
}
|
|
1025
|
+
for (const nodeState of state.toolNodes) {
|
|
1026
|
+
if (!toolNodesByKey.has(nodeState.stateKey)) {
|
|
1027
|
+
throw new Error(
|
|
1028
|
+
`Cannot restore subagent tool state for "${nodeState.stateKey}".`
|
|
1029
|
+
);
|
|
1030
|
+
}
|
|
1031
|
+
}
|
|
1032
|
+
const registry =
|
|
1033
|
+
state.toolOutputReferences == null
|
|
1034
|
+
? undefined
|
|
1035
|
+
: this.getOrCreateToolOutputRegistry();
|
|
1036
|
+
if (state.toolOutputReferences != null && registry == null) {
|
|
1037
|
+
throw new Error('Cannot restore disabled tool output references.');
|
|
1038
|
+
}
|
|
1039
|
+
|
|
1040
|
+
this.toolCallStepIds.clear();
|
|
1041
|
+
for (const { toolCallId, stepId } of state.toolCallSteps) {
|
|
1042
|
+
this.toolCallStepIds.set(toolCallId, stepId);
|
|
1043
|
+
}
|
|
1044
|
+
this.sessions.clear();
|
|
1045
|
+
for (const { toolName, context } of state.toolSessions) {
|
|
1046
|
+
this.sessions.set(toolName, {
|
|
1047
|
+
...context,
|
|
1048
|
+
...(context.files == null
|
|
1049
|
+
? {}
|
|
1050
|
+
: { files: context.files.map((file) => ({ ...file })) }),
|
|
1051
|
+
});
|
|
1052
|
+
}
|
|
1053
|
+
for (const nodeState of state.toolNodes) {
|
|
1054
|
+
const node = toolNodesByKey.get(nodeState.stateKey)!;
|
|
1055
|
+
node.restoreSubagentResumeState(nodeState);
|
|
1056
|
+
}
|
|
1057
|
+
this.clearEagerEventToolUsageCounts();
|
|
1058
|
+
for (const usageState of state.eagerToolUsage) {
|
|
1059
|
+
const usageCounts = this.getEagerEventToolUsageCount(usageState.agentId);
|
|
1060
|
+
for (const { toolName, count } of usageState.toolUsageCounts) {
|
|
1061
|
+
usageCounts.set(toolName, count);
|
|
1062
|
+
}
|
|
1063
|
+
}
|
|
1064
|
+
this.eagerEventToolSuppressions.clear();
|
|
1065
|
+
for (const toolName of state.eagerToolSuppressions) {
|
|
1066
|
+
this.eagerEventToolSuppressions.add(toolName);
|
|
1067
|
+
}
|
|
1068
|
+
if (state.toolOutputReferences != null && registry != null) {
|
|
1069
|
+
registry.restoreState(runId, state.toolOutputReferences);
|
|
1070
|
+
}
|
|
1071
|
+
}
|
|
1072
|
+
|
|
911
1073
|
/**
|
|
912
1074
|
* Returns the shared `ToolOutputReferenceRegistry` for this run,
|
|
913
1075
|
* constructing it on first access. Returns `undefined` when the
|
|
@@ -957,7 +1119,10 @@ export abstract class Graph<
|
|
|
957
1119
|
*/
|
|
958
1120
|
private _compiledToolNodes: Set<{
|
|
959
1121
|
clearDirectPathTurns(): void;
|
|
1122
|
+
createSubagentResumeState(): SubagentToolNodeResumeState;
|
|
1123
|
+
restoreSubagentResumeState(state: SubagentToolNodeResumeState): void;
|
|
960
1124
|
}> = new Set();
|
|
1125
|
+
private _subagentExecutors = new Set<SubagentExecutor>();
|
|
961
1126
|
public getOrCreateFileCheckpointer(): t.LocalFileCheckpointer | undefined {
|
|
962
1127
|
// Return the cached instance unconditionally if one exists. The
|
|
963
1128
|
// toolExecution check below decides whether to *create* a new
|
|
@@ -999,11 +1164,15 @@ export abstract class Graph<
|
|
|
999
1164
|
export class StandardGraph extends Graph<t.BaseGraphState, t.GraphNode> {
|
|
1000
1165
|
overrideModel?: t.ChatModel;
|
|
1001
1166
|
private subagentModelOverride?: t.ChatModel;
|
|
1167
|
+
private readonly graphFactory: GraphFactory;
|
|
1168
|
+
private readonly supportsMultiAgentChildren: boolean;
|
|
1002
1169
|
/** Optional compile options passed into workflow.compile() */
|
|
1003
1170
|
compileOptions?: t.CompileOptions | undefined;
|
|
1004
1171
|
/** Whether the workflow was actually compiled with a checkpointer. */
|
|
1005
1172
|
hasCompiledCheckpointer: boolean = false;
|
|
1006
1173
|
messages: BaseMessage[] = [];
|
|
1174
|
+
/** Whether a rebuilt resume seeded the message baseline from its checkpoint. */
|
|
1175
|
+
private hasRestoredCheckpointMessages = false;
|
|
1007
1176
|
/** Cached run messages preserved before clearHeavyState() so getRunMessages() works after cleanup. */
|
|
1008
1177
|
private cachedRunMessages?: BaseMessage[];
|
|
1009
1178
|
/** Per-agent discovery snapshots preserved before contexts are reset on cleanup. */
|
|
@@ -1045,6 +1214,8 @@ export class StandardGraph extends Graph<t.BaseGraphState, t.GraphNode> {
|
|
|
1045
1214
|
subagentUsageSink?: t.SubagentUsageSink;
|
|
1046
1215
|
/** See {@link t.StandardGraphInput.subagentScope}. */
|
|
1047
1216
|
subagentScope: boolean;
|
|
1217
|
+
/** See {@link t.StandardGraphInput.subagentExecutionContext}. */
|
|
1218
|
+
private readonly subagentExecutionContext?: t.SubagentExecutionContext;
|
|
1048
1219
|
/** See {@link t.StandardGraphInput.preemption}. */
|
|
1049
1220
|
preemption?: t.StreamPreemption;
|
|
1050
1221
|
/**
|
|
@@ -1058,8 +1229,7 @@ export class StandardGraph extends Graph<t.BaseGraphState, t.GraphNode> {
|
|
|
1058
1229
|
* generation key + chunk index (see `resolveGenerationKey`). Per-run
|
|
1059
1230
|
* accumulation state, cleared by both reset paths.
|
|
1060
1231
|
*/
|
|
1061
|
-
streamedToolCallArgTallies: Map<string, StreamedToolCallArgTally> =
|
|
1062
|
-
new Map();
|
|
1232
|
+
streamedToolCallArgTallies: Map<string, StreamedToolCallArgTally> = new Map();
|
|
1063
1233
|
/** Streamed chunk events per model generation, keyed by generation key. */
|
|
1064
1234
|
streamDeltaEventCounts: Map<string, StreamDeltaEventTally> = new Map();
|
|
1065
1235
|
/** Per-chunk-object, per-generation charge balances (lazily created; see
|
|
@@ -1167,26 +1337,42 @@ export class StandardGraph extends Graph<t.BaseGraphState, t.GraphNode> {
|
|
|
1167
1337
|
*/
|
|
1168
1338
|
pendingPreemptReturn = new Set<string>();
|
|
1169
1339
|
|
|
1170
|
-
constructor(
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1340
|
+
constructor(
|
|
1341
|
+
{
|
|
1342
|
+
runId,
|
|
1343
|
+
signal,
|
|
1344
|
+
agents,
|
|
1345
|
+
langfuse,
|
|
1346
|
+
tokenCounter,
|
|
1347
|
+
indexTokenCountMap,
|
|
1348
|
+
calibrationRatio,
|
|
1349
|
+
subagentUsageSink,
|
|
1350
|
+
subagentScope,
|
|
1351
|
+
subagentExecutionContext,
|
|
1352
|
+
preemption,
|
|
1353
|
+
streamLimits,
|
|
1354
|
+
}: t.StandardGraphInput,
|
|
1355
|
+
dependencies?: GraphFactoryDependencies
|
|
1356
|
+
) {
|
|
1183
1357
|
super();
|
|
1358
|
+
this.supportsMultiAgentChildren = dependencies != null;
|
|
1359
|
+
this.graphFactory =
|
|
1360
|
+
dependencies?.graphFactory ??
|
|
1361
|
+
((request): StandardGraph => {
|
|
1362
|
+
if (request.kind !== 'standard') {
|
|
1363
|
+
throw new Error(
|
|
1364
|
+
'A polymorphic graph factory is required for multi-agent graph construction.'
|
|
1365
|
+
);
|
|
1366
|
+
}
|
|
1367
|
+
return new StandardGraph(request.input);
|
|
1368
|
+
});
|
|
1184
1369
|
this.runId = runId;
|
|
1185
1370
|
this.langfuseScopeRunId = `${runId ?? 'graph'}:${nanoid()}`;
|
|
1186
1371
|
this.signal = signal;
|
|
1187
1372
|
this.langfuse = langfuse;
|
|
1188
1373
|
this.subagentUsageSink = subagentUsageSink;
|
|
1189
1374
|
this.subagentScope = subagentScope === true;
|
|
1375
|
+
this.subagentExecutionContext = subagentExecutionContext;
|
|
1190
1376
|
this.preemption = preemption;
|
|
1191
1377
|
this.streamLimits = resolveStreamLimits(streamLimits);
|
|
1192
1378
|
|
|
@@ -1213,7 +1399,9 @@ export class StandardGraph extends Graph<t.BaseGraphState, t.GraphNode> {
|
|
|
1213
1399
|
/* Init */
|
|
1214
1400
|
|
|
1215
1401
|
resetValues(keepContent?: boolean, checkpointScope?: string): void {
|
|
1402
|
+
this.resetSubagentCheckpointThreadIds();
|
|
1216
1403
|
this.messages = [];
|
|
1404
|
+
this.hasRestoredCheckpointMessages = false;
|
|
1217
1405
|
this.cachedRunMessages = undefined;
|
|
1218
1406
|
this.cachedDiscoveredTools = undefined;
|
|
1219
1407
|
this.config = resetIfNotEmpty(this.config, undefined);
|
|
@@ -1310,6 +1498,23 @@ export class StandardGraph extends Graph<t.BaseGraphState, t.GraphNode> {
|
|
|
1310
1498
|
: undefined;
|
|
1311
1499
|
}
|
|
1312
1500
|
|
|
1501
|
+
/** Seeds the sidecar message view that checkpoint restoration bypasses. */
|
|
1502
|
+
override restoreCheckpointMessages(
|
|
1503
|
+
messages: BaseMessage[],
|
|
1504
|
+
pendingMessages?: BaseMessage[]
|
|
1505
|
+
): void {
|
|
1506
|
+
if (this.messages.length > 0) {
|
|
1507
|
+
return;
|
|
1508
|
+
}
|
|
1509
|
+
this.messages =
|
|
1510
|
+
pendingMessages == null
|
|
1511
|
+
? [...messages]
|
|
1512
|
+
: messagesStateReducer(messages, pendingMessages);
|
|
1513
|
+
this.startIndex = this.messages.length;
|
|
1514
|
+
this.hasRestoredCheckpointMessages = true;
|
|
1515
|
+
this.cachedRunMessages = undefined;
|
|
1516
|
+
}
|
|
1517
|
+
|
|
1313
1518
|
override clearHeavyState(): void {
|
|
1314
1519
|
this.cachedRunMessages = this.messages.slice(this.startIndex);
|
|
1315
1520
|
this.cachedDiscoveredTools = new Map(
|
|
@@ -1798,6 +2003,15 @@ export class StandardGraph extends Graph<t.BaseGraphState, t.GraphNode> {
|
|
|
1798
2003
|
runLangfuse: this.langfuse,
|
|
1799
2004
|
agentLangfuse: agentContext?.langfuse,
|
|
1800
2005
|
});
|
|
2006
|
+
const interruptingToolNames = new Set(this.interruptingToolNames ?? []);
|
|
2007
|
+
if (
|
|
2008
|
+
this.humanInTheLoop?.enabled === true &&
|
|
2009
|
+
(agentContext?.subagentConfigs?.length ?? 0) > 0
|
|
2010
|
+
) {
|
|
2011
|
+
interruptingToolNames.add(Constants.SUBAGENT);
|
|
2012
|
+
}
|
|
2013
|
+
const effectiveInterruptingToolNames =
|
|
2014
|
+
interruptingToolNames.size > 0 ? interruptingToolNames : undefined;
|
|
1801
2015
|
|
|
1802
2016
|
if (eventDrivenMode) {
|
|
1803
2017
|
const schemaTools = createSchemaOnlyTools(toolDefinitions);
|
|
@@ -1849,11 +2063,7 @@ export class StandardGraph extends Graph<t.BaseGraphState, t.GraphNode> {
|
|
|
1849
2063
|
eagerEventToolSuppressions: this.eagerEventToolSuppressions,
|
|
1850
2064
|
toolExecution: this.toolExecution,
|
|
1851
2065
|
directToolNames: directToolNames.size > 0 ? directToolNames : undefined,
|
|
1852
|
-
interruptingToolNames:
|
|
1853
|
-
this.interruptingToolNames != null &&
|
|
1854
|
-
this.interruptingToolNames.length > 0
|
|
1855
|
-
? new Set(this.interruptingToolNames)
|
|
1856
|
-
: undefined,
|
|
2066
|
+
interruptingToolNames: effectiveInterruptingToolNames,
|
|
1857
2067
|
maxContextTokens: agentContext?.maxContextTokens,
|
|
1858
2068
|
maxToolResultChars: agentContext?.maxToolResultChars,
|
|
1859
2069
|
toolOutputRegistry: this.getOrCreateToolOutputRegistry(),
|
|
@@ -1916,11 +2126,7 @@ export class StandardGraph extends Graph<t.BaseGraphState, t.GraphNode> {
|
|
|
1916
2126
|
sessions: this.sessions,
|
|
1917
2127
|
toolExecution: this.toolExecution,
|
|
1918
2128
|
codeSessionToolNames: this.codeSessionToolNames,
|
|
1919
|
-
interruptingToolNames:
|
|
1920
|
-
this.interruptingToolNames != null &&
|
|
1921
|
-
this.interruptingToolNames.length > 0
|
|
1922
|
-
? new Set(this.interruptingToolNames)
|
|
1923
|
-
: undefined,
|
|
2129
|
+
interruptingToolNames: effectiveInterruptingToolNames,
|
|
1924
2130
|
hookRegistry: this.hookRegistry,
|
|
1925
2131
|
humanInTheLoop: this.humanInTheLoop,
|
|
1926
2132
|
maxContextTokens: agentContext?.maxContextTokens,
|
|
@@ -3377,7 +3583,9 @@ export class StandardGraph extends Graph<t.BaseGraphState, t.GraphNode> {
|
|
|
3377
3583
|
* would start new provider work after the run-wide breaker fired.
|
|
3378
3584
|
* Rethrow the breaker's own stream-limit reason instead. */
|
|
3379
3585
|
{
|
|
3380
|
-
const trippedReason = this.resolveTrippedBreakerReason(
|
|
3586
|
+
const trippedReason = this.resolveTrippedBreakerReason(
|
|
3587
|
+
attemptBreaker.signal
|
|
3588
|
+
);
|
|
3381
3589
|
if (trippedReason != null) {
|
|
3382
3590
|
throw trippedReason;
|
|
3383
3591
|
}
|
|
@@ -3624,7 +3832,9 @@ export class StandardGraph extends Graph<t.BaseGraphState, t.GraphNode> {
|
|
|
3624
3832
|
}
|
|
3625
3833
|
{
|
|
3626
3834
|
/** Same sibling-abort translation guard as the primary catch. */
|
|
3627
|
-
const trippedReason = this.resolveTrippedBreakerReason(
|
|
3835
|
+
const trippedReason = this.resolveTrippedBreakerReason(
|
|
3836
|
+
attemptBreaker.signal
|
|
3837
|
+
);
|
|
3628
3838
|
if (trippedReason != null) {
|
|
3629
3839
|
throw trippedReason;
|
|
3630
3840
|
}
|
|
@@ -4037,15 +4247,57 @@ export class StandardGraph extends Graph<t.BaseGraphState, t.GraphNode> {
|
|
|
4037
4247
|
agentContext.subagentConfigs.length > 0 &&
|
|
4038
4248
|
effectiveSubagentDepth > 0
|
|
4039
4249
|
) {
|
|
4040
|
-
const
|
|
4250
|
+
const executableConfigs = normalizeSubagentConfigEntries(
|
|
4041
4251
|
agentContext.subagentConfigs,
|
|
4042
4252
|
agentContext
|
|
4043
4253
|
);
|
|
4044
|
-
if (
|
|
4254
|
+
if (executableConfigs.length > 0) {
|
|
4255
|
+
if (
|
|
4256
|
+
!this.supportsMultiAgentChildren &&
|
|
4257
|
+
executableConfigs.some(isGraphSubagentConfig)
|
|
4258
|
+
) {
|
|
4259
|
+
throw new Error(
|
|
4260
|
+
'Graph subagents require constructing the parent with createGraph() or an injected GraphFactory dependency.'
|
|
4261
|
+
);
|
|
4262
|
+
}
|
|
4045
4263
|
const getParentHandlerRegistry = (): HandlerRegistry | undefined =>
|
|
4046
4264
|
this.handlerRegistry ?? this.parentToolHandlerRegistry;
|
|
4265
|
+
const createConfiguredChildGraph: GraphFactory = (request) => {
|
|
4266
|
+
const childGraph = this.graphFactory(request);
|
|
4267
|
+
if (this.subagentModelOverride != null) {
|
|
4268
|
+
childGraph.overrideModel = this.subagentModelOverride;
|
|
4269
|
+
childGraph.setSubagentModelOverride(this.subagentModelOverride);
|
|
4270
|
+
}
|
|
4271
|
+
const childHandlerRegistry = createChildHandlerRegistry(
|
|
4272
|
+
getParentHandlerRegistry()
|
|
4273
|
+
);
|
|
4274
|
+
// Pure execution-ordering hint (unlike `humanInTheLoop`). It only
|
|
4275
|
+
// reorders tools already in the child's direct group; it does not
|
|
4276
|
+
// force a schema-only event tool onto the direct execution path.
|
|
4277
|
+
applyGraphRuntimeConfig(childGraph, {
|
|
4278
|
+
hookRegistry: this.hookRegistry,
|
|
4279
|
+
humanInTheLoop: this.humanInTheLoop,
|
|
4280
|
+
toolOutputReferences: this.toolOutputReferences,
|
|
4281
|
+
eagerEventToolExecution: this.eagerEventToolExecution,
|
|
4282
|
+
codeSessionToolNames: this.codeSessionToolNames,
|
|
4283
|
+
interruptingToolNames: this.interruptingToolNames,
|
|
4284
|
+
toolExecution: this.toolExecution,
|
|
4285
|
+
});
|
|
4286
|
+
if (this.humanInTheLoop?.enabled === true) {
|
|
4287
|
+
childGraph.compileOptions = {
|
|
4288
|
+
checkpointer: this.compileOptions?.checkpointer,
|
|
4289
|
+
};
|
|
4290
|
+
}
|
|
4291
|
+
childGraph.parentToolHandlerRegistry = childHandlerRegistry;
|
|
4292
|
+
childGraph.eventToolExecutionAvailable =
|
|
4293
|
+
childHandlerRegistry?.getHandler(GraphEvents.ON_TOOL_EXECUTE) !=
|
|
4294
|
+
null;
|
|
4295
|
+
return childGraph;
|
|
4296
|
+
};
|
|
4047
4297
|
const executor = new SubagentExecutor({
|
|
4048
|
-
configs: new Map(
|
|
4298
|
+
configs: new Map(
|
|
4299
|
+
executableConfigs.map((config) => [config.type, config])
|
|
4300
|
+
),
|
|
4049
4301
|
parentSignal: this.signal,
|
|
4050
4302
|
breakerScope: {
|
|
4051
4303
|
controller: (): AbortController => this.breakerAbort,
|
|
@@ -4057,48 +4309,22 @@ export class StandardGraph extends Graph<t.BaseGraphState, t.GraphNode> {
|
|
|
4057
4309
|
parentHandlerRegistry: getParentHandlerRegistry,
|
|
4058
4310
|
parentRunId: this.runId ?? '',
|
|
4059
4311
|
parentAgentId: agentContext.agentId,
|
|
4312
|
+
executionContext: this.subagentExecutionContext,
|
|
4060
4313
|
langfuse: this.langfuse,
|
|
4061
4314
|
tokenCounter: agentContext.tokenCounter,
|
|
4062
4315
|
usageSink: this.subagentUsageSink,
|
|
4063
4316
|
streamLimits: this.streamLimits,
|
|
4317
|
+
humanInTheLoop: this.humanInTheLoop,
|
|
4318
|
+
checkpointer: this.compileOptions?.checkpointer,
|
|
4064
4319
|
maxDepth: effectiveSubagentDepth,
|
|
4065
|
-
createChildGraph: (input): StandardGraph =>
|
|
4066
|
-
|
|
4067
|
-
|
|
4068
|
-
|
|
4069
|
-
|
|
4070
|
-
|
|
4071
|
-
const toolHandlerRegistry = createToolHandlerRegistry(
|
|
4072
|
-
getParentHandlerRegistry()
|
|
4073
|
-
);
|
|
4074
|
-
childGraph.hookRegistry = this.hookRegistry;
|
|
4075
|
-
/**
|
|
4076
|
-
* Do not propagate `humanInTheLoop` into the child graph yet:
|
|
4077
|
-
* nested subagent interrupts need a stable child checkpoint and
|
|
4078
|
-
* resume bridge. Child hooks still fire; `ask` decisions fail
|
|
4079
|
-
* closed inside the subagent until that flow is implemented.
|
|
4080
|
-
*/
|
|
4081
|
-
childGraph.toolOutputReferences = this.toolOutputReferences;
|
|
4082
|
-
childGraph.eagerEventToolExecution = this.eagerEventToolExecution;
|
|
4083
|
-
childGraph.codeSessionToolNames = this.codeSessionToolNames;
|
|
4084
|
-
// Pure execution-ordering hint (unlike `humanInTheLoop` above).
|
|
4085
|
-
// It ONLY reorders tools already in the child's direct group;
|
|
4086
|
-
// it does not force a name onto the direct path (that fold-in
|
|
4087
|
-
// was removed — Codex review of #294). So for a self-spawned
|
|
4088
|
-
// child that scrubs inherited `graphTools` (keeping only the
|
|
4089
|
-
// event `toolDefinition` / schema-only stub for a name like
|
|
4090
|
-
// `ask_user_question`), the name isn't in the child's direct
|
|
4091
|
-
// group and this is a no-op — the stub is still dispatched via
|
|
4092
|
-
// ON_TOOL_EXECUTE, never invoked directly. Where the child DOES
|
|
4093
|
-
// have the executable graphTool, the guard correctly applies.
|
|
4094
|
-
childGraph.interruptingToolNames = this.interruptingToolNames;
|
|
4095
|
-
childGraph.toolExecution = this.toolExecution;
|
|
4096
|
-
childGraph.parentToolHandlerRegistry = toolHandlerRegistry;
|
|
4097
|
-
childGraph.eventToolExecutionAvailable =
|
|
4098
|
-
toolHandlerRegistry != null;
|
|
4099
|
-
return childGraph;
|
|
4100
|
-
},
|
|
4320
|
+
createChildGraph: (input): StandardGraph =>
|
|
4321
|
+
createConfiguredChildGraph({
|
|
4322
|
+
kind: 'standard',
|
|
4323
|
+
input,
|
|
4324
|
+
}),
|
|
4325
|
+
createChildGraphByKind: createConfiguredChildGraph,
|
|
4101
4326
|
});
|
|
4327
|
+
this.registerSubagentExecutor(executor);
|
|
4102
4328
|
|
|
4103
4329
|
const subagentTool = tool(async (rawInput, config) => {
|
|
4104
4330
|
const input = rawInput as {
|
|
@@ -4109,24 +4335,26 @@ export class StandardGraph extends Graph<t.BaseGraphState, t.GraphNode> {
|
|
|
4109
4335
|
typeof input.description === 'string' &&
|
|
4110
4336
|
input.description.trim().length > 0
|
|
4111
4337
|
? input.description
|
|
4112
|
-
:
|
|
4338
|
+
: DEFAULT_SUBAGENT_DESCRIPTION;
|
|
4113
4339
|
const subagentType =
|
|
4114
4340
|
typeof input.subagent_type === 'string' ? input.subagent_type : '';
|
|
4115
4341
|
const threadId = config.configurable?.thread_id as string | undefined;
|
|
4116
|
-
/**
|
|
4117
|
-
*
|
|
4118
|
-
|
|
4119
|
-
|
|
4120
|
-
|
|
4121
|
-
|
|
4122
|
-
|
|
4123
|
-
|
|
4124
|
-
|
|
4125
|
-
|
|
4126
|
-
|
|
4127
|
-
|
|
4128
|
-
|
|
4129
|
-
|
|
4342
|
+
/** Surface the parent call id so child checkpoints, interrupts, and
|
|
4343
|
+
* update events remain correlated across replay and resume. */
|
|
4344
|
+
const toolRuntime = config as {
|
|
4345
|
+
toolCallId?: string;
|
|
4346
|
+
toolCall?: { id?: string };
|
|
4347
|
+
};
|
|
4348
|
+
const toolCall = toolRuntime.toolCall;
|
|
4349
|
+
let parentToolCallId: string | undefined;
|
|
4350
|
+
if (
|
|
4351
|
+
typeof toolRuntime.toolCallId === 'string' &&
|
|
4352
|
+
toolRuntime.toolCallId !== ''
|
|
4353
|
+
) {
|
|
4354
|
+
parentToolCallId = toolRuntime.toolCallId;
|
|
4355
|
+
} else if (typeof toolCall?.id === 'string' && toolCall.id !== '') {
|
|
4356
|
+
parentToolCallId = toolCall.id;
|
|
4357
|
+
}
|
|
4130
4358
|
/** The parent tool batch's entry-captured scope (stamped by
|
|
4131
4359
|
* ToolNode before PreToolUse hooks) — binds this child to the
|
|
4132
4360
|
* run that dispatched it, not to whatever controller a reset
|
|
@@ -4138,6 +4366,7 @@ export class StandardGraph extends Graph<t.BaseGraphState, t.GraphNode> {
|
|
|
4138
4366
|
description,
|
|
4139
4367
|
subagentType,
|
|
4140
4368
|
threadId,
|
|
4369
|
+
signal: config.signal,
|
|
4141
4370
|
parentToolCallId,
|
|
4142
4371
|
breaker: batchScope?.controller,
|
|
4143
4372
|
/**
|
|
@@ -4151,7 +4380,23 @@ export class StandardGraph extends Graph<t.BaseGraphState, t.GraphNode> {
|
|
|
4151
4380
|
| undefined,
|
|
4152
4381
|
});
|
|
4153
4382
|
return result.content;
|
|
4154
|
-
}, buildSubagentToolParams(
|
|
4383
|
+
}, buildSubagentToolParams(executableConfigs));
|
|
4384
|
+
const replayableSubagentTool = subagentTool as typeof subagentTool &
|
|
4385
|
+
ReplayableSubagentTool;
|
|
4386
|
+
replayableSubagentTool[SUBAGENT_REPLAY_CONTROLLER] = {
|
|
4387
|
+
getResumeManifest: (
|
|
4388
|
+
parentToolCallIds,
|
|
4389
|
+
config
|
|
4390
|
+
): Promise<SubagentResumeManifest | undefined> =>
|
|
4391
|
+
executor.getResumeManifest(parentToolCallIds, config),
|
|
4392
|
+
getSettledOutput: (
|
|
4393
|
+
call,
|
|
4394
|
+
config
|
|
4395
|
+
): Promise<SettledSubagentToolOutput | undefined> =>
|
|
4396
|
+
executor.getSettledToolOutput(call, config),
|
|
4397
|
+
persistSettledOutput: (call, config, output): Promise<void> =>
|
|
4398
|
+
executor.persistSettledToolOutput(call, config, output),
|
|
4399
|
+
};
|
|
4155
4400
|
|
|
4156
4401
|
if (!agentContext.graphTools) {
|
|
4157
4402
|
agentContext.graphTools = [];
|
|
@@ -4399,7 +4644,7 @@ export class StandardGraph extends Graph<t.BaseGraphState, t.GraphNode> {
|
|
|
4399
4644
|
const StateAnnotation = Annotation.Root({
|
|
4400
4645
|
messages: Annotation<BaseMessage[]>({
|
|
4401
4646
|
reducer: (a, b) => {
|
|
4402
|
-
if (!this.messages.length) {
|
|
4647
|
+
if (!this.messages.length && !this.hasRestoredCheckpointMessages) {
|
|
4403
4648
|
this.startIndex = a.length + b.length;
|
|
4404
4649
|
}
|
|
4405
4650
|
const result = messagesStateReducer(a, b);
|