@illuma-ai/agents 1.0.81

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 (558) hide show
  1. package/README.md +485 -0
  2. package/dist/cjs/agents/AgentContext.cjs +734 -0
  3. package/dist/cjs/agents/AgentContext.cjs.map +1 -0
  4. package/dist/cjs/common/enum.cjs +190 -0
  5. package/dist/cjs/common/enum.cjs.map +1 -0
  6. package/dist/cjs/events.cjs +172 -0
  7. package/dist/cjs/events.cjs.map +1 -0
  8. package/dist/cjs/graphs/Graph.cjs +1615 -0
  9. package/dist/cjs/graphs/Graph.cjs.map +1 -0
  10. package/dist/cjs/graphs/MultiAgentGraph.cjs +890 -0
  11. package/dist/cjs/graphs/MultiAgentGraph.cjs.map +1 -0
  12. package/dist/cjs/instrumentation.cjs +21 -0
  13. package/dist/cjs/instrumentation.cjs.map +1 -0
  14. package/dist/cjs/llm/anthropic/index.cjs +292 -0
  15. package/dist/cjs/llm/anthropic/index.cjs.map +1 -0
  16. package/dist/cjs/llm/anthropic/types.cjs +50 -0
  17. package/dist/cjs/llm/anthropic/types.cjs.map +1 -0
  18. package/dist/cjs/llm/anthropic/utils/message_inputs.cjs +630 -0
  19. package/dist/cjs/llm/anthropic/utils/message_inputs.cjs.map +1 -0
  20. package/dist/cjs/llm/anthropic/utils/message_outputs.cjs +218 -0
  21. package/dist/cjs/llm/anthropic/utils/message_outputs.cjs.map +1 -0
  22. package/dist/cjs/llm/anthropic/utils/tools.cjs +29 -0
  23. package/dist/cjs/llm/anthropic/utils/tools.cjs.map +1 -0
  24. package/dist/cjs/llm/bedrock/index.cjs +282 -0
  25. package/dist/cjs/llm/bedrock/index.cjs.map +1 -0
  26. package/dist/cjs/llm/fake.cjs +97 -0
  27. package/dist/cjs/llm/fake.cjs.map +1 -0
  28. package/dist/cjs/llm/google/index.cjs +216 -0
  29. package/dist/cjs/llm/google/index.cjs.map +1 -0
  30. package/dist/cjs/llm/google/utils/common.cjs +647 -0
  31. package/dist/cjs/llm/google/utils/common.cjs.map +1 -0
  32. package/dist/cjs/llm/openai/index.cjs +1028 -0
  33. package/dist/cjs/llm/openai/index.cjs.map +1 -0
  34. package/dist/cjs/llm/openai/utils/index.cjs +765 -0
  35. package/dist/cjs/llm/openai/utils/index.cjs.map +1 -0
  36. package/dist/cjs/llm/openrouter/index.cjs +212 -0
  37. package/dist/cjs/llm/openrouter/index.cjs.map +1 -0
  38. package/dist/cjs/llm/providers.cjs +43 -0
  39. package/dist/cjs/llm/providers.cjs.map +1 -0
  40. package/dist/cjs/llm/text.cjs +69 -0
  41. package/dist/cjs/llm/text.cjs.map +1 -0
  42. package/dist/cjs/llm/vertexai/index.cjs +329 -0
  43. package/dist/cjs/llm/vertexai/index.cjs.map +1 -0
  44. package/dist/cjs/main.cjs +240 -0
  45. package/dist/cjs/main.cjs.map +1 -0
  46. package/dist/cjs/messages/cache.cjs +387 -0
  47. package/dist/cjs/messages/cache.cjs.map +1 -0
  48. package/dist/cjs/messages/content.cjs +53 -0
  49. package/dist/cjs/messages/content.cjs.map +1 -0
  50. package/dist/cjs/messages/core.cjs +367 -0
  51. package/dist/cjs/messages/core.cjs.map +1 -0
  52. package/dist/cjs/messages/format.cjs +761 -0
  53. package/dist/cjs/messages/format.cjs.map +1 -0
  54. package/dist/cjs/messages/ids.cjs +23 -0
  55. package/dist/cjs/messages/ids.cjs.map +1 -0
  56. package/dist/cjs/messages/prune.cjs +398 -0
  57. package/dist/cjs/messages/prune.cjs.map +1 -0
  58. package/dist/cjs/messages/tools.cjs +96 -0
  59. package/dist/cjs/messages/tools.cjs.map +1 -0
  60. package/dist/cjs/run.cjs +328 -0
  61. package/dist/cjs/run.cjs.map +1 -0
  62. package/dist/cjs/schemas/validate.cjs +324 -0
  63. package/dist/cjs/schemas/validate.cjs.map +1 -0
  64. package/dist/cjs/splitStream.cjs +210 -0
  65. package/dist/cjs/splitStream.cjs.map +1 -0
  66. package/dist/cjs/stream.cjs +620 -0
  67. package/dist/cjs/stream.cjs.map +1 -0
  68. package/dist/cjs/tools/BrowserTools.cjs +248 -0
  69. package/dist/cjs/tools/BrowserTools.cjs.map +1 -0
  70. package/dist/cjs/tools/Calculator.cjs +66 -0
  71. package/dist/cjs/tools/Calculator.cjs.map +1 -0
  72. package/dist/cjs/tools/CodeExecutor.cjs +234 -0
  73. package/dist/cjs/tools/CodeExecutor.cjs.map +1 -0
  74. package/dist/cjs/tools/ProgrammaticToolCalling.cjs +636 -0
  75. package/dist/cjs/tools/ProgrammaticToolCalling.cjs.map +1 -0
  76. package/dist/cjs/tools/ToolNode.cjs +548 -0
  77. package/dist/cjs/tools/ToolNode.cjs.map +1 -0
  78. package/dist/cjs/tools/ToolSearch.cjs +909 -0
  79. package/dist/cjs/tools/ToolSearch.cjs.map +1 -0
  80. package/dist/cjs/tools/handlers.cjs +255 -0
  81. package/dist/cjs/tools/handlers.cjs.map +1 -0
  82. package/dist/cjs/tools/schema.cjs +31 -0
  83. package/dist/cjs/tools/schema.cjs.map +1 -0
  84. package/dist/cjs/tools/search/anthropic.cjs +40 -0
  85. package/dist/cjs/tools/search/anthropic.cjs.map +1 -0
  86. package/dist/cjs/tools/search/content.cjs +140 -0
  87. package/dist/cjs/tools/search/content.cjs.map +1 -0
  88. package/dist/cjs/tools/search/firecrawl.cjs +179 -0
  89. package/dist/cjs/tools/search/firecrawl.cjs.map +1 -0
  90. package/dist/cjs/tools/search/format.cjs +203 -0
  91. package/dist/cjs/tools/search/format.cjs.map +1 -0
  92. package/dist/cjs/tools/search/highlights.cjs +245 -0
  93. package/dist/cjs/tools/search/highlights.cjs.map +1 -0
  94. package/dist/cjs/tools/search/rerankers.cjs +174 -0
  95. package/dist/cjs/tools/search/rerankers.cjs.map +1 -0
  96. package/dist/cjs/tools/search/schema.cjs +117 -0
  97. package/dist/cjs/tools/search/schema.cjs.map +1 -0
  98. package/dist/cjs/tools/search/search.cjs +566 -0
  99. package/dist/cjs/tools/search/search.cjs.map +1 -0
  100. package/dist/cjs/tools/search/serper-scraper.cjs +132 -0
  101. package/dist/cjs/tools/search/serper-scraper.cjs.map +1 -0
  102. package/dist/cjs/tools/search/tool.cjs +456 -0
  103. package/dist/cjs/tools/search/tool.cjs.map +1 -0
  104. package/dist/cjs/tools/search/utils.cjs +66 -0
  105. package/dist/cjs/tools/search/utils.cjs.map +1 -0
  106. package/dist/cjs/types/graph.cjs +29 -0
  107. package/dist/cjs/types/graph.cjs.map +1 -0
  108. package/dist/cjs/utils/contextAnalytics.cjs +66 -0
  109. package/dist/cjs/utils/contextAnalytics.cjs.map +1 -0
  110. package/dist/cjs/utils/events.cjs +31 -0
  111. package/dist/cjs/utils/events.cjs.map +1 -0
  112. package/dist/cjs/utils/graph.cjs +16 -0
  113. package/dist/cjs/utils/graph.cjs.map +1 -0
  114. package/dist/cjs/utils/handlers.cjs +70 -0
  115. package/dist/cjs/utils/handlers.cjs.map +1 -0
  116. package/dist/cjs/utils/llm.cjs +27 -0
  117. package/dist/cjs/utils/llm.cjs.map +1 -0
  118. package/dist/cjs/utils/misc.cjs +56 -0
  119. package/dist/cjs/utils/misc.cjs.map +1 -0
  120. package/dist/cjs/utils/run.cjs +73 -0
  121. package/dist/cjs/utils/run.cjs.map +1 -0
  122. package/dist/cjs/utils/schema.cjs +27 -0
  123. package/dist/cjs/utils/schema.cjs.map +1 -0
  124. package/dist/cjs/utils/title.cjs +125 -0
  125. package/dist/cjs/utils/title.cjs.map +1 -0
  126. package/dist/cjs/utils/tokens.cjs +125 -0
  127. package/dist/cjs/utils/tokens.cjs.map +1 -0
  128. package/dist/cjs/utils/toonFormat.cjs +388 -0
  129. package/dist/cjs/utils/toonFormat.cjs.map +1 -0
  130. package/dist/esm/agents/AgentContext.mjs +732 -0
  131. package/dist/esm/agents/AgentContext.mjs.map +1 -0
  132. package/dist/esm/common/enum.mjs +190 -0
  133. package/dist/esm/common/enum.mjs.map +1 -0
  134. package/dist/esm/events.mjs +164 -0
  135. package/dist/esm/events.mjs.map +1 -0
  136. package/dist/esm/graphs/Graph.mjs +1612 -0
  137. package/dist/esm/graphs/Graph.mjs.map +1 -0
  138. package/dist/esm/graphs/MultiAgentGraph.mjs +888 -0
  139. package/dist/esm/graphs/MultiAgentGraph.mjs.map +1 -0
  140. package/dist/esm/instrumentation.mjs +19 -0
  141. package/dist/esm/instrumentation.mjs.map +1 -0
  142. package/dist/esm/llm/anthropic/index.mjs +290 -0
  143. package/dist/esm/llm/anthropic/index.mjs.map +1 -0
  144. package/dist/esm/llm/anthropic/types.mjs +48 -0
  145. package/dist/esm/llm/anthropic/types.mjs.map +1 -0
  146. package/dist/esm/llm/anthropic/utils/message_inputs.mjs +627 -0
  147. package/dist/esm/llm/anthropic/utils/message_inputs.mjs.map +1 -0
  148. package/dist/esm/llm/anthropic/utils/message_outputs.mjs +216 -0
  149. package/dist/esm/llm/anthropic/utils/message_outputs.mjs.map +1 -0
  150. package/dist/esm/llm/anthropic/utils/tools.mjs +27 -0
  151. package/dist/esm/llm/anthropic/utils/tools.mjs.map +1 -0
  152. package/dist/esm/llm/bedrock/index.mjs +280 -0
  153. package/dist/esm/llm/bedrock/index.mjs.map +1 -0
  154. package/dist/esm/llm/fake.mjs +94 -0
  155. package/dist/esm/llm/fake.mjs.map +1 -0
  156. package/dist/esm/llm/google/index.mjs +214 -0
  157. package/dist/esm/llm/google/index.mjs.map +1 -0
  158. package/dist/esm/llm/google/utils/common.mjs +638 -0
  159. package/dist/esm/llm/google/utils/common.mjs.map +1 -0
  160. package/dist/esm/llm/openai/index.mjs +1018 -0
  161. package/dist/esm/llm/openai/index.mjs.map +1 -0
  162. package/dist/esm/llm/openai/utils/index.mjs +759 -0
  163. package/dist/esm/llm/openai/utils/index.mjs.map +1 -0
  164. package/dist/esm/llm/openrouter/index.mjs +210 -0
  165. package/dist/esm/llm/openrouter/index.mjs.map +1 -0
  166. package/dist/esm/llm/providers.mjs +39 -0
  167. package/dist/esm/llm/providers.mjs.map +1 -0
  168. package/dist/esm/llm/text.mjs +67 -0
  169. package/dist/esm/llm/text.mjs.map +1 -0
  170. package/dist/esm/llm/vertexai/index.mjs +327 -0
  171. package/dist/esm/llm/vertexai/index.mjs.map +1 -0
  172. package/dist/esm/main.mjs +37 -0
  173. package/dist/esm/main.mjs.map +1 -0
  174. package/dist/esm/messages/cache.mjs +382 -0
  175. package/dist/esm/messages/cache.mjs.map +1 -0
  176. package/dist/esm/messages/content.mjs +51 -0
  177. package/dist/esm/messages/content.mjs.map +1 -0
  178. package/dist/esm/messages/core.mjs +359 -0
  179. package/dist/esm/messages/core.mjs.map +1 -0
  180. package/dist/esm/messages/format.mjs +752 -0
  181. package/dist/esm/messages/format.mjs.map +1 -0
  182. package/dist/esm/messages/ids.mjs +21 -0
  183. package/dist/esm/messages/ids.mjs.map +1 -0
  184. package/dist/esm/messages/prune.mjs +393 -0
  185. package/dist/esm/messages/prune.mjs.map +1 -0
  186. package/dist/esm/messages/tools.mjs +93 -0
  187. package/dist/esm/messages/tools.mjs.map +1 -0
  188. package/dist/esm/run.mjs +325 -0
  189. package/dist/esm/run.mjs.map +1 -0
  190. package/dist/esm/schemas/validate.mjs +317 -0
  191. package/dist/esm/schemas/validate.mjs.map +1 -0
  192. package/dist/esm/splitStream.mjs +207 -0
  193. package/dist/esm/splitStream.mjs.map +1 -0
  194. package/dist/esm/stream.mjs +616 -0
  195. package/dist/esm/stream.mjs.map +1 -0
  196. package/dist/esm/tools/BrowserTools.mjs +244 -0
  197. package/dist/esm/tools/BrowserTools.mjs.map +1 -0
  198. package/dist/esm/tools/Calculator.mjs +41 -0
  199. package/dist/esm/tools/Calculator.mjs.map +1 -0
  200. package/dist/esm/tools/CodeExecutor.mjs +226 -0
  201. package/dist/esm/tools/CodeExecutor.mjs.map +1 -0
  202. package/dist/esm/tools/ProgrammaticToolCalling.mjs +622 -0
  203. package/dist/esm/tools/ProgrammaticToolCalling.mjs.map +1 -0
  204. package/dist/esm/tools/ToolNode.mjs +545 -0
  205. package/dist/esm/tools/ToolNode.mjs.map +1 -0
  206. package/dist/esm/tools/ToolSearch.mjs +870 -0
  207. package/dist/esm/tools/ToolSearch.mjs.map +1 -0
  208. package/dist/esm/tools/handlers.mjs +250 -0
  209. package/dist/esm/tools/handlers.mjs.map +1 -0
  210. package/dist/esm/tools/schema.mjs +28 -0
  211. package/dist/esm/tools/schema.mjs.map +1 -0
  212. package/dist/esm/tools/search/anthropic.mjs +37 -0
  213. package/dist/esm/tools/search/anthropic.mjs.map +1 -0
  214. package/dist/esm/tools/search/content.mjs +119 -0
  215. package/dist/esm/tools/search/content.mjs.map +1 -0
  216. package/dist/esm/tools/search/firecrawl.mjs +176 -0
  217. package/dist/esm/tools/search/firecrawl.mjs.map +1 -0
  218. package/dist/esm/tools/search/format.mjs +201 -0
  219. package/dist/esm/tools/search/format.mjs.map +1 -0
  220. package/dist/esm/tools/search/highlights.mjs +243 -0
  221. package/dist/esm/tools/search/highlights.mjs.map +1 -0
  222. package/dist/esm/tools/search/rerankers.mjs +168 -0
  223. package/dist/esm/tools/search/rerankers.mjs.map +1 -0
  224. package/dist/esm/tools/search/schema.mjs +104 -0
  225. package/dist/esm/tools/search/schema.mjs.map +1 -0
  226. package/dist/esm/tools/search/search.mjs +563 -0
  227. package/dist/esm/tools/search/search.mjs.map +1 -0
  228. package/dist/esm/tools/search/serper-scraper.mjs +129 -0
  229. package/dist/esm/tools/search/serper-scraper.mjs.map +1 -0
  230. package/dist/esm/tools/search/tool.mjs +454 -0
  231. package/dist/esm/tools/search/tool.mjs.map +1 -0
  232. package/dist/esm/tools/search/utils.mjs +61 -0
  233. package/dist/esm/tools/search/utils.mjs.map +1 -0
  234. package/dist/esm/types/graph.mjs +26 -0
  235. package/dist/esm/types/graph.mjs.map +1 -0
  236. package/dist/esm/utils/contextAnalytics.mjs +64 -0
  237. package/dist/esm/utils/contextAnalytics.mjs.map +1 -0
  238. package/dist/esm/utils/events.mjs +29 -0
  239. package/dist/esm/utils/events.mjs.map +1 -0
  240. package/dist/esm/utils/graph.mjs +13 -0
  241. package/dist/esm/utils/graph.mjs.map +1 -0
  242. package/dist/esm/utils/handlers.mjs +68 -0
  243. package/dist/esm/utils/handlers.mjs.map +1 -0
  244. package/dist/esm/utils/llm.mjs +24 -0
  245. package/dist/esm/utils/llm.mjs.map +1 -0
  246. package/dist/esm/utils/misc.mjs +53 -0
  247. package/dist/esm/utils/misc.mjs.map +1 -0
  248. package/dist/esm/utils/run.mjs +70 -0
  249. package/dist/esm/utils/run.mjs.map +1 -0
  250. package/dist/esm/utils/schema.mjs +24 -0
  251. package/dist/esm/utils/schema.mjs.map +1 -0
  252. package/dist/esm/utils/title.mjs +122 -0
  253. package/dist/esm/utils/title.mjs.map +1 -0
  254. package/dist/esm/utils/tokens.mjs +121 -0
  255. package/dist/esm/utils/tokens.mjs.map +1 -0
  256. package/dist/esm/utils/toonFormat.mjs +381 -0
  257. package/dist/esm/utils/toonFormat.mjs.map +1 -0
  258. package/dist/types/agents/AgentContext.d.ts +293 -0
  259. package/dist/types/common/enum.d.ts +155 -0
  260. package/dist/types/common/index.d.ts +1 -0
  261. package/dist/types/events.d.ts +31 -0
  262. package/dist/types/graphs/Graph.d.ts +216 -0
  263. package/dist/types/graphs/MultiAgentGraph.d.ts +104 -0
  264. package/dist/types/graphs/index.d.ts +2 -0
  265. package/dist/types/index.d.ts +21 -0
  266. package/dist/types/instrumentation.d.ts +1 -0
  267. package/dist/types/llm/anthropic/index.d.ts +39 -0
  268. package/dist/types/llm/anthropic/types.d.ts +37 -0
  269. package/dist/types/llm/anthropic/utils/message_inputs.d.ts +14 -0
  270. package/dist/types/llm/anthropic/utils/message_outputs.d.ts +14 -0
  271. package/dist/types/llm/anthropic/utils/output_parsers.d.ts +22 -0
  272. package/dist/types/llm/anthropic/utils/tools.d.ts +3 -0
  273. package/dist/types/llm/bedrock/index.d.ts +141 -0
  274. package/dist/types/llm/bedrock/types.d.ts +27 -0
  275. package/dist/types/llm/bedrock/utils/index.d.ts +5 -0
  276. package/dist/types/llm/bedrock/utils/message_inputs.d.ts +31 -0
  277. package/dist/types/llm/bedrock/utils/message_outputs.d.ts +33 -0
  278. package/dist/types/llm/fake.d.ts +31 -0
  279. package/dist/types/llm/google/index.d.ts +24 -0
  280. package/dist/types/llm/google/types.d.ts +42 -0
  281. package/dist/types/llm/google/utils/common.d.ts +34 -0
  282. package/dist/types/llm/google/utils/tools.d.ts +10 -0
  283. package/dist/types/llm/google/utils/zod_to_genai_parameters.d.ts +14 -0
  284. package/dist/types/llm/openai/index.d.ts +127 -0
  285. package/dist/types/llm/openai/types.d.ts +10 -0
  286. package/dist/types/llm/openai/utils/index.d.ts +29 -0
  287. package/dist/types/llm/openrouter/index.d.ts +15 -0
  288. package/dist/types/llm/providers.d.ts +5 -0
  289. package/dist/types/llm/text.d.ts +21 -0
  290. package/dist/types/llm/vertexai/index.d.ts +293 -0
  291. package/dist/types/messages/cache.d.ts +54 -0
  292. package/dist/types/messages/content.d.ts +7 -0
  293. package/dist/types/messages/core.d.ts +14 -0
  294. package/dist/types/messages/format.d.ts +137 -0
  295. package/dist/types/messages/ids.d.ts +3 -0
  296. package/dist/types/messages/index.d.ts +7 -0
  297. package/dist/types/messages/prune.d.ts +52 -0
  298. package/dist/types/messages/reducer.d.ts +9 -0
  299. package/dist/types/messages/tools.d.ts +17 -0
  300. package/dist/types/mockStream.d.ts +32 -0
  301. package/dist/types/prompts/collab.d.ts +1 -0
  302. package/dist/types/prompts/index.d.ts +2 -0
  303. package/dist/types/prompts/taskmanager.d.ts +41 -0
  304. package/dist/types/run.d.ts +41 -0
  305. package/dist/types/schemas/index.d.ts +1 -0
  306. package/dist/types/schemas/validate.d.ts +59 -0
  307. package/dist/types/splitStream.d.ts +37 -0
  308. package/dist/types/stream.d.ts +15 -0
  309. package/dist/types/test/mockTools.d.ts +28 -0
  310. package/dist/types/tools/BrowserTools.d.ts +87 -0
  311. package/dist/types/tools/Calculator.d.ts +34 -0
  312. package/dist/types/tools/CodeExecutor.d.ts +57 -0
  313. package/dist/types/tools/ProgrammaticToolCalling.d.ts +138 -0
  314. package/dist/types/tools/ToolNode.d.ts +51 -0
  315. package/dist/types/tools/ToolSearch.d.ts +219 -0
  316. package/dist/types/tools/handlers.d.ts +22 -0
  317. package/dist/types/tools/schema.d.ts +12 -0
  318. package/dist/types/tools/search/anthropic.d.ts +16 -0
  319. package/dist/types/tools/search/content.d.ts +4 -0
  320. package/dist/types/tools/search/firecrawl.d.ts +54 -0
  321. package/dist/types/tools/search/format.d.ts +5 -0
  322. package/dist/types/tools/search/highlights.d.ts +13 -0
  323. package/dist/types/tools/search/index.d.ts +3 -0
  324. package/dist/types/tools/search/rerankers.d.ts +38 -0
  325. package/dist/types/tools/search/schema.d.ts +103 -0
  326. package/dist/types/tools/search/search.d.ts +8 -0
  327. package/dist/types/tools/search/serper-scraper.d.ts +59 -0
  328. package/dist/types/tools/search/test.d.ts +1 -0
  329. package/dist/types/tools/search/tool.d.ts +3 -0
  330. package/dist/types/tools/search/types.d.ts +575 -0
  331. package/dist/types/tools/search/utils.d.ts +10 -0
  332. package/dist/types/types/graph.d.ts +399 -0
  333. package/dist/types/types/index.d.ts +5 -0
  334. package/dist/types/types/llm.d.ts +105 -0
  335. package/dist/types/types/messages.d.ts +4 -0
  336. package/dist/types/types/run.d.ts +112 -0
  337. package/dist/types/types/stream.d.ts +308 -0
  338. package/dist/types/types/tools.d.ts +296 -0
  339. package/dist/types/utils/contextAnalytics.d.ts +37 -0
  340. package/dist/types/utils/events.d.ts +6 -0
  341. package/dist/types/utils/graph.d.ts +2 -0
  342. package/dist/types/utils/handlers.d.ts +34 -0
  343. package/dist/types/utils/index.d.ts +9 -0
  344. package/dist/types/utils/llm.d.ts +3 -0
  345. package/dist/types/utils/llmConfig.d.ts +3 -0
  346. package/dist/types/utils/logging.d.ts +1 -0
  347. package/dist/types/utils/misc.d.ts +7 -0
  348. package/dist/types/utils/run.d.ts +27 -0
  349. package/dist/types/utils/schema.d.ts +8 -0
  350. package/dist/types/utils/title.d.ts +4 -0
  351. package/dist/types/utils/tokens.d.ts +28 -0
  352. package/dist/types/utils/toonFormat.d.ts +111 -0
  353. package/package.json +190 -0
  354. package/src/agents/AgentContext.test.ts +458 -0
  355. package/src/agents/AgentContext.ts +972 -0
  356. package/src/agents/__tests__/AgentContext.test.ts +805 -0
  357. package/src/agents/__tests__/resolveStructuredOutputMode.test.ts +137 -0
  358. package/src/common/enum.ts +203 -0
  359. package/src/common/index.ts +2 -0
  360. package/src/events.ts +223 -0
  361. package/src/graphs/Graph.ts +2228 -0
  362. package/src/graphs/MultiAgentGraph.ts +1063 -0
  363. package/src/graphs/__tests__/structured-output.integration.test.ts +809 -0
  364. package/src/graphs/__tests__/structured-output.test.ts +183 -0
  365. package/src/graphs/index.ts +2 -0
  366. package/src/index.ts +34 -0
  367. package/src/instrumentation.ts +22 -0
  368. package/src/llm/anthropic/Jacob_Lee_Resume_2023.pdf +0 -0
  369. package/src/llm/anthropic/index.ts +413 -0
  370. package/src/llm/anthropic/llm.spec.ts +1442 -0
  371. package/src/llm/anthropic/types.ts +140 -0
  372. package/src/llm/anthropic/utils/message_inputs.ts +757 -0
  373. package/src/llm/anthropic/utils/message_outputs.ts +289 -0
  374. package/src/llm/anthropic/utils/output_parsers.ts +133 -0
  375. package/src/llm/anthropic/utils/tools.ts +29 -0
  376. package/src/llm/bedrock/__tests__/bedrock-caching.test.ts +495 -0
  377. package/src/llm/bedrock/index.ts +411 -0
  378. package/src/llm/bedrock/llm.spec.ts +616 -0
  379. package/src/llm/bedrock/types.ts +51 -0
  380. package/src/llm/bedrock/utils/index.ts +18 -0
  381. package/src/llm/bedrock/utils/message_inputs.ts +563 -0
  382. package/src/llm/bedrock/utils/message_outputs.ts +310 -0
  383. package/src/llm/fake.ts +133 -0
  384. package/src/llm/google/data/gettysburg10.wav +0 -0
  385. package/src/llm/google/data/hotdog.jpg +0 -0
  386. package/src/llm/google/index.ts +337 -0
  387. package/src/llm/google/llm.spec.ts +934 -0
  388. package/src/llm/google/types.ts +56 -0
  389. package/src/llm/google/utils/common.ts +873 -0
  390. package/src/llm/google/utils/tools.ts +160 -0
  391. package/src/llm/google/utils/zod_to_genai_parameters.ts +86 -0
  392. package/src/llm/openai/index.ts +1366 -0
  393. package/src/llm/openai/types.ts +24 -0
  394. package/src/llm/openai/utils/index.ts +1035 -0
  395. package/src/llm/openai/utils/isReasoningModel.test.ts +90 -0
  396. package/src/llm/openrouter/index.ts +291 -0
  397. package/src/llm/providers.ts +52 -0
  398. package/src/llm/text.ts +94 -0
  399. package/src/llm/vertexai/index.ts +359 -0
  400. package/src/messages/__tests__/tools.test.ts +473 -0
  401. package/src/messages/cache.test.ts +1261 -0
  402. package/src/messages/cache.ts +518 -0
  403. package/src/messages/content.test.ts +362 -0
  404. package/src/messages/content.ts +63 -0
  405. package/src/messages/core.ts +473 -0
  406. package/src/messages/ensureThinkingBlock.test.ts +468 -0
  407. package/src/messages/format.ts +1029 -0
  408. package/src/messages/formatAgentMessages.test.ts +1513 -0
  409. package/src/messages/formatAgentMessages.tools.test.ts +419 -0
  410. package/src/messages/formatMessage.test.ts +693 -0
  411. package/src/messages/ids.ts +26 -0
  412. package/src/messages/index.ts +7 -0
  413. package/src/messages/labelContentByAgent.test.ts +887 -0
  414. package/src/messages/prune.ts +568 -0
  415. package/src/messages/reducer.ts +80 -0
  416. package/src/messages/shiftIndexTokenCountMap.test.ts +81 -0
  417. package/src/messages/tools.ts +108 -0
  418. package/src/mockStream.ts +99 -0
  419. package/src/prompts/collab.ts +6 -0
  420. package/src/prompts/index.ts +2 -0
  421. package/src/prompts/taskmanager.ts +61 -0
  422. package/src/run.ts +467 -0
  423. package/src/schemas/index.ts +2 -0
  424. package/src/schemas/schema-preparation.test.ts +500 -0
  425. package/src/schemas/validate.test.ts +358 -0
  426. package/src/schemas/validate.ts +454 -0
  427. package/src/scripts/abort.ts +157 -0
  428. package/src/scripts/ant_web_search.ts +158 -0
  429. package/src/scripts/ant_web_search_edge_case.ts +162 -0
  430. package/src/scripts/ant_web_search_error_edge_case.ts +148 -0
  431. package/src/scripts/args.ts +48 -0
  432. package/src/scripts/caching.ts +132 -0
  433. package/src/scripts/cli.ts +172 -0
  434. package/src/scripts/cli2.ts +133 -0
  435. package/src/scripts/cli3.ts +184 -0
  436. package/src/scripts/cli4.ts +191 -0
  437. package/src/scripts/cli5.ts +191 -0
  438. package/src/scripts/code_exec.ts +213 -0
  439. package/src/scripts/code_exec_files.ts +236 -0
  440. package/src/scripts/code_exec_multi_session.ts +241 -0
  441. package/src/scripts/code_exec_ptc.ts +334 -0
  442. package/src/scripts/code_exec_session.ts +282 -0
  443. package/src/scripts/code_exec_simple.ts +147 -0
  444. package/src/scripts/content.ts +138 -0
  445. package/src/scripts/empty_input.ts +137 -0
  446. package/src/scripts/handoff-test.ts +135 -0
  447. package/src/scripts/image.ts +178 -0
  448. package/src/scripts/memory.ts +97 -0
  449. package/src/scripts/multi-agent-chain.ts +331 -0
  450. package/src/scripts/multi-agent-conditional.ts +221 -0
  451. package/src/scripts/multi-agent-document-review-chain.ts +197 -0
  452. package/src/scripts/multi-agent-hybrid-flow.ts +310 -0
  453. package/src/scripts/multi-agent-parallel-start.ts +265 -0
  454. package/src/scripts/multi-agent-parallel.ts +394 -0
  455. package/src/scripts/multi-agent-sequence.ts +217 -0
  456. package/src/scripts/multi-agent-supervisor.ts +365 -0
  457. package/src/scripts/multi-agent-test.ts +186 -0
  458. package/src/scripts/parallel-asymmetric-tools-test.ts +274 -0
  459. package/src/scripts/parallel-full-metadata-test.ts +240 -0
  460. package/src/scripts/parallel-tools-test.ts +340 -0
  461. package/src/scripts/programmatic_exec.ts +396 -0
  462. package/src/scripts/programmatic_exec_agent.ts +231 -0
  463. package/src/scripts/search.ts +146 -0
  464. package/src/scripts/sequential-full-metadata-test.ts +197 -0
  465. package/src/scripts/simple.ts +225 -0
  466. package/src/scripts/single-agent-metadata-test.ts +198 -0
  467. package/src/scripts/stream.ts +140 -0
  468. package/src/scripts/test-custom-prompt-key.ts +145 -0
  469. package/src/scripts/test-handoff-input.ts +170 -0
  470. package/src/scripts/test-handoff-preamble.ts +277 -0
  471. package/src/scripts/test-multi-agent-list-handoff.ts +417 -0
  472. package/src/scripts/test-parallel-agent-labeling.ts +325 -0
  473. package/src/scripts/test-parallel-handoffs.ts +291 -0
  474. package/src/scripts/test-thinking-handoff-bedrock.ts +153 -0
  475. package/src/scripts/test-thinking-handoff.ts +155 -0
  476. package/src/scripts/test-tools-before-handoff.ts +226 -0
  477. package/src/scripts/test_code_api.ts +361 -0
  478. package/src/scripts/thinking-bedrock.ts +159 -0
  479. package/src/scripts/thinking.ts +171 -0
  480. package/src/scripts/tool_search.ts +162 -0
  481. package/src/scripts/tools.ts +177 -0
  482. package/src/specs/agent-handoffs.test.ts +888 -0
  483. package/src/specs/anthropic.simple.test.ts +387 -0
  484. package/src/specs/azure.simple.test.ts +364 -0
  485. package/src/specs/cache.simple.test.ts +396 -0
  486. package/src/specs/deepseek.simple.test.ts +283 -0
  487. package/src/specs/emergency-prune.test.ts +407 -0
  488. package/src/specs/moonshot.simple.test.ts +358 -0
  489. package/src/specs/openai.simple.test.ts +311 -0
  490. package/src/specs/openrouter.simple.test.ts +107 -0
  491. package/src/specs/prune.test.ts +901 -0
  492. package/src/specs/reasoning.test.ts +201 -0
  493. package/src/specs/spec.utils.ts +3 -0
  494. package/src/specs/thinking-handoff.test.ts +620 -0
  495. package/src/specs/thinking-prune.test.ts +703 -0
  496. package/src/specs/token-distribution-edge-case.test.ts +316 -0
  497. package/src/specs/token-memoization.test.ts +32 -0
  498. package/src/specs/tool-error.test.ts +198 -0
  499. package/src/splitStream.test.ts +691 -0
  500. package/src/splitStream.ts +234 -0
  501. package/src/stream.test.ts +94 -0
  502. package/src/stream.ts +801 -0
  503. package/src/test/mockTools.ts +386 -0
  504. package/src/tools/BrowserTools.ts +393 -0
  505. package/src/tools/Calculator.test.ts +278 -0
  506. package/src/tools/Calculator.ts +46 -0
  507. package/src/tools/CodeExecutor.ts +270 -0
  508. package/src/tools/ProgrammaticToolCalling.ts +785 -0
  509. package/src/tools/ToolNode.ts +674 -0
  510. package/src/tools/ToolSearch.ts +1095 -0
  511. package/src/tools/__tests__/BrowserTools.test.ts +265 -0
  512. package/src/tools/__tests__/ProgrammaticToolCalling.integration.test.ts +319 -0
  513. package/src/tools/__tests__/ProgrammaticToolCalling.test.ts +1006 -0
  514. package/src/tools/__tests__/ToolSearch.integration.test.ts +162 -0
  515. package/src/tools/__tests__/ToolSearch.test.ts +1003 -0
  516. package/src/tools/handlers.ts +363 -0
  517. package/src/tools/schema.ts +37 -0
  518. package/src/tools/search/anthropic.ts +51 -0
  519. package/src/tools/search/content.test.ts +173 -0
  520. package/src/tools/search/content.ts +147 -0
  521. package/src/tools/search/firecrawl.ts +210 -0
  522. package/src/tools/search/format.ts +250 -0
  523. package/src/tools/search/highlights.ts +320 -0
  524. package/src/tools/search/index.ts +3 -0
  525. package/src/tools/search/jina-reranker.test.ts +130 -0
  526. package/src/tools/search/output.md +2775 -0
  527. package/src/tools/search/rerankers.ts +242 -0
  528. package/src/tools/search/schema.ts +113 -0
  529. package/src/tools/search/search.ts +768 -0
  530. package/src/tools/search/serper-scraper.ts +155 -0
  531. package/src/tools/search/test.html +884 -0
  532. package/src/tools/search/test.md +643 -0
  533. package/src/tools/search/test.ts +159 -0
  534. package/src/tools/search/tool.ts +657 -0
  535. package/src/tools/search/types.ts +665 -0
  536. package/src/tools/search/utils.ts +79 -0
  537. package/src/types/graph.test.ts +218 -0
  538. package/src/types/graph.ts +533 -0
  539. package/src/types/index.ts +6 -0
  540. package/src/types/llm.ts +140 -0
  541. package/src/types/messages.ts +4 -0
  542. package/src/types/run.ts +128 -0
  543. package/src/types/stream.ts +417 -0
  544. package/src/types/tools.ts +355 -0
  545. package/src/utils/contextAnalytics.ts +103 -0
  546. package/src/utils/events.ts +32 -0
  547. package/src/utils/graph.ts +11 -0
  548. package/src/utils/handlers.ts +107 -0
  549. package/src/utils/index.ts +9 -0
  550. package/src/utils/llm.ts +26 -0
  551. package/src/utils/llmConfig.ts +208 -0
  552. package/src/utils/logging.ts +48 -0
  553. package/src/utils/misc.ts +57 -0
  554. package/src/utils/run.ts +106 -0
  555. package/src/utils/schema.ts +35 -0
  556. package/src/utils/title.ts +177 -0
  557. package/src/utils/tokens.ts +142 -0
  558. package/src/utils/toonFormat.ts +475 -0
@@ -0,0 +1,785 @@
1
+ // src/tools/ProgrammaticToolCalling.ts
2
+ import { config } from 'dotenv';
3
+ import fetch, { RequestInit } from 'node-fetch';
4
+ import { HttpsProxyAgent } from 'https-proxy-agent';
5
+ import { getEnvironmentVariable } from '@langchain/core/utils/env';
6
+ import { tool, DynamicStructuredTool } from '@langchain/core/tools';
7
+ import type { ToolCall } from '@langchain/core/messages/tool';
8
+ import type * as t from '@/types';
9
+ import { imageExtRegex, getCodeBaseURL } from './CodeExecutor';
10
+ import { EnvVar, Constants } from '@/common';
11
+
12
+ config();
13
+
14
+ // ============================================================================
15
+ // Constants
16
+ // ============================================================================
17
+
18
+ const imageMessage = 'Image is already displayed to the user';
19
+ const otherMessage = 'File is already downloaded by the user';
20
+ const accessMessage =
21
+ 'Note: Files from previous executions are automatically available and can be modified.';
22
+ const emptyOutputMessage =
23
+ 'stdout: Empty. Ensure you\'re writing output explicitly.\n';
24
+
25
+ /** Default max round-trips to prevent infinite loops */
26
+ const DEFAULT_MAX_ROUND_TRIPS = 20;
27
+
28
+ /** Default execution timeout in milliseconds */
29
+ const DEFAULT_TIMEOUT = 60000;
30
+
31
+ // ============================================================================
32
+ // Schema
33
+ // ============================================================================
34
+
35
+ export const ProgrammaticToolCallingSchema = {
36
+ type: 'object',
37
+ properties: {
38
+ code: {
39
+ type: 'string',
40
+ minLength: 1,
41
+ description: `Python code that calls tools programmatically. Tools are available as async functions.
42
+
43
+ CRITICAL - STATELESS EXECUTION:
44
+ Each call is a fresh Python interpreter. Variables, imports, and data do NOT persist between calls.
45
+ You MUST complete your entire workflow in ONE code block: query → process → output.
46
+ DO NOT split work across multiple calls expecting to reuse variables.
47
+
48
+ Your code is auto-wrapped in async context. Just write logic with await—no boilerplate needed.
49
+
50
+ Example (Complete workflow in one call):
51
+ # Query data
52
+ data = await query_database(sql="SELECT * FROM users")
53
+ # Process it
54
+ df = pd.DataFrame(data)
55
+ summary = df.groupby('region').sum()
56
+ # Output results
57
+ await write_to_sheet(spreadsheet_id=sid, data=summary.to_dict())
58
+ print(f"Wrote {len(summary)} rows")
59
+
60
+ Example (Parallel calls):
61
+ sf, ny = await asyncio.gather(get_weather(city="SF"), get_weather(city="NY"))
62
+ print(f"SF: {sf}, NY: {ny}")
63
+
64
+ Rules:
65
+ - EVERYTHING in one call—no state persists between executions
66
+ - Just write code with await—auto-wrapped in async context
67
+ - DO NOT define async def main() or call asyncio.run()
68
+ - Tools are pre-defined—DO NOT write function definitions
69
+ - Only print() output returns to the model`,
70
+ },
71
+ timeout: {
72
+ type: 'integer',
73
+ minimum: 1000,
74
+ maximum: 300000,
75
+ default: DEFAULT_TIMEOUT,
76
+ description:
77
+ 'Maximum execution time in milliseconds. Default: 60 seconds. Max: 5 minutes.',
78
+ },
79
+ },
80
+ required: ['code'],
81
+ } as const;
82
+
83
+ export const ProgrammaticToolCallingName = Constants.PROGRAMMATIC_TOOL_CALLING;
84
+
85
+ export const ProgrammaticToolCallingDescription = `
86
+ Run tools via Python code. Auto-wrapped in async context—just use \`await\` directly.
87
+
88
+ CRITICAL - STATELESS: Each call is a fresh interpreter. Variables/imports do NOT persist.
89
+ Complete your ENTIRE workflow in ONE call: fetch → process → save. No splitting across calls.
90
+
91
+ Rules:
92
+ - Everything in ONE code block—no state carries over between executions
93
+ - Do NOT define \`async def main()\` or call \`asyncio.run()\`—just write code with await
94
+ - Tools are pre-defined—DO NOT write function definitions
95
+ - Only \`print()\` output returns; tool results are raw dicts/lists/strings
96
+ - Generated files are automatically available in /mnt/data/ for subsequent executions
97
+ - Tool names normalized: hyphens→underscores, keywords get \`_tool\` suffix
98
+
99
+ When to use: loops, conditionals, parallel (\`asyncio.gather\`), multi-step pipelines.
100
+
101
+ Example (complete pipeline):
102
+ data = await query_db(sql="..."); df = process(data); await save_to_sheet(data=df); print("Done")
103
+ `.trim();
104
+
105
+ export const ProgrammaticToolCallingDefinition = {
106
+ name: ProgrammaticToolCallingName,
107
+ description: ProgrammaticToolCallingDescription,
108
+ schema: ProgrammaticToolCallingSchema,
109
+ } as const;
110
+
111
+ // ============================================================================
112
+ // Helper Functions
113
+ // ============================================================================
114
+
115
+ /** Python reserved keywords that get `_tool` suffix in Code API */
116
+ const PYTHON_KEYWORDS = new Set([
117
+ 'False',
118
+ 'None',
119
+ 'True',
120
+ 'and',
121
+ 'as',
122
+ 'assert',
123
+ 'async',
124
+ 'await',
125
+ 'break',
126
+ 'class',
127
+ 'continue',
128
+ 'def',
129
+ 'del',
130
+ 'elif',
131
+ 'else',
132
+ 'except',
133
+ 'finally',
134
+ 'for',
135
+ 'from',
136
+ 'global',
137
+ 'if',
138
+ 'import',
139
+ 'in',
140
+ 'is',
141
+ 'lambda',
142
+ 'nonlocal',
143
+ 'not',
144
+ 'or',
145
+ 'pass',
146
+ 'raise',
147
+ 'return',
148
+ 'try',
149
+ 'while',
150
+ 'with',
151
+ 'yield',
152
+ ]);
153
+
154
+ /**
155
+ * Normalizes a tool name to Python identifier format.
156
+ * Must match the Code API's `normalizePythonFunctionName` exactly:
157
+ * 1. Replace hyphens and spaces with underscores
158
+ * 2. Remove any other invalid characters
159
+ * 3. Prefix with underscore if starts with number
160
+ * 4. Append `_tool` if it's a Python keyword
161
+ * @param name - The tool name to normalize
162
+ * @returns Normalized Python-safe identifier
163
+ */
164
+ export function normalizeToPythonIdentifier(name: string): string {
165
+ let normalized = name.replace(/[-\s]/g, '_');
166
+
167
+ normalized = normalized.replace(/[^a-zA-Z0-9_]/g, '');
168
+
169
+ if (/^[0-9]/.test(normalized)) {
170
+ normalized = '_' + normalized;
171
+ }
172
+
173
+ if (PYTHON_KEYWORDS.has(normalized)) {
174
+ normalized = normalized + '_tool';
175
+ }
176
+
177
+ return normalized;
178
+ }
179
+
180
+ /**
181
+ * Extracts tool names that are actually called in the Python code.
182
+ * Handles hyphen/underscore conversion since Python identifiers use underscores.
183
+ * @param code - The Python code to analyze
184
+ * @param toolNameMap - Map from normalized Python name to original tool name
185
+ * @returns Set of original tool names found in the code
186
+ */
187
+ export function extractUsedToolNames(
188
+ code: string,
189
+ toolNameMap: Map<string, string>
190
+ ): Set<string> {
191
+ const usedTools = new Set<string>();
192
+
193
+ for (const [pythonName, originalName] of toolNameMap) {
194
+ const escapedName = pythonName.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
195
+ const pattern = new RegExp(`\\b${escapedName}\\s*\\(`, 'g');
196
+
197
+ if (pattern.test(code)) {
198
+ usedTools.add(originalName);
199
+ }
200
+ }
201
+
202
+ return usedTools;
203
+ }
204
+
205
+ /**
206
+ * Filters tool definitions to only include tools actually used in the code.
207
+ * Handles the hyphen-to-underscore conversion for Python compatibility.
208
+ * @param toolDefs - All available tool definitions
209
+ * @param code - The Python code to analyze
210
+ * @param debug - Enable debug logging
211
+ * @returns Filtered array of tool definitions
212
+ */
213
+ export function filterToolsByUsage(
214
+ toolDefs: t.LCTool[],
215
+ code: string,
216
+ debug = false
217
+ ): t.LCTool[] {
218
+ const toolNameMap = new Map<string, string>();
219
+ for (const tool of toolDefs) {
220
+ const pythonName = normalizeToPythonIdentifier(tool.name);
221
+ toolNameMap.set(pythonName, tool.name);
222
+ }
223
+
224
+ const usedToolNames = extractUsedToolNames(code, toolNameMap);
225
+
226
+ if (debug) {
227
+ // eslint-disable-next-line no-console
228
+ console.log(
229
+ `[PTC Debug] Tool filtering: found ${usedToolNames.size}/${toolDefs.length} tools in code`
230
+ );
231
+ if (usedToolNames.size > 0) {
232
+ // eslint-disable-next-line no-console
233
+ console.log(
234
+ `[PTC Debug] Matched tools: ${Array.from(usedToolNames).join(', ')}`
235
+ );
236
+ }
237
+ }
238
+
239
+ if (usedToolNames.size === 0) {
240
+ if (debug) {
241
+ // eslint-disable-next-line no-console
242
+ console.log(
243
+ '[PTC Debug] No tools detected in code - sending all tools as fallback'
244
+ );
245
+ }
246
+ return toolDefs;
247
+ }
248
+
249
+ return toolDefs.filter((tool) => usedToolNames.has(tool.name));
250
+ }
251
+
252
+ /**
253
+ * Fetches files from a previous session to make them available for the current execution.
254
+ * Files are returned as CodeEnvFile references to be included in the request.
255
+ * @param baseUrl - The base URL for the Code API
256
+ * @param apiKey - The API key for authentication
257
+ * @param sessionId - The session ID to fetch files from
258
+ * @param proxy - Optional HTTP proxy URL
259
+ * @returns Array of CodeEnvFile references, or empty array if fetch fails
260
+ */
261
+ export async function fetchSessionFiles(
262
+ baseUrl: string,
263
+ apiKey: string,
264
+ sessionId: string,
265
+ proxy?: string
266
+ ): Promise<t.CodeEnvFile[]> {
267
+ try {
268
+ const filesEndpoint = `${baseUrl}/files/${sessionId}?detail=full`;
269
+ const fetchOptions: RequestInit = {
270
+ method: 'GET',
271
+ headers: {
272
+ 'User-Agent': 'Illuma/1.0',
273
+ 'X-API-Key': apiKey,
274
+ },
275
+ };
276
+
277
+ if (proxy != null && proxy !== '') {
278
+ fetchOptions.agent = new HttpsProxyAgent(proxy);
279
+ }
280
+
281
+ const response = await fetch(filesEndpoint, fetchOptions);
282
+ if (!response.ok) {
283
+ throw new Error(`Failed to fetch files for session: ${response.status}`);
284
+ }
285
+
286
+ const files = await response.json();
287
+ if (!Array.isArray(files) || files.length === 0) {
288
+ return [];
289
+ }
290
+
291
+ return files.map((file: Record<string, unknown>) => {
292
+ // Extract the ID from the file name (part after session ID prefix and before extension)
293
+ const nameParts = (file.name as string).split('/');
294
+ const id = nameParts.length > 1 ? nameParts[1].split('.')[0] : '';
295
+
296
+ return {
297
+ session_id: sessionId,
298
+ id,
299
+ name: (file.metadata as Record<string, unknown>)[
300
+ 'original-filename'
301
+ ] as string,
302
+ };
303
+ });
304
+ } catch (error) {
305
+ // eslint-disable-next-line no-console
306
+ console.warn(
307
+ `Failed to fetch files for session: ${sessionId}, ${(error as Error).message}`
308
+ );
309
+ return [];
310
+ }
311
+ }
312
+
313
+ /**
314
+ * Makes an HTTP request to the Code API.
315
+ * @param endpoint - The API endpoint URL
316
+ * @param apiKey - The API key for authentication
317
+ * @param body - The request body
318
+ * @param proxy - Optional HTTP proxy URL
319
+ * @returns The parsed API response
320
+ */
321
+ export async function makeRequest(
322
+ endpoint: string,
323
+ apiKey: string,
324
+ body: Record<string, unknown>,
325
+ proxy?: string
326
+ ): Promise<t.ProgrammaticExecutionResponse> {
327
+ const fetchOptions: RequestInit = {
328
+ method: 'POST',
329
+ headers: {
330
+ 'Content-Type': 'application/json',
331
+ 'User-Agent': 'Illuma/1.0',
332
+ 'X-API-Key': apiKey,
333
+ },
334
+ body: JSON.stringify(body),
335
+ };
336
+
337
+ if (proxy != null && proxy !== '') {
338
+ fetchOptions.agent = new HttpsProxyAgent(proxy);
339
+ }
340
+
341
+ const response = await fetch(endpoint, fetchOptions);
342
+
343
+ if (!response.ok) {
344
+ const errorText = await response.text();
345
+ throw new Error(
346
+ `HTTP error! status: ${response.status}, body: ${errorText}`
347
+ );
348
+ }
349
+
350
+ return (await response.json()) as t.ProgrammaticExecutionResponse;
351
+ }
352
+
353
+ /**
354
+ * Unwraps tool responses that may be formatted as tuples or content blocks.
355
+ * MCP tools return [content, artifacts], we need to extract the raw data.
356
+ * @param result - The raw result from tool.invoke()
357
+ * @param isMCPTool - Whether this is an MCP tool (has mcp property)
358
+ * @returns Unwrapped raw data (string, object, or parsed JSON)
359
+ */
360
+ export function unwrapToolResponse(
361
+ result: unknown,
362
+ isMCPTool: boolean
363
+ ): unknown {
364
+ // Only unwrap if this is an MCP tool and result is a tuple
365
+ if (!isMCPTool) {
366
+ return result;
367
+ }
368
+
369
+ /**
370
+ * Checks if a value is a content block object (has type and text).
371
+ */
372
+ const isContentBlock = (value: unknown): boolean => {
373
+ if (typeof value !== 'object' || value === null || Array.isArray(value)) {
374
+ return false;
375
+ }
376
+ const obj = value as Record<string, unknown>;
377
+ return typeof obj.type === 'string';
378
+ };
379
+
380
+ /**
381
+ * Checks if an array is an array of content blocks.
382
+ */
383
+ const isContentBlockArray = (arr: unknown[]): boolean => {
384
+ return arr.length > 0 && arr.every(isContentBlock);
385
+ };
386
+
387
+ /**
388
+ * Extracts text from a single content block object.
389
+ * Returns the text if it's a text block, otherwise returns null.
390
+ */
391
+ const extractTextFromBlock = (block: unknown): string | null => {
392
+ if (typeof block !== 'object' || block === null) return null;
393
+ const b = block as Record<string, unknown>;
394
+ if (b.type === 'text' && typeof b.text === 'string') {
395
+ return b.text;
396
+ }
397
+ return null;
398
+ };
399
+
400
+ /**
401
+ * Extracts text from content blocks (array or single object).
402
+ * Returns combined text or null if no text blocks found.
403
+ */
404
+ const extractTextFromContent = (content: unknown): string | null => {
405
+ // Single content block object: { type: 'text', text: '...' }
406
+ if (
407
+ typeof content === 'object' &&
408
+ content !== null &&
409
+ !Array.isArray(content)
410
+ ) {
411
+ const text = extractTextFromBlock(content);
412
+ if (text !== null) return text;
413
+ }
414
+
415
+ // Array of content blocks: [{ type: 'text', text: '...' }, ...]
416
+ if (Array.isArray(content) && content.length > 0) {
417
+ const texts = content
418
+ .map(extractTextFromBlock)
419
+ .filter((t): t is string => t !== null);
420
+ if (texts.length > 0) {
421
+ return texts.join('\n');
422
+ }
423
+ }
424
+
425
+ return null;
426
+ };
427
+
428
+ /**
429
+ * Tries to parse a string as JSON if it looks like JSON.
430
+ */
431
+ const maybeParseJSON = (str: string): unknown => {
432
+ const trimmed = str.trim();
433
+ if (trimmed.startsWith('{') || trimmed.startsWith('[')) {
434
+ try {
435
+ return JSON.parse(trimmed);
436
+ } catch {
437
+ return str;
438
+ }
439
+ }
440
+ return str;
441
+ };
442
+
443
+ // Handle array of content blocks at top level FIRST
444
+ // (before checking for tuple, since both are arrays)
445
+ if (Array.isArray(result) && isContentBlockArray(result)) {
446
+ const extractedText = extractTextFromContent(result);
447
+ if (extractedText !== null) {
448
+ return maybeParseJSON(extractedText);
449
+ }
450
+ }
451
+
452
+ // Check if result is a tuple/array with [content, artifacts]
453
+ if (Array.isArray(result) && result.length >= 1) {
454
+ const [content] = result;
455
+
456
+ // If first element is a string, return it (possibly parsed as JSON)
457
+ if (typeof content === 'string') {
458
+ return maybeParseJSON(content);
459
+ }
460
+
461
+ // Try to extract text from content blocks
462
+ const extractedText = extractTextFromContent(content);
463
+ if (extractedText !== null) {
464
+ return maybeParseJSON(extractedText);
465
+ }
466
+
467
+ // If first element is an object (but not a text block), return it
468
+ if (typeof content === 'object' && content !== null) {
469
+ return content;
470
+ }
471
+ }
472
+
473
+ // Handle single content block object at top level (not in tuple)
474
+ const extractedText = extractTextFromContent(result);
475
+ if (extractedText !== null) {
476
+ return maybeParseJSON(extractedText);
477
+ }
478
+
479
+ // Not a formatted response, return as-is
480
+ return result;
481
+ }
482
+
483
+ /**
484
+ * Executes tools in parallel when requested by the API.
485
+ * Uses Promise.all for parallel execution, catching individual errors.
486
+ * Unwraps formatted responses (e.g., MCP tool tuples) to raw data.
487
+ * @param toolCalls - Array of tool calls from the API
488
+ * @param toolMap - Map of tool names to executable tools
489
+ * @returns Array of tool results
490
+ */
491
+ export async function executeTools(
492
+ toolCalls: t.PTCToolCall[],
493
+ toolMap: t.ToolMap
494
+ ): Promise<t.PTCToolResult[]> {
495
+ const executions = toolCalls.map(async (call): Promise<t.PTCToolResult> => {
496
+ const tool = toolMap.get(call.name);
497
+
498
+ if (!tool) {
499
+ return {
500
+ call_id: call.id,
501
+ result: null,
502
+ is_error: true,
503
+ error_message: `Tool '${call.name}' not found. Available tools: ${Array.from(toolMap.keys()).join(', ')}`,
504
+ };
505
+ }
506
+
507
+ try {
508
+ const result = await tool.invoke(call.input, {
509
+ metadata: { [Constants.PROGRAMMATIC_TOOL_CALLING]: true },
510
+ });
511
+
512
+ const isMCPTool = tool.mcp === true;
513
+ const unwrappedResult = unwrapToolResponse(result, isMCPTool);
514
+
515
+ return {
516
+ call_id: call.id,
517
+ result: unwrappedResult,
518
+ is_error: false,
519
+ };
520
+ } catch (error) {
521
+ return {
522
+ call_id: call.id,
523
+ result: null,
524
+ is_error: true,
525
+ error_message: (error as Error).message || 'Tool execution failed',
526
+ };
527
+ }
528
+ });
529
+
530
+ return await Promise.all(executions);
531
+ }
532
+
533
+ /**
534
+ * Formats the completed response for the agent.
535
+ * @param response - The completed API response
536
+ * @returns Tuple of [formatted string, artifact]
537
+ */
538
+ export function formatCompletedResponse(
539
+ response: t.ProgrammaticExecutionResponse
540
+ ): [string, t.ProgrammaticExecutionArtifact] {
541
+ let formatted = '';
542
+
543
+ if (response.stdout != null && response.stdout !== '') {
544
+ formatted += `stdout:\n${response.stdout}\n`;
545
+ } else {
546
+ formatted += emptyOutputMessage;
547
+ }
548
+
549
+ if (response.stderr != null && response.stderr !== '') {
550
+ formatted += `stderr:\n${response.stderr}\n`;
551
+ }
552
+
553
+ if (response.files && response.files.length > 0) {
554
+ formatted += 'Generated files:\n';
555
+
556
+ const fileCount = response.files.length;
557
+ for (let i = 0; i < fileCount; i++) {
558
+ const file = response.files[i];
559
+ const isImage = imageExtRegex.test(file.name);
560
+ formatted += `- /mnt/data/${file.name} | ${isImage ? imageMessage : otherMessage}`;
561
+
562
+ if (i < fileCount - 1) {
563
+ formatted += fileCount <= 3 ? ', ' : ',\n';
564
+ }
565
+ }
566
+
567
+ formatted += `\n\n${accessMessage}`;
568
+ }
569
+
570
+ return [
571
+ formatted.trim(),
572
+ {
573
+ session_id: response.session_id,
574
+ files: response.files,
575
+ },
576
+ ];
577
+ }
578
+
579
+ // ============================================================================
580
+ // Tool Factory
581
+ // ============================================================================
582
+
583
+ /**
584
+ * Creates a Programmatic Tool Calling tool for complex multi-tool workflows.
585
+ *
586
+ * This tool enables AI agents to write Python code that orchestrates multiple
587
+ * tool calls programmatically, reducing LLM round-trips and token usage.
588
+ *
589
+ * The tool map must be provided at runtime via config.configurable.toolMap.
590
+ *
591
+ * @param params - Configuration parameters (apiKey, baseUrl, maxRoundTrips, proxy)
592
+ * @returns A LangChain DynamicStructuredTool for programmatic tool calling
593
+ *
594
+ * @example
595
+ * const ptcTool = createProgrammaticToolCallingTool({
596
+ * apiKey: process.env.CODE_API_KEY,
597
+ * maxRoundTrips: 20
598
+ * });
599
+ *
600
+ * const [output, artifact] = await ptcTool.invoke(
601
+ * { code, tools },
602
+ * { configurable: { toolMap } }
603
+ * );
604
+ */
605
+ export function createProgrammaticToolCallingTool(
606
+ initParams: t.ProgrammaticToolCallingParams = {}
607
+ ): DynamicStructuredTool {
608
+ const apiKey =
609
+ (initParams[EnvVar.CODE_API_KEY] as string | undefined) ??
610
+ initParams.apiKey ??
611
+ getEnvironmentVariable(EnvVar.CODE_API_KEY) ??
612
+ '';
613
+
614
+ if (!apiKey) {
615
+ throw new Error(
616
+ 'No API key provided for programmatic tool calling. ' +
617
+ 'Set CODE_API_KEY environment variable or pass apiKey in initParams.'
618
+ );
619
+ }
620
+
621
+ const baseUrl = initParams.baseUrl ?? getCodeBaseURL();
622
+ const maxRoundTrips = initParams.maxRoundTrips ?? DEFAULT_MAX_ROUND_TRIPS;
623
+ const proxy = initParams.proxy ?? process.env.PROXY;
624
+ const debug = initParams.debug ?? process.env.PTC_DEBUG === 'true';
625
+ const EXEC_ENDPOINT = `${baseUrl}/exec/programmatic`;
626
+
627
+ const description = `
628
+ Run tools via Python code. Auto-wrapped in async context—just use \`await\` directly.
629
+
630
+ CRITICAL - STATELESS: Each call is a fresh interpreter. Variables/imports do NOT persist.
631
+ Complete your ENTIRE workflow in ONE call: fetch → process → save. No splitting across calls.
632
+
633
+ Rules:
634
+ - Everything in ONE code block—no state carries over between executions
635
+ - Do NOT define \`async def main()\` or call \`asyncio.run()\`—just write code with await
636
+ - Tools are pre-defined—DO NOT write function definitions
637
+ - Only \`print()\` output returns; tool results are raw dicts/lists/strings
638
+ - Generated files are automatically available in /mnt/data/ for subsequent executions
639
+ - Tool names normalized: hyphens→underscores, keywords get \`_tool\` suffix
640
+
641
+ When to use: loops, conditionals, parallel (\`asyncio.gather\`), multi-step pipelines.
642
+
643
+ Example (complete pipeline):
644
+ data = await query_db(sql="..."); df = process(data); await save_to_sheet(data=df); print("Done")
645
+ `.trim();
646
+
647
+ return tool(
648
+ async (rawParams, config) => {
649
+ const params = rawParams as { code: string; timeout?: number };
650
+ const { code, timeout = DEFAULT_TIMEOUT } = params;
651
+
652
+ // Extra params injected by ToolNode (follows web_search pattern)
653
+ const { toolMap, toolDefs, session_id, _injected_files } =
654
+ (config.toolCall ?? {}) as ToolCall &
655
+ Partial<t.ProgrammaticCache> & {
656
+ session_id?: string;
657
+ _injected_files?: t.CodeEnvFile[];
658
+ };
659
+
660
+ if (toolMap == null || toolMap.size === 0) {
661
+ throw new Error(
662
+ 'No toolMap provided. ' +
663
+ 'ToolNode should inject this from AgentContext when invoked through the graph.'
664
+ );
665
+ }
666
+
667
+ if (toolDefs == null || toolDefs.length === 0) {
668
+ throw new Error(
669
+ 'No tool definitions provided. ' +
670
+ 'Either pass tools in the input or ensure ToolNode injects toolDefs.'
671
+ );
672
+ }
673
+
674
+ let roundTrip = 0;
675
+
676
+ try {
677
+ // ====================================================================
678
+ // Phase 1: Filter tools and make initial request
679
+ // ====================================================================
680
+
681
+ const effectiveTools = filterToolsByUsage(toolDefs, code, debug);
682
+
683
+ if (debug) {
684
+ // eslint-disable-next-line no-console
685
+ console.log(
686
+ `[PTC Debug] Sending ${effectiveTools.length} tools to API ` +
687
+ `(filtered from ${toolDefs.length})`
688
+ );
689
+ }
690
+
691
+ /**
692
+ * File injection priority:
693
+ * 1. Use _injected_files from ToolNode (avoids /files endpoint race condition)
694
+ * 2. Fall back to fetching from /files endpoint if session_id provided but no injected files
695
+ */
696
+ let files: t.CodeEnvFile[] | undefined;
697
+ if (_injected_files && _injected_files.length > 0) {
698
+ files = _injected_files;
699
+ } else if (session_id != null && session_id.length > 0) {
700
+ files = await fetchSessionFiles(baseUrl, apiKey, session_id, proxy);
701
+ }
702
+
703
+ let response = await makeRequest(
704
+ EXEC_ENDPOINT,
705
+ apiKey,
706
+ {
707
+ code,
708
+ tools: effectiveTools,
709
+ session_id,
710
+ timeout,
711
+ ...(files && files.length > 0 ? { files } : {}),
712
+ },
713
+ proxy
714
+ );
715
+
716
+ // ====================================================================
717
+ // Phase 2: Handle response loop
718
+ // ====================================================================
719
+
720
+ while (response.status === 'tool_call_required') {
721
+ roundTrip++;
722
+
723
+ if (roundTrip > maxRoundTrips) {
724
+ throw new Error(
725
+ `Exceeded maximum round trips (${maxRoundTrips}). ` +
726
+ 'This may indicate an infinite loop, excessive tool calls, ' +
727
+ 'or a logic error in your code.'
728
+ );
729
+ }
730
+
731
+ if (debug) {
732
+ // eslint-disable-next-line no-console
733
+ console.log(
734
+ `[PTC Debug] Round trip ${roundTrip}: ${response.tool_calls?.length ?? 0} tool(s) to execute`
735
+ );
736
+ }
737
+
738
+ const toolResults = await executeTools(
739
+ response.tool_calls ?? [],
740
+ toolMap
741
+ );
742
+
743
+ response = await makeRequest(
744
+ EXEC_ENDPOINT,
745
+ apiKey,
746
+ {
747
+ continuation_token: response.continuation_token,
748
+ tool_results: toolResults,
749
+ },
750
+ proxy
751
+ );
752
+ }
753
+
754
+ // ====================================================================
755
+ // Phase 3: Handle final state
756
+ // ====================================================================
757
+
758
+ if (response.status === 'completed') {
759
+ return formatCompletedResponse(response);
760
+ }
761
+
762
+ if (response.status === 'error') {
763
+ throw new Error(
764
+ `Execution error: ${response.error}` +
765
+ (response.stderr != null && response.stderr !== ''
766
+ ? `\n\nStderr:\n${response.stderr}`
767
+ : '')
768
+ );
769
+ }
770
+
771
+ throw new Error(`Unexpected response status: ${response.status}`);
772
+ } catch (error) {
773
+ throw new Error(
774
+ `Programmatic execution failed: ${(error as Error).message}`
775
+ );
776
+ }
777
+ },
778
+ {
779
+ name: Constants.PROGRAMMATIC_TOOL_CALLING,
780
+ description,
781
+ schema: ProgrammaticToolCallingSchema,
782
+ responseFormat: Constants.CONTENT_AND_ARTIFACT,
783
+ }
784
+ );
785
+ }