@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.
Files changed (162) hide show
  1. package/dist/cjs/agents/AgentContext.cjs +2 -1
  2. package/dist/cjs/agents/AgentContext.cjs.map +1 -1
  3. package/dist/cjs/graphs/Graph.cjs +342 -109
  4. package/dist/cjs/graphs/Graph.cjs.map +1 -1
  5. package/dist/cjs/graphs/MultiAgentGraph.cjs +3 -1
  6. package/dist/cjs/graphs/MultiAgentGraph.cjs.map +1 -1
  7. package/dist/cjs/langfuse.cjs +6 -0
  8. package/dist/cjs/langfuse.cjs.map +1 -1
  9. package/dist/cjs/llm/anthropic/utils/message_inputs.cjs +79 -6
  10. package/dist/cjs/llm/anthropic/utils/message_inputs.cjs.map +1 -1
  11. package/dist/cjs/llm/bedrock/utils/message_inputs.cjs +37 -10
  12. package/dist/cjs/llm/bedrock/utils/message_inputs.cjs.map +1 -1
  13. package/dist/cjs/llm/google/utils/common.cjs +19 -7
  14. package/dist/cjs/llm/google/utils/common.cjs.map +1 -1
  15. package/dist/cjs/llm/invoke.cjs +64 -3
  16. package/dist/cjs/llm/invoke.cjs.map +1 -1
  17. package/dist/cjs/llm/openai/index.cjs +41 -5
  18. package/dist/cjs/llm/openai/index.cjs.map +1 -1
  19. package/dist/cjs/llm/openai/utils/index.cjs +25 -4
  20. package/dist/cjs/llm/openai/utils/index.cjs.map +1 -1
  21. package/dist/cjs/llm/openrouter/index.cjs +4 -1
  22. package/dist/cjs/llm/openrouter/index.cjs.map +1 -1
  23. package/dist/cjs/main.cjs +19 -2
  24. package/dist/cjs/messages/cache.cjs +54 -33
  25. package/dist/cjs/messages/cache.cjs.map +1 -1
  26. package/dist/cjs/messages/contextPruning.cjs +17 -43
  27. package/dist/cjs/messages/contextPruning.cjs.map +1 -1
  28. package/dist/cjs/messages/core.cjs +315 -23
  29. package/dist/cjs/messages/core.cjs.map +1 -1
  30. package/dist/cjs/messages/format.cjs +218 -60
  31. package/dist/cjs/messages/format.cjs.map +1 -1
  32. package/dist/cjs/messages/index.cjs +1 -1
  33. package/dist/cjs/messages/prune.cjs +503 -127
  34. package/dist/cjs/messages/prune.cjs.map +1 -1
  35. package/dist/cjs/stream.cjs +7 -3
  36. package/dist/cjs/stream.cjs.map +1 -1
  37. package/dist/cjs/summarization/node.cjs +28 -14
  38. package/dist/cjs/summarization/node.cjs.map +1 -1
  39. package/dist/cjs/tools/ToolNode.cjs +54 -41
  40. package/dist/cjs/tools/ToolNode.cjs.map +1 -1
  41. package/dist/cjs/tools/toolOutputReferences.cjs +6 -0
  42. package/dist/cjs/tools/toolOutputReferences.cjs.map +1 -1
  43. package/dist/cjs/utils/index.cjs +1 -1
  44. package/dist/cjs/utils/llm.cjs +1 -1
  45. package/dist/cjs/utils/llm.cjs.map +1 -1
  46. package/dist/cjs/utils/tokens.cjs +307 -20
  47. package/dist/cjs/utils/tokens.cjs.map +1 -1
  48. package/dist/cjs/utils/toolContent.cjs +1514 -0
  49. package/dist/cjs/utils/toolContent.cjs.map +1 -0
  50. package/dist/esm/agents/AgentContext.mjs +2 -1
  51. package/dist/esm/agents/AgentContext.mjs.map +1 -1
  52. package/dist/esm/graphs/Graph.mjs +349 -116
  53. package/dist/esm/graphs/Graph.mjs.map +1 -1
  54. package/dist/esm/graphs/MultiAgentGraph.mjs +3 -1
  55. package/dist/esm/graphs/MultiAgentGraph.mjs.map +1 -1
  56. package/dist/esm/langfuse.mjs +6 -0
  57. package/dist/esm/langfuse.mjs.map +1 -1
  58. package/dist/esm/llm/anthropic/utils/message_inputs.mjs +79 -6
  59. package/dist/esm/llm/anthropic/utils/message_inputs.mjs.map +1 -1
  60. package/dist/esm/llm/bedrock/utils/message_inputs.mjs +37 -10
  61. package/dist/esm/llm/bedrock/utils/message_inputs.mjs.map +1 -1
  62. package/dist/esm/llm/google/utils/common.mjs +19 -7
  63. package/dist/esm/llm/google/utils/common.mjs.map +1 -1
  64. package/dist/esm/llm/invoke.mjs +65 -5
  65. package/dist/esm/llm/invoke.mjs.map +1 -1
  66. package/dist/esm/llm/openai/index.mjs +41 -5
  67. package/dist/esm/llm/openai/index.mjs.map +1 -1
  68. package/dist/esm/llm/openai/utils/index.mjs +25 -4
  69. package/dist/esm/llm/openai/utils/index.mjs.map +1 -1
  70. package/dist/esm/llm/openrouter/index.mjs +4 -1
  71. package/dist/esm/llm/openrouter/index.mjs.map +1 -1
  72. package/dist/esm/main.mjs +7 -7
  73. package/dist/esm/messages/cache.mjs +55 -34
  74. package/dist/esm/messages/cache.mjs.map +1 -1
  75. package/dist/esm/messages/contextPruning.mjs +17 -43
  76. package/dist/esm/messages/contextPruning.mjs.map +1 -1
  77. package/dist/esm/messages/core.mjs +305 -24
  78. package/dist/esm/messages/core.mjs.map +1 -1
  79. package/dist/esm/messages/format.mjs +218 -61
  80. package/dist/esm/messages/format.mjs.map +1 -1
  81. package/dist/esm/messages/index.mjs +1 -1
  82. package/dist/esm/messages/prune.mjs +500 -128
  83. package/dist/esm/messages/prune.mjs.map +1 -1
  84. package/dist/esm/stream.mjs +7 -3
  85. package/dist/esm/stream.mjs.map +1 -1
  86. package/dist/esm/summarization/node.mjs +28 -14
  87. package/dist/esm/summarization/node.mjs.map +1 -1
  88. package/dist/esm/tools/ToolNode.mjs +54 -41
  89. package/dist/esm/tools/ToolNode.mjs.map +1 -1
  90. package/dist/esm/tools/toolOutputReferences.mjs +6 -0
  91. package/dist/esm/tools/toolOutputReferences.mjs.map +1 -1
  92. package/dist/esm/utils/index.mjs +1 -1
  93. package/dist/esm/utils/llm.mjs +1 -1
  94. package/dist/esm/utils/llm.mjs.map +1 -1
  95. package/dist/esm/utils/tokens.mjs +307 -21
  96. package/dist/esm/utils/tokens.mjs.map +1 -1
  97. package/dist/esm/utils/toolContent.mjs +1503 -0
  98. package/dist/esm/utils/toolContent.mjs.map +1 -0
  99. package/dist/types/graphs/Graph.d.ts +1 -1
  100. package/dist/types/llm/invoke.d.ts +27 -1
  101. package/dist/types/llm/openai/index.d.ts +4 -0
  102. package/dist/types/llm/openai/utils/index.d.ts +2 -0
  103. package/dist/types/llm/openrouter/index.d.ts +5 -0
  104. package/dist/types/messages/contextPruning.d.ts +2 -1
  105. package/dist/types/messages/core.d.ts +36 -0
  106. package/dist/types/messages/format.d.ts +6 -0
  107. package/dist/types/messages/prune.d.ts +16 -12
  108. package/dist/types/types/stream.d.ts +1 -1
  109. package/dist/types/utils/tokens.d.ts +7 -0
  110. package/dist/types/utils/toolContent.d.ts +107 -0
  111. package/package.json +13 -9
  112. package/src/__tests__/stream.eagerEventExecution.test.ts +74 -0
  113. package/src/agents/AgentContext.ts +1 -0
  114. package/src/graphs/Graph.ts +698 -200
  115. package/src/graphs/MultiAgentGraph.ts +6 -1
  116. package/src/graphs/__tests__/Graph.contextOverflow.test.ts +1128 -4
  117. package/src/langfuse.ts +15 -0
  118. package/src/llm/anthropic/utils/message_inputs.ts +158 -12
  119. package/src/llm/anthropic/utils/tool-id-normalization.test.ts +109 -0
  120. package/src/llm/bedrock/utils/message_inputs.test.ts +49 -1
  121. package/src/llm/bedrock/utils/message_inputs.ts +86 -13
  122. package/src/llm/google/utils/common.test.ts +75 -9
  123. package/src/llm/google/utils/common.ts +34 -3
  124. package/src/llm/invoke.test.ts +488 -0
  125. package/src/llm/invoke.ts +196 -2
  126. package/src/llm/openai/index.ts +106 -6
  127. package/src/llm/openai/utils/index.ts +109 -53
  128. package/src/llm/openai/utils/messages.test.ts +330 -1
  129. package/src/llm/openrouter/index.ts +12 -2
  130. package/src/llm/openrouter/reasoning.test.ts +314 -0
  131. package/src/messages/__tests__/observationMasking.test.ts +93 -2
  132. package/src/messages/cache.tail.test.ts +193 -0
  133. package/src/messages/cache.test.ts +113 -0
  134. package/src/messages/cache.ts +92 -60
  135. package/src/messages/contextPruning.test.ts +184 -0
  136. package/src/messages/contextPruning.ts +49 -42
  137. package/src/messages/core.ts +653 -40
  138. package/src/messages/ensureThinkingBlock.test.ts +49 -1
  139. package/src/messages/foldToollessToolBlocks.test.ts +163 -5
  140. package/src/messages/format.ts +363 -91
  141. package/src/messages/formatAgentMessages.test.ts +604 -14
  142. package/src/messages/formatAgentMessages.tools.test.ts +103 -0
  143. package/src/messages/prune.ts +996 -183
  144. package/src/specs/langfuse-callbacks.test.ts +203 -1
  145. package/src/specs/prune.test.ts +1083 -6
  146. package/src/specs/summarization-unit.test.ts +105 -0
  147. package/src/specs/tokens.test.ts +609 -32
  148. package/src/stream.ts +23 -15
  149. package/src/summarization/__tests__/node.test.ts +77 -0
  150. package/src/summarization/node.ts +46 -18
  151. package/src/tools/ToolNode.ts +147 -68
  152. package/src/tools/__tests__/ToolNode.onResultCompletion.test.ts +148 -1
  153. package/src/tools/__tests__/ToolNode.outputReferences.test.ts +112 -3
  154. package/src/tools/__tests__/annotateMessagesForLLM.test.ts +32 -0
  155. package/src/tools/__tests__/directToolHooks.test.ts +255 -7
  156. package/src/tools/toolOutputReferences.ts +6 -0
  157. package/src/types/stream.ts +1 -1
  158. package/src/utils/llm.test.ts +18 -0
  159. package/src/utils/llm.ts +4 -1
  160. package/src/utils/tokens.ts +586 -31
  161. package/src/utils/toolContent.test.ts +1432 -0
  162. package/src/utils/toolContent.ts +2707 -0
@@ -0,0 +1,1514 @@
1
+ const require_truncation = require("./truncation.cjs");
2
+ let _langchain_core_messages = require("@langchain/core/messages");
3
+ let node_util_types = require("node:util/types");
4
+ //#region src/utils/toolContent.ts
5
+ const ATOMIC_CONTENT_TYPES = new Set([
6
+ "audio",
7
+ "computer_screenshot",
8
+ "document",
9
+ "file",
10
+ "image",
11
+ "image_file",
12
+ "image_url",
13
+ "input_audio",
14
+ "input_image",
15
+ "media",
16
+ "resource",
17
+ "resource_link",
18
+ "video",
19
+ "video_url"
20
+ ]);
21
+ const MAX_TOOL_CONTENT_TYPE_CHARS = 256;
22
+ const MAX_PROVIDER_IMAGE_URL_CHARS = 16384;
23
+ const MAX_PROVIDER_FILE_ID_CHARS = 4096;
24
+ const PROVIDER_NATIVE_TOOL_RESULT_TYPES = new Set([
25
+ "search_result",
26
+ "server_tool_call_result",
27
+ "tool_result",
28
+ "toolResponse",
29
+ "web_search_result",
30
+ "web_search_tool_result"
31
+ ]);
32
+ const SERIALIZATION_CHUNK_SIZE = 4096;
33
+ const MAX_STRUCTURED_SERIALIZATION_DEPTH = 200;
34
+ const MAX_STRUCTURED_SERIALIZATION_WORK = 1e6;
35
+ const MAX_STRUCTURED_CHARACTER_WORK = 1e6;
36
+ const MAX_STRUCTURED_PROPERTY_CACHE_ENTRIES = 1e4;
37
+ const PROXY_VALUE_PLACEHOLDER = "[Proxy value omitted]";
38
+ const CHARACTER_WORK_PLACEHOLDER = "[truncated: character traversal limit exceeded]";
39
+ function createStructuredWorkState() {
40
+ return {
41
+ remaining: MAX_STRUCTURED_SERIALIZATION_WORK,
42
+ characterRemaining: MAX_STRUCTURED_CHARACTER_WORK,
43
+ exceeded: false,
44
+ propertyCache: /* @__PURE__ */ new WeakMap(),
45
+ propertyCacheEntries: 0
46
+ };
47
+ }
48
+ function consumeStructuredWork(state) {
49
+ if (state.remaining <= 0) {
50
+ state.exceeded = true;
51
+ state.failurePlaceholder ??= "[Traversal limit exceeded]";
52
+ return false;
53
+ }
54
+ state.remaining--;
55
+ return true;
56
+ }
57
+ function consumeStructuredCharacterWork(state) {
58
+ if (state.characterRemaining <= 0) {
59
+ state.exceeded = true;
60
+ state.failurePlaceholder ??= CHARACTER_WORK_PLACEHOLDER;
61
+ return false;
62
+ }
63
+ state.characterRemaining--;
64
+ return true;
65
+ }
66
+ function hasExceededStructuredWork(state) {
67
+ return state.exceeded;
68
+ }
69
+ function conservativeStructuredLength(limit) {
70
+ return limit >= Number.MAX_SAFE_INTEGER ? Number.MAX_SAFE_INTEGER : limit + 1;
71
+ }
72
+ function jsonStringLength(value, limit, work) {
73
+ let length = 2;
74
+ for (let i = 0; i < value.length; i++) {
75
+ if (!consumeStructuredCharacterWork(work)) return conservativeStructuredLength(limit);
76
+ const code = value.charCodeAt(i);
77
+ if (code === 8 || code === 9 || code === 10 || code === 12 || code === 13 || code === 34 || code === 92) length += 2;
78
+ else if (code < 32) length += 6;
79
+ else if (code >= 55296 && code <= 56319) {
80
+ if (!consumeStructuredCharacterWork(work)) return conservativeStructuredLength(limit);
81
+ const next = value.charCodeAt(i + 1);
82
+ if (next >= 56320 && next <= 57343) {
83
+ length += 2;
84
+ i++;
85
+ } else length += 6;
86
+ } else if (code >= 56320 && code <= 57343) length += 6;
87
+ else length++;
88
+ if (length > limit) return conservativeStructuredLength(limit);
89
+ }
90
+ return length;
91
+ }
92
+ function readNativeArrayBufferByteLength(value) {
93
+ if (value == null || typeof value !== "object" || NATIVE_ARRAY_BUFFER_BYTE_LENGTH_GETTER == null) return;
94
+ try {
95
+ return NATIVE_ARRAY_BUFFER_BYTE_LENGTH_GETTER.call(value);
96
+ } catch {
97
+ return;
98
+ }
99
+ }
100
+ function readNativeDate(value) {
101
+ if (value == null || typeof value !== "object") return { matched: false };
102
+ try {
103
+ return {
104
+ matched: true,
105
+ time: NATIVE_DATE_GET_TIME.call(value)
106
+ };
107
+ } catch {
108
+ return { matched: false };
109
+ }
110
+ }
111
+ function readNativeBoxedString(value) {
112
+ try {
113
+ return String.prototype.valueOf.call(value);
114
+ } catch {
115
+ return;
116
+ }
117
+ }
118
+ function readNativeBoxedNumber(value) {
119
+ try {
120
+ return Number.prototype.valueOf.call(value);
121
+ } catch {
122
+ return;
123
+ }
124
+ }
125
+ function readNativeBoxedBoolean(value) {
126
+ try {
127
+ return Boolean.prototype.valueOf.call(value);
128
+ } catch {
129
+ return;
130
+ }
131
+ }
132
+ function estimateStructuredChars(value, limit = Number.MAX_SAFE_INTEGER, ancestors = [], work = createStructuredWorkState(), depth = 0) {
133
+ if (hasExceededStructuredWork(work)) return conservativeStructuredLength(limit);
134
+ if (typeof value === "string") return jsonStringLength(value, limit, work);
135
+ if (typeof value === "bigint") return jsonStringLength(value.toString(), limit, work);
136
+ if (typeof value === "number") return Number.isFinite(value) ? String(value === 0 ? 0 : value).length : 4;
137
+ if (typeof value === "boolean" || value == null) return String(value).length;
138
+ if ((0, node_util_types.isProxy)(value)) {
139
+ work.exceeded = true;
140
+ work.failurePlaceholder = PROXY_VALUE_PLACEHOLDER;
141
+ return conservativeStructuredLength(limit);
142
+ }
143
+ if (typeof value === "undefined" || typeof value === "function") return 4;
144
+ if (typeof value !== "object") return jsonStringLength(String(value), limit, work);
145
+ const valueIsArray = isArray(value);
146
+ if (!valueIsArray) {
147
+ const arrayBufferByteLength = readNativeArrayBufferByteLength(value);
148
+ if (arrayBufferByteLength != null) {
149
+ if (!isSafeNativeArrayBuffer(value)) {
150
+ work.exceeded = true;
151
+ return conservativeStructuredLength(limit);
152
+ }
153
+ return Math.min(limit + 1, Math.ceil(arrayBufferByteLength * 4 / 3) + 32);
154
+ }
155
+ if (ArrayBuffer.isView(value)) {
156
+ const view = readSafeNativeArrayBufferView(value, void 0, void 0, false);
157
+ if (view == null) {
158
+ work.exceeded = true;
159
+ return conservativeStructuredLength(limit);
160
+ }
161
+ return Math.min(limit + 1, Math.ceil(view.byteLength * 4 / 3) + 32);
162
+ }
163
+ const date = readNativeDate(value);
164
+ if (date.matched) {
165
+ if (!isSafeNativeDate(value)) {
166
+ work.exceeded = true;
167
+ return conservativeStructuredLength(limit);
168
+ }
169
+ return Number.isFinite(date.time) ? jsonStringLength(Date.prototype.toISOString.call(value), limit, work) : 4;
170
+ }
171
+ const boxedString = readNativeBoxedString(value);
172
+ if (boxedString != null) return jsonStringLength(boxedString, limit, work);
173
+ const boxedNumber = readNativeBoxedNumber(value);
174
+ if (boxedNumber != null) return Number.isFinite(boxedNumber) ? String(boxedNumber === 0 ? 0 : boxedNumber).length : 4;
175
+ const boxedBoolean = readNativeBoxedBoolean(value);
176
+ if (boxedBoolean != null) return String(boxedBoolean).length;
177
+ let prototype;
178
+ try {
179
+ prototype = Object.getPrototypeOf(value);
180
+ } catch {
181
+ work.exceeded = true;
182
+ return conservativeStructuredLength(limit);
183
+ }
184
+ if ((0, node_util_types.isProxy)(prototype) || prototype !== Object.prototype && prototype !== null) {
185
+ work.exceeded = true;
186
+ return conservativeStructuredLength(limit);
187
+ }
188
+ } else {
189
+ let prototype;
190
+ try {
191
+ prototype = Object.getPrototypeOf(value);
192
+ } catch {
193
+ work.exceeded = true;
194
+ return conservativeStructuredLength(limit);
195
+ }
196
+ if ((0, node_util_types.isProxy)(prototype) || prototype !== Array.prototype && prototype !== null) {
197
+ work.exceeded = true;
198
+ return conservativeStructuredLength(limit);
199
+ }
200
+ }
201
+ if (depth >= MAX_STRUCTURED_SERIALIZATION_DEPTH) return jsonStringLength("[Max serialization depth]", limit, work);
202
+ if (ancestors.includes(value)) return 12;
203
+ ancestors.push(value);
204
+ let length = 2;
205
+ try {
206
+ if (valueIsArray) {
207
+ const arrayLength = readStructuredArrayLength(value, work);
208
+ if (arrayLength == null) return conservativeStructuredLength(limit);
209
+ for (let i = 0; i < arrayLength && length <= limit; i++) {
210
+ if (!consumeStructuredWork(work)) return conservativeStructuredLength(limit);
211
+ if (i > 0) length++;
212
+ length += estimateStructuredChars(readStructuredProperty(value, i, work), Math.max(0, limit - length), ancestors, work, depth + 1);
213
+ }
214
+ } else {
215
+ let emitted = 0;
216
+ for (const key in value) {
217
+ if (!consumeStructuredWork(work)) return conservativeStructuredLength(limit);
218
+ if (!Object.prototype.propertyIsEnumerable.call(value, key)) continue;
219
+ if (length > limit) break;
220
+ const nested = readStructuredProperty(value, key, work);
221
+ if (typeof nested === "undefined" || typeof nested === "function" || typeof nested === "symbol") continue;
222
+ if (emitted > 0) length++;
223
+ length += jsonStringLength(key, Math.max(0, limit - length), work) + 1;
224
+ length += estimateStructuredChars(nested, Math.max(0, limit - length), ancestors, work, depth + 1);
225
+ emitted++;
226
+ }
227
+ }
228
+ } catch {
229
+ work.exceeded = true;
230
+ return conservativeStructuredLength(limit);
231
+ } finally {
232
+ ancestors.pop();
233
+ }
234
+ if (hasExceededStructuredWork(work)) return conservativeStructuredLength(limit);
235
+ return Math.min(limit + 1, length);
236
+ }
237
+ function normalizeCharLimit(limit) {
238
+ return Number.isFinite(limit) ? Math.max(0, Math.floor(limit)) : Number.MAX_SAFE_INTEGER;
239
+ }
240
+ function createSegmentedStringBuffer() {
241
+ return {
242
+ segments: [],
243
+ head: 0,
244
+ pending: [],
245
+ pendingChars: 0,
246
+ length: 0
247
+ };
248
+ }
249
+ function flushSegmentedStringBuffer(buffer) {
250
+ if (buffer.pendingChars === 0) return;
251
+ buffer.segments.push(buffer.pending.join(""));
252
+ buffer.pending = [];
253
+ buffer.pendingChars = 0;
254
+ }
255
+ function appendToSegmentedStringBuffer(buffer, chunk) {
256
+ if (chunk.length === 0) return;
257
+ buffer.pending.push(chunk);
258
+ buffer.pendingChars += chunk.length;
259
+ buffer.length += chunk.length;
260
+ if (buffer.pendingChars >= SERIALIZATION_CHUNK_SIZE) flushSegmentedStringBuffer(buffer);
261
+ }
262
+ function trimSegmentedStringBufferStart(buffer, chars) {
263
+ let remaining = Math.min(chars, buffer.length);
264
+ if (remaining <= 0) return;
265
+ flushSegmentedStringBuffer(buffer);
266
+ while (remaining > 0 && buffer.head < buffer.segments.length) {
267
+ const segment = buffer.segments[buffer.head];
268
+ if (segment.length <= remaining) {
269
+ remaining -= segment.length;
270
+ buffer.length -= segment.length;
271
+ buffer.head++;
272
+ } else {
273
+ buffer.segments[buffer.head] = segment.slice(remaining);
274
+ buffer.length -= remaining;
275
+ remaining = 0;
276
+ }
277
+ }
278
+ if (buffer.head >= 1024 && buffer.head * 2 >= buffer.segments.length) {
279
+ buffer.segments = buffer.segments.slice(buffer.head);
280
+ buffer.head = 0;
281
+ }
282
+ }
283
+ function materializeSegmentedStringBuffer(buffer) {
284
+ const segments = buffer.segments.slice(buffer.head);
285
+ if (buffer.pendingChars > 0) segments.push(buffer.pending.join(""));
286
+ return segments.join("");
287
+ }
288
+ function appendSerializedChunk(collector, chunk) {
289
+ if (chunk.length === 0) return;
290
+ collector.totalChars += chunk.length;
291
+ const prefixRemaining = collector.prefixLimit - collector.prefix.length;
292
+ if (prefixRemaining > 0) appendToSegmentedStringBuffer(collector.prefix, chunk.slice(0, prefixRemaining));
293
+ if (collector.suffixLimit <= 0) return;
294
+ appendToSegmentedStringBuffer(collector.suffix, chunk);
295
+ if (collector.suffix.length >= collector.suffixLimit + SERIALIZATION_CHUNK_SIZE) trimSegmentedStringBufferStart(collector.suffix, collector.suffix.length - collector.suffixLimit);
296
+ }
297
+ function appendJsonSafeRange(collector, value, start, end) {
298
+ let offset = start;
299
+ while (offset < end) {
300
+ let chunkEnd = Math.min(end, offset + SERIALIZATION_CHUNK_SIZE);
301
+ if (chunkEnd < end && chunkEnd > offset && value.charCodeAt(chunkEnd - 1) >= 55296 && value.charCodeAt(chunkEnd - 1) <= 56319 && value.charCodeAt(chunkEnd) >= 56320 && value.charCodeAt(chunkEnd) <= 57343) chunkEnd--;
302
+ appendSerializedChunk(collector, value.slice(offset, chunkEnd));
303
+ offset = chunkEnd;
304
+ }
305
+ }
306
+ /**
307
+ * Emits one JSON string incrementally. Calling JSON.stringify on the complete
308
+ * string would allocate an escaped copy before the output cap could apply.
309
+ */
310
+ function appendJsonString(collector, value) {
311
+ if (collector.work.exceeded) {
312
+ appendSerializedChunk(collector, `"${collector.work.failurePlaceholder ?? CHARACTER_WORK_PLACEHOLDER}"`);
313
+ return;
314
+ }
315
+ appendSerializedChunk(collector, "\"");
316
+ let safeStart = 0;
317
+ for (let i = 0; i < value.length; i++) {
318
+ if (!consumeStructuredCharacterWork(collector.work)) {
319
+ appendJsonSafeRange(collector, value, safeStart, i);
320
+ appendSerializedChunk(collector, `${CHARACTER_WORK_PLACEHOLDER}"`);
321
+ return;
322
+ }
323
+ const code = value.charCodeAt(i);
324
+ let escaped;
325
+ switch (code) {
326
+ case 8:
327
+ escaped = "\\b";
328
+ break;
329
+ case 9:
330
+ escaped = "\\t";
331
+ break;
332
+ case 10:
333
+ escaped = "\\n";
334
+ break;
335
+ case 12:
336
+ escaped = "\\f";
337
+ break;
338
+ case 13:
339
+ escaped = "\\r";
340
+ break;
341
+ case 34:
342
+ escaped = "\\\"";
343
+ break;
344
+ case 92:
345
+ escaped = "\\\\";
346
+ break;
347
+ default: if (code < 32) escaped = `\\u${code.toString(16).padStart(4, "0")}`;
348
+ else if (code >= 55296 && code <= 56319) {
349
+ if (!consumeStructuredCharacterWork(collector.work)) {
350
+ appendJsonSafeRange(collector, value, safeStart, i);
351
+ appendSerializedChunk(collector, `${CHARACTER_WORK_PLACEHOLDER}"`);
352
+ return;
353
+ }
354
+ const next = value.charCodeAt(i + 1);
355
+ if (next >= 56320 && next <= 57343) i++;
356
+ else escaped = `\\u${code.toString(16).padStart(4, "0")}`;
357
+ } else if (code >= 56320 && code <= 57343) escaped = `\\u${code.toString(16).padStart(4, "0")}`;
358
+ }
359
+ if (escaped != null) {
360
+ appendJsonSafeRange(collector, value, safeStart, i);
361
+ appendSerializedChunk(collector, escaped);
362
+ safeStart = i + 1;
363
+ }
364
+ }
365
+ appendJsonSafeRange(collector, value, safeStart, value.length);
366
+ appendSerializedChunk(collector, "\"");
367
+ }
368
+ function readStructuredProperty(value, key, work) {
369
+ const normalizedKey = String(key);
370
+ const cachedProperties = work.propertyCache.get(value);
371
+ if (cachedProperties != null && cachedProperties.has(normalizedKey)) return cachedProperties.get(normalizedKey);
372
+ try {
373
+ const descriptor = Object.getOwnPropertyDescriptor(value, normalizedKey);
374
+ let propertyValue;
375
+ if (descriptor == null) propertyValue = void 0;
376
+ else if ("value" in descriptor) propertyValue = descriptor.value;
377
+ else propertyValue = "[Property accessor omitted]";
378
+ if (work.propertyCacheEntries < MAX_STRUCTURED_PROPERTY_CACHE_ENTRIES) {
379
+ const properties = cachedProperties ?? /* @__PURE__ */ new Map();
380
+ if (cachedProperties == null) work.propertyCache.set(value, properties);
381
+ properties.set(normalizedKey, propertyValue);
382
+ work.propertyCacheEntries++;
383
+ }
384
+ return propertyValue;
385
+ } catch {
386
+ work.exceeded = true;
387
+ work.remaining = 0;
388
+ return "[Unreadable property omitted]";
389
+ }
390
+ }
391
+ function readStructuredArrayLength(value, work) {
392
+ const length = readStructuredProperty(value, "length", work);
393
+ if (typeof length === "number" && Number.isSafeInteger(length) && length >= 0) return length;
394
+ work.exceeded = true;
395
+ work.remaining = 0;
396
+ }
397
+ /**
398
+ * Provider-neutral JSON writer which deliberately does not invoke `toJSON` or
399
+ * property accessors. Native `JSON.stringify` can invoke both before a replacer
400
+ * can bound their output.
401
+ */
402
+ function appendStructuredValue(collector, value, ancestors, depth, position) {
403
+ if (collector.work.exceeded) {
404
+ appendSerializedChunk(collector, `"${collector.work.failurePlaceholder ?? CHARACTER_WORK_PLACEHOLDER}"`);
405
+ return true;
406
+ }
407
+ if (typeof value === "string") {
408
+ appendJsonString(collector, value);
409
+ return true;
410
+ }
411
+ if (typeof value === "bigint") {
412
+ appendJsonString(collector, value.toString());
413
+ return true;
414
+ }
415
+ if (typeof value === "number") {
416
+ appendSerializedChunk(collector, Number.isFinite(value) ? String(value === 0 ? 0 : value) : "null");
417
+ return true;
418
+ }
419
+ if (typeof value === "boolean" || value === null) {
420
+ appendSerializedChunk(collector, String(value));
421
+ return true;
422
+ }
423
+ if ((0, node_util_types.isProxy)(value)) {
424
+ appendSerializedChunk(collector, `"${PROXY_VALUE_PLACEHOLDER}"`);
425
+ collector.work.exceeded = true;
426
+ collector.work.failurePlaceholder = PROXY_VALUE_PLACEHOLDER;
427
+ return true;
428
+ }
429
+ if (typeof value === "undefined" || typeof value === "function" || typeof value === "symbol") {
430
+ if (position === "object") return false;
431
+ if (position === "array") appendSerializedChunk(collector, "null");
432
+ else if (typeof value === "undefined") appendSerializedChunk(collector, "undefined");
433
+ else appendJsonString(collector, typeof value === "function" ? "[Function]" : String(value));
434
+ return true;
435
+ }
436
+ const valueIsArray = isArray(value);
437
+ if (!valueIsArray) {
438
+ const arrayBufferByteLength = readNativeArrayBufferByteLength(value);
439
+ if (arrayBufferByteLength != null) {
440
+ if (!isSafeNativeArrayBuffer(value)) {
441
+ appendSerializedChunk(collector, "\"[Unsafe ArrayBuffer omitted]\"");
442
+ collector.work.exceeded = true;
443
+ return true;
444
+ }
445
+ appendJsonString(collector, `[ArrayBuffer: ${arrayBufferByteLength} bytes]`);
446
+ return true;
447
+ }
448
+ if (ArrayBuffer.isView(value)) {
449
+ const view = readSafeNativeArrayBufferView(value, void 0, void 0, false);
450
+ if (view == null) {
451
+ appendSerializedChunk(collector, "\"[Unsafe ArrayBufferView omitted]\"");
452
+ collector.work.exceeded = true;
453
+ return true;
454
+ }
455
+ appendJsonString(collector, `[${view.name}: ${view.byteLength} bytes]`);
456
+ return true;
457
+ }
458
+ const date = readNativeDate(value);
459
+ if (date.matched) {
460
+ if (!isSafeNativeDate(value)) {
461
+ appendSerializedChunk(collector, "\"[Unsafe Date omitted]\"");
462
+ collector.work.exceeded = true;
463
+ } else if (!Number.isFinite(date.time)) appendSerializedChunk(collector, "null");
464
+ else appendJsonString(collector, Date.prototype.toISOString.call(value));
465
+ return true;
466
+ }
467
+ const boxedString = readNativeBoxedString(value);
468
+ if (boxedString != null) {
469
+ appendJsonString(collector, boxedString);
470
+ return true;
471
+ }
472
+ const boxedNumber = readNativeBoxedNumber(value);
473
+ if (boxedNumber != null) {
474
+ appendSerializedChunk(collector, Number.isFinite(boxedNumber) ? String(boxedNumber === 0 ? 0 : boxedNumber) : "null");
475
+ return true;
476
+ }
477
+ const boxedBoolean = readNativeBoxedBoolean(value);
478
+ if (boxedBoolean != null) {
479
+ appendSerializedChunk(collector, String(boxedBoolean));
480
+ return true;
481
+ }
482
+ let prototype;
483
+ try {
484
+ prototype = Object.getPrototypeOf(value);
485
+ } catch {
486
+ appendSerializedChunk(collector, "\"[Unreadable object omitted]\"");
487
+ collector.work.exceeded = true;
488
+ return true;
489
+ }
490
+ if ((0, node_util_types.isProxy)(prototype) || prototype !== Object.prototype && prototype !== null) {
491
+ appendSerializedChunk(collector, "\"[Unsupported object omitted]\"");
492
+ collector.work.exceeded = true;
493
+ return true;
494
+ }
495
+ } else {
496
+ let prototype;
497
+ try {
498
+ prototype = Object.getPrototypeOf(value);
499
+ } catch {
500
+ appendSerializedChunk(collector, "\"[Unreadable array omitted]\"");
501
+ collector.work.exceeded = true;
502
+ return true;
503
+ }
504
+ if ((0, node_util_types.isProxy)(prototype) || prototype !== Array.prototype && prototype !== null) {
505
+ appendSerializedChunk(collector, "\"[Unsafe array omitted]\"");
506
+ collector.work.exceeded = true;
507
+ return true;
508
+ }
509
+ }
510
+ if (depth >= MAX_STRUCTURED_SERIALIZATION_DEPTH) {
511
+ appendJsonString(collector, "[Max serialization depth]");
512
+ return true;
513
+ }
514
+ if (ancestors.has(value)) {
515
+ appendJsonString(collector, "[Circular]");
516
+ return true;
517
+ }
518
+ ancestors.add(value);
519
+ try {
520
+ if (valueIsArray) {
521
+ const arrayLength = readStructuredArrayLength(value, collector.work);
522
+ if (arrayLength == null) {
523
+ appendJsonString(collector, "[Unreadable array omitted]");
524
+ return true;
525
+ }
526
+ appendSerializedChunk(collector, "[");
527
+ for (let i = 0; i < arrayLength; i++) {
528
+ if (!consumeStructuredWork(collector.work)) {
529
+ if (i > 0) appendSerializedChunk(collector, ",");
530
+ appendJsonString(collector, `[Traversal limit exceeded: ${arrayLength - i} array entries omitted]`);
531
+ break;
532
+ }
533
+ if (i > 0) appendSerializedChunk(collector, ",");
534
+ appendStructuredValue(collector, readStructuredProperty(value, i, collector.work), ancestors, depth + 1, "array");
535
+ }
536
+ appendSerializedChunk(collector, "]");
537
+ return true;
538
+ }
539
+ appendSerializedChunk(collector, "{");
540
+ let emitted = 0;
541
+ for (const key in value) {
542
+ if (!consumeStructuredWork(collector.work)) {
543
+ if (emitted > 0) appendSerializedChunk(collector, ",");
544
+ appendSerializedChunk(collector, "\"_truncated\":\"[Traversal limit exceeded]\"");
545
+ break;
546
+ }
547
+ if (!Object.prototype.propertyIsEnumerable.call(value, key)) continue;
548
+ const nested = readStructuredProperty(value, key, collector.work);
549
+ if (typeof nested === "undefined" || typeof nested === "function" || typeof nested === "symbol") continue;
550
+ if (emitted > 0) appendSerializedChunk(collector, ",");
551
+ appendJsonString(collector, key);
552
+ appendSerializedChunk(collector, ":");
553
+ appendStructuredValue(collector, nested, ancestors, depth + 1, "object");
554
+ emitted++;
555
+ }
556
+ appendSerializedChunk(collector, "}");
557
+ return true;
558
+ } finally {
559
+ ancestors.delete(value);
560
+ }
561
+ }
562
+ function formatBoundedStructuredContent(collector, maxChars, prefix, suffix) {
563
+ if (collector.totalChars <= maxChars) return prefix.slice(0, collector.totalChars);
564
+ const indicator = collector.work.exceeded ? "\n\n… [truncated: safe traversal limit exceeded] …\n\n" : `\n\n… [truncated: ${collector.totalChars} chars exceeded ${maxChars} limit] …\n\n`;
565
+ const available = maxChars - indicator.length;
566
+ if (available <= 0) return prefix.slice(0, maxChars);
567
+ if (available < 200) return prefix.slice(0, available) + indicator.trimEnd();
568
+ const headSize = Math.ceil(available * .7);
569
+ const tailSize = available - headSize;
570
+ let headEnd = headSize;
571
+ const headNewline = prefix.lastIndexOf("\n", headSize);
572
+ if (headNewline > headSize - 200 && headNewline > 0) headEnd = headNewline;
573
+ let tailStart = Math.max(0, suffix.length - tailSize);
574
+ const tailNewline = suffix.indexOf("\n", tailStart);
575
+ if (tailNewline > 0 && tailNewline < tailStart + 200) tailStart = tailNewline + 1;
576
+ return prefix.slice(0, headEnd) + indicator + suffix.slice(tailStart);
577
+ }
578
+ /**
579
+ * Serializes structured output while retaining at most the requested provider
580
+ * preview and registry prefix. The traversal never calls `toJSON` and never
581
+ * materializes the complete serialized string when it exceeds those limits.
582
+ *
583
+ * `prefixChars` is useful for the tool-output registry: it receives the exact
584
+ * serialized prefix up to `registry.perOutputLimit`, while `content` retains
585
+ * the provider-facing head/tail truncation behavior at `maxChars`. Property
586
+ * accessors are represented by a fixed placeholder instead of being invoked.
587
+ */
588
+ function serializeStructuredValueBounded(value, maxChars, prefixChars = 0, work = createStructuredWorkState()) {
589
+ const normalizedMaxChars = normalizeCharLimit(maxChars);
590
+ const normalizedPrefixChars = normalizeCharLimit(prefixChars);
591
+ const prefixLimit = Math.max(normalizedMaxChars, normalizedPrefixChars);
592
+ const collector = {
593
+ totalChars: 0,
594
+ prefix: createSegmentedStringBuffer(),
595
+ suffix: createSegmentedStringBuffer(),
596
+ prefixLimit,
597
+ suffixLimit: normalizedMaxChars === Number.MAX_SAFE_INTEGER ? 0 : normalizedMaxChars,
598
+ work
599
+ };
600
+ try {
601
+ appendStructuredValue(collector, value, /* @__PURE__ */ new Set(), 0, "top");
602
+ } catch {
603
+ collector.totalChars = 0;
604
+ collector.prefix = createSegmentedStringBuffer();
605
+ collector.suffix = createSegmentedStringBuffer();
606
+ collector.work.exceeded = true;
607
+ appendSerializedChunk(collector, "\"[Unserializable structured value]\"");
608
+ }
609
+ const prefix = materializeSegmentedStringBuffer(collector.prefix);
610
+ const suffix = materializeSegmentedStringBuffer(collector.suffix);
611
+ const originalChars = collector.work.exceeded ? Number.MAX_SAFE_INTEGER : collector.totalChars;
612
+ return {
613
+ content: formatBoundedStructuredContent(collector, normalizedMaxChars, prefix, suffix),
614
+ prefix: prefix.slice(0, normalizedPrefixChars),
615
+ originalChars,
616
+ truncated: collector.work.exceeded || collector.totalChars > normalizedMaxChars
617
+ };
618
+ }
619
+ function serializeStructuredValueWithinLimit(value, maxChars, work = createStructuredWorkState()) {
620
+ return serializeStructuredValueBounded(value, maxChars, 0, work).content;
621
+ }
622
+ function isTextBlockUnchecked(value) {
623
+ if (!isRecord(value) || (0, node_util_types.isProxy)(value)) return false;
624
+ try {
625
+ const prototype = Object.getPrototypeOf(value);
626
+ if (prototype !== Object.prototype && prototype !== null) return false;
627
+ const keys = Object.keys(value);
628
+ if (keys.length !== 2 || !keys.includes("type") || !keys.includes("text")) return false;
629
+ const type = readOwnEnumerableDataProperty(value, "type");
630
+ const text = readOwnEnumerableDataProperty(value, "text");
631
+ return type.found && type.value === "text" && text.found && typeof text.value === "string";
632
+ } catch {
633
+ return false;
634
+ }
635
+ }
636
+ function isArray(value) {
637
+ try {
638
+ return Array.isArray(value);
639
+ } catch {
640
+ return false;
641
+ }
642
+ }
643
+ function getDenseTextBlockArrayLength(content) {
644
+ if ((0, node_util_types.isProxy)(content)) return;
645
+ const validation = createToolBlockClassificationContext();
646
+ const containerWork = { value: MAX_ATOMIC_VALIDATION_WORK };
647
+ let contentLength;
648
+ try {
649
+ const prototype = Object.getPrototypeOf(content);
650
+ if (prototype !== Array.prototype && prototype !== null || hasPotentiallyCallableToJSON(content, containerWork, validation.totalRemaining)) return;
651
+ contentLength = content.length;
652
+ } catch {
653
+ return;
654
+ }
655
+ if (contentLength === 0 || contentLength > MAX_STRUCTURED_SERIALIZATION_WORK) return;
656
+ let length = contentLength - 1;
657
+ try {
658
+ for (let i = 0; i < contentLength; i++) {
659
+ const descriptor = Object.getOwnPropertyDescriptor(content, String(i));
660
+ if (descriptor == null || !("value" in descriptor)) return;
661
+ const block = descriptor.value;
662
+ if (classifyToolContentBlock(block, validation) !== TOOL_BLOCK_TEXT || validation.totalRemaining.value <= 0) return;
663
+ const text = readOwnEnumerableDataProperty(block, "text");
664
+ length += typeof text.value === "string" ? text.value.length : 0;
665
+ if (length >= Number.MAX_SAFE_INTEGER) return Number.MAX_SAFE_INTEGER;
666
+ }
667
+ } catch {
668
+ return;
669
+ }
670
+ return length;
671
+ }
672
+ function isRecord(value) {
673
+ return typeof value === "object" && value != null;
674
+ }
675
+ function readOwnEnumerableDataProperty(record, key) {
676
+ try {
677
+ const descriptor = Object.getOwnPropertyDescriptor(record, key);
678
+ if (descriptor == null || descriptor.enumerable !== true || !("value" in descriptor)) return { found: false };
679
+ return {
680
+ found: true,
681
+ value: descriptor.value
682
+ };
683
+ } catch {
684
+ return { found: false };
685
+ }
686
+ }
687
+ function hasString(record, key) {
688
+ const property = readOwnEnumerableDataProperty(record, key);
689
+ return property.found && typeof property.value === "string" && property.value !== "";
690
+ }
691
+ function hasValue(record, key) {
692
+ const property = readOwnEnumerableDataProperty(record, key);
693
+ return property.found && property.value !== void 0;
694
+ }
695
+ function isStringPayload(value) {
696
+ return typeof value === "string" && value.length > 0;
697
+ }
698
+ function isBinaryPayload(value) {
699
+ if (typeof value === "string") return value.length > 0;
700
+ if (isArray(value)) return false;
701
+ const arrayBufferByteLength = readNativeArrayBufferByteLength(value);
702
+ if (arrayBufferByteLength != null) return isSafeNativeArrayBuffer(value) && arrayBufferByteLength > 0;
703
+ if (ArrayBuffer.isView(value)) {
704
+ const view = readSafeNativeArrayBufferView(value);
705
+ return view != null && view.byteLength > 0;
706
+ }
707
+ return false;
708
+ }
709
+ function isContentPayload(value) {
710
+ return isArray(value) && value.length > 0;
711
+ }
712
+ function hasPayloadPath(record, path, validator = isBinaryPayload) {
713
+ let value = record;
714
+ for (const key of path) {
715
+ if (!isRecord(value)) return false;
716
+ const property = readOwnEnumerableDataProperty(value, key);
717
+ if (!property.found) return false;
718
+ value = property.value;
719
+ }
720
+ return validator(value);
721
+ }
722
+ function hasAnyPayloadPath(record, paths, validator = isBinaryPayload) {
723
+ return paths.some((path) => hasPayloadPath(record, path, validator));
724
+ }
725
+ function isProviderNativeToolResultBlock(record, type) {
726
+ if (type === "search_result") return hasString(record, "title") && hasString(record, "source") && hasPayloadPath(record, ["content"], isArray);
727
+ if (type === "web_search_result") return hasString(record, "url");
728
+ if (type === "web_search_tool_result") {
729
+ const content = readOwnEnumerableDataProperty(record, "content");
730
+ return hasString(record, "tool_use_id") && content.found && (isArray(content.value) || isRecord(content.value));
731
+ }
732
+ if (type === "tool_result") return hasString(record, "tool_use_id");
733
+ if (type === "server_tool_call_result") {
734
+ const status = readOwnEnumerableDataProperty(record, "status");
735
+ return hasString(record, "toolCallId") && status.found && (status.value === "success" || status.value === "error") && hasValue(record, "output");
736
+ }
737
+ if (type === "toolResponse") {
738
+ const response = readOwnEnumerableDataProperty(record, "toolResponse");
739
+ return response.found && isRecord(response.value);
740
+ }
741
+ return false;
742
+ }
743
+ const MAX_ATOMIC_VALIDATION_WORK = 1e4;
744
+ const MAX_ATOMIC_VALIDATION_DEPTH = 50;
745
+ const NATIVE_ARRAY_BUFFER_BYTE_LENGTH_GETTER = Object.getOwnPropertyDescriptor(ArrayBuffer.prototype, "byteLength")?.get;
746
+ const NATIVE_TYPED_ARRAY_PROTOTYPE = Object.getPrototypeOf(Uint8Array.prototype);
747
+ const NATIVE_TYPED_ARRAY_BYTE_LENGTH_GETTER = Object.getOwnPropertyDescriptor(NATIVE_TYPED_ARRAY_PROTOTYPE, "byteLength")?.get;
748
+ const NATIVE_DATA_VIEW_BYTE_LENGTH_GETTER = Object.getOwnPropertyDescriptor(DataView.prototype, "byteLength")?.get;
749
+ const NATIVE_ARRAY_BUFFER_VIEW_NAMES = new Map([
750
+ [Buffer.prototype, "Buffer"],
751
+ [DataView.prototype, "DataView"],
752
+ [Int8Array.prototype, "Int8Array"],
753
+ [Uint8Array.prototype, "Uint8Array"],
754
+ [Uint8ClampedArray.prototype, "Uint8ClampedArray"],
755
+ [Int16Array.prototype, "Int16Array"],
756
+ [Uint16Array.prototype, "Uint16Array"],
757
+ [Int32Array.prototype, "Int32Array"],
758
+ [Uint32Array.prototype, "Uint32Array"],
759
+ [Float32Array.prototype, "Float32Array"],
760
+ [Float64Array.prototype, "Float64Array"],
761
+ [BigInt64Array.prototype, "BigInt64Array"],
762
+ [BigUint64Array.prototype, "BigUint64Array"]
763
+ ]);
764
+ const NATIVE_DATE_GET_TIME = Date.prototype.getTime;
765
+ const NATIVE_DATE_TO_JSON = Date.prototype.toJSON;
766
+ const NATIVE_DATE_TO_ISO_STRING = Date.prototype.toISOString;
767
+ const NATIVE_DATE_VALUE_OF = Date.prototype.valueOf;
768
+ const NATIVE_DATE_TO_STRING = Date.prototype.toString;
769
+ const NATIVE_DATE_TO_PRIMITIVE = Date.prototype[Symbol.toPrimitive];
770
+ const NATIVE_DATE_PROTOTYPE_METHODS = [
771
+ ["getTime", NATIVE_DATE_GET_TIME],
772
+ ["toJSON", NATIVE_DATE_TO_JSON],
773
+ ["toISOString", NATIVE_DATE_TO_ISO_STRING],
774
+ ["valueOf", NATIVE_DATE_VALUE_OF],
775
+ ["toString", NATIVE_DATE_TO_STRING],
776
+ [Symbol.toPrimitive, NATIVE_DATE_TO_PRIMITIVE]
777
+ ];
778
+ function consumeAtomicValidationWork(remaining, totalRemaining, amount = 1) {
779
+ if (amount > remaining.value || totalRemaining != null && amount > totalRemaining.value) {
780
+ remaining.value = 0;
781
+ if (totalRemaining != null) totalRemaining.value = 0;
782
+ return false;
783
+ }
784
+ remaining.value -= amount;
785
+ if (totalRemaining != null) totalRemaining.value -= amount;
786
+ return true;
787
+ }
788
+ function hasPotentiallyCallableToJSON(value, remaining, totalRemaining) {
789
+ let current = value;
790
+ const seen = /* @__PURE__ */ new Set();
791
+ for (let depth = 0; current != null && depth < 100; depth++) {
792
+ if ((0, node_util_types.isProxy)(current)) return true;
793
+ if (remaining != null && !consumeAtomicValidationWork(remaining, totalRemaining)) return true;
794
+ if (seen.has(current)) return true;
795
+ seen.add(current);
796
+ const descriptor = Object.getOwnPropertyDescriptor(current, "toJSON");
797
+ if (descriptor != null) return typeof descriptor.value === "function" || typeof descriptor.get === "function";
798
+ current = Object.getPrototypeOf(current);
799
+ }
800
+ return current != null;
801
+ }
802
+ function readSafeNativeArrayBufferView(value, remaining, totalRemaining, rejectCallableToJSON = true) {
803
+ try {
804
+ const prototype = Object.getPrototypeOf(value);
805
+ if (prototype == null || (0, node_util_types.isProxy)(prototype)) return;
806
+ const name = NATIVE_ARRAY_BUFFER_VIEW_NAMES.get(prototype);
807
+ if (name == null || Object.getOwnPropertyDescriptor(value, "byteLength") != null || Object.getOwnPropertyDescriptor(value, "constructor") != null || Object.getOwnPropertyDescriptor(value, "toJSON") != null || rejectCallableToJSON && hasPotentiallyCallableToJSON(value, remaining, totalRemaining)) return;
808
+ const getter = prototype === DataView.prototype ? NATIVE_DATA_VIEW_BYTE_LENGTH_GETTER : NATIVE_TYPED_ARRAY_BYTE_LENGTH_GETTER;
809
+ if (getter == null) return;
810
+ const byteLength = getter.call(value);
811
+ return Number.isSafeInteger(byteLength) && byteLength >= 0 ? {
812
+ byteLength,
813
+ name
814
+ } : void 0;
815
+ } catch {
816
+ return;
817
+ }
818
+ }
819
+ function isSafeNativeArrayBuffer(value, remaining, totalRemaining) {
820
+ try {
821
+ if (Object.getPrototypeOf(value) !== ArrayBuffer.prototype || NATIVE_ARRAY_BUFFER_BYTE_LENGTH_GETTER == null || Object.getOwnPropertyDescriptor(ArrayBuffer.prototype, "byteLength")?.get !== NATIVE_ARRAY_BUFFER_BYTE_LENGTH_GETTER || hasPotentiallyCallableToJSON(value, remaining, totalRemaining)) return false;
822
+ NATIVE_ARRAY_BUFFER_BYTE_LENGTH_GETTER.call(value);
823
+ for (const key in value) {
824
+ if (remaining != null && !consumeAtomicValidationWork(remaining, totalRemaining)) return false;
825
+ if (Object.prototype.propertyIsEnumerable.call(value, key)) return false;
826
+ }
827
+ return Object.getOwnPropertyDescriptor(value, "byteLength") == null;
828
+ } catch {
829
+ return false;
830
+ }
831
+ }
832
+ function isSafeNativeDate(value) {
833
+ try {
834
+ if (Object.getPrototypeOf(value) !== Date.prototype) return false;
835
+ NATIVE_DATE_GET_TIME.call(value);
836
+ for (const [key, nativeMethod] of NATIVE_DATE_PROTOTYPE_METHODS) if (Object.getOwnPropertyDescriptor(value, key) != null || Object.getOwnPropertyDescriptor(Date.prototype, key)?.value !== nativeMethod) return false;
837
+ return true;
838
+ } catch {
839
+ return false;
840
+ }
841
+ }
842
+ function hasUnsafeCallableToJSON(value, seen = /* @__PURE__ */ new Set(), remaining = { value: MAX_ATOMIC_VALIDATION_WORK }, depth = 0, totalRemaining) {
843
+ if ((0, node_util_types.isProxy)(value)) return true;
844
+ if (!isRecord(value)) return false;
845
+ if (seen.has(value) || depth >= MAX_ATOMIC_VALIDATION_DEPTH || !consumeAtomicValidationWork(remaining, totalRemaining)) return true;
846
+ const valueIsArray = isArray(value);
847
+ if (!valueIsArray) {
848
+ if (readNativeArrayBufferByteLength(value) != null) return !isSafeNativeArrayBuffer(value, remaining, totalRemaining);
849
+ if (readNativeDate(value).matched) return !isSafeNativeDate(value);
850
+ if (ArrayBuffer.isView(value)) return readSafeNativeArrayBufferView(value, remaining, totalRemaining) == null;
851
+ }
852
+ seen.add(value);
853
+ try {
854
+ if (hasPotentiallyCallableToJSON(value, remaining, totalRemaining)) return true;
855
+ if (valueIsArray) {
856
+ const prototype = Object.getPrototypeOf(value);
857
+ if (prototype !== Array.prototype && prototype !== null) return true;
858
+ const length = Object.getOwnPropertyDescriptor(value, "length")?.value;
859
+ if (typeof length !== "number" || !Number.isSafeInteger(length) || length < 0 || !consumeAtomicValidationWork(remaining, totalRemaining, length)) return true;
860
+ for (let i = 0; i < length; i++) {
861
+ const descriptor = Object.getOwnPropertyDescriptor(value, String(i));
862
+ if (descriptor == null || typeof descriptor.get === "function" || typeof descriptor.set === "function") return true;
863
+ if (hasUnsafeCallableToJSON(descriptor.value, seen, remaining, depth + 1, totalRemaining)) return true;
864
+ }
865
+ return false;
866
+ }
867
+ const prototype = Object.getPrototypeOf(value);
868
+ if (prototype !== Object.prototype && prototype !== null) return true;
869
+ for (const key in value) {
870
+ const descriptor = Object.getOwnPropertyDescriptor(value, key);
871
+ if (descriptor == null) return true;
872
+ if (descriptor.enumerable !== true) continue;
873
+ if (typeof descriptor.get === "function" || typeof descriptor.set === "function" || !consumeAtomicValidationWork(remaining, totalRemaining)) return true;
874
+ if (hasUnsafeCallableToJSON(descriptor.value, seen, remaining, depth + 1, totalRemaining)) return true;
875
+ }
876
+ return false;
877
+ } catch {
878
+ return true;
879
+ } finally {
880
+ seen.delete(value);
881
+ }
882
+ }
883
+ function isAtomicToolContentBlock(value) {
884
+ try {
885
+ return !hasUnsafeCallableToJSON(value) && isAtomicToolContentBlockUnchecked(value);
886
+ } catch {
887
+ return false;
888
+ }
889
+ }
890
+ function isAtomicToolContentBlockUnchecked(value) {
891
+ if (!isRecord(value)) return false;
892
+ const record = value;
893
+ const typeProperty = readOwnEnumerableDataProperty(record, "type");
894
+ if (!typeProperty.found) {
895
+ const cachePointProperty = readOwnEnumerableDataProperty(record, "cachePoint");
896
+ if (!cachePointProperty.found || !isRecord(cachePointProperty.value)) return false;
897
+ const cachePointType = readOwnEnumerableDataProperty(cachePointProperty.value, "type");
898
+ return cachePointType.found && cachePointType.value === "default";
899
+ }
900
+ const type = typeof typeProperty.value === "string" ? typeProperty.value : "";
901
+ if (type.length > MAX_TOOL_CONTENT_TYPE_CHARS) return false;
902
+ const slashIndex = type.indexOf("/");
903
+ const isMimeType = slashIndex > 0 && slashIndex < type.length - 1 && slashIndex === type.lastIndexOf("/");
904
+ if (!ATOMIC_CONTENT_TYPES.has(type) && !PROVIDER_NATIVE_TOOL_RESULT_TYPES.has(type) && !isMimeType) return false;
905
+ if (PROVIDER_NATIVE_TOOL_RESULT_TYPES.has(type)) return isProviderNativeToolResultBlock(record, type);
906
+ if (type === "computer_screenshot") return hasAnyPayloadPath(record, [["image_url"], ["file_id"]], isStringPayload);
907
+ if (type === "input_image") return hasAnyPayloadPath(record, [["image_url"], ["file_id"]], isStringPayload);
908
+ if (type === "image_url") return hasAnyPayloadPath(record, [["image_url"], ["image_url", "url"]], isStringPayload);
909
+ if (type === "image_file") return hasAnyPayloadPath(record, [["image_file", "file_id"], ["image_file", "fileId"]], isStringPayload);
910
+ if (type === "input_audio") return hasAnyPayloadPath(record, [["input_audio", "data"], ["input_audio", "bytes"]]);
911
+ if (type === "resource_link") return hasString(record, "uri");
912
+ if (type === "video_url") return hasAnyPayloadPath(record, [["video_url"], ["video_url", "url"]], isStringPayload);
913
+ if (type === "resource") return hasAnyPayloadPath(record, [
914
+ ["resource", "blob"],
915
+ ["resource", "bytes"],
916
+ ["resource", "data"],
917
+ ["resource", "text"]
918
+ ]) || hasPayloadPath(record, ["resource", "content"], isContentPayload);
919
+ if (isMimeType) return hasPayloadPath(record, ["data"], isStringPayload);
920
+ if (type === "image" || type === "audio" || type === "video") return hasAnyPayloadPath(record, [
921
+ ["data"],
922
+ ["bytes"],
923
+ ["url"],
924
+ ["source", "data"],
925
+ ["source", "bytes"],
926
+ ["source", "url"],
927
+ [type, "data"],
928
+ [type, "bytes"],
929
+ [type, "url"],
930
+ [
931
+ type,
932
+ "source",
933
+ "data"
934
+ ],
935
+ [
936
+ type,
937
+ "source",
938
+ "bytes"
939
+ ],
940
+ [
941
+ type,
942
+ "source",
943
+ "url"
944
+ ]
945
+ ]);
946
+ if (type === "media") return (hasString(record, "mimeType") || hasString(record, "mime_type")) && hasAnyPayloadPath(record, [
947
+ ["data"],
948
+ ["bytes"],
949
+ ["fileUri"],
950
+ ["media", "data"],
951
+ ["media", "bytes"],
952
+ ["media", "fileUri"],
953
+ [
954
+ "media",
955
+ "source",
956
+ "bytes"
957
+ ]
958
+ ]);
959
+ if (type === "document" || type === "file") {
960
+ const nestedType = type;
961
+ return hasAnyPayloadPath(record, [
962
+ ["data"],
963
+ ["bytes"],
964
+ ["url"],
965
+ ["file_data"],
966
+ ["file_id"],
967
+ ["fileId"],
968
+ ["fileUri"],
969
+ ["source", "data"],
970
+ ["source", "bytes"],
971
+ ["source", "url"],
972
+ ["source", "file_data"],
973
+ ["source", "file_id"],
974
+ ["source", "fileId"],
975
+ ["source", "fileUri"],
976
+ [nestedType, "data"],
977
+ [nestedType, "bytes"],
978
+ [nestedType, "url"],
979
+ [nestedType, "file_data"],
980
+ [nestedType, "file_id"],
981
+ [nestedType, "fileId"],
982
+ [nestedType, "fileUri"],
983
+ [
984
+ nestedType,
985
+ "source",
986
+ "data"
987
+ ],
988
+ [
989
+ nestedType,
990
+ "source",
991
+ "bytes"
992
+ ],
993
+ [
994
+ nestedType,
995
+ "source",
996
+ "url"
997
+ ]
998
+ ]) || hasPayloadPath(record, ["source", "content"], isContentPayload) || hasPayloadPath(record, [
999
+ nestedType,
1000
+ "source",
1001
+ "content"
1002
+ ], isContentPayload) || readOwnEnumerableDataProperty(record, "source_type").value === "text" && hasString(record, "text") || readOwnEnumerableDataProperty(record, "source_type").value === "id" && hasString(record, "id");
1003
+ }
1004
+ return false;
1005
+ }
1006
+ const TOOL_BLOCK_OPAQUE = 0;
1007
+ const TOOL_BLOCK_TEXT = 1;
1008
+ const TOOL_BLOCK_ATOMIC = 2;
1009
+ function createToolBlockClassificationContext() {
1010
+ return {
1011
+ totalRemaining: { value: MAX_STRUCTURED_SERIALIZATION_WORK },
1012
+ cache: /* @__PURE__ */ new WeakMap()
1013
+ };
1014
+ }
1015
+ function classifyToolContentBlock(value, context) {
1016
+ if (isRecord(value)) {
1017
+ const cached = context.cache.get(value);
1018
+ if (cached != null) return cached;
1019
+ }
1020
+ const remaining = { value: MAX_ATOMIC_VALIDATION_WORK };
1021
+ let kind = TOOL_BLOCK_OPAQUE;
1022
+ try {
1023
+ if (hasUnsafeCallableToJSON(value, /* @__PURE__ */ new Set(), remaining, 0, context.totalRemaining)) kind = TOOL_BLOCK_OPAQUE;
1024
+ else if (isAtomicToolContentBlockUnchecked(value)) kind = TOOL_BLOCK_ATOMIC;
1025
+ else kind = isTextBlockUnchecked(value) ? TOOL_BLOCK_TEXT : TOOL_BLOCK_OPAQUE;
1026
+ } catch {
1027
+ kind = TOOL_BLOCK_OPAQUE;
1028
+ }
1029
+ if (isRecord(value) && context.totalRemaining.value > 0) context.cache.set(value, kind);
1030
+ return kind;
1031
+ }
1032
+ function getToolContentCharLength(content) {
1033
+ if (typeof content === "string") return content.length;
1034
+ if (isArray(content)) {
1035
+ const denseTextLength = getDenseTextBlockArrayLength(content);
1036
+ if (denseTextLength != null) return denseTextLength;
1037
+ }
1038
+ try {
1039
+ return estimateStructuredChars(content);
1040
+ } catch {
1041
+ return Number.MAX_SAFE_INTEGER;
1042
+ }
1043
+ }
1044
+ /**
1045
+ * Produces provider-facing tool-result text without ever exceeding `maxChars`.
1046
+ */
1047
+ function serializeToolContentBounded(content, maxChars) {
1048
+ const normalizedMaxChars = normalizeCharLimit(maxChars);
1049
+ if (typeof content === "string") return require_truncation.truncateToolResultContent(content, normalizedMaxChars);
1050
+ if (!isArray(content)) return serializeStructuredValueWithinLimit(content, normalizedMaxChars);
1051
+ const originalChars = getDenseTextBlockArrayLength(content);
1052
+ if (originalChars == null) return serializeStructuredValueWithinLimit(content, normalizedMaxChars);
1053
+ return serializeDenseTextBlocksWithinLimit(content, originalChars, normalizedMaxChars);
1054
+ }
1055
+ function serializeDenseTextBlocksWithinLimit(textBlocks, originalChars, normalizedMaxChars) {
1056
+ if (originalChars <= normalizedMaxChars) return textBlocks.map((block) => block.text).join("\n");
1057
+ const indicator = `\n\n… [truncated: ${originalChars} chars exceeded ${normalizedMaxChars} limit] …`;
1058
+ const available = Math.max(0, normalizedMaxChars - indicator.length);
1059
+ let preview = "";
1060
+ for (let i = 0; i < textBlocks.length && preview.length < available; i++) {
1061
+ if (i > 0) preview += "\n";
1062
+ preview += textBlocks[i].text.slice(0, available - preview.length);
1063
+ }
1064
+ return (preview + indicator).slice(0, normalizedMaxChars);
1065
+ }
1066
+ function isProviderImageUrl(value) {
1067
+ if (typeof value !== "string" || value === "") return false;
1068
+ const isDataImage = value.startsWith("data:image/");
1069
+ if (value.length > (isDataImage ? 5e6 : MAX_PROVIDER_IMAGE_URL_CHARS)) return false;
1070
+ for (let i = 0; i < value.length; i++) {
1071
+ const code = value.charCodeAt(i);
1072
+ if (code <= 32 || code === 127) return false;
1073
+ }
1074
+ if (isDataImage) {
1075
+ const separator = value.indexOf(",");
1076
+ if (separator < 0 || !value.slice(0, separator).toLowerCase().endsWith(";base64")) return false;
1077
+ const payload = value.slice(separator + 1);
1078
+ return payload.length > 0 && payload.length % 4 === 0 && /^[a-z0-9+/]+={0,2}$/i.test(payload);
1079
+ }
1080
+ try {
1081
+ const url = new URL(value);
1082
+ return url.protocol === "http:" || url.protocol === "https:";
1083
+ } catch {
1084
+ return false;
1085
+ }
1086
+ }
1087
+ function isProviderFileId(value) {
1088
+ return typeof value === "string" && value.length <= MAX_PROVIDER_FILE_ID_CHARS && /^file[-_][a-z0-9_-]+$/i.test(value);
1089
+ }
1090
+ function hasOnlyEnumerableKeys(record, allowed) {
1091
+ try {
1092
+ return Object.keys(record).every((key) => allowed.has(key));
1093
+ } catch {
1094
+ return false;
1095
+ }
1096
+ }
1097
+ const SINGLE_TEXT_TOOL_CONTENT_KEYS = new Set(["type", "text"]);
1098
+ const CACHE_CONTROLLED_TEXT_TOOL_CONTENT_KEYS = new Set([
1099
+ "type",
1100
+ "text",
1101
+ "cache_control"
1102
+ ]);
1103
+ const CACHE_CONTROL_KEYS = new Set(["type", "ttl"]);
1104
+ function hasSafePlainPrototype(value) {
1105
+ try {
1106
+ const prototype = Object.getPrototypeOf(value);
1107
+ return (prototype === Object.prototype || prototype === null) && !hasPotentiallyCallableToJSON(value);
1108
+ } catch {
1109
+ return false;
1110
+ }
1111
+ }
1112
+ function readSafeArrayItem(content, expectedLength, index) {
1113
+ if (!isArray(content) || (0, node_util_types.isProxy)(content)) return { found: false };
1114
+ try {
1115
+ if (Object.getOwnPropertyDescriptor(content, "length")?.value !== expectedLength) return { found: false };
1116
+ const prototype = Object.getPrototypeOf(content);
1117
+ if (prototype !== Array.prototype && prototype !== null || hasPotentiallyCallableToJSON(content)) return { found: false };
1118
+ const item = Object.getOwnPropertyDescriptor(content, String(index));
1119
+ if (item?.enumerable !== true || !("value" in item)) return { found: false };
1120
+ return {
1121
+ found: true,
1122
+ value: item.value
1123
+ };
1124
+ } catch {
1125
+ return { found: false };
1126
+ }
1127
+ }
1128
+ /** Reads one safe text block and returns its bounded text payload. */
1129
+ function getBoundedSingleTextToolContent(content, maxChars) {
1130
+ const block = readSafeArrayItem(content, 1, 0);
1131
+ if (!block.found || !isRecord(block.value) || (0, node_util_types.isProxy)(block.value) || !hasSafePlainPrototype(block.value) || !hasOnlyEnumerableKeys(block.value, SINGLE_TEXT_TOOL_CONTENT_KEYS)) return;
1132
+ const type = readOwnEnumerableDataProperty(block.value, "type");
1133
+ const text = readOwnEnumerableDataProperty(block.value, "text");
1134
+ if (!type.found || type.value !== "text" || !text.found || typeof text.value !== "string") return;
1135
+ const normalizedMaxChars = Number.isFinite(maxChars) ? Math.max(0, Math.floor(maxChars)) : Number.MAX_SAFE_INTEGER;
1136
+ return require_truncation.truncateToolResultContent(text.value, normalizedMaxChars);
1137
+ }
1138
+ /**
1139
+ * Canonicalizes the single cache-decorated text block produced by tail prompt
1140
+ * caching without invoking accessors or custom serialization hooks.
1141
+ */
1142
+ function getBoundedCacheControlledTextToolContent(content, maxChars) {
1143
+ const block = readSafeArrayItem(content, 1, 0);
1144
+ if (!block.found || !isRecord(block.value) || (0, node_util_types.isProxy)(block.value) || !hasSafePlainPrototype(block.value) || !hasOnlyEnumerableKeys(block.value, CACHE_CONTROLLED_TEXT_TOOL_CONTENT_KEYS)) return;
1145
+ const type = readOwnEnumerableDataProperty(block.value, "type");
1146
+ const text = readOwnEnumerableDataProperty(block.value, "text");
1147
+ const cacheControl = readOwnEnumerableDataProperty(block.value, "cache_control");
1148
+ if (!type.found || type.value !== "text" || !text.found || typeof text.value !== "string" || !cacheControl.found || !isRecord(cacheControl.value) || (0, node_util_types.isProxy)(cacheControl.value) || !hasSafePlainPrototype(cacheControl.value) || !hasOnlyEnumerableKeys(cacheControl.value, CACHE_CONTROL_KEYS)) return;
1149
+ const cacheType = readOwnEnumerableDataProperty(cacheControl.value, "type");
1150
+ const ttl = readOwnEnumerableDataProperty(cacheControl.value, "ttl");
1151
+ let hasOwnTtl;
1152
+ try {
1153
+ hasOwnTtl = Object.getOwnPropertyDescriptor(cacheControl.value, "ttl") != null;
1154
+ } catch {
1155
+ return;
1156
+ }
1157
+ if (!cacheType.found || cacheType.value !== "ephemeral" || hasOwnTtl && (!ttl.found || ttl.value !== "1h")) return;
1158
+ const normalizedMaxChars = Number.isFinite(maxChars) ? Math.max(0, Math.floor(maxChars)) : Number.MAX_SAFE_INTEGER;
1159
+ return [{
1160
+ type: "text",
1161
+ text: require_truncation.truncateToolResultContent(text.value, normalizedMaxChars),
1162
+ cache_control: {
1163
+ type: "ephemeral",
1164
+ ...ttl.found ? { ttl: "1h" } : {}
1165
+ }
1166
+ }];
1167
+ }
1168
+ const INPUT_IMAGE_KEYS = new Set([
1169
+ "type",
1170
+ "image_url",
1171
+ "file_id",
1172
+ "detail"
1173
+ ]);
1174
+ const COMPUTER_SCREENSHOT_KEYS = new Set([
1175
+ "type",
1176
+ "image_url",
1177
+ "file_id"
1178
+ ]);
1179
+ const IMAGE_URL_KEYS = new Set([
1180
+ "type",
1181
+ "image_url",
1182
+ "detail"
1183
+ ]);
1184
+ const NESTED_IMAGE_URL_KEYS = new Set(["url", "detail"]);
1185
+ const INPUT_IMAGE_DETAILS = new Set([
1186
+ "low",
1187
+ "high",
1188
+ "auto",
1189
+ "original"
1190
+ ]);
1191
+ /**
1192
+ * Selects the exact screenshot shape accepted by LangChain's Responses
1193
+ * converter without invoking accessors or user-defined serialization hooks.
1194
+ */
1195
+ function getComputerCallOutputScreenshot(content) {
1196
+ if (isProviderImageUrl(content)) return {
1197
+ type: "input_image",
1198
+ image_url: content
1199
+ };
1200
+ if (!isArray(content) || hasUnsafeCallableToJSON(content) || content.length !== 1) return;
1201
+ const descriptor = Object.getOwnPropertyDescriptor(content, "0");
1202
+ if (descriptor == null || !("value" in descriptor)) return;
1203
+ const block = descriptor.value;
1204
+ if (!isRecord(block)) return;
1205
+ const type = readOwnEnumerableDataProperty(block, "type");
1206
+ if (!type.found) return;
1207
+ const imageUrl = readOwnEnumerableDataProperty(block, "image_url");
1208
+ const fileId = readOwnEnumerableDataProperty(block, "file_id");
1209
+ const validImageUrl = imageUrl.found && isProviderImageUrl(imageUrl.value) ? imageUrl.value : void 0;
1210
+ const validFileId = fileId.found && isProviderFileId(fileId.value) ? fileId.value : void 0;
1211
+ const hasImageUrl = validImageUrl != null;
1212
+ const hasFileId = validFileId != null;
1213
+ if (type.value === "input_image" && hasOnlyEnumerableKeys(block, INPUT_IMAGE_KEYS)) {
1214
+ if (imageUrl.found && !hasImageUrl || fileId.found && !hasFileId || hasImageUrl === hasFileId) return;
1215
+ const detail = readOwnEnumerableDataProperty(block, "detail");
1216
+ if (detail.found && (typeof detail.value !== "string" || !INPUT_IMAGE_DETAILS.has(detail.value))) return;
1217
+ return hasImageUrl ? {
1218
+ type: "input_image",
1219
+ image_url: validImageUrl,
1220
+ ...detail.found ? { detail: detail.value } : {}
1221
+ } : {
1222
+ type: "input_image",
1223
+ file_id: validFileId,
1224
+ ...detail.found ? { detail: detail.value } : {}
1225
+ };
1226
+ }
1227
+ if (type.value === "computer_screenshot" && hasOnlyEnumerableKeys(block, COMPUTER_SCREENSHOT_KEYS)) {
1228
+ if (imageUrl.found && !hasImageUrl || fileId.found && !hasFileId || hasImageUrl === hasFileId) return;
1229
+ return hasImageUrl ? {
1230
+ type: "computer_screenshot",
1231
+ image_url: validImageUrl
1232
+ } : {
1233
+ type: "computer_screenshot",
1234
+ file_id: validFileId
1235
+ };
1236
+ }
1237
+ if (type.value === "image_url" && !fileId.found && hasOnlyEnumerableKeys(block, IMAGE_URL_KEYS)) {
1238
+ if (hasImageUrl) return {
1239
+ type: "input_image",
1240
+ image_url: validImageUrl
1241
+ };
1242
+ if (imageUrl.found && isRecord(imageUrl.value) && hasOnlyEnumerableKeys(imageUrl.value, NESTED_IMAGE_URL_KEYS)) {
1243
+ const url = readOwnEnumerableDataProperty(imageUrl.value, "url");
1244
+ if (url.found && isProviderImageUrl(url.value)) return {
1245
+ type: "input_image",
1246
+ image_url: url.value
1247
+ };
1248
+ }
1249
+ }
1250
+ }
1251
+ /** Returns whether content can be sent as a native computer screenshot. */
1252
+ function isComputerCallOutputContent(content) {
1253
+ return getComputerCallOutputScreenshot(content) != null;
1254
+ }
1255
+ /** Returns whether a ToolMessage carries the native computer-output marker. */
1256
+ function hasComputerCallOutputMarker(message) {
1257
+ try {
1258
+ if (message.getType() !== "tool") return false;
1259
+ const metadata = message.additional_kwargs;
1260
+ if (!isRecord(metadata)) return false;
1261
+ const type = readOwnEnumerableDataProperty(metadata, "type");
1262
+ return type.found && type.value === "computer_call_output";
1263
+ } catch {
1264
+ return false;
1265
+ }
1266
+ }
1267
+ /** Native Responses computer screenshots are indivisible provider payloads. */
1268
+ function isComputerCallOutputMessage(message) {
1269
+ return hasComputerCallOutputMarker(message) && isComputerCallOutputContent(message.content);
1270
+ }
1271
+ /**
1272
+ * Bounds structured tool output without slicing binary/media payloads.
1273
+ * Purely textual/structured arrays become a universally valid string tool
1274
+ * result. For mixed-media arrays, compactable blocks become one text preview
1275
+ * while atomic blocks remain intact.
1276
+ */
1277
+ function compactToolContent(content, maxChars) {
1278
+ const normalizedMaxChars = Number.isFinite(maxChars) ? Math.max(0, Math.floor(maxChars)) : Number.MAX_SAFE_INTEGER;
1279
+ if (typeof content === "string") return {
1280
+ content: require_truncation.truncateToolResultContent(content, normalizedMaxChars),
1281
+ changed: content.length > normalizedMaxChars,
1282
+ originalChars: content.length
1283
+ };
1284
+ if (!isArray(content)) {
1285
+ const serialized = serializeStructuredValueBounded(content, normalizedMaxChars);
1286
+ return {
1287
+ content: serialized.content,
1288
+ changed: true,
1289
+ originalChars: serialized.originalChars
1290
+ };
1291
+ }
1292
+ if ((0, node_util_types.isProxy)(content)) {
1293
+ const serialized = serializeStructuredValueBounded(content, normalizedMaxChars);
1294
+ return {
1295
+ content: serialized.content,
1296
+ changed: true,
1297
+ originalChars: serialized.originalChars
1298
+ };
1299
+ }
1300
+ const contentBlocks = content;
1301
+ let contentLength;
1302
+ try {
1303
+ contentLength = contentBlocks.length;
1304
+ } catch {
1305
+ return {
1306
+ content: serializeStructuredValueBounded(contentBlocks, normalizedMaxChars).content,
1307
+ changed: true,
1308
+ originalChars: Number.MAX_SAFE_INTEGER
1309
+ };
1310
+ }
1311
+ if (contentLength > MAX_STRUCTURED_SERIALIZATION_WORK) {
1312
+ const serialized = serializeStructuredValueBounded(contentBlocks, normalizedMaxChars);
1313
+ return {
1314
+ content: serialized.content,
1315
+ changed: true,
1316
+ originalChars: serialized.originalChars
1317
+ };
1318
+ }
1319
+ try {
1320
+ const blockKinds = new Uint8Array(contentLength);
1321
+ const validation = createToolBlockClassificationContext();
1322
+ const structuredWork = createStructuredWorkState();
1323
+ const containerValidationWork = { value: MAX_ATOMIC_VALIDATION_WORK };
1324
+ const containerPrototype = Object.getPrototypeOf(contentBlocks);
1325
+ if (containerPrototype !== Array.prototype && containerPrototype !== null || hasPotentiallyCallableToJSON(contentBlocks, containerValidationWork, validation.totalRemaining)) {
1326
+ const serialized = serializeStructuredValueBounded(contentBlocks, normalizedMaxChars);
1327
+ return {
1328
+ content: serialized.content,
1329
+ changed: true,
1330
+ originalChars: serialized.originalChars
1331
+ };
1332
+ }
1333
+ let atomicBlockCount = 0;
1334
+ let denseTextLength = contentLength > 0 ? contentLength - 1 : void 0;
1335
+ for (let i = 0; i < contentLength; i++) {
1336
+ const descriptor = Object.getOwnPropertyDescriptor(contentBlocks, String(i));
1337
+ if (descriptor == null || typeof descriptor.get === "function" || typeof descriptor.set === "function") {
1338
+ const serialized = serializeStructuredValueBounded(contentBlocks, normalizedMaxChars);
1339
+ return {
1340
+ content: serialized.content,
1341
+ changed: true,
1342
+ originalChars: serialized.originalChars
1343
+ };
1344
+ }
1345
+ const block = descriptor.value;
1346
+ const kind = classifyToolContentBlock(block, validation);
1347
+ if (validation.totalRemaining.value <= 0) {
1348
+ const serialized = serializeStructuredValueBounded(contentBlocks, normalizedMaxChars);
1349
+ return {
1350
+ content: serialized.content,
1351
+ changed: true,
1352
+ originalChars: serialized.originalChars
1353
+ };
1354
+ }
1355
+ blockKinds[i] = kind;
1356
+ if (kind === TOOL_BLOCK_ATOMIC) atomicBlockCount++;
1357
+ if (denseTextLength == null) continue;
1358
+ if (kind !== TOOL_BLOCK_TEXT) {
1359
+ denseTextLength = void 0;
1360
+ continue;
1361
+ }
1362
+ const text = readOwnEnumerableDataProperty(block, "text").value;
1363
+ denseTextLength += typeof text === "string" ? text.length : 0;
1364
+ if (denseTextLength >= Number.MAX_SAFE_INTEGER) denseTextLength = Number.MAX_SAFE_INTEGER;
1365
+ }
1366
+ const originalChars = denseTextLength ?? estimateStructuredChars(contentBlocks, Number.MAX_SAFE_INTEGER, [], structuredWork);
1367
+ if (atomicBlockCount === 0) {
1368
+ if (denseTextLength != null && originalChars <= normalizedMaxChars) return {
1369
+ content: contentBlocks,
1370
+ changed: false,
1371
+ originalChars
1372
+ };
1373
+ return {
1374
+ content: require_truncation.truncateToolResultContent(denseTextLength != null ? serializeDenseTextBlocksWithinLimit(contentBlocks, denseTextLength, normalizedMaxChars) : serializeStructuredValueWithinLimit(contentBlocks, normalizedMaxChars, structuredWork), normalizedMaxChars),
1375
+ changed: true,
1376
+ originalChars
1377
+ };
1378
+ }
1379
+ let hasOpaqueBlocks = false;
1380
+ const normalizedBlocks = [];
1381
+ const normalizedKinds = [];
1382
+ let opaqueRun = [];
1383
+ const flushOpaqueRun = () => {
1384
+ if (opaqueRun.length === 0) return;
1385
+ normalizedBlocks.push({
1386
+ type: "text",
1387
+ text: serializeStructuredValueWithinLimit(opaqueRun, normalizedMaxChars, structuredWork)
1388
+ });
1389
+ normalizedKinds.push(TOOL_BLOCK_TEXT);
1390
+ opaqueRun = [];
1391
+ };
1392
+ for (let i = 0; i < contentLength; i++) {
1393
+ const block = contentBlocks[i];
1394
+ const kind = blockKinds[i];
1395
+ if (kind !== TOOL_BLOCK_OPAQUE) {
1396
+ flushOpaqueRun();
1397
+ normalizedBlocks.push(block);
1398
+ normalizedKinds.push(kind);
1399
+ } else {
1400
+ hasOpaqueBlocks = true;
1401
+ opaqueRun.push(block);
1402
+ }
1403
+ }
1404
+ flushOpaqueRun();
1405
+ if (estimateStructuredChars(normalizedBlocks, Number.MAX_SAFE_INTEGER, [], structuredWork) <= normalizedMaxChars) return {
1406
+ content: hasOpaqueBlocks ? normalizedBlocks : contentBlocks,
1407
+ changed: hasOpaqueBlocks,
1408
+ originalChars
1409
+ };
1410
+ const atomicBudget = Math.floor(normalizedMaxChars / 2);
1411
+ let atomicChars = 0;
1412
+ let preservedAtomicCount = 0;
1413
+ const preservedAtomicFlags = new Uint8Array(normalizedBlocks.length);
1414
+ let omittedAtomicCount = 0;
1415
+ const omittedAtomicTypes = [];
1416
+ const compactableBlocks = [];
1417
+ let compactableChars = 0;
1418
+ for (let i = 0; i < normalizedBlocks.length; i++) {
1419
+ const block = normalizedBlocks[i];
1420
+ if (normalizedKinds[i] !== TOOL_BLOCK_ATOMIC) {
1421
+ if (compactableBlocks.length > 0) compactableChars++;
1422
+ compactableBlocks.push(block);
1423
+ compactableChars += block.text.length;
1424
+ continue;
1425
+ }
1426
+ const blockChars = estimateStructuredChars(block, atomicBudget - atomicChars, [], structuredWork);
1427
+ if (atomicChars + blockChars <= atomicBudget) {
1428
+ preservedAtomicFlags[i] = 1;
1429
+ preservedAtomicCount++;
1430
+ atomicChars += blockChars;
1431
+ } else {
1432
+ omittedAtomicCount++;
1433
+ const typeProperty = isRecord(block) ? readOwnEnumerableDataProperty(block, "type") : { found: false };
1434
+ if (omittedAtomicTypes.length < 8) {
1435
+ const rawType = typeProperty.found && typeof typeProperty.value === "string" ? typeProperty.value : "media";
1436
+ omittedAtomicTypes.push(require_truncation.truncateToolResultContent(rawType, 80));
1437
+ }
1438
+ }
1439
+ }
1440
+ let previewSource = serializeDenseTextBlocksWithinLimit(compactableBlocks, compactableChars, normalizedMaxChars);
1441
+ if (omittedAtomicCount > 0) {
1442
+ const undisplayedCount = omittedAtomicCount - omittedAtomicTypes.length;
1443
+ const omittedNotice = `[omitted ${omittedAtomicCount} oversized atomic tool-content block${omittedAtomicCount === 1 ? "" : "s"}: ${omittedAtomicTypes.join(", ")}${undisplayedCount > 0 ? `, +${undisplayedCount} more` : ""}]`;
1444
+ previewSource = previewSource.length > 0 ? `${previewSource}\n${omittedNotice}` : omittedNotice;
1445
+ }
1446
+ const structuralAllowance = preservedAtomicCount * 4 + (previewSource.length > 0 ? 32 : 2);
1447
+ const previewBudget = Math.max(0, normalizedMaxChars - atomicChars - structuralAllowance);
1448
+ const preview = require_truncation.truncateToolResultContent(previewSource, previewBudget);
1449
+ const compacted = [];
1450
+ let previewInserted = false;
1451
+ for (let i = 0; i < normalizedBlocks.length; i++) {
1452
+ const block = normalizedBlocks[i];
1453
+ if (normalizedKinds[i] === TOOL_BLOCK_ATOMIC) {
1454
+ if (preservedAtomicFlags[i] === 1) compacted.push(block);
1455
+ } else if (!previewInserted) {
1456
+ if (preview.length > 0) compacted.push({
1457
+ type: "text",
1458
+ text: preview
1459
+ });
1460
+ previewInserted = true;
1461
+ }
1462
+ }
1463
+ if (!previewInserted && preview.length > 0) compacted.push({
1464
+ type: "text",
1465
+ text: preview
1466
+ });
1467
+ if ((preservedAtomicCount > 0 || compacted.length === 0 ? estimateStructuredChars(compacted, Number.MAX_SAFE_INTEGER, [], structuredWork) : preview.length) > normalizedMaxChars) return {
1468
+ content: serializeStructuredValueWithinLimit(normalizedBlocks, normalizedMaxChars, structuredWork),
1469
+ changed: true,
1470
+ originalChars
1471
+ };
1472
+ return {
1473
+ content: compacted,
1474
+ changed: true,
1475
+ originalChars
1476
+ };
1477
+ } catch {
1478
+ const serialized = serializeStructuredValueBounded(contentBlocks, normalizedMaxChars);
1479
+ return {
1480
+ content: serialized.content,
1481
+ changed: true,
1482
+ originalChars: serialized.originalChars
1483
+ };
1484
+ }
1485
+ }
1486
+ /** Clones a ToolMessage while retaining fields omitted by ad-hoc clones. */
1487
+ function cloneToolMessageWithContent(message, content, artifact = message.artifact) {
1488
+ return new _langchain_core_messages.ToolMessage({
1489
+ content,
1490
+ tool_call_id: message.tool_call_id,
1491
+ name: message.name,
1492
+ id: message.id,
1493
+ status: message.status,
1494
+ artifact,
1495
+ metadata: message.metadata,
1496
+ additional_kwargs: message.additional_kwargs,
1497
+ response_metadata: message.response_metadata
1498
+ });
1499
+ }
1500
+ //#endregion
1501
+ exports.cloneToolMessageWithContent = cloneToolMessageWithContent;
1502
+ exports.compactToolContent = compactToolContent;
1503
+ exports.getBoundedCacheControlledTextToolContent = getBoundedCacheControlledTextToolContent;
1504
+ exports.getBoundedSingleTextToolContent = getBoundedSingleTextToolContent;
1505
+ exports.getComputerCallOutputScreenshot = getComputerCallOutputScreenshot;
1506
+ exports.getToolContentCharLength = getToolContentCharLength;
1507
+ exports.hasComputerCallOutputMarker = hasComputerCallOutputMarker;
1508
+ exports.isAtomicToolContentBlock = isAtomicToolContentBlock;
1509
+ exports.isComputerCallOutputContent = isComputerCallOutputContent;
1510
+ exports.isComputerCallOutputMessage = isComputerCallOutputMessage;
1511
+ exports.serializeStructuredValueBounded = serializeStructuredValueBounded;
1512
+ exports.serializeToolContentBounded = serializeToolContentBounded;
1513
+
1514
+ //# sourceMappingURL=toolContent.cjs.map