@illuma-ai/agents 1.0.89 → 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
@@ -0,0 +1,990 @@
1
+ /**
2
+ * End-to-End tests for context management across subagents, handoffs, and chaining.
3
+ *
4
+ * These tests exercise the full lifecycle of context management scenarios that
5
+ * span multiple agents and turns, validating that context is preserved, compacted,
6
+ * and transferred correctly across all agent execution patterns.
7
+ *
8
+ * Run with:
9
+ * npx jest --no-coverage --forceExit src/graphs/contextManagement.e2e.test.ts
10
+ */
11
+ import {
12
+ HumanMessage,
13
+ AIMessage,
14
+ SystemMessage,
15
+ ToolMessage,
16
+ BaseMessage,
17
+ } from '@langchain/core/messages';
18
+ import type { TokenCounter } from '@/types/run';
19
+ import {
20
+ summarize,
21
+ createEmergencySummary,
22
+ formatMessagesForSummary,
23
+ buildFullSummaryPrompt,
24
+ } from '@/messages/summarize';
25
+ import { getContextUtilization } from '@/messages/prune';
26
+
27
+ // ---------------------------------------------------------------------------
28
+ // Helpers
29
+ // ---------------------------------------------------------------------------
30
+
31
+ /** Simple token counter: 1 token ≈ 4 chars */
32
+ const simpleTokenCounter: TokenCounter = (msg: BaseMessage): number => {
33
+ const content =
34
+ typeof msg.content === 'string' ? msg.content : JSON.stringify(msg.content);
35
+ return Math.ceil(content.length / 4);
36
+ };
37
+
38
+ /** Create a realistic conversation with N turns */
39
+ function buildConversation(turns: number, charPerMessage = 200): BaseMessage[] {
40
+ const messages: BaseMessage[] = [];
41
+ for (let i = 0; i < turns; i++) {
42
+ messages.push(
43
+ new HumanMessage({
44
+ content: `User message ${i}: ${'x'.repeat(charPerMessage)}`,
45
+ })
46
+ );
47
+ messages.push(
48
+ new AIMessage({
49
+ content: `AI response ${i}: ${'y'.repeat(charPerMessage)}`,
50
+ })
51
+ );
52
+ }
53
+ return messages;
54
+ }
55
+
56
+ /** Simulates a summarize callback that returns a structured summary */
57
+ const mockSummarizeCallback = async (
58
+ prompt: string,
59
+ _maxTokens: number
60
+ ): Promise<string> => {
61
+ return `[Summary] Conversation covered ${prompt.length} chars of content. Key topics discussed. Active context preserved.`;
62
+ };
63
+
64
+ /** Simulates a summarize callback that always fails */
65
+ const failingSummarizeCallback = async (): Promise<string> => {
66
+ throw new Error('LLM unavailable');
67
+ };
68
+
69
+ // ============================================================================
70
+ // 1. Subagent Result Truncation E2E
71
+ // ============================================================================
72
+
73
+ describe('Subagent result truncation E2E', () => {
74
+ it('truncated subagent result fits within parent context budget', () => {
75
+ // Simulate: subagent produces 50K chars, parent has 10K token budget
76
+ const subagentResult = 'Finding: '.repeat(5000) + 'Conclusion reached.';
77
+ const parentMaxTokens = 10000;
78
+ const maxResultChars = 8192 * 4; // 8192 tokens * 4 chars/token = 32768
79
+
80
+ // Truncation logic (mirrors TaskTool.truncateResult)
81
+ const truncationNotice =
82
+ '\n\n[... sub-agent output truncated — middle section omitted to fit parent context ...]\n\n';
83
+ const available = maxResultChars - truncationNotice.length;
84
+ const headSize = Math.floor(available * 0.6);
85
+ const tailSize = available - headSize;
86
+ const truncated =
87
+ subagentResult.substring(0, headSize) +
88
+ truncationNotice +
89
+ subagentResult.substring(subagentResult.length - tailSize);
90
+
91
+ // Result fits in parent budget (32768 chars ≈ 8192 tokens)
92
+ const resultTokens = Math.ceil(truncated.length / 4);
93
+ expect(resultTokens).toBeLessThanOrEqual(parentMaxTokens);
94
+ expect(truncated).toContain('Finding:');
95
+ expect(truncated).toContain('Conclusion reached.');
96
+ expect(truncated).toContain('sub-agent output truncated');
97
+ });
98
+
99
+ it('multiple subagent results combined still fit parent context', () => {
100
+ // Simulate 3 parallel subagent tasks each returning large results
101
+ const maxResultCharsPerSubagent = 8192;
102
+ const results = [
103
+ 'A'.repeat(maxResultCharsPerSubagent),
104
+ 'B'.repeat(maxResultCharsPerSubagent),
105
+ 'C'.repeat(maxResultCharsPerSubagent),
106
+ ];
107
+
108
+ // Parent context: system + messages + 3 tool results
109
+ const systemTokens = 500;
110
+ const conversationTokens = 2000;
111
+ const totalResultTokens = results.reduce(
112
+ (sum, r) => sum + Math.ceil(r.length / 4),
113
+ 0
114
+ );
115
+ const totalUsed = systemTokens + conversationTokens + totalResultTokens;
116
+
117
+ // With 3 subagents at 8192 chars each (≈2048 tokens each), total ≈ 6144 + 2500 = 8644 tokens
118
+ // Fits within a 16K context window
119
+ expect(totalUsed).toBeLessThan(16000);
120
+ });
121
+
122
+ it('subagent result truncation preserves actionable content', () => {
123
+ // Simulate a subagent that found code, data, and conclusions
124
+ const codeBlock = '```typescript\nfunction process() { return 42; }\n```\n';
125
+ const dataSection =
126
+ 'Data: ' + JSON.stringify({ metric: 99.5, status: 'healthy' }) + '\n';
127
+ const middlePadding = 'Analysis details '.repeat(3000); // ~51K chars
128
+ const conclusion =
129
+ '\nFinal answer: The system is operating within normal parameters.';
130
+
131
+ const fullResult = codeBlock + dataSection + middlePadding + conclusion;
132
+ const maxChars = 2000;
133
+
134
+ // Truncation keeps head (60%) and tail (40%)
135
+ const notice =
136
+ '\n\n[... sub-agent output truncated — middle section omitted to fit parent context ...]\n\n';
137
+ const available = maxChars - notice.length;
138
+ const headSize = Math.floor(available * 0.6);
139
+ const tailSize = available - headSize;
140
+ const truncated =
141
+ fullResult.substring(0, headSize) +
142
+ notice +
143
+ fullResult.substring(fullResult.length - tailSize);
144
+
145
+ // Head should contain the code and data (actionable)
146
+ expect(truncated).toContain('function process()');
147
+ expect(truncated).toContain('metric');
148
+ // Tail should contain the conclusion
149
+ expect(truncated).toContain('Final answer');
150
+ });
151
+ });
152
+
153
+ // ============================================================================
154
+ // 2. Agent Handoff with Context Compaction E2E
155
+ // ============================================================================
156
+
157
+ describe('Agent handoff with context compaction E2E', () => {
158
+ it('compacts context before handoff when sender exceeds receiver budget', async () => {
159
+ // Agent A has 200K context, Agent B has 32K context
160
+ const senderMessages = buildConversation(50, 500); // 50 turns, ~500 chars each ≈ lots of tokens
161
+ const receiverMaxTokens = 8000; // 32K chars
162
+
163
+ // Calculate sender's context tokens
164
+ const senderTokens = senderMessages.reduce(
165
+ (sum, m) => sum + simpleTokenCounter(m),
166
+ 0
167
+ );
168
+
169
+ // Check if compaction needed (>70% of receiver budget)
170
+ const compactionThreshold = receiverMaxTokens * 0.7;
171
+ expect(senderTokens).toBeGreaterThan(compactionThreshold);
172
+
173
+ // Compact: summarize + keep last 3 messages
174
+ const result = await summarize(senderMessages, mockSummarizeCallback, {
175
+ tokenCounter: simpleTokenCounter,
176
+ summaryBudget: Math.floor(receiverMaxTokens * 0.2),
177
+ });
178
+
179
+ expect(result.tier).toBe('full');
180
+ expect(result.summary).toBeTruthy();
181
+
182
+ // Build compacted messages: system summary + last 3 messages
183
+ const compactedMessages = [
184
+ new SystemMessage({ content: `[Handoff Briefing]\n${result.summary}` }),
185
+ ...senderMessages.slice(-3),
186
+ ];
187
+
188
+ // Compacted context fits receiver budget
189
+ const compactedTokens = compactedMessages.reduce(
190
+ (sum, m) => sum + simpleTokenCounter(m),
191
+ 0
192
+ );
193
+ expect(compactedTokens).toBeLessThan(receiverMaxTokens);
194
+ });
195
+
196
+ it('preserves critical context through handoff compaction', async () => {
197
+ // First message has the user's original intent
198
+ const messages: BaseMessage[] = [
199
+ new HumanMessage({
200
+ content:
201
+ 'Create a quarterly revenue report for Q4 2025 with charts and analysis',
202
+ }),
203
+ new AIMessage({ content: 'I will analyze the revenue data.' }),
204
+ // ... many intermediate messages ...
205
+ ...buildConversation(20, 300),
206
+ // Last messages have current progress
207
+ new HumanMessage({
208
+ content: 'Now add the competitor comparison section',
209
+ }),
210
+ new AIMessage({
211
+ content: 'Adding competitor analysis from the market data...',
212
+ }),
213
+ ];
214
+
215
+ // Emergency summary should capture first user intent and last state
216
+ const emergency = createEmergencySummary(messages);
217
+ expect(emergency).toContain('quarterly revenue report');
218
+ expect(emergency).toContain('competitor');
219
+
220
+ // Full summary should also capture it
221
+ const result = await summarize(messages, mockSummarizeCallback, {
222
+ tokenCounter: simpleTokenCounter,
223
+ });
224
+ expect(result.summary.length).toBeGreaterThan(0);
225
+ expect(result.messagesCompacted).toBe(messages.length);
226
+ });
227
+
228
+ it('handles handoff to agent with smaller context gracefully', async () => {
229
+ // Simulate large context being handed to a mini agent
230
+ const largeContext = buildConversation(100, 400); // Very large conversation
231
+ const miniAgentBudget = 4000; // Very small budget (~16K chars)
232
+
233
+ // First try full summarize
234
+ const result = await summarize(largeContext, mockSummarizeCallback, {
235
+ tokenCounter: simpleTokenCounter,
236
+ summaryBudget: Math.floor(miniAgentBudget * 0.2),
237
+ });
238
+
239
+ // Should produce a summary
240
+ expect(result.summary.length).toBeGreaterThan(0);
241
+
242
+ // Build handoff context
243
+ const handoffMessages = [
244
+ new SystemMessage({ content: `[Handoff Briefing]\n${result.summary}` }),
245
+ ...largeContext.slice(-2), // Keep last exchange
246
+ ];
247
+
248
+ const handoffTokens = handoffMessages.reduce(
249
+ (sum, m) => sum + simpleTokenCounter(m),
250
+ 0
251
+ );
252
+ // Should fit within mini agent budget with room for its own responses
253
+ expect(handoffTokens).toBeLessThan(miniAgentBudget * 0.5);
254
+ });
255
+
256
+ it('generates error ToolMessage for invalid handoff destination', () => {
257
+ const agentContexts = new Map([
258
+ ['research-agent', { name: 'Research Agent', maxContextTokens: 200000 }],
259
+ ['writing-agent', { name: 'Writing Agent', maxContextTokens: 32000 }],
260
+ ]);
261
+
262
+ const invalidDest = 'coding-agent';
263
+ expect(agentContexts.has(invalidDest)).toBe(false);
264
+
265
+ // Build error message for self-correction
266
+ const availableAgents = Array.from(agentContexts.keys()).join(', ');
267
+ const errorMsg = new ToolMessage({
268
+ content: `Agent "${invalidDest}" does not exist. Available agents: ${availableAgents}. Please choose a valid agent.`,
269
+ tool_call_id: 'handoff_call_123',
270
+ });
271
+
272
+ expect(errorMsg.content).toContain('coding-agent');
273
+ expect(errorMsg.content).toContain('research-agent');
274
+ expect(errorMsg.content).toContain('writing-agent');
275
+ });
276
+ });
277
+
278
+ // ============================================================================
279
+ // 3. Agent Chaining with Rolling Summaries
280
+ // ============================================================================
281
+
282
+ describe('Agent chaining with rolling summaries', () => {
283
+ it('maintains context across 3-agent chain via rolling summaries', async () => {
284
+ // Agent A: Research phase
285
+ const agentAMessages: BaseMessage[] = [
286
+ new HumanMessage({ content: 'Research the impact of AI on healthcare' }),
287
+ new AIMessage({
288
+ content:
289
+ 'Found 15 papers on AI diagnostics, drug discovery, and telemedicine.',
290
+ }),
291
+ new HumanMessage({ content: 'Focus on drug discovery findings' }),
292
+ new AIMessage({
293
+ content:
294
+ 'Drug discovery: AI reduces development time by 40%. Key compounds identified.',
295
+ }),
296
+ ];
297
+
298
+ // Summarize Agent A context before passing to Agent B
299
+ const summaryA = await summarize(agentAMessages, mockSummarizeCallback, {
300
+ tokenCounter: simpleTokenCounter,
301
+ });
302
+ expect(summaryA.tier).toBe('full');
303
+
304
+ // Agent B: Analysis phase — receives Agent A's summary
305
+ const agentBMessages: BaseMessage[] = [
306
+ new SystemMessage({
307
+ content: `[Previous Agent Summary]\n${summaryA.summary}`,
308
+ }),
309
+ new HumanMessage({
310
+ content: 'Analyze the drug discovery data and create visualizations',
311
+ }),
312
+ new AIMessage({
313
+ content:
314
+ 'Created 3 charts showing AI impact on drug development timelines.',
315
+ }),
316
+ ];
317
+
318
+ // Summarize Agent B context (including Agent A's summary) before passing to Agent C
319
+ const summaryB = await summarize(agentBMessages, mockSummarizeCallback, {
320
+ tokenCounter: simpleTokenCounter,
321
+ });
322
+ expect(summaryB.tier).toBe('full');
323
+ // Agent B's summary should reference Agent A's work
324
+ expect(summaryB.messagesCompacted).toBe(agentBMessages.length);
325
+
326
+ // Agent C: Report generation — receives accumulated summaries
327
+ const agentCMessages: BaseMessage[] = [
328
+ new SystemMessage({ content: `[Chain Summary]\n${summaryB.summary}` }),
329
+ new HumanMessage({
330
+ content:
331
+ 'Generate the final report with all findings and visualizations',
332
+ }),
333
+ ];
334
+
335
+ // Agent C has enough context to generate the report
336
+ const cTokens = agentCMessages.reduce(
337
+ (sum, m) => sum + simpleTokenCounter(m),
338
+ 0
339
+ );
340
+ expect(cTokens).toBeLessThan(8000); // Well within any model's budget
341
+ });
342
+
343
+ it('chain summary grows but stays within budget', async () => {
344
+ // Simulate a 5-agent chain where each adds to the rolling summary
345
+ let rollingSummary = '';
346
+
347
+ for (let i = 0; i < 5; i++) {
348
+ const agentMessages: BaseMessage[] = [
349
+ ...(rollingSummary
350
+ ? [
351
+ new SystemMessage({
352
+ content: `[Chain Summary]\n${rollingSummary}`,
353
+ }),
354
+ ]
355
+ : []),
356
+ new HumanMessage({ content: `Agent ${i} task: process step ${i}` }),
357
+ new AIMessage({
358
+ content: `Agent ${i} completed step ${i}. ${'Result data '.repeat(50)}`,
359
+ }),
360
+ ];
361
+
362
+ const result = await summarize(agentMessages, mockSummarizeCallback, {
363
+ tokenCounter: simpleTokenCounter,
364
+ summaryBudget: 500,
365
+ });
366
+
367
+ rollingSummary = result.summary;
368
+ }
369
+
370
+ // After 5 agents, rolling summary should still be manageable
371
+ const summaryTokens = Math.ceil(rollingSummary.length / 4);
372
+ expect(summaryTokens).toBeLessThan(1000); // Summary stays compact
373
+ expect(rollingSummary.length).toBeGreaterThan(0);
374
+ });
375
+
376
+ it('emergency summary preserves chain context when LLM fails', async () => {
377
+ // Agent chain where LLM fails mid-chain
378
+ const chainMessages: BaseMessage[] = [
379
+ new SystemMessage({
380
+ content: '[Chain Summary] Previous agents researched AI healthcare.',
381
+ }),
382
+ new HumanMessage({
383
+ content: 'Continue the analysis with cost projections',
384
+ }),
385
+ new AIMessage({ content: 'Cost analysis shows 30% reduction possible.' }),
386
+ new ToolMessage({
387
+ content: 'spreadsheet data loaded',
388
+ tool_call_id: 'tool_1',
389
+ }),
390
+ new HumanMessage({ content: 'Add regulatory compliance section' }),
391
+ new AIMessage({
392
+ content: 'Regulatory review completed for FDA pathways.',
393
+ }),
394
+ ];
395
+
396
+ // LLM unavailable — falls to emergency
397
+ const result = await summarize(chainMessages, failingSummarizeCallback, {
398
+ tokenCounter: simpleTokenCounter,
399
+ });
400
+
401
+ expect(result.tier).toBe('emergency');
402
+ expect(result.summary).toContain('cost projections'); // First user msg
403
+ expect(result.summary).toContain('FDA'); // Last AI msg
404
+ expect(result.summary).toContain('Messages compacted: 6'); // Total count
405
+ });
406
+ });
407
+
408
+ // ============================================================================
409
+ // 4. Continuation Exhaustion and Retry
410
+ // ============================================================================
411
+
412
+ describe('Continuation exhaustion and retry', () => {
413
+ it('detects max_tokens finish reason requiring continuation', () => {
414
+ const finishReasons = ['length', 'max_tokens', 'end_turn', 'stop', null];
415
+ const needsContinuation = finishReasons.filter(
416
+ (r) => r === 'length' || r === 'max_tokens'
417
+ );
418
+ expect(needsContinuation).toEqual(['length', 'max_tokens']);
419
+ });
420
+
421
+ it('enforces maxContinuations limit', () => {
422
+ const maxContinuations = 5;
423
+ let continuationCount = 0;
424
+ const results: string[] = [];
425
+
426
+ // Simulate continuation loop
427
+ while (continuationCount < maxContinuations) {
428
+ const finishReason = 'max_tokens'; // Always hits limit
429
+ if (finishReason !== 'max_tokens' && finishReason !== 'length') {
430
+ break;
431
+ }
432
+ continuationCount++;
433
+ results.push(`Continuation ${continuationCount}`);
434
+ }
435
+
436
+ expect(continuationCount).toBe(maxContinuations);
437
+ expect(results.length).toBe(maxContinuations);
438
+ });
439
+
440
+ it('appends truncation notice when all continuations exhausted', () => {
441
+ const maxContinuations = 5;
442
+ const continuationCount = 5;
443
+ const lastFinishReason = 'max_tokens';
444
+
445
+ const isExhausted =
446
+ continuationCount >= maxContinuations &&
447
+ lastFinishReason === 'max_tokens';
448
+ expect(isExhausted).toBe(true);
449
+
450
+ // Truncation notice appended to last content
451
+ const truncationNotice =
452
+ '\n\n[Note: Response was truncated due to length. Ask me to continue if you need the rest.]';
453
+ const lastContent = 'Some AI response that was cut off';
454
+ const withNotice = lastContent + truncationNotice;
455
+ expect(withNotice).toContain('truncated due to length');
456
+ expect(withNotice).toContain('continue');
457
+ });
458
+
459
+ it('retry-once logic: retries after 2s delay then gives up', async () => {
460
+ let attempts = 0;
461
+ let retried = false;
462
+
463
+ const simulateContinuation = async (): Promise<string> => {
464
+ attempts++;
465
+ if (attempts === 1) {
466
+ throw new Error('Temporary failure');
467
+ }
468
+ return 'Recovered content';
469
+ };
470
+
471
+ // First attempt fails, retry once
472
+ try {
473
+ await simulateContinuation();
474
+ } catch {
475
+ if (!retried) {
476
+ retried = true;
477
+ // In real code: await new Promise(r => setTimeout(r, 2000));
478
+ const result = await simulateContinuation();
479
+ expect(result).toBe('Recovered content');
480
+ }
481
+ }
482
+
483
+ expect(attempts).toBe(2);
484
+ expect(retried).toBe(true);
485
+ });
486
+
487
+ it('saves partial response with interruption notice on final failure', () => {
488
+ const partialResponse = 'Here is the beginning of the analysis...';
489
+ const interruptionNotice =
490
+ '\n\n[Response interrupted: An error occurred while generating this response. The content above may be incomplete.]';
491
+
492
+ const finalContent = partialResponse + interruptionNotice;
493
+ expect(finalContent).toContain('interrupted');
494
+ expect(finalContent).toContain('beginning of the analysis');
495
+ });
496
+
497
+ it('context compaction enables additional continuations', async () => {
498
+ // After 5 continuations, compact context to free space for more
499
+ const longConversation = buildConversation(30, 400); // 30 turns
500
+
501
+ // Before compaction: high utilization
502
+ const totalTokens = longConversation.reduce(
503
+ (sum, m) => sum + simpleTokenCounter(m),
504
+ 0
505
+ );
506
+ const maxTokens = totalTokens + 2000; // Just barely fits
507
+ const utilBefore = getContextUtilization(
508
+ Object.fromEntries(
509
+ longConversation.map((_, i) => [
510
+ String(i),
511
+ simpleTokenCounter(longConversation[i]),
512
+ ])
513
+ ),
514
+ 500,
515
+ maxTokens
516
+ );
517
+ expect(utilBefore).toBeGreaterThan(80);
518
+
519
+ // After compaction
520
+ const result = await summarize(longConversation, mockSummarizeCallback, {
521
+ tokenCounter: simpleTokenCounter,
522
+ });
523
+
524
+ const compactedMessages = [
525
+ new SystemMessage({
526
+ content: `[Conversation Summary]\n${result.summary}`,
527
+ }),
528
+ ...longConversation.slice(-3),
529
+ ];
530
+ const compactedTokens = compactedMessages.reduce(
531
+ (sum, m) => sum + simpleTokenCounter(m),
532
+ 0
533
+ );
534
+
535
+ // After compaction, plenty of room for more continuations
536
+ expect(compactedTokens).toBeLessThan(maxTokens * 0.5);
537
+ });
538
+ });
539
+
540
+ // ============================================================================
541
+ // 5. Pre-invocation Utilization Gate
542
+ // ============================================================================
543
+
544
+ describe('Pre-invocation utilization gate', () => {
545
+ it('emits warning at 70-85% utilization', () => {
546
+ const maxContextTokens = 10000;
547
+ const currentTokens = 7500; // 75%
548
+
549
+ const utilization = (currentTokens / maxContextTokens) * 100;
550
+ const events: Array<{ type: string; level: string }> = [];
551
+
552
+ if (utilization > 95) {
553
+ events.push({ type: 'ON_CONTEXT_PRESSURE', level: 'emergency' });
554
+ } else if (utilization > 85) {
555
+ events.push({ type: 'ON_CONTEXT_PRESSURE', level: 'critical' });
556
+ } else if (utilization > 70) {
557
+ events.push({ type: 'ON_CONTEXT_PRESSURE', level: 'warning' });
558
+ }
559
+
560
+ expect(events).toHaveLength(1);
561
+ expect(events[0].level).toBe('warning');
562
+ });
563
+
564
+ it('triggers proactive compaction at 85-95% utilization', async () => {
565
+ const maxContextTokens = 10000;
566
+ const currentTokens = 9000; // 90%
567
+ const utilization = (currentTokens / maxContextTokens) * 100;
568
+
569
+ expect(utilization).toBeGreaterThan(85);
570
+ expect(utilization).toBeLessThan(95);
571
+
572
+ // Should trigger proactive compaction
573
+ const messages = buildConversation(20, 200);
574
+ const result = await summarize(messages, mockSummarizeCallback, {
575
+ tokenCounter: simpleTokenCounter,
576
+ });
577
+
578
+ expect(result.summary.length).toBeGreaterThan(0);
579
+ // After compaction, utilization should drop significantly
580
+ const compactedTokens = Math.ceil(result.summary.length / 4) + 500; // summary + last few messages
581
+ const newUtilization = (compactedTokens / maxContextTokens) * 100;
582
+ expect(newUtilization).toBeLessThan(50);
583
+ });
584
+
585
+ it('triggers emergency compaction at >95% utilization', async () => {
586
+ const maxContextTokens = 10000;
587
+ const currentTokens = 9600; // 96%
588
+ const utilization = (currentTokens / maxContextTokens) * 100;
589
+
590
+ expect(utilization).toBeGreaterThan(95);
591
+
592
+ // Emergency: no LLM call, pure extraction
593
+ const messages = buildConversation(30, 300);
594
+ const emergency = createEmergencySummary(messages);
595
+ expect(emergency).toBeTruthy();
596
+ expect(emergency.length).toBeLessThan(2000); // Emergency summaries are compact
597
+ });
598
+
599
+ it('injects delegation hint at >70% utilization for agents with task tool', () => {
600
+ const utilization = 75;
601
+ const hasTaskTool = true;
602
+
603
+ if (utilization > 70 && hasTaskTool) {
604
+ const delegationHint = new HumanMessage({
605
+ content:
606
+ '[System] Context window is at 75% capacity. Consider delegating complex sub-tasks ' +
607
+ 'to the task tool to maintain context availability.',
608
+ });
609
+ expect(delegationHint.content).toContain('75%');
610
+ expect(delegationHint.content).toContain('task tool');
611
+ }
612
+ });
613
+
614
+ it('does not inject delegation hint below 70%', () => {
615
+ const utilization = 65;
616
+ let delegationInjected = false;
617
+
618
+ if (utilization > 70) {
619
+ delegationInjected = true;
620
+ }
621
+
622
+ expect(delegationInjected).toBe(false);
623
+ });
624
+ });
625
+
626
+ // ============================================================================
627
+ // 6. Emergency Context Preservation (First+Last Pair)
628
+ // ============================================================================
629
+
630
+ describe('Emergency context preservation', () => {
631
+ it('preserves first user message and last AI message from 50-turn conversation', () => {
632
+ const messages = buildConversation(50, 200);
633
+ const emergency = createEmergencySummary(messages);
634
+
635
+ // Should contain first user intent
636
+ expect(emergency).toContain('User message 0');
637
+ // Should contain last AI state
638
+ expect(emergency).toContain('AI response 49');
639
+ // Should report correct count
640
+ expect(emergency).toContain('Messages compacted: 100');
641
+ });
642
+
643
+ it('captures tool names in emergency summary', () => {
644
+ const messages: BaseMessage[] = [
645
+ new HumanMessage({ content: 'Search for revenue data' }),
646
+ new ToolMessage({
647
+ content: 'Found 5 documents',
648
+ tool_call_id: 'tc_1',
649
+ name: 'file_search',
650
+ }),
651
+ new ToolMessage({
652
+ content: 'Web results for Q4',
653
+ tool_call_id: 'tc_2',
654
+ name: 'web_search',
655
+ }),
656
+ new ToolMessage({
657
+ content: 'Code executed successfully',
658
+ tool_call_id: 'tc_3',
659
+ name: 'code_execution',
660
+ }),
661
+ new AIMessage({ content: 'Analysis complete' }),
662
+ ];
663
+
664
+ const emergency = createEmergencySummary(messages);
665
+ expect(emergency).toContain('file_search');
666
+ expect(emergency).toContain('web_search');
667
+ expect(emergency).toContain('code_execution');
668
+ });
669
+
670
+ it('emergency summary never throws even with malformed messages', () => {
671
+ const weirdMessages: BaseMessage[] = [
672
+ new HumanMessage({ content: '' }), // Empty
673
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
674
+ new AIMessage({ content: [{ type: 'text', text: '' }] as any }), // Complex empty
675
+ new SystemMessage({ content: 'system' }),
676
+ ];
677
+
678
+ expect(() => createEmergencySummary(weirdMessages)).not.toThrow();
679
+ const result = createEmergencySummary(weirdMessages);
680
+ expect(typeof result).toBe('string');
681
+ });
682
+
683
+ it('preserves context even when all intermediate messages are removed', async () => {
684
+ const messages: BaseMessage[] = [
685
+ new HumanMessage({
686
+ content: 'CRITICAL: Build the authentication system for the app',
687
+ }),
688
+ ...buildConversation(40, 300), // 40 turns of intermediate work
689
+ new HumanMessage({ content: 'Now deploy to production' }),
690
+ new AIMessage({
691
+ content: 'Deploying the authentication system to AWS ECS...',
692
+ }),
693
+ ];
694
+
695
+ const emergency = createEmergencySummary(messages);
696
+ // First user message preserved
697
+ expect(emergency).toContain('authentication system');
698
+ // Last AI response preserved
699
+ expect(emergency).toContain('Deploying');
700
+ });
701
+ });
702
+
703
+ // ============================================================================
704
+ // 7. Multi-Agent Context Handoff Scenarios
705
+ // ============================================================================
706
+
707
+ describe('Multi-agent context handoff scenarios', () => {
708
+ it('research agent → writing agent handoff preserves findings', async () => {
709
+ const researchMessages: BaseMessage[] = [
710
+ new HumanMessage({
711
+ content: 'Research competitors: Acme Corp, Beta Inc, Gamma Ltd',
712
+ }),
713
+ new ToolMessage({
714
+ content: 'Acme Corp: $50M revenue, 200 employees',
715
+ tool_call_id: 'ws_1',
716
+ name: 'web_search',
717
+ }),
718
+ new ToolMessage({
719
+ content: 'Beta Inc: $30M revenue, 150 employees',
720
+ tool_call_id: 'ws_2',
721
+ name: 'web_search',
722
+ }),
723
+ new AIMessage({
724
+ content:
725
+ 'Found competitive data: Acme leads with $50M, Beta at $30M, Gamma data unavailable.',
726
+ }),
727
+ ];
728
+
729
+ // Summarize for handoff
730
+ const result = await summarize(researchMessages, mockSummarizeCallback, {
731
+ tokenCounter: simpleTokenCounter,
732
+ });
733
+
734
+ expect(result.tier).toBe('full');
735
+ expect(result.messagesCompacted).toBe(4);
736
+
737
+ // Writing agent receives the summary
738
+ const writingContext = [
739
+ new SystemMessage({
740
+ content: `[Handoff from Research Agent]\n${result.summary}\n\nYou are the Writing Agent. Create a report based on the research above.`,
741
+ }),
742
+ ];
743
+
744
+ const writingTokens = writingContext.reduce(
745
+ (sum, m) => sum + simpleTokenCounter(m),
746
+ 0
747
+ );
748
+ expect(writingTokens).toBeLessThan(2000);
749
+ });
750
+
751
+ it('handles cascade handoff: A → B → C → A (circular)', async () => {
752
+ // A → B handoff
753
+ const summaryAB = await summarize(
754
+ buildConversation(5, 200),
755
+ mockSummarizeCallback,
756
+ {
757
+ tokenCounter: simpleTokenCounter,
758
+ }
759
+ );
760
+
761
+ // B → C handoff
762
+ const summaryBC = await summarize(
763
+ [
764
+ new SystemMessage({ content: `[From A]\n${summaryAB.summary}` }),
765
+ ...buildConversation(3, 200),
766
+ ],
767
+ mockSummarizeCallback,
768
+ { tokenCounter: simpleTokenCounter }
769
+ );
770
+
771
+ // C → A handoff (back to original)
772
+ const summaryCA = await summarize(
773
+ [
774
+ new SystemMessage({ content: `[From B via A]\n${summaryBC.summary}` }),
775
+ ...buildConversation(3, 200),
776
+ ],
777
+ mockSummarizeCallback,
778
+ { tokenCounter: simpleTokenCounter }
779
+ );
780
+
781
+ // All summaries should exist and be compact
782
+ expect(summaryAB.summary.length).toBeGreaterThan(0);
783
+ expect(summaryBC.summary.length).toBeGreaterThan(0);
784
+ expect(summaryCA.summary.length).toBeGreaterThan(0);
785
+
786
+ // Final summary shouldn't have exploded in size
787
+ const finalTokens = Math.ceil(summaryCA.summary.length / 4);
788
+ expect(finalTokens).toBeLessThan(1000);
789
+ });
790
+
791
+ it('multi-agent workflow state is included in full summary prompt', () => {
792
+ const messages: BaseMessage[] = [
793
+ new HumanMessage({ content: 'Start multi-agent research' }),
794
+ new AIMessage({ content: 'Delegating to specialized agents.' }),
795
+ ];
796
+
797
+ const formatted = formatMessagesForSummary(messages);
798
+ const prompt = buildFullSummaryPrompt(formatted, {
799
+ isMultiAgent: true,
800
+ agentWorkflowState: {
801
+ currentAgentId: 'analysis-agent',
802
+ agentChain: ['research-agent', 'analysis-agent'],
803
+ pendingAgents: ['writing-agent'],
804
+ },
805
+ });
806
+
807
+ expect(prompt).toContain('analysis-agent');
808
+ expect(prompt).toContain('research-agent');
809
+ expect(prompt).toContain('writing-agent');
810
+ expect(prompt).toContain('Agent Workflow State');
811
+ });
812
+ });
813
+
814
+ // ============================================================================
815
+ // 8. summaryModel Dedicated Cheap Model Usage
816
+ // ============================================================================
817
+
818
+ describe('summaryModel dedicated cheap model usage', () => {
819
+ it('summarize passes maxOutputTokens to callback for model configuration', async () => {
820
+ let capturedMaxTokens: number | undefined;
821
+
822
+ const trackingCallback = async (
823
+ prompt: string,
824
+ maxTokens: number
825
+ ): Promise<string> => {
826
+ capturedMaxTokens = maxTokens;
827
+ return '[Summary] Tracked callback.';
828
+ };
829
+
830
+ await summarize(buildConversation(5, 200), trackingCallback, {
831
+ tokenCounter: simpleTokenCounter,
832
+ maxOutputTokens: 2048,
833
+ });
834
+
835
+ expect(capturedMaxTokens).toBe(2048);
836
+ });
837
+
838
+ it('Tier 2 uses lower maxTokens (512) than Tier 1', async () => {
839
+ const capturedMaxTokens: number[] = [];
840
+ let callCount = 0;
841
+
842
+ const tieredCallback = async (
843
+ prompt: string,
844
+ maxTokens: number
845
+ ): Promise<string> => {
846
+ capturedMaxTokens.push(maxTokens);
847
+ callCount++;
848
+ if (callCount === 1) {
849
+ throw new Error('Tier 1 failed'); // Force fallback to Tier 2
850
+ }
851
+ return '[Simple Summary]';
852
+ };
853
+
854
+ await summarize(buildConversation(5, 200), tieredCallback, {
855
+ tokenCounter: simpleTokenCounter,
856
+ maxOutputTokens: 1024,
857
+ });
858
+
859
+ // Tier 1 tried with 1024, Tier 2 tried with 512
860
+ expect(capturedMaxTokens[0]).toBe(1024);
861
+ expect(capturedMaxTokens[1]).toBe(512);
862
+ });
863
+
864
+ it('summaryModel config follows titleModel pattern', () => {
865
+ // Verify the config structure matches expectations
866
+ const endpointConfig = {
867
+ titleModel: 'us.amazon.nova-micro-v1:0',
868
+ summaryModel: 'us.anthropic.claude-haiku-4-5-20251001-v1:0',
869
+ modelDisplayLabel: 'Ranger',
870
+ };
871
+
872
+ // summaryModel should be a different, cheaper model than the main model
873
+ expect(endpointConfig.summaryModel).not.toBe(endpointConfig.titleModel);
874
+ expect(endpointConfig.summaryModel).toContain('haiku'); // Cheap model
875
+ });
876
+
877
+ it('falls back through provider defaults when no summaryModel configured', () => {
878
+ const providers = [
879
+ { name: 'bedrock', expected: 'claude-3-haiku-20240307' },
880
+ { name: 'anthropic', expected: 'claude-3-haiku-20240307' },
881
+ { name: 'openAI', expected: 'gpt-4o-mini' },
882
+ { name: 'google', expected: 'gemini-2.0-flash' },
883
+ { name: 'unknown', expected: 'claude-3-haiku-20240307' },
884
+ ];
885
+
886
+ for (const { name, expected } of providers) {
887
+ let summaryModel: string;
888
+ if (name === 'bedrock' || name === 'anthropic') {
889
+ summaryModel = 'claude-3-haiku-20240307';
890
+ } else if (name === 'openAI' || name === 'azureOpenAI') {
891
+ summaryModel = 'gpt-4o-mini';
892
+ } else if (name === 'google') {
893
+ summaryModel = 'gemini-2.0-flash';
894
+ } else {
895
+ summaryModel = 'claude-3-haiku-20240307';
896
+ }
897
+ expect(summaryModel).toBe(expected);
898
+ }
899
+ });
900
+ });
901
+
902
+ // ============================================================================
903
+ // 9. Config Wiring Validation
904
+ // ============================================================================
905
+
906
+ describe('Config wiring validation', () => {
907
+ it('contextManagement config has all required fields', () => {
908
+ const config = {
909
+ compactMode: 'auto',
910
+ recoveryMode: 'summarize',
911
+ continuationRetries: 1,
912
+ toolResultBudgetPct: 0.3,
913
+ subagentMaxResultTokens: 8192,
914
+ chainRollingSummary: false,
915
+ fileReadDedup: true,
916
+ compactionAudit: true,
917
+ };
918
+
919
+ // All fields present
920
+ expect(config.compactMode).toBeDefined();
921
+ expect(config.recoveryMode).toBeDefined();
922
+ expect(config.continuationRetries).toBeDefined();
923
+ expect(config.toolResultBudgetPct).toBeDefined();
924
+ expect(config.subagentMaxResultTokens).toBeDefined();
925
+ expect(config.chainRollingSummary).toBeDefined();
926
+ expect(config.fileReadDedup).toBeDefined();
927
+ expect(config.compactionAudit).toBeDefined();
928
+ });
929
+
930
+ it('subagentMaxResultTokens converts to chars correctly', () => {
931
+ const tokenValues = [4096, 8192, 16384, 32768];
932
+ for (const tokens of tokenValues) {
933
+ const chars = tokens * 4;
934
+ expect(chars).toBe(tokens * 4);
935
+ // Chars should be reasonable (not exceeding 200K chars)
936
+ expect(chars).toBeLessThan(200000);
937
+ }
938
+ });
939
+
940
+ it('compactMode values are valid', () => {
941
+ const validModes = ['auto', 'summarize', 'prune'];
942
+ for (const mode of validModes) {
943
+ expect(['auto', 'summarize', 'prune']).toContain(mode);
944
+ }
945
+ });
946
+
947
+ it('recoveryMode values are valid', () => {
948
+ const validModes = ['summarize', 'prune', 'emergency'];
949
+ for (const mode of validModes) {
950
+ expect(['summarize', 'prune', 'emergency']).toContain(mode);
951
+ }
952
+ });
953
+ });
954
+
955
+ // ============================================================================
956
+ // 10. Stress Tests: Large Conversations
957
+ // ============================================================================
958
+
959
+ describe('Stress tests with large conversations', () => {
960
+ it('handles 200-turn conversation summarization', async () => {
961
+ const messages = buildConversation(200, 100); // 400 messages
962
+ expect(messages.length).toBe(400);
963
+
964
+ const result = await summarize(messages, mockSummarizeCallback, {
965
+ tokenCounter: simpleTokenCounter,
966
+ });
967
+
968
+ expect(result.summary.length).toBeGreaterThan(0);
969
+ expect(result.messagesCompacted).toBe(400);
970
+ });
971
+
972
+ it('emergency summary from 500-turn conversation is still compact', () => {
973
+ const messages = buildConversation(500, 50); // 1000 messages
974
+ const emergency = createEmergencySummary(messages);
975
+
976
+ // Emergency summary should be compact regardless of input size
977
+ expect(emergency.length).toBeLessThan(3000);
978
+ expect(emergency).toContain('Messages compacted: 1000');
979
+ });
980
+
981
+ it('getContextUtilization handles 1000-message token map', () => {
982
+ const map: Record<string, number> = {};
983
+ for (let i = 0; i < 1000; i++) {
984
+ map[String(i)] = 100;
985
+ }
986
+ const result = getContextUtilization(map, 500, 200000);
987
+ // 1000 * 100 + 500 = 100500 / 200000 = 50.25%
988
+ expect(result).toBeCloseTo(50.25, 1);
989
+ });
990
+ });