@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
@@ -1,6 +1,6 @@
1
- import { ContentTypes } from '@/common';
2
- import { labelContentByAgent } from './format';
3
1
  import type { MessageContentComplex, ToolCallContent } from '@/types';
2
+ import { labelContentByAgent } from './format';
3
+ import { ContentTypes } from '@/common';
4
4
 
5
5
  /**
6
6
  * Type guard to check if content is ToolCallContent
@@ -9,8 +9,8 @@ import type {
9
9
  MessageContentComplex,
10
10
  ReasoningContentText,
11
11
  } from '@/types/stream';
12
- import type { TokenCounter } from '@/types/run';
13
12
  import type { ContextPruningConfig } from '@/types/graph';
13
+ import type { TokenCounter } from '@/types/run';
14
14
  import {
15
15
  calculateMaxToolResultChars,
16
16
  truncateToolResultContent,
@@ -1,10 +1,10 @@
1
+ import { v4 } from 'uuid';
1
2
  import {
2
3
  BaseMessage,
3
4
  RemoveMessage,
4
5
  BaseMessageLike,
5
6
  coerceMessageLikeToMessage,
6
7
  } from '@langchain/core/messages';
7
- import { v4 } from 'uuid';
8
8
 
9
9
  export const REMOVE_ALL_MESSAGES = '__remove_all__';
10
10
 
@@ -1,8 +1,8 @@
1
1
  // src/messages/toolDiscovery.ts
2
2
  import { AIMessageChunk, ToolMessage } from '@langchain/core/messages';
3
3
  import type { BaseMessage } from '@langchain/core/messages';
4
- import { Constants } from '@/common';
5
4
  import { findLastIndex } from './core';
5
+ import { Constants } from '@/common';
6
6
 
7
7
  type ToolSearchArtifact = {
8
8
  tool_references?: Array<{ tool_name: string }>;
@@ -1,11 +1,11 @@
1
- import { GraphEvents } from '@/common';
1
+ import type * as t from '@/types';
2
2
  import {
3
3
  createChatCompletionChunk,
4
4
  createOpenAIHandlers,
5
5
  createOpenAIStreamTracker,
6
6
  sendOpenAIFinalChunk,
7
7
  } from '@/openai';
8
- import type * as t from '@/types';
8
+ import { GraphEvents } from '@/common';
9
9
 
10
10
  describe('OpenAI-compatible adapters', () => {
11
11
  it('creates chunks and streams message deltas as SSE data', async () => {
@@ -1,6 +1,6 @@
1
- import { GraphEvents } from '@/common';
2
1
  import type { UsageMetadata } from '@langchain/core/messages';
3
2
  import type * as t from '@/types';
3
+ import { GraphEvents } from '@/common';
4
4
 
5
5
  export interface OpenAICompatibleWriter {
6
6
  write(data: string): void | Promise<void>;
@@ -1,11 +1,11 @@
1
- import { GraphEvents } from '@/common';
1
+ import type * as t from '@/types';
2
2
  import {
3
3
  buildResponse,
4
4
  createResponseTracker,
5
5
  createResponsesEventHandlers,
6
6
  emitResponseCompleted,
7
7
  } from '@/responses';
8
- import type * as t from '@/types';
8
+ import { GraphEvents } from '@/common';
9
9
 
10
10
  describe('Responses-compatible adapters', () => {
11
11
  it('streams semantic response events through a generic writer', async () => {
@@ -1,6 +1,6 @@
1
- import { GraphEvents } from '@/common';
2
1
  import type { UsageMetadata } from '@langchain/core/messages';
3
2
  import type * as t from '@/types';
3
+ import { GraphEvents } from '@/common';
4
4
 
5
5
  export interface ResponsesCompatibleWriter {
6
6
  write(data: string): void | Promise<void>;
package/src/run.ts CHANGED
@@ -1,52 +1,56 @@
1
1
  // src/run.ts
2
- import { initializeLangfuseTracing } from './instrumentation';
2
+ import { HumanMessage } from '@langchain/core/messages';
3
3
  import { PromptTemplate } from '@langchain/core/prompts';
4
4
  import { RunnableLambda } from '@langchain/core/runnables';
5
5
  import { AzureChatOpenAI, ChatOpenAI } from '@langchain/openai';
6
+ import { BaseCallbackHandler } from '@langchain/core/callbacks/base';
6
7
  import {
7
8
  Command,
8
9
  INTERRUPT,
9
10
  MemorySaver,
10
11
  isInterrupted,
11
12
  } from '@langchain/langgraph';
12
- import { HumanMessage } from '@langchain/core/messages';
13
- import { BaseCallbackHandler } from '@langchain/core/callbacks/base';
14
13
  import type {
15
14
  MessageContentComplex,
16
15
  BaseMessage,
17
16
  } from '@langchain/core/messages';
18
17
  import type { StringPromptValue } from '@langchain/core/prompt_values';
19
18
  import type { RunnableConfig } from '@langchain/core/runnables';
19
+ import type { HookRegistry } from '@/hooks';
20
20
  import type * as t from '@/types';
21
- import {
22
- createCompletionTitleRunnable,
23
- createTitleRunnable,
24
- } from '@/utils/title';
25
- import { createTokenCounter, encodingForModel } from '@/utils/tokens';
26
- import { GraphEvents, Callback, TitleMethod } from '@/common';
27
- import { MultiAgentGraph } from '@/graphs/MultiAgentGraph';
28
- import { StandardGraph } from '@/graphs/Graph';
29
- import { initializeModel } from '@/llm/init';
30
- import { HandlerRegistry } from '@/events';
31
- import { executeHooks } from '@/hooks';
32
- import { isOpenAILike } from '@/utils/llm';
33
- import {
34
- appendCallbacks,
35
- findCallback,
36
- type CallbackEntry,
37
- } from '@/utils/callbacks';
38
21
  import {
39
22
  createLangfuseTraceMetadata,
40
23
  createLangfuseHandler,
41
24
  disposeLangfuseHandler,
42
25
  getLangfuseTraceName,
43
26
  isLangfuseCallbackHandler,
27
+ withLangfuseAttributes,
44
28
  } from '@/langfuse';
45
29
  import {
46
30
  resolveLangfuseConfig,
47
31
  withLangfuseToolOutputTracingConfig,
48
32
  } from '@/langfuseToolOutputTracing';
49
- import type { HookRegistry } from '@/hooks';
33
+ import {
34
+ appendCallbacks,
35
+ findCallback,
36
+ type CallbackEntry,
37
+ } from '@/utils/callbacks';
38
+ import {
39
+ createCompletionTitleRunnable,
40
+ createTitleRunnable,
41
+ } from '@/utils/title';
42
+ import {
43
+ initializeLangfuseTracing,
44
+ runWithTraceIdSeed,
45
+ } from './instrumentation';
46
+ import { createTokenCounter, encodingForModel } from '@/utils/tokens';
47
+ import { GraphEvents, Callback, TitleMethod } from '@/common';
48
+ import { MultiAgentGraph } from '@/graphs/MultiAgentGraph';
49
+ import { StandardGraph } from '@/graphs/Graph';
50
+ import { initializeModel } from '@/llm/init';
51
+ import { HandlerRegistry } from '@/events';
52
+ import { isOpenAILike } from '@/utils/llm';
53
+ import { executeHooks } from '@/hooks';
50
54
 
51
55
  export const defaultOmitOptions = new Set([
52
56
  'stream',
@@ -552,9 +556,7 @@ export class Run<_T extends t.BaseGraphState> {
552
556
  }
553
557
 
554
558
  private shouldClearHookSession(streamThrew: boolean): boolean {
555
- return (
556
- this._interrupt == null || this._haltedReason != null || streamThrew
557
- );
559
+ return this._interrupt == null || this._haltedReason != null || streamThrew;
558
560
  }
559
561
 
560
562
  private isAwaitingResume(streamThrew: boolean): boolean {
@@ -584,9 +586,7 @@ export class Run<_T extends t.BaseGraphState> {
584
586
  private getStreamToolOutputTracingLangfuseConfig(
585
587
  graph: StandardGraph | MultiAgentGraph
586
588
  ): t.LangfuseConfig | undefined {
587
- const toolOutputTracingConfigs = Array.from(
588
- graph.agentContexts.values()
589
- )
589
+ const toolOutputTracingConfigs = Array.from(graph.agentContexts.values())
590
590
  .map((context) => {
591
591
  return resolveLangfuseConfig(this.langfuse, context.langfuse)
592
592
  ?.toolOutputTracing;
@@ -732,6 +732,7 @@ export class Run<_T extends t.BaseGraphState> {
732
732
  agentId: graph.defaultAgentId,
733
733
  agentName: primaryContext?.name,
734
734
  });
735
+ const traceName = config.runName ?? getLangfuseTraceName(traceMetadata);
735
736
  const streamLangfuseConfig = this.getStreamLangfuseConfig(graph);
736
737
  initializeLangfuseTracing(streamLangfuseConfig);
737
738
  const langfuseHandler = createLangfuseHandler({
@@ -742,7 +743,7 @@ export class Run<_T extends t.BaseGraphState> {
742
743
  tags: ['librechat', 'agent'],
743
744
  });
744
745
  if (langfuseHandler != null) {
745
- config.runName = config.runName ?? getLangfuseTraceName(traceMetadata);
746
+ config.runName = traceName;
746
747
  config.callbacks = appendCallbacks(config.callbacks, [langfuseHandler]);
747
748
  }
748
749
 
@@ -906,10 +907,30 @@ export class Run<_T extends t.BaseGraphState> {
906
907
  };
907
908
 
908
909
  try {
909
- await withLangfuseToolOutputTracingConfig(
910
- streamLangfuseConfig,
911
- consumeStream,
912
- this.getStreamToolOutputTracingLangfuseConfig(graph)
910
+ // When opted in, seed the root trace id from this run's id so feedback /
911
+ // other external signals can be attached to the trace later without a
912
+ // lookup (see SeededTraceIdGenerator in ./instrumentation).
913
+ await runWithTraceIdSeed(
914
+ streamLangfuseConfig?.deterministicTraceId === true
915
+ ? this.id
916
+ : undefined,
917
+ () =>
918
+ withLangfuseToolOutputTracingConfig(
919
+ streamLangfuseConfig,
920
+ () =>
921
+ withLangfuseAttributes(
922
+ {
923
+ langfuse: streamLangfuseConfig,
924
+ userId,
925
+ sessionId,
926
+ traceName,
927
+ traceMetadata,
928
+ tags: ['librechat', 'agent'],
929
+ },
930
+ consumeStream
931
+ ),
932
+ this.getStreamToolOutputTracingLangfuseConfig(graph)
933
+ )
913
934
  );
914
935
  } catch (err) {
915
936
  streamThrew = true;
@@ -1253,6 +1274,9 @@ export class Run<_T extends t.BaseGraphState> {
1253
1274
  titlePromptTemplate,
1254
1275
  }: t.RunTitleOptions): Promise<{ language?: string; title?: string }> {
1255
1276
  let titleLangfuseHandler: CallbackEntry | undefined;
1277
+ let titleLangfuseConfig: t.LangfuseConfig | undefined;
1278
+ let titleUserId: string | undefined;
1279
+ let titleSessionId: string | undefined;
1256
1280
  const titleContext =
1257
1281
  this.Graph == null
1258
1282
  ? undefined
@@ -1264,23 +1288,23 @@ export class Run<_T extends t.BaseGraphState> {
1264
1288
  const titleRunName = getLangfuseTraceName(traceMetadata, 'LibreChat Title');
1265
1289
 
1266
1290
  if (chainOptions != null) {
1267
- const userId =
1291
+ titleUserId =
1268
1292
  typeof chainOptions.configurable?.user_id === 'string'
1269
1293
  ? chainOptions.configurable.user_id
1270
1294
  : undefined;
1271
- const sessionId =
1295
+ titleSessionId =
1272
1296
  typeof chainOptions.configurable?.thread_id === 'string'
1273
1297
  ? chainOptions.configurable.thread_id
1274
1298
  : undefined;
1275
- const titleLangfuseConfig = resolveLangfuseConfig(
1299
+ titleLangfuseConfig = resolveLangfuseConfig(
1276
1300
  this.langfuse,
1277
1301
  titleContext?.langfuse
1278
1302
  );
1279
1303
  initializeLangfuseTracing(titleLangfuseConfig);
1280
1304
  titleLangfuseHandler = createLangfuseHandler({
1281
1305
  langfuse: titleLangfuseConfig,
1282
- userId,
1283
- sessionId,
1306
+ userId: titleUserId,
1307
+ sessionId: titleSessionId,
1284
1308
  traceMetadata,
1285
1309
  tags: ['librechat', 'title'],
1286
1310
  });
@@ -1354,15 +1378,30 @@ export class Run<_T extends t.BaseGraphState> {
1354
1378
  runName: chainOptions?.runName ?? titleRunName,
1355
1379
  });
1356
1380
 
1381
+ const invokeTitleChain = (
1382
+ runtimeConfig: Partial<RunnableConfig>
1383
+ ): Promise<{ language?: string; title?: string }> =>
1384
+ withLangfuseAttributes(
1385
+ {
1386
+ langfuse: titleLangfuseConfig,
1387
+ userId: titleUserId,
1388
+ sessionId: titleSessionId,
1389
+ traceName: runtimeConfig.runName ?? titleRunName,
1390
+ traceMetadata,
1391
+ tags: ['librechat', 'title'],
1392
+ },
1393
+ () =>
1394
+ fullChain.invoke(
1395
+ { input: inputText, output: response },
1396
+ runtimeConfig
1397
+ )
1398
+ );
1399
+
1357
1400
  try {
1358
1401
  try {
1359
1402
  return await withLangfuseToolOutputTracingConfig(
1360
1403
  this.langfuse,
1361
- () =>
1362
- fullChain.invoke(
1363
- { input: inputText, output: response },
1364
- invokeConfig
1365
- ),
1404
+ () => invokeTitleChain(invokeConfig),
1366
1405
  titleContext?.langfuse
1367
1406
  );
1368
1407
  } catch (_e) {
@@ -1378,11 +1417,7 @@ export class Run<_T extends t.BaseGraphState> {
1378
1417
  });
1379
1418
  return await withLangfuseToolOutputTracingConfig(
1380
1419
  this.langfuse,
1381
- () =>
1382
- fullChain.invoke(
1383
- { input: inputText, output: response },
1384
- safeConfig as Partial<RunnableConfig>
1385
- ),
1420
+ () => invokeTitleChain(safeConfig as Partial<RunnableConfig>),
1386
1421
  titleContext?.langfuse
1387
1422
  );
1388
1423
  }
@@ -1,11 +1,10 @@
1
1
  import { MemorySaver } from '@langchain/langgraph';
2
2
  import { HumanMessage, BaseMessage } from '@langchain/core/messages';
3
- import type { RunnableConfig } from '@langchain/core/runnables';
4
3
  import type {
5
4
  BaseCheckpointSaver,
6
5
  CheckpointTuple,
7
6
  } from '@langchain/langgraph';
8
- import type { HookRegistry } from '@/hooks';
7
+ import type { RunnableConfig } from '@langchain/core/runnables';
9
8
  import type {
10
9
  AgentSessionConfig,
11
10
  AgentSessionCheckpointing,
@@ -22,15 +21,16 @@ import type {
22
21
  SessionEntry,
23
22
  SessionForkOptions,
24
23
  } from './types';
24
+ import type { HookRegistry } from '@/hooks';
25
25
  import type * as t from '@/types';
26
+ import { deserializeMessage } from './messageSerialization';
27
+ import { createSummarizeNode } from '@/summarization/node';
28
+ import { JsonlSessionStore } from './JsonlSessionStore';
26
29
  import { AgentContext } from '@/agents/AgentContext';
27
30
  import { ContentTypes, GraphEvents } from '@/common';
28
- import { Run } from '@/run';
29
31
  import { createRunId, createSessionId } from './ids';
30
- import { deserializeMessage } from './messageSerialization';
31
- import { JsonlSessionStore } from './JsonlSessionStore';
32
32
  import { createRunHandlers } from './handlers';
33
- import { createSummarizeNode } from '@/summarization/node';
33
+ import { Run } from '@/run';
34
34
 
35
35
  function isBaseMessage(value: unknown): value is BaseMessage {
36
36
  return (
@@ -1,5 +1,6 @@
1
1
  import { homedir } from 'os';
2
2
  import { createHash } from 'crypto';
3
+ import { SystemMessage } from '@langchain/core/messages';
3
4
  import { basename, dirname, isAbsolute, join, resolve } from 'path';
4
5
  import {
5
6
  access,
@@ -10,6 +11,7 @@ import {
10
11
  stat,
11
12
  writeFile,
12
13
  } from 'fs/promises';
14
+ import type { BaseMessage } from '@langchain/core/messages';
13
15
  import type {
14
16
  CreateSessionFileOptions,
15
17
  SessionBranchOptions,
@@ -26,15 +28,13 @@ import type {
26
28
  SessionStateEntry,
27
29
  SessionTreeNode,
28
30
  } from './types';
29
- import type { BaseMessage } from '@langchain/core/messages';
30
- import { SystemMessage } from '@langchain/core/messages';
31
- import { createEntryId, createSessionId, createTimestamp } from './ids';
32
31
  import {
33
32
  deserializeMessage,
34
33
  getMessageRole,
35
34
  serializeMessage,
36
35
  toJsonValue,
37
36
  } from './messageSerialization';
37
+ import { createEntryId, createSessionId, createTimestamp } from './ids';
38
38
 
39
39
  const SESSION_VERSION = 1;
40
40
  const DEFAULT_SESSION_ROOT = join(
@@ -1,19 +1,19 @@
1
- import { mkdtemp, readFile, rm, writeFile } from 'fs/promises';
2
- import { dirname, join } from 'path';
3
1
  import { tmpdir } from 'os';
2
+ import { dirname, join } from 'path';
3
+ import { MemorySaver } from '@langchain/langgraph';
4
+ import { mkdtemp, readFile, rm, writeFile } from 'fs/promises';
4
5
  import {
5
6
  AIMessage,
6
7
  HumanMessage,
7
8
  RemoveMessage,
8
9
  } from '@langchain/core/messages';
9
- import { MemorySaver } from '@langchain/langgraph';
10
- import type { BaseMessage } from '@langchain/core/messages';
11
10
  import type { Checkpoint, CheckpointMetadata } from '@langchain/langgraph';
11
+ import type { BaseMessage } from '@langchain/core/messages';
12
+ import type * as t from '@/types';
12
13
  import { JsonlSessionStore, createAgentSession } from '@/session';
13
14
  import { toJsonValue } from '@/session/messageSerialization';
14
15
  import * as providers from '@/llm/providers';
15
16
  import { GraphEvents } from '@/common';
16
- import type * as t from '@/types';
17
17
  import { Run } from '@/run';
18
18
 
19
19
  type MockRun = {
@@ -1,8 +1,8 @@
1
+ import type { AgentSessionStreamEvent } from '@/session';
2
+ import type * as t from '@/types';
1
3
  import { ContentTypes, GraphEvents, StepTypes } from '@/common';
2
4
  import { composeEventHandlers } from '@/events';
3
5
  import { createRunHandlers } from '@/session';
4
- import type { AgentSessionStreamEvent } from '@/session';
5
- import type * as t from '@/types';
6
6
 
7
7
  describe('createRunHandlers', () => {
8
8
  it('emits live session events through the same graph handlers before user handlers', async () => {
@@ -1,15 +1,15 @@
1
1
  import type { UsageMetadata } from '@langchain/core/messages';
2
- import { GraphEvents } from '@/common';
3
- import { ModelEndHandler, ToolEndHandler } from '@/events';
4
- import { createContentAggregator } from '@/stream';
5
- import type * as t from '@/types';
6
2
  import type {
7
3
  AgentSessionHandlersResult,
8
4
  AgentSessionStreamEvent,
9
5
  AgentSessionUsage,
10
6
  } from './types';
11
- import { createTimestamp } from './ids';
7
+ import type * as t from '@/types';
8
+ import { ModelEndHandler, ToolEndHandler } from '@/events';
12
9
  import { toJsonValue } from './messageSerialization';
10
+ import { createContentAggregator } from '@/stream';
11
+ import { createTimestamp } from './ids';
12
+ import { GraphEvents } from '@/common';
13
13
 
14
14
  type CompletedRunStepResult =
15
15
  | t.ToolEndEvent
@@ -1,6 +1,6 @@
1
1
  import type { RunnableConfig } from '@langchain/core/runnables';
2
- import type { BaseMessage } from '@langchain/core/messages';
3
2
  import type { BaseCheckpointSaver } from '@langchain/langgraph';
3
+ import type { BaseMessage } from '@langchain/core/messages';
4
4
  import type * as t from '@/types';
5
5
 
6
6
  export type JsonPrimitive = string | number | boolean | null;
@@ -1,8 +1,8 @@
1
1
  // src/specs/agent-handoffs.test.ts
2
2
  import { DynamicStructuredTool } from '@langchain/core/tools';
3
3
  import { AIMessage, HumanMessage, ToolMessage } from '@langchain/core/messages';
4
- import type { ToolCall } from '@langchain/core/messages/tool';
5
4
  import type { RunnableConfig } from '@langchain/core/runnables';
5
+ import type { ToolCall } from '@langchain/core/messages/tool';
6
6
  import type * as t from '@/types';
7
7
  import { Providers, GraphEvents, Constants } from '@/common';
8
8
  import { StandardGraph } from '@/graphs/Graph';
@@ -0,0 +1,50 @@
1
+ import { createHash } from 'node:crypto';
2
+ import {
3
+ initializeLangfuseTracing,
4
+ runWithTraceIdSeed,
5
+ } from '@/instrumentation';
6
+
7
+ const langfuse = {
8
+ publicKey: 'pk-lf-test',
9
+ secretKey: 'sk-lf-test',
10
+ baseUrl: 'http://localhost:3999',
11
+ };
12
+
13
+ /** sha256(seed) → first 32 hex chars; what `@langfuse/tracing` `createTraceId` produces. */
14
+ const expectedTraceId = (seed: string): string =>
15
+ createHash('sha256').update(seed, 'utf8').digest('hex').slice(0, 32);
16
+
17
+ describe('deterministic Langfuse trace ids', () => {
18
+ it('derives the root trace id from the seed when run inside runWithTraceIdSeed', () => {
19
+ const provider = initializeLangfuseTracing(langfuse);
20
+ expect(provider).toBeDefined();
21
+ const tracer = provider!.getTracer('deterministic-trace-id-test');
22
+
23
+ const seed = 'response-message-id-1234';
24
+ let traceId: string | undefined;
25
+ runWithTraceIdSeed(seed, () => {
26
+ const span = tracer.startSpan('AgentRun');
27
+ traceId = span.spanContext().traceId;
28
+ span.end();
29
+ });
30
+
31
+ expect(traceId).toBe(expectedTraceId(seed));
32
+ });
33
+
34
+ it('falls back to a random trace id when no seed is active', () => {
35
+ const provider = initializeLangfuseTracing(langfuse);
36
+ const tracer = provider!.getTracer('deterministic-trace-id-test');
37
+
38
+ const span = tracer.startSpan('AgentRun');
39
+ const traceId = span.spanContext().traceId;
40
+ span.end();
41
+
42
+ expect(traceId).toMatch(/^[0-9a-f]{32}$/);
43
+ expect(traceId).not.toBe(expectedTraceId('response-message-id-1234'));
44
+ });
45
+
46
+ it('runWithTraceIdSeed is a passthrough when the seed is undefined', () => {
47
+ const sentinel = {};
48
+ expect(runWithTraceIdSeed(undefined, () => sentinel)).toBe(sentinel);
49
+ });
50
+ });
@@ -1,8 +1,8 @@
1
- import { CallbackManager } from '@langchain/core/callbacks/manager';
2
1
  import { HumanMessage } from '@langchain/core/messages';
2
+ import { CallbackManager } from '@langchain/core/callbacks/manager';
3
+ import type * as t from '@/types';
3
4
  import { Providers } from '@/common';
4
5
  import { Run } from '@/run';
5
- import type * as t from '@/types';
6
6
 
7
7
  const mockSpan = {
8
8
  end: jest.fn(),
@@ -1,4 +1,5 @@
1
1
  import { CallbackHandler } from '@langfuse/langchain';
2
+ import { propagateAttributes } from '@langfuse/tracing';
2
3
  import { Providers } from '@/common';
3
4
  import { Run } from '@/run';
4
5
 
@@ -6,9 +7,17 @@ jest.mock('@langfuse/langchain', () => ({
6
7
  CallbackHandler: jest.fn().mockImplementation(() => ({})),
7
8
  }));
8
9
 
10
+ jest.mock('@langfuse/tracing', () => ({
11
+ ...jest.requireActual('@langfuse/tracing'),
12
+ propagateAttributes: jest.fn((_params, action: () => unknown) => action()),
13
+ }));
14
+
9
15
  const MockedCallbackHandler = CallbackHandler as jest.MockedClass<
10
16
  typeof CallbackHandler
11
17
  >;
18
+ const MockedPropagateAttributes = propagateAttributes as jest.MockedFunction<
19
+ typeof propagateAttributes
20
+ >;
12
21
 
13
22
  async function createTestRun(
14
23
  agentName?: string,
@@ -70,6 +79,35 @@ describe('Langfuse trace metadata includes agentName', () => {
70
79
  expect(ctorArgs?.traceMetadata).toMatchObject({ agentName: 'DWAINE' });
71
80
  });
72
81
 
82
+ it('propagates Langfuse identity around processStream observations', async () => {
83
+ const run = await createTestRun('DWAINE');
84
+ await run.processStream(
85
+ { messages: [] },
86
+ {
87
+ configurable: {
88
+ thread_id: 'thread-123',
89
+ user_id: 'user-456',
90
+ requestBody: { parentMessageId: 'parent-789' },
91
+ },
92
+ version: 'v2',
93
+ }
94
+ );
95
+
96
+ expect(MockedPropagateAttributes).toHaveBeenCalledTimes(1);
97
+ expect(MockedPropagateAttributes.mock.calls[0][0]).toMatchObject({
98
+ userId: 'user-456',
99
+ sessionId: 'thread-123',
100
+ traceName: 'LibreChat Agent: DWAINE',
101
+ tags: ['librechat', 'agent'],
102
+ metadata: {
103
+ messageId: 'test-run-id',
104
+ parentMessageId: 'parent-789',
105
+ agentId: 'agent_abc123',
106
+ agentName: 'DWAINE',
107
+ },
108
+ });
109
+ });
110
+
73
111
  it('falls back to agentId when agent has no explicit name', async () => {
74
112
  const run = await createTestRun();
75
113
  await run.processStream(
@@ -93,6 +131,7 @@ describe('Langfuse trace metadata includes agentName', () => {
93
131
  );
94
132
 
95
133
  expect(MockedCallbackHandler).not.toHaveBeenCalled();
134
+ expect(MockedPropagateAttributes).not.toHaveBeenCalled();
96
135
  });
97
136
 
98
137
  it('does not create the legacy CallbackHandler when explicit agent config is supplied', async () => {
@@ -1,5 +1,5 @@
1
- import { AIMessage, ToolMessage, HumanMessage } from '@langchain/core/messages';
2
1
  import { LangfuseOtelSpanAttributes } from '@langfuse/tracing';
2
+ import { AIMessage, ToolMessage, HumanMessage } from '@langchain/core/messages';
3
3
  import type { ReadableSpan } from '@opentelemetry/sdk-trace-base';
4
4
  import type { BaseMessage } from '@langchain/core/messages';
5
5
  import type { TPayload } from '@/types';
@@ -9,21 +9,21 @@
9
9
  *
10
10
  * Uses FakeListChatModel — no API keys required.
11
11
  */
12
+ import { FakeListChatModel } from '@langchain/core/utils/testing';
12
13
  import {
13
14
  HumanMessage,
14
15
  AIMessage,
15
16
  BaseMessage,
16
17
  UsageMetadata,
17
18
  } from '@langchain/core/messages';
18
- import { FakeListChatModel } from '@langchain/core/utils/testing';
19
19
  import type * as t from '@/types';
20
20
  import { ToolEndHandler, ModelEndHandler } from '@/events';
21
- import { GraphEvents, Providers } from '@/common';
22
- import { createContentAggregator } from '@/stream';
23
21
  import { createTokenCounter } from '@/utils/tokens';
22
+ import { createContentAggregator } from '@/stream';
23
+ import { GraphEvents, Providers } from '@/common';
24
24
  import { getLLMConfig } from '@/utils/llmConfig';
25
- import { Run } from '@/run';
26
25
  import * as providers from '@/llm/providers';
26
+ import { Run } from '@/run';
27
27
 
28
28
  function getSummaryText(summary: t.SummaryContentBlock | undefined): string {
29
29
  if (!summary) return '';
@@ -1,9 +1,8 @@
1
- import { AIMessage, HumanMessage } from '@langchain/core/messages';
2
1
  import { FakeListChatModel } from '@langchain/core/utils/testing';
3
- import type { ToolCall } from '@langchain/core/messages/tool';
2
+ import { AIMessage, HumanMessage } from '@langchain/core/messages';
4
3
  import type { RunnableConfig } from '@langchain/core/runnables';
4
+ import type { ToolCall } from '@langchain/core/messages/tool';
5
5
  import type * as t from '@/types';
6
- import { Run } from '@/run';
7
6
  import {
8
7
  Constants,
9
8
  GraphEvents,
@@ -13,6 +12,7 @@ import {
13
12
  StandardGraph,
14
13
  } from '@/index';
15
14
  import * as providers from '@/llm/providers';
15
+ import { Run } from '@/run';
16
16
 
17
17
  const CHILD_RESPONSE = 'Research result: Paris is the capital of France.';
18
18