@librechat/agents 3.1.75 → 3.1.77-dev.1

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 (272) hide show
  1. package/dist/cjs/graphs/Graph.cjs +22 -3
  2. package/dist/cjs/graphs/Graph.cjs.map +1 -1
  3. package/dist/cjs/hitl/askUserQuestion.cjs +67 -0
  4. package/dist/cjs/hitl/askUserQuestion.cjs.map +1 -0
  5. package/dist/cjs/hooks/HookRegistry.cjs +54 -0
  6. package/dist/cjs/hooks/HookRegistry.cjs.map +1 -1
  7. package/dist/cjs/hooks/createToolPolicyHook.cjs +115 -0
  8. package/dist/cjs/hooks/createToolPolicyHook.cjs.map +1 -0
  9. package/dist/cjs/hooks/executeHooks.cjs +40 -1
  10. package/dist/cjs/hooks/executeHooks.cjs.map +1 -1
  11. package/dist/cjs/hooks/types.cjs +1 -0
  12. package/dist/cjs/hooks/types.cjs.map +1 -1
  13. package/dist/cjs/langchain/google-common.cjs +3 -0
  14. package/dist/cjs/langchain/google-common.cjs.map +1 -0
  15. package/dist/cjs/langchain/index.cjs +86 -0
  16. package/dist/cjs/langchain/index.cjs.map +1 -0
  17. package/dist/cjs/langchain/language_models/chat_models.cjs +3 -0
  18. package/dist/cjs/langchain/language_models/chat_models.cjs.map +1 -0
  19. package/dist/cjs/langchain/messages/tool.cjs +3 -0
  20. package/dist/cjs/langchain/messages/tool.cjs.map +1 -0
  21. package/dist/cjs/langchain/messages.cjs +51 -0
  22. package/dist/cjs/langchain/messages.cjs.map +1 -0
  23. package/dist/cjs/langchain/openai.cjs +3 -0
  24. package/dist/cjs/langchain/openai.cjs.map +1 -0
  25. package/dist/cjs/langchain/prompts.cjs +11 -0
  26. package/dist/cjs/langchain/prompts.cjs.map +1 -0
  27. package/dist/cjs/langchain/runnables.cjs +19 -0
  28. package/dist/cjs/langchain/runnables.cjs.map +1 -0
  29. package/dist/cjs/langchain/tools.cjs +23 -0
  30. package/dist/cjs/langchain/tools.cjs.map +1 -0
  31. package/dist/cjs/langchain/utils/env.cjs +11 -0
  32. package/dist/cjs/langchain/utils/env.cjs.map +1 -0
  33. package/dist/cjs/llm/anthropic/index.cjs +145 -52
  34. package/dist/cjs/llm/anthropic/index.cjs.map +1 -1
  35. package/dist/cjs/llm/anthropic/types.cjs.map +1 -1
  36. package/dist/cjs/llm/anthropic/utils/message_inputs.cjs +21 -14
  37. package/dist/cjs/llm/anthropic/utils/message_inputs.cjs.map +1 -1
  38. package/dist/cjs/llm/anthropic/utils/message_outputs.cjs +84 -70
  39. package/dist/cjs/llm/anthropic/utils/message_outputs.cjs.map +1 -1
  40. package/dist/cjs/llm/bedrock/index.cjs +1 -1
  41. package/dist/cjs/llm/bedrock/index.cjs.map +1 -1
  42. package/dist/cjs/llm/bedrock/utils/message_inputs.cjs +213 -3
  43. package/dist/cjs/llm/bedrock/utils/message_inputs.cjs.map +1 -1
  44. package/dist/cjs/llm/bedrock/utils/message_outputs.cjs +2 -1
  45. package/dist/cjs/llm/bedrock/utils/message_outputs.cjs.map +1 -1
  46. package/dist/cjs/llm/google/utils/common.cjs +5 -4
  47. package/dist/cjs/llm/google/utils/common.cjs.map +1 -1
  48. package/dist/cjs/llm/openai/index.cjs +519 -655
  49. package/dist/cjs/llm/openai/index.cjs.map +1 -1
  50. package/dist/cjs/llm/openai/utils/index.cjs +20 -458
  51. package/dist/cjs/llm/openai/utils/index.cjs.map +1 -1
  52. package/dist/cjs/llm/openrouter/index.cjs +57 -175
  53. package/dist/cjs/llm/openrouter/index.cjs.map +1 -1
  54. package/dist/cjs/llm/vertexai/index.cjs +5 -3
  55. package/dist/cjs/llm/vertexai/index.cjs.map +1 -1
  56. package/dist/cjs/main.cjs +112 -3
  57. package/dist/cjs/main.cjs.map +1 -1
  58. package/dist/cjs/messages/cache.cjs +2 -1
  59. package/dist/cjs/messages/cache.cjs.map +1 -1
  60. package/dist/cjs/messages/core.cjs +7 -6
  61. package/dist/cjs/messages/core.cjs.map +1 -1
  62. package/dist/cjs/messages/format.cjs +73 -15
  63. package/dist/cjs/messages/format.cjs.map +1 -1
  64. package/dist/cjs/messages/langchain.cjs +26 -0
  65. package/dist/cjs/messages/langchain.cjs.map +1 -0
  66. package/dist/cjs/messages/prune.cjs +7 -6
  67. package/dist/cjs/messages/prune.cjs.map +1 -1
  68. package/dist/cjs/run.cjs +400 -42
  69. package/dist/cjs/run.cjs.map +1 -1
  70. package/dist/cjs/tools/ToolNode.cjs +556 -56
  71. package/dist/cjs/tools/ToolNode.cjs.map +1 -1
  72. package/dist/cjs/tools/search/search.cjs +55 -66
  73. package/dist/cjs/tools/search/search.cjs.map +1 -1
  74. package/dist/cjs/tools/search/tavily-scraper.cjs +189 -0
  75. package/dist/cjs/tools/search/tavily-scraper.cjs.map +1 -0
  76. package/dist/cjs/tools/search/tavily-search.cjs +372 -0
  77. package/dist/cjs/tools/search/tavily-search.cjs.map +1 -0
  78. package/dist/cjs/tools/search/tool.cjs +26 -4
  79. package/dist/cjs/tools/search/tool.cjs.map +1 -1
  80. package/dist/cjs/tools/search/utils.cjs +10 -3
  81. package/dist/cjs/tools/search/utils.cjs.map +1 -1
  82. package/dist/esm/graphs/Graph.mjs +22 -3
  83. package/dist/esm/graphs/Graph.mjs.map +1 -1
  84. package/dist/esm/hitl/askUserQuestion.mjs +65 -0
  85. package/dist/esm/hitl/askUserQuestion.mjs.map +1 -0
  86. package/dist/esm/hooks/HookRegistry.mjs +54 -0
  87. package/dist/esm/hooks/HookRegistry.mjs.map +1 -1
  88. package/dist/esm/hooks/createToolPolicyHook.mjs +113 -0
  89. package/dist/esm/hooks/createToolPolicyHook.mjs.map +1 -0
  90. package/dist/esm/hooks/executeHooks.mjs +40 -1
  91. package/dist/esm/hooks/executeHooks.mjs.map +1 -1
  92. package/dist/esm/hooks/types.mjs +1 -0
  93. package/dist/esm/hooks/types.mjs.map +1 -1
  94. package/dist/esm/langchain/google-common.mjs +2 -0
  95. package/dist/esm/langchain/google-common.mjs.map +1 -0
  96. package/dist/esm/langchain/index.mjs +5 -0
  97. package/dist/esm/langchain/index.mjs.map +1 -0
  98. package/dist/esm/langchain/language_models/chat_models.mjs +2 -0
  99. package/dist/esm/langchain/language_models/chat_models.mjs.map +1 -0
  100. package/dist/esm/langchain/messages/tool.mjs +2 -0
  101. package/dist/esm/langchain/messages/tool.mjs.map +1 -0
  102. package/dist/esm/langchain/messages.mjs +2 -0
  103. package/dist/esm/langchain/messages.mjs.map +1 -0
  104. package/dist/esm/langchain/openai.mjs +2 -0
  105. package/dist/esm/langchain/openai.mjs.map +1 -0
  106. package/dist/esm/langchain/prompts.mjs +2 -0
  107. package/dist/esm/langchain/prompts.mjs.map +1 -0
  108. package/dist/esm/langchain/runnables.mjs +2 -0
  109. package/dist/esm/langchain/runnables.mjs.map +1 -0
  110. package/dist/esm/langchain/tools.mjs +2 -0
  111. package/dist/esm/langchain/tools.mjs.map +1 -0
  112. package/dist/esm/langchain/utils/env.mjs +2 -0
  113. package/dist/esm/langchain/utils/env.mjs.map +1 -0
  114. package/dist/esm/llm/anthropic/index.mjs +146 -54
  115. package/dist/esm/llm/anthropic/index.mjs.map +1 -1
  116. package/dist/esm/llm/anthropic/types.mjs.map +1 -1
  117. package/dist/esm/llm/anthropic/utils/message_inputs.mjs +21 -14
  118. package/dist/esm/llm/anthropic/utils/message_inputs.mjs.map +1 -1
  119. package/dist/esm/llm/anthropic/utils/message_outputs.mjs +84 -71
  120. package/dist/esm/llm/anthropic/utils/message_outputs.mjs.map +1 -1
  121. package/dist/esm/llm/bedrock/index.mjs +1 -1
  122. package/dist/esm/llm/bedrock/index.mjs.map +1 -1
  123. package/dist/esm/llm/bedrock/utils/message_inputs.mjs +214 -4
  124. package/dist/esm/llm/bedrock/utils/message_inputs.mjs.map +1 -1
  125. package/dist/esm/llm/bedrock/utils/message_outputs.mjs +2 -1
  126. package/dist/esm/llm/bedrock/utils/message_outputs.mjs.map +1 -1
  127. package/dist/esm/llm/google/utils/common.mjs +5 -4
  128. package/dist/esm/llm/google/utils/common.mjs.map +1 -1
  129. package/dist/esm/llm/openai/index.mjs +520 -656
  130. package/dist/esm/llm/openai/index.mjs.map +1 -1
  131. package/dist/esm/llm/openai/utils/index.mjs +23 -459
  132. package/dist/esm/llm/openai/utils/index.mjs.map +1 -1
  133. package/dist/esm/llm/openrouter/index.mjs +57 -175
  134. package/dist/esm/llm/openrouter/index.mjs.map +1 -1
  135. package/dist/esm/llm/vertexai/index.mjs +5 -3
  136. package/dist/esm/llm/vertexai/index.mjs.map +1 -1
  137. package/dist/esm/main.mjs +7 -0
  138. package/dist/esm/main.mjs.map +1 -1
  139. package/dist/esm/messages/cache.mjs +2 -1
  140. package/dist/esm/messages/cache.mjs.map +1 -1
  141. package/dist/esm/messages/core.mjs +7 -6
  142. package/dist/esm/messages/core.mjs.map +1 -1
  143. package/dist/esm/messages/format.mjs +73 -15
  144. package/dist/esm/messages/format.mjs.map +1 -1
  145. package/dist/esm/messages/langchain.mjs +23 -0
  146. package/dist/esm/messages/langchain.mjs.map +1 -0
  147. package/dist/esm/messages/prune.mjs +7 -6
  148. package/dist/esm/messages/prune.mjs.map +1 -1
  149. package/dist/esm/run.mjs +400 -42
  150. package/dist/esm/run.mjs.map +1 -1
  151. package/dist/esm/tools/ToolNode.mjs +557 -57
  152. package/dist/esm/tools/ToolNode.mjs.map +1 -1
  153. package/dist/esm/tools/search/search.mjs +55 -66
  154. package/dist/esm/tools/search/search.mjs.map +1 -1
  155. package/dist/esm/tools/search/tavily-scraper.mjs +186 -0
  156. package/dist/esm/tools/search/tavily-scraper.mjs.map +1 -0
  157. package/dist/esm/tools/search/tavily-search.mjs +370 -0
  158. package/dist/esm/tools/search/tavily-search.mjs.map +1 -0
  159. package/dist/esm/tools/search/tool.mjs +26 -4
  160. package/dist/esm/tools/search/tool.mjs.map +1 -1
  161. package/dist/esm/tools/search/utils.mjs +10 -3
  162. package/dist/esm/tools/search/utils.mjs.map +1 -1
  163. package/dist/types/graphs/Graph.d.ts +7 -0
  164. package/dist/types/hitl/askUserQuestion.d.ts +55 -0
  165. package/dist/types/hitl/index.d.ts +6 -0
  166. package/dist/types/hooks/HookRegistry.d.ts +58 -0
  167. package/dist/types/hooks/createToolPolicyHook.d.ts +87 -0
  168. package/dist/types/hooks/index.d.ts +4 -1
  169. package/dist/types/hooks/types.d.ts +109 -3
  170. package/dist/types/index.d.ts +10 -0
  171. package/dist/types/langchain/google-common.d.ts +1 -0
  172. package/dist/types/langchain/index.d.ts +8 -0
  173. package/dist/types/langchain/language_models/chat_models.d.ts +1 -0
  174. package/dist/types/langchain/messages/tool.d.ts +1 -0
  175. package/dist/types/langchain/messages.d.ts +2 -0
  176. package/dist/types/langchain/openai.d.ts +1 -0
  177. package/dist/types/langchain/prompts.d.ts +1 -0
  178. package/dist/types/langchain/runnables.d.ts +2 -0
  179. package/dist/types/langchain/tools.d.ts +2 -0
  180. package/dist/types/langchain/utils/env.d.ts +1 -0
  181. package/dist/types/llm/anthropic/index.d.ts +22 -9
  182. package/dist/types/llm/anthropic/types.d.ts +5 -1
  183. package/dist/types/llm/anthropic/utils/message_outputs.d.ts +13 -6
  184. package/dist/types/llm/anthropic/utils/output_parsers.d.ts +1 -1
  185. package/dist/types/llm/openai/index.d.ts +21 -24
  186. package/dist/types/llm/openrouter/index.d.ts +11 -9
  187. package/dist/types/llm/vertexai/index.d.ts +1 -0
  188. package/dist/types/messages/cache.d.ts +4 -1
  189. package/dist/types/messages/format.d.ts +4 -1
  190. package/dist/types/messages/langchain.d.ts +27 -0
  191. package/dist/types/run.d.ts +117 -1
  192. package/dist/types/tools/ToolNode.d.ts +26 -1
  193. package/dist/types/tools/search/tavily-scraper.d.ts +19 -0
  194. package/dist/types/tools/search/tavily-search.d.ts +4 -0
  195. package/dist/types/tools/search/types.d.ts +99 -5
  196. package/dist/types/tools/search/utils.d.ts +2 -2
  197. package/dist/types/types/graph.d.ts +23 -37
  198. package/dist/types/types/hitl.d.ts +272 -0
  199. package/dist/types/types/index.d.ts +1 -0
  200. package/dist/types/types/llm.d.ts +3 -3
  201. package/dist/types/types/run.d.ts +33 -0
  202. package/dist/types/types/stream.d.ts +1 -1
  203. package/dist/types/types/tools.d.ts +19 -0
  204. package/package.json +80 -17
  205. package/src/graphs/Graph.ts +33 -4
  206. package/src/graphs/__tests__/composition.smoke.test.ts +188 -0
  207. package/src/hitl/askUserQuestion.ts +72 -0
  208. package/src/hitl/index.ts +7 -0
  209. package/src/hooks/HookRegistry.ts +71 -0
  210. package/src/hooks/__tests__/createToolPolicyHook.test.ts +259 -0
  211. package/src/hooks/createToolPolicyHook.ts +184 -0
  212. package/src/hooks/executeHooks.ts +50 -1
  213. package/src/hooks/index.ts +6 -0
  214. package/src/hooks/types.ts +112 -0
  215. package/src/index.ts +22 -0
  216. package/src/langchain/google-common.ts +1 -0
  217. package/src/langchain/index.ts +8 -0
  218. package/src/langchain/language_models/chat_models.ts +1 -0
  219. package/src/langchain/messages/tool.ts +5 -0
  220. package/src/langchain/messages.ts +21 -0
  221. package/src/langchain/openai.ts +1 -0
  222. package/src/langchain/prompts.ts +1 -0
  223. package/src/langchain/runnables.ts +7 -0
  224. package/src/langchain/tools.ts +8 -0
  225. package/src/langchain/utils/env.ts +1 -0
  226. package/src/llm/anthropic/index.ts +252 -84
  227. package/src/llm/anthropic/llm.spec.ts +751 -102
  228. package/src/llm/anthropic/types.ts +9 -1
  229. package/src/llm/anthropic/utils/message_inputs.ts +37 -19
  230. package/src/llm/anthropic/utils/message_outputs.ts +119 -101
  231. package/src/llm/bedrock/index.ts +2 -2
  232. package/src/llm/bedrock/llm.spec.ts +341 -0
  233. package/src/llm/bedrock/utils/message_inputs.ts +303 -4
  234. package/src/llm/bedrock/utils/message_outputs.ts +2 -1
  235. package/src/llm/custom-chat-models.smoke.test.ts +836 -0
  236. package/src/llm/google/llm.spec.ts +339 -57
  237. package/src/llm/google/utils/common.ts +53 -48
  238. package/src/llm/openai/contentBlocks.test.ts +346 -0
  239. package/src/llm/openai/index.ts +856 -833
  240. package/src/llm/openai/utils/index.ts +107 -78
  241. package/src/llm/openai/utils/messages.test.ts +159 -0
  242. package/src/llm/openrouter/index.ts +124 -247
  243. package/src/llm/openrouter/reasoning.test.ts +8 -1
  244. package/src/llm/vertexai/index.ts +11 -5
  245. package/src/llm/vertexai/llm.spec.ts +28 -1
  246. package/src/messages/cache.test.ts +4 -3
  247. package/src/messages/cache.ts +3 -2
  248. package/src/messages/core.ts +16 -9
  249. package/src/messages/format.ts +96 -16
  250. package/src/messages/formatAgentMessages.test.ts +166 -1
  251. package/src/messages/langchain.ts +39 -0
  252. package/src/messages/prune.ts +12 -8
  253. package/src/run.ts +456 -47
  254. package/src/scripts/caching.ts +2 -3
  255. package/src/specs/summarization.test.ts +51 -58
  256. package/src/tools/ToolNode.ts +706 -63
  257. package/src/tools/__tests__/hitl.test.ts +3593 -0
  258. package/src/tools/search/search.ts +83 -73
  259. package/src/tools/search/tavily-scraper.ts +235 -0
  260. package/src/tools/search/tavily-search.ts +424 -0
  261. package/src/tools/search/tavily.test.ts +965 -0
  262. package/src/tools/search/tool.ts +36 -26
  263. package/src/tools/search/types.ts +133 -8
  264. package/src/tools/search/utils.ts +13 -5
  265. package/src/types/graph.ts +32 -87
  266. package/src/types/hitl.ts +303 -0
  267. package/src/types/index.ts +1 -0
  268. package/src/types/llm.ts +3 -3
  269. package/src/types/run.ts +33 -0
  270. package/src/types/stream.ts +1 -1
  271. package/src/types/tools.ts +19 -0
  272. package/src/utils/llmConfig.ts +1 -6
@@ -1,5 +1,9 @@
1
1
  import Anthropic from '@anthropic-ai/sdk';
2
- import { BindToolsInput } from '@langchain/core/language_models/chat_models';
2
+
3
+ import type { BindToolsInput } from '@langchain/core/language_models/chat_models';
4
+ import type { AnthropicBeta } from '@anthropic-ai/sdk/resources';
5
+
6
+ export type { AnthropicBeta };
3
7
 
4
8
  export type AnthropicStreamUsage = Anthropic.Usage;
5
9
  export type AnthropicMessageDeltaEvent = Anthropic.MessageDeltaEvent;
@@ -22,8 +26,12 @@ export type AnthropicMessageCreateParams =
22
26
  export type AnthropicStreamingMessageCreateParams =
23
27
  Anthropic.MessageCreateParamsStreaming;
24
28
  export type AnthropicThinkingConfigParam = Anthropic.ThinkingConfigParam;
29
+ export type AnthropicContextManagementConfigParam =
30
+ Anthropic.Beta.BetaContextManagementConfig;
25
31
  export type AnthropicMessageStreamEvent = Anthropic.MessageStreamEvent;
26
32
  export type AnthropicRequestOptions = Anthropic.RequestOptions;
33
+ export type AnthropicMCPServerURLDefinition =
34
+ Anthropic.Beta.Messages.BetaRequestMCPServerURLDefinition;
27
35
  export type AnthropicToolChoice =
28
36
  | {
29
37
  type: 'tool';
@@ -10,10 +10,8 @@ import {
10
10
  type AIMessage,
11
11
  type ToolMessage,
12
12
  isAIMessage,
13
+ type Data,
13
14
  type StandardContentBlockConverter,
14
- type StandardTextBlock,
15
- type StandardImageBlock,
16
- type StandardFileBlock,
17
15
  MessageContentComplex,
18
16
  isDataContentBlock,
19
17
  convertToProviderContentBlock,
@@ -36,6 +34,19 @@ import {
36
34
  } from '../types';
37
35
  import { Constants } from '@/common';
38
36
 
37
+ type StandardTextBlock = Data.StandardTextBlock;
38
+ type StandardImageBlock = Data.StandardImageBlock;
39
+ type StandardFileBlock = Data.StandardFileBlock;
40
+ type ImageUrlContentBlock = MessageContentComplex & {
41
+ image_url: string | { url: string };
42
+ };
43
+ type GoogleFunctionCallBlock = MessageContentComplex & {
44
+ functionCall: {
45
+ name: string;
46
+ args: Record<string, unknown>;
47
+ };
48
+ };
49
+
39
50
  function _formatImage(imageUrl: string) {
40
51
  const parsed = parseBase64DataUrl({ dataUrl: imageUrl });
41
52
  if (parsed) {
@@ -83,7 +94,7 @@ function _ensureMessageContents(
83
94
  messages: BaseMessage[]
84
95
  ): (SystemMessage | HumanMessage | AIMessage)[] {
85
96
  // Merge runs of human/tool messages into single human messages with content blocks.
86
- const updatedMsgs = [];
97
+ const updatedMsgs: BaseMessage[] = [];
87
98
  for (const message of messages) {
88
99
  if (message._getType() === 'tool') {
89
100
  if (typeof message.content === 'string') {
@@ -134,7 +145,7 @@ function _ensureMessageContents(
134
145
  updatedMsgs.push(message);
135
146
  }
136
147
  }
137
- return updatedMsgs;
148
+ return updatedMsgs as (SystemMessage | HumanMessage | AIMessage)[];
138
149
  }
139
150
 
140
151
  export function _convertLangChainToolCallToAnthropic(
@@ -364,7 +375,8 @@ function _formatContent(message: BaseMessage) {
364
375
  if (typeof content === 'string') {
365
376
  return content;
366
377
  } else {
367
- const contentBlocks = content.map((contentPart) => {
378
+ const contentParts = content as MessageContentComplex[];
379
+ const contentBlocks = contentParts.map((contentPart) => {
368
380
  /**
369
381
  * Normalize server_tool_use blocks into a clean shape the API accepts.
370
382
  * These blocks may arrive with the correct type (server_tool_use) or mislabeled
@@ -465,10 +477,11 @@ function _formatContent(message: BaseMessage) {
465
477
 
466
478
  if (contentPart.type === 'image_url') {
467
479
  let source;
468
- if (typeof contentPart.image_url === 'string') {
469
- source = _formatImage(contentPart.image_url);
480
+ const imageUrl = (contentPart as ImageUrlContentBlock).image_url;
481
+ if (typeof imageUrl === 'string') {
482
+ source = _formatImage(imageUrl);
470
483
  } else {
471
- source = _formatImage(contentPart.image_url.url);
484
+ source = _formatImage(imageUrl.url);
472
485
  }
473
486
  return {
474
487
  type: 'image' as const, // Explicitly setting the type as "image"
@@ -484,38 +497,42 @@ function _formatContent(message: BaseMessage) {
484
497
  ...(cacheControl ? { cache_control: cacheControl } : {}),
485
498
  };
486
499
  } else if (contentPart.type === 'thinking') {
500
+ const thinkingPart = contentPart as AnthropicThinkingBlockParam;
487
501
  const block: AnthropicThinkingBlockParam = {
488
502
  type: 'thinking' as const, // Explicitly setting the type as "thinking"
489
- thinking: contentPart.thinking,
490
- signature: contentPart.signature,
503
+ thinking: thinkingPart.thinking,
504
+ signature: thinkingPart.signature,
491
505
  ...(cacheControl ? { cache_control: cacheControl } : {}),
492
506
  };
493
507
  return block;
494
508
  } else if (contentPart.type === 'redacted_thinking') {
509
+ const redactedPart = contentPart as AnthropicRedactedThinkingBlockParam;
495
510
  const block: AnthropicRedactedThinkingBlockParam = {
496
511
  type: 'redacted_thinking' as const, // Explicitly setting the type as "redacted_thinking"
497
- data: contentPart.data,
512
+ data: redactedPart.data,
498
513
  ...(cacheControl ? { cache_control: cacheControl } : {}),
499
514
  };
500
515
  return block;
501
516
  } else if (contentPart.type === 'search_result') {
517
+ const searchResultPart = contentPart as AnthropicSearchResultBlockParam;
502
518
  const block: AnthropicSearchResultBlockParam = {
503
519
  type: 'search_result' as const,
504
- title: contentPart.title,
505
- source: contentPart.source,
520
+ title: searchResultPart.title,
521
+ source: searchResultPart.source,
506
522
  ...('cache_control' in contentPart && contentPart.cache_control
507
523
  ? { cache_control: contentPart.cache_control }
508
524
  : {}),
509
525
  ...('citations' in contentPart && contentPart.citations
510
526
  ? { citations: contentPart.citations }
511
527
  : {}),
512
- content: contentPart.content,
528
+ content: searchResultPart.content,
513
529
  };
514
530
  return block;
515
531
  } else if (contentPart.type === 'compaction') {
532
+ const compactionPart = contentPart as AnthropicCompactionBlockParam;
516
533
  const block: AnthropicCompactionBlockParam = {
517
534
  type: 'compaction' as const,
518
- content: contentPart.content,
535
+ content: compactionPart.content,
519
536
  ...(cacheControl ? { cache_control: cacheControl } : {}),
520
537
  };
521
538
  return block;
@@ -585,12 +602,13 @@ function _formatContent(message: BaseMessage) {
585
602
  typeof contentPart.functionCall === 'object' &&
586
603
  isAIMessage(message)
587
604
  ) {
605
+ const functionCallPart = contentPart as GoogleFunctionCallBlock;
588
606
  const correspondingToolCall = message.tool_calls?.find(
589
- (toolCall) => toolCall.name === contentPart.functionCall.name
607
+ (toolCall) => toolCall.name === functionCallPart.functionCall.name
590
608
  );
591
609
  if (!correspondingToolCall) {
592
610
  throw new Error(
593
- `Could not find tool call for function call ${contentPart.functionCall.name}`
611
+ `Could not find tool call for function call ${functionCallPart.functionCall.name}`
594
612
  );
595
613
  }
596
614
  // Google GenAI models include a `functionCall` object inside content. We should ignore it as Anthropic will not support it.
@@ -598,7 +616,7 @@ function _formatContent(message: BaseMessage) {
598
616
  id: correspondingToolCall.id,
599
617
  type: 'tool_use',
600
618
  name: correspondingToolCall.name,
601
- input: contentPart.functionCall.args,
619
+ input: functionCallPart.functionCall.args,
602
620
  };
603
621
  } else {
604
622
  console.error(
@@ -1,16 +1,47 @@
1
- /**
2
- * This util file contains functions for converting Anthropic messages to LangChain messages.
3
- */
4
- import Anthropic from '@anthropic-ai/sdk';
5
- import {
6
- AIMessage,
7
- AIMessageChunk,
8
- UsageMetadata,
9
- } from '@langchain/core/messages';
1
+ /** This util file contains functions for converting Anthropic messages to LangChain messages. */
2
+ import { AIMessage, AIMessageChunk } from '@langchain/core/messages';
3
+
4
+ import type Anthropic from '@anthropic-ai/sdk';
5
+ import type { UsageMetadata } from '@langchain/core/messages';
10
6
  import type { ToolCallChunk } from '@langchain/core/messages/tool';
11
- import { ChatGeneration } from '@langchain/core/outputs';
7
+ import type { ChatGeneration } from '@langchain/core/outputs';
8
+ import type { MessageContentComplex } from '@/types';
9
+ import type { AnthropicMessageResponse } from '../types';
10
+
11
+ import { toLangChainContent } from '@/messages/langchain';
12
12
  import { extractToolCalls } from './output_parsers';
13
- import { AnthropicMessageResponse } from '../types';
13
+
14
+ interface AnthropicUsageData {
15
+ input_tokens?: number | null;
16
+ output_tokens?: number | null;
17
+ cache_creation_input_tokens?: number | null;
18
+ cache_read_input_tokens?: number | null;
19
+ }
20
+
21
+ export function getAnthropicUsageMetadata(
22
+ usage: AnthropicUsageData | null | undefined
23
+ ): UsageMetadata | undefined {
24
+ if (usage == null) {
25
+ return undefined;
26
+ }
27
+
28
+ const cacheCreationInputTokens = usage.cache_creation_input_tokens ?? 0;
29
+ const cacheReadInputTokens = usage.cache_read_input_tokens ?? 0;
30
+ // Anthropic reports uncached input separately from cache creation/read tokens.
31
+ const inputTokens =
32
+ (usage.input_tokens ?? 0) + cacheCreationInputTokens + cacheReadInputTokens;
33
+ const outputTokens = usage.output_tokens ?? 0;
34
+
35
+ return {
36
+ input_tokens: inputTokens,
37
+ output_tokens: outputTokens,
38
+ total_tokens: inputTokens + outputTokens,
39
+ input_token_details: {
40
+ cache_creation: cacheCreationInputTokens,
41
+ cache_read: cacheReadInputTokens,
42
+ },
43
+ };
44
+ }
14
45
 
15
46
  function _isAnthropicCompactionBlock(
16
47
  block: unknown
@@ -32,34 +63,23 @@ export function _makeMessageChunkFromAnthropicEvent(
32
63
  ): {
33
64
  chunk: AIMessageChunk;
34
65
  } | null {
66
+ const responseMetadata = { model_provider: 'anthropic' };
35
67
  if (data.type === 'message_start') {
36
68
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
37
69
  const { content, usage, ...additionalKwargs } = data.message;
38
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
39
- const filteredAdditionalKwargs: Record<string, any> = {};
40
- for (const [key, value] of Object.entries(additionalKwargs)) {
41
- if (value !== undefined && value !== null) {
42
- filteredAdditionalKwargs[key] = value;
43
- }
44
- }
45
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
46
- const { input_tokens, output_tokens, ...rest }: Record<string, any> =
47
- usage ?? {};
48
- const usageMetadata: UsageMetadata = {
49
- input_tokens,
50
- output_tokens,
51
- total_tokens: input_tokens + output_tokens,
52
- input_token_details: {
53
- cache_creation: rest.cache_creation_input_tokens,
54
- cache_read: rest.cache_read_input_tokens,
55
- },
56
- };
70
+ const {
71
+ input_tokens: _inputTokens,
72
+ output_tokens: _outputTokens,
73
+ ...rest
74
+ } = usage;
75
+ const usageMetadata = getAnthropicUsageMetadata(usage);
57
76
  return {
58
77
  chunk: new AIMessageChunk({
59
78
  content: fields.coerceContentToString ? '' : [],
60
- additional_kwargs: filteredAdditionalKwargs,
79
+ additional_kwargs: additionalKwargs,
61
80
  usage_metadata: fields.streamUsage ? usageMetadata : undefined,
62
81
  response_metadata: {
82
+ ...responseMetadata,
63
83
  usage: {
64
84
  ...rest,
65
85
  },
@@ -68,20 +88,25 @@ export function _makeMessageChunkFromAnthropicEvent(
68
88
  }),
69
89
  };
70
90
  } else if (data.type === 'message_delta') {
91
+ const messageDeltaResponseMetadata = { ...responseMetadata };
92
+ if ('context_management' in data.delta) {
93
+ Object.assign(messageDeltaResponseMetadata, {
94
+ context_management: data.delta.context_management,
95
+ });
96
+ }
71
97
  const usageMetadata: UsageMetadata = {
72
98
  input_tokens: 0,
73
99
  output_tokens: data.usage.output_tokens,
74
100
  total_tokens: data.usage.output_tokens,
75
101
  input_token_details: {
76
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
77
- cache_creation: (data.usage as any).cache_creation_input_tokens,
78
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
79
- cache_read: (data.usage as any).cache_read_input_tokens,
102
+ cache_creation: data.usage.cache_creation_input_tokens ?? undefined,
103
+ cache_read: data.usage.cache_read_input_tokens ?? undefined,
80
104
  },
81
105
  };
82
106
  return {
83
107
  chunk: new AIMessageChunk({
84
108
  content: fields.coerceContentToString ? '' : [],
109
+ response_metadata: messageDeltaResponseMetadata,
85
110
  additional_kwargs: { ...data.delta },
86
111
  usage_metadata: fields.streamUsage ? usageMetadata : undefined,
87
112
  }),
@@ -119,21 +144,21 @@ export function _makeMessageChunkFromAnthropicEvent(
119
144
  } else {
120
145
  toolCallChunks = [];
121
146
  }
147
+ const content = [
148
+ {
149
+ index: data.index,
150
+ ...data.content_block,
151
+ input:
152
+ contentBlock.type === 'server_tool_use' ||
153
+ contentBlock.type === 'tool_use'
154
+ ? ''
155
+ : undefined,
156
+ },
157
+ ];
122
158
  return {
123
159
  chunk: new AIMessageChunk({
124
- content: fields.coerceContentToString
125
- ? ''
126
- : [
127
- {
128
- index: data.index,
129
- ...data.content_block,
130
- input:
131
- contentBlock.type === 'server_tool_use' ||
132
- contentBlock.type === 'tool_use'
133
- ? ''
134
- : undefined,
135
- },
136
- ],
160
+ content: fields.coerceContentToString ? '' : content,
161
+ response_metadata: responseMetadata,
137
162
  additional_kwargs: {},
138
163
  tool_call_chunks: toolCallChunks,
139
164
  }),
@@ -154,8 +179,7 @@ export function _makeMessageChunkFromAnthropicEvent(
154
179
  }),
155
180
  };
156
181
  } else {
157
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
158
- const contentBlock: Record<string, any> = data.delta;
182
+ const contentBlock: Record<string, unknown> = { ...data.delta };
159
183
  if ('citation' in contentBlock) {
160
184
  contentBlock.citations = [contentBlock.citation];
161
185
  delete contentBlock.citation;
@@ -167,6 +191,7 @@ export function _makeMessageChunkFromAnthropicEvent(
167
191
  return {
168
192
  chunk: new AIMessageChunk({
169
193
  content: [{ index: data.index, ...contentBlock, type: 'thinking' }],
194
+ response_metadata: responseMetadata,
170
195
  }),
171
196
  };
172
197
  }
@@ -174,6 +199,7 @@ export function _makeMessageChunkFromAnthropicEvent(
174
199
  return {
175
200
  chunk: new AIMessageChunk({
176
201
  content: [{ index: data.index, ...contentBlock, type: 'text' }],
202
+ response_metadata: responseMetadata,
177
203
  }),
178
204
  };
179
205
  }
@@ -181,17 +207,17 @@ export function _makeMessageChunkFromAnthropicEvent(
181
207
  data.type === 'content_block_delta' &&
182
208
  data.delta.type === 'input_json_delta'
183
209
  ) {
210
+ const content = [
211
+ {
212
+ index: data.index,
213
+ input: data.delta.partial_json,
214
+ type: data.delta.type,
215
+ },
216
+ ];
184
217
  return {
185
218
  chunk: new AIMessageChunk({
186
- content: fields.coerceContentToString
187
- ? ''
188
- : [
189
- {
190
- index: data.index,
191
- input: data.delta.partial_json,
192
- type: data.delta.type,
193
- },
194
- ],
219
+ content: fields.coerceContentToString ? '' : content,
220
+ response_metadata: responseMetadata,
195
221
  additional_kwargs: {},
196
222
  tool_call_chunks: [
197
223
  {
@@ -206,21 +232,19 @@ export function _makeMessageChunkFromAnthropicEvent(
206
232
  data.content_block.type === 'text'
207
233
  ) {
208
234
  const content = data.content_block.text;
209
- if (content !== undefined) {
210
- return {
211
- chunk: new AIMessageChunk({
212
- content: fields.coerceContentToString
213
- ? content
214
- : [
215
- {
216
- index: data.index,
217
- ...data.content_block,
218
- },
219
- ],
220
- additional_kwargs: {},
221
- }),
222
- };
223
- }
235
+ const contentBlock = [
236
+ {
237
+ index: data.index,
238
+ ...data.content_block,
239
+ },
240
+ ];
241
+ return {
242
+ chunk: new AIMessageChunk({
243
+ content: fields.coerceContentToString ? content : contentBlock,
244
+ response_metadata: responseMetadata,
245
+ additional_kwargs: {},
246
+ }),
247
+ };
224
248
  } else if (
225
249
  data.type === 'content_block_start' &&
226
250
  data.content_block.type === 'redacted_thinking'
@@ -230,6 +254,7 @@ export function _makeMessageChunkFromAnthropicEvent(
230
254
  content: fields.coerceContentToString
231
255
  ? ''
232
256
  : [{ index: data.index, ...data.content_block }],
257
+ response_metadata: responseMetadata,
233
258
  }),
234
259
  };
235
260
  } else if (
@@ -242,6 +267,7 @@ export function _makeMessageChunkFromAnthropicEvent(
242
267
  content: fields.coerceContentToString
243
268
  ? content
244
269
  : [{ index: data.index, ...data.content_block }],
270
+ response_metadata: responseMetadata,
245
271
  }),
246
272
  };
247
273
  } else if (
@@ -253,23 +279,24 @@ export function _makeMessageChunkFromAnthropicEvent(
253
279
  content: fields.coerceContentToString
254
280
  ? ''
255
281
  : [{ index: data.index, ...data.content_block }],
282
+ response_metadata: responseMetadata,
256
283
  }),
257
284
  };
258
285
  } else if (
259
286
  data.type === 'content_block_delta' &&
260
287
  data.delta.type === 'compaction_delta'
261
288
  ) {
289
+ const content = [
290
+ {
291
+ index: data.index,
292
+ ...data.delta,
293
+ type: 'compaction',
294
+ },
295
+ ];
262
296
  return {
263
297
  chunk: new AIMessageChunk({
264
- content: fields.coerceContentToString
265
- ? ''
266
- : [
267
- {
268
- index: data.index,
269
- ...data.delta,
270
- type: 'compaction',
271
- },
272
- ],
298
+ content: fields.coerceContentToString ? '' : content,
299
+ response_metadata: responseMetadata,
273
300
  }),
274
301
  };
275
302
  }
@@ -280,20 +307,12 @@ export function anthropicResponseToChatMessages(
280
307
  messages: AnthropicMessageResponse[],
281
308
  additionalKwargs: Record<string, unknown>
282
309
  ): ChatGeneration[] {
283
- const usage: Record<string, number> | null | undefined =
284
- additionalKwargs.usage as Record<string, number> | null | undefined;
285
- const usageMetadata =
286
- usage != null
287
- ? {
288
- input_tokens: usage.input_tokens ?? 0,
289
- output_tokens: usage.output_tokens ?? 0,
290
- total_tokens: (usage.input_tokens ?? 0) + (usage.output_tokens ?? 0),
291
- input_token_details: {
292
- cache_creation: usage.cache_creation_input_tokens,
293
- cache_read: usage.cache_read_input_tokens,
294
- },
295
- }
296
- : undefined;
310
+ const responseMetadata = {
311
+ ...additionalKwargs,
312
+ model_provider: 'anthropic',
313
+ };
314
+ const usage = additionalKwargs.usage as AnthropicUsageData | null | undefined;
315
+ const usageMetadata = getAnthropicUsageMetadata(usage);
297
316
  if (messages.length === 1 && messages[0].type === 'text') {
298
317
  return [
299
318
  {
@@ -302,7 +321,7 @@ export function anthropicResponseToChatMessages(
302
321
  content: messages[0].text,
303
322
  additional_kwargs: additionalKwargs,
304
323
  usage_metadata: usageMetadata,
305
- response_metadata: additionalKwargs,
324
+ response_metadata: responseMetadata,
306
325
  id: additionalKwargs.id as string,
307
326
  }),
308
327
  },
@@ -313,12 +332,11 @@ export function anthropicResponseToChatMessages(
313
332
  {
314
333
  text: '',
315
334
  message: new AIMessage({
316
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
317
- content: messages as any,
335
+ content: toLangChainContent(messages as MessageContentComplex[]),
318
336
  additional_kwargs: additionalKwargs,
319
337
  tool_calls: toolCalls,
320
338
  usage_metadata: usageMetadata,
321
- response_metadata: additionalKwargs,
339
+ response_metadata: responseMetadata,
322
340
  id: additionalKwargs.id as string,
323
341
  }),
324
342
  },
@@ -27,7 +27,7 @@ import { AIMessageChunk } from '@langchain/core/messages';
27
27
  import { ChatGenerationChunk, ChatResult } from '@langchain/core/outputs';
28
28
  import type { CallbackManagerForLLMRun } from '@langchain/core/callbacks/manager';
29
29
  import type { ChatBedrockConverseInput } from '@langchain/aws';
30
- import type { BaseMessage } from '@langchain/core/messages';
30
+ import type { BaseMessage, ResponseMetadata } from '@langchain/core/messages';
31
31
  import {
32
32
  convertToConverseMessages,
33
33
  handleConverseStreamContentBlockStart,
@@ -238,7 +238,7 @@ export class CustomChatBedrockConverse extends ChatBedrockConverse {
238
238
  text: '',
239
239
  message: new AIMessageChunk({
240
240
  content: '',
241
- response_metadata: event,
241
+ response_metadata: { ...event } as ResponseMetadata,
242
242
  }),
243
243
  });
244
244
  }