@illuma-ai/agents 1.5.1 → 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 (319) hide show
  1. package/README.md +0 -62
  2. package/dist/cjs/agents/AgentContext.cjs +160 -259
  3. package/dist/cjs/agents/AgentContext.cjs.map +1 -1
  4. package/dist/cjs/common/enum.cjs +12 -12
  5. package/dist/cjs/common/enum.cjs.map +1 -1
  6. package/dist/cjs/graphs/Graph.cjs +30 -13
  7. package/dist/cjs/graphs/Graph.cjs.map +1 -1
  8. package/dist/cjs/graphs/MultiAgentGraph.cjs +1 -1
  9. package/dist/cjs/graphs/MultiAgentGraph.cjs.map +1 -1
  10. package/dist/cjs/graphs/phases/memoryFlushPhase.cjs +1 -1
  11. package/dist/cjs/graphs/phases/memoryFlushPhase.cjs.map +1 -1
  12. package/dist/cjs/hooks/HookRegistry.cjs +1 -1
  13. package/dist/cjs/hooks/HookRegistry.cjs.map +1 -1
  14. package/dist/cjs/hooks/matchers.cjs +2 -2
  15. package/dist/cjs/hooks/matchers.cjs.map +1 -1
  16. package/dist/cjs/hooks/types.cjs +1 -1
  17. package/dist/cjs/hooks/types.cjs.map +1 -1
  18. package/dist/cjs/llm/anthropic/utils/message_inputs.cjs +1 -5
  19. package/dist/cjs/llm/anthropic/utils/message_inputs.cjs.map +1 -1
  20. package/dist/cjs/llm/bedrock/index.cjs +33 -61
  21. package/dist/cjs/llm/bedrock/index.cjs.map +1 -1
  22. package/dist/cjs/llm/openai/index.cjs +1 -1
  23. package/dist/cjs/llm/openai/index.cjs.map +1 -1
  24. package/dist/cjs/llm/openai/utils/index.cjs +10 -27
  25. package/dist/cjs/llm/openai/utils/index.cjs.map +1 -1
  26. package/dist/cjs/main.cjs +3 -84
  27. package/dist/cjs/main.cjs.map +1 -1
  28. package/dist/cjs/memory/citations.cjs +4 -4
  29. package/dist/cjs/memory/citations.cjs.map +1 -1
  30. package/dist/cjs/memory/constants.cjs +17 -17
  31. package/dist/cjs/memory/constants.cjs.map +1 -1
  32. package/dist/cjs/memory/mmr.cjs +1 -1
  33. package/dist/cjs/memory/mmr.cjs.map +1 -1
  34. package/dist/cjs/memory/paths.cjs +1 -1
  35. package/dist/cjs/memory/paths.cjs.map +1 -1
  36. package/dist/cjs/memory/recallTracking.cjs +3 -3
  37. package/dist/cjs/memory/recallTracking.cjs.map +1 -1
  38. package/dist/cjs/memory/temporalDecay.cjs +2 -2
  39. package/dist/cjs/memory/temporalDecay.cjs.map +1 -1
  40. package/dist/cjs/messages/cache.cjs +0 -89
  41. package/dist/cjs/messages/cache.cjs.map +1 -1
  42. package/dist/cjs/messages/format.cjs +13 -71
  43. package/dist/cjs/messages/format.cjs.map +1 -1
  44. package/dist/cjs/tools/BashExecutor.cjs +11 -21
  45. package/dist/cjs/tools/BashExecutor.cjs.map +1 -1
  46. package/dist/cjs/tools/CodeExecutor.cjs +13 -41
  47. package/dist/cjs/tools/CodeExecutor.cjs.map +1 -1
  48. package/dist/cjs/tools/ProgrammaticToolCalling.cjs +11 -16
  49. package/dist/cjs/tools/ProgrammaticToolCalling.cjs.map +1 -1
  50. package/dist/cjs/tools/ToolNode.cjs +78 -13
  51. package/dist/cjs/tools/ToolNode.cjs.map +1 -1
  52. package/dist/cjs/tools/memory/memoryAppendTool.cjs +1 -1
  53. package/dist/cjs/tools/memory/memoryAppendTool.cjs.map +1 -1
  54. package/dist/cjs/tools/memory/memoryGetTool.cjs +2 -2
  55. package/dist/cjs/tools/memory/memoryGetTool.cjs.map +1 -1
  56. package/dist/cjs/tools/memory/memorySearchTool.cjs +3 -3
  57. package/dist/cjs/tools/memory/memorySearchTool.cjs.map +1 -1
  58. package/dist/cjs/tools/memory/shared.cjs +1 -1
  59. package/dist/cjs/tools/memory/shared.cjs.map +1 -1
  60. package/dist/cjs/tools/search/search.cjs +3 -11
  61. package/dist/cjs/tools/search/search.cjs.map +1 -1
  62. package/dist/cjs/tools/search/tool.cjs +4 -28
  63. package/dist/cjs/tools/search/tool.cjs.map +1 -1
  64. package/dist/cjs/tools/search/utils.cjs +3 -10
  65. package/dist/cjs/tools/search/utils.cjs.map +1 -1
  66. package/dist/cjs/tools/subagent/SubagentExecutor.cjs +48 -0
  67. package/dist/cjs/tools/subagent/SubagentExecutor.cjs.map +1 -1
  68. package/dist/cjs/types/graph.cjs.map +1 -1
  69. package/dist/esm/agents/AgentContext.mjs +160 -259
  70. package/dist/esm/agents/AgentContext.mjs.map +1 -1
  71. package/dist/esm/common/enum.mjs +12 -12
  72. package/dist/esm/common/enum.mjs.map +1 -1
  73. package/dist/esm/graphs/Graph.mjs +30 -13
  74. package/dist/esm/graphs/Graph.mjs.map +1 -1
  75. package/dist/esm/graphs/MultiAgentGraph.mjs +1 -1
  76. package/dist/esm/graphs/MultiAgentGraph.mjs.map +1 -1
  77. package/dist/esm/graphs/phases/memoryFlushPhase.mjs +1 -1
  78. package/dist/esm/graphs/phases/memoryFlushPhase.mjs.map +1 -1
  79. package/dist/esm/hooks/HookRegistry.mjs +1 -1
  80. package/dist/esm/hooks/HookRegistry.mjs.map +1 -1
  81. package/dist/esm/hooks/matchers.mjs +2 -2
  82. package/dist/esm/hooks/matchers.mjs.map +1 -1
  83. package/dist/esm/hooks/types.mjs +1 -1
  84. package/dist/esm/hooks/types.mjs.map +1 -1
  85. package/dist/esm/llm/anthropic/utils/message_inputs.mjs +1 -5
  86. package/dist/esm/llm/anthropic/utils/message_inputs.mjs.map +1 -1
  87. package/dist/esm/llm/bedrock/index.mjs +34 -61
  88. package/dist/esm/llm/bedrock/index.mjs.map +1 -1
  89. package/dist/esm/llm/openai/index.mjs +1 -1
  90. package/dist/esm/llm/openai/index.mjs.map +1 -1
  91. package/dist/esm/llm/openai/utils/index.mjs +10 -27
  92. package/dist/esm/llm/openai/utils/index.mjs.map +1 -1
  93. package/dist/esm/main.mjs +1 -5
  94. package/dist/esm/main.mjs.map +1 -1
  95. package/dist/esm/memory/citations.mjs +4 -4
  96. package/dist/esm/memory/citations.mjs.map +1 -1
  97. package/dist/esm/memory/constants.mjs +17 -17
  98. package/dist/esm/memory/constants.mjs.map +1 -1
  99. package/dist/esm/memory/mmr.mjs +1 -1
  100. package/dist/esm/memory/mmr.mjs.map +1 -1
  101. package/dist/esm/memory/paths.mjs +1 -1
  102. package/dist/esm/memory/paths.mjs.map +1 -1
  103. package/dist/esm/memory/recallTracking.mjs +3 -3
  104. package/dist/esm/memory/recallTracking.mjs.map +1 -1
  105. package/dist/esm/memory/temporalDecay.mjs +2 -2
  106. package/dist/esm/memory/temporalDecay.mjs.map +1 -1
  107. package/dist/esm/messages/cache.mjs +0 -89
  108. package/dist/esm/messages/cache.mjs.map +1 -1
  109. package/dist/esm/messages/format.mjs +13 -71
  110. package/dist/esm/messages/format.mjs.map +1 -1
  111. package/dist/esm/tools/BashExecutor.mjs +12 -22
  112. package/dist/esm/tools/BashExecutor.mjs.map +1 -1
  113. package/dist/esm/tools/CodeExecutor.mjs +14 -41
  114. package/dist/esm/tools/CodeExecutor.mjs.map +1 -1
  115. package/dist/esm/tools/ProgrammaticToolCalling.mjs +12 -17
  116. package/dist/esm/tools/ProgrammaticToolCalling.mjs.map +1 -1
  117. package/dist/esm/tools/ToolNode.mjs +78 -13
  118. package/dist/esm/tools/ToolNode.mjs.map +1 -1
  119. package/dist/esm/tools/memory/memoryAppendTool.mjs +1 -1
  120. package/dist/esm/tools/memory/memoryAppendTool.mjs.map +1 -1
  121. package/dist/esm/tools/memory/memoryGetTool.mjs +2 -2
  122. package/dist/esm/tools/memory/memoryGetTool.mjs.map +1 -1
  123. package/dist/esm/tools/memory/memorySearchTool.mjs +3 -3
  124. package/dist/esm/tools/memory/memorySearchTool.mjs.map +1 -1
  125. package/dist/esm/tools/memory/shared.mjs +1 -1
  126. package/dist/esm/tools/memory/shared.mjs.map +1 -1
  127. package/dist/esm/tools/search/search.mjs +3 -11
  128. package/dist/esm/tools/search/search.mjs.map +1 -1
  129. package/dist/esm/tools/search/tool.mjs +4 -28
  130. package/dist/esm/tools/search/tool.mjs.map +1 -1
  131. package/dist/esm/tools/search/utils.mjs +3 -10
  132. package/dist/esm/tools/search/utils.mjs.map +1 -1
  133. package/dist/esm/tools/subagent/SubagentExecutor.mjs +48 -0
  134. package/dist/esm/tools/subagent/SubagentExecutor.mjs.map +1 -1
  135. package/dist/esm/types/graph.mjs.map +1 -1
  136. package/dist/types/agents/AgentContext.d.ts +25 -95
  137. package/dist/types/common/enum.d.ts +12 -12
  138. package/dist/types/graphs/Graph.d.ts +2 -2
  139. package/dist/types/graphs/phases/memoryFlushPhase.d.ts +2 -2
  140. package/dist/types/hooks/HookRegistry.d.ts +1 -1
  141. package/dist/types/hooks/matchers.d.ts +2 -2
  142. package/dist/types/hooks/types.d.ts +1 -1
  143. package/dist/types/index.d.ts +0 -1
  144. package/dist/types/llm/bedrock/index.d.ts +1 -54
  145. package/dist/types/llm/openai/index.d.ts +1 -1
  146. package/dist/types/memory/citations.d.ts +4 -4
  147. package/dist/types/memory/constants.d.ts +17 -17
  148. package/dist/types/memory/mmr.d.ts +3 -3
  149. package/dist/types/memory/paths.d.ts +1 -1
  150. package/dist/types/memory/temporalDecay.d.ts +2 -2
  151. package/dist/types/memory/types.d.ts +3 -3
  152. package/dist/types/messages/format.d.ts +2 -5
  153. package/dist/types/tools/CodeExecutor.d.ts +0 -6
  154. package/dist/types/tools/ToolNode.d.ts +3 -3
  155. package/dist/types/tools/memory/shared.d.ts +1 -1
  156. package/dist/types/tools/search/test.d.ts +1 -0
  157. package/dist/types/tools/search/types.d.ts +5 -99
  158. package/dist/types/tools/search/utils.d.ts +2 -2
  159. package/dist/types/tools/subagent/SubagentExecutor.d.ts +29 -0
  160. package/dist/types/types/graph.d.ts +30 -34
  161. package/dist/types/types/index.d.ts +0 -1
  162. package/dist/types/types/messages.d.ts +1 -1
  163. package/dist/types/types/run.d.ts +1 -3
  164. package/dist/types/types/tools.d.ts +5 -14
  165. package/package.json +1 -61
  166. package/src/agents/AgentContext.test.ts +176 -0
  167. package/src/agents/AgentContext.ts +179 -305
  168. package/src/agents/__tests__/AgentContext.test.ts +0 -632
  169. package/src/common/__tests__/enum.test.ts +1 -1
  170. package/src/common/enum.ts +12 -12
  171. package/src/graphs/Graph.ts +32 -13
  172. package/src/graphs/MultiAgentGraph.ts +1 -1
  173. package/src/graphs/gapFeatures.test.ts +1 -1
  174. package/src/graphs/phases/__tests__/memoryFlushPhase.test.ts +1 -1
  175. package/src/graphs/phases/memoryFlushPhase.ts +2 -2
  176. package/src/hooks/HookRegistry.ts +1 -1
  177. package/src/hooks/index.ts +1 -1
  178. package/src/hooks/matchers.ts +2 -2
  179. package/src/hooks/types.ts +1 -1
  180. package/src/index.ts +0 -6
  181. package/src/llm/anthropic/utils/message_inputs.ts +1 -10
  182. package/src/llm/bedrock/__tests__/bedrock-caching.test.ts +18 -166
  183. package/src/llm/bedrock/index.ts +41 -116
  184. package/src/llm/openai/index.ts +2 -2
  185. package/src/llm/openai/utils/index.ts +14 -31
  186. package/src/memory/citations.ts +4 -4
  187. package/src/memory/constants.ts +17 -17
  188. package/src/memory/mmr.ts +3 -3
  189. package/src/memory/paths.ts +1 -1
  190. package/src/memory/recallTracking.ts +3 -3
  191. package/src/memory/temporalDecay.ts +2 -2
  192. package/src/memory/types.ts +3 -3
  193. package/src/messages/cache.test.ts +24 -62
  194. package/src/messages/cache.ts +0 -112
  195. package/src/messages/ensureThinkingBlock.test.ts +1 -1
  196. package/src/messages/format.ts +13 -92
  197. package/src/messages/formatAgentMessages.test.ts +1 -1
  198. package/src/scripts/subagent-configurable-inheritance.ts +263 -0
  199. package/src/scripts/subagent-event-driven-debug.ts +2 -2
  200. package/src/specs/anthropic.simple.test.ts +0 -61
  201. package/src/specs/prune.orphans.test.ts +1 -1
  202. package/src/tools/BashExecutor.ts +13 -37
  203. package/src/tools/CodeExecutor.ts +14 -59
  204. package/src/tools/ProgrammaticToolCalling.ts +14 -29
  205. package/src/tools/ToolNode.ts +75 -14
  206. package/src/tools/__tests__/CodeExecutor.test.ts +3 -3
  207. package/src/tools/__tests__/ProgrammaticToolCalling.test.ts +0 -60
  208. package/src/tools/__tests__/SubagentExecutor.test.ts +157 -0
  209. package/src/tools/memory/memoryAppendTool.ts +1 -1
  210. package/src/tools/memory/memoryGetTool.ts +2 -2
  211. package/src/tools/memory/memorySearchTool.ts +3 -3
  212. package/src/tools/memory/shared.ts +1 -1
  213. package/src/tools/search/output.md +2775 -0
  214. package/src/tools/search/search.ts +2 -12
  215. package/src/tools/search/test.html +884 -0
  216. package/src/tools/search/test.md +643 -0
  217. package/src/tools/search/test.ts +159 -0
  218. package/src/tools/search/tool.ts +2 -36
  219. package/src/tools/search/types.ts +8 -133
  220. package/src/tools/search/utils.ts +5 -13
  221. package/src/tools/subagent/SubagentExecutor.ts +78 -0
  222. package/src/types/graph.ts +27 -34
  223. package/src/types/index.ts +0 -1
  224. package/src/types/messages.ts +1 -1
  225. package/src/types/run.ts +1 -3
  226. package/src/types/tools.ts +5 -14
  227. package/dist/cjs/langchain/google-common.cjs +0 -3
  228. package/dist/cjs/langchain/google-common.cjs.map +0 -1
  229. package/dist/cjs/langchain/index.cjs +0 -86
  230. package/dist/cjs/langchain/index.cjs.map +0 -1
  231. package/dist/cjs/langchain/language_models/chat_models.cjs +0 -3
  232. package/dist/cjs/langchain/language_models/chat_models.cjs.map +0 -1
  233. package/dist/cjs/langchain/messages/tool.cjs +0 -3
  234. package/dist/cjs/langchain/messages/tool.cjs.map +0 -1
  235. package/dist/cjs/langchain/messages.cjs +0 -51
  236. package/dist/cjs/langchain/messages.cjs.map +0 -1
  237. package/dist/cjs/langchain/openai.cjs +0 -3
  238. package/dist/cjs/langchain/openai.cjs.map +0 -1
  239. package/dist/cjs/langchain/prompts.cjs +0 -11
  240. package/dist/cjs/langchain/prompts.cjs.map +0 -1
  241. package/dist/cjs/langchain/runnables.cjs +0 -19
  242. package/dist/cjs/langchain/runnables.cjs.map +0 -1
  243. package/dist/cjs/langchain/tools.cjs +0 -23
  244. package/dist/cjs/langchain/tools.cjs.map +0 -1
  245. package/dist/cjs/langchain/utils/env.cjs +0 -11
  246. package/dist/cjs/langchain/utils/env.cjs.map +0 -1
  247. package/dist/cjs/llm/bedrock/cacheSupport.cjs +0 -55
  248. package/dist/cjs/llm/bedrock/cacheSupport.cjs.map +0 -1
  249. package/dist/cjs/tools/search/tavily-scraper.cjs +0 -189
  250. package/dist/cjs/tools/search/tavily-scraper.cjs.map +0 -1
  251. package/dist/cjs/tools/search/tavily-search.cjs +0 -372
  252. package/dist/cjs/tools/search/tavily-search.cjs.map +0 -1
  253. package/dist/cjs/types/agent-cache.cjs +0 -54
  254. package/dist/cjs/types/agent-cache.cjs.map +0 -1
  255. package/dist/esm/langchain/google-common.mjs +0 -2
  256. package/dist/esm/langchain/google-common.mjs.map +0 -1
  257. package/dist/esm/langchain/index.mjs +0 -5
  258. package/dist/esm/langchain/index.mjs.map +0 -1
  259. package/dist/esm/langchain/language_models/chat_models.mjs +0 -2
  260. package/dist/esm/langchain/language_models/chat_models.mjs.map +0 -1
  261. package/dist/esm/langchain/messages/tool.mjs +0 -2
  262. package/dist/esm/langchain/messages/tool.mjs.map +0 -1
  263. package/dist/esm/langchain/messages.mjs +0 -2
  264. package/dist/esm/langchain/messages.mjs.map +0 -1
  265. package/dist/esm/langchain/openai.mjs +0 -2
  266. package/dist/esm/langchain/openai.mjs.map +0 -1
  267. package/dist/esm/langchain/prompts.mjs +0 -2
  268. package/dist/esm/langchain/prompts.mjs.map +0 -1
  269. package/dist/esm/langchain/runnables.mjs +0 -2
  270. package/dist/esm/langchain/runnables.mjs.map +0 -1
  271. package/dist/esm/langchain/tools.mjs +0 -2
  272. package/dist/esm/langchain/tools.mjs.map +0 -1
  273. package/dist/esm/langchain/utils/env.mjs +0 -2
  274. package/dist/esm/langchain/utils/env.mjs.map +0 -1
  275. package/dist/esm/llm/bedrock/cacheSupport.mjs +0 -52
  276. package/dist/esm/llm/bedrock/cacheSupport.mjs.map +0 -1
  277. package/dist/esm/tools/search/tavily-scraper.mjs +0 -186
  278. package/dist/esm/tools/search/tavily-scraper.mjs.map +0 -1
  279. package/dist/esm/tools/search/tavily-search.mjs +0 -370
  280. package/dist/esm/tools/search/tavily-search.mjs.map +0 -1
  281. package/dist/esm/types/agent-cache.mjs +0 -52
  282. package/dist/esm/types/agent-cache.mjs.map +0 -1
  283. package/dist/types/langchain/google-common.d.ts +0 -1
  284. package/dist/types/langchain/index.d.ts +0 -8
  285. package/dist/types/langchain/language_models/chat_models.d.ts +0 -1
  286. package/dist/types/langchain/messages/tool.d.ts +0 -1
  287. package/dist/types/langchain/messages.d.ts +0 -2
  288. package/dist/types/langchain/openai.d.ts +0 -1
  289. package/dist/types/langchain/prompts.d.ts +0 -1
  290. package/dist/types/langchain/runnables.d.ts +0 -2
  291. package/dist/types/langchain/tools.d.ts +0 -2
  292. package/dist/types/langchain/utils/env.d.ts +0 -1
  293. package/dist/types/llm/bedrock/cacheSupport.d.ts +0 -35
  294. package/dist/types/tools/search/tavily-scraper.d.ts +0 -19
  295. package/dist/types/tools/search/tavily-search.d.ts +0 -4
  296. package/dist/types/tools/subagent/types.d.ts +0 -84
  297. package/dist/types/types/agent-cache.d.ts +0 -71
  298. package/src/agents/__tests__/AgentContext.cacheTtl.live.test.ts +0 -259
  299. package/src/agents/__tests__/AgentContext.crossAgentTier1.live.test.ts +0 -266
  300. package/src/agents/__tests__/AgentContext.crossUserCache.live.test.ts +0 -342
  301. package/src/langchain/google-common.ts +0 -1
  302. package/src/langchain/index.ts +0 -8
  303. package/src/langchain/language_models/chat_models.ts +0 -1
  304. package/src/langchain/messages/tool.ts +0 -5
  305. package/src/langchain/messages.ts +0 -21
  306. package/src/langchain/openai.ts +0 -1
  307. package/src/langchain/prompts.ts +0 -1
  308. package/src/langchain/runnables.ts +0 -7
  309. package/src/langchain/tools.ts +0 -8
  310. package/src/langchain/utils/env.ts +0 -1
  311. package/src/llm/anthropic/utils/server-tool-inputs.test.ts +0 -436
  312. package/src/llm/bedrock/cacheSupport.test.ts +0 -99
  313. package/src/llm/bedrock/cacheSupport.ts +0 -53
  314. package/src/tools/search/tavily-scraper.ts +0 -235
  315. package/src/tools/search/tavily-search.ts +0 -424
  316. package/src/tools/search/tavily.test.ts +0 -965
  317. package/src/tools/subagent/types.test.ts +0 -70
  318. package/src/tools/subagent/types.ts +0 -115
  319. package/src/types/agent-cache.ts +0 -74
@@ -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;
@@ -148,7 +148,7 @@ describe('ensureThinkingBlockInMessages', () => {
148
148
  // Bedrock reasoning models produce reasoning on the first AI response,
149
149
  // then subsequent tool calls in the same chain have content: "" with no
150
150
  // reasoning block. These should NOT be converted because the chain
151
- // already has a thinking block standard.
151
+ // already has a thinking block upstream.
152
152
  const messages = [
153
153
  new HumanMessage({ content: 'show me something cool' }),
154
154
  new AIMessage({
@@ -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. 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;
@@ -791,15 +715,14 @@ function extractSkillName(args: unknown): string | undefined {
791
715
  * When SkillTool is invoked, the body is injected as a HumanMessage into LangGraph state
792
716
  * but NOT persisted to conversation history. On follow-up runs the skill body is lost.
793
717
  * Pass `skills` to reconstruct the HumanMessage at the right position after each skill
794
- * ToolMessage. PRs #96 / #97.
718
+ * ToolMessage. Upstream PRs #96 / #97.
795
719
  * @returns - Object containing formatted messages and updated indexTokenCountMap if provided.
796
720
  */
797
721
  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>;
@@ -903,7 +826,7 @@ export const formatAgentMessages = (
903
826
  if (discoveredTools.has(toolName)) {
904
827
  /** Valid tool - keep it */
905
828
  filteredContent.push(part);
906
- // Skill body reconstruction (PRs #96/#97): when a
829
+ // Skill body reconstruction (upstream PRs #96/#97): when a
907
830
  // SkillTool tool_call is present in this assistant turn, mark
908
831
  // the skill name so we can reconstruct the body HumanMessage
909
832
  // after the assistant turn has been pushed.
@@ -1008,14 +931,12 @@ 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
1017
938
  // HumanMessages are excluded from the assistant's token distribution
1018
- // (PR #97 fix).
939
+ // (upstream PR #97 fix).
1019
940
  const endMessageIndex = messages.length;
1020
941
 
1021
942
  if (pendingSkillNames?.size) {
@@ -643,7 +643,7 @@ describe('formatAgentMessages', () => {
643
643
  tool_call: {
644
644
  id: 'commits_1',
645
645
  name: 'list_commits_mcp_github',
646
- args: '{"owner":"illuma-ai","repo":"agents"}',
646
+ args: '{"owner":"librechat","repo":"librechat"}',
647
647
  output:
648
648
  '[{"sha":"abc123","message":"feat: add deferred tools"},{"sha":"def456","message":"fix: tool loading"}]',
649
649
  },
@@ -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
+ });
@@ -10,7 +10,7 @@ import { Providers, GraphEvents, Constants } from '@/common';
10
10
  import { Run } from '@/run';
11
11
 
12
12
  /**
13
- * Repro for the reference consumer setup: event-driven tools via `toolDefinitions`
13
+ * Repro for LibreChat's actual setup: event-driven tools via `toolDefinitions`
14
14
  * + an ON_TOOL_EXECUTE handler that runs the tool. Self-spawn subagent must
15
15
  * be able to drive the SAME tool pipeline.
16
16
  */
@@ -20,7 +20,7 @@ if (!apiKey) {
20
20
  process.exit(1);
21
21
  }
22
22
 
23
- // Simulate consumer: tool definitions only, execution routed via event.
23
+ // Simulate LibreChat: tool definitions only, execution routed via event.
24
24
  const calculatorDef: t.LCTool = {
25
25
  name: 'calculator',
26
26
  description: 'Evaluate a math expression. Use for any arithmetic.',