@illuma-ai/agents 1.5.0 → 2.1.1

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 (424) hide show
  1. package/README.md +0 -62
  2. package/dist/cjs/agents/AgentContext.cjs +159 -258
  3. package/dist/cjs/agents/AgentContext.cjs.map +1 -1
  4. package/dist/cjs/graphs/Graph.cjs +25 -8
  5. package/dist/cjs/graphs/Graph.cjs.map +1 -1
  6. package/dist/cjs/llm/anthropic/utils/message_inputs.cjs +1 -5
  7. package/dist/cjs/llm/anthropic/utils/message_inputs.cjs.map +1 -1
  8. package/dist/cjs/llm/bedrock/index.cjs +33 -61
  9. package/dist/cjs/llm/bedrock/index.cjs.map +1 -1
  10. package/dist/cjs/llm/openai/utils/index.cjs +10 -27
  11. package/dist/cjs/llm/openai/utils/index.cjs.map +1 -1
  12. package/dist/cjs/main.cjs +3 -84
  13. package/dist/cjs/main.cjs.map +1 -1
  14. package/dist/cjs/messages/cache.cjs +0 -89
  15. package/dist/cjs/messages/cache.cjs.map +1 -1
  16. package/dist/cjs/messages/format.cjs +10 -68
  17. package/dist/cjs/messages/format.cjs.map +1 -1
  18. package/dist/cjs/tools/BashExecutor.cjs +11 -21
  19. package/dist/cjs/tools/BashExecutor.cjs.map +1 -1
  20. package/dist/cjs/tools/CodeExecutor.cjs +10 -37
  21. package/dist/cjs/tools/CodeExecutor.cjs.map +1 -1
  22. package/dist/cjs/tools/ProgrammaticToolCalling.cjs +11 -16
  23. package/dist/cjs/tools/ProgrammaticToolCalling.cjs.map +1 -1
  24. package/dist/cjs/tools/ToolNode.cjs +73 -8
  25. package/dist/cjs/tools/ToolNode.cjs.map +1 -1
  26. package/dist/cjs/tools/search/search.cjs +3 -11
  27. package/dist/cjs/tools/search/search.cjs.map +1 -1
  28. package/dist/cjs/tools/search/tool.cjs +4 -28
  29. package/dist/cjs/tools/search/tool.cjs.map +1 -1
  30. package/dist/cjs/tools/search/utils.cjs +3 -10
  31. package/dist/cjs/tools/search/utils.cjs.map +1 -1
  32. package/dist/cjs/tools/subagent/SubagentExecutor.cjs +48 -0
  33. package/dist/cjs/tools/subagent/SubagentExecutor.cjs.map +1 -1
  34. package/dist/cjs/types/graph.cjs.map +1 -1
  35. package/dist/esm/agents/AgentContext.mjs +159 -258
  36. package/dist/esm/agents/AgentContext.mjs.map +1 -1
  37. package/dist/esm/graphs/Graph.mjs +25 -8
  38. package/dist/esm/graphs/Graph.mjs.map +1 -1
  39. package/dist/esm/llm/anthropic/utils/message_inputs.mjs +1 -5
  40. package/dist/esm/llm/anthropic/utils/message_inputs.mjs.map +1 -1
  41. package/dist/esm/llm/bedrock/index.mjs +34 -61
  42. package/dist/esm/llm/bedrock/index.mjs.map +1 -1
  43. package/dist/esm/llm/openai/utils/index.mjs +10 -27
  44. package/dist/esm/llm/openai/utils/index.mjs.map +1 -1
  45. package/dist/esm/main.mjs +1 -5
  46. package/dist/esm/main.mjs.map +1 -1
  47. package/dist/esm/messages/cache.mjs +0 -89
  48. package/dist/esm/messages/cache.mjs.map +1 -1
  49. package/dist/esm/messages/format.mjs +10 -68
  50. package/dist/esm/messages/format.mjs.map +1 -1
  51. package/dist/esm/tools/BashExecutor.mjs +12 -22
  52. package/dist/esm/tools/BashExecutor.mjs.map +1 -1
  53. package/dist/esm/tools/CodeExecutor.mjs +11 -37
  54. package/dist/esm/tools/CodeExecutor.mjs.map +1 -1
  55. package/dist/esm/tools/ProgrammaticToolCalling.mjs +12 -17
  56. package/dist/esm/tools/ProgrammaticToolCalling.mjs.map +1 -1
  57. package/dist/esm/tools/ToolNode.mjs +73 -8
  58. package/dist/esm/tools/ToolNode.mjs.map +1 -1
  59. package/dist/esm/tools/search/search.mjs +3 -11
  60. package/dist/esm/tools/search/search.mjs.map +1 -1
  61. package/dist/esm/tools/search/tool.mjs +4 -28
  62. package/dist/esm/tools/search/tool.mjs.map +1 -1
  63. package/dist/esm/tools/search/utils.mjs +3 -10
  64. package/dist/esm/tools/search/utils.mjs.map +1 -1
  65. package/dist/esm/tools/subagent/SubagentExecutor.mjs +48 -0
  66. package/dist/esm/tools/subagent/SubagentExecutor.mjs.map +1 -1
  67. package/dist/esm/types/graph.mjs.map +1 -1
  68. package/dist/types/agents/AgentContext.d.ts +25 -95
  69. package/dist/types/index.d.ts +0 -1
  70. package/dist/types/llm/bedrock/index.d.ts +1 -54
  71. package/dist/types/messages/format.d.ts +1 -4
  72. package/dist/types/tools/CodeExecutor.d.ts +0 -6
  73. package/dist/types/tools/search/types.d.ts +5 -99
  74. package/dist/types/tools/search/utils.d.ts +2 -2
  75. package/dist/types/tools/subagent/SubagentExecutor.d.ts +29 -0
  76. package/dist/types/types/graph.d.ts +24 -27
  77. package/dist/types/types/index.d.ts +0 -1
  78. package/dist/types/types/run.d.ts +0 -2
  79. package/dist/types/types/tools.d.ts +0 -9
  80. package/package.json +1 -61
  81. package/src/agents/AgentContext.test.ts +176 -0
  82. package/src/agents/AgentContext.ts +178 -304
  83. package/src/agents/__tests__/AgentContext.test.ts +0 -632
  84. package/src/graphs/Graph.ts +27 -8
  85. package/src/index.ts +0 -6
  86. package/src/llm/anthropic/utils/message_inputs.ts +1 -10
  87. package/src/llm/bedrock/__tests__/bedrock-caching.test.ts +18 -166
  88. package/src/llm/bedrock/index.ts +41 -116
  89. package/src/llm/openai/utils/index.ts +14 -31
  90. package/src/messages/cache.test.ts +24 -62
  91. package/src/messages/cache.ts +0 -112
  92. package/src/messages/format.ts +10 -89
  93. package/src/scripts/subagent-configurable-inheritance.ts +263 -0
  94. package/src/specs/anthropic.simple.test.ts +0 -61
  95. package/src/tools/BashExecutor.ts +13 -37
  96. package/src/tools/CodeExecutor.ts +11 -55
  97. package/src/tools/ProgrammaticToolCalling.ts +14 -29
  98. package/src/tools/ToolNode.ts +69 -8
  99. package/src/tools/__tests__/ProgrammaticToolCalling.test.ts +0 -60
  100. package/src/tools/__tests__/SubagentExecutor.test.ts +157 -0
  101. package/src/tools/search/search.ts +2 -12
  102. package/src/tools/search/tool.ts +2 -36
  103. package/src/tools/search/types.ts +8 -133
  104. package/src/tools/search/utils.ts +5 -13
  105. package/src/tools/subagent/SubagentExecutor.ts +78 -0
  106. package/src/types/graph.ts +21 -27
  107. package/src/types/index.ts +0 -1
  108. package/src/types/run.ts +0 -2
  109. package/src/types/tools.ts +0 -9
  110. package/dist/cjs/langchain/google-common.cjs +0 -3
  111. package/dist/cjs/langchain/google-common.cjs.map +0 -1
  112. package/dist/cjs/langchain/index.cjs +0 -86
  113. package/dist/cjs/langchain/index.cjs.map +0 -1
  114. package/dist/cjs/langchain/language_models/chat_models.cjs +0 -3
  115. package/dist/cjs/langchain/language_models/chat_models.cjs.map +0 -1
  116. package/dist/cjs/langchain/messages/tool.cjs +0 -3
  117. package/dist/cjs/langchain/messages/tool.cjs.map +0 -1
  118. package/dist/cjs/langchain/messages.cjs +0 -51
  119. package/dist/cjs/langchain/messages.cjs.map +0 -1
  120. package/dist/cjs/langchain/openai.cjs +0 -3
  121. package/dist/cjs/langchain/openai.cjs.map +0 -1
  122. package/dist/cjs/langchain/prompts.cjs +0 -11
  123. package/dist/cjs/langchain/prompts.cjs.map +0 -1
  124. package/dist/cjs/langchain/runnables.cjs +0 -19
  125. package/dist/cjs/langchain/runnables.cjs.map +0 -1
  126. package/dist/cjs/langchain/tools.cjs +0 -23
  127. package/dist/cjs/langchain/tools.cjs.map +0 -1
  128. package/dist/cjs/langchain/utils/env.cjs +0 -11
  129. package/dist/cjs/langchain/utils/env.cjs.map +0 -1
  130. package/dist/cjs/llm/bedrock/cacheSupport.cjs +0 -55
  131. package/dist/cjs/llm/bedrock/cacheSupport.cjs.map +0 -1
  132. package/dist/cjs/tools/search/tavily-scraper.cjs +0 -189
  133. package/dist/cjs/tools/search/tavily-scraper.cjs.map +0 -1
  134. package/dist/cjs/tools/search/tavily-search.cjs +0 -372
  135. package/dist/cjs/tools/search/tavily-search.cjs.map +0 -1
  136. package/dist/cjs/types/agent-cache.cjs +0 -53
  137. package/dist/cjs/types/agent-cache.cjs.map +0 -1
  138. package/dist/esm/langchain/google-common.mjs +0 -2
  139. package/dist/esm/langchain/google-common.mjs.map +0 -1
  140. package/dist/esm/langchain/index.mjs +0 -5
  141. package/dist/esm/langchain/index.mjs.map +0 -1
  142. package/dist/esm/langchain/language_models/chat_models.mjs +0 -2
  143. package/dist/esm/langchain/language_models/chat_models.mjs.map +0 -1
  144. package/dist/esm/langchain/messages/tool.mjs +0 -2
  145. package/dist/esm/langchain/messages/tool.mjs.map +0 -1
  146. package/dist/esm/langchain/messages.mjs +0 -2
  147. package/dist/esm/langchain/messages.mjs.map +0 -1
  148. package/dist/esm/langchain/openai.mjs +0 -2
  149. package/dist/esm/langchain/openai.mjs.map +0 -1
  150. package/dist/esm/langchain/prompts.mjs +0 -2
  151. package/dist/esm/langchain/prompts.mjs.map +0 -1
  152. package/dist/esm/langchain/runnables.mjs +0 -2
  153. package/dist/esm/langchain/runnables.mjs.map +0 -1
  154. package/dist/esm/langchain/tools.mjs +0 -2
  155. package/dist/esm/langchain/tools.mjs.map +0 -1
  156. package/dist/esm/langchain/utils/env.mjs +0 -2
  157. package/dist/esm/langchain/utils/env.mjs.map +0 -1
  158. package/dist/esm/llm/bedrock/cacheSupport.mjs +0 -52
  159. package/dist/esm/llm/bedrock/cacheSupport.mjs.map +0 -1
  160. package/dist/esm/tools/search/tavily-scraper.mjs +0 -186
  161. package/dist/esm/tools/search/tavily-scraper.mjs.map +0 -1
  162. package/dist/esm/tools/search/tavily-search.mjs +0 -370
  163. package/dist/esm/tools/search/tavily-search.mjs.map +0 -1
  164. package/dist/esm/types/agent-cache.mjs +0 -51
  165. package/dist/esm/types/agent-cache.mjs.map +0 -1
  166. package/dist/types/langchain/google-common.d.ts +0 -1
  167. package/dist/types/langchain/index.d.ts +0 -8
  168. package/dist/types/langchain/language_models/chat_models.d.ts +0 -1
  169. package/dist/types/langchain/messages/tool.d.ts +0 -1
  170. package/dist/types/langchain/messages.d.ts +0 -2
  171. package/dist/types/langchain/openai.d.ts +0 -1
  172. package/dist/types/langchain/prompts.d.ts +0 -1
  173. package/dist/types/langchain/runnables.d.ts +0 -2
  174. package/dist/types/langchain/tools.d.ts +0 -2
  175. package/dist/types/langchain/utils/env.d.ts +0 -1
  176. package/dist/types/llm/bedrock/cacheSupport.d.ts +0 -35
  177. package/dist/types/tools/search/tavily-scraper.d.ts +0 -19
  178. package/dist/types/tools/search/tavily-search.d.ts +0 -4
  179. package/dist/types/tools/subagent/types.d.ts +0 -84
  180. package/dist/types/types/agent-cache.d.ts +0 -70
  181. package/src/agents/AgentContext.js.map +0 -1
  182. package/src/agents/AgentContext.test.js.map +0 -1
  183. package/src/agents/__tests__/AgentContext.cacheTtl.live.test.ts +0 -259
  184. package/src/agents/__tests__/AgentContext.crossAgentTier1.live.test.ts +0 -264
  185. package/src/agents/__tests__/AgentContext.crossUserCache.live.test.ts +0 -342
  186. package/src/agents/__tests__/AgentContext.test.js.map +0 -1
  187. package/src/agents/__tests__/resolveStructuredOutputMode.test.js.map +0 -1
  188. package/src/common/enum.js.map +0 -1
  189. package/src/common/index.js.map +0 -1
  190. package/src/events.js.map +0 -1
  191. package/src/graphs/Graph.js.map +0 -1
  192. package/src/graphs/MultiAgentGraph.js.map +0 -1
  193. package/src/graphs/__tests__/structured-output.integration.test.js.map +0 -1
  194. package/src/graphs/__tests__/structured-output.test.js.map +0 -1
  195. package/src/graphs/contextManagement.e2e.test.js.map +0 -1
  196. package/src/graphs/contextManagement.test.js.map +0 -1
  197. package/src/graphs/handoffValidation.test.js.map +0 -1
  198. package/src/graphs/index.js.map +0 -1
  199. package/src/index.js.map +0 -1
  200. package/src/instrumentation.js.map +0 -1
  201. package/src/langchain/google-common.ts +0 -1
  202. package/src/langchain/index.ts +0 -8
  203. package/src/langchain/language_models/chat_models.ts +0 -1
  204. package/src/langchain/messages/tool.ts +0 -5
  205. package/src/langchain/messages.ts +0 -21
  206. package/src/langchain/openai.ts +0 -1
  207. package/src/langchain/prompts.ts +0 -1
  208. package/src/langchain/runnables.ts +0 -7
  209. package/src/langchain/tools.ts +0 -8
  210. package/src/langchain/utils/env.ts +0 -1
  211. package/src/llm/anthropic/index.js.map +0 -1
  212. package/src/llm/anthropic/types.js.map +0 -1
  213. package/src/llm/anthropic/utils/message_inputs.js.map +0 -1
  214. package/src/llm/anthropic/utils/message_outputs.js.map +0 -1
  215. package/src/llm/anthropic/utils/output_parsers.js.map +0 -1
  216. package/src/llm/anthropic/utils/server-tool-inputs.test.ts +0 -436
  217. package/src/llm/anthropic/utils/tools.js.map +0 -1
  218. package/src/llm/bedrock/__tests__/bedrock-caching.test.js.map +0 -1
  219. package/src/llm/bedrock/cacheSupport.test.ts +0 -99
  220. package/src/llm/bedrock/cacheSupport.ts +0 -53
  221. package/src/llm/bedrock/index.js.map +0 -1
  222. package/src/llm/bedrock/types.js.map +0 -1
  223. package/src/llm/bedrock/utils/index.js.map +0 -1
  224. package/src/llm/bedrock/utils/message_inputs.js.map +0 -1
  225. package/src/llm/bedrock/utils/message_outputs.js.map +0 -1
  226. package/src/llm/fake.js.map +0 -1
  227. package/src/llm/google/index.js.map +0 -1
  228. package/src/llm/google/types.js.map +0 -1
  229. package/src/llm/google/utils/common.js.map +0 -1
  230. package/src/llm/google/utils/tools.js.map +0 -1
  231. package/src/llm/google/utils/zod_to_genai_parameters.js.map +0 -1
  232. package/src/llm/openai/index.js.map +0 -1
  233. package/src/llm/openai/types.js.map +0 -1
  234. package/src/llm/openai/utils/index.js.map +0 -1
  235. package/src/llm/openai/utils/isReasoningModel.test.js.map +0 -1
  236. package/src/llm/openrouter/index.js.map +0 -1
  237. package/src/llm/openrouter/reasoning.test.js.map +0 -1
  238. package/src/llm/providers.js.map +0 -1
  239. package/src/llm/text.js.map +0 -1
  240. package/src/llm/vertexai/index.js.map +0 -1
  241. package/src/messages/__tests__/tools.test.js.map +0 -1
  242. package/src/messages/cache.js.map +0 -1
  243. package/src/messages/cache.test.js.map +0 -1
  244. package/src/messages/content.js.map +0 -1
  245. package/src/messages/content.test.js.map +0 -1
  246. package/src/messages/core.js.map +0 -1
  247. package/src/messages/ensureThinkingBlock.test.js.map +0 -1
  248. package/src/messages/format.js.map +0 -1
  249. package/src/messages/formatAgentMessages.test.js.map +0 -1
  250. package/src/messages/formatAgentMessages.tools.test.js.map +0 -1
  251. package/src/messages/formatMessage.test.js.map +0 -1
  252. package/src/messages/ids.js.map +0 -1
  253. package/src/messages/index.js.map +0 -1
  254. package/src/messages/labelContentByAgent.test.js.map +0 -1
  255. package/src/messages/prune.js.map +0 -1
  256. package/src/messages/reducer.js.map +0 -1
  257. package/src/messages/shiftIndexTokenCountMap.test.js.map +0 -1
  258. package/src/messages/summarize.js.map +0 -1
  259. package/src/messages/summarize.test.js.map +0 -1
  260. package/src/messages/tools.js.map +0 -1
  261. package/src/mockStream.js.map +0 -1
  262. package/src/prompts/collab.js.map +0 -1
  263. package/src/prompts/index.js.map +0 -1
  264. package/src/prompts/taskmanager.js.map +0 -1
  265. package/src/run.js.map +0 -1
  266. package/src/schemas/index.js.map +0 -1
  267. package/src/schemas/schema-preparation.test.js.map +0 -1
  268. package/src/schemas/validate.js.map +0 -1
  269. package/src/schemas/validate.test.js.map +0 -1
  270. package/src/scripts/abort.js.map +0 -1
  271. package/src/scripts/ant_web_search.js.map +0 -1
  272. package/src/scripts/ant_web_search_edge_case.js.map +0 -1
  273. package/src/scripts/ant_web_search_error_edge_case.js.map +0 -1
  274. package/src/scripts/args.js.map +0 -1
  275. package/src/scripts/bedrock-cache-debug.js.map +0 -1
  276. package/src/scripts/bedrock-content-aggregation-test.js.map +0 -1
  277. package/src/scripts/bedrock-merge-test.js.map +0 -1
  278. package/src/scripts/bedrock-parallel-tools-test.js.map +0 -1
  279. package/src/scripts/caching.js.map +0 -1
  280. package/src/scripts/cli.js.map +0 -1
  281. package/src/scripts/cli2.js.map +0 -1
  282. package/src/scripts/cli3.js.map +0 -1
  283. package/src/scripts/cli4.js.map +0 -1
  284. package/src/scripts/cli5.js.map +0 -1
  285. package/src/scripts/code_exec.js.map +0 -1
  286. package/src/scripts/code_exec_files.js.map +0 -1
  287. package/src/scripts/code_exec_multi_session.js.map +0 -1
  288. package/src/scripts/code_exec_ptc.js.map +0 -1
  289. package/src/scripts/code_exec_session.js.map +0 -1
  290. package/src/scripts/code_exec_simple.js.map +0 -1
  291. package/src/scripts/content.js.map +0 -1
  292. package/src/scripts/empty_input.js.map +0 -1
  293. package/src/scripts/handoff-test.js.map +0 -1
  294. package/src/scripts/image.js.map +0 -1
  295. package/src/scripts/memory.js.map +0 -1
  296. package/src/scripts/multi-agent-chain.js.map +0 -1
  297. package/src/scripts/multi-agent-conditional.js.map +0 -1
  298. package/src/scripts/multi-agent-document-review-chain.js.map +0 -1
  299. package/src/scripts/multi-agent-hybrid-flow.js.map +0 -1
  300. package/src/scripts/multi-agent-parallel-start.js.map +0 -1
  301. package/src/scripts/multi-agent-parallel.js.map +0 -1
  302. package/src/scripts/multi-agent-sequence.js.map +0 -1
  303. package/src/scripts/multi-agent-supervisor.js.map +0 -1
  304. package/src/scripts/multi-agent-test.js.map +0 -1
  305. package/src/scripts/parallel-asymmetric-tools-test.js.map +0 -1
  306. package/src/scripts/parallel-full-metadata-test.js.map +0 -1
  307. package/src/scripts/parallel-tools-test.js.map +0 -1
  308. package/src/scripts/programmatic_exec.js.map +0 -1
  309. package/src/scripts/programmatic_exec_agent.js.map +0 -1
  310. package/src/scripts/search.js.map +0 -1
  311. package/src/scripts/sequential-full-metadata-test.js.map +0 -1
  312. package/src/scripts/simple.js.map +0 -1
  313. package/src/scripts/single-agent-metadata-test.js.map +0 -1
  314. package/src/scripts/stream.js.map +0 -1
  315. package/src/scripts/test-custom-prompt-key.js.map +0 -1
  316. package/src/scripts/test-handoff-input.js.map +0 -1
  317. package/src/scripts/test-handoff-preamble.js.map +0 -1
  318. package/src/scripts/test-handoff-steering.js.map +0 -1
  319. package/src/scripts/test-multi-agent-list-handoff.js.map +0 -1
  320. package/src/scripts/test-parallel-agent-labeling.js.map +0 -1
  321. package/src/scripts/test-parallel-handoffs.js.map +0 -1
  322. package/src/scripts/test-thinking-handoff-bedrock.js.map +0 -1
  323. package/src/scripts/test-thinking-handoff.js.map +0 -1
  324. package/src/scripts/test-thinking-to-thinking-handoff-bedrock.js.map +0 -1
  325. package/src/scripts/test-tool-before-handoff-role-order.js.map +0 -1
  326. package/src/scripts/test-tools-before-handoff.js.map +0 -1
  327. package/src/scripts/test_code_api.js.map +0 -1
  328. package/src/scripts/thinking-bedrock.js.map +0 -1
  329. package/src/scripts/thinking-vertexai.js.map +0 -1
  330. package/src/scripts/thinking.js.map +0 -1
  331. package/src/scripts/tool_search.js.map +0 -1
  332. package/src/scripts/tools.js.map +0 -1
  333. package/src/specs/agent-handoffs-bedrock.integration.test.js.map +0 -1
  334. package/src/specs/agent-handoffs.test.js.map +0 -1
  335. package/src/specs/anthropic.simple.test.js.map +0 -1
  336. package/src/specs/azure.simple.test.js.map +0 -1
  337. package/src/specs/cache.simple.test.js.map +0 -1
  338. package/src/specs/custom-event-await.test.js.map +0 -1
  339. package/src/specs/deepseek.simple.test.js.map +0 -1
  340. package/src/specs/emergency-prune.test.js.map +0 -1
  341. package/src/specs/moonshot.simple.test.js.map +0 -1
  342. package/src/specs/observability.integration.test.js.map +0 -1
  343. package/src/specs/openai.simple.test.js.map +0 -1
  344. package/src/specs/openrouter.simple.test.js.map +0 -1
  345. package/src/specs/prune.test.js.map +0 -1
  346. package/src/specs/reasoning.test.js.map +0 -1
  347. package/src/specs/spec.utils.js.map +0 -1
  348. package/src/specs/thinking-handoff.test.js.map +0 -1
  349. package/src/specs/thinking-prune.test.js.map +0 -1
  350. package/src/specs/token-distribution-edge-case.test.js.map +0 -1
  351. package/src/specs/token-memoization.test.js.map +0 -1
  352. package/src/specs/tokens.test.js.map +0 -1
  353. package/src/specs/tool-error.test.js.map +0 -1
  354. package/src/splitStream.js.map +0 -1
  355. package/src/splitStream.test.js.map +0 -1
  356. package/src/stream.js.map +0 -1
  357. package/src/stream.test.js.map +0 -1
  358. package/src/test/mockTools.js.map +0 -1
  359. package/src/tools/BrowserTools.js.map +0 -1
  360. package/src/tools/Calculator.js.map +0 -1
  361. package/src/tools/Calculator.test.js.map +0 -1
  362. package/src/tools/CodeExecutor.js.map +0 -1
  363. package/src/tools/ProgrammaticToolCalling.js.map +0 -1
  364. package/src/tools/StreamingToolCallBuffer.js.map +0 -1
  365. package/src/tools/ToolNode.js.map +0 -1
  366. package/src/tools/ToolSearch.js.map +0 -1
  367. package/src/tools/__tests__/BrowserTools.test.js.map +0 -1
  368. package/src/tools/__tests__/ProgrammaticToolCalling.integration.test.js.map +0 -1
  369. package/src/tools/__tests__/ProgrammaticToolCalling.test.js.map +0 -1
  370. package/src/tools/__tests__/StreamingToolCallBuffer.test.js.map +0 -1
  371. package/src/tools/__tests__/ToolApproval.test.js.map +0 -1
  372. package/src/tools/__tests__/ToolNode.recovery.test.js.map +0 -1
  373. package/src/tools/__tests__/ToolNode.session.test.js.map +0 -1
  374. package/src/tools/__tests__/ToolSearch.integration.test.js.map +0 -1
  375. package/src/tools/__tests__/ToolSearch.test.js.map +0 -1
  376. package/src/tools/__tests__/handlers.test.js.map +0 -1
  377. package/src/tools/__tests__/truncation-recovery.integration.test.js.map +0 -1
  378. package/src/tools/handlers.js.map +0 -1
  379. package/src/tools/schema.js.map +0 -1
  380. package/src/tools/search/anthropic.js.map +0 -1
  381. package/src/tools/search/content.js.map +0 -1
  382. package/src/tools/search/content.test.js.map +0 -1
  383. package/src/tools/search/firecrawl.js.map +0 -1
  384. package/src/tools/search/format.js.map +0 -1
  385. package/src/tools/search/highlights.js.map +0 -1
  386. package/src/tools/search/index.js.map +0 -1
  387. package/src/tools/search/jina-reranker.test.js.map +0 -1
  388. package/src/tools/search/rerankers.js.map +0 -1
  389. package/src/tools/search/schema.js.map +0 -1
  390. package/src/tools/search/search.js.map +0 -1
  391. package/src/tools/search/serper-scraper.js.map +0 -1
  392. package/src/tools/search/tavily-scraper.ts +0 -235
  393. package/src/tools/search/tavily-search.ts +0 -424
  394. package/src/tools/search/tavily.test.ts +0 -965
  395. package/src/tools/search/test.js.map +0 -1
  396. package/src/tools/search/tool.js.map +0 -1
  397. package/src/tools/search/types.js.map +0 -1
  398. package/src/tools/search/utils.js.map +0 -1
  399. package/src/tools/subagent/types.test.ts +0 -70
  400. package/src/tools/subagent/types.ts +0 -115
  401. package/src/types/agent-cache.ts +0 -73
  402. package/src/types/graph.js.map +0 -1
  403. package/src/types/graph.test.js.map +0 -1
  404. package/src/types/index.js.map +0 -1
  405. package/src/types/llm.js.map +0 -1
  406. package/src/types/messages.js.map +0 -1
  407. package/src/types/run.js.map +0 -1
  408. package/src/types/stream.js.map +0 -1
  409. package/src/types/tools.js.map +0 -1
  410. package/src/utils/contextAnalytics.js.map +0 -1
  411. package/src/utils/contextAnalytics.test.js.map +0 -1
  412. package/src/utils/events.js.map +0 -1
  413. package/src/utils/graph.js.map +0 -1
  414. package/src/utils/handlers.js.map +0 -1
  415. package/src/utils/index.js.map +0 -1
  416. package/src/utils/llm.js.map +0 -1
  417. package/src/utils/llmConfig.js.map +0 -1
  418. package/src/utils/logging.js.map +0 -1
  419. package/src/utils/misc.js.map +0 -1
  420. package/src/utils/run.js.map +0 -1
  421. package/src/utils/schema.js.map +0 -1
  422. package/src/utils/title.js.map +0 -1
  423. package/src/utils/tokens.js.map +0 -1
  424. package/src/utils/toonFormat.js.map +0 -1
@@ -412,14 +412,7 @@ describe('addBedrockCacheControl (Bedrock cache checkpoints)', () => {
412
412
  expect(first[1]).toEqual({ cachePoint: { type: 'default' } });
413
413
  });
414
414
 
415
- it('skips system messages (cachePoint added inline by AgentContext.buildSystemRunnable)', () => {
416
- /* Contract change (upstream PR #128 alignment): system message
417
- * cachePoint is now emitted inline in AgentContext.buildSystemRunnable.
418
- * addBedrockCacheControl must therefore SKIP system messages so the
419
- * 2-cachePoint per-request budget stays available for the conversation
420
- * tail. Caching the system prefix is what unlocks cross-user cost
421
- * savings — Bedrock's prompt cache is account-scoped, so a stable
422
- * system prefix shared across users hits the same cache entry. */
415
+ it('works with the example from the langchain pr (with multi-turn behavior)', () => {
423
416
  const messages: TestMsg[] = [
424
417
  {
425
418
  role: 'system',
@@ -437,17 +430,15 @@ describe('addBedrockCacheControl (Bedrock cache checkpoints)', () => {
437
430
 
438
431
  const result = addBedrockCacheControl(messages);
439
432
 
440
- const system = result[0].content as MessageContentComplex[];
441
- const user = result[1].content as MessageContentComplex[];
433
+ let system = result[0].content as MessageContentComplex[];
434
+ let user = result[1].content as MessageContentComplex[];
442
435
 
443
- // System message is left untouched addBedrockCacheControl does NOT
444
- // add a cachePoint here. The cachePoint is added in AgentContext when
445
- // the system message is first built.
446
- expect(system).toEqual([
447
- { type: ContentTypes.TEXT, text: 'You\'re an advanced AI assistant.' },
448
- ]);
449
-
450
- // User message still gets a cachePoint (last eligible).
436
+ // Both messages get cachePoints (last 2 eligible messages)
437
+ expect(system[0]).toEqual({
438
+ type: ContentTypes.TEXT,
439
+ text: 'You\'re an advanced AI assistant.',
440
+ });
441
+ expect(system[1]).toEqual({ cachePoint: { type: 'default' } });
451
442
  expect(user[0]).toEqual({
452
443
  type: ContentTypes.TEXT,
453
444
  text: 'What is the capital of France?',
@@ -467,59 +458,30 @@ describe('addBedrockCacheControl (Bedrock cache checkpoints)', () => {
467
458
 
468
459
  const result2 = addBedrockCacheControl(result);
469
460
 
470
- const system2 = result2[0].content as MessageContentComplex[];
471
- const user2 = result2[1].content as MessageContentComplex[];
472
- const assistant2 = result2[2].content as MessageContentComplex[];
461
+ system = result2[0].content as MessageContentComplex[];
462
+ user = result2[1].content as MessageContentComplex[];
463
+ const assistant = result2[2].content as MessageContentComplex[];
473
464
 
474
- // System message still untouched.
475
- expect(system2).toEqual([
476
- { type: ContentTypes.TEXT, text: 'You\'re an advanced AI assistant.' },
477
- ]);
465
+ // System message no longer has cachePoint (it's not in the last 2 eligible)
466
+ expect(system[0]).toEqual({
467
+ type: ContentTypes.TEXT,
468
+ text: 'You\'re an advanced AI assistant.',
469
+ });
470
+ expect(system.length).toBe(1);
478
471
 
479
- // Both conversation messages now get cachePoints (last 2 eligible).
480
- expect(user2[0]).toEqual({
472
+ // User message gets cachePoint (second-to-last eligible)
473
+ expect(user[0]).toEqual({
481
474
  type: ContentTypes.TEXT,
482
475
  text: 'What is the capital of France?',
483
476
  });
484
- expect(user2[1]).toEqual({ cachePoint: { type: 'default' } });
477
+ expect(user[1]).toEqual({ cachePoint: { type: 'default' } });
485
478
 
486
- expect(assistant2[0]).toEqual({
479
+ // Assistant message gets cachePoint (last eligible)
480
+ expect(assistant[0]).toEqual({
487
481
  type: ContentTypes.TEXT,
488
482
  text: 'Sure! The capital of France is Paris.',
489
483
  });
490
- expect(assistant2[1]).toEqual({ cachePoint: { type: 'default' } });
491
- });
492
-
493
- it('strips stray Anthropic cache_control from system message (cross-provider safety)', () => {
494
- /* If a system message arrives with an Anthropic-style cache_control
495
- * marker (e.g. cross-provider switch), addBedrockCacheControl should
496
- * sanitize it — Bedrock ignores cache_control and stale markers can
497
- * confuse provider validation. */
498
- const messages: TestMsg[] = [
499
- {
500
- role: 'system',
501
- content: [
502
- {
503
- type: ContentTypes.TEXT,
504
- text: 'You\'re an advanced AI assistant.',
505
- cache_control: { type: 'ephemeral' },
506
- } as MessageContentComplex,
507
- ],
508
- },
509
- {
510
- role: 'user',
511
- content: [{ type: ContentTypes.TEXT, text: 'Hi' }],
512
- },
513
- ];
514
-
515
- const result = addBedrockCacheControl(messages);
516
- const system = result[0].content as MessageContentComplex[];
517
-
518
- expect(system).toHaveLength(1);
519
- expect('cache_control' in system[0]).toBe(false);
520
- expect((system[0] as { text?: string }).text).toBe(
521
- 'You\'re an advanced AI assistant.'
522
- );
484
+ expect(assistant[1]).toEqual({ cachePoint: { type: 'default' } });
523
485
  });
524
486
 
525
487
  it('is idempotent - calling multiple times does not add duplicate cache points', () => {
@@ -14,61 +14,6 @@ type MessageWithContent = {
14
14
  content?: string | MessageContentComplex[];
15
15
  };
16
16
 
17
- type MessageContentWithCacheControl = MessageContentComplex & {
18
- cache_control?: unknown;
19
- };
20
-
21
- /**
22
- * Strips Anthropic-style `cache_control` markers from every block in the
23
- * given content array. Returns the (possibly cloned) content and a flag
24
- * indicating whether anything was actually modified — so callers can avoid
25
- * unnecessary message clones.
26
- *
27
- * Used to sanitize a system message's content array before adding Bedrock
28
- * cache points, so stray Anthropic markers (e.g. left over from a previous
29
- * Anthropic-provider turn) don't prevent the Bedrock provider from caching
30
- * the system prefix.
31
- */
32
- function stripAnthropicCacheControlFromBlocks(
33
- content: MessageContentComplex[]
34
- ): { content: MessageContentComplex[]; modified: boolean } {
35
- let modified = false;
36
- const strippedContent = content.map((block) => {
37
- if (!('cache_control' in block)) {
38
- return block;
39
- }
40
-
41
- const cloned: MessageContentWithCacheControl = { ...block };
42
- delete cloned.cache_control;
43
- modified = true;
44
- return cloned;
45
- });
46
-
47
- return { content: strippedContent, modified };
48
- }
49
-
50
- /**
51
- * For the Bedrock cache pass, system messages must NOT carry Anthropic
52
- * cache_control markers (those are an Anthropic-specific encoding and
53
- * Bedrock uses cachePoint blocks instead). Strip them before the cache
54
- * point insertion logic walks the message.
55
- */
56
- function sanitizeBedrockSystemMessage<T extends MessageWithContent>(
57
- message: T
58
- ): T {
59
- const content = message.content;
60
- if (!Array.isArray(content)) {
61
- return message;
62
- }
63
-
64
- const stripped = stripAnthropicCacheControlFromBlocks(content);
65
- if (!stripped.modified) {
66
- return message;
67
- }
68
-
69
- return cloneMessage(message, stripped.content);
70
- }
71
-
72
17
  /** Debug logger for cache operations - set ILLUMA_DEBUG_CACHE=true to enable */
73
18
  const debugCache = (message: string, data?: unknown): void => {
74
19
  if (process.env.ILLUMA_DEBUG_CACHE === 'true') {
@@ -416,36 +361,8 @@ export function addBedrockCacheControl<
416
361
 
417
362
  // Clone messages to avoid mutating originals
418
363
  const updatedMessages: T[] = messages.map((msg) => {
419
- /* PRESERVE cachePoint on system messages — they're added inline by
420
- * AgentContext.buildSystemRunnable to mark the cacheable system prefix
421
- * for account-level caching. Only strip stray Anthropic cache_control
422
- * (which Bedrock ignores). For non-system messages keep the existing
423
- * behaviour: full strip + repopulate based on last-2 strategy. */
424
- const msgType =
425
- 'getType' in msg && typeof msg.getType === 'function'
426
- ? msg.getType()
427
- : undefined;
428
- const msgRole = (msg as Record<string, unknown>).role as string | undefined;
429
- const isSystem = msgType === 'system' || msgRole === 'system';
430
-
431
364
  const content = msg.content;
432
365
  if (Array.isArray(content)) {
433
- if (isSystem) {
434
- /* System: keep cachePoint, only strip Anthropic cache_control. */
435
- if (hasAnthropicCacheControl(content)) {
436
- const stripped = content.map((block) => {
437
- const rec = block as Record<string, unknown>;
438
- if ('cache_control' in rec) {
439
- const { cache_control: _, ...rest } = rec;
440
- return rest as MessageContentComplex;
441
- }
442
- return block;
443
- });
444
- return cloneMessage(msg, stripped) as T;
445
- }
446
- return cloneMessage(msg, content) as T;
447
- }
448
-
449
366
  // Strip existing cachePoint blocks and Anthropic-style cache_control
450
367
  const stripped = content
451
368
  .filter((block) => !isCachePoint(block))
@@ -539,35 +456,6 @@ export function addBedrockCacheControl<
539
456
  const message = updatedMessages[i];
540
457
  const msgContent = message.content;
541
458
 
542
- /* System messages are handled by AgentContext.buildSystemRunnable —
543
- * the cachePoint is emitted INLINE in the system message content array
544
- * so the cacheable system prefix gets a marker every turn (not just
545
- * when the system message happens to be in the last 2 eligible). The
546
- * Bedrock converter (src/llm/bedrock/utils/message_inputs.ts:261-294)
547
- * passes through cachePoint blocks in system content arrays.
548
- *
549
- * If we ALSO marked system here, we'd: (a) waste one of the two
550
- * cachePoint budget slots that Bedrock honours per-request, starving
551
- * the conversation tail, and (b) potentially double-mark a stable
552
- * prefix that already has its own cachePoint.
553
- *
554
- * As a defensive cleanup, strip stray Anthropic-style cache_control
555
- * markers from the system message — Bedrock ignores them and they
556
- * can confuse provider validation. */
557
- const _msgType =
558
- 'getType' in message && typeof message.getType === 'function'
559
- ? message.getType()
560
- : undefined;
561
- const _msgRole = (message as Record<string, unknown>).role as
562
- | string
563
- | undefined;
564
- if (_msgType === 'system' || _msgRole === 'system') {
565
- updatedMessages[i] = sanitizeBedrockSystemMessage(
566
- message as MessageWithContent
567
- ) as T;
568
- continue;
569
- }
570
-
571
459
  // Skip empty/whitespace-only content
572
460
  if (msgContent == null) continue;
573
461
  if (typeof msgContent === 'string' && msgContent.trim() === '') continue;
@@ -274,90 +274,18 @@ export const formatFromLangChain = (
274
274
  };
275
275
  };
276
276
 
277
- /* DeepSeek reasoning roundtrip: when active, accumulate reasoning text
278
- * from THINK/THINKING/REASONING blocks and attach to the next AI message
279
- * as `additional_kwargs.reasoning_content` so it survives multi-turn
280
- * replays through the OpenAI-compatible DeepSeek API. Upstream PR #136. */
281
- interface FormatAssistantMessageOptions {
282
- preserveReasoningContent?: boolean;
283
- }
284
-
285
- interface FormatAgentMessagesOptions {
286
- provider?: Providers;
287
- }
288
-
289
- function extractReasoningContent(
290
- part: MessageContentComplex | undefined | null
291
- ): string {
292
- if (part == null || typeof part !== 'object') return '';
293
- if (part.type === ContentTypes.THINK) {
294
- const think = (part as ReasoningContentText).think;
295
- return typeof think === 'string' ? think : '';
296
- }
297
- if (part.type === ContentTypes.THINKING) {
298
- const thinking = (part as { thinking?: string }).thinking;
299
- return typeof thinking === 'string' ? thinking : '';
300
- }
301
- if (part.type === ContentTypes.REASONING) {
302
- const reasoning = (part as { reasoning?: string }).reasoning;
303
- return typeof reasoning === 'string' ? reasoning : '';
304
- }
305
- if (part.type === ContentTypes.REASONING_CONTENT) {
306
- /* Bedrock/Google nested shape: { reasoningContent: { text: ... } } */
307
- const nested = (part as { reasoningContent?: { text?: string } })
308
- .reasoningContent;
309
- if (nested && typeof nested.text === 'string') return nested.text;
310
- }
311
- return '';
312
- }
313
-
314
277
  /**
315
278
  * Helper function to format an assistant message
316
279
  * @param message The message to format
317
- * @param options Optional formatting options (e.g. DeepSeek reasoning roundtrip)
318
280
  * @returns Array of formatted messages
319
281
  */
320
282
  function formatAssistantMessage(
321
- message: Partial<TMessage>,
322
- options?: FormatAssistantMessageOptions
283
+ message: Partial<TMessage>
323
284
  ): Array<AIMessage | ToolMessage> {
324
285
  const formattedMessages: Array<AIMessage | ToolMessage> = [];
325
286
  let currentContent: MessageContentComplex[] = [];
326
287
  let lastAIMessage: AIMessage | null = null;
327
288
  let hasReasoning = false;
328
- let pendingReasoningContent = '';
329
- const shouldPreserveReasoningContent =
330
- options?.preserveReasoningContent === true;
331
-
332
- const takePendingReasoningContent = (): string | undefined => {
333
- if (!shouldPreserveReasoningContent || !pendingReasoningContent) {
334
- return undefined;
335
- }
336
- const reasoningContent = pendingReasoningContent;
337
- pendingReasoningContent = '';
338
- return reasoningContent;
339
- };
340
-
341
- const createAIMessage = (
342
- content: string | MessageContentComplex[]
343
- ): AIMessage => {
344
- const reasoningContent = takePendingReasoningContent();
345
- return new AIMessage({
346
- content,
347
- ...(reasoningContent != null && {
348
- additional_kwargs: { reasoning_content: reasoningContent },
349
- }),
350
- });
351
- };
352
-
353
- const attachPendingReasoningContent = (aiMessage: AIMessage): void => {
354
- const reasoningContent = takePendingReasoningContent();
355
- if (reasoningContent == null) return;
356
- aiMessage.additional_kwargs.reasoning_content =
357
- typeof aiMessage.additional_kwargs.reasoning_content === 'string'
358
- ? `${aiMessage.additional_kwargs.reasoning_content}${reasoningContent}`
359
- : reasoningContent;
360
- };
361
289
 
362
290
  if (Array.isArray(message.content)) {
363
291
  for (const part of message.content as Array<
@@ -380,15 +308,15 @@ function formatAssistantMessage(
380
308
  }, '');
381
309
  content =
382
310
  `${content}\n${part[ContentTypes.TEXT] ?? part.text ?? ''}`.trim();
383
- lastAIMessage = createAIMessage(content);
311
+ lastAIMessage = new AIMessage({ content });
384
312
  formattedMessages.push(lastAIMessage);
385
313
  currentContent = [];
386
314
  continue;
387
315
  }
388
316
  // Create a new AIMessage with this text and prepare for tool calls
389
- lastAIMessage = createAIMessage(
390
- part.text != null ? part.text : ''
391
- );
317
+ lastAIMessage = new AIMessage({
318
+ content: part.text != null ? part.text : '',
319
+ });
392
320
  formattedMessages.push(lastAIMessage);
393
321
  } else if (part.type === ContentTypes.TOOL_CALL) {
394
322
  // Skip malformed tool call entries without tool_call property
@@ -413,10 +341,8 @@ function formatAssistantMessage(
413
341
 
414
342
  if (!lastAIMessage) {
415
343
  // "Heal" the payload by creating an AIMessage to precede the tool call
416
- lastAIMessage = createAIMessage('');
344
+ lastAIMessage = new AIMessage({ content: '' });
417
345
  formattedMessages.push(lastAIMessage);
418
- } else {
419
- attachPendingReasoningContent(lastAIMessage);
420
346
  }
421
347
 
422
348
  const tool_call: ToolCallPart = _tool_call;
@@ -459,12 +385,10 @@ function formatAssistantMessage(
459
385
  } else if (
460
386
  part.type === ContentTypes.THINK ||
461
387
  part.type === ContentTypes.THINKING ||
462
- part.type === ContentTypes.REASONING ||
463
388
  part.type === ContentTypes.REASONING_CONTENT ||
464
389
  part.type === 'redacted_thinking'
465
390
  ) {
466
391
  hasReasoning = true;
467
- pendingReasoningContent += extractReasoningContent(part);
468
392
  continue;
469
393
  } else if (
470
394
  part.type === ContentTypes.ERROR ||
@@ -494,10 +418,10 @@ function formatAssistantMessage(
494
418
  .trim();
495
419
 
496
420
  if (content) {
497
- formattedMessages.push(createAIMessage(content));
421
+ formattedMessages.push(new AIMessage({ content }));
498
422
  }
499
423
  } else if (currentContent.length > 0) {
500
- formattedMessages.push(createAIMessage(currentContent));
424
+ formattedMessages.push(new AIMessage({ content: currentContent }));
501
425
  }
502
426
 
503
427
  return formattedMessages;
@@ -798,8 +722,7 @@ export const formatAgentMessages = (
798
722
  payload: TPayload,
799
723
  indexTokenCountMap?: Record<number, number | undefined>,
800
724
  tools?: Set<string>,
801
- skills?: Map<string, string>,
802
- options?: FormatAgentMessagesOptions
725
+ skills?: Map<string, string>
803
726
  ): {
804
727
  messages: Array<HumanMessage | AIMessage | SystemMessage | ToolMessage>;
805
728
  indexTokenCountMap?: Record<number, number>;
@@ -1008,9 +931,7 @@ export const formatAgentMessages = (
1008
931
  }
1009
932
 
1010
933
  // Process the assistant message using the helper function
1011
- const formattedMessages = formatAssistantMessage(processedMessage, {
1012
- preserveReasoningContent: options?.provider === Providers.DEEPSEEK,
1013
- });
934
+ const formattedMessages = formatAssistantMessage(processedMessage);
1014
935
  messages.push(...formattedMessages);
1015
936
 
1016
937
  // Capture index range BEFORE skill body injection so injected
@@ -0,0 +1,263 @@
1
+ import { config } from 'dotenv';
2
+ config();
3
+
4
+ import { HumanMessage } from '@langchain/core/messages';
5
+ import type * as t from '@/types';
6
+ import { ChatModelStreamHandler } from '@/stream';
7
+ import { ToolEndHandler, ModelEndHandler } from '@/events';
8
+ import { Providers, GraphEvents } from '@/common';
9
+ import { Run } from '@/run';
10
+
11
+ /**
12
+ * Live verification that host-set fields on the parent's outer
13
+ * `configurable` (e.g. `requestBody`, `user`, `userMCPAuthMap`)
14
+ * propagate into the subagent's `ON_TOOL_EXECUTE` dispatches.
15
+ *
16
+ * Pass criteria: when the SUBAGENT calls the calculator tool, the
17
+ * `data.configurable` arriving at the parent's ON_TOOL_EXECUTE
18
+ * handler contains every key the parent put on its outer
19
+ * configurable (with `thread_id` overridden to a child run id).
20
+ */
21
+ const apiKey = process.env.OPENAI_API_KEY!;
22
+ if (!apiKey) {
23
+ console.error('Missing OPENAI_API_KEY');
24
+ process.exit(1);
25
+ }
26
+
27
+ const calculatorDef: t.LCTool = {
28
+ name: 'calculator',
29
+ description: 'Evaluate a math expression. Use for any arithmetic.',
30
+ parameters: {
31
+ type: 'object',
32
+ properties: {
33
+ expression: {
34
+ type: 'string',
35
+ description: "A JS math expression, e.g. '42 * 58'",
36
+ },
37
+ },
38
+ required: ['expression'],
39
+ },
40
+ };
41
+
42
+ type ConfigurableSnapshot = {
43
+ agentId: string | undefined;
44
+ configurable: Record<string, unknown> | undefined;
45
+ metadata: Record<string, unknown> | undefined;
46
+ };
47
+
48
+ async function main() {
49
+ console.log('=== Subagent parentConfigurable inheritance — live ===\n');
50
+
51
+ // Parent has NO tools — it can only delegate via the math subagent.
52
+ // The math subagent has the calculator. This forces the spawn-subagent
53
+ // path so we can observe the subagent's `ON_TOOL_EXECUTE` dispatch.
54
+ const mathSubagentInputs: t.AgentInputs = {
55
+ agentId: 'math-worker',
56
+ provider: Providers.OPENAI,
57
+ clientOptions: { modelName: 'gpt-4o', apiKey },
58
+ instructions:
59
+ 'You compute arithmetic. Always use the calculator tool — never estimate. Return the final numeric result as plain text.',
60
+ maxContextTokens: 8000,
61
+ toolDefinitions: [calculatorDef],
62
+ };
63
+
64
+ const parentAgent: t.AgentInputs = {
65
+ agentId: 'supervisor',
66
+ provider: Providers.OPENAI,
67
+ clientOptions: { modelName: 'gpt-4o', apiKey },
68
+ instructions: `You delegate arithmetic to the "math" subagent. You have NO calculator yourself. For any math task, spawn the "math" subagent with the full task as its description, then echo the subagent's text result back to the user.`,
69
+ maxContextTokens: 8000,
70
+ // No toolDefinitions on the parent — only the subagent gets the calculator.
71
+ subagentConfigs: [
72
+ {
73
+ type: 'math',
74
+ name: 'math',
75
+ description:
76
+ 'A focused arithmetic worker that uses the calculator tool to compute numerical results.',
77
+ agentInputs: mathSubagentInputs,
78
+ },
79
+ ],
80
+ };
81
+
82
+ const parentSnapshots: ConfigurableSnapshot[] = [];
83
+ const subagentSnapshots: ConfigurableSnapshot[] = [];
84
+
85
+ const customHandlers: Record<string, t.EventHandler> = {
86
+ [GraphEvents.CHAT_MODEL_STREAM]: new ChatModelStreamHandler(),
87
+ [GraphEvents.TOOL_END]: new ToolEndHandler(),
88
+ [GraphEvents.CHAT_MODEL_END]: new ModelEndHandler(),
89
+ [GraphEvents.ON_TOOL_EXECUTE]: {
90
+ handle: (_event, rawData): void => {
91
+ const data = rawData as t.ToolExecuteBatchRequest;
92
+ const snapshot: ConfigurableSnapshot = {
93
+ agentId: data.agentId,
94
+ configurable: data.configurable as
95
+ | Record<string, unknown>
96
+ | undefined,
97
+ metadata: data.metadata as Record<string, unknown> | undefined,
98
+ };
99
+ const callsLabel = data.toolCalls.map((c) => c.name).join(',');
100
+ // Parent and subagent have different agent IDs in this script
101
+ // (parent: 'supervisor', subagent: 'math-worker'). With a self-spawn
102
+ // subagent both would be the same; this script uses a non-self
103
+ // subagent precisely so we can distinguish reliably.
104
+ const isSubagent = data.agentId !== 'supervisor';
105
+ const metadataRunId = (data.metadata as { run_id?: string } | undefined)
106
+ ?.run_id;
107
+ if (isSubagent) {
108
+ subagentSnapshots.push(snapshot);
109
+ } else {
110
+ parentSnapshots.push(snapshot);
111
+ }
112
+ console.log(
113
+ `[ON_TOOL_EXECUTE] origin=${isSubagent ? 'SUBAGENT' : 'PARENT'} agentId=${data.agentId} calls=${callsLabel}`
114
+ );
115
+ console.log(
116
+ ` metadata keys: ${Object.keys(data.metadata ?? {}).join(',') || '<none>'}`
117
+ );
118
+ console.log(
119
+ ` metadata.run_id="${metadataRunId ?? '<none>'}" configurable.run_id="${(data.configurable as { run_id?: string } | undefined)?.run_id ?? '<none>'}" configurable.thread_id="${(data.configurable as { thread_id?: string } | undefined)?.thread_id ?? '<none>'}"`
120
+ );
121
+ const results: t.ToolExecuteResult[] = data.toolCalls.map((call) => {
122
+ const args = call.args as { expression?: string };
123
+ const expression = args.expression ?? '';
124
+ let content: string;
125
+ try {
126
+ // eslint-disable-next-line no-eval
127
+ const result = eval(expression);
128
+ content = `${expression} = ${result}`;
129
+ } catch (err) {
130
+ content = `Error: ${String(err)}`;
131
+ }
132
+ return {
133
+ toolCallId: call.id!,
134
+ status: 'success',
135
+ content,
136
+ };
137
+ });
138
+ data.resolve(results);
139
+ },
140
+ },
141
+ };
142
+
143
+ const run = await Run.create<t.IState>({
144
+ runId: `sub-cfg-inherit-${Date.now()}`,
145
+ graphConfig: { type: 'standard', agents: [parentAgent] },
146
+ customHandlers,
147
+ });
148
+
149
+ const question = new HumanMessage(
150
+ 'Compute (42 * 58) + (13 ** 3). Use the self subagent, and have it use the calculator.'
151
+ );
152
+
153
+ // Parent's outer configurable carries host-set fields AND explicit
154
+ // run-identity fields so we can verify whether LangGraph respects or
155
+ // overwrites parent's `run_id` / `parent_run_id` when we forward them
156
+ // into the child's `workflow.invoke`.
157
+ const outerConfigurable = {
158
+ thread_id: 'parent-thread-conv-xyz',
159
+ run_id: 'parent-run-id-001',
160
+ parent_run_id: 'grandparent-run-id-000',
161
+ user_id: 'user_abc',
162
+ user: { id: 'user_abc', email: 'a@b.c', role: 'USER' },
163
+ requestBody: {
164
+ messageId: 'msg-response-id-001',
165
+ conversationId: 'parent-thread-conv-xyz',
166
+ parentMessageId: 'user-message-id-000',
167
+ },
168
+ userMCPAuthMap: { 'mcp-github': { token: 'abc' } },
169
+ };
170
+
171
+ console.log('User:', question.content);
172
+ console.log(
173
+ 'Parent outer configurable keys:',
174
+ Object.keys(outerConfigurable)
175
+ );
176
+ console.log();
177
+
178
+ await run.processStream(
179
+ { messages: [question] },
180
+ {
181
+ configurable: outerConfigurable,
182
+ version: 'v2' as const,
183
+ }
184
+ );
185
+
186
+ console.log('\n=== Verification ===');
187
+ console.log(
188
+ `Parent ON_TOOL_EXECUTE dispatches captured: ${parentSnapshots.length}`
189
+ );
190
+ console.log(
191
+ `Subagent ON_TOOL_EXECUTE dispatches captured: ${subagentSnapshots.length}`
192
+ );
193
+
194
+ if (subagentSnapshots.length === 0) {
195
+ console.error(
196
+ '\n❌ FAIL: subagent never invoked a tool — model may not have spawned the subagent.'
197
+ );
198
+ process.exit(2);
199
+ }
200
+
201
+ const expectedHostKeys = ['user_id', 'user', 'requestBody', 'userMCPAuthMap'];
202
+ let allPassed = true;
203
+ subagentSnapshots.forEach((snap, idx) => {
204
+ const cfg = snap.configurable ?? {};
205
+ const meta = snap.metadata ?? {};
206
+ console.log(
207
+ `\nSubagent dispatch #${idx + 1} (agentId=${snap.agentId}, metadata.run_id=${(meta as { run_id?: string }).run_id ?? '-'}):`
208
+ );
209
+
210
+ // Host-set fields must propagate.
211
+ for (const key of expectedHostKeys) {
212
+ const present = key in cfg;
213
+ const value = cfg[key];
214
+ console.log(
215
+ ` ${present ? '✅' : '❌'} ${key} = ${JSON.stringify(value)}`
216
+ );
217
+ if (!present) allPassed = false;
218
+ }
219
+
220
+ // Run-identity fields: with full inheritance we expect parent's
221
+ // values to flow through. LangGraph runtime MAY overwrite them at
222
+ // child-invoke time — the script logs what actually arrived so we
223
+ // can see empirically what propagates.
224
+ console.log(
225
+ ` ⓘ thread_id observed: "${cfg.thread_id as string}" (parent's: "${outerConfigurable.thread_id}")`
226
+ );
227
+ console.log(
228
+ ` ⓘ run_id observed: "${cfg.run_id as string}" (parent's: "${outerConfigurable.run_id}")`
229
+ );
230
+ console.log(
231
+ ` ⓘ parent_run_id observed: "${cfg.parent_run_id as string}" (parent's: "${outerConfigurable.parent_run_id}")`
232
+ );
233
+
234
+ const threadInherited = cfg.thread_id === outerConfigurable.thread_id;
235
+ const runInherited = cfg.run_id === outerConfigurable.run_id;
236
+ const parentRunInherited =
237
+ cfg.parent_run_id === outerConfigurable.parent_run_id;
238
+ console.log(
239
+ ` ${threadInherited ? '✅' : '⚠️ '} thread_id inherited from parent: ${threadInherited}`
240
+ );
241
+ console.log(
242
+ ` ${runInherited ? '✅' : '⚠️ '} run_id inherited from parent: ${runInherited}`
243
+ );
244
+ console.log(
245
+ ` ${parentRunInherited ? '✅' : '⚠️ '} parent_run_id inherited from parent: ${parentRunInherited}`
246
+ );
247
+ });
248
+
249
+ if (allPassed) {
250
+ console.log(
251
+ '\n✅ Host-set fields propagate. (Run-identity inheritance is informational — see ⚠️ markers above for any LangGraph-runtime overwrites.)'
252
+ );
253
+ process.exit(0);
254
+ } else {
255
+ console.log('\n❌ FAIL: at least one expected host-set key was missing.');
256
+ process.exit(1);
257
+ }
258
+ }
259
+
260
+ main().catch((err) => {
261
+ console.error('Script error:', err);
262
+ process.exit(1);
263
+ });