@librechat/agents 3.4.6 → 3.5.0

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 (1027) hide show
  1. package/dist/cjs/agents/AgentContext.cjs +0 -356
  2. package/dist/cjs/agents/AgentContext.cjs.map +1 -1
  3. package/dist/cjs/agents/projection.cjs +0 -9
  4. package/dist/cjs/agents/projection.cjs.map +1 -1
  5. package/dist/cjs/common/constants.cjs +0 -26
  6. package/dist/cjs/common/constants.cjs.map +1 -1
  7. package/dist/cjs/common/enum.cjs +0 -85
  8. package/dist/cjs/common/enum.cjs.map +1 -1
  9. package/dist/cjs/events.cjs +0 -14
  10. package/dist/cjs/events.cjs.map +1 -1
  11. package/dist/cjs/graphs/Graph.cjs +1 -909
  12. package/dist/cjs/graphs/Graph.cjs.map +1 -1
  13. package/dist/cjs/graphs/MultiAgentGraph.cjs +7 -272
  14. package/dist/cjs/graphs/MultiAgentGraph.cjs.map +1 -1
  15. package/dist/cjs/graphs/applyGraphRuntimeConfig.cjs.map +1 -1
  16. package/dist/cjs/graphs/createGraph.cjs.map +1 -1
  17. package/dist/cjs/hitl/askUserQuestion.cjs +0 -53
  18. package/dist/cjs/hitl/askUserQuestion.cjs.map +1 -1
  19. package/dist/cjs/hitl/askUserQuestions.cjs +0 -20
  20. package/dist/cjs/hitl/askUserQuestions.cjs.map +1 -1
  21. package/dist/cjs/hitl/askUserQuestionsInterrupt.cjs +0 -6
  22. package/dist/cjs/hitl/askUserQuestionsInterrupt.cjs.map +1 -1
  23. package/dist/cjs/hooks/HookRegistry.cjs +0 -127
  24. package/dist/cjs/hooks/HookRegistry.cjs.map +1 -1
  25. package/dist/cjs/hooks/createToolPolicyHook.cjs +0 -38
  26. package/dist/cjs/hooks/createToolPolicyHook.cjs.map +1 -1
  27. package/dist/cjs/hooks/createWorkspacePolicyHook.cjs +0 -77
  28. package/dist/cjs/hooks/createWorkspacePolicyHook.cjs.map +1 -1
  29. package/dist/cjs/hooks/executeHooks.cjs +0 -79
  30. package/dist/cjs/hooks/executeHooks.cjs.map +1 -1
  31. package/dist/cjs/hooks/index.cjs +0 -16
  32. package/dist/cjs/hooks/index.cjs.map +1 -1
  33. package/dist/cjs/hooks/matchers.cjs +0 -104
  34. package/dist/cjs/hooks/matchers.cjs.map +1 -1
  35. package/dist/cjs/hooks/types.cjs +0 -8
  36. package/dist/cjs/hooks/types.cjs.map +1 -1
  37. package/dist/cjs/instrumentation.cjs +0 -14
  38. package/dist/cjs/instrumentation.cjs.map +1 -1
  39. package/dist/cjs/langfuse.cjs +0 -75
  40. package/dist/cjs/langfuse.cjs.map +1 -1
  41. package/dist/cjs/langfuseConfig.cjs.map +1 -1
  42. package/dist/cjs/langfuseRuntimeContext.cjs +0 -13
  43. package/dist/cjs/langfuseRuntimeContext.cjs.map +1 -1
  44. package/dist/cjs/langfuseRuntimeScope.cjs +0 -4
  45. package/dist/cjs/langfuseRuntimeScope.cjs.map +1 -1
  46. package/dist/cjs/langfuseSpanRegistry.cjs +0 -28
  47. package/dist/cjs/langfuseSpanRegistry.cjs.map +1 -1
  48. package/dist/cjs/langfuseToolOutputTracing.cjs +0 -3
  49. package/dist/cjs/langfuseToolOutputTracing.cjs.map +1 -1
  50. package/dist/cjs/langfuseTraceShaping.cjs +0 -74
  51. package/dist/cjs/langfuseTraceShaping.cjs.map +1 -1
  52. package/dist/cjs/llm/anthropic/index.cjs +0 -3
  53. package/dist/cjs/llm/anthropic/index.cjs.map +1 -1
  54. package/dist/cjs/llm/anthropic/types.cjs.map +1 -1
  55. package/dist/cjs/llm/anthropic/utils/message_inputs.cjs +1 -111
  56. package/dist/cjs/llm/anthropic/utils/message_inputs.cjs.map +1 -1
  57. package/dist/cjs/llm/anthropic/utils/message_outputs.cjs +0 -1
  58. package/dist/cjs/llm/anthropic/utils/message_outputs.cjs.map +1 -1
  59. package/dist/cjs/llm/anthropic/utils/stream_events.cjs +0 -8
  60. package/dist/cjs/llm/anthropic/utils/stream_events.cjs.map +1 -1
  61. package/dist/cjs/llm/anthropic/utils/tools.cjs.map +1 -1
  62. package/dist/cjs/llm/bedrock/cachePoints.cjs.map +1 -1
  63. package/dist/cjs/llm/bedrock/index.cjs +1 -95
  64. package/dist/cjs/llm/bedrock/index.cjs.map +1 -1
  65. package/dist/cjs/llm/bedrock/toolCache.cjs.map +1 -1
  66. package/dist/cjs/llm/bedrock/utils/message_inputs.cjs +0 -78
  67. package/dist/cjs/llm/bedrock/utils/message_inputs.cjs.map +1 -1
  68. package/dist/cjs/llm/bedrock/utils/message_outputs.cjs +0 -24
  69. package/dist/cjs/llm/bedrock/utils/message_outputs.cjs.map +1 -1
  70. package/dist/cjs/llm/contextOverflowRecovery.cjs +0 -62
  71. package/dist/cjs/llm/contextOverflowRecovery.cjs.map +1 -1
  72. package/dist/cjs/llm/fake.cjs.map +1 -1
  73. package/dist/cjs/llm/google/index.cjs +2 -21
  74. package/dist/cjs/llm/google/index.cjs.map +1 -1
  75. package/dist/cjs/llm/google/utils/common.cjs +5 -35
  76. package/dist/cjs/llm/google/utils/common.cjs.map +1 -1
  77. package/dist/cjs/llm/init.cjs +0 -9
  78. package/dist/cjs/llm/init.cjs.map +1 -1
  79. package/dist/cjs/llm/invoke.cjs +1 -270
  80. package/dist/cjs/llm/invoke.cjs.map +1 -1
  81. package/dist/cjs/llm/mistral/index.cjs.map +1 -1
  82. package/dist/cjs/llm/openai/index.cjs +0 -99
  83. package/dist/cjs/llm/openai/index.cjs.map +1 -1
  84. package/dist/cjs/llm/openai/streamMetadata.cjs +0 -21
  85. package/dist/cjs/llm/openai/streamMetadata.cjs.map +1 -1
  86. package/dist/cjs/llm/openai/utils/index.cjs.map +1 -1
  87. package/dist/cjs/llm/openrouter/index.cjs +0 -1
  88. package/dist/cjs/llm/openrouter/index.cjs.map +1 -1
  89. package/dist/cjs/llm/openrouter/toolCache.cjs +0 -6
  90. package/dist/cjs/llm/openrouter/toolCache.cjs.map +1 -1
  91. package/dist/cjs/llm/preempt.cjs +0 -75
  92. package/dist/cjs/llm/preempt.cjs.map +1 -1
  93. package/dist/cjs/llm/providers.cjs.map +1 -1
  94. package/dist/cjs/llm/request.cjs +0 -10
  95. package/dist/cjs/llm/request.cjs.map +1 -1
  96. package/dist/cjs/llm/stream/chunkAdapters.cjs +0 -62
  97. package/dist/cjs/llm/stream/chunkAdapters.cjs.map +1 -1
  98. package/dist/cjs/llm/stream/smoother.cjs +0 -58
  99. package/dist/cjs/llm/stream/smoother.cjs.map +1 -1
  100. package/dist/cjs/llm/streamLimits.cjs +4 -293
  101. package/dist/cjs/llm/streamLimits.cjs.map +1 -1
  102. package/dist/cjs/llm/truncation.cjs +0 -36
  103. package/dist/cjs/llm/truncation.cjs.map +1 -1
  104. package/dist/cjs/llm/vertexai/index.cjs +0 -330
  105. package/dist/cjs/llm/vertexai/index.cjs.map +1 -1
  106. package/dist/cjs/messages/alternation.cjs +0 -43
  107. package/dist/cjs/messages/alternation.cjs.map +1 -1
  108. package/dist/cjs/messages/anthropicToolCache.cjs +0 -45
  109. package/dist/cjs/messages/anthropicToolCache.cjs.map +1 -1
  110. package/dist/cjs/messages/assistantPhase.cjs +0 -12
  111. package/dist/cjs/messages/assistantPhase.cjs.map +1 -1
  112. package/dist/cjs/messages/budget.cjs +0 -9
  113. package/dist/cjs/messages/budget.cjs.map +1 -1
  114. package/dist/cjs/messages/cache.cjs +0 -172
  115. package/dist/cjs/messages/cache.cjs.map +1 -1
  116. package/dist/cjs/messages/content.cjs +0 -9
  117. package/dist/cjs/messages/content.cjs.map +1 -1
  118. package/dist/cjs/messages/contextPruning.cjs +0 -15
  119. package/dist/cjs/messages/contextPruning.cjs.map +1 -1
  120. package/dist/cjs/messages/contextPruningSettings.cjs +0 -3
  121. package/dist/cjs/messages/contextPruningSettings.cjs.map +1 -1
  122. package/dist/cjs/messages/core.cjs +0 -48
  123. package/dist/cjs/messages/core.cjs.map +1 -1
  124. package/dist/cjs/messages/format.cjs +1 -345
  125. package/dist/cjs/messages/format.cjs.map +1 -1
  126. package/dist/cjs/messages/handoffCue.cjs +0 -36
  127. package/dist/cjs/messages/handoffCue.cjs.map +1 -1
  128. package/dist/cjs/messages/ids.cjs.map +1 -1
  129. package/dist/cjs/messages/injected.cjs +0 -33
  130. package/dist/cjs/messages/injected.cjs.map +1 -1
  131. package/dist/cjs/messages/langchain.cjs +0 -14
  132. package/dist/cjs/messages/langchain.cjs.map +1 -1
  133. package/dist/cjs/messages/prune.cjs +1 -184
  134. package/dist/cjs/messages/prune.cjs.map +1 -1
  135. package/dist/cjs/messages/recency.cjs +0 -32
  136. package/dist/cjs/messages/recency.cjs.map +1 -1
  137. package/dist/cjs/messages/reducer.cjs +0 -30
  138. package/dist/cjs/messages/reducer.cjs.map +1 -1
  139. package/dist/cjs/messages/tools.cjs +0 -14
  140. package/dist/cjs/messages/tools.cjs.map +1 -1
  141. package/dist/cjs/openai/index.cjs.map +1 -1
  142. package/dist/cjs/prompts/activityLabel.cjs +9 -79
  143. package/dist/cjs/prompts/activityLabel.cjs.map +1 -1
  144. package/dist/cjs/responses/index.cjs.map +1 -1
  145. package/dist/cjs/run.cjs +2 -538
  146. package/dist/cjs/run.cjs.map +1 -1
  147. package/dist/cjs/session/AgentSession.cjs +1 -17
  148. package/dist/cjs/session/AgentSession.cjs.map +1 -1
  149. package/dist/cjs/session/JsonlSessionStore.cjs.map +1 -1
  150. package/dist/cjs/session/handlers.cjs +0 -7
  151. package/dist/cjs/session/handlers.cjs.map +1 -1
  152. package/dist/cjs/session/ids.cjs.map +1 -1
  153. package/dist/cjs/session/messageSerialization.cjs +0 -4
  154. package/dist/cjs/session/messageSerialization.cjs.map +1 -1
  155. package/dist/cjs/stream.cjs +1 -93
  156. package/dist/cjs/stream.cjs.map +1 -1
  157. package/dist/cjs/summarization/index.cjs +0 -27
  158. package/dist/cjs/summarization/index.cjs.map +1 -1
  159. package/dist/cjs/summarization/node.cjs +0 -273
  160. package/dist/cjs/summarization/node.cjs.map +1 -1
  161. package/dist/cjs/tools/BashExecutor.cjs +0 -35
  162. package/dist/cjs/tools/BashExecutor.cjs.map +1 -1
  163. package/dist/cjs/tools/BashProgrammaticToolCalling.cjs +0 -24
  164. package/dist/cjs/tools/BashProgrammaticToolCalling.cjs.map +1 -1
  165. package/dist/cjs/tools/Calculator.cjs.map +1 -1
  166. package/dist/cjs/tools/CodeExecutor.cjs +0 -13
  167. package/dist/cjs/tools/CodeExecutor.cjs.map +1 -1
  168. package/dist/cjs/tools/CodeSessionFileSummary.cjs.map +1 -1
  169. package/dist/cjs/tools/ProgrammaticToolCalling.cjs +0 -101
  170. package/dist/cjs/tools/ProgrammaticToolCalling.cjs.map +1 -1
  171. package/dist/cjs/tools/ReadFile.cjs.map +1 -1
  172. package/dist/cjs/tools/SkillTool.cjs +0 -5
  173. package/dist/cjs/tools/SkillTool.cjs.map +1 -1
  174. package/dist/cjs/tools/SubagentTool.cjs +0 -10
  175. package/dist/cjs/tools/SubagentTool.cjs.map +1 -1
  176. package/dist/cjs/tools/ToolNode.cjs +6 -1038
  177. package/dist/cjs/tools/ToolNode.cjs.map +1 -1
  178. package/dist/cjs/tools/ToolSearch.cjs +0 -179
  179. package/dist/cjs/tools/ToolSearch.cjs.map +1 -1
  180. package/dist/cjs/tools/cloudflare/CloudflareBridgeRuntime.cjs.map +1 -1
  181. package/dist/cjs/tools/cloudflare/CloudflareProgrammaticToolCalling.cjs.map +1 -1
  182. package/dist/cjs/tools/cloudflare/CloudflareSandboxExecutionEngine.cjs +0 -39
  183. package/dist/cjs/tools/cloudflare/CloudflareSandboxExecutionEngine.cjs.map +1 -1
  184. package/dist/cjs/tools/cloudflare/CloudflareSandboxTools.cjs.map +1 -1
  185. package/dist/cjs/tools/eagerEventExecution.cjs +0 -6
  186. package/dist/cjs/tools/eagerEventExecution.cjs.map +1 -1
  187. package/dist/cjs/tools/handlers.cjs +1 -41
  188. package/dist/cjs/tools/handlers.cjs.map +1 -1
  189. package/dist/cjs/tools/intentArg.cjs +1 -132
  190. package/dist/cjs/tools/intentArg.cjs.map +1 -1
  191. package/dist/cjs/tools/local/CompileCheckTool.cjs +0 -25
  192. package/dist/cjs/tools/local/CompileCheckTool.cjs.map +1 -1
  193. package/dist/cjs/tools/local/FileCheckpointer.cjs +0 -23
  194. package/dist/cjs/tools/local/FileCheckpointer.cjs.map +1 -1
  195. package/dist/cjs/tools/local/LocalCodingTools.cjs +0 -80
  196. package/dist/cjs/tools/local/LocalCodingTools.cjs.map +1 -1
  197. package/dist/cjs/tools/local/LocalExecutionEngine.cjs +0 -126
  198. package/dist/cjs/tools/local/LocalExecutionEngine.cjs.map +1 -1
  199. package/dist/cjs/tools/local/LocalExecutionTools.cjs.map +1 -1
  200. package/dist/cjs/tools/local/LocalProgrammaticToolCalling.cjs +0 -12
  201. package/dist/cjs/tools/local/LocalProgrammaticToolCalling.cjs.map +1 -1
  202. package/dist/cjs/tools/local/attachments.cjs +0 -44
  203. package/dist/cjs/tools/local/attachments.cjs.map +1 -1
  204. package/dist/cjs/tools/local/bashAst.cjs +0 -16
  205. package/dist/cjs/tools/local/bashAst.cjs.map +1 -1
  206. package/dist/cjs/tools/local/editStrategies.cjs +0 -14
  207. package/dist/cjs/tools/local/editStrategies.cjs.map +1 -1
  208. package/dist/cjs/tools/local/resolveLocalExecutionTools.cjs.map +1 -1
  209. package/dist/cjs/tools/local/syntaxCheck.cjs +0 -31
  210. package/dist/cjs/tools/local/syntaxCheck.cjs.map +1 -1
  211. package/dist/cjs/tools/local/textEncoding.cjs +0 -11
  212. package/dist/cjs/tools/local/textEncoding.cjs.map +1 -1
  213. package/dist/cjs/tools/local/workspaceFS.cjs +0 -33
  214. package/dist/cjs/tools/local/workspaceFS.cjs.map +1 -1
  215. package/dist/cjs/tools/ptcTimeout.cjs.map +1 -1
  216. package/dist/cjs/tools/schema.cjs +0 -8
  217. package/dist/cjs/tools/schema.cjs.map +1 -1
  218. package/dist/cjs/tools/search/anthropic.cjs +0 -9
  219. package/dist/cjs/tools/search/anthropic.cjs.map +1 -1
  220. package/dist/cjs/tools/search/content.cjs.map +1 -1
  221. package/dist/cjs/tools/search/crw-scraper.cjs +0 -33
  222. package/dist/cjs/tools/search/crw-scraper.cjs.map +1 -1
  223. package/dist/cjs/tools/search/crw-search.cjs +0 -2
  224. package/dist/cjs/tools/search/crw-search.cjs.map +1 -1
  225. package/dist/cjs/tools/search/firecrawl.cjs +0 -25
  226. package/dist/cjs/tools/search/firecrawl.cjs.map +1 -1
  227. package/dist/cjs/tools/search/format.cjs +0 -30
  228. package/dist/cjs/tools/search/format.cjs.map +1 -1
  229. package/dist/cjs/tools/search/highlights.cjs +0 -16
  230. package/dist/cjs/tools/search/highlights.cjs.map +1 -1
  231. package/dist/cjs/tools/search/keenable-scraper.cjs +0 -8
  232. package/dist/cjs/tools/search/keenable-scraper.cjs.map +1 -1
  233. package/dist/cjs/tools/search/keenable-search.cjs +0 -7
  234. package/dist/cjs/tools/search/keenable-search.cjs.map +1 -1
  235. package/dist/cjs/tools/search/rerankers.cjs +0 -35
  236. package/dist/cjs/tools/search/rerankers.cjs.map +1 -1
  237. package/dist/cjs/tools/search/schema.cjs +0 -1
  238. package/dist/cjs/tools/search/schema.cjs.map +1 -1
  239. package/dist/cjs/tools/search/search.cjs +1 -14
  240. package/dist/cjs/tools/search/search.cjs.map +1 -1
  241. package/dist/cjs/tools/search/serper-scraper.cjs +0 -46
  242. package/dist/cjs/tools/search/serper-scraper.cjs.map +1 -1
  243. package/dist/cjs/tools/search/tavily-scraper.cjs.map +1 -1
  244. package/dist/cjs/tools/search/tavily-search.cjs.map +1 -1
  245. package/dist/cjs/tools/search/tool.cjs +0 -25
  246. package/dist/cjs/tools/search/tool.cjs.map +1 -1
  247. package/dist/cjs/tools/search/utils.cjs +0 -8
  248. package/dist/cjs/tools/search/utils.cjs.map +1 -1
  249. package/dist/cjs/tools/skillCatalog.cjs +0 -6
  250. package/dist/cjs/tools/skillCatalog.cjs.map +1 -1
  251. package/dist/cjs/tools/streamedToolCallSeals.cjs +0 -6
  252. package/dist/cjs/tools/streamedToolCallSeals.cjs.map +1 -1
  253. package/dist/cjs/tools/subagent/SubagentExecutionRegistry.cjs +0 -2
  254. package/dist/cjs/tools/subagent/SubagentExecutionRegistry.cjs.map +1 -1
  255. package/dist/cjs/tools/subagent/SubagentExecutor.cjs +3 -213
  256. package/dist/cjs/tools/subagent/SubagentExecutor.cjs.map +1 -1
  257. package/dist/cjs/tools/subagent/SubagentReplay.cjs.map +1 -1
  258. package/dist/cjs/tools/subagent/childGraphConfig.cjs +0 -4
  259. package/dist/cjs/tools/subagent/childGraphConfig.cjs.map +1 -1
  260. package/dist/cjs/tools/subagent/runtimeLimits.cjs.map +1 -1
  261. package/dist/cjs/tools/toolOutputReferences.cjs +1 -322
  262. package/dist/cjs/tools/toolOutputReferences.cjs.map +1 -1
  263. package/dist/cjs/types/hitl.cjs +0 -5
  264. package/dist/cjs/types/hitl.cjs.map +1 -1
  265. package/dist/cjs/utils/callbacks.cjs.map +1 -1
  266. package/dist/cjs/utils/errors.cjs +14 -165
  267. package/dist/cjs/utils/errors.cjs.map +1 -1
  268. package/dist/cjs/utils/events.cjs +0 -10
  269. package/dist/cjs/utils/events.cjs.map +1 -1
  270. package/dist/cjs/utils/graph.cjs.map +1 -1
  271. package/dist/cjs/utils/handlers.cjs +0 -3
  272. package/dist/cjs/utils/handlers.cjs.map +1 -1
  273. package/dist/cjs/utils/llm.cjs +0 -1
  274. package/dist/cjs/utils/llm.cjs.map +1 -1
  275. package/dist/cjs/utils/misc.cjs +0 -16
  276. package/dist/cjs/utils/misc.cjs.map +1 -1
  277. package/dist/cjs/utils/proxy.cjs +0 -26
  278. package/dist/cjs/utils/proxy.cjs.map +1 -1
  279. package/dist/cjs/utils/run.cjs +0 -6
  280. package/dist/cjs/utils/run.cjs.map +1 -1
  281. package/dist/cjs/utils/schema.cjs +0 -5
  282. package/dist/cjs/utils/schema.cjs.map +1 -1
  283. package/dist/cjs/utils/title.cjs +0 -6
  284. package/dist/cjs/utils/title.cjs.map +1 -1
  285. package/dist/cjs/utils/tokens.cjs +0 -113
  286. package/dist/cjs/utils/tokens.cjs.map +1 -1
  287. package/dist/cjs/utils/toolContent.cjs +0 -41
  288. package/dist/cjs/utils/toolContent.cjs.map +1 -1
  289. package/dist/cjs/utils/truncation.cjs +0 -61
  290. package/dist/cjs/utils/truncation.cjs.map +1 -1
  291. package/dist/esm/agents/AgentContext.mjs +0 -356
  292. package/dist/esm/agents/AgentContext.mjs.map +1 -1
  293. package/dist/esm/agents/projection.mjs +0 -9
  294. package/dist/esm/agents/projection.mjs.map +1 -1
  295. package/dist/esm/common/constants.mjs +0 -26
  296. package/dist/esm/common/constants.mjs.map +1 -1
  297. package/dist/esm/common/enum.mjs +0 -85
  298. package/dist/esm/common/enum.mjs.map +1 -1
  299. package/dist/esm/events.mjs +0 -14
  300. package/dist/esm/events.mjs.map +1 -1
  301. package/dist/esm/graphs/Graph.mjs +1 -909
  302. package/dist/esm/graphs/Graph.mjs.map +1 -1
  303. package/dist/esm/graphs/MultiAgentGraph.mjs +7 -272
  304. package/dist/esm/graphs/MultiAgentGraph.mjs.map +1 -1
  305. package/dist/esm/graphs/applyGraphRuntimeConfig.mjs.map +1 -1
  306. package/dist/esm/graphs/createGraph.mjs.map +1 -1
  307. package/dist/esm/hitl/askUserQuestion.mjs +0 -53
  308. package/dist/esm/hitl/askUserQuestion.mjs.map +1 -1
  309. package/dist/esm/hitl/askUserQuestions.mjs +0 -20
  310. package/dist/esm/hitl/askUserQuestions.mjs.map +1 -1
  311. package/dist/esm/hitl/askUserQuestionsInterrupt.mjs +0 -6
  312. package/dist/esm/hitl/askUserQuestionsInterrupt.mjs.map +1 -1
  313. package/dist/esm/hooks/HookRegistry.mjs +0 -127
  314. package/dist/esm/hooks/HookRegistry.mjs.map +1 -1
  315. package/dist/esm/hooks/createToolPolicyHook.mjs +0 -38
  316. package/dist/esm/hooks/createToolPolicyHook.mjs.map +1 -1
  317. package/dist/esm/hooks/createWorkspacePolicyHook.mjs +0 -77
  318. package/dist/esm/hooks/createWorkspacePolicyHook.mjs.map +1 -1
  319. package/dist/esm/hooks/executeHooks.mjs +0 -79
  320. package/dist/esm/hooks/executeHooks.mjs.map +1 -1
  321. package/dist/esm/hooks/index.mjs +0 -16
  322. package/dist/esm/hooks/index.mjs.map +1 -1
  323. package/dist/esm/hooks/matchers.mjs +0 -104
  324. package/dist/esm/hooks/matchers.mjs.map +1 -1
  325. package/dist/esm/hooks/types.mjs +0 -8
  326. package/dist/esm/hooks/types.mjs.map +1 -1
  327. package/dist/esm/instrumentation.mjs +0 -14
  328. package/dist/esm/instrumentation.mjs.map +1 -1
  329. package/dist/esm/langfuse.mjs +0 -75
  330. package/dist/esm/langfuse.mjs.map +1 -1
  331. package/dist/esm/langfuseConfig.mjs.map +1 -1
  332. package/dist/esm/langfuseRuntimeContext.mjs +0 -13
  333. package/dist/esm/langfuseRuntimeContext.mjs.map +1 -1
  334. package/dist/esm/langfuseRuntimeScope.mjs +0 -4
  335. package/dist/esm/langfuseRuntimeScope.mjs.map +1 -1
  336. package/dist/esm/langfuseSpanRegistry.mjs +0 -28
  337. package/dist/esm/langfuseSpanRegistry.mjs.map +1 -1
  338. package/dist/esm/langfuseToolOutputTracing.mjs +0 -3
  339. package/dist/esm/langfuseToolOutputTracing.mjs.map +1 -1
  340. package/dist/esm/langfuseTraceShaping.mjs +0 -74
  341. package/dist/esm/langfuseTraceShaping.mjs.map +1 -1
  342. package/dist/esm/llm/anthropic/index.mjs +0 -3
  343. package/dist/esm/llm/anthropic/index.mjs.map +1 -1
  344. package/dist/esm/llm/anthropic/types.mjs.map +1 -1
  345. package/dist/esm/llm/anthropic/utils/message_inputs.mjs +1 -111
  346. package/dist/esm/llm/anthropic/utils/message_inputs.mjs.map +1 -1
  347. package/dist/esm/llm/anthropic/utils/message_outputs.mjs +0 -1
  348. package/dist/esm/llm/anthropic/utils/message_outputs.mjs.map +1 -1
  349. package/dist/esm/llm/anthropic/utils/stream_events.mjs +0 -8
  350. package/dist/esm/llm/anthropic/utils/stream_events.mjs.map +1 -1
  351. package/dist/esm/llm/anthropic/utils/tools.mjs.map +1 -1
  352. package/dist/esm/llm/bedrock/cachePoints.mjs.map +1 -1
  353. package/dist/esm/llm/bedrock/index.mjs +1 -95
  354. package/dist/esm/llm/bedrock/index.mjs.map +1 -1
  355. package/dist/esm/llm/bedrock/toolCache.mjs.map +1 -1
  356. package/dist/esm/llm/bedrock/utils/message_inputs.mjs +0 -78
  357. package/dist/esm/llm/bedrock/utils/message_inputs.mjs.map +1 -1
  358. package/dist/esm/llm/bedrock/utils/message_outputs.mjs +0 -24
  359. package/dist/esm/llm/bedrock/utils/message_outputs.mjs.map +1 -1
  360. package/dist/esm/llm/contextOverflowRecovery.mjs +0 -62
  361. package/dist/esm/llm/contextOverflowRecovery.mjs.map +1 -1
  362. package/dist/esm/llm/fake.mjs.map +1 -1
  363. package/dist/esm/llm/google/index.mjs +2 -21
  364. package/dist/esm/llm/google/index.mjs.map +1 -1
  365. package/dist/esm/llm/google/utils/common.mjs +5 -35
  366. package/dist/esm/llm/google/utils/common.mjs.map +1 -1
  367. package/dist/esm/llm/init.mjs +0 -9
  368. package/dist/esm/llm/init.mjs.map +1 -1
  369. package/dist/esm/llm/invoke.mjs +1 -270
  370. package/dist/esm/llm/invoke.mjs.map +1 -1
  371. package/dist/esm/llm/mistral/index.mjs.map +1 -1
  372. package/dist/esm/llm/openai/index.mjs +0 -99
  373. package/dist/esm/llm/openai/index.mjs.map +1 -1
  374. package/dist/esm/llm/openai/streamMetadata.mjs +0 -21
  375. package/dist/esm/llm/openai/streamMetadata.mjs.map +1 -1
  376. package/dist/esm/llm/openai/utils/index.mjs.map +1 -1
  377. package/dist/esm/llm/openrouter/index.mjs +0 -1
  378. package/dist/esm/llm/openrouter/index.mjs.map +1 -1
  379. package/dist/esm/llm/openrouter/toolCache.mjs +0 -6
  380. package/dist/esm/llm/openrouter/toolCache.mjs.map +1 -1
  381. package/dist/esm/llm/preempt.mjs +0 -75
  382. package/dist/esm/llm/preempt.mjs.map +1 -1
  383. package/dist/esm/llm/providers.mjs.map +1 -1
  384. package/dist/esm/llm/request.mjs +0 -10
  385. package/dist/esm/llm/request.mjs.map +1 -1
  386. package/dist/esm/llm/stream/chunkAdapters.mjs +0 -62
  387. package/dist/esm/llm/stream/chunkAdapters.mjs.map +1 -1
  388. package/dist/esm/llm/stream/smoother.mjs +0 -58
  389. package/dist/esm/llm/stream/smoother.mjs.map +1 -1
  390. package/dist/esm/llm/streamLimits.mjs +4 -293
  391. package/dist/esm/llm/streamLimits.mjs.map +1 -1
  392. package/dist/esm/llm/truncation.mjs +0 -36
  393. package/dist/esm/llm/truncation.mjs.map +1 -1
  394. package/dist/esm/llm/vertexai/index.mjs +0 -330
  395. package/dist/esm/llm/vertexai/index.mjs.map +1 -1
  396. package/dist/esm/messages/alternation.mjs +0 -43
  397. package/dist/esm/messages/alternation.mjs.map +1 -1
  398. package/dist/esm/messages/anthropicToolCache.mjs +0 -45
  399. package/dist/esm/messages/anthropicToolCache.mjs.map +1 -1
  400. package/dist/esm/messages/assistantPhase.mjs +0 -12
  401. package/dist/esm/messages/assistantPhase.mjs.map +1 -1
  402. package/dist/esm/messages/budget.mjs +0 -9
  403. package/dist/esm/messages/budget.mjs.map +1 -1
  404. package/dist/esm/messages/cache.mjs +0 -172
  405. package/dist/esm/messages/cache.mjs.map +1 -1
  406. package/dist/esm/messages/content.mjs +0 -9
  407. package/dist/esm/messages/content.mjs.map +1 -1
  408. package/dist/esm/messages/contextPruning.mjs +0 -15
  409. package/dist/esm/messages/contextPruning.mjs.map +1 -1
  410. package/dist/esm/messages/contextPruningSettings.mjs +0 -3
  411. package/dist/esm/messages/contextPruningSettings.mjs.map +1 -1
  412. package/dist/esm/messages/core.mjs +0 -48
  413. package/dist/esm/messages/core.mjs.map +1 -1
  414. package/dist/esm/messages/format.mjs +1 -345
  415. package/dist/esm/messages/format.mjs.map +1 -1
  416. package/dist/esm/messages/handoffCue.mjs +0 -36
  417. package/dist/esm/messages/handoffCue.mjs.map +1 -1
  418. package/dist/esm/messages/ids.mjs.map +1 -1
  419. package/dist/esm/messages/injected.mjs +0 -33
  420. package/dist/esm/messages/injected.mjs.map +1 -1
  421. package/dist/esm/messages/langchain.mjs +0 -14
  422. package/dist/esm/messages/langchain.mjs.map +1 -1
  423. package/dist/esm/messages/prune.mjs +1 -184
  424. package/dist/esm/messages/prune.mjs.map +1 -1
  425. package/dist/esm/messages/recency.mjs +0 -32
  426. package/dist/esm/messages/recency.mjs.map +1 -1
  427. package/dist/esm/messages/reducer.mjs +0 -30
  428. package/dist/esm/messages/reducer.mjs.map +1 -1
  429. package/dist/esm/messages/tools.mjs +0 -14
  430. package/dist/esm/messages/tools.mjs.map +1 -1
  431. package/dist/esm/openai/index.mjs.map +1 -1
  432. package/dist/esm/prompts/activityLabel.mjs +9 -79
  433. package/dist/esm/prompts/activityLabel.mjs.map +1 -1
  434. package/dist/esm/responses/index.mjs.map +1 -1
  435. package/dist/esm/run.mjs +2 -538
  436. package/dist/esm/run.mjs.map +1 -1
  437. package/dist/esm/session/AgentSession.mjs +1 -17
  438. package/dist/esm/session/AgentSession.mjs.map +1 -1
  439. package/dist/esm/session/JsonlSessionStore.mjs.map +1 -1
  440. package/dist/esm/session/handlers.mjs +0 -7
  441. package/dist/esm/session/handlers.mjs.map +1 -1
  442. package/dist/esm/session/ids.mjs.map +1 -1
  443. package/dist/esm/session/messageSerialization.mjs +0 -4
  444. package/dist/esm/session/messageSerialization.mjs.map +1 -1
  445. package/dist/esm/stream.mjs +1 -93
  446. package/dist/esm/stream.mjs.map +1 -1
  447. package/dist/esm/summarization/index.mjs +0 -27
  448. package/dist/esm/summarization/index.mjs.map +1 -1
  449. package/dist/esm/summarization/node.mjs +0 -273
  450. package/dist/esm/summarization/node.mjs.map +1 -1
  451. package/dist/esm/tools/BashExecutor.mjs +0 -35
  452. package/dist/esm/tools/BashExecutor.mjs.map +1 -1
  453. package/dist/esm/tools/BashProgrammaticToolCalling.mjs +0 -24
  454. package/dist/esm/tools/BashProgrammaticToolCalling.mjs.map +1 -1
  455. package/dist/esm/tools/Calculator.mjs.map +1 -1
  456. package/dist/esm/tools/CodeExecutor.mjs +0 -13
  457. package/dist/esm/tools/CodeExecutor.mjs.map +1 -1
  458. package/dist/esm/tools/CodeSessionFileSummary.mjs.map +1 -1
  459. package/dist/esm/tools/ProgrammaticToolCalling.mjs +0 -101
  460. package/dist/esm/tools/ProgrammaticToolCalling.mjs.map +1 -1
  461. package/dist/esm/tools/ReadFile.mjs.map +1 -1
  462. package/dist/esm/tools/SkillTool.mjs +0 -5
  463. package/dist/esm/tools/SkillTool.mjs.map +1 -1
  464. package/dist/esm/tools/SubagentTool.mjs +0 -10
  465. package/dist/esm/tools/SubagentTool.mjs.map +1 -1
  466. package/dist/esm/tools/ToolNode.mjs +6 -1038
  467. package/dist/esm/tools/ToolNode.mjs.map +1 -1
  468. package/dist/esm/tools/ToolSearch.mjs +0 -179
  469. package/dist/esm/tools/ToolSearch.mjs.map +1 -1
  470. package/dist/esm/tools/cloudflare/CloudflareBridgeRuntime.mjs.map +1 -1
  471. package/dist/esm/tools/cloudflare/CloudflareProgrammaticToolCalling.mjs.map +1 -1
  472. package/dist/esm/tools/cloudflare/CloudflareSandboxExecutionEngine.mjs +0 -39
  473. package/dist/esm/tools/cloudflare/CloudflareSandboxExecutionEngine.mjs.map +1 -1
  474. package/dist/esm/tools/cloudflare/CloudflareSandboxTools.mjs.map +1 -1
  475. package/dist/esm/tools/eagerEventExecution.mjs +0 -6
  476. package/dist/esm/tools/eagerEventExecution.mjs.map +1 -1
  477. package/dist/esm/tools/handlers.mjs +1 -41
  478. package/dist/esm/tools/handlers.mjs.map +1 -1
  479. package/dist/esm/tools/intentArg.mjs +1 -132
  480. package/dist/esm/tools/intentArg.mjs.map +1 -1
  481. package/dist/esm/tools/local/CompileCheckTool.mjs +0 -25
  482. package/dist/esm/tools/local/CompileCheckTool.mjs.map +1 -1
  483. package/dist/esm/tools/local/FileCheckpointer.mjs +0 -23
  484. package/dist/esm/tools/local/FileCheckpointer.mjs.map +1 -1
  485. package/dist/esm/tools/local/LocalCodingTools.mjs +0 -80
  486. package/dist/esm/tools/local/LocalCodingTools.mjs.map +1 -1
  487. package/dist/esm/tools/local/LocalExecutionEngine.mjs +0 -126
  488. package/dist/esm/tools/local/LocalExecutionEngine.mjs.map +1 -1
  489. package/dist/esm/tools/local/LocalExecutionTools.mjs.map +1 -1
  490. package/dist/esm/tools/local/LocalProgrammaticToolCalling.mjs +0 -12
  491. package/dist/esm/tools/local/LocalProgrammaticToolCalling.mjs.map +1 -1
  492. package/dist/esm/tools/local/attachments.mjs +0 -44
  493. package/dist/esm/tools/local/attachments.mjs.map +1 -1
  494. package/dist/esm/tools/local/bashAst.mjs +0 -16
  495. package/dist/esm/tools/local/bashAst.mjs.map +1 -1
  496. package/dist/esm/tools/local/editStrategies.mjs +0 -14
  497. package/dist/esm/tools/local/editStrategies.mjs.map +1 -1
  498. package/dist/esm/tools/local/resolveLocalExecutionTools.mjs.map +1 -1
  499. package/dist/esm/tools/local/syntaxCheck.mjs +0 -31
  500. package/dist/esm/tools/local/syntaxCheck.mjs.map +1 -1
  501. package/dist/esm/tools/local/textEncoding.mjs +0 -11
  502. package/dist/esm/tools/local/textEncoding.mjs.map +1 -1
  503. package/dist/esm/tools/local/workspaceFS.mjs +0 -33
  504. package/dist/esm/tools/local/workspaceFS.mjs.map +1 -1
  505. package/dist/esm/tools/ptcTimeout.mjs.map +1 -1
  506. package/dist/esm/tools/schema.mjs +0 -8
  507. package/dist/esm/tools/schema.mjs.map +1 -1
  508. package/dist/esm/tools/search/anthropic.mjs +0 -9
  509. package/dist/esm/tools/search/anthropic.mjs.map +1 -1
  510. package/dist/esm/tools/search/content.mjs.map +1 -1
  511. package/dist/esm/tools/search/crw-scraper.mjs +0 -33
  512. package/dist/esm/tools/search/crw-scraper.mjs.map +1 -1
  513. package/dist/esm/tools/search/crw-search.mjs +0 -2
  514. package/dist/esm/tools/search/crw-search.mjs.map +1 -1
  515. package/dist/esm/tools/search/firecrawl.mjs +0 -25
  516. package/dist/esm/tools/search/firecrawl.mjs.map +1 -1
  517. package/dist/esm/tools/search/format.mjs +0 -30
  518. package/dist/esm/tools/search/format.mjs.map +1 -1
  519. package/dist/esm/tools/search/highlights.mjs +0 -16
  520. package/dist/esm/tools/search/highlights.mjs.map +1 -1
  521. package/dist/esm/tools/search/keenable-scraper.mjs +0 -8
  522. package/dist/esm/tools/search/keenable-scraper.mjs.map +1 -1
  523. package/dist/esm/tools/search/keenable-search.mjs +0 -7
  524. package/dist/esm/tools/search/keenable-search.mjs.map +1 -1
  525. package/dist/esm/tools/search/rerankers.mjs +0 -35
  526. package/dist/esm/tools/search/rerankers.mjs.map +1 -1
  527. package/dist/esm/tools/search/schema.mjs +0 -1
  528. package/dist/esm/tools/search/schema.mjs.map +1 -1
  529. package/dist/esm/tools/search/search.mjs +1 -14
  530. package/dist/esm/tools/search/search.mjs.map +1 -1
  531. package/dist/esm/tools/search/serper-scraper.mjs +0 -46
  532. package/dist/esm/tools/search/serper-scraper.mjs.map +1 -1
  533. package/dist/esm/tools/search/tavily-scraper.mjs.map +1 -1
  534. package/dist/esm/tools/search/tavily-search.mjs.map +1 -1
  535. package/dist/esm/tools/search/tool.mjs +0 -25
  536. package/dist/esm/tools/search/tool.mjs.map +1 -1
  537. package/dist/esm/tools/search/utils.mjs +0 -8
  538. package/dist/esm/tools/search/utils.mjs.map +1 -1
  539. package/dist/esm/tools/skillCatalog.mjs +0 -6
  540. package/dist/esm/tools/skillCatalog.mjs.map +1 -1
  541. package/dist/esm/tools/streamedToolCallSeals.mjs +0 -6
  542. package/dist/esm/tools/streamedToolCallSeals.mjs.map +1 -1
  543. package/dist/esm/tools/subagent/SubagentExecutionRegistry.mjs +0 -2
  544. package/dist/esm/tools/subagent/SubagentExecutionRegistry.mjs.map +1 -1
  545. package/dist/esm/tools/subagent/SubagentExecutor.mjs +3 -213
  546. package/dist/esm/tools/subagent/SubagentExecutor.mjs.map +1 -1
  547. package/dist/esm/tools/subagent/SubagentReplay.mjs.map +1 -1
  548. package/dist/esm/tools/subagent/childGraphConfig.mjs +0 -4
  549. package/dist/esm/tools/subagent/childGraphConfig.mjs.map +1 -1
  550. package/dist/esm/tools/subagent/runtimeLimits.mjs.map +1 -1
  551. package/dist/esm/tools/toolOutputReferences.mjs +1 -322
  552. package/dist/esm/tools/toolOutputReferences.mjs.map +1 -1
  553. package/dist/esm/types/hitl.mjs +0 -5
  554. package/dist/esm/types/hitl.mjs.map +1 -1
  555. package/dist/esm/utils/callbacks.mjs.map +1 -1
  556. package/dist/esm/utils/errors.mjs +14 -165
  557. package/dist/esm/utils/errors.mjs.map +1 -1
  558. package/dist/esm/utils/events.mjs +0 -10
  559. package/dist/esm/utils/events.mjs.map +1 -1
  560. package/dist/esm/utils/graph.mjs.map +1 -1
  561. package/dist/esm/utils/handlers.mjs +0 -3
  562. package/dist/esm/utils/handlers.mjs.map +1 -1
  563. package/dist/esm/utils/llm.mjs +0 -1
  564. package/dist/esm/utils/llm.mjs.map +1 -1
  565. package/dist/esm/utils/misc.mjs +0 -16
  566. package/dist/esm/utils/misc.mjs.map +1 -1
  567. package/dist/esm/utils/proxy.mjs +0 -26
  568. package/dist/esm/utils/proxy.mjs.map +1 -1
  569. package/dist/esm/utils/run.mjs +0 -6
  570. package/dist/esm/utils/run.mjs.map +1 -1
  571. package/dist/esm/utils/schema.mjs +0 -5
  572. package/dist/esm/utils/schema.mjs.map +1 -1
  573. package/dist/esm/utils/title.mjs +0 -6
  574. package/dist/esm/utils/title.mjs.map +1 -1
  575. package/dist/esm/utils/tokens.mjs +0 -113
  576. package/dist/esm/utils/tokens.mjs.map +1 -1
  577. package/dist/esm/utils/toolContent.mjs +0 -41
  578. package/dist/esm/utils/toolContent.mjs.map +1 -1
  579. package/dist/esm/utils/truncation.mjs +0 -61
  580. package/dist/esm/utils/truncation.mjs.map +1 -1
  581. package/dist/types/agents/AgentContext.d.ts +3 -3
  582. package/dist/types/agents/__tests__/promptCacheLiveHelpers.d.ts +3 -3
  583. package/dist/types/agents/projection.d.ts +1 -1
  584. package/dist/types/events.d.ts +2 -2
  585. package/dist/types/graphs/Graph.d.ts +11 -11
  586. package/dist/types/graphs/MultiAgentGraph.d.ts +2 -2
  587. package/dist/types/graphs/createGraph.d.ts +4 -4
  588. package/dist/types/graphs/graphFactory.d.ts +1 -1
  589. package/dist/types/hitl/askUserQuestion.d.ts +1 -1
  590. package/dist/types/hitl/askUserQuestions.d.ts +1 -1
  591. package/dist/types/hitl/askUserQuestionsInterrupt.d.ts +1 -1
  592. package/dist/types/hooks/types.d.ts +1 -1
  593. package/dist/types/instrumentation.d.ts +1 -1
  594. package/dist/types/langfuse.d.ts +3 -3
  595. package/dist/types/langfuseConfig.d.ts +2 -2
  596. package/dist/types/langfuseRuntimeContext.d.ts +1 -1
  597. package/dist/types/langfuseRuntimeScope.d.ts +2 -2
  598. package/dist/types/langfuseSpanRegistry.d.ts +1 -1
  599. package/dist/types/langfuseToolOutputTracing.d.ts +3 -3
  600. package/dist/types/llm/anthropic/index.d.ts +1 -1
  601. package/dist/types/llm/bedrock/index.d.ts +1 -1
  602. package/dist/types/llm/bedrock/toolCache.d.ts +2 -2
  603. package/dist/types/llm/contextOverflowRecovery.d.ts +2 -2
  604. package/dist/types/llm/google/index.d.ts +1 -1
  605. package/dist/types/llm/init.d.ts +2 -2
  606. package/dist/types/llm/invoke.d.ts +6 -6
  607. package/dist/types/llm/mistral/index.d.ts +1 -1
  608. package/dist/types/llm/openai/index.d.ts +2 -2
  609. package/dist/types/llm/openrouter/index.d.ts +2 -2
  610. package/dist/types/llm/openrouter/toolCache.d.ts +2 -2
  611. package/dist/types/llm/providers.d.ts +2 -2
  612. package/dist/types/llm/request.d.ts +2 -2
  613. package/dist/types/llm/stream/chunkAdapters.d.ts +1 -1
  614. package/dist/types/llm/streamLimits.d.ts +1 -1
  615. package/dist/types/llm/truncation.d.ts +1 -1
  616. package/dist/types/llm/vertexai/index.d.ts +1 -1
  617. package/dist/types/messages/alternation.d.ts +1 -1
  618. package/dist/types/messages/anthropicToolCache.d.ts +2 -2
  619. package/dist/types/messages/assistantPhase.d.ts +3 -3
  620. package/dist/types/messages/budget.d.ts +1 -1
  621. package/dist/types/messages/cache.d.ts +1 -1
  622. package/dist/types/messages/contextPruning.d.ts +2 -2
  623. package/dist/types/messages/core.d.ts +2 -2
  624. package/dist/types/messages/format.d.ts +2 -2
  625. package/dist/types/messages/ids.d.ts +2 -2
  626. package/dist/types/messages/injected.d.ts +1 -1
  627. package/dist/types/messages/langchain.d.ts +1 -1
  628. package/dist/types/messages/prune.d.ts +3 -3
  629. package/dist/types/openai/index.d.ts +1 -1
  630. package/dist/types/prompts/activityLabel.d.ts +2 -2
  631. package/dist/types/responses/index.d.ts +1 -1
  632. package/dist/types/run.d.ts +3 -3
  633. package/dist/types/session/handlers.d.ts +1 -1
  634. package/dist/types/session/types.d.ts +1 -1
  635. package/dist/types/stream.d.ts +4 -4
  636. package/dist/types/summarization/index.d.ts +1 -1
  637. package/dist/types/summarization/node.d.ts +6 -6
  638. package/dist/types/test/mockTools.d.ts +1 -1
  639. package/dist/types/tools/BashExecutor.d.ts +2 -2
  640. package/dist/types/tools/BashProgrammaticToolCalling.d.ts +2 -2
  641. package/dist/types/tools/CodeExecutor.d.ts +3 -3
  642. package/dist/types/tools/CodeSessionFileSummary.d.ts +1 -1
  643. package/dist/types/tools/ProgrammaticToolCalling.d.ts +2 -2
  644. package/dist/types/tools/ReadFile.d.ts +1 -1
  645. package/dist/types/tools/SkillTool.d.ts +1 -1
  646. package/dist/types/tools/SubagentTool.d.ts +3 -3
  647. package/dist/types/tools/ToolNode.d.ts +5 -5
  648. package/dist/types/tools/ToolSearch.d.ts +2 -2
  649. package/dist/types/tools/cloudflare/CloudflareBridgeRuntime.d.ts +1 -1
  650. package/dist/types/tools/cloudflare/CloudflareProgrammaticToolCalling.d.ts +1 -1
  651. package/dist/types/tools/cloudflare/CloudflareSandboxExecutionEngine.d.ts +2 -2
  652. package/dist/types/tools/cloudflare/CloudflareSandboxTools.d.ts +1 -1
  653. package/dist/types/tools/eagerEventExecution.d.ts +1 -1
  654. package/dist/types/tools/handlers.d.ts +3 -3
  655. package/dist/types/tools/intentArg.d.ts +1 -1
  656. package/dist/types/tools/local/CompileCheckTool.d.ts +2 -2
  657. package/dist/types/tools/local/FileCheckpointer.d.ts +1 -1
  658. package/dist/types/tools/local/LocalCodingTools.d.ts +2 -2
  659. package/dist/types/tools/local/LocalExecutionEngine.d.ts +1 -1
  660. package/dist/types/tools/local/LocalExecutionTools.d.ts +1 -1
  661. package/dist/types/tools/local/LocalProgrammaticToolCalling.d.ts +1 -1
  662. package/dist/types/tools/local/bashAst.d.ts +1 -1
  663. package/dist/types/tools/local/resolveLocalExecutionTools.d.ts +1 -1
  664. package/dist/types/tools/local/syntaxCheck.d.ts +1 -1
  665. package/dist/types/tools/ptcTimeout.d.ts +1 -1
  666. package/dist/types/tools/schema.d.ts +1 -1
  667. package/dist/types/tools/search/anthropic.d.ts +1 -1
  668. package/dist/types/tools/skillCatalog.d.ts +1 -1
  669. package/dist/types/tools/subagent/SubagentExecutor.d.ts +5 -5
  670. package/dist/types/tools/subagent/SubagentReplay.d.ts +3 -3
  671. package/dist/types/tools/subagent/childGraphConfig.d.ts +2 -2
  672. package/dist/types/types/activityLabel.d.ts +3 -3
  673. package/dist/types/types/graph.d.ts +7 -7
  674. package/dist/types/types/llm.d.ts +9 -9
  675. package/dist/types/types/run.d.ts +7 -7
  676. package/dist/types/types/stream.d.ts +5 -5
  677. package/dist/types/types/summarize.d.ts +2 -2
  678. package/dist/types/types/tools.d.ts +5 -5
  679. package/dist/types/utils/__tests__/fixtures/contextOverflowSignatures.d.ts +1 -1
  680. package/dist/types/utils/errors.d.ts +1 -1
  681. package/dist/types/utils/events.d.ts +1 -1
  682. package/dist/types/utils/handlers.d.ts +3 -3
  683. package/dist/types/utils/llm.d.ts +1 -1
  684. package/dist/types/utils/llmConfig.d.ts +1 -1
  685. package/dist/types/utils/title.d.ts +1 -1
  686. package/package.json +10 -3
  687. package/src/llm/google/utils/common.ts +6 -4
  688. package/src/__tests__/stream.eagerArgsDivergence.test.ts +0 -911
  689. package/src/__tests__/stream.eagerEventExecution.test.ts +0 -5046
  690. package/src/__tests__/stream.streamLimits.test.ts +0 -1982
  691. package/src/agents/__tests__/AgentContext.anthropic.live.test.ts +0 -448
  692. package/src/agents/__tests__/AgentContext.bedrock.live.test.ts +0 -655
  693. package/src/agents/__tests__/AgentContext.openrouter.live.test.ts +0 -128
  694. package/src/agents/__tests__/AgentContext.overflow.test.ts +0 -205
  695. package/src/agents/__tests__/AgentContext.test.ts +0 -2425
  696. package/src/agents/__tests__/projection.test.ts +0 -73
  697. package/src/agents/__tests__/promptCacheLiveHelpers.ts +0 -175
  698. package/src/aggregator.test.ts +0 -1214
  699. package/src/graphs/__tests__/Graph.breakerLifecycle.test.ts +0 -273
  700. package/src/graphs/__tests__/Graph.closeRunStep.test.ts +0 -385
  701. package/src/graphs/__tests__/Graph.contextOverflow.test.ts +0 -1766
  702. package/src/graphs/__tests__/Graph.preemptSignal.test.ts +0 -126
  703. package/src/graphs/__tests__/Graph.reasoning.test.ts +0 -1717
  704. package/src/graphs/__tests__/Graph.subagentResumeState.test.ts +0 -80
  705. package/src/graphs/__tests__/MultiAgentGraph.test.ts +0 -177
  706. package/src/graphs/__tests__/composition.smoke.test.ts +0 -509
  707. package/src/graphs/__tests__/createGraph.test.ts +0 -206
  708. package/src/hooks/__tests__/HookRegistry.test.ts +0 -334
  709. package/src/hooks/__tests__/compactHooks.test.ts +0 -250
  710. package/src/hooks/__tests__/createToolPolicyHook.test.ts +0 -268
  711. package/src/hooks/__tests__/createWorkspacePolicyHook.test.ts +0 -405
  712. package/src/hooks/__tests__/executeHooks.test.ts +0 -1294
  713. package/src/hooks/__tests__/integration.test.ts +0 -337
  714. package/src/hooks/__tests__/matchers.test.ts +0 -238
  715. package/src/hooks/__tests__/preemptBoundary.test.ts +0 -152
  716. package/src/hooks/__tests__/toolHooks.test.ts +0 -669
  717. package/src/llm/__tests__/contextOverflowRecovery.test.ts +0 -401
  718. package/src/llm/__tests__/fallbackOverflow.test.ts +0 -287
  719. package/src/llm/anthropic/Jacob_Lee_Resume_2023.pdf +0 -0
  720. package/src/llm/anthropic/inherited-content-utils.spec.ts +0 -249
  721. package/src/llm/anthropic/inherited-stream-events.spec.ts +0 -1259
  722. package/src/llm/anthropic/inherited-strict.spec.ts +0 -302
  723. package/src/llm/anthropic/llm.spec.ts +0 -3394
  724. package/src/llm/anthropic/utils/cross-provider-reasoning.test.ts +0 -383
  725. package/src/llm/anthropic/utils/cross-provider-server-tools.test.ts +0 -110
  726. package/src/llm/anthropic/utils/server-tool-inputs.test.ts +0 -508
  727. package/src/llm/anthropic/utils/streaming-tool-input.test.ts +0 -361
  728. package/src/llm/anthropic/utils/stripPrefillCache.test.ts +0 -111
  729. package/src/llm/anthropic/utils/tool-id-normalization.test.ts +0 -287
  730. package/src/llm/bedrock/inherited-cache.spec.ts +0 -144
  731. package/src/llm/bedrock/inherited.spec.ts +0 -724
  732. package/src/llm/bedrock/llm.spec.ts +0 -1533
  733. package/src/llm/bedrock/streamSealDispatch.test.ts +0 -331
  734. package/src/llm/bedrock/toolCache.test.ts +0 -194
  735. package/src/llm/bedrock/utils/cross-provider-reasoning.test.ts +0 -131
  736. package/src/llm/bedrock/utils/cross-provider-server-tools.test.ts +0 -122
  737. package/src/llm/bedrock/utils/message_inputs.test.ts +0 -650
  738. package/src/llm/bedrock/utils/message_outputs.test.ts +0 -85
  739. package/src/llm/bedrock/utils/toolResultCachePoint.test.ts +0 -118
  740. package/src/llm/custom-chat-models.smoke.test.ts +0 -1966
  741. package/src/llm/google/data/gettysburg10.wav +0 -0
  742. package/src/llm/google/data/hotdog.jpg +0 -0
  743. package/src/llm/google/inherited-stream-events.spec.ts +0 -350
  744. package/src/llm/google/llm.spec.ts +0 -1388
  745. package/src/llm/google/streamSmoothing.test.ts +0 -121
  746. package/src/llm/google/utils/common.test.ts +0 -185
  747. package/src/llm/invoke.alternation.test.ts +0 -87
  748. package/src/llm/invoke.handoffCue.test.ts +0 -112
  749. package/src/llm/invoke.streamLimits.test.ts +0 -142
  750. package/src/llm/invoke.test.ts +0 -1198
  751. package/src/llm/mistral/streamSmoothing.test.ts +0 -97
  752. package/src/llm/openai/cacheWriteTokens.test.ts +0 -112
  753. package/src/llm/openai/contentBlocks.test.ts +0 -381
  754. package/src/llm/openai/deepseek.test.ts +0 -747
  755. package/src/llm/openai/inherited-deepseek.spec.ts +0 -347
  756. package/src/llm/openai/inherited-xai.spec.ts +0 -416
  757. package/src/llm/openai/llm.spec.ts +0 -1774
  758. package/src/llm/openai/managedRequests.test.ts +0 -182
  759. package/src/llm/openai/sequentialToolCallSeals.test.ts +0 -199
  760. package/src/llm/openai/streamMetadata.spec.ts +0 -86
  761. package/src/llm/openai/streamMetadataDedup.spec.ts +0 -166
  762. package/src/llm/openai/utils/isReasoningModel.test.ts +0 -90
  763. package/src/llm/openai/utils/messages.test.ts +0 -488
  764. package/src/llm/openrouter/reasoning.test.ts +0 -561
  765. package/src/llm/openrouter/toolCache.test.ts +0 -134
  766. package/src/llm/preempt.test.ts +0 -323
  767. package/src/llm/stream/chunkAdapters.test.ts +0 -202
  768. package/src/llm/stream/reassembly.test.ts +0 -241
  769. package/src/llm/stream/smoother.bench.test.ts +0 -155
  770. package/src/llm/stream/smoother.test.ts +0 -519
  771. package/src/llm/streamLimits.test.ts +0 -450
  772. package/src/llm/truncation.test.ts +0 -242
  773. package/src/llm/vertexai/fixThoughtSignatures.test.ts +0 -154
  774. package/src/llm/vertexai/inherited-stream-events.spec.ts +0 -271
  775. package/src/llm/vertexai/llm.spec.ts +0 -159
  776. package/src/llm/vertexai/repairUsageMetadata.test.ts +0 -54
  777. package/src/llm/vertexai/sealStreamedToolCalls.test.ts +0 -88
  778. package/src/llm/vertexai/streamSealDispatch.test.ts +0 -148
  779. package/src/llm/vertexai/streamSmoothing.test.ts +0 -109
  780. package/src/messages/__tests__/anthropicToolCache.test.ts +0 -339
  781. package/src/messages/__tests__/observationMasking.test.ts +0 -312
  782. package/src/messages/__tests__/recency.test.ts +0 -267
  783. package/src/messages/__tests__/tools.test.ts +0 -473
  784. package/src/messages/alternation.test.ts +0 -212
  785. package/src/messages/assistantPhase.test.ts +0 -75
  786. package/src/messages/cache.tail.test.ts +0 -533
  787. package/src/messages/cache.test.ts +0 -2166
  788. package/src/messages/content.test.ts +0 -362
  789. package/src/messages/contextPruning.test.ts +0 -184
  790. package/src/messages/ensureThinkingBlock.test.ts +0 -1427
  791. package/src/messages/foldToollessToolBlocks.test.ts +0 -596
  792. package/src/messages/formatAgentMessages.reducer.test.ts +0 -162
  793. package/src/messages/formatAgentMessages.skills.test.ts +0 -513
  794. package/src/messages/formatAgentMessages.steer.test.ts +0 -598
  795. package/src/messages/formatAgentMessages.test.ts +0 -8111
  796. package/src/messages/formatAgentMessages.tools.test.ts +0 -522
  797. package/src/messages/formatMessage.test.ts +0 -693
  798. package/src/messages/handoffCue.test.ts +0 -96
  799. package/src/messages/injected.test.ts +0 -107
  800. package/src/messages/labelContentByAgent.test.ts +0 -962
  801. package/src/messages/reducer.spec.ts +0 -32
  802. package/src/messages/shiftIndexTokenCountMap.test.ts +0 -81
  803. package/src/messages/tailCacheConversion.test.ts +0 -161
  804. package/src/openai/__tests__/openai.test.ts +0 -337
  805. package/src/responses/__tests__/responses.test.ts +0 -652
  806. package/src/scripts/abort.ts +0 -157
  807. package/src/scripts/activity-labels/captured.json +0 -56
  808. package/src/scripts/activity-labels/checks.cjs +0 -205
  809. package/src/scripts/activity-labels/corpus.cjs +0 -473
  810. package/src/scripts/activity-labels/report.cjs +0 -203
  811. package/src/scripts/activity-labels/rescore.cjs +0 -102
  812. package/src/scripts/activity-labels/run.ts +0 -705
  813. package/src/scripts/activity-labels/variants.ts +0 -71
  814. package/src/scripts/ant_web_search.ts +0 -159
  815. package/src/scripts/ant_web_search_edge_case.ts +0 -163
  816. package/src/scripts/ant_web_search_error_edge_case.ts +0 -149
  817. package/src/scripts/args.ts +0 -48
  818. package/src/scripts/bedrock-cache-debug.ts +0 -250
  819. package/src/scripts/bedrock-content-aggregation-test.ts +0 -266
  820. package/src/scripts/bedrock-merge-test.ts +0 -107
  821. package/src/scripts/bedrock-parallel-tools-test.ts +0 -204
  822. package/src/scripts/bench-prompt-cache.ts +0 -479
  823. package/src/scripts/caching.ts +0 -132
  824. package/src/scripts/cli.ts +0 -172
  825. package/src/scripts/cli2.ts +0 -133
  826. package/src/scripts/cli3.ts +0 -184
  827. package/src/scripts/cli4.ts +0 -191
  828. package/src/scripts/cli5.ts +0 -191
  829. package/src/scripts/code_exec.ts +0 -214
  830. package/src/scripts/code_exec_files.ts +0 -237
  831. package/src/scripts/code_exec_multi_session.ts +0 -237
  832. package/src/scripts/code_exec_ptc.ts +0 -335
  833. package/src/scripts/code_exec_session.ts +0 -283
  834. package/src/scripts/code_exec_simple.ts +0 -148
  835. package/src/scripts/compare_pi_vs_ours.ts +0 -1259
  836. package/src/scripts/content.ts +0 -139
  837. package/src/scripts/context-overflow-probe.ts +0 -997
  838. package/src/scripts/empty_input.ts +0 -137
  839. package/src/scripts/handoff-test.ts +0 -134
  840. package/src/scripts/local_engine.ts +0 -166
  841. package/src/scripts/local_engine_checkpointer.ts +0 -205
  842. package/src/scripts/local_engine_compile.ts +0 -263
  843. package/src/scripts/local_engine_hooks.ts +0 -226
  844. package/src/scripts/local_engine_image.ts +0 -201
  845. package/src/scripts/local_engine_ptc.ts +0 -151
  846. package/src/scripts/local_engine_workspace.ts +0 -258
  847. package/src/scripts/memory.ts +0 -107
  848. package/src/scripts/multi-agent-chain.ts +0 -332
  849. package/src/scripts/multi-agent-conditional.ts +0 -222
  850. package/src/scripts/multi-agent-document-review-chain.ts +0 -198
  851. package/src/scripts/multi-agent-hybrid-flow.ts +0 -311
  852. package/src/scripts/multi-agent-parallel-start.ts +0 -265
  853. package/src/scripts/multi-agent-parallel.ts +0 -395
  854. package/src/scripts/multi-agent-sequence.ts +0 -217
  855. package/src/scripts/multi-agent-subagent.ts +0 -246
  856. package/src/scripts/multi-agent-supervisor.ts +0 -366
  857. package/src/scripts/multi-agent-test.ts +0 -187
  858. package/src/scripts/openrouter_prompt_cache_live.ts +0 -310
  859. package/src/scripts/parallel-asymmetric-tools-test.ts +0 -275
  860. package/src/scripts/parallel-full-metadata-test.ts +0 -241
  861. package/src/scripts/parallel-tools-test.ts +0 -341
  862. package/src/scripts/preempt-probe.ts +0 -330
  863. package/src/scripts/preempt-scenarios.ts +0 -388
  864. package/src/scripts/programmatic_exec.ts +0 -387
  865. package/src/scripts/programmatic_exec_agent.ts +0 -232
  866. package/src/scripts/search.ts +0 -147
  867. package/src/scripts/sequential-full-metadata-test.ts +0 -198
  868. package/src/scripts/session_live.ts +0 -548
  869. package/src/scripts/simple.ts +0 -226
  870. package/src/scripts/single-agent-metadata-test.ts +0 -196
  871. package/src/scripts/stream.ts +0 -141
  872. package/src/scripts/subagent-configurable-inheritance.ts +0 -252
  873. package/src/scripts/subagent-event-driven-debug.ts +0 -190
  874. package/src/scripts/subagent-tools-debug.ts +0 -160
  875. package/src/scripts/subagent-usage-sink.ts +0 -176
  876. package/src/scripts/summarization-recency.ts +0 -462
  877. package/src/scripts/test-custom-prompt-key.ts +0 -145
  878. package/src/scripts/test-handoff-input.ts +0 -170
  879. package/src/scripts/test-handoff-preamble.ts +0 -278
  880. package/src/scripts/test-handoff-steering.ts +0 -430
  881. package/src/scripts/test-multi-agent-list-handoff.ts +0 -418
  882. package/src/scripts/test-parallel-agent-labeling.ts +0 -327
  883. package/src/scripts/test-parallel-handoffs.ts +0 -292
  884. package/src/scripts/test-thinking-handoff-bedrock.ts +0 -154
  885. package/src/scripts/test-thinking-handoff.ts +0 -156
  886. package/src/scripts/test-thinking-to-thinking-handoff-bedrock.ts +0 -166
  887. package/src/scripts/test-tool-before-handoff-role-order.ts +0 -276
  888. package/src/scripts/test-tools-before-handoff.ts +0 -222
  889. package/src/scripts/test_code_api.ts +0 -354
  890. package/src/scripts/thinking-bedrock.ts +0 -160
  891. package/src/scripts/thinking-vertexai.ts +0 -168
  892. package/src/scripts/thinking.ts +0 -172
  893. package/src/scripts/tool_search.ts +0 -153
  894. package/src/scripts/tools.ts +0 -163
  895. package/src/session/__tests__/JsonlSessionStore.test.ts +0 -1463
  896. package/src/session/__tests__/handlers.test.ts +0 -161
  897. package/src/specs/activity-label-observability.live.test.ts +0 -262
  898. package/src/specs/activity-label-observability.test.ts +0 -167
  899. package/src/specs/activity-label-prompt.test.ts +0 -359
  900. package/src/specs/activity-label-trace-seed.test.ts +0 -47
  901. package/src/specs/activity-phase-label.test.ts +0 -306
  902. package/src/specs/agent-handoffs.live.test.ts +0 -140
  903. package/src/specs/agent-handoffs.test.ts +0 -2465
  904. package/src/specs/anthropic.simple.test.ts +0 -453
  905. package/src/specs/ask-user-question-batch.test.ts +0 -289
  906. package/src/specs/ask-user-questions.live.test.ts +0 -185
  907. package/src/specs/ask-user-questions.test.ts +0 -293
  908. package/src/specs/azure.simple.test.ts +0 -502
  909. package/src/specs/bedrock-toolless.live.test.ts +0 -123
  910. package/src/specs/bedrock-truncation.live.test.ts +0 -191
  911. package/src/specs/cache.simple.test.ts +0 -416
  912. package/src/specs/context-accuracy.live.test.ts +0 -409
  913. package/src/specs/context-overflow-recovery.live.test.ts +0 -213
  914. package/src/specs/context-usage-event.test.ts +0 -117
  915. package/src/specs/context-usage.live.test.ts +0 -297
  916. package/src/specs/custom-event-await.test.ts +0 -304
  917. package/src/specs/deepseek.simple.test.ts +0 -290
  918. package/src/specs/deterministic-trace-id.test.ts +0 -43
  919. package/src/specs/discovered-tools.test.ts +0 -217
  920. package/src/specs/durability-checkpoint.integration.test.ts +0 -243
  921. package/src/specs/graph-subagent.live.test.ts +0 -242
  922. package/src/specs/graph-subagent.test.ts +0 -322
  923. package/src/specs/handoffCue.test.ts +0 -165
  924. package/src/specs/langfuse-callbacks.test.ts +0 -1578
  925. package/src/specs/langfuse-config.test.ts +0 -247
  926. package/src/specs/langfuse-instrumentation.test.ts +0 -393
  927. package/src/specs/langfuse-metadata.test.ts +0 -245
  928. package/src/specs/langfuse-routing.integration.test.ts +0 -844
  929. package/src/specs/langfuse-runtime-context.test.ts +0 -92
  930. package/src/specs/langfuse-span-registry.test.ts +0 -87
  931. package/src/specs/langfuse-tool-output-tracing.test.ts +0 -1858
  932. package/src/specs/langfuse-trace-shaping.test.ts +0 -591
  933. package/src/specs/moonshot.simple.test.ts +0 -367
  934. package/src/specs/multi-agent-summarization.test.ts +0 -396
  935. package/src/specs/openai.simple.test.ts +0 -315
  936. package/src/specs/openrouter.simple.test.ts +0 -275
  937. package/src/specs/preemptSeal.test.ts +0 -678
  938. package/src/specs/prune.test.ts +0 -3741
  939. package/src/specs/reasoning.test.ts +0 -201
  940. package/src/specs/run-step-timestamps.test.ts +0 -414
  941. package/src/specs/spec.utils.ts +0 -15
  942. package/src/specs/subagent.test.ts +0 -864
  943. package/src/specs/summarization-unit.test.ts +0 -973
  944. package/src/specs/summarization.test.ts +0 -3823
  945. package/src/specs/summarize-prune.test.ts +0 -376
  946. package/src/specs/thinking-handoff.test.ts +0 -621
  947. package/src/specs/thinking-prune.test.ts +0 -827
  948. package/src/specs/token-accounting-e2e.test.ts +0 -1034
  949. package/src/specs/token-accounting-pipeline.test.ts +0 -1008
  950. package/src/specs/token-distribution-edge-case.test.ts +0 -315
  951. package/src/specs/token-memoization.test.ts +0 -40
  952. package/src/specs/tokens.test.ts +0 -1000
  953. package/src/specs/tool-error-resume.test.ts +0 -194
  954. package/src/specs/tool-error.test.ts +0 -198
  955. package/src/specs/vllm-reasoning-toolcalls.test.ts +0 -340
  956. package/src/stream.dispatch.test.ts +0 -63
  957. package/src/stream.test.ts +0 -144
  958. package/src/summarization/__tests__/aggregator.test.ts +0 -236
  959. package/src/summarization/__tests__/node.test.ts +0 -1996
  960. package/src/summarization/__tests__/trigger.test.ts +0 -149
  961. package/src/summarization/chunkHandler.test.ts +0 -196
  962. package/src/test/mockTools.ts +0 -386
  963. package/src/tools/Calculator.test.ts +0 -278
  964. package/src/tools/__tests__/BashExecutor.test.ts +0 -108
  965. package/src/tools/__tests__/CloudflareSandboxExecution.test.ts +0 -939
  966. package/src/tools/__tests__/CodeApiAuthHeaders.test.ts +0 -858
  967. package/src/tools/__tests__/CodeExecutor.stateful.test.ts +0 -124
  968. package/src/tools/__tests__/LocalExecutionRoots.test.ts +0 -8
  969. package/src/tools/__tests__/LocalExecutionTools.test.ts +0 -2733
  970. package/src/tools/__tests__/ProgrammaticToolCalling.integration.test.ts +0 -318
  971. package/src/tools/__tests__/ProgrammaticToolCalling.test.ts +0 -1557
  972. package/src/tools/__tests__/ReadFile.test.ts +0 -44
  973. package/src/tools/__tests__/SkillTool.test.ts +0 -442
  974. package/src/tools/__tests__/SubagentExecutor.test.ts +0 -3728
  975. package/src/tools/__tests__/SubagentReplay.test.ts +0 -329
  976. package/src/tools/__tests__/SubagentTool.test.ts +0 -149
  977. package/src/tools/__tests__/ToolNode.breakerSignal.test.ts +0 -595
  978. package/src/tools/__tests__/ToolNode.eagerEventExecution.test.ts +0 -1191
  979. package/src/tools/__tests__/ToolNode.invalidToolCalls.test.ts +0 -757
  980. package/src/tools/__tests__/ToolNode.langfuse.test.ts +0 -57
  981. package/src/tools/__tests__/ToolNode.onResultCompletion.test.ts +0 -736
  982. package/src/tools/__tests__/ToolNode.outputReferences.test.ts +0 -1710
  983. package/src/tools/__tests__/ToolNode.runtimeState.test.ts +0 -120
  984. package/src/tools/__tests__/ToolNode.session.test.ts +0 -1352
  985. package/src/tools/__tests__/ToolNode.streamLimits.test.ts +0 -69
  986. package/src/tools/__tests__/ToolSearch.integration.test.ts +0 -161
  987. package/src/tools/__tests__/ToolSearch.test.ts +0 -1227
  988. package/src/tools/__tests__/annotateMessagesForLLM.test.ts +0 -561
  989. package/src/tools/__tests__/directToolHITLResumeScope.test.ts +0 -980
  990. package/src/tools/__tests__/directToolHooks.test.ts +0 -700
  991. package/src/tools/__tests__/eagerEventExecution.session.test.ts +0 -92
  992. package/src/tools/__tests__/handlers.test.ts +0 -997
  993. package/src/tools/__tests__/hitl.test.ts +0 -4663
  994. package/src/tools/__tests__/intentArg.test.ts +0 -357
  995. package/src/tools/__tests__/intentCoverage.test.ts +0 -139
  996. package/src/tools/__tests__/localToolNames.test.ts +0 -75
  997. package/src/tools/__tests__/skillCatalog.test.ts +0 -161
  998. package/src/tools/__tests__/subagentHooks.test.ts +0 -1651
  999. package/src/tools/__tests__/toolOutputReferences.test.ts +0 -515
  1000. package/src/tools/__tests__/workspaceSeam.test.ts +0 -147
  1001. package/src/tools/local/__tests__/FileCheckpointer.test.ts +0 -162
  1002. package/src/tools/local/__tests__/editStrategies.test.ts +0 -134
  1003. package/src/tools/search/content.test.ts +0 -173
  1004. package/src/tools/search/crw.test.ts +0 -836
  1005. package/src/tools/search/format.test.ts +0 -242
  1006. package/src/tools/search/http-agent.test.ts +0 -133
  1007. package/src/tools/search/jina-reranker.test.ts +0 -306
  1008. package/src/tools/search/keenable-scraper.test.ts +0 -153
  1009. package/src/tools/search/keenable.test.ts +0 -183
  1010. package/src/tools/search/outcome.test.ts +0 -90
  1011. package/src/tools/search/output.md +0 -2775
  1012. package/src/tools/search/rag-api-reranker.test.ts +0 -891
  1013. package/src/tools/search/source-processing.test.ts +0 -516
  1014. package/src/tools/search/tavily.test.ts +0 -965
  1015. package/src/tools/search/test.html +0 -884
  1016. package/src/tools/search/test.md +0 -643
  1017. package/src/tools/subagent/__tests__/SubagentExecutionRegistry.test.ts +0 -637
  1018. package/src/tools/subagent/__tests__/SubagentExecutor.lazy.test.ts +0 -3054
  1019. package/src/tools/subagent/__tests__/childGraphConfig.test.ts +0 -521
  1020. package/src/utils/__tests__/apportion.test.ts +0 -32
  1021. package/src/utils/__tests__/errors.test.ts +0 -270
  1022. package/src/utils/__tests__/fixtures/contextOverflowSignatures.ts +0 -336
  1023. package/src/utils/__tests__/redactSecrets.test.ts +0 -56
  1024. package/src/utils/__tests__/truncation.test.ts +0 -66
  1025. package/src/utils/llm.test.ts +0 -18
  1026. package/src/utils/proxy.test.ts +0 -176
  1027. package/src/utils/toolContent.test.ts +0 -1432
@@ -1,3394 +0,0 @@
1
- /* eslint-disable no-process-env */
2
- import { config } from 'dotenv';
3
- config();
4
- import { expect, test } from '@jest/globals';
5
- import * as fs from 'fs/promises';
6
- import {
7
- AIMessage,
8
- AIMessageChunk,
9
- HumanMessage,
10
- SystemMessage,
11
- ToolMessage,
12
- } from '@langchain/core/messages';
13
- import { ChatPromptValue } from '@langchain/core/prompt_values';
14
- import {
15
- PromptTemplate,
16
- ChatPromptTemplate,
17
- AIMessagePromptTemplate,
18
- HumanMessagePromptTemplate,
19
- SystemMessagePromptTemplate,
20
- } from '@langchain/core/prompts';
21
- import { CallbackManager } from '@langchain/core/callbacks/manager';
22
- import { concat } from '@langchain/core/utils/stream';
23
- import type Anthropic from '@anthropic-ai/sdk';
24
- import { AnthropicVertex } from '@anthropic-ai/vertex-sdk';
25
- import { tool } from '@langchain/core/tools';
26
- import { z } from 'zod';
27
- import type { BaseLanguageModelInput } from '@langchain/core/language_models/base';
28
- import type {
29
- BaseMessage,
30
- ContentBlock,
31
- MessageContentComplex,
32
- } from '@langchain/core/messages';
33
- import { toLangChainContent } from '@/messages/langchain';
34
- import { formatAgentMessages } from '@/messages/format';
35
- import { Constants, ContentTypes, GraphEvents, Providers } from '@/common';
36
- import { _documentsInParams, CustomAnthropic as ChatAnthropic } from './index';
37
- import { partitionAndMarkAnthropicToolCache } from '@/messages/anthropicToolCache';
38
- import { ChatModelStreamHandler, createContentAggregator } from '@/stream';
39
- import { ModelEndHandler, ToolEndHandler } from '@/events';
40
- import { Run } from '@/run';
41
- import type { CustomAnthropicCallOptions } from './index';
42
- import type {
43
- AnthropicContextManagementConfigParam,
44
- AnthropicMessageCreateParams,
45
- AnthropicMessageStreamEvent,
46
- AnthropicMessageResponse,
47
- AnthropicOutputConfig,
48
- AnthropicRequestOptions,
49
- AnthropicStreamingMessageCreateParams,
50
- AnthropicThinkingConfigParam,
51
- ChatAnthropicContentBlock,
52
- } from './types';
53
- import type {
54
- AnthropicClientOptions,
55
- IState,
56
- MessageContentComplex as LibreChatContentBlock,
57
- MessageDeltaEvent,
58
- ReasoningDeltaEvent,
59
- RunConfig,
60
- RunStep,
61
- RunStepDeltaEvent,
62
- SharedLLMConfig,
63
- StreamEventData,
64
- ToolEndEvent,
65
- TPayload,
66
- } from '@/types';
67
- import {
68
- _convertMessagesToAnthropicPayload,
69
- modelDisallowsAssistantPrefill,
70
- stripUnsupportedAssistantPrefill,
71
- } from './utils/message_inputs';
72
- import {
73
- _makeMessageChunkFromAnthropicEvent,
74
- getAnthropicUsageMetadata,
75
- } from './utils/message_outputs';
76
- jest.setTimeout(120000);
77
-
78
- async function invoke(
79
- chat: ChatAnthropic,
80
- invocationType: string,
81
- input: BaseLanguageModelInput
82
- ): Promise<AIMessageChunk | AIMessage> {
83
- if (invocationType === 'stream') {
84
- let output: AIMessageChunk | undefined;
85
-
86
- const stream = await chat.stream(input);
87
-
88
- for await (const chunk of stream) {
89
- if (!output) {
90
- output = chunk;
91
- } else {
92
- output = output.concat(chunk);
93
- }
94
- }
95
-
96
- return output!;
97
- }
98
-
99
- return chat.invoke(input);
100
- }
101
-
102
- // use this for tests involving "extended thinking"
103
- const extendedThinkingModelName = 'claude-sonnet-4-5-20250929';
104
-
105
- // use this for tests involving citations
106
- const citationsModelName = 'claude-sonnet-4-5-20250929';
107
-
108
- // use this for tests involving PDF documents
109
- const pdfModelName = 'claude-haiku-4-5-20251001';
110
-
111
- const remoteImageUrl =
112
- 'https://raw.githubusercontent.com/langchain-ai/langchainjs/main/libs/providers/langchain-google-genai/src/tests/data/hotdog.jpg';
113
-
114
- // Use this model for all other tests
115
- const modelName = 'claude-haiku-4-5-20251001';
116
- const webSearchModelName =
117
- process.env.ANTHROPIC_WEB_SEARCH_MODEL ?? 'claude-opus-4-7';
118
-
119
- type AnthropicThinkingResponseBlock = Anthropic.Messages.ThinkingBlock & {
120
- index?: number;
121
- };
122
-
123
- type AnthropicRedactedThinkingResponseBlock =
124
- Anthropic.Messages.RedactedThinkingBlock & {
125
- index?: number;
126
- };
127
-
128
- type AnthropicOutputConfigWithTaskBudget = AnthropicOutputConfig & {
129
- task_budget: {
130
- type: 'tokens';
131
- total: number;
132
- };
133
- };
134
-
135
- type LangChainErrorWithCode = {
136
- lc_error_code?: string;
137
- };
138
-
139
- type CitationContentBlock = ContentBlock & {
140
- citations: Array<{
141
- type?: string;
142
- source?: unknown;
143
- }>;
144
- };
145
-
146
- type CompactionContentBlock = ContentBlock & {
147
- type: 'compaction';
148
- content: string;
149
- };
150
-
151
- type AnthropicContentBlockWithId = ContentBlock & {
152
- id?: unknown;
153
- input?: unknown;
154
- name?: unknown;
155
- };
156
-
157
- function getLangChainErrorCode(error: unknown): string | undefined {
158
- if (typeof error !== 'object' || error == null) {
159
- return undefined;
160
- }
161
-
162
- if (!('lc_error_code' in error)) {
163
- return undefined;
164
- }
165
-
166
- const { lc_error_code } = error as LangChainErrorWithCode;
167
- return typeof lc_error_code === 'string' ? lc_error_code : undefined;
168
- }
169
-
170
- function expectContentArray<T>(content: string | T[]): T[] {
171
- expect(Array.isArray(content)).toBe(true);
172
- if (!Array.isArray(content)) {
173
- throw new Error('Expected array content');
174
- }
175
- return content;
176
- }
177
-
178
- function expectDefined<T>(value: T | undefined): T {
179
- expect(value).toBeDefined();
180
- if (value === undefined) {
181
- throw new Error('Expected defined value');
182
- }
183
- return value;
184
- }
185
-
186
- function isThinkingBlock(
187
- block: unknown
188
- ): block is AnthropicThinkingResponseBlock {
189
- return (
190
- typeof block === 'object' &&
191
- block !== null &&
192
- 'type' in block &&
193
- block.type === 'thinking'
194
- );
195
- }
196
-
197
- function isRedactedThinkingBlock(
198
- block: unknown
199
- ): block is AnthropicRedactedThinkingResponseBlock {
200
- return (
201
- typeof block === 'object' &&
202
- block !== null &&
203
- 'type' in block &&
204
- block.type === 'redacted_thinking'
205
- );
206
- }
207
-
208
- function isReasoningContentBlock(
209
- block: ContentBlock
210
- ): block is ContentBlock.Reasoning {
211
- return block.type === 'reasoning';
212
- }
213
-
214
- function isTextContentBlock(block: ContentBlock): block is ContentBlock.Text {
215
- return block.type === 'text';
216
- }
217
-
218
- function hasCitations(block: ContentBlock): block is CitationContentBlock {
219
- if (!('citations' in block)) {
220
- return false;
221
- }
222
-
223
- const { citations } = block as { citations?: unknown };
224
- return Array.isArray(citations) && citations.length > 0;
225
- }
226
-
227
- function isCompactionBlock(
228
- block: ContentBlock
229
- ): block is CompactionContentBlock {
230
- if (block.type !== 'compaction') {
231
- return false;
232
- }
233
-
234
- const { content } = block as { content?: unknown };
235
- return typeof content === 'string';
236
- }
237
-
238
- function isServerToolUseBlock(
239
- block: ContentBlock
240
- ): block is AnthropicContentBlockWithId {
241
- return (
242
- block.type === 'server_tool_use' &&
243
- typeof (block as AnthropicContentBlockWithId).id === 'string' &&
244
- ((block as AnthropicContentBlockWithId).id as string).startsWith(
245
- Constants.ANTHROPIC_SERVER_TOOL_PREFIX
246
- )
247
- );
248
- }
249
-
250
- function expectAnthropicPayloadContentIsNonEmpty(
251
- payload: AnthropicMessageCreateParams
252
- ): void {
253
- for (const message of payload.messages) {
254
- if (typeof message.content === 'string') {
255
- expect(message.content.trim().length).toBeGreaterThan(0);
256
- continue;
257
- }
258
-
259
- expect(message.content.length).toBeGreaterThan(0);
260
- for (const block of message.content) {
261
- if (block.type !== 'text') {
262
- continue;
263
- }
264
- expect(block.text.trim().length).toBeGreaterThan(0);
265
- }
266
- }
267
- }
268
-
269
- function expectNoDanglingServerToolUses(
270
- payload: AnthropicMessageCreateParams
271
- ): void {
272
- for (const message of payload.messages) {
273
- if (typeof message.content === 'string') {
274
- continue;
275
- }
276
-
277
- const serverToolResultIds = new Set(
278
- message.content
279
- .map((block) =>
280
- 'tool_use_id' in block &&
281
- typeof block.tool_use_id === 'string' &&
282
- block.tool_use_id.startsWith(Constants.ANTHROPIC_SERVER_TOOL_PREFIX)
283
- ? block.tool_use_id
284
- : undefined
285
- )
286
- .filter((id): id is string => id != null)
287
- );
288
-
289
- for (const block of message.content) {
290
- if (block.type !== 'server_tool_use') {
291
- continue;
292
- }
293
- expect(serverToolResultIds.has(block.id)).toBe(true);
294
- }
295
- }
296
- }
297
-
298
- function getPromptCachedWebSearchTools(): Parameters<
299
- ChatAnthropic['bindTools']
300
- >[0] {
301
- const tools = partitionAndMarkAnthropicToolCache(
302
- [
303
- {
304
- type: 'web_search_20250305',
305
- name: 'web_search',
306
- max_uses: 3,
307
- },
308
- ] as never,
309
- () => false
310
- );
311
- return tools as Parameters<ChatAnthropic['bindTools']>[0];
312
- }
313
-
314
- function getWebSearchTool(): {
315
- type: 'web_search_20250305';
316
- name: 'web_search';
317
- max_uses: number;
318
- } {
319
- return {
320
- type: 'web_search_20250305',
321
- name: 'web_search',
322
- max_uses: 3,
323
- };
324
- }
325
-
326
- function getWebSearchLLMConfig(): AnthropicClientOptions & SharedLLMConfig {
327
- return {
328
- provider: Providers.ANTHROPIC,
329
- model: webSearchModelName,
330
- maxTokens: 1024,
331
- promptCache: true,
332
- streaming: true,
333
- streamUsage: true,
334
- thinking: { type: 'adaptive' },
335
- } as AnthropicClientOptions & SharedLLMConfig;
336
- }
337
-
338
- async function createWebSearchRun({
339
- runId,
340
- customHandlers,
341
- }: {
342
- runId: string;
343
- customHandlers?: RunConfig['customHandlers'];
344
- }): Promise<Run<IState>> {
345
- return await Run.create<IState>({
346
- runId,
347
- graphConfig: {
348
- type: 'standard',
349
- llmConfig: getWebSearchLLMConfig(),
350
- tools: [getWebSearchTool()],
351
- instructions:
352
- 'You are a concise assistant. Use web search when current facts are needed.',
353
- },
354
- returnContent: true,
355
- skipCleanup: true,
356
- customHandlers,
357
- });
358
- }
359
-
360
- function createLibreChatContentHandlers(): {
361
- aggregateContent: ReturnType<
362
- typeof createContentAggregator
363
- >['aggregateContent'];
364
- contentParts: Array<LibreChatContentBlock | undefined>;
365
- customHandlers: NonNullable<RunConfig['customHandlers']>;
366
- } {
367
- const { contentParts, aggregateContent } = createContentAggregator();
368
- const customHandlers = {
369
- [GraphEvents.TOOL_END]: new ToolEndHandler(),
370
- [GraphEvents.CHAT_MODEL_END]: new ModelEndHandler(),
371
- [GraphEvents.CHAT_MODEL_STREAM]: new ChatModelStreamHandler(),
372
- [GraphEvents.ON_RUN_STEP_COMPLETED]: {
373
- handle: (
374
- event: GraphEvents.ON_RUN_STEP_COMPLETED,
375
- data: StreamEventData
376
- ): void => {
377
- aggregateContent({
378
- event,
379
- data: data as unknown as { result: ToolEndEvent },
380
- });
381
- },
382
- },
383
- [GraphEvents.ON_RUN_STEP]: {
384
- handle: (event: GraphEvents.ON_RUN_STEP, data: StreamEventData): void => {
385
- aggregateContent({ event, data: data as RunStep });
386
- },
387
- },
388
- [GraphEvents.ON_RUN_STEP_DELTA]: {
389
- handle: (
390
- event: GraphEvents.ON_RUN_STEP_DELTA,
391
- data: StreamEventData
392
- ): void => {
393
- aggregateContent({ event, data: data as RunStepDeltaEvent });
394
- },
395
- },
396
- [GraphEvents.ON_MESSAGE_DELTA]: {
397
- handle: (
398
- event: GraphEvents.ON_MESSAGE_DELTA,
399
- data: StreamEventData
400
- ): void => {
401
- aggregateContent({ event, data: data as MessageDeltaEvent });
402
- },
403
- },
404
- [GraphEvents.ON_REASONING_DELTA]: {
405
- handle: (
406
- event: GraphEvents.ON_REASONING_DELTA,
407
- data: StreamEventData
408
- ): void => {
409
- aggregateContent({ event, data: data as ReasoningDeltaEvent });
410
- },
411
- },
412
- };
413
- return { aggregateContent, contentParts, customHandlers };
414
- }
415
-
416
- test('Test ChatAnthropic', async () => {
417
- const chat = new ChatAnthropic({
418
- modelName,
419
- maxRetries: 0,
420
- });
421
- const message = new HumanMessage('Hello!');
422
- const res = await chat.invoke([message]);
423
- expect(res.response_metadata.usage).toBeDefined();
424
- });
425
-
426
- test('Test ChatAnthropic with a bad API key throws appropriate error', async () => {
427
- const chat = new ChatAnthropic({
428
- modelName,
429
- maxRetries: 0,
430
- apiKey: 'bad',
431
- });
432
- let error: unknown;
433
- try {
434
- const message = new HumanMessage('Hello!');
435
- await chat.invoke([message]);
436
- } catch (e) {
437
- error = e;
438
- }
439
- expect(error).toBeDefined();
440
- expect(getLangChainErrorCode(error)).toEqual('MODEL_AUTHENTICATION');
441
- });
442
-
443
- test('Test ChatAnthropic with unknown model throws appropriate error', async () => {
444
- const chat = new ChatAnthropic({
445
- modelName: 'badbad',
446
- maxRetries: 0,
447
- });
448
- let error: unknown;
449
- try {
450
- const message = new HumanMessage('Hello!');
451
- await chat.invoke([message]);
452
- } catch (e) {
453
- error = e;
454
- }
455
- expect(error).toBeDefined();
456
- expect(getLangChainErrorCode(error)).toEqual('MODEL_NOT_FOUND');
457
- });
458
-
459
- test('Test ChatAnthropic Generate', async () => {
460
- const chat = new ChatAnthropic({
461
- modelName,
462
- maxRetries: 0,
463
- });
464
- const message = new HumanMessage('Hello!');
465
- const res = await chat.generate([[message], [message]]);
466
- expect(res.generations.length).toBe(2);
467
- for (const generation of res.generations) {
468
- expect(generation.length).toBe(1);
469
- for (const message of generation) {
470
- // console.log(message.text);
471
- }
472
- }
473
- // console.log({ res });
474
- });
475
-
476
- test.skip('Test ChatAnthropic Generate w/ ClientOptions', async () => {
477
- const chat = new ChatAnthropic({
478
- modelName,
479
- maxRetries: 0,
480
- clientOptions: {
481
- defaultHeaders: {
482
- 'Helicone-Auth': 'HELICONE_API_KEY',
483
- },
484
- },
485
- });
486
- const message = new HumanMessage('Hello!');
487
- const res = await chat.generate([[message], [message]]);
488
- expect(res.generations.length).toBe(2);
489
- for (const generation of res.generations) {
490
- expect(generation.length).toBe(1);
491
- for (const message of generation) {
492
- // console.log(message.text);
493
- }
494
- }
495
- // console.log({ res });
496
- });
497
-
498
- test('Test ChatAnthropic Generate with a signal in call options', async () => {
499
- const chat = new ChatAnthropic({
500
- modelName,
501
- maxRetries: 0,
502
- });
503
- const controller = new AbortController();
504
- const message = new HumanMessage(
505
- 'How is your day going? Be extremely verbose!'
506
- );
507
- await expect(() => {
508
- const res = chat.generate([[message], [message]], {
509
- signal: controller.signal,
510
- });
511
- setTimeout(() => {
512
- controller.abort();
513
- }, 1000);
514
- return res;
515
- }).rejects.toThrow();
516
- }, 10000);
517
-
518
- test('Test ChatAnthropic tokenUsage with a batch', async () => {
519
- const model = new ChatAnthropic({
520
- temperature: 0,
521
- maxRetries: 0,
522
- modelName,
523
- });
524
- const res = await model.generate([
525
- [new HumanMessage(`Hello!`)],
526
- [new HumanMessage(`Hi!`)],
527
- ]);
528
- // console.log({ res });
529
- });
530
-
531
- test('Test ChatAnthropic in streaming mode', async () => {
532
- let nrNewTokens = 0;
533
- let streamedCompletion = '';
534
-
535
- const model = new ChatAnthropic({
536
- modelName,
537
- maxRetries: 0,
538
- streaming: true,
539
- callbacks: CallbackManager.fromHandlers({
540
- async handleLLMNewToken(token: string) {
541
- nrNewTokens += 1;
542
- streamedCompletion += token;
543
- },
544
- }),
545
- });
546
- const message = new HumanMessage('Hello!');
547
- const res = await model.invoke([message]);
548
- // console.log({ res });
549
-
550
- expect(nrNewTokens > 0).toBe(true);
551
- expect(res.content).toBe(streamedCompletion);
552
- });
553
-
554
- test('Test ChatAnthropic in streaming mode with a signal', async () => {
555
- let nrNewTokens = 0;
556
- let streamedCompletion = '';
557
-
558
- const model = new ChatAnthropic({
559
- modelName,
560
- maxRetries: 0,
561
- streaming: true,
562
- callbacks: CallbackManager.fromHandlers({
563
- async handleLLMNewToken(token: string) {
564
- nrNewTokens += 1;
565
- streamedCompletion += token;
566
- },
567
- }),
568
- });
569
- const controller = new AbortController();
570
- const message = new HumanMessage(
571
- 'Hello! Give me an extremely verbose response'
572
- );
573
- await expect(() => {
574
- const res = model.invoke([message], {
575
- signal: controller.signal,
576
- });
577
- setTimeout(() => {
578
- controller.abort();
579
- }, 500);
580
- return res;
581
- }).rejects.toThrow();
582
-
583
- // console.log({ nrNewTokens, streamedCompletion });
584
- }, 5000);
585
-
586
- test.skip('Test ChatAnthropic prompt value', async () => {
587
- const chat = new ChatAnthropic({
588
- modelName,
589
- maxRetries: 0,
590
- });
591
- const message = new HumanMessage('Hello!');
592
- const res = await chat.generatePrompt([new ChatPromptValue([message])]);
593
- expect(res.generations.length).toBe(1);
594
- for (const generation of res.generations) {
595
- for (const g of generation) {
596
- // console.log(g.text);
597
- }
598
- }
599
- // console.log({ res });
600
- });
601
-
602
- test.skip('ChatAnthropic, docs, prompt templates', async () => {
603
- const chat = new ChatAnthropic({
604
- modelName,
605
- maxRetries: 0,
606
- temperature: 0,
607
- });
608
-
609
- const systemPrompt = PromptTemplate.fromTemplate(
610
- 'You are a helpful assistant that translates {input_language} to {output_language}.'
611
- );
612
-
613
- const chatPrompt = ChatPromptTemplate.fromMessages([
614
- new SystemMessagePromptTemplate(systemPrompt),
615
- HumanMessagePromptTemplate.fromTemplate('{text}'),
616
- ]);
617
-
618
- const responseA = await chat.generatePrompt([
619
- await chatPrompt.formatPromptValue({
620
- input_language: 'English',
621
- output_language: 'French',
622
- text: 'I love programming.',
623
- }),
624
- ]);
625
-
626
- // console.log(responseA.generations);
627
- });
628
-
629
- test.skip('ChatAnthropic, longer chain of messages', async () => {
630
- const chat = new ChatAnthropic({
631
- modelName,
632
- maxRetries: 0,
633
- temperature: 0,
634
- });
635
-
636
- const chatPrompt = ChatPromptTemplate.fromMessages([
637
- HumanMessagePromptTemplate.fromTemplate(`Hi, my name is Joe!`),
638
- AIMessagePromptTemplate.fromTemplate(`Nice to meet you, Joe!`),
639
- HumanMessagePromptTemplate.fromTemplate('{text}'),
640
- ]);
641
-
642
- const responseA = await chat.generatePrompt([
643
- await chatPrompt.formatPromptValue({
644
- text: 'What did I just say my name was?',
645
- }),
646
- ]);
647
-
648
- // console.log(responseA.generations);
649
- });
650
-
651
- test.skip('ChatAnthropic, Anthropic apiUrl set manually via constructor', async () => {
652
- // Pass the default URL through (should use this, and work as normal)
653
- const anthropicApiUrl = 'https://api.anthropic.com';
654
- const chat = new ChatAnthropic({
655
- modelName,
656
- maxRetries: 0,
657
- anthropicApiUrl,
658
- });
659
- const message = new HumanMessage('Hello!');
660
- const res = await chat.invoke([message]);
661
- // console.log({ res });
662
- });
663
-
664
- test('Test ChatAnthropic stream method', async () => {
665
- const model = new ChatAnthropic({
666
- maxTokens: 50,
667
- maxRetries: 0,
668
- modelName,
669
- });
670
- const stream = await model.stream('Print hello world.');
671
- const chunks: AIMessageChunk[] = [];
672
- for await (const chunk of stream) {
673
- chunks.push(chunk);
674
- }
675
- expect(chunks.length).toBeGreaterThan(1);
676
- });
677
-
678
- test('Test ChatAnthropic stream method with abort', async () => {
679
- await expect(async () => {
680
- const model = new ChatAnthropic({
681
- maxTokens: 500,
682
- maxRetries: 0,
683
- modelName,
684
- });
685
- const stream = await model.stream(
686
- 'How is your day going? Be extremely verbose.',
687
- {
688
- signal: AbortSignal.timeout(1000),
689
- }
690
- );
691
- for await (const chunk of stream) {
692
- // console.log(chunk);
693
- }
694
- }).rejects.toThrow();
695
- });
696
-
697
- test('Test ChatAnthropic stream method with early break', async () => {
698
- const model = new ChatAnthropic({
699
- maxTokens: 50,
700
- maxRetries: 0,
701
- modelName,
702
- });
703
- const stream = await model.stream(
704
- 'How is your day going? Be extremely verbose.'
705
- );
706
- let i = 0;
707
- for await (const chunk of stream) {
708
- // console.log(chunk);
709
- i += 1;
710
- if (i > 10) {
711
- break;
712
- }
713
- }
714
- });
715
-
716
- test('Test ChatAnthropic headers passed through', async () => {
717
- const chat = new ChatAnthropic({
718
- modelName,
719
- maxRetries: 0,
720
- apiKey: 'NOT_REAL',
721
- clientOptions: {
722
- defaultHeaders: {
723
- 'X-Api-Key': process.env.ANTHROPIC_API_KEY,
724
- },
725
- },
726
- });
727
- const message = new HumanMessage('Hello!');
728
- const res = await chat.invoke([message]);
729
- // console.log({ res });
730
- });
731
-
732
- describe('ChatAnthropic image inputs', () => {
733
- test.each(['invoke', 'stream'])(
734
- 'Test ChatAnthropic image_url, %s',
735
- async (invocationType: string) => {
736
- const chat = new ChatAnthropic({
737
- modelName,
738
- maxRetries: 0,
739
- });
740
-
741
- const dataUrlRes = invoke(chat, invocationType, [
742
- new HumanMessage({
743
- content: [
744
- {
745
- type: 'image_url',
746
- image_url: {
747
- url: 'data:image/jpeg;base64,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',
748
- },
749
- },
750
- { type: 'text', text: 'Describe this image.' },
751
- ],
752
- }),
753
- ]);
754
-
755
- await expect(dataUrlRes).resolves.toBeDefined();
756
-
757
- const urlRes = invoke(chat, invocationType, [
758
- new HumanMessage({
759
- content: [
760
- {
761
- type: 'image_url',
762
- image_url: remoteImageUrl,
763
- },
764
- { type: 'text', text: 'Describe this image.' },
765
- ],
766
- }),
767
- ]);
768
-
769
- await expect(urlRes).resolves.toBeDefined();
770
-
771
- const invalidSchemeRes = invoke(chat, invocationType, [
772
- new HumanMessage({
773
- content: [
774
- {
775
- type: 'image_url',
776
- image_url: 'file:///path/to/image.png',
777
- },
778
- { type: 'text', text: 'Describe this image.' },
779
- ],
780
- }),
781
- ]);
782
-
783
- await expect(invalidSchemeRes).rejects.toThrow(
784
- [
785
- 'Invalid image URL protocol: "file:". Anthropic only supports images as http, https, or base64-encoded data URLs on \'image_url\' content blocks.',
786
- 'Example: data:image/png;base64,/9j/4AAQSk...',
787
- 'Example: https://example.com/image.jpg',
788
- ].join('\n\n')
789
- );
790
-
791
- const invalidUrlRes = invoke(chat, invocationType, [
792
- new HumanMessage({
793
- content: [
794
- {
795
- type: 'image_url',
796
- image_url: "this isn't a valid URL",
797
- },
798
- { type: 'text', text: 'Describe this image.' },
799
- ],
800
- }),
801
- ]);
802
-
803
- await expect(invalidUrlRes).rejects.toThrow(
804
- [
805
- `Malformed image URL: "this isn't a valid URL". Content blocks of type 'image_url' must be a valid http, https, or base64-encoded data URL.`,
806
- 'Example: data:image/png;base64,/9j/4AAQSk...',
807
- 'Example: https://example.com/image.jpg',
808
- ].join('\n\n')
809
- );
810
- }
811
- );
812
-
813
- test.each(['invoke', 'stream'])(
814
- 'Test ChatAnthropic Anthropic Image Block, %s',
815
- async (invocationType: string) => {
816
- const chat = new ChatAnthropic({
817
- modelName,
818
- maxRetries: 0,
819
- });
820
- const base64Res = invoke(chat, invocationType, [
821
- new HumanMessage({
822
- content: [
823
- {
824
- type: 'image',
825
- source: {
826
- type: 'base64',
827
- media_type: 'image/jpeg',
828
- data: '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',
829
- },
830
- },
831
- {
832
- type: 'text',
833
- text: 'Describe this image',
834
- },
835
- ],
836
- }),
837
- ]);
838
-
839
- await expect(base64Res).resolves.toBeDefined();
840
-
841
- const urlRes = chat.invoke([
842
- new HumanMessage({
843
- content: [
844
- {
845
- type: 'image',
846
- source: {
847
- type: 'url',
848
- url: remoteImageUrl,
849
- },
850
- },
851
- ],
852
- }),
853
- ]);
854
-
855
- await expect(urlRes).resolves.toBeDefined();
856
- }
857
- );
858
- });
859
-
860
- test('Stream tokens', async () => {
861
- const model = new ChatAnthropic({
862
- modelName,
863
- temperature: 0,
864
- maxTokens: 10,
865
- });
866
- let res: AIMessageChunk | null = null;
867
- for await (const chunk of await model.stream(
868
- 'Why is the sky blue? Be concise.'
869
- )) {
870
- if (!res) {
871
- res = chunk;
872
- } else {
873
- res = res.concat(chunk);
874
- }
875
- }
876
- // console.log(res);
877
- expect(res?.usage_metadata).toBeDefined();
878
- if (!res?.usage_metadata) {
879
- return;
880
- }
881
- expect(res.usage_metadata.input_tokens).toBeGreaterThan(1);
882
- expect(res.usage_metadata.output_tokens).toBeGreaterThan(1);
883
- expect(res.usage_metadata.total_tokens).toBe(
884
- res.usage_metadata.input_tokens + res.usage_metadata.output_tokens
885
- );
886
- });
887
-
888
- test('Anthropic usage metadata includes cache input token buckets', () => {
889
- const usageMetadata = getAnthropicUsageMetadata({
890
- input_tokens: 10,
891
- output_tokens: 5,
892
- cache_creation_input_tokens: 20,
893
- cache_read_input_tokens: 30,
894
- });
895
-
896
- expect(usageMetadata).toEqual({
897
- input_tokens: 60,
898
- output_tokens: 5,
899
- total_tokens: 65,
900
- input_token_details: {
901
- cache_creation: 20,
902
- cache_read: 30,
903
- },
904
- });
905
- });
906
-
907
- type AnthropicStreamEvent = Anthropic.Beta.Messages.BetaRawMessageStreamEvent;
908
-
909
- function createMockAnthropicStream(events: AnthropicStreamEvent[]) {
910
- return {
911
- controller: { abort: jest.fn() },
912
- async *[Symbol.asyncIterator]() {
913
- for (const event of events) {
914
- yield event;
915
- }
916
- },
917
- };
918
- }
919
-
920
- class MockStreamingAnthropic extends ChatAnthropic {
921
- constructor(private readonly mockEvents: AnthropicStreamEvent[]) {
922
- super({
923
- modelName,
924
- apiKey: 'test-key',
925
- maxTokens: 10,
926
- streamUsage: true,
927
- });
928
- }
929
-
930
- protected override async createStreamWithRetry() {
931
- return createMockAnthropicStream(this.mockEvents) as never;
932
- }
933
- }
934
-
935
- class RecordingStreamingAnthropic extends ChatAnthropic {
936
- messageStartOutputTokens = 0;
937
- readonly messageDeltaOutputTokens: number[] = [];
938
-
939
- protected override async createStreamWithRetry(
940
- request: AnthropicStreamingMessageCreateParams,
941
- options?: AnthropicRequestOptions
942
- ) {
943
- const stream = await super.createStreamWithRetry(request, options);
944
- const recorder = this;
945
-
946
- return {
947
- controller: stream.controller,
948
- async *[Symbol.asyncIterator](): AsyncGenerator<AnthropicMessageStreamEvent> {
949
- for await (const event of stream) {
950
- if (event.type === 'message_start') {
951
- recorder.messageStartOutputTokens =
952
- event.message.usage.output_tokens ??
953
- recorder.messageStartOutputTokens;
954
- } else if (event.type === 'message_delta') {
955
- recorder.messageDeltaOutputTokens.push(event.usage.output_tokens);
956
- }
957
- yield event;
958
- }
959
- },
960
- } as unknown as typeof stream;
961
- }
962
- }
963
-
964
- test('Anthropic message_delta usage preserves cumulative input totals', () => {
965
- const event: AnthropicStreamEvent = {
966
- type: 'message_delta',
967
- context_management: null,
968
- delta: {
969
- container: null,
970
- stop_details: null,
971
- stop_reason: 'end_turn',
972
- stop_sequence: null,
973
- },
974
- usage: {
975
- input_tokens: 243,
976
- output_tokens: 375,
977
- cache_creation_input_tokens: 11,
978
- cache_read_input_tokens: 13,
979
- fallback_credit: null,
980
- server_tool_use: null,
981
- iterations: null,
982
- output_tokens_details: null,
983
- },
984
- };
985
-
986
- const result = _makeMessageChunkFromAnthropicEvent(event, {
987
- streamUsage: true,
988
- coerceContentToString: true,
989
- });
990
-
991
- expect(result?.chunk.usage_metadata).toEqual({
992
- input_tokens: 267,
993
- output_tokens: 375,
994
- total_tokens: 642,
995
- input_token_details: {
996
- cache_creation: 11,
997
- cache_read: 13,
998
- },
999
- });
1000
- });
1001
-
1002
- test('Anthropic stream usage does not double-count cumulative input tokens', async () => {
1003
- const events: AnthropicStreamEvent[] = [
1004
- {
1005
- type: 'message_start',
1006
- message: {
1007
- id: 'msg_token_accounting',
1008
- container: null,
1009
- context_management: null,
1010
- content: [],
1011
- diagnostics: null,
1012
- model: modelName,
1013
- role: 'assistant',
1014
- stop_details: null,
1015
- stop_reason: null,
1016
- stop_sequence: null,
1017
- type: 'message',
1018
- usage: {
1019
- cache_creation: null,
1020
- cache_creation_input_tokens: 20,
1021
- cache_read_input_tokens: 30,
1022
- fallback_credit: null,
1023
- inference_geo: null,
1024
- input_tokens: 243,
1025
- iterations: null,
1026
- output_tokens: 7,
1027
- server_tool_use: null,
1028
- service_tier: null,
1029
- speed: null,
1030
- output_tokens_details: null,
1031
- },
1032
- },
1033
- },
1034
- {
1035
- type: 'message_delta',
1036
- context_management: null,
1037
- delta: {
1038
- container: null,
1039
- stop_details: null,
1040
- stop_reason: 'end_turn',
1041
- stop_sequence: null,
1042
- },
1043
- usage: {
1044
- input_tokens: 243,
1045
- output_tokens: 375,
1046
- cache_creation_input_tokens: 20,
1047
- cache_read_input_tokens: 30,
1048
- fallback_credit: null,
1049
- server_tool_use: null,
1050
- iterations: null,
1051
- output_tokens_details: null,
1052
- },
1053
- },
1054
- { type: 'message_stop' },
1055
- ];
1056
- const model = new MockStreamingAnthropic(events);
1057
-
1058
- let full: AIMessageChunk | undefined;
1059
- for await (const chunk of await model.stream('hello')) {
1060
- full = !full ? chunk : concat(full, chunk);
1061
- }
1062
-
1063
- expect(full?.usage_metadata).toEqual({
1064
- input_tokens: 293,
1065
- output_tokens: 375,
1066
- total_tokens: 668,
1067
- input_token_details: {
1068
- cache_creation: 20,
1069
- cache_read: 30,
1070
- },
1071
- output_token_details: {},
1072
- });
1073
- });
1074
-
1075
- test('Anthropic stream usage accepts input first reported at message_delta', async () => {
1076
- const events: AnthropicStreamEvent[] = [
1077
- {
1078
- type: 'message_start',
1079
- message: {
1080
- id: 'msg_late_input_usage',
1081
- container: null,
1082
- context_management: null,
1083
- content: [],
1084
- diagnostics: null,
1085
- model: modelName,
1086
- role: 'assistant',
1087
- stop_details: null,
1088
- stop_reason: null,
1089
- stop_sequence: null,
1090
- type: 'message',
1091
- usage: {
1092
- cache_creation: null,
1093
- cache_creation_input_tokens: 0,
1094
- cache_read_input_tokens: 0,
1095
- fallback_credit: null,
1096
- inference_geo: null,
1097
- input_tokens: 0,
1098
- iterations: null,
1099
- output_tokens: 0,
1100
- server_tool_use: null,
1101
- service_tier: null,
1102
- speed: null,
1103
- output_tokens_details: null,
1104
- },
1105
- },
1106
- },
1107
- {
1108
- type: 'message_delta',
1109
- context_management: null,
1110
- delta: {
1111
- container: null,
1112
- stop_details: null,
1113
- stop_reason: 'end_turn',
1114
- stop_sequence: null,
1115
- },
1116
- usage: {
1117
- input_tokens: 100,
1118
- output_tokens: 42,
1119
- cache_creation_input_tokens: 500,
1120
- cache_read_input_tokens: 200,
1121
- fallback_credit: null,
1122
- server_tool_use: null,
1123
- iterations: null,
1124
- output_tokens_details: null,
1125
- },
1126
- },
1127
- { type: 'message_stop' },
1128
- ];
1129
- const model = new MockStreamingAnthropic(events);
1130
-
1131
- let full: AIMessageChunk | undefined;
1132
- for await (const chunk of await model.stream('hello')) {
1133
- full = !full ? chunk : concat(full, chunk);
1134
- }
1135
-
1136
- expect(full?.usage_metadata).toEqual({
1137
- input_tokens: 800,
1138
- output_tokens: 42,
1139
- total_tokens: 842,
1140
- input_token_details: {
1141
- cache_creation: 500,
1142
- cache_read: 200,
1143
- },
1144
- output_token_details: {},
1145
- });
1146
- });
1147
-
1148
- test('Anthropic stream usage handles multiple cumulative message_delta events', async () => {
1149
- const events: AnthropicStreamEvent[] = [
1150
- {
1151
- type: 'message_start',
1152
- message: {
1153
- id: 'msg_token_accounting_multi_delta',
1154
- container: null,
1155
- context_management: null,
1156
- content: [],
1157
- diagnostics: null,
1158
- model: modelName,
1159
- role: 'assistant',
1160
- stop_details: null,
1161
- stop_reason: null,
1162
- stop_sequence: null,
1163
- type: 'message',
1164
- usage: {
1165
- cache_creation: null,
1166
- cache_creation_input_tokens: 0,
1167
- cache_read_input_tokens: 0,
1168
- fallback_credit: null,
1169
- inference_geo: null,
1170
- input_tokens: 243,
1171
- iterations: null,
1172
- output_tokens: 7,
1173
- server_tool_use: null,
1174
- service_tier: null,
1175
- speed: null,
1176
- output_tokens_details: null,
1177
- },
1178
- },
1179
- },
1180
- {
1181
- type: 'message_delta',
1182
- context_management: null,
1183
- delta: {
1184
- container: null,
1185
- stop_details: null,
1186
- stop_reason: null,
1187
- stop_sequence: null,
1188
- },
1189
- usage: {
1190
- input_tokens: 243,
1191
- output_tokens: 100,
1192
- cache_creation_input_tokens: 0,
1193
- cache_read_input_tokens: 0,
1194
- fallback_credit: null,
1195
- server_tool_use: null,
1196
- iterations: null,
1197
- output_tokens_details: null,
1198
- },
1199
- },
1200
- {
1201
- type: 'message_delta',
1202
- context_management: null,
1203
- delta: {
1204
- container: null,
1205
- stop_details: null,
1206
- stop_reason: 'end_turn',
1207
- stop_sequence: null,
1208
- },
1209
- usage: {
1210
- input_tokens: 243,
1211
- output_tokens: 375,
1212
- cache_creation_input_tokens: 0,
1213
- cache_read_input_tokens: 0,
1214
- fallback_credit: null,
1215
- server_tool_use: null,
1216
- iterations: null,
1217
- output_tokens_details: null,
1218
- },
1219
- },
1220
- { type: 'message_stop' },
1221
- ];
1222
- const model = new MockStreamingAnthropic(events);
1223
-
1224
- let full: AIMessageChunk | undefined;
1225
- for await (const chunk of await model.stream('hello')) {
1226
- full = !full ? chunk : concat(full, chunk);
1227
- }
1228
-
1229
- expect(full?.usage_metadata).toEqual({
1230
- input_tokens: 243,
1231
- output_tokens: 375,
1232
- total_tokens: 618,
1233
- input_token_details: {
1234
- cache_creation: 0,
1235
- cache_read: 0,
1236
- },
1237
- output_token_details: {},
1238
- });
1239
- });
1240
-
1241
- test('Anthropic stream smoothing skips empty text block starts', async () => {
1242
- const events: AnthropicStreamEvent[] = [
1243
- {
1244
- type: 'content_block_start',
1245
- index: 0,
1246
- content_block: {
1247
- type: 'text',
1248
- text: '',
1249
- citations: null,
1250
- },
1251
- },
1252
- {
1253
- type: 'content_block_delta',
1254
- index: 0,
1255
- delta: {
1256
- type: 'text_delta',
1257
- text: 'hello',
1258
- },
1259
- },
1260
- { type: 'message_stop' },
1261
- ];
1262
- const model = new MockStreamingAnthropic(events);
1263
- const contents: string[] = [];
1264
-
1265
- for await (const chunk of await model.stream('hello')) {
1266
- if (typeof chunk.content === 'string') {
1267
- contents.push(chunk.content);
1268
- }
1269
- }
1270
-
1271
- expect(contents).toEqual(['hello']);
1272
- });
1273
-
1274
- test('Anthropic stream smoothing closes a queue-full producer after early break', async () => {
1275
- const events: AnthropicStreamEvent[] = [
1276
- {
1277
- type: 'content_block_delta',
1278
- index: 0,
1279
- delta: {
1280
- type: 'text_delta',
1281
- text: 'word '.repeat(3000),
1282
- },
1283
- },
1284
- { type: 'message_stop' },
1285
- ];
1286
- const model = new MockStreamingAnthropic(events);
1287
- const readOneChunk = async (): Promise<void> => {
1288
- for await (const chunk of await model.stream('hello')) {
1289
- if (typeof chunk.content === 'string' && chunk.content.length > 0) {
1290
- break;
1291
- }
1292
- }
1293
- };
1294
- const timeout = new Promise<never>((_, reject) => {
1295
- setTimeout(() => {
1296
- reject(new Error('stream close timed out'));
1297
- }, 1000);
1298
- });
1299
-
1300
- await expect(
1301
- Promise.race([readOneChunk(), timeout])
1302
- ).resolves.toBeUndefined();
1303
- });
1304
-
1305
- test('Anthropic live stream usage matches raw cumulative output snapshots', async () => {
1306
- const model = new RecordingStreamingAnthropic({
1307
- modelName,
1308
- temperature: 0,
1309
- maxTokens: 500,
1310
- _lc_stream_delay: 0,
1311
- });
1312
-
1313
- let full: AIMessageChunk | undefined;
1314
- const stream = await model.stream(
1315
- 'Write exactly 18 numbered lines about reliable software telemetry. Each line should contain exactly seven words. Do not add an intro or outro.'
1316
- );
1317
- for await (const chunk of stream) {
1318
- full = !full ? chunk : concat(full, chunk);
1319
- }
1320
-
1321
- expect(model.messageDeltaOutputTokens.length).toBeGreaterThan(0);
1322
- const rawOutputTokens =
1323
- model.messageDeltaOutputTokens[model.messageDeltaOutputTokens.length - 1];
1324
- expect(rawOutputTokens).toBeGreaterThanOrEqual(
1325
- model.messageStartOutputTokens
1326
- );
1327
- expect(full?.usage_metadata?.output_tokens).toBe(rawOutputTokens);
1328
- expect(full?.usage_metadata?.total_tokens).toBe(
1329
- (full?.usage_metadata?.input_tokens ?? 0) +
1330
- (full?.usage_metadata?.output_tokens ?? 0)
1331
- );
1332
-
1333
- if (model.messageDeltaOutputTokens.length > 1) {
1334
- const summedOutputTokens = model.messageDeltaOutputTokens.reduce(
1335
- (sum, tokens) => sum + tokens,
1336
- 0
1337
- );
1338
- expect(full?.usage_metadata?.output_tokens).toBeLessThan(
1339
- summedOutputTokens
1340
- );
1341
- }
1342
- });
1343
-
1344
- test('document detection ignores null content placeholders', () => {
1345
- const params: AnthropicMessageCreateParams = {
1346
- model: modelName,
1347
- max_tokens: 16,
1348
- messages: [
1349
- {
1350
- role: 'user',
1351
- content: [null as never, { type: 'text', text: 'hello' }],
1352
- },
1353
- ],
1354
- };
1355
-
1356
- expect(_documentsInParams(params)).toBe(false);
1357
- });
1358
-
1359
- test('id is supplied when invoking', async () => {
1360
- const model = new ChatAnthropic({ modelName });
1361
- const result = await model.invoke('Hello');
1362
- expect(result.id).toBeDefined();
1363
- expect(result.id).not.toEqual('');
1364
- });
1365
-
1366
- test('id is supplied when streaming', async () => {
1367
- const model = new ChatAnthropic({ modelName });
1368
- let finalChunk: AIMessageChunk | undefined;
1369
- for await (const chunk of await model.stream('Hello')) {
1370
- finalChunk = !finalChunk ? chunk : concat(finalChunk, chunk);
1371
- }
1372
- expect(finalChunk).toBeDefined();
1373
- if (!finalChunk) return;
1374
- expect(finalChunk.id).toBeDefined();
1375
- expect(finalChunk.id).not.toEqual('');
1376
- });
1377
-
1378
- const CACHED_TEXT = `## Components
1379
-
1380
- LangChain provides standard, extendable interfaces and external integrations for various components useful for building with LLMs.
1381
- Some components LangChain implements, some components we rely on third-party integrations for, and others are a mix.
1382
-
1383
- ### Chat models
1384
-
1385
- <span data-heading-keywords="chat model,chat models"></span>
1386
-
1387
- Language models that use a sequence of messages as inputs and return chat messages as outputs (as opposed to using plain text).
1388
- These are generally newer models (older models are generally \`LLMs\`, see below).
1389
- Chat models support the assignment of distinct roles to conversation messages, helping to distinguish messages from the AI, users, and instructions such as system messages.
1390
-
1391
- Although the underlying models are messages in, message out, the LangChain wrappers also allow these models to take a string as input.
1392
- This gives them the same interface as LLMs (and simpler to use).
1393
- When a string is passed in as input, it will be converted to a \`HumanMessage\` under the hood before being passed to the underlying model.
1394
-
1395
- LangChain does not host any Chat Models, rather we rely on third party integrations.
1396
-
1397
- We have some standardized parameters when constructing ChatModels:
1398
-
1399
- - \`model\`: the name of the model
1400
-
1401
- Chat Models also accept other parameters that are specific to that integration.
1402
-
1403
- :::important
1404
- Some chat models have been fine-tuned for **tool calling** and provide a dedicated API for it.
1405
- Generally, such models are better at tool calling than non-fine-tuned models, and are recommended for use cases that require tool calling.
1406
- Please see the [tool calling section](/docs/concepts/#functiontool-calling) for more information.
1407
- :::
1408
-
1409
- For specifics on how to use chat models, see the [relevant how-to guides here](/docs/how_to/#chat-models).
1410
-
1411
- #### Multimodality
1412
-
1413
- Some chat models are multimodal, accepting images, audio and even video as inputs.
1414
- These are still less common, meaning model providers haven't standardized on the "best" way to define the API.
1415
- Multimodal outputs are even less common. As such, we've kept our multimodal abstractions fairly light weight
1416
- and plan to further solidify the multimodal APIs and interaction patterns as the field matures.
1417
-
1418
- In LangChain, most chat models that support multimodal inputs also accept those values in OpenAI's content blocks format.
1419
- So far this is restricted to image inputs. For models like Gemini which support video and other bytes input, the APIs also support the native, model-specific representations.
1420
-
1421
- For specifics on how to use multimodal models, see the [relevant how-to guides here](/docs/how_to/#multimodal).
1422
-
1423
- ### LLMs
1424
-
1425
- <span data-heading-keywords="llm,llms"></span>
1426
-
1427
- :::caution
1428
- Pure text-in/text-out LLMs tend to be older or lower-level. Many popular models are best used as [chat completion models](/docs/concepts/#chat-models),
1429
- even for non-chat use cases.
1430
-
1431
- You are probably looking for [the section above instead](/docs/concepts/#chat-models).
1432
- :::
1433
-
1434
- Language models that takes a string as input and returns a string.
1435
- These are traditionally older models (newer models generally are [Chat Models](/docs/concepts/#chat-models), see above).
1436
-
1437
- Although the underlying models are string in, string out, the LangChain wrappers also allow these models to take messages as input.
1438
- This gives them the same interface as [Chat Models](/docs/concepts/#chat-models).
1439
- When messages are passed in as input, they will be formatted into a string under the hood before being passed to the underlying model.
1440
-
1441
- LangChain does not host any LLMs, rather we rely on third party integrations.
1442
-
1443
- For specifics on how to use LLMs, see the [relevant how-to guides here](/docs/how_to/#llms).
1444
-
1445
- ### Message types
1446
-
1447
- Some language models take an array of messages as input and return a message.
1448
- There are a few different types of messages.
1449
- All messages have a \`role\`, \`content\`, and \`response_metadata\` property.
1450
-
1451
- The \`role\` describes WHO is saying the message.
1452
- LangChain has different message classes for different roles.
1453
-
1454
- The \`content\` property describes the content of the message.
1455
- This can be a few different things:
1456
-
1457
- - A string (most models deal this type of content)
1458
- - A List of objects (this is used for multi-modal input, where the object contains information about that input type and that input location)
1459
-
1460
- #### HumanMessage
1461
-
1462
- This represents a message from the user.
1463
-
1464
- #### AIMessage
1465
-
1466
- This represents a message from the model. In addition to the \`content\` property, these messages also have:
1467
-
1468
- **\`response_metadata\`**
1469
-
1470
- The \`response_metadata\` property contains additional metadata about the response. The data here is often specific to each model provider.
1471
- This is where information like log-probs and token usage may be stored.
1472
-
1473
- **\`tool_calls\`**
1474
-
1475
- These represent a decision from an language model to call a tool. They are included as part of an \`AIMessage\` output.
1476
- They can be accessed from there with the \`.tool_calls\` property.
1477
-
1478
- This property returns a list of \`ToolCall\`s. A \`ToolCall\` is an object with the following arguments:
1479
-
1480
- - \`name\`: The name of the tool that should be called.
1481
- - \`args\`: The arguments to that tool.
1482
- - \`id\`: The id of that tool call.
1483
-
1484
- #### SystemMessage
1485
-
1486
- This represents a system message, which tells the model how to behave. Not every model provider supports this.
1487
-
1488
- #### ToolMessage
1489
-
1490
- This represents the result of a tool call. In addition to \`role\` and \`content\`, this message has:
1491
-
1492
- - a \`tool_call_id\` field which conveys the id of the call to the tool that was called to produce this result.
1493
- - an \`artifact\` field which can be used to pass along arbitrary artifacts of the tool execution which are useful to track but which should not be sent to the model.
1494
-
1495
- #### (Legacy) FunctionMessage
1496
-
1497
- This is a legacy message type, corresponding to OpenAI's legacy function-calling API. \`ToolMessage\` should be used instead to correspond to the updated tool-calling API.
1498
-
1499
- This represents the result of a function call. In addition to \`role\` and \`content\`, this message has a \`name\` parameter which conveys the name of the function that was called to produce this result.
1500
-
1501
- ### Prompt templates
1502
-
1503
- <span data-heading-keywords="prompt,prompttemplate,chatprompttemplate"></span>
1504
-
1505
- Prompt templates help to translate user input and parameters into instructions for a language model.
1506
- This can be used to guide a model's response, helping it understand the context and generate relevant and coherent language-based output.
1507
-
1508
- Prompt Templates take as input an object, where each key represents a variable in the prompt template to fill in.
1509
-
1510
- Prompt Templates output a PromptValue. This PromptValue can be passed to an LLM or a ChatModel, and can also be cast to a string or an array of messages.
1511
- The reason this PromptValue exists is to make it easy to switch between strings and messages.
1512
-
1513
- There are a few different types of prompt templates:
1514
-
1515
- #### String PromptTemplates
1516
-
1517
- These prompt templates are used to format a single string, and generally are used for simpler inputs.
1518
- For example, a common way to construct and use a PromptTemplate is as follows:
1519
-
1520
- \`\`\`typescript
1521
- import { PromptTemplate } from "@langchain/core/prompts";
1522
-
1523
- const promptTemplate = PromptTemplate.fromTemplate(
1524
- "Tell me a joke about {topic}"
1525
- );
1526
-
1527
- await promptTemplate.invoke({ topic: "cats" });
1528
- \`\`\`
1529
-
1530
- #### ChatPromptTemplates
1531
-
1532
- These prompt templates are used to format an array of messages. These "templates" consist of an array of templates themselves.
1533
- For example, a common way to construct and use a ChatPromptTemplate is as follows:
1534
-
1535
- \`\`\`typescript
1536
- import { ChatPromptTemplate } from "@langchain/core/prompts";
1537
-
1538
- const promptTemplate = ChatPromptTemplate.fromMessages([
1539
- ["system", "You are a helpful assistant"],
1540
- ["user", "Tell me a joke about {topic}"],
1541
- ]);
1542
-
1543
- await promptTemplate.invoke({ topic: "cats" });
1544
- \`\`\`
1545
-
1546
- In the above example, this ChatPromptTemplate will construct two messages when called.
1547
- The first is a system message, that has no variables to format.
1548
- The second is a HumanMessage, and will be formatted by the \`topic\` variable the user passes in.
1549
-
1550
- #### MessagesPlaceholder
1551
-
1552
- <span data-heading-keywords="messagesplaceholder"></span>
1553
-
1554
- This prompt template is responsible for adding an array of messages in a particular place.
1555
- In the above ChatPromptTemplate, we saw how we could format two messages, each one a string.
1556
- But what if we wanted the user to pass in an array of messages that we would slot into a particular spot?
1557
- This is how you use MessagesPlaceholder.
1558
-
1559
- \`\`\`typescript
1560
- import {
1561
- ChatPromptTemplate,
1562
- MessagesPlaceholder,
1563
- } from "@langchain/core/prompts";
1564
- import { HumanMessage } from "@langchain/core/messages";
1565
-
1566
- const promptTemplate = ChatPromptTemplate.fromMessages([
1567
- ["system", "You are a helpful assistant"],
1568
- new MessagesPlaceholder("msgs"),
1569
- ]);
1570
-
1571
- promptTemplate.invoke({ msgs: [new HumanMessage({ content: "hi!" })] });
1572
- \`\`\`
1573
-
1574
- This will produce an array of two messages, the first one being a system message, and the second one being the HumanMessage we passed in.
1575
- If we had passed in 5 messages, then it would have produced 6 messages in total (the system message plus the 5 passed in).
1576
- This is useful for letting an array of messages be slotted into a particular spot.
1577
-
1578
- An alternative way to accomplish the same thing without using the \`MessagesPlaceholder\` class explicitly is:
1579
-
1580
- \`\`\`typescript
1581
- const promptTemplate = ChatPromptTemplate.fromMessages([
1582
- ["system", "You are a helpful assistant"],
1583
- ["placeholder", "{msgs}"], // <-- This is the changed part
1584
- ]);
1585
- \`\`\`
1586
-
1587
- For specifics on how to use prompt templates, see the [relevant how-to guides here](/docs/how_to/#prompt-templates).
1588
-
1589
- ### Example Selectors
1590
-
1591
- One common prompting technique for achieving better performance is to include examples as part of the prompt.
1592
- This gives the language model concrete examples of how it should behave.
1593
- Sometimes these examples are hardcoded into the prompt, but for more advanced situations it may be nice to dynamically select them.
1594
- Example Selectors are classes responsible for selecting and then formatting examples into prompts.
1595
-
1596
- For specifics on how to use example selectors, see the [relevant how-to guides here](/docs/how_to/#example-selectors).
1597
-
1598
- ### Output parsers
1599
-
1600
- <span data-heading-keywords="output parser"></span>
1601
-
1602
- :::note
1603
-
1604
- The information here refers to parsers that take a text output from a model try to parse it into a more structured representation.
1605
- More and more models are supporting function (or tool) calling, which handles this automatically.
1606
- It is recommended to use function/tool calling rather than output parsing.
1607
- See documentation for that [here](/docs/concepts/#function-tool-calling).
1608
-
1609
- :::
1610
-
1611
- Responsible for taking the output of a model and transforming it to a more suitable format for downstream tasks.
1612
- Useful when you are using LLMs to generate structured data, or to normalize output from chat models and LLMs.
1613
-
1614
- There are two main methods an output parser must implement:
1615
-
1616
- - "Get format instructions": A method which returns a string containing instructions for how the output of a language model should be formatted.
1617
- - "Parse": A method which takes in a string (assumed to be the response from a language model) and parses it into some structure.
1618
-
1619
- And then one optional one:
1620
-
1621
- - "Parse with prompt": A method which takes in a string (assumed to be the response from a language model) and a prompt (assumed to be the prompt that generated such a response) and parses it into some structure. The prompt is largely provided in the event the OutputParser wants to retry or fix the output in some way, and needs information from the prompt to do so.
1622
-
1623
- Output parsers accept a string or \`BaseMessage\` as input and can return an arbitrary type.
1624
-
1625
- LangChain has many different types of output parsers. This is a list of output parsers LangChain supports. The table below has various pieces of information:
1626
-
1627
- **Name**: The name of the output parser
1628
-
1629
- **Supports Streaming**: Whether the output parser supports streaming.
1630
-
1631
- **Input Type**: Expected input type. Most output parsers work on both strings and messages, but some (like OpenAI Functions) need a message with specific arguments.
1632
-
1633
- **Output Type**: The output type of the object returned by the parser.
1634
-
1635
- **Description**: Our commentary on this output parser and when to use it.
1636
-
1637
- The current date is ${new Date().toISOString()}`;
1638
-
1639
- test('system prompt caching', async () => {
1640
- const model = new ChatAnthropic({
1641
- modelName: citationsModelName,
1642
- clientOptions: {
1643
- defaultHeaders: {
1644
- 'anthropic-beta': 'prompt-caching-2024-07-31',
1645
- },
1646
- },
1647
- });
1648
- const messages = [
1649
- new SystemMessage({
1650
- content: [
1651
- {
1652
- type: 'text',
1653
- text: `${new Date().toISOString()} (Now)`,
1654
- },
1655
- {
1656
- type: 'text',
1657
- text: `You are a pirate. Always respond in pirate dialect.\nUse the following as context when answering questions: ${CACHED_TEXT}`,
1658
- cache_control: { type: 'ephemeral' },
1659
- },
1660
- ],
1661
- }),
1662
- new HumanMessage({
1663
- content: 'What types of messages are supported in LangChain?',
1664
- }),
1665
- ];
1666
- const res = await model.invoke(messages);
1667
- expect(
1668
- res.usage_metadata?.input_token_details?.cache_creation
1669
- ).toBeGreaterThan(0);
1670
- expect(res.usage_metadata?.input_token_details?.cache_read).toBe(0);
1671
- expect(res.usage_metadata?.input_tokens).toBeGreaterThan(
1672
- res.usage_metadata?.input_token_details?.cache_creation ?? 0
1673
- );
1674
- const res2 = await model.invoke(messages);
1675
- expect(res2.usage_metadata?.input_token_details?.cache_creation).toBe(0);
1676
- expect(res2.usage_metadata?.input_token_details?.cache_read).toBeGreaterThan(
1677
- 0
1678
- );
1679
- expect(res2.usage_metadata?.input_tokens).toBeGreaterThan(
1680
- res2.usage_metadata?.input_token_details?.cache_read ?? 0
1681
- );
1682
- const stream = await model.stream(messages);
1683
- let agg;
1684
- for await (const chunk of stream) {
1685
- agg = agg === undefined ? chunk : concat(agg, chunk);
1686
- }
1687
- expect(agg).toBeDefined();
1688
- expect(agg!.usage_metadata?.input_token_details?.cache_creation).toBe(0);
1689
- expect(agg!.usage_metadata?.input_token_details?.cache_read).toBeGreaterThan(
1690
- 0
1691
- );
1692
- expect(agg!.usage_metadata?.input_tokens).toBeGreaterThan(
1693
- agg!.usage_metadata?.input_token_details?.cache_read ?? 0
1694
- );
1695
- });
1696
-
1697
- // TODO: Add proper test with long tool content
1698
- test.skip('tool caching', async () => {
1699
- const model = new ChatAnthropic({
1700
- modelName,
1701
- clientOptions: {
1702
- defaultHeaders: {
1703
- 'anthropic-beta': 'prompt-caching-2024-07-31',
1704
- },
1705
- },
1706
- }).bindTools([
1707
- {
1708
- name: 'get_weather',
1709
- description: 'Get the weather for a specific location',
1710
- input_schema: {
1711
- type: 'object',
1712
- properties: {
1713
- location: {
1714
- type: 'string',
1715
- description: 'Location to get the weather for',
1716
- },
1717
- unit: {
1718
- type: 'string',
1719
- description: 'Temperature unit to return',
1720
- },
1721
- },
1722
- required: ['location'],
1723
- },
1724
- cache_control: { type: 'ephemeral' },
1725
- },
1726
- ]);
1727
- const messages = [
1728
- new HumanMessage({
1729
- content: 'What is the weather in Regensburg?',
1730
- }),
1731
- ];
1732
- const res = await model.invoke(messages);
1733
- console.log(res);
1734
- expect(
1735
- res.usage_metadata?.input_token_details?.cache_creation
1736
- ).toBeGreaterThan(0);
1737
- expect(res.usage_metadata?.input_token_details?.cache_read).toBe(0);
1738
- const res2 = await model.invoke(messages);
1739
- expect(res2.usage_metadata?.input_token_details?.cache_creation).toBe(0);
1740
- expect(res2.usage_metadata?.input_token_details?.cache_read).toBeGreaterThan(
1741
- 0
1742
- );
1743
- });
1744
-
1745
- test.skip('Test ChatAnthropic with custom client', async () => {
1746
- const client = new AnthropicVertex();
1747
- const chat = new ChatAnthropic({
1748
- modelName,
1749
- maxRetries: 0,
1750
- createClient: () => client,
1751
- });
1752
- const message = new HumanMessage('Hello!');
1753
- const res = await chat.invoke([message]);
1754
- // console.log({ res });
1755
- expect(res.usage_metadata?.input_token_details).toBeDefined();
1756
- });
1757
-
1758
- test('human message caching', async () => {
1759
- const model = new ChatAnthropic({
1760
- modelName: citationsModelName,
1761
- });
1762
-
1763
- const messages = [
1764
- new SystemMessage({
1765
- content: [
1766
- {
1767
- type: 'text',
1768
- text: `${new Date().toISOString()} (Now)`,
1769
- },
1770
- {
1771
- type: 'text',
1772
- text: `You are a pirate. Always respond in pirate dialect.\nUse the following as context when answering questions: ${CACHED_TEXT}`,
1773
- },
1774
- ],
1775
- }),
1776
- new HumanMessage({
1777
- content: [
1778
- {
1779
- type: 'text',
1780
- text: 'What types of messages are supported in LangChain?',
1781
- cache_control: { type: 'ephemeral' },
1782
- },
1783
- ],
1784
- }),
1785
- ];
1786
-
1787
- const res = await model.invoke(messages);
1788
- expect(
1789
- res.usage_metadata?.input_token_details?.cache_creation
1790
- ).toBeGreaterThan(0);
1791
- expect(res.usage_metadata?.input_token_details?.cache_read).toBe(0);
1792
- expect(res.usage_metadata?.input_tokens).toBeGreaterThan(
1793
- res.usage_metadata?.input_token_details?.cache_creation ?? 0
1794
- );
1795
- const res2 = await model.invoke(messages);
1796
- expect(res2.usage_metadata?.input_token_details?.cache_creation).toBe(0);
1797
- expect(res2.usage_metadata?.input_token_details?.cache_read).toBeGreaterThan(
1798
- 0
1799
- );
1800
- expect(res2.usage_metadata?.input_tokens).toBeGreaterThan(
1801
- res2.usage_metadata?.input_token_details?.cache_read ?? 0
1802
- );
1803
-
1804
- const stream = await model.stream(messages);
1805
- let agg;
1806
- for await (const chunk of stream) {
1807
- agg = agg === undefined ? chunk : concat(agg, chunk);
1808
- }
1809
- expect(agg).toBeDefined();
1810
- expect(agg!.usage_metadata?.input_token_details?.cache_creation).toBe(0);
1811
- expect(agg!.usage_metadata?.input_token_details?.cache_read).toBeGreaterThan(
1812
- 0
1813
- );
1814
- expect(agg!.usage_metadata?.input_tokens).toBeGreaterThan(
1815
- agg!.usage_metadata?.input_token_details?.cache_read ?? 0
1816
- );
1817
- });
1818
-
1819
- describe('Anthropic web search live regressions', () => {
1820
- test('accepts prompt-cache markers on built-in web search tools', async () => {
1821
- const model = new ChatAnthropic({
1822
- model: webSearchModelName,
1823
- maxTokens: 1024,
1824
- thinking: { type: 'adaptive' },
1825
- });
1826
- const tools = getPromptCachedWebSearchTools();
1827
- const formattedTools = model.formatStructuredToolToAnthropic(tools);
1828
-
1829
- expect(formattedTools?.[0]).toMatchObject({
1830
- type: 'web_search_20250305',
1831
- name: 'web_search',
1832
- cache_control: { type: 'ephemeral' },
1833
- });
1834
- expect(formattedTools?.[0]).not.toHaveProperty('extras');
1835
-
1836
- const response = await model
1837
- .bindTools(tools)
1838
- .invoke([
1839
- new HumanMessage(
1840
- 'Use web search once and answer with only the word: ok'
1841
- ),
1842
- ]);
1843
-
1844
- expect(response.content.length).toBeGreaterThan(0);
1845
- });
1846
-
1847
- test('replays LibreChat-persisted web search content across runs', async () => {
1848
- const threadId = `web-search-e2e-${Date.now()}`;
1849
- const firstPrompt =
1850
- 'Use web search. Who is the lowest seed survived in 2026 NBA playoffs? Answer with only the team name.';
1851
- const followUpPrompt = "Who are 76ers' opponents in current series?";
1852
- const { contentParts: firstContentParts, customHandlers: firstHandlers } =
1853
- createLibreChatContentHandlers();
1854
- const firstRun = await createWebSearchRun({
1855
- runId: `${threadId}-turn-1`,
1856
- customHandlers: firstHandlers,
1857
- });
1858
- const runConfig = {
1859
- configurable: { provider: Providers.ANTHROPIC, thread_id: threadId },
1860
- streamMode: 'values',
1861
- version: 'v2' as const,
1862
- };
1863
-
1864
- const firstRunContent = await firstRun.processStream(
1865
- { messages: [new HumanMessage(firstPrompt)] },
1866
- runConfig
1867
- );
1868
- const persistedAssistantContent = firstContentParts.filter(
1869
- (part): part is LibreChatContentBlock => part != null
1870
- );
1871
- const hasPersistedServerToolCall = persistedAssistantContent.some(
1872
- (part) =>
1873
- part.type === ContentTypes.TOOL_CALL &&
1874
- typeof part.tool_call?.id === 'string' &&
1875
- part.tool_call.id.startsWith(Constants.ANTHROPIC_SERVER_TOOL_PREFIX)
1876
- );
1877
- const hasPersistedAnswerText = persistedAssistantContent.some(
1878
- (part) =>
1879
- part.type === ContentTypes.TEXT &&
1880
- typeof part.text === 'string' &&
1881
- part.text.trim().length > 0
1882
- );
1883
-
1884
- expect(firstRunContent).toBeDefined();
1885
- expect(persistedAssistantContent.length).toBeGreaterThan(0);
1886
- expect(hasPersistedServerToolCall).toBe(true);
1887
- expect(hasPersistedAnswerText).toBe(true);
1888
-
1889
- const persistedPayload: TPayload = [
1890
- { role: 'user', content: firstPrompt },
1891
- { role: 'assistant', content: persistedAssistantContent },
1892
- { role: 'user', content: followUpPrompt },
1893
- ];
1894
- const { messages } = formatAgentMessages(
1895
- persistedPayload,
1896
- undefined,
1897
- new Set(['web_search']),
1898
- undefined,
1899
- { provider: Providers.ANTHROPIC }
1900
- );
1901
- const anthropicPayload = _convertMessagesToAnthropicPayload(messages);
1902
- const secondRun = await createWebSearchRun({
1903
- runId: `${threadId}-turn-2`,
1904
- });
1905
-
1906
- expectAnthropicPayloadContentIsNonEmpty(anthropicPayload);
1907
- expectNoDanglingServerToolUses(anthropicPayload);
1908
- await expect(
1909
- secondRun.processStream({ messages }, runConfig)
1910
- ).resolves.toBeDefined();
1911
- });
1912
- });
1913
-
1914
- test('Can accept PDF documents', async () => {
1915
- const model = new ChatAnthropic({
1916
- modelName: pdfModelName,
1917
- });
1918
-
1919
- const pdfPath = './src/llm/anthropic/Jacob_Lee_Resume_2023.pdf';
1920
- const pdfBase64 = await fs.readFile(pdfPath, 'base64');
1921
-
1922
- const response = await model.invoke([
1923
- ['system', 'Use the provided documents to answer the question'],
1924
- [
1925
- 'user',
1926
- [
1927
- {
1928
- type: 'document',
1929
- source: {
1930
- type: 'base64',
1931
- media_type: 'application/pdf',
1932
- data: pdfBase64,
1933
- },
1934
- },
1935
- {
1936
- type: 'text',
1937
- text: 'Summarize the contents of this PDF',
1938
- },
1939
- ],
1940
- ],
1941
- ]);
1942
-
1943
- expect(response.content.length).toBeGreaterThan(10);
1944
- });
1945
-
1946
- describe('Citations', () => {
1947
- test('document blocks', async () => {
1948
- const citationsModel = new ChatAnthropic({
1949
- model: citationsModelName,
1950
- });
1951
- const messages = [
1952
- {
1953
- role: 'user',
1954
- content: [
1955
- {
1956
- type: 'document',
1957
- source: {
1958
- type: 'text',
1959
- media_type: 'text/plain',
1960
- data: "The grass the user is asking about is bluegrass. The sky is orange because it's night.",
1961
- },
1962
- title: 'My Document',
1963
- context: 'This is a trustworthy document.',
1964
- citations: {
1965
- enabled: true,
1966
- },
1967
- },
1968
- {
1969
- type: 'text',
1970
- text: 'What color is the grass and sky?',
1971
- },
1972
- ],
1973
- },
1974
- ];
1975
-
1976
- const response = await citationsModel.invoke(messages);
1977
-
1978
- const responseBlocks = expectContentArray<ContentBlock>(response.content);
1979
- expect(responseBlocks.length).toBeGreaterThan(2);
1980
- const blocksWithCitations = responseBlocks.filter(hasCitations);
1981
- expect(blocksWithCitations.length).toEqual(2);
1982
- expect(typeof blocksWithCitations[0].citations[0]).toEqual('object');
1983
-
1984
- const stream = await citationsModel.stream(messages);
1985
- let aggregated;
1986
- let chunkHasCitation = false;
1987
- for await (const chunk of stream) {
1988
- aggregated = aggregated === undefined ? chunk : concat(aggregated, chunk);
1989
- if (
1990
- !chunkHasCitation &&
1991
- Array.isArray(chunk.content) &&
1992
- chunk.content.some(hasCitations)
1993
- ) {
1994
- chunkHasCitation = true;
1995
- }
1996
- }
1997
- expect(chunkHasCitation).toBe(true);
1998
- const aggregatedBlocks = expectContentArray<ContentBlock>(
1999
- aggregated?.content ?? []
2000
- );
2001
- expect(aggregatedBlocks.length).toBeGreaterThan(2);
2002
- expect(aggregatedBlocks.some(hasCitations)).toBe(true);
2003
- });
2004
- describe('search result blocks', () => {
2005
- const citationsModel = new ChatAnthropic({
2006
- model: citationsModelName,
2007
- clientOptions: {
2008
- defaultHeaders: {
2009
- 'anthropic-beta': 'search-results-2025-06-09',
2010
- },
2011
- },
2012
- });
2013
-
2014
- const messages = [
2015
- {
2016
- role: 'user',
2017
- content: [
2018
- {
2019
- type: 'search_result',
2020
- title: 'History of France',
2021
- source: 'https://example.com/france-history',
2022
- citations: { enabled: true },
2023
- content: [
2024
- {
2025
- type: 'text',
2026
- text: 'The capital of France is Paris.',
2027
- },
2028
- {
2029
- type: 'text',
2030
- text: 'The old capital of France was Lyon.',
2031
- },
2032
- ],
2033
- },
2034
- {
2035
- type: 'search_result',
2036
- title: 'Geography of France',
2037
- source: 'https://example.com/france-geography',
2038
- citations: { enabled: true },
2039
- content: [
2040
- {
2041
- type: 'text',
2042
- text: 'France is a country in Europe.',
2043
- },
2044
- {
2045
- type: 'text',
2046
- text: 'France borders Spain to the south.',
2047
- },
2048
- ],
2049
- },
2050
- {
2051
- type: 'text',
2052
- text: 'What is the capital of France and where is it located? You must cite your sources.',
2053
- },
2054
- ],
2055
- },
2056
- ];
2057
-
2058
- test('without streaming', async () => {
2059
- const response = await citationsModel.invoke(messages);
2060
-
2061
- const responseBlocks = expectContentArray<ContentBlock>(response.content);
2062
- expect(responseBlocks.length).toBeGreaterThan(0);
2063
-
2064
- // Check that we have cited content
2065
- const blocksWithCitations = responseBlocks.filter(hasCitations);
2066
- expect(blocksWithCitations.length).toBeGreaterThan(0);
2067
-
2068
- // Verify citation structure
2069
- const citation = blocksWithCitations[0].citations[0];
2070
- expect(typeof citation).toBe('object');
2071
- expect(citation.type).toBe('search_result_location');
2072
- expect(citation.source).toBeDefined();
2073
- });
2074
- test('with streaming', async () => {
2075
- // Test streaming
2076
- const stream = await citationsModel.stream(messages);
2077
- let aggregated;
2078
- let chunkHasCitation = false;
2079
- for await (const chunk of stream) {
2080
- aggregated =
2081
- aggregated === undefined ? chunk : concat(aggregated, chunk);
2082
- if (
2083
- !chunkHasCitation &&
2084
- Array.isArray(chunk.content) &&
2085
- chunk.content.some(hasCitations)
2086
- ) {
2087
- chunkHasCitation = true;
2088
- }
2089
- }
2090
- expect(chunkHasCitation).toBe(true);
2091
- const aggregatedBlocks = expectContentArray<ContentBlock>(
2092
- aggregated?.content ?? []
2093
- );
2094
- expect(aggregatedBlocks.some(hasCitations)).toBe(true);
2095
- });
2096
- });
2097
-
2098
- test('search result blocks from tool', async () => {
2099
- const ragTool = tool(
2100
- (): ChatAnthropicContentBlock[] => [
2101
- {
2102
- type: 'search_result',
2103
- title: 'History of France',
2104
- source: 'https://example.com/france-history',
2105
- citations: { enabled: true },
2106
- content: [
2107
- {
2108
- type: 'text',
2109
- text: 'The capital of France is Paris.',
2110
- },
2111
- {
2112
- type: 'text',
2113
- text: 'France was established as a republic in 1792.',
2114
- },
2115
- ],
2116
- },
2117
- {
2118
- type: 'search_result',
2119
- title: 'Geography of France',
2120
- source: 'https://example.com/france-geography',
2121
- citations: { enabled: true },
2122
- content: [
2123
- {
2124
- type: 'text',
2125
- text: 'France is located in Western Europe.',
2126
- },
2127
- {
2128
- type: 'text',
2129
- text: 'France has a population of approximately 67 million people.',
2130
- },
2131
- ],
2132
- },
2133
- ],
2134
- {
2135
- name: 'search_knowledge_base',
2136
- description: 'Search the knowledge base for information about France',
2137
- schema: z.object({
2138
- query: z.string().describe('The search query'),
2139
- }),
2140
- }
2141
- );
2142
-
2143
- const citationsModel = new ChatAnthropic({
2144
- model: citationsModelName,
2145
- clientOptions: {
2146
- defaultHeaders: {
2147
- 'anthropic-beta': 'search-results-2025-06-09',
2148
- },
2149
- },
2150
- }).bindTools([ragTool]);
2151
-
2152
- const messages: BaseMessage[] = [
2153
- new HumanMessage(
2154
- 'Search for information about France and tell me what you find with proper citations.'
2155
- ),
2156
- ];
2157
-
2158
- const response = await citationsModel.invoke(messages);
2159
- messages.push(response);
2160
-
2161
- expect(Array.isArray(response.content)).toBe(true);
2162
- expect(response.content.length).toBeGreaterThan(0);
2163
-
2164
- // Check that the model called the tool
2165
- expect(response.tool_calls?.length).toBeGreaterThan(0);
2166
- expect(response.tool_calls?.[0].name).toBe('search_knowledge_base');
2167
-
2168
- const toolResponse = await ragTool.invoke(response.tool_calls![0]);
2169
- messages.push(toolResponse);
2170
-
2171
- const response2 = await citationsModel.invoke(messages);
2172
-
2173
- const response2Blocks = expectContentArray<ContentBlock>(response2.content);
2174
- expect(response2Blocks.length).toBeGreaterThan(0);
2175
- // Make sure that a citation exists somewhere in the content list
2176
- const citationBlock = expectDefined(response2Blocks.find(hasCitations));
2177
- expect(citationBlock.citations[0].type).toBe('search_result_location');
2178
- expect(citationBlock.citations[0].source).toBeDefined();
2179
- });
2180
- });
2181
-
2182
- // Inherited from @langchain/anthropic@1.5.1 tests/chat_models.test.ts — verifies
2183
- // the fork honors upstream's `thinkingExplicitlySet` gating in invocationParams.
2184
- describe('invocationParams thinking gating', () => {
2185
- test('omits thinking when not explicitly configured', () => {
2186
- const model = new ChatAnthropic({
2187
- model: 'claude-haiku-4-5-20251001',
2188
- apiKey: 'testing',
2189
- });
2190
-
2191
- expect(model.invocationParams({}).thinking).toBeUndefined();
2192
- });
2193
-
2194
- test('includes thinking when explicitly disabled', () => {
2195
- const model = new ChatAnthropic({
2196
- model: 'claude-haiku-4-5-20251001',
2197
- apiKey: 'testing',
2198
- thinking: { type: 'disabled' },
2199
- });
2200
-
2201
- expect(model.invocationParams({}).thinking).toEqual({ type: 'disabled' });
2202
- });
2203
-
2204
- test('includes thinking when explicitly enabled', () => {
2205
- const model = new ChatAnthropic({
2206
- model: 'claude-haiku-4-5-20251001',
2207
- temperature: 1,
2208
- apiKey: 'testing',
2209
- thinking: { type: 'enabled', budget_tokens: 1000 },
2210
- });
2211
-
2212
- expect(model.invocationParams({}).thinking).toEqual({
2213
- type: 'enabled',
2214
- budget_tokens: 1000,
2215
- });
2216
- });
2217
- });
2218
-
2219
- // Inherited from @langchain/anthropic@1.5.1 — top-level request cache_control.
2220
- describe('invocationParams cache_control', () => {
2221
- const newModel = () =>
2222
- new ChatAnthropic({
2223
- model: 'claude-haiku-4-5-20251001',
2224
- apiKey: 'testing',
2225
- });
2226
-
2227
- test('includes cache_control when provided in call options', () => {
2228
- expect(
2229
- newModel().invocationParams({ cache_control: { type: 'ephemeral' } })
2230
- .cache_control
2231
- ).toEqual({ type: 'ephemeral' });
2232
- });
2233
-
2234
- test('includes cache_control with 1h ttl', () => {
2235
- expect(
2236
- newModel().invocationParams({
2237
- cache_control: { type: 'ephemeral', ttl: '1h' },
2238
- }).cache_control
2239
- ).toEqual({ type: 'ephemeral', ttl: '1h' });
2240
- });
2241
-
2242
- test('omits cache_control when not provided', () => {
2243
- expect(newModel().invocationParams({}).cache_control).toBeUndefined();
2244
- });
2245
- });
2246
-
2247
- describe('Opus 4.7', () => {
2248
- test('default max_tokens for claude-opus-4-7 is 16384', () => {
2249
- const model = new ChatAnthropic({
2250
- model: 'claude-opus-4-7',
2251
- apiKey: 'testing',
2252
- });
2253
-
2254
- const params = model.invocationParams({});
2255
-
2256
- expect(params.max_tokens).toBe(16384);
2257
- });
2258
-
2259
- test('does not apply Opus 4.7 rules to longer prefix matches', () => {
2260
- const model = new ChatAnthropic({
2261
- model: 'claude-opus-4-70',
2262
- apiKey: 'testing',
2263
- topK: 40,
2264
- });
2265
-
2266
- const params = model.invocationParams({});
2267
-
2268
- expect(params.top_k).toBe(40);
2269
- });
2270
-
2271
- test('rejects thinking.type=enabled for claude-opus-4-7', () => {
2272
- const model = new ChatAnthropic({
2273
- model: 'claude-opus-4-7',
2274
- apiKey: 'testing',
2275
- thinking: { type: 'enabled', budget_tokens: 2048 },
2276
- });
2277
-
2278
- expect(() => model.invocationParams({})).toThrow(
2279
- 'thinking.type="enabled" is not supported for claude-opus-4-7; use thinking.type="adaptive" instead'
2280
- );
2281
- });
2282
-
2283
- test('rejects thinking.budget_tokens for claude-opus-4-7', () => {
2284
- const model = new ChatAnthropic({
2285
- model: 'claude-opus-4-7',
2286
- apiKey: 'testing',
2287
- thinking: {
2288
- type: 'adaptive',
2289
- budget_tokens: 2048,
2290
- } as AnthropicThinkingConfigParam & { budget_tokens: number },
2291
- });
2292
-
2293
- expect(() => model.invocationParams({})).toThrow(
2294
- 'thinking.budget_tokens is not supported for claude-opus-4-7; use outputConfig.effort instead'
2295
- );
2296
- });
2297
-
2298
- test('rejects non-default sampling params for claude-opus-4-7', () => {
2299
- const model = new ChatAnthropic({
2300
- model: 'claude-opus-4-7',
2301
- apiKey: 'testing',
2302
- temperature: 0.1,
2303
- });
2304
-
2305
- expect(() => model.invocationParams({})).toThrow(
2306
- 'temperature is not supported for claude-opus-4-7 when set to non-default values'
2307
- );
2308
- });
2309
-
2310
- test('does not include sampling params for claude-opus-4-7 even if set to defaults', () => {
2311
- const model = new ChatAnthropic({
2312
- model: 'claude-opus-4-7',
2313
- apiKey: 'testing',
2314
- temperature: 1,
2315
- topP: 1,
2316
- });
2317
-
2318
- const params = model.invocationParams({});
2319
-
2320
- expect(params.temperature).toBeUndefined();
2321
- expect(params.top_p).toBeUndefined();
2322
- expect(params.top_k).toBeUndefined();
2323
- });
2324
-
2325
- test('passes thinking.display through for claude-opus-4-7', () => {
2326
- const model = new ChatAnthropic({
2327
- model: 'claude-opus-4-7',
2328
- apiKey: 'testing',
2329
- thinking: { type: 'adaptive', display: 'summarized' },
2330
- });
2331
-
2332
- const params = model.invocationParams({});
2333
-
2334
- expect(params.thinking).toEqual({
2335
- type: 'adaptive',
2336
- display: 'summarized',
2337
- });
2338
- });
2339
-
2340
- test('auto-adds task budget beta when outputConfig.task_budget is provided', () => {
2341
- const model = new ChatAnthropic({
2342
- model: 'claude-opus-4-7',
2343
- apiKey: 'testing',
2344
- outputConfig: {
2345
- effort: 'high',
2346
- task_budget: { type: 'tokens', total: 128000 },
2347
- } as AnthropicOutputConfigWithTaskBudget,
2348
- });
2349
-
2350
- const params = model.invocationParams({});
2351
-
2352
- expect(params.betas).toContain('task-budgets-2026-03-13');
2353
- expect(params.output_config).toEqual({
2354
- effort: 'high',
2355
- task_budget: {
2356
- type: 'tokens',
2357
- total: 128000,
2358
- },
2359
- });
2360
- });
2361
- });
2362
-
2363
- test('Test thinking blocks multiturn invoke', async () => {
2364
- const model = new ChatAnthropic({
2365
- model: extendedThinkingModelName,
2366
- maxTokens: 5000,
2367
- thinking: { type: 'enabled', budget_tokens: 2000 },
2368
- });
2369
-
2370
- async function doInvoke(messages: BaseMessage[]) {
2371
- const response = await model.invoke(messages);
2372
-
2373
- expect(Array.isArray(response.content)).toBe(true);
2374
- const content = response.content as AnthropicMessageResponse[];
2375
- expect(content.some(isThinkingBlock)).toBe(true);
2376
-
2377
- for (const block of content) {
2378
- expect(typeof block).toBe('object');
2379
- if (isThinkingBlock(block)) {
2380
- expect(Object.keys(block).sort()).toEqual(
2381
- ['type', 'thinking', 'signature'].sort()
2382
- );
2383
- expect(block.thinking).toBeTruthy();
2384
- expect(typeof block.thinking).toBe('string');
2385
- expect(block.signature).toBeTruthy();
2386
- expect(typeof block.signature).toBe('string');
2387
- }
2388
- }
2389
- return response;
2390
- }
2391
-
2392
- const invokeMessages: BaseMessage[] = [new HumanMessage('Hello')];
2393
-
2394
- invokeMessages.push(await doInvoke(invokeMessages));
2395
- invokeMessages.push(new HumanMessage('What is 42+7?'));
2396
-
2397
- // test a second time to make sure that we've got input translation working correctly
2398
- await model.invoke(invokeMessages);
2399
- });
2400
-
2401
- test('Test thinking blocks multiturn streaming', async () => {
2402
- const model = new ChatAnthropic({
2403
- model: extendedThinkingModelName,
2404
- maxTokens: 5000,
2405
- thinking: { type: 'enabled', budget_tokens: 2000 },
2406
- });
2407
-
2408
- async function doStreaming(messages: BaseMessage[]) {
2409
- let full: AIMessageChunk | null = null;
2410
- for await (const chunk of await model.stream(messages)) {
2411
- full = full ? concat(full, chunk) : chunk;
2412
- }
2413
- expect(full).toBeInstanceOf(AIMessageChunk);
2414
- expect(Array.isArray(full?.content)).toBe(true);
2415
- const content3 = full?.content as AnthropicMessageResponse[];
2416
- expect(content3.some(isThinkingBlock)).toBe(true);
2417
-
2418
- for (const block of content3) {
2419
- expect(typeof block).toBe('object');
2420
- if (isThinkingBlock(block)) {
2421
- expect(Object.keys(block).sort()).toEqual(
2422
- ['type', 'thinking', 'signature', 'index'].sort()
2423
- );
2424
- expect(block.thinking).toBeTruthy();
2425
- expect(typeof block.thinking).toBe('string');
2426
- expect(block.signature).toBeTruthy();
2427
- expect(typeof block.signature).toBe('string');
2428
- }
2429
- }
2430
- return full as AIMessageChunk;
2431
- }
2432
-
2433
- const streamingMessages: BaseMessage[] = [new HumanMessage('Hello')];
2434
-
2435
- streamingMessages.push(await doStreaming(streamingMessages));
2436
- streamingMessages.push(new HumanMessage('What is 42+7?'));
2437
-
2438
- // test a second time to make sure that we've got input translation working correctly
2439
- await doStreaming(streamingMessages);
2440
- });
2441
-
2442
- test('Test redacted thinking blocks multiturn invoke', async () => {
2443
- const model = new ChatAnthropic({
2444
- model: extendedThinkingModelName,
2445
- maxTokens: 5000,
2446
- thinking: { type: 'enabled', budget_tokens: 2000 },
2447
- });
2448
-
2449
- async function doInvoke(messages: BaseMessage[]) {
2450
- const response = await model.invoke(messages);
2451
- let hasReasoning = false;
2452
- const content = response.content as AnthropicMessageResponse[];
2453
-
2454
- for (const block of content) {
2455
- expect(typeof block).toBe('object');
2456
- if (isRedactedThinkingBlock(block)) {
2457
- hasReasoning = true;
2458
- expect(Object.keys(block).sort()).toEqual(['type', 'data'].sort());
2459
- expect(block.data).toBeTruthy();
2460
- expect(typeof block.data).toBe('string');
2461
- }
2462
- }
2463
- if (!hasReasoning) {
2464
- expect(response.content.length).toBeGreaterThan(0);
2465
- }
2466
- return response;
2467
- }
2468
-
2469
- const invokeMessages: BaseMessage[] = [
2470
- new HumanMessage(
2471
- 'ANTHROPIC_MAGIC_STRING_TRIGGER_REDACTED_THINKING_46C9A13E193C177646C7398A98432ECCCE4C1253D5E2D82641AC0E52CC2876CB'
2472
- ),
2473
- ];
2474
-
2475
- invokeMessages.push(await doInvoke(invokeMessages));
2476
- invokeMessages.push(new HumanMessage('What is 42+7?'));
2477
-
2478
- // test a second time to make sure that we've got input translation working correctly
2479
- await doInvoke(invokeMessages);
2480
- });
2481
-
2482
- test('Test redacted thinking blocks multiturn streaming', async () => {
2483
- const model = new ChatAnthropic({
2484
- model: extendedThinkingModelName,
2485
- maxTokens: 5000,
2486
- thinking: { type: 'enabled', budget_tokens: 2000 },
2487
- });
2488
-
2489
- async function doStreaming(messages: BaseMessage[]) {
2490
- let full: AIMessageChunk | null = null;
2491
- for await (const chunk of await model.stream(messages)) {
2492
- full = full ? concat(full, chunk) : chunk;
2493
- }
2494
- expect(full).toBeInstanceOf(AIMessageChunk);
2495
- expect(Array.isArray(full?.content)).toBe(true);
2496
- let streamHasReasoning = false;
2497
- const content = full?.content as AnthropicMessageResponse[];
2498
-
2499
- for (const block of content) {
2500
- expect(typeof block).toBe('object');
2501
- if (isRedactedThinkingBlock(block)) {
2502
- streamHasReasoning = true;
2503
- expect(Object.keys(block).sort()).toEqual(
2504
- ['type', 'data', 'index'].sort()
2505
- );
2506
- expect(block.data).toBeTruthy();
2507
- expect(typeof block.data).toBe('string');
2508
- }
2509
- }
2510
- if (!streamHasReasoning) {
2511
- expect(full?.content.length).toBeGreaterThan(0);
2512
- }
2513
- return full as AIMessageChunk;
2514
- }
2515
-
2516
- const streamingMessages: BaseMessage[] = [
2517
- new HumanMessage(
2518
- 'ANTHROPIC_MAGIC_STRING_TRIGGER_REDACTED_THINKING_46C9A13E193C177646C7398A98432ECCCE4C1253D5E2D82641AC0E52CC2876CB'
2519
- ),
2520
- ];
2521
-
2522
- streamingMessages.push(await doStreaming(streamingMessages));
2523
- streamingMessages.push(new HumanMessage('What is 42+7?'));
2524
-
2525
- // test a second time to make sure that we've got input translation working correctly
2526
- await doStreaming(streamingMessages);
2527
- });
2528
-
2529
- test('Can properly format messages with redacted thinking blocks', () => {
2530
- const messageHistory = [
2531
- new AIMessage({
2532
- content: toLangChainContent([
2533
- {
2534
- type: 'redacted_thinking',
2535
- data: 'encrypted-redacted-thinking-data',
2536
- },
2537
- {
2538
- type: 'text',
2539
- text: 'Continuing after redacted thinking.',
2540
- },
2541
- ] satisfies ChatAnthropicContentBlock[]),
2542
- }),
2543
- ];
2544
-
2545
- const formattedMessages = _convertMessagesToAnthropicPayload(messageHistory);
2546
-
2547
- expect(formattedMessages.messages).toHaveLength(1);
2548
- expect(formattedMessages.messages[0].role).toBe('assistant');
2549
- expect(formattedMessages.messages[0].content).toEqual([
2550
- {
2551
- type: 'redacted_thinking',
2552
- data: 'encrypted-redacted-thinking-data',
2553
- },
2554
- {
2555
- type: 'text',
2556
- text: 'Continuing after redacted thinking.',
2557
- },
2558
- ]);
2559
- });
2560
-
2561
- test('Can convert redacted thinking stream blocks', () => {
2562
- const event: Anthropic.Beta.Messages.BetaRawMessageStreamEvent = {
2563
- type: 'content_block_start',
2564
- index: 0,
2565
- content_block: {
2566
- type: 'redacted_thinking',
2567
- data: 'encrypted-redacted-thinking-data',
2568
- },
2569
- };
2570
- const result = _makeMessageChunkFromAnthropicEvent(event, {
2571
- streamUsage: true,
2572
- coerceContentToString: false,
2573
- });
2574
-
2575
- expect(result?.chunk.content).toEqual([
2576
- {
2577
- index: 0,
2578
- type: 'redacted_thinking',
2579
- data: 'encrypted-redacted-thinking-data',
2580
- },
2581
- ]);
2582
- expect(result?.chunk.contentBlocks).toEqual([
2583
- {
2584
- type: 'non_standard',
2585
- value: {
2586
- index: 0,
2587
- type: 'redacted_thinking',
2588
- data: 'encrypted-redacted-thinking-data',
2589
- },
2590
- },
2591
- ]);
2592
- });
2593
-
2594
- test('Can handle google function calling blocks in content', async () => {
2595
- const chat = new ChatAnthropic({
2596
- modelName: 'claude-sonnet-4-5-20250929',
2597
- maxRetries: 0,
2598
- });
2599
- const toolCallId = 'tool_call_id';
2600
- const messages = [
2601
- new SystemMessage("You're a helpful assistant"),
2602
- new HumanMessage('What is the weather like in San Francisco?'),
2603
- new AIMessage({
2604
- content: toLangChainContent([
2605
- {
2606
- // Pass a content block with the `functionCall` object that Google returns.
2607
- functionCall: {
2608
- args: {
2609
- location: 'san francisco',
2610
- },
2611
- name: 'get_weather',
2612
- },
2613
- } as MessageContentComplex,
2614
- ]),
2615
- tool_calls: [
2616
- {
2617
- id: toolCallId,
2618
- name: 'get_weather',
2619
- args: {
2620
- location: 'san francisco',
2621
- },
2622
- },
2623
- ],
2624
- }),
2625
- new ToolMessage({
2626
- tool_call_id: toolCallId,
2627
- content: 'The weather is sunny',
2628
- }),
2629
- new HumanMessage(
2630
- 'Give me a one sentence description of what the sky looks like.'
2631
- ),
2632
- ];
2633
- const res = await chat.invoke(messages);
2634
- expect(res.content.length).toBeGreaterThan(1);
2635
- });
2636
-
2637
- describe('Opus 4.1', () => {
2638
- test('works without passing any args', async () => {
2639
- const model = new ChatAnthropic({
2640
- model: 'claude-opus-4-1',
2641
- });
2642
-
2643
- const response = await model.invoke(
2644
- 'Please respond to this message simply with: Hello'
2645
- );
2646
-
2647
- expect(response.content.length).toBeGreaterThan(0);
2648
- });
2649
-
2650
- test('works with streaming and thinking', async () => {
2651
- const model = new ChatAnthropic({
2652
- model: 'claude-opus-4-1',
2653
- thinking: {
2654
- type: 'enabled',
2655
- budget_tokens: 1024,
2656
- },
2657
- });
2658
-
2659
- const response = await model.invoke(
2660
- 'Please respond to this message simply with: Hello'
2661
- );
2662
-
2663
- expect(response.content.length).toBeGreaterThan(0);
2664
- });
2665
- });
2666
-
2667
- describe('Sonnet 4.5', () => {
2668
- test('works without passing any args', async () => {
2669
- const model = new ChatAnthropic({
2670
- model: 'claude-sonnet-4-5-20250929',
2671
- });
2672
-
2673
- const response = await model.invoke(
2674
- 'Please respond to this message simply with: Hello'
2675
- );
2676
-
2677
- expect(response.content.length).toBeGreaterThan(0);
2678
- });
2679
-
2680
- test('works with streaming and thinking', async () => {
2681
- const model = new ChatAnthropic({
2682
- model: 'claude-sonnet-4-5-20250929',
2683
- thinking: {
2684
- type: 'enabled',
2685
- budget_tokens: 1024,
2686
- },
2687
- });
2688
-
2689
- const response = await model.invoke(
2690
- 'Please respond to this message simply with: Hello'
2691
- );
2692
-
2693
- expect(response.content.length).toBeGreaterThan(0);
2694
- });
2695
-
2696
- test('works when passing topP arg', async () => {
2697
- const model = new ChatAnthropic({
2698
- model: 'claude-sonnet-4-5-20250929',
2699
- topP: 0.99,
2700
- });
2701
-
2702
- const response = await model.invoke(
2703
- 'Please respond to this message simply with: Hello'
2704
- );
2705
-
2706
- expect(response.content.length).toBeGreaterThan(0);
2707
- });
2708
- });
2709
-
2710
- describe('Opus 4.5', () => {
2711
- test('works without passing any args', async () => {
2712
- const model = new ChatAnthropic({
2713
- model: 'claude-opus-4-5',
2714
- });
2715
-
2716
- const response = await model.invoke(
2717
- 'Please respond to this message simply with: Hello'
2718
- );
2719
-
2720
- expect(response.content.length).toBeGreaterThan(0);
2721
- });
2722
- });
2723
-
2724
- test("won't modify structured output content if outputVersion is set", async () => {
2725
- const schema = z.object({ name: z.string() });
2726
- const model = new ChatAnthropic({
2727
- model: 'claude-opus-4-1',
2728
- outputVersion: 'v1',
2729
- });
2730
-
2731
- const response = await model
2732
- .withStructuredOutput(schema)
2733
- .invoke("respond with the name 'John'");
2734
-
2735
- expect(response.name).toBeDefined();
2736
- });
2737
-
2738
- describe('will work with native structured output', () => {
2739
- const schema = z.object({ name: z.string() });
2740
-
2741
- test.each(['claude-opus-4-1', 'claude-sonnet-4-5-20250929'])(
2742
- 'works with %s',
2743
- async (structuredOutputModelName) => {
2744
- const model = new ChatAnthropic({
2745
- model: structuredOutputModelName,
2746
- });
2747
-
2748
- const response = await model
2749
- .withStructuredOutput(schema, { method: 'jsonSchema' })
2750
- .invoke("respond with the name 'John'");
2751
-
2752
- expect(response.name).toBeDefined();
2753
- }
2754
- );
2755
- });
2756
-
2757
- describe('Anthropic Reasoning with contentBlocks', () => {
2758
- test('invoke returns thinking as reasoning in contentBlocks', async () => {
2759
- const model = new ChatAnthropic({
2760
- model: extendedThinkingModelName,
2761
- maxTokens: 5000,
2762
- thinking: { type: 'enabled', budget_tokens: 2000 },
2763
- });
2764
-
2765
- const result = await model.invoke('What is 2 + 2?');
2766
- const blocks = result.contentBlocks;
2767
-
2768
- expect(blocks.length).toBeGreaterThan(0);
2769
-
2770
- const reasoningBlocks = blocks.filter(isReasoningContentBlock);
2771
- expect(reasoningBlocks.length).toBeGreaterThan(0);
2772
- expect(reasoningBlocks[0].reasoning.length).toBeGreaterThan(10);
2773
-
2774
- const textBlocks = blocks.filter((block) => block.type === 'text');
2775
- expect(textBlocks.length).toBeGreaterThan(0);
2776
- });
2777
-
2778
- test('stream returns thinking as reasoning in contentBlocks', async () => {
2779
- const model = new ChatAnthropic({
2780
- model: extendedThinkingModelName,
2781
- maxTokens: 5000,
2782
- thinking: { type: 'enabled', budget_tokens: 2000 },
2783
- });
2784
-
2785
- let fullMessage: AIMessageChunk | null = null;
2786
- for await (const chunk of await model.stream('What is 3 + 3?')) {
2787
- fullMessage = fullMessage ? concat(fullMessage, chunk) : chunk;
2788
- }
2789
-
2790
- expect(fullMessage).toBeDefined();
2791
-
2792
- const blocks = fullMessage!.contentBlocks;
2793
- expect(blocks.length).toBeGreaterThan(0);
2794
-
2795
- const reasoningBlocks = blocks.filter(isReasoningContentBlock);
2796
- expect(reasoningBlocks.length).toBeGreaterThan(0);
2797
- expect(reasoningBlocks[0].reasoning.length).toBeGreaterThan(10);
2798
- });
2799
- });
2800
-
2801
- describe('Claude assistant prefill compatibility', () => {
2802
- test.each([
2803
- 'claude-sonnet-4-6',
2804
- 'claude-sonnet-4-6@20260217',
2805
- 'claude-opus-4-7',
2806
- 'claude-opus-4-10',
2807
- 'global.anthropic.claude-opus-4-6-v1:0',
2808
- 'anthropic/claude-sonnet-4.6',
2809
- 'anthropic/claude-sonnet-4.12',
2810
- ])('detects %s as not supporting assistant prefill', (model) => {
2811
- expect(modelDisallowsAssistantPrefill(model)).toBe(true);
2812
- });
2813
-
2814
- test.each([
2815
- 'claude-sonnet-4-5-20250929',
2816
- 'claude-opus-4-20250514',
2817
- 'anthropic.claude-opus-4-20250514-v1:0',
2818
- 'gpt-5.4',
2819
- ])('leaves %s prefill support unchanged', (model) => {
2820
- expect(modelDisallowsAssistantPrefill(model)).toBe(false);
2821
- });
2822
-
2823
- test('strips trailing assistant messages for Claude 4.6+ requests', () => {
2824
- const request = {
2825
- model: 'claude-opus-4-6',
2826
- max_tokens: 100,
2827
- messages: [
2828
- { role: 'user' as const, content: 'What changed?' },
2829
- { role: 'assistant' as const, content: 'Draft prefill' },
2830
- { role: 'assistant' as const, content: 'Another prefill' },
2831
- ],
2832
- };
2833
-
2834
- const sanitized = stripUnsupportedAssistantPrefill(request);
2835
-
2836
- expect(sanitized).not.toBe(request);
2837
- expect(sanitized.messages).toEqual([
2838
- { role: 'user', content: 'What changed?' },
2839
- ]);
2840
- });
2841
-
2842
- test('does not strip assistant messages for older Claude models', () => {
2843
- const request = {
2844
- model: 'claude-sonnet-4-5-20250929',
2845
- max_tokens: 100,
2846
- messages: [
2847
- { role: 'user' as const, content: 'Write JSON only.' },
2848
- { role: 'assistant' as const, content: '{' },
2849
- ],
2850
- };
2851
-
2852
- expect(stripUnsupportedAssistantPrefill(request)).toBe(request);
2853
- });
2854
- });
2855
-
2856
- const opus46Model = 'claude-opus-4-6';
2857
-
2858
- describe('Opus 4.6', () => {
2859
- describe('Adaptive thinking', () => {
2860
- test('invocationParams accepts adaptive thinking type', () => {
2861
- const model = new ChatAnthropic({
2862
- model: opus46Model,
2863
- apiKey: 'testing',
2864
- maxTokens: 4096,
2865
- thinking: { type: 'adaptive' },
2866
- });
2867
-
2868
- const params = model.invocationParams({});
2869
-
2870
- expect(params.thinking).toEqual({ type: 'adaptive' });
2871
- });
2872
-
2873
- test('adaptive thinking disables temperature/topK/topP', () => {
2874
- const model = new ChatAnthropic({
2875
- model: opus46Model,
2876
- apiKey: 'testing',
2877
- maxTokens: 4096,
2878
- thinking: { type: 'adaptive' },
2879
- });
2880
-
2881
- const params = model.invocationParams({});
2882
-
2883
- expect(params.temperature).toBeUndefined();
2884
- expect(params.top_k).toBeUndefined();
2885
- expect(params.top_p).toBeUndefined();
2886
- });
2887
-
2888
- test('adaptive thinking treats sampling sentinels as unset', () => {
2889
- const model = new ChatAnthropic({
2890
- model: opus46Model,
2891
- apiKey: 'testing',
2892
- maxTokens: 4096,
2893
- thinking: { type: 'adaptive' },
2894
- });
2895
- model.temperature = -1;
2896
- model.topP = -1;
2897
- model.top_k = -1;
2898
-
2899
- const params = model.invocationParams({});
2900
-
2901
- expect(params.temperature).toBeUndefined();
2902
- expect(params.top_k).toBeUndefined();
2903
- expect(params.top_p).toBeUndefined();
2904
- });
2905
-
2906
- test('adaptive thinking throws on non-default temperature', () => {
2907
- const model = new ChatAnthropic({
2908
- model: opus46Model,
2909
- temperature: 0.5,
2910
- apiKey: 'testing',
2911
- maxTokens: 4096,
2912
- thinking: { type: 'adaptive' },
2913
- });
2914
-
2915
- expect(() => model.invocationParams({})).toThrow(
2916
- 'temperature is not supported when thinking is enabled'
2917
- );
2918
- });
2919
-
2920
- test('adaptive thinking invoke', async () => {
2921
- const model = new ChatAnthropic({
2922
- model: opus46Model,
2923
- maxTokens: 4096,
2924
- thinking: { type: 'adaptive' },
2925
- });
2926
-
2927
- const result = await model.invoke('What is 15 * 23?');
2928
- expect(result.content).toBeDefined();
2929
-
2930
- if (Array.isArray(result.content)) {
2931
- const textBlocks = result.content.filter(isTextContentBlock);
2932
- expect(textBlocks.length).toBeGreaterThan(0);
2933
- } else {
2934
- expect(typeof result.content).toBe('string');
2935
- expect((result.content as string).length).toBeGreaterThan(0);
2936
- }
2937
- });
2938
-
2939
- test('adaptive thinking multiturn round-trip', async () => {
2940
- const model = new ChatAnthropic({
2941
- model: opus46Model,
2942
- maxTokens: 4096,
2943
- thinking: { type: 'adaptive' },
2944
- });
2945
-
2946
- const messages: BaseMessage[] = [new HumanMessage('Hello')];
2947
- const response1 = await model.invoke(messages);
2948
- messages.push(response1);
2949
- messages.push(new HumanMessage('What is 42 + 7?'));
2950
-
2951
- const response2 = await model.invoke(messages);
2952
- expect(response2.content).toBeDefined();
2953
- });
2954
-
2955
- test('withStructuredOutput jsonSchema', async () => {
2956
- const model = new ChatAnthropic({
2957
- model: opus46Model,
2958
- maxTokens: 4096,
2959
- });
2960
-
2961
- const schema = z.object({
2962
- answer: z.number().describe('The numeric answer'),
2963
- });
2964
-
2965
- const structured = model.withStructuredOutput(schema, {
2966
- method: 'jsonSchema',
2967
- });
2968
-
2969
- const result = await structured.invoke('What is 2 + 2?');
2970
- expect(result).toBeDefined();
2971
- expect(typeof result.answer).toBe('number');
2972
- });
2973
- });
2974
-
2975
- describe('Effort parameter (outputConfig)', () => {
2976
- test('invocationParams passes outputConfig from constructor', () => {
2977
- const model = new ChatAnthropic({
2978
- model: opus46Model,
2979
- apiKey: 'testing',
2980
- maxTokens: 4096,
2981
- outputConfig: { effort: 'medium' },
2982
- });
2983
-
2984
- const params = model.invocationParams({});
2985
-
2986
- expect(params.output_config).toEqual({ effort: 'medium' });
2987
- });
2988
-
2989
- test('invocationParams passes outputConfig from call options', () => {
2990
- const model = new ChatAnthropic({
2991
- model: opus46Model,
2992
- apiKey: 'testing',
2993
- maxTokens: 4096,
2994
- });
2995
-
2996
- const params = model.invocationParams({
2997
- outputConfig: { effort: 'low' },
2998
- });
2999
-
3000
- expect(params.output_config).toEqual({ effort: 'low' });
3001
- });
3002
-
3003
- test('call-option outputConfig overrides constructor outputConfig', () => {
3004
- const model = new ChatAnthropic({
3005
- model: opus46Model,
3006
- apiKey: 'testing',
3007
- maxTokens: 4096,
3008
- outputConfig: { effort: 'high' },
3009
- });
3010
-
3011
- const params = model.invocationParams({
3012
- outputConfig: { effort: 'low' },
3013
- });
3014
-
3015
- expect(params.output_config).toEqual({ effort: 'low' });
3016
- });
3017
-
3018
- test('effort max is accepted', () => {
3019
- const model = new ChatAnthropic({
3020
- model: opus46Model,
3021
- apiKey: 'testing',
3022
- maxTokens: 4096,
3023
- outputConfig: { effort: 'max' },
3024
- });
3025
-
3026
- const params = model.invocationParams({});
3027
-
3028
- expect(params.output_config).toEqual({ effort: 'max' });
3029
- });
3030
-
3031
- test('output_config is undefined when not set', () => {
3032
- const model = new ChatAnthropic({
3033
- model: opus46Model,
3034
- apiKey: 'testing',
3035
- maxTokens: 4096,
3036
- });
3037
-
3038
- const params = model.invocationParams({});
3039
-
3040
- expect(params.output_config).toBeUndefined();
3041
- });
3042
-
3043
- test.each(['low', 'medium', 'high'] as const)(
3044
- 'invoke with %s effort',
3045
- async (effort) => {
3046
- const model = new ChatAnthropic({
3047
- model: opus46Model,
3048
- maxTokens: 4096,
3049
- thinking: { type: 'adaptive' },
3050
- outputConfig: { effort },
3051
- });
3052
-
3053
- const result = await model.invoke('Say hello.');
3054
- expect(result.content).toBeDefined();
3055
- }
3056
- );
3057
-
3058
- test.each(['low', 'medium', 'high'] as const)(
3059
- 'stream with %s effort',
3060
- async (effort) => {
3061
- const model = new ChatAnthropic({
3062
- model: opus46Model,
3063
- maxTokens: 4096,
3064
- thinking: { type: 'adaptive' },
3065
- outputConfig: { effort },
3066
- });
3067
-
3068
- let full: AIMessageChunk | undefined;
3069
- for await (const chunk of await model.stream('Say hello.')) {
3070
- full = full ? concat(full, chunk) : chunk;
3071
- }
3072
- expect(full).toBeInstanceOf(AIMessageChunk);
3073
- expect(full!.content).toBeDefined();
3074
- }
3075
- );
3076
-
3077
- test('via call options', async () => {
3078
- const model = new ChatAnthropic({
3079
- model: opus46Model,
3080
- maxTokens: 4096,
3081
- thinking: { type: 'adaptive' },
3082
- });
3083
-
3084
- const options: CustomAnthropicCallOptions = {
3085
- outputConfig: { effort: 'low' },
3086
- };
3087
- const result = await model.invoke('Say hello.', options);
3088
- expect(result.content).toBeDefined();
3089
- });
3090
- });
3091
-
3092
- describe('outputFormat to outputConfig.format migration', () => {
3093
- test('deprecated outputFormat on call options maps to output_config.format', () => {
3094
- const model = new ChatAnthropic({
3095
- model: opus46Model,
3096
- apiKey: 'testing',
3097
- maxTokens: 4096,
3098
- });
3099
-
3100
- const params = model.invocationParams({
3101
- outputFormat: {
3102
- type: 'json_schema',
3103
- schema: { type: 'object' },
3104
- },
3105
- });
3106
-
3107
- expect(params.output_config).toEqual({
3108
- format: {
3109
- type: 'json_schema',
3110
- schema: { type: 'object' },
3111
- },
3112
- });
3113
- });
3114
-
3115
- test('outputConfig.format takes precedence over deprecated outputFormat', () => {
3116
- const model = new ChatAnthropic({
3117
- model: opus46Model,
3118
- apiKey: 'testing',
3119
- maxTokens: 4096,
3120
- });
3121
-
3122
- const params = model.invocationParams({
3123
- outputConfig: {
3124
- format: {
3125
- type: 'json_schema',
3126
- schema: { type: 'object', properties: { a: { type: 'string' } } },
3127
- },
3128
- },
3129
- outputFormat: {
3130
- type: 'json_schema',
3131
- schema: { type: 'object', properties: { b: { type: 'number' } } },
3132
- },
3133
- });
3134
-
3135
- expect(params.output_config?.format).toEqual({
3136
- type: 'json_schema',
3137
- schema: { type: 'object', properties: { a: { type: 'string' } } },
3138
- });
3139
- });
3140
-
3141
- test('effort and format can be combined in outputConfig', () => {
3142
- const model = new ChatAnthropic({
3143
- model: opus46Model,
3144
- apiKey: 'testing',
3145
- maxTokens: 4096,
3146
- outputConfig: { effort: 'medium' },
3147
- });
3148
-
3149
- const params = model.invocationParams({
3150
- outputFormat: {
3151
- type: 'json_schema',
3152
- schema: { type: 'object' },
3153
- },
3154
- });
3155
-
3156
- expect(params.output_config).toEqual({
3157
- effort: 'medium',
3158
- format: {
3159
- type: 'json_schema',
3160
- schema: { type: 'object' },
3161
- },
3162
- });
3163
- });
3164
- });
3165
-
3166
- describe('Data residency (inferenceGeo)', () => {
3167
- test('invocationParams passes inferenceGeo from constructor', () => {
3168
- const model = new ChatAnthropic({
3169
- model: opus46Model,
3170
- apiKey: 'testing',
3171
- maxTokens: 4096,
3172
- inferenceGeo: 'us',
3173
- });
3174
-
3175
- const params = model.invocationParams({});
3176
-
3177
- expect(params.inference_geo).toBe('us');
3178
- });
3179
-
3180
- test('invocationParams passes inferenceGeo from call options', () => {
3181
- const model = new ChatAnthropic({
3182
- model: opus46Model,
3183
- apiKey: 'testing',
3184
- maxTokens: 4096,
3185
- });
3186
-
3187
- const params = model.invocationParams({
3188
- inferenceGeo: 'us',
3189
- });
3190
-
3191
- expect(params.inference_geo).toBe('us');
3192
- });
3193
-
3194
- test('call-option inferenceGeo overrides constructor inferenceGeo', () => {
3195
- const model = new ChatAnthropic({
3196
- model: opus46Model,
3197
- apiKey: 'testing',
3198
- maxTokens: 4096,
3199
- inferenceGeo: 'eu',
3200
- });
3201
-
3202
- const params = model.invocationParams({
3203
- inferenceGeo: 'us',
3204
- });
3205
-
3206
- expect(params.inference_geo).toBe('us');
3207
- });
3208
-
3209
- test('inferenceGeo is undefined when not set', () => {
3210
- const model = new ChatAnthropic({
3211
- model: opus46Model,
3212
- apiKey: 'testing',
3213
- maxTokens: 4096,
3214
- });
3215
-
3216
- const params = model.invocationParams({});
3217
-
3218
- expect(params.inference_geo).toBeUndefined();
3219
- });
3220
-
3221
- test('inferenceGeo accepted by API', async () => {
3222
- const model = new ChatAnthropic({
3223
- model: opus46Model,
3224
- maxTokens: 256,
3225
- inferenceGeo: 'us',
3226
- });
3227
-
3228
- const result = await model.invoke('Say hello.');
3229
- expect(result.content).toBeDefined();
3230
- });
3231
- });
3232
-
3233
- describe('Compaction API', () => {
3234
- const compactionConfig: AnthropicContextManagementConfigParam = {
3235
- edits: [
3236
- {
3237
- type: 'compact_20260112' as const,
3238
- trigger: { type: 'input_tokens' as const, value: 50000 },
3239
- },
3240
- ],
3241
- };
3242
-
3243
- function buildLongConversation(): BaseMessage[] {
3244
- const padding =
3245
- 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. ' +
3246
- 'Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. ' +
3247
- 'Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris ' +
3248
- 'nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in ' +
3249
- 'reprehenderit in voluptate velit esse cillum dolore eu fugiat. ';
3250
-
3251
- const messages: BaseMessage[] = [];
3252
- for (let i = 0; i < 300; i++) {
3253
- messages.push(new HumanMessage(`${padding} (message ${i})`));
3254
- messages.push(new AIMessage(`Acknowledged message ${i}. ${padding}`));
3255
- }
3256
- messages.push(new HumanMessage('Summarize our conversation.'));
3257
- return messages;
3258
- }
3259
-
3260
- test('context_management passed through invocationParams', () => {
3261
- const model = new ChatAnthropic({
3262
- model: opus46Model,
3263
- apiKey: 'testing',
3264
- maxTokens: 4096,
3265
- contextManagement: compactionConfig,
3266
- });
3267
-
3268
- const params = model.invocationParams({});
3269
-
3270
- const contextManagement = expectDefined(params.context_management);
3271
- const edits = expectDefined(contextManagement.edits);
3272
- expect(edits[0].type).toBe('compact_20260112');
3273
- });
3274
-
3275
- test('accepted by API without triggering', async () => {
3276
- const model = new ChatAnthropic({
3277
- model: opus46Model,
3278
- maxTokens: 4096,
3279
- contextManagement: compactionConfig,
3280
- });
3281
-
3282
- const response = await model.invoke('Say hello.');
3283
- expect(response.content).toBeDefined();
3284
- });
3285
-
3286
- test('triggers compaction block (invoke)', async () => {
3287
- const model = new ChatAnthropic({
3288
- model: opus46Model,
3289
- maxTokens: 4096,
3290
- contextManagement: compactionConfig,
3291
- });
3292
-
3293
- const result = await model.invoke(buildLongConversation());
3294
-
3295
- const blocks = expectContentArray<ContentBlock>(result.content);
3296
- const compactionBlock = expectDefined(blocks.find(isCompactionBlock));
3297
- expect(typeof compactionBlock.content).toBe('string');
3298
- expect(compactionBlock.content.length).toBeGreaterThan(0);
3299
- });
3300
-
3301
- test('triggers compaction block (stream)', async () => {
3302
- const model = new ChatAnthropic({
3303
- model: opus46Model,
3304
- maxTokens: 4096,
3305
- contextManagement: compactionConfig,
3306
- });
3307
-
3308
- let full: AIMessageChunk | undefined;
3309
- for await (const chunk of await model.stream(buildLongConversation())) {
3310
- full = full ? concat(full, chunk) : chunk;
3311
- }
3312
-
3313
- expect(full).toBeInstanceOf(AIMessageChunk);
3314
- const blocks = expectContentArray<ContentBlock>(full!.content);
3315
- const compactionBlock = expectDefined(blocks.find(isCompactionBlock));
3316
- expect(typeof compactionBlock.content).toBe('string');
3317
- expect(compactionBlock.content.length).toBeGreaterThan(0);
3318
- });
3319
-
3320
- test('Can properly format messages with compaction blocks', () => {
3321
- const messageHistory = [
3322
- new AIMessage({
3323
- content: [
3324
- {
3325
- type: 'compaction',
3326
- content:
3327
- 'Summary: The user asked about building a web scraper...',
3328
- },
3329
- {
3330
- type: 'text',
3331
- text: 'Based on our conversation so far, let me continue...',
3332
- },
3333
- ],
3334
- }),
3335
- ];
3336
-
3337
- const formattedMessages =
3338
- _convertMessagesToAnthropicPayload(messageHistory);
3339
-
3340
- expect(formattedMessages.messages).toHaveLength(1);
3341
- expect(formattedMessages.messages[0].role).toBe('assistant');
3342
- expect(formattedMessages.messages[0].content).toHaveLength(2);
3343
-
3344
- const [compactionBlock, textBlock] =
3345
- expectContentArray<Anthropic.Messages.ContentBlockParam>(
3346
- formattedMessages.messages[0].content
3347
- );
3348
- expect(compactionBlock).toEqual({
3349
- type: 'compaction',
3350
- content: 'Summary: The user asked about building a web scraper...',
3351
- });
3352
- expect(textBlock).toEqual({
3353
- type: 'text',
3354
- text: 'Based on our conversation so far, let me continue...',
3355
- });
3356
- });
3357
- });
3358
- });
3359
-
3360
- describe('Tool input survives message conversion', () => {
3361
- // Adapted from @langchain/anthropic's "converting messages doesn't drop tool input".
3362
- // Guards the core >= 1.1.46 streaming-aggregation regression where the tool_use
3363
- // content block's input was emptied (and re-serialization dropped it).
3364
- test('converting messages does not drop tool input (live)', async () => {
3365
- const jokeTool = {
3366
- name: 'generate_random_joke',
3367
- description: 'Generate a random joke.',
3368
- schema: z.object({
3369
- prompt: z.string().describe('The prompt to generate the joke for.'),
3370
- }),
3371
- };
3372
- const model = new ChatAnthropic({
3373
- model: 'claude-sonnet-4-5-20250929',
3374
- temperature: 0,
3375
- }).bindTools([jokeTool]);
3376
-
3377
- const result = await model.invoke([
3378
- new HumanMessage(
3379
- 'Generate three (3) random jokes. Use the generate_random_joke tool and call it three times before responding. This is very important.'
3380
- ),
3381
- ]);
3382
- expect(result.tool_calls?.length ?? 0).toBeGreaterThan(0);
3383
-
3384
- const converted = _convertMessagesToAnthropicPayload([result]);
3385
- const toolUseBlocks = (
3386
- converted.messages[0].content as unknown as Array<Record<string, unknown>>
3387
- ).filter((block) => block.type === 'tool_use');
3388
- expect(toolUseBlocks.length).toBeGreaterThan(0);
3389
- for (const block of toolUseBlocks) {
3390
- expect(block.input).toBeDefined();
3391
- expect((block.input as Record<string, unknown>).prompt).toBeDefined();
3392
- }
3393
- });
3394
- });