@librechat/agents 2.4.322 → 3.0.0-rc1

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 (258) hide show
  1. package/dist/cjs/agents/AgentContext.cjs +218 -0
  2. package/dist/cjs/agents/AgentContext.cjs.map +1 -0
  3. package/dist/cjs/common/enum.cjs +14 -5
  4. package/dist/cjs/common/enum.cjs.map +1 -1
  5. package/dist/cjs/events.cjs +10 -6
  6. package/dist/cjs/events.cjs.map +1 -1
  7. package/dist/cjs/graphs/Graph.cjs +309 -212
  8. package/dist/cjs/graphs/Graph.cjs.map +1 -1
  9. package/dist/cjs/graphs/MultiAgentGraph.cjs +322 -0
  10. package/dist/cjs/graphs/MultiAgentGraph.cjs.map +1 -0
  11. package/dist/cjs/llm/anthropic/index.cjs +54 -9
  12. package/dist/cjs/llm/anthropic/index.cjs.map +1 -1
  13. package/dist/cjs/llm/anthropic/types.cjs.map +1 -1
  14. package/dist/cjs/llm/anthropic/utils/message_inputs.cjs +52 -6
  15. package/dist/cjs/llm/anthropic/utils/message_inputs.cjs.map +1 -1
  16. package/dist/cjs/llm/anthropic/utils/message_outputs.cjs +22 -2
  17. package/dist/cjs/llm/anthropic/utils/message_outputs.cjs.map +1 -1
  18. package/dist/cjs/llm/anthropic/utils/tools.cjs +29 -0
  19. package/dist/cjs/llm/anthropic/utils/tools.cjs.map +1 -0
  20. package/dist/cjs/llm/google/index.cjs +144 -0
  21. package/dist/cjs/llm/google/index.cjs.map +1 -0
  22. package/dist/cjs/llm/google/utils/common.cjs +477 -0
  23. package/dist/cjs/llm/google/utils/common.cjs.map +1 -0
  24. package/dist/cjs/llm/ollama/index.cjs +67 -0
  25. package/dist/cjs/llm/ollama/index.cjs.map +1 -0
  26. package/dist/cjs/llm/ollama/utils.cjs +158 -0
  27. package/dist/cjs/llm/ollama/utils.cjs.map +1 -0
  28. package/dist/cjs/llm/openai/index.cjs +389 -3
  29. package/dist/cjs/llm/openai/index.cjs.map +1 -1
  30. package/dist/cjs/llm/openai/utils/index.cjs +672 -0
  31. package/dist/cjs/llm/openai/utils/index.cjs.map +1 -0
  32. package/dist/cjs/llm/providers.cjs +15 -15
  33. package/dist/cjs/llm/providers.cjs.map +1 -1
  34. package/dist/cjs/llm/text.cjs +14 -3
  35. package/dist/cjs/llm/text.cjs.map +1 -1
  36. package/dist/cjs/llm/vertexai/index.cjs +330 -0
  37. package/dist/cjs/llm/vertexai/index.cjs.map +1 -0
  38. package/dist/cjs/main.cjs +11 -0
  39. package/dist/cjs/main.cjs.map +1 -1
  40. package/dist/cjs/run.cjs +120 -81
  41. package/dist/cjs/run.cjs.map +1 -1
  42. package/dist/cjs/stream.cjs +85 -51
  43. package/dist/cjs/stream.cjs.map +1 -1
  44. package/dist/cjs/tools/ToolNode.cjs +10 -4
  45. package/dist/cjs/tools/ToolNode.cjs.map +1 -1
  46. package/dist/cjs/tools/handlers.cjs +119 -13
  47. package/dist/cjs/tools/handlers.cjs.map +1 -1
  48. package/dist/cjs/tools/search/anthropic.cjs +40 -0
  49. package/dist/cjs/tools/search/anthropic.cjs.map +1 -0
  50. package/dist/cjs/tools/search/firecrawl.cjs +55 -9
  51. package/dist/cjs/tools/search/firecrawl.cjs.map +1 -1
  52. package/dist/cjs/tools/search/format.cjs +6 -6
  53. package/dist/cjs/tools/search/format.cjs.map +1 -1
  54. package/dist/cjs/tools/search/rerankers.cjs +7 -29
  55. package/dist/cjs/tools/search/rerankers.cjs.map +1 -1
  56. package/dist/cjs/tools/search/search.cjs +86 -16
  57. package/dist/cjs/tools/search/search.cjs.map +1 -1
  58. package/dist/cjs/tools/search/tool.cjs +4 -2
  59. package/dist/cjs/tools/search/tool.cjs.map +1 -1
  60. package/dist/cjs/tools/search/utils.cjs +1 -1
  61. package/dist/cjs/tools/search/utils.cjs.map +1 -1
  62. package/dist/cjs/utils/events.cjs +31 -0
  63. package/dist/cjs/utils/events.cjs.map +1 -0
  64. package/dist/cjs/utils/title.cjs +57 -21
  65. package/dist/cjs/utils/title.cjs.map +1 -1
  66. package/dist/cjs/utils/tokens.cjs +54 -7
  67. package/dist/cjs/utils/tokens.cjs.map +1 -1
  68. package/dist/esm/agents/AgentContext.mjs +216 -0
  69. package/dist/esm/agents/AgentContext.mjs.map +1 -0
  70. package/dist/esm/common/enum.mjs +15 -6
  71. package/dist/esm/common/enum.mjs.map +1 -1
  72. package/dist/esm/events.mjs +10 -6
  73. package/dist/esm/events.mjs.map +1 -1
  74. package/dist/esm/graphs/Graph.mjs +311 -214
  75. package/dist/esm/graphs/Graph.mjs.map +1 -1
  76. package/dist/esm/graphs/MultiAgentGraph.mjs +320 -0
  77. package/dist/esm/graphs/MultiAgentGraph.mjs.map +1 -0
  78. package/dist/esm/llm/anthropic/index.mjs +54 -9
  79. package/dist/esm/llm/anthropic/index.mjs.map +1 -1
  80. package/dist/esm/llm/anthropic/types.mjs.map +1 -1
  81. package/dist/esm/llm/anthropic/utils/message_inputs.mjs +52 -6
  82. package/dist/esm/llm/anthropic/utils/message_inputs.mjs.map +1 -1
  83. package/dist/esm/llm/anthropic/utils/message_outputs.mjs +22 -2
  84. package/dist/esm/llm/anthropic/utils/message_outputs.mjs.map +1 -1
  85. package/dist/esm/llm/anthropic/utils/tools.mjs +27 -0
  86. package/dist/esm/llm/anthropic/utils/tools.mjs.map +1 -0
  87. package/dist/esm/llm/google/index.mjs +142 -0
  88. package/dist/esm/llm/google/index.mjs.map +1 -0
  89. package/dist/esm/llm/google/utils/common.mjs +471 -0
  90. package/dist/esm/llm/google/utils/common.mjs.map +1 -0
  91. package/dist/esm/llm/ollama/index.mjs +65 -0
  92. package/dist/esm/llm/ollama/index.mjs.map +1 -0
  93. package/dist/esm/llm/ollama/utils.mjs +155 -0
  94. package/dist/esm/llm/ollama/utils.mjs.map +1 -0
  95. package/dist/esm/llm/openai/index.mjs +388 -4
  96. package/dist/esm/llm/openai/index.mjs.map +1 -1
  97. package/dist/esm/llm/openai/utils/index.mjs +666 -0
  98. package/dist/esm/llm/openai/utils/index.mjs.map +1 -0
  99. package/dist/esm/llm/providers.mjs +5 -5
  100. package/dist/esm/llm/providers.mjs.map +1 -1
  101. package/dist/esm/llm/text.mjs +14 -3
  102. package/dist/esm/llm/text.mjs.map +1 -1
  103. package/dist/esm/llm/vertexai/index.mjs +328 -0
  104. package/dist/esm/llm/vertexai/index.mjs.map +1 -0
  105. package/dist/esm/main.mjs +6 -5
  106. package/dist/esm/main.mjs.map +1 -1
  107. package/dist/esm/run.mjs +121 -83
  108. package/dist/esm/run.mjs.map +1 -1
  109. package/dist/esm/stream.mjs +87 -54
  110. package/dist/esm/stream.mjs.map +1 -1
  111. package/dist/esm/tools/ToolNode.mjs +10 -4
  112. package/dist/esm/tools/ToolNode.mjs.map +1 -1
  113. package/dist/esm/tools/handlers.mjs +119 -15
  114. package/dist/esm/tools/handlers.mjs.map +1 -1
  115. package/dist/esm/tools/search/anthropic.mjs +37 -0
  116. package/dist/esm/tools/search/anthropic.mjs.map +1 -0
  117. package/dist/esm/tools/search/firecrawl.mjs +55 -9
  118. package/dist/esm/tools/search/firecrawl.mjs.map +1 -1
  119. package/dist/esm/tools/search/format.mjs +7 -7
  120. package/dist/esm/tools/search/format.mjs.map +1 -1
  121. package/dist/esm/tools/search/rerankers.mjs +7 -29
  122. package/dist/esm/tools/search/rerankers.mjs.map +1 -1
  123. package/dist/esm/tools/search/search.mjs +86 -16
  124. package/dist/esm/tools/search/search.mjs.map +1 -1
  125. package/dist/esm/tools/search/tool.mjs +4 -2
  126. package/dist/esm/tools/search/tool.mjs.map +1 -1
  127. package/dist/esm/tools/search/utils.mjs +1 -1
  128. package/dist/esm/tools/search/utils.mjs.map +1 -1
  129. package/dist/esm/utils/events.mjs +29 -0
  130. package/dist/esm/utils/events.mjs.map +1 -0
  131. package/dist/esm/utils/title.mjs +57 -22
  132. package/dist/esm/utils/title.mjs.map +1 -1
  133. package/dist/esm/utils/tokens.mjs +54 -8
  134. package/dist/esm/utils/tokens.mjs.map +1 -1
  135. package/dist/types/agents/AgentContext.d.ts +91 -0
  136. package/dist/types/common/enum.d.ts +15 -6
  137. package/dist/types/events.d.ts +5 -4
  138. package/dist/types/graphs/Graph.d.ts +64 -67
  139. package/dist/types/graphs/MultiAgentGraph.d.ts +37 -0
  140. package/dist/types/graphs/index.d.ts +1 -0
  141. package/dist/types/llm/anthropic/index.d.ts +11 -0
  142. package/dist/types/llm/anthropic/types.d.ts +9 -3
  143. package/dist/types/llm/anthropic/utils/message_inputs.d.ts +1 -1
  144. package/dist/types/llm/anthropic/utils/output_parsers.d.ts +4 -4
  145. package/dist/types/llm/anthropic/utils/tools.d.ts +3 -0
  146. package/dist/types/llm/google/index.d.ts +13 -0
  147. package/dist/types/llm/google/types.d.ts +32 -0
  148. package/dist/types/llm/google/utils/common.d.ts +19 -0
  149. package/dist/types/llm/google/utils/tools.d.ts +10 -0
  150. package/dist/types/llm/google/utils/zod_to_genai_parameters.d.ts +14 -0
  151. package/dist/types/llm/ollama/index.d.ts +7 -0
  152. package/dist/types/llm/ollama/utils.d.ts +7 -0
  153. package/dist/types/llm/openai/index.d.ts +72 -3
  154. package/dist/types/llm/openai/types.d.ts +10 -0
  155. package/dist/types/llm/openai/utils/index.d.ts +20 -0
  156. package/dist/types/llm/text.d.ts +1 -1
  157. package/dist/types/llm/vertexai/index.d.ts +293 -0
  158. package/dist/types/messages/reducer.d.ts +9 -0
  159. package/dist/types/run.d.ts +19 -12
  160. package/dist/types/scripts/ant_web_search.d.ts +1 -0
  161. package/dist/types/scripts/args.d.ts +2 -1
  162. package/dist/types/scripts/handoff-test.d.ts +1 -0
  163. package/dist/types/scripts/multi-agent-conditional.d.ts +1 -0
  164. package/dist/types/scripts/multi-agent-parallel.d.ts +1 -0
  165. package/dist/types/scripts/multi-agent-sequence.d.ts +1 -0
  166. package/dist/types/scripts/multi-agent-test.d.ts +1 -0
  167. package/dist/types/stream.d.ts +10 -3
  168. package/dist/types/tools/CodeExecutor.d.ts +2 -2
  169. package/dist/types/tools/ToolNode.d.ts +1 -1
  170. package/dist/types/tools/handlers.d.ts +17 -4
  171. package/dist/types/tools/search/anthropic.d.ts +16 -0
  172. package/dist/types/tools/search/firecrawl.d.ts +15 -0
  173. package/dist/types/tools/search/rerankers.d.ts +0 -1
  174. package/dist/types/tools/search/types.d.ts +30 -9
  175. package/dist/types/types/graph.d.ts +95 -15
  176. package/dist/types/types/llm.d.ts +24 -10
  177. package/dist/types/types/run.d.ts +46 -8
  178. package/dist/types/types/stream.d.ts +16 -2
  179. package/dist/types/types/tools.d.ts +1 -1
  180. package/dist/types/utils/events.d.ts +6 -0
  181. package/dist/types/utils/title.d.ts +2 -1
  182. package/dist/types/utils/tokens.d.ts +24 -0
  183. package/package.json +33 -17
  184. package/src/agents/AgentContext.ts +315 -0
  185. package/src/common/enum.ts +14 -5
  186. package/src/events.ts +24 -13
  187. package/src/graphs/Graph.ts +495 -312
  188. package/src/graphs/MultiAgentGraph.ts +381 -0
  189. package/src/graphs/index.ts +2 -1
  190. package/src/llm/anthropic/Jacob_Lee_Resume_2023.pdf +0 -0
  191. package/src/llm/anthropic/index.ts +78 -13
  192. package/src/llm/anthropic/llm.spec.ts +491 -115
  193. package/src/llm/anthropic/types.ts +39 -3
  194. package/src/llm/anthropic/utils/message_inputs.ts +67 -11
  195. package/src/llm/anthropic/utils/message_outputs.ts +21 -2
  196. package/src/llm/anthropic/utils/output_parsers.ts +25 -6
  197. package/src/llm/anthropic/utils/tools.ts +29 -0
  198. package/src/llm/google/index.ts +218 -0
  199. package/src/llm/google/types.ts +43 -0
  200. package/src/llm/google/utils/common.ts +646 -0
  201. package/src/llm/google/utils/tools.ts +160 -0
  202. package/src/llm/google/utils/zod_to_genai_parameters.ts +86 -0
  203. package/src/llm/ollama/index.ts +89 -0
  204. package/src/llm/ollama/utils.ts +193 -0
  205. package/src/llm/openai/index.ts +600 -14
  206. package/src/llm/openai/types.ts +24 -0
  207. package/src/llm/openai/utils/index.ts +912 -0
  208. package/src/llm/openai/utils/isReasoningModel.test.ts +90 -0
  209. package/src/llm/providers.ts +10 -9
  210. package/src/llm/text.ts +26 -7
  211. package/src/llm/vertexai/index.ts +360 -0
  212. package/src/messages/reducer.ts +80 -0
  213. package/src/run.ts +181 -112
  214. package/src/scripts/ant_web_search.ts +158 -0
  215. package/src/scripts/args.ts +12 -8
  216. package/src/scripts/cli4.ts +29 -21
  217. package/src/scripts/cli5.ts +29 -21
  218. package/src/scripts/code_exec.ts +54 -23
  219. package/src/scripts/code_exec_files.ts +48 -17
  220. package/src/scripts/code_exec_simple.ts +46 -27
  221. package/src/scripts/handoff-test.ts +135 -0
  222. package/src/scripts/image.ts +52 -20
  223. package/src/scripts/multi-agent-conditional.ts +220 -0
  224. package/src/scripts/multi-agent-example-output.md +110 -0
  225. package/src/scripts/multi-agent-parallel.ts +337 -0
  226. package/src/scripts/multi-agent-sequence.ts +212 -0
  227. package/src/scripts/multi-agent-test.ts +186 -0
  228. package/src/scripts/search.ts +1 -9
  229. package/src/scripts/simple.ts +25 -10
  230. package/src/scripts/tools.ts +48 -18
  231. package/src/specs/anthropic.simple.test.ts +150 -34
  232. package/src/specs/azure.simple.test.ts +325 -0
  233. package/src/specs/openai.simple.test.ts +140 -33
  234. package/src/specs/openrouter.simple.test.ts +107 -0
  235. package/src/specs/prune.test.ts +4 -9
  236. package/src/specs/reasoning.test.ts +80 -44
  237. package/src/specs/token-memoization.test.ts +39 -0
  238. package/src/stream.test.ts +94 -0
  239. package/src/stream.ts +139 -60
  240. package/src/tools/ToolNode.ts +21 -7
  241. package/src/tools/handlers.ts +192 -18
  242. package/src/tools/search/anthropic.ts +51 -0
  243. package/src/tools/search/firecrawl.ts +69 -20
  244. package/src/tools/search/format.ts +6 -8
  245. package/src/tools/search/rerankers.ts +7 -40
  246. package/src/tools/search/search.ts +97 -16
  247. package/src/tools/search/tool.ts +5 -2
  248. package/src/tools/search/types.ts +30 -10
  249. package/src/tools/search/utils.ts +1 -1
  250. package/src/types/graph.ts +272 -103
  251. package/src/types/llm.ts +25 -12
  252. package/src/types/run.ts +51 -13
  253. package/src/types/stream.ts +22 -1
  254. package/src/types/tools.ts +16 -10
  255. package/src/utils/events.ts +32 -0
  256. package/src/utils/llmConfig.ts +19 -7
  257. package/src/utils/title.ts +104 -30
  258. package/src/utils/tokens.ts +69 -10
@@ -1,6 +1,10 @@
1
1
  import Anthropic from '@anthropic-ai/sdk';
2
2
  import { BindToolsInput } from '@langchain/core/language_models/chat_models';
3
3
 
4
+ export type AnthropicStreamUsage = Anthropic.Usage;
5
+ export type AnthropicMessageDeltaEvent = Anthropic.MessageDeltaEvent;
6
+ export type AnthropicMessageStartEvent = Anthropic.MessageStartEvent;
7
+
4
8
  export type AnthropicToolResponse = {
5
9
  type: 'tool_use';
6
10
  id: string;
@@ -9,10 +13,7 @@ export type AnthropicToolResponse = {
9
13
  input: Record<string, any>;
10
14
  };
11
15
 
12
- export type AnthropicStreamUsage = Anthropic.Usage;
13
16
  export type AnthropicMessageParam = Anthropic.MessageParam;
14
- export type AnthropicMessageDeltaEvent = Anthropic.MessageDeltaEvent;
15
- export type AnthropicMessageStartEvent = Anthropic.MessageStartEvent;
16
17
  export type AnthropicMessageResponse =
17
18
  | Anthropic.ContentBlock
18
19
  | AnthropicToolResponse;
@@ -42,6 +43,41 @@ export type AnthropicDocumentBlockParam = Anthropic.Messages.DocumentBlockParam;
42
43
  export type AnthropicThinkingBlockParam = Anthropic.Messages.ThinkingBlockParam;
43
44
  export type AnthropicRedactedThinkingBlockParam =
44
45
  Anthropic.Messages.RedactedThinkingBlockParam;
46
+ export type AnthropicServerToolUseBlockParam =
47
+ Anthropic.Messages.ServerToolUseBlockParam;
48
+ export type AnthropicWebSearchToolResultBlockParam =
49
+ Anthropic.Messages.WebSearchToolResultBlockParam;
50
+ export type AnthropicWebSearchResultBlockParam =
51
+ Anthropic.Messages.WebSearchResultBlockParam;
52
+ export type AnthropicSearchResultBlockParam =
53
+ Anthropic.Beta.BetaSearchResultBlockParam;
54
+
55
+ // Union of all possible content block types including server tool use
56
+ export type AnthropicContentBlock =
57
+ | AnthropicTextBlockParam
58
+ | AnthropicImageBlockParam
59
+ | AnthropicToolUseBlockParam
60
+ | AnthropicToolResultBlockParam
61
+ | AnthropicDocumentBlockParam
62
+ | AnthropicThinkingBlockParam
63
+ | AnthropicRedactedThinkingBlockParam
64
+ | AnthropicServerToolUseBlockParam
65
+ | AnthropicWebSearchToolResultBlockParam
66
+ | AnthropicWebSearchResultBlockParam;
67
+
68
+ // Union of all possible content block types including server tool use
69
+ export type ChatAnthropicContentBlock =
70
+ | AnthropicTextBlockParam
71
+ | AnthropicImageBlockParam
72
+ | AnthropicToolUseBlockParam
73
+ | AnthropicToolResultBlockParam
74
+ | AnthropicDocumentBlockParam
75
+ | AnthropicThinkingBlockParam
76
+ | AnthropicRedactedThinkingBlockParam
77
+ | AnthropicServerToolUseBlockParam
78
+ | AnthropicWebSearchToolResultBlockParam
79
+ | AnthropicWebSearchResultBlockParam
80
+ | AnthropicSearchResultBlockParam;
45
81
 
46
82
  export function isAnthropicImageBlockParam(
47
83
  block: unknown
@@ -9,7 +9,6 @@ import {
9
9
  HumanMessage,
10
10
  type AIMessage,
11
11
  type ToolMessage,
12
- type MessageContent,
13
12
  isAIMessage,
14
13
  type StandardContentBlockConverter,
15
14
  type StandardTextBlock,
@@ -21,18 +20,21 @@ import {
21
20
  parseBase64DataUrl,
22
21
  } from '@langchain/core/messages';
23
22
  import { ToolCall } from '@langchain/core/messages/tool';
24
- import type {
23
+ import {
25
24
  AnthropicImageBlockParam,
26
25
  AnthropicMessageCreateParams,
27
26
  AnthropicTextBlockParam,
28
- AnthropicToolResponse,
29
27
  AnthropicToolResultBlockParam,
30
28
  AnthropicToolUseBlockParam,
31
29
  AnthropicDocumentBlockParam,
32
30
  AnthropicThinkingBlockParam,
33
31
  AnthropicRedactedThinkingBlockParam,
34
- } from '@/llm/anthropic/types';
35
- import { isAnthropicImageBlockParam } from '@/llm/anthropic/types';
32
+ AnthropicServerToolUseBlockParam,
33
+ AnthropicWebSearchToolResultBlockParam,
34
+ isAnthropicImageBlockParam,
35
+ AnthropicSearchResultBlockParam,
36
+ AnthropicToolResponse,
37
+ } from '../types';
36
38
 
37
39
  function _formatImage(imageUrl: string) {
38
40
  const parsed = parseBase64DataUrl({ dataUrl: imageUrl });
@@ -118,7 +120,10 @@ function _ensureMessageContents(
118
120
  content: [
119
121
  {
120
122
  type: 'tool_result',
121
- content: _formatContent(message.content),
123
+ // rare case: message.content could be undefined
124
+ ...(message.content != null
125
+ ? { content: _formatContent(message) }
126
+ : {}),
122
127
  tool_use_id: (message as ToolMessage).tool_call_id,
123
128
  },
124
129
  ],
@@ -342,9 +347,17 @@ const standardContentBlockConverter: StandardContentBlockConverter<{
342
347
  },
343
348
  };
344
349
 
345
- function _formatContent(content: MessageContent) {
346
- const toolTypes = ['tool_use', 'tool_result', 'input_json_delta'];
350
+ function _formatContent(message: BaseMessage) {
351
+ const toolTypes = [
352
+ 'tool_use',
353
+ 'tool_result',
354
+ 'input_json_delta',
355
+ 'server_tool_use',
356
+ 'web_search_tool_result',
357
+ 'web_search_result',
358
+ ];
347
359
  const textTypes = ['text', 'text_delta'];
360
+ const { content } = message;
348
361
 
349
362
  if (typeof content === 'string') {
350
363
  return content;
@@ -395,6 +408,20 @@ function _formatContent(content: MessageContent) {
395
408
  ...(cacheControl ? { cache_control: cacheControl } : {}),
396
409
  };
397
410
  return block;
411
+ } else if (contentPart.type === 'search_result') {
412
+ const block: AnthropicSearchResultBlockParam = {
413
+ type: 'search_result' as const, // Explicitly setting the type as "search_result"
414
+ title: contentPart.title,
415
+ source: contentPart.source,
416
+ ...('cache_control' in contentPart && contentPart.cache_control
417
+ ? { cache_control: contentPart.cache_control }
418
+ : {}),
419
+ ...('citations' in contentPart && contentPart.citations
420
+ ? { citations: contentPart.citations }
421
+ : {}),
422
+ content: contentPart.content,
423
+ };
424
+ return block;
398
425
  } else if (
399
426
  textTypes.find((t) => t === contentPart.type) &&
400
427
  'text' in contentPart
@@ -404,6 +431,9 @@ function _formatContent(content: MessageContent) {
404
431
  type: 'text' as const, // Explicitly setting the type as "text"
405
432
  text: contentPart.text,
406
433
  ...(cacheControl ? { cache_control: cacheControl } : {}),
434
+ ...('citations' in contentPart && contentPart.citations
435
+ ? { citations: contentPart.citations }
436
+ : {}),
407
437
  };
408
438
  } else if (toolTypes.find((t) => t === contentPart.type)) {
409
439
  const contentPartCopy = { ...contentPart };
@@ -435,6 +465,27 @@ function _formatContent(content: MessageContent) {
435
465
  ...(cacheControl ? { cache_control: cacheControl } : {}),
436
466
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
437
467
  } as any;
468
+ } else if (
469
+ 'functionCall' in contentPart &&
470
+ contentPart.functionCall &&
471
+ typeof contentPart.functionCall === 'object' &&
472
+ isAIMessage(message)
473
+ ) {
474
+ const correspondingToolCall = message.tool_calls?.find(
475
+ (toolCall) => toolCall.name === contentPart.functionCall.name
476
+ );
477
+ if (!correspondingToolCall) {
478
+ throw new Error(
479
+ `Could not find tool call for function call ${contentPart.functionCall.name}`
480
+ );
481
+ }
482
+ // Google GenAI models include a `functionCall` object inside content. We should ignore it as Anthropic will not support it.
483
+ return {
484
+ id: correspondingToolCall.id,
485
+ type: 'tool_use',
486
+ name: correspondingToolCall.name,
487
+ input: contentPart.functionCall.args,
488
+ };
438
489
  } else {
439
490
  throw new Error('Unsupported message content format');
440
491
  }
@@ -498,7 +549,8 @@ export function _convertMessagesToAnthropicPayload(
498
549
  content.find(
499
550
  (contentPart) =>
500
551
  (contentPart.type === 'tool_use' ||
501
- contentPart.type === 'input_json_delta') &&
552
+ contentPart.type === 'input_json_delta' ||
553
+ contentPart.type === 'server_tool_use') &&
502
554
  contentPart.id === toolCall.id
503
555
  )
504
556
  );
@@ -509,13 +561,13 @@ export function _convertMessagesToAnthropicPayload(
509
561
  }
510
562
  return {
511
563
  role,
512
- content: _formatContent(message.content),
564
+ content: _formatContent(message),
513
565
  };
514
566
  }
515
567
  } else {
516
568
  return {
517
569
  role,
518
- content: _formatContent(message.content),
570
+ content: _formatContent(message),
519
571
  };
520
572
  }
521
573
  });
@@ -544,6 +596,8 @@ function mergeMessages(messages: AnthropicMessageCreateParams['messages']) {
544
596
  | AnthropicDocumentBlockParam
545
597
  | AnthropicThinkingBlockParam
546
598
  | AnthropicRedactedThinkingBlockParam
599
+ | AnthropicServerToolUseBlockParam
600
+ | AnthropicWebSearchToolResultBlockParam
547
601
  >
548
602
  ): Array<
549
603
  | AnthropicTextBlockParam
@@ -553,6 +607,8 @@ function mergeMessages(messages: AnthropicMessageCreateParams['messages']) {
553
607
  | AnthropicDocumentBlockParam
554
608
  | AnthropicThinkingBlockParam
555
609
  | AnthropicRedactedThinkingBlockParam
610
+ | AnthropicServerToolUseBlockParam
611
+ | AnthropicWebSearchToolResultBlockParam
556
612
  > => {
557
613
  if (typeof content === 'string') {
558
614
  return [
@@ -77,7 +77,12 @@ export function _makeMessageChunkFromAnthropicEvent(
77
77
  };
78
78
  } else if (
79
79
  data.type === 'content_block_start' &&
80
- ['tool_use', 'document'].includes(data.content_block.type)
80
+ [
81
+ 'tool_use',
82
+ 'document',
83
+ 'server_tool_use',
84
+ 'web_search_tool_result',
85
+ ].includes(data.content_block.type)
81
86
  ) {
82
87
  const contentBlock = data.content_block;
83
88
  let toolCallChunks: ToolCallChunk[];
@@ -90,6 +95,16 @@ export function _makeMessageChunkFromAnthropicEvent(
90
95
  args: '',
91
96
  },
92
97
  ];
98
+ } else if (contentBlock.type === 'server_tool_use') {
99
+ // Handle anthropic built-in server tool use (like web search)
100
+ toolCallChunks = [
101
+ {
102
+ id: contentBlock.id,
103
+ index: data.index,
104
+ name: contentBlock.name,
105
+ args: '',
106
+ },
107
+ ];
93
108
  } else {
94
109
  toolCallChunks = [];
95
110
  }
@@ -101,7 +116,11 @@ export function _makeMessageChunkFromAnthropicEvent(
101
116
  {
102
117
  index: data.index,
103
118
  ...data.content_block,
104
- input: '',
119
+ input:
120
+ contentBlock.type === 'server_tool_use' ||
121
+ contentBlock.type === 'tool_use'
122
+ ? ''
123
+ : undefined,
105
124
  },
106
125
  ],
107
126
  additional_kwargs: {},
@@ -1,17 +1,20 @@
1
1
  /* eslint-disable @typescript-eslint/explicit-function-return-type */
2
2
  /* eslint-disable @typescript-eslint/no-empty-object-type */
3
- import { z } from 'zod';
4
3
  import {
5
4
  BaseLLMOutputParser,
6
5
  OutputParserException,
7
6
  } from '@langchain/core/output_parsers';
8
- import { JsonOutputKeyToolsParserParams } from '@langchain/core/output_parsers/openai_tools';
7
+ import { JsonOutputKeyToolsParserParamsInterop } from '@langchain/core/output_parsers/openai_tools';
9
8
  import { ChatGeneration } from '@langchain/core/outputs';
10
9
  import { ToolCall } from '@langchain/core/messages/tool';
10
+ import {
11
+ interopSafeParseAsync,
12
+ InteropZodType,
13
+ } from '@langchain/core/utils/types';
11
14
 
12
15
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
13
16
  interface AnthropicToolsOutputParserParams<T extends Record<string, any>>
14
- extends JsonOutputKeyToolsParserParams<T> {}
17
+ extends JsonOutputKeyToolsParserParamsInterop<T> {}
15
18
 
16
19
  export class AnthropicToolsOutputParser<
17
20
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
@@ -31,7 +34,7 @@ export class AnthropicToolsOutputParser<
31
34
  /** Whether to return only the first tool call. */
32
35
  returnSingle = false;
33
36
 
34
- zodSchema?: z.ZodType<T>;
37
+ zodSchema?: InteropZodType<T>;
35
38
 
36
39
  constructor(params: AnthropicToolsOutputParserParams<T>) {
37
40
  super(params);
@@ -62,7 +65,10 @@ export class AnthropicToolsOutputParser<
62
65
  if (this.zodSchema === undefined) {
63
66
  return parsedResult as T;
64
67
  }
65
- const zodParsedResult = await this.zodSchema.safeParseAsync(parsedResult);
68
+ const zodParsedResult = await interopSafeParseAsync(
69
+ this.zodSchema,
70
+ parsedResult
71
+ );
66
72
  if (zodParsedResult.success) {
67
73
  return zodParsedResult.data;
68
74
  } else {
@@ -71,7 +77,7 @@ export class AnthropicToolsOutputParser<
71
77
  result,
72
78
  null,
73
79
  2
74
- )}". Error: ${JSON.stringify(zodParsedResult.error.errors)}`,
80
+ )}". Error: ${JSON.stringify(zodParsedResult.error.issues)}`,
75
81
  JSON.stringify(parsedResult, null, 2)
76
82
  );
77
83
  }
@@ -100,6 +106,7 @@ export class AnthropicToolsOutputParser<
100
106
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
101
107
  export function extractToolCalls(content: Record<string, any>[]) {
102
108
  const toolCalls: ToolCall[] = [];
109
+
103
110
  for (const block of content) {
104
111
  if (block.type === 'tool_use') {
105
112
  toolCalls.push({
@@ -108,7 +115,19 @@ export function extractToolCalls(content: Record<string, any>[]) {
108
115
  id: block.id,
109
116
  type: 'tool_call',
110
117
  });
118
+ } else if (
119
+ block.type === 'server_tool_use' &&
120
+ block.name === 'web_search'
121
+ ) {
122
+ // Handle Anthropic built-in web search tool
123
+ toolCalls.push({
124
+ name: block.name,
125
+ args: block.input,
126
+ id: block.id,
127
+ type: 'tool_call',
128
+ });
111
129
  }
112
130
  }
131
+
113
132
  return toolCalls;
114
133
  }
@@ -0,0 +1,29 @@
1
+ import type { Anthropic } from '@anthropic-ai/sdk';
2
+ import { AnthropicToolChoice } from '../types.js';
3
+
4
+ export function handleToolChoice(
5
+ toolChoice?: AnthropicToolChoice
6
+ ):
7
+ | Anthropic.Messages.ToolChoiceAuto
8
+ | Anthropic.Messages.ToolChoiceAny
9
+ | Anthropic.Messages.ToolChoiceTool
10
+ | undefined {
11
+ if (toolChoice == null) {
12
+ return undefined;
13
+ } else if (toolChoice === 'any') {
14
+ return {
15
+ type: 'any',
16
+ };
17
+ } else if (toolChoice === 'auto') {
18
+ return {
19
+ type: 'auto',
20
+ };
21
+ } else if (typeof toolChoice === 'string') {
22
+ return {
23
+ type: 'tool',
24
+ name: toolChoice,
25
+ };
26
+ } else {
27
+ return toolChoice;
28
+ }
29
+ }
@@ -0,0 +1,218 @@
1
+ /* eslint-disable @typescript-eslint/ban-ts-comment */
2
+ import { AIMessageChunk } from '@langchain/core/messages';
3
+ import { ChatGenerationChunk } from '@langchain/core/outputs';
4
+ import { ChatGoogleGenerativeAI } from '@langchain/google-genai';
5
+ import { getEnvironmentVariable } from '@langchain/core/utils/env';
6
+ import { GoogleGenerativeAI as GenerativeAI } from '@google/generative-ai';
7
+ import type {
8
+ GenerateContentRequest,
9
+ SafetySetting,
10
+ } from '@google/generative-ai';
11
+ import type { CallbackManagerForLLMRun } from '@langchain/core/callbacks/manager';
12
+ import type { BaseMessage, UsageMetadata } from '@langchain/core/messages';
13
+ import type { GeminiGenerationConfig } from '@langchain/google-common';
14
+ import type { GeminiApiUsageMetadata } from './types';
15
+ import type { GoogleClientOptions } from '@/types';
16
+ import {
17
+ convertResponseContentToChatGenerationChunk,
18
+ convertBaseMessagesToContent,
19
+ } from './utils/common';
20
+
21
+ export class CustomChatGoogleGenerativeAI extends ChatGoogleGenerativeAI {
22
+ thinkingConfig?: GeminiGenerationConfig['thinkingConfig'];
23
+ constructor(fields: GoogleClientOptions) {
24
+ super(fields);
25
+
26
+ this.model = fields.model.replace(/^models\//, '');
27
+
28
+ this.maxOutputTokens = fields.maxOutputTokens ?? this.maxOutputTokens;
29
+
30
+ if (this.maxOutputTokens != null && this.maxOutputTokens < 0) {
31
+ throw new Error('`maxOutputTokens` must be a positive integer');
32
+ }
33
+
34
+ this.temperature = fields.temperature ?? this.temperature;
35
+ if (
36
+ this.temperature != null &&
37
+ (this.temperature < 0 || this.temperature > 2)
38
+ ) {
39
+ throw new Error('`temperature` must be in the range of [0.0,2.0]');
40
+ }
41
+
42
+ this.topP = fields.topP ?? this.topP;
43
+ if (this.topP != null && this.topP < 0) {
44
+ throw new Error('`topP` must be a positive integer');
45
+ }
46
+
47
+ if (this.topP != null && this.topP > 1) {
48
+ throw new Error('`topP` must be below 1.');
49
+ }
50
+
51
+ this.topK = fields.topK ?? this.topK;
52
+ if (this.topK != null && this.topK < 0) {
53
+ throw new Error('`topK` must be a positive integer');
54
+ }
55
+
56
+ this.stopSequences = fields.stopSequences ?? this.stopSequences;
57
+
58
+ this.apiKey = fields.apiKey ?? getEnvironmentVariable('GOOGLE_API_KEY');
59
+ if (this.apiKey == null || this.apiKey === '') {
60
+ throw new Error(
61
+ 'Please set an API key for Google GenerativeAI ' +
62
+ 'in the environment variable GOOGLE_API_KEY ' +
63
+ 'or in the `apiKey` field of the ' +
64
+ 'ChatGoogleGenerativeAI constructor'
65
+ );
66
+ }
67
+
68
+ this.safetySettings = fields.safetySettings ?? this.safetySettings;
69
+ if (this.safetySettings && this.safetySettings.length > 0) {
70
+ const safetySettingsSet = new Set(
71
+ this.safetySettings.map((s) => s.category)
72
+ );
73
+ if (safetySettingsSet.size !== this.safetySettings.length) {
74
+ throw new Error(
75
+ 'The categories in `safetySettings` array must be unique'
76
+ );
77
+ }
78
+ }
79
+
80
+ this.thinkingConfig = fields.thinkingConfig ?? this.thinkingConfig;
81
+
82
+ this.streaming = fields.streaming ?? this.streaming;
83
+ this.json = fields.json;
84
+
85
+ // @ts-ignore - Accessing private property from parent class
86
+ this.client = new GenerativeAI(this.apiKey).getGenerativeModel(
87
+ {
88
+ model: this.model,
89
+ safetySettings: this.safetySettings as SafetySetting[],
90
+ generationConfig: {
91
+ stopSequences: this.stopSequences,
92
+ maxOutputTokens: this.maxOutputTokens,
93
+ temperature: this.temperature,
94
+ topP: this.topP,
95
+ topK: this.topK,
96
+ ...(this.json != null
97
+ ? { responseMimeType: 'application/json' }
98
+ : {}),
99
+ },
100
+ },
101
+ {
102
+ apiVersion: fields.apiVersion,
103
+ baseUrl: fields.baseUrl,
104
+ customHeaders: fields.customHeaders,
105
+ }
106
+ );
107
+ this.streamUsage = fields.streamUsage ?? this.streamUsage;
108
+ }
109
+
110
+ invocationParams(
111
+ options?: this['ParsedCallOptions']
112
+ ): Omit<GenerateContentRequest, 'contents'> {
113
+ const params = super.invocationParams(options);
114
+ if (this.thinkingConfig) {
115
+ /** @ts-ignore */
116
+ this.client.generationConfig = {
117
+ /** @ts-ignore */
118
+ ...this.client.generationConfig,
119
+ /** @ts-ignore */
120
+ thinkingConfig: this.thinkingConfig,
121
+ };
122
+ }
123
+ return params;
124
+ }
125
+
126
+ async *_streamResponseChunks(
127
+ messages: BaseMessage[],
128
+ options: this['ParsedCallOptions'],
129
+ runManager?: CallbackManagerForLLMRun
130
+ ): AsyncGenerator<ChatGenerationChunk> {
131
+ const prompt = convertBaseMessagesToContent(
132
+ messages,
133
+ this._isMultimodalModel,
134
+ this.useSystemInstruction
135
+ );
136
+ let actualPrompt = prompt;
137
+ if (prompt?.[0].role === 'system') {
138
+ const [systemInstruction] = prompt;
139
+ /** @ts-ignore */
140
+ this.client.systemInstruction = systemInstruction;
141
+ actualPrompt = prompt.slice(1);
142
+ }
143
+ const parameters = this.invocationParams(options);
144
+ const request = {
145
+ ...parameters,
146
+ contents: actualPrompt,
147
+ };
148
+ const stream = await this.caller.callWithOptions(
149
+ { signal: options.signal },
150
+ async () => {
151
+ /** @ts-ignore */
152
+ const { stream } = await this.client.generateContentStream(request);
153
+ return stream;
154
+ }
155
+ );
156
+
157
+ let index = 0;
158
+ let lastUsageMetadata: UsageMetadata | undefined;
159
+ for await (const response of stream) {
160
+ if (
161
+ 'usageMetadata' in response &&
162
+ this.streamUsage !== false &&
163
+ options.streamUsage !== false
164
+ ) {
165
+ const genAIUsageMetadata = response.usageMetadata as
166
+ | GeminiApiUsageMetadata
167
+ | undefined;
168
+
169
+ const output_tokens =
170
+ (genAIUsageMetadata?.candidatesTokenCount ?? 0) +
171
+ (genAIUsageMetadata?.thoughtsTokenCount ?? 0);
172
+ lastUsageMetadata = {
173
+ input_tokens: genAIUsageMetadata?.promptTokenCount ?? 0,
174
+ output_tokens,
175
+ total_tokens: genAIUsageMetadata?.totalTokenCount ?? 0,
176
+ };
177
+ }
178
+
179
+ const chunk = convertResponseContentToChatGenerationChunk(response, {
180
+ usageMetadata: undefined,
181
+ index,
182
+ });
183
+ index += 1;
184
+ if (!chunk) {
185
+ continue;
186
+ }
187
+
188
+ yield chunk;
189
+ await runManager?.handleLLMNewToken(
190
+ chunk.text || '',
191
+ undefined,
192
+ undefined,
193
+ undefined,
194
+ undefined,
195
+ { chunk }
196
+ );
197
+ }
198
+
199
+ if (lastUsageMetadata) {
200
+ const finalChunk = new ChatGenerationChunk({
201
+ text: '',
202
+ message: new AIMessageChunk({
203
+ content: '',
204
+ usage_metadata: lastUsageMetadata,
205
+ }),
206
+ });
207
+ yield finalChunk;
208
+ await runManager?.handleLLMNewToken(
209
+ finalChunk.text || '',
210
+ undefined,
211
+ undefined,
212
+ undefined,
213
+ undefined,
214
+ { chunk: finalChunk }
215
+ );
216
+ }
217
+ }
218
+ }
@@ -0,0 +1,43 @@
1
+ import {
2
+ CodeExecutionTool,
3
+ FunctionDeclarationsTool as GoogleGenerativeAIFunctionDeclarationsTool,
4
+ GoogleSearchRetrievalTool,
5
+ } from '@google/generative-ai';
6
+ import { BindToolsInput } from '@langchain/core/language_models/chat_models';
7
+
8
+ export type GoogleGenerativeAIToolType =
9
+ | BindToolsInput
10
+ | GoogleGenerativeAIFunctionDeclarationsTool
11
+ | CodeExecutionTool
12
+ | GoogleSearchRetrievalTool;
13
+
14
+ /** Enum for content modality types */
15
+ enum Modality {
16
+ MODALITY_UNSPECIFIED = 'MODALITY_UNSPECIFIED',
17
+ TEXT = 'TEXT',
18
+ IMAGE = 'IMAGE',
19
+ VIDEO = 'VIDEO',
20
+ AUDIO = 'AUDIO',
21
+ DOCUMENT = 'DOCUMENT',
22
+ }
23
+
24
+ /** Interface for modality token count */
25
+ interface ModalityTokenCount {
26
+ modality: Modality;
27
+ tokenCount: number;
28
+ }
29
+
30
+ /** Main interface for Gemini API usage metadata */
31
+ export interface GeminiApiUsageMetadata {
32
+ promptTokenCount?: number;
33
+ totalTokenCount?: number;
34
+ thoughtsTokenCount?: number;
35
+ candidatesTokenCount?: number;
36
+ toolUsePromptTokenCount?: number;
37
+ cachedContentTokenCount?: number;
38
+ promptTokensDetails: ModalityTokenCount[];
39
+ candidatesTokensDetails?: ModalityTokenCount[];
40
+ cacheTokensDetails?: ModalityTokenCount[];
41
+ toolUsePromptTokensDetails?: ModalityTokenCount[];
42
+ trafficType?: string;
43
+ }