@librechat/agents 3.2.2 → 3.2.31

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 (401) hide show
  1. package/dist/cjs/agents/AgentContext.cjs +3 -2
  2. package/dist/cjs/agents/AgentContext.cjs.map +1 -1
  3. package/dist/cjs/events.cjs.map +1 -1
  4. package/dist/cjs/graphs/Graph.cjs +200 -54
  5. package/dist/cjs/graphs/Graph.cjs.map +1 -1
  6. package/dist/cjs/graphs/MultiAgentGraph.cjs.map +1 -1
  7. package/dist/cjs/hooks/createWorkspacePolicyHook.cjs +13 -7
  8. package/dist/cjs/hooks/createWorkspacePolicyHook.cjs.map +1 -1
  9. package/dist/cjs/hooks/executeHooks.cjs.map +1 -1
  10. package/dist/cjs/hooks/types.cjs.map +1 -1
  11. package/dist/cjs/instrumentation.cjs +33 -0
  12. package/dist/cjs/instrumentation.cjs.map +1 -1
  13. package/dist/cjs/langfuse.cjs +17 -1
  14. package/dist/cjs/langfuse.cjs.map +1 -1
  15. package/dist/cjs/langfuseToolOutputTracing.cjs +2 -2
  16. package/dist/cjs/langfuseToolOutputTracing.cjs.map +1 -1
  17. package/dist/cjs/llm/anthropic/index.cjs +1 -1
  18. package/dist/cjs/llm/anthropic/index.cjs.map +1 -1
  19. package/dist/cjs/llm/anthropic/utils/message_inputs.cjs.map +1 -1
  20. package/dist/cjs/llm/anthropic/utils/message_outputs.cjs +1 -1
  21. package/dist/cjs/llm/anthropic/utils/message_outputs.cjs.map +1 -1
  22. package/dist/cjs/llm/bedrock/index.cjs +2 -2
  23. package/dist/cjs/llm/bedrock/index.cjs.map +1 -1
  24. package/dist/cjs/llm/bedrock/toolCache.cjs +8 -5
  25. package/dist/cjs/llm/bedrock/toolCache.cjs.map +1 -1
  26. package/dist/cjs/llm/fake.cjs +16 -14
  27. package/dist/cjs/llm/fake.cjs.map +1 -1
  28. package/dist/cjs/llm/google/index.cjs +22 -0
  29. package/dist/cjs/llm/google/index.cjs.map +1 -1
  30. package/dist/cjs/llm/google/utils/common.cjs +88 -27
  31. package/dist/cjs/llm/google/utils/common.cjs.map +1 -1
  32. package/dist/cjs/llm/init.cjs +2 -2
  33. package/dist/cjs/llm/invoke.cjs +108 -11
  34. package/dist/cjs/llm/invoke.cjs.map +1 -1
  35. package/dist/cjs/llm/openai/index.cjs +1 -1
  36. package/dist/cjs/llm/openai/index.cjs.map +1 -1
  37. package/dist/cjs/llm/openai/utils/index.cjs +1 -1
  38. package/dist/cjs/llm/openai/utils/index.cjs.map +1 -1
  39. package/dist/cjs/llm/openrouter/index.cjs.map +1 -1
  40. package/dist/cjs/llm/vertexai/index.cjs.map +1 -1
  41. package/dist/cjs/main.cjs +1 -0
  42. package/dist/cjs/main.cjs.map +1 -1
  43. package/dist/cjs/messages/cache.cjs +8 -7
  44. package/dist/cjs/messages/cache.cjs.map +1 -1
  45. package/dist/cjs/messages/content.cjs.map +1 -1
  46. package/dist/cjs/messages/contextPruning.cjs.map +1 -1
  47. package/dist/cjs/messages/format.cjs +124 -17
  48. package/dist/cjs/messages/format.cjs.map +1 -1
  49. package/dist/cjs/messages/prune.cjs.map +1 -1
  50. package/dist/cjs/messages/reducer.cjs +1 -1
  51. package/dist/cjs/messages/reducer.cjs.map +1 -1
  52. package/dist/cjs/messages/tools.cjs +1 -1
  53. package/dist/cjs/messages/tools.cjs.map +1 -1
  54. package/dist/cjs/openai/index.cjs.map +1 -1
  55. package/dist/cjs/responses/index.cjs.map +1 -1
  56. package/dist/cjs/run.cjs +47 -21
  57. package/dist/cjs/run.cjs.map +1 -1
  58. package/dist/cjs/session/AgentSession.cjs +4 -4
  59. package/dist/cjs/session/AgentSession.cjs.map +1 -1
  60. package/dist/cjs/session/JsonlSessionStore.cjs +2 -2
  61. package/dist/cjs/session/JsonlSessionStore.cjs.map +1 -1
  62. package/dist/cjs/session/handlers.cjs +2 -2
  63. package/dist/cjs/session/handlers.cjs.map +1 -1
  64. package/dist/cjs/stream.cjs +248 -25
  65. package/dist/cjs/stream.cjs.map +1 -1
  66. package/dist/cjs/summarization/node.cjs.map +1 -1
  67. package/dist/cjs/tools/BashProgrammaticToolCalling.cjs +1 -1
  68. package/dist/cjs/tools/BashProgrammaticToolCalling.cjs.map +1 -1
  69. package/dist/cjs/tools/Calculator.cjs +1 -1
  70. package/dist/cjs/tools/Calculator.cjs.map +1 -1
  71. package/dist/cjs/tools/CodeExecutor.cjs +1 -1
  72. package/dist/cjs/tools/CodeExecutor.cjs.map +1 -1
  73. package/dist/cjs/tools/SubagentTool.cjs.map +1 -1
  74. package/dist/cjs/tools/ToolNode.cjs +37 -18
  75. package/dist/cjs/tools/ToolNode.cjs.map +1 -1
  76. package/dist/cjs/tools/ToolSearch.cjs +1 -1
  77. package/dist/cjs/tools/ToolSearch.cjs.map +1 -1
  78. package/dist/cjs/tools/cloudflare/CloudflareSandboxExecutionEngine.cjs +7 -4
  79. package/dist/cjs/tools/cloudflare/CloudflareSandboxExecutionEngine.cjs.map +1 -1
  80. package/dist/cjs/tools/cloudflare/CloudflareSandboxTools.cjs +4 -4
  81. package/dist/cjs/tools/cloudflare/CloudflareSandboxTools.cjs.map +1 -1
  82. package/dist/cjs/tools/handlers.cjs +2 -1
  83. package/dist/cjs/tools/handlers.cjs.map +1 -1
  84. package/dist/cjs/tools/local/CompileCheckTool.cjs.map +1 -1
  85. package/dist/cjs/tools/local/FileCheckpointer.cjs +2 -1
  86. package/dist/cjs/tools/local/FileCheckpointer.cjs.map +1 -1
  87. package/dist/cjs/tools/local/LocalCodingTools.cjs +45 -19
  88. package/dist/cjs/tools/local/LocalCodingTools.cjs.map +1 -1
  89. package/dist/cjs/tools/local/LocalExecutionEngine.cjs +3 -3
  90. package/dist/cjs/tools/local/LocalExecutionEngine.cjs.map +1 -1
  91. package/dist/cjs/tools/local/LocalExecutionTools.cjs +2 -2
  92. package/dist/cjs/tools/local/LocalExecutionTools.cjs.map +1 -1
  93. package/dist/cjs/tools/local/LocalProgrammaticToolCalling.cjs +4 -3
  94. package/dist/cjs/tools/local/LocalProgrammaticToolCalling.cjs.map +1 -1
  95. package/dist/cjs/tools/local/attachments.cjs +0 -5
  96. package/dist/cjs/tools/local/attachments.cjs.map +1 -1
  97. package/dist/cjs/tools/local/resolveLocalExecutionTools.cjs +4 -4
  98. package/dist/cjs/tools/local/resolveLocalExecutionTools.cjs.map +1 -1
  99. package/dist/cjs/tools/search/firecrawl.cjs +1 -1
  100. package/dist/cjs/tools/search/firecrawl.cjs.map +1 -1
  101. package/dist/cjs/tools/search/rerankers.cjs +7 -3
  102. package/dist/cjs/tools/search/rerankers.cjs.map +1 -1
  103. package/dist/cjs/tools/search/tavily-search.cjs +1 -1
  104. package/dist/cjs/tools/search/tavily-search.cjs.map +1 -1
  105. package/dist/cjs/tools/search/utils.cjs +76 -8
  106. package/dist/cjs/tools/search/utils.cjs.map +1 -1
  107. package/dist/cjs/tools/subagent/SubagentExecutor.cjs +1 -1
  108. package/dist/cjs/tools/subagent/SubagentExecutor.cjs.map +1 -1
  109. package/dist/cjs/utils/handlers.cjs +1 -1
  110. package/dist/cjs/utils/handlers.cjs.map +1 -1
  111. package/dist/cjs/utils/run.cjs +1 -1
  112. package/dist/cjs/utils/run.cjs.map +1 -1
  113. package/dist/esm/agents/AgentContext.mjs +3 -2
  114. package/dist/esm/agents/AgentContext.mjs.map +1 -1
  115. package/dist/esm/events.mjs.map +1 -1
  116. package/dist/esm/graphs/Graph.mjs +200 -54
  117. package/dist/esm/graphs/Graph.mjs.map +1 -1
  118. package/dist/esm/graphs/MultiAgentGraph.mjs.map +1 -1
  119. package/dist/esm/hooks/createWorkspacePolicyHook.mjs +13 -7
  120. package/dist/esm/hooks/createWorkspacePolicyHook.mjs.map +1 -1
  121. package/dist/esm/hooks/executeHooks.mjs.map +1 -1
  122. package/dist/esm/hooks/types.mjs.map +1 -1
  123. package/dist/esm/instrumentation.mjs +33 -1
  124. package/dist/esm/instrumentation.mjs.map +1 -1
  125. package/dist/esm/langfuse.mjs +17 -2
  126. package/dist/esm/langfuse.mjs.map +1 -1
  127. package/dist/esm/langfuseToolOutputTracing.mjs +2 -2
  128. package/dist/esm/langfuseToolOutputTracing.mjs.map +1 -1
  129. package/dist/esm/llm/anthropic/index.mjs +1 -1
  130. package/dist/esm/llm/anthropic/index.mjs.map +1 -1
  131. package/dist/esm/llm/anthropic/utils/message_inputs.mjs.map +1 -1
  132. package/dist/esm/llm/anthropic/utils/message_outputs.mjs +1 -1
  133. package/dist/esm/llm/anthropic/utils/message_outputs.mjs.map +1 -1
  134. package/dist/esm/llm/bedrock/index.mjs +2 -2
  135. package/dist/esm/llm/bedrock/index.mjs.map +1 -1
  136. package/dist/esm/llm/bedrock/toolCache.mjs +8 -5
  137. package/dist/esm/llm/bedrock/toolCache.mjs.map +1 -1
  138. package/dist/esm/llm/fake.mjs +16 -14
  139. package/dist/esm/llm/fake.mjs.map +1 -1
  140. package/dist/esm/llm/google/index.mjs +23 -1
  141. package/dist/esm/llm/google/index.mjs.map +1 -1
  142. package/dist/esm/llm/google/utils/common.mjs +88 -27
  143. package/dist/esm/llm/google/utils/common.mjs.map +1 -1
  144. package/dist/esm/llm/init.mjs +2 -2
  145. package/dist/esm/llm/invoke.mjs +104 -7
  146. package/dist/esm/llm/invoke.mjs.map +1 -1
  147. package/dist/esm/llm/openai/index.mjs +1 -1
  148. package/dist/esm/llm/openai/index.mjs.map +1 -1
  149. package/dist/esm/llm/openai/utils/index.mjs +1 -1
  150. package/dist/esm/llm/openai/utils/index.mjs.map +1 -1
  151. package/dist/esm/llm/openrouter/index.mjs.map +1 -1
  152. package/dist/esm/llm/vertexai/index.mjs.map +1 -1
  153. package/dist/esm/main.mjs +1 -1
  154. package/dist/esm/messages/cache.mjs +8 -7
  155. package/dist/esm/messages/cache.mjs.map +1 -1
  156. package/dist/esm/messages/content.mjs.map +1 -1
  157. package/dist/esm/messages/contextPruning.mjs.map +1 -1
  158. package/dist/esm/messages/format.mjs +124 -18
  159. package/dist/esm/messages/format.mjs.map +1 -1
  160. package/dist/esm/messages/prune.mjs.map +1 -1
  161. package/dist/esm/messages/reducer.mjs +1 -1
  162. package/dist/esm/messages/reducer.mjs.map +1 -1
  163. package/dist/esm/messages/tools.mjs +1 -1
  164. package/dist/esm/messages/tools.mjs.map +1 -1
  165. package/dist/esm/openai/index.mjs.map +1 -1
  166. package/dist/esm/responses/index.mjs.map +1 -1
  167. package/dist/esm/run.mjs +47 -21
  168. package/dist/esm/run.mjs.map +1 -1
  169. package/dist/esm/session/AgentSession.mjs +4 -4
  170. package/dist/esm/session/AgentSession.mjs.map +1 -1
  171. package/dist/esm/session/JsonlSessionStore.mjs +2 -2
  172. package/dist/esm/session/JsonlSessionStore.mjs.map +1 -1
  173. package/dist/esm/session/handlers.mjs +2 -2
  174. package/dist/esm/session/handlers.mjs.map +1 -1
  175. package/dist/esm/stream.mjs +248 -25
  176. package/dist/esm/stream.mjs.map +1 -1
  177. package/dist/esm/summarization/node.mjs.map +1 -1
  178. package/dist/esm/tools/BashProgrammaticToolCalling.mjs +1 -1
  179. package/dist/esm/tools/BashProgrammaticToolCalling.mjs.map +1 -1
  180. package/dist/esm/tools/Calculator.mjs +1 -1
  181. package/dist/esm/tools/Calculator.mjs.map +1 -1
  182. package/dist/esm/tools/CodeExecutor.mjs +1 -1
  183. package/dist/esm/tools/CodeExecutor.mjs.map +1 -1
  184. package/dist/esm/tools/SubagentTool.mjs.map +1 -1
  185. package/dist/esm/tools/ToolNode.mjs +37 -18
  186. package/dist/esm/tools/ToolNode.mjs.map +1 -1
  187. package/dist/esm/tools/ToolSearch.mjs +1 -1
  188. package/dist/esm/tools/ToolSearch.mjs.map +1 -1
  189. package/dist/esm/tools/cloudflare/CloudflareSandboxExecutionEngine.mjs +7 -4
  190. package/dist/esm/tools/cloudflare/CloudflareSandboxExecutionEngine.mjs.map +1 -1
  191. package/dist/esm/tools/cloudflare/CloudflareSandboxTools.mjs +4 -4
  192. package/dist/esm/tools/cloudflare/CloudflareSandboxTools.mjs.map +1 -1
  193. package/dist/esm/tools/handlers.mjs +2 -1
  194. package/dist/esm/tools/handlers.mjs.map +1 -1
  195. package/dist/esm/tools/local/CompileCheckTool.mjs.map +1 -1
  196. package/dist/esm/tools/local/FileCheckpointer.mjs +2 -1
  197. package/dist/esm/tools/local/FileCheckpointer.mjs.map +1 -1
  198. package/dist/esm/tools/local/LocalCodingTools.mjs +45 -19
  199. package/dist/esm/tools/local/LocalCodingTools.mjs.map +1 -1
  200. package/dist/esm/tools/local/LocalExecutionEngine.mjs +3 -3
  201. package/dist/esm/tools/local/LocalExecutionEngine.mjs.map +1 -1
  202. package/dist/esm/tools/local/LocalExecutionTools.mjs +2 -2
  203. package/dist/esm/tools/local/LocalExecutionTools.mjs.map +1 -1
  204. package/dist/esm/tools/local/LocalProgrammaticToolCalling.mjs +4 -3
  205. package/dist/esm/tools/local/LocalProgrammaticToolCalling.mjs.map +1 -1
  206. package/dist/esm/tools/local/attachments.mjs +0 -5
  207. package/dist/esm/tools/local/attachments.mjs.map +1 -1
  208. package/dist/esm/tools/local/resolveLocalExecutionTools.mjs +4 -4
  209. package/dist/esm/tools/local/resolveLocalExecutionTools.mjs.map +1 -1
  210. package/dist/esm/tools/search/firecrawl.mjs +1 -1
  211. package/dist/esm/tools/search/firecrawl.mjs.map +1 -1
  212. package/dist/esm/tools/search/rerankers.mjs +8 -4
  213. package/dist/esm/tools/search/rerankers.mjs.map +1 -1
  214. package/dist/esm/tools/search/tavily-search.mjs +1 -1
  215. package/dist/esm/tools/search/tavily-search.mjs.map +1 -1
  216. package/dist/esm/tools/search/utils.mjs +76 -9
  217. package/dist/esm/tools/search/utils.mjs.map +1 -1
  218. package/dist/esm/tools/subagent/SubagentExecutor.mjs +1 -1
  219. package/dist/esm/tools/subagent/SubagentExecutor.mjs.map +1 -1
  220. package/dist/esm/utils/handlers.mjs +1 -1
  221. package/dist/esm/utils/handlers.mjs.map +1 -1
  222. package/dist/esm/utils/run.mjs +1 -1
  223. package/dist/esm/utils/run.mjs.map +1 -1
  224. package/dist/types/agents/__tests__/promptCacheLiveHelpers.d.ts +1 -1
  225. package/dist/types/events.d.ts +1 -1
  226. package/dist/types/graphs/Graph.d.ts +7 -1
  227. package/dist/types/hooks/executeHooks.d.ts +1 -1
  228. package/dist/types/hooks/types.d.ts +5 -0
  229. package/dist/types/instrumentation.d.ts +1 -0
  230. package/dist/types/langfuse.d.ts +4 -0
  231. package/dist/types/llm/anthropic/utils/message_inputs.d.ts +1 -1
  232. package/dist/types/llm/anthropic/utils/message_outputs.d.ts +1 -1
  233. package/dist/types/llm/anthropic/utils/output_parsers.d.ts +2 -2
  234. package/dist/types/llm/bedrock/index.d.ts +2 -2
  235. package/dist/types/llm/fake.d.ts +3 -3
  236. package/dist/types/llm/google/index.d.ts +1 -0
  237. package/dist/types/llm/google/types.d.ts +1 -1
  238. package/dist/types/llm/google/utils/common.d.ts +2 -2
  239. package/dist/types/llm/google/utils/tools.d.ts +1 -1
  240. package/dist/types/llm/google/utils/zod_to_genai_parameters.d.ts +1 -1
  241. package/dist/types/llm/openai/index.d.ts +2 -2
  242. package/dist/types/llm/openai/utils/index.d.ts +1 -1
  243. package/dist/types/llm/openrouter/index.d.ts +4 -4
  244. package/dist/types/messages/contextPruning.d.ts +1 -1
  245. package/dist/types/messages/format.d.ts +9 -4
  246. package/dist/types/messages/prune.d.ts +1 -1
  247. package/dist/types/session/JsonlSessionStore.d.ts +1 -1
  248. package/dist/types/session/handlers.d.ts +1 -1
  249. package/dist/types/session/types.d.ts +1 -1
  250. package/dist/types/summarization/node.d.ts +1 -1
  251. package/dist/types/tools/SubagentTool.d.ts +2 -2
  252. package/dist/types/tools/ToolNode.d.ts +9 -2
  253. package/dist/types/tools/cloudflare/CloudflareSandboxExecutionEngine.d.ts +1 -1
  254. package/dist/types/tools/search/types.d.ts +1 -1
  255. package/dist/types/tools/search/utils.d.ts +11 -0
  256. package/dist/types/types/graph.d.ts +12 -4
  257. package/dist/types/types/llm.d.ts +4 -3
  258. package/dist/types/types/messages.d.ts +1 -1
  259. package/dist/types/types/run.d.ts +6 -6
  260. package/dist/types/types/stream.d.ts +2 -2
  261. package/dist/types/types/tools.d.ts +5 -1
  262. package/dist/types/utils/handlers.d.ts +2 -2
  263. package/dist/types/utils/run.d.ts +1 -1
  264. package/package.json +6 -3
  265. package/src/__tests__/stream.eagerEventExecution.test.ts +543 -6
  266. package/src/agents/AgentContext.ts +2 -2
  267. package/src/agents/__tests__/AgentContext.test.ts +3 -3
  268. package/src/agents/__tests__/promptCacheLiveHelpers.ts +1 -1
  269. package/src/events.ts +1 -1
  270. package/src/graphs/Graph.ts +329 -72
  271. package/src/graphs/MultiAgentGraph.ts +1 -1
  272. package/src/graphs/__tests__/Graph.reasoning.test.ts +919 -6
  273. package/src/graphs/__tests__/MultiAgentGraph.test.ts +1 -1
  274. package/src/graphs/__tests__/composition.smoke.test.ts +1 -1
  275. package/src/hooks/__tests__/HookRegistry.test.ts +1 -1
  276. package/src/hooks/__tests__/compactHooks.test.ts +8 -8
  277. package/src/hooks/__tests__/createWorkspacePolicyHook.test.ts +34 -22
  278. package/src/hooks/__tests__/executeHooks.test.ts +3 -3
  279. package/src/hooks/__tests__/integration.test.ts +3 -3
  280. package/src/hooks/__tests__/toolHooks.test.ts +10 -10
  281. package/src/hooks/createWorkspacePolicyHook.ts +17 -14
  282. package/src/hooks/executeHooks.ts +1 -1
  283. package/src/hooks/types.ts +5 -0
  284. package/src/instrumentation.ts +49 -8
  285. package/src/langfuse.ts +35 -1
  286. package/src/langfuseToolOutputTracing.ts +2 -2
  287. package/src/llm/anthropic/index.ts +1 -1
  288. package/src/llm/anthropic/utils/message_inputs.ts +1 -1
  289. package/src/llm/anthropic/utils/message_outputs.ts +3 -5
  290. package/src/llm/anthropic/utils/output_parsers.ts +5 -5
  291. package/src/llm/bedrock/index.ts +4 -4
  292. package/src/llm/bedrock/toolCache.test.ts +48 -9
  293. package/src/llm/bedrock/toolCache.ts +11 -6
  294. package/src/llm/custom-chat-models.smoke.test.ts +114 -0
  295. package/src/llm/fake.ts +30 -25
  296. package/src/llm/google/index.ts +43 -1
  297. package/src/llm/google/llm.spec.ts +173 -1
  298. package/src/llm/google/types.ts +1 -1
  299. package/src/llm/google/utils/common.ts +154 -45
  300. package/src/llm/google/utils/tools.ts +8 -8
  301. package/src/llm/google/utils/zod_to_genai_parameters.ts +4 -4
  302. package/src/llm/invoke.test.ts +3 -3
  303. package/src/llm/invoke.ts +170 -10
  304. package/src/llm/openai/index.ts +4 -4
  305. package/src/llm/openai/utils/index.ts +14 -14
  306. package/src/llm/openrouter/index.ts +4 -4
  307. package/src/llm/openrouter/reasoning.test.ts +2 -2
  308. package/src/llm/vertexai/fixThoughtSignatures.test.ts +1 -1
  309. package/src/llm/vertexai/index.ts +1 -1
  310. package/src/messages/cache.test.ts +22 -0
  311. package/src/messages/cache.ts +25 -12
  312. package/src/messages/content.ts +1 -1
  313. package/src/messages/contextPruning.ts +1 -1
  314. package/src/messages/format.ts +227 -43
  315. package/src/messages/formatAgentMessages.skills.test.ts +105 -26
  316. package/src/messages/formatAgentMessages.test.ts +841 -10
  317. package/src/messages/labelContentByAgent.test.ts +2 -2
  318. package/src/messages/prune.ts +1 -1
  319. package/src/messages/reducer.ts +1 -1
  320. package/src/messages/tools.ts +1 -1
  321. package/src/openai/__tests__/openai.test.ts +2 -2
  322. package/src/openai/index.ts +1 -1
  323. package/src/responses/__tests__/responses.test.ts +2 -2
  324. package/src/responses/index.ts +1 -1
  325. package/src/run.ts +82 -47
  326. package/src/session/AgentSession.ts +6 -6
  327. package/src/session/JsonlSessionStore.ts +3 -3
  328. package/src/session/__tests__/JsonlSessionStore.test.ts +5 -5
  329. package/src/session/__tests__/handlers.test.ts +2 -2
  330. package/src/session/handlers.ts +5 -5
  331. package/src/session/types.ts +1 -1
  332. package/src/specs/agent-handoffs.test.ts +1 -1
  333. package/src/specs/deterministic-trace-id.test.ts +50 -0
  334. package/src/specs/langfuse-callbacks.test.ts +2 -2
  335. package/src/specs/langfuse-metadata.test.ts +39 -0
  336. package/src/specs/langfuse-tool-output-tracing.test.ts +1 -1
  337. package/src/specs/multi-agent-summarization.test.ts +4 -4
  338. package/src/specs/subagent.test.ts +3 -3
  339. package/src/specs/summarization-unit.test.ts +1 -1
  340. package/src/specs/thinking-handoff.test.ts +1 -1
  341. package/src/splitStream.test.ts +48 -0
  342. package/src/stream.test.ts +53 -3
  343. package/src/stream.ts +450 -39
  344. package/src/summarization/__tests__/aggregator.test.ts +2 -2
  345. package/src/summarization/__tests__/node.test.ts +2 -2
  346. package/src/summarization/node.ts +1 -1
  347. package/src/tools/BashProgrammaticToolCalling.ts +5 -5
  348. package/src/tools/Calculator.ts +1 -1
  349. package/src/tools/CodeExecutor.ts +2 -4
  350. package/src/tools/SubagentTool.ts +2 -2
  351. package/src/tools/ToolNode.ts +37 -16
  352. package/src/tools/ToolSearch.ts +1 -1
  353. package/src/tools/__tests__/CloudflareSandboxExecution.test.ts +4 -4
  354. package/src/tools/__tests__/CodeApiAuthHeaders.test.ts +12 -12
  355. package/src/tools/__tests__/LocalExecutionTools.test.ts +125 -93
  356. package/src/tools/__tests__/ProgrammaticToolCalling.test.ts +29 -5
  357. package/src/tools/__tests__/ReadFile.test.ts +1 -1
  358. package/src/tools/__tests__/SkillTool.test.ts +4 -4
  359. package/src/tools/__tests__/SubagentExecutor.test.ts +17 -13
  360. package/src/tools/__tests__/SubagentTool.test.ts +2 -2
  361. package/src/tools/__tests__/ToolNode.eagerEventExecution.test.ts +1 -1
  362. package/src/tools/__tests__/ToolNode.outputReferences.test.ts +2 -5
  363. package/src/tools/__tests__/ToolNode.session.test.ts +1 -1
  364. package/src/tools/__tests__/ToolSearch.test.ts +1 -1
  365. package/src/tools/__tests__/annotateMessagesForLLM.test.ts +1 -1
  366. package/src/tools/__tests__/directToolHITLResumeScope.test.ts +35 -32
  367. package/src/tools/__tests__/directToolHooks.test.ts +41 -0
  368. package/src/tools/__tests__/handlers.test.ts +2 -2
  369. package/src/tools/__tests__/hitl.test.ts +11 -11
  370. package/src/tools/__tests__/localToolNames.test.ts +8 -6
  371. package/src/tools/__tests__/skillCatalog.test.ts +1 -1
  372. package/src/tools/__tests__/subagentHooks.test.ts +20 -10
  373. package/src/tools/__tests__/workspaceSeam.test.ts +20 -7
  374. package/src/tools/cloudflare/CloudflareSandboxExecutionEngine.ts +9 -6
  375. package/src/tools/cloudflare/CloudflareSandboxTools.ts +19 -19
  376. package/src/tools/handlers.ts +5 -5
  377. package/src/tools/local/CompileCheckTool.ts +4 -7
  378. package/src/tools/local/FileCheckpointer.ts +6 -5
  379. package/src/tools/local/LocalCodingTools.ts +100 -45
  380. package/src/tools/local/LocalExecutionEngine.ts +5 -5
  381. package/src/tools/local/LocalExecutionTools.ts +9 -9
  382. package/src/tools/local/LocalProgrammaticToolCalling.ts +5 -4
  383. package/src/tools/local/attachments.ts +0 -6
  384. package/src/tools/local/resolveLocalExecutionTools.ts +15 -15
  385. package/src/tools/search/firecrawl.ts +1 -1
  386. package/src/tools/search/jina-reranker.test.ts +148 -37
  387. package/src/tools/search/rerankers.ts +14 -4
  388. package/src/tools/search/tavily-search.ts +2 -2
  389. package/src/tools/search/types.ts +1 -1
  390. package/src/tools/search/utils.ts +99 -9
  391. package/src/tools/subagent/SubagentExecutor.ts +12 -6
  392. package/src/types/graph.ts +20 -12
  393. package/src/types/llm.ts +7 -6
  394. package/src/types/messages.ts +1 -1
  395. package/src/types/run.ts +7 -7
  396. package/src/types/stream.ts +2 -2
  397. package/src/types/tools.ts +5 -1
  398. package/src/utils/handlers.ts +2 -2
  399. package/src/utils/llmConfig.ts +1 -1
  400. package/src/utils/logging.ts +20 -10
  401. package/src/utils/run.ts +2 -2
@@ -15,17 +15,30 @@ type OpenAITool = {
15
15
  };
16
16
  };
17
17
 
18
- function createOpenAITool(name: string): OpenAITool {
18
+ type CreateOpenAIToolOptions = {
19
+ description?: string;
20
+ omitDescription?: boolean;
21
+ };
22
+
23
+ function createOpenAITool(
24
+ name: string,
25
+ options: CreateOpenAIToolOptions = {}
26
+ ): OpenAITool {
27
+ const functionDefinition: OpenAITool['function'] = {
28
+ name,
29
+ parameters: {
30
+ type: 'object',
31
+ properties: {},
32
+ },
33
+ };
34
+ const description = options.description ?? `${name} description`;
35
+ if (options.omitDescription !== true) {
36
+ functionDefinition.description = description;
37
+ }
38
+
19
39
  return {
20
40
  type: 'function',
21
- function: {
22
- name,
23
- description: `${name} description`,
24
- parameters: {
25
- type: 'object',
26
- properties: {},
27
- },
28
- },
41
+ function: functionDefinition,
29
42
  };
30
43
  }
31
44
 
@@ -40,6 +53,11 @@ function toolNames(tools: Tool[] | undefined): string[] {
40
53
  return (tools ?? []).map(toolName);
41
54
  }
42
55
 
56
+ function getToolSpec(entry: Tool): Tool.ToolSpecMember['toolSpec'] {
57
+ expect(entry).toHaveProperty('toolSpec');
58
+ return (entry as Tool.ToolSpecMember).toolSpec;
59
+ }
60
+
43
61
  describe('partitionAndMarkBedrockToolCache', () => {
44
62
  it('inserts the Bedrock cache point after the last static tool', () => {
45
63
  const tools = [
@@ -128,4 +146,25 @@ describe('partitionAndMarkBedrockToolCache', () => {
128
146
 
129
147
  expect(toolNames(result?.tools)).toEqual(['direct_tool', 'cachePoint']);
130
148
  });
149
+
150
+ it('omits empty OpenAI tool descriptions when converting for Bedrock', () => {
151
+ const tools = [
152
+ createOpenAITool('missing_description', { omitDescription: true }),
153
+ createOpenAITool('empty_description', { description: '' }),
154
+ createOpenAITool('described_tool'),
155
+ ] as GraphTools;
156
+
157
+ const marked = partitionAndMarkBedrockToolCache(
158
+ tools,
159
+ () => false
160
+ ) as Tool[];
161
+ const result = insertBedrockToolCachePoint({ tools: marked }, false);
162
+ const convertedTools = result?.tools ?? [];
163
+
164
+ expect(getToolSpec(convertedTools[0])).not.toHaveProperty('description');
165
+ expect(getToolSpec(convertedTools[1])).not.toHaveProperty('description');
166
+ expect(getToolSpec(convertedTools[2]).description).toBe(
167
+ 'described_tool description'
168
+ );
169
+ });
131
170
  });
@@ -1,5 +1,5 @@
1
- import type { Tool, ToolConfiguration } from '@aws-sdk/client-bedrock-runtime';
2
1
  import type { BindToolsInput } from '@langchain/core/language_models/chat_models';
2
+ import type { Tool, ToolConfiguration } from '@aws-sdk/client-bedrock-runtime';
3
3
  import type { OpenAIClient } from '@langchain/openai';
4
4
  import type { DocumentType } from '@smithy/types';
5
5
  import type { GraphTools } from '@/types';
@@ -60,12 +60,17 @@ function getToolName(tool: unknown): string | undefined {
60
60
  }
61
61
 
62
62
  function openAIToBedrockTool(tool: OpenAIFunctionTool): Tool.ToolSpecMember {
63
+ const toolSpec: NonNullable<Tool.ToolSpecMember['toolSpec']> = {
64
+ name: tool.function.name,
65
+ inputSchema: { json: tool.function.parameters as DocumentType },
66
+ };
67
+
68
+ if (tool.function.description != null && tool.function.description !== '') {
69
+ toolSpec.description = tool.function.description;
70
+ }
71
+
63
72
  return {
64
- toolSpec: {
65
- name: tool.function.name,
66
- description: tool.function.description,
67
- inputSchema: { json: tool.function.parameters as DocumentType },
68
- },
73
+ toolSpec,
69
74
  };
70
75
  }
71
76
 
@@ -135,6 +135,22 @@ type OpenRouterReasoningStreamChoice = Omit<
135
135
  > & {
136
136
  delta: OpenRouterReasoningStreamDelta;
137
137
  };
138
+ type OpenAICompatibleReasoningStreamDelta =
139
+ OpenAIClient.Chat.Completions.ChatCompletionChunk.Choice.Delta & {
140
+ reasoning?: string;
141
+ reasoning_details?: Array<{
142
+ type: 'reasoning.text';
143
+ text?: string;
144
+ format?: string;
145
+ index?: number;
146
+ }>;
147
+ };
148
+ type OpenAICompatibleReasoningStreamChoice = Omit<
149
+ OpenAIClient.Chat.Completions.ChatCompletionChunk.Choice,
150
+ 'delta'
151
+ > & {
152
+ delta: OpenAICompatibleReasoningStreamDelta;
153
+ };
138
154
  type PromptTokensDetailsWithCacheWrite = NonNullable<
139
155
  OpenAIClient.Completions.CompletionUsage['prompt_tokens_details']
140
156
  > & {
@@ -472,6 +488,104 @@ describe('custom chat model class smoke tests', () => {
472
488
  );
473
489
  });
474
490
 
491
+ it('preserves OpenAI-compatible reasoning deltas during OpenAI streaming', async () => {
492
+ const model = new ChatOpenAI({
493
+ model: 'openai/gpt-oss-120b',
494
+ apiKey: 'test-key',
495
+ streaming: true,
496
+ });
497
+ const completions = (model as unknown as StreamingCompletionBackedModel)
498
+ .completions;
499
+ const createChunk = (
500
+ choice: OpenAICompatibleReasoningStreamChoice
501
+ ): OpenAIClient.Chat.Completions.ChatCompletionChunk => ({
502
+ id: 'chatcmpl-openai-compatible-reasoning',
503
+ object: 'chat.completion.chunk',
504
+ created: 0,
505
+ model: 'openai/gpt-oss-120b',
506
+ choices: [choice],
507
+ });
508
+
509
+ async function* streamChunks(): AsyncGenerator<OpenAIClient.Chat.Completions.ChatCompletionChunk> {
510
+ yield createChunk({
511
+ index: 0,
512
+ delta: {
513
+ role: 'assistant',
514
+ content: '',
515
+ },
516
+ finish_reason: null,
517
+ });
518
+ yield createChunk({
519
+ index: 0,
520
+ delta: {
521
+ reasoning: 'Think ',
522
+ reasoning_details: [
523
+ {
524
+ type: 'reasoning.text',
525
+ text: 'Think ',
526
+ format: 'text',
527
+ index: 0,
528
+ },
529
+ ],
530
+ },
531
+ finish_reason: null,
532
+ });
533
+ yield createChunk({
534
+ index: 0,
535
+ delta: {
536
+ reasoning: 'hard',
537
+ reasoning_details: [
538
+ {
539
+ type: 'reasoning.text',
540
+ text: 'hard',
541
+ format: 'text',
542
+ index: 0,
543
+ },
544
+ ],
545
+ },
546
+ finish_reason: null,
547
+ });
548
+ yield createChunk({
549
+ index: 0,
550
+ delta: { content: 'answer' },
551
+ finish_reason: 'stop',
552
+ });
553
+ }
554
+
555
+ completions.completionWithRetry = async (): Promise<
556
+ AsyncIterable<OpenAIClient.Chat.Completions.ChatCompletionChunk>
557
+ > => streamChunks();
558
+
559
+ const chunks: AIMessageChunk[] = [];
560
+ const stream = await model.stream([new HumanMessage('think')]);
561
+ for await (const chunk of stream) {
562
+ chunks.push(chunk);
563
+ }
564
+
565
+ expect(
566
+ chunks
567
+ .map((chunk) => chunk.additional_kwargs.reasoning_content)
568
+ .filter((reasoningContent) => reasoningContent != null)
569
+ ).toEqual(['Think ', 'hard']);
570
+ expect(chunks[1].additional_kwargs.reasoning_details).toEqual([
571
+ {
572
+ type: 'reasoning.text',
573
+ text: 'Think ',
574
+ format: 'text',
575
+ index: 0,
576
+ },
577
+ ]);
578
+ expect(chunks[2].additional_kwargs.reasoning_details).toEqual([
579
+ {
580
+ type: 'reasoning.text',
581
+ text: 'hard',
582
+ format: 'text',
583
+ index: 0,
584
+ },
585
+ ]);
586
+ expect(chunks.at(-1)?.content).toBe('answer');
587
+ });
588
+
475
589
  it('skips custom OpenAI-compatible SSE events during Azure streaming', async () => {
476
590
  await expectCustomSSEEventsSkipped(
477
591
  new AzureChatOpenAI({
package/src/llm/fake.ts CHANGED
@@ -1,9 +1,9 @@
1
- import { ChatGenerationChunk } from '@langchain/core/outputs';
2
1
  import { AIMessageChunk } from '@langchain/core/messages';
3
- import type { CallbackManagerForLLMRun } from '@langchain/core/callbacks/manager';
4
- import type { BaseMessage } from '@langchain/core/messages';
2
+ import { ChatGenerationChunk } from '@langchain/core/outputs';
5
3
  import { FakeListChatModel } from '@langchain/core/utils/testing';
6
4
  import { ToolCall, ToolCallChunk } from '@langchain/core/messages/tool';
5
+ import type { CallbackManagerForLLMRun } from '@langchain/core/callbacks/manager';
6
+ import type { BaseMessage } from '@langchain/core/messages';
7
7
 
8
8
  type SplitStrategy = {
9
9
  type: 'regex' | 'fixed';
@@ -20,7 +20,7 @@ export class FakeChatModel extends FakeListChatModel {
20
20
  sleep,
21
21
  emitCustomEvent,
22
22
  splitStrategy = { type: 'regex', value: /(?<=\s+)|(?=\s+)/ },
23
- toolCalls = []
23
+ toolCalls = [],
24
24
  }: {
25
25
  responses: string[];
26
26
  sleep?: number;
@@ -45,25 +45,31 @@ export class FakeChatModel extends FakeListChatModel {
45
45
  return chunks;
46
46
  }
47
47
  }
48
- _createResponseChunk(text: string, tool_call_chunks?: ToolCallChunk[]): ChatGenerationChunk {
48
+ _createResponseChunk(
49
+ text: string,
50
+ tool_call_chunks?: ToolCallChunk[]
51
+ ): ChatGenerationChunk {
49
52
  return new ChatGenerationChunk({
50
53
  text,
51
54
  generationInfo: {},
52
55
  message: new AIMessageChunk({
53
56
  content: text,
54
57
  tool_call_chunks,
55
- additional_kwargs: tool_call_chunks ? {
56
- tool_calls: tool_call_chunks.map((toolCall) => ({
57
- index: toolCall.index ?? 0,
58
- id: toolCall.id ?? '',
59
- type: 'function',
60
- function: {
61
- name: toolCall.name ?? '',
62
- arguments: toolCall.args ?? '',
63
- },
64
- })),
65
- } : undefined,
66
- })});
58
+ additional_kwargs: tool_call_chunks
59
+ ? {
60
+ tool_calls: tool_call_chunks.map((toolCall) => ({
61
+ index: toolCall.index ?? 0,
62
+ id: toolCall.id ?? '',
63
+ type: 'function',
64
+ function: {
65
+ name: toolCall.name ?? '',
66
+ arguments: toolCall.args ?? '',
67
+ },
68
+ })),
69
+ }
70
+ : undefined,
71
+ }),
72
+ });
67
73
  }
68
74
 
69
75
  async *_streamResponseChunks(
@@ -96,7 +102,7 @@ export class FakeChatModel extends FakeListChatModel {
96
102
  await this._sleepIfRequested();
97
103
  if (this.toolCalls.length > 0 && !this.addedToolCalls) {
98
104
  this.addedToolCalls = true;
99
- const toolCallChunks = this.toolCalls.map((toolCall) => {;
105
+ const toolCallChunks = this.toolCalls.map((toolCall) => {
100
106
  return {
101
107
  name: toolCall.name,
102
108
  args: JSON.stringify(toolCall.args),
@@ -116,13 +122,12 @@ export function createFakeStreamingLLM({
116
122
  sleep,
117
123
  splitStrategy,
118
124
  toolCalls,
119
- } : {
120
- responses: string[],
121
- sleep?: number,
122
- splitStrategy?: SplitStrategy,
123
- toolCalls?: ToolCall[]
124
- }
125
- ): FakeChatModel {
125
+ }: {
126
+ responses: string[];
127
+ sleep?: number;
128
+ splitStrategy?: SplitStrategy;
129
+ toolCalls?: ToolCall[];
130
+ }): FakeChatModel {
126
131
  return new FakeChatModel({
127
132
  sleep,
128
133
  responses,
@@ -3,10 +3,14 @@ import { AIMessageChunk } from '@langchain/core/messages';
3
3
  import { ChatGenerationChunk } from '@langchain/core/outputs';
4
4
  import { ChatGoogleGenerativeAI } from '@langchain/google-genai';
5
5
  import { getEnvironmentVariable } from '@langchain/core/utils/env';
6
- import { GoogleGenerativeAI as GenerativeAI } from '@google/generative-ai';
6
+ import {
7
+ FunctionCallingMode,
8
+ GoogleGenerativeAI as GenerativeAI,
9
+ } from '@google/generative-ai';
7
10
  import type {
8
11
  GenerateContentRequest,
9
12
  SafetySetting,
13
+ ToolConfig,
10
14
  } from '@google/generative-ai';
11
15
  import type { CallbackManagerForLLMRun } from '@langchain/core/callbacks/manager';
12
16
  import type { BaseMessage, UsageMetadata } from '@langchain/core/messages';
@@ -18,8 +22,21 @@ import {
18
22
  mapGenerateContentResultToChatResult,
19
23
  } from './utils/common';
20
24
 
25
+ type GoogleToolConfigWithServerSideInvocations = ToolConfig & {
26
+ includeServerSideToolInvocations?: boolean;
27
+ functionCallingConfig?: Omit<
28
+ NonNullable<ToolConfig['functionCallingConfig']>,
29
+ 'mode'
30
+ > & {
31
+ mode?:
32
+ | NonNullable<ToolConfig['functionCallingConfig']>['mode']
33
+ | 'VALIDATED';
34
+ };
35
+ };
36
+
21
37
  export class CustomChatGoogleGenerativeAI extends ChatGoogleGenerativeAI {
22
38
  thinkingConfig?: GoogleThinkingConfig;
39
+ includeServerSideToolInvocations?: boolean;
23
40
 
24
41
  /**
25
42
  * Override to add gemini-3 model support for multimodal and function calling thought signatures
@@ -92,6 +109,9 @@ export class CustomChatGoogleGenerativeAI extends ChatGoogleGenerativeAI {
92
109
  }
93
110
 
94
111
  this.thinkingConfig = fields.thinkingConfig ?? this.thinkingConfig;
112
+ this.includeServerSideToolInvocations =
113
+ fields.includeServerSideToolInvocations ??
114
+ this.includeServerSideToolInvocations;
95
115
 
96
116
  this.streaming = fields.streaming ?? this.streaming;
97
117
  this.json = fields.json;
@@ -191,6 +211,28 @@ export class CustomChatGoogleGenerativeAI extends ChatGoogleGenerativeAI {
191
211
  thinkingConfig: this.thinkingConfig,
192
212
  };
193
213
  }
214
+ if (
215
+ this.includeServerSideToolInvocations === true &&
216
+ Array.isArray(params.tools) &&
217
+ params.tools.length > 0
218
+ ) {
219
+ const toolConfig = params.toolConfig as
220
+ | GoogleToolConfigWithServerSideInvocations
221
+ | undefined;
222
+ const functionCallingConfig = toolConfig?.functionCallingConfig;
223
+ params.toolConfig = {
224
+ ...toolConfig,
225
+ ...(functionCallingConfig?.mode === FunctionCallingMode.AUTO
226
+ ? {
227
+ functionCallingConfig: {
228
+ ...functionCallingConfig,
229
+ mode: 'VALIDATED',
230
+ },
231
+ }
232
+ : {}),
233
+ includeServerSideToolInvocations: true,
234
+ } as ToolConfig;
235
+ }
194
236
  return params;
195
237
  }
196
238
 
@@ -29,7 +29,12 @@ import type {
29
29
  } from '@google/generative-ai';
30
30
  import type { ContentBlock } from '@langchain/core/messages';
31
31
  import { CustomChatGoogleGenerativeAI as ChatGoogleGenerativeAI } from './index';
32
- import { _FUNCTION_CALL_THOUGHT_SIGNATURES_MAP_KEY } from './utils/common';
32
+ import {
33
+ convertMessageContentToParts,
34
+ convertResponseContentToChatGenerationChunk,
35
+ mapGenerateContentResultToChatResult,
36
+ _FUNCTION_CALL_THOUGHT_SIGNATURES_MAP_KEY,
37
+ } from './utils/common';
33
38
 
34
39
  // Save the original value of the 'LANGCHAIN_CALLBACKS_BACKGROUND' environment variable
35
40
  const originalBackground = process.env.LANGCHAIN_CALLBACKS_BACKGROUND;
@@ -731,6 +736,173 @@ test('Invoke with JSON mode', async () => {
731
736
  );
732
737
  });
733
738
 
739
+ test('Includes server-side tool invocation config when enabled', () => {
740
+ const model = new ChatGoogleGenerativeAI({
741
+ apiKey: 'test-key',
742
+ model: 'gemini-3.5-flash',
743
+ includeServerSideToolInvocations: true,
744
+ });
745
+ const getWeather = {
746
+ name: 'get_weather',
747
+ description: 'Get the weather',
748
+ };
749
+
750
+ const request = model.invocationParams({
751
+ tools: [{ googleSearch: {} }, { functionDeclarations: [getWeather] }],
752
+ });
753
+
754
+ expect(request.toolConfig).toEqual(
755
+ expect.objectContaining({
756
+ includeServerSideToolInvocations: true,
757
+ })
758
+ );
759
+ });
760
+
761
+ test('Normalizes auto tool choice when server-side tool invocation config is enabled', () => {
762
+ const model = new ChatGoogleGenerativeAI({
763
+ apiKey: 'test-key',
764
+ model: 'gemini-3.5-flash',
765
+ includeServerSideToolInvocations: true,
766
+ });
767
+ const getWeather = {
768
+ name: 'get_weather',
769
+ description: 'Get the weather',
770
+ };
771
+
772
+ const request = model.invocationParams({
773
+ tools: [{ googleSearch: {} }, { functionDeclarations: [getWeather] }],
774
+ tool_choice: 'auto',
775
+ });
776
+ const toolConfig = request.toolConfig as
777
+ | {
778
+ includeServerSideToolInvocations?: boolean;
779
+ functionCallingConfig?: { mode?: string };
780
+ }
781
+ | undefined;
782
+
783
+ expect(toolConfig).toEqual(
784
+ expect.objectContaining({
785
+ includeServerSideToolInvocations: true,
786
+ })
787
+ );
788
+ expect(toolConfig?.functionCallingConfig?.mode).toBe('VALIDATED');
789
+ });
790
+
791
+ test('Preserves Gemini server-side tool context parts in history', () => {
792
+ const toolCallPart = {
793
+ type: 'toolCall',
794
+ agentId: 'agent_1',
795
+ groupId: 1,
796
+ thoughtSignature: 'signature-1',
797
+ toolCall: {
798
+ id: 'server-search-1',
799
+ name: 'google_search',
800
+ args: {},
801
+ },
802
+ } as const;
803
+ const toolResponsePart = {
804
+ type: 'toolResponse',
805
+ agentId: 'agent_1',
806
+ groupId: 1,
807
+ toolResponse: {
808
+ id: 'server-search-1',
809
+ name: 'google_search',
810
+ response: { results: [] },
811
+ },
812
+ } as const;
813
+ const message = new AIMessage({
814
+ content: [toolCallPart, toolResponsePart],
815
+ });
816
+
817
+ expect(convertMessageContentToParts(message, true, [])).toEqual([
818
+ {
819
+ toolCall: toolCallPart.toolCall,
820
+ thoughtSignature: 'signature-1',
821
+ },
822
+ {
823
+ toolResponse: toolResponsePart.toolResponse,
824
+ },
825
+ ]);
826
+ });
827
+
828
+ test('Preserves Gemini function-call ids in history', () => {
829
+ const aiMessage = new AIMessage({
830
+ content: '',
831
+ tool_calls: [
832
+ {
833
+ id: 'call_weather_1',
834
+ name: 'get_weather',
835
+ args: { city: 'NYC' },
836
+ },
837
+ ],
838
+ });
839
+ const toolMessage = new ToolMessage({
840
+ content: 'sunny',
841
+ name: 'get_weather',
842
+ tool_call_id: 'call_weather_1',
843
+ });
844
+
845
+ expect(convertMessageContentToParts(aiMessage, true, [])).toEqual([
846
+ {
847
+ functionCall: {
848
+ id: 'call_weather_1',
849
+ name: 'get_weather',
850
+ args: { city: 'NYC' },
851
+ },
852
+ },
853
+ ]);
854
+ expect(convertMessageContentToParts(toolMessage, true, [aiMessage])).toEqual([
855
+ {
856
+ functionResponse: {
857
+ id: 'call_weather_1',
858
+ name: 'get_weather',
859
+ response: { result: 'sunny' },
860
+ },
861
+ },
862
+ ]);
863
+ });
864
+
865
+ test('Preserves Gemini server-side tool context parts from responses', () => {
866
+ const toolCallPart = {
867
+ toolCall: {
868
+ id: 'server-search-1',
869
+ name: 'google_search',
870
+ args: {},
871
+ },
872
+ };
873
+ const toolResponsePart = {
874
+ toolResponse: {
875
+ id: 'server-search-1',
876
+ name: 'google_search',
877
+ response: { results: [] },
878
+ },
879
+ };
880
+ const response = {
881
+ candidates: [
882
+ {
883
+ content: {
884
+ role: 'model',
885
+ parts: [toolCallPart, toolResponsePart],
886
+ },
887
+ },
888
+ ],
889
+ } as unknown as Parameters<
890
+ typeof convertResponseContentToChatGenerationChunk
891
+ >[0];
892
+
893
+ const chunk = convertResponseContentToChatGenerationChunk(response, {
894
+ index: 0,
895
+ });
896
+ const result = mapGenerateContentResultToChatResult(response);
897
+
898
+ const expectedContent = [
899
+ { ...toolCallPart, type: 'toolCall' },
900
+ { ...toolResponsePart, type: 'toolResponse' },
901
+ ];
902
+ expect(chunk?.message.content).toEqual(expectedContent);
903
+ expect(result.generations[0].message.content).toEqual(expectedContent);
904
+ });
905
+
734
906
  test('Supports tool_choice', async () => {
735
907
  const model = createGoogleModel({
736
908
  model: 'gemini-2.0-flash',
@@ -1,9 +1,9 @@
1
+ import { BindToolsInput } from '@langchain/core/language_models/chat_models';
1
2
  import {
2
3
  CodeExecutionTool,
3
4
  FunctionDeclarationsTool as GoogleGenerativeAIFunctionDeclarationsTool,
4
5
  GoogleSearchRetrievalTool,
5
6
  } from '@google/generative-ai';
6
- import { BindToolsInput } from '@langchain/core/language_models/chat_models';
7
7
 
8
8
  /** New GoogleSearch tool for Gemini 2.0+ models */
9
9
  export interface GoogleSearchTool {