@librechat/agents 3.7.15 → 3.7.16
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 +91 -0
- package/dist/cjs/agents/AgentContext.cjs.map +1 -1
- package/dist/cjs/agents/projection.cjs +2 -1
- package/dist/cjs/agents/projection.cjs.map +1 -1
- package/dist/cjs/graphs/Graph.cjs +47 -6
- package/dist/cjs/graphs/Graph.cjs.map +1 -1
- package/dist/cjs/graphs/MultiAgentGraph.cjs +20 -7
- package/dist/cjs/graphs/MultiAgentGraph.cjs.map +1 -1
- package/dist/cjs/llm/anthropic/utils/message_inputs.cjs +1 -1
- package/dist/cjs/llm/openai/utils/index.cjs +1 -1
- package/dist/cjs/llm/openai/utils/index.cjs.map +1 -1
- package/dist/cjs/llm/preempt.cjs +1 -10
- package/dist/cjs/llm/preempt.cjs.map +1 -1
- package/dist/cjs/main.cjs +23 -3
- package/dist/cjs/messages/contextPruning.cjs +1 -1
- package/dist/cjs/messages/contextPruning.cjs.map +1 -1
- package/dist/cjs/messages/core.cjs +29 -1
- package/dist/cjs/messages/core.cjs.map +1 -1
- package/dist/cjs/messages/fading.cjs +122 -0
- package/dist/cjs/messages/fading.cjs.map +1 -0
- package/dist/cjs/messages/format.cjs +1 -1
- package/dist/cjs/messages/index.cjs +1 -0
- package/dist/cjs/messages/prune.cjs +364 -236
- package/dist/cjs/messages/prune.cjs.map +1 -1
- package/dist/cjs/run.cjs +27 -0
- package/dist/cjs/run.cjs.map +1 -1
- package/dist/cjs/session/AgentSession.cjs +213 -8
- package/dist/cjs/session/AgentSession.cjs.map +1 -1
- package/dist/cjs/session/JsonlSessionStore.cjs +41 -0
- package/dist/cjs/session/JsonlSessionStore.cjs.map +1 -1
- package/dist/cjs/session/index.cjs +1 -1
- package/dist/cjs/stream.cjs +1 -1
- package/dist/cjs/summarization/node.cjs +1 -1
- package/dist/cjs/tools/ToolNode.cjs +1 -1
- package/dist/cjs/tools/subagent/SubagentExecutor.cjs +2 -0
- package/dist/cjs/tools/subagent/SubagentExecutor.cjs.map +1 -1
- package/dist/cjs/tools/subagent/SubagentReplay.cjs +2 -1
- package/dist/cjs/tools/subagent/SubagentReplay.cjs.map +1 -1
- package/dist/cjs/utils/index.cjs +1 -1
- package/dist/cjs/utils/truncation.cjs +9 -0
- package/dist/cjs/utils/truncation.cjs.map +1 -1
- package/dist/esm/agents/AgentContext.mjs +92 -1
- package/dist/esm/agents/AgentContext.mjs.map +1 -1
- package/dist/esm/agents/projection.mjs +2 -1
- package/dist/esm/agents/projection.mjs.map +1 -1
- package/dist/esm/graphs/Graph.mjs +47 -6
- package/dist/esm/graphs/Graph.mjs.map +1 -1
- package/dist/esm/graphs/MultiAgentGraph.mjs +20 -7
- package/dist/esm/graphs/MultiAgentGraph.mjs.map +1 -1
- package/dist/esm/llm/anthropic/utils/message_inputs.mjs +1 -1
- package/dist/esm/llm/openai/utils/index.mjs +2 -2
- package/dist/esm/llm/openai/utils/index.mjs.map +1 -1
- package/dist/esm/llm/preempt.mjs +1 -10
- package/dist/esm/llm/preempt.mjs.map +1 -1
- package/dist/esm/main.mjs +6 -5
- package/dist/esm/messages/contextPruning.mjs +1 -1
- package/dist/esm/messages/contextPruning.mjs.map +1 -1
- package/dist/esm/messages/core.mjs +29 -2
- package/dist/esm/messages/core.mjs.map +1 -1
- package/dist/esm/messages/fading.mjs +108 -0
- package/dist/esm/messages/fading.mjs.map +1 -0
- package/dist/esm/messages/format.mjs +1 -1
- package/dist/esm/messages/index.mjs +1 -0
- package/dist/esm/messages/prune.mjs +363 -235
- package/dist/esm/messages/prune.mjs.map +1 -1
- package/dist/esm/run.mjs +27 -0
- package/dist/esm/run.mjs.map +1 -1
- package/dist/esm/session/AgentSession.mjs +213 -8
- package/dist/esm/session/AgentSession.mjs.map +1 -1
- package/dist/esm/session/JsonlSessionStore.mjs +41 -0
- package/dist/esm/session/JsonlSessionStore.mjs.map +1 -1
- package/dist/esm/session/index.mjs +1 -1
- package/dist/esm/stream.mjs +1 -1
- package/dist/esm/summarization/node.mjs +1 -1
- package/dist/esm/tools/ToolNode.mjs +1 -1
- package/dist/esm/tools/subagent/SubagentExecutor.mjs +2 -0
- package/dist/esm/tools/subagent/SubagentExecutor.mjs.map +1 -1
- package/dist/esm/tools/subagent/SubagentReplay.mjs +2 -1
- package/dist/esm/tools/subagent/SubagentReplay.mjs.map +1 -1
- package/dist/esm/utils/index.mjs +1 -1
- package/dist/esm/utils/truncation.mjs +7 -1
- package/dist/esm/utils/truncation.mjs.map +1 -1
- package/dist/types/agents/AgentContext.d.ts +32 -1
- package/dist/types/agents/projection.d.ts +3 -1
- package/dist/types/graphs/Graph.d.ts +14 -1
- package/dist/types/graphs/MultiAgentGraph.d.ts +7 -0
- package/dist/types/messages/contextPruning.d.ts +2 -0
- package/dist/types/messages/core.d.ts +2 -0
- package/dist/types/messages/fading.d.ts +81 -0
- package/dist/types/messages/index.d.ts +1 -0
- package/dist/types/messages/prune.d.ts +71 -24
- package/dist/types/run.d.ts +16 -0
- package/dist/types/session/AgentSession.d.ts +15 -0
- package/dist/types/session/JsonlSessionStore.d.ts +4 -1
- package/dist/types/session/types.d.ts +9 -0
- package/dist/types/tools/subagent/SubagentReplay.d.ts +3 -1
- package/dist/types/types/graph.d.ts +23 -0
- package/dist/types/types/run.d.ts +10 -0
- package/dist/types/utils/truncation.d.ts +9 -0
- package/package.json +1 -1
- package/src/agents/AgentContext.ts +175 -1
- package/src/agents/projection.ts +4 -0
- package/src/graphs/Graph.ts +97 -11
- package/src/graphs/MultiAgentGraph.ts +54 -6
- package/src/llm/openai/utils/index.ts +3 -1
- package/src/llm/preempt.ts +4 -17
- package/src/messages/contextPruning.ts +7 -1
- package/src/messages/core.ts +52 -0
- package/src/messages/fading.ts +301 -0
- package/src/messages/index.ts +1 -0
- package/src/messages/prune.ts +719 -507
- package/src/run.ts +52 -0
- package/src/session/AgentSession.ts +397 -8
- package/src/session/JsonlSessionStore.ts +71 -0
- package/src/session/types.ts +10 -0
- package/src/tools/subagent/SubagentExecutor.ts +6 -0
- package/src/tools/subagent/SubagentReplay.ts +15 -2
- package/src/types/graph.ts +25 -0
- package/src/types/run.ts +10 -0
- package/src/utils/truncation.ts +25 -0
|
@@ -1,9 +1,11 @@
|
|
|
1
|
+
import { HARD_MAX_TOOL_CALL_INPUT_CHARS, calculateMaxToolCallInputChars, calculateMaxToolResultChars } from "../utils/truncation.mjs";
|
|
2
|
+
import { fadingRungForExchangeChars, isFadingTier, resolveFadingCaps, resolveFadingTier, seedFadingTier } from "./fading.mjs";
|
|
1
3
|
import "../common/enum.mjs";
|
|
2
4
|
import "../common/index.mjs";
|
|
3
|
-
import {
|
|
4
|
-
import { cloneToolMessageWithContent, compactToolContent, getToolContentCharLength, isComputerCallOutputMessage, serializeStructuredValueBounded, serializeToolContentBounded } from "../utils/toolContent.mjs";
|
|
5
|
+
import { cloneToolMessageWithContent, compactToolContent, isComputerCallOutputMessage, serializeStructuredValueBounded, serializeToolContentBounded } from "../utils/toolContent.mjs";
|
|
5
6
|
import { toLangChainContent } from "./langchain.mjs";
|
|
6
|
-
import {
|
|
7
|
+
import { cloneMessage } from "./cache.mjs";
|
|
8
|
+
import { dropIncompleteToolStreamContent, hasNonEmptyTextContent } from "./core.mjs";
|
|
7
9
|
import { hasUnsafeStructuredSerialization } from "../utils/tokens.mjs";
|
|
8
10
|
import { getProviderFamily } from "../llm/providerRegistry.mjs";
|
|
9
11
|
import { resolveContextPruningSettings } from "./contextPruningSettings.mjs";
|
|
@@ -29,14 +31,6 @@ function prependItems(target, prefix) {
|
|
|
29
31
|
}
|
|
30
32
|
const DEFAULT_RESERVE_RATIO = .05;
|
|
31
33
|
const REPLY_PRIMER_TOKENS = 3;
|
|
32
|
-
const PRESSURE_THRESHOLD_MASKING = .8;
|
|
33
|
-
const PRESSURE_BANDS = [
|
|
34
|
-
[.99, .05],
|
|
35
|
-
[.9, .2],
|
|
36
|
-
[.85, .5],
|
|
37
|
-
[.8, 1]
|
|
38
|
-
];
|
|
39
|
-
const MASKED_RESULT_MAX_CHARS = 300;
|
|
40
34
|
const ORIGINAL_CONTENT_MAX_CHARS = 2e6;
|
|
41
35
|
function enforceOriginalContentCap(map) {
|
|
42
36
|
let total = 0;
|
|
@@ -59,17 +53,30 @@ function getToolCallIds(message) {
|
|
|
59
53
|
if (message.getType() !== "ai" && messageRole !== "assistant") return /* @__PURE__ */ new Set();
|
|
60
54
|
const ids = /* @__PURE__ */ new Set();
|
|
61
55
|
const aiMessage = message;
|
|
62
|
-
|
|
63
|
-
if (Array.isArray(
|
|
56
|
+
const toolCalls = aiMessage.tool_calls;
|
|
57
|
+
if (Array.isArray(toolCalls) && !isProxy(toolCalls)) for (const toolCall of toolCalls) {
|
|
58
|
+
if (typeof toolCall !== "object") continue;
|
|
59
|
+
const id = getStringProperty(toolCall, "id");
|
|
60
|
+
if (id != null && id.length > 0) ids.add(id);
|
|
61
|
+
}
|
|
62
|
+
const rawToolCalls = readPropertyWithoutAccessors(aiMessage.additional_kwargs, "tool_calls");
|
|
63
|
+
if (!rawToolCalls.accessor && Array.isArray(rawToolCalls.value) && !isProxy(rawToolCalls.value)) for (const toolCall of rawToolCalls.value) {
|
|
64
|
+
if (toolCall == null || typeof toolCall !== "object") continue;
|
|
65
|
+
const id = getStringProperty(toolCall, "id");
|
|
66
|
+
if (id != null && id.length > 0) ids.add(id);
|
|
67
|
+
}
|
|
68
|
+
if (Array.isArray(aiMessage.content) && !isProxy(aiMessage.content)) for (const part of aiMessage.content) {
|
|
64
69
|
if (typeof part !== "object") continue;
|
|
65
|
-
const
|
|
66
|
-
|
|
70
|
+
const type = getStringProperty(part, "type");
|
|
71
|
+
const id = getStringProperty(part, "id");
|
|
72
|
+
if ((type === "tool_use" || type === "tool_call") && id != null && id.length > 0) ids.add(id);
|
|
67
73
|
}
|
|
68
74
|
const toolOutputSource = getResponsesToolOutputSource(message);
|
|
69
75
|
if (toolOutputSource != null) for (const item of toolOutputSource.items) {
|
|
70
76
|
if (item == null || typeof item !== "object") continue;
|
|
71
|
-
const
|
|
72
|
-
|
|
77
|
+
const type = getStringProperty(item, "type");
|
|
78
|
+
const callId = getStringProperty(item, "call_id");
|
|
79
|
+
if ((type === "function_call" || type === "custom_tool_call" || type === "computer_call") && callId != null && callId !== "") ids.add(callId);
|
|
73
80
|
}
|
|
74
81
|
return ids;
|
|
75
82
|
}
|
|
@@ -445,72 +452,117 @@ function getMessagesWithinTokenLimit({ messages: _messages, maxContextTokens, in
|
|
|
445
452
|
function checkValidNumber(value) {
|
|
446
453
|
return typeof value === "number" && !isNaN(value) && value > 0;
|
|
447
454
|
}
|
|
448
|
-
function
|
|
449
|
-
const { messages, indexTokenCountMap, tokenCounter } = params;
|
|
450
|
-
let maskedCount = 0;
|
|
451
|
-
let seenNonToolCallAI = false;
|
|
452
|
-
const consumedIndices = [];
|
|
455
|
+
function findConsumedBoundary(messages) {
|
|
453
456
|
for (let i = messages.length - 1; i >= 0; i--) {
|
|
454
|
-
const
|
|
455
|
-
|
|
456
|
-
if (type === "ai") {
|
|
457
|
-
if (typeof msg.content === "string" ? msg.content.trim().length > 0 : Array.isArray(msg.content) && msg.content.some((b) => typeof b === "object" && b.type === "text" && typeof b.text === "string" && b.text.trim().length > 0)) seenNonToolCallAI = true;
|
|
458
|
-
} else if (type === "tool" && seenNonToolCallAI) consumedIndices.push(i);
|
|
457
|
+
const message = messages[i];
|
|
458
|
+
if (message.getType() === "ai" && hasNonEmptyTextContent(message.content)) return i;
|
|
459
459
|
}
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
const
|
|
464
|
-
|
|
465
|
-
|
|
460
|
+
return 0;
|
|
461
|
+
}
|
|
462
|
+
function applyFadingCaps(params) {
|
|
463
|
+
const { messages, indexTokenCountMap, tokenCounter, caps, masked } = params;
|
|
464
|
+
const fromIndex = params.fromIndex ?? 0;
|
|
465
|
+
const maskedFromIndex = params.maskedFromIndex ?? 0;
|
|
466
|
+
const consumedBoundary = masked ? findConsumedBoundary(messages) : 0;
|
|
467
|
+
const start = masked ? Math.min(fromIndex, maskedFromIndex) : fromIndex;
|
|
468
|
+
let truncated = 0;
|
|
469
|
+
let maskedCount = 0;
|
|
470
|
+
for (let i = start; i < messages.length; i++) {
|
|
466
471
|
const message = messages[i];
|
|
467
|
-
if (isComputerCallOutputMessage(message)) continue;
|
|
468
|
-
const
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
const compacted = compactToolContent(content, maxChars);
|
|
472
|
+
if (message.getType() !== "tool" || isComputerCallOutputMessage(message)) continue;
|
|
473
|
+
const consumed = masked && i < consumedBoundary;
|
|
474
|
+
if (consumed ? i < maskedFromIndex : i < fromIndex) continue;
|
|
475
|
+
const maxChars = consumed ? caps.consumedChars : caps.resultChars;
|
|
476
|
+
if (!Number.isFinite(maxChars)) continue;
|
|
477
|
+
const canonicalContent = params.canonicalMessages?.[i]?.content ?? message.content;
|
|
478
|
+
const compacted = compactToolContent(canonicalContent, maxChars);
|
|
475
479
|
if (!compacted.changed) continue;
|
|
476
|
-
if (params.originalContentStore && !params.originalContentStore.has(i)) {
|
|
477
|
-
const original = serializeToolContentBounded(
|
|
480
|
+
if (consumed && params.originalContentStore && !params.originalContentStore.has(i)) {
|
|
481
|
+
const original = serializeToolContentBounded(canonicalContent, ORIGINAL_CONTENT_MAX_CHARS);
|
|
478
482
|
params.originalContentStore.set(i, original);
|
|
479
|
-
|
|
483
|
+
params.onContentStored?.(i, original);
|
|
480
484
|
}
|
|
481
485
|
const cloned = cloneToolMessageWithContent(message, compacted.content);
|
|
482
486
|
messages[i] = cloned;
|
|
483
487
|
indexTokenCountMap[i] = tokenCounter(cloned);
|
|
484
|
-
maskedCount++;
|
|
488
|
+
if (consumed) maskedCount++;
|
|
489
|
+
else truncated++;
|
|
485
490
|
}
|
|
486
|
-
|
|
491
|
+
const inputs = Number.isFinite(caps.inputChars) ? applyToolCallInputCaps({
|
|
492
|
+
messages,
|
|
493
|
+
canonicalMessages: params.canonicalMessages,
|
|
494
|
+
maxInputChars: caps.inputChars,
|
|
495
|
+
indexTokenCountMap,
|
|
496
|
+
tokenCounter,
|
|
497
|
+
fromIndex
|
|
498
|
+
}) : 0;
|
|
499
|
+
return {
|
|
500
|
+
truncated,
|
|
501
|
+
inputs,
|
|
502
|
+
masked: maskedCount,
|
|
503
|
+
consumedBoundary
|
|
504
|
+
};
|
|
487
505
|
}
|
|
488
|
-
function
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
506
|
+
function maskConsumedToolResults(params) {
|
|
507
|
+
if (params.maxChars == null && params.availableRawBudget != null && params.availableRawBudget > 0) {
|
|
508
|
+
const consumedBoundary = findConsumedBoundary(params.messages);
|
|
509
|
+
const consumedIndices = [];
|
|
510
|
+
for (let i = 0; i < consumedBoundary; i++) if (params.messages[i].getType() === "tool") consumedIndices.push(i);
|
|
511
|
+
const count = consumedIndices.length;
|
|
512
|
+
const totalBudgetChars = params.availableRawBudget * 4;
|
|
513
|
+
let masked = 0;
|
|
514
|
+
for (let c = 0; c < count; c++) {
|
|
515
|
+
const i = consumedIndices[c];
|
|
516
|
+
const message = params.messages[i];
|
|
517
|
+
if (isComputerCallOutputMessage(message)) continue;
|
|
518
|
+
const weight = .2 + .8 * (count > 1 ? c / (count - 1) : 1);
|
|
519
|
+
const totalWeight = count > 1 ? .6 * count : 1;
|
|
520
|
+
const maxChars = Math.max(300, Math.floor(weight / totalWeight * totalBudgetChars));
|
|
521
|
+
const compacted = compactToolContent(message.content, maxChars);
|
|
522
|
+
if (!compacted.changed) continue;
|
|
523
|
+
if (params.originalContentStore != null && !params.originalContentStore.has(i)) {
|
|
524
|
+
const original = serializeToolContentBounded(message.content, ORIGINAL_CONTENT_MAX_CHARS);
|
|
525
|
+
params.originalContentStore.set(i, original);
|
|
526
|
+
params.onContentStored?.(i, original);
|
|
527
|
+
}
|
|
528
|
+
const cloned = cloneToolMessageWithContent(message, compacted.content);
|
|
529
|
+
params.messages[i] = cloned;
|
|
530
|
+
params.indexTokenCountMap[i] = params.tokenCounter(cloned);
|
|
531
|
+
masked++;
|
|
532
|
+
}
|
|
533
|
+
return masked;
|
|
505
534
|
}
|
|
506
|
-
return
|
|
535
|
+
return applyFadingCaps({
|
|
536
|
+
messages: params.messages,
|
|
537
|
+
indexTokenCountMap: params.indexTokenCountMap,
|
|
538
|
+
tokenCounter: params.tokenCounter,
|
|
539
|
+
caps: {
|
|
540
|
+
resultChars: Number.POSITIVE_INFINITY,
|
|
541
|
+
consumedChars: Math.max(300, Math.floor(params.maxChars ?? 300)),
|
|
542
|
+
inputChars: Number.POSITIVE_INFINITY
|
|
543
|
+
},
|
|
544
|
+
masked: true,
|
|
545
|
+
originalContentStore: params.originalContentStore,
|
|
546
|
+
onContentStored: params.onContentStored
|
|
547
|
+
}).masked;
|
|
548
|
+
}
|
|
549
|
+
function preFlightTruncateToolResults(params) {
|
|
550
|
+
return applyFadingCaps({
|
|
551
|
+
messages: params.messages,
|
|
552
|
+
indexTokenCountMap: params.indexTokenCountMap,
|
|
553
|
+
tokenCounter: params.tokenCounter,
|
|
554
|
+
caps: {
|
|
555
|
+
resultChars: calculateMaxToolResultChars(params.maxContextTokens),
|
|
556
|
+
consumedChars: Number.POSITIVE_INFINITY,
|
|
557
|
+
inputChars: Number.POSITIVE_INFINITY
|
|
558
|
+
},
|
|
559
|
+
masked: false
|
|
560
|
+
}).truncated;
|
|
507
561
|
}
|
|
508
|
-
const HARD_MAX_TOOL_CALL_INPUT_CHARS = 2e5;
|
|
509
|
-
const MIN_JSON_VALUE_CHARS = 4;
|
|
510
562
|
const ACCESSOR_INPUT_PLACEHOLDER = "[Property accessor omitted]";
|
|
511
563
|
function normalizeToolInputLimit(maxChars) {
|
|
512
564
|
if (!Number.isFinite(maxChars)) return HARD_MAX_TOOL_CALL_INPUT_CHARS;
|
|
513
|
-
return Math.max(
|
|
565
|
+
return Math.max(4, Math.floor(maxChars));
|
|
514
566
|
}
|
|
515
567
|
function readPropertyWithoutAccessors(value, key) {
|
|
516
568
|
let current = value;
|
|
@@ -600,33 +652,62 @@ function cloneAIMessageWithProjectedStreamContent(message, changes, streamConten
|
|
|
600
652
|
};
|
|
601
653
|
return Object.create(Object.getPrototypeOf(message), descriptors);
|
|
602
654
|
}
|
|
655
|
+
const TOOL_INPUT_TRUNCATION_MARKER = "… [truncated]\n";
|
|
603
656
|
function createBoundedTruncationValue(preview, originalChars, maxChars) {
|
|
604
657
|
const normalizedMaxChars = normalizeToolInputLimit(maxChars);
|
|
658
|
+
const canonicalPrefix = preview.startsWith(TOOL_INPUT_TRUNCATION_MARKER) ? preview.slice(14) : preview;
|
|
605
659
|
if (JSON.stringify({
|
|
606
|
-
_truncated:
|
|
660
|
+
_truncated: TOOL_INPUT_TRUNCATION_MARKER,
|
|
607
661
|
_originalChars: originalChars
|
|
608
662
|
}).length > normalizedMaxChars) return {};
|
|
609
663
|
let low = 0;
|
|
610
|
-
let high = Math.min(
|
|
664
|
+
let high = Math.min(canonicalPrefix.length, normalizedMaxChars);
|
|
611
665
|
while (low < high) {
|
|
612
666
|
const next = Math.ceil((low + high) / 2);
|
|
613
667
|
const candidate = {
|
|
614
|
-
_truncated:
|
|
668
|
+
_truncated: TOOL_INPUT_TRUNCATION_MARKER + canonicalPrefix.slice(0, next),
|
|
615
669
|
_originalChars: originalChars
|
|
616
670
|
};
|
|
617
671
|
if (JSON.stringify(candidate).length <= normalizedMaxChars) low = next;
|
|
618
672
|
else high = next - 1;
|
|
619
673
|
}
|
|
620
674
|
return {
|
|
621
|
-
_truncated:
|
|
675
|
+
_truncated: TOOL_INPUT_TRUNCATION_MARKER + canonicalPrefix.slice(0, low),
|
|
622
676
|
_originalChars: originalChars
|
|
623
677
|
};
|
|
624
678
|
}
|
|
679
|
+
function readBoundedTruncationValue(input) {
|
|
680
|
+
if (input == null || typeof input !== "object" || isProxy(input)) return;
|
|
681
|
+
try {
|
|
682
|
+
const prototype = Object.getPrototypeOf(input);
|
|
683
|
+
const keys = Object.keys(input);
|
|
684
|
+
if (prototype !== Object.prototype && prototype !== null || keys.length !== 2 || !keys.includes("_truncated") || !keys.includes("_originalChars")) return;
|
|
685
|
+
} catch {
|
|
686
|
+
return;
|
|
687
|
+
}
|
|
688
|
+
const preview = readPropertyWithoutAccessors(input, "_truncated");
|
|
689
|
+
const originalChars = readPropertyWithoutAccessors(input, "_originalChars");
|
|
690
|
+
return preview.own && !preview.accessor && typeof preview.value === "string" && originalChars.own && !originalChars.accessor && typeof originalChars.value === "number" && Number.isFinite(originalChars.value) && originalChars.value >= 0 ? {
|
|
691
|
+
preview: preview.value,
|
|
692
|
+
originalChars: originalChars.value
|
|
693
|
+
} : void 0;
|
|
694
|
+
}
|
|
625
695
|
function projectToolInputWithinLimit(input, maxChars) {
|
|
626
696
|
const normalizedMaxChars = normalizeToolInputLimit(maxChars);
|
|
627
|
-
const
|
|
697
|
+
const priorTruncation = readBoundedTruncationValue(input);
|
|
698
|
+
if (priorTruncation != null) {
|
|
699
|
+
if (!serializeStructuredValueBounded(input, normalizedMaxChars).truncated) return {
|
|
700
|
+
value: input,
|
|
701
|
+
changed: false
|
|
702
|
+
};
|
|
703
|
+
return {
|
|
704
|
+
value: createBoundedTruncationValue(priorTruncation.preview, priorTruncation.originalChars, normalizedMaxChars),
|
|
705
|
+
changed: true
|
|
706
|
+
};
|
|
707
|
+
}
|
|
708
|
+
const serialized = serializeStructuredValueBounded(input, normalizedMaxChars, normalizedMaxChars);
|
|
628
709
|
if (serialized.truncated) return {
|
|
629
|
-
value: createBoundedTruncationValue(serialized.
|
|
710
|
+
value: createBoundedTruncationValue(serialized.prefix, serialized.originalChars, normalizedMaxChars),
|
|
630
711
|
changed: true
|
|
631
712
|
};
|
|
632
713
|
if (!hasUnsafeStructuredSerialization(input)) return {
|
|
@@ -647,9 +728,9 @@ function projectToolInputWithinLimit(input, maxChars) {
|
|
|
647
728
|
}
|
|
648
729
|
function serializeToolCallInput(input, maxChars = HARD_MAX_TOOL_CALL_INPUT_CHARS) {
|
|
649
730
|
const normalizedMaxChars = normalizeToolInputLimit(maxChars);
|
|
650
|
-
const serialized = serializeStructuredValueBounded(projectToolInputWithinLimit(input, normalizedMaxChars).value, normalizedMaxChars);
|
|
731
|
+
const serialized = serializeStructuredValueBounded(projectToolInputWithinLimit(input, normalizedMaxChars).value, normalizedMaxChars, normalizedMaxChars);
|
|
651
732
|
if (!serialized.truncated) return serialized.content === "undefined" ? "null" : serialized.content;
|
|
652
|
-
const fallback = createBoundedTruncationValue(serialized.
|
|
733
|
+
const fallback = createBoundedTruncationValue(serialized.prefix, serialized.originalChars, normalizedMaxChars);
|
|
653
734
|
return JSON.stringify(fallback);
|
|
654
735
|
}
|
|
655
736
|
function projectKnownInputProperty(value, key, maxChars, changes) {
|
|
@@ -675,7 +756,7 @@ function projectInlineToolInput(block, maxChars) {
|
|
|
675
756
|
if (nestedProperty.found && !nestedProperty.accessor && nestedProperty.value != null && typeof nestedProperty.value === "object") {
|
|
676
757
|
const nestedChanges = {};
|
|
677
758
|
projectKnownInputProperty(nestedProperty.value, "args", maxChars, nestedChanges);
|
|
678
|
-
if (Object.keys(nestedChanges).length > 0) changes.tool_call = cloneWithProjectedProperties(nestedProperty.value, nestedChanges);
|
|
759
|
+
if (Object.keys(nestedChanges).length > 0) changes.tool_call = isProxy(nestedProperty.value) ? { args: ACCESSOR_INPUT_PLACEHOLDER } : cloneWithProjectedProperties(nestedProperty.value, nestedChanges);
|
|
679
760
|
else if (!nestedProperty.own) changes.tool_call = nestedProperty.value;
|
|
680
761
|
} else if (nestedProperty.accessor) changes.tool_call = { args: ACCESSOR_INPUT_PLACEHOLDER };
|
|
681
762
|
return Object.keys(changes).length > 0 ? cloneWithProjectedProperties(block, changes) : block;
|
|
@@ -686,11 +767,34 @@ function projectSerializedArguments(value, maxChars) {
|
|
|
686
767
|
value,
|
|
687
768
|
changed: false
|
|
688
769
|
};
|
|
770
|
+
if (typeof value === "string" && value.includes("\"_truncated\"") && value.includes("\"_originalChars\"")) try {
|
|
771
|
+
const priorTruncation = readBoundedTruncationValue(JSON.parse(value));
|
|
772
|
+
if (priorTruncation != null) return {
|
|
773
|
+
value: JSON.stringify(createBoundedTruncationValue(priorTruncation.preview, priorTruncation.originalChars, normalizedMaxChars)),
|
|
774
|
+
changed: true
|
|
775
|
+
};
|
|
776
|
+
} catch {}
|
|
689
777
|
return {
|
|
690
778
|
value: serializeToolCallInput(value, normalizedMaxChars),
|
|
691
779
|
changed: true
|
|
692
780
|
};
|
|
693
781
|
}
|
|
782
|
+
const TRUNCATED_STRING_INPUT_PATTERN = /\n… \[truncated: (\d+) chars\]$/u;
|
|
783
|
+
function projectStringInputWithinLimit(value, maxChars) {
|
|
784
|
+
const normalizedMaxChars = normalizeToolInputLimit(maxChars);
|
|
785
|
+
if (value.length <= normalizedMaxChars) return {
|
|
786
|
+
value,
|
|
787
|
+
changed: false
|
|
788
|
+
};
|
|
789
|
+
const match = TRUNCATED_STRING_INPUT_PATTERN.exec(value);
|
|
790
|
+
const originalChars = match == null ? value.length : Number(match[1]);
|
|
791
|
+
const prefix = match == null ? value : value.slice(0, match.index);
|
|
792
|
+
const marker = `\n… [truncated: ${originalChars} chars]`;
|
|
793
|
+
return {
|
|
794
|
+
value: marker.length >= normalizedMaxChars ? prefix.slice(0, normalizedMaxChars) : prefix.slice(0, normalizedMaxChars - marker.length) + marker,
|
|
795
|
+
changed: true
|
|
796
|
+
};
|
|
797
|
+
}
|
|
694
798
|
function selectProjectedSerializedArguments(property, canonical, maxChars) {
|
|
695
799
|
if (canonical != null) return {
|
|
696
800
|
value: canonical,
|
|
@@ -794,7 +898,7 @@ function projectResponsesOutput(output, maxChars, canonicalArguments, canonicalI
|
|
|
794
898
|
changed: !inputProperty.own || inputProperty.value !== source
|
|
795
899
|
};
|
|
796
900
|
else if (type === "custom_tool_call") {
|
|
797
|
-
const value = typeof source === "string" ?
|
|
901
|
+
const value = typeof source === "string" ? projectStringInputWithinLimit(source, maxChars).value : serializeToolCallInput(source, maxChars);
|
|
798
902
|
projectedInput = {
|
|
799
903
|
value,
|
|
800
904
|
changed: !inputProperty.own || inputProperty.value !== value
|
|
@@ -816,14 +920,10 @@ function projectResponsesOutput(output, maxChars, canonicalArguments, canonicalI
|
|
|
816
920
|
changed: state.changed
|
|
817
921
|
};
|
|
818
922
|
}
|
|
819
|
-
function
|
|
820
|
-
if (maxContextTokens == null || maxContextTokens <= 0) return HARD_MAX_TOOL_CALL_INPUT_CHARS;
|
|
821
|
-
return Math.max(MIN_JSON_VALUE_CHARS, Math.min(Math.floor(maxContextTokens * .15) * 4, HARD_MAX_TOOL_CALL_INPUT_CHARS));
|
|
822
|
-
}
|
|
823
|
-
function projectToolCallInputsInternal(messages, maxInputChars, dropIncompleteStreamContent) {
|
|
923
|
+
function projectToolCallInputsInternal(messages, maxInputChars, dropIncompleteStreamContent, fromIndex = 0) {
|
|
824
924
|
const normalizedMaxInputChars = normalizeToolInputLimit(maxInputChars);
|
|
825
925
|
let projectedMessages;
|
|
826
|
-
for (let i =
|
|
926
|
+
for (let i = fromIndex; i < messages.length; i++) {
|
|
827
927
|
const message = messages[i];
|
|
828
928
|
const messageRole = message.role;
|
|
829
929
|
if (message.getType() !== "ai" && messageRole !== "assistant") continue;
|
|
@@ -891,25 +991,47 @@ function projectToolCallInputsInternal(messages, maxInputChars, dropIncompleteSt
|
|
|
891
991
|
}
|
|
892
992
|
return projectedMessages ?? messages;
|
|
893
993
|
}
|
|
894
|
-
function projectToolCallInputs(messages, maxInputChars) {
|
|
895
|
-
return projectToolCallInputsInternal(messages, maxInputChars, false);
|
|
994
|
+
function projectToolCallInputs(messages, maxInputChars, fromIndex = 0) {
|
|
995
|
+
return projectToolCallInputsInternal(messages, maxInputChars, false, fromIndex);
|
|
896
996
|
}
|
|
897
997
|
function projectToolMessagesForProvider(messages, maxInputChars) {
|
|
898
998
|
return projectToolCallInputsInternal(messages, maxInputChars, true);
|
|
899
999
|
}
|
|
900
|
-
function
|
|
901
|
-
const { messages,
|
|
902
|
-
const
|
|
903
|
-
|
|
1000
|
+
function applyToolCallInputCaps(params) {
|
|
1001
|
+
const { messages, maxInputChars, indexTokenCountMap, tokenCounter } = params;
|
|
1002
|
+
const fromIndex = params.fromIndex ?? 0;
|
|
1003
|
+
const sourceMessages = params.canonicalMessages ?? messages;
|
|
1004
|
+
const projected = projectToolCallInputs(sourceMessages, maxInputChars, fromIndex);
|
|
1005
|
+
if (projected === sourceMessages) return 0;
|
|
904
1006
|
let truncatedCount = 0;
|
|
905
|
-
for (let i =
|
|
1007
|
+
for (let i = fromIndex; i < messages.length; i++) {
|
|
1008
|
+
if (projected[i] === sourceMessages[i]) continue;
|
|
906
1009
|
if (projected[i] === messages[i]) continue;
|
|
907
|
-
|
|
908
|
-
|
|
1010
|
+
const current = messages[i];
|
|
1011
|
+
const canonical = sourceMessages[i];
|
|
1012
|
+
const capped = projected[i];
|
|
1013
|
+
const changes = {};
|
|
1014
|
+
if (capped.content !== canonical.content) changes.content = capped.content;
|
|
1015
|
+
if (capped.tool_calls !== canonical.tool_calls) changes.tool_calls = capped.tool_calls;
|
|
1016
|
+
const additionalKwargsChanges = {};
|
|
1017
|
+
for (const key of ["tool_calls", "function_call"]) if (capped.additional_kwargs[key] !== canonical.additional_kwargs[key]) additionalKwargsChanges[key] = capped.additional_kwargs[key];
|
|
1018
|
+
if (Object.keys(additionalKwargsChanges).length > 0) changes.additional_kwargs = cloneWithProjectedProperties(current.additional_kwargs, additionalKwargsChanges);
|
|
1019
|
+
if (capped.response_metadata.output !== canonical.response_metadata.output) changes.response_metadata = cloneWithProjectedProperties(current.response_metadata, { output: capped.response_metadata.output });
|
|
1020
|
+
const merged = cloneWithProjectedProperties(current, changes);
|
|
1021
|
+
messages[i] = merged;
|
|
1022
|
+
indexTokenCountMap[i] = tokenCounter(merged);
|
|
909
1023
|
truncatedCount++;
|
|
910
1024
|
}
|
|
911
1025
|
return truncatedCount;
|
|
912
1026
|
}
|
|
1027
|
+
function preFlightTruncateToolCallInputs(params) {
|
|
1028
|
+
return applyToolCallInputCaps({
|
|
1029
|
+
messages: params.messages,
|
|
1030
|
+
maxInputChars: calculateMaxToolCallInputChars(params.maxContextTokens),
|
|
1031
|
+
indexTokenCountMap: params.indexTokenCountMap,
|
|
1032
|
+
tokenCounter: params.tokenCounter
|
|
1033
|
+
});
|
|
1034
|
+
}
|
|
913
1035
|
function createPruneMessages(factoryParams) {
|
|
914
1036
|
const providerFamily = factoryParams.provider == null ? void 0 : getProviderFamily(factoryParams.provider);
|
|
915
1037
|
const usesBedrockThinking = factoryParams.provider === "bedrock" || providerFamily === "bedrock";
|
|
@@ -926,12 +1048,43 @@ function createPruneMessages(factoryParams) {
|
|
|
926
1048
|
let calibrationRatio = factoryParams.calibrationRatio != null && factoryParams.calibrationRatio > 0 ? factoryParams.calibrationRatio : 1;
|
|
927
1049
|
let bestInstructionOverhead;
|
|
928
1050
|
const reconciledLegacyAiMessages = /* @__PURE__ */ new WeakSet();
|
|
1051
|
+
const canonicalizedToolCallMessages = /* @__PURE__ */ new WeakSet();
|
|
929
1052
|
let bestVarianceAbs = Infinity;
|
|
930
1053
|
let bestInstructionEstimate;
|
|
931
1054
|
const originalToolContent = /* @__PURE__ */ new Map();
|
|
932
1055
|
let originalToolContentSize = 0;
|
|
1056
|
+
const canonicalByProjection = /* @__PURE__ */ new WeakMap();
|
|
1057
|
+
let fadingTier = seedFadingTier(factoryParams.maxTokens, factoryParams.fadingTier);
|
|
1058
|
+
let restoredTierPending = isFadingTier(factoryParams.fadingTier);
|
|
1059
|
+
let maxToolExchangeWidth = 1;
|
|
1060
|
+
let toolExchangeWidthThrough = 0;
|
|
1061
|
+
let toolExchangeWidthSources = [];
|
|
1062
|
+
let fadedThrough = 0;
|
|
1063
|
+
let maskedThrough = 0;
|
|
933
1064
|
const contextPruningSettings = resolveContextPruningSettings(factoryParams.contextPruningConfig);
|
|
934
1065
|
return function pruneMessages(params) {
|
|
1066
|
+
const suppliedCanonicalMessages = params.canonicalMessages;
|
|
1067
|
+
const derivesCanonicalHistory = suppliedCanonicalMessages == null;
|
|
1068
|
+
const canonicalMessages = suppliedCanonicalMessages ?? params.messages.map((message) => {
|
|
1069
|
+
const recovered = canonicalByProjection.get(message);
|
|
1070
|
+
if (recovered != null) return recovered;
|
|
1071
|
+
return Array.isArray(message.content) ? cloneMessage(message, [...message.content]) : message;
|
|
1072
|
+
});
|
|
1073
|
+
const priorWidthLength = toolExchangeWidthSources.length;
|
|
1074
|
+
if (derivesCanonicalHistory ? canonicalMessages.length < priorWidthLength || toolExchangeWidthSources.some((source, index) => canonicalMessages[index] !== source) : canonicalMessages.length < priorWidthLength || (params.canonicalPrefixStable === true ? priorWidthLength > 0 && canonicalMessages[priorWidthLength - 1] !== toolExchangeWidthSources[priorWidthLength - 1] : toolExchangeWidthSources.some((source, index) => canonicalMessages[index] !== source))) {
|
|
1075
|
+
maxToolExchangeWidth = 1;
|
|
1076
|
+
toolExchangeWidthThrough = 0;
|
|
1077
|
+
toolExchangeWidthSources = [];
|
|
1078
|
+
fadedThrough = 0;
|
|
1079
|
+
maskedThrough = 0;
|
|
1080
|
+
originalToolContent.clear();
|
|
1081
|
+
originalToolContentSize = 0;
|
|
1082
|
+
}
|
|
1083
|
+
for (let i = toolExchangeWidthThrough; i < canonicalMessages.length; i++) {
|
|
1084
|
+
maxToolExchangeWidth = Math.max(maxToolExchangeWidth, getToolCallIds(canonicalMessages[i]).size);
|
|
1085
|
+
toolExchangeWidthSources[i] = canonicalMessages[i];
|
|
1086
|
+
}
|
|
1087
|
+
toolExchangeWidthThrough = canonicalMessages.length;
|
|
935
1088
|
let newOriginalToolContent;
|
|
936
1089
|
if (params.messages.length === 0) {
|
|
937
1090
|
const emptyInstructionTokens = factoryParams.getInstructionTokens?.() ?? 0;
|
|
@@ -945,6 +1098,7 @@ function createPruneMessages(factoryParams) {
|
|
|
945
1098
|
prePruneContextTokens: 0,
|
|
946
1099
|
remainingContextTokens: Math.max(0, emptyBudget - emptyInstructionTokens - emptyReplyPrimerTokens),
|
|
947
1100
|
calibrationRatio,
|
|
1101
|
+
fadingTier,
|
|
948
1102
|
resolvedInstructionOverhead: bestInstructionOverhead,
|
|
949
1103
|
contextBudget: emptyBudget,
|
|
950
1104
|
effectiveInstructionTokens: emptyInstructionTokens
|
|
@@ -987,14 +1141,33 @@ function createPruneMessages(factoryParams) {
|
|
|
987
1141
|
};
|
|
988
1142
|
for (let i = 0; i < params.messages.length; i++) {
|
|
989
1143
|
let message = params.messages[i];
|
|
990
|
-
|
|
1144
|
+
let cachedCount = indexTokenCountMap[i];
|
|
991
1145
|
const messageType = message.getType();
|
|
992
1146
|
const messageRole = message.role;
|
|
993
|
-
|
|
1147
|
+
const isAssistant = messageType === "ai" || messageRole === "assistant";
|
|
1148
|
+
if (isAssistant && !canonicalizedToolCallMessages.has(message)) {
|
|
1149
|
+
const [canonicalized] = projectToolCallInputs([message], HARD_MAX_TOOL_CALL_INPUT_CHARS);
|
|
1150
|
+
if (canonicalized !== message) {
|
|
1151
|
+
message = canonicalized;
|
|
1152
|
+
params.messages[i] = message;
|
|
1153
|
+
const canonicalizedCount = factoryParams.tokenCounter(message);
|
|
1154
|
+
indexTokenCountMap[i] = canonicalizedCount;
|
|
1155
|
+
totalTokens += canonicalizedCount - (cachedCount ?? 0);
|
|
1156
|
+
cachedCount = canonicalizedCount;
|
|
1157
|
+
if (i >= lastTurnStartIndex) newOutputs.add(i);
|
|
1158
|
+
}
|
|
1159
|
+
canonicalizedToolCallMessages.add(message);
|
|
1160
|
+
}
|
|
1161
|
+
if ((isAssistant ? readPropertyWithoutAccessors(message.additional_kwargs, "function_call") : void 0)?.found === true && !reconciledLegacyAiMessages.has(message)) {
|
|
994
1162
|
const [projected] = projectToolCallInputs([message], calculateMaxToolCallInputChars(factoryParams.maxTokens));
|
|
995
1163
|
if (projected !== message) {
|
|
996
1164
|
message = projected;
|
|
997
1165
|
params.messages[i] = message;
|
|
1166
|
+
const projectedCount = factoryParams.tokenCounter(message);
|
|
1167
|
+
indexTokenCountMap[i] = projectedCount;
|
|
1168
|
+
totalTokens += projectedCount - (cachedCount ?? 0);
|
|
1169
|
+
cachedCount = projectedCount;
|
|
1170
|
+
if (i >= lastTurnStartIndex) newOutputs.add(i);
|
|
998
1171
|
}
|
|
999
1172
|
reconciledLegacyAiMessages.add(message);
|
|
1000
1173
|
if (cachedCount !== void 0 || i < lastTurnStartIndex) applyReconciledCount(i, cachedCount, factoryParams.tokenCounter(message));
|
|
@@ -1081,15 +1254,6 @@ function createPruneMessages(factoryParams) {
|
|
|
1081
1254
|
const pruningBudget = factoryParams.maxTokens - reserveTokens;
|
|
1082
1255
|
const effectiveMaxTokens = Math.max(0, pruningBudget - currentInstructionTokens);
|
|
1083
1256
|
let calibratedTotalTokens = Math.round(totalTokens * calibrationRatio);
|
|
1084
|
-
factoryParams.log?.("debug", "Budget", {
|
|
1085
|
-
maxTokens: factoryParams.maxTokens,
|
|
1086
|
-
pruningBudget,
|
|
1087
|
-
effectiveMax: effectiveMaxTokens,
|
|
1088
|
-
instructionTokens: currentInstructionTokens,
|
|
1089
|
-
messageCount: params.messages.length,
|
|
1090
|
-
calibratedTotalTokens,
|
|
1091
|
-
calibrationRatio: Math.round(calibrationRatio * 100) / 100
|
|
1092
|
-
});
|
|
1093
1257
|
if (effectiveMaxTokens === 0 && factoryParams.summarizationEnabled === true && params.messages.length > 0) {
|
|
1094
1258
|
factoryParams.log?.("warn", "Instructions consume entire budget — yielding all messages for summarization", {
|
|
1095
1259
|
instructionTokens: currentInstructionTokens,
|
|
@@ -1105,81 +1269,102 @@ function createPruneMessages(factoryParams) {
|
|
|
1105
1269
|
remainingContextTokens: 0,
|
|
1106
1270
|
contextPressure: pruningBudget > 0 ? calibratedTotalTokens / pruningBudget : 0,
|
|
1107
1271
|
calibrationRatio,
|
|
1272
|
+
fadingTier,
|
|
1108
1273
|
resolvedInstructionOverhead: bestInstructionOverhead,
|
|
1109
1274
|
contextBudget: pruningBudget,
|
|
1110
1275
|
effectiveInstructionTokens: currentInstructionTokens
|
|
1111
1276
|
};
|
|
1112
1277
|
}
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1278
|
+
const storeOriginalToolContent = (index, content) => {
|
|
1279
|
+
originalToolContentSize += content.length;
|
|
1280
|
+
if (newOriginalToolContent == null) newOriginalToolContent = /* @__PURE__ */ new Map();
|
|
1281
|
+
newOriginalToolContent.set(index, content);
|
|
1282
|
+
while (originalToolContentSize > 2e6 && originalToolContent.size > 0) {
|
|
1283
|
+
const oldest = originalToolContent.keys().next();
|
|
1284
|
+
if (oldest.done === true) break;
|
|
1285
|
+
const removed = originalToolContent.get(oldest.value);
|
|
1286
|
+
if (removed != null) originalToolContentSize -= removed.length;
|
|
1287
|
+
originalToolContent.delete(oldest.value);
|
|
1288
|
+
}
|
|
1289
|
+
};
|
|
1290
|
+
let restoredFading = {
|
|
1291
|
+
truncated: 0,
|
|
1292
|
+
inputs: 0,
|
|
1293
|
+
masked: 0,
|
|
1294
|
+
consumedBoundary: 0
|
|
1295
|
+
};
|
|
1296
|
+
if (restoredTierPending) {
|
|
1297
|
+
restoredFading = applyFadingCaps({
|
|
1123
1298
|
messages: params.messages,
|
|
1299
|
+
canonicalMessages,
|
|
1124
1300
|
indexTokenCountMap,
|
|
1125
1301
|
tokenCounter: factoryParams.tokenCounter,
|
|
1126
|
-
|
|
1302
|
+
caps: resolveFadingCaps(fadingTier, factoryParams.maxToolResultChars),
|
|
1303
|
+
masked: fadingTier.masked,
|
|
1127
1304
|
originalContentStore: factoryParams.summarizationEnabled === true ? originalToolContent : void 0,
|
|
1128
|
-
onContentStored: factoryParams.summarizationEnabled === true ?
|
|
1129
|
-
originalToolContentSize += content.length;
|
|
1130
|
-
if (newOriginalToolContent == null) newOriginalToolContent = /* @__PURE__ */ new Map();
|
|
1131
|
-
newOriginalToolContent.set(index, content);
|
|
1132
|
-
while (originalToolContentSize > 2e6 && originalToolContent.size > 0) {
|
|
1133
|
-
const oldest = originalToolContent.keys().next();
|
|
1134
|
-
if (oldest.done === true) break;
|
|
1135
|
-
const removed = originalToolContent.get(oldest.value);
|
|
1136
|
-
if (removed != null) originalToolContentSize -= removed.length;
|
|
1137
|
-
originalToolContent.delete(oldest.value);
|
|
1138
|
-
}
|
|
1139
|
-
} : void 0
|
|
1305
|
+
onContentStored: factoryParams.summarizationEnabled === true ? storeOriginalToolContent : void 0
|
|
1140
1306
|
});
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
}
|
|
1307
|
+
fadedThrough = params.messages.length;
|
|
1308
|
+
maskedThrough = restoredFading.consumedBoundary;
|
|
1309
|
+
restoredTierPending = false;
|
|
1145
1310
|
}
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1311
|
+
totalTokens = sumTokenCounts(indexTokenCountMap, params.messages.length);
|
|
1312
|
+
calibratedTotalTokens = Math.round(totalTokens * calibrationRatio);
|
|
1313
|
+
const contextPressure = pruningBudget > 0 ? calibratedTotalTokens / pruningBudget : 0;
|
|
1314
|
+
factoryParams.log?.("debug", "Budget", {
|
|
1315
|
+
maxTokens: factoryParams.maxTokens,
|
|
1316
|
+
pruningBudget,
|
|
1317
|
+
effectiveMax: effectiveMaxTokens,
|
|
1318
|
+
instructionTokens: currentInstructionTokens,
|
|
1319
|
+
messageCount: params.messages.length,
|
|
1320
|
+
calibratedTotalTokens,
|
|
1321
|
+
calibrationRatio: Math.round(calibrationRatio * 100) / 100
|
|
1322
|
+
});
|
|
1323
|
+
const fade = (signals) => {
|
|
1324
|
+
const nextTier = resolveFadingTier(fadingTier, factoryParams.maxTokens, signals, factoryParams.maxToolResultChars);
|
|
1325
|
+
if (nextTier !== fadingTier) {
|
|
1326
|
+
fadingTier = nextTier;
|
|
1327
|
+
fadedThrough = 0;
|
|
1328
|
+
maskedThrough = 0;
|
|
1329
|
+
}
|
|
1330
|
+
const result = applyFadingCaps({
|
|
1156
1331
|
messages: params.messages,
|
|
1157
|
-
|
|
1332
|
+
canonicalMessages,
|
|
1158
1333
|
indexTokenCountMap,
|
|
1159
|
-
tokenCounter: factoryParams.tokenCounter
|
|
1334
|
+
tokenCounter: factoryParams.tokenCounter,
|
|
1335
|
+
caps: resolveFadingCaps(fadingTier, factoryParams.maxToolResultChars),
|
|
1336
|
+
masked: fadingTier.masked,
|
|
1337
|
+
fromIndex: fadedThrough,
|
|
1338
|
+
maskedFromIndex: maskedThrough,
|
|
1339
|
+
originalContentStore: factoryParams.summarizationEnabled === true ? originalToolContent : void 0,
|
|
1340
|
+
onContentStored: factoryParams.summarizationEnabled === true ? storeOriginalToolContent : void 0
|
|
1160
1341
|
});
|
|
1342
|
+
fadedThrough = params.messages.length;
|
|
1343
|
+
maskedThrough = result.consumedBoundary;
|
|
1344
|
+
return result;
|
|
1345
|
+
};
|
|
1346
|
+
const fadingSignals = {
|
|
1347
|
+
contextPressure,
|
|
1348
|
+
effectiveRawTokens: calibrationRatio > 0 ? Math.floor(effectiveMaxTokens / calibrationRatio) : effectiveMaxTokens,
|
|
1349
|
+
summarizationEnabled: factoryParams.summarizationEnabled === true,
|
|
1350
|
+
toolExchangeWidth: maxToolExchangeWidth
|
|
1351
|
+
};
|
|
1352
|
+
const faded = fade(fadingSignals);
|
|
1353
|
+
const observationsMasked = restoredFading.masked + faded.masked;
|
|
1354
|
+
const preFlightResultCount = restoredFading.truncated + faded.truncated;
|
|
1355
|
+
const preFlightInputCount = restoredFading.inputs + faded.inputs;
|
|
1356
|
+
if (observationsMasked > 0) {
|
|
1357
|
+
cumulativeRawSent = 0;
|
|
1358
|
+
cumulativeProviderReported = 0;
|
|
1161
1359
|
}
|
|
1162
1360
|
if (factoryParams.contextPruningConfig?.enabled === true && factoryParams.summarizationEnabled !== true) applyContextPruning({
|
|
1163
1361
|
messages: params.messages,
|
|
1362
|
+
canonicalMessages,
|
|
1164
1363
|
indexTokenCountMap,
|
|
1165
1364
|
tokenCounter: factoryParams.tokenCounter,
|
|
1166
1365
|
resolvedSettings: contextPruningSettings
|
|
1167
1366
|
});
|
|
1168
|
-
|
|
1169
|
-
if (factoryParams.summarizationEnabled === true && rawSpaceEffectiveMax > 0) {
|
|
1170
|
-
preFlightResultCount = preFlightTruncateToolResults({
|
|
1171
|
-
messages: params.messages,
|
|
1172
|
-
maxContextTokens: rawSpaceEffectiveMax,
|
|
1173
|
-
indexTokenCountMap,
|
|
1174
|
-
tokenCounter: factoryParams.tokenCounter
|
|
1175
|
-
});
|
|
1176
|
-
preFlightInputCount = preFlightTruncateToolCallInputs({
|
|
1177
|
-
messages: params.messages,
|
|
1178
|
-
maxContextTokens: rawSpaceEffectiveMax,
|
|
1179
|
-
indexTokenCountMap,
|
|
1180
|
-
tokenCounter: factoryParams.tokenCounter
|
|
1181
|
-
});
|
|
1182
|
-
}
|
|
1367
|
+
if (derivesCanonicalHistory) for (let i = 0; i < params.messages.length; i++) canonicalByProjection.set(params.messages[i], canonicalMessages[i]);
|
|
1183
1368
|
const preTruncationTotalTokens = totalTokens;
|
|
1184
1369
|
totalTokens = sumTokenCounts(indexTokenCountMap, params.messages.length);
|
|
1185
1370
|
calibratedTotalTokens = Math.round(totalTokens * calibrationRatio);
|
|
@@ -1204,6 +1389,7 @@ function createPruneMessages(factoryParams) {
|
|
|
1204
1389
|
originalToolContent: originalToolContent.size > 0 ? originalToolContent : void 0,
|
|
1205
1390
|
newOriginalToolContent,
|
|
1206
1391
|
calibrationRatio,
|
|
1392
|
+
fadingTier,
|
|
1207
1393
|
resolvedInstructionOverhead: bestInstructionOverhead,
|
|
1208
1394
|
contextBudget: pruningBudget,
|
|
1209
1395
|
effectiveInstructionTokens: currentInstructionTokens
|
|
@@ -1242,96 +1428,36 @@ function createPruneMessages(factoryParams) {
|
|
|
1242
1428
|
let context = repairedContext;
|
|
1243
1429
|
let reclaimedTokens = initialReclaimedTokens;
|
|
1244
1430
|
if (droppedMessages.length > 0) appendItems(messagesToRefine, droppedMessages);
|
|
1245
|
-
if (context.length === 0 && params.messages.length > 0 && effectiveMaxTokens > 0 && factoryParams.summarizationEnabled === true) {
|
|
1246
|
-
const fadingBudget = Math.max(1024, effectiveMaxTokens);
|
|
1247
|
-
factoryParams.log?.("debug", "Fallback fading — empty context with summarization", {
|
|
1248
|
-
messageCount: params.messages.length,
|
|
1249
|
-
effectiveMaxTokens,
|
|
1250
|
-
fadingBudget
|
|
1251
|
-
});
|
|
1252
|
-
const fadedMessages = [...params.messages];
|
|
1253
|
-
const preFadingTokenCounts = {};
|
|
1254
|
-
for (let i = 0; i < params.messages.length; i++) preFadingTokenCounts[i] = indexTokenCountMap[i];
|
|
1255
|
-
preFlightTruncateToolResults({
|
|
1256
|
-
messages: fadedMessages,
|
|
1257
|
-
maxContextTokens: fadingBudget,
|
|
1258
|
-
indexTokenCountMap,
|
|
1259
|
-
tokenCounter: factoryParams.tokenCounter
|
|
1260
|
-
});
|
|
1261
|
-
preFlightTruncateToolCallInputs({
|
|
1262
|
-
messages: fadedMessages,
|
|
1263
|
-
maxContextTokens: fadingBudget,
|
|
1264
|
-
indexTokenCountMap,
|
|
1265
|
-
tokenCounter: factoryParams.tokenCounter
|
|
1266
|
-
});
|
|
1267
|
-
const fadingRetry = getMessagesWithinTokenLimit({
|
|
1268
|
-
maxContextTokens: pruningBudget,
|
|
1269
|
-
messages: fadedMessages,
|
|
1270
|
-
indexTokenCountMap,
|
|
1271
|
-
startType: params.startType,
|
|
1272
|
-
thinkingEnabled: factoryParams.thinkingEnabled,
|
|
1273
|
-
tokenCounter: factoryParams.tokenCounter,
|
|
1274
|
-
instructionTokens: currentInstructionTokens,
|
|
1275
|
-
reasoningType: usesBedrockThinking ? "reasoning_content" : "thinking",
|
|
1276
|
-
thinkingStartIndex: factoryParams.thinkingEnabled === true ? runThinkingStartIndex : void 0
|
|
1277
|
-
});
|
|
1278
|
-
const fadingRepaired = repairOrphanedToolMessages({
|
|
1279
|
-
context: fadingRetry.context,
|
|
1280
|
-
allMessages: fadedMessages,
|
|
1281
|
-
tokenCounter: factoryParams.tokenCounter,
|
|
1282
|
-
indexTokenCountMap
|
|
1283
|
-
});
|
|
1284
|
-
if (fadingRepaired.context.length > 0) {
|
|
1285
|
-
context = fadingRepaired.context;
|
|
1286
|
-
reclaimedTokens = fadingRepaired.reclaimedTokens;
|
|
1287
|
-
appendItems(messagesToRefine, fadingRetry.messagesToRefine);
|
|
1288
|
-
if (fadingRepaired.droppedMessages.length > 0) appendItems(messagesToRefine, fadingRepaired.droppedMessages);
|
|
1289
|
-
factoryParams.log?.("debug", "Fallback fading recovered context", {
|
|
1290
|
-
contextLength: context.length,
|
|
1291
|
-
messagesToRefineCount: messagesToRefine.length,
|
|
1292
|
-
remainingTokens: fadingRetry.remainingContextTokens
|
|
1293
|
-
});
|
|
1294
|
-
for (const [key, value] of Object.entries(preFadingTokenCounts)) indexTokenCountMap[key] = value;
|
|
1295
|
-
} else for (const [key, value] of Object.entries(preFadingTokenCounts)) indexTokenCountMap[key] = value;
|
|
1296
|
-
}
|
|
1297
1431
|
if (context.length === 0 && params.messages.length > 0 && effectiveMaxTokens > 0) {
|
|
1298
1432
|
const perMessageTokenBudget = Math.floor(effectiveMaxTokens / Math.max(1, params.messages.length));
|
|
1299
1433
|
const emergencyMaxChars = Math.max(200, perMessageTokenBudget * 4);
|
|
1434
|
+
const emergencyTier = resolveFadingTier(fadingTier, factoryParams.maxTokens, {
|
|
1435
|
+
...fadingSignals,
|
|
1436
|
+
minRung: fadingRungForExchangeChars(factoryParams.maxTokens, emergencyMaxChars, factoryParams.maxToolResultChars)
|
|
1437
|
+
}, factoryParams.maxToolResultChars);
|
|
1438
|
+
const emergencyCaps = resolveFadingCaps(emergencyTier, factoryParams.maxToolResultChars);
|
|
1300
1439
|
factoryParams.log?.("warn", "Empty context, entering emergency truncation", {
|
|
1301
1440
|
messageCount: params.messages.length,
|
|
1302
1441
|
effectiveMax: effectiveMaxTokens,
|
|
1303
|
-
emergencyMaxChars
|
|
1442
|
+
emergencyMaxChars,
|
|
1443
|
+
budgetTokens: emergencyCaps.budgetTokens
|
|
1304
1444
|
});
|
|
1305
1445
|
const emergencyMessages = [...params.messages];
|
|
1306
1446
|
const preEmergencyTokenCounts = {};
|
|
1307
1447
|
for (let i = 0; i < params.messages.length; i++) preEmergencyTokenCounts[i] = indexTokenCountMap[i];
|
|
1308
1448
|
try {
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
const cloned = cloneToolMessageWithContent(message, compacted.content);
|
|
1318
|
-
emergencyMessages[i] = cloned;
|
|
1319
|
-
indexTokenCountMap[i] = factoryParams.tokenCounter(cloned);
|
|
1320
|
-
emergencyTruncatedCount++;
|
|
1321
|
-
}
|
|
1322
|
-
}
|
|
1323
|
-
}
|
|
1324
|
-
const projectedToolInputs = projectToolCallInputs(emergencyMessages, emergencyMaxChars);
|
|
1325
|
-
if (projectedToolInputs !== emergencyMessages) for (let i = 0; i < emergencyMessages.length; i++) {
|
|
1326
|
-
if (projectedToolInputs[i] === emergencyMessages[i]) continue;
|
|
1327
|
-
emergencyMessages[i] = projectedToolInputs[i];
|
|
1328
|
-
indexTokenCountMap[i] = factoryParams.tokenCounter(projectedToolInputs[i]);
|
|
1329
|
-
emergencyTruncatedCount++;
|
|
1330
|
-
}
|
|
1449
|
+
const emergency = applyFadingCaps({
|
|
1450
|
+
messages: emergencyMessages,
|
|
1451
|
+
canonicalMessages,
|
|
1452
|
+
indexTokenCountMap,
|
|
1453
|
+
tokenCounter: factoryParams.tokenCounter,
|
|
1454
|
+
caps: emergencyCaps,
|
|
1455
|
+
masked: emergencyTier.masked
|
|
1456
|
+
});
|
|
1331
1457
|
factoryParams.log?.("info", "Emergency truncation complete");
|
|
1332
1458
|
factoryParams.log?.("debug", "Emergency truncation details", {
|
|
1333
|
-
truncatedCount:
|
|
1334
|
-
|
|
1459
|
+
truncatedCount: emergency.truncated + emergency.inputs + emergency.masked,
|
|
1460
|
+
budgetTokens: emergencyCaps.budgetTokens
|
|
1335
1461
|
});
|
|
1336
1462
|
const retryResult = getMessagesWithinTokenLimit({
|
|
1337
1463
|
maxContextTokens: pruningBudget,
|
|
@@ -1352,6 +1478,7 @@ function createPruneMessages(factoryParams) {
|
|
|
1352
1478
|
});
|
|
1353
1479
|
context = repaired.context;
|
|
1354
1480
|
reclaimedTokens = repaired.reclaimedTokens;
|
|
1481
|
+
messagesToRefine.length = 0;
|
|
1355
1482
|
appendItems(messagesToRefine, retryResult.messagesToRefine);
|
|
1356
1483
|
if (repaired.droppedMessages.length > 0) appendItems(messagesToRefine, repaired.droppedMessages);
|
|
1357
1484
|
factoryParams.log?.("debug", "Emergency truncation retry result", {
|
|
@@ -1377,6 +1504,7 @@ function createPruneMessages(factoryParams) {
|
|
|
1377
1504
|
originalToolContent: originalToolContent.size > 0 ? originalToolContent : void 0,
|
|
1378
1505
|
newOriginalToolContent,
|
|
1379
1506
|
calibrationRatio,
|
|
1507
|
+
fadingTier,
|
|
1380
1508
|
resolvedInstructionOverhead: bestInstructionOverhead,
|
|
1381
1509
|
contextBudget: pruningBudget,
|
|
1382
1510
|
effectiveInstructionTokens: currentInstructionTokens
|
|
@@ -1384,6 +1512,6 @@ function createPruneMessages(factoryParams) {
|
|
|
1384
1512
|
};
|
|
1385
1513
|
}
|
|
1386
1514
|
//#endregion
|
|
1387
|
-
export { CALIBRATION_RATIO_MAX, CALIBRATION_RATIO_MIN, DEFAULT_RESERVE_RATIO, ORIGINAL_CONTENT_MAX_CHARS, REPLY_PRIMER_TOKENS,
|
|
1515
|
+
export { CALIBRATION_RATIO_MAX, CALIBRATION_RATIO_MIN, DEFAULT_RESERVE_RATIO, ORIGINAL_CONTENT_MAX_CHARS, REPLY_PRIMER_TOKENS, applyFadingCaps, calculateTotalTokens, checkValidNumber, clampCalibrationRatio, createPruneMessages, enforceOriginalContentCap, getMessagesWithinTokenLimit, maskConsumedToolResults, preFlightTruncateToolCallInputs, preFlightTruncateToolResults, projectToolCallInputs, projectToolMessagesForProvider, repairOrphanedToolMessages, sanitizeOrphanToolBlocks, serializeToolCallInput };
|
|
1388
1516
|
|
|
1389
1517
|
//# sourceMappingURL=prune.mjs.map
|