@librechat/agents 3.8.0 → 3.8.2

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 (248) hide show
  1. package/dist/cjs/agents/AgentContext.cjs +13 -3
  2. package/dist/cjs/agents/AgentContext.cjs.map +1 -1
  3. package/dist/cjs/graphs/Graph.cjs +176 -55
  4. package/dist/cjs/graphs/Graph.cjs.map +1 -1
  5. package/dist/cjs/graphs/MultiAgentGraph.cjs +16 -6
  6. package/dist/cjs/graphs/MultiAgentGraph.cjs.map +1 -1
  7. package/dist/cjs/hitl/approvalReview.cjs +89 -0
  8. package/dist/cjs/hitl/approvalReview.cjs.map +1 -0
  9. package/dist/cjs/langfuse.cjs +42 -0
  10. package/dist/cjs/langfuse.cjs.map +1 -1
  11. package/dist/cjs/langfuseToolOutputTracing.cjs +42 -0
  12. package/dist/cjs/langfuseToolOutputTracing.cjs.map +1 -1
  13. package/dist/cjs/langfuseTraceShaping.cjs +7 -1
  14. package/dist/cjs/langfuseTraceShaping.cjs.map +1 -1
  15. package/dist/cjs/llm/anthropic/utils/message_inputs.cjs +6 -10
  16. package/dist/cjs/llm/anthropic/utils/message_inputs.cjs.map +1 -1
  17. package/dist/cjs/llm/bedrock/utils/message_inputs.cjs +2 -7
  18. package/dist/cjs/llm/bedrock/utils/message_inputs.cjs.map +1 -1
  19. package/dist/cjs/llm/contextPressureMeter.cjs +51 -10
  20. package/dist/cjs/llm/contextPressureMeter.cjs.map +1 -1
  21. package/dist/cjs/llm/init.cjs +1 -1
  22. package/dist/cjs/llm/invoke.cjs +2 -2
  23. package/dist/cjs/llm/openai/index.cjs +4 -3
  24. package/dist/cjs/llm/openai/index.cjs.map +1 -1
  25. package/dist/cjs/llm/openai/utils/index.cjs +5 -4
  26. package/dist/cjs/llm/openai/utils/index.cjs.map +1 -1
  27. package/dist/cjs/llm/preempt.cjs +3 -2
  28. package/dist/cjs/llm/preempt.cjs.map +1 -1
  29. package/dist/cjs/llm/prepareProviderRequest.cjs +9 -7
  30. package/dist/cjs/llm/prepareProviderRequest.cjs.map +1 -1
  31. package/dist/cjs/llm/providers.cjs +1 -1
  32. package/dist/cjs/main.cjs +14 -8
  33. package/dist/cjs/messages/alternation.cjs +1 -5
  34. package/dist/cjs/messages/alternation.cjs.map +1 -1
  35. package/dist/cjs/messages/budget.cjs +206 -7
  36. package/dist/cjs/messages/budget.cjs.map +1 -1
  37. package/dist/cjs/messages/cache.cjs +3 -9
  38. package/dist/cjs/messages/cache.cjs.map +1 -1
  39. package/dist/cjs/messages/core.cjs +26 -38
  40. package/dist/cjs/messages/core.cjs.map +1 -1
  41. package/dist/cjs/messages/format.cjs +132 -43
  42. package/dist/cjs/messages/format.cjs.map +1 -1
  43. package/dist/cjs/messages/index.cjs +2 -0
  44. package/dist/cjs/messages/prune.cjs +14 -9
  45. package/dist/cjs/messages/prune.cjs.map +1 -1
  46. package/dist/cjs/messages/reasoningTypes.cjs +21 -0
  47. package/dist/cjs/messages/reasoningTypes.cjs.map +1 -0
  48. package/dist/cjs/messages/recency.cjs +15 -94
  49. package/dist/cjs/messages/recency.cjs.map +1 -1
  50. package/dist/cjs/messages/toolHistoryProjection.cjs +243 -0
  51. package/dist/cjs/messages/toolHistoryProjection.cjs.map +1 -0
  52. package/dist/cjs/messages/toolResultTypes.cjs +145 -4
  53. package/dist/cjs/messages/toolResultTypes.cjs.map +1 -1
  54. package/dist/cjs/run.cjs +22 -10
  55. package/dist/cjs/run.cjs.map +1 -1
  56. package/dist/cjs/session/AgentSession.cjs +7 -5
  57. package/dist/cjs/session/AgentSession.cjs.map +1 -1
  58. package/dist/cjs/session/JsonlSessionStore.cjs +3 -0
  59. package/dist/cjs/session/JsonlSessionStore.cjs.map +1 -1
  60. package/dist/cjs/session/index.cjs +1 -1
  61. package/dist/cjs/session/sessionProjection.cjs +75 -0
  62. package/dist/cjs/session/sessionProjection.cjs.map +1 -0
  63. package/dist/cjs/stream.cjs +20 -19
  64. package/dist/cjs/stream.cjs.map +1 -1
  65. package/dist/cjs/summarization/index.cjs.map +1 -1
  66. package/dist/cjs/summarization/node.cjs +19 -9
  67. package/dist/cjs/summarization/node.cjs.map +1 -1
  68. package/dist/cjs/summarization/shared.cjs +9 -0
  69. package/dist/cjs/summarization/shared.cjs.map +1 -1
  70. package/dist/cjs/tools/ToolNode.cjs +256 -84
  71. package/dist/cjs/tools/ToolNode.cjs.map +1 -1
  72. package/dist/cjs/tools/local/CompileCheckTool.cjs +1 -1
  73. package/dist/cjs/tools/local/LocalCodingTools.cjs +1 -1
  74. package/dist/cjs/tools/subagent/SubagentExecutor.cjs +24 -9
  75. package/dist/cjs/tools/subagent/SubagentExecutor.cjs.map +1 -1
  76. package/dist/cjs/tools/subagent/SubagentReplay.cjs +2 -0
  77. package/dist/cjs/tools/subagent/SubagentReplay.cjs.map +1 -1
  78. package/dist/cjs/tools/toolBatchReplay.cjs +187 -0
  79. package/dist/cjs/tools/toolBatchReplay.cjs.map +1 -0
  80. package/dist/cjs/tools/toolOutputReferences.cjs +12 -0
  81. package/dist/cjs/tools/toolOutputReferences.cjs.map +1 -1
  82. package/dist/cjs/types/hitl.cjs +4 -0
  83. package/dist/cjs/types/hitl.cjs.map +1 -1
  84. package/dist/cjs/utils/events.cjs +13 -0
  85. package/dist/cjs/utils/events.cjs.map +1 -1
  86. package/dist/cjs/utils/tokens.cjs +105 -0
  87. package/dist/cjs/utils/tokens.cjs.map +1 -1
  88. package/dist/esm/agents/AgentContext.mjs +13 -3
  89. package/dist/esm/agents/AgentContext.mjs.map +1 -1
  90. package/dist/esm/graphs/Graph.mjs +178 -57
  91. package/dist/esm/graphs/Graph.mjs.map +1 -1
  92. package/dist/esm/graphs/MultiAgentGraph.mjs +16 -6
  93. package/dist/esm/graphs/MultiAgentGraph.mjs.map +1 -1
  94. package/dist/esm/hitl/approvalReview.mjs +83 -0
  95. package/dist/esm/hitl/approvalReview.mjs.map +1 -0
  96. package/dist/esm/langfuse.mjs +43 -2
  97. package/dist/esm/langfuse.mjs.map +1 -1
  98. package/dist/esm/langfuseToolOutputTracing.mjs +41 -1
  99. package/dist/esm/langfuseToolOutputTracing.mjs.map +1 -1
  100. package/dist/esm/langfuseTraceShaping.mjs +7 -1
  101. package/dist/esm/langfuseTraceShaping.mjs.map +1 -1
  102. package/dist/esm/llm/anthropic/utils/message_inputs.mjs +6 -10
  103. package/dist/esm/llm/anthropic/utils/message_inputs.mjs.map +1 -1
  104. package/dist/esm/llm/bedrock/utils/message_inputs.mjs +2 -7
  105. package/dist/esm/llm/bedrock/utils/message_inputs.mjs.map +1 -1
  106. package/dist/esm/llm/contextPressureMeter.mjs +52 -11
  107. package/dist/esm/llm/contextPressureMeter.mjs.map +1 -1
  108. package/dist/esm/llm/init.mjs +1 -1
  109. package/dist/esm/llm/invoke.mjs +2 -2
  110. package/dist/esm/llm/openai/index.mjs +2 -1
  111. package/dist/esm/llm/openai/index.mjs.map +1 -1
  112. package/dist/esm/llm/openai/utils/index.mjs +5 -4
  113. package/dist/esm/llm/openai/utils/index.mjs.map +1 -1
  114. package/dist/esm/llm/preempt.mjs +2 -1
  115. package/dist/esm/llm/preempt.mjs.map +1 -1
  116. package/dist/esm/llm/prepareProviderRequest.mjs +9 -7
  117. package/dist/esm/llm/prepareProviderRequest.mjs.map +1 -1
  118. package/dist/esm/llm/providers.mjs +1 -1
  119. package/dist/esm/main.mjs +13 -10
  120. package/dist/esm/messages/alternation.mjs +2 -6
  121. package/dist/esm/messages/alternation.mjs.map +1 -1
  122. package/dist/esm/messages/budget.mjs +206 -8
  123. package/dist/esm/messages/budget.mjs.map +1 -1
  124. package/dist/esm/messages/cache.mjs +3 -9
  125. package/dist/esm/messages/cache.mjs.map +1 -1
  126. package/dist/esm/messages/core.mjs +24 -34
  127. package/dist/esm/messages/core.mjs.map +1 -1
  128. package/dist/esm/messages/format.mjs +133 -44
  129. package/dist/esm/messages/format.mjs.map +1 -1
  130. package/dist/esm/messages/index.mjs +2 -0
  131. package/dist/esm/messages/prune.mjs +14 -9
  132. package/dist/esm/messages/prune.mjs.map +1 -1
  133. package/dist/esm/messages/reasoningTypes.mjs +20 -0
  134. package/dist/esm/messages/reasoningTypes.mjs.map +1 -0
  135. package/dist/esm/messages/recency.mjs +16 -95
  136. package/dist/esm/messages/recency.mjs.map +1 -1
  137. package/dist/esm/messages/toolHistoryProjection.mjs +237 -0
  138. package/dist/esm/messages/toolHistoryProjection.mjs.map +1 -0
  139. package/dist/esm/messages/toolResultTypes.mjs +141 -4
  140. package/dist/esm/messages/toolResultTypes.mjs.map +1 -1
  141. package/dist/esm/run.mjs +23 -11
  142. package/dist/esm/run.mjs.map +1 -1
  143. package/dist/esm/session/AgentSession.mjs +7 -5
  144. package/dist/esm/session/AgentSession.mjs.map +1 -1
  145. package/dist/esm/session/JsonlSessionStore.mjs +3 -0
  146. package/dist/esm/session/JsonlSessionStore.mjs.map +1 -1
  147. package/dist/esm/session/index.mjs +1 -1
  148. package/dist/esm/session/sessionProjection.mjs +72 -0
  149. package/dist/esm/session/sessionProjection.mjs.map +1 -0
  150. package/dist/esm/stream.mjs +17 -16
  151. package/dist/esm/stream.mjs.map +1 -1
  152. package/dist/esm/summarization/index.mjs.map +1 -1
  153. package/dist/esm/summarization/node.mjs +20 -10
  154. package/dist/esm/summarization/node.mjs.map +1 -1
  155. package/dist/esm/summarization/shared.mjs +9 -1
  156. package/dist/esm/summarization/shared.mjs.map +1 -1
  157. package/dist/esm/tools/ToolNode.mjs +256 -84
  158. package/dist/esm/tools/ToolNode.mjs.map +1 -1
  159. package/dist/esm/tools/local/CompileCheckTool.mjs +1 -1
  160. package/dist/esm/tools/local/LocalCodingTools.mjs +1 -1
  161. package/dist/esm/tools/subagent/SubagentExecutor.mjs +24 -9
  162. package/dist/esm/tools/subagent/SubagentExecutor.mjs.map +1 -1
  163. package/dist/esm/tools/subagent/SubagentReplay.mjs +1 -1
  164. package/dist/esm/tools/subagent/SubagentReplay.mjs.map +1 -1
  165. package/dist/esm/tools/toolBatchReplay.mjs +176 -0
  166. package/dist/esm/tools/toolBatchReplay.mjs.map +1 -0
  167. package/dist/esm/tools/toolOutputReferences.mjs +12 -0
  168. package/dist/esm/tools/toolOutputReferences.mjs.map +1 -1
  169. package/dist/esm/types/hitl.mjs +4 -1
  170. package/dist/esm/types/hitl.mjs.map +1 -1
  171. package/dist/esm/utils/events.mjs +13 -0
  172. package/dist/esm/utils/events.mjs.map +1 -1
  173. package/dist/esm/utils/tokens.mjs +105 -1
  174. package/dist/esm/utils/tokens.mjs.map +1 -1
  175. package/dist/types/agents/AgentContext.d.ts +13 -1
  176. package/dist/types/graphs/Graph.d.ts +27 -0
  177. package/dist/types/hitl/approvalReview.d.ts +32 -0
  178. package/dist/types/hooks/types.d.ts +4 -2
  179. package/dist/types/index.d.ts +1 -0
  180. package/dist/types/langfuse.d.ts +5 -0
  181. package/dist/types/langfuseToolOutputTracing.d.ts +2 -0
  182. package/dist/types/llm/contextPressureMeter.d.ts +2 -1
  183. package/dist/types/llm/prepareProviderRequest.d.ts +7 -1
  184. package/dist/types/messages/budget.d.ts +15 -10
  185. package/dist/types/messages/core.d.ts +8 -17
  186. package/dist/types/messages/format.d.ts +3 -2
  187. package/dist/types/messages/index.d.ts +1 -1
  188. package/dist/types/messages/prune.d.ts +1 -1
  189. package/dist/types/messages/reasoningTypes.d.ts +7 -0
  190. package/dist/types/messages/recency.d.ts +3 -0
  191. package/dist/types/messages/toolHistoryProjection.d.ts +65 -0
  192. package/dist/types/messages/toolResultTypes.d.ts +31 -1
  193. package/dist/types/session/sessionProjection.d.ts +10 -0
  194. package/dist/types/summarization/index.d.ts +2 -1
  195. package/dist/types/summarization/node.d.ts +1 -0
  196. package/dist/types/summarization/shared.d.ts +12 -0
  197. package/dist/types/tools/ToolNode.d.ts +12 -6
  198. package/dist/types/tools/subagent/SubagentReplay.d.ts +2 -0
  199. package/dist/types/tools/toolBatchReplay.d.ts +54 -0
  200. package/dist/types/tools/toolOutputReferences.d.ts +2 -0
  201. package/dist/types/types/graph.d.ts +20 -0
  202. package/dist/types/types/run.d.ts +4 -0
  203. package/dist/types/types/summarize.d.ts +4 -1
  204. package/dist/types/utils/tokens.d.ts +2 -1
  205. package/package.json +1 -1
  206. package/src/agents/AgentContext.ts +34 -3
  207. package/src/graphs/Graph.ts +465 -147
  208. package/src/graphs/MultiAgentGraph.ts +28 -6
  209. package/src/hitl/approvalReview.ts +209 -0
  210. package/src/hooks/types.ts +4 -1
  211. package/src/index.ts +1 -0
  212. package/src/langfuse.ts +67 -9
  213. package/src/langfuseToolOutputTracing.ts +91 -0
  214. package/src/langfuseTraceShaping.ts +17 -4
  215. package/src/llm/anthropic/utils/message_inputs.ts +5 -10
  216. package/src/llm/bedrock/utils/message_inputs.ts +2 -8
  217. package/src/llm/contextPressureMeter.ts +80 -12
  218. package/src/llm/openai/utils/index.ts +5 -4
  219. package/src/llm/prepareProviderRequest.ts +21 -16
  220. package/src/messages/alternation.ts +2 -15
  221. package/src/messages/budget.ts +439 -23
  222. package/src/messages/cache.ts +8 -9
  223. package/src/messages/core.ts +65 -95
  224. package/src/messages/format.ts +262 -78
  225. package/src/messages/index.ts +1 -1
  226. package/src/messages/prune.ts +31 -12
  227. package/src/messages/reasoningTypes.ts +23 -0
  228. package/src/messages/recency.ts +35 -179
  229. package/src/messages/toolHistoryProjection.ts +460 -0
  230. package/src/messages/toolResultTypes.ts +331 -100
  231. package/src/run.ts +44 -22
  232. package/src/session/AgentSession.ts +33 -16
  233. package/src/session/JsonlSessionStore.ts +6 -0
  234. package/src/session/sessionProjection.ts +126 -0
  235. package/src/stream.ts +14 -19
  236. package/src/summarization/index.ts +2 -0
  237. package/src/summarization/node.ts +62 -13
  238. package/src/summarization/shared.ts +23 -0
  239. package/src/tools/ToolNode.ts +518 -184
  240. package/src/tools/subagent/SubagentExecutor.ts +35 -6
  241. package/src/tools/subagent/SubagentReplay.ts +2 -2
  242. package/src/tools/toolBatchReplay.ts +395 -0
  243. package/src/tools/toolOutputReferences.ts +16 -0
  244. package/src/types/graph.ts +20 -0
  245. package/src/types/run.ts +4 -0
  246. package/src/types/summarize.ts +4 -1
  247. package/src/utils/events.ts +19 -0
  248. package/src/utils/tokens.ts +183 -0
@@ -11,6 +11,11 @@ import type { ContentBlock as LangChainContentBlock } from '@langchain/core/mess
11
11
  import type { ToolCall, ToolCallChunk } from '@langchain/core/messages/tool';
12
12
  import type { ProviderMessageProvenancePart } from './provenance';
13
13
  import type * as t from '@/types';
14
+ import type {
15
+ ResponsesReplayPosition,
16
+ ToolHistoryPreparation,
17
+ OrderedToolHistoryProjection,
18
+ } from './toolHistoryProjection';
14
19
  import {
15
20
  cloneToolMessageWithContent,
16
21
  compactToolContent,
@@ -31,8 +36,16 @@ import {
31
36
  } from './provenance';
32
37
  import { HARD_MAX_TOOL_RESULT_CHARS } from '@/utils/truncation';
33
38
  import { stripAnthropicCacheControl } from './cache';
39
+ import { isReasoningContentBlock } from './reasoningTypes';
34
40
  import { ContentTypes, Providers } from '@/common';
35
41
  import { toLangChainContent } from './langchain';
42
+ import {
43
+ OPENAI_RESPONSES_REPLAY_POSITIONS_KEY,
44
+ createToolHistoryPreparation,
45
+ getGeneratedImageMimeType,
46
+ getResponsesHistorySource,
47
+ isResponsesReplayPosition,
48
+ } from './toolHistoryProjection';
36
49
 
37
50
  type ReasoningSummary = { summary?: Array<{ text?: string }> };
38
51
  type ReasoningDetail = { type?: string; text?: string };
@@ -227,8 +240,7 @@ function getAdditionalReasoningContent(
227
240
  /**
228
241
  * True when a content block is a provider reasoning block: Anthropic
229
242
  * `thinking` / `redacted_thinking`, Google `reasoning`, Bedrock
230
- * `reasoning_content`, and the streamed delta variants that prefix each of
231
- * those names.
243
+ * `reasoning_content`, LibreChat `think`, and their known streamed variants.
232
244
  *
233
245
  * Shared rather than re-derived because two very different readers must agree
234
246
  * on the same answer: the stream classifier, which decides what the host has
@@ -236,38 +248,18 @@ function getAdditionalReasoningContent(
236
248
  * holds anything worth keeping. A turn the host renders as thinking-only must
237
249
  * never look like a visible answer to the gate.
238
250
  *
239
- * Prefix matching, not equality, because providers stream these as suffixed
240
- * delta types. `reasoning_content` needs no clause of its own — it already
241
- * carries the `reasoning` prefix.
251
+ * Exact matching prevents unrelated custom block types that happen to share a
252
+ * prefix from being silently classified as hidden reasoning.
242
253
  */
243
- export function isReasoningContentBlock(block: { type?: string }): boolean {
244
- const type = block.type;
245
- if (type == null) {
246
- return false;
247
- }
248
- return (
249
- type.startsWith(ContentTypes.THINKING) ||
250
- type.startsWith(ContentTypes.REASONING) ||
251
- type === 'redacted_thinking'
252
- );
253
- }
254
+ export { isReasoningContentBlock } from './reasoningTypes';
254
255
 
255
256
  function hasReasoningContent(content: BaseMessage['content']): boolean {
256
257
  if (!Array.isArray(content)) {
257
258
  return false;
258
259
  }
259
- return content.some((item) => {
260
- if (typeof item !== 'object' || !('type' in item)) {
261
- return false;
262
- }
263
- return (
264
- item.type === ContentTypes.THINK ||
265
- item.type === ContentTypes.THINKING ||
266
- item.type === ContentTypes.REASONING ||
267
- item.type === ContentTypes.REASONING_CONTENT ||
268
- item.type === 'redacted_thinking'
269
- );
270
- });
260
+ return content.some(
261
+ (item) => typeof item === 'object' && isReasoningContentBlock(item)
262
+ );
271
263
  }
272
264
 
273
265
  export function modifyDeltaProperties(
@@ -856,19 +848,13 @@ function hasReplayableEncryptedReasoning(reasoning: unknown): boolean {
856
848
 
857
849
  type ResponsesReplayProjection = 'fallback' | 'native';
858
850
 
859
- export const OPENAI_RESPONSES_REPLAY_POSITIONS_KEY =
860
- '__openai_responses_replay_positions__';
851
+ export { OPENAI_RESPONSES_REPLAY_POSITIONS_KEY } from './toolHistoryProjection';
861
852
 
862
853
  /** Reasoning item currently streaming, so a terminal ciphertext seals against its own id. */
863
854
  export const OPENAI_RESPONSES_ACTIVE_REASONING_ID_KEY =
864
855
  '__openai_responses_active_reasoning_id__';
865
856
 
866
- export type ResponsesReplayPosition = {
867
- contentIndex?: number;
868
- itemId: string;
869
- kind: 'message' | 'output' | 'reasoning' | 'text';
870
- outputIndex: number;
871
- };
857
+ export type { ResponsesReplayPosition } from './toolHistoryProjection';
872
858
 
873
859
  type CompletedGeneratedImages = {
874
860
  blocks: PositionedResponsesReplayBlock[];
@@ -1297,56 +1283,7 @@ function projectPreemptedResponsesV1Content(
1297
1283
  }
1298
1284
 
1299
1285
  function getAuthoritativeResponsesOutput(message: AIMessage): unknown[] {
1300
- const responseOutput = message.response_metadata.output;
1301
- const toolOutputs = message.additional_kwargs.tool_outputs;
1302
- if (Array.isArray(responseOutput) && responseOutput.length > 0) {
1303
- return responseOutput;
1304
- }
1305
- return Array.isArray(toolOutputs) ? toolOutputs : [];
1306
- }
1307
-
1308
- function isResponsesReplayPosition(
1309
- value: unknown
1310
- ): value is ResponsesReplayPosition {
1311
- if (value == null || typeof value !== 'object') {
1312
- return false;
1313
- }
1314
- const position = value as Partial<ResponsesReplayPosition>;
1315
- return (
1316
- (position.kind === 'message' ||
1317
- position.kind === 'output' ||
1318
- position.kind === 'reasoning' ||
1319
- position.kind === 'text') &&
1320
- typeof position.itemId === 'string' &&
1321
- position.itemId.length > 0 &&
1322
- typeof position.outputIndex === 'number' &&
1323
- Number.isSafeInteger(position.outputIndex) &&
1324
- position.outputIndex >= 0 &&
1325
- (position.contentIndex == null ||
1326
- (typeof position.contentIndex === 'number' &&
1327
- Number.isSafeInteger(position.contentIndex) &&
1328
- position.contentIndex >= 0))
1329
- );
1330
- }
1331
-
1332
- function getGeneratedImageMimeType(data: string): string {
1333
- const bytes = Buffer.from(data.slice(0, 16), 'base64');
1334
- if (bytes[0] === 0xff && bytes[1] === 0xd8 && bytes[2] === 0xff) {
1335
- return 'image/jpeg';
1336
- }
1337
- if (
1338
- bytes[0] === 0x52 &&
1339
- bytes[1] === 0x49 &&
1340
- bytes[2] === 0x46 &&
1341
- bytes[3] === 0x46 &&
1342
- bytes[8] === 0x57 &&
1343
- bytes[9] === 0x45 &&
1344
- bytes[10] === 0x42 &&
1345
- bytes[11] === 0x50
1346
- ) {
1347
- return 'image/webp';
1348
- }
1349
- return 'image/png';
1286
+ return getResponsesHistorySource(message)?.items ?? [];
1350
1287
  }
1351
1288
 
1352
1289
  function getResponsesReplayItemKey(
@@ -1382,7 +1319,8 @@ function getResponsesReplayArtifacts(
1382
1319
  output: readonly unknown[],
1383
1320
  maxChars: number,
1384
1321
  replayProjection: ResponsesReplayProjection,
1385
- replayPositionValue?: unknown
1322
+ replayPositionValue?: unknown,
1323
+ history?: OrderedToolHistoryProjection
1386
1324
  ): ResponsesReplayArtifacts {
1387
1325
  const blocks: PositionedResponsesReplayBlock[] = [];
1388
1326
  const data = new Set<string>();
@@ -1441,7 +1379,11 @@ function getResponsesReplayArtifacts(
1441
1379
  kind: 'message',
1442
1380
  outputIndex,
1443
1381
  });
1444
- if (!('content' in item) || !Array.isArray(item.content)) {
1382
+ if (
1383
+ history != null ||
1384
+ !('content' in item) ||
1385
+ !Array.isArray(item.content)
1386
+ ) {
1445
1387
  continue;
1446
1388
  }
1447
1389
  for (
@@ -1473,6 +1415,24 @@ function getResponsesReplayArtifacts(
1473
1415
  });
1474
1416
  }
1475
1417
  }
1418
+ if (history?.source.coverage === 'complete-output') {
1419
+ for (const contribution of history.contributions) {
1420
+ if (contribution.kind !== 'text') {
1421
+ continue;
1422
+ }
1423
+ const itemId =
1424
+ contribution.itemId ?? `message-${contribution.outputIndex}`;
1425
+ textPositionsByKey.set(
1426
+ `${itemId}:${contribution.outputIndex}:${contribution.contentIndex ?? 0}`,
1427
+ {
1428
+ itemId,
1429
+ kind: 'text',
1430
+ outputIndex: contribution.outputIndex,
1431
+ contentIndex: contribution.contentIndex,
1432
+ }
1433
+ );
1434
+ }
1435
+ }
1476
1436
  if (hasAuthoritativeMessage) {
1477
1437
  for (const [itemId, outputIndex] of authoritativeOutputIndicesByItemId) {
1478
1438
  outputPositionsByItemId.set(itemId, {
@@ -1918,7 +1878,8 @@ function isPreemptedOpenAIResponsesMessage(message: AIMessage): boolean {
1918
1878
  function projectPreemptedOpenAIResponsesMessage(
1919
1879
  message: AIMessage,
1920
1880
  maxChars: number,
1921
- replayProjection: ResponsesReplayProjection
1881
+ replayProjection: ResponsesReplayProjection,
1882
+ preparation: ToolHistoryPreparation = createToolHistoryPreparation()
1922
1883
  ): AIMessage {
1923
1884
  if (!isPreemptedOpenAIResponsesMessage(message)) {
1924
1885
  return message;
@@ -1929,7 +1890,9 @@ function projectPreemptedOpenAIResponsesMessage(
1929
1890
  const retainsEncryptedReasoning =
1930
1891
  replayProjection === 'native' &&
1931
1892
  hasReplayableEncryptedReasoning(additionalKwargs.reasoning);
1932
- const authoritativeOutput = getAuthoritativeResponsesOutput(message);
1893
+ const history = preparation.get(message);
1894
+ const authoritativeOutput =
1895
+ history?.source.items ?? getAuthoritativeResponsesOutput(message);
1933
1896
  const {
1934
1897
  generatedImages,
1935
1898
  messagePositions,
@@ -1941,7 +1904,8 @@ function projectPreemptedOpenAIResponsesMessage(
1941
1904
  authoritativeOutput,
1942
1905
  maxChars,
1943
1906
  replayProjection,
1944
- additionalKwargs[OPENAI_RESPONSES_REPLAY_POSITIONS_KEY]
1907
+ additionalKwargs[OPENAI_RESPONSES_REPLAY_POSITIONS_KEY],
1908
+ history
1945
1909
  );
1946
1910
  const reasoningItemId =
1947
1911
  retainsEncryptedReasoning &&
@@ -2043,7 +2007,8 @@ function projectPreemptedOpenAIResponsesMessage(
2043
2007
  export function projectToolStreamContentForProvider(
2044
2008
  messages: BaseMessage[],
2045
2009
  responsesReplayProjection?: ResponsesReplayProjection,
2046
- maxChars = HARD_MAX_TOOL_RESULT_CHARS
2010
+ maxChars = HARD_MAX_TOOL_RESULT_CHARS,
2011
+ preparation: ToolHistoryPreparation = createToolHistoryPreparation()
2047
2012
  ): BaseMessage[] {
2048
2013
  let projected: BaseMessage[] | undefined;
2049
2014
  for (let i = 0; i < messages.length; i++) {
@@ -2059,7 +2024,8 @@ export function projectToolStreamContentForProvider(
2059
2024
  const replaySafeMessage = projectPreemptedOpenAIResponsesMessage(
2060
2025
  assistantMessage,
2061
2026
  maxChars,
2062
- responsesReplayProjection
2027
+ responsesReplayProjection,
2028
+ preparation
2063
2029
  );
2064
2030
  if (replaySafeMessage !== assistantMessage) {
2065
2031
  projected ??= [...messages];
@@ -2798,14 +2764,18 @@ export function findLastIndex<T>(
2798
2764
  function readOwnDataProperty(target: object, key: PropertyKey): unknown {
2799
2765
  try {
2800
2766
  const descriptor = Object.getOwnPropertyDescriptor(target, key);
2801
- return descriptor != null && 'value' in descriptor ? descriptor.value : undefined;
2767
+ return descriptor != null && 'value' in descriptor
2768
+ ? descriptor.value
2769
+ : undefined;
2802
2770
  } catch {
2803
2771
  return undefined;
2804
2772
  }
2805
2773
  }
2806
2774
 
2807
2775
  /** Whether message content carries non-whitespace text in any text block. */
2808
- export function hasNonEmptyTextContent(content: BaseMessage['content']): boolean {
2776
+ export function hasNonEmptyTextContent(
2777
+ content: BaseMessage['content']
2778
+ ): boolean {
2809
2779
  if (typeof content === 'string') {
2810
2780
  return content.trim() !== '';
2811
2781
  }