@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
@@ -9,7 +9,8 @@ import {
9
9
  REPLY_PRIMER_TOKENS,
10
10
  isSyntheticProviderContextMessage,
11
11
  } from '@/messages';
12
- import { apportionTokenCounts } from '@/utils';
12
+ import { createToolMessageUsageAccumulator } from '@/messages/budget';
13
+ import { readTokenMetadataProperty, apportionTokenCounts } from '@/utils';
13
14
 
14
15
  interface ContextPressureUsage {
15
16
  contextBudget?: number;
@@ -19,6 +20,7 @@ interface ContextPressureUsage {
19
20
  }
20
21
 
21
22
  interface ContextPressureMeterParams {
23
+ provider?: t.ProviderName;
22
24
  tokenCounter?: t.TokenCounter;
23
25
  tokenCountCache?: ExactTokenCountCache;
24
26
  sourceMessages: BaseMessage[];
@@ -89,6 +91,21 @@ function readDataProperty(
89
91
  : { own: true, safe: false };
90
92
  }
91
93
 
94
+ function readCacheMetadataProperty(
95
+ owner: object,
96
+ property: PropertyKey,
97
+ path: string
98
+ ): { safe: boolean; value?: unknown } {
99
+ try {
100
+ return {
101
+ safe: true,
102
+ value: readTokenMetadataProperty(owner, property, path),
103
+ };
104
+ } catch {
105
+ return { safe: false };
106
+ }
107
+ }
108
+
92
109
  function getStableTokenSurface(
93
110
  message: BaseMessage
94
111
  ): StableTokenSurface | undefined {
@@ -105,10 +122,13 @@ function getStableTokenSurface(
105
122
  }
106
123
  const messageType = message.getType();
107
124
  const roleProperty = readDataProperty(message, 'role');
108
- if (!roleProperty.safe || (!roleProperty.own && 'role' in message)) {
125
+ const resolvedRoleProperty = roleProperty.own
126
+ ? roleProperty
127
+ : readCacheMetadataProperty(message, 'role', 'message.role');
128
+ if (!resolvedRoleProperty.safe) {
109
129
  return undefined;
110
130
  }
111
- const role = roleProperty.value;
131
+ const role = resolvedRoleProperty.value;
112
132
  if (role != null && typeof role !== 'string') {
113
133
  return undefined;
114
134
  }
@@ -129,6 +149,14 @@ function getStableTokenSurface(
129
149
  return undefined;
130
150
  }
131
151
  const additionalKwargs = rawAdditionalKwargs;
152
+ const rawToolCalls = readCacheMetadataProperty(
153
+ additionalKwargs,
154
+ 'tool_calls',
155
+ 'additional_kwargs.tool_calls'
156
+ );
157
+ if (!rawToolCalls.safe || rawToolCalls.value != null) {
158
+ return undefined;
159
+ }
132
160
  const typeProperty = readDataProperty(additionalKwargs, 'type');
133
161
  if (!typeProperty.safe) {
134
162
  return undefined;
@@ -138,16 +166,16 @@ function getStableTokenSurface(
138
166
  message as AIMessage,
139
167
  'tool_calls'
140
168
  );
141
- if (
142
- !toolCallsProperty.safe ||
143
- (!toolCallsProperty.own && 'tool_calls' in message)
144
- ) {
169
+ const resolvedToolCallsProperty = toolCallsProperty.own
170
+ ? toolCallsProperty
171
+ : readCacheMetadataProperty(message, 'tool_calls', 'message.tool_calls');
172
+ if (!resolvedToolCallsProperty.safe) {
145
173
  return undefined;
146
174
  }
147
- const toolCalls = toolCallsProperty.value;
175
+ const toolCalls = resolvedToolCallsProperty.value;
148
176
  if (
149
177
  toolCalls != null &&
150
- (!Array.isArray(toolCalls) || isProxy(toolCalls) || toolCalls.length > 0)
178
+ (isProxy(toolCalls) || !Array.isArray(toolCalls) || toolCalls.length > 0)
151
179
  ) {
152
180
  return undefined;
153
181
  }
@@ -230,6 +258,7 @@ function getProviderMessageOriginKey(message: BaseMessage): string | undefined {
230
258
 
231
259
  /** Measures repeated provider projections while tokenizing each message object once. */
232
260
  export function createContextPressureMeter({
261
+ provider,
233
262
  tokenCounter,
234
263
  tokenCountCache,
235
264
  sourceMessages,
@@ -382,6 +411,22 @@ export function createContextPressureMeter({
382
411
  ? availableMessageTokens -
383
412
  Math.min(availableMessageTokens, Math.max(0, baselineRemaining))
384
413
  : undefined;
414
+ const toolUsage = createToolMessageUsageAccumulator(provider);
415
+ const toolUsageState: { error?: Error } = {};
416
+ const addToolUsage = (
417
+ message: BaseMessage,
418
+ getRawTokens: () => number
419
+ ): void => {
420
+ if (toolUsageState.error != null) {
421
+ return;
422
+ }
423
+ try {
424
+ toolUsage.add(message, getRawTokens);
425
+ } catch (error) {
426
+ toolUsageState.error =
427
+ error instanceof Error ? error : new Error(String(error));
428
+ }
429
+ };
385
430
 
386
431
  let projectedMessageTokens: number;
387
432
  if (
@@ -423,15 +468,18 @@ export function createContextPressureMeter({
423
468
  const usedOrigins = new Set<number>();
424
469
  for (const message of messages) {
425
470
  const origin = origins.get(message);
471
+ let rawTokens: number | undefined;
472
+ const getRawTokens = (): number => (rawTokens ??= count(message));
473
+ addToolUsage(message, getRawTokens);
426
474
  if (origin == null || usedOrigins.has(origin)) {
427
- newRawTokens += count(message);
475
+ newRawTokens += getRawTokens();
428
476
  continue;
429
477
  }
430
478
  usedOrigins.add(origin);
431
479
  const projectionDelta =
432
480
  message === baseline[origin].message
433
481
  ? 0
434
- : count(message) - baseline[origin].rawTokens;
482
+ : getRawTokens() - baseline[origin].rawTokens;
435
483
  projectedMessageTokens += Math.max(
436
484
  0,
437
485
  attribution.attributedByOrigin[origin] +
@@ -442,16 +490,36 @@ export function createContextPressureMeter({
442
490
  } else {
443
491
  let rawTokens = REPLY_PRIMER_TOKENS;
444
492
  for (const message of messages) {
445
- rawTokens += count(message);
493
+ const messageTokens = count(message);
494
+ addToolUsage(message, () => messageTokens);
495
+ rawTokens += messageTokens;
446
496
  }
447
497
  projectedMessageTokens = Math.round(rawTokens * usageRatio);
448
498
  }
499
+ let measuredToolUsage:
500
+ | Pick<
501
+ t.TokenBudgetBreakdown,
502
+ 'toolMessageTokens' | 'toolMessageTokenCounts'
503
+ >
504
+ | undefined;
505
+ try {
506
+ measuredToolUsage =
507
+ toolUsageState.error == null ? toolUsage.finish(usageRatio) : undefined;
508
+ } catch (error) {
509
+ toolUsageState.error =
510
+ error instanceof Error ? error : new Error(String(error));
511
+ measuredToolUsage = undefined;
512
+ }
449
513
  return {
450
514
  fits: projectedMessageTokens <= availableMessageTokens,
451
515
  projectedMessageTokens,
452
516
  availableMessageTokens,
453
517
  contextBudget,
454
518
  effectiveInstructionTokens,
519
+ ...measuredToolUsage,
520
+ ...(toolUsageState.error == null
521
+ ? {}
522
+ : { toolMessageUsageError: toolUsageState.error }),
455
523
  };
456
524
  };
457
525
 
@@ -56,6 +56,7 @@ import {
56
56
  serializeToolCallInput,
57
57
  } from '@/messages/prune';
58
58
  import { toLangChainContent } from '@/messages/langchain';
59
+ import { isAnthropicThinkingContentBlock } from '@/messages/reasoningTypes';
59
60
 
60
61
  export type { OpenAICallOptions, OpenAIChatInput };
61
62
 
@@ -361,7 +362,7 @@ export function _convertMessagesToOpenAIParams(
361
362
  role = 'developer';
362
363
  }
363
364
 
364
- let hasAnthropicThinkingBlock: boolean = false;
365
+ let hasReasoningBlock = false;
365
366
 
366
367
  let content: unknown;
367
368
  if (
@@ -384,8 +385,8 @@ export function _convertMessagesToOpenAIParams(
384
385
  content = message.content;
385
386
  } else {
386
387
  content = message.content.map((m) => {
387
- if ('type' in m && m.type === 'thinking') {
388
- hasAnthropicThinkingBlock = true;
388
+ if (isAnthropicThinkingContentBlock(m)) {
389
+ hasReasoningBlock = true;
389
390
  return m;
390
391
  }
391
392
  if (isDataContentBlock(m)) {
@@ -416,7 +417,7 @@ export function _convertMessagesToOpenAIParams(
416
417
  completionParam.tool_calls = message.tool_calls.map(
417
418
  convertLangChainToolCallToBoundedOpenAI
418
419
  );
419
- completionParam.content = hasAnthropicThinkingBlock ? content : '';
420
+ completionParam.content = hasReasoningBlock ? content : '';
420
421
  if (
421
422
  options?.includeReasoningDetails === true &&
422
423
  message.additional_kwargs.reasoning_details != null
@@ -7,6 +7,7 @@ import type {
7
7
  import type { RunnableConfig } from '@langchain/core/runnables';
8
8
  import type { ToolOutputReferenceRegistry } from '@/tools/toolOutputReferences';
9
9
  import type * as t from '@/types';
10
+ import type { ToolHistoryPreparation } from '@/messages/toolHistoryProjection';
10
11
  import {
11
12
  projectCacheControlledToolOutputsToText,
12
13
  projectComputerCallOutputsToText,
@@ -27,15 +28,12 @@ import {
27
28
  stripBedrockCacheControl,
28
29
  cloneMessage,
29
30
  } from '@/messages/cache';
30
- import {
31
- isAnthropicLike,
32
- isGoogleLike,
33
- isOpenAILike,
34
- } from '@/utils/llm';
31
+ import { isAnthropicLike, isGoogleLike, isOpenAILike } from '@/utils/llm';
35
32
  import { annotateMessagesForLLM } from '@/tools/toolOutputReferences';
36
33
  import { providerRequiresStrictAlternation } from '@/llm/providers';
37
34
  import { getProviderFamily } from '@/llm/providerRegistry';
38
35
  import { Providers } from '@/common';
36
+ import { createToolHistoryPreparation } from '@/messages/toolHistoryProjection';
39
37
 
40
38
  const preparedProviderRequestBrand = Symbol('PreparedProviderRequest');
41
39
  const OMITTED_ATTACHMENT_TEXT =
@@ -90,6 +88,9 @@ export interface ProviderPayloadMeasurement {
90
88
  readonly availableMessageTokens?: number;
91
89
  readonly contextBudget?: number;
92
90
  readonly effectiveInstructionTokens?: number;
91
+ readonly toolMessageTokens?: number;
92
+ readonly toolMessageTokenCounts?: Record<string, number>;
93
+ readonly toolMessageUsageError?: Error;
93
94
  }
94
95
 
95
96
  export interface PreparedProviderRequest {
@@ -120,6 +121,7 @@ export interface PrepareProviderRequestParams {
120
121
  config?: RunnableConfig;
121
122
  maxToolResultChars?: number;
122
123
  measure?: (messages: BaseMessage[]) => ProviderPayloadMeasurement;
124
+ toolHistory?: ToolHistoryPreparation;
123
125
  }
124
126
 
125
127
  export function usesNativeOpenAIResponses(
@@ -164,11 +166,8 @@ export function usesNativeOpenAIResponses(
164
166
  } else if (effectiveCallOptions == null) {
165
167
  effectiveCallOptions = runnable.defaultOptions;
166
168
  }
167
- if (
168
- runnable._useResponsesApi?.(effectiveCallOptions) === true ||
169
- runnable._useResponsesApi?.(undefined) === true
170
- ) {
171
- return true;
169
+ if (typeof runnable._useResponsesApi === 'function') {
170
+ return runnable._useResponsesApi(effectiveCallOptions) === true;
172
171
  }
173
172
  } catch {
174
173
  // Continue through RunnableSequence/RunnableBinding wrappers.
@@ -208,6 +207,7 @@ interface ProjectMessagesForProviderParams {
208
207
  provider: t.ProviderName;
209
208
  maxToolResultChars?: number;
210
209
  callOptions?: unknown;
210
+ toolHistory?: ToolHistoryPreparation;
211
211
  }
212
212
 
213
213
  function isSerializedBuffer(value: object): value is SerializedBuffer {
@@ -380,10 +380,7 @@ function projectAttachmentsForProvider(
380
380
  }
381
381
  content ??= copyUsableContentPrefix(sourceContent, blockIndex);
382
382
  const mimeType = BEDROCK_DOCUMENT_MIME_TYPES[block.document.format];
383
- if (
384
- mimeType == null ||
385
- !canProjectBedrockDocument(provider, mimeType)
386
- ) {
383
+ if (mimeType == null || !canProjectBedrockDocument(provider, mimeType)) {
387
384
  continue;
388
385
  }
389
386
  const standardFile = toStandardFileBlock(block);
@@ -408,7 +405,12 @@ function projectAttachmentsForProvider(
408
405
  }
409
406
 
410
407
  function projectMessagesForProviderMode(
411
- { messages, provider, maxToolResultChars }: ProjectMessagesForProviderParams,
408
+ {
409
+ messages,
410
+ provider,
411
+ maxToolResultChars,
412
+ toolHistory,
413
+ }: ProjectMessagesForProviderParams,
412
414
  projectionMode: ProviderMessageProjectionMode
413
415
  ): BaseMessage[] {
414
416
  const providerFamily = getProviderFamily(provider);
@@ -417,7 +419,8 @@ function projectMessagesForProviderMode(
417
419
  projectToolStreamContentForProvider(
418
420
  messages,
419
421
  nativeOpenAIResponses ? 'native' : 'fallback',
420
- maxToolResultChars
422
+ maxToolResultChars,
423
+ toolHistory
421
424
  ),
422
425
  provider
423
426
  );
@@ -529,6 +532,7 @@ export function prepareProviderRequest({
529
532
  config,
530
533
  maxToolResultChars,
531
534
  measure,
535
+ toolHistory = createToolHistoryPreparation(),
532
536
  }: PrepareProviderRequestParams): PreparedProviderRequest {
533
537
  const projectionMode = resolveProviderMessageProjectionMode(
534
538
  model,
@@ -542,6 +546,7 @@ export function prepareProviderRequest({
542
546
  provider,
543
547
  maxToolResultChars,
544
548
  callOptions: config,
549
+ toolHistory,
545
550
  },
546
551
  projectionMode
547
552
  );
@@ -4,10 +4,10 @@ import type { BaseMessage, MessageContent } from '@langchain/core/messages';
4
4
  import type { ProviderMessageProvenancePart } from './provenance';
5
5
  import type { ProviderToolCallIndex } from './toolResultTypes';
6
6
  import {
7
+ appendProviderMessageToolCalls,
7
8
  appendProviderToolCallDescriptor,
8
9
  consumeProviderToolResultPair,
9
10
  getBoundedProviderPairingArrayProperty,
10
- getProviderAIMessageToolCallDescriptor,
11
11
  getProviderToolCallPartDescriptor,
12
12
  getProviderToolResultPartDescriptor,
13
13
  } from './toolResultTypes';
@@ -42,6 +42,7 @@ export const strictAlternationProviders: ReadonlySet<Providers> = new Set([
42
42
  */
43
43
  function collectProviderToolCalls(message: BaseMessage): ProviderToolCallIndex {
44
44
  const calls: ProviderToolCallIndex = new Map();
45
+ appendProviderMessageToolCalls(message, calls);
45
46
  const content = getBoundedProviderPairingArrayProperty(message, 'content');
46
47
  if (content != null) {
47
48
  for (let index = 0; index < content.length; index++) {
@@ -51,20 +52,6 @@ function collectProviderToolCalls(message: BaseMessage): ProviderToolCallIndex {
51
52
  }
52
53
  }
53
54
  }
54
- const toolCalls = getBoundedProviderPairingArrayProperty(
55
- message,
56
- 'tool_calls'
57
- );
58
- if (toolCalls != null) {
59
- for (let index = 0; index < toolCalls.length; index++) {
60
- const descriptor = getProviderAIMessageToolCallDescriptor(
61
- toolCalls[index]
62
- );
63
- if (descriptor != null) {
64
- appendProviderToolCallDescriptor(calls, descriptor);
65
- }
66
- }
67
- }
68
55
  return calls;
69
56
  }
70
57