@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
@@ -2,12 +2,12 @@ import { expect } from '@jest/globals';
2
2
  import { HumanMessage } from '@langchain/core/messages';
3
3
  import type { UsageMetadata } from '@langchain/core/messages';
4
4
  import type { ClientOptions } from '@langchain/openai';
5
+ import type { ChatOpenRouterInput } from '@/llm/openrouter';
5
6
  import type * as t from '@/types';
6
7
  import { GraphEvents, Providers } from '@/common';
7
8
  import { AgentContext } from '../AgentContext';
8
9
  import { ModelEndHandler } from '@/events';
9
10
  import { Run } from '@/run';
10
- import type { ChatOpenRouterInput } from '@/llm/openrouter';
11
11
 
12
12
  type LivePromptCacheProvider =
13
13
  | Providers.ANTHROPIC
package/src/events.ts CHANGED
@@ -4,8 +4,8 @@ import type {
4
4
  BaseMessageFields,
5
5
  UsageMetadata,
6
6
  } from '@langchain/core/messages';
7
- import type { MultiAgentGraph, StandardGraph } from '@/graphs';
8
7
  import type { Logger } from 'winston';
8
+ import type { MultiAgentGraph, StandardGraph } from '@/graphs';
9
9
  import type * as t from '@/types';
10
10
  import { Constants } from '@/common';
11
11
 
@@ -11,6 +11,7 @@ import type {
11
11
  MessageContent,
12
12
  } from '@langchain/core/messages';
13
13
  import type { ToolCall } from '@langchain/core/messages/tool';
14
+ import type { HookRegistry } from '@/hooks';
14
15
  import type * as t from '@/types';
15
16
  import {
16
17
  formatAnthropicArtifactContent,
@@ -29,12 +30,16 @@ import {
29
30
  partitionAndMarkAnthropicToolCache,
30
31
  } from '@/messages';
31
32
  import {
32
- GraphNodeKeys,
33
- ContentTypes,
34
- GraphEvents,
35
- Providers,
36
- StepTypes,
37
- } from '@/common';
33
+ resolveLangfuseConfig,
34
+ shouldTraceToolNodeForLangfuse,
35
+ withLangfuseToolOutputTracingConfig,
36
+ } from '@/langfuseToolOutputTracing';
37
+ import {
38
+ createLangfuseHandler,
39
+ createLangfuseTraceMetadata,
40
+ disposeLangfuseHandler,
41
+ isLangfuseCallbackHandler,
42
+ } from '@/langfuse';
38
43
  import {
39
44
  resetIfNotEmpty,
40
45
  isAnthropicLike,
@@ -43,46 +48,41 @@ import {
43
48
  joinKeys,
44
49
  sleep,
45
50
  } from '@/utils';
46
- import { SubagentExecutor, resolveSubagentConfigs } from '@/tools/subagent';
47
- import { buildSubagentToolParams } from '@/tools/SubagentTool';
51
+ import {
52
+ GraphNodeKeys,
53
+ ContentTypes,
54
+ GraphEvents,
55
+ Providers,
56
+ StepTypes,
57
+ } from '@/common';
58
+ import {
59
+ appendCallbacks,
60
+ findCallback,
61
+ type CallbackEntry,
62
+ } from '@/utils/callbacks';
63
+ import { partitionAndMarkOpenRouterToolCache } from '@/llm/openrouter/toolCache';
48
64
  import { ToolNode as CustomToolNode, toolsCondition } from '@/tools/ToolNode';
65
+ import { createLocalCodingToolBundle } from '@/tools/local/LocalCodingTools';
66
+ import { SubagentExecutor, resolveSubagentConfigs } from '@/tools/subagent';
49
67
  import { ToolOutputReferenceRegistry } from '@/tools/toolOutputReferences';
68
+ import { partitionAndMarkBedrockToolCache } from '@/llm/bedrock/toolCache';
50
69
  import { safeDispatchCustomEvent, emitAgentLog } from '@/utils/events';
70
+ import { createCloudflareCodingToolBundle } from '@/tools/cloudflare';
51
71
  import { attemptInvoke, tryFallbackProviders } from '@/llm/invoke';
72
+ import { buildSubagentToolParams } from '@/tools/SubagentTool';
73
+ import { initializeLangfuseTracing } from '@/instrumentation';
52
74
  import { shouldTriggerSummarization } from '@/summarization';
75
+ import { resolveLocalToolsForBinding } from '@/tools/local';
53
76
  import { createSummarizeNode } from '@/summarization/node';
54
77
  import { messagesStateReducer } from '@/messages/reducer';
55
- import {
56
- appendCallbacks,
57
- findCallback,
58
- type CallbackEntry,
59
- } from '@/utils/callbacks';
60
78
  import { createSchemaOnlyTools } from '@/tools/schema';
61
79
  import { AgentContext } from '@/agents/AgentContext';
62
80
  import { createFakeStreamingLLM } from '@/llm/fake';
63
81
  import { handleToolCalls } from '@/tools/handlers';
64
- import { resolveLocalToolsForBinding } from '@/tools/local';
65
- import { createLocalCodingToolBundle } from '@/tools/local/LocalCodingTools';
66
- import { createCloudflareCodingToolBundle } from '@/tools/cloudflare';
67
82
  import { isThinkingEnabled } from '@/llm/request';
68
83
  import { initializeModel } from '@/llm/init';
69
- import {
70
- createLangfuseHandler,
71
- createLangfuseTraceMetadata,
72
- disposeLangfuseHandler,
73
- isLangfuseCallbackHandler,
74
- } from '@/langfuse';
75
- import { initializeLangfuseTracing } from '@/instrumentation';
76
- import {
77
- resolveLangfuseConfig,
78
- shouldTraceToolNodeForLangfuse,
79
- withLangfuseToolOutputTracingConfig,
80
- } from '@/langfuseToolOutputTracing';
81
84
  import { HandlerRegistry } from '@/events';
82
85
  import { ChatOpenAI } from '@/llm/openai';
83
- import { partitionAndMarkOpenRouterToolCache } from '@/llm/openrouter/toolCache';
84
- import { partitionAndMarkBedrockToolCache } from '@/llm/bedrock/toolCache';
85
- import type { HookRegistry } from '@/hooks';
86
86
 
87
87
  const { AGENT, TOOLS, SUMMARIZE } = GraphNodeKeys;
88
88
 
@@ -177,7 +177,42 @@ function getResponseReasoningContent({
177
177
  );
178
178
  }
179
179
 
180
- function getTextMessageDeltaContent(
180
+ function isTextMessageContentPart(
181
+ contentPart: MessageContent[number] | t.MessageContentComplex
182
+ ): boolean {
183
+ return (
184
+ typeof contentPart === 'object' &&
185
+ 'type' in contentPart &&
186
+ typeof contentPart.type === 'string' &&
187
+ contentPart.type.startsWith('text')
188
+ );
189
+ }
190
+
191
+ function isGoogleServerSideToolMessageContentPart(
192
+ contentPart: MessageContent[number] | t.MessageContentComplex
193
+ ): boolean {
194
+ return (
195
+ typeof contentPart === 'object' &&
196
+ 'type' in contentPart &&
197
+ (contentPart.type === 'toolCall' || contentPart.type === 'toolResponse')
198
+ );
199
+ }
200
+
201
+ function hasGoogleServerSideToolDeltaContent(
202
+ provider: Providers | undefined,
203
+ content: t.MessageDelta['content']
204
+ ): content is t.MessageContentComplex[] {
205
+ return (
206
+ isGoogleLike(provider) &&
207
+ Array.isArray(content) &&
208
+ content.some((contentPart) =>
209
+ isGoogleServerSideToolMessageContentPart(contentPart)
210
+ )
211
+ );
212
+ }
213
+
214
+ function getMessageDeltaContent(
215
+ provider: Providers | undefined,
181
216
  content: MessageContent | undefined
182
217
  ): t.MessageDelta['content'] | undefined {
183
218
  if (content == null) {
@@ -191,28 +226,142 @@ function getTextMessageDeltaContent(
191
226
  if (content.length === 0) {
192
227
  return undefined;
193
228
  }
194
- if (
195
- !content.every(
196
- (contentPart) =>
197
- typeof contentPart === 'object' &&
198
- 'type' in contentPart &&
199
- typeof contentPart.type === 'string' &&
200
- contentPart.type.startsWith('text')
201
- )
202
- ) {
229
+
230
+ const hasGoogleServerSideToolPart =
231
+ isGoogleLike(provider) &&
232
+ content.some((contentPart) =>
233
+ isGoogleServerSideToolMessageContentPart(contentPart)
234
+ );
235
+ if (content.every((contentPart) => isTextMessageContentPart(contentPart))) {
236
+ return content as t.MessageDelta['content'];
237
+ }
238
+ if (!hasGoogleServerSideToolPart) {
203
239
  return undefined;
204
240
  }
205
- return content as t.MessageDelta['content'];
241
+ const messageContent = content.filter(
242
+ (contentPart) =>
243
+ isTextMessageContentPart(contentPart) ||
244
+ isGoogleServerSideToolMessageContentPart(contentPart)
245
+ );
246
+ return messageContent.length > 0
247
+ ? (messageContent as t.MessageDelta['content'])
248
+ : undefined;
249
+ }
250
+
251
+ function hasTextDeltaContent(
252
+ content: t.MessageDelta['content'] | undefined
253
+ ): boolean {
254
+ if (content == null) {
255
+ return false;
256
+ }
257
+ return content.some((contentPart) => {
258
+ if (contentPart.type?.startsWith(ContentTypes.TEXT) !== true) {
259
+ return false;
260
+ }
261
+ const text = (contentPart as Partial<{ text: string }>).text;
262
+ return typeof text === 'string' && text !== '';
263
+ });
264
+ }
265
+
266
+ function hasReasoningDeltaContent(
267
+ content: t.ReasoningDelta['content'] | undefined
268
+ ): boolean {
269
+ if (content == null) {
270
+ return false;
271
+ }
272
+ return content.some(
273
+ (contentPart) =>
274
+ contentPart.type === ContentTypes.THINK && contentPart.think !== ''
275
+ );
276
+ }
277
+
278
+ function getCurrentStepIds({
279
+ graph,
280
+ metadata,
281
+ }: {
282
+ graph: Graph<t.BaseGraphState>;
283
+ metadata: Record<string, unknown>;
284
+ }): string[] {
285
+ const baseStepKey = graph.getStepBaseKey(metadata);
286
+ const currentStepIds: string[] = [];
287
+ for (const [stepKey, stepIds] of graph.stepKeyIds) {
288
+ if (stepKey !== baseStepKey && !stepKey.startsWith(`${baseStepKey}_`)) {
289
+ continue;
290
+ }
291
+ currentStepIds.push(...stepIds);
292
+ }
293
+ return currentStepIds;
294
+ }
295
+
296
+ function hasCurrentTextDeltaStep({
297
+ graph,
298
+ metadata,
299
+ }: {
300
+ graph: Graph<t.BaseGraphState>;
301
+ metadata: Record<string, unknown>;
302
+ }): boolean {
303
+ return getCurrentStepIds({ graph, metadata }).some((stepId) =>
304
+ graph.messageStepHasTextDeltas.has(stepId)
305
+ );
306
+ }
307
+
308
+ function hasCurrentReasoningDeltaStep({
309
+ graph,
310
+ metadata,
311
+ }: {
312
+ graph: Graph<t.BaseGraphState>;
313
+ metadata: Record<string, unknown>;
314
+ }): boolean {
315
+ return getCurrentStepIds({ graph, metadata }).some((stepId) =>
316
+ graph.reasoningStepHasDeltas.has(stepId)
317
+ );
318
+ }
319
+
320
+ function clearCurrentDeltaStepMarkers({
321
+ graph,
322
+ metadata,
323
+ }: {
324
+ graph: Graph<t.BaseGraphState>;
325
+ metadata: Record<string, unknown>;
326
+ }): void {
327
+ for (const stepId of getCurrentStepIds({ graph, metadata })) {
328
+ graph.messageStepHasTextDeltas.delete(stepId);
329
+ graph.reasoningStepHasDeltas.delete(stepId);
330
+ }
331
+ }
332
+
333
+ async function dispatchMessageCreationStep({
334
+ graph,
335
+ stepKey,
336
+ messageId,
337
+ metadata,
338
+ }: {
339
+ graph: Graph<t.BaseGraphState>;
340
+ stepKey: string;
341
+ messageId: string;
342
+ metadata: Record<string, unknown>;
343
+ }): Promise<string> {
344
+ await graph.dispatchRunStep(
345
+ stepKey,
346
+ {
347
+ type: StepTypes.MESSAGE_CREATION,
348
+ message_creation: { message_id: messageId },
349
+ },
350
+ metadata
351
+ );
352
+ return graph.getStepIdByKey(stepKey);
206
353
  }
207
354
 
208
355
  async function dispatchTextMessageContent({
209
356
  graph,
210
357
  stepKey,
358
+ provider,
211
359
  content,
212
360
  metadata,
213
361
  }: {
214
362
  graph: Graph<t.BaseGraphState>;
215
363
  stepKey: string;
364
+ provider?: Providers;
216
365
  content: t.MessageDelta['content'];
217
366
  metadata: Record<string, unknown>;
218
367
  }): Promise<boolean> {
@@ -220,15 +369,28 @@ async function dispatchTextMessageContent({
220
369
  if (!messageId) {
221
370
  return false;
222
371
  }
223
- await graph.dispatchRunStep(
372
+ if (hasGoogleServerSideToolDeltaContent(provider, content)) {
373
+ for (const contentPart of content) {
374
+ const stepId = await dispatchMessageCreationStep({
375
+ graph,
376
+ stepKey,
377
+ messageId,
378
+ metadata,
379
+ });
380
+ await graph.dispatchMessageDelta(
381
+ stepId,
382
+ { content: [contentPart] },
383
+ metadata
384
+ );
385
+ }
386
+ return true;
387
+ }
388
+ const stepId = await dispatchMessageCreationStep({
389
+ graph,
224
390
  stepKey,
225
- {
226
- type: StepTypes.MESSAGE_CREATION,
227
- message_creation: { message_id: messageId },
228
- },
229
- metadata
230
- );
231
- const stepId = graph.getStepIdByKey(stepKey);
391
+ messageId,
392
+ metadata,
393
+ });
232
394
  await graph.dispatchMessageDelta(stepId, { content }, metadata);
233
395
  return true;
234
396
  }
@@ -291,6 +453,29 @@ function markPostReasoningContent(agentContext: AgentContext): void {
291
453
  agentContext.reasoningTransitionCount++;
292
454
  }
293
455
 
456
+ function getDispatchableFinalReasoningContent({
457
+ agentContext,
458
+ responseReasoningContent,
459
+ hasStreamedTextDeltaStep,
460
+ hasStreamedReasoningDeltaStep,
461
+ }: {
462
+ agentContext: AgentContext;
463
+ responseReasoningContent: string | undefined;
464
+ hasStreamedTextDeltaStep: boolean;
465
+ hasStreamedReasoningDeltaStep: boolean;
466
+ }): string | undefined {
467
+ if (responseReasoningContent == null || hasStreamedReasoningDeltaStep) {
468
+ return undefined;
469
+ }
470
+ if (
471
+ agentContext.provider === Providers.OPENROUTER &&
472
+ hasStreamedTextDeltaStep
473
+ ) {
474
+ return undefined;
475
+ }
476
+ return responseReasoningContent;
477
+ }
478
+
294
479
  export abstract class Graph<
295
480
  T extends t.BaseGraphState = t.BaseGraphState,
296
481
  _TNodeName extends string = string,
@@ -309,6 +494,9 @@ export abstract class Graph<
309
494
  abstract getKeyList(
310
495
  metadata: Record<string, unknown> | undefined
311
496
  ): (string | number | undefined)[];
497
+ abstract getStepBaseKey(
498
+ metadata: Record<string, unknown> | undefined
499
+ ): string;
312
500
  abstract getStepKey(metadata: Record<string, unknown> | undefined): string;
313
501
  abstract checkKeyList(keyList: (string | number | undefined)[]): boolean;
314
502
  abstract getStepIdByKey(stepKey: string, index?: number): string;
@@ -340,6 +528,7 @@ export abstract class Graph<
340
528
  state: t.AgentSubgraphState,
341
529
  config?: RunnableConfig
342
530
  ) => Promise<Partial<t.AgentSubgraphState>>;
531
+ messageStepHasTextDeltas: Set<string> = new Set();
343
532
  messageStepHasToolCalls: Map<string, boolean> = new Map();
344
533
  messageIdsByStepKey: Map<string, string> = new Map();
345
534
  prelimMessageIdsByStepKey: Map<string, string> = new Map();
@@ -354,6 +543,7 @@ export abstract class Graph<
354
543
  * the same step are scoped to the active custom event dispatch.
355
544
  */
356
545
  handlerDispatchedStepIds: Set<string> = new Set();
546
+ reasoningStepHasDeltas: Set<string> = new Set();
357
547
  protected handlerDispatchedEventCounts: Map<string, number> = new Map();
358
548
  signal?: AbortSignal;
359
549
  /** Set of invoked tool call IDs from non-message run steps completed mid-run, if any */
@@ -429,6 +619,8 @@ export abstract class Graph<
429
619
  this.stepKeyIds = new Map();
430
620
  this.toolCallStepIds.clear();
431
621
  this.messageIdsByStepKey = new Map();
622
+ this.messageStepHasTextDeltas = new Set();
623
+ this.reasoningStepHasDeltas = new Set();
432
624
  this.messageStepHasToolCalls = new Map();
433
625
  this.prelimMessageIdsByStepKey = new Map();
434
626
  this.invokedToolIds = undefined;
@@ -705,6 +897,14 @@ export class StandardGraph extends Graph<t.BaseGraphState, t.GraphNode> {
705
897
  this.messageStepHasToolCalls,
706
898
  new Map()
707
899
  );
900
+ this.messageStepHasTextDeltas = resetIfNotEmpty(
901
+ this.messageStepHasTextDeltas,
902
+ new Set()
903
+ );
904
+ this.reasoningStepHasDeltas = resetIfNotEmpty(
905
+ this.reasoningStepHasDeltas,
906
+ new Set()
907
+ );
708
908
  this.prelimMessageIdsByStepKey = resetIfNotEmpty(
709
909
  this.prelimMessageIdsByStepKey,
710
910
  new Map()
@@ -764,6 +964,17 @@ export class StandardGraph extends Graph<t.BaseGraphState, t.GraphNode> {
764
964
  return agentContext;
765
965
  }
766
966
 
967
+ getStepBaseKey(metadata: Record<string, unknown> | undefined): string {
968
+ if (!metadata) return '';
969
+
970
+ const keyList = this.getInvocationKeyList(metadata);
971
+ if (this.checkKeyList(keyList)) {
972
+ throw new Error('Missing metadata');
973
+ }
974
+
975
+ return joinKeys(keyList);
976
+ }
977
+
767
978
  getStepKey(metadata: Record<string, unknown> | undefined): string {
768
979
  if (!metadata) return '';
769
980
 
@@ -810,6 +1021,33 @@ export class StandardGraph extends Graph<t.BaseGraphState, t.GraphNode> {
810
1021
  ): (string | number | undefined)[] {
811
1022
  if (!metadata) return [];
812
1023
 
1024
+ const keyList = this.getInvocationKeyList(metadata);
1025
+ const agentContext = this.getAgentContext(metadata);
1026
+ if (
1027
+ agentContext.currentTokenType === ContentTypes.THINK ||
1028
+ agentContext.currentTokenType === 'think_and_text'
1029
+ ) {
1030
+ keyList.push('reasoning');
1031
+ } else if (agentContext.tokenTypeSwitch === 'content') {
1032
+ keyList.push(`post-reasoning-${agentContext.reasoningTransitionCount}`);
1033
+ }
1034
+
1035
+ return keyList;
1036
+ }
1037
+
1038
+ private getInvocationKeyList(
1039
+ metadata: Record<string, unknown>
1040
+ ): (string | number | undefined)[] {
1041
+ const keyList = this.getBaseKeyList(metadata);
1042
+ if (this.invokedToolIds != null && this.invokedToolIds.size > 0) {
1043
+ keyList.push(this.invokedToolIds.size + '');
1044
+ }
1045
+ return keyList;
1046
+ }
1047
+
1048
+ private getBaseKeyList(
1049
+ metadata: Record<string, unknown>
1050
+ ): (string | number | undefined)[] {
813
1051
  const configurable = this.config?.configurable;
814
1052
  const runId =
815
1053
  (metadata.run_id as string | undefined) ??
@@ -831,20 +1069,6 @@ export class StandardGraph extends Graph<t.BaseGraphState, t.GraphNode> {
831
1069
  checkpointNs,
832
1070
  ];
833
1071
 
834
- const agentContext = this.getAgentContext(metadata);
835
- if (
836
- agentContext.currentTokenType === ContentTypes.THINK ||
837
- agentContext.currentTokenType === 'think_and_text'
838
- ) {
839
- keyList.push('reasoning');
840
- } else if (agentContext.tokenTypeSwitch === 'content') {
841
- keyList.push(`post-reasoning-${agentContext.reasoningTransitionCount}`);
842
- }
843
-
844
- if (this.invokedToolIds != null && this.invokedToolIds.size > 0) {
845
- keyList.push(this.invokedToolIds.size + '');
846
- }
847
-
848
1072
  return keyList;
849
1073
  }
850
1074
 
@@ -994,6 +1218,7 @@ export class StandardGraph extends Graph<t.BaseGraphState, t.GraphNode> {
994
1218
  sessions: this.sessions,
995
1219
  toolDefinitions: toolDefMap,
996
1220
  agentId: agentContext?.agentId,
1221
+ executingAgentId: agentContext?.agentId,
997
1222
  toolCallStepIds: this.toolCallStepIds,
998
1223
  toolRegistry: agentContext?.toolRegistry,
999
1224
  hookRegistry: this.hookRegistry,
@@ -1038,6 +1263,10 @@ export class StandardGraph extends Graph<t.BaseGraphState, t.GraphNode> {
1038
1263
  trace: traceToolNode,
1039
1264
  runLangfuse: this.langfuse,
1040
1265
  agentLangfuse: agentContext?.langfuse,
1266
+ // `agentId` is intentionally left unset on this path (it is the
1267
+ // subagent-scope marker); `executingAgentId` always identifies the owning
1268
+ // agent so hooks can attribute the batch even at the top level.
1269
+ executingAgentId: agentContext?.agentId,
1041
1270
  toolCallStepIds: this.toolCallStepIds,
1042
1271
  errorHandler: (data, metadata): Promise<void> =>
1043
1272
  StandardGraph.handleToolCallErrorStatic(this, data, metadata),
@@ -1610,6 +1839,7 @@ export class StandardGraph extends Graph<t.BaseGraphState, t.GraphNode> {
1610
1839
  };
1611
1840
  }
1612
1841
  }
1842
+ const metadata = config.metadata as Record<string, unknown>;
1613
1843
 
1614
1844
  try {
1615
1845
  result = await withLangfuseToolOutputTracingConfig(
@@ -1627,6 +1857,10 @@ export class StandardGraph extends Graph<t.BaseGraphState, t.GraphNode> {
1627
1857
  agentContext.langfuse
1628
1858
  );
1629
1859
  } catch (primaryError) {
1860
+ clearCurrentDeltaStepMarkers({
1861
+ graph: this,
1862
+ metadata,
1863
+ });
1630
1864
  result = await withLangfuseToolOutputTracingConfig(
1631
1865
  this.langfuse,
1632
1866
  () =>
@@ -1667,32 +1901,48 @@ export class StandardGraph extends Graph<t.BaseGraphState, t.GraphNode> {
1667
1901
  const toolCalls = (responseMessage as AIMessageChunk | undefined)
1668
1902
  ?.tool_calls;
1669
1903
  const hasToolCalls = Array.isArray(toolCalls) && toolCalls.length > 0;
1670
- const metadata = config.metadata as Record<string, unknown>;
1671
1904
  const responseReasoningContent = getResponseReasoningContent({
1672
1905
  responseMessage: responseMessage as Partial<AIMessageChunk> | undefined,
1673
1906
  reasoningKey: agentContext.reasoningKey,
1674
1907
  });
1675
- const textMessageContent = getTextMessageDeltaContent(
1908
+ const textMessageContent = getMessageDeltaContent(
1909
+ agentContext.provider,
1676
1910
  responseMessage?.content as MessageContent | undefined
1677
1911
  );
1912
+ const hasStreamedTextDeltaStep = hasCurrentTextDeltaStep({
1913
+ graph: this,
1914
+ metadata,
1915
+ });
1916
+ const hasStreamedReasoningDeltaStep = hasCurrentReasoningDeltaStep({
1917
+ graph: this,
1918
+ metadata,
1919
+ });
1920
+ const dispatchableFinalReasoningContent =
1921
+ getDispatchableFinalReasoningContent({
1922
+ agentContext,
1923
+ responseReasoningContent,
1924
+ hasStreamedTextDeltaStep,
1925
+ hasStreamedReasoningDeltaStep,
1926
+ });
1678
1927
 
1679
1928
  if (hasToolCalls) {
1680
1929
  const dispatchedReasoning =
1681
- responseReasoningContent != null &&
1930
+ dispatchableFinalReasoningContent != null &&
1682
1931
  (await dispatchReasoningContent({
1683
1932
  graph: this,
1684
1933
  agentContext,
1685
- reasoningContent: responseReasoningContent,
1934
+ reasoningContent: dispatchableFinalReasoningContent,
1686
1935
  metadata,
1687
1936
  }));
1688
1937
  if (dispatchedReasoning) {
1689
1938
  markPostReasoningContent(agentContext);
1690
1939
  }
1691
- if (textMessageContent != null) {
1940
+ if (textMessageContent != null && !hasStreamedTextDeltaStep) {
1692
1941
  const stepKey = this.getStepKey(metadata);
1693
1942
  const dispatchedText = await dispatchTextMessageContent({
1694
1943
  graph: this,
1695
1944
  stepKey,
1945
+ provider: agentContext.provider,
1696
1946
  content: textMessageContent,
1697
1947
  metadata,
1698
1948
  });
@@ -1711,21 +1961,22 @@ export class StandardGraph extends Graph<t.BaseGraphState, t.GraphNode> {
1711
1961
  */
1712
1962
  if (!hasToolCalls && responseMessage != null) {
1713
1963
  const dispatchedReasoning =
1714
- responseReasoningContent != null &&
1964
+ dispatchableFinalReasoningContent != null &&
1715
1965
  (await dispatchReasoningContent({
1716
1966
  graph: this,
1717
1967
  agentContext,
1718
- reasoningContent: responseReasoningContent,
1968
+ reasoningContent: dispatchableFinalReasoningContent,
1719
1969
  metadata,
1720
1970
  }));
1721
1971
  if (dispatchedReasoning && textMessageContent != null) {
1722
1972
  markPostReasoningContent(agentContext);
1723
1973
  }
1724
- if (textMessageContent != null) {
1974
+ if (textMessageContent != null && !hasStreamedTextDeltaStep) {
1725
1975
  const stepKey = this.getStepKey(metadata);
1726
1976
  await dispatchTextMessageContent({
1727
1977
  graph: this,
1728
1978
  stepKey,
1979
+ provider: agentContext.provider,
1729
1980
  content: textMessageContent,
1730
1981
  metadata,
1731
1982
  });
@@ -2294,6 +2545,9 @@ export class StandardGraph extends Graph<t.BaseGraphState, t.GraphNode> {
2294
2545
  id,
2295
2546
  delta,
2296
2547
  };
2548
+ if (hasTextDeltaContent(delta.content)) {
2549
+ this.messageStepHasTextDeltas.add(id);
2550
+ }
2297
2551
  const handler = this.handlerRegistry?.getHandler(
2298
2552
  GraphEvents.ON_MESSAGE_DELTA
2299
2553
  );
@@ -2332,6 +2586,9 @@ export class StandardGraph extends Graph<t.BaseGraphState, t.GraphNode> {
2332
2586
  id: stepId,
2333
2587
  delta,
2334
2588
  };
2589
+ if (hasReasoningDeltaContent(delta.content)) {
2590
+ this.reasoningStepHasDeltas.add(stepId);
2591
+ }
2335
2592
  const handler = this.handlerRegistry?.getHandler(
2336
2593
  GraphEvents.ON_REASONING_DELTA
2337
2594
  );
@@ -15,8 +15,8 @@ import {
15
15
  getCurrentTaskInput,
16
16
  messagesStateReducer,
17
17
  } from '@langchain/langgraph';
18
- import type { LangGraphRunnableConfig } from '@langchain/langgraph';
19
18
  import type { BaseMessage, AIMessageChunk } from '@langchain/core/messages';
19
+ import type { LangGraphRunnableConfig } from '@langchain/langgraph';
20
20
  import type { ToolRunnableConfig } from '@langchain/core/tools';
21
21
  import type * as t from '@/types';
22
22
  import { StandardGraph } from './Graph';