@librechat/agents 3.2.21 → 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 (398) 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 +2 -2
  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 +41 -20
  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 +2 -2
  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 +41 -20
  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/langfuse.d.ts +4 -0
  230. package/dist/types/llm/anthropic/utils/message_inputs.d.ts +1 -1
  231. package/dist/types/llm/anthropic/utils/message_outputs.d.ts +1 -1
  232. package/dist/types/llm/anthropic/utils/output_parsers.d.ts +2 -2
  233. package/dist/types/llm/bedrock/index.d.ts +2 -2
  234. package/dist/types/llm/fake.d.ts +3 -3
  235. package/dist/types/llm/google/index.d.ts +1 -0
  236. package/dist/types/llm/google/types.d.ts +1 -1
  237. package/dist/types/llm/google/utils/common.d.ts +2 -2
  238. package/dist/types/llm/google/utils/tools.d.ts +1 -1
  239. package/dist/types/llm/google/utils/zod_to_genai_parameters.d.ts +1 -1
  240. package/dist/types/llm/openai/index.d.ts +2 -2
  241. package/dist/types/llm/openai/utils/index.d.ts +1 -1
  242. package/dist/types/llm/openrouter/index.d.ts +4 -4
  243. package/dist/types/messages/contextPruning.d.ts +1 -1
  244. package/dist/types/messages/format.d.ts +9 -4
  245. package/dist/types/messages/prune.d.ts +1 -1
  246. package/dist/types/session/JsonlSessionStore.d.ts +1 -1
  247. package/dist/types/session/handlers.d.ts +1 -1
  248. package/dist/types/session/types.d.ts +1 -1
  249. package/dist/types/summarization/node.d.ts +1 -1
  250. package/dist/types/tools/SubagentTool.d.ts +2 -2
  251. package/dist/types/tools/ToolNode.d.ts +9 -2
  252. package/dist/types/tools/cloudflare/CloudflareSandboxExecutionEngine.d.ts +1 -1
  253. package/dist/types/tools/search/types.d.ts +1 -1
  254. package/dist/types/tools/search/utils.d.ts +11 -0
  255. package/dist/types/types/graph.d.ts +4 -4
  256. package/dist/types/types/llm.d.ts +4 -3
  257. package/dist/types/types/messages.d.ts +1 -1
  258. package/dist/types/types/run.d.ts +6 -6
  259. package/dist/types/types/stream.d.ts +2 -2
  260. package/dist/types/types/tools.d.ts +5 -1
  261. package/dist/types/utils/handlers.d.ts +2 -2
  262. package/dist/types/utils/run.d.ts +1 -1
  263. package/package.json +6 -3
  264. package/src/__tests__/stream.eagerEventExecution.test.ts +543 -6
  265. package/src/agents/AgentContext.ts +2 -2
  266. package/src/agents/__tests__/AgentContext.test.ts +3 -3
  267. package/src/agents/__tests__/promptCacheLiveHelpers.ts +1 -1
  268. package/src/events.ts +1 -1
  269. package/src/graphs/Graph.ts +329 -72
  270. package/src/graphs/MultiAgentGraph.ts +1 -1
  271. package/src/graphs/__tests__/Graph.reasoning.test.ts +919 -6
  272. package/src/graphs/__tests__/MultiAgentGraph.test.ts +1 -1
  273. package/src/graphs/__tests__/composition.smoke.test.ts +1 -1
  274. package/src/hooks/__tests__/HookRegistry.test.ts +1 -1
  275. package/src/hooks/__tests__/compactHooks.test.ts +8 -8
  276. package/src/hooks/__tests__/createWorkspacePolicyHook.test.ts +34 -22
  277. package/src/hooks/__tests__/executeHooks.test.ts +3 -3
  278. package/src/hooks/__tests__/integration.test.ts +3 -3
  279. package/src/hooks/__tests__/toolHooks.test.ts +10 -10
  280. package/src/hooks/createWorkspacePolicyHook.ts +17 -14
  281. package/src/hooks/executeHooks.ts +1 -1
  282. package/src/hooks/types.ts +5 -0
  283. package/src/instrumentation.ts +11 -11
  284. package/src/langfuse.ts +35 -1
  285. package/src/langfuseToolOutputTracing.ts +2 -2
  286. package/src/llm/anthropic/index.ts +1 -1
  287. package/src/llm/anthropic/utils/message_inputs.ts +1 -1
  288. package/src/llm/anthropic/utils/message_outputs.ts +3 -5
  289. package/src/llm/anthropic/utils/output_parsers.ts +5 -5
  290. package/src/llm/bedrock/index.ts +4 -4
  291. package/src/llm/bedrock/toolCache.test.ts +48 -9
  292. package/src/llm/bedrock/toolCache.ts +11 -6
  293. package/src/llm/fake.ts +30 -25
  294. package/src/llm/google/index.ts +43 -1
  295. package/src/llm/google/llm.spec.ts +173 -1
  296. package/src/llm/google/types.ts +1 -1
  297. package/src/llm/google/utils/common.ts +154 -45
  298. package/src/llm/google/utils/tools.ts +8 -8
  299. package/src/llm/google/utils/zod_to_genai_parameters.ts +4 -4
  300. package/src/llm/invoke.test.ts +3 -3
  301. package/src/llm/invoke.ts +170 -10
  302. package/src/llm/openai/index.ts +4 -4
  303. package/src/llm/openai/utils/index.ts +14 -14
  304. package/src/llm/openrouter/index.ts +4 -4
  305. package/src/llm/openrouter/reasoning.test.ts +2 -2
  306. package/src/llm/vertexai/fixThoughtSignatures.test.ts +1 -1
  307. package/src/llm/vertexai/index.ts +1 -1
  308. package/src/messages/cache.test.ts +22 -0
  309. package/src/messages/cache.ts +25 -12
  310. package/src/messages/content.ts +1 -1
  311. package/src/messages/contextPruning.ts +1 -1
  312. package/src/messages/format.ts +227 -43
  313. package/src/messages/formatAgentMessages.skills.test.ts +105 -26
  314. package/src/messages/formatAgentMessages.test.ts +841 -10
  315. package/src/messages/labelContentByAgent.test.ts +2 -2
  316. package/src/messages/prune.ts +1 -1
  317. package/src/messages/reducer.ts +1 -1
  318. package/src/messages/tools.ts +1 -1
  319. package/src/openai/__tests__/openai.test.ts +2 -2
  320. package/src/openai/index.ts +1 -1
  321. package/src/responses/__tests__/responses.test.ts +2 -2
  322. package/src/responses/index.ts +1 -1
  323. package/src/run.ts +68 -41
  324. package/src/session/AgentSession.ts +6 -6
  325. package/src/session/JsonlSessionStore.ts +3 -3
  326. package/src/session/__tests__/JsonlSessionStore.test.ts +5 -5
  327. package/src/session/__tests__/handlers.test.ts +2 -2
  328. package/src/session/handlers.ts +5 -5
  329. package/src/session/types.ts +1 -1
  330. package/src/specs/agent-handoffs.test.ts +1 -1
  331. package/src/specs/langfuse-callbacks.test.ts +2 -2
  332. package/src/specs/langfuse-metadata.test.ts +39 -0
  333. package/src/specs/langfuse-tool-output-tracing.test.ts +1 -1
  334. package/src/specs/multi-agent-summarization.test.ts +4 -4
  335. package/src/specs/subagent.test.ts +3 -3
  336. package/src/specs/summarization-unit.test.ts +1 -1
  337. package/src/specs/thinking-handoff.test.ts +1 -1
  338. package/src/splitStream.test.ts +48 -0
  339. package/src/stream.test.ts +53 -3
  340. package/src/stream.ts +450 -39
  341. package/src/summarization/__tests__/aggregator.test.ts +2 -2
  342. package/src/summarization/__tests__/node.test.ts +2 -2
  343. package/src/summarization/node.ts +1 -1
  344. package/src/tools/BashProgrammaticToolCalling.ts +5 -5
  345. package/src/tools/Calculator.ts +1 -1
  346. package/src/tools/CodeExecutor.ts +2 -4
  347. package/src/tools/SubagentTool.ts +2 -2
  348. package/src/tools/ToolNode.ts +37 -16
  349. package/src/tools/ToolSearch.ts +1 -1
  350. package/src/tools/__tests__/CloudflareSandboxExecution.test.ts +4 -4
  351. package/src/tools/__tests__/CodeApiAuthHeaders.test.ts +12 -12
  352. package/src/tools/__tests__/LocalExecutionTools.test.ts +125 -93
  353. package/src/tools/__tests__/ProgrammaticToolCalling.test.ts +29 -5
  354. package/src/tools/__tests__/ReadFile.test.ts +1 -1
  355. package/src/tools/__tests__/SkillTool.test.ts +4 -4
  356. package/src/tools/__tests__/SubagentExecutor.test.ts +17 -13
  357. package/src/tools/__tests__/SubagentTool.test.ts +2 -2
  358. package/src/tools/__tests__/ToolNode.eagerEventExecution.test.ts +1 -1
  359. package/src/tools/__tests__/ToolNode.outputReferences.test.ts +2 -5
  360. package/src/tools/__tests__/ToolNode.session.test.ts +1 -1
  361. package/src/tools/__tests__/ToolSearch.test.ts +1 -1
  362. package/src/tools/__tests__/annotateMessagesForLLM.test.ts +1 -1
  363. package/src/tools/__tests__/directToolHITLResumeScope.test.ts +35 -32
  364. package/src/tools/__tests__/directToolHooks.test.ts +41 -0
  365. package/src/tools/__tests__/handlers.test.ts +2 -2
  366. package/src/tools/__tests__/hitl.test.ts +11 -11
  367. package/src/tools/__tests__/localToolNames.test.ts +8 -6
  368. package/src/tools/__tests__/skillCatalog.test.ts +1 -1
  369. package/src/tools/__tests__/subagentHooks.test.ts +20 -10
  370. package/src/tools/__tests__/workspaceSeam.test.ts +20 -7
  371. package/src/tools/cloudflare/CloudflareSandboxExecutionEngine.ts +9 -6
  372. package/src/tools/cloudflare/CloudflareSandboxTools.ts +19 -19
  373. package/src/tools/handlers.ts +5 -5
  374. package/src/tools/local/CompileCheckTool.ts +4 -7
  375. package/src/tools/local/FileCheckpointer.ts +6 -5
  376. package/src/tools/local/LocalCodingTools.ts +100 -45
  377. package/src/tools/local/LocalExecutionEngine.ts +5 -5
  378. package/src/tools/local/LocalExecutionTools.ts +9 -9
  379. package/src/tools/local/LocalProgrammaticToolCalling.ts +5 -4
  380. package/src/tools/local/attachments.ts +0 -6
  381. package/src/tools/local/resolveLocalExecutionTools.ts +15 -15
  382. package/src/tools/search/firecrawl.ts +1 -1
  383. package/src/tools/search/jina-reranker.test.ts +148 -37
  384. package/src/tools/search/rerankers.ts +14 -4
  385. package/src/tools/search/tavily-search.ts +2 -2
  386. package/src/tools/search/types.ts +1 -1
  387. package/src/tools/search/utils.ts +99 -9
  388. package/src/tools/subagent/SubagentExecutor.ts +12 -6
  389. package/src/types/graph.ts +12 -12
  390. package/src/types/llm.ts +7 -6
  391. package/src/types/messages.ts +1 -1
  392. package/src/types/run.ts +7 -7
  393. package/src/types/stream.ts +2 -2
  394. package/src/types/tools.ts +5 -1
  395. package/src/utils/handlers.ts +2 -2
  396. package/src/utils/llmConfig.ts +1 -1
  397. package/src/utils/logging.ts +20 -10
  398. package/src/utils/run.ts +2 -2
@@ -1,6 +1,6 @@
1
1
  import { expect, test, describe } from '@jest/globals';
2
- import type { GeminiContent } from '@langchain/google-common';
3
2
  import { AIMessage, HumanMessage, ToolMessage } from '@langchain/core/messages';
3
+ import type { GeminiContent } from '@langchain/google-common';
4
4
  import { fixThoughtSignatures } from './index';
5
5
 
6
6
  const SIG_A = 'AY89a1/sigA==';
@@ -1,5 +1,6 @@
1
1
  import { ChatGoogle } from '@langchain/google-gauth';
2
2
  import { ChatConnection } from '@langchain/google-common';
3
+ import { AIMessageChunk, isAIMessage } from '@langchain/core/messages';
3
4
  import type {
4
5
  GeminiContent,
5
6
  GeminiRequest,
@@ -8,7 +9,6 @@ import type {
8
9
  } from '@langchain/google-common';
9
10
  import type { CallbackManagerForLLMRun } from '@langchain/core/callbacks/manager';
10
11
  import type { BaseMessage, UsageMetadata } from '@langchain/core/messages';
11
- import { AIMessageChunk, isAIMessage } from '@langchain/core/messages';
12
12
  import type { ChatGenerationChunk } from '@langchain/core/outputs';
13
13
  import type { GoogleThinkingConfig, VertexAIClientOptions } from '@/types';
14
14
 
@@ -16,6 +16,7 @@ import {
16
16
  } from './cache';
17
17
  import { _convertMessagesToOpenAIParams } from '@/llm/openai/utils';
18
18
  import { toLangChainContent } from './langchain';
19
+ import { formatAgentMessages } from './format';
19
20
  import { ContentTypes } from '@/common/enum';
20
21
 
21
22
  type CacheControlBlock = MessageContentComplex & {
@@ -1474,6 +1475,27 @@ describe('Multi-turn cache cleanup', () => {
1474
1475
  });
1475
1476
 
1476
1477
  describe('LangChain message type preservation', () => {
1478
+ it('preserves direct roles for formatted LangChain messages after addCacheControl', () => {
1479
+ const { messages } = formatAgentMessages([
1480
+ { role: 'user', content: 'Hello' },
1481
+ { role: 'assistant', content: 'Hi there' },
1482
+ { role: 'user', content: 'Thanks' },
1483
+ ]);
1484
+
1485
+ const result = addCacheControl(messages);
1486
+
1487
+ expect(result.map((message) => message.role)).toEqual([
1488
+ 'user',
1489
+ 'assistant',
1490
+ 'user',
1491
+ ]);
1492
+ expect(result[0]).toBeInstanceOf(HumanMessage);
1493
+ expect(result[0]).not.toBe(messages[0]);
1494
+ expect(Object.keys(result[0])).not.toContain('role');
1495
+ expect(result[1]).toBe(messages[1]);
1496
+ expect(result[2]).not.toBe(messages[2]);
1497
+ });
1498
+
1477
1499
  it('should preserve instanceof for LangChain messages after addCacheControl', () => {
1478
1500
  const messages: BaseMessage[] = [
1479
1501
  new HumanMessage({ content: [{ type: 'text', text: 'Hello' }] }),
@@ -6,10 +6,11 @@ import {
6
6
  SystemMessage,
7
7
  MessageContentComplex,
8
8
  } from '@langchain/core/messages';
9
- import type { AnthropicMessage } from '@/types/messages';
10
9
  import type Anthropic from '@anthropic-ai/sdk';
11
- import { ContentTypes } from '@/common/enum';
10
+ import type { AnthropicMessage } from '@/types/messages';
12
11
  import { toLangChainContent } from './langchain';
12
+ import { ContentTypes } from '@/common/enum';
13
+ import { withMessageRole } from './format';
13
14
 
14
15
  type MessageWithContent = {
15
16
  content?: string | MessageContentComplex[];
@@ -56,19 +57,31 @@ function cloneMessage<T extends MessageWithContent>(
56
57
  const msgType = message.getType();
57
58
  switch (msgType) {
58
59
  case 'ai':
59
- return new AIMessage({
60
- ...baseParams,
61
- tool_calls: (message as unknown as AIMessage).tool_calls,
62
- }) as unknown as T;
60
+ return withMessageRole(
61
+ new AIMessage({
62
+ ...baseParams,
63
+ tool_calls: (message as unknown as AIMessage).tool_calls,
64
+ }),
65
+ 'assistant'
66
+ ) as unknown as T;
63
67
  case 'human':
64
- return new HumanMessage(baseParams) as unknown as T;
68
+ return withMessageRole(
69
+ new HumanMessage(baseParams),
70
+ 'user'
71
+ ) as unknown as T;
65
72
  case 'system':
66
- return new SystemMessage(baseParams) as unknown as T;
73
+ return withMessageRole(
74
+ new SystemMessage(baseParams),
75
+ 'system'
76
+ ) as unknown as T;
67
77
  case 'tool':
68
- return new ToolMessage({
69
- ...baseParams,
70
- tool_call_id: (message as unknown as ToolMessage).tool_call_id,
71
- }) as unknown as T;
78
+ return withMessageRole(
79
+ new ToolMessage({
80
+ ...baseParams,
81
+ tool_call_id: (message as unknown as ToolMessage).tool_call_id,
82
+ }),
83
+ 'tool'
84
+ ) as unknown as T;
72
85
  default:
73
86
  break;
74
87
  }
@@ -1,5 +1,5 @@
1
- import { ContentTypes } from '@/common';
2
1
  import type { BaseMessage } from '@langchain/core/messages';
2
+ import { ContentTypes } from '@/common';
3
3
 
4
4
  /**
5
5
  * Formats an array of messages for LangChain, making sure all content fields are strings
@@ -13,9 +13,9 @@
13
13
  */
14
14
 
15
15
  import { ToolMessage, type BaseMessage } from '@langchain/core/messages';
16
+ import type { ContextPruningSettings } from './contextPruningSettings';
16
17
  import type { ContextPruningConfig } from '@/types/graph';
17
18
  import type { TokenCounter } from '@/types/run';
18
- import type { ContextPruningSettings } from './contextPruningSettings';
19
19
  import { resolveContextPruningSettings } from './contextPruningSettings';
20
20
 
21
21
  /**
@@ -11,6 +11,7 @@ import type {
11
11
  MessageContent,
12
12
  MessageContentImageUrl,
13
13
  } from '@langchain/core/messages';
14
+ import type { RunnableConfig } from '@langchain/core/runnables';
14
15
  import type { ToolCall } from '@langchain/core/messages/tool';
15
16
  import type {
16
17
  BedrockReasoningContentText,
@@ -25,10 +26,10 @@ import type {
25
26
  TPayload,
26
27
  TMessage,
27
28
  } from '@/types';
28
- import type { RunnableConfig } from '@langchain/core/runnables';
29
- import { emitAgentLog } from '@/utils/events';
30
- import { Providers, ContentTypes, Constants } from '@/common';
29
+ import { normalizeAnthropicToolCallId } from '@/llm/anthropic/utils/message_inputs';
31
30
  import { toLangChainContent, toLangChainMessageFields } from './langchain';
31
+ import { Providers, ContentTypes, Constants } from '@/common';
32
+ import { emitAgentLog } from '@/utils/events';
32
33
 
33
34
  interface MediaMessageParams {
34
35
  message: {
@@ -106,6 +107,29 @@ interface FormatMessageParams {
106
107
  langChain?: boolean;
107
108
  }
108
109
 
110
+ export type LangChainMessageRole = 'system' | 'user' | 'assistant' | 'tool';
111
+
112
+ export type RoleBearingMessage<T extends BaseMessage = BaseMessage> = T & {
113
+ role: LangChainMessageRole;
114
+ };
115
+
116
+ export function withMessageRole<T extends BaseMessage>(
117
+ message: T,
118
+ role: LangChainMessageRole
119
+ ): RoleBearingMessage<T> {
120
+ const roleMessage = message as T & { role?: LangChainMessageRole };
121
+ if (roleMessage.role === role) {
122
+ return roleMessage as RoleBearingMessage<T>;
123
+ }
124
+ Object.defineProperty(roleMessage, 'role', {
125
+ value: role,
126
+ writable: true,
127
+ enumerable: false,
128
+ configurable: true,
129
+ });
130
+ return roleMessage as RoleBearingMessage<T>;
131
+ }
132
+
109
133
  interface FormattedMessage {
110
134
  role: string;
111
135
  content: string | MessageContentComplex[];
@@ -127,9 +151,9 @@ export const formatMessage = ({
127
151
  langChain = false,
128
152
  }: FormatMessageParams):
129
153
  | FormattedMessage
130
- | HumanMessage
131
- | AIMessage
132
- | SystemMessage => {
154
+ | RoleBearingMessage<HumanMessage>
155
+ | RoleBearingMessage<AIMessage>
156
+ | RoleBearingMessage<SystemMessage> => {
133
157
  // eslint-disable-next-line prefer-const
134
158
  let { role: _role, _name, sender, text, content: _content, lc_id } = message;
135
159
  if (lc_id && lc_id[2] && !langChain) {
@@ -217,7 +241,10 @@ export const formatMessage = ({
217
241
  return mediaMessage;
218
242
  }
219
243
 
220
- return new HumanMessage(toLangChainMessageFields(mediaMessage));
244
+ return withMessageRole(
245
+ new HumanMessage(toLangChainMessageFields(mediaMessage)),
246
+ 'user'
247
+ );
221
248
  }
222
249
 
223
250
  if (!langChain) {
@@ -225,11 +252,20 @@ export const formatMessage = ({
225
252
  }
226
253
 
227
254
  if (role === 'user') {
228
- return new HumanMessage(toLangChainMessageFields(formattedMessage));
255
+ return withMessageRole(
256
+ new HumanMessage(toLangChainMessageFields(formattedMessage)),
257
+ 'user'
258
+ );
229
259
  } else if (role === 'assistant') {
230
- return new AIMessage(toLangChainMessageFields(formattedMessage));
260
+ return withMessageRole(
261
+ new AIMessage(toLangChainMessageFields(formattedMessage)),
262
+ 'assistant'
263
+ );
231
264
  } else {
232
- return new SystemMessage(toLangChainMessageFields(formattedMessage));
265
+ return withMessageRole(
266
+ new SystemMessage(toLangChainMessageFields(formattedMessage)),
267
+ 'system'
268
+ );
233
269
  }
234
270
  };
235
271
 
@@ -243,14 +279,21 @@ export const formatMessage = ({
243
279
  export const formatLangChainMessages = (
244
280
  messages: Array<MessageInput>,
245
281
  formatOptions: Omit<FormatMessageParams, 'message' | 'langChain'>
246
- ): Array<HumanMessage | AIMessage | SystemMessage> => {
282
+ ): Array<
283
+ | RoleBearingMessage<HumanMessage>
284
+ | RoleBearingMessage<AIMessage>
285
+ | RoleBearingMessage<SystemMessage>
286
+ > => {
247
287
  return messages.map((msg) => {
248
288
  const formatted = formatMessage({
249
289
  ...formatOptions,
250
290
  message: msg,
251
291
  langChain: true,
252
292
  });
253
- return formatted as HumanMessage | AIMessage | SystemMessage;
293
+ return formatted as
294
+ | RoleBearingMessage<HumanMessage>
295
+ | RoleBearingMessage<AIMessage>
296
+ | RoleBearingMessage<SystemMessage>;
254
297
  });
255
298
  };
256
299
 
@@ -284,6 +327,7 @@ export const formatFromLangChain = (
284
327
  };
285
328
 
286
329
  interface FormatAssistantMessageOptions {
330
+ preserveUnpairedServerToolUses?: boolean;
287
331
  preserveReasoningContent?: boolean;
288
332
  provider?: Providers;
289
333
  }
@@ -371,6 +415,40 @@ function getToolUseId(part: MessageContentComplex): string | undefined {
371
415
  return part.tool_use_id;
372
416
  }
373
417
 
418
+ function isValidServerToolResult(part: MessageContentComplex): boolean {
419
+ const toolUseId = getToolUseId(part);
420
+ if (
421
+ toolUseId?.startsWith(Constants.ANTHROPIC_SERVER_TOOL_PREFIX) !== true ||
422
+ !('content' in part)
423
+ ) {
424
+ return false;
425
+ }
426
+ const { content } = part as { content?: unknown };
427
+ return (
428
+ Array.isArray(content) ||
429
+ (content != null &&
430
+ typeof content === 'object' &&
431
+ 'type' in content &&
432
+ (content as { type?: unknown }).type === 'web_search_tool_result_error')
433
+ );
434
+ }
435
+
436
+ function getToolCallId(part: MessageContentComplex): string | undefined {
437
+ if (part.type !== ContentTypes.TOOL_CALL) {
438
+ return undefined;
439
+ }
440
+ const id = part.tool_call?.id;
441
+ return typeof id === 'string' && id !== '' ? id : undefined;
442
+ }
443
+
444
+ function hasToolCallOutput(part: MessageContentComplex): boolean {
445
+ if (part.type !== ContentTypes.TOOL_CALL) {
446
+ return false;
447
+ }
448
+ const output = part.tool_call?.output;
449
+ return output != null && output !== '';
450
+ }
451
+
374
452
  /**
375
453
  * Helper function to format an assistant message
376
454
  * @param message The message to format
@@ -380,16 +458,20 @@ function getToolUseId(part: MessageContentComplex): string | undefined {
380
458
  function formatAssistantMessage(
381
459
  message: Partial<TMessage>,
382
460
  options?: FormatAssistantMessageOptions
383
- ): Array<AIMessage | ToolMessage> {
384
- const formattedMessages: Array<AIMessage | ToolMessage> = [];
461
+ ): Array<RoleBearingMessage<AIMessage> | RoleBearingMessage<ToolMessage>> {
462
+ const formattedMessages: Array<
463
+ RoleBearingMessage<AIMessage> | RoleBearingMessage<ToolMessage>
464
+ > = [];
385
465
  let currentContent: MessageContentComplex[] = [];
386
- let lastAIMessage: AIMessage | null = null;
466
+ let lastAIMessage: RoleBearingMessage<AIMessage> | null = null;
387
467
  let hasReasoning = false;
388
468
  let pendingReasoningContent = '';
389
469
  const emittedServerToolUseIds = new Set<string>();
390
470
  const pendingServerToolUses = new Map<string, MessageContentComplex>();
391
471
  const shouldPreserveReasoningContent =
392
472
  options?.preserveReasoningContent === true;
473
+ const serverToolResultIds = new Set<string>();
474
+ const preferredToolCallParts = new Map<string, MessageContentComplex>();
393
475
 
394
476
  const takePendingReasoningContent = (): string | undefined => {
395
477
  if (!shouldPreserveReasoningContent || !pendingReasoningContent) {
@@ -400,14 +482,19 @@ function formatAssistantMessage(
400
482
  return reasoningContent;
401
483
  };
402
484
 
403
- const createAIMessage = (content: MessageContent): AIMessage => {
485
+ const createAIMessage = (
486
+ content: MessageContent
487
+ ): RoleBearingMessage<AIMessage> => {
404
488
  const reasoningContent = takePendingReasoningContent();
405
- return new AIMessage({
406
- content,
407
- ...(reasoningContent != null && {
408
- additional_kwargs: { reasoning_content: reasoningContent },
489
+ return withMessageRole(
490
+ new AIMessage({
491
+ content,
492
+ ...(reasoningContent != null && {
493
+ additional_kwargs: { reasoning_content: reasoningContent },
494
+ }),
409
495
  }),
410
- });
496
+ 'assistant'
497
+ );
411
498
  };
412
499
 
413
500
  const attachPendingReasoningContent = (aiMessage: AIMessage): void => {
@@ -437,15 +524,52 @@ function formatAssistantMessage(
437
524
  MessageContentComplex | undefined | null
438
525
  >;
439
526
 
527
+ for (const part of contentParts) {
528
+ if (part == null) {
529
+ continue;
530
+ }
531
+ if (isValidServerToolResult(part)) {
532
+ serverToolResultIds.add(getToolUseId(part) ?? '');
533
+ }
534
+ if (options?.provider === Providers.ANTHROPIC) {
535
+ const toolCallId = getToolCallId(part);
536
+ if (toolCallId == null) {
537
+ continue;
538
+ }
539
+ const preferredPart = preferredToolCallParts.get(toolCallId);
540
+ if (
541
+ preferredPart == null ||
542
+ (!hasToolCallOutput(preferredPart) && hasToolCallOutput(part))
543
+ ) {
544
+ preferredToolCallParts.set(toolCallId, part);
545
+ }
546
+ }
547
+ }
548
+
440
549
  for (const part of contentParts) {
441
550
  if (part == null) {
442
551
  continue;
443
552
  }
444
553
  const toolUseId = getToolUseId(part);
445
554
  if (toolUseId != null) {
555
+ const isServerToolResult = isValidServerToolResult(part);
556
+ if (
557
+ toolUseId.startsWith(Constants.ANTHROPIC_SERVER_TOOL_PREFIX) &&
558
+ !isServerToolResult
559
+ ) {
560
+ continue;
561
+ }
446
562
  flushPendingServerToolUse(toolUseId);
563
+ if (isServerToolResult) {
564
+ currentContent.push(part);
565
+ continue;
566
+ }
447
567
  } else if (hasMeaningfulAssistantContent(part)) {
448
- pendingServerToolUses.clear();
568
+ for (const id of pendingServerToolUses.keys()) {
569
+ if (!serverToolResultIds.has(id)) {
570
+ pendingServerToolUses.delete(id);
571
+ }
572
+ }
449
573
  }
450
574
  if (part.type === ContentTypes.TEXT && part.tool_call_ids) {
451
575
  /*
@@ -453,6 +577,15 @@ function formatAssistantMessage(
453
577
  For Anthropic models, the "tool_calls" field on a message is only respected if content is a string.
454
578
  */
455
579
  if (currentContent.length > 0) {
580
+ if (
581
+ currentContent.some((content) => content.type !== ContentTypes.TEXT)
582
+ ) {
583
+ currentContent.push(part);
584
+ lastAIMessage = createAIMessage(toLangChainContent(currentContent));
585
+ formattedMessages.push(lastAIMessage);
586
+ currentContent = [];
587
+ continue;
588
+ }
456
589
  let content = currentContent.reduce((acc, curr) => {
457
590
  if (curr.type === ContentTypes.TEXT) {
458
591
  return `${acc}${getTextContent(curr)}\n`;
@@ -473,6 +606,14 @@ function formatAssistantMessage(
473
606
  if (part.tool_call == null) {
474
607
  continue;
475
608
  }
609
+ const toolCallId = getToolCallId(part);
610
+ if (
611
+ options?.provider === Providers.ANTHROPIC &&
612
+ toolCallId != null &&
613
+ preferredToolCallParts.get(toolCallId) !== part
614
+ ) {
615
+ continue;
616
+ }
476
617
 
477
618
  // Note: `tool_calls` list is defined when constructed by `AIMessage` class, and outputs should be excluded from it
478
619
  const {
@@ -494,6 +635,12 @@ function formatAssistantMessage(
494
635
  typeof _tool_call.id === 'string' &&
495
636
  _tool_call.id.startsWith(Constants.ANTHROPIC_SERVER_TOOL_PREFIX)
496
637
  ) {
638
+ if (
639
+ !serverToolResultIds.has(_tool_call.id) &&
640
+ options.preserveUnpairedServerToolUses !== true
641
+ ) {
642
+ continue;
643
+ }
497
644
  if (
498
645
  emittedServerToolUseIds.has(_tool_call.id) ||
499
646
  pendingServerToolUses.has(_tool_call.id)
@@ -531,17 +678,34 @@ function formatAssistantMessage(
531
678
  }
532
679
 
533
680
  tool_call.args = args;
534
- if (!lastAIMessage.tool_calls) {
535
- lastAIMessage.tool_calls = [];
681
+ if (
682
+ options?.provider === Providers.ANTHROPIC &&
683
+ Array.isArray(lastAIMessage.content)
684
+ ) {
685
+ const content = lastAIMessage.content as MessageContentComplex[];
686
+ content.push({
687
+ type: 'tool_use',
688
+ id: normalizeAnthropicToolCallId(tool_call.id ?? ''),
689
+ name: tool_call.name,
690
+ input: args,
691
+ } as MessageContentComplex);
692
+ lastAIMessage.content = content as MessageContent;
693
+ } else {
694
+ if (!lastAIMessage.tool_calls) {
695
+ lastAIMessage.tool_calls = [];
696
+ }
697
+ lastAIMessage.tool_calls.push(tool_call as ToolCall);
536
698
  }
537
- lastAIMessage.tool_calls.push(tool_call as ToolCall);
538
699
 
539
700
  formattedMessages.push(
540
- new ToolMessage({
541
- tool_call_id: tool_call.id ?? '',
542
- name: tool_call.name,
543
- content: output != null ? output : '',
544
- })
701
+ withMessageRole(
702
+ new ToolMessage({
703
+ tool_call_id: tool_call.id ?? '',
704
+ name: tool_call.name,
705
+ content: output != null ? output : '',
706
+ }),
707
+ 'tool'
708
+ )
545
709
  );
546
710
  } else if (
547
711
  part.type === ContentTypes.THINK ||
@@ -1007,7 +1171,12 @@ export const formatAgentMessages = (
1007
1171
  skills?: Map<string, string>,
1008
1172
  options?: FormatAgentMessagesOptions
1009
1173
  ): {
1010
- messages: Array<HumanMessage | AIMessage | SystemMessage | ToolMessage>;
1174
+ messages: Array<
1175
+ | RoleBearingMessage<HumanMessage>
1176
+ | RoleBearingMessage<AIMessage>
1177
+ | RoleBearingMessage<SystemMessage>
1178
+ | RoleBearingMessage<ToolMessage>
1179
+ >;
1011
1180
  indexTokenCountMap?: Record<number, number>;
1012
1181
  /** Cross-run summary extracted from the payload. Should be forwarded to the
1013
1182
  * agent run so it can be included in the system message via AgentContext. */
@@ -1022,7 +1191,10 @@ export const formatAgentMessages = (
1022
1191
  };
1023
1192
  } => {
1024
1193
  const messages: Array<
1025
- HumanMessage | AIMessage | SystemMessage | ToolMessage
1194
+ | RoleBearingMessage<HumanMessage>
1195
+ | RoleBearingMessage<AIMessage>
1196
+ | RoleBearingMessage<SystemMessage>
1197
+ | RoleBearingMessage<ToolMessage>
1026
1198
  > = [];
1027
1199
  // If indexTokenCountMap is provided, create a new map to track the updated indices
1028
1200
  const updatedIndexTokenCountMap: Record<number, number> = {};
@@ -1078,7 +1250,10 @@ export const formatAgentMessages = (
1078
1250
  const formattedMessage = formatMessage({
1079
1251
  message: message as MessageInput,
1080
1252
  langChain: true,
1081
- }) as HumanMessage | AIMessage | SystemMessage;
1253
+ }) as
1254
+ | RoleBearingMessage<HumanMessage>
1255
+ | RoleBearingMessage<AIMessage>
1256
+ | RoleBearingMessage<SystemMessage>;
1082
1257
  if (sourceMessageId != null && sourceMessageId !== '') {
1083
1258
  formattedMessage.id = sourceMessageId;
1084
1259
  }
@@ -1254,6 +1429,7 @@ export const formatAgentMessages = (
1254
1429
  }
1255
1430
 
1256
1431
  const formattedMessages = formatAssistantMessage(processedMessage, {
1432
+ preserveUnpairedServerToolUses: i === payload.length - 1,
1257
1433
  preserveReasoningContent: options?.provider === Providers.DEEPSEEK,
1258
1434
  provider: options?.provider,
1259
1435
  });
@@ -1273,15 +1449,18 @@ export const formatAgentMessages = (
1273
1449
  const body = skills?.get(skillName) ?? '';
1274
1450
  if (body) {
1275
1451
  messages.push(
1276
- new HumanMessage({
1277
- content: body,
1278
- additional_kwargs: {
1279
- role: 'user',
1280
- isMeta: true,
1281
- source: 'skill',
1282
- skillName,
1283
- },
1284
- })
1452
+ withMessageRole(
1453
+ new HumanMessage({
1454
+ content: body,
1455
+ additional_kwargs: {
1456
+ role: 'user',
1457
+ isMeta: true,
1458
+ source: 'skill',
1459
+ skillName,
1460
+ },
1461
+ }),
1462
+ 'user'
1463
+ )
1285
1464
  );
1286
1465
  }
1287
1466
  }
@@ -1721,7 +1900,12 @@ export function ensureThinkingBlockInMessages(
1721
1900
  'ensureThinkingBlockInMessages: injecting [Previous agent context] HumanMessage' +
1722
1901
  ` (${parts.length} msgs at index ${i}, no thinking block in chain)`
1723
1902
  );
1724
- result.push(new HumanMessage({ content: toLangChainContent(parts) }));
1903
+ result.push(
1904
+ withMessageRole(
1905
+ new HumanMessage({ content: toLangChainContent(parts) }),
1906
+ 'user'
1907
+ )
1908
+ );
1725
1909
  i = j;
1726
1910
  } else {
1727
1911
  // Keep the message as is