@librechat/agents 3.3.2 → 3.3.4
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 +2 -1
- package/dist/cjs/agents/AgentContext.cjs.map +1 -1
- package/dist/cjs/graphs/Graph.cjs +342 -109
- package/dist/cjs/graphs/Graph.cjs.map +1 -1
- package/dist/cjs/graphs/MultiAgentGraph.cjs +3 -1
- package/dist/cjs/graphs/MultiAgentGraph.cjs.map +1 -1
- package/dist/cjs/langfuse.cjs +6 -0
- package/dist/cjs/langfuse.cjs.map +1 -1
- package/dist/cjs/llm/anthropic/utils/message_inputs.cjs +79 -6
- package/dist/cjs/llm/anthropic/utils/message_inputs.cjs.map +1 -1
- package/dist/cjs/llm/bedrock/utils/message_inputs.cjs +37 -10
- package/dist/cjs/llm/bedrock/utils/message_inputs.cjs.map +1 -1
- package/dist/cjs/llm/google/utils/common.cjs +19 -7
- package/dist/cjs/llm/google/utils/common.cjs.map +1 -1
- package/dist/cjs/llm/invoke.cjs +64 -3
- package/dist/cjs/llm/invoke.cjs.map +1 -1
- package/dist/cjs/llm/openai/index.cjs +41 -5
- package/dist/cjs/llm/openai/index.cjs.map +1 -1
- package/dist/cjs/llm/openai/utils/index.cjs +25 -4
- package/dist/cjs/llm/openai/utils/index.cjs.map +1 -1
- package/dist/cjs/llm/openrouter/index.cjs +4 -1
- package/dist/cjs/llm/openrouter/index.cjs.map +1 -1
- package/dist/cjs/main.cjs +19 -2
- package/dist/cjs/messages/cache.cjs +54 -33
- package/dist/cjs/messages/cache.cjs.map +1 -1
- package/dist/cjs/messages/contextPruning.cjs +17 -43
- package/dist/cjs/messages/contextPruning.cjs.map +1 -1
- package/dist/cjs/messages/core.cjs +315 -23
- package/dist/cjs/messages/core.cjs.map +1 -1
- package/dist/cjs/messages/format.cjs +218 -60
- package/dist/cjs/messages/format.cjs.map +1 -1
- package/dist/cjs/messages/index.cjs +1 -1
- package/dist/cjs/messages/prune.cjs +503 -127
- package/dist/cjs/messages/prune.cjs.map +1 -1
- package/dist/cjs/stream.cjs +7 -3
- package/dist/cjs/stream.cjs.map +1 -1
- package/dist/cjs/summarization/node.cjs +28 -14
- package/dist/cjs/summarization/node.cjs.map +1 -1
- package/dist/cjs/tools/ToolNode.cjs +54 -41
- package/dist/cjs/tools/ToolNode.cjs.map +1 -1
- package/dist/cjs/tools/toolOutputReferences.cjs +6 -0
- package/dist/cjs/tools/toolOutputReferences.cjs.map +1 -1
- package/dist/cjs/utils/index.cjs +1 -1
- package/dist/cjs/utils/llm.cjs +1 -1
- package/dist/cjs/utils/llm.cjs.map +1 -1
- package/dist/cjs/utils/tokens.cjs +307 -20
- package/dist/cjs/utils/tokens.cjs.map +1 -1
- package/dist/cjs/utils/toolContent.cjs +1514 -0
- package/dist/cjs/utils/toolContent.cjs.map +1 -0
- package/dist/esm/agents/AgentContext.mjs +2 -1
- package/dist/esm/agents/AgentContext.mjs.map +1 -1
- package/dist/esm/graphs/Graph.mjs +349 -116
- package/dist/esm/graphs/Graph.mjs.map +1 -1
- package/dist/esm/graphs/MultiAgentGraph.mjs +3 -1
- package/dist/esm/graphs/MultiAgentGraph.mjs.map +1 -1
- package/dist/esm/langfuse.mjs +6 -0
- package/dist/esm/langfuse.mjs.map +1 -1
- package/dist/esm/llm/anthropic/utils/message_inputs.mjs +79 -6
- package/dist/esm/llm/anthropic/utils/message_inputs.mjs.map +1 -1
- package/dist/esm/llm/bedrock/utils/message_inputs.mjs +37 -10
- package/dist/esm/llm/bedrock/utils/message_inputs.mjs.map +1 -1
- package/dist/esm/llm/google/utils/common.mjs +19 -7
- package/dist/esm/llm/google/utils/common.mjs.map +1 -1
- package/dist/esm/llm/invoke.mjs +65 -5
- package/dist/esm/llm/invoke.mjs.map +1 -1
- package/dist/esm/llm/openai/index.mjs +41 -5
- package/dist/esm/llm/openai/index.mjs.map +1 -1
- package/dist/esm/llm/openai/utils/index.mjs +25 -4
- package/dist/esm/llm/openai/utils/index.mjs.map +1 -1
- package/dist/esm/llm/openrouter/index.mjs +4 -1
- package/dist/esm/llm/openrouter/index.mjs.map +1 -1
- package/dist/esm/main.mjs +7 -7
- package/dist/esm/messages/cache.mjs +55 -34
- package/dist/esm/messages/cache.mjs.map +1 -1
- package/dist/esm/messages/contextPruning.mjs +17 -43
- package/dist/esm/messages/contextPruning.mjs.map +1 -1
- package/dist/esm/messages/core.mjs +305 -24
- package/dist/esm/messages/core.mjs.map +1 -1
- package/dist/esm/messages/format.mjs +218 -61
- package/dist/esm/messages/format.mjs.map +1 -1
- package/dist/esm/messages/index.mjs +1 -1
- package/dist/esm/messages/prune.mjs +500 -128
- package/dist/esm/messages/prune.mjs.map +1 -1
- package/dist/esm/stream.mjs +7 -3
- package/dist/esm/stream.mjs.map +1 -1
- package/dist/esm/summarization/node.mjs +28 -14
- package/dist/esm/summarization/node.mjs.map +1 -1
- package/dist/esm/tools/ToolNode.mjs +54 -41
- package/dist/esm/tools/ToolNode.mjs.map +1 -1
- package/dist/esm/tools/toolOutputReferences.mjs +6 -0
- package/dist/esm/tools/toolOutputReferences.mjs.map +1 -1
- package/dist/esm/utils/index.mjs +1 -1
- package/dist/esm/utils/llm.mjs +1 -1
- package/dist/esm/utils/llm.mjs.map +1 -1
- package/dist/esm/utils/tokens.mjs +307 -21
- package/dist/esm/utils/tokens.mjs.map +1 -1
- package/dist/esm/utils/toolContent.mjs +1503 -0
- package/dist/esm/utils/toolContent.mjs.map +1 -0
- package/dist/types/graphs/Graph.d.ts +1 -1
- package/dist/types/llm/invoke.d.ts +27 -1
- package/dist/types/llm/openai/index.d.ts +4 -0
- package/dist/types/llm/openai/utils/index.d.ts +2 -0
- package/dist/types/llm/openrouter/index.d.ts +5 -0
- package/dist/types/messages/contextPruning.d.ts +2 -1
- package/dist/types/messages/core.d.ts +36 -0
- package/dist/types/messages/format.d.ts +6 -0
- package/dist/types/messages/prune.d.ts +16 -12
- package/dist/types/types/stream.d.ts +1 -1
- package/dist/types/utils/tokens.d.ts +7 -0
- package/dist/types/utils/toolContent.d.ts +107 -0
- package/package.json +13 -9
- package/src/__tests__/stream.eagerEventExecution.test.ts +74 -0
- package/src/agents/AgentContext.ts +1 -0
- package/src/graphs/Graph.ts +698 -200
- package/src/graphs/MultiAgentGraph.ts +6 -1
- package/src/graphs/__tests__/Graph.contextOverflow.test.ts +1128 -4
- package/src/langfuse.ts +15 -0
- package/src/llm/anthropic/utils/message_inputs.ts +158 -12
- package/src/llm/anthropic/utils/tool-id-normalization.test.ts +109 -0
- package/src/llm/bedrock/utils/message_inputs.test.ts +49 -1
- package/src/llm/bedrock/utils/message_inputs.ts +86 -13
- package/src/llm/google/utils/common.test.ts +75 -9
- package/src/llm/google/utils/common.ts +34 -3
- package/src/llm/invoke.test.ts +488 -0
- package/src/llm/invoke.ts +196 -2
- package/src/llm/openai/index.ts +106 -6
- package/src/llm/openai/utils/index.ts +109 -53
- package/src/llm/openai/utils/messages.test.ts +330 -1
- package/src/llm/openrouter/index.ts +12 -2
- package/src/llm/openrouter/reasoning.test.ts +314 -0
- package/src/messages/__tests__/observationMasking.test.ts +93 -2
- package/src/messages/cache.tail.test.ts +193 -0
- package/src/messages/cache.test.ts +113 -0
- package/src/messages/cache.ts +92 -60
- package/src/messages/contextPruning.test.ts +184 -0
- package/src/messages/contextPruning.ts +49 -42
- package/src/messages/core.ts +653 -40
- package/src/messages/ensureThinkingBlock.test.ts +49 -1
- package/src/messages/foldToollessToolBlocks.test.ts +163 -5
- package/src/messages/format.ts +363 -91
- package/src/messages/formatAgentMessages.test.ts +604 -14
- package/src/messages/formatAgentMessages.tools.test.ts +103 -0
- package/src/messages/prune.ts +996 -183
- package/src/specs/langfuse-callbacks.test.ts +203 -1
- package/src/specs/prune.test.ts +1083 -6
- package/src/specs/summarization-unit.test.ts +105 -0
- package/src/specs/tokens.test.ts +609 -32
- package/src/stream.ts +23 -15
- package/src/summarization/__tests__/node.test.ts +77 -0
- package/src/summarization/node.ts +46 -18
- package/src/tools/ToolNode.ts +147 -68
- package/src/tools/__tests__/ToolNode.onResultCompletion.test.ts +148 -1
- package/src/tools/__tests__/ToolNode.outputReferences.test.ts +112 -3
- package/src/tools/__tests__/annotateMessagesForLLM.test.ts +32 -0
- package/src/tools/__tests__/directToolHooks.test.ts +255 -7
- package/src/tools/toolOutputReferences.ts +6 -0
- package/src/types/stream.ts +1 -1
- package/src/utils/llm.test.ts +18 -0
- package/src/utils/llm.ts +4 -1
- package/src/utils/tokens.ts +586 -31
- package/src/utils/toolContent.test.ts +1432 -0
- package/src/utils/toolContent.ts +2707 -0
|
@@ -5,15 +5,17 @@ const require_langfuseToolOutputTracing = require("../langfuseToolOutputTracing.
|
|
|
5
5
|
const require_callbacks = require("../utils/callbacks.cjs");
|
|
6
6
|
const require_enum = require("../common/enum.cjs");
|
|
7
7
|
require("../common/index.cjs");
|
|
8
|
+
const require_truncation = require("../utils/truncation.cjs");
|
|
9
|
+
const require_toolContent = require("../utils/toolContent.cjs");
|
|
8
10
|
const require_tokens = require("../utils/tokens.cjs");
|
|
9
11
|
const require_instrumentation = require("../instrumentation.cjs");
|
|
12
|
+
const require_cache = require("../messages/cache.cjs");
|
|
10
13
|
const require_core = require("../messages/core.cjs");
|
|
11
14
|
const require_ids = require("../messages/ids.cjs");
|
|
12
15
|
const require_prune = require("../messages/prune.cjs");
|
|
13
16
|
const require_budget = require("../messages/budget.cjs");
|
|
14
17
|
const require_events = require("../utils/events.cjs");
|
|
15
18
|
const require_format = require("../messages/format.cjs");
|
|
16
|
-
const require_cache = require("../messages/cache.cjs");
|
|
17
19
|
const require_anthropicToolCache = require("../messages/anthropicToolCache.cjs");
|
|
18
20
|
const require_content = require("../messages/content.cjs");
|
|
19
21
|
const require_tools = require("../messages/tools.cjs");
|
|
@@ -27,10 +29,10 @@ const require_toolOutputReferences = require("../tools/toolOutputReferences.cjs"
|
|
|
27
29
|
const require_events$1 = require("../events.cjs");
|
|
28
30
|
const require_run = require("../utils/run.cjs");
|
|
29
31
|
require("../utils/index.cjs");
|
|
30
|
-
const require_contextOverflowRecovery = require("../llm/contextOverflowRecovery.cjs");
|
|
31
32
|
const require_toolCache = require("../llm/bedrock/toolCache.cjs");
|
|
32
33
|
const require_init = require("../llm/init.cjs");
|
|
33
34
|
const require_invoke = require("../llm/invoke.cjs");
|
|
35
|
+
const require_contextOverflowRecovery = require("../llm/contextOverflowRecovery.cjs");
|
|
34
36
|
const require_toolCache$1 = require("../llm/openrouter/toolCache.cjs");
|
|
35
37
|
const require_LocalCodingTools = require("../tools/local/LocalCodingTools.cjs");
|
|
36
38
|
const require_CloudflareSandboxTools = require("../tools/cloudflare/CloudflareSandboxTools.cjs");
|
|
@@ -51,6 +53,7 @@ let _langchain_core_messages = require("@langchain/core/messages");
|
|
|
51
53
|
let _langchain_langgraph = require("@langchain/langgraph");
|
|
52
54
|
let _langchain_core_tools = require("@langchain/core/tools");
|
|
53
55
|
let nanoid = require("nanoid");
|
|
56
|
+
let _langchain_core_errors = require("@langchain/core/errors");
|
|
54
57
|
//#region src/graphs/Graph.ts
|
|
55
58
|
const { AGENT, TOOLS, SUMMARIZE } = require_enum.GraphNodeKeys;
|
|
56
59
|
/** Minimum relative variance before calibrated toolSchemaTokens overrides current value. */
|
|
@@ -62,19 +65,6 @@ function createToolHandlerRegistry(source) {
|
|
|
62
65
|
registry.register("on_tool_execute", toolHandler);
|
|
63
66
|
return registry;
|
|
64
67
|
}
|
|
65
|
-
/**
|
|
66
|
-
* Start index of the span post-prune formatters can mutate in place: the
|
|
67
|
-
* trailing tool batch plus its owning AI message (artifact formatting touches
|
|
68
|
-
* every tool result after the last AI tool call; Bedrock rewrites the AI
|
|
69
|
-
* message before a trailing tool result). Capped so the usage-snapshot
|
|
70
|
-
* recount stays constant-cost.
|
|
71
|
-
*/
|
|
72
|
-
function trailingMutationStart(messages) {
|
|
73
|
-
const MAX_SPAN = 16;
|
|
74
|
-
let index = messages.length - 1;
|
|
75
|
-
while (index >= 0 && messages[index]?.getType() === "tool" && messages.length - index < MAX_SPAN) index--;
|
|
76
|
-
return Math.max(0, Math.min(index, messages.length - 2));
|
|
77
|
-
}
|
|
78
68
|
function getHandlerDispatchedEventKey(eventName, stepId) {
|
|
79
69
|
return `${eventName}:${stepId}`;
|
|
80
70
|
}
|
|
@@ -901,6 +891,7 @@ var StandardGraph = class StandardGraph extends Graph {
|
|
|
901
891
|
provider: agentContext.provider,
|
|
902
892
|
tokenCounter: agentContext.tokenCounter,
|
|
903
893
|
maxTokens: agentContext.maxContextTokens,
|
|
894
|
+
maxToolResultChars: agentContext.maxToolResultChars,
|
|
904
895
|
thinkingEnabled: require_request.isThinkingEnabled(agentContext.provider, agentContext.clientOptions),
|
|
905
896
|
indexTokenCountMap: agentContext.indexTokenCountMap,
|
|
906
897
|
contextPruningConfig: agentContext.contextPruningConfig,
|
|
@@ -1010,28 +1001,73 @@ var StandardGraph = class StandardGraph extends Graph {
|
|
|
1010
1001
|
}
|
|
1011
1002
|
}
|
|
1012
1003
|
let finalMessages = messagesToUse;
|
|
1013
|
-
/**
|
|
1014
|
-
*
|
|
1015
|
-
*
|
|
1016
|
-
*
|
|
1017
|
-
*
|
|
1018
|
-
*
|
|
1019
|
-
|
|
1020
|
-
let
|
|
1021
|
-
|
|
1022
|
-
let preFormatLegacyTokens = 0;
|
|
1004
|
+
/**
|
|
1005
|
+
* Keep the pruner's provider-grounded aggregate as the authoritative
|
|
1006
|
+
* baseline, then attribute it across retained messages. Provider
|
|
1007
|
+
* transforms can shrink one message while expanding or adding another;
|
|
1008
|
+
* per-origin accounting prevents that unrelated shrink from canceling
|
|
1009
|
+
* the expansion. Raw counts are frozen before in-place formatters run.
|
|
1010
|
+
*/
|
|
1011
|
+
let providerMessageBaseline;
|
|
1012
|
+
const providerMessageOrigins = /* @__PURE__ */ new WeakMap();
|
|
1023
1013
|
if (contextUsage != null && agentContext.tokenCounter != null) {
|
|
1024
|
-
|
|
1025
|
-
for (
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1014
|
+
const sourceIndices = /* @__PURE__ */ new WeakMap();
|
|
1015
|
+
for (let i = 0; i < messages.length; i++) sourceIndices.set(messages[i], i);
|
|
1016
|
+
providerMessageBaseline = messagesToUse.map((message, index) => {
|
|
1017
|
+
const rawTokens = agentContext.tokenCounter(message);
|
|
1018
|
+
const sourceIndex = sourceIndices.get(message);
|
|
1019
|
+
const indexedTokens = sourceIndex != null ? agentContext.indexTokenCountMap[sourceIndex] : void 0;
|
|
1020
|
+
const accountingWeight = indexedTokens != null && Number.isFinite(indexedTokens) && indexedTokens >= 0 ? indexedTokens : rawTokens;
|
|
1021
|
+
if (!providerMessageOrigins.has(message)) providerMessageOrigins.set(message, index);
|
|
1022
|
+
return {
|
|
1023
|
+
rawTokens,
|
|
1024
|
+
accountingWeight
|
|
1025
|
+
};
|
|
1026
|
+
});
|
|
1027
|
+
}
|
|
1028
|
+
const getProviderMessageOriginKey = (message) => {
|
|
1029
|
+
const type = message.getType();
|
|
1030
|
+
if (message instanceof _langchain_core_messages.ToolMessage && typeof message.tool_call_id === "string" && message.tool_call_id.length > 0) return `tool:call:${message.tool_call_id}`;
|
|
1031
|
+
if (typeof message.id === "string" && message.id.length > 0) return `${type}:id:${message.id}`;
|
|
1032
|
+
};
|
|
1033
|
+
/**
|
|
1034
|
+
* Provider projections clone messages. Preserve their baseline origin
|
|
1035
|
+
* without writing tracking metadata onto the wire. Synthetic fold
|
|
1036
|
+
* messages intentionally remain unattributed and are charged in full.
|
|
1037
|
+
*/
|
|
1038
|
+
const trackProviderMessageOrigins = (before, after) => {
|
|
1039
|
+
if (providerMessageBaseline == null || before === after) return after;
|
|
1040
|
+
if (before.length === after.length) {
|
|
1041
|
+
for (let i = 0; i < after.length; i++) {
|
|
1042
|
+
const origin = providerMessageOrigins.get(before[i]);
|
|
1043
|
+
if (origin != null && !providerMessageOrigins.has(after[i]) && before[i].getType() === after[i].getType() && !require_format.isSyntheticProviderContextMessage(after[i])) providerMessageOrigins.set(after[i], origin);
|
|
1031
1044
|
}
|
|
1045
|
+
return after;
|
|
1046
|
+
}
|
|
1047
|
+
const keyedOrigins = /* @__PURE__ */ new Map();
|
|
1048
|
+
for (const message of before) {
|
|
1049
|
+
const origin = providerMessageOrigins.get(message);
|
|
1050
|
+
const key = getProviderMessageOriginKey(message);
|
|
1051
|
+
if (origin == null || key == null) continue;
|
|
1052
|
+
keyedOrigins.set(key, keyedOrigins.has(key) ? null : origin);
|
|
1053
|
+
}
|
|
1054
|
+
for (const message of after) {
|
|
1055
|
+
if (providerMessageOrigins.has(message) || require_format.isSyntheticProviderContextMessage(message)) continue;
|
|
1056
|
+
const key = getProviderMessageOriginKey(message);
|
|
1057
|
+
const origin = key != null ? keyedOrigins.get(key) : void 0;
|
|
1058
|
+
if (origin != null) providerMessageOrigins.set(message, origin);
|
|
1032
1059
|
}
|
|
1060
|
+
return after;
|
|
1061
|
+
};
|
|
1062
|
+
if (agentContext.useLegacyContent) {
|
|
1063
|
+
const before = finalMessages;
|
|
1064
|
+
finalMessages = trackProviderMessageOrigins(before, require_content.formatContentStrings(before));
|
|
1033
1065
|
}
|
|
1034
|
-
|
|
1066
|
+
const maxProviderToolResultChars = agentContext.maxToolResultChars ?? require_truncation.calculateMaxToolResultChars(agentContext.maxContextTokens);
|
|
1067
|
+
const beforeToolStreamProjection = finalMessages;
|
|
1068
|
+
finalMessages = trackProviderMessageOrigins(beforeToolStreamProjection, require_core.projectToolStreamContentForProvider(beforeToolStreamProjection));
|
|
1069
|
+
const beforeToolInputProjection = finalMessages;
|
|
1070
|
+
finalMessages = trackProviderMessageOrigins(beforeToolInputProjection, require_prune.projectToolCallInputs(beforeToolInputProjection, require_prune.calculateMaxToolCallInputChars(agentContext.maxContextTokens)));
|
|
1035
1071
|
const lastMessageX = finalMessages.length >= 2 ? finalMessages[finalMessages.length - 2] : null;
|
|
1036
1072
|
const lastMessageY = finalMessages.length >= 1 ? finalMessages[finalMessages.length - 1] : null;
|
|
1037
1073
|
const anthropicLike = require_llm.isAnthropicLike(agentContext.provider, agentContext.clientOptions);
|
|
@@ -1042,34 +1078,186 @@ var StandardGraph = class StandardGraph extends Graph {
|
|
|
1042
1078
|
text: trimmed
|
|
1043
1079
|
}] : "";
|
|
1044
1080
|
}
|
|
1081
|
+
const localProviderOverflowMeasurements = /* @__PURE__ */ new WeakMap();
|
|
1082
|
+
const measureProviderPayload = (candidate, contextBudgetOverride, forceRawRecount = false) => {
|
|
1083
|
+
const contextBudget = contextBudgetOverride ?? contextUsage?.contextBudget;
|
|
1084
|
+
const effectiveInstructionTokens = contextUsage?.effectiveInstructionTokens ?? (forceRawRecount ? agentContext.instructionTokens : void 0);
|
|
1085
|
+
if (agentContext.tokenCounter == null || contextBudget == null || effectiveInstructionTokens == null) return { fits: true };
|
|
1086
|
+
const availableMessageTokens = Math.max(0, contextBudget - effectiveInstructionTokens);
|
|
1087
|
+
let usageRatio = agentContext.calibrationRatio > 0 ? agentContext.calibrationRatio : 1;
|
|
1088
|
+
if (contextUsage?.calibrationRatio != null && contextUsage.calibrationRatio > 0) usageRatio = contextUsage.calibrationRatio;
|
|
1089
|
+
if (forceRawRecount) usageRatio = Math.max(1, usageRatio);
|
|
1090
|
+
const baselineRemaining = contextUsage?.remainingContextTokens;
|
|
1091
|
+
const accountedMessageTokens = !forceRawRecount && providerMessageBaseline != null && baselineRemaining != null && Number.isFinite(baselineRemaining) ? availableMessageTokens - Math.min(availableMessageTokens, Math.max(0, baselineRemaining)) : void 0;
|
|
1092
|
+
let projectedMessageTokens;
|
|
1093
|
+
if (accountedMessageTokens != null && providerMessageBaseline != null) {
|
|
1094
|
+
const replyPrimerTokens = Math.round(3 * usageRatio);
|
|
1095
|
+
const rawWeights = {};
|
|
1096
|
+
let totalWeight = 0;
|
|
1097
|
+
for (let i = 0; i < providerMessageBaseline.length; i++) {
|
|
1098
|
+
const weight = providerMessageBaseline[i].accountingWeight;
|
|
1099
|
+
rawWeights[i] = weight;
|
|
1100
|
+
totalWeight += weight;
|
|
1101
|
+
}
|
|
1102
|
+
const attributableTokens = totalWeight > 0 ? Math.min(Math.max(0, accountedMessageTokens - replyPrimerTokens), Math.round(totalWeight * usageRatio)) : 0;
|
|
1103
|
+
const apportionedTokens = totalWeight > 0 ? require_tokens.apportionTokenCounts(rawWeights, attributableTokens / totalWeight, attributableTokens) : {};
|
|
1104
|
+
const attributedByOrigin = providerMessageBaseline.map((_, origin) => apportionedTokens[origin] || 0);
|
|
1105
|
+
projectedMessageTokens = Math.max(replyPrimerTokens, accountedMessageTokens - attributableTokens);
|
|
1106
|
+
let newRawTokens = 0;
|
|
1107
|
+
const usedOrigins = /* @__PURE__ */ new Set();
|
|
1108
|
+
for (const message of candidate) {
|
|
1109
|
+
const rawTokens = agentContext.tokenCounter(message);
|
|
1110
|
+
const origin = providerMessageOrigins.get(message);
|
|
1111
|
+
if (origin == null || usedOrigins.has(origin)) {
|
|
1112
|
+
newRawTokens += rawTokens;
|
|
1113
|
+
continue;
|
|
1114
|
+
}
|
|
1115
|
+
usedOrigins.add(origin);
|
|
1116
|
+
projectedMessageTokens += Math.max(0, attributedByOrigin[origin] + Math.round((rawTokens - providerMessageBaseline[origin].rawTokens) * usageRatio));
|
|
1117
|
+
}
|
|
1118
|
+
projectedMessageTokens += Math.round(newRawTokens * usageRatio);
|
|
1119
|
+
} else {
|
|
1120
|
+
let rawTokens = 3;
|
|
1121
|
+
for (const message of candidate) rawTokens += agentContext.tokenCounter(message);
|
|
1122
|
+
projectedMessageTokens = Math.round(rawTokens * usageRatio);
|
|
1123
|
+
}
|
|
1124
|
+
return {
|
|
1125
|
+
fits: projectedMessageTokens <= availableMessageTokens,
|
|
1126
|
+
projectedMessageTokens,
|
|
1127
|
+
availableMessageTokens,
|
|
1128
|
+
contextBudget,
|
|
1129
|
+
effectiveInstructionTokens
|
|
1130
|
+
};
|
|
1131
|
+
};
|
|
1132
|
+
const createProviderPayloadOverflowError = ({ projection, provider, info }) => {
|
|
1133
|
+
const error = new _langchain_core_errors.ContextOverflowError(JSON.stringify({
|
|
1134
|
+
type: "final_context_overflow",
|
|
1135
|
+
info,
|
|
1136
|
+
provider,
|
|
1137
|
+
projectedMessageTokens: projection.projectedMessageTokens,
|
|
1138
|
+
availableMessageTokens: projection.availableMessageTokens
|
|
1139
|
+
}));
|
|
1140
|
+
if (projection.projectedMessageTokens != null && projection.contextBudget != null && projection.effectiveInstructionTokens != null) localProviderOverflowMeasurements.set(error, {
|
|
1141
|
+
contextBudget: projection.contextBudget,
|
|
1142
|
+
estimatedPromptTokens: projection.projectedMessageTokens + projection.effectiveInstructionTokens
|
|
1143
|
+
});
|
|
1144
|
+
return error;
|
|
1145
|
+
};
|
|
1146
|
+
const applyProviderMessageTransforms = (candidate) => {
|
|
1147
|
+
let transformed = candidate;
|
|
1148
|
+
if (require_request.isThinkingEnabled(agentContext.provider, agentContext.clientOptions)) {
|
|
1149
|
+
/**
|
|
1150
|
+
* Current-run AI messages may validly omit a thinking block. The
|
|
1151
|
+
* boundary prevents them from being mistaken for foreign history.
|
|
1152
|
+
*/
|
|
1153
|
+
const before = transformed;
|
|
1154
|
+
transformed = trackProviderMessageOrigins(before, require_format.ensureThinkingBlockInMessages(before, agentContext.provider, config, this.startIndex));
|
|
1155
|
+
}
|
|
1156
|
+
/**
|
|
1157
|
+
* Tool-less destinations cannot send inherited tool blocks without a
|
|
1158
|
+
* tool schema, so fold those interactions into provider-valid content.
|
|
1159
|
+
*/
|
|
1160
|
+
if (toolsForBinding == null || toolsForBinding.length === 0) {
|
|
1161
|
+
const before = transformed;
|
|
1162
|
+
transformed = trackProviderMessageOrigins(before, require_format.foldToolBlocksForToollessAgent(before, config));
|
|
1163
|
+
if (agentContext.useLegacyContent) {
|
|
1164
|
+
const beforeLegacyFormat = transformed;
|
|
1165
|
+
transformed = trackProviderMessageOrigins(beforeLegacyFormat, require_content.formatContentStrings(beforeLegacyFormat));
|
|
1166
|
+
}
|
|
1167
|
+
}
|
|
1168
|
+
return transformed;
|
|
1169
|
+
};
|
|
1170
|
+
const toolOutputRegistry = this.getOrCreateToolOutputRegistry();
|
|
1171
|
+
const providerRunId = config.configurable?.run_id;
|
|
1172
|
+
const projectProviderReferences = (candidate) => trackProviderMessageOrigins(candidate, require_toolOutputReferences.annotateMessagesForLLM(candidate, toolOutputRegistry, providerRunId));
|
|
1173
|
+
const compactSyntheticProviderContext = (candidate) => {
|
|
1174
|
+
const synthetic = [];
|
|
1175
|
+
for (let i = 0; i < candidate.length; i++) {
|
|
1176
|
+
const message = candidate[i];
|
|
1177
|
+
if (!(message instanceof _langchain_core_messages.HumanMessage) || !require_format.isSyntheticProviderContextMessage(message)) continue;
|
|
1178
|
+
const content = message.content;
|
|
1179
|
+
synthetic.push({
|
|
1180
|
+
index: i,
|
|
1181
|
+
message,
|
|
1182
|
+
chars: require_toolContent.getToolContentCharLength(content)
|
|
1183
|
+
});
|
|
1184
|
+
}
|
|
1185
|
+
if (synthetic.length === 0) return candidate;
|
|
1186
|
+
const buildCandidate = (scale) => {
|
|
1187
|
+
const compacted = [...candidate];
|
|
1188
|
+
for (const { index, message, chars } of synthetic) {
|
|
1189
|
+
const content = require_toolContent.compactToolContent(message.content, Math.floor(chars * scale)).content;
|
|
1190
|
+
compacted[index] = new _langchain_core_messages.HumanMessage({
|
|
1191
|
+
content,
|
|
1192
|
+
id: message.id,
|
|
1193
|
+
name: message.name,
|
|
1194
|
+
additional_kwargs: message.additional_kwargs,
|
|
1195
|
+
response_metadata: message.response_metadata
|
|
1196
|
+
});
|
|
1197
|
+
}
|
|
1198
|
+
return compacted;
|
|
1199
|
+
};
|
|
1200
|
+
let best = buildCandidate(0);
|
|
1201
|
+
if (!measureProviderPayload(best).fits) return candidate;
|
|
1202
|
+
let low = 0;
|
|
1203
|
+
let high = 1;
|
|
1204
|
+
for (let i = 0; i < 12; i++) {
|
|
1205
|
+
const scale = (low + high) / 2;
|
|
1206
|
+
const attempt = buildCandidate(scale);
|
|
1207
|
+
if (measureProviderPayload(attempt).fits) {
|
|
1208
|
+
best = attempt;
|
|
1209
|
+
low = scale;
|
|
1210
|
+
} else high = scale;
|
|
1211
|
+
}
|
|
1212
|
+
return best;
|
|
1213
|
+
};
|
|
1214
|
+
let artifactBaseMessages;
|
|
1045
1215
|
if (lastMessageY instanceof _langchain_core_messages.ToolMessage) {
|
|
1046
|
-
|
|
1047
|
-
|
|
1216
|
+
let artifactCandidate = finalMessages;
|
|
1217
|
+
if (anthropicLike) artifactCandidate = trackProviderMessageOrigins(finalMessages, require_core.projectAnthropicArtifactContent(finalMessages, maxProviderToolResultChars));
|
|
1218
|
+
else if (require_llm.isOpenAILike(agentContext.provider) && agentContext.provider !== "deepseek" || require_llm.isGoogleLike(agentContext.provider)) artifactCandidate = trackProviderMessageOrigins(finalMessages, require_core.projectArtifactPayload(finalMessages, maxProviderToolResultChars));
|
|
1219
|
+
if (artifactCandidate !== finalMessages) {
|
|
1220
|
+
const projection = measureProviderPayload(artifactCandidate);
|
|
1221
|
+
if (projection.fits) {
|
|
1222
|
+
artifactBaseMessages = finalMessages;
|
|
1223
|
+
finalMessages = artifactCandidate;
|
|
1224
|
+
} else require_events.emitAgentLog(config, "warn", "graph", "Artifact payload omitted because it exceeds the remaining context budget", {
|
|
1225
|
+
projectedMessageTokens: projection.projectedMessageTokens,
|
|
1226
|
+
availableMessageTokens: projection.availableMessageTokens
|
|
1227
|
+
}, {
|
|
1228
|
+
runId: this.runId,
|
|
1229
|
+
agentId
|
|
1230
|
+
});
|
|
1231
|
+
}
|
|
1048
1232
|
}
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1233
|
+
finalMessages = projectProviderReferences(applyProviderMessageTransforms(finalMessages));
|
|
1234
|
+
let finalProjection = measureProviderPayload(finalMessages);
|
|
1235
|
+
if (artifactBaseMessages != null) {
|
|
1236
|
+
if (!finalProjection.fits) {
|
|
1237
|
+
finalMessages = projectProviderReferences(applyProviderMessageTransforms(artifactBaseMessages));
|
|
1238
|
+
finalProjection = measureProviderPayload(finalMessages);
|
|
1239
|
+
require_events.emitAgentLog(config, "warn", "graph", "Artifact payload omitted after final provider formatting exceeded the remaining context budget", {
|
|
1240
|
+
projectedMessageTokens: finalProjection.projectedMessageTokens,
|
|
1241
|
+
availableMessageTokens: finalProjection.availableMessageTokens
|
|
1242
|
+
}, {
|
|
1243
|
+
runId: this.runId,
|
|
1244
|
+
agentId
|
|
1245
|
+
});
|
|
1246
|
+
}
|
|
1247
|
+
}
|
|
1248
|
+
if (!finalProjection.fits) {
|
|
1249
|
+
const compacted = compactSyntheticProviderContext(finalMessages);
|
|
1250
|
+
if (compacted !== finalMessages) {
|
|
1251
|
+
finalMessages = compacted;
|
|
1252
|
+
finalProjection = measureProviderPayload(finalMessages);
|
|
1253
|
+
require_events.emitAgentLog(config, finalProjection.fits ? "warn" : "error", "graph", finalProjection.fits ? "Synthetic provider context compacted to fit the final payload budget" : "Final provider payload still exceeds budget after synthetic context compaction", {
|
|
1254
|
+
projectedMessageTokens: finalProjection.projectedMessageTokens,
|
|
1255
|
+
availableMessageTokens: finalProjection.availableMessageTokens
|
|
1256
|
+
}, {
|
|
1257
|
+
runId: this.runId,
|
|
1258
|
+
agentId
|
|
1259
|
+
});
|
|
1260
|
+
}
|
|
1073
1261
|
}
|
|
1074
1262
|
const anthropicPromptCacheEnabled = agentContext.provider === "anthropic" && agentContext.clientOptions?.promptCache === true;
|
|
1075
1263
|
const openRouterPromptCacheEnabled = agentContext.provider === "openrouter" && agentContext.clientOptions?.promptCache === true;
|
|
@@ -1077,7 +1265,11 @@ var StandardGraph = class StandardGraph extends Graph {
|
|
|
1077
1265
|
const providerPromptCacheEnabled = anthropicPromptCacheEnabled || openRouterPromptCacheEnabled || bedrockPromptCacheEnabled;
|
|
1078
1266
|
if (anthropicLike && (!agentContext.pruneMessages || finalMessages !== messagesToUse || providerPromptCacheEnabled)) {
|
|
1079
1267
|
const beforeSanitize = finalMessages.length;
|
|
1080
|
-
|
|
1268
|
+
const beforeSanitizeMessages = finalMessages;
|
|
1269
|
+
finalMessages = trackProviderMessageOrigins(beforeSanitizeMessages, require_prune.sanitizeOrphanToolBlocks(beforeSanitizeMessages, (source, clone) => {
|
|
1270
|
+
const origin = providerMessageOrigins.get(source);
|
|
1271
|
+
if (origin != null) providerMessageOrigins.set(clone, origin);
|
|
1272
|
+
}));
|
|
1081
1273
|
if (finalMessages.length !== beforeSanitize) require_events.emitAgentLog(config, "warn", "sanitize", "Orphan tool blocks removed", {
|
|
1082
1274
|
before: beforeSanitize,
|
|
1083
1275
|
after: finalMessages.length,
|
|
@@ -1087,11 +1279,34 @@ var StandardGraph = class StandardGraph extends Graph {
|
|
|
1087
1279
|
agentId
|
|
1088
1280
|
});
|
|
1089
1281
|
}
|
|
1090
|
-
if ((anthropicPromptCacheEnabled || openRouterPromptCacheEnabled) && !agentContext.systemRunnable)
|
|
1091
|
-
|
|
1282
|
+
if ((anthropicPromptCacheEnabled || openRouterPromptCacheEnabled) && !agentContext.systemRunnable) {
|
|
1283
|
+
const beforeCacheControl = finalMessages;
|
|
1284
|
+
finalMessages = trackProviderMessageOrigins(beforeCacheControl, require_cache.addTailCacheControl(beforeCacheControl, require_cache.resolvePromptCacheTtl(anthropicPromptCacheEnabled ? agentContext.clientOptions?.promptCacheTtl : agentContext.clientOptions?.promptCacheTtl)));
|
|
1285
|
+
} else if (bedrockPromptCacheEnabled) {
|
|
1092
1286
|
const bedrockOptions = agentContext.clientOptions;
|
|
1093
|
-
|
|
1287
|
+
const beforeCacheControl = finalMessages;
|
|
1288
|
+
finalMessages = trackProviderMessageOrigins(beforeCacheControl, require_cache.addBedrockTailCacheControl(beforeCacheControl, require_cache.resolveBedrockPromptCacheTtl(bedrockOptions?.promptCacheTtl, bedrockOptions?.model)));
|
|
1094
1289
|
}
|
|
1290
|
+
const fallbackBaseMessages = finalMessages;
|
|
1291
|
+
const beforeFinalProviderProjection = fallbackBaseMessages;
|
|
1292
|
+
finalMessages = trackProviderMessageOrigins(beforeFinalProviderProjection, require_invoke.projectMessagesForProvider({
|
|
1293
|
+
model: this.overrideModel ?? model,
|
|
1294
|
+
messages: beforeFinalProviderProjection,
|
|
1295
|
+
provider: agentContext.provider,
|
|
1296
|
+
maxToolResultChars: maxProviderToolResultChars,
|
|
1297
|
+
callOptions: config
|
|
1298
|
+
}));
|
|
1299
|
+
/**
|
|
1300
|
+
* Prompt-cache placement and orphan sanitization are provider-wire
|
|
1301
|
+
* transforms too. Re-measure after both so no content added after the
|
|
1302
|
+
* earlier artifact/synthetic compaction decision can bypass the guard.
|
|
1303
|
+
*/
|
|
1304
|
+
finalProjection = measureProviderPayload(finalMessages);
|
|
1305
|
+
const preInvokeContextOverflowError = !finalProjection.fits ? createProviderPayloadOverflowError({
|
|
1306
|
+
projection: finalProjection,
|
|
1307
|
+
provider: agentContext.provider,
|
|
1308
|
+
info: "Provider message formatting exceeded the context budget and no safe synthetic-context compaction could make it fit."
|
|
1309
|
+
}) : void 0;
|
|
1095
1310
|
if (agentContext.lastStreamCall != null && agentContext.streamBuffer != null) {
|
|
1096
1311
|
const timeSinceLastCall = Date.now() - agentContext.lastStreamCall;
|
|
1097
1312
|
if (timeSinceLastCall < agentContext.streamBuffer) await require_run.sleep(Math.ceil((agentContext.streamBuffer - timeSinceLastCall) / 1e3) * 1e3);
|
|
@@ -1125,28 +1340,9 @@ var StandardGraph = class StandardGraph extends Graph {
|
|
|
1125
1340
|
}
|
|
1126
1341
|
/** Past the empty-prompt guard — a model call is now guaranteed */
|
|
1127
1342
|
if (contextUsage != null) {
|
|
1128
|
-
|
|
1129
|
-
if (agentContext.tokenCounter != null && finalMessages.length !== messagesToUse.length) {
|
|
1130
|
-
/** Post-prune formatting restructured the payload (e.g. thinking
|
|
1131
|
-
* placeholder collapse, orphan drops) — recount so the gauge
|
|
1132
|
-
* reflects what is actually sent */
|
|
1133
|
-
let rawTokens = 0;
|
|
1134
|
-
for (const message of finalMessages) rawTokens += agentContext.tokenCounter(message);
|
|
1343
|
+
if (finalProjection.projectedMessageTokens != null && finalProjection.availableMessageTokens != null) {
|
|
1135
1344
|
contextUsage.breakdown.messageCount = finalMessages.length;
|
|
1136
|
-
|
|
1137
|
-
} else if (preFormatTailTokens != null && agentContext.tokenCounter != null && contextUsage.remainingContextTokens != null) {
|
|
1138
|
-
/** Same-length formatting can still mutate in place — the trailing
|
|
1139
|
-
* tool batch (artifacts, Bedrock rewrites) and any legacy-converted
|
|
1140
|
-
* messages before it — adjust remaining by the calibrated delta */
|
|
1141
|
-
let postFormatTailTokens = 0;
|
|
1142
|
-
for (const message of finalMessages.slice(tailStart)) postFormatTailTokens += agentContext.tokenCounter(message);
|
|
1143
|
-
let formatDelta = postFormatTailTokens - preFormatTailTokens;
|
|
1144
|
-
if (legacyIndices != null && legacyIndices.length > 0) {
|
|
1145
|
-
let postFormatLegacyTokens = 0;
|
|
1146
|
-
for (const index of legacyIndices) postFormatLegacyTokens += agentContext.tokenCounter(finalMessages[index]);
|
|
1147
|
-
formatDelta += postFormatLegacyTokens - preFormatLegacyTokens;
|
|
1148
|
-
}
|
|
1149
|
-
if (formatDelta !== 0) contextUsage.remainingContextTokens = Math.max(0, Math.min(contextUsage.contextBudget ?? Number.MAX_SAFE_INTEGER, contextUsage.remainingContextTokens - Math.round(formatDelta * usageRatio)));
|
|
1345
|
+
contextUsage.remainingContextTokens = Math.max(0, finalProjection.availableMessageTokens - finalProjection.projectedMessageTokens);
|
|
1150
1346
|
}
|
|
1151
1347
|
require_budget.syncBudgetDerivedFields(contextUsage);
|
|
1152
1348
|
/** Awaited so async host handlers receive the pre-invoke snapshot
|
|
@@ -1194,6 +1390,7 @@ var StandardGraph = class StandardGraph extends Graph {
|
|
|
1194
1390
|
}
|
|
1195
1391
|
const metadata = config.metadata;
|
|
1196
1392
|
try {
|
|
1393
|
+
if (preInvokeContextOverflowError != null) throw preInvokeContextOverflowError;
|
|
1197
1394
|
result = await require_langfuseRuntimeScope.withLangfuseRuntimeScope(require_langfuseRuntimeScope.resolveLangfuseRuntimeScope({
|
|
1198
1395
|
runLangfuse: this.langfuse,
|
|
1199
1396
|
langfuseOverlay: agentContext.langfuse
|
|
@@ -1223,31 +1420,37 @@ var StandardGraph = class StandardGraph extends Graph {
|
|
|
1223
1420
|
* keeps the original error and one round trip instead of three.
|
|
1224
1421
|
*/
|
|
1225
1422
|
const estimatedPromptTokens = getEstimatedPromptTokens(contextUsage);
|
|
1226
|
-
/**
|
|
1227
|
-
* A previous correction that left the prompt no smaller proves this
|
|
1228
|
-
* state has nothing left to compact — an emptied message list whose
|
|
1229
|
-
* content rides along in an injected summary, for instance. Measuring
|
|
1230
|
-
* that beats trying to predict every such configuration.
|
|
1231
|
-
*/
|
|
1232
|
-
const recoveryStalled = agentContext.overflowRecoveryStalled(estimatedPromptTokens);
|
|
1233
1423
|
const canSummarizeOverflow = agentContext.summarizationEnabled === true && require_recency.splitAtRecencyBoundary(messages, {
|
|
1234
1424
|
turns: agentContext.summarizationConfig?.retainRecent?.turns ?? 2,
|
|
1235
1425
|
tokens: agentContext.summarizationConfig?.retainRecent?.tokens,
|
|
1236
1426
|
tokenCounter: agentContext.tokenCounter
|
|
1237
1427
|
}).head.length > 0;
|
|
1428
|
+
const getLocalProviderOverflowMeasurement = (error) => typeof error === "object" && error !== null ? localProviderOverflowMeasurements.get(error) : void 0;
|
|
1429
|
+
const getRecoveryPromptEstimate = (error, fallbackContext) => {
|
|
1430
|
+
const resolvedFallbackContext = fallbackContext ?? require_invoke.getFallbackErrorContext(error);
|
|
1431
|
+
return getLocalProviderOverflowMeasurement(error)?.estimatedPromptTokens ?? (resolvedFallbackContext == null ? estimatedPromptTokens : void 0);
|
|
1432
|
+
};
|
|
1238
1433
|
const planRecovery = (error, attributedFallbackContext) => {
|
|
1239
|
-
if (recoveryStalled) return null;
|
|
1240
1434
|
/**
|
|
1241
1435
|
* When the rejection came from a fallback, plan against *that*
|
|
1242
1436
|
* client: its window and output allowance are why it was configured
|
|
1243
1437
|
* as an alternative in the first place.
|
|
1244
1438
|
*/
|
|
1245
1439
|
const fallbackContext = attributedFallbackContext ?? require_invoke.getFallbackErrorContext(error);
|
|
1440
|
+
const localMeasurement = getLocalProviderOverflowMeasurement(error);
|
|
1441
|
+
const recoveryPromptEstimate = getRecoveryPromptEstimate(error, fallbackContext);
|
|
1442
|
+
/**
|
|
1443
|
+
* A previous correction that left the rejected prompt no smaller
|
|
1444
|
+
* proves this state has nothing left to compact. Use the fallback
|
|
1445
|
+
* projection when one exists so unlike provider formats are never
|
|
1446
|
+
* compared through the primary's cheaper pre-projection estimate.
|
|
1447
|
+
*/
|
|
1448
|
+
if (agentContext.overflowRecoveryStalled(recoveryPromptEstimate)) return null;
|
|
1246
1449
|
const recovery = require_contextOverflowRecovery.planContextOverflowRecovery({
|
|
1247
1450
|
error,
|
|
1248
1451
|
provider: fallbackContext?.provider ?? agentContext.provider,
|
|
1249
|
-
maxContextTokens: fallbackContext?.maxContextTokens ?? agentContext.maxContextTokens,
|
|
1250
|
-
estimatedPromptTokens,
|
|
1452
|
+
maxContextTokens: localMeasurement?.contextBudget ?? fallbackContext?.maxContextTokens ?? agentContext.maxContextTokens,
|
|
1453
|
+
estimatedPromptTokens: recoveryPromptEstimate,
|
|
1251
1454
|
calibrationRatio: agentContext.calibrationRatio,
|
|
1252
1455
|
instructionTokens: agentContext.instructionTokens,
|
|
1253
1456
|
canSummarize: agentContext.summarizationEnabled === true,
|
|
@@ -1257,20 +1460,23 @@ var StandardGraph = class StandardGraph extends Graph {
|
|
|
1257
1460
|
if (recovery == null) return null;
|
|
1258
1461
|
const translatedRecovery = fallbackContext != null ? {
|
|
1259
1462
|
...recovery,
|
|
1260
|
-
budgetTokens: minDefined(require_contextOverflowRecovery.getBlindRecoveryBudget(agentContext.maxContextTokens), require_contextOverflowRecovery.translateRecoveryBudget(recovery.budgetTokens, recovery.observedCalibrationRatio ?? 5, agentContext.calibrationRatio)),
|
|
1463
|
+
budgetTokens: minDefined(require_contextOverflowRecovery.getBlindRecoveryBudget(agentContext.maxContextTokens), localMeasurement != null ? recovery.budgetTokens : require_contextOverflowRecovery.translateRecoveryBudget(recovery.budgetTokens, recovery.observedCalibrationRatio ?? 5, agentContext.calibrationRatio)),
|
|
1261
1464
|
observedCalibrationRatio: void 0
|
|
1262
1465
|
} : recovery;
|
|
1263
1466
|
return canSummarizeOverflow || agentContext.tokenCounter != null && translatedRecovery.budgetTokens != null ? translatedRecovery : null;
|
|
1264
1467
|
};
|
|
1265
1468
|
const recovery = planRecovery(primaryError);
|
|
1266
|
-
if (recovery != null)
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1469
|
+
if (recovery != null) {
|
|
1470
|
+
const recoveryPromptEstimate = getRecoveryPromptEstimate(primaryError);
|
|
1471
|
+
return this.beginOverflowRecovery({
|
|
1472
|
+
recovery,
|
|
1473
|
+
agentContext,
|
|
1474
|
+
agentId,
|
|
1475
|
+
config,
|
|
1476
|
+
originalToolContent: prunedOriginalToolContent,
|
|
1477
|
+
estimatedPromptTokens: recoveryPromptEstimate
|
|
1478
|
+
});
|
|
1479
|
+
}
|
|
1274
1480
|
/**
|
|
1275
1481
|
* A fallback can reject the same prompt as too large even when the
|
|
1276
1482
|
* primary failed for an unrelated reason — a fallback with a smaller
|
|
@@ -1284,7 +1490,7 @@ var StandardGraph = class StandardGraph extends Graph {
|
|
|
1284
1490
|
}), () => require_invoke.tryFallbackProviders({
|
|
1285
1491
|
fallbacks,
|
|
1286
1492
|
tools: agentContext.tools,
|
|
1287
|
-
messages:
|
|
1493
|
+
messages: fallbackBaseMessages,
|
|
1288
1494
|
config: invokeConfig,
|
|
1289
1495
|
primaryError,
|
|
1290
1496
|
context: this,
|
|
@@ -1297,16 +1503,40 @@ var StandardGraph = class StandardGraph extends Graph {
|
|
|
1297
1503
|
provider: agentContext.provider,
|
|
1298
1504
|
estimatedPromptTokens: getEstimatedPromptTokens(contextUsage),
|
|
1299
1505
|
maxContextTokens: agentContext.maxContextTokens
|
|
1506
|
+
},
|
|
1507
|
+
prepareProviderMessages: ({ model: fallbackModel, messages: fallbackMessages, provider: fallbackProvider, maxContextTokens: fallbackMaxContextTokens, config: fallbackConfig }) => {
|
|
1508
|
+
const projectedFallbackMessages = trackProviderMessageOrigins(fallbackMessages, require_invoke.projectMessagesForProvider({
|
|
1509
|
+
model: fallbackModel,
|
|
1510
|
+
messages: fallbackMessages,
|
|
1511
|
+
provider: fallbackProvider,
|
|
1512
|
+
maxToolResultChars: agentContext.maxToolResultChars ?? require_truncation.calculateMaxToolResultChars(fallbackMaxContextTokens ?? agentContext.maxContextTokens),
|
|
1513
|
+
callOptions: fallbackConfig
|
|
1514
|
+
}));
|
|
1515
|
+
const primaryContextBudget = contextUsage?.contextBudget;
|
|
1516
|
+
const projection = measureProviderPayload(projectedFallbackMessages, fallbackMaxContextTokens == null ? primaryContextBudget : Math.min(primaryContextBudget ?? fallbackMaxContextTokens, fallbackMaxContextTokens), true);
|
|
1517
|
+
if (!projection.fits) throw createProviderPayloadOverflowError({
|
|
1518
|
+
projection,
|
|
1519
|
+
provider: fallbackProvider,
|
|
1520
|
+
info: "Fallback provider message formatting exceeded the context budget before invocation."
|
|
1521
|
+
});
|
|
1522
|
+
return projectedFallbackMessages;
|
|
1300
1523
|
}
|
|
1301
1524
|
}));
|
|
1302
1525
|
} catch (fallbackError) {
|
|
1303
1526
|
const overflowCandidates = require_invoke.getFallbackOverflowCandidates(fallbackError);
|
|
1304
1527
|
let fallbackRecovery = null;
|
|
1528
|
+
let fallbackRecoveryPromptEstimate;
|
|
1305
1529
|
for (const candidate of overflowCandidates) {
|
|
1306
1530
|
fallbackRecovery = planRecovery(candidate.error, candidate.context);
|
|
1307
|
-
if (fallbackRecovery != null)
|
|
1531
|
+
if (fallbackRecovery != null) {
|
|
1532
|
+
fallbackRecoveryPromptEstimate = getRecoveryPromptEstimate(candidate.error, candidate.context);
|
|
1533
|
+
break;
|
|
1534
|
+
}
|
|
1535
|
+
}
|
|
1536
|
+
if (overflowCandidates.length === 0) {
|
|
1537
|
+
fallbackRecovery = planRecovery(fallbackError);
|
|
1538
|
+
fallbackRecoveryPromptEstimate = getRecoveryPromptEstimate(fallbackError);
|
|
1308
1539
|
}
|
|
1309
|
-
if (overflowCandidates.length === 0) fallbackRecovery = planRecovery(fallbackError);
|
|
1310
1540
|
if (fallbackRecovery == null) throw fallbackError;
|
|
1311
1541
|
return this.beginOverflowRecovery({
|
|
1312
1542
|
recovery: fallbackRecovery,
|
|
@@ -1314,7 +1544,7 @@ var StandardGraph = class StandardGraph extends Graph {
|
|
|
1314
1544
|
agentId,
|
|
1315
1545
|
config,
|
|
1316
1546
|
originalToolContent: prunedOriginalToolContent,
|
|
1317
|
-
estimatedPromptTokens
|
|
1547
|
+
estimatedPromptTokens: fallbackRecoveryPromptEstimate
|
|
1318
1548
|
});
|
|
1319
1549
|
}
|
|
1320
1550
|
} finally {
|
|
@@ -1690,13 +1920,16 @@ var StandardGraph = class StandardGraph extends Graph {
|
|
|
1690
1920
|
const stepId = graph.toolCallStepIds.get(data.id) ?? "";
|
|
1691
1921
|
if (!stepId) return false;
|
|
1692
1922
|
const { name, input: args, error } = data;
|
|
1923
|
+
const eventValueLimit = require_truncation.calculateMaxToolResultChars();
|
|
1924
|
+
const errorOutputPrefix = "Error processing tool";
|
|
1925
|
+
const errorDetail = error?.message != null ? `: ${require_toolContent.serializeToolContentBounded(error.message, Math.max(0, eventValueLimit - 21 - 2))}` : "";
|
|
1693
1926
|
const runStep = graph.getRunStep(stepId);
|
|
1694
1927
|
if (!runStep) return false;
|
|
1695
1928
|
const tool_call = {
|
|
1696
1929
|
id: data.id,
|
|
1697
1930
|
name: name || "",
|
|
1698
|
-
args:
|
|
1699
|
-
output:
|
|
1931
|
+
args: require_toolContent.serializeToolContentBounded(args, eventValueLimit),
|
|
1932
|
+
output: `${errorOutputPrefix}${errorDetail}`,
|
|
1700
1933
|
progress: 1
|
|
1701
1934
|
};
|
|
1702
1935
|
const handler = graph.handlerRegistry?.getHandler("on_run_step_completed");
|