@illuma-ai/agents 1.0.90 → 1.0.93

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 (838) hide show
  1. package/dist/cjs/agents/AgentContext.cjs +98 -49
  2. package/dist/cjs/agents/AgentContext.cjs.map +1 -1
  3. package/dist/cjs/common/constants.cjs +25 -0
  4. package/dist/cjs/common/constants.cjs.map +1 -0
  5. package/dist/cjs/common/enum.cjs +30 -0
  6. package/dist/cjs/common/enum.cjs.map +1 -1
  7. package/dist/cjs/events.cjs +9 -4
  8. package/dist/cjs/events.cjs.map +1 -1
  9. package/dist/cjs/graphs/Graph.cjs +397 -92
  10. package/dist/cjs/graphs/Graph.cjs.map +1 -1
  11. package/dist/cjs/graphs/MultiAgentGraph.cjs +223 -92
  12. package/dist/cjs/graphs/MultiAgentGraph.cjs.map +1 -1
  13. package/dist/cjs/instrumentation.cjs +30 -14
  14. package/dist/cjs/instrumentation.cjs.map +1 -1
  15. package/dist/cjs/llm/anthropic/index.cjs +43 -11
  16. package/dist/cjs/llm/anthropic/index.cjs.map +1 -1
  17. package/dist/cjs/llm/anthropic/types.cjs.map +1 -1
  18. package/dist/cjs/llm/anthropic/utils/message_inputs.cjs +10 -7
  19. package/dist/cjs/llm/anthropic/utils/message_inputs.cjs.map +1 -1
  20. package/dist/cjs/llm/anthropic/utils/message_outputs.cjs +32 -0
  21. package/dist/cjs/llm/anthropic/utils/message_outputs.cjs.map +1 -1
  22. package/dist/cjs/llm/anthropic/utils/tools.cjs.map +1 -1
  23. package/dist/cjs/llm/bedrock/index.cjs +129 -101
  24. package/dist/cjs/llm/bedrock/index.cjs.map +1 -1
  25. package/dist/cjs/llm/bedrock/utils/message_inputs.cjs +489 -0
  26. package/dist/cjs/llm/bedrock/utils/message_inputs.cjs.map +1 -0
  27. package/dist/cjs/llm/bedrock/utils/message_outputs.cjs +176 -0
  28. package/dist/cjs/llm/bedrock/utils/message_outputs.cjs.map +1 -0
  29. package/dist/cjs/llm/fake.cjs.map +1 -1
  30. package/dist/cjs/llm/google/index.cjs.map +1 -1
  31. package/dist/cjs/llm/google/utils/common.cjs.map +1 -1
  32. package/dist/cjs/llm/openai/index.cjs +1 -1
  33. package/dist/cjs/llm/openai/index.cjs.map +1 -1
  34. package/dist/cjs/llm/openai/utils/index.cjs.map +1 -1
  35. package/dist/cjs/llm/openrouter/index.cjs +59 -5
  36. package/dist/cjs/llm/openrouter/index.cjs.map +1 -1
  37. package/dist/cjs/llm/providers.cjs.map +1 -1
  38. package/dist/cjs/llm/text.cjs.map +1 -1
  39. package/dist/cjs/llm/vertexai/index.cjs +80 -2
  40. package/dist/cjs/llm/vertexai/index.cjs.map +1 -1
  41. package/dist/cjs/main.cjs +60 -27
  42. package/dist/cjs/main.cjs.map +1 -1
  43. package/dist/cjs/messages/cache.cjs +131 -108
  44. package/dist/cjs/messages/cache.cjs.map +1 -1
  45. package/dist/cjs/messages/content.cjs.map +1 -1
  46. package/dist/cjs/messages/core.cjs +3 -0
  47. package/dist/cjs/messages/core.cjs.map +1 -1
  48. package/dist/cjs/messages/format.cjs +265 -47
  49. package/dist/cjs/messages/format.cjs.map +1 -1
  50. package/dist/cjs/messages/ids.cjs.map +1 -1
  51. package/dist/cjs/messages/prune.cjs +55 -2
  52. package/dist/cjs/messages/prune.cjs.map +1 -1
  53. package/dist/cjs/messages/summarize.cjs +170 -0
  54. package/dist/cjs/messages/summarize.cjs.map +1 -0
  55. package/dist/cjs/messages/tools.cjs.map +1 -1
  56. package/dist/cjs/run.cjs +87 -30
  57. package/dist/cjs/run.cjs.map +1 -1
  58. package/dist/cjs/schemas/validate.cjs.map +1 -1
  59. package/dist/cjs/splitStream.cjs.map +1 -1
  60. package/dist/cjs/stream.cjs +59 -25
  61. package/dist/cjs/stream.cjs.map +1 -1
  62. package/dist/cjs/tools/AskUser.cjs +131 -0
  63. package/dist/cjs/tools/AskUser.cjs.map +1 -0
  64. package/dist/cjs/tools/BrowserTools.cjs +11 -7
  65. package/dist/cjs/tools/BrowserTools.cjs.map +1 -1
  66. package/dist/cjs/tools/Calculator.cjs.map +1 -1
  67. package/dist/cjs/tools/CodeExecutor.cjs +46 -4
  68. package/dist/cjs/tools/CodeExecutor.cjs.map +1 -1
  69. package/dist/cjs/tools/ProgrammaticToolCalling.cjs +36 -53
  70. package/dist/cjs/tools/ProgrammaticToolCalling.cjs.map +1 -1
  71. package/dist/cjs/tools/StreamingToolCallBuffer.cjs +208 -0
  72. package/dist/cjs/tools/StreamingToolCallBuffer.cjs.map +1 -0
  73. package/dist/cjs/tools/ToolNode.cjs +333 -30
  74. package/dist/cjs/tools/ToolNode.cjs.map +1 -1
  75. package/dist/cjs/tools/ToolSearch.cjs +66 -30
  76. package/dist/cjs/tools/ToolSearch.cjs.map +1 -1
  77. package/dist/cjs/tools/handlers.cjs +94 -8
  78. package/dist/cjs/tools/handlers.cjs.map +1 -1
  79. package/dist/cjs/tools/schema.cjs.map +1 -1
  80. package/dist/cjs/tools/search/content.cjs.map +1 -1
  81. package/dist/cjs/tools/search/firecrawl.cjs.map +1 -1
  82. package/dist/cjs/tools/search/format.cjs.map +1 -1
  83. package/dist/cjs/tools/search/highlights.cjs.map +1 -1
  84. package/dist/cjs/tools/search/rerankers.cjs.map +1 -1
  85. package/dist/cjs/tools/search/schema.cjs.map +1 -1
  86. package/dist/cjs/tools/search/search.cjs +1 -0
  87. package/dist/cjs/tools/search/search.cjs.map +1 -1
  88. package/dist/cjs/tools/search/serper-scraper.cjs.map +1 -1
  89. package/dist/cjs/tools/search/tool.cjs.map +1 -1
  90. package/dist/cjs/tools/search/utils.cjs.map +1 -1
  91. package/dist/cjs/types/graph.cjs +1 -1
  92. package/dist/cjs/types/graph.cjs.map +1 -1
  93. package/dist/cjs/utils/contextAnalytics.cjs +23 -6
  94. package/dist/cjs/utils/contextAnalytics.cjs.map +1 -1
  95. package/dist/cjs/utils/events.cjs.map +1 -1
  96. package/dist/cjs/utils/graph.cjs.map +1 -1
  97. package/dist/cjs/utils/handlers.cjs.map +1 -1
  98. package/dist/cjs/utils/llm.cjs.map +1 -1
  99. package/dist/cjs/utils/misc.cjs.map +1 -1
  100. package/dist/cjs/utils/run.cjs +3 -1
  101. package/dist/cjs/utils/run.cjs.map +1 -1
  102. package/dist/cjs/utils/schema.cjs.map +1 -1
  103. package/dist/cjs/utils/title.cjs.map +1 -1
  104. package/dist/cjs/utils/tokens.cjs +33 -58
  105. package/dist/cjs/utils/tokens.cjs.map +1 -1
  106. package/dist/cjs/utils/toolCallContinuation.cjs +55 -0
  107. package/dist/cjs/utils/toolCallContinuation.cjs.map +1 -0
  108. package/dist/cjs/utils/toonFormat.cjs.map +1 -1
  109. package/dist/esm/agents/AgentContext.mjs +98 -49
  110. package/dist/esm/agents/AgentContext.mjs.map +1 -1
  111. package/dist/esm/common/constants.mjs +22 -0
  112. package/dist/esm/common/constants.mjs.map +1 -0
  113. package/dist/esm/common/enum.mjs +31 -1
  114. package/dist/esm/common/enum.mjs.map +1 -1
  115. package/dist/esm/events.mjs +9 -4
  116. package/dist/esm/events.mjs.map +1 -1
  117. package/dist/esm/graphs/Graph.mjs +393 -88
  118. package/dist/esm/graphs/Graph.mjs.map +1 -1
  119. package/dist/esm/graphs/MultiAgentGraph.mjs +224 -93
  120. package/dist/esm/graphs/MultiAgentGraph.mjs.map +1 -1
  121. package/dist/esm/instrumentation.mjs +30 -14
  122. package/dist/esm/instrumentation.mjs.map +1 -1
  123. package/dist/esm/llm/anthropic/index.mjs +43 -11
  124. package/dist/esm/llm/anthropic/index.mjs.map +1 -1
  125. package/dist/esm/llm/anthropic/types.mjs.map +1 -1
  126. package/dist/esm/llm/anthropic/utils/message_inputs.mjs +10 -7
  127. package/dist/esm/llm/anthropic/utils/message_inputs.mjs.map +1 -1
  128. package/dist/esm/llm/anthropic/utils/message_outputs.mjs +32 -0
  129. package/dist/esm/llm/anthropic/utils/message_outputs.mjs.map +1 -1
  130. package/dist/esm/llm/anthropic/utils/tools.mjs.map +1 -1
  131. package/dist/esm/llm/bedrock/index.mjs +128 -101
  132. package/dist/esm/llm/bedrock/index.mjs.map +1 -1
  133. package/dist/esm/llm/bedrock/utils/message_inputs.mjs +484 -0
  134. package/dist/esm/llm/bedrock/utils/message_inputs.mjs.map +1 -0
  135. package/dist/esm/llm/bedrock/utils/message_outputs.mjs +171 -0
  136. package/dist/esm/llm/bedrock/utils/message_outputs.mjs.map +1 -0
  137. package/dist/esm/llm/fake.mjs.map +1 -1
  138. package/dist/esm/llm/google/index.mjs.map +1 -1
  139. package/dist/esm/llm/google/utils/common.mjs.map +1 -1
  140. package/dist/esm/llm/openai/index.mjs +1 -1
  141. package/dist/esm/llm/openai/index.mjs.map +1 -1
  142. package/dist/esm/llm/openai/utils/index.mjs.map +1 -1
  143. package/dist/esm/llm/openrouter/index.mjs +59 -5
  144. package/dist/esm/llm/openrouter/index.mjs.map +1 -1
  145. package/dist/esm/llm/providers.mjs.map +1 -1
  146. package/dist/esm/llm/text.mjs.map +1 -1
  147. package/dist/esm/llm/vertexai/index.mjs +80 -2
  148. package/dist/esm/llm/vertexai/index.mjs.map +1 -1
  149. package/dist/esm/main.mjs +8 -3
  150. package/dist/esm/main.mjs.map +1 -1
  151. package/dist/esm/messages/cache.mjs +131 -108
  152. package/dist/esm/messages/cache.mjs.map +1 -1
  153. package/dist/esm/messages/content.mjs.map +1 -1
  154. package/dist/esm/messages/core.mjs +4 -1
  155. package/dist/esm/messages/core.mjs.map +1 -1
  156. package/dist/esm/messages/format.mjs +267 -49
  157. package/dist/esm/messages/format.mjs.map +1 -1
  158. package/dist/esm/messages/ids.mjs.map +1 -1
  159. package/dist/esm/messages/prune.mjs +56 -4
  160. package/dist/esm/messages/prune.mjs.map +1 -1
  161. package/dist/esm/messages/summarize.mjs +161 -0
  162. package/dist/esm/messages/summarize.mjs.map +1 -0
  163. package/dist/esm/messages/tools.mjs.map +1 -1
  164. package/dist/esm/run.mjs +88 -31
  165. package/dist/esm/run.mjs.map +1 -1
  166. package/dist/esm/schemas/validate.mjs.map +1 -1
  167. package/dist/esm/splitStream.mjs.map +1 -1
  168. package/dist/esm/stream.mjs +60 -26
  169. package/dist/esm/stream.mjs.map +1 -1
  170. package/dist/esm/tools/AskUser.mjs +125 -0
  171. package/dist/esm/tools/AskUser.mjs.map +1 -0
  172. package/dist/esm/tools/BrowserTools.mjs +11 -7
  173. package/dist/esm/tools/BrowserTools.mjs.map +1 -1
  174. package/dist/esm/tools/Calculator.mjs.map +1 -1
  175. package/dist/esm/tools/CodeExecutor.mjs +46 -4
  176. package/dist/esm/tools/CodeExecutor.mjs.map +1 -1
  177. package/dist/esm/tools/ProgrammaticToolCalling.mjs +37 -54
  178. package/dist/esm/tools/ProgrammaticToolCalling.mjs.map +1 -1
  179. package/dist/esm/tools/StreamingToolCallBuffer.mjs +206 -0
  180. package/dist/esm/tools/StreamingToolCallBuffer.mjs.map +1 -0
  181. package/dist/esm/tools/ToolNode.mjs +333 -30
  182. package/dist/esm/tools/ToolNode.mjs.map +1 -1
  183. package/dist/esm/tools/ToolSearch.mjs +66 -30
  184. package/dist/esm/tools/ToolSearch.mjs.map +1 -1
  185. package/dist/esm/tools/handlers.mjs +95 -9
  186. package/dist/esm/tools/handlers.mjs.map +1 -1
  187. package/dist/esm/tools/schema.mjs.map +1 -1
  188. package/dist/esm/tools/search/content.mjs.map +1 -1
  189. package/dist/esm/tools/search/firecrawl.mjs.map +1 -1
  190. package/dist/esm/tools/search/format.mjs.map +1 -1
  191. package/dist/esm/tools/search/highlights.mjs.map +1 -1
  192. package/dist/esm/tools/search/rerankers.mjs.map +1 -1
  193. package/dist/esm/tools/search/schema.mjs.map +1 -1
  194. package/dist/esm/tools/search/search.mjs +1 -0
  195. package/dist/esm/tools/search/search.mjs.map +1 -1
  196. package/dist/esm/tools/search/serper-scraper.mjs.map +1 -1
  197. package/dist/esm/tools/search/tool.mjs.map +1 -1
  198. package/dist/esm/tools/search/utils.mjs.map +1 -1
  199. package/dist/esm/types/graph.mjs +1 -1
  200. package/dist/esm/types/graph.mjs.map +1 -1
  201. package/dist/esm/utils/contextAnalytics.mjs +23 -6
  202. package/dist/esm/utils/contextAnalytics.mjs.map +1 -1
  203. package/dist/esm/utils/events.mjs.map +1 -1
  204. package/dist/esm/utils/graph.mjs.map +1 -1
  205. package/dist/esm/utils/handlers.mjs.map +1 -1
  206. package/dist/esm/utils/llm.mjs.map +1 -1
  207. package/dist/esm/utils/misc.mjs.map +1 -1
  208. package/dist/esm/utils/run.mjs +3 -1
  209. package/dist/esm/utils/run.mjs.map +1 -1
  210. package/dist/esm/utils/schema.mjs.map +1 -1
  211. package/dist/esm/utils/title.mjs.map +1 -1
  212. package/dist/esm/utils/tokens.mjs +33 -59
  213. package/dist/esm/utils/tokens.mjs.map +1 -1
  214. package/dist/esm/utils/toolCallContinuation.mjs +52 -0
  215. package/dist/esm/utils/toolCallContinuation.mjs.map +1 -0
  216. package/dist/esm/utils/toonFormat.mjs.map +1 -1
  217. package/dist/types/agents/AgentContext.d.ts +14 -7
  218. package/dist/types/common/constants.d.ts +18 -0
  219. package/dist/types/common/enum.d.ts +28 -0
  220. package/dist/types/common/index.d.ts +1 -0
  221. package/dist/types/events.d.ts +10 -3
  222. package/dist/types/graphs/Graph.d.ts +37 -0
  223. package/dist/types/index.d.ts +4 -0
  224. package/dist/types/llm/anthropic/index.d.ts +7 -1
  225. package/dist/types/llm/anthropic/types.d.ts +5 -2
  226. package/dist/types/llm/anthropic/utils/message_outputs.d.ts +1 -1
  227. package/dist/types/llm/bedrock/index.d.ts +40 -33
  228. package/dist/types/llm/bedrock/utils/message_outputs.d.ts +1 -1
  229. package/dist/types/llm/google/index.d.ts +2 -3
  230. package/dist/types/llm/openrouter/index.d.ts +21 -1
  231. package/dist/types/llm/vertexai/index.d.ts +3 -2
  232. package/dist/types/messages/cache.d.ts +1 -1
  233. package/dist/types/messages/index.d.ts +1 -0
  234. package/dist/types/messages/prune.d.ts +2 -7
  235. package/dist/types/messages/summarize.d.ts +33 -0
  236. package/dist/types/run.d.ts +6 -0
  237. package/dist/types/tools/AskUser.d.ts +408 -0
  238. package/dist/types/tools/BrowserTools.d.ts +2 -2
  239. package/dist/types/tools/CodeExecutor.d.ts +2 -2
  240. package/dist/types/tools/StreamingToolCallBuffer.d.ts +106 -0
  241. package/dist/types/tools/ToolNode.d.ts +55 -3
  242. package/dist/types/tools/ToolSearch.d.ts +9 -5
  243. package/dist/types/tools/handlers.d.ts +2 -2
  244. package/dist/types/types/graph.d.ts +9 -2
  245. package/dist/types/types/llm.d.ts +8 -3
  246. package/dist/types/types/run.d.ts +2 -0
  247. package/dist/types/types/tools.d.ts +20 -2
  248. package/dist/types/utils/contextAnalytics.d.ts +5 -4
  249. package/dist/types/utils/index.d.ts +1 -0
  250. package/dist/types/utils/tokens.d.ts +6 -19
  251. package/dist/types/utils/toolCallContinuation.d.ts +30 -0
  252. package/package.json +15 -8
  253. package/src/agents/AgentContext.js +782 -0
  254. package/src/agents/AgentContext.js.map +1 -0
  255. package/src/agents/AgentContext.test.js +421 -0
  256. package/src/agents/AgentContext.test.js.map +1 -0
  257. package/src/agents/AgentContext.ts +132 -64
  258. package/src/agents/__tests__/AgentContext.test.js +678 -0
  259. package/src/agents/__tests__/AgentContext.test.js.map +1 -0
  260. package/src/agents/__tests__/AgentContext.test.ts +25 -4
  261. package/src/agents/__tests__/resolveStructuredOutputMode.test.js +117 -0
  262. package/src/agents/__tests__/resolveStructuredOutputMode.test.js.map +1 -0
  263. package/src/common/__tests__/enum.test.ts +135 -0
  264. package/src/common/constants.ts +21 -0
  265. package/src/common/enum.js +192 -0
  266. package/src/common/enum.js.map +1 -0
  267. package/src/common/enum.ts +30 -0
  268. package/src/common/index.js +3 -0
  269. package/src/common/index.js.map +1 -0
  270. package/src/common/index.ts +2 -1
  271. package/src/events.js +166 -0
  272. package/src/events.js.map +1 -0
  273. package/src/events.ts +11 -14
  274. package/src/graphs/Graph.js +1857 -0
  275. package/src/graphs/Graph.js.map +1 -0
  276. package/src/graphs/Graph.ts +580 -162
  277. package/src/graphs/MultiAgentGraph.js +1092 -0
  278. package/src/graphs/MultiAgentGraph.js.map +1 -0
  279. package/src/graphs/MultiAgentGraph.ts +331 -112
  280. package/src/graphs/__tests__/adaptive-thinking.test.ts +369 -0
  281. package/src/graphs/__tests__/graph-direct-tool-names.test.ts +210 -0
  282. package/src/graphs/__tests__/multi-agent-edges.test.ts +237 -0
  283. package/src/graphs/__tests__/structured-output.integration.test.js +624 -0
  284. package/src/graphs/__tests__/structured-output.integration.test.js.map +1 -0
  285. package/src/graphs/__tests__/structured-output.test.js +144 -0
  286. package/src/graphs/__tests__/structured-output.test.js.map +1 -0
  287. package/src/graphs/contextManagement.e2e.test.js +718 -0
  288. package/src/graphs/contextManagement.e2e.test.js.map +1 -0
  289. package/src/graphs/contextManagement.e2e.test.ts +990 -0
  290. package/src/graphs/contextManagement.test.js +485 -0
  291. package/src/graphs/contextManagement.test.js.map +1 -0
  292. package/src/graphs/contextManagement.test.ts +625 -0
  293. package/src/graphs/handoffValidation.test.js +276 -0
  294. package/src/graphs/handoffValidation.test.js.map +1 -0
  295. package/src/graphs/handoffValidation.test.ts +353 -0
  296. package/src/graphs/index.js +3 -0
  297. package/src/graphs/index.js.map +1 -0
  298. package/src/index.js +28 -0
  299. package/src/index.js.map +1 -0
  300. package/src/index.ts +13 -0
  301. package/src/instrumentation.js +21 -0
  302. package/src/instrumentation.js.map +1 -0
  303. package/src/instrumentation.ts +38 -17
  304. package/src/llm/anthropic/index.js +319 -0
  305. package/src/llm/anthropic/index.js.map +1 -0
  306. package/src/llm/anthropic/index.ts +68 -15
  307. package/src/llm/anthropic/llm.spec.ts +402 -0
  308. package/src/llm/anthropic/types.js +46 -0
  309. package/src/llm/anthropic/types.js.map +1 -0
  310. package/src/llm/anthropic/types.ts +8 -2
  311. package/src/llm/anthropic/utils/message_inputs.js +627 -0
  312. package/src/llm/anthropic/utils/message_inputs.js.map +1 -0
  313. package/src/llm/anthropic/utils/message_inputs.ts +16 -33
  314. package/src/llm/anthropic/utils/message_outputs.js +290 -0
  315. package/src/llm/anthropic/utils/message_outputs.js.map +1 -0
  316. package/src/llm/anthropic/utils/message_outputs.ts +40 -1
  317. package/src/llm/anthropic/utils/output_parsers.js +89 -0
  318. package/src/llm/anthropic/utils/output_parsers.js.map +1 -0
  319. package/src/llm/anthropic/utils/tools.js +25 -0
  320. package/src/llm/anthropic/utils/tools.js.map +1 -0
  321. package/src/llm/bedrock/__tests__/bedrock-caching.test.js +392 -0
  322. package/src/llm/bedrock/__tests__/bedrock-caching.test.js.map +1 -0
  323. package/src/llm/bedrock/__tests__/bedrock-caching.test.ts +24 -40
  324. package/src/llm/bedrock/index.js +303 -0
  325. package/src/llm/bedrock/index.js.map +1 -0
  326. package/src/llm/bedrock/index.ts +171 -134
  327. package/src/llm/bedrock/llm.spec.ts +395 -52
  328. package/src/llm/bedrock/types.js +2 -0
  329. package/src/llm/bedrock/types.js.map +1 -0
  330. package/src/llm/bedrock/utils/index.js +6 -0
  331. package/src/llm/bedrock/utils/index.js.map +1 -0
  332. package/src/llm/bedrock/utils/message_inputs.js +463 -0
  333. package/src/llm/bedrock/utils/message_inputs.js.map +1 -0
  334. package/src/llm/bedrock/utils/message_inputs.ts +30 -5
  335. package/src/llm/bedrock/utils/message_outputs.js +269 -0
  336. package/src/llm/bedrock/utils/message_outputs.js.map +1 -0
  337. package/src/llm/bedrock/utils/message_outputs.ts +70 -22
  338. package/src/llm/fake.js +92 -0
  339. package/src/llm/fake.js.map +1 -0
  340. package/src/llm/google/index.js +215 -0
  341. package/src/llm/google/index.js.map +1 -0
  342. package/src/llm/google/index.ts +2 -3
  343. package/src/llm/google/types.js +12 -0
  344. package/src/llm/google/types.js.map +1 -0
  345. package/src/llm/google/utils/common.js +670 -0
  346. package/src/llm/google/utils/common.js.map +1 -0
  347. package/src/llm/google/utils/tools.js +111 -0
  348. package/src/llm/google/utils/tools.js.map +1 -0
  349. package/src/llm/google/utils/zod_to_genai_parameters.js +47 -0
  350. package/src/llm/google/utils/zod_to_genai_parameters.js.map +1 -0
  351. package/src/llm/openai/index.js +1033 -0
  352. package/src/llm/openai/index.js.map +1 -0
  353. package/src/llm/openai/types.js +2 -0
  354. package/src/llm/openai/types.js.map +1 -0
  355. package/src/llm/openai/utils/index.js +756 -0
  356. package/src/llm/openai/utils/index.js.map +1 -0
  357. package/src/llm/openai/utils/isReasoningModel.test.js +79 -0
  358. package/src/llm/openai/utils/isReasoningModel.test.js.map +1 -0
  359. package/src/llm/openrouter/index.js +261 -0
  360. package/src/llm/openrouter/index.js.map +1 -0
  361. package/src/llm/openrouter/index.ts +117 -6
  362. package/src/llm/openrouter/reasoning.test.js +181 -0
  363. package/src/llm/openrouter/reasoning.test.js.map +1 -0
  364. package/src/llm/openrouter/reasoning.test.ts +207 -0
  365. package/src/llm/providers.js +36 -0
  366. package/src/llm/providers.js.map +1 -0
  367. package/src/llm/text.js +65 -0
  368. package/src/llm/text.js.map +1 -0
  369. package/src/llm/vertexai/index.js +402 -0
  370. package/src/llm/vertexai/index.js.map +1 -0
  371. package/src/llm/vertexai/index.ts +115 -5
  372. package/src/llm/vertexai/llm.spec.ts +114 -0
  373. package/src/messages/__tests__/tools.test.js +392 -0
  374. package/src/messages/__tests__/tools.test.js.map +1 -0
  375. package/src/messages/cache.js +404 -0
  376. package/src/messages/cache.js.map +1 -0
  377. package/src/messages/cache.test.js +1167 -0
  378. package/src/messages/cache.test.js.map +1 -0
  379. package/src/messages/cache.test.ts +178 -16
  380. package/src/messages/cache.ts +152 -147
  381. package/src/messages/content.js +48 -0
  382. package/src/messages/content.js.map +1 -0
  383. package/src/messages/content.test.js +314 -0
  384. package/src/messages/content.test.js.map +1 -0
  385. package/src/messages/core.js +359 -0
  386. package/src/messages/core.js.map +1 -0
  387. package/src/messages/core.ts +5 -0
  388. package/src/messages/ensureThinkingBlock.test.js +997 -0
  389. package/src/messages/ensureThinkingBlock.test.js.map +1 -0
  390. package/src/messages/ensureThinkingBlock.test.ts +751 -10
  391. package/src/messages/format.js +973 -0
  392. package/src/messages/format.js.map +1 -0
  393. package/src/messages/format.ts +334 -57
  394. package/src/messages/formatAgentMessages.test.js +2278 -0
  395. package/src/messages/formatAgentMessages.test.js.map +1 -0
  396. package/src/messages/formatAgentMessages.test.ts +1175 -1
  397. package/src/messages/formatAgentMessages.tools.test.js +362 -0
  398. package/src/messages/formatAgentMessages.tools.test.js.map +1 -0
  399. package/src/messages/formatMessage.test.js +608 -0
  400. package/src/messages/formatMessage.test.js.map +1 -0
  401. package/src/messages/ids.js +18 -0
  402. package/src/messages/ids.js.map +1 -0
  403. package/src/messages/index.js +9 -0
  404. package/src/messages/index.js.map +1 -0
  405. package/src/messages/index.ts +1 -0
  406. package/src/messages/labelContentByAgent.test.js +725 -0
  407. package/src/messages/labelContentByAgent.test.js.map +1 -0
  408. package/src/messages/prune.js +438 -0
  409. package/src/messages/prune.js.map +1 -0
  410. package/src/messages/prune.ts +87 -25
  411. package/src/messages/reducer.js +60 -0
  412. package/src/messages/reducer.js.map +1 -0
  413. package/src/messages/shiftIndexTokenCountMap.test.js +63 -0
  414. package/src/messages/shiftIndexTokenCountMap.test.js.map +1 -0
  415. package/src/messages/summarize.js +146 -0
  416. package/src/messages/summarize.js.map +1 -0
  417. package/src/messages/summarize.test.js +332 -0
  418. package/src/messages/summarize.test.js.map +1 -0
  419. package/src/messages/summarize.test.ts +466 -0
  420. package/src/messages/summarize.ts +222 -0
  421. package/src/messages/tools.js +90 -0
  422. package/src/messages/tools.js.map +1 -0
  423. package/src/mockStream.js +81 -0
  424. package/src/mockStream.js.map +1 -0
  425. package/src/prompts/collab.js +7 -0
  426. package/src/prompts/collab.js.map +1 -0
  427. package/src/prompts/index.js +3 -0
  428. package/src/prompts/index.js.map +1 -0
  429. package/src/prompts/taskmanager.js +58 -0
  430. package/src/prompts/taskmanager.js.map +1 -0
  431. package/src/run.js +427 -0
  432. package/src/run.js.map +1 -0
  433. package/src/run.ts +101 -33
  434. package/src/schemas/index.js +3 -0
  435. package/src/schemas/index.js.map +1 -0
  436. package/src/schemas/schema-preparation.test.js +370 -0
  437. package/src/schemas/schema-preparation.test.js.map +1 -0
  438. package/src/schemas/validate.js +314 -0
  439. package/src/schemas/validate.js.map +1 -0
  440. package/src/schemas/validate.test.js +264 -0
  441. package/src/schemas/validate.test.js.map +1 -0
  442. package/src/scripts/abort.js +127 -0
  443. package/src/scripts/abort.js.map +1 -0
  444. package/src/scripts/ant_web_search.js +130 -0
  445. package/src/scripts/ant_web_search.js.map +1 -0
  446. package/src/scripts/ant_web_search.ts +1 -0
  447. package/src/scripts/ant_web_search_edge_case.js +133 -0
  448. package/src/scripts/ant_web_search_edge_case.js.map +1 -0
  449. package/src/scripts/ant_web_search_edge_case.ts +1 -0
  450. package/src/scripts/ant_web_search_error_edge_case.js +119 -0
  451. package/src/scripts/ant_web_search_error_edge_case.js.map +1 -0
  452. package/src/scripts/ant_web_search_error_edge_case.ts +1 -0
  453. package/src/scripts/args.js +41 -0
  454. package/src/scripts/args.js.map +1 -0
  455. package/src/scripts/bedrock-cache-debug.js +186 -0
  456. package/src/scripts/bedrock-cache-debug.js.map +1 -0
  457. package/src/scripts/bedrock-cache-debug.ts +250 -0
  458. package/src/scripts/bedrock-content-aggregation-test.js +195 -0
  459. package/src/scripts/bedrock-content-aggregation-test.js.map +1 -0
  460. package/src/scripts/bedrock-content-aggregation-test.ts +266 -0
  461. package/src/scripts/bedrock-merge-test.js +80 -0
  462. package/src/scripts/bedrock-merge-test.js.map +1 -0
  463. package/src/scripts/bedrock-merge-test.ts +107 -0
  464. package/src/scripts/bedrock-parallel-tools-test.js +150 -0
  465. package/src/scripts/bedrock-parallel-tools-test.js.map +1 -0
  466. package/src/scripts/bedrock-parallel-tools-test.ts +204 -0
  467. package/src/scripts/caching.js +106 -0
  468. package/src/scripts/caching.js.map +1 -0
  469. package/src/scripts/caching.ts +1 -0
  470. package/src/scripts/cli.js +152 -0
  471. package/src/scripts/cli.js.map +1 -0
  472. package/src/scripts/cli2.js +119 -0
  473. package/src/scripts/cli2.js.map +1 -0
  474. package/src/scripts/cli3.js +163 -0
  475. package/src/scripts/cli3.js.map +1 -0
  476. package/src/scripts/cli4.js +165 -0
  477. package/src/scripts/cli4.js.map +1 -0
  478. package/src/scripts/cli5.js +165 -0
  479. package/src/scripts/cli5.js.map +1 -0
  480. package/src/scripts/code_exec.js +171 -0
  481. package/src/scripts/code_exec.js.map +1 -0
  482. package/src/scripts/code_exec.ts +1 -0
  483. package/src/scripts/code_exec_files.js +180 -0
  484. package/src/scripts/code_exec_files.js.map +1 -0
  485. package/src/scripts/code_exec_files.ts +1 -0
  486. package/src/scripts/code_exec_multi_session.js +185 -0
  487. package/src/scripts/code_exec_multi_session.js.map +1 -0
  488. package/src/scripts/code_exec_multi_session.ts +9 -13
  489. package/src/scripts/code_exec_ptc.js +265 -0
  490. package/src/scripts/code_exec_ptc.js.map +1 -0
  491. package/src/scripts/code_exec_ptc.ts +1 -0
  492. package/src/scripts/code_exec_session.js +217 -0
  493. package/src/scripts/code_exec_session.js.map +1 -0
  494. package/src/scripts/code_exec_session.ts +1 -0
  495. package/src/scripts/code_exec_simple.js +120 -0
  496. package/src/scripts/code_exec_simple.js.map +1 -0
  497. package/src/scripts/code_exec_simple.ts +1 -0
  498. package/src/scripts/content.js +111 -0
  499. package/src/scripts/content.js.map +1 -0
  500. package/src/scripts/content.ts +1 -0
  501. package/src/scripts/empty_input.js +125 -0
  502. package/src/scripts/empty_input.js.map +1 -0
  503. package/src/scripts/handoff-test.js +96 -0
  504. package/src/scripts/handoff-test.js.map +1 -0
  505. package/src/scripts/image.js +138 -0
  506. package/src/scripts/image.js.map +1 -0
  507. package/src/scripts/image.ts +3 -1
  508. package/src/scripts/memory.js +83 -0
  509. package/src/scripts/memory.js.map +1 -0
  510. package/src/scripts/memory.ts +16 -6
  511. package/src/scripts/multi-agent-chain.js +271 -0
  512. package/src/scripts/multi-agent-chain.js.map +1 -0
  513. package/src/scripts/multi-agent-chain.ts +1 -0
  514. package/src/scripts/multi-agent-conditional.js +185 -0
  515. package/src/scripts/multi-agent-conditional.js.map +1 -0
  516. package/src/scripts/multi-agent-conditional.ts +1 -0
  517. package/src/scripts/multi-agent-document-review-chain.js +171 -0
  518. package/src/scripts/multi-agent-document-review-chain.js.map +1 -0
  519. package/src/scripts/multi-agent-document-review-chain.ts +1 -0
  520. package/src/scripts/multi-agent-hybrid-flow.js +264 -0
  521. package/src/scripts/multi-agent-hybrid-flow.js.map +1 -0
  522. package/src/scripts/multi-agent-hybrid-flow.ts +1 -0
  523. package/src/scripts/multi-agent-parallel-start.js +214 -0
  524. package/src/scripts/multi-agent-parallel-start.js.map +1 -0
  525. package/src/scripts/multi-agent-parallel-start.ts +4 -4
  526. package/src/scripts/multi-agent-parallel.js +346 -0
  527. package/src/scripts/multi-agent-parallel.js.map +1 -0
  528. package/src/scripts/multi-agent-parallel.ts +1 -0
  529. package/src/scripts/multi-agent-sequence.js +184 -0
  530. package/src/scripts/multi-agent-sequence.js.map +1 -0
  531. package/src/scripts/multi-agent-sequence.ts +4 -4
  532. package/src/scripts/multi-agent-supervisor.js +324 -0
  533. package/src/scripts/multi-agent-supervisor.js.map +1 -0
  534. package/src/scripts/multi-agent-supervisor.ts +1 -0
  535. package/src/scripts/multi-agent-test.js +147 -0
  536. package/src/scripts/multi-agent-test.js.map +1 -0
  537. package/src/scripts/multi-agent-test.ts +1 -0
  538. package/src/scripts/parallel-asymmetric-tools-test.js +202 -0
  539. package/src/scripts/parallel-asymmetric-tools-test.js.map +1 -0
  540. package/src/scripts/parallel-asymmetric-tools-test.ts +1 -0
  541. package/src/scripts/parallel-full-metadata-test.js +176 -0
  542. package/src/scripts/parallel-full-metadata-test.js.map +1 -0
  543. package/src/scripts/parallel-full-metadata-test.ts +1 -0
  544. package/src/scripts/parallel-tools-test.js +256 -0
  545. package/src/scripts/parallel-tools-test.js.map +1 -0
  546. package/src/scripts/parallel-tools-test.ts +1 -0
  547. package/src/scripts/poc-multi-agent-comprehensive.ts +1222 -0
  548. package/src/scripts/programmatic_exec.js +277 -0
  549. package/src/scripts/programmatic_exec.js.map +1 -0
  550. package/src/scripts/programmatic_exec_agent.js +168 -0
  551. package/src/scripts/programmatic_exec_agent.js.map +1 -0
  552. package/src/scripts/programmatic_exec_agent.ts +1 -0
  553. package/src/scripts/search.js +118 -0
  554. package/src/scripts/search.js.map +1 -0
  555. package/src/scripts/search.ts +1 -0
  556. package/src/scripts/sequential-full-metadata-test.js +143 -0
  557. package/src/scripts/sequential-full-metadata-test.js.map +1 -0
  558. package/src/scripts/sequential-full-metadata-test.ts +1 -0
  559. package/src/scripts/simple.js +174 -0
  560. package/src/scripts/simple.js.map +1 -0
  561. package/src/scripts/simple.ts +2 -1
  562. package/src/scripts/single-agent-metadata-test.js +152 -0
  563. package/src/scripts/single-agent-metadata-test.js.map +1 -0
  564. package/src/scripts/single-agent-metadata-test.ts +4 -6
  565. package/src/scripts/stream.js +113 -0
  566. package/src/scripts/stream.js.map +1 -0
  567. package/src/scripts/stream.ts +1 -0
  568. package/src/scripts/test-custom-prompt-key.js +132 -0
  569. package/src/scripts/test-custom-prompt-key.js.map +1 -0
  570. package/src/scripts/test-handoff-input.js +143 -0
  571. package/src/scripts/test-handoff-input.js.map +1 -0
  572. package/src/scripts/test-handoff-preamble.js +227 -0
  573. package/src/scripts/test-handoff-preamble.js.map +1 -0
  574. package/src/scripts/test-handoff-preamble.ts +1 -0
  575. package/src/scripts/test-handoff-steering.js +353 -0
  576. package/src/scripts/test-handoff-steering.js.map +1 -0
  577. package/src/scripts/test-handoff-steering.ts +430 -0
  578. package/src/scripts/test-multi-agent-list-handoff.js +318 -0
  579. package/src/scripts/test-multi-agent-list-handoff.js.map +1 -0
  580. package/src/scripts/test-multi-agent-list-handoff.ts +1 -0
  581. package/src/scripts/test-parallel-agent-labeling.js +253 -0
  582. package/src/scripts/test-parallel-agent-labeling.js.map +1 -0
  583. package/src/scripts/test-parallel-agent-labeling.ts +2 -0
  584. package/src/scripts/test-parallel-handoffs.js +229 -0
  585. package/src/scripts/test-parallel-handoffs.js.map +1 -0
  586. package/src/scripts/test-parallel-handoffs.ts +1 -0
  587. package/src/scripts/test-thinking-handoff-bedrock.js +132 -0
  588. package/src/scripts/test-thinking-handoff-bedrock.js.map +1 -0
  589. package/src/scripts/test-thinking-handoff-bedrock.ts +1 -0
  590. package/src/scripts/test-thinking-handoff.js +132 -0
  591. package/src/scripts/test-thinking-handoff.js.map +1 -0
  592. package/src/scripts/test-thinking-handoff.ts +1 -0
  593. package/src/scripts/test-thinking-to-thinking-handoff-bedrock.js +140 -0
  594. package/src/scripts/test-thinking-to-thinking-handoff-bedrock.js.map +1 -0
  595. package/src/scripts/test-thinking-to-thinking-handoff-bedrock.ts +166 -0
  596. package/src/scripts/test-tool-before-handoff-role-order.js +223 -0
  597. package/src/scripts/test-tool-before-handoff-role-order.js.map +1 -0
  598. package/src/scripts/test-tool-before-handoff-role-order.ts +276 -0
  599. package/src/scripts/test-tools-before-handoff.js +187 -0
  600. package/src/scripts/test-tools-before-handoff.js.map +1 -0
  601. package/src/scripts/test-tools-before-handoff.ts +4 -8
  602. package/src/scripts/test_code_api.js +263 -0
  603. package/src/scripts/test_code_api.js.map +1 -0
  604. package/src/scripts/thinking-bedrock.js +128 -0
  605. package/src/scripts/thinking-bedrock.js.map +1 -0
  606. package/src/scripts/thinking-bedrock.ts +1 -0
  607. package/src/scripts/thinking-vertexai.js +130 -0
  608. package/src/scripts/thinking-vertexai.js.map +1 -0
  609. package/src/scripts/thinking-vertexai.ts +168 -0
  610. package/src/scripts/thinking.js +134 -0
  611. package/src/scripts/thinking.js.map +1 -0
  612. package/src/scripts/thinking.ts +1 -0
  613. package/src/scripts/tool_search.js +114 -0
  614. package/src/scripts/tool_search.js.map +1 -0
  615. package/src/scripts/tools.js +125 -0
  616. package/src/scripts/tools.js.map +1 -0
  617. package/src/scripts/tools.ts +5 -19
  618. package/src/specs/agent-handoffs-bedrock.integration.test.js +280 -0
  619. package/src/specs/agent-handoffs-bedrock.integration.test.js.map +1 -0
  620. package/src/specs/agent-handoffs-bedrock.integration.test.ts +412 -375
  621. package/src/specs/agent-handoffs.test.js +924 -0
  622. package/src/specs/agent-handoffs.test.js.map +1 -0
  623. package/src/specs/agent-handoffs.test.ts +152 -39
  624. package/src/specs/anthropic.simple.test.js +287 -0
  625. package/src/specs/anthropic.simple.test.js.map +1 -0
  626. package/src/specs/anthropic.simple.test.ts +7 -4
  627. package/src/specs/azure.simple.test.js +381 -0
  628. package/src/specs/azure.simple.test.js.map +1 -0
  629. package/src/specs/azure.simple.test.ts +143 -5
  630. package/src/specs/cache.simple.test.js +282 -0
  631. package/src/specs/cache.simple.test.js.map +1 -0
  632. package/src/specs/cache.simple.test.ts +9 -2
  633. package/src/specs/custom-event-await.test.js +148 -0
  634. package/src/specs/custom-event-await.test.js.map +1 -0
  635. package/src/specs/custom-event-await.test.ts +215 -0
  636. package/src/specs/deepseek.simple.test.js +189 -0
  637. package/src/specs/deepseek.simple.test.js.map +1 -0
  638. package/src/specs/deepseek.simple.test.ts +4 -2
  639. package/src/specs/emergency-prune.test.js +308 -0
  640. package/src/specs/emergency-prune.test.js.map +1 -0
  641. package/src/specs/moonshot.simple.test.js +237 -0
  642. package/src/specs/moonshot.simple.test.js.map +1 -0
  643. package/src/specs/moonshot.simple.test.ts +6 -2
  644. package/src/specs/observability.integration.test.js +1337 -0
  645. package/src/specs/observability.integration.test.js.map +1 -0
  646. package/src/specs/observability.integration.test.ts +2223 -0
  647. package/src/specs/openai.simple.test.js +233 -0
  648. package/src/specs/openai.simple.test.js.map +1 -0
  649. package/src/specs/openai.simple.test.ts +4 -2
  650. package/src/specs/openrouter.simple.test.js +202 -0
  651. package/src/specs/openrouter.simple.test.js.map +1 -0
  652. package/src/specs/openrouter.simple.test.ts +165 -4
  653. package/src/specs/prune.test.js +733 -0
  654. package/src/specs/prune.test.js.map +1 -0
  655. package/src/specs/prune.test.ts +1 -0
  656. package/src/specs/reasoning.test.js +144 -0
  657. package/src/specs/reasoning.test.js.map +1 -0
  658. package/src/specs/reasoning.test.ts +2 -2
  659. package/src/specs/spec.utils.js +4 -0
  660. package/src/specs/spec.utils.js.map +1 -0
  661. package/src/specs/thinking-handoff.test.js +486 -0
  662. package/src/specs/thinking-handoff.test.js.map +1 -0
  663. package/src/specs/thinking-handoff.test.ts +3 -2
  664. package/src/specs/thinking-prune.test.js +600 -0
  665. package/src/specs/thinking-prune.test.js.map +1 -0
  666. package/src/specs/token-distribution-edge-case.test.js +246 -0
  667. package/src/specs/token-distribution-edge-case.test.js.map +1 -0
  668. package/src/specs/token-memoization.test.js +32 -0
  669. package/src/specs/token-memoization.test.js.map +1 -0
  670. package/src/specs/token-memoization.test.ts +14 -5
  671. package/src/specs/tokens.test.js +49 -0
  672. package/src/specs/tokens.test.js.map +1 -0
  673. package/src/specs/tokens.test.ts +64 -0
  674. package/src/specs/tool-error.test.js +139 -0
  675. package/src/specs/tool-error.test.js.map +1 -0
  676. package/src/specs/tool-error.test.ts +2 -2
  677. package/src/splitStream.js +204 -0
  678. package/src/splitStream.js.map +1 -0
  679. package/src/splitStream.test.js +504 -0
  680. package/src/splitStream.test.js.map +1 -0
  681. package/src/stream.js +650 -0
  682. package/src/stream.js.map +1 -0
  683. package/src/stream.test.js +225 -0
  684. package/src/stream.test.js.map +1 -0
  685. package/src/stream.test.ts +25 -15
  686. package/src/stream.ts +82 -32
  687. package/src/test/mockTools.js +340 -0
  688. package/src/test/mockTools.js.map +1 -0
  689. package/src/tools/AskUser.ts +159 -0
  690. package/src/tools/BrowserTools.js +245 -0
  691. package/src/tools/BrowserTools.js.map +1 -0
  692. package/src/tools/BrowserTools.ts +12 -8
  693. package/src/tools/Calculator.js +38 -0
  694. package/src/tools/Calculator.js.map +1 -0
  695. package/src/tools/Calculator.test.js +225 -0
  696. package/src/tools/Calculator.test.js.map +1 -0
  697. package/src/tools/CodeExecutor.js +233 -0
  698. package/src/tools/CodeExecutor.js.map +1 -0
  699. package/src/tools/CodeExecutor.selfhealing.test.ts +435 -0
  700. package/src/tools/CodeExecutor.ts +62 -4
  701. package/src/tools/ProgrammaticToolCalling.js +602 -0
  702. package/src/tools/ProgrammaticToolCalling.js.map +1 -0
  703. package/src/tools/ProgrammaticToolCalling.ts +40 -52
  704. package/src/tools/StreamingToolCallBuffer.js +179 -0
  705. package/src/tools/StreamingToolCallBuffer.js.map +1 -0
  706. package/src/tools/StreamingToolCallBuffer.ts +218 -0
  707. package/src/tools/ToolNode.js +930 -0
  708. package/src/tools/ToolNode.js.map +1 -0
  709. package/src/tools/ToolNode.ts +454 -41
  710. package/src/tools/ToolSearch.js +904 -0
  711. package/src/tools/ToolSearch.js.map +1 -0
  712. package/src/tools/ToolSearch.ts +84 -33
  713. package/src/tools/__tests__/AskUser.test.ts +537 -0
  714. package/src/tools/__tests__/BrowserTools.test.js +306 -0
  715. package/src/tools/__tests__/BrowserTools.test.js.map +1 -0
  716. package/src/tools/__tests__/BrowserTools.test.ts +131 -6
  717. package/src/tools/__tests__/ProgrammaticToolCalling.integration.test.js +276 -0
  718. package/src/tools/__tests__/ProgrammaticToolCalling.integration.test.js.map +1 -0
  719. package/src/tools/__tests__/ProgrammaticToolCalling.test.js +807 -0
  720. package/src/tools/__tests__/ProgrammaticToolCalling.test.js.map +1 -0
  721. package/src/tools/__tests__/StreamingToolCallBuffer.test.js +175 -0
  722. package/src/tools/__tests__/StreamingToolCallBuffer.test.js.map +1 -0
  723. package/src/tools/__tests__/StreamingToolCallBuffer.test.ts +263 -0
  724. package/src/tools/__tests__/ToolApproval.test.js +675 -0
  725. package/src/tools/__tests__/ToolApproval.test.js.map +1 -0
  726. package/src/tools/__tests__/ToolApproval.test.ts +194 -20
  727. package/src/tools/__tests__/ToolNode.hitl.test.ts +267 -0
  728. package/src/tools/__tests__/ToolNode.recovery.test.js +200 -0
  729. package/src/tools/__tests__/ToolNode.recovery.test.js.map +1 -0
  730. package/src/tools/__tests__/ToolNode.recovery.test.ts +276 -0
  731. package/src/tools/__tests__/ToolNode.session.test.js +319 -0
  732. package/src/tools/__tests__/ToolNode.session.test.js.map +1 -0
  733. package/src/tools/__tests__/ToolNode.session.test.ts +465 -0
  734. package/src/tools/__tests__/ToolSearch.integration.test.js +125 -0
  735. package/src/tools/__tests__/ToolSearch.integration.test.js.map +1 -0
  736. package/src/tools/__tests__/ToolSearch.test.js +812 -0
  737. package/src/tools/__tests__/ToolSearch.test.js.map +1 -0
  738. package/src/tools/__tests__/ToolSearch.test.ts +78 -5
  739. package/src/tools/__tests__/handlers.test.js +799 -0
  740. package/src/tools/__tests__/handlers.test.js.map +1 -0
  741. package/src/tools/__tests__/handlers.test.ts +1100 -0
  742. package/src/tools/__tests__/truncation-recovery.integration.test.js +362 -0
  743. package/src/tools/__tests__/truncation-recovery.integration.test.js.map +1 -0
  744. package/src/tools/__tests__/truncation-recovery.integration.test.ts +560 -0
  745. package/src/tools/handlers.js +306 -0
  746. package/src/tools/handlers.js.map +1 -0
  747. package/src/tools/handlers.ts +119 -16
  748. package/src/tools/schema.js +25 -0
  749. package/src/tools/schema.js.map +1 -0
  750. package/src/tools/search/anthropic.js +34 -0
  751. package/src/tools/search/anthropic.js.map +1 -0
  752. package/src/tools/search/content.js +116 -0
  753. package/src/tools/search/content.js.map +1 -0
  754. package/src/tools/search/content.test.js +133 -0
  755. package/src/tools/search/content.test.js.map +1 -0
  756. package/src/tools/search/firecrawl.js +173 -0
  757. package/src/tools/search/firecrawl.js.map +1 -0
  758. package/src/tools/search/format.js +198 -0
  759. package/src/tools/search/format.js.map +1 -0
  760. package/src/tools/search/highlights.js +241 -0
  761. package/src/tools/search/highlights.js.map +1 -0
  762. package/src/tools/search/index.js +3 -0
  763. package/src/tools/search/index.js.map +1 -0
  764. package/src/tools/search/jina-reranker.test.js +106 -0
  765. package/src/tools/search/jina-reranker.test.js.map +1 -0
  766. package/src/tools/search/rerankers.js +165 -0
  767. package/src/tools/search/rerankers.js.map +1 -0
  768. package/src/tools/search/schema.js +102 -0
  769. package/src/tools/search/schema.js.map +1 -0
  770. package/src/tools/search/search.js +561 -0
  771. package/src/tools/search/search.js.map +1 -0
  772. package/src/tools/search/serper-scraper.js +126 -0
  773. package/src/tools/search/serper-scraper.js.map +1 -0
  774. package/src/tools/search/test.js +129 -0
  775. package/src/tools/search/test.js.map +1 -0
  776. package/src/tools/search/tool.js +453 -0
  777. package/src/tools/search/tool.js.map +1 -0
  778. package/src/tools/search/types.js +2 -0
  779. package/src/tools/search/types.js.map +1 -0
  780. package/src/tools/search/utils.js +59 -0
  781. package/src/tools/search/utils.js.map +1 -0
  782. package/src/types/graph.js +24 -0
  783. package/src/types/graph.js.map +1 -0
  784. package/src/types/graph.test.js +192 -0
  785. package/src/types/graph.test.js.map +1 -0
  786. package/src/types/graph.ts +26 -6
  787. package/src/types/index.js +7 -0
  788. package/src/types/index.js.map +1 -0
  789. package/src/types/llm.js +2 -0
  790. package/src/types/llm.js.map +1 -0
  791. package/src/types/llm.ts +8 -3
  792. package/src/types/messages.js +2 -0
  793. package/src/types/messages.js.map +1 -0
  794. package/src/types/run.js +2 -0
  795. package/src/types/run.js.map +1 -0
  796. package/src/types/run.ts +2 -0
  797. package/src/types/stream.js +2 -0
  798. package/src/types/stream.js.map +1 -0
  799. package/src/types/tools.js +2 -0
  800. package/src/types/tools.js.map +1 -0
  801. package/src/types/tools.ts +21 -2
  802. package/src/utils/contextAnalytics.js +79 -0
  803. package/src/utils/contextAnalytics.js.map +1 -0
  804. package/src/utils/contextAnalytics.test.js +166 -0
  805. package/src/utils/contextAnalytics.test.js.map +1 -0
  806. package/src/utils/contextAnalytics.test.ts +222 -0
  807. package/src/utils/contextAnalytics.ts +27 -9
  808. package/src/utils/events.js +26 -0
  809. package/src/utils/events.js.map +1 -0
  810. package/src/utils/graph.js +11 -0
  811. package/src/utils/graph.js.map +1 -0
  812. package/src/utils/handlers.js +65 -0
  813. package/src/utils/handlers.js.map +1 -0
  814. package/src/utils/index.js +10 -0
  815. package/src/utils/index.js.map +1 -0
  816. package/src/utils/index.ts +1 -0
  817. package/src/utils/llm.js +21 -0
  818. package/src/utils/llm.js.map +1 -0
  819. package/src/utils/llmConfig.js +205 -0
  820. package/src/utils/llmConfig.js.map +1 -0
  821. package/src/utils/llmConfig.ts +5 -5
  822. package/src/utils/logging.js +37 -0
  823. package/src/utils/logging.js.map +1 -0
  824. package/src/utils/misc.js +51 -0
  825. package/src/utils/misc.js.map +1 -0
  826. package/src/utils/run.js +69 -0
  827. package/src/utils/run.js.map +1 -0
  828. package/src/utils/run.ts +108 -106
  829. package/src/utils/schema.js +21 -0
  830. package/src/utils/schema.js.map +1 -0
  831. package/src/utils/title.js +119 -0
  832. package/src/utils/title.js.map +1 -0
  833. package/src/utils/tokens.js +92 -0
  834. package/src/utils/tokens.js.map +1 -0
  835. package/src/utils/tokens.ts +118 -142
  836. package/src/utils/toolCallContinuation.ts +55 -0
  837. package/src/utils/toonFormat.js +379 -0
  838. package/src/utils/toonFormat.js.map +1 -0
@@ -3,6 +3,22 @@ import type { ExtendedMessageContent } from '@/types';
3
3
  import { ensureThinkingBlockInMessages } from './format';
4
4
  import { Providers, ContentTypes } from '@/common';
5
5
 
6
+ /** Helper: extract concatenated text from a message's content (string or structured array). */
7
+ function getTextContent(msg: {
8
+ content: string | ExtendedMessageContent[];
9
+ }): string {
10
+ if (typeof msg.content === 'string') {
11
+ return msg.content;
12
+ }
13
+ if (Array.isArray(msg.content)) {
14
+ return (msg.content as ExtendedMessageContent[])
15
+ .filter((b) => b.type === 'text')
16
+ .map((b) => String(b.text ?? ''))
17
+ .join('\n');
18
+ }
19
+ return '';
20
+ }
21
+
6
22
  describe('ensureThinkingBlockInMessages', () => {
7
23
  describe('messages with thinking blocks (should not be modified)', () => {
8
24
  test('should not modify AI message that already has thinking block', () => {
@@ -89,6 +105,213 @@ describe('ensureThinkingBlockInMessages', () => {
89
105
  );
90
106
  });
91
107
 
108
+ test('should not modify AI message when reasoning_content is not the first block (Bedrock whitespace artifact)', () => {
109
+ // Bedrock emits a "\n\n" text chunk before the thinking block,
110
+ // pushing reasoning_content to content[1] instead of content[0].
111
+ const messages = [
112
+ new HumanMessage({ content: 'Do something' }),
113
+ new AIMessage({
114
+ content: [
115
+ { type: 'text', text: '\n\n' },
116
+ {
117
+ type: ContentTypes.REASONING_CONTENT,
118
+ reasoningText: { text: 'Let me think about this' },
119
+ },
120
+ { type: 'text', text: 'Let me help!' },
121
+ ],
122
+ tool_calls: [
123
+ {
124
+ id: 'call_bedrock',
125
+ name: 'some_tool',
126
+ args: { x: 1 },
127
+ type: 'tool_call' as const,
128
+ },
129
+ ],
130
+ }),
131
+ new ToolMessage({
132
+ content: 'tool result',
133
+ tool_call_id: 'call_bedrock',
134
+ }),
135
+ ];
136
+
137
+ const result = ensureThinkingBlockInMessages(messages, Providers.BEDROCK);
138
+
139
+ expect(result).toHaveLength(3);
140
+ expect(result[0]).toBeInstanceOf(HumanMessage);
141
+ expect(result[1]).toBeInstanceOf(AIMessage);
142
+ expect(result[2]).toBeInstanceOf(ToolMessage);
143
+ // The AI message should be preserved, not converted to a HumanMessage
144
+ expect(result[1].content).toEqual(messages[1].content);
145
+ });
146
+
147
+ test('should not convert follow-up tool calls in a thinking-enabled chain (Bedrock multi-step)', () => {
148
+ // Bedrock reasoning models produce reasoning on the first AI response,
149
+ // then subsequent tool calls in the same chain have content: "" with no
150
+ // reasoning block. These should NOT be converted because the chain
151
+ // already has a thinking block upstream.
152
+ const messages = [
153
+ new HumanMessage({ content: 'show me something cool' }),
154
+ new AIMessage({
155
+ content: [
156
+ { type: 'text', text: '\n\n' },
157
+ {
158
+ type: ContentTypes.REASONING_CONTENT,
159
+ reasoningText: { text: 'Let me navigate to a page' },
160
+ },
161
+ { type: 'text', text: 'Let me whip up something fun!' },
162
+ ],
163
+ tool_calls: [
164
+ {
165
+ id: 'call_nav',
166
+ name: 'navigate_page',
167
+ args: { url: 'about:blank' },
168
+ type: 'tool_call' as const,
169
+ },
170
+ ],
171
+ }),
172
+ new ToolMessage({
173
+ content: 'Navigated to about:blank',
174
+ tool_call_id: 'call_nav',
175
+ }),
176
+ // Follow-up: content: "", tool calls, NO reasoning block
177
+ new AIMessage({
178
+ content: '',
179
+ tool_calls: [
180
+ {
181
+ id: 'call_eval',
182
+ name: 'evaluate_script',
183
+ args: { script: 'document.title = "test"' },
184
+ type: 'tool_call' as const,
185
+ },
186
+ ],
187
+ }),
188
+ new ToolMessage({
189
+ content: 'Script executed',
190
+ tool_call_id: 'call_eval',
191
+ }),
192
+ ];
193
+
194
+ const result = ensureThinkingBlockInMessages(messages, Providers.BEDROCK);
195
+
196
+ // All 5 messages preserved — the follow-up AI message at index 3 is NOT converted
197
+ expect(result).toHaveLength(5);
198
+ expect(result[0]).toBeInstanceOf(HumanMessage);
199
+ expect(result[1]).toBeInstanceOf(AIMessage);
200
+ expect(result[2]).toBeInstanceOf(ToolMessage);
201
+ expect(result[3]).toBeInstanceOf(AIMessage);
202
+ expect(result[3].content).toBe('');
203
+ expect((result[3] as AIMessage).tool_calls).toHaveLength(1);
204
+ expect(result[4]).toBeInstanceOf(ToolMessage);
205
+ });
206
+
207
+ test('should not convert multiple follow-up tool calls in a long chain', () => {
208
+ // Three AI→Tool rounds: only the first has reasoning
209
+ const messages = [
210
+ new HumanMessage({ content: 'do stuff' }),
211
+ new AIMessage({
212
+ content: [
213
+ {
214
+ type: ContentTypes.REASONING_CONTENT,
215
+ reasoningText: { text: 'Planning...' },
216
+ },
217
+ ],
218
+ tool_calls: [
219
+ { id: 'c1', name: 'step1', args: {}, type: 'tool_call' as const },
220
+ ],
221
+ }),
222
+ new ToolMessage({ content: 'r1', tool_call_id: 'c1' }),
223
+ new AIMessage({
224
+ content: '',
225
+ tool_calls: [
226
+ { id: 'c2', name: 'step2', args: {}, type: 'tool_call' as const },
227
+ ],
228
+ }),
229
+ new ToolMessage({ content: 'r2', tool_call_id: 'c2' }),
230
+ new AIMessage({
231
+ content: '',
232
+ tool_calls: [
233
+ { id: 'c3', name: 'step3', args: {}, type: 'tool_call' as const },
234
+ ],
235
+ }),
236
+ new ToolMessage({ content: 'r3', tool_call_id: 'c3' }),
237
+ ];
238
+
239
+ const result = ensureThinkingBlockInMessages(messages, Providers.BEDROCK);
240
+
241
+ expect(result).toHaveLength(7);
242
+ expect(result[1]).toBeInstanceOf(AIMessage);
243
+ expect(result[3]).toBeInstanceOf(AIMessage);
244
+ expect(result[5]).toBeInstanceOf(AIMessage);
245
+ });
246
+
247
+ test('should still convert non-thinking agent tool calls after a human message boundary', () => {
248
+ // A chain with thinking, then a new human message, then a chain WITHOUT thinking
249
+ const messages = [
250
+ new HumanMessage({ content: 'first request' }),
251
+ new AIMessage({
252
+ content: [
253
+ {
254
+ type: ContentTypes.REASONING_CONTENT,
255
+ reasoningText: { text: 'Thinking...' },
256
+ },
257
+ ],
258
+ tool_calls: [
259
+ { id: 'c1', name: 'tool1', args: {}, type: 'tool_call' as const },
260
+ ],
261
+ }),
262
+ new ToolMessage({ content: 'r1', tool_call_id: 'c1' }),
263
+ new HumanMessage({ content: 'second request' }),
264
+ // This chain has NO thinking blocks — should be converted
265
+ new AIMessage({
266
+ content: 'Using a tool',
267
+ tool_calls: [
268
+ { id: 'c2', name: 'tool2', args: {}, type: 'tool_call' as const },
269
+ ],
270
+ }),
271
+ new ToolMessage({ content: 'r2', tool_call_id: 'c2' }),
272
+ ];
273
+
274
+ const result = ensureThinkingBlockInMessages(messages, Providers.BEDROCK);
275
+
276
+ // First chain preserved (3 msgs), human preserved, second chain converted (1 HumanMessage)
277
+ expect(result).toHaveLength(5);
278
+ expect(result[0]).toBeInstanceOf(HumanMessage);
279
+ expect(result[1]).toBeInstanceOf(AIMessage); // reasoning chain — kept
280
+ expect(result[2]).toBeInstanceOf(ToolMessage);
281
+ expect(result[3]).toBeInstanceOf(HumanMessage); // user message
282
+ expect(result[4]).toBeInstanceOf(HumanMessage); // converted — no thinking in this chain
283
+ expect(getTextContent(result[4])).toContain('[Previous agent context]');
284
+ });
285
+
286
+ test('should detect thinking via additional_kwargs.reasoning_content in chain', () => {
287
+ const messages = [
288
+ new HumanMessage({ content: 'hello' }),
289
+ new AIMessage({
290
+ content: '',
291
+ additional_kwargs: {
292
+ reasoning_content: 'Some reasoning...',
293
+ },
294
+ tool_calls: [
295
+ { id: 'c1', name: 'tool1', args: {}, type: 'tool_call' as const },
296
+ ],
297
+ }),
298
+ new ToolMessage({ content: 'r1', tool_call_id: 'c1' }),
299
+ new AIMessage({
300
+ content: '',
301
+ tool_calls: [
302
+ { id: 'c2', name: 'tool2', args: {}, type: 'tool_call' as const },
303
+ ],
304
+ }),
305
+ new ToolMessage({ content: 'r2', tool_call_id: 'c2' }),
306
+ ];
307
+
308
+ const result = ensureThinkingBlockInMessages(messages, Providers.BEDROCK);
309
+
310
+ // Index 3 should NOT be converted — index 1 has reasoning in additional_kwargs
311
+ expect(result).toHaveLength(5);
312
+ expect(result[3]).toBeInstanceOf(AIMessage);
313
+ });
314
+
92
315
  test('should not modify AI message with reasoning block and tool calls', () => {
93
316
  const messages = [
94
317
  new HumanMessage({ content: 'Calculate something' }),
@@ -162,9 +385,10 @@ describe('ensureThinkingBlockInMessages', () => {
162
385
  expect(result[1]).toBeInstanceOf(HumanMessage);
163
386
 
164
387
  // Check that the converted message includes the context prefix
165
- expect(result[1].content).toContain('[Previous agent context]');
166
- expect(result[1].content).toContain('Let me check the weather');
167
- expect(result[1].content).toContain('Sunny, 75°F');
388
+ const text = getTextContent(result[1]);
389
+ expect(text).toContain('[Previous agent context]');
390
+ expect(text).toContain('Let me check the weather');
391
+ expect(text).toContain('Sunny, 75°F');
168
392
  });
169
393
 
170
394
  test('should convert AI message with tool_use in content to HumanMessage', () => {
@@ -195,9 +419,10 @@ describe('ensureThinkingBlockInMessages', () => {
195
419
  expect(result).toHaveLength(2);
196
420
  expect(result[0]).toBeInstanceOf(HumanMessage);
197
421
  expect(result[1]).toBeInstanceOf(HumanMessage);
198
- expect(result[1].content).toContain('[Previous agent context]');
199
- expect(result[1].content).toContain('Searching...');
200
- expect(result[1].content).toContain('Found results');
422
+ const text = getTextContent(result[1]);
423
+ expect(text).toContain('[Previous agent context]');
424
+ expect(text).toContain('Searching...');
425
+ expect(text).toContain('Found results');
201
426
  });
202
427
 
203
428
  test('should handle multiple tool messages in sequence', () => {
@@ -238,8 +463,9 @@ describe('ensureThinkingBlockInMessages', () => {
238
463
  // Should combine all tool messages into one HumanMessage
239
464
  expect(result).toHaveLength(2);
240
465
  expect(result[1]).toBeInstanceOf(HumanMessage);
241
- expect(result[1].content).toContain('Result 1');
242
- expect(result[1].content).toContain('Result 2');
466
+ const text = getTextContent(result[1]);
467
+ expect(text).toContain('Result 1');
468
+ expect(text).toContain('Result 2');
243
469
  });
244
470
  });
245
471
 
@@ -374,11 +600,73 @@ describe('ensureThinkingBlockInMessages', () => {
374
600
  expect(result[0]).toBeInstanceOf(HumanMessage);
375
601
  expect(result[0].content).toBe('Do task 1');
376
602
  expect(result[1]).toBeInstanceOf(HumanMessage);
377
- expect(result[1].content).toContain('Doing task 1');
603
+ expect(getTextContent(result[1])).toContain('Doing task 1');
378
604
  expect(result[2]).toBeInstanceOf(HumanMessage);
379
605
  expect(result[2].content).toBe('Do task 2');
380
606
  expect(result[3]).toBeInstanceOf(HumanMessage);
381
- expect(result[3].content).toContain('Doing task 2');
607
+ expect(getTextContent(result[3])).toContain('Doing task 2');
608
+ });
609
+ });
610
+
611
+ describe('fast exit when last message is HumanMessage', () => {
612
+ test('should return messages as-is when last message is a HumanMessage', () => {
613
+ const messages = [
614
+ new HumanMessage({ content: 'first request' }),
615
+ new AIMessage({
616
+ content: 'Using a tool',
617
+ tool_calls: [
618
+ { id: 'c1', name: 'tool1', args: {}, type: 'tool_call' as const },
619
+ ],
620
+ }),
621
+ new ToolMessage({ content: 'r1', tool_call_id: 'c1' }),
622
+ new HumanMessage({ content: 'second request' }),
623
+ ];
624
+
625
+ const result = ensureThinkingBlockInMessages(
626
+ messages,
627
+ Providers.ANTHROPIC
628
+ );
629
+
630
+ // Should return the exact same array reference — no processing done
631
+ expect(result).toBe(messages);
632
+ expect(result).toHaveLength(4);
633
+ });
634
+
635
+ test('should return messages as-is when only message is a HumanMessage', () => {
636
+ const messages = [new HumanMessage({ content: 'hello' })];
637
+
638
+ const result = ensureThinkingBlockInMessages(
639
+ messages,
640
+ Providers.ANTHROPIC
641
+ );
642
+
643
+ expect(result).toBe(messages);
644
+ });
645
+
646
+ test('should still process when last message is not a HumanMessage', () => {
647
+ const messages = [
648
+ new HumanMessage({ content: 'do something' }),
649
+ new AIMessage({
650
+ content: 'Using a tool',
651
+ tool_calls: [
652
+ { id: 'c1', name: 'tool1', args: {}, type: 'tool_call' as const },
653
+ ],
654
+ }),
655
+ new ToolMessage({ content: 'r1', tool_call_id: 'c1' }),
656
+ ];
657
+
658
+ const result = ensureThinkingBlockInMessages(
659
+ messages,
660
+ Providers.ANTHROPIC
661
+ );
662
+
663
+ // Should process — last message is ToolMessage, not HumanMessage
664
+ expect(result).not.toBe(messages);
665
+ expect(result).toHaveLength(2);
666
+ expect(result[0]).toBeInstanceOf(HumanMessage);
667
+ expect(result[0].content).toBe('do something');
668
+ expect(result[1]).toBeInstanceOf(HumanMessage);
669
+ expect(getTextContent(result[1])).toContain('[Previous agent context]');
382
670
  });
383
671
  });
384
672
 
@@ -465,4 +753,457 @@ describe('ensureThinkingBlockInMessages', () => {
465
753
  expect(result[1]).toBeInstanceOf(ToolMessage);
466
754
  });
467
755
  });
756
+
757
+ describe('image content preservation (token amplification fix)', () => {
758
+ const FAKE_BASE64 =
759
+ 'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk';
760
+
761
+ /**
762
+ * Reproduces the reported bug: a base64 image from an MCP tool, when
763
+ * serialized by the old getBufferString() path, would become text tokens.
764
+ * With the fix, the base64 data stays in a structured image block.
765
+ */
766
+ test('should not serialize base64 image as text (reported 174x token amplification)', () => {
767
+ const LARGE_BASE64 = 'A'.repeat(10_000);
768
+
769
+ const messages = [
770
+ new HumanMessage({ content: 'Take a screenshot' }),
771
+ new AIMessage({
772
+ content: 'Taking a screenshot.',
773
+ tool_calls: [
774
+ {
775
+ id: 'call_mcp',
776
+ name: 'screenshot',
777
+ args: {},
778
+ type: 'tool_call' as const,
779
+ },
780
+ ],
781
+ }),
782
+ new ToolMessage({
783
+ content: [
784
+ { type: 'text', text: 'Screenshot captured (1280x720)' },
785
+ {
786
+ type: 'image_url',
787
+ image_url: { url: `data:image/png;base64,${LARGE_BASE64}` },
788
+ },
789
+ ],
790
+ tool_call_id: 'call_mcp',
791
+ }),
792
+ ];
793
+
794
+ const result = ensureThinkingBlockInMessages(
795
+ messages,
796
+ Providers.ANTHROPIC
797
+ );
798
+
799
+ expect(result).toHaveLength(2);
800
+ expect(result[1]).toBeInstanceOf(HumanMessage);
801
+
802
+ const content = result[1].content as ExtendedMessageContent[];
803
+ const textBlocks = content.filter((b) => b.type === 'text');
804
+ const imageBlocks = content.filter((b) => b.type === 'image_url');
805
+
806
+ expect(imageBlocks).toHaveLength(1);
807
+
808
+ const allText = textBlocks.map((b) => String(b.text ?? '')).join('\n');
809
+ expect(allText).toContain('[Previous agent context]');
810
+ expect(allText).toContain('Screenshot captured');
811
+ expect(allText).not.toContain(LARGE_BASE64);
812
+ // Text must be orders of magnitude smaller than the image data
813
+ expect(allText.length).toBeLessThan(LARGE_BASE64.length / 10);
814
+ });
815
+
816
+ test('should preserve image_url blocks from ToolMessage instead of serializing as text', () => {
817
+ const messages = [
818
+ new HumanMessage({ content: 'Take a screenshot' }),
819
+ new AIMessage({
820
+ content: 'Taking screenshot now.',
821
+ tool_calls: [
822
+ {
823
+ id: 'call_ss',
824
+ name: 'screenshot',
825
+ args: {},
826
+ type: 'tool_call' as const,
827
+ },
828
+ ],
829
+ }),
830
+ new ToolMessage({
831
+ content: [
832
+ { type: 'text', text: 'Screenshot captured' },
833
+ {
834
+ type: 'image_url',
835
+ image_url: {
836
+ url: `data:image/png;base64,${FAKE_BASE64}`,
837
+ },
838
+ },
839
+ ],
840
+ tool_call_id: 'call_ss',
841
+ }),
842
+ ];
843
+
844
+ const result = ensureThinkingBlockInMessages(
845
+ messages,
846
+ Providers.ANTHROPIC
847
+ );
848
+
849
+ expect(result).toHaveLength(2);
850
+ expect(result[1]).toBeInstanceOf(HumanMessage);
851
+
852
+ // Content should be an array with structured blocks
853
+ const content = result[1].content as ExtendedMessageContent[];
854
+ expect(Array.isArray(content)).toBe(true);
855
+
856
+ // Should have text block(s) and an image_url block
857
+ const textBlocks = content.filter((b) => b.type === 'text');
858
+ const imageBlocks = content.filter((b) => b.type === 'image_url');
859
+
860
+ expect(textBlocks.length).toBeGreaterThanOrEqual(1);
861
+ expect(imageBlocks).toHaveLength(1);
862
+
863
+ // The image block should be preserved as-is (not serialized to text)
864
+ const imageBlock = imageBlocks[0] as {
865
+ type: string;
866
+ image_url: { url: string };
867
+ };
868
+ expect(imageBlock.image_url.url).toContain(FAKE_BASE64);
869
+
870
+ // The text should contain context info but NOT the base64 data
871
+ const allText = textBlocks.map((b) => String(b.text ?? '')).join('\n');
872
+ expect(allText).toContain('[Previous agent context]');
873
+ expect(allText).toContain('Screenshot captured');
874
+ expect(allText).not.toContain(FAKE_BASE64);
875
+ });
876
+
877
+ test('should preserve Anthropic-style image blocks from ToolMessage', () => {
878
+ const messages = [
879
+ new HumanMessage({ content: 'Take a screenshot' }),
880
+ new AIMessage({
881
+ content: 'Let me capture that.',
882
+ tool_calls: [
883
+ {
884
+ id: 'call_ss2',
885
+ name: 'screenshot',
886
+ args: {},
887
+ type: 'tool_call' as const,
888
+ },
889
+ ],
890
+ }),
891
+ new ToolMessage({
892
+ content: [
893
+ { type: 'text', text: 'Here is the screenshot' },
894
+ {
895
+ type: 'image',
896
+ source: {
897
+ type: 'base64',
898
+ media_type: 'image/png',
899
+ data: FAKE_BASE64,
900
+ },
901
+ },
902
+ ],
903
+ tool_call_id: 'call_ss2',
904
+ }),
905
+ ];
906
+
907
+ const result = ensureThinkingBlockInMessages(
908
+ messages,
909
+ Providers.ANTHROPIC
910
+ );
911
+
912
+ expect(result).toHaveLength(2);
913
+ const content = result[1].content as ExtendedMessageContent[];
914
+ expect(Array.isArray(content)).toBe(true);
915
+
916
+ const imageBlocks = content.filter((b) => b.type === 'image');
917
+ expect(imageBlocks).toHaveLength(1);
918
+ const imageBlock = imageBlocks[0] as {
919
+ type: string;
920
+ source: { data: string };
921
+ };
922
+ expect(imageBlock.source.data).toBe(FAKE_BASE64);
923
+
924
+ // Text should not contain base64
925
+ const allText = content
926
+ .filter((b) => b.type === 'text')
927
+ .map((b) => String(b.text ?? ''))
928
+ .join('\n');
929
+ expect(allText).not.toContain(FAKE_BASE64);
930
+ });
931
+
932
+ test('should handle multiple images across multiple ToolMessages', () => {
933
+ const messages = [
934
+ new HumanMessage({ content: 'Compare two pages' }),
935
+ new AIMessage({
936
+ content: 'Taking screenshots of both pages.',
937
+ tool_calls: [
938
+ {
939
+ id: 'call_a',
940
+ name: 'screenshot',
941
+ args: { page: 'A' },
942
+ type: 'tool_call' as const,
943
+ },
944
+ {
945
+ id: 'call_b',
946
+ name: 'screenshot',
947
+ args: { page: 'B' },
948
+ type: 'tool_call' as const,
949
+ },
950
+ ],
951
+ }),
952
+ new ToolMessage({
953
+ content: [
954
+ { type: 'text', text: 'Page A screenshot' },
955
+ {
956
+ type: 'image_url',
957
+ image_url: { url: 'data:image/png;base64,PAGE_A_DATA' },
958
+ },
959
+ ],
960
+ tool_call_id: 'call_a',
961
+ }),
962
+ new ToolMessage({
963
+ content: [
964
+ { type: 'text', text: 'Page B screenshot' },
965
+ {
966
+ type: 'image_url',
967
+ image_url: { url: 'data:image/png;base64,PAGE_B_DATA' },
968
+ },
969
+ ],
970
+ tool_call_id: 'call_b',
971
+ }),
972
+ ];
973
+
974
+ const result = ensureThinkingBlockInMessages(
975
+ messages,
976
+ Providers.ANTHROPIC
977
+ );
978
+
979
+ expect(result).toHaveLength(2);
980
+ const content = result[1].content as ExtendedMessageContent[];
981
+ const imageBlocks = content.filter((b) => b.type === 'image_url');
982
+ expect(imageBlocks).toHaveLength(2);
983
+
984
+ const allText = content
985
+ .filter((b) => b.type === 'text')
986
+ .map((b) => String(b.text ?? ''))
987
+ .join('\n');
988
+ expect(allText).toContain('Page A screenshot');
989
+ expect(allText).toContain('Page B screenshot');
990
+ });
991
+
992
+ test('should still produce text-only content when no images are present', () => {
993
+ const messages = [
994
+ new HumanMessage({ content: 'Do something' }),
995
+ new AIMessage({
996
+ content: 'Doing it.',
997
+ tool_calls: [
998
+ {
999
+ id: 'call_t',
1000
+ name: 'tool',
1001
+ args: { x: 1 },
1002
+ type: 'tool_call' as const,
1003
+ },
1004
+ ],
1005
+ }),
1006
+ new ToolMessage({
1007
+ content: 'plain text result',
1008
+ tool_call_id: 'call_t',
1009
+ }),
1010
+ ];
1011
+
1012
+ const result = ensureThinkingBlockInMessages(
1013
+ messages,
1014
+ Providers.ANTHROPIC
1015
+ );
1016
+
1017
+ expect(result).toHaveLength(2);
1018
+ const content = result[1].content as ExtendedMessageContent[];
1019
+ // When no images, should still be an array with a single text block
1020
+ expect(Array.isArray(content)).toBe(true);
1021
+ expect(content).toHaveLength(1);
1022
+ expect(content[0].type).toBe('text');
1023
+ expect(content[0].text).toContain('[Previous agent context]');
1024
+ expect(content[0].text).toContain('plain text result');
1025
+ });
1026
+
1027
+ test('should not double-serialize when AIMessage has both content tool_use and tool_calls', () => {
1028
+ const messages = [
1029
+ new HumanMessage({ content: 'Search for something' }),
1030
+ new AIMessage({
1031
+ content: [
1032
+ { type: 'text', text: 'Searching...' },
1033
+ {
1034
+ type: 'tool_use',
1035
+ id: 'call_dual',
1036
+ name: 'search',
1037
+ input: { query: 'test' },
1038
+ },
1039
+ ],
1040
+ tool_calls: [
1041
+ {
1042
+ id: 'call_dual',
1043
+ name: 'search',
1044
+ args: { query: 'test' },
1045
+ type: 'tool_call' as const,
1046
+ },
1047
+ ],
1048
+ }),
1049
+ new ToolMessage({
1050
+ content: 'Found 5 results',
1051
+ tool_call_id: 'call_dual',
1052
+ }),
1053
+ ];
1054
+
1055
+ const result = ensureThinkingBlockInMessages(
1056
+ messages,
1057
+ Providers.ANTHROPIC
1058
+ );
1059
+
1060
+ expect(result).toHaveLength(2);
1061
+ const allText = getTextContent(result[1]);
1062
+ // Array content path serializes tool_use blocks but skips appendToolCalls
1063
+ expect(allText).not.toContain('[tool_call]');
1064
+ expect(allText).toContain('[tool_use]');
1065
+ });
1066
+
1067
+ test('should serialize tool_calls when content is empty array (no tool_use blocks)', () => {
1068
+ const messages = [
1069
+ new HumanMessage({ content: 'Do something' }),
1070
+ new AIMessage({
1071
+ content: [],
1072
+ tool_calls: [
1073
+ {
1074
+ id: 'call_empty',
1075
+ name: 'some_tool',
1076
+ args: { x: 1 },
1077
+ type: 'tool_call' as const,
1078
+ },
1079
+ ],
1080
+ }),
1081
+ new ToolMessage({
1082
+ content: 'tool result',
1083
+ tool_call_id: 'call_empty',
1084
+ }),
1085
+ ];
1086
+
1087
+ const result = ensureThinkingBlockInMessages(
1088
+ messages,
1089
+ Providers.ANTHROPIC
1090
+ );
1091
+
1092
+ expect(result).toHaveLength(2);
1093
+ const allText = getTextContent(result[1]);
1094
+ // With empty content array, should fall back to tool_calls
1095
+ expect(allText).toContain('[tool_call]');
1096
+ expect(allText).toContain('some_tool');
1097
+ });
1098
+
1099
+ test('should serialize unrecognized block types instead of dropping them', () => {
1100
+ const messages = [
1101
+ new HumanMessage({ content: 'Fetch resource' }),
1102
+ new AIMessage({
1103
+ content: 'Fetching.',
1104
+ tool_calls: [
1105
+ {
1106
+ id: 'call_res',
1107
+ name: 'fetch_resource',
1108
+ args: {},
1109
+ type: 'tool_call' as const,
1110
+ },
1111
+ ],
1112
+ }),
1113
+ new ToolMessage({
1114
+ content: [
1115
+ { type: 'text', text: 'Resource fetched' },
1116
+ {
1117
+ type: 'resource',
1118
+ resource: { uri: 'file:///data.csv', text: 'a,b,c' },
1119
+ },
1120
+ ],
1121
+ tool_call_id: 'call_res',
1122
+ }),
1123
+ ];
1124
+
1125
+ const result = ensureThinkingBlockInMessages(
1126
+ messages,
1127
+ Providers.ANTHROPIC
1128
+ );
1129
+
1130
+ expect(result).toHaveLength(2);
1131
+ const allText = getTextContent(result[1]);
1132
+ // The resource block should be serialized as text, not silently dropped
1133
+ expect(allText).toContain('[resource]');
1134
+ expect(allText).toContain('data.csv');
1135
+ });
1136
+
1137
+ test('should preserve image blocks when provider is Bedrock', () => {
1138
+ const messages = [
1139
+ new HumanMessage({ content: 'Screenshot' }),
1140
+ new AIMessage({
1141
+ content: 'Taking screenshot.',
1142
+ tool_calls: [
1143
+ {
1144
+ id: 'call_br',
1145
+ name: 'screenshot',
1146
+ args: {},
1147
+ type: 'tool_call' as const,
1148
+ },
1149
+ ],
1150
+ }),
1151
+ new ToolMessage({
1152
+ content: [
1153
+ { type: 'text', text: 'Captured' },
1154
+ {
1155
+ type: 'image_url',
1156
+ image_url: { url: `data:image/png;base64,${FAKE_BASE64}` },
1157
+ },
1158
+ ],
1159
+ tool_call_id: 'call_br',
1160
+ }),
1161
+ ];
1162
+
1163
+ const result = ensureThinkingBlockInMessages(messages, Providers.BEDROCK);
1164
+
1165
+ expect(result).toHaveLength(2);
1166
+ expect(result[1]).toBeInstanceOf(HumanMessage);
1167
+ const content = result[1].content as ExtendedMessageContent[];
1168
+ const imageBlocks = content.filter((b) => b.type === 'image_url');
1169
+ expect(imageBlocks).toHaveLength(1);
1170
+ const allText = getTextContent(result[1]);
1171
+ expect(allText).not.toContain(FAKE_BASE64);
1172
+ });
1173
+
1174
+ test('should shallow-copy image blocks to prevent aliasing', () => {
1175
+ const originalImageBlock = {
1176
+ type: 'image_url',
1177
+ image_url: { url: `data:image/png;base64,${FAKE_BASE64}` },
1178
+ };
1179
+ const messages = [
1180
+ new HumanMessage({ content: 'Screenshot' }),
1181
+ new AIMessage({
1182
+ content: 'Taking screenshot.',
1183
+ tool_calls: [
1184
+ {
1185
+ id: 'call_alias',
1186
+ name: 'screenshot',
1187
+ args: {},
1188
+ type: 'tool_call' as const,
1189
+ },
1190
+ ],
1191
+ }),
1192
+ new ToolMessage({
1193
+ content: [{ type: 'text', text: 'Captured' }, originalImageBlock],
1194
+ tool_call_id: 'call_alias',
1195
+ }),
1196
+ ];
1197
+
1198
+ const result = ensureThinkingBlockInMessages(
1199
+ messages,
1200
+ Providers.ANTHROPIC
1201
+ );
1202
+
1203
+ const content = result[1].content as ExtendedMessageContent[];
1204
+ const outputImageBlock = content.find((b) => b.type === 'image_url');
1205
+ // Should be a different object reference (shallow copy)
1206
+ expect(outputImageBlock).not.toBe(originalImageBlock);
1207
+ });
1208
+ });
468
1209
  });