@librechat/agents 3.6.9 → 3.6.10

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 (141) hide show
  1. package/dist/cjs/agents/AgentContext.cjs +46 -39
  2. package/dist/cjs/agents/AgentContext.cjs.map +1 -1
  3. package/dist/cjs/agents/projection.cjs +2 -2
  4. package/dist/cjs/agents/projection.cjs.map +1 -1
  5. package/dist/cjs/graphs/Graph.cjs +28 -18
  6. package/dist/cjs/graphs/Graph.cjs.map +1 -1
  7. package/dist/cjs/graphs/MultiAgentGraph.cjs +87 -16
  8. package/dist/cjs/graphs/MultiAgentGraph.cjs.map +1 -1
  9. package/dist/cjs/llm/openai/index.cjs +10 -0
  10. package/dist/cjs/llm/openai/index.cjs.map +1 -1
  11. package/dist/cjs/main.cjs +14 -0
  12. package/dist/cjs/messages/alternation.cjs +125 -20
  13. package/dist/cjs/messages/alternation.cjs.map +1 -1
  14. package/dist/cjs/messages/core.cjs +195 -18
  15. package/dist/cjs/messages/core.cjs.map +1 -1
  16. package/dist/cjs/messages/format.cjs +488 -118
  17. package/dist/cjs/messages/format.cjs.map +1 -1
  18. package/dist/cjs/messages/handoffCue.cjs +3 -2
  19. package/dist/cjs/messages/handoffCue.cjs.map +1 -1
  20. package/dist/cjs/messages/index.cjs +1 -0
  21. package/dist/cjs/messages/injected.cjs +5 -2
  22. package/dist/cjs/messages/injected.cjs.map +1 -1
  23. package/dist/cjs/messages/provenance.cjs +411 -0
  24. package/dist/cjs/messages/provenance.cjs.map +1 -0
  25. package/dist/cjs/messages/prune.cjs +18 -13
  26. package/dist/cjs/messages/prune.cjs.map +1 -1
  27. package/dist/cjs/messages/toolResultTypes.cjs +663 -0
  28. package/dist/cjs/messages/toolResultTypes.cjs.map +1 -0
  29. package/dist/cjs/run.cjs +7 -4
  30. package/dist/cjs/run.cjs.map +1 -1
  31. package/dist/cjs/tools/BashProgrammaticToolCalling.cjs +21 -4
  32. package/dist/cjs/tools/BashProgrammaticToolCalling.cjs.map +1 -1
  33. package/dist/cjs/tools/CallerCapabilities.cjs +48 -0
  34. package/dist/cjs/tools/CallerCapabilities.cjs.map +1 -0
  35. package/dist/cjs/tools/ProgrammaticCallerPolicy.cjs +34 -0
  36. package/dist/cjs/tools/ProgrammaticCallerPolicy.cjs.map +1 -0
  37. package/dist/cjs/tools/ProgrammaticToolCalling.cjs +21 -4
  38. package/dist/cjs/tools/ProgrammaticToolCalling.cjs.map +1 -1
  39. package/dist/cjs/tools/ToolNode.cjs +25 -24
  40. package/dist/cjs/tools/ToolNode.cjs.map +1 -1
  41. package/dist/cjs/tools/cloudflare/CloudflareProgrammaticToolCalling.cjs +12 -4
  42. package/dist/cjs/tools/cloudflare/CloudflareProgrammaticToolCalling.cjs.map +1 -1
  43. package/dist/cjs/tools/local/LocalProgrammaticToolCalling.cjs +13 -4
  44. package/dist/cjs/tools/local/LocalProgrammaticToolCalling.cjs.map +1 -1
  45. package/dist/cjs/tools/local/resolveLocalExecutionTools.cjs +47 -11
  46. package/dist/cjs/tools/local/resolveLocalExecutionTools.cjs.map +1 -1
  47. package/dist/cjs/tools/ptcTimeout.cjs.map +1 -1
  48. package/dist/cjs/utils/toolContent.cjs +2 -2
  49. package/dist/cjs/utils/toolContent.cjs.map +1 -1
  50. package/dist/esm/agents/AgentContext.mjs +46 -39
  51. package/dist/esm/agents/AgentContext.mjs.map +1 -1
  52. package/dist/esm/agents/projection.mjs +2 -2
  53. package/dist/esm/agents/projection.mjs.map +1 -1
  54. package/dist/esm/graphs/Graph.mjs +30 -20
  55. package/dist/esm/graphs/Graph.mjs.map +1 -1
  56. package/dist/esm/graphs/MultiAgentGraph.mjs +87 -16
  57. package/dist/esm/graphs/MultiAgentGraph.mjs.map +1 -1
  58. package/dist/esm/llm/openai/index.mjs +10 -0
  59. package/dist/esm/llm/openai/index.mjs.map +1 -1
  60. package/dist/esm/main.mjs +4 -3
  61. package/dist/esm/messages/alternation.mjs +125 -20
  62. package/dist/esm/messages/alternation.mjs.map +1 -1
  63. package/dist/esm/messages/core.mjs +196 -19
  64. package/dist/esm/messages/core.mjs.map +1 -1
  65. package/dist/esm/messages/format.mjs +488 -119
  66. package/dist/esm/messages/format.mjs.map +1 -1
  67. package/dist/esm/messages/handoffCue.mjs +3 -2
  68. package/dist/esm/messages/handoffCue.mjs.map +1 -1
  69. package/dist/esm/messages/index.mjs +1 -0
  70. package/dist/esm/messages/injected.mjs +5 -2
  71. package/dist/esm/messages/injected.mjs.map +1 -1
  72. package/dist/esm/messages/provenance.mjs +401 -0
  73. package/dist/esm/messages/provenance.mjs.map +1 -0
  74. package/dist/esm/messages/prune.mjs +18 -13
  75. package/dist/esm/messages/prune.mjs.map +1 -1
  76. package/dist/esm/messages/toolResultTypes.mjs +657 -0
  77. package/dist/esm/messages/toolResultTypes.mjs.map +1 -0
  78. package/dist/esm/run.mjs +7 -4
  79. package/dist/esm/run.mjs.map +1 -1
  80. package/dist/esm/tools/BashProgrammaticToolCalling.mjs +21 -4
  81. package/dist/esm/tools/BashProgrammaticToolCalling.mjs.map +1 -1
  82. package/dist/esm/tools/CallerCapabilities.mjs +45 -0
  83. package/dist/esm/tools/CallerCapabilities.mjs.map +1 -0
  84. package/dist/esm/tools/ProgrammaticCallerPolicy.mjs +32 -0
  85. package/dist/esm/tools/ProgrammaticCallerPolicy.mjs.map +1 -0
  86. package/dist/esm/tools/ProgrammaticToolCalling.mjs +21 -4
  87. package/dist/esm/tools/ProgrammaticToolCalling.mjs.map +1 -1
  88. package/dist/esm/tools/ToolNode.mjs +25 -24
  89. package/dist/esm/tools/ToolNode.mjs.map +1 -1
  90. package/dist/esm/tools/cloudflare/CloudflareProgrammaticToolCalling.mjs +14 -6
  91. package/dist/esm/tools/cloudflare/CloudflareProgrammaticToolCalling.mjs.map +1 -1
  92. package/dist/esm/tools/local/LocalProgrammaticToolCalling.mjs +15 -6
  93. package/dist/esm/tools/local/LocalProgrammaticToolCalling.mjs.map +1 -1
  94. package/dist/esm/tools/local/resolveLocalExecutionTools.mjs +47 -12
  95. package/dist/esm/tools/local/resolveLocalExecutionTools.mjs.map +1 -1
  96. package/dist/esm/tools/ptcTimeout.mjs.map +1 -1
  97. package/dist/esm/utils/toolContent.mjs +2 -2
  98. package/dist/esm/utils/toolContent.mjs.map +1 -1
  99. package/dist/types/agents/AgentContext.d.ts +8 -13
  100. package/dist/types/agents/projection.d.ts +3 -1
  101. package/dist/types/graphs/Graph.d.ts +1 -1
  102. package/dist/types/llm/openai/index.d.ts +20 -0
  103. package/dist/types/messages/format.d.ts +5 -0
  104. package/dist/types/messages/index.d.ts +1 -0
  105. package/dist/types/messages/provenance.d.ts +85 -0
  106. package/dist/types/messages/toolResultTypes.d.ts +33 -0
  107. package/dist/types/tools/CallerCapabilities.d.ts +12 -0
  108. package/dist/types/tools/ProgrammaticCallerPolicy.d.ts +20 -0
  109. package/dist/types/tools/ToolNode.d.ts +4 -7
  110. package/dist/types/tools/local/resolveLocalExecutionTools.d.ts +4 -0
  111. package/dist/types/tools/ptcTimeout.d.ts +8 -0
  112. package/dist/types/types/graph.d.ts +3 -1
  113. package/dist/types/types/tools.d.ts +13 -2
  114. package/package.json +1 -1
  115. package/src/agents/AgentContext.ts +109 -67
  116. package/src/agents/projection.ts +9 -1
  117. package/src/graphs/Graph.ts +56 -23
  118. package/src/graphs/MultiAgentGraph.ts +175 -33
  119. package/src/llm/openai/index.ts +43 -0
  120. package/src/messages/alternation.ts +217 -34
  121. package/src/messages/core.ts +358 -38
  122. package/src/messages/format.ts +958 -137
  123. package/src/messages/handoffCue.ts +7 -4
  124. package/src/messages/index.ts +1 -0
  125. package/src/messages/injected.ts +9 -6
  126. package/src/messages/provenance.ts +897 -0
  127. package/src/messages/prune.ts +28 -10
  128. package/src/messages/toolResultTypes.ts +1174 -0
  129. package/src/run.ts +9 -4
  130. package/src/tools/BashProgrammaticToolCalling.ts +46 -12
  131. package/src/tools/CallerCapabilities.ts +78 -0
  132. package/src/tools/ProgrammaticCallerPolicy.ts +97 -0
  133. package/src/tools/ProgrammaticToolCalling.ts +41 -7
  134. package/src/tools/ToolNode.ts +70 -52
  135. package/src/tools/cloudflare/CloudflareProgrammaticToolCalling.ts +24 -26
  136. package/src/tools/local/LocalProgrammaticToolCalling.ts +28 -23
  137. package/src/tools/local/resolveLocalExecutionTools.ts +132 -13
  138. package/src/tools/ptcTimeout.ts +6 -0
  139. package/src/types/graph.ts +3 -0
  140. package/src/types/tools.ts +14 -3
  141. package/src/utils/toolContent.ts +2 -2
@@ -2,7 +2,9 @@ import "../common/enum.mjs";
2
2
  import "../common/index.mjs";
3
3
  import { HARD_MAX_TOOL_RESULT_CHARS } from "../utils/truncation.mjs";
4
4
  import { compactToolContent, getToolContentCharLength, isAtomicToolContentBlock, serializeStructuredValueBounded } from "../utils/toolContent.mjs";
5
+ import { hasBijectiveProviderContentPartMapping, inspectProviderMessageProvenance, inspectProviderSourceMessageIds, setInvalidProviderMessageProvenance, setProviderMessageProvenance } from "./provenance.mjs";
5
6
  import { toLangChainContent, toLangChainMessageFields } from "./langchain.mjs";
7
+ import { appendProviderToolCallDescriptor, consumeProviderToolResultPair, getBoundedProviderPairingArrayProperty, getProviderToolCallPartDescriptor, getProviderToolResultPartDescriptor, hasStructurallyValidAnthropicWebSearchResultContent } from "./toolResultTypes.mjs";
6
8
  import { normalizeAnthropicToolCallId } from "../llm/anthropic/utils/message_inputs.mjs";
7
9
  import { emitAgentLog } from "../utils/events.mjs";
8
10
  import { AIMessage, AIMessageChunk, HumanMessage, SystemMessage, ToolMessage } from "@langchain/core/messages";
@@ -57,10 +59,10 @@ const formatMessage = ({ message, userName, endpoint, assistantName, langChain =
57
59
  }
58
60
  const { image_urls, documents, videos, audios } = message;
59
61
  const mediaParts = [];
60
- if (Array.isArray(documents) && documents.length > 0) mediaParts.push(...documents);
61
- if (Array.isArray(videos) && videos.length > 0) mediaParts.push(...videos);
62
- if (Array.isArray(audios) && audios.length > 0) mediaParts.push(...audios);
63
- if (Array.isArray(image_urls) && image_urls.length > 0) mediaParts.push(...image_urls);
62
+ if (Array.isArray(documents) && documents.length > 0) for (const document of documents) mediaParts.push(document);
63
+ if (Array.isArray(videos) && videos.length > 0) for (const video of videos) mediaParts.push(video);
64
+ if (Array.isArray(audios) && audios.length > 0) for (const audio of audios) mediaParts.push(audio);
65
+ if (Array.isArray(image_urls) && image_urls.length > 0) for (const imageUrl of image_urls) mediaParts.push(imageUrl);
64
66
  if (mediaParts.length > 0 && role === "user") {
65
67
  const mediaMessage = formatMediaMessage({
66
68
  message: {
@@ -137,10 +139,45 @@ function getToolUseId(part) {
137
139
  if (!("tool_use_id" in part) || typeof part.tool_use_id !== "string") return;
138
140
  return part.tool_use_id;
139
141
  }
140
- function isValidServerToolResult(part) {
141
- if (getToolUseId(part)?.startsWith("srvtoolu_") !== true || !("content" in part)) return false;
142
- const { content } = part;
143
- return Array.isArray(content) || content != null && typeof content === "object" && "type" in content && content.type === "web_search_tool_result_error";
142
+ function collectTrustedToolResultSourceContentPartIndices(content, sourceContentPartOffset) {
143
+ if (content == null) return;
144
+ let calls;
145
+ let trusted;
146
+ let previousPart;
147
+ for (let index = 0; index < content.length; index++) {
148
+ const part = content[index];
149
+ if (part == null) {
150
+ previousPart = part;
151
+ continue;
152
+ }
153
+ const call = getProviderToolCallPartDescriptor(part);
154
+ if (call != null) {
155
+ calls ??= /* @__PURE__ */ new Map();
156
+ appendProviderToolCallDescriptor(calls, call);
157
+ }
158
+ const result = getProviderToolResultPartDescriptor(part);
159
+ if (result != null) {
160
+ calls ??= /* @__PURE__ */ new Map();
161
+ if (consumeProviderToolResultPair(result, calls, previousPart)) {
162
+ trusted ??= /* @__PURE__ */ new Set();
163
+ trusted.add(sourceContentPartOffset + index);
164
+ }
165
+ }
166
+ previousPart = part;
167
+ }
168
+ return trusted;
169
+ }
170
+ function sourceContentPartIndicesAreTrustedToolResult(sourceContentPartIndices, trustedToolSourceContentPartIndices) {
171
+ if (typeof sourceContentPartIndices === "number") return trustedToolSourceContentPartIndices?.has(sourceContentPartIndices) === true;
172
+ if (sourceContentPartIndices.length === 0) return false;
173
+ for (const sourceContentPartIndex of sourceContentPartIndices) if (trustedToolSourceContentPartIndices?.has(sourceContentPartIndex) !== true) return false;
174
+ return true;
175
+ }
176
+ function isTrustedServerToolResult(part, sourceContentPartIndices, trustedToolSourceContentPartIndices) {
177
+ return getToolUseId(part)?.startsWith("srvtoolu_") === true && sourceContentPartIndicesAreTrustedToolResult(sourceContentPartIndices, trustedToolSourceContentPartIndices);
178
+ }
179
+ function isServerToolResultForWire(part) {
180
+ return getToolUseId(part)?.startsWith("srvtoolu_") === true && hasStructurallyValidAnthropicWebSearchResultContent(part);
144
181
  }
145
182
  function getToolCallId(part) {
146
183
  if (part.type !== "tool_call") return;
@@ -161,44 +198,148 @@ function endsWithSteerMessage(formatted) {
161
198
  if (formatted.length === 0) return false;
162
199
  return formatted[formatted.length - 1].additional_kwargs.source === "steer";
163
200
  }
201
+ function createProviderMessageProvenanceBuilder() {
202
+ return { parts: [] };
203
+ }
204
+ function appendProviderProvenanceContribution(builder, attribution, sourceMessageId, sourceContentPartIndex) {
205
+ const last = builder.parts[builder.parts.length - 1];
206
+ if (builder.parts.length === 0 || last.attribution !== attribution || last.sourceMessageId !== sourceMessageId || last.sourceContentPartIndices == null !== (sourceContentPartIndex == null)) {
207
+ builder.parts.push({
208
+ attribution,
209
+ ...sourceMessageId != null && { sourceMessageId },
210
+ ...sourceContentPartIndex != null && { sourceContentPartIndices: [sourceContentPartIndex] }
211
+ });
212
+ builder.lastSeenSourceContentPartIndices = void 0;
213
+ return;
214
+ }
215
+ if (sourceContentPartIndex == null) return;
216
+ const sourceContentPartIndices = last.sourceContentPartIndices ??= [];
217
+ if (sourceContentPartIndices.length === 0) {
218
+ sourceContentPartIndices.push(sourceContentPartIndex);
219
+ return;
220
+ }
221
+ const seen = builder.lastSeenSourceContentPartIndices ??= new Set(sourceContentPartIndices);
222
+ if (!seen.has(sourceContentPartIndex)) {
223
+ seen.add(sourceContentPartIndex);
224
+ sourceContentPartIndices.push(sourceContentPartIndex);
225
+ }
226
+ }
227
+ function appendProviderProvenanceIndices(builder, attribution, sourceMessageId, sourceContentPartIndices, toolSourceContentPartIndices) {
228
+ if (typeof sourceContentPartIndices === "number") {
229
+ appendProviderProvenanceContribution(builder, toolSourceContentPartIndices?.has(sourceContentPartIndices) === true ? "tool" : attribution, sourceMessageId, sourceContentPartIndices);
230
+ return;
231
+ }
232
+ if (sourceContentPartIndices == null || sourceContentPartIndices.length === 0) {
233
+ appendProviderProvenanceContribution(builder, attribution, sourceMessageId);
234
+ return;
235
+ }
236
+ for (const sourceContentPartIndex of sourceContentPartIndices) appendProviderProvenanceContribution(builder, toolSourceContentPartIndices?.has(sourceContentPartIndex) === true ? "tool" : attribution, sourceMessageId, sourceContentPartIndex);
237
+ }
238
+ function appendSourceContentPartIndices(target, sourceContentPartIndices) {
239
+ if (typeof sourceContentPartIndices === "number") target.push(sourceContentPartIndices);
240
+ else for (const sourceContentPartIndex of sourceContentPartIndices) target.push(sourceContentPartIndex);
241
+ }
242
+ function appendProviderProvenanceParts(builder, parts) {
243
+ for (const part of parts) appendProviderProvenanceIndices(builder, part.attribution, part.sourceMessageId, part.sourceContentPartIndices);
244
+ }
245
+ function mergeAdjacentProviderProvenanceParts(parts) {
246
+ const builder = createProviderMessageProvenanceBuilder();
247
+ appendProviderProvenanceParts(builder, parts);
248
+ return builder.parts;
249
+ }
250
+ function createProviderContentProvenanceParts(content, sourceContentPartOffset, sourceMessageId, defaultAttribution) {
251
+ const builder = createProviderMessageProvenanceBuilder();
252
+ for (let index = 0; index < content.length; index++) {
253
+ if (content[index] == null) continue;
254
+ appendProviderProvenanceContribution(builder, defaultAttribution, sourceMessageId, sourceContentPartOffset + index);
255
+ }
256
+ return builder.parts;
257
+ }
164
258
  function formatAssistantMessage(message, options) {
165
259
  const formattedMessages = [];
166
- const appendFormattedMessage = (formattedMessage) => {
167
- stampSourceMessageIdentity(formattedMessage, options?.sourceMessageId, formattedMessages.length);
260
+ const formattedMessageProvenance = /* @__PURE__ */ new Map();
261
+ const appendFormattedMessage = (formattedMessage, attribution, sourceContentPartIndices, provenanceBuilder) => {
262
+ const builder = provenanceBuilder ?? createProviderMessageProvenanceBuilder();
263
+ if (provenanceBuilder == null) appendProviderProvenanceIndices(builder, attribution, options?.sourceMessageId, sourceContentPartIndices);
264
+ formattedMessageProvenance.set(formattedMessage, builder);
168
265
  formattedMessages.push(formattedMessage);
169
266
  };
267
+ const finalizeFormattedMessages = () => {
268
+ for (let index = 0; index < formattedMessages.length; index++) {
269
+ const formattedMessage = formattedMessages[index];
270
+ stampSourceMessageIdentity(formattedMessage, options?.sourceMessageId, index, "model", void 0, formattedMessageProvenance.get(formattedMessage)?.parts);
271
+ }
272
+ return formattedMessages;
273
+ };
274
+ const appendSourcePartIndices = (formattedMessage, attribution, sourceContentPartIndices) => {
275
+ const builder = formattedMessageProvenance.get(formattedMessage);
276
+ if (builder == null) return;
277
+ appendProviderProvenanceIndices(builder, attribution, options?.sourceMessageId, sourceContentPartIndices);
278
+ };
279
+ const getSourcePartIndices = (partIndex) => options?.sourceContentPartIndices?.[partIndex] ?? (options?.sourceContentPartOffset ?? 0) + partIndex;
280
+ const createSourceProvenanceBuilder = (sourceContentPartIndices, attribution, applyToolOverrides = false) => {
281
+ const builder = createProviderMessageProvenanceBuilder();
282
+ appendProviderProvenanceIndices(builder, attribution, options?.sourceMessageId, sourceContentPartIndices, applyToolOverrides ? options?.toolSourceContentPartIndices : void 0);
283
+ return builder;
284
+ };
170
285
  let currentContent = [];
286
+ let currentContentProvenance = createProviderMessageProvenanceBuilder();
287
+ const appendCurrentContentProvenance = (sourceContentPartIndices, attribution, applyToolOverrides = false) => {
288
+ appendProviderProvenanceIndices(currentContentProvenance, attribution, options?.sourceMessageId, sourceContentPartIndices, applyToolOverrides ? options?.toolSourceContentPartIndices : void 0);
289
+ };
171
290
  let lastAIMessage = null;
172
291
  let hasReasoning = false;
173
292
  let pendingReasoningContent = "";
293
+ let pendingReasoningSourcePartIndices = [];
174
294
  const emittedServerToolUseIds = /* @__PURE__ */ new Set();
175
295
  const pendingServerToolUses = /* @__PURE__ */ new Map();
176
296
  const shouldPreserveReasoningContent = options?.preserveReasoningContent === true;
177
297
  const serverToolResultIds = /* @__PURE__ */ new Set();
178
298
  const preferredToolCallParts = /* @__PURE__ */ new Map();
179
299
  const takePendingReasoningContent = () => {
180
- if (!shouldPreserveReasoningContent || !pendingReasoningContent) return;
181
- const reasoningContent = pendingReasoningContent;
300
+ if (!shouldPreserveReasoningContent || !pendingReasoningContent) return { sourceContentPartIndices: [] };
301
+ const content = pendingReasoningContent;
302
+ const sourceContentPartIndices = pendingReasoningSourcePartIndices;
182
303
  pendingReasoningContent = "";
183
- return reasoningContent;
304
+ pendingReasoningSourcePartIndices = [];
305
+ return {
306
+ content,
307
+ sourceContentPartIndices
308
+ };
184
309
  };
185
310
  const createAIMessage = (content) => {
186
- const reasoningContent = takePendingReasoningContent();
187
- return withMessageRole(new AIMessage({
188
- content,
189
- ...reasoningContent != null && { additional_kwargs: { reasoning_content: reasoningContent } }
190
- }), "assistant");
311
+ const reasoning = takePendingReasoningContent();
312
+ return {
313
+ message: withMessageRole(new AIMessage({
314
+ content,
315
+ ...reasoning.content != null && { additional_kwargs: { reasoning_content: reasoning.content } }
316
+ }), "assistant"),
317
+ reasoningSourceContentPartIndices: reasoning.sourceContentPartIndices
318
+ };
319
+ };
320
+ const appendAIMessage = (content, provenance) => {
321
+ const created = createAIMessage(content);
322
+ let combinedProvenance = provenance;
323
+ if (created.reasoningSourceContentPartIndices.length > 0) {
324
+ combinedProvenance = createProviderMessageProvenanceBuilder();
325
+ appendProviderProvenanceIndices(combinedProvenance, "model", options?.sourceMessageId, created.reasoningSourceContentPartIndices);
326
+ appendProviderProvenanceParts(combinedProvenance, provenance.parts);
327
+ }
328
+ appendFormattedMessage(created.message, "model", void 0, combinedProvenance);
329
+ return created.message;
191
330
  };
192
331
  const attachPendingReasoningContent = (aiMessage) => {
193
- const reasoningContent = takePendingReasoningContent();
194
- if (reasoningContent == null) return;
195
- aiMessage.additional_kwargs.reasoning_content = typeof aiMessage.additional_kwargs.reasoning_content === "string" ? `${aiMessage.additional_kwargs.reasoning_content}${reasoningContent}` : reasoningContent;
332
+ const reasoning = takePendingReasoningContent();
333
+ if (reasoning.content == null) return;
334
+ aiMessage.additional_kwargs.reasoning_content = typeof aiMessage.additional_kwargs.reasoning_content === "string" ? `${aiMessage.additional_kwargs.reasoning_content}${reasoning.content}` : reasoning.content;
335
+ appendSourcePartIndices(aiMessage, "model", reasoning.sourceContentPartIndices);
196
336
  };
197
337
  const flushPendingServerToolUse = (toolUseId) => {
198
- for (const [id, content] of pendingServerToolUses) {
338
+ for (const [id, pending] of pendingServerToolUses) {
199
339
  pendingServerToolUses.delete(id);
200
340
  if (id === toolUseId) {
201
- currentContent.push(content);
341
+ currentContent.push(pending.content);
342
+ appendCurrentContentProvenance(pending.sourceContentPartIndices, "model", true);
202
343
  emittedServerToolUseIds.add(id);
203
344
  return;
204
345
  }
@@ -206,9 +347,21 @@ function formatAssistantMessage(message, options) {
206
347
  };
207
348
  if (Array.isArray(message.content)) {
208
349
  const contentParts = message.content;
209
- for (const part of contentParts) {
350
+ let trustedServerToolResultPartIndices;
351
+ let wireServerToolResultPartIndices;
352
+ for (let partIndex = 0; partIndex < contentParts.length; partIndex++) {
353
+ const part = contentParts[partIndex];
210
354
  if (part == null) continue;
211
- if (isValidServerToolResult(part)) serverToolResultIds.add(getToolUseId(part) ?? "");
355
+ const isTrustedResult = isTrustedServerToolResult(part, getSourcePartIndices(partIndex), options?.toolSourceContentPartIndices);
356
+ if (isTrustedResult) {
357
+ trustedServerToolResultPartIndices ??= /* @__PURE__ */ new Set();
358
+ trustedServerToolResultPartIndices.add(partIndex);
359
+ }
360
+ if (isTrustedResult || isServerToolResultForWire(part)) {
361
+ wireServerToolResultPartIndices ??= /* @__PURE__ */ new Set();
362
+ wireServerToolResultPartIndices.add(partIndex);
363
+ serverToolResultIds.add(getToolUseId(part) ?? "");
364
+ }
212
365
  if (options?.provider === "anthropic") {
213
366
  const toolCallId = getToolCallId(part);
214
367
  if (toolCallId == null) continue;
@@ -216,15 +369,18 @@ function formatAssistantMessage(message, options) {
216
369
  if (preferredPart == null || !hasToolCallOutput(preferredPart) && hasToolCallOutput(part)) preferredToolCallParts.set(toolCallId, part);
217
370
  }
218
371
  }
219
- for (const part of contentParts) {
372
+ for (let partIndex = 0; partIndex < contentParts.length; partIndex++) {
373
+ const part = contentParts[partIndex];
220
374
  if (part == null) continue;
375
+ const sourcePartIndices = getSourcePartIndices(partIndex);
221
376
  const toolUseId = getToolUseId(part);
222
377
  if (toolUseId != null) {
223
- const isServerToolResult = isValidServerToolResult(part);
224
- if (toolUseId.startsWith("srvtoolu_") && !isServerToolResult) continue;
378
+ const isServerToolResult = trustedServerToolResultPartIndices?.has(partIndex) === true;
379
+ const isWireServerToolResult = wireServerToolResultPartIndices?.has(partIndex) === true;
225
380
  flushPendingServerToolUse(toolUseId);
226
- if (isServerToolResult) {
381
+ if (isWireServerToolResult) {
227
382
  currentContent.push(part);
383
+ appendCurrentContentProvenance(sourcePartIndices, isServerToolResult ? "tool" : "model", !isServerToolResult);
228
384
  continue;
229
385
  }
230
386
  } else if (hasMeaningfulAssistantContent(part)) {
@@ -234,9 +390,10 @@ function formatAssistantMessage(message, options) {
234
390
  if (currentContent.length > 0) {
235
391
  if (currentContent.some((content) => content.type !== "text")) {
236
392
  currentContent.push(part);
237
- lastAIMessage = createAIMessage(toLangChainContent(currentContent));
238
- appendFormattedMessage(lastAIMessage);
393
+ appendCurrentContentProvenance(sourcePartIndices, "model", true);
394
+ lastAIMessage = appendAIMessage(toLangChainContent(currentContent), currentContentProvenance);
239
395
  currentContent = [];
396
+ currentContentProvenance = createProviderMessageProvenanceBuilder();
240
397
  continue;
241
398
  }
242
399
  let content = currentContent.reduce((acc, curr) => {
@@ -244,13 +401,13 @@ function formatAssistantMessage(message, options) {
244
401
  return acc;
245
402
  }, "");
246
403
  content = `${content}\n${getTextContent(part)}`.trim();
247
- lastAIMessage = createAIMessage(content);
248
- appendFormattedMessage(lastAIMessage);
404
+ appendCurrentContentProvenance(sourcePartIndices, "model", true);
405
+ lastAIMessage = appendAIMessage(content, currentContentProvenance);
249
406
  currentContent = [];
407
+ currentContentProvenance = createProviderMessageProvenanceBuilder();
250
408
  continue;
251
409
  }
252
- lastAIMessage = createAIMessage(getTextContent(part));
253
- appendFormattedMessage(lastAIMessage);
410
+ lastAIMessage = appendAIMessage(getTextContent(part), createSourceProvenanceBuilder(sourcePartIndices, "model", true));
254
411
  } else if (part.type === "tool_call") {
255
412
  if (part.tool_call == null) continue;
256
413
  const toolCallId = getToolCallId(part);
@@ -261,17 +418,21 @@ function formatAssistantMessage(message, options) {
261
418
  if (!serverToolResultIds.has(_tool_call.id) && options.preserveUnpairedServerToolUses !== true) continue;
262
419
  if (emittedServerToolUseIds.has(_tool_call.id) || pendingServerToolUses.has(_tool_call.id)) continue;
263
420
  pendingServerToolUses.set(_tool_call.id, {
264
- type: "server_tool_use",
265
- id: _tool_call.id,
266
- name: _tool_call.name,
267
- input: parseServerToolInput(_args)
421
+ content: {
422
+ type: "server_tool_use",
423
+ id: _tool_call.id,
424
+ name: _tool_call.name,
425
+ input: parseServerToolInput(_args)
426
+ },
427
+ sourceContentPartIndices: sourcePartIndices
268
428
  });
269
429
  continue;
270
430
  }
271
- if (!lastAIMessage) {
272
- lastAIMessage = createAIMessage("");
273
- appendFormattedMessage(lastAIMessage);
274
- } else attachPendingReasoningContent(lastAIMessage);
431
+ if (!lastAIMessage) lastAIMessage = appendAIMessage("", createSourceProvenanceBuilder(sourcePartIndices, "model"));
432
+ else {
433
+ attachPendingReasoningContent(lastAIMessage);
434
+ appendSourcePartIndices(lastAIMessage, "model", sourcePartIndices);
435
+ }
275
436
  const tool_call = _tool_call;
276
437
  let args = _args;
277
438
  try {
@@ -297,28 +458,22 @@ function formatAssistantMessage(message, options) {
297
458
  tool_call_id: tool_call.id ?? "",
298
459
  name: tool_call.name,
299
460
  content: formatToolCallOutput(output)
300
- }), "tool"));
461
+ }), "tool"), "tool", sourcePartIndices);
301
462
  } else if (part.type === "think" || part.type === "thinking" || part.type === "reasoning" || part.type === "reasoning_content" || part.type === "redacted_thinking") {
302
463
  hasReasoning = true;
303
464
  pendingReasoningContent += extractReasoningContent(part);
465
+ appendSourceContentPartIndices(pendingReasoningSourcePartIndices, sourcePartIndices);
304
466
  continue;
305
467
  } else if (part.type === "steer") {
306
468
  if (currentContent.length > 0) {
307
- if (currentContent.some((content) => content.type !== "text")) {
308
- lastAIMessage = createAIMessage(toLangChainContent(currentContent));
309
- appendFormattedMessage(lastAIMessage);
310
- } else {
469
+ if (currentContent.some((content) => content.type !== "text")) appendAIMessage(toLangChainContent(currentContent), currentContentProvenance);
470
+ else {
311
471
  const flushed = currentContent.reduce((acc, curr) => `${acc}${getTextContent(curr)}\n`, "").trim();
312
- if (flushed.length > 0) {
313
- lastAIMessage = createAIMessage(flushed);
314
- appendFormattedMessage(lastAIMessage);
315
- }
472
+ if (flushed.length > 0) appendAIMessage(flushed, currentContentProvenance);
316
473
  }
317
474
  currentContent = [];
318
- } else if (shouldPreserveReasoningContent && pendingReasoningContent) {
319
- lastAIMessage = createAIMessage("");
320
- appendFormattedMessage(lastAIMessage);
321
- }
475
+ currentContentProvenance = createProviderMessageProvenanceBuilder();
476
+ } else if (shouldPreserveReasoningContent && pendingReasoningContent) appendAIMessage("", createProviderMessageProvenanceBuilder());
322
477
  const steerPart = part;
323
478
  appendFormattedMessage(withMessageRole(new HumanMessage({
324
479
  content: Array.isArray(steerPart.media) && steerPart.media.length > 0 ? toLangChainContent(steerPart.media) : steerPart.steer ?? "",
@@ -326,42 +481,71 @@ function formatAssistantMessage(message, options) {
326
481
  role: "user",
327
482
  source: "steer"
328
483
  }
329
- }), "user"));
484
+ }), "user"), "user", sourcePartIndices);
330
485
  lastAIMessage = null;
331
486
  hasReasoning = false;
332
487
  pendingReasoningContent = "";
488
+ pendingReasoningSourcePartIndices = [];
333
489
  } else if (part.type === "error" || part.type === "agent_update" || part.type === "summary" || part.type === "activity_label") continue;
334
490
  else {
335
491
  if (part.type === "text" && !getTextContent(part).trim()) continue;
336
492
  currentContent.push(part);
493
+ appendCurrentContentProvenance(sourcePartIndices, "model", true);
337
494
  }
338
495
  }
339
- for (const content of pendingServerToolUses.values()) currentContent.push(content);
496
+ for (const pending of pendingServerToolUses.values()) {
497
+ currentContent.push(pending.content);
498
+ appendCurrentContentProvenance(pending.sourceContentPartIndices, "model", true);
499
+ }
340
500
  }
341
501
  if (hasReasoning && currentContent.length > 0) {
342
502
  let content = "";
343
503
  for (const part of currentContent) {
344
504
  if (part.type !== "text") {
345
- appendFormattedMessage(createAIMessage(toLangChainContent(currentContent)));
346
- return formattedMessages;
505
+ appendAIMessage(toLangChainContent(currentContent), currentContentProvenance);
506
+ return finalizeFormattedMessages();
347
507
  }
348
508
  content += `${getTextContent(part)}\n`;
349
509
  }
350
510
  content = content.trim();
351
- if (content) appendFormattedMessage(createAIMessage(content));
352
- } else if (currentContent.length > 0) appendFormattedMessage(createAIMessage(toLangChainContent(currentContent)));
353
- return formattedMessages;
511
+ if (content) appendAIMessage(content, currentContentProvenance);
512
+ } else if (currentContent.length > 0) appendAIMessage(toLangChainContent(currentContent), currentContentProvenance);
513
+ return finalizeFormattedMessages();
354
514
  }
355
515
  function getSourceMessageId(message) {
356
- const candidate = message.messageId ?? message.id;
357
- if (typeof candidate !== "string") return;
358
- const normalized = candidate.trim();
359
- return normalized.length > 0 ? normalized : void 0;
516
+ const candidates = [message.messageId, message.id];
517
+ for (const candidate of candidates) {
518
+ if (typeof candidate !== "string") continue;
519
+ const normalized = candidate.trim();
520
+ if (normalized.length > 0) return normalized;
521
+ }
360
522
  }
361
- function stampSourceMessageIdentity(message, sourceMessageId, derivedIndex = 0) {
362
- if (sourceMessageId == null) return;
363
- message.additional_kwargs.sourceMessageId = sourceMessageId;
364
- if (derivedIndex !== 0) return;
523
+ function stampSourceMessageIdentity(message, sourceMessageId, derivedIndex = 0, attribution = "model", sourceContentPartIndices, provenanceParts) {
524
+ if (sourceMessageId != null) message.additional_kwargs.sourceMessageId = sourceMessageId;
525
+ let partsToStamp;
526
+ if (provenanceParts != null && provenanceParts.length > 0) {
527
+ let needsSourceMessageId = false;
528
+ if (sourceMessageId != null) {
529
+ for (const part of provenanceParts) if (part.sourceMessageId == null) {
530
+ needsSourceMessageId = true;
531
+ break;
532
+ }
533
+ }
534
+ if (needsSourceMessageId) {
535
+ const completedParts = [];
536
+ for (const part of provenanceParts) completedParts.push({
537
+ ...part,
538
+ ...part.sourceMessageId == null && { sourceMessageId }
539
+ });
540
+ partsToStamp = completedParts;
541
+ } else partsToStamp = provenanceParts;
542
+ } else partsToStamp = [{
543
+ attribution,
544
+ ...sourceMessageId != null && { sourceMessageId },
545
+ ...sourceContentPartIndices != null && { sourceContentPartIndices }
546
+ }];
547
+ setProviderMessageProvenance(message, partsToStamp);
548
+ if (sourceMessageId == null || derivedIndex !== 0) return;
365
549
  message.id = sourceMessageId;
366
550
  message.lc_kwargs.id = sourceMessageId;
367
551
  }
@@ -393,7 +577,7 @@ function labelAllAgentContent(contentParts, agentIdMap, agentNames) {
393
577
  type: "text",
394
578
  text: formattedParts.join("\n\n")
395
579
  });
396
- } else result.push(...agentContentBuffer);
580
+ } else for (const part of agentContentBuffer) result.push(part);
397
581
  agentContentBuffer = [];
398
582
  };
399
583
  for (let i = 0; i < contentParts.length; i++) {
@@ -445,7 +629,7 @@ const labelContentByAgent = (contentParts, agentIdMap, agentNames, options) => {
445
629
  const transferToolCall = result[transferToolCallIndex];
446
630
  if (transferToolCall.type === "tool_call" && transferToolCall.tool_call?.id === transferToolCallId) transferToolCall.tool_call.output = formattedParts.join("\n\n");
447
631
  }
448
- } else result.push(...agentContentBuffer);
632
+ } else for (const part of agentContentBuffer) result.push(part);
449
633
  agentContentBuffer = [];
450
634
  transferToolCallIndex = void 0;
451
635
  transferToolCallId = void 0;
@@ -583,7 +767,9 @@ const formatAgentMessages = (payload, indexTokenCountMap, tools, skills, options
583
767
  if (!pendingSteerAnchor) return;
584
768
  pendingSteerAnchor = false;
585
769
  if (next.role === "assistant") return;
586
- messages.push(withMessageRole(new AIMessage({ content: STEER_ANCHOR_PLACEHOLDER }), "assistant"));
770
+ const anchor = withMessageRole(new AIMessage({ content: STEER_ANCHOR_PLACEHOLDER }), "assistant");
771
+ stampSourceMessageIdentity(anchor, void 0, 0, "synthetic");
772
+ messages.push(anchor);
587
773
  };
588
774
  const updatedIndexTokenCountMap = {};
589
775
  let boundaryTokenAdjustment;
@@ -598,6 +784,7 @@ const formatAgentMessages = (payload, indexTokenCountMap, tools, skills, options
598
784
  indexMapping[i] = [];
599
785
  continue;
600
786
  }
787
+ const sourceContentPartOffset = summaryBoundary?.mode === "positional" && summaryBoundary.messageIndex === i ? summaryBoundary.contentIndex + 1 : 0;
601
788
  if (typeof message.content === "string") message = {
602
789
  ...message,
603
790
  content: [{
@@ -614,7 +801,11 @@ const formatAgentMessages = (payload, indexTokenCountMap, tools, skills, options
614
801
  message,
615
802
  langChain: true
616
803
  });
617
- stampSourceMessageIdentity(formattedMessage, sourceMessageId);
804
+ let attribution = "synthetic";
805
+ if (formattedMessage.role === "user") attribution = "user";
806
+ else if (formattedMessage.role === "assistant") attribution = "model";
807
+ const provenanceParts = createProviderContentProvenanceParts(message.content, sourceContentPartOffset, sourceMessageId, attribution);
808
+ stampSourceMessageIdentity(formattedMessage, sourceMessageId, 0, attribution, void 0, provenanceParts);
618
809
  flushSteerAnchor(formattedMessage);
619
810
  messages.push(formattedMessage);
620
811
  indexMapping[i] = [messages.length - 1];
@@ -622,16 +813,24 @@ const formatAgentMessages = (payload, indexTokenCountMap, tools, skills, options
622
813
  }
623
814
  const startMessageIndex = messages.length;
624
815
  let processedMessage = message;
816
+ let processedSourceContentPartIndices;
817
+ const processedToolSourceContentPartIndices = collectTrustedToolResultSourceContentPartIndices(getBoundedProviderPairingArrayProperty(message, "content"), sourceContentPartOffset);
625
818
  let pendingSkillNames;
626
819
  if (discoveredTools) {
627
820
  const content = message.content;
628
821
  if (content != null && Array.isArray(content)) {
629
822
  const filteredContent = [];
823
+ const filteredSourceContentPartIndices = [];
630
824
  const invalidToolCallIds = /* @__PURE__ */ new Set();
631
825
  const invalidToolStrings = [];
632
- for (const part of content) {
826
+ const invalidToolSourceContentPartIndices = [];
827
+ for (let partIndex = 0; partIndex < content.length; partIndex++) {
828
+ const part = content[partIndex];
829
+ const partSourceContentIndices = sourceContentPartOffset + partIndex;
830
+ if (part == null || typeof part !== "object") continue;
633
831
  if (part.type !== "tool_call") {
634
832
  filteredContent.push(part);
833
+ filteredSourceContentPartIndices.push(partSourceContentIndices);
635
834
  continue;
636
835
  }
637
836
  if (part.tool_call == null || part.tool_call.name == null || part.tool_call.name === "") {
@@ -645,6 +844,7 @@ const formatAgentMessages = (payload, indexTokenCountMap, tools, skills, options
645
844
  }
646
845
  if (discoveredTools.has(toolName)) {
647
846
  filteredContent.push(part);
847
+ filteredSourceContentPartIndices.push(partSourceContentIndices);
648
848
  if (toolName === "skill" && skills?.size != null && skills.size > 0) {
649
849
  const skillName = extractSkillName(part.tool_call.args) ?? "";
650
850
  if (skillName) (pendingSkillNames ??= /* @__PURE__ */ new Set()).add(skillName);
@@ -653,6 +853,7 @@ const formatAgentMessages = (payload, indexTokenCountMap, tools, skills, options
653
853
  if (typeof part.tool_call.id === "string" && part.tool_call.id !== "") invalidToolCallIds.add(part.tool_call.id);
654
854
  const output = part.tool_call.output ?? "";
655
855
  invalidToolStrings.push(`Tool: ${toolName}, ${output}`);
856
+ appendSourceContentPartIndices(invalidToolSourceContentPartIndices, partSourceContentIndices);
656
857
  }
657
858
  }
658
859
  if (invalidToolCallIds.size > 0) {
@@ -675,21 +876,29 @@ const formatAgentMessages = (payload, indexTokenCountMap, tools, skills, options
675
876
  ...lastTextPart,
676
877
  ["text"]: existingText ? `${existingText}\n${invalidToolText}` : invalidToolText
677
878
  };
678
- } else filteredContent.push({
679
- type: "text",
680
- ["text"]: invalidToolText
681
- });
879
+ const lastTextSourceContentPartIndices = filteredSourceContentPartIndices[lastTextPartIndex];
880
+ filteredSourceContentPartIndices[lastTextPartIndex] = [...typeof lastTextSourceContentPartIndices === "number" ? [lastTextSourceContentPartIndices] : lastTextSourceContentPartIndices, ...invalidToolSourceContentPartIndices];
881
+ } else {
882
+ filteredContent.push({
883
+ type: "text",
884
+ ["text"]: invalidToolText
885
+ });
886
+ filteredSourceContentPartIndices.push(invalidToolSourceContentPartIndices);
887
+ }
888
+ }
889
+ if (filteredContent.length !== content.length || invalidToolStrings.length > 0) {
890
+ processedMessage = {
891
+ ...message,
892
+ content: filteredContent
893
+ };
894
+ processedSourceContentPartIndices = filteredSourceContentPartIndices;
682
895
  }
683
- if (filteredContent.length !== content.length || invalidToolStrings.length > 0) processedMessage = {
684
- ...message,
685
- content: filteredContent
686
- };
687
896
  }
688
897
  }
689
898
  if (!discoveredTools && skills?.size != null && skills.size > 0) {
690
899
  const content = processedMessage.content;
691
900
  if (Array.isArray(content)) for (const part of content) {
692
- if (part.type !== "tool_call" || part.tool_call?.name !== "skill") continue;
901
+ if (part == null || typeof part !== "object" || part.type !== "tool_call" || part.tool_call?.name !== "skill") continue;
693
902
  const skillName = extractSkillName(part.tool_call.args) ?? "";
694
903
  if (skillName) (pendingSkillNames ??= /* @__PURE__ */ new Set()).add(skillName);
695
904
  }
@@ -698,10 +907,13 @@ const formatAgentMessages = (payload, indexTokenCountMap, tools, skills, options
698
907
  preserveUnpairedServerToolUses: i === payload.length - 1,
699
908
  preserveReasoningContent: options?.preserveReasoningContent ?? options?.provider === "deepseek",
700
909
  provider: options?.provider,
701
- sourceMessageId
910
+ sourceMessageId,
911
+ sourceContentPartOffset,
912
+ sourceContentPartIndices: processedSourceContentPartIndices,
913
+ toolSourceContentPartIndices: processedToolSourceContentPartIndices
702
914
  });
703
915
  if (formattedMessages.length > 0) flushSteerAnchor(formattedMessages[0]);
704
- messages.push(...formattedMessages);
916
+ for (const formattedMessage of formattedMessages) messages.push(formattedMessage);
705
917
  if (endsWithSteerMessage(formattedMessages)) pendingSteerAnchor = true;
706
918
  const endMessageIndex = messages.length;
707
919
  if (pendingSkillNames?.size != null && pendingSkillNames.size > 0) {
@@ -709,15 +921,19 @@ const formatAgentMessages = (payload, indexTokenCountMap, tools, skills, options
709
921
  for (const skillName of pendingSkillNames) {
710
922
  if (skipSkillBodyNames != null && skipSkillBodyNames.has(skillName)) continue;
711
923
  const body = skills?.get(skillName) ?? "";
712
- if (body) messages.push(withMessageRole(new HumanMessage({
713
- content: body,
714
- additional_kwargs: {
715
- role: "user",
716
- isMeta: true,
717
- source: "skill",
718
- skillName
719
- }
720
- }), "user"));
924
+ if (body) {
925
+ const skillMessage = withMessageRole(new HumanMessage({
926
+ content: body,
927
+ additional_kwargs: {
928
+ role: "user",
929
+ isMeta: true,
930
+ source: "skill",
931
+ skillName
932
+ }
933
+ }), "user");
934
+ stampSourceMessageIdentity(skillMessage, void 0, 0, "synthetic");
935
+ messages.push(skillMessage);
936
+ }
721
937
  }
722
938
  }
723
939
  const resultIndices = [];
@@ -899,18 +1115,94 @@ function serializeFoldedValue(value) {
899
1115
  const compacted = compactToolContent(value, MAX_FOLDED_BLOCK_CHARS).content;
900
1116
  return typeof compacted === "string" ? compacted : serializeStructuredValueBounded(compacted, MAX_FOLDED_BLOCK_CHARS).content;
901
1117
  }
902
- function markSyntheticProviderContext(message) {
1118
+ function getFoldedSourceAttribution(message) {
1119
+ const messageType = message.getType();
1120
+ if (messageType === "ai") return "model";
1121
+ if (messageType === "tool") return "tool";
1122
+ if (messageType === "system") return "synthetic";
1123
+ return "user";
1124
+ }
1125
+ function getSyntheticProviderContextProvenanceParts(sourceMessages) {
1126
+ const parts = [{ attribution: "synthetic" }];
1127
+ for (const source of sourceMessages) {
1128
+ const { message: sourceMessage, retainedContentPartIndices, mappingAmbiguous } = source;
1129
+ const provenanceState = inspectProviderMessageProvenance(sourceMessage);
1130
+ const sourceMessageIdsState = inspectProviderSourceMessageIds(sourceMessage);
1131
+ if (provenanceState.status === "invalid" || sourceMessageIdsState.status === "invalid") return null;
1132
+ const explicit = provenanceState.status === "valid" ? provenanceState.provenance : void 0;
1133
+ const sourceMessageIds = sourceMessageIdsState.status === "valid" ? sourceMessageIdsState.sourceMessageIds : [];
1134
+ const fallbackAttribution = getFoldedSourceAttribution(sourceMessage);
1135
+ const sourcePartStart = parts.length;
1136
+ const retainedSourceIds = /* @__PURE__ */ new Set();
1137
+ const contentLength = Array.isArray(sourceMessage.content) ? sourceMessage.content.length : void 0;
1138
+ const mapsOneToOne = mappingAmbiguous !== true && retainedContentPartIndices != null && contentLength != null && explicit != null && hasBijectiveProviderContentPartMapping(explicit.parts, contentLength);
1139
+ const retainedAllContentParts = mappingAmbiguous !== true && retainedContentPartIndices != null && contentLength != null && retainedContentPartIndices.size === contentLength;
1140
+ const retainUnindexedSourceIds = mappingAmbiguous !== true && retainedContentPartIndices == null || retainedAllContentParts || sourceMessageIds.length <= 1;
1141
+ for (const part of explicit?.parts ?? []) {
1142
+ let sourceContentPartIndices = part.sourceContentPartIndices;
1143
+ if (mappingAmbiguous === true && sourceContentPartIndices != null) sourceContentPartIndices = void 0;
1144
+ if (retainedContentPartIndices != null && sourceContentPartIndices != null && !retainedAllContentParts) if (!mapsOneToOne) sourceContentPartIndices = void 0;
1145
+ else {
1146
+ const retainedSourceContentPartIndices = [];
1147
+ for (const sourceContentPartIndex of sourceContentPartIndices) if (retainedContentPartIndices.has(sourceContentPartIndex)) retainedSourceContentPartIndices.push(sourceContentPartIndex);
1148
+ if (retainedSourceContentPartIndices.length === 0) continue;
1149
+ sourceContentPartIndices = retainedSourceContentPartIndices;
1150
+ }
1151
+ const sourceMessageId = sourceContentPartIndices != null || retainUnindexedSourceIds ? part.sourceMessageId : void 0;
1152
+ parts.push({
1153
+ attribution: part.attribution,
1154
+ ...sourceMessageId != null && { sourceMessageId },
1155
+ ...sourceContentPartIndices != null && { sourceContentPartIndices }
1156
+ });
1157
+ if (sourceMessageId != null) retainedSourceIds.add(sourceMessageId);
1158
+ }
1159
+ for (const sourceMessageId of sourceMessageIds) {
1160
+ if (!retainUnindexedSourceIds) break;
1161
+ if (!retainedSourceIds.has(sourceMessageId)) parts.push({
1162
+ attribution: fallbackAttribution,
1163
+ sourceMessageId
1164
+ });
1165
+ }
1166
+ if (parts.length === sourcePartStart) parts.push({ attribution: fallbackAttribution });
1167
+ }
1168
+ return mergeAdjacentProviderProvenanceParts(parts);
1169
+ }
1170
+ function markSyntheticProviderContext(message, sourceMessages = []) {
903
1171
  syntheticProviderContextMessages.add(message);
1172
+ const parts = getSyntheticProviderContextProvenanceParts(sourceMessages);
1173
+ if (parts == null) {
1174
+ setInvalidProviderMessageProvenance(message);
1175
+ return message;
1176
+ }
1177
+ setProviderMessageProvenance(message, parts.length > 0 ? parts : [{ attribution: "synthetic" }]);
904
1178
  return message;
905
1179
  }
906
- function appendSyntheticProviderContextMessage(result, parts) {
1180
+ function appendSyntheticProviderContextMessage(result, parts, sourceMessages = []) {
907
1181
  if (parts.length === 0) return false;
908
- result.push(markSyntheticProviderContext(withMessageRole(new HumanMessage({ content: toLangChainContent(parts) }), "user")));
1182
+ result.push(markSyntheticProviderContext(withMessageRole(new HumanMessage({ content: toLangChainContent(parts) }), "user"), sourceMessages));
909
1183
  return true;
910
1184
  }
911
1185
  function isSyntheticProviderContextMessage(message) {
912
1186
  return syntheticProviderContextMessages.has(message);
913
1187
  }
1188
+ function compactSyntheticProviderContextMessage(message, maxChars) {
1189
+ const compactedContent = compactToolContent(message.content, maxChars);
1190
+ if (!compactedContent.changed) return message;
1191
+ const compacted = new HumanMessage({
1192
+ content: compactedContent.content,
1193
+ id: message.id,
1194
+ name: message.name,
1195
+ additional_kwargs: { ...message.additional_kwargs },
1196
+ response_metadata: message.response_metadata
1197
+ });
1198
+ syntheticProviderContextMessages.add(compacted);
1199
+ setProviderMessageProvenance(compacted, [
1200
+ { attribution: "synthetic" },
1201
+ { attribution: "user" },
1202
+ { attribution: "tool" }
1203
+ ]);
1204
+ return compacted;
1205
+ }
914
1206
  function flushTextChunks(textChunks, parts) {
915
1207
  if (textChunks.length === 0) return;
916
1208
  parts.push({
@@ -922,20 +1214,34 @@ function flushTextChunks(textChunks, parts) {
922
1214
  function appendMessageContent(msg, role, textChunks, parts, budget) {
923
1215
  const { content } = msg;
924
1216
  if (typeof content === "string") {
925
- if (content && consumeFoldedWork(textChunks, budget)) appendFoldedLine(textChunks, budget, [`${role}: `, content]);
926
- appendToolCalls(msg, role, textChunks, budget);
927
- return;
1217
+ const remainingCharsBefore = budget.remainingChars;
1218
+ let contentComplete = true;
1219
+ if (content) contentComplete = consumeFoldedWork(textChunks, budget) && appendFoldedLine(textChunks, budget, [`${role}: `, content]);
1220
+ const toolCalls = appendToolCalls(msg, role, textChunks, budget);
1221
+ return budget.remainingChars < remainingCharsBefore || toolCalls.contributed ? {
1222
+ message: msg,
1223
+ ...(!contentComplete || !toolCalls.complete) && { mappingAmbiguous: true }
1224
+ } : void 0;
928
1225
  }
929
1226
  if (!Array.isArray(content)) {
930
- appendToolCalls(msg, role, textChunks, budget);
931
- return;
1227
+ const toolCalls = appendToolCalls(msg, role, textChunks, budget);
1228
+ return toolCalls.contributed ? {
1229
+ message: msg,
1230
+ ...!toolCalls.complete && { mappingAmbiguous: true }
1231
+ } : void 0;
932
1232
  }
933
1233
  let hasToolUseBlock = false;
934
- for (const block of content) {
1234
+ const retainedContentPartIndices = /* @__PURE__ */ new Set();
1235
+ for (let blockIndex = 0; blockIndex < content.length; blockIndex++) {
1236
+ const block = content[blockIndex];
935
1237
  if (!consumeFoldedWork(textChunks, budget)) {
936
1238
  hasToolUseBlock = true;
937
1239
  break;
938
1240
  }
1241
+ const remainingCharsBefore = budget.remainingChars;
1242
+ const markBlockRetained = () => {
1243
+ if (budget.remainingChars < remainingCharsBefore) retainedContentPartIndices.add(blockIndex);
1244
+ };
939
1245
  const blockTypeValue = readFoldedDataProperty(block, "type");
940
1246
  const blockType = typeof blockTypeValue === "string" ? blockTypeValue : void 0;
941
1247
  if (blockType !== "tool_use" && blockType !== "tool_call" && blockType !== "tool_result" && isAtomicToolContentBlock(block)) {
@@ -943,12 +1249,14 @@ function appendMessageContent(msg, role, textChunks, parts, budget) {
943
1249
  const blockChars = getToolContentCharLength([block]);
944
1250
  if (blockChars > budget.remainingChars) {
945
1251
  appendFoldedLine(textChunks, budget, [`${role}: [${blockType ?? "media"} omitted: folded context limit]`]);
1252
+ markBlockRetained();
946
1253
  continue;
947
1254
  }
948
1255
  flushTextChunks(textChunks, parts);
949
1256
  parts.push({ ...block });
950
1257
  budget.remainingChars -= blockChars;
951
1258
  } else appendFoldedLine(textChunks, budget, [`${role}: [${blockType ?? "media"}] `, serializeFoldedValue(block)]);
1259
+ markBlockRetained();
952
1260
  continue;
953
1261
  }
954
1262
  if (blockType === "tool_use") {
@@ -956,6 +1264,7 @@ function appendMessageContent(msg, role, textChunks, parts, budget) {
956
1264
  const name = readFoldedDataProperty(block, "name");
957
1265
  const input = readFoldedDataProperty(block, "input");
958
1266
  appendFoldedLine(textChunks, budget, [`${role}: [tool_use] ${typeof name === "string" ? name : ""} `, serializeFoldedValue(input ?? {})]);
1267
+ markBlockRetained();
959
1268
  continue;
960
1269
  }
961
1270
  if (blockType === "tool_call") {
@@ -973,6 +1282,7 @@ function appendMessageContent(msg, role, textChunks, parts, budget) {
973
1282
  appendFoldedLine(textChunks, budget, [`${role}: [tool_use] ${name}${argsText ? " " : ""}`, argsText]);
974
1283
  const output = readFoldedDataProperty(nested, "output");
975
1284
  if (output != null && output !== "") appendFoldedLine(textChunks, budget, ["Tool: ", typeof output === "string" ? output : serializeFoldedValue(output)]);
1285
+ markBlockRetained();
976
1286
  continue;
977
1287
  }
978
1288
  if (blockType === "tool_result") {
@@ -1003,23 +1313,60 @@ function appendMessageContent(msg, role, textChunks, parts, budget) {
1003
1313
  }
1004
1314
  }
1005
1315
  else if (inner != null) appendFoldedLine(textChunks, budget, [`${role}: [tool_result] `, serializeFoldedValue(inner)]);
1316
+ markBlockRetained();
1006
1317
  continue;
1007
1318
  }
1008
1319
  const text = readFoldedDataProperty(block, "text") ?? readFoldedDataProperty(block, "input");
1009
1320
  if (typeof text === "string" && text) {
1010
1321
  appendFoldedLine(textChunks, budget, [`${role}: `, text]);
1322
+ markBlockRetained();
1011
1323
  continue;
1012
1324
  }
1013
1325
  if (blockType != null && blockType !== "") appendFoldedLine(textChunks, budget, [`${role}: [${blockType}] `, serializeFoldedValue(block)]);
1326
+ markBlockRetained();
1014
1327
  }
1015
- if (!hasToolUseBlock) appendToolCalls(msg, role, textChunks, budget);
1328
+ const toolCalls = !hasToolUseBlock ? appendToolCalls(msg, role, textChunks, budget) : {
1329
+ contributed: false,
1330
+ complete: true
1331
+ };
1332
+ if (toolCalls.contributed) return {
1333
+ message: msg,
1334
+ ...!toolCalls.complete && { mappingAmbiguous: true }
1335
+ };
1336
+ return retainedContentPartIndices.size > 0 ? {
1337
+ message: msg,
1338
+ retainedContentPartIndices
1339
+ } : void 0;
1016
1340
  }
1017
1341
  function appendToolCalls(msg, role, textChunks, budget) {
1018
- if (role !== "AI") return;
1342
+ if (role !== "AI") return {
1343
+ contributed: false,
1344
+ complete: true
1345
+ };
1346
+ const remainingCharsBefore = budget.remainingChars;
1347
+ let complete = true;
1019
1348
  const aiMsg = msg;
1020
1349
  if (aiMsg.tool_calls && aiMsg.tool_calls.length > 0) {
1350
+ const rawToolCalls = aiMsg.additional_kwargs.tool_calls;
1351
+ if (Array.isArray(rawToolCalls)) if (rawToolCalls.length !== aiMsg.tool_calls.length) complete = false;
1352
+ else for (let index = 0; index < rawToolCalls.length; index++) {
1353
+ const rawToolCall = rawToolCalls[index];
1354
+ const parsedToolCall = aiMsg.tool_calls[index];
1355
+ const fn = readFoldedDataProperty(rawToolCall, "function");
1356
+ const rawId = readFoldedDataProperty(rawToolCall, "id");
1357
+ const rawName = readFoldedDataProperty(fn, "name");
1358
+ const parsedId = readFoldedDataProperty(parsedToolCall, "id");
1359
+ const parsedName = readFoldedDataProperty(parsedToolCall, "name");
1360
+ if (fn == null || rawId !== parsedId || rawName !== parsedName) {
1361
+ complete = false;
1362
+ break;
1363
+ }
1364
+ }
1021
1365
  for (const tc of aiMsg.tool_calls) {
1022
- if (!consumeFoldedWork(textChunks, budget)) break;
1366
+ if (!consumeFoldedWork(textChunks, budget)) {
1367
+ complete = false;
1368
+ break;
1369
+ }
1023
1370
  const name = readFoldedDataProperty(tc, "name");
1024
1371
  const args = readFoldedDataProperty(tc, "args");
1025
1372
  appendFoldedLine(textChunks, budget, [
@@ -1028,14 +1375,26 @@ function appendToolCalls(msg, role, textChunks, budget) {
1028
1375
  ")"
1029
1376
  ]);
1030
1377
  }
1031
- return;
1378
+ return {
1379
+ contributed: budget.remainingChars < remainingCharsBefore,
1380
+ complete
1381
+ };
1032
1382
  }
1033
1383
  const rawToolCalls = aiMsg.additional_kwargs.tool_calls;
1034
- if (!Array.isArray(rawToolCalls)) return;
1384
+ if (!Array.isArray(rawToolCalls)) return {
1385
+ contributed: false,
1386
+ complete: true
1387
+ };
1035
1388
  for (const tc of rawToolCalls) {
1036
- if (!consumeFoldedWork(textChunks, budget)) break;
1389
+ if (!consumeFoldedWork(textChunks, budget)) {
1390
+ complete = false;
1391
+ break;
1392
+ }
1037
1393
  const fn = readFoldedDataProperty(tc, "function");
1038
- if (fn == null) continue;
1394
+ if (fn == null) {
1395
+ complete = false;
1396
+ continue;
1397
+ }
1039
1398
  const name = readFoldedDataProperty(fn, "name");
1040
1399
  const args = readFoldedDataProperty(fn, "arguments");
1041
1400
  appendFoldedLine(textChunks, budget, [
@@ -1044,6 +1403,10 @@ function appendToolCalls(msg, role, textChunks, budget) {
1044
1403
  ")"
1045
1404
  ]);
1046
1405
  }
1406
+ return {
1407
+ contributed: budget.remainingChars < remainingCharsBefore,
1408
+ complete
1409
+ };
1047
1410
  }
1048
1411
  function ensureThinkingBlockInMessages(messages, _provider, config, runStartIndex) {
1049
1412
  if (messages.length === 0) return messages;
@@ -1092,15 +1455,18 @@ function ensureThinkingBlockInMessages(messages, _provider, config, runStartInde
1092
1455
  }
1093
1456
  const parts = [];
1094
1457
  const textChunks = [];
1458
+ const foldedSourceMessages = [];
1095
1459
  appendFoldedLine(textChunks, foldBudget, ["[Previous agent context]"]);
1096
- appendMessageContent(msg, "AI", textChunks, parts, foldBudget);
1460
+ const aiSource = appendMessageContent(msg, "AI", textChunks, parts, foldBudget);
1461
+ if (aiSource != null) foldedSourceMessages.push(aiSource);
1097
1462
  let j = i + 1;
1098
1463
  while (j < messages.length && isToolMessage$1(messages[j])) {
1099
- appendMessageContent(messages[j], "Tool", textChunks, parts, foldBudget);
1464
+ const toolSource = appendMessageContent(messages[j], "Tool", textChunks, parts, foldBudget);
1465
+ if (toolSource != null) foldedSourceMessages.push(toolSource);
1100
1466
  j++;
1101
1467
  }
1102
1468
  flushTextChunks(textChunks, parts);
1103
- if (appendSyntheticProviderContextMessage(result, parts)) emitAgentLog(config, "warn", "format", `ensureThinkingBlockInMessages: injecting [Previous agent context] HumanMessage (${parts.length} msgs at index ${i}, no thinking block in chain)`);
1469
+ if (appendSyntheticProviderContextMessage(result, parts, foldedSourceMessages)) emitAgentLog(config, "warn", "format", `ensureThinkingBlockInMessages: injecting [Previous agent context] HumanMessage (${parts.length} msgs at index ${i}, no thinking block in chain)`);
1104
1470
  i = j;
1105
1471
  } else {
1106
1472
  result.push(msg);
@@ -1141,17 +1507,20 @@ function foldToolBlocksForToollessAgent(messages, config) {
1141
1507
  if (result === null) result = messages.slice(0, i);
1142
1508
  const parts = [];
1143
1509
  const textChunks = [];
1510
+ const foldedSourceMessages = [];
1144
1511
  appendFoldedLine(textChunks, foldBudget, ["[Previous tool interaction]"]);
1145
- appendMessageContent(msg, isToolResultMessage(msg) ? "Tool" : "AI", textChunks, parts, foldBudget);
1512
+ const initialSource = appendMessageContent(msg, isToolResultMessage(msg) ? "Tool" : "AI", textChunks, parts, foldBudget);
1513
+ if (initialSource != null) foldedSourceMessages.push(initialSource);
1146
1514
  foldedCount++;
1147
1515
  let j = i + 1;
1148
1516
  while (j < messages.length && isToolResultMessage(messages[j])) {
1149
- appendMessageContent(messages[j], "Tool", textChunks, parts, foldBudget);
1517
+ const toolSource = appendMessageContent(messages[j], "Tool", textChunks, parts, foldBudget);
1518
+ if (toolSource != null) foldedSourceMessages.push(toolSource);
1150
1519
  foldedCount++;
1151
1520
  j++;
1152
1521
  }
1153
1522
  flushTextChunks(textChunks, parts);
1154
- appendSyntheticProviderContextMessage(result, parts);
1523
+ appendSyntheticProviderContextMessage(result, parts, foldedSourceMessages);
1155
1524
  i = j;
1156
1525
  }
1157
1526
  if (result === null) return messages;
@@ -1173,6 +1542,6 @@ function chainHasThinkingBlock(messages, currentIndex) {
1173
1542
  return false;
1174
1543
  }
1175
1544
  //#endregion
1176
- export { ensureThinkingBlockInMessages, foldToolBlocksForToollessAgent, formatAgentMessages, formatFromLangChain, formatLangChainMessages, formatMediaMessage, formatMessage, isSyntheticProviderContextMessage, labelContentByAgent, shiftIndexTokenCountMap, withMessageRole };
1545
+ export { compactSyntheticProviderContextMessage, ensureThinkingBlockInMessages, foldToolBlocksForToollessAgent, formatAgentMessages, formatFromLangChain, formatLangChainMessages, formatMediaMessage, formatMessage, isSyntheticProviderContextMessage, labelContentByAgent, shiftIndexTokenCountMap, withMessageRole };
1177
1546
 
1178
1547
  //# sourceMappingURL=format.mjs.map