@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
@@ -1,7 +1,11 @@
1
1
  import "../common/enum.mjs";
2
2
  import "../common/index.mjs";
3
+ import { HARD_MAX_TOOL_RESULT_CHARS } from "../utils/truncation.mjs";
4
+ import { cloneToolMessageWithContent, compactToolContent, getBoundedCacheControlledTextToolContent, getBoundedSingleTextToolContent, getComputerCallOutputScreenshot, hasComputerCallOutputMarker, isComputerCallOutputMessage, serializeToolContentBounded } from "../utils/toolContent.mjs";
3
5
  import { toLangChainContent } from "./langchain.mjs";
6
+ import { stripAnthropicCacheControl } from "./cache.mjs";
4
7
  import { AIMessage, AIMessageChunk, HumanMessage, ToolMessage } from "@langchain/core/messages";
8
+ import { isProxy } from "node:util/types";
5
9
  //#region src/messages/core.ts
6
10
  function getConverseOverrideMessage({ userMessage, lastMessageX, lastMessageY }) {
7
11
  return new HumanMessage(`
@@ -247,49 +251,326 @@ function convertMessagesToContent(messages) {
247
251
  function stringifyToolMessageContent(content) {
248
252
  return content == null ? "" : String(content);
249
253
  }
250
- function formatAnthropicArtifactContent(messages) {
254
+ function appendContentBlocks(target, content) {
255
+ if (typeof content === "string") {
256
+ target.push({
257
+ type: "text",
258
+ text: content
259
+ });
260
+ return;
261
+ }
262
+ for (const block of content) target.push(block);
263
+ }
264
+ /**
265
+ * Appends one artifact/tool-content segment without retaining an unbounded
266
+ * intermediate block array. Both operands are compacted before they are
267
+ * combined, and the combined result is compacted again under the aggregate
268
+ * cap.
269
+ */
270
+ function appendBoundedContent(current, next, maxChars) {
271
+ const boundedNext = compactToolContent(next, maxChars).content;
272
+ if (current == null) return boundedNext;
273
+ const combined = [];
274
+ appendContentBlocks(combined, current);
275
+ appendContentBlocks(combined, boundedNext);
276
+ return compactToolContent(toLangChainContent(combined), maxChars).content;
277
+ }
278
+ function cloneAIMessageWithToolCalls(message, toolCalls, removedCallIds) {
279
+ const descriptors = Object.getOwnPropertyDescriptors(message);
280
+ let descriptor = descriptors.tool_calls;
281
+ descriptors.tool_calls = {
282
+ configurable: descriptor?.configurable ?? true,
283
+ enumerable: descriptor?.enumerable ?? true,
284
+ value: toolCalls,
285
+ writable: descriptor?.writable ?? true
286
+ };
287
+ const toolCallChunks = descriptors.tool_call_chunks?.value;
288
+ if (Array.isArray(toolCallChunks)) {
289
+ descriptor = descriptors.tool_call_chunks;
290
+ descriptors.tool_call_chunks = {
291
+ configurable: descriptor?.configurable ?? true,
292
+ enumerable: descriptor?.enumerable ?? true,
293
+ value: toolCallChunks.filter((chunk) => typeof chunk.id !== "string" || !removedCallIds.has(chunk.id)),
294
+ writable: descriptor?.writable ?? true
295
+ };
296
+ }
297
+ return Object.create(Object.getPrototypeOf(message), descriptors);
298
+ }
299
+ function cloneAIMessageWithContent(message, content) {
300
+ const descriptors = Object.getOwnPropertyDescriptors(message);
301
+ const descriptor = descriptors.content;
302
+ descriptors.content = {
303
+ configurable: descriptor?.configurable ?? true,
304
+ enumerable: descriptor?.enumerable ?? true,
305
+ value: content,
306
+ writable: descriptor?.writable ?? true
307
+ };
308
+ const lcKwargs = descriptors.lc_kwargs;
309
+ if (lcKwargs != null && "value" in lcKwargs && typeof lcKwargs.value === "object" && lcKwargs.value != null) descriptors.lc_kwargs = {
310
+ ...lcKwargs,
311
+ value: {
312
+ ...lcKwargs.value,
313
+ content
314
+ }
315
+ };
316
+ return Object.create(Object.getPrototypeOf(message), descriptors);
317
+ }
318
+ /**
319
+ * Drops incomplete streamed text-input fragments that some providers retain
320
+ * beside the assembled parsed tool call. They are neither user-visible text
321
+ * nor valid content blocks for a subsequent provider.
322
+ */
323
+ function projectToolStreamContentForProvider(messages) {
324
+ let projected;
325
+ for (let i = 0; i < messages.length; i++) {
326
+ const message = messages[i];
327
+ if (message.getType() !== "ai" || !Array.isArray(message.content)) continue;
328
+ const content = message.content.filter((block) => {
329
+ if (block == null || typeof block !== "object") return true;
330
+ try {
331
+ if (isProxy(block)) return false;
332
+ const type = Object.getOwnPropertyDescriptor(block, "type");
333
+ if (type == null) return true;
334
+ if (type.enumerable !== true || !("value" in type)) return false;
335
+ if (type.value !== "text") return true;
336
+ const text = Object.getOwnPropertyDescriptor(block, "text");
337
+ return text?.enumerable === true && "value" in text && typeof text.value === "string" && text.value !== "";
338
+ } catch {
339
+ return false;
340
+ }
341
+ });
342
+ if (content.length === message.content.length) continue;
343
+ projected ??= [...messages];
344
+ projected[i] = cloneAIMessageWithContent(message, toLangChainContent(content));
345
+ }
346
+ return projected ?? messages;
347
+ }
348
+ function projectStructuredOpenAIToolContent(content, maxChars, cacheControlledTextProjection) {
349
+ if (cacheControlledTextProjection !== "serialize") {
350
+ const cacheControlledContent = getBoundedCacheControlledTextToolContent(content, maxChars);
351
+ if (cacheControlledContent != null) return cacheControlledTextProjection === "preserve" ? cacheControlledContent : cacheControlledContent[0].text;
352
+ const singleTextContent = getBoundedSingleTextToolContent(content, maxChars);
353
+ if (singleTextContent != null) return singleTextContent;
354
+ }
355
+ return serializeToolContentBounded(cacheControlledTextProjection === "preserve" ? stripAnthropicCacheControl([{ content }])[0].content : content, maxChars);
356
+ }
357
+ /**
358
+ * OpenAI Chat tool messages only accept strings or text-only parts, while the
359
+ * Responses API serializes any structured ToolMessage after graph accounting.
360
+ * Project every non-string tool result to one bounded string before the final
361
+ * provider payload is measured so both APIs receive the exact representation
362
+ * the budget guard counted. Native Responses computer screenshots stay
363
+ * structured because their dedicated converter sends the media block directly.
364
+ */
365
+ function projectOpenAIToolMessageContentInternal(messages, maxChars, deduplicateResponsesComputerCalls, cacheControlledTextProjection) {
366
+ const pendingComputerCallIds = [];
367
+ const seenComputerCallIds = /* @__PURE__ */ new Set();
368
+ let projected;
369
+ for (let i = 0; i < messages.length; i++) {
370
+ const message = messages[i];
371
+ const messageRole = message.role;
372
+ if (message.getType() === "ai" || messageRole === "assistant") {
373
+ const parsedComputerCallIds = /* @__PURE__ */ new Set();
374
+ const toolCalls = message.tool_calls;
375
+ if (Array.isArray(toolCalls)) for (const toolCall of toolCalls) {
376
+ const record = toolCall;
377
+ if (record.type !== "tool_call" || record.isComputerTool !== true || typeof record.id !== "string" || record.id === "") continue;
378
+ if (parsedComputerCallIds.has(record.id)) throw new Error(`Duplicate computer call id "${record.id}"`);
379
+ parsedComputerCallIds.add(record.id);
380
+ if (seenComputerCallIds.has(record.id)) throw new Error(`Duplicate computer call id "${record.id}"`);
381
+ seenComputerCallIds.add(record.id);
382
+ pendingComputerCallIds.push(record.id);
383
+ }
384
+ const rawOutput = message.response_metadata.output;
385
+ const fallbackOutput = message.additional_kwargs.tool_outputs;
386
+ let actualToolOutputs = [];
387
+ if (Array.isArray(rawOutput) && rawOutput.length > 0) actualToolOutputs = rawOutput;
388
+ else if (Array.isArray(fallbackOutput)) actualToolOutputs = fallbackOutput;
389
+ const rawComputerCallIds = /* @__PURE__ */ new Set();
390
+ for (const item of actualToolOutputs) {
391
+ if (item == null || typeof item !== "object") continue;
392
+ const record = item;
393
+ if (record.type !== "computer_call" || typeof record.call_id !== "string" || record.call_id === "") continue;
394
+ if (rawComputerCallIds.has(record.call_id)) throw new Error(`Duplicate computer call id "${record.call_id}"`);
395
+ rawComputerCallIds.add(record.call_id);
396
+ if (parsedComputerCallIds.has(record.call_id)) continue;
397
+ if (seenComputerCallIds.has(record.call_id)) throw new Error(`Duplicate computer call id "${record.call_id}"`);
398
+ seenComputerCallIds.add(record.call_id);
399
+ pendingComputerCallIds.push(record.call_id);
400
+ }
401
+ if (deduplicateResponsesComputerCalls && Array.isArray(toolCalls) && rawComputerCallIds.size > 0) {
402
+ /**
403
+ * The non-streaming Responses converter marks parsed computer calls,
404
+ * but the streaming converter currently emits the same call as an
405
+ * ordinary parsed `computer_use` tool call. In both cases the raw
406
+ * `computer_call` item is authoritative and is replayed by LangChain,
407
+ * so remove every parsed representation with the same call id.
408
+ */
409
+ const projectedToolCalls = toolCalls.filter((toolCall) => typeof toolCall.id !== "string" || !rawComputerCallIds.has(toolCall.id));
410
+ if (projectedToolCalls.length !== toolCalls.length) {
411
+ projected ??= [...messages];
412
+ projected[i] = cloneAIMessageWithToolCalls(message, projectedToolCalls, rawComputerCallIds);
413
+ }
414
+ }
415
+ }
416
+ if (message instanceof ToolMessage && hasComputerCallOutputMarker(message)) {
417
+ const screenshot = getComputerCallOutputScreenshot(message.content);
418
+ if (screenshot == null) throw new Error("Invalid computer call output screenshot");
419
+ if (pendingComputerCallIds[0] !== message.tool_call_id) throw new Error(`Invalid computer call output pairing for "${message.tool_call_id}"`);
420
+ pendingComputerCallIds.shift();
421
+ projected ??= [...messages];
422
+ projected[i] = cloneToolMessageWithContent(message, [screenshot]);
423
+ continue;
424
+ }
425
+ if (!(message instanceof ToolMessage) || typeof message.content === "string") continue;
426
+ projected ??= [...messages];
427
+ projected[i] = cloneToolMessageWithContent(message, projectStructuredOpenAIToolContent(message.content, maxChars, cacheControlledTextProjection));
428
+ }
429
+ if (pendingComputerCallIds.length > 0) throw new Error(`Missing computer call output for "${pendingComputerCallIds[0]}"`);
430
+ return projected ?? messages;
431
+ }
432
+ /** Projects OpenAI-compatible tool content without changing parsed call parents. */
433
+ function projectOpenAIToolMessageContent(messages, maxChars = HARD_MAX_TOOL_RESULT_CHARS) {
434
+ return projectOpenAIToolMessageContentInternal(messages, maxChars, false, "serialize");
435
+ }
436
+ /** Projects an actual OpenAI-compatible Chat attempt and removes cache metadata. */
437
+ function projectOpenAIChatToolMessageContent(messages, maxChars = HARD_MAX_TOOL_RESULT_CHARS) {
438
+ return projectOpenAIToolMessageContentInternal(messages, maxChars, false, "text");
439
+ }
440
+ /** Preserves OpenRouter's cache-decorated text blocks for a Chat attempt. */
441
+ function projectOpenRouterToolMessageContent(messages, maxChars = HARD_MAX_TOOL_RESULT_CHARS) {
442
+ return projectOpenAIToolMessageContentInternal(messages, maxChars, false, "preserve");
443
+ }
444
+ /** Projects Responses tool content and collapses parsed/raw computer-call mirrors. */
445
+ function projectOpenAIResponsesToolMessageContent(messages, maxChars = HARD_MAX_TOOL_RESULT_CHARS) {
446
+ return projectOpenAIToolMessageContentInternal(messages, maxChars, true, "text");
447
+ }
448
+ /** Removes Anthropic/OpenRouter cache metadata before unsupported providers run. */
449
+ function projectCacheControlledToolOutputsToText(messages, maxChars = HARD_MAX_TOOL_RESULT_CHARS) {
450
+ let projected;
451
+ for (let i = 0; i < messages.length; i++) {
452
+ const message = messages[i];
453
+ if (!(message instanceof ToolMessage) || typeof message.content === "string") continue;
454
+ const cacheControlledContent = getBoundedCacheControlledTextToolContent(message.content, maxChars);
455
+ if (cacheControlledContent == null) continue;
456
+ projected ??= [...messages];
457
+ projected[i] = cloneToolMessageWithContent(message, cacheControlledContent[0].text);
458
+ }
459
+ return projected ?? messages;
460
+ }
461
+ /** Unwraps a canonical single text block after provider cache markers are removed. */
462
+ function projectSingleTextToolOutputsToText(messages, maxChars = HARD_MAX_TOOL_RESULT_CHARS) {
463
+ let projected;
464
+ for (let i = 0; i < messages.length; i++) {
465
+ const message = messages[i];
466
+ if (!(message instanceof ToolMessage) || typeof message.content === "string") continue;
467
+ const text = getBoundedSingleTextToolContent(message.content, maxChars);
468
+ if (text == null) continue;
469
+ projected ??= [...messages];
470
+ projected[i] = cloneToolMessageWithContent(message, text);
471
+ }
472
+ return projected ?? messages;
473
+ }
474
+ /** Serializes provider-neutral structured tool outputs without media pairing. */
475
+ function projectStructuredToolOutputsToText(messages, maxChars = HARD_MAX_TOOL_RESULT_CHARS) {
476
+ let projected;
477
+ for (let i = 0; i < messages.length; i++) {
478
+ const message = messages[i];
479
+ if (!(message instanceof ToolMessage) || typeof message.content === "string" || hasComputerCallOutputMarker(message)) continue;
480
+ projected ??= [...messages];
481
+ projected[i] = cloneToolMessageWithContent(message, serializeToolContentBounded(message.content, maxChars));
482
+ }
483
+ return projected ?? messages;
484
+ }
485
+ /**
486
+ * Non-Responses providers cannot consume native computer screenshots. Keep
487
+ * the tool-call structure intact, but replace screenshot bytes with a bounded
488
+ * text marker at the actual invocation boundary.
489
+ */
490
+ function projectComputerCallOutputsToText(messages) {
491
+ let projected;
492
+ for (let i = 0; i < messages.length; i++) {
493
+ const message = messages[i];
494
+ if (!(message instanceof ToolMessage) || !hasComputerCallOutputMarker(message)) continue;
495
+ projected ??= [...messages];
496
+ projected[i] = cloneToolMessageWithContent(message, "[Computer screenshot omitted for this provider]");
497
+ }
498
+ return projected ?? messages;
499
+ }
500
+ function projectAnthropicArtifactContent(messages, maxChars = HARD_MAX_TOOL_RESULT_CHARS) {
251
501
  const lastMessage = messages[messages.length - 1];
252
- if (!(lastMessage instanceof ToolMessage)) return;
253
- const latestAIParentIndex = findLastIndex(messages, (msg) => (msg instanceof AIMessageChunk && (msg.tool_calls?.length ?? 0) > 0 && msg.tool_calls?.some((tc) => tc.id === lastMessage.tool_call_id)) ?? false);
254
- if (latestAIParentIndex === -1) return;
502
+ if (!(lastMessage instanceof ToolMessage)) return messages;
503
+ const latestAIParentIndex = findLastIndex(messages, (msg) => ((msg instanceof AIMessage || msg instanceof AIMessageChunk) && (msg.tool_calls?.length ?? 0) > 0 && msg.tool_calls?.some((tc) => tc.id === lastMessage.tool_call_id)) ?? false);
504
+ if (latestAIParentIndex === -1) return messages;
255
505
  const message = messages[latestAIParentIndex];
256
506
  const toolCallIdSet = /* @__PURE__ */ new Set();
257
507
  if (message.tool_calls) {
258
508
  for (const tc of message.tool_calls) if (tc.id != null) toolCallIdSet.add(tc.id);
259
509
  }
510
+ let formattedMessages;
260
511
  for (let j = latestAIParentIndex + 1; j < messages.length; j++) {
261
512
  const msg = messages[j];
262
- if (msg instanceof ToolMessage && toolCallIdSet.has(msg.tool_call_id) && msg.artifact != null && Array.isArray(msg.artifact?.content)) msg.content = (Array.isArray(msg.content) ? msg.content : [{
263
- type: "text",
264
- text: stringifyToolMessageContent(msg.content)
265
- }]).concat(msg.artifact.content);
513
+ if (msg instanceof ToolMessage && !isComputerCallOutputMessage(msg) && toolCallIdSet.has(msg.tool_call_id) && msg.artifact != null && (typeof msg.artifact?.content === "string" && msg.artifact.content.length > 0 || Array.isArray(msg.artifact?.content) && msg.artifact.content.length > 0)) {
514
+ const artifactContent = typeof msg.artifact.content === "string" ? [{
515
+ type: "text",
516
+ text: msg.artifact.content
517
+ }] : msg.artifact.content;
518
+ const content = appendBoundedContent(compactToolContent(Array.isArray(msg.content) ? msg.content : stringifyToolMessageContent(msg.content), maxChars).content, artifactContent, maxChars);
519
+ formattedMessages ??= [...messages];
520
+ formattedMessages[j] = cloneToolMessageWithContent(msg, content, {
521
+ ...msg.artifact,
522
+ content: []
523
+ });
524
+ }
266
525
  }
526
+ return formattedMessages ?? messages;
267
527
  }
268
- function formatArtifactPayload(messages) {
528
+ /**
529
+ * Mutating compatibility wrapper retained for existing package consumers.
530
+ * New provider-call paths should use `projectAnthropicArtifactContent`.
531
+ */
532
+ function formatAnthropicArtifactContent(messages) {
533
+ const projected = projectAnthropicArtifactContent(messages);
534
+ if (projected === messages) return;
535
+ for (let i = 0; i < messages.length; i++) if (messages[i] instanceof ToolMessage && projected[i] instanceof ToolMessage && projected[i] !== messages[i]) messages[i].content = projected[i].content;
536
+ }
537
+ function projectArtifactPayload(messages, maxChars = HARD_MAX_TOOL_RESULT_CHARS) {
269
538
  const lastMessageY = messages[messages.length - 1];
270
- if (!(lastMessageY instanceof ToolMessage)) return;
271
- const latestAIParentIndex = findLastIndex(messages, (msg) => (msg instanceof AIMessageChunk && (msg.tool_calls?.length ?? 0) > 0 && msg.tool_calls?.some((tc) => tc.id === lastMessageY.tool_call_id)) ?? false);
272
- if (latestAIParentIndex === -1) return;
273
- const aggregatedContent = [];
539
+ if (!(lastMessageY instanceof ToolMessage)) return messages;
540
+ const latestAIParentIndex = findLastIndex(messages, (msg) => ((msg instanceof AIMessage || msg instanceof AIMessageChunk) && (msg.tool_calls?.length ?? 0) > 0 && msg.tool_calls?.some((tc) => tc.id === lastMessageY.tool_call_id)) ?? false);
541
+ if (latestAIParentIndex === -1) return messages;
542
+ let aggregatedContent;
543
+ let formattedMessages;
274
544
  for (let i = latestAIParentIndex + 1; i < messages.length; i++) {
275
545
  const msg = messages[i];
276
- if (!(msg instanceof ToolMessage) || !Array.isArray(msg.artifact?.content)) continue;
277
- let currentContent = msg.content;
278
- if (!Array.isArray(currentContent)) currentContent = [{
279
- type: "text",
280
- text: msg.content
281
- }];
282
- aggregatedContent.push(...currentContent);
283
- msg.content = "Tool response is included in the next message as a Human message";
284
- aggregatedContent.push(...msg.artifact.content);
546
+ if (!(msg instanceof ToolMessage) || isComputerCallOutputMessage(msg) || !(typeof msg.artifact?.content === "string" && msg.artifact.content.length > 0 || Array.isArray(msg.artifact?.content) && msg.artifact.content.length > 0)) continue;
547
+ aggregatedContent = appendBoundedContent(aggregatedContent, msg.content, maxChars);
548
+ formattedMessages ??= [...messages];
549
+ formattedMessages[i] = cloneToolMessageWithContent(msg, "Tool response is included in the next message as a Human message", {
550
+ ...msg.artifact,
551
+ content: []
552
+ });
553
+ aggregatedContent = appendBoundedContent(aggregatedContent, msg.artifact.content, maxChars);
285
554
  }
286
- if (aggregatedContent.length > 0) messages.push(new HumanMessage({ content: toLangChainContent(aggregatedContent) }));
555
+ if (aggregatedContent != null) formattedMessages?.push(new HumanMessage({ content: aggregatedContent }));
556
+ return formattedMessages ?? messages;
557
+ }
558
+ /**
559
+ * Mutating compatibility wrapper retained for existing package consumers.
560
+ * New provider-call paths should use `projectArtifactPayload`.
561
+ */
562
+ function formatArtifactPayload(messages) {
563
+ const originalLength = messages.length;
564
+ const projected = projectArtifactPayload(messages);
565
+ if (projected === messages) return;
566
+ for (let i = 0; i < originalLength; i++) if (messages[i] instanceof ToolMessage && projected[i] instanceof ToolMessage && projected[i] !== messages[i]) messages[i].content = projected[i].content;
567
+ messages.push(...projected.slice(originalLength));
287
568
  }
288
569
  function findLastIndex(array, predicate) {
289
570
  for (let i = array.length - 1; i >= 0; i--) if (predicate(array[i])) return i;
290
571
  return -1;
291
572
  }
292
573
  //#endregion
293
- export { convertMessagesToContent, findLastIndex, formatAnthropicArtifactContent, formatAnthropicMessage, formatArtifactPayload, getConverseOverrideMessage, modifyDeltaProperties };
574
+ export { convertMessagesToContent, findLastIndex, formatAnthropicArtifactContent, formatAnthropicMessage, formatArtifactPayload, getConverseOverrideMessage, modifyDeltaProperties, projectAnthropicArtifactContent, projectArtifactPayload, projectCacheControlledToolOutputsToText, projectComputerCallOutputsToText, projectOpenAIChatToolMessageContent, projectOpenAIResponsesToolMessageContent, projectOpenAIToolMessageContent, projectOpenRouterToolMessageContent, projectSingleTextToolOutputsToText, projectStructuredToolOutputsToText, projectToolStreamContentForProvider };
294
575
 
295
576
  //# sourceMappingURL=core.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"core.mjs","names":[],"sources":["../../../src/messages/core.ts"],"sourcesContent":["// src/messages.ts\nimport {\n AIMessage,\n BaseMessage,\n ToolMessage,\n HumanMessage,\n AIMessageChunk,\n} from '@langchain/core/messages';\nimport type { ToolCall } from '@langchain/core/messages/tool';\nimport type * as t from '@/types';\nimport { ContentTypes, Providers } from '@/common';\nimport { toLangChainContent } from './langchain';\n\ntype ReasoningSummary = { summary?: Array<{ text?: string }> };\ntype ReasoningDetail = { type?: string; text?: string };\ntype ReasoningAdditionalKwargs = {\n reasoning_content?: string | Partial<ReasoningSummary> | null;\n reasoning?: string | Partial<ReasoningSummary> | null;\n reasoning_details?: ReasoningDetail[] | null;\n};\n\nexport function getConverseOverrideMessage({\n userMessage,\n lastMessageX,\n lastMessageY,\n}: {\n userMessage: string[];\n lastMessageX: AIMessageChunk | null;\n lastMessageY: ToolMessage;\n}): HumanMessage {\n const content = `\nUser: ${userMessage[1]}\n\n---\n# YOU HAVE ALREADY RESPONDED TO THE LATEST USER MESSAGE:\n\n# Observations:\n- ${lastMessageX?.content}\n\n# Tool Calls:\n- ${lastMessageX?.tool_calls?.join('\\n- ')}\n\n# Tool Responses:\n- ${lastMessageY.content}\n`;\n\n return new HumanMessage(content);\n}\n\nconst _allowedTypes = ['image_url', 'text', 'tool_use', 'tool_result'];\nconst allowedTypesByProvider: Record<string, string[]> = {\n default: _allowedTypes,\n [Providers.ANTHROPIC]: [\n ..._allowedTypes,\n 'thinking',\n 'redacted_thinking',\n 'server_tool_use',\n 'web_search_tool_result',\n 'web_search_result',\n ],\n [Providers.BEDROCK]: [..._allowedTypes, 'reasoning_content'],\n [Providers.OPENAI]: _allowedTypes,\n};\n\nconst modifyContent = ({\n provider,\n messageType,\n content,\n}: {\n provider: Providers;\n messageType: string;\n content: t.ExtendedMessageContent[];\n}): (t.ExtendedMessageContent | null)[] => {\n const allowedTypes =\n allowedTypesByProvider[provider] ?? allowedTypesByProvider.default;\n return content.map((item: t.ExtendedMessageContent | null) => {\n if (\n item &&\n typeof item === 'object' &&\n 'type' in item &&\n item.type != null &&\n item.type\n ) {\n let newType = item.type;\n if (newType.endsWith('_delta')) {\n newType = newType.replace('_delta', '');\n }\n if (!allowedTypes.includes(newType)) {\n newType = 'text';\n }\n\n /* Handle the edge case for empty object 'tool_use' input in AI messages */\n if (\n messageType === 'ai' &&\n newType === 'tool_use' &&\n 'input' in item &&\n item.input === ''\n ) {\n return { ...item, type: newType, input: '{}' };\n }\n\n return { ...item, type: newType };\n }\n return item;\n });\n};\n\ntype ContentBlock =\n | Partial<t.BedrockReasoningContentText>\n | t.MessageDeltaUpdate;\n\nfunction reduceBlocks(blocks: ContentBlock[]): ContentBlock[] {\n const reduced: ContentBlock[] = [];\n\n for (const block of blocks) {\n const lastBlock = reduced[reduced.length - 1] as ContentBlock | undefined;\n\n // Merge consecutive 'reasoning_content'\n if (\n block.type === 'reasoning_content' &&\n lastBlock?.type === 'reasoning_content'\n ) {\n // append text if exists\n if (block.reasoningText?.text != null && block.reasoningText.text) {\n (\n lastBlock.reasoningText as t.BedrockReasoningContentText['reasoningText']\n ).text =\n (lastBlock.reasoningText?.text ?? '') + block.reasoningText.text;\n }\n // preserve the signature if exists\n if (\n block.reasoningText?.signature != null &&\n block.reasoningText.signature\n ) {\n (\n lastBlock.reasoningText as t.BedrockReasoningContentText['reasoningText']\n ).signature = block.reasoningText.signature;\n }\n }\n // Merge consecutive 'text'\n else if (block.type === 'text' && lastBlock?.type === 'text') {\n lastBlock.text += block.text;\n }\n // add a new block as it's a different type or first element\n else {\n // deep copy to avoid mutation of original\n reduced.push(JSON.parse(JSON.stringify(block)));\n }\n }\n\n return reduced;\n}\n\nfunction getReasoningText(\n value: string | Partial<ReasoningSummary> | null | undefined\n): string | undefined {\n if (typeof value === 'string') {\n return value !== '' ? value : undefined;\n }\n const summaryText = value?.summary\n ?.map((summary) => summary.text ?? '')\n .filter((text) => text !== '')\n .join('');\n return summaryText != null && summaryText !== '' ? summaryText : undefined;\n}\n\nfunction getReasoningDetailsText(\n value: ReasoningDetail[] | null | undefined\n): string | undefined {\n if (!Array.isArray(value)) {\n return undefined;\n }\n const reasoningText = value\n .filter((detail) => detail.type === 'reasoning.text')\n .map((detail) => detail.text ?? '')\n .filter((text) => text !== '')\n .join('');\n return reasoningText !== '' ? reasoningText : undefined;\n}\n\nfunction getAdditionalReasoningContent(\n message: BaseMessage\n): string | undefined {\n const additionalKwargs =\n message.additional_kwargs as ReasoningAdditionalKwargs | undefined;\n if (additionalKwargs == null) {\n return undefined;\n }\n\n const reasoningContent = getReasoningText(\n additionalKwargs.reasoning_content\n );\n if (reasoningContent != null) {\n return reasoningContent;\n }\n\n const reasoning = getReasoningText(additionalKwargs.reasoning);\n if (reasoning != null) {\n return reasoning;\n }\n\n return getReasoningDetailsText(additionalKwargs.reasoning_details);\n}\n\nfunction hasReasoningContent(content: BaseMessage['content']): boolean {\n if (!Array.isArray(content)) {\n return false;\n }\n return content.some((item) => {\n if (typeof item !== 'object' || !('type' in item)) {\n return false;\n }\n return (\n item.type === ContentTypes.THINK ||\n item.type === ContentTypes.THINKING ||\n item.type === ContentTypes.REASONING ||\n item.type === ContentTypes.REASONING_CONTENT ||\n item.type === 'redacted_thinking'\n );\n });\n}\n\nexport function modifyDeltaProperties(\n provider: Providers,\n obj?: AIMessageChunk\n): AIMessageChunk | undefined {\n if (!obj || typeof obj !== 'object') return obj;\n\n const messageType = (obj as Partial<AIMessageChunk>)._getType\n ? obj._getType()\n : '';\n\n if (provider === Providers.BEDROCK && Array.isArray(obj.content)) {\n obj.content = toLangChainContent(\n reduceBlocks(obj.content as ContentBlock[])\n );\n }\n if (Array.isArray(obj.content)) {\n obj.content = toLangChainContent(\n modifyContent({\n provider,\n messageType,\n content: obj.content as t.ExtendedMessageContent[],\n }) as t.MessageContentComplex[]\n );\n }\n if (\n (obj as Partial<AIMessageChunk>).lc_kwargs &&\n Array.isArray(obj.lc_kwargs.content)\n ) {\n if (provider === Providers.BEDROCK) {\n obj.lc_kwargs.content = reduceBlocks(\n obj.lc_kwargs.content as ContentBlock[]\n );\n }\n obj.lc_kwargs.content = modifyContent({\n provider,\n messageType,\n content: obj.lc_kwargs.content,\n });\n }\n return obj;\n}\n\nexport function formatAnthropicMessage(message: AIMessageChunk): AIMessage {\n if (!message.tool_calls || message.tool_calls.length === 0) {\n return new AIMessage({ content: toLangChainContent(message.content) });\n }\n\n const toolCallMap = new Map(message.tool_calls.map((tc) => [tc.id, tc]));\n let formattedContent: string | t.ExtendedMessageContent[];\n\n if (Array.isArray(message.content)) {\n formattedContent = message.content.reduce<t.ExtendedMessageContent[]>(\n (acc, item) => {\n if (typeof item === 'object') {\n const extendedItem = item as t.ExtendedMessageContent;\n if (\n extendedItem.type === 'text' &&\n extendedItem.text != null &&\n extendedItem.text\n ) {\n acc.push({ type: 'text', text: extendedItem.text });\n } else if (\n extendedItem.type === 'tool_use' &&\n extendedItem.id != null &&\n extendedItem.id\n ) {\n const toolCall = toolCallMap.get(extendedItem.id);\n if (toolCall) {\n acc.push({\n type: 'tool_use',\n id: extendedItem.id,\n name: toolCall.name,\n input: toolCall.args as unknown as string,\n });\n }\n } else if (\n 'input' in extendedItem &&\n extendedItem.input != null &&\n extendedItem.input\n ) {\n try {\n const parsedInput = JSON.parse(extendedItem.input);\n const toolCall = message.tool_calls?.find(\n (tc) => tc.args.input === parsedInput.input\n );\n if (toolCall) {\n acc.push({\n type: 'tool_use',\n id: toolCall.id,\n name: toolCall.name,\n input: toolCall.args as unknown as string,\n });\n }\n } catch {\n if (extendedItem.input) {\n acc.push({ type: 'text', text: extendedItem.input });\n }\n }\n }\n } else if (typeof item === 'string') {\n acc.push({ type: 'text', text: item });\n }\n return acc;\n },\n []\n );\n } else if (typeof message.content === 'string') {\n formattedContent = message.content;\n } else {\n formattedContent = [];\n }\n\n // const formattedToolCalls: ToolCall[] = message.tool_calls.map(toolCall => ({\n // id: toolCall.id ?? '',\n // name: toolCall.name,\n // args: toolCall.args,\n // type: 'tool_call',\n // }));\n\n const formattedToolCalls: t.AgentToolCall[] = message.tool_calls.map(\n (toolCall) => ({\n id: toolCall.id ?? '',\n type: 'function',\n function: {\n name: toolCall.name,\n arguments: toolCall.args,\n },\n })\n );\n\n return new AIMessage({\n content: toLangChainContent(formattedContent),\n tool_calls: formattedToolCalls as ToolCall[],\n additional_kwargs: {\n ...message.additional_kwargs,\n },\n });\n}\n\nexport function convertMessagesToContent(\n messages: BaseMessage[]\n): t.MessageContentComplex[] {\n const processedContent: t.MessageContentComplex[] = [];\n\n const addToolCallBoundary = (): number => {\n processedContent.push({ type: ContentTypes.TEXT, text: '' });\n return processedContent.length - 1;\n };\n\n const addContentPart = (message: BaseMessage | null): number | undefined => {\n const content =\n message?.lc_kwargs.content != null\n ? message.lc_kwargs.content\n : message?.content;\n if (content === undefined) {\n return undefined;\n }\n const reasoningContent =\n message?._getType() === 'ai' && !hasReasoningContent(content)\n ? getAdditionalReasoningContent(message)\n : undefined;\n if (reasoningContent != null) {\n processedContent.push({\n type: ContentTypes.THINK,\n think: reasoningContent,\n });\n }\n if (typeof content === 'string') {\n if (content === '') {\n return undefined;\n }\n processedContent.push({\n type: ContentTypes.TEXT,\n text: content,\n });\n return processedContent.length - 1;\n } else if (Array.isArray(content)) {\n let textContentIndex: number | undefined;\n for (const item of content) {\n if (item == null || item.type === 'tool_use') {\n continue;\n }\n processedContent.push(item);\n if (item.type === ContentTypes.TEXT) {\n textContentIndex = processedContent.length - 1;\n }\n }\n return textContentIndex;\n }\n return undefined;\n };\n\n let currentAIMessageIndex = -1;\n const toolCallMap = new Map<string, t.CustomToolCall>();\n\n for (let i = 0; i < messages.length; i++) {\n const message = messages[i] as BaseMessage | null;\n const messageType = message?._getType();\n\n if (\n messageType === 'ai' &&\n ((message as AIMessage).tool_calls?.length ?? 0) > 0\n ) {\n const tool_calls = (message as AIMessage).tool_calls || [];\n for (const tool_call of tool_calls) {\n if (tool_call.id == null || !tool_call.id) {\n continue;\n }\n\n toolCallMap.set(tool_call.id, tool_call);\n }\n\n currentAIMessageIndex =\n addContentPart(message) ?? addToolCallBoundary();\n continue;\n } else if (\n messageType === 'tool' &&\n (message as ToolMessage).tool_call_id\n ) {\n const id = (message as ToolMessage).tool_call_id;\n const output = (message as ToolMessage).content;\n const tool_call = toolCallMap.get(id);\n if (currentAIMessageIndex === -1) {\n processedContent.push({ type: 'text', text: '' });\n currentAIMessageIndex = processedContent.length - 1;\n }\n const contentPart = processedContent[currentAIMessageIndex];\n processedContent.push({\n type: 'tool_call',\n tool_call: Object.assign({}, tool_call, { output }),\n });\n const tool_call_ids = contentPart.tool_call_ids || [];\n tool_call_ids.push(id);\n contentPart.tool_call_ids = tool_call_ids;\n continue;\n } else if (messageType !== 'ai') {\n continue;\n }\n\n addContentPart(message);\n }\n\n return processedContent;\n}\n\nfunction stringifyToolMessageContent(\n content: ToolMessage['content'] | null | undefined\n): string {\n return content == null ? '' : String(content);\n}\n\nexport function formatAnthropicArtifactContent(messages: BaseMessage[]): void {\n const lastMessage = messages[messages.length - 1];\n if (!(lastMessage instanceof ToolMessage)) return;\n\n // Find the latest AIMessage with tool_calls that this tool message belongs to\n const latestAIParentIndex = findLastIndex(\n messages,\n (msg) =>\n (msg instanceof AIMessageChunk &&\n (msg.tool_calls?.length ?? 0) > 0 &&\n msg.tool_calls?.some((tc) => tc.id === lastMessage.tool_call_id)) ??\n false\n );\n\n if (latestAIParentIndex === -1) return;\n\n // Build tool call ID set and merge artifact content in a single forward pass.\n const message = messages[latestAIParentIndex] as AIMessageChunk;\n const toolCallIdSet = new Set<string>();\n if (message.tool_calls) {\n for (const tc of message.tool_calls) {\n if (tc.id != null) {\n toolCallIdSet.add(tc.id);\n }\n }\n }\n\n for (let j = latestAIParentIndex + 1; j < messages.length; j++) {\n const msg = messages[j];\n if (\n msg instanceof ToolMessage &&\n toolCallIdSet.has(msg.tool_call_id) &&\n msg.artifact != null &&\n Array.isArray(msg.artifact?.content)\n ) {\n const base = Array.isArray(msg.content)\n ? msg.content\n : [\n {\n type: ContentTypes.TEXT,\n text: stringifyToolMessageContent(msg.content),\n },\n ];\n msg.content = base.concat(msg.artifact.content);\n }\n }\n}\n\nexport function formatArtifactPayload(messages: BaseMessage[]): void {\n const lastMessageY = messages[messages.length - 1];\n if (!(lastMessageY instanceof ToolMessage)) return;\n\n // Find the latest AIMessage with tool_calls that this tool message belongs to\n const latestAIParentIndex = findLastIndex(\n messages,\n (msg) =>\n (msg instanceof AIMessageChunk &&\n (msg.tool_calls?.length ?? 0) > 0 &&\n msg.tool_calls?.some((tc) => tc.id === lastMessageY.tool_call_id)) ??\n false\n );\n\n if (latestAIParentIndex === -1) return;\n\n // Single pass: collect relevant tool messages with artifacts and aggregate\n const aggregatedContent: t.MessageContentComplex[] = [];\n\n for (let i = latestAIParentIndex + 1; i < messages.length; i++) {\n const msg = messages[i];\n if (\n !(msg instanceof ToolMessage) ||\n !Array.isArray(msg.artifact?.content)\n ) {\n continue;\n }\n let currentContent = msg.content;\n if (!Array.isArray(currentContent)) {\n currentContent = [{ type: 'text', text: msg.content }];\n }\n aggregatedContent.push(...(currentContent as t.MessageContentComplex[]));\n msg.content =\n 'Tool response is included in the next message as a Human message';\n aggregatedContent.push(...msg.artifact.content);\n }\n\n if (aggregatedContent.length > 0) {\n messages.push(\n new HumanMessage({ content: toLangChainContent(aggregatedContent) })\n );\n }\n}\n\nexport function findLastIndex<T>(\n array: T[],\n predicate: (value: T) => boolean\n): number {\n for (let i = array.length - 1; i >= 0; i--) {\n if (predicate(array[i])) {\n return i;\n }\n }\n return -1;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"core.mjs","names":[],"sources":["../../../src/messages/core.ts"],"sourcesContent":["// src/messages.ts\nimport { isProxy } from 'node:util/types';\nimport {\n AIMessage,\n BaseMessage,\n ToolMessage,\n HumanMessage,\n AIMessageChunk,\n} from '@langchain/core/messages';\nimport type { ToolCall, ToolCallChunk } from '@langchain/core/messages/tool';\nimport type * as t from '@/types';\nimport {\n cloneToolMessageWithContent,\n compactToolContent,\n getBoundedCacheControlledTextToolContent,\n getBoundedSingleTextToolContent,\n getComputerCallOutputScreenshot,\n hasComputerCallOutputMarker,\n isComputerCallOutputMessage,\n serializeToolContentBounded,\n} from '@/utils/toolContent';\nimport { HARD_MAX_TOOL_RESULT_CHARS } from '@/utils/truncation';\nimport { stripAnthropicCacheControl } from './cache';\nimport { ContentTypes, Providers } from '@/common';\nimport { toLangChainContent } from './langchain';\n\ntype ReasoningSummary = { summary?: Array<{ text?: string }> };\ntype ReasoningDetail = { type?: string; text?: string };\ntype ReasoningAdditionalKwargs = {\n reasoning_content?: string | Partial<ReasoningSummary> | null;\n reasoning?: string | Partial<ReasoningSummary> | null;\n reasoning_details?: ReasoningDetail[] | null;\n};\n\nexport function getConverseOverrideMessage({\n userMessage,\n lastMessageX,\n lastMessageY,\n}: {\n userMessage: string[];\n lastMessageX: AIMessageChunk | null;\n lastMessageY: ToolMessage;\n}): HumanMessage {\n const content = `\nUser: ${userMessage[1]}\n\n---\n# YOU HAVE ALREADY RESPONDED TO THE LATEST USER MESSAGE:\n\n# Observations:\n- ${lastMessageX?.content}\n\n# Tool Calls:\n- ${lastMessageX?.tool_calls?.join('\\n- ')}\n\n# Tool Responses:\n- ${lastMessageY.content}\n`;\n\n return new HumanMessage(content);\n}\n\nconst _allowedTypes = ['image_url', 'text', 'tool_use', 'tool_result'];\nconst allowedTypesByProvider: Record<string, string[]> = {\n default: _allowedTypes,\n [Providers.ANTHROPIC]: [\n ..._allowedTypes,\n 'thinking',\n 'redacted_thinking',\n 'server_tool_use',\n 'web_search_tool_result',\n 'web_search_result',\n ],\n [Providers.BEDROCK]: [..._allowedTypes, 'reasoning_content'],\n [Providers.OPENAI]: _allowedTypes,\n};\n\nconst modifyContent = ({\n provider,\n messageType,\n content,\n}: {\n provider: Providers;\n messageType: string;\n content: t.ExtendedMessageContent[];\n}): (t.ExtendedMessageContent | null)[] => {\n const allowedTypes =\n allowedTypesByProvider[provider] ?? allowedTypesByProvider.default;\n return content.map((item: t.ExtendedMessageContent | null) => {\n if (\n item &&\n typeof item === 'object' &&\n 'type' in item &&\n item.type != null &&\n item.type\n ) {\n let newType = item.type;\n if (newType.endsWith('_delta')) {\n newType = newType.replace('_delta', '');\n }\n if (!allowedTypes.includes(newType)) {\n newType = 'text';\n }\n\n /* Handle the edge case for empty object 'tool_use' input in AI messages */\n if (\n messageType === 'ai' &&\n newType === 'tool_use' &&\n 'input' in item &&\n item.input === ''\n ) {\n return { ...item, type: newType, input: '{}' };\n }\n\n return { ...item, type: newType };\n }\n return item;\n });\n};\n\ntype ContentBlock =\n | Partial<t.BedrockReasoningContentText>\n | t.MessageDeltaUpdate;\n\nfunction reduceBlocks(blocks: ContentBlock[]): ContentBlock[] {\n const reduced: ContentBlock[] = [];\n\n for (const block of blocks) {\n const lastBlock = reduced[reduced.length - 1] as ContentBlock | undefined;\n\n // Merge consecutive 'reasoning_content'\n if (\n block.type === 'reasoning_content' &&\n lastBlock?.type === 'reasoning_content'\n ) {\n // append text if exists\n if (block.reasoningText?.text != null && block.reasoningText.text) {\n (\n lastBlock.reasoningText as t.BedrockReasoningContentText['reasoningText']\n ).text =\n (lastBlock.reasoningText?.text ?? '') + block.reasoningText.text;\n }\n // preserve the signature if exists\n if (\n block.reasoningText?.signature != null &&\n block.reasoningText.signature\n ) {\n (\n lastBlock.reasoningText as t.BedrockReasoningContentText['reasoningText']\n ).signature = block.reasoningText.signature;\n }\n }\n // Merge consecutive 'text'\n else if (block.type === 'text' && lastBlock?.type === 'text') {\n lastBlock.text += block.text;\n }\n // add a new block as it's a different type or first element\n else {\n // deep copy to avoid mutation of original\n reduced.push(JSON.parse(JSON.stringify(block)));\n }\n }\n\n return reduced;\n}\n\nfunction getReasoningText(\n value: string | Partial<ReasoningSummary> | null | undefined\n): string | undefined {\n if (typeof value === 'string') {\n return value !== '' ? value : undefined;\n }\n const summaryText = value?.summary\n ?.map((summary) => summary.text ?? '')\n .filter((text) => text !== '')\n .join('');\n return summaryText != null && summaryText !== '' ? summaryText : undefined;\n}\n\nfunction getReasoningDetailsText(\n value: ReasoningDetail[] | null | undefined\n): string | undefined {\n if (!Array.isArray(value)) {\n return undefined;\n }\n const reasoningText = value\n .filter((detail) => detail.type === 'reasoning.text')\n .map((detail) => detail.text ?? '')\n .filter((text) => text !== '')\n .join('');\n return reasoningText !== '' ? reasoningText : undefined;\n}\n\nfunction getAdditionalReasoningContent(\n message: BaseMessage\n): string | undefined {\n const additionalKwargs = message.additional_kwargs as\n | ReasoningAdditionalKwargs\n | undefined;\n if (additionalKwargs == null) {\n return undefined;\n }\n\n const reasoningContent = getReasoningText(additionalKwargs.reasoning_content);\n if (reasoningContent != null) {\n return reasoningContent;\n }\n\n const reasoning = getReasoningText(additionalKwargs.reasoning);\n if (reasoning != null) {\n return reasoning;\n }\n\n return getReasoningDetailsText(additionalKwargs.reasoning_details);\n}\n\nfunction hasReasoningContent(content: BaseMessage['content']): boolean {\n if (!Array.isArray(content)) {\n return false;\n }\n return content.some((item) => {\n if (typeof item !== 'object' || !('type' in item)) {\n return false;\n }\n return (\n item.type === ContentTypes.THINK ||\n item.type === ContentTypes.THINKING ||\n item.type === ContentTypes.REASONING ||\n item.type === ContentTypes.REASONING_CONTENT ||\n item.type === 'redacted_thinking'\n );\n });\n}\n\nexport function modifyDeltaProperties(\n provider: Providers,\n obj?: AIMessageChunk\n): AIMessageChunk | undefined {\n if (!obj || typeof obj !== 'object') return obj;\n\n const messageType = (obj as Partial<AIMessageChunk>)._getType\n ? obj._getType()\n : '';\n\n if (provider === Providers.BEDROCK && Array.isArray(obj.content)) {\n obj.content = toLangChainContent(\n reduceBlocks(obj.content as ContentBlock[])\n );\n }\n if (Array.isArray(obj.content)) {\n obj.content = toLangChainContent(\n modifyContent({\n provider,\n messageType,\n content: obj.content as t.ExtendedMessageContent[],\n }) as t.MessageContentComplex[]\n );\n }\n if (\n (obj as Partial<AIMessageChunk>).lc_kwargs &&\n Array.isArray(obj.lc_kwargs.content)\n ) {\n if (provider === Providers.BEDROCK) {\n obj.lc_kwargs.content = reduceBlocks(\n obj.lc_kwargs.content as ContentBlock[]\n );\n }\n obj.lc_kwargs.content = modifyContent({\n provider,\n messageType,\n content: obj.lc_kwargs.content,\n });\n }\n return obj;\n}\n\nexport function formatAnthropicMessage(message: AIMessageChunk): AIMessage {\n if (!message.tool_calls || message.tool_calls.length === 0) {\n return new AIMessage({ content: toLangChainContent(message.content) });\n }\n\n const toolCallMap = new Map(message.tool_calls.map((tc) => [tc.id, tc]));\n let formattedContent: string | t.ExtendedMessageContent[];\n\n if (Array.isArray(message.content)) {\n formattedContent = message.content.reduce<t.ExtendedMessageContent[]>(\n (acc, item) => {\n if (typeof item === 'object') {\n const extendedItem = item as t.ExtendedMessageContent;\n if (\n extendedItem.type === 'text' &&\n extendedItem.text != null &&\n extendedItem.text\n ) {\n acc.push({ type: 'text', text: extendedItem.text });\n } else if (\n extendedItem.type === 'tool_use' &&\n extendedItem.id != null &&\n extendedItem.id\n ) {\n const toolCall = toolCallMap.get(extendedItem.id);\n if (toolCall) {\n acc.push({\n type: 'tool_use',\n id: extendedItem.id,\n name: toolCall.name,\n input: toolCall.args as unknown as string,\n });\n }\n } else if (\n 'input' in extendedItem &&\n extendedItem.input != null &&\n extendedItem.input\n ) {\n try {\n const parsedInput = JSON.parse(extendedItem.input);\n const toolCall = message.tool_calls?.find(\n (tc) => tc.args.input === parsedInput.input\n );\n if (toolCall) {\n acc.push({\n type: 'tool_use',\n id: toolCall.id,\n name: toolCall.name,\n input: toolCall.args as unknown as string,\n });\n }\n } catch {\n if (extendedItem.input) {\n acc.push({ type: 'text', text: extendedItem.input });\n }\n }\n }\n } else if (typeof item === 'string') {\n acc.push({ type: 'text', text: item });\n }\n return acc;\n },\n []\n );\n } else if (typeof message.content === 'string') {\n formattedContent = message.content;\n } else {\n formattedContent = [];\n }\n\n // const formattedToolCalls: ToolCall[] = message.tool_calls.map(toolCall => ({\n // id: toolCall.id ?? '',\n // name: toolCall.name,\n // args: toolCall.args,\n // type: 'tool_call',\n // }));\n\n const formattedToolCalls: t.AgentToolCall[] = message.tool_calls.map(\n (toolCall) => ({\n id: toolCall.id ?? '',\n type: 'function',\n function: {\n name: toolCall.name,\n arguments: toolCall.args,\n },\n })\n );\n\n return new AIMessage({\n content: toLangChainContent(formattedContent),\n tool_calls: formattedToolCalls as ToolCall[],\n additional_kwargs: {\n ...message.additional_kwargs,\n },\n });\n}\n\nexport function convertMessagesToContent(\n messages: BaseMessage[]\n): t.MessageContentComplex[] {\n const processedContent: t.MessageContentComplex[] = [];\n\n const addToolCallBoundary = (): number => {\n processedContent.push({ type: ContentTypes.TEXT, text: '' });\n return processedContent.length - 1;\n };\n\n const addContentPart = (message: BaseMessage | null): number | undefined => {\n const content =\n message?.lc_kwargs.content != null\n ? message.lc_kwargs.content\n : message?.content;\n if (content === undefined) {\n return undefined;\n }\n const reasoningContent =\n message?._getType() === 'ai' && !hasReasoningContent(content)\n ? getAdditionalReasoningContent(message)\n : undefined;\n if (reasoningContent != null) {\n processedContent.push({\n type: ContentTypes.THINK,\n think: reasoningContent,\n });\n }\n if (typeof content === 'string') {\n if (content === '') {\n return undefined;\n }\n processedContent.push({\n type: ContentTypes.TEXT,\n text: content,\n });\n return processedContent.length - 1;\n } else if (Array.isArray(content)) {\n let textContentIndex: number | undefined;\n for (const item of content) {\n if (item == null || item.type === 'tool_use') {\n continue;\n }\n processedContent.push(item);\n if (item.type === ContentTypes.TEXT) {\n textContentIndex = processedContent.length - 1;\n }\n }\n return textContentIndex;\n }\n return undefined;\n };\n\n let currentAIMessageIndex = -1;\n const toolCallMap = new Map<string, t.CustomToolCall>();\n\n for (let i = 0; i < messages.length; i++) {\n const message = messages[i] as BaseMessage | null;\n const messageType = message?._getType();\n\n if (\n messageType === 'ai' &&\n ((message as AIMessage).tool_calls?.length ?? 0) > 0\n ) {\n const tool_calls = (message as AIMessage).tool_calls || [];\n for (const tool_call of tool_calls) {\n if (tool_call.id == null || !tool_call.id) {\n continue;\n }\n\n toolCallMap.set(tool_call.id, tool_call);\n }\n\n currentAIMessageIndex = addContentPart(message) ?? addToolCallBoundary();\n continue;\n } else if (\n messageType === 'tool' &&\n (message as ToolMessage).tool_call_id\n ) {\n const id = (message as ToolMessage).tool_call_id;\n const output = (message as ToolMessage).content;\n const tool_call = toolCallMap.get(id);\n if (currentAIMessageIndex === -1) {\n processedContent.push({ type: 'text', text: '' });\n currentAIMessageIndex = processedContent.length - 1;\n }\n const contentPart = processedContent[currentAIMessageIndex];\n processedContent.push({\n type: 'tool_call',\n tool_call: Object.assign({}, tool_call, { output }),\n });\n const tool_call_ids = contentPart.tool_call_ids || [];\n tool_call_ids.push(id);\n contentPart.tool_call_ids = tool_call_ids;\n continue;\n } else if (messageType !== 'ai') {\n continue;\n }\n\n addContentPart(message);\n }\n\n return processedContent;\n}\n\nfunction stringifyToolMessageContent(\n content: ToolMessage['content'] | null | undefined\n): string {\n return content == null ? '' : String(content);\n}\n\nfunction appendContentBlocks(\n target: t.MessageContentComplex[],\n content: BaseMessage['content']\n): void {\n if (typeof content === 'string') {\n target.push({ type: ContentTypes.TEXT, text: content });\n return;\n }\n for (const block of content) {\n target.push(block as t.MessageContentComplex);\n }\n}\n\n/**\n * Appends one artifact/tool-content segment without retaining an unbounded\n * intermediate block array. Both operands are compacted before they are\n * combined, and the combined result is compacted again under the aggregate\n * cap.\n */\nfunction appendBoundedContent(\n current: BaseMessage['content'] | undefined,\n next: unknown,\n maxChars: number\n): BaseMessage['content'] {\n const boundedNext = compactToolContent(next, maxChars).content;\n if (current == null) {\n return boundedNext;\n }\n\n const combined: t.MessageContentComplex[] = [];\n appendContentBlocks(combined, current);\n appendContentBlocks(combined, boundedNext);\n return compactToolContent(toLangChainContent(combined), maxChars).content;\n}\n\nfunction cloneAIMessageWithToolCalls(\n message: AIMessage,\n toolCalls: ToolCall[],\n removedCallIds: ReadonlySet<string>\n): AIMessage {\n const descriptors = Object.getOwnPropertyDescriptors(message) as Record<\n string,\n PropertyDescriptor | undefined\n >;\n let descriptor = descriptors.tool_calls;\n descriptors.tool_calls = {\n configurable: descriptor?.configurable ?? true,\n enumerable: descriptor?.enumerable ?? true,\n value: toolCalls,\n writable: descriptor?.writable ?? true,\n };\n const toolCallChunks = descriptors.tool_call_chunks?.value as\n | ToolCallChunk[]\n | undefined;\n if (Array.isArray(toolCallChunks)) {\n descriptor = descriptors.tool_call_chunks;\n descriptors.tool_call_chunks = {\n configurable: descriptor?.configurable ?? true,\n enumerable: descriptor?.enumerable ?? true,\n value: toolCallChunks.filter(\n (chunk) => typeof chunk.id !== 'string' || !removedCallIds.has(chunk.id)\n ),\n writable: descriptor?.writable ?? true,\n };\n }\n return Object.create(\n Object.getPrototypeOf(message),\n descriptors as PropertyDescriptorMap\n ) as AIMessage;\n}\n\nfunction cloneAIMessageWithContent(\n message: AIMessage,\n content: AIMessage['content']\n): AIMessage {\n const descriptors = Object.getOwnPropertyDescriptors(message) as Record<\n string,\n PropertyDescriptor | undefined\n >;\n const descriptor = descriptors.content;\n descriptors.content = {\n configurable: descriptor?.configurable ?? true,\n enumerable: descriptor?.enumerable ?? true,\n value: content,\n writable: descriptor?.writable ?? true,\n };\n const lcKwargs = descriptors.lc_kwargs;\n if (\n lcKwargs != null &&\n 'value' in lcKwargs &&\n typeof lcKwargs.value === 'object' &&\n lcKwargs.value != null\n ) {\n descriptors.lc_kwargs = {\n ...lcKwargs,\n value: {\n ...(lcKwargs.value as Record<string, unknown>),\n content,\n },\n };\n }\n return Object.create(\n Object.getPrototypeOf(message),\n descriptors as PropertyDescriptorMap\n ) as AIMessage;\n}\n\n/**\n * Drops incomplete streamed text-input fragments that some providers retain\n * beside the assembled parsed tool call. They are neither user-visible text\n * nor valid content blocks for a subsequent provider.\n */\nexport function projectToolStreamContentForProvider(\n messages: BaseMessage[]\n): BaseMessage[] {\n let projected: BaseMessage[] | undefined;\n for (let i = 0; i < messages.length; i++) {\n const message = messages[i];\n if (message.getType() !== 'ai' || !Array.isArray(message.content)) {\n continue;\n }\n const content = message.content.filter((block) => {\n if (block == null || typeof block !== 'object') {\n return true;\n }\n try {\n if (isProxy(block)) {\n return false;\n }\n const type = Object.getOwnPropertyDescriptor(block, 'type');\n if (type == null) {\n return true;\n }\n if (type.enumerable !== true || !('value' in type)) {\n return false;\n }\n if (type.value !== 'text') {\n return true;\n }\n const text = Object.getOwnPropertyDescriptor(block, 'text');\n return (\n text?.enumerable === true &&\n 'value' in text &&\n typeof text.value === 'string' &&\n text.value !== ''\n );\n } catch {\n return false;\n }\n });\n if (content.length === message.content.length) {\n continue;\n }\n projected ??= [...messages];\n projected[i] = cloneAIMessageWithContent(\n message as AIMessage,\n toLangChainContent(content)\n );\n }\n return projected ?? messages;\n}\n\ntype CacheControlledTextProjection = 'serialize' | 'preserve' | 'text';\n\nfunction projectStructuredOpenAIToolContent(\n content: ToolMessage['content'],\n maxChars: number,\n cacheControlledTextProjection: CacheControlledTextProjection\n): ToolMessage['content'] {\n if (cacheControlledTextProjection !== 'serialize') {\n const cacheControlledContent = getBoundedCacheControlledTextToolContent(\n content,\n maxChars\n );\n if (cacheControlledContent != null) {\n return cacheControlledTextProjection === 'preserve'\n ? cacheControlledContent\n : cacheControlledContent[0].text;\n }\n const singleTextContent = getBoundedSingleTextToolContent(\n content,\n maxChars\n );\n if (singleTextContent != null) {\n return singleTextContent;\n }\n }\n const serializableContent =\n cacheControlledTextProjection === 'preserve'\n ? stripAnthropicCacheControl([{ content }])[0].content\n : content;\n return serializeToolContentBounded(serializableContent, maxChars);\n}\n\n/**\n * OpenAI Chat tool messages only accept strings or text-only parts, while the\n * Responses API serializes any structured ToolMessage after graph accounting.\n * Project every non-string tool result to one bounded string before the final\n * provider payload is measured so both APIs receive the exact representation\n * the budget guard counted. Native Responses computer screenshots stay\n * structured because their dedicated converter sends the media block directly.\n */\nfunction projectOpenAIToolMessageContentInternal(\n messages: BaseMessage[],\n maxChars: number,\n deduplicateResponsesComputerCalls: boolean,\n cacheControlledTextProjection: CacheControlledTextProjection\n): BaseMessage[] {\n const pendingComputerCallIds: string[] = [];\n const seenComputerCallIds = new Set<string>();\n let projected: BaseMessage[] | undefined;\n for (let i = 0; i < messages.length; i++) {\n const message = messages[i];\n const messageRole = (message as BaseMessage & { role?: unknown }).role;\n const isAssistant =\n message.getType() === 'ai' || messageRole === 'assistant';\n if (isAssistant) {\n const parsedComputerCallIds = new Set<string>();\n const toolCalls = (message as AIMessage).tool_calls;\n if (Array.isArray(toolCalls)) {\n for (const toolCall of toolCalls) {\n const record = toolCall as ToolCall & {\n isComputerTool?: unknown;\n };\n if (\n record.type !== 'tool_call' ||\n record.isComputerTool !== true ||\n typeof record.id !== 'string' ||\n record.id === ''\n ) {\n continue;\n }\n if (parsedComputerCallIds.has(record.id)) {\n throw new Error(`Duplicate computer call id \"${record.id}\"`);\n }\n parsedComputerCallIds.add(record.id);\n if (seenComputerCallIds.has(record.id)) {\n throw new Error(`Duplicate computer call id \"${record.id}\"`);\n }\n seenComputerCallIds.add(record.id);\n pendingComputerCallIds.push(record.id);\n }\n }\n\n const rawOutput = (\n message.response_metadata as {\n output?: unknown;\n }\n ).output;\n const fallbackOutput = (\n message.additional_kwargs as {\n tool_outputs?: unknown;\n }\n ).tool_outputs;\n let actualToolOutputs: unknown[] = [];\n if (Array.isArray(rawOutput) && rawOutput.length > 0) {\n actualToolOutputs = rawOutput;\n } else if (Array.isArray(fallbackOutput)) {\n actualToolOutputs = fallbackOutput;\n }\n const rawComputerCallIds = new Set<string>();\n for (const item of actualToolOutputs) {\n if (item == null || typeof item !== 'object') {\n continue;\n }\n const record = item as {\n type?: unknown;\n call_id?: unknown;\n };\n if (\n record.type !== 'computer_call' ||\n typeof record.call_id !== 'string' ||\n record.call_id === ''\n ) {\n continue;\n }\n if (rawComputerCallIds.has(record.call_id)) {\n throw new Error(`Duplicate computer call id \"${record.call_id}\"`);\n }\n rawComputerCallIds.add(record.call_id);\n // LangChain can retain the same call in parsed and raw forms. It sends\n // one logical call, so collapse that representation duplicate.\n if (parsedComputerCallIds.has(record.call_id)) {\n continue;\n }\n if (seenComputerCallIds.has(record.call_id)) {\n throw new Error(`Duplicate computer call id \"${record.call_id}\"`);\n }\n seenComputerCallIds.add(record.call_id);\n pendingComputerCallIds.push(record.call_id);\n }\n\n if (\n deduplicateResponsesComputerCalls &&\n Array.isArray(toolCalls) &&\n rawComputerCallIds.size > 0\n ) {\n /**\n * The non-streaming Responses converter marks parsed computer calls,\n * but the streaming converter currently emits the same call as an\n * ordinary parsed `computer_use` tool call. In both cases the raw\n * `computer_call` item is authoritative and is replayed by LangChain,\n * so remove every parsed representation with the same call id.\n */\n const projectedToolCalls = toolCalls.filter(\n (toolCall) =>\n typeof toolCall.id !== 'string' ||\n !rawComputerCallIds.has(toolCall.id)\n );\n if (projectedToolCalls.length !== toolCalls.length) {\n projected ??= [...messages];\n projected[i] = cloneAIMessageWithToolCalls(\n message as AIMessage,\n projectedToolCalls,\n rawComputerCallIds\n );\n }\n }\n }\n\n if (\n message instanceof ToolMessage &&\n hasComputerCallOutputMarker(message)\n ) {\n const screenshot = getComputerCallOutputScreenshot(message.content);\n if (screenshot == null) {\n throw new Error('Invalid computer call output screenshot');\n }\n if (pendingComputerCallIds[0] !== message.tool_call_id) {\n throw new Error(\n `Invalid computer call output pairing for \"${message.tool_call_id}\"`\n );\n }\n pendingComputerCallIds.shift();\n projected ??= [...messages];\n projected[i] = cloneToolMessageWithContent(message, [screenshot]);\n continue;\n }\n if (\n !(message instanceof ToolMessage) ||\n typeof message.content === 'string'\n ) {\n continue;\n }\n projected ??= [...messages];\n projected[i] = cloneToolMessageWithContent(\n message,\n projectStructuredOpenAIToolContent(\n message.content,\n maxChars,\n cacheControlledTextProjection\n )\n );\n }\n if (pendingComputerCallIds.length > 0) {\n throw new Error(\n `Missing computer call output for \"${pendingComputerCallIds[0]}\"`\n );\n }\n return projected ?? messages;\n}\n\n/** Projects OpenAI-compatible tool content without changing parsed call parents. */\nexport function projectOpenAIToolMessageContent(\n messages: BaseMessage[],\n maxChars = HARD_MAX_TOOL_RESULT_CHARS\n): BaseMessage[] {\n return projectOpenAIToolMessageContentInternal(\n messages,\n maxChars,\n false,\n 'serialize'\n );\n}\n\n/** Projects an actual OpenAI-compatible Chat attempt and removes cache metadata. */\nexport function projectOpenAIChatToolMessageContent(\n messages: BaseMessage[],\n maxChars = HARD_MAX_TOOL_RESULT_CHARS\n): BaseMessage[] {\n return projectOpenAIToolMessageContentInternal(\n messages,\n maxChars,\n false,\n 'text'\n );\n}\n\n/** Preserves OpenRouter's cache-decorated text blocks for a Chat attempt. */\nexport function projectOpenRouterToolMessageContent(\n messages: BaseMessage[],\n maxChars = HARD_MAX_TOOL_RESULT_CHARS\n): BaseMessage[] {\n return projectOpenAIToolMessageContentInternal(\n messages,\n maxChars,\n false,\n 'preserve'\n );\n}\n\n/** Projects Responses tool content and collapses parsed/raw computer-call mirrors. */\nexport function projectOpenAIResponsesToolMessageContent(\n messages: BaseMessage[],\n maxChars = HARD_MAX_TOOL_RESULT_CHARS\n): BaseMessage[] {\n return projectOpenAIToolMessageContentInternal(\n messages,\n maxChars,\n true,\n 'text'\n );\n}\n\n/** Removes Anthropic/OpenRouter cache metadata before unsupported providers run. */\nexport function projectCacheControlledToolOutputsToText(\n messages: BaseMessage[],\n maxChars = HARD_MAX_TOOL_RESULT_CHARS\n): BaseMessage[] {\n let projected: BaseMessage[] | undefined;\n for (let i = 0; i < messages.length; i++) {\n const message = messages[i];\n if (\n !(message instanceof ToolMessage) ||\n typeof message.content === 'string'\n ) {\n continue;\n }\n const cacheControlledContent = getBoundedCacheControlledTextToolContent(\n message.content,\n maxChars\n );\n if (cacheControlledContent == null) {\n continue;\n }\n projected ??= [...messages];\n projected[i] = cloneToolMessageWithContent(\n message,\n cacheControlledContent[0].text\n );\n }\n return projected ?? messages;\n}\n\n/** Unwraps a canonical single text block after provider cache markers are removed. */\nexport function projectSingleTextToolOutputsToText(\n messages: BaseMessage[],\n maxChars = HARD_MAX_TOOL_RESULT_CHARS\n): BaseMessage[] {\n let projected: BaseMessage[] | undefined;\n for (let i = 0; i < messages.length; i++) {\n const message = messages[i];\n if (\n !(message instanceof ToolMessage) ||\n typeof message.content === 'string'\n ) {\n continue;\n }\n const text = getBoundedSingleTextToolContent(message.content, maxChars);\n if (text == null) {\n continue;\n }\n projected ??= [...messages];\n projected[i] = cloneToolMessageWithContent(message, text);\n }\n return projected ?? messages;\n}\n\n/** Serializes provider-neutral structured tool outputs without media pairing. */\nexport function projectStructuredToolOutputsToText(\n messages: BaseMessage[],\n maxChars = HARD_MAX_TOOL_RESULT_CHARS\n): BaseMessage[] {\n let projected: BaseMessage[] | undefined;\n for (let i = 0; i < messages.length; i++) {\n const message = messages[i];\n if (\n !(message instanceof ToolMessage) ||\n typeof message.content === 'string' ||\n hasComputerCallOutputMarker(message)\n ) {\n continue;\n }\n projected ??= [...messages];\n projected[i] = cloneToolMessageWithContent(\n message,\n serializeToolContentBounded(message.content, maxChars)\n );\n }\n return projected ?? messages;\n}\n\n/**\n * Non-Responses providers cannot consume native computer screenshots. Keep\n * the tool-call structure intact, but replace screenshot bytes with a bounded\n * text marker at the actual invocation boundary.\n */\nexport function projectComputerCallOutputsToText(\n messages: BaseMessage[]\n): BaseMessage[] {\n let projected: BaseMessage[] | undefined;\n for (let i = 0; i < messages.length; i++) {\n const message = messages[i];\n if (\n !(message instanceof ToolMessage) ||\n !hasComputerCallOutputMarker(message)\n ) {\n continue;\n }\n projected ??= [...messages];\n projected[i] = cloneToolMessageWithContent(\n message,\n '[Computer screenshot omitted for this provider]'\n );\n }\n return projected ?? messages;\n}\n\nexport function projectAnthropicArtifactContent(\n messages: BaseMessage[],\n maxChars = HARD_MAX_TOOL_RESULT_CHARS\n): BaseMessage[] {\n const lastMessage = messages[messages.length - 1];\n if (!(lastMessage instanceof ToolMessage)) return messages;\n\n // Find the latest AIMessage with tool_calls that this tool message belongs to\n const latestAIParentIndex = findLastIndex(\n messages,\n (msg) =>\n ((msg instanceof AIMessage || msg instanceof AIMessageChunk) &&\n (msg.tool_calls?.length ?? 0) > 0 &&\n msg.tool_calls?.some((tc) => tc.id === lastMessage.tool_call_id)) ??\n false\n );\n\n if (latestAIParentIndex === -1) return messages;\n\n // Build tool call ID set and merge artifact content in a single forward pass.\n const message = messages[latestAIParentIndex] as AIMessage | AIMessageChunk;\n const toolCallIdSet = new Set<string>();\n if (message.tool_calls) {\n for (const tc of message.tool_calls) {\n if (tc.id != null) {\n toolCallIdSet.add(tc.id);\n }\n }\n }\n\n let formattedMessages: BaseMessage[] | undefined;\n for (let j = latestAIParentIndex + 1; j < messages.length; j++) {\n const msg = messages[j];\n if (\n msg instanceof ToolMessage &&\n !isComputerCallOutputMessage(msg) &&\n toolCallIdSet.has(msg.tool_call_id) &&\n msg.artifact != null &&\n ((typeof msg.artifact?.content === 'string' &&\n msg.artifact.content.length > 0) ||\n (Array.isArray(msg.artifact?.content) &&\n msg.artifact.content.length > 0))\n ) {\n const artifactContent =\n typeof msg.artifact.content === 'string'\n ? [\n {\n type: ContentTypes.TEXT,\n text: msg.artifact.content,\n },\n ]\n : msg.artifact.content;\n const baseContent = Array.isArray(msg.content)\n ? msg.content\n : stringifyToolMessageContent(msg.content);\n const content = appendBoundedContent(\n compactToolContent(baseContent, maxChars).content,\n artifactContent,\n maxChars\n );\n formattedMessages ??= [...messages];\n formattedMessages[j] = cloneToolMessageWithContent(msg, content, {\n ...msg.artifact,\n content: [],\n });\n }\n }\n return formattedMessages ?? messages;\n}\n\n/**\n * Mutating compatibility wrapper retained for existing package consumers.\n * New provider-call paths should use `projectAnthropicArtifactContent`.\n */\nexport function formatAnthropicArtifactContent(messages: BaseMessage[]): void {\n const projected = projectAnthropicArtifactContent(messages);\n if (projected === messages) {\n return;\n }\n for (let i = 0; i < messages.length; i++) {\n if (\n messages[i] instanceof ToolMessage &&\n projected[i] instanceof ToolMessage &&\n projected[i] !== messages[i]\n ) {\n messages[i].content = projected[i].content;\n }\n }\n}\n\nexport function projectArtifactPayload(\n messages: BaseMessage[],\n maxChars = HARD_MAX_TOOL_RESULT_CHARS\n): BaseMessage[] {\n const lastMessageY = messages[messages.length - 1];\n if (!(lastMessageY instanceof ToolMessage)) return messages;\n\n // Find the latest AIMessage with tool_calls that this tool message belongs to\n const latestAIParentIndex = findLastIndex(\n messages,\n (msg) =>\n ((msg instanceof AIMessage || msg instanceof AIMessageChunk) &&\n (msg.tool_calls?.length ?? 0) > 0 &&\n msg.tool_calls?.some((tc) => tc.id === lastMessageY.tool_call_id)) ??\n false\n );\n\n if (latestAIParentIndex === -1) return messages;\n\n // Single pass: collect relevant tool messages with artifacts and aggregate\n let aggregatedContent: BaseMessage['content'] | undefined;\n let formattedMessages: BaseMessage[] | undefined;\n\n for (let i = latestAIParentIndex + 1; i < messages.length; i++) {\n const msg = messages[i];\n if (\n !(msg instanceof ToolMessage) ||\n isComputerCallOutputMessage(msg) ||\n !(\n (typeof msg.artifact?.content === 'string' &&\n msg.artifact.content.length > 0) ||\n (Array.isArray(msg.artifact?.content) &&\n msg.artifact.content.length > 0)\n )\n ) {\n continue;\n }\n aggregatedContent = appendBoundedContent(\n aggregatedContent,\n msg.content,\n maxChars\n );\n formattedMessages ??= [...messages];\n formattedMessages[i] = cloneToolMessageWithContent(\n msg,\n 'Tool response is included in the next message as a Human message',\n {\n ...msg.artifact,\n content: [],\n }\n );\n aggregatedContent = appendBoundedContent(\n aggregatedContent,\n msg.artifact.content,\n maxChars\n );\n }\n\n if (aggregatedContent != null) {\n formattedMessages?.push(new HumanMessage({ content: aggregatedContent }));\n }\n return formattedMessages ?? messages;\n}\n\n/**\n * Mutating compatibility wrapper retained for existing package consumers.\n * New provider-call paths should use `projectArtifactPayload`.\n */\nexport function formatArtifactPayload(messages: BaseMessage[]): void {\n const originalLength = messages.length;\n const projected = projectArtifactPayload(messages);\n if (projected === messages) {\n return;\n }\n for (let i = 0; i < originalLength; i++) {\n if (\n messages[i] instanceof ToolMessage &&\n projected[i] instanceof ToolMessage &&\n projected[i] !== messages[i]\n ) {\n messages[i].content = projected[i].content;\n }\n }\n messages.push(...projected.slice(originalLength));\n}\n\nexport function findLastIndex<T>(\n array: T[],\n predicate: (value: T) => boolean\n): number {\n for (let i = array.length - 1; i >= 0; i--) {\n if (predicate(array[i])) {\n return i;\n }\n }\n return -1;\n}\n"],"mappings":"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"}