@librechat/agents 3.9.1 → 3.9.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/graphs/Graph.cjs +13 -4
- package/dist/cjs/graphs/Graph.cjs.map +1 -1
- package/dist/cjs/graphs/MultiAgentGraph.cjs +97 -5
- package/dist/cjs/graphs/MultiAgentGraph.cjs.map +1 -1
- package/dist/cjs/graphs/handoff.cjs +195 -0
- package/dist/cjs/graphs/handoff.cjs.map +1 -0
- package/dist/cjs/graphs/index.cjs +1 -0
- package/dist/cjs/main.cjs +3 -0
- package/dist/cjs/messages/contextPruning.cjs +2 -1
- package/dist/cjs/messages/contextPruning.cjs.map +1 -1
- package/dist/cjs/messages/prune.cjs +3 -3
- package/dist/cjs/messages/prune.cjs.map +1 -1
- package/dist/cjs/run.cjs +33 -3
- package/dist/cjs/run.cjs.map +1 -1
- package/dist/cjs/tools/ToolNode.cjs +4 -1
- package/dist/cjs/tools/ToolNode.cjs.map +1 -1
- package/dist/cjs/utils/toolContent.cjs +6 -6
- package/dist/cjs/utils/toolContent.cjs.map +1 -1
- package/dist/cjs/utils/truncation.cjs +14 -5
- package/dist/cjs/utils/truncation.cjs.map +1 -1
- package/dist/esm/graphs/Graph.mjs +13 -4
- package/dist/esm/graphs/Graph.mjs.map +1 -1
- package/dist/esm/graphs/MultiAgentGraph.mjs +97 -5
- package/dist/esm/graphs/MultiAgentGraph.mjs.map +1 -1
- package/dist/esm/graphs/handoff.mjs +193 -0
- package/dist/esm/graphs/handoff.mjs.map +1 -0
- package/dist/esm/graphs/index.mjs +1 -0
- package/dist/esm/main.mjs +3 -2
- package/dist/esm/messages/contextPruning.mjs +2 -1
- package/dist/esm/messages/contextPruning.mjs.map +1 -1
- package/dist/esm/messages/prune.mjs +4 -4
- package/dist/esm/messages/prune.mjs.map +1 -1
- package/dist/esm/run.mjs +33 -3
- package/dist/esm/run.mjs.map +1 -1
- package/dist/esm/tools/ToolNode.mjs +4 -1
- package/dist/esm/tools/ToolNode.mjs.map +1 -1
- package/dist/esm/utils/toolContent.mjs +7 -7
- package/dist/esm/utils/toolContent.mjs.map +1 -1
- package/dist/esm/utils/truncation.mjs +14 -6
- package/dist/esm/utils/truncation.mjs.map +1 -1
- package/dist/types/graphs/Graph.d.ts +2 -0
- package/dist/types/graphs/MultiAgentGraph.d.ts +3 -0
- package/dist/types/graphs/handoff.d.ts +28 -0
- package/dist/types/graphs/index.d.ts +1 -0
- package/dist/types/run.d.ts +4 -0
- package/dist/types/tools/ToolNode.d.ts +2 -1
- package/dist/types/types/graph.d.ts +46 -1
- package/dist/types/types/run.d.ts +3 -1
- package/dist/types/types/tools.d.ts +3 -0
- package/dist/types/utils/toolContent.d.ts +1 -1
- package/dist/types/utils/truncation.d.ts +2 -0
- package/package.json +1 -1
- package/src/graphs/Graph.ts +8 -0
- package/src/graphs/MultiAgentGraph.ts +142 -4
- package/src/graphs/handoff.ts +263 -0
- package/src/graphs/index.ts +2 -0
- package/src/messages/contextPruning.ts +8 -2
- package/src/messages/prune.ts +15 -10
- package/src/run.ts +54 -2
- package/src/tools/ToolNode.ts +14 -6
- package/src/types/graph.ts +44 -1
- package/src/types/run.ts +3 -1
- package/src/types/tools.ts +3 -0
- package/src/utils/toolContent.ts +23 -7
- package/src/utils/truncation.ts +31 -6
package/src/utils/toolContent.ts
CHANGED
|
@@ -3,6 +3,7 @@ import { ToolMessage, type BaseMessage } from '@langchain/core/messages';
|
|
|
3
3
|
import {
|
|
4
4
|
HARD_MAX_TOTAL_TOOL_OUTPUT_SIZE,
|
|
5
5
|
truncateToolResultContent,
|
|
6
|
+
sliceWithoutSplittingSurrogates,
|
|
6
7
|
} from './truncation';
|
|
7
8
|
|
|
8
9
|
type ToolContent = BaseMessage['content'];
|
|
@@ -421,7 +422,7 @@ type SegmentedStringBuffer = {
|
|
|
421
422
|
export type BoundedStructuredSerialization = {
|
|
422
423
|
/** Provider-facing head/tail preview, bounded by `maxChars`. */
|
|
423
424
|
content: string;
|
|
424
|
-
/**
|
|
425
|
+
/** Code-point-aligned serialized prefix up to the traversal-work ceiling. */
|
|
425
426
|
prefix: string;
|
|
426
427
|
/** Exact length, or `Number.MAX_SAFE_INTEGER` when traversal was capped. */
|
|
427
428
|
originalChars: number;
|
|
@@ -505,6 +506,10 @@ function materializeSegmentedStringBuffer(
|
|
|
505
506
|
return segments.join('');
|
|
506
507
|
}
|
|
507
508
|
|
|
509
|
+
/**
|
|
510
|
+
* Retains exact code-unit prefixes internally. Trimming surrogate edges here
|
|
511
|
+
* would let later chunks fill the gap and corrupt the prefix; trim on exposure.
|
|
512
|
+
*/
|
|
508
513
|
function appendSerializedChunk(
|
|
509
514
|
collector: StructuredSerializationCollector,
|
|
510
515
|
chunk: string
|
|
@@ -953,7 +958,7 @@ function formatBoundedStructuredContent(
|
|
|
953
958
|
suffix: string
|
|
954
959
|
): string {
|
|
955
960
|
if (collector.totalChars <= maxChars) {
|
|
956
|
-
return prefix
|
|
961
|
+
return sliceWithoutSplittingSurrogates(prefix, 0, collector.totalChars);
|
|
957
962
|
}
|
|
958
963
|
|
|
959
964
|
const indicator = collector.work.exceeded
|
|
@@ -962,10 +967,13 @@ function formatBoundedStructuredContent(
|
|
|
962
967
|
`${maxChars} limit] …\n\n`;
|
|
963
968
|
const available = maxChars - indicator.length;
|
|
964
969
|
if (available <= 0) {
|
|
965
|
-
return prefix
|
|
970
|
+
return sliceWithoutSplittingSurrogates(prefix, 0, maxChars);
|
|
966
971
|
}
|
|
967
972
|
if (available < 200) {
|
|
968
|
-
return
|
|
973
|
+
return (
|
|
974
|
+
sliceWithoutSplittingSurrogates(prefix, 0, available) +
|
|
975
|
+
indicator.trimEnd()
|
|
976
|
+
);
|
|
969
977
|
}
|
|
970
978
|
|
|
971
979
|
const headSize = Math.ceil(available * 0.7);
|
|
@@ -982,7 +990,11 @@ function formatBoundedStructuredContent(
|
|
|
982
990
|
tailStart = tailNewline + 1;
|
|
983
991
|
}
|
|
984
992
|
|
|
985
|
-
return
|
|
993
|
+
return (
|
|
994
|
+
sliceWithoutSplittingSurrogates(prefix, 0, headEnd) +
|
|
995
|
+
indicator +
|
|
996
|
+
sliceWithoutSplittingSurrogates(suffix, tailStart)
|
|
997
|
+
);
|
|
986
998
|
}
|
|
987
999
|
|
|
988
1000
|
/**
|
|
@@ -1036,7 +1048,7 @@ export function serializeStructuredValueBounded(
|
|
|
1036
1048
|
prefix,
|
|
1037
1049
|
suffix
|
|
1038
1050
|
),
|
|
1039
|
-
prefix: prefix
|
|
1051
|
+
prefix: sliceWithoutSplittingSurrogates(prefix, 0, normalizedPrefixChars),
|
|
1040
1052
|
originalChars,
|
|
1041
1053
|
truncated:
|
|
1042
1054
|
collector.work.exceeded || collector.totalChars > normalizedMaxChars,
|
|
@@ -1931,7 +1943,11 @@ function serializeDenseTextBlocksWithinLimit(
|
|
|
1931
1943
|
}
|
|
1932
1944
|
preview += textBlocks[i].text.slice(0, available - preview.length);
|
|
1933
1945
|
}
|
|
1934
|
-
return (
|
|
1946
|
+
return sliceWithoutSplittingSurrogates(
|
|
1947
|
+
sliceWithoutSplittingSurrogates(preview, 0) + indicator,
|
|
1948
|
+
0,
|
|
1949
|
+
normalizedMaxChars
|
|
1950
|
+
);
|
|
1935
1951
|
}
|
|
1936
1952
|
|
|
1937
1953
|
export type CompactToolContentResult = {
|
package/src/utils/truncation.ts
CHANGED
|
@@ -5,6 +5,22 @@
|
|
|
5
5
|
* consuming the entire context window.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
+
/** Slices by UTF-16 code units, dropping orphaned surrogate halves at either edge. */
|
|
9
|
+
export function sliceWithoutSplittingSurrogates(
|
|
10
|
+
value: string,
|
|
11
|
+
start: number,
|
|
12
|
+
end?: number
|
|
13
|
+
): string {
|
|
14
|
+
const sliced = value.slice(start, end);
|
|
15
|
+
const first = sliced.charCodeAt(0);
|
|
16
|
+
const last = sliced.charCodeAt(sliced.length - 1);
|
|
17
|
+
const trimStart = first >= 0xdc00 && first <= 0xdfff;
|
|
18
|
+
const trimEnd = last >= 0xd800 && last <= 0xdbff;
|
|
19
|
+
return trimStart || trimEnd
|
|
20
|
+
? sliced.slice(trimStart ? 1 : 0, sliced.length - (trimEnd ? 1 : 0))
|
|
21
|
+
: sliced;
|
|
22
|
+
}
|
|
23
|
+
|
|
8
24
|
/**
|
|
9
25
|
* Absolute hard cap on tool result length (characters).
|
|
10
26
|
* Even if the model has a 1M-token context, a single tool result
|
|
@@ -85,7 +101,9 @@ export function truncateToolInput(
|
|
|
85
101
|
|
|
86
102
|
if (available < 100) {
|
|
87
103
|
return {
|
|
88
|
-
_truncated:
|
|
104
|
+
_truncated:
|
|
105
|
+
sliceWithoutSplittingSurrogates(serialized, 0, maxChars) +
|
|
106
|
+
indicator.trimEnd(),
|
|
89
107
|
_originalChars: serialized.length,
|
|
90
108
|
};
|
|
91
109
|
}
|
|
@@ -95,9 +113,9 @@ export function truncateToolInput(
|
|
|
95
113
|
|
|
96
114
|
return {
|
|
97
115
|
_truncated:
|
|
98
|
-
serialized
|
|
116
|
+
sliceWithoutSplittingSurrogates(serialized, 0, headSize) +
|
|
99
117
|
indicator +
|
|
100
|
-
|
|
118
|
+
sliceWithoutSplittingSurrogates(serialized, serialized.length - tailSize),
|
|
101
119
|
_originalChars: serialized.length,
|
|
102
120
|
};
|
|
103
121
|
}
|
|
@@ -126,12 +144,15 @@ export function truncateToolResultContent(
|
|
|
126
144
|
const indicator = `\n\n… [truncated: ${content.length} chars exceeded ${maxChars} limit] …\n\n`;
|
|
127
145
|
const available = maxChars - indicator.length;
|
|
128
146
|
if (available <= 0) {
|
|
129
|
-
return content
|
|
147
|
+
return sliceWithoutSplittingSurrogates(content, 0, maxChars);
|
|
130
148
|
}
|
|
131
149
|
|
|
132
150
|
// When budget is too small for a meaningful tail, fall back to head-only
|
|
133
151
|
if (available < 200) {
|
|
134
|
-
return
|
|
152
|
+
return (
|
|
153
|
+
sliceWithoutSplittingSurrogates(content, 0, available) +
|
|
154
|
+
indicator.trimEnd()
|
|
155
|
+
);
|
|
135
156
|
}
|
|
136
157
|
|
|
137
158
|
const headSize = Math.ceil(available * 0.7);
|
|
@@ -150,7 +171,11 @@ export function truncateToolResultContent(
|
|
|
150
171
|
tailStart = tailNewline + 1;
|
|
151
172
|
}
|
|
152
173
|
|
|
153
|
-
return
|
|
174
|
+
return (
|
|
175
|
+
sliceWithoutSplittingSurrogates(content, 0, headEnd) +
|
|
176
|
+
indicator +
|
|
177
|
+
sliceWithoutSplittingSurrogates(content, tailStart)
|
|
178
|
+
);
|
|
154
179
|
}
|
|
155
180
|
|
|
156
181
|
/** Absolute hard cap on a single tool-call input (characters). */
|