@librechat/agents 3.3.13 → 3.4.1
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/graphs/Graph.cjs +121 -27
- package/dist/cjs/graphs/Graph.cjs.map +1 -1
- package/dist/cjs/hooks/HookRegistry.cjs +83 -0
- package/dist/cjs/hooks/HookRegistry.cjs.map +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/anthropic/index.cjs +35 -206
- package/dist/cjs/llm/anthropic/index.cjs.map +1 -1
- package/dist/cjs/llm/bedrock/index.cjs +121 -241
- package/dist/cjs/llm/bedrock/index.cjs.map +1 -1
- package/dist/cjs/llm/google/index.cjs +19 -12
- package/dist/cjs/llm/google/index.cjs.map +1 -1
- package/dist/cjs/llm/init.cjs +3 -3
- package/dist/cjs/llm/invoke.cjs +2 -2
- package/dist/cjs/llm/mistral/index.cjs +26 -0
- package/dist/cjs/llm/mistral/index.cjs.map +1 -0
- package/dist/cjs/llm/openai/index.cjs +82 -80
- package/dist/cjs/llm/openai/index.cjs.map +1 -1
- package/dist/cjs/llm/openrouter/index.cjs.map +1 -1
- package/dist/cjs/llm/providers.cjs +19 -19
- package/dist/cjs/llm/providers.cjs.map +1 -1
- package/dist/cjs/llm/stream/chunkAdapters.cjs +198 -0
- package/dist/cjs/llm/stream/chunkAdapters.cjs.map +1 -0
- package/dist/cjs/llm/stream/smoother.cjs +369 -0
- package/dist/cjs/llm/stream/smoother.cjs.map +1 -0
- package/dist/cjs/llm/vertexai/index.cjs +13 -1
- package/dist/cjs/llm/vertexai/index.cjs.map +1 -1
- package/dist/cjs/main.cjs +25 -16
- package/dist/cjs/messages/format.cjs +40 -23
- package/dist/cjs/messages/format.cjs.map +1 -1
- package/dist/cjs/run.cjs +82 -15
- 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/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/ToolNode.cjs +316 -94
- package/dist/cjs/tools/ToolNode.cjs.map +1 -1
- package/dist/cjs/tools/ToolSearch.cjs +1 -1
- package/dist/cjs/tools/subagent/SubagentExecutor.cjs +664 -80
- package/dist/cjs/tools/subagent/SubagentExecutor.cjs.map +1 -1
- package/dist/cjs/tools/subagent/SubagentReplay.cjs +175 -0
- package/dist/cjs/tools/subagent/SubagentReplay.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/cjs/utils/tokens.cjs +76 -29
- package/dist/cjs/utils/tokens.cjs.map +1 -1
- package/dist/esm/graphs/Graph.mjs +121 -27
- package/dist/esm/graphs/Graph.mjs.map +1 -1
- package/dist/esm/hooks/HookRegistry.mjs +83 -0
- package/dist/esm/hooks/HookRegistry.mjs.map +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/anthropic/index.mjs +34 -205
- package/dist/esm/llm/anthropic/index.mjs.map +1 -1
- package/dist/esm/llm/bedrock/index.mjs +120 -240
- package/dist/esm/llm/bedrock/index.mjs.map +1 -1
- package/dist/esm/llm/google/index.mjs +19 -12
- package/dist/esm/llm/google/index.mjs.map +1 -1
- package/dist/esm/llm/init.mjs +1 -1
- package/dist/esm/llm/invoke.mjs +2 -2
- package/dist/esm/llm/mistral/index.mjs +26 -0
- package/dist/esm/llm/mistral/index.mjs.map +1 -0
- package/dist/esm/llm/openai/index.mjs +82 -80
- package/dist/esm/llm/openai/index.mjs.map +1 -1
- package/dist/esm/llm/openrouter/index.mjs.map +1 -1
- package/dist/esm/llm/providers.mjs +3 -3
- package/dist/esm/llm/providers.mjs.map +1 -1
- package/dist/esm/llm/stream/chunkAdapters.mjs +195 -0
- package/dist/esm/llm/stream/chunkAdapters.mjs.map +1 -0
- package/dist/esm/llm/stream/smoother.mjs +365 -0
- package/dist/esm/llm/stream/smoother.mjs.map +1 -0
- package/dist/esm/llm/vertexai/index.mjs +13 -1
- package/dist/esm/llm/vertexai/index.mjs.map +1 -1
- package/dist/esm/main.mjs +13 -11
- package/dist/esm/messages/format.mjs +40 -23
- package/dist/esm/messages/format.mjs.map +1 -1
- package/dist/esm/run.mjs +83 -16
- 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/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/ToolNode.mjs +317 -95
- package/dist/esm/tools/ToolNode.mjs.map +1 -1
- package/dist/esm/tools/ToolSearch.mjs +1 -1
- package/dist/esm/tools/subagent/SubagentExecutor.mjs +665 -81
- package/dist/esm/tools/subagent/SubagentExecutor.mjs.map +1 -1
- package/dist/esm/tools/subagent/SubagentReplay.mjs +168 -0
- package/dist/esm/tools/subagent/SubagentReplay.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/esm/utils/tokens.mjs +76 -30
- package/dist/esm/utils/tokens.mjs.map +1 -1
- package/dist/types/graphs/Graph.d.ts +19 -1
- 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/index.d.ts +3 -0
- package/dist/types/llm/google/index.d.ts +2 -0
- package/dist/types/llm/mistral/index.d.ts +11 -0
- package/dist/types/llm/openai/index.d.ts +20 -4
- package/dist/types/llm/openrouter/index.d.ts +4 -1
- package/dist/types/llm/stream/chunkAdapters.d.ts +48 -0
- package/dist/types/llm/stream/smoother.d.ts +95 -0
- package/dist/types/llm/vertexai/index.d.ts +2 -0
- package/dist/types/run.d.ts +4 -1
- package/dist/types/session/AgentSession.d.ts +1 -0
- package/dist/types/tools/ToolNode.d.ts +23 -15
- package/dist/types/tools/subagent/SubagentExecutor.d.ts +49 -7
- package/dist/types/tools/subagent/SubagentReplay.d.ts +81 -0
- package/dist/types/tools/toolOutputReferences.d.ts +12 -0
- package/dist/types/types/graph.d.ts +5 -5
- package/dist/types/types/hitl.d.ts +15 -0
- package/dist/types/types/llm.d.ts +21 -14
- package/dist/types/utils/tokens.d.ts +10 -0
- package/package.json +6 -2
- package/src/graphs/Graph.ts +257 -52
- 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/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/index.ts +8 -0
- package/src/llm/anthropic/index.ts +85 -354
- package/src/llm/bedrock/index.ts +174 -390
- package/src/llm/bedrock/llm.spec.ts +2 -0
- package/src/llm/bedrock/streamSealDispatch.test.ts +76 -0
- package/src/llm/custom-chat-models.smoke.test.ts +16 -1
- package/src/llm/google/index.ts +17 -18
- package/src/llm/google/streamSmoothing.test.ts +121 -0
- package/src/llm/mistral/index.ts +33 -0
- package/src/llm/mistral/streamSmoothing.test.ts +97 -0
- package/src/llm/openai/deepseek.test.ts +56 -0
- package/src/llm/openai/index.ts +119 -126
- package/src/llm/openrouter/index.ts +4 -1
- package/src/llm/providers.ts +3 -3
- package/src/llm/stream/chunkAdapters.test.ts +202 -0
- package/src/llm/stream/chunkAdapters.ts +317 -0
- package/src/llm/stream/reassembly.test.ts +241 -0
- package/src/llm/stream/smoother.bench.test.ts +155 -0
- package/src/llm/stream/smoother.test.ts +519 -0
- package/src/llm/stream/smoother.ts +574 -0
- package/src/llm/vertexai/index.ts +17 -1
- package/src/llm/vertexai/streamSmoothing.test.ts +109 -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 +164 -18
- package/src/session/AgentSession.ts +52 -2
- package/src/session/__tests__/JsonlSessionStore.test.ts +53 -0
- package/src/specs/subagent.test.ts +44 -0
- package/src/specs/tokens.test.ts +159 -14
- package/src/summarization/__tests__/node.test.ts +32 -14
- package/src/summarization/node.ts +15 -11
- package/src/tools/ToolNode.ts +631 -157
- package/src/tools/__tests__/SubagentExecutor.test.ts +590 -7
- package/src/tools/__tests__/SubagentReplay.test.ts +300 -0
- package/src/tools/__tests__/ToolNode.breakerSignal.test.ts +208 -2
- package/src/tools/__tests__/directToolHITLResumeScope.test.ts +486 -2
- package/src/tools/__tests__/hitl.test.ts +234 -5
- package/src/tools/__tests__/subagentHooks.test.ts +1040 -62
- package/src/tools/__tests__/toolOutputReferences.test.ts +19 -2
- package/src/tools/subagent/SubagentExecutor.ts +1438 -136
- package/src/tools/subagent/SubagentReplay.ts +575 -0
- package/src/tools/toolOutputReferences.ts +40 -1
- package/src/types/graph.ts +5 -5
- package/src/types/hitl.ts +16 -0
- package/src/types/llm.ts +53 -36
- package/src/utils/tokens.ts +115 -30
|
@@ -524,11 +524,11 @@ export interface AgentInputs {
|
|
|
524
524
|
* raise a LangGraph `interrupt()` (e.g. a tool built on `askUserQuestion()`) —
|
|
525
525
|
* the host-side event handler runs outside the graph task, where `interrupt()`
|
|
526
526
|
* throws. Do NOT also list these tools in `toolDefinitions` (they would be bound
|
|
527
|
-
* twice). NOT inherited by SELF-SPAWNED subagent children
|
|
528
|
-
* shallow
|
|
529
|
-
*
|
|
530
|
-
* `
|
|
531
|
-
*
|
|
527
|
+
* twice). NOT inherited by SELF-SPAWNED subagent children: `buildChildInputs`
|
|
528
|
+
* scrubs the shallow-spread parent copy so parent-scoped direct tools are not
|
|
529
|
+
* exposed to a child implicitly. An EXPLICIT child config that lists its own
|
|
530
|
+
* `graphTools` keeps them; with HITL enabled, those tools share the parent's
|
|
531
|
+
* checkpointer and may pause and resume inside the child graph.
|
|
532
532
|
*
|
|
533
533
|
* Deliberately `GenericTool[]`, not `GraphTools`: the wider union admits
|
|
534
534
|
* schema-only shapes (OpenAI `BindToolsInput`, Google tool objects) that
|
|
@@ -97,6 +97,17 @@ export type ToolApprovalDecisionMap = Record<string, ToolApprovalDecision>;
|
|
|
97
97
|
* below; this type alias is primarily an integration-layer contract.
|
|
98
98
|
*/
|
|
99
99
|
export type HumanInterruptType = 'tool_approval' | 'ask_user_question';
|
|
100
|
+
/** Identifies an interrupt that originated inside a checkpointed subagent. */
|
|
101
|
+
export interface SubagentInterruptScope {
|
|
102
|
+
/** Child execution run id used by subagent update and usage events. */
|
|
103
|
+
run_id: string;
|
|
104
|
+
/** Child agent id that owns the interrupted tool call. */
|
|
105
|
+
agent_id: string;
|
|
106
|
+
/** Configured subagent type selected by the parent tool call. */
|
|
107
|
+
subagent_type: string;
|
|
108
|
+
/** Parent `subagent` tool call that launched this child. */
|
|
109
|
+
parent_tool_call_id?: string;
|
|
110
|
+
}
|
|
100
111
|
/**
|
|
101
112
|
* Structured payload the SDK passes to `interrupt()` when one or more
|
|
102
113
|
* pending tool calls require host approval. All `ask`-decision tool calls
|
|
@@ -110,6 +121,10 @@ export interface ToolApprovalInterruptPayload {
|
|
|
110
121
|
type: 'tool_approval';
|
|
111
122
|
action_requests: ToolApprovalRequest[];
|
|
112
123
|
review_configs: ToolApprovalReviewConfig[];
|
|
124
|
+
/** Hook-registry session whose policy raised this interrupt. */
|
|
125
|
+
hook_session_id?: string;
|
|
126
|
+
/** Present when the approval request was bridged from a child graph. */
|
|
127
|
+
subagent?: SubagentInterruptScope;
|
|
113
128
|
}
|
|
114
129
|
/**
|
|
115
130
|
* Pre-defined option the user can pick when answering an
|
|
@@ -28,7 +28,7 @@ export type AzureClientOptions = Partial<OpenAIChatInput> & Partial<AzureOpenAII
|
|
|
28
28
|
deploymentName?: string;
|
|
29
29
|
} & BaseChatModelParams & {
|
|
30
30
|
configuration?: OAIClientOptions;
|
|
31
|
-
} & ManagedRequestOptions;
|
|
31
|
+
} & ManagedRequestOptions & StreamSmoothingOptions;
|
|
32
32
|
/**
|
|
33
33
|
* Controls whether Claude's reasoning content is returned in adaptive
|
|
34
34
|
* thinking responses. Added for Claude Opus 4.7, which omits thinking by
|
|
@@ -58,8 +58,19 @@ export type ManagedRequestOptions = {
|
|
|
58
58
|
promptCacheExplicit?: boolean;
|
|
59
59
|
safety_identifier?: string;
|
|
60
60
|
};
|
|
61
|
-
|
|
62
|
-
|
|
61
|
+
/**
|
|
62
|
+
* Adaptive stream-smoothing configuration shared by every provider client.
|
|
63
|
+
*/
|
|
64
|
+
export type StreamSmoothingOptions = {
|
|
65
|
+
/**
|
|
66
|
+
* Minimum delay in milliseconds between visible streamed content deltas.
|
|
67
|
+
* Defaults to 25; piece sizes adapt to the backlog so render lag stays
|
|
68
|
+
* bounded regardless of provider chunk size. Set 0 to disable smoothing.
|
|
69
|
+
*/
|
|
70
|
+
_lc_stream_delay?: number;
|
|
71
|
+
};
|
|
72
|
+
export type OpenAIClientOptions = ChatOpenAIFields & ManagedRequestOptions & StreamSmoothingOptions;
|
|
73
|
+
export type AnthropicClientOptions = Omit<AnthropicInput, 'thinking'> & StreamSmoothingOptions & {
|
|
63
74
|
thinking?: ThinkingConfig;
|
|
64
75
|
promptCache?: boolean;
|
|
65
76
|
/**
|
|
@@ -69,12 +80,12 @@ export type AnthropicClientOptions = Omit<AnthropicInput, 'thinking'> & {
|
|
|
69
80
|
*/
|
|
70
81
|
promptCacheTtl?: PromptCacheTtl;
|
|
71
82
|
};
|
|
72
|
-
export type MistralAIClientOptions = ChatMistralAIInput;
|
|
73
|
-
export type VertexAIClientOptions = ChatVertexAIInput & {
|
|
83
|
+
export type MistralAIClientOptions = ChatMistralAIInput & StreamSmoothingOptions;
|
|
84
|
+
export type VertexAIClientOptions = ChatVertexAIInput & StreamSmoothingOptions & {
|
|
74
85
|
includeThoughts?: boolean;
|
|
75
86
|
thinkingConfig?: GoogleThinkingConfig;
|
|
76
87
|
};
|
|
77
|
-
export type BedrockAnthropicInput = ChatBedrockConverseInput & {
|
|
88
|
+
export type BedrockAnthropicInput = ChatBedrockConverseInput & StreamSmoothingOptions & {
|
|
78
89
|
additionalModelRequestFields?: ChatBedrockConverseInput['additionalModelRequestFields'] & AnthropicReasoning;
|
|
79
90
|
promptCache?: boolean;
|
|
80
91
|
/**
|
|
@@ -84,20 +95,16 @@ export type BedrockAnthropicInput = ChatBedrockConverseInput & {
|
|
|
84
95
|
* server-side, so the default is safe to leave on.
|
|
85
96
|
*/
|
|
86
97
|
promptCacheTtl?: PromptCacheTtl;
|
|
87
|
-
/**
|
|
88
|
-
* Minimum delay in milliseconds between visible streamed content deltas.
|
|
89
|
-
*/
|
|
90
|
-
_lc_stream_delay?: number;
|
|
91
98
|
};
|
|
92
99
|
export type BedrockConverseClientOptions = BedrockAnthropicInput;
|
|
93
100
|
export type BedrockAnthropicClientOptions = BedrockAnthropicInput;
|
|
94
|
-
export type GoogleClientOptions = GoogleGenerativeAIChatInput & {
|
|
101
|
+
export type GoogleClientOptions = GoogleGenerativeAIChatInput & StreamSmoothingOptions & {
|
|
95
102
|
customHeaders?: RequestOptions['customHeaders'];
|
|
96
103
|
thinkingConfig?: GoogleThinkingConfig;
|
|
97
104
|
includeServerSideToolInvocations?: boolean;
|
|
98
105
|
};
|
|
99
|
-
export type DeepSeekClientOptions = Partial<ChatDeepSeekInput
|
|
100
|
-
export type XAIClientOptions = ChatXAIInput;
|
|
106
|
+
export type DeepSeekClientOptions = Partial<ChatDeepSeekInput> & StreamSmoothingOptions;
|
|
107
|
+
export type XAIClientOptions = ChatXAIInput & StreamSmoothingOptions;
|
|
101
108
|
export type ClientOptions = OpenAIClientOptions | AzureClientOptions | AnthropicClientOptions | MistralAIClientOptions | VertexAIClientOptions | BedrockConverseClientOptions | GoogleClientOptions | DeepSeekClientOptions | XAIClientOptions;
|
|
102
109
|
export type SharedLLMConfig = {
|
|
103
110
|
provider: Providers;
|
|
@@ -122,7 +129,7 @@ export type ProviderOptionsMap = {
|
|
|
122
129
|
[Providers.ANTHROPIC]: AnthropicClientOptions;
|
|
123
130
|
[Providers.MISTRALAI]: MistralAIClientOptions;
|
|
124
131
|
[Providers.MISTRAL]: MistralAIClientOptions;
|
|
125
|
-
[Providers.OPENROUTER]: ChatOpenRouterCallOptions;
|
|
132
|
+
[Providers.OPENROUTER]: ChatOpenRouterCallOptions & StreamSmoothingOptions;
|
|
126
133
|
[Providers.BEDROCK]: BedrockAnthropicClientOptions;
|
|
127
134
|
[Providers.XAI]: XAIClientOptions;
|
|
128
135
|
[Providers.MOONSHOT]: OpenAIClientOptions;
|
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
import type { BaseMessage } from '@langchain/core/messages';
|
|
2
2
|
export type EncodingName = 'o200k_base' | 'claude';
|
|
3
|
+
export type UnsafeTokenMeasurementReason = 'message_proxy' | 'content_proxy' | 'metadata_proxy' | 'metadata_accessor' | 'invalid_count';
|
|
4
|
+
export declare class UnsafeTokenMeasurementError extends Error {
|
|
5
|
+
readonly type = "unsafe_token_measurement";
|
|
6
|
+
readonly reason: UnsafeTokenMeasurementReason;
|
|
7
|
+
readonly path: string;
|
|
8
|
+
constructor({ reason, path, }: {
|
|
9
|
+
reason: UnsafeTokenMeasurementReason;
|
|
10
|
+
path: string;
|
|
11
|
+
});
|
|
12
|
+
}
|
|
3
13
|
/** Safety margin for image and document token estimates (5% overestimate). */
|
|
4
14
|
export declare const IMAGE_TOKEN_SAFETY_MARGIN = 1.05;
|
|
5
15
|
/**
|
package/package.json
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@librechat/agents",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.4.1",
|
|
4
|
+
"reova": {
|
|
5
|
+
"enabled": true,
|
|
6
|
+
"endpoint": "https://telemetry.reo.dev/data"
|
|
7
|
+
},
|
|
4
8
|
"main": "./dist/cjs/main.cjs",
|
|
5
9
|
"module": "./dist/esm/main.mjs",
|
|
6
10
|
"types": "./dist/types/index.d.ts",
|
|
@@ -248,7 +252,7 @@
|
|
|
248
252
|
"nanoid": "^3.3.7",
|
|
249
253
|
"okapibm25": "^1.4.1",
|
|
250
254
|
"openai": "^6.46.0",
|
|
251
|
-
"
|
|
255
|
+
"reova": "^0.4.1",
|
|
252
256
|
"socks-proxy-agent": "^8.0.5",
|
|
253
257
|
"uuid": "^11.1.1"
|
|
254
258
|
},
|
package/src/graphs/Graph.ts
CHANGED
|
@@ -17,6 +17,13 @@ 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,
|
|
@@ -60,14 +67,6 @@ import {
|
|
|
60
67
|
appendPredecessorHandoffCue,
|
|
61
68
|
removePredecessorHandoffCue,
|
|
62
69
|
} from '@/messages';
|
|
63
|
-
import {
|
|
64
|
-
attemptInvoke,
|
|
65
|
-
tryFallbackProviders,
|
|
66
|
-
getFallbackErrorContext,
|
|
67
|
-
getFallbackOverflowCandidates,
|
|
68
|
-
projectMessagesForProvider,
|
|
69
|
-
resolveServingModelId,
|
|
70
|
-
} from '@/llm/invoke';
|
|
71
70
|
import {
|
|
72
71
|
resetIfNotEmpty,
|
|
73
72
|
isAnthropicLike,
|
|
@@ -79,6 +78,21 @@ import {
|
|
|
79
78
|
joinKeys,
|
|
80
79
|
sleep,
|
|
81
80
|
} from '@/utils';
|
|
81
|
+
import {
|
|
82
|
+
attemptInvoke,
|
|
83
|
+
tryFallbackProviders,
|
|
84
|
+
getFallbackErrorContext,
|
|
85
|
+
getFallbackOverflowCandidates,
|
|
86
|
+
projectMessagesForProvider,
|
|
87
|
+
resolveServingModelId,
|
|
88
|
+
} from '@/llm/invoke';
|
|
89
|
+
import {
|
|
90
|
+
resolveStreamLimits,
|
|
91
|
+
StreamLimitExceededError,
|
|
92
|
+
sweepStaleStreamLimitEntries,
|
|
93
|
+
STREAM_LIMIT_EPOCH_KEY,
|
|
94
|
+
RUN_BREAKER_SCOPE_CONFIG_KEY,
|
|
95
|
+
} from '@/llm/streamLimits';
|
|
82
96
|
import {
|
|
83
97
|
Constants,
|
|
84
98
|
GraphNodeKeys,
|
|
@@ -122,17 +136,11 @@ import {
|
|
|
122
136
|
findCallback,
|
|
123
137
|
type CallbackEntry,
|
|
124
138
|
} 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
139
|
import { partitionAndMarkOpenRouterToolCache } from '@/llm/openrouter/toolCache';
|
|
133
140
|
import { ToolNode as CustomToolNode, toolsCondition } from '@/tools/ToolNode';
|
|
134
141
|
import { shouldTraceToolNodeForLangfuse } from '@/langfuseToolOutputTracing';
|
|
135
142
|
import { createLocalCodingToolBundle } from '@/tools/local/LocalCodingTools';
|
|
143
|
+
import { SUBAGENT_REPLAY_CONTROLLER } from '@/tools/subagent/SubagentReplay';
|
|
136
144
|
import { SubagentExecutor, resolveSubagentConfigs } from '@/tools/subagent';
|
|
137
145
|
import { partitionAndMarkBedrockToolCache } from '@/llm/bedrock/toolCache';
|
|
138
146
|
import { safeDispatchCustomEvent, emitAgentLog } from '@/utils/events';
|
|
@@ -630,6 +638,10 @@ export abstract class Graph<
|
|
|
630
638
|
_TNodeName extends string = string,
|
|
631
639
|
> {
|
|
632
640
|
abstract resetValues(keepContent?: boolean, checkpointScope?: string): void;
|
|
641
|
+
restoreCheckpointMessages(
|
|
642
|
+
_messages: BaseMessage[],
|
|
643
|
+
_pendingMessages?: BaseMessage[]
|
|
644
|
+
): void {}
|
|
633
645
|
abstract initializeTools({
|
|
634
646
|
currentTools,
|
|
635
647
|
currentToolMap,
|
|
@@ -848,11 +860,18 @@ export abstract class Graph<
|
|
|
848
860
|
// Flush each compiled ToolNode's direct-path turn cache so it
|
|
849
861
|
// doesn't leak across Runs (Codex P2 #33). The cache survives
|
|
850
862
|
// `run()` re-entry by design (resume-stable), but end-of-Run
|
|
851
|
-
// is the right point to reset it.
|
|
863
|
+
// is the right point to reset it. Retain the registrations because
|
|
864
|
+
// the compiled workflow can be reused for later Runs; compilation
|
|
865
|
+
// will not register these instances again.
|
|
852
866
|
for (const node of this._compiledToolNodes) {
|
|
853
867
|
node.clearDirectPathTurns();
|
|
854
868
|
}
|
|
855
|
-
|
|
869
|
+
// Subagent executors are likewise compiled once and reused. Clear
|
|
870
|
+
// their per-Run state without dropping the registrations needed by
|
|
871
|
+
// subsequent cleanup cycles.
|
|
872
|
+
for (const executor of this._subagentExecutors) {
|
|
873
|
+
executor.clearHeavyState();
|
|
874
|
+
}
|
|
856
875
|
this.sessions.clear();
|
|
857
876
|
}
|
|
858
877
|
|
|
@@ -904,10 +923,137 @@ export abstract class Graph<
|
|
|
904
923
|
*/
|
|
905
924
|
protected registerCompiledToolNode(node: {
|
|
906
925
|
clearDirectPathTurns(): void;
|
|
926
|
+
createSubagentResumeState(): SubagentToolNodeResumeState;
|
|
927
|
+
restoreSubagentResumeState(state: SubagentToolNodeResumeState): void;
|
|
907
928
|
}): void {
|
|
908
929
|
this._compiledToolNodes.add(node);
|
|
909
930
|
}
|
|
910
931
|
|
|
932
|
+
protected registerSubagentExecutor(executor: SubagentExecutor): void {
|
|
933
|
+
this._subagentExecutors.add(executor);
|
|
934
|
+
}
|
|
935
|
+
|
|
936
|
+
protected resetSubagentCheckpointThreadIds(): void {
|
|
937
|
+
for (const executor of this._subagentExecutors) {
|
|
938
|
+
executor.resetCheckpointThreadIds();
|
|
939
|
+
}
|
|
940
|
+
}
|
|
941
|
+
|
|
942
|
+
getChildCheckpointThreadIds(): string[] {
|
|
943
|
+
const threadIds = new Set<string>();
|
|
944
|
+
for (const executor of this._subagentExecutors) {
|
|
945
|
+
for (const threadId of executor.getChildCheckpointThreadIds()) {
|
|
946
|
+
threadIds.add(threadId);
|
|
947
|
+
}
|
|
948
|
+
}
|
|
949
|
+
return [...threadIds];
|
|
950
|
+
}
|
|
951
|
+
|
|
952
|
+
createSubagentResumeState(runId: string): SubagentGraphResumeState {
|
|
953
|
+
return {
|
|
954
|
+
toolCallSteps: [...this.toolCallStepIds].map(([toolCallId, stepId]) => ({
|
|
955
|
+
toolCallId,
|
|
956
|
+
stepId,
|
|
957
|
+
})),
|
|
958
|
+
toolSessions: [...this.sessions].map(([toolName, context]) => ({
|
|
959
|
+
toolName,
|
|
960
|
+
context: {
|
|
961
|
+
...context,
|
|
962
|
+
...(context.files == null
|
|
963
|
+
? {}
|
|
964
|
+
: { files: context.files.map((file) => ({ ...file })) }),
|
|
965
|
+
},
|
|
966
|
+
})),
|
|
967
|
+
toolNodes: [...this._compiledToolNodes].map((node) =>
|
|
968
|
+
node.createSubagentResumeState()
|
|
969
|
+
),
|
|
970
|
+
eagerToolUsage: [
|
|
971
|
+
{
|
|
972
|
+
agentId: '',
|
|
973
|
+
toolUsageCounts: [...this.eagerEventToolUsageCount].map(
|
|
974
|
+
([toolName, count]) => ({ toolName, count })
|
|
975
|
+
),
|
|
976
|
+
},
|
|
977
|
+
...[...this.eagerEventToolUsageCountsByAgentId].map(
|
|
978
|
+
([agentId, usageCounts]) => ({
|
|
979
|
+
agentId,
|
|
980
|
+
toolUsageCounts: [...usageCounts].map(([toolName, count]) => ({
|
|
981
|
+
toolName,
|
|
982
|
+
count,
|
|
983
|
+
})),
|
|
984
|
+
})
|
|
985
|
+
),
|
|
986
|
+
],
|
|
987
|
+
eagerToolSuppressions: [...this.eagerEventToolSuppressions],
|
|
988
|
+
...(this._toolOutputRegistry == null
|
|
989
|
+
? {}
|
|
990
|
+
: {
|
|
991
|
+
toolOutputReferences: this._toolOutputRegistry.snapshotState(runId),
|
|
992
|
+
}),
|
|
993
|
+
};
|
|
994
|
+
}
|
|
995
|
+
|
|
996
|
+
restoreSubagentResumeState(
|
|
997
|
+
state: SubagentGraphResumeState,
|
|
998
|
+
runId: string
|
|
999
|
+
): void {
|
|
1000
|
+
const toolNodesByKey = new Map(
|
|
1001
|
+
[...this._compiledToolNodes].map((node) => {
|
|
1002
|
+
const nodeState = node.createSubagentResumeState();
|
|
1003
|
+
return [nodeState.stateKey, node] as const;
|
|
1004
|
+
})
|
|
1005
|
+
);
|
|
1006
|
+
if (toolNodesByKey.size !== state.toolNodes.length) {
|
|
1007
|
+
throw new Error('Cannot restore changed subagent tool topology.');
|
|
1008
|
+
}
|
|
1009
|
+
for (const nodeState of state.toolNodes) {
|
|
1010
|
+
if (!toolNodesByKey.has(nodeState.stateKey)) {
|
|
1011
|
+
throw new Error(
|
|
1012
|
+
`Cannot restore subagent tool state for "${nodeState.stateKey}".`
|
|
1013
|
+
);
|
|
1014
|
+
}
|
|
1015
|
+
}
|
|
1016
|
+
const registry =
|
|
1017
|
+
state.toolOutputReferences == null
|
|
1018
|
+
? undefined
|
|
1019
|
+
: this.getOrCreateToolOutputRegistry();
|
|
1020
|
+
if (state.toolOutputReferences != null && registry == null) {
|
|
1021
|
+
throw new Error('Cannot restore disabled tool output references.');
|
|
1022
|
+
}
|
|
1023
|
+
|
|
1024
|
+
this.toolCallStepIds.clear();
|
|
1025
|
+
for (const { toolCallId, stepId } of state.toolCallSteps) {
|
|
1026
|
+
this.toolCallStepIds.set(toolCallId, stepId);
|
|
1027
|
+
}
|
|
1028
|
+
this.sessions.clear();
|
|
1029
|
+
for (const { toolName, context } of state.toolSessions) {
|
|
1030
|
+
this.sessions.set(toolName, {
|
|
1031
|
+
...context,
|
|
1032
|
+
...(context.files == null
|
|
1033
|
+
? {}
|
|
1034
|
+
: { files: context.files.map((file) => ({ ...file })) }),
|
|
1035
|
+
});
|
|
1036
|
+
}
|
|
1037
|
+
for (const nodeState of state.toolNodes) {
|
|
1038
|
+
const node = toolNodesByKey.get(nodeState.stateKey)!;
|
|
1039
|
+
node.restoreSubagentResumeState(nodeState);
|
|
1040
|
+
}
|
|
1041
|
+
this.clearEagerEventToolUsageCounts();
|
|
1042
|
+
for (const usageState of state.eagerToolUsage) {
|
|
1043
|
+
const usageCounts = this.getEagerEventToolUsageCount(usageState.agentId);
|
|
1044
|
+
for (const { toolName, count } of usageState.toolUsageCounts) {
|
|
1045
|
+
usageCounts.set(toolName, count);
|
|
1046
|
+
}
|
|
1047
|
+
}
|
|
1048
|
+
this.eagerEventToolSuppressions.clear();
|
|
1049
|
+
for (const toolName of state.eagerToolSuppressions) {
|
|
1050
|
+
this.eagerEventToolSuppressions.add(toolName);
|
|
1051
|
+
}
|
|
1052
|
+
if (state.toolOutputReferences != null && registry != null) {
|
|
1053
|
+
registry.restoreState(runId, state.toolOutputReferences);
|
|
1054
|
+
}
|
|
1055
|
+
}
|
|
1056
|
+
|
|
911
1057
|
/**
|
|
912
1058
|
* Returns the shared `ToolOutputReferenceRegistry` for this run,
|
|
913
1059
|
* constructing it on first access. Returns `undefined` when the
|
|
@@ -957,7 +1103,10 @@ export abstract class Graph<
|
|
|
957
1103
|
*/
|
|
958
1104
|
private _compiledToolNodes: Set<{
|
|
959
1105
|
clearDirectPathTurns(): void;
|
|
1106
|
+
createSubagentResumeState(): SubagentToolNodeResumeState;
|
|
1107
|
+
restoreSubagentResumeState(state: SubagentToolNodeResumeState): void;
|
|
960
1108
|
}> = new Set();
|
|
1109
|
+
private _subagentExecutors = new Set<SubagentExecutor>();
|
|
961
1110
|
public getOrCreateFileCheckpointer(): t.LocalFileCheckpointer | undefined {
|
|
962
1111
|
// Return the cached instance unconditionally if one exists. The
|
|
963
1112
|
// toolExecution check below decides whether to *create* a new
|
|
@@ -998,11 +1147,14 @@ export abstract class Graph<
|
|
|
998
1147
|
|
|
999
1148
|
export class StandardGraph extends Graph<t.BaseGraphState, t.GraphNode> {
|
|
1000
1149
|
overrideModel?: t.ChatModel;
|
|
1150
|
+
private subagentModelOverride?: t.ChatModel;
|
|
1001
1151
|
/** Optional compile options passed into workflow.compile() */
|
|
1002
1152
|
compileOptions?: t.CompileOptions | undefined;
|
|
1003
1153
|
/** Whether the workflow was actually compiled with a checkpointer. */
|
|
1004
1154
|
hasCompiledCheckpointer: boolean = false;
|
|
1005
1155
|
messages: BaseMessage[] = [];
|
|
1156
|
+
/** Whether a rebuilt resume seeded the message baseline from its checkpoint. */
|
|
1157
|
+
private hasRestoredCheckpointMessages = false;
|
|
1006
1158
|
/** Cached run messages preserved before clearHeavyState() so getRunMessages() works after cleanup. */
|
|
1007
1159
|
private cachedRunMessages?: BaseMessage[];
|
|
1008
1160
|
/** Per-agent discovery snapshots preserved before contexts are reset on cleanup. */
|
|
@@ -1057,8 +1209,7 @@ export class StandardGraph extends Graph<t.BaseGraphState, t.GraphNode> {
|
|
|
1057
1209
|
* generation key + chunk index (see `resolveGenerationKey`). Per-run
|
|
1058
1210
|
* accumulation state, cleared by both reset paths.
|
|
1059
1211
|
*/
|
|
1060
|
-
streamedToolCallArgTallies: Map<string, StreamedToolCallArgTally> =
|
|
1061
|
-
new Map();
|
|
1212
|
+
streamedToolCallArgTallies: Map<string, StreamedToolCallArgTally> = new Map();
|
|
1062
1213
|
/** Streamed chunk events per model generation, keyed by generation key. */
|
|
1063
1214
|
streamDeltaEventCounts: Map<string, StreamDeltaEventTally> = new Map();
|
|
1064
1215
|
/** Per-chunk-object, per-generation charge balances (lazily created; see
|
|
@@ -1212,7 +1363,9 @@ export class StandardGraph extends Graph<t.BaseGraphState, t.GraphNode> {
|
|
|
1212
1363
|
/* Init */
|
|
1213
1364
|
|
|
1214
1365
|
resetValues(keepContent?: boolean, checkpointScope?: string): void {
|
|
1366
|
+
this.resetSubagentCheckpointThreadIds();
|
|
1215
1367
|
this.messages = [];
|
|
1368
|
+
this.hasRestoredCheckpointMessages = false;
|
|
1216
1369
|
this.cachedRunMessages = undefined;
|
|
1217
1370
|
this.cachedDiscoveredTools = undefined;
|
|
1218
1371
|
this.config = resetIfNotEmpty(this.config, undefined);
|
|
@@ -1309,6 +1462,23 @@ export class StandardGraph extends Graph<t.BaseGraphState, t.GraphNode> {
|
|
|
1309
1462
|
: undefined;
|
|
1310
1463
|
}
|
|
1311
1464
|
|
|
1465
|
+
/** Seeds the sidecar message view that checkpoint restoration bypasses. */
|
|
1466
|
+
override restoreCheckpointMessages(
|
|
1467
|
+
messages: BaseMessage[],
|
|
1468
|
+
pendingMessages?: BaseMessage[]
|
|
1469
|
+
): void {
|
|
1470
|
+
if (this.messages.length > 0) {
|
|
1471
|
+
return;
|
|
1472
|
+
}
|
|
1473
|
+
this.messages =
|
|
1474
|
+
pendingMessages == null
|
|
1475
|
+
? [...messages]
|
|
1476
|
+
: messagesStateReducer(messages, pendingMessages);
|
|
1477
|
+
this.startIndex = this.messages.length;
|
|
1478
|
+
this.hasRestoredCheckpointMessages = true;
|
|
1479
|
+
this.cachedRunMessages = undefined;
|
|
1480
|
+
}
|
|
1481
|
+
|
|
1312
1482
|
override clearHeavyState(): void {
|
|
1313
1483
|
this.cachedRunMessages = this.messages.slice(this.startIndex);
|
|
1314
1484
|
this.cachedDiscoveredTools = new Map(
|
|
@@ -1320,6 +1490,7 @@ export class StandardGraph extends Graph<t.BaseGraphState, t.GraphNode> {
|
|
|
1320
1490
|
super.clearHeavyState();
|
|
1321
1491
|
this.messages = [];
|
|
1322
1492
|
this.overrideModel = undefined;
|
|
1493
|
+
this.subagentModelOverride = undefined;
|
|
1323
1494
|
/** Stream-limit accounting (argument tallies, event counts, charge
|
|
1324
1495
|
* credits) deliberately SURVIVES cleanup: this runs in `processStream`'s
|
|
1325
1496
|
* finally, which an ordinary parallel-branch failure reaches while
|
|
@@ -1796,6 +1967,15 @@ export class StandardGraph extends Graph<t.BaseGraphState, t.GraphNode> {
|
|
|
1796
1967
|
runLangfuse: this.langfuse,
|
|
1797
1968
|
agentLangfuse: agentContext?.langfuse,
|
|
1798
1969
|
});
|
|
1970
|
+
const interruptingToolNames = new Set(this.interruptingToolNames ?? []);
|
|
1971
|
+
if (
|
|
1972
|
+
this.humanInTheLoop?.enabled === true &&
|
|
1973
|
+
(agentContext?.subagentConfigs?.length ?? 0) > 0
|
|
1974
|
+
) {
|
|
1975
|
+
interruptingToolNames.add(Constants.SUBAGENT);
|
|
1976
|
+
}
|
|
1977
|
+
const effectiveInterruptingToolNames =
|
|
1978
|
+
interruptingToolNames.size > 0 ? interruptingToolNames : undefined;
|
|
1799
1979
|
|
|
1800
1980
|
if (eventDrivenMode) {
|
|
1801
1981
|
const schemaTools = createSchemaOnlyTools(toolDefinitions);
|
|
@@ -1847,11 +2027,7 @@ export class StandardGraph extends Graph<t.BaseGraphState, t.GraphNode> {
|
|
|
1847
2027
|
eagerEventToolSuppressions: this.eagerEventToolSuppressions,
|
|
1848
2028
|
toolExecution: this.toolExecution,
|
|
1849
2029
|
directToolNames: directToolNames.size > 0 ? directToolNames : undefined,
|
|
1850
|
-
interruptingToolNames:
|
|
1851
|
-
this.interruptingToolNames != null &&
|
|
1852
|
-
this.interruptingToolNames.length > 0
|
|
1853
|
-
? new Set(this.interruptingToolNames)
|
|
1854
|
-
: undefined,
|
|
2030
|
+
interruptingToolNames: effectiveInterruptingToolNames,
|
|
1855
2031
|
maxContextTokens: agentContext?.maxContextTokens,
|
|
1856
2032
|
maxToolResultChars: agentContext?.maxToolResultChars,
|
|
1857
2033
|
toolOutputRegistry: this.getOrCreateToolOutputRegistry(),
|
|
@@ -1914,11 +2090,7 @@ export class StandardGraph extends Graph<t.BaseGraphState, t.GraphNode> {
|
|
|
1914
2090
|
sessions: this.sessions,
|
|
1915
2091
|
toolExecution: this.toolExecution,
|
|
1916
2092
|
codeSessionToolNames: this.codeSessionToolNames,
|
|
1917
|
-
interruptingToolNames:
|
|
1918
|
-
this.interruptingToolNames != null &&
|
|
1919
|
-
this.interruptingToolNames.length > 0
|
|
1920
|
-
? new Set(this.interruptingToolNames)
|
|
1921
|
-
: undefined,
|
|
2093
|
+
interruptingToolNames: effectiveInterruptingToolNames,
|
|
1922
2094
|
hookRegistry: this.hookRegistry,
|
|
1923
2095
|
humanInTheLoop: this.humanInTheLoop,
|
|
1924
2096
|
maxContextTokens: agentContext?.maxContextTokens,
|
|
@@ -1944,6 +2116,11 @@ export class StandardGraph extends Graph<t.BaseGraphState, t.GraphNode> {
|
|
|
1944
2116
|
});
|
|
1945
2117
|
}
|
|
1946
2118
|
|
|
2119
|
+
/** Explicitly overrides the model used by isolated descendant subagent graphs. */
|
|
2120
|
+
setSubagentModelOverride(model: t.ChatModel): void {
|
|
2121
|
+
this.subagentModelOverride = model;
|
|
2122
|
+
}
|
|
2123
|
+
|
|
1947
2124
|
getUsageMetadata(
|
|
1948
2125
|
finalMessage?: BaseMessage
|
|
1949
2126
|
): Partial<UsageMetadata> | undefined {
|
|
@@ -3370,7 +3547,9 @@ export class StandardGraph extends Graph<t.BaseGraphState, t.GraphNode> {
|
|
|
3370
3547
|
* would start new provider work after the run-wide breaker fired.
|
|
3371
3548
|
* Rethrow the breaker's own stream-limit reason instead. */
|
|
3372
3549
|
{
|
|
3373
|
-
const trippedReason = this.resolveTrippedBreakerReason(
|
|
3550
|
+
const trippedReason = this.resolveTrippedBreakerReason(
|
|
3551
|
+
attemptBreaker.signal
|
|
3552
|
+
);
|
|
3374
3553
|
if (trippedReason != null) {
|
|
3375
3554
|
throw trippedReason;
|
|
3376
3555
|
}
|
|
@@ -3617,7 +3796,9 @@ export class StandardGraph extends Graph<t.BaseGraphState, t.GraphNode> {
|
|
|
3617
3796
|
}
|
|
3618
3797
|
{
|
|
3619
3798
|
/** Same sibling-abort translation guard as the primary catch. */
|
|
3620
|
-
const trippedReason = this.resolveTrippedBreakerReason(
|
|
3799
|
+
const trippedReason = this.resolveTrippedBreakerReason(
|
|
3800
|
+
attemptBreaker.signal
|
|
3801
|
+
);
|
|
3621
3802
|
if (trippedReason != null) {
|
|
3622
3803
|
throw trippedReason;
|
|
3623
3804
|
}
|
|
@@ -4054,19 +4235,25 @@ export class StandardGraph extends Graph<t.BaseGraphState, t.GraphNode> {
|
|
|
4054
4235
|
tokenCounter: agentContext.tokenCounter,
|
|
4055
4236
|
usageSink: this.subagentUsageSink,
|
|
4056
4237
|
streamLimits: this.streamLimits,
|
|
4238
|
+
humanInTheLoop: this.humanInTheLoop,
|
|
4239
|
+
checkpointer: this.compileOptions?.checkpointer,
|
|
4057
4240
|
maxDepth: effectiveSubagentDepth,
|
|
4058
4241
|
createChildGraph: (input): StandardGraph => {
|
|
4059
4242
|
const childGraph = new StandardGraph(input);
|
|
4243
|
+
if (this.subagentModelOverride != null) {
|
|
4244
|
+
childGraph.overrideModel = this.subagentModelOverride;
|
|
4245
|
+
childGraph.setSubagentModelOverride(this.subagentModelOverride);
|
|
4246
|
+
}
|
|
4060
4247
|
const toolHandlerRegistry = createToolHandlerRegistry(
|
|
4061
4248
|
getParentHandlerRegistry()
|
|
4062
4249
|
);
|
|
4063
4250
|
childGraph.hookRegistry = this.hookRegistry;
|
|
4064
|
-
|
|
4065
|
-
|
|
4066
|
-
|
|
4067
|
-
|
|
4068
|
-
|
|
4069
|
-
|
|
4251
|
+
childGraph.humanInTheLoop = this.humanInTheLoop;
|
|
4252
|
+
if (this.humanInTheLoop?.enabled === true) {
|
|
4253
|
+
childGraph.compileOptions = {
|
|
4254
|
+
checkpointer: this.compileOptions?.checkpointer,
|
|
4255
|
+
};
|
|
4256
|
+
}
|
|
4070
4257
|
childGraph.toolOutputReferences = this.toolOutputReferences;
|
|
4071
4258
|
childGraph.eagerEventToolExecution = this.eagerEventToolExecution;
|
|
4072
4259
|
childGraph.codeSessionToolNames = this.codeSessionToolNames;
|
|
@@ -4088,6 +4275,7 @@ export class StandardGraph extends Graph<t.BaseGraphState, t.GraphNode> {
|
|
|
4088
4275
|
return childGraph;
|
|
4089
4276
|
},
|
|
4090
4277
|
});
|
|
4278
|
+
this.registerSubagentExecutor(executor);
|
|
4091
4279
|
|
|
4092
4280
|
const subagentTool = tool(async (rawInput, config) => {
|
|
4093
4281
|
const input = rawInput as {
|
|
@@ -4102,20 +4290,22 @@ export class StandardGraph extends Graph<t.BaseGraphState, t.GraphNode> {
|
|
|
4102
4290
|
const subagentType =
|
|
4103
4291
|
typeof input.subagent_type === 'string' ? input.subagent_type : '';
|
|
4104
4292
|
const threadId = config.configurable?.thread_id as string | undefined;
|
|
4105
|
-
/**
|
|
4106
|
-
*
|
|
4107
|
-
|
|
4108
|
-
|
|
4109
|
-
|
|
4110
|
-
|
|
4111
|
-
|
|
4112
|
-
|
|
4113
|
-
|
|
4114
|
-
|
|
4115
|
-
|
|
4116
|
-
|
|
4117
|
-
|
|
4118
|
-
|
|
4293
|
+
/** Surface the parent call id so child checkpoints, interrupts, and
|
|
4294
|
+
* update events remain correlated across replay and resume. */
|
|
4295
|
+
const toolRuntime = config as {
|
|
4296
|
+
toolCallId?: string;
|
|
4297
|
+
toolCall?: { id?: string };
|
|
4298
|
+
};
|
|
4299
|
+
const toolCall = toolRuntime.toolCall;
|
|
4300
|
+
let parentToolCallId: string | undefined;
|
|
4301
|
+
if (
|
|
4302
|
+
typeof toolRuntime.toolCallId === 'string' &&
|
|
4303
|
+
toolRuntime.toolCallId !== ''
|
|
4304
|
+
) {
|
|
4305
|
+
parentToolCallId = toolRuntime.toolCallId;
|
|
4306
|
+
} else if (typeof toolCall?.id === 'string' && toolCall.id !== '') {
|
|
4307
|
+
parentToolCallId = toolCall.id;
|
|
4308
|
+
}
|
|
4119
4309
|
/** The parent tool batch's entry-captured scope (stamped by
|
|
4120
4310
|
* ToolNode before PreToolUse hooks) — binds this child to the
|
|
4121
4311
|
* run that dispatched it, not to whatever controller a reset
|
|
@@ -4141,6 +4331,21 @@ export class StandardGraph extends Graph<t.BaseGraphState, t.GraphNode> {
|
|
|
4141
4331
|
});
|
|
4142
4332
|
return result.content;
|
|
4143
4333
|
}, buildSubagentToolParams(resolvedConfigs));
|
|
4334
|
+
const replayableSubagentTool = subagentTool as typeof subagentTool &
|
|
4335
|
+
ReplayableSubagentTool;
|
|
4336
|
+
replayableSubagentTool[SUBAGENT_REPLAY_CONTROLLER] = {
|
|
4337
|
+
getResumeManifest: (
|
|
4338
|
+
parentToolCallIds
|
|
4339
|
+
): Promise<SubagentResumeManifest | undefined> =>
|
|
4340
|
+
executor.getResumeManifest(parentToolCallIds),
|
|
4341
|
+
getSettledOutput: (
|
|
4342
|
+
call,
|
|
4343
|
+
config
|
|
4344
|
+
): Promise<SettledSubagentToolOutput | undefined> =>
|
|
4345
|
+
executor.getSettledToolOutput(call, config),
|
|
4346
|
+
persistSettledOutput: (call, config, output): Promise<void> =>
|
|
4347
|
+
executor.persistSettledToolOutput(call, config, output),
|
|
4348
|
+
};
|
|
4144
4349
|
|
|
4145
4350
|
if (!agentContext.graphTools) {
|
|
4146
4351
|
agentContext.graphTools = [];
|
|
@@ -4388,7 +4593,7 @@ export class StandardGraph extends Graph<t.BaseGraphState, t.GraphNode> {
|
|
|
4388
4593
|
const StateAnnotation = Annotation.Root({
|
|
4389
4594
|
messages: Annotation<BaseMessage[]>({
|
|
4390
4595
|
reducer: (a, b) => {
|
|
4391
|
-
if (!this.messages.length) {
|
|
4596
|
+
if (!this.messages.length && !this.hasRestoredCheckpointMessages) {
|
|
4392
4597
|
this.startIndex = a.length + b.length;
|
|
4393
4598
|
}
|
|
4394
4599
|
const result = messagesStateReducer(a, b);
|