@langchain/langgraph 0.4.8 → 1.0.0-alpha.0

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 (494) hide show
  1. package/CHANGELOG.md +7 -2
  2. package/README.md +1 -2
  3. package/dist/_virtual/rolldown_runtime.cjs +25 -0
  4. package/dist/channels/any_value.d.cts +26 -0
  5. package/dist/channels/any_value.d.cts.map +1 -0
  6. package/dist/channels/any_value.d.ts +16 -9
  7. package/dist/channels/any_value.d.ts.map +1 -0
  8. package/dist/channels/base.cjs +97 -133
  9. package/dist/channels/base.cjs.map +1 -0
  10. package/dist/channels/base.d.cts +73 -0
  11. package/dist/channels/base.d.cts.map +1 -0
  12. package/dist/channels/base.d.ts +73 -74
  13. package/dist/channels/base.d.ts.map +1 -0
  14. package/dist/channels/base.js +94 -127
  15. package/dist/channels/base.js.map +1 -1
  16. package/dist/channels/binop.cjs +47 -77
  17. package/dist/channels/binop.cjs.map +1 -0
  18. package/dist/channels/binop.d.cts +22 -0
  19. package/dist/channels/binop.d.cts.map +1 -0
  20. package/dist/channels/binop.d.ts +17 -12
  21. package/dist/channels/binop.d.ts.map +1 -0
  22. package/dist/channels/binop.js +45 -71
  23. package/dist/channels/binop.js.map +1 -1
  24. package/dist/channels/dynamic_barrier_value.d.cts +43 -0
  25. package/dist/channels/dynamic_barrier_value.d.cts.map +1 -0
  26. package/dist/channels/dynamic_barrier_value.d.ts +20 -34
  27. package/dist/channels/dynamic_barrier_value.d.ts.map +1 -0
  28. package/dist/channels/ephemeral_value.cjs +46 -70
  29. package/dist/channels/ephemeral_value.cjs.map +1 -0
  30. package/dist/channels/ephemeral_value.d.cts +23 -0
  31. package/dist/channels/ephemeral_value.d.cts.map +1 -0
  32. package/dist/channels/ephemeral_value.d.ts +18 -11
  33. package/dist/channels/ephemeral_value.d.ts.map +1 -0
  34. package/dist/channels/ephemeral_value.js +45 -65
  35. package/dist/channels/ephemeral_value.js.map +1 -1
  36. package/dist/channels/index.cjs +2 -10
  37. package/dist/channels/index.js +4 -3
  38. package/dist/channels/last_value.cjs +91 -140
  39. package/dist/channels/last_value.cjs.map +1 -0
  40. package/dist/channels/last_value.d.cts +30 -0
  41. package/dist/channels/last_value.d.cts.map +1 -0
  42. package/dist/channels/last_value.d.ts +15 -23
  43. package/dist/channels/last_value.d.ts.map +1 -0
  44. package/dist/channels/last_value.js +88 -133
  45. package/dist/channels/last_value.js.map +1 -1
  46. package/dist/channels/named_barrier_value.cjs +114 -170
  47. package/dist/channels/named_barrier_value.cjs.map +1 -0
  48. package/dist/channels/named_barrier_value.d.cts +33 -0
  49. package/dist/channels/named_barrier_value.d.cts.map +1 -0
  50. package/dist/channels/named_barrier_value.d.ts +19 -29
  51. package/dist/channels/named_barrier_value.d.ts.map +1 -0
  52. package/dist/channels/named_barrier_value.js +112 -163
  53. package/dist/channels/named_barrier_value.js.map +1 -1
  54. package/dist/channels/topic.cjs +63 -96
  55. package/dist/channels/topic.cjs.map +1 -0
  56. package/dist/channels/topic.d.cts +26 -0
  57. package/dist/channels/topic.d.cts.map +1 -0
  58. package/dist/channels/topic.d.ts +21 -18
  59. package/dist/channels/topic.d.ts.map +1 -0
  60. package/dist/channels/topic.js +61 -90
  61. package/dist/channels/topic.js.map +1 -1
  62. package/dist/constants.cjs +373 -452
  63. package/dist/constants.cjs.map +1 -0
  64. package/dist/constants.d.cts +284 -0
  65. package/dist/constants.d.cts.map +1 -0
  66. package/dist/constants.d.ts +112 -148
  67. package/dist/constants.d.ts.map +1 -0
  68. package/dist/constants.js +333 -444
  69. package/dist/constants.js.map +1 -1
  70. package/dist/errors.cjs +150 -179
  71. package/dist/errors.cjs.map +1 -0
  72. package/dist/errors.d.cts +80 -0
  73. package/dist/errors.d.cts.map +1 -0
  74. package/dist/errors.d.ts +55 -46
  75. package/dist/errors.d.ts.map +1 -0
  76. package/dist/errors.js +139 -165
  77. package/dist/errors.js.map +1 -1
  78. package/dist/func/index.cjs +289 -290
  79. package/dist/func/index.cjs.map +1 -0
  80. package/dist/func/index.d.cts +289 -0
  81. package/dist/func/index.d.cts.map +1 -0
  82. package/dist/func/index.d.ts +81 -71
  83. package/dist/func/index.d.ts.map +1 -0
  84. package/dist/func/index.js +285 -284
  85. package/dist/func/index.js.map +1 -1
  86. package/dist/func/types.d.cts +64 -0
  87. package/dist/func/types.d.cts.map +1 -0
  88. package/dist/func/types.d.ts +24 -19
  89. package/dist/func/types.d.ts.map +1 -0
  90. package/dist/graph/annotation.cjs +96 -120
  91. package/dist/graph/annotation.cjs.map +1 -0
  92. package/dist/graph/annotation.d.cts +116 -0
  93. package/dist/graph/annotation.d.cts.map +1 -0
  94. package/dist/graph/annotation.d.ts +33 -34
  95. package/dist/graph/annotation.d.ts.map +1 -0
  96. package/dist/graph/annotation.js +91 -112
  97. package/dist/graph/annotation.js.map +1 -1
  98. package/dist/graph/graph.cjs +419 -723
  99. package/dist/graph/graph.cjs.map +1 -0
  100. package/dist/graph/graph.d.cts +131 -0
  101. package/dist/graph/graph.d.cts.map +1 -0
  102. package/dist/graph/graph.d.ts +122 -91
  103. package/dist/graph/graph.d.ts.map +1 -0
  104. package/dist/graph/graph.js +412 -713
  105. package/dist/graph/graph.js.map +1 -1
  106. package/dist/graph/index.cjs +4 -17
  107. package/dist/graph/index.js +6 -5
  108. package/dist/graph/message.cjs +59 -104
  109. package/dist/graph/message.cjs.map +1 -0
  110. package/dist/graph/message.d.cts +19 -0
  111. package/dist/graph/message.d.cts.map +1 -0
  112. package/dist/graph/message.d.ts +11 -10
  113. package/dist/graph/message.d.ts.map +1 -0
  114. package/dist/graph/message.js +56 -98
  115. package/dist/graph/message.js.map +1 -1
  116. package/dist/graph/messages_annotation.cjs +106 -106
  117. package/dist/graph/messages_annotation.cjs.map +1 -0
  118. package/dist/graph/messages_annotation.d.cts +111 -0
  119. package/dist/graph/messages_annotation.d.cts.map +1 -0
  120. package/dist/graph/messages_annotation.d.ts +18 -9
  121. package/dist/graph/messages_annotation.d.ts.map +1 -0
  122. package/dist/graph/messages_annotation.js +100 -100
  123. package/dist/graph/messages_annotation.js.map +1 -1
  124. package/dist/graph/state.cjs +476 -777
  125. package/dist/graph/state.cjs.map +1 -0
  126. package/dist/graph/state.d.cts +216 -0
  127. package/dist/graph/state.d.cts.map +1 -0
  128. package/dist/graph/state.d.ts +129 -134
  129. package/dist/graph/state.d.ts.map +1 -0
  130. package/dist/graph/state.js +470 -768
  131. package/dist/graph/state.js.map +1 -1
  132. package/dist/graph/zod/index.cjs +10 -21
  133. package/dist/graph/zod/index.d.cts +3 -0
  134. package/dist/graph/zod/index.d.ts +3 -3
  135. package/dist/graph/zod/index.js +4 -4
  136. package/dist/graph/zod/meta.cjs +142 -177
  137. package/dist/graph/zod/meta.cjs.map +1 -0
  138. package/dist/graph/zod/meta.d.cts +116 -0
  139. package/dist/graph/zod/meta.d.cts.map +1 -0
  140. package/dist/graph/zod/meta.d.ts +99 -97
  141. package/dist/graph/zod/meta.d.ts.map +1 -0
  142. package/dist/graph/zod/meta.js +136 -170
  143. package/dist/graph/zod/meta.js.map +1 -1
  144. package/dist/graph/zod/plugin.cjs +36 -39
  145. package/dist/graph/zod/plugin.cjs.map +1 -0
  146. package/dist/graph/zod/plugin.js +34 -35
  147. package/dist/graph/zod/plugin.js.map +1 -1
  148. package/dist/graph/zod/schema.cjs +82 -110
  149. package/dist/graph/zod/schema.cjs.map +1 -0
  150. package/dist/graph/zod/schema.d.cts +38 -0
  151. package/dist/graph/zod/schema.d.cts.map +1 -0
  152. package/dist/graph/zod/schema.d.ts +12 -6
  153. package/dist/graph/zod/schema.d.ts.map +1 -0
  154. package/dist/graph/zod/schema.js +77 -103
  155. package/dist/graph/zod/schema.js.map +1 -1
  156. package/dist/graph/zod/zod-registry.cjs +41 -47
  157. package/dist/graph/zod/zod-registry.cjs.map +1 -0
  158. package/dist/graph/zod/zod-registry.d.cts +51 -0
  159. package/dist/graph/zod/zod-registry.d.cts.map +1 -0
  160. package/dist/graph/zod/zod-registry.d.ts +34 -26
  161. package/dist/graph/zod/zod-registry.d.ts.map +1 -0
  162. package/dist/graph/zod/zod-registry.js +37 -41
  163. package/dist/graph/zod/zod-registry.js.map +1 -1
  164. package/dist/hash.cjs +205 -267
  165. package/dist/hash.cjs.map +1 -0
  166. package/dist/hash.js +205 -265
  167. package/dist/hash.js.map +1 -1
  168. package/dist/index.cjs +110 -33
  169. package/dist/index.cjs.map +1 -0
  170. package/dist/index.d.cts +25 -0
  171. package/dist/index.d.ts +25 -5
  172. package/dist/index.js +18 -7
  173. package/dist/index.js.map +1 -1
  174. package/dist/interrupt.cjs +79 -85
  175. package/dist/interrupt.cjs.map +1 -0
  176. package/dist/interrupt.d.cts +49 -0
  177. package/dist/interrupt.d.cts.map +1 -0
  178. package/dist/interrupt.d.ts +6 -1
  179. package/dist/interrupt.d.ts.map +1 -0
  180. package/dist/interrupt.js +76 -80
  181. package/dist/interrupt.js.map +1 -1
  182. package/dist/prebuilt/agentName.cjs +139 -172
  183. package/dist/prebuilt/agentName.cjs.map +1 -0
  184. package/dist/prebuilt/agentName.d.cts +42 -0
  185. package/dist/prebuilt/agentName.d.cts.map +1 -0
  186. package/dist/prebuilt/agentName.d.ts +13 -21
  187. package/dist/prebuilt/agentName.d.ts.map +1 -0
  188. package/dist/prebuilt/agentName.js +139 -168
  189. package/dist/prebuilt/agentName.js.map +1 -1
  190. package/dist/prebuilt/agent_executor.cjs +42 -80
  191. package/dist/prebuilt/agent_executor.cjs.map +1 -0
  192. package/dist/prebuilt/agent_executor.d.cts +57 -0
  193. package/dist/prebuilt/agent_executor.d.cts.map +1 -0
  194. package/dist/prebuilt/agent_executor.d.ts +46 -37
  195. package/dist/prebuilt/agent_executor.d.ts.map +1 -0
  196. package/dist/prebuilt/agent_executor.js +40 -75
  197. package/dist/prebuilt/agent_executor.js.map +1 -1
  198. package/dist/prebuilt/chat_agent_executor.cjs +66 -128
  199. package/dist/prebuilt/chat_agent_executor.cjs.map +1 -0
  200. package/dist/prebuilt/chat_agent_executor.d.cts +23 -0
  201. package/dist/prebuilt/chat_agent_executor.d.cts.map +1 -0
  202. package/dist/prebuilt/chat_agent_executor.d.ts +18 -10
  203. package/dist/prebuilt/chat_agent_executor.d.ts.map +1 -0
  204. package/dist/prebuilt/chat_agent_executor.js +63 -123
  205. package/dist/prebuilt/chat_agent_executor.js.map +1 -1
  206. package/dist/prebuilt/index.cjs +15 -18
  207. package/dist/prebuilt/index.d.cts +8 -0
  208. package/dist/prebuilt/index.d.ts +8 -8
  209. package/dist/prebuilt/index.js +8 -7
  210. package/dist/prebuilt/interrupt.d.cts +73 -0
  211. package/dist/prebuilt/interrupt.d.cts.map +1 -0
  212. package/dist/prebuilt/interrupt.d.ts +32 -15
  213. package/dist/prebuilt/interrupt.d.ts.map +1 -0
  214. package/dist/prebuilt/react_agent_executor.cjs +317 -473
  215. package/dist/prebuilt/react_agent_executor.cjs.map +1 -0
  216. package/dist/prebuilt/react_agent_executor.d.cts +229 -0
  217. package/dist/prebuilt/react_agent_executor.d.cts.map +1 -0
  218. package/dist/prebuilt/react_agent_executor.d.ts +171 -143
  219. package/dist/prebuilt/react_agent_executor.d.ts.map +1 -0
  220. package/dist/prebuilt/react_agent_executor.js +315 -465
  221. package/dist/prebuilt/react_agent_executor.js.map +1 -1
  222. package/dist/prebuilt/tool_executor.cjs +45 -67
  223. package/dist/prebuilt/tool_executor.cjs.map +1 -0
  224. package/dist/prebuilt/tool_executor.d.cts +42 -0
  225. package/dist/prebuilt/tool_executor.d.cts.map +1 -0
  226. package/dist/prebuilt/tool_executor.d.ts +30 -24
  227. package/dist/prebuilt/tool_executor.d.ts.map +1 -0
  228. package/dist/prebuilt/tool_executor.js +44 -63
  229. package/dist/prebuilt/tool_executor.js.map +1 -1
  230. package/dist/prebuilt/tool_node.cjs +213 -275
  231. package/dist/prebuilt/tool_node.cjs.map +1 -0
  232. package/dist/prebuilt/tool_node.d.cts +151 -0
  233. package/dist/prebuilt/tool_node.d.cts.map +1 -0
  234. package/dist/prebuilt/tool_node.d.ts +30 -17
  235. package/dist/prebuilt/tool_node.d.ts.map +1 -0
  236. package/dist/prebuilt/tool_node.js +209 -268
  237. package/dist/prebuilt/tool_node.js.map +1 -1
  238. package/dist/pregel/algo.cjs +521 -692
  239. package/dist/pregel/algo.cjs.map +1 -0
  240. package/dist/pregel/algo.d.cts +13 -0
  241. package/dist/pregel/algo.d.cts.map +1 -0
  242. package/dist/pregel/algo.d.ts +8 -38
  243. package/dist/pregel/algo.d.ts.map +1 -0
  244. package/dist/pregel/algo.js +516 -683
  245. package/dist/pregel/algo.js.map +1 -1
  246. package/dist/pregel/call.cjs +46 -42
  247. package/dist/pregel/call.cjs.map +1 -0
  248. package/dist/pregel/call.js +43 -37
  249. package/dist/pregel/call.js.map +1 -1
  250. package/dist/pregel/debug.cjs +153 -223
  251. package/dist/pregel/debug.cjs.map +1 -0
  252. package/dist/pregel/debug.js +152 -215
  253. package/dist/pregel/debug.js.map +1 -1
  254. package/dist/pregel/index.cjs +1134 -1604
  255. package/dist/pregel/index.cjs.map +1 -0
  256. package/dist/pregel/index.d.cts +534 -0
  257. package/dist/pregel/index.d.cts.map +1 -0
  258. package/dist/pregel/index.d.ts +458 -422
  259. package/dist/pregel/index.d.ts.map +1 -0
  260. package/dist/pregel/index.js +1125 -1592
  261. package/dist/pregel/index.js.map +1 -1
  262. package/dist/pregel/io.cjs +127 -234
  263. package/dist/pregel/io.cjs.map +1 -0
  264. package/dist/pregel/io.js +122 -225
  265. package/dist/pregel/io.js.map +1 -1
  266. package/dist/pregel/loop.cjs +539 -954
  267. package/dist/pregel/loop.cjs.map +1 -0
  268. package/dist/pregel/loop.js +536 -948
  269. package/dist/pregel/loop.js.map +1 -1
  270. package/dist/pregel/messages.cjs +104 -196
  271. package/dist/pregel/messages.cjs.map +1 -0
  272. package/dist/pregel/messages.js +102 -191
  273. package/dist/pregel/messages.js.map +1 -1
  274. package/dist/pregel/read.cjs +150 -280
  275. package/dist/pregel/read.cjs.map +1 -0
  276. package/dist/pregel/read.d.cts +51 -0
  277. package/dist/pregel/read.d.cts.map +1 -0
  278. package/dist/pregel/read.d.ts +48 -46
  279. package/dist/pregel/read.d.ts.map +1 -0
  280. package/dist/pregel/read.js +147 -274
  281. package/dist/pregel/read.js.map +1 -1
  282. package/dist/pregel/remote.cjs +339 -458
  283. package/dist/pregel/remote.cjs.map +1 -0
  284. package/dist/pregel/remote.d.cts +121 -0
  285. package/dist/pregel/remote.d.cts.map +1 -0
  286. package/dist/pregel/remote.d.ts +79 -69
  287. package/dist/pregel/remote.d.ts.map +1 -0
  288. package/dist/pregel/remote.js +337 -453
  289. package/dist/pregel/remote.js.map +1 -1
  290. package/dist/pregel/retry.cjs +87 -138
  291. package/dist/pregel/retry.cjs.map +1 -0
  292. package/dist/pregel/retry.js +83 -130
  293. package/dist/pregel/retry.js.map +1 -1
  294. package/dist/pregel/runnable_types.d.cts +25 -0
  295. package/dist/pregel/runnable_types.d.cts.map +1 -0
  296. package/dist/pregel/runnable_types.d.ts +22 -16
  297. package/dist/pregel/runnable_types.d.ts.map +1 -0
  298. package/dist/pregel/runner.cjs +222 -315
  299. package/dist/pregel/runner.cjs.map +1 -0
  300. package/dist/pregel/runner.js +219 -308
  301. package/dist/pregel/runner.js.map +1 -1
  302. package/dist/pregel/stream.cjs +89 -130
  303. package/dist/pregel/stream.cjs.map +1 -0
  304. package/dist/pregel/stream.js +87 -125
  305. package/dist/pregel/stream.js.map +1 -1
  306. package/dist/pregel/types.cjs +25 -62
  307. package/dist/pregel/types.cjs.map +1 -0
  308. package/dist/pregel/types.d.cts +437 -0
  309. package/dist/pregel/types.d.cts.map +1 -0
  310. package/dist/pregel/types.d.ts +377 -431
  311. package/dist/pregel/types.d.ts.map +1 -0
  312. package/dist/pregel/types.js +23 -57
  313. package/dist/pregel/types.js.map +1 -1
  314. package/dist/pregel/utils/config.cjs +100 -147
  315. package/dist/pregel/utils/config.cjs.map +1 -0
  316. package/dist/pregel/utils/config.d.cts +36 -0
  317. package/dist/pregel/utils/config.d.cts.map +1 -0
  318. package/dist/pregel/utils/config.d.ts +12 -9
  319. package/dist/pregel/utils/config.d.ts.map +1 -0
  320. package/dist/pregel/utils/config.js +98 -143
  321. package/dist/pregel/utils/config.js.map +1 -1
  322. package/dist/pregel/utils/index.cjs +87 -125
  323. package/dist/pregel/utils/index.cjs.map +1 -0
  324. package/dist/pregel/utils/index.d.cts +51 -0
  325. package/dist/pregel/utils/index.d.cts.map +1 -0
  326. package/dist/pregel/utils/index.d.ts +45 -61
  327. package/dist/pregel/utils/index.d.ts.map +1 -0
  328. package/dist/pregel/utils/index.js +86 -120
  329. package/dist/pregel/utils/index.js.map +1 -1
  330. package/dist/pregel/utils/subgraph.cjs +15 -26
  331. package/dist/pregel/utils/subgraph.cjs.map +1 -0
  332. package/dist/pregel/utils/subgraph.js +12 -21
  333. package/dist/pregel/utils/subgraph.js.map +1 -1
  334. package/dist/pregel/validate.cjs +42 -92
  335. package/dist/pregel/validate.cjs.map +1 -0
  336. package/dist/pregel/validate.js +39 -84
  337. package/dist/pregel/validate.js.map +1 -1
  338. package/dist/pregel/write.cjs +87 -137
  339. package/dist/pregel/write.cjs.map +1 -0
  340. package/dist/pregel/write.d.cts +35 -0
  341. package/dist/pregel/write.d.cts.map +1 -0
  342. package/dist/pregel/write.d.ts +27 -23
  343. package/dist/pregel/write.d.ts.map +1 -0
  344. package/dist/pregel/write.js +83 -131
  345. package/dist/pregel/write.js.map +1 -1
  346. package/dist/remote.cjs +3 -6
  347. package/dist/remote.d.cts +2 -0
  348. package/dist/remote.d.ts +2 -1
  349. package/dist/remote.js +3 -2
  350. package/dist/setup/async_local_storage.cjs +10 -7
  351. package/dist/setup/async_local_storage.cjs.map +1 -0
  352. package/dist/setup/async_local_storage.js +7 -2
  353. package/dist/setup/async_local_storage.js.map +1 -1
  354. package/dist/ui/index.cjs +4 -0
  355. package/dist/ui/index.d.cts +5 -0
  356. package/dist/ui/index.d.ts +5 -0
  357. package/dist/ui/index.js +3 -0
  358. package/dist/ui/stream.cjs +145 -0
  359. package/dist/ui/stream.cjs.map +1 -0
  360. package/dist/ui/stream.d.cts +25 -0
  361. package/dist/ui/stream.d.cts.map +1 -0
  362. package/dist/ui/stream.d.ts +25 -0
  363. package/dist/ui/stream.d.ts.map +1 -0
  364. package/dist/ui/stream.js +143 -0
  365. package/dist/ui/stream.js.map +1 -0
  366. package/dist/ui/types.infer.d.cts +53 -0
  367. package/dist/ui/types.infer.d.cts.map +1 -0
  368. package/dist/ui/types.infer.d.ts +53 -0
  369. package/dist/ui/types.infer.d.ts.map +1 -0
  370. package/dist/ui/types.message.d.cts +95 -0
  371. package/dist/ui/types.message.d.cts.map +1 -0
  372. package/dist/ui/types.message.d.ts +95 -0
  373. package/dist/ui/types.message.d.ts.map +1 -0
  374. package/dist/ui/types.schema.d.cts +228 -0
  375. package/dist/ui/types.schema.d.cts.map +1 -0
  376. package/dist/ui/types.schema.d.ts +228 -0
  377. package/dist/ui/types.schema.d.ts.map +1 -0
  378. package/dist/utils.cjs +77 -147
  379. package/dist/utils.cjs.map +1 -0
  380. package/dist/utils.d.cts +32 -0
  381. package/dist/utils.d.cts.map +1 -0
  382. package/dist/utils.d.ts +29 -25
  383. package/dist/utils.d.ts.map +1 -0
  384. package/dist/utils.js +73 -140
  385. package/dist/utils.js.map +1 -1
  386. package/dist/web.cjs +97 -55
  387. package/dist/web.d.cts +23 -0
  388. package/dist/web.d.ts +23 -14
  389. package/dist/web.js +15 -8
  390. package/package.json +83 -86
  391. package/dist/channels/any_value.cjs +0 -65
  392. package/dist/channels/any_value.js +0 -61
  393. package/dist/channels/any_value.js.map +0 -1
  394. package/dist/channels/dynamic_barrier_value.cjs +0 -212
  395. package/dist/channels/dynamic_barrier_value.js +0 -207
  396. package/dist/channels/dynamic_barrier_value.js.map +0 -1
  397. package/dist/channels/index.d.ts +0 -7
  398. package/dist/channels/index.js.map +0 -1
  399. package/dist/func/types.cjs +0 -15
  400. package/dist/func/types.js +0 -12
  401. package/dist/func/types.js.map +0 -1
  402. package/dist/graph/index.d.ts +0 -4
  403. package/dist/graph/index.js.map +0 -1
  404. package/dist/graph/message.test.cjs +0 -196
  405. package/dist/graph/message.test.d.ts +0 -1
  406. package/dist/graph/message.test.js +0 -194
  407. package/dist/graph/message.test.js.map +0 -1
  408. package/dist/graph/zod/index.js.map +0 -1
  409. package/dist/graph/zod/plugin.d.ts +0 -28
  410. package/dist/hash.d.ts +0 -2
  411. package/dist/prebuilt/index.js.map +0 -1
  412. package/dist/prebuilt/interrupt.cjs +0 -3
  413. package/dist/prebuilt/interrupt.js +0 -2
  414. package/dist/prebuilt/interrupt.js.map +0 -1
  415. package/dist/pregel/call.d.ts +0 -16
  416. package/dist/pregel/debug.d.ts +0 -41
  417. package/dist/pregel/debug.test.cjs +0 -258
  418. package/dist/pregel/debug.test.d.ts +0 -1
  419. package/dist/pregel/debug.test.js +0 -256
  420. package/dist/pregel/debug.test.js.map +0 -1
  421. package/dist/pregel/io.d.ts +0 -30
  422. package/dist/pregel/io.mapCommand.test.cjs +0 -150
  423. package/dist/pregel/io.mapCommand.test.d.ts +0 -1
  424. package/dist/pregel/io.mapCommand.test.js +0 -148
  425. package/dist/pregel/io.mapCommand.test.js.map +0 -1
  426. package/dist/pregel/loop.d.ts +0 -147
  427. package/dist/pregel/messages.d.ts +0 -30
  428. package/dist/pregel/messages.test.cjs +0 -369
  429. package/dist/pregel/messages.test.d.ts +0 -1
  430. package/dist/pregel/messages.test.js +0 -367
  431. package/dist/pregel/messages.test.js.map +0 -1
  432. package/dist/pregel/read.test.cjs +0 -194
  433. package/dist/pregel/read.test.d.ts +0 -1
  434. package/dist/pregel/read.test.js +0 -192
  435. package/dist/pregel/read.test.js.map +0 -1
  436. package/dist/pregel/retry.d.ts +0 -17
  437. package/dist/pregel/runnable_types.cjs +0 -3
  438. package/dist/pregel/runnable_types.js +0 -2
  439. package/dist/pregel/runnable_types.js.map +0 -1
  440. package/dist/pregel/runner.d.ts +0 -79
  441. package/dist/pregel/runner.test.cjs +0 -66
  442. package/dist/pregel/runner.test.d.ts +0 -1
  443. package/dist/pregel/runner.test.js +0 -64
  444. package/dist/pregel/runner.test.js.map +0 -1
  445. package/dist/pregel/stream.d.ts +0 -40
  446. package/dist/pregel/utils/config.test.cjs +0 -214
  447. package/dist/pregel/utils/config.test.d.ts +0 -1
  448. package/dist/pregel/utils/config.test.js +0 -212
  449. package/dist/pregel/utils/config.test.js.map +0 -1
  450. package/dist/pregel/utils/subgraph.d.ts +0 -4
  451. package/dist/pregel/utils/subgraph.test.cjs +0 -83
  452. package/dist/pregel/utils/subgraph.test.d.ts +0 -1
  453. package/dist/pregel/utils/subgraph.test.js +0 -81
  454. package/dist/pregel/utils/subgraph.test.js.map +0 -1
  455. package/dist/pregel/validate.d.ts +0 -16
  456. package/dist/pregel/validate.test.cjs +0 -220
  457. package/dist/pregel/validate.test.d.ts +0 -1
  458. package/dist/pregel/validate.test.js +0 -218
  459. package/dist/pregel/validate.test.js.map +0 -1
  460. package/dist/pregel/write.test.cjs +0 -181
  461. package/dist/pregel/write.test.d.ts +0 -1
  462. package/dist/pregel/write.test.js +0 -179
  463. package/dist/pregel/write.test.js.map +0 -1
  464. package/dist/remote.js.map +0 -1
  465. package/dist/setup/async_local_storage.d.ts +0 -1
  466. package/dist/web.js.map +0 -1
  467. package/index.cjs +0 -1
  468. package/index.d.cts +0 -1
  469. package/index.d.ts +0 -1
  470. package/index.js +0 -1
  471. package/prebuilt.cjs +0 -1
  472. package/prebuilt.d.cts +0 -1
  473. package/prebuilt.d.ts +0 -1
  474. package/prebuilt.js +0 -1
  475. package/pregel.cjs +0 -1
  476. package/pregel.d.cts +0 -1
  477. package/pregel.d.ts +0 -1
  478. package/pregel.js +0 -1
  479. package/remote.cjs +0 -1
  480. package/remote.d.cts +0 -1
  481. package/remote.d.ts +0 -1
  482. package/remote.js +0 -1
  483. package/web.cjs +0 -1
  484. package/web.d.cts +0 -1
  485. package/web.d.ts +0 -1
  486. package/web.js +0 -1
  487. package/zod/schema.cjs +0 -1
  488. package/zod/schema.d.cts +0 -1
  489. package/zod/schema.d.ts +0 -1
  490. package/zod/schema.js +0 -1
  491. package/zod.cjs +0 -1
  492. package/zod.d.cts +0 -1
  493. package/zod.d.ts +0 -1
  494. package/zod.js +0 -1
@@ -1,1602 +1,1135 @@
1
- /* eslint-disable no-param-reassign */
2
- import { _coerceToRunnable, getCallbackManagerForConfig, mergeConfigs, patchConfig, Runnable, RunnableSequence, } from "@langchain/core/runnables";
3
- import { compareChannelVersions, copyCheckpoint, emptyCheckpoint, SCHEDULED, uuid5, } from "@langchain/langgraph-checkpoint";
4
- import { createCheckpoint, emptyChannels, getOnlyChannels, } from "../channels/base.js";
5
- import { CHECKPOINT_NAMESPACE_END, CHECKPOINT_NAMESPACE_SEPARATOR, CONFIG_KEY_CHECKPOINTER, CONFIG_KEY_NODE_FINISHED, CONFIG_KEY_READ, CONFIG_KEY_SEND, CONFIG_KEY_STREAM, CONFIG_KEY_TASK_ID, COPY, END, ERROR, INPUT, INTERRUPT, isInterrupted, NULL_TASK_ID, PUSH, CONFIG_KEY_DURABILITY, CONFIG_KEY_CHECKPOINT_NS, TASKS, } from "../constants.js";
6
- import { GraphRecursionError, GraphValueError, InvalidUpdateError, } from "../errors.js";
1
+ import { GraphRecursionError, GraphValueError, InvalidUpdateError } from "../errors.js";
2
+ import { createCheckpoint, emptyChannels, getOnlyChannels } from "../channels/base.js";
3
+ import { CHECKPOINT_NAMESPACE_END, CHECKPOINT_NAMESPACE_SEPARATOR, CONFIG_KEY_CHECKPOINTER, CONFIG_KEY_CHECKPOINT_NS, CONFIG_KEY_DURABILITY, CONFIG_KEY_NODE_FINISHED, CONFIG_KEY_READ, CONFIG_KEY_SEND, CONFIG_KEY_STREAM, CONFIG_KEY_TASK_ID, COPY, END, ERROR, INPUT, INTERRUPT, NULL_TASK_ID, PUSH, TASKS, isInterrupted } from "../constants.js";
4
+ import { ensureLangGraphConfig, getConfig, recastCheckpointNamespace } from "./utils/config.js";
7
5
  import { gatherIterator, patchConfigurable } from "../utils.js";
8
- import { _applyWrites, _localRead, _prepareNextTasks, } from "./algo.js";
9
- import { printStepCheckpoint, printStepTasks, printStepWrites, tasksWithWrites, } from "./debug.js";
6
+ import { ChannelWrite, PASSTHROUGH } from "./write.js";
7
+ import { PregelNode } from "./read.js";
10
8
  import { mapInput, readChannels } from "./io.js";
9
+ import { _coerceToDict, combineAbortSignals, combineCallbacks, getNewChannelVersions, patchCheckpointMap } from "./utils/index.js";
10
+ import { _applyWrites, _localRead, _prepareNextTasks } from "./algo.js";
11
+ import { findSubgraphPregel } from "./utils/subgraph.js";
12
+ import { printStepCheckpoint, printStepTasks, printStepWrites, tasksWithWrites } from "./debug.js";
13
+ import { IterableReadableStreamWithAbortSignal, IterableReadableWritableStream } from "./stream.js";
11
14
  import { PregelLoop } from "./loop.js";
12
15
  import { StreamMessagesHandler } from "./messages.js";
13
- import { PregelNode } from "./read.js";
14
16
  import { PregelRunner } from "./runner.js";
15
- import { IterableReadableStreamWithAbortSignal, IterableReadableWritableStream, } from "./stream.js";
16
- import { ensureLangGraphConfig, getConfig, recastCheckpointNamespace, } from "./utils/config.js";
17
- import { _coerceToDict, combineAbortSignals, combineCallbacks, getNewChannelVersions, patchCheckpointMap, } from "./utils/index.js";
18
- import { findSubgraphPregel } from "./utils/subgraph.js";
19
17
  import { validateGraph, validateKeys } from "./validate.js";
20
- import { ChannelWrite, PASSTHROUGH } from "./write.js";
21
18
  import { Topic } from "../channels/topic.js";
19
+ import { SCHEDULED, compareChannelVersions, copyCheckpoint, emptyCheckpoint, uuid5 } from "@langchain/langgraph-checkpoint";
20
+ import { Runnable, RunnableSequence, _coerceToRunnable, getCallbackManagerForConfig, mergeConfigs, patchConfig } from "@langchain/core/runnables";
21
+
22
+ //#region src/pregel/index.ts
22
23
  /**
23
- * Utility class for working with channels in the Pregel system.
24
- * Provides static methods for subscribing to channels and writing to them.
25
- *
26
- * Channels are the communication pathways between nodes in a Pregel graph.
27
- * They enable message passing and state updates between different parts of the graph.
28
- */
29
- export class Channel {
30
- static subscribeTo(channels, options) {
31
- const { key, tags } = {
32
- key: undefined,
33
- tags: undefined,
34
- ...(options ?? {}),
35
- };
36
- if (Array.isArray(channels) && key !== undefined) {
37
- throw new Error("Can't specify a key when subscribing to multiple channels");
38
- }
39
- let channelMappingOrArray;
40
- if (typeof channels === "string") {
41
- if (key) {
42
- channelMappingOrArray = { [key]: channels };
43
- }
44
- else {
45
- channelMappingOrArray = [channels];
46
- }
47
- }
48
- else {
49
- channelMappingOrArray = Object.fromEntries(channels.map((chan) => [chan, chan]));
50
- }
51
- const triggers = Array.isArray(channels) ? channels : [channels];
52
- return new PregelNode({
53
- channels: channelMappingOrArray,
54
- triggers,
55
- tags,
56
- });
57
- }
58
- /**
59
- * Creates a ChannelWrite that specifies how to write values to channels.
60
- * This is used to define how nodes send output to channels.
61
- *
62
- * @example
63
- * ```typescript
64
- * // Write to multiple channels
65
- * const write = Channel.writeTo(["output", "state"]);
66
- *
67
- * // Write with specific values
68
- * const write = Channel.writeTo(["output"], {
69
- * state: "completed",
70
- * result: calculateResult()
71
- * });
72
- *
73
- * // Write with a transformation function
74
- * const write = Channel.writeTo(["output"], {
75
- * result: (x) => processResult(x)
76
- * });
77
- * ```
78
- *
79
- * @param channels - Array of channel names to write to
80
- * @param writes - Optional map of channel names to values or transformations
81
- * @returns A ChannelWrite object that can be used to write to the specified channels
82
- */
83
- static writeTo(channels, writes) {
84
- const channelWriteEntries = [];
85
- for (const channel of channels) {
86
- channelWriteEntries.push({
87
- channel,
88
- value: PASSTHROUGH,
89
- skipNone: false,
90
- });
91
- }
92
- for (const [key, value] of Object.entries(writes ?? {})) {
93
- if (Runnable.isRunnable(value) || typeof value === "function") {
94
- channelWriteEntries.push({
95
- channel: key,
96
- value: PASSTHROUGH,
97
- skipNone: true,
98
- mapper: _coerceToRunnable(value),
99
- });
100
- }
101
- else {
102
- channelWriteEntries.push({
103
- channel: key,
104
- value,
105
- skipNone: false,
106
- });
107
- }
108
- }
109
- return new ChannelWrite(channelWriteEntries);
110
- }
111
- }
112
- // This is a workaround to allow Pregel to override `invoke` / `stream` and `withConfig`
113
- // without having to adhere to the types in the `Runnable` class (thanks to `any`).
114
- // Alternatively we could mark those methods with @ts-ignore / @ts-expect-error,
115
- // but these do not get carried over when building via `tsc`.
116
- class PartialRunnable extends Runnable {
117
- constructor() {
118
- super(...arguments);
119
- Object.defineProperty(this, "lc_namespace", {
120
- enumerable: true,
121
- configurable: true,
122
- writable: true,
123
- value: ["langgraph", "pregel"]
124
- });
125
- }
126
- invoke(_input, _options
127
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
128
- ) {
129
- throw new Error("Not implemented");
130
- }
131
- // Overriden by `Pregel`
132
- withConfig(_config) {
133
- return super.withConfig(_config);
134
- }
135
- // Overriden by `Pregel`
136
- stream(input, options
137
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
138
- ) {
139
- return super.stream(input, options);
140
- }
141
- }
24
+ * Utility class for working with channels in the Pregel system.
25
+ * Provides static methods for subscribing to channels and writing to them.
26
+ *
27
+ * Channels are the communication pathways between nodes in a Pregel graph.
28
+ * They enable message passing and state updates between different parts of the graph.
29
+ */
30
+ var Channel = class {
31
+ static subscribeTo(channels, options) {
32
+ const { key, tags } = {
33
+ key: void 0,
34
+ tags: void 0,
35
+ ...options ?? {}
36
+ };
37
+ if (Array.isArray(channels) && key !== void 0) throw new Error("Can't specify a key when subscribing to multiple channels");
38
+ let channelMappingOrArray;
39
+ if (typeof channels === "string") if (key) channelMappingOrArray = { [key]: channels };
40
+ else channelMappingOrArray = [channels];
41
+ else channelMappingOrArray = Object.fromEntries(channels.map((chan) => [chan, chan]));
42
+ const triggers = Array.isArray(channels) ? channels : [channels];
43
+ return new PregelNode({
44
+ channels: channelMappingOrArray,
45
+ triggers,
46
+ tags
47
+ });
48
+ }
49
+ /**
50
+ * Creates a ChannelWrite that specifies how to write values to channels.
51
+ * This is used to define how nodes send output to channels.
52
+ *
53
+ * @example
54
+ * ```typescript
55
+ * // Write to multiple channels
56
+ * const write = Channel.writeTo(["output", "state"]);
57
+ *
58
+ * // Write with specific values
59
+ * const write = Channel.writeTo(["output"], {
60
+ * state: "completed",
61
+ * result: calculateResult()
62
+ * });
63
+ *
64
+ * // Write with a transformation function
65
+ * const write = Channel.writeTo(["output"], {
66
+ * result: (x) => processResult(x)
67
+ * });
68
+ * ```
69
+ *
70
+ * @param channels - Array of channel names to write to
71
+ * @param writes - Optional map of channel names to values or transformations
72
+ * @returns A ChannelWrite object that can be used to write to the specified channels
73
+ */
74
+ static writeTo(channels, writes) {
75
+ const channelWriteEntries = [];
76
+ for (const channel of channels) channelWriteEntries.push({
77
+ channel,
78
+ value: PASSTHROUGH,
79
+ skipNone: false
80
+ });
81
+ for (const [key, value] of Object.entries(writes ?? {})) if (Runnable.isRunnable(value) || typeof value === "function") channelWriteEntries.push({
82
+ channel: key,
83
+ value: PASSTHROUGH,
84
+ skipNone: true,
85
+ mapper: _coerceToRunnable(value)
86
+ });
87
+ else channelWriteEntries.push({
88
+ channel: key,
89
+ value,
90
+ skipNone: false
91
+ });
92
+ return new ChannelWrite(channelWriteEntries);
93
+ }
94
+ };
95
+ var PartialRunnable = class extends Runnable {
96
+ lc_namespace = ["langgraph", "pregel"];
97
+ invoke(_input, _options) {
98
+ throw new Error("Not implemented");
99
+ }
100
+ withConfig(_config) {
101
+ return super.withConfig(_config);
102
+ }
103
+ stream(input, options) {
104
+ return super.stream(input, options);
105
+ }
106
+ };
142
107
  /**
143
- * The Pregel class is the core runtime engine of LangGraph, implementing a message-passing graph computation model
144
- * inspired by [Google's Pregel system](https://research.google/pubs/pregel-a-system-for-large-scale-graph-processing/).
145
- * It provides the foundation for building reliable, controllable agent workflows that can evolve state over time.
146
- *
147
- * Key features:
148
- * - Message passing between nodes in discrete "supersteps"
149
- * - Built-in persistence layer through checkpointers
150
- * - First-class streaming support for values, updates, and events
151
- * - Human-in-the-loop capabilities via interrupts
152
- * - Support for parallel node execution within supersteps
153
- *
154
- * The Pregel class is not intended to be instantiated directly by consumers. Instead, use the following higher-level APIs:
155
- * - {@link StateGraph}: The main graph class for building agent workflows
156
- * - Compiling a {@link StateGraph} will return a {@link CompiledGraph} instance, which extends `Pregel`
157
- * - Functional API: A declarative approach using tasks and entrypoints
158
- * - A `Pregel` instance is returned by the {@link entrypoint} function
159
- *
160
- * @example
161
- * ```typescript
162
- * // Using StateGraph API
163
- * const graph = new StateGraph(annotation)
164
- * .addNode("nodeA", myNodeFunction)
165
- * .addEdge("nodeA", "nodeB")
166
- * .compile();
167
- *
168
- * // The compiled graph is a Pregel instance
169
- * const result = await graph.invoke(input);
170
- * ```
171
- *
172
- * @example
173
- * ```typescript
174
- * // Using Functional API
175
- * import { task, entrypoint } from "@langchain/langgraph";
176
- * import { MemorySaver } from "@langchain/langgraph-checkpoint";
177
- *
178
- * // Define tasks that can be composed
179
- * const addOne = task("add", async (x: number) => x + 1);
180
- *
181
- * // Create a workflow using the entrypoint function
182
- * const workflow = entrypoint({
183
- * name: "workflow",
184
- * checkpointer: new MemorySaver()
185
- * }, async (numbers: number[]) => {
186
- * // Tasks can be run in parallel
187
- * const results = await Promise.all(numbers.map(n => addOne(n)));
188
- * return results;
189
- * });
190
- *
191
- * // The workflow is a Pregel instance
192
- * const result = await workflow.invoke([1, 2, 3]); // Returns [2, 3, 4]
193
- * ```
194
- *
195
- * @typeParam Nodes - Mapping of node names to their {@link PregelNode} implementations
196
- * @typeParam Channels - Mapping of channel names to their {@link BaseChannel} or {@link ManagedValueSpec} implementations
197
- * @typeParam ContextType - Type of context that can be passed to the graph
198
- * @typeParam InputType - Type of input values accepted by the graph
199
- * @typeParam OutputType - Type of output values produced by the graph
200
- */
201
- export class Pregel extends PartialRunnable {
202
- /**
203
- * Name of the class when serialized
204
- * @internal
205
- */
206
- static lc_name() {
207
- return "LangGraph";
208
- }
209
- /**
210
- * Constructor for Pregel - meant for internal use only.
211
- *
212
- * @internal
213
- */
214
- constructor(fields) {
215
- super(fields);
216
- /** @internal LangChain namespace for serialization necessary because Pregel extends Runnable */
217
- Object.defineProperty(this, "lc_namespace", {
218
- enumerable: true,
219
- configurable: true,
220
- writable: true,
221
- value: ["langgraph", "pregel"]
222
- });
223
- /** @internal Flag indicating this is a Pregel instance - necessary for serialization */
224
- Object.defineProperty(this, "lg_is_pregel", {
225
- enumerable: true,
226
- configurable: true,
227
- writable: true,
228
- value: true
229
- });
230
- /** The nodes in the graph, mapping node names to their PregelNode instances */
231
- Object.defineProperty(this, "nodes", {
232
- enumerable: true,
233
- configurable: true,
234
- writable: true,
235
- value: void 0
236
- });
237
- /** The channels in the graph, mapping channel names to their BaseChannel or ManagedValueSpec instances */
238
- Object.defineProperty(this, "channels", {
239
- enumerable: true,
240
- configurable: true,
241
- writable: true,
242
- value: void 0
243
- });
244
- /**
245
- * The input channels for the graph. These channels receive the initial input when the graph is invoked.
246
- * Can be a single channel key or an array of channel keys.
247
- */
248
- Object.defineProperty(this, "inputChannels", {
249
- enumerable: true,
250
- configurable: true,
251
- writable: true,
252
- value: void 0
253
- });
254
- /**
255
- * The output channels for the graph. These channels contain the final output when the graph completes.
256
- * Can be a single channel key or an array of channel keys.
257
- */
258
- Object.defineProperty(this, "outputChannels", {
259
- enumerable: true,
260
- configurable: true,
261
- writable: true,
262
- value: void 0
263
- });
264
- /** Whether to automatically validate the graph structure when it is compiled. Defaults to true. */
265
- Object.defineProperty(this, "autoValidate", {
266
- enumerable: true,
267
- configurable: true,
268
- writable: true,
269
- value: true
270
- });
271
- /**
272
- * The streaming modes enabled for this graph. Defaults to ["values"].
273
- * Supported modes:
274
- * - "values": Streams the full state after each step
275
- * - "updates": Streams state updates after each step
276
- * - "messages": Streams messages from within nodes
277
- * - "custom": Streams custom events from within nodes
278
- * - "debug": Streams events related to the execution of the graph - useful for tracing & debugging graph execution
279
- */
280
- Object.defineProperty(this, "streamMode", {
281
- enumerable: true,
282
- configurable: true,
283
- writable: true,
284
- value: ["values"]
285
- });
286
- /**
287
- * Optional channels to stream. If not specified, all channels will be streamed.
288
- * Can be a single channel key or an array of channel keys.
289
- */
290
- Object.defineProperty(this, "streamChannels", {
291
- enumerable: true,
292
- configurable: true,
293
- writable: true,
294
- value: void 0
295
- });
296
- /**
297
- * Optional array of node names or "all" to interrupt after executing these nodes.
298
- * Used for implementing human-in-the-loop workflows.
299
- */
300
- Object.defineProperty(this, "interruptAfter", {
301
- enumerable: true,
302
- configurable: true,
303
- writable: true,
304
- value: void 0
305
- });
306
- /**
307
- * Optional array of node names or "all" to interrupt before executing these nodes.
308
- * Used for implementing human-in-the-loop workflows.
309
- */
310
- Object.defineProperty(this, "interruptBefore", {
311
- enumerable: true,
312
- configurable: true,
313
- writable: true,
314
- value: void 0
315
- });
316
- /** Optional timeout in milliseconds for the execution of each superstep */
317
- Object.defineProperty(this, "stepTimeout", {
318
- enumerable: true,
319
- configurable: true,
320
- writable: true,
321
- value: void 0
322
- });
323
- /** Whether to enable debug logging. Defaults to false. */
324
- Object.defineProperty(this, "debug", {
325
- enumerable: true,
326
- configurable: true,
327
- writable: true,
328
- value: false
329
- });
330
- /**
331
- * Optional checkpointer for persisting graph state.
332
- * When provided, saves a checkpoint of the graph state at every superstep.
333
- * When false or undefined, checkpointing is disabled, and the graph will not be able to save or restore state.
334
- */
335
- Object.defineProperty(this, "checkpointer", {
336
- enumerable: true,
337
- configurable: true,
338
- writable: true,
339
- value: void 0
340
- });
341
- /** Optional retry policy for handling failures in node execution */
342
- Object.defineProperty(this, "retryPolicy", {
343
- enumerable: true,
344
- configurable: true,
345
- writable: true,
346
- value: void 0
347
- });
348
- /** The default configuration for graph execution, can be overridden on a per-invocation basis */
349
- Object.defineProperty(this, "config", {
350
- enumerable: true,
351
- configurable: true,
352
- writable: true,
353
- value: void 0
354
- });
355
- /**
356
- * Optional long-term memory store for the graph, allows for persistence & retrieval of data across threads
357
- */
358
- Object.defineProperty(this, "store", {
359
- enumerable: true,
360
- configurable: true,
361
- writable: true,
362
- value: void 0
363
- });
364
- Object.defineProperty(this, "triggerToNodes", {
365
- enumerable: true,
366
- configurable: true,
367
- writable: true,
368
- value: {}
369
- });
370
- /**
371
- * Optional cache for the graph, useful for caching tasks.
372
- */
373
- Object.defineProperty(this, "cache", {
374
- enumerable: true,
375
- configurable: true,
376
- writable: true,
377
- value: void 0
378
- });
379
- let { streamMode } = fields;
380
- if (streamMode != null && !Array.isArray(streamMode)) {
381
- streamMode = [streamMode];
382
- }
383
- this.nodes = fields.nodes;
384
- this.channels = fields.channels;
385
- if (TASKS in this.channels &&
386
- "lc_graph_name" in this.channels[TASKS] &&
387
- this.channels[TASKS].lc_graph_name !== "Topic") {
388
- throw new Error(`Channel '${TASKS}' is reserved and cannot be used in the graph.`);
389
- }
390
- else {
391
- this.channels[TASKS] =
392
- new Topic({ accumulate: false });
393
- }
394
- this.autoValidate = fields.autoValidate ?? this.autoValidate;
395
- this.streamMode = streamMode ?? this.streamMode;
396
- this.inputChannels = fields.inputChannels;
397
- this.outputChannels = fields.outputChannels;
398
- this.streamChannels = fields.streamChannels ?? this.streamChannels;
399
- this.interruptAfter = fields.interruptAfter;
400
- this.interruptBefore = fields.interruptBefore;
401
- this.stepTimeout = fields.stepTimeout ?? this.stepTimeout;
402
- this.debug = fields.debug ?? this.debug;
403
- this.checkpointer = fields.checkpointer;
404
- this.retryPolicy = fields.retryPolicy;
405
- this.config = fields.config;
406
- this.store = fields.store;
407
- this.cache = fields.cache;
408
- this.name = fields.name;
409
- if (this.autoValidate) {
410
- this.validate();
411
- }
412
- }
413
- /**
414
- * Creates a new instance of the Pregel graph with updated configuration.
415
- * This method follows the immutable pattern - instead of modifying the current instance,
416
- * it returns a new instance with the merged configuration.
417
- *
418
- * @example
419
- * ```typescript
420
- * // Create a new instance with debug enabled
421
- * const debugGraph = graph.withConfig({ debug: true });
422
- *
423
- * // Create a new instance with a specific thread ID
424
- * const threadGraph = graph.withConfig({
425
- * configurable: { thread_id: "123" }
426
- * });
427
- * ```
428
- *
429
- * @param config - The configuration to merge with the current configuration
430
- * @returns A new Pregel instance with the merged configuration
431
- */
432
- withConfig(config) {
433
- const mergedConfig = mergeConfigs(this.config, config);
434
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
435
- return new this.constructor({ ...this, config: mergedConfig });
436
- }
437
- /**
438
- * Validates the graph structure to ensure it is well-formed.
439
- * Checks for:
440
- * - No orphaned nodes
441
- * - Valid input/output channel configurations
442
- * - Valid interrupt configurations
443
- *
444
- * @returns this - The Pregel instance for method chaining
445
- * @throws {GraphValidationError} If the graph structure is invalid
446
- */
447
- validate() {
448
- validateGraph({
449
- nodes: this.nodes,
450
- channels: this.channels,
451
- outputChannels: this.outputChannels,
452
- inputChannels: this.inputChannels,
453
- streamChannels: this.streamChannels,
454
- interruptAfterNodes: this.interruptAfter,
455
- interruptBeforeNodes: this.interruptBefore,
456
- });
457
- for (const [name, node] of Object.entries(this.nodes)) {
458
- for (const trigger of node.triggers) {
459
- this.triggerToNodes[trigger] ??= [];
460
- this.triggerToNodes[trigger].push(name);
461
- }
462
- }
463
- return this;
464
- }
465
- /**
466
- * Gets a list of all channels that should be streamed.
467
- * If streamChannels is specified, returns those channels.
468
- * Otherwise, returns all channels in the graph.
469
- *
470
- * @returns Array of channel keys to stream
471
- */
472
- get streamChannelsList() {
473
- if (Array.isArray(this.streamChannels)) {
474
- return this.streamChannels;
475
- }
476
- else if (this.streamChannels) {
477
- return [this.streamChannels];
478
- }
479
- else {
480
- return Object.keys(this.channels);
481
- }
482
- }
483
- /**
484
- * Gets the channels to stream in their original format.
485
- * If streamChannels is specified, returns it as-is (either single key or array).
486
- * Otherwise, returns all channels in the graph as an array.
487
- *
488
- * @returns Channel keys to stream, either as a single key or array
489
- */
490
- get streamChannelsAsIs() {
491
- if (this.streamChannels) {
492
- return this.streamChannels;
493
- }
494
- else {
495
- return Object.keys(this.channels);
496
- }
497
- }
498
- /**
499
- * Gets a drawable representation of the graph structure.
500
- * This is an async version of getGraph() and is the preferred method to use.
501
- *
502
- * @param config - Configuration for generating the graph visualization
503
- * @returns A representation of the graph that can be visualized
504
- */
505
- async getGraphAsync(config) {
506
- return this.getGraph(config);
507
- }
508
- /**
509
- * Gets all subgraphs within this graph.
510
- * A subgraph is a Pregel instance that is nested within a node of this graph.
511
- *
512
- * @deprecated Use getSubgraphsAsync instead. The async method will become the default in the next minor release.
513
- * @param namespace - Optional namespace to filter subgraphs
514
- * @param recurse - Whether to recursively get subgraphs of subgraphs
515
- * @returns Generator yielding tuples of [name, subgraph]
516
- */
517
- *getSubgraphs(namespace, recurse
518
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
519
- ) {
520
- for (const [name, node] of Object.entries(this.nodes)) {
521
- // filter by prefix
522
- if (namespace !== undefined) {
523
- if (!namespace.startsWith(name)) {
524
- continue;
525
- }
526
- }
527
- const candidates = node.subgraphs?.length ? node.subgraphs : [node.bound];
528
- for (const candidate of candidates) {
529
- const graph = findSubgraphPregel(candidate);
530
- if (graph !== undefined) {
531
- if (name === namespace) {
532
- yield [name, graph];
533
- return;
534
- }
535
- if (namespace === undefined) {
536
- yield [name, graph];
537
- }
538
- if (recurse) {
539
- let newNamespace = namespace;
540
- if (namespace !== undefined) {
541
- newNamespace = namespace.slice(name.length + 1);
542
- }
543
- for (const [subgraphName, subgraph] of graph.getSubgraphs(newNamespace, recurse)) {
544
- yield [
545
- `${name}${CHECKPOINT_NAMESPACE_SEPARATOR}${subgraphName}`,
546
- subgraph,
547
- ];
548
- }
549
- }
550
- }
551
- }
552
- }
553
- }
554
- /**
555
- * Gets all subgraphs within this graph asynchronously.
556
- * A subgraph is a Pregel instance that is nested within a node of this graph.
557
- *
558
- * @param namespace - Optional namespace to filter subgraphs
559
- * @param recurse - Whether to recursively get subgraphs of subgraphs
560
- * @returns AsyncGenerator yielding tuples of [name, subgraph]
561
- */
562
- async *getSubgraphsAsync(namespace, recurse
563
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
564
- ) {
565
- yield* this.getSubgraphs(namespace, recurse);
566
- }
567
- /**
568
- * Prepares a state snapshot from saved checkpoint data.
569
- * This is an internal method used by getState and getStateHistory.
570
- *
571
- * @param config - Configuration for preparing the snapshot
572
- * @param saved - Optional saved checkpoint data
573
- * @param subgraphCheckpointer - Optional checkpointer for subgraphs
574
- * @param applyPendingWrites - Whether to apply pending writes to tasks and then to channels
575
- * @returns A snapshot of the graph state
576
- * @internal
577
- */
578
- async _prepareStateSnapshot({ config, saved, subgraphCheckpointer, applyPendingWrites = false, }) {
579
- if (saved === undefined) {
580
- return {
581
- values: {},
582
- next: [],
583
- config,
584
- tasks: [],
585
- };
586
- }
587
- // Create all channels
588
- const channels = emptyChannels(this.channels, saved.checkpoint);
589
- // Apply null writes first (from NULL_TASK_ID)
590
- if (saved.pendingWrites?.length) {
591
- const nullWrites = saved.pendingWrites
592
- .filter(([taskId, _]) => taskId === NULL_TASK_ID)
593
- .map(([_, channel, value]) => [String(channel), value]);
594
- if (nullWrites.length > 0) {
595
- _applyWrites(saved.checkpoint, channels, [
596
- {
597
- name: INPUT,
598
- writes: nullWrites,
599
- triggers: [],
600
- },
601
- ], undefined, this.triggerToNodes);
602
- }
603
- }
604
- // Prepare next tasks
605
- const nextTasks = Object.values(_prepareNextTasks(saved.checkpoint, saved.pendingWrites, this.nodes, channels, saved.config, true, { step: (saved.metadata?.step ?? -1) + 1, store: this.store }));
606
- // Find subgraphs
607
- const subgraphs = await gatherIterator(this.getSubgraphsAsync());
608
- const parentNamespace = saved.config.configurable?.checkpoint_ns ?? "";
609
- const taskStates = {};
610
- // Prepare task states for subgraphs
611
- for (const task of nextTasks) {
612
- const matchingSubgraph = subgraphs.find(([name]) => name === task.name);
613
- if (!matchingSubgraph) {
614
- continue;
615
- }
616
- // assemble checkpoint_ns for this task
617
- let taskNs = `${String(task.name)}${CHECKPOINT_NAMESPACE_END}${task.id}`;
618
- if (parentNamespace) {
619
- taskNs = `${parentNamespace}${CHECKPOINT_NAMESPACE_SEPARATOR}${taskNs}`;
620
- }
621
- if (subgraphCheckpointer === undefined) {
622
- // set config as signal that subgraph checkpoints exist
623
- const config = {
624
- configurable: {
625
- thread_id: saved.config.configurable?.thread_id,
626
- checkpoint_ns: taskNs,
627
- },
628
- };
629
- taskStates[task.id] = config;
630
- }
631
- else {
632
- // get the state of the subgraph
633
- const subgraphConfig = {
634
- configurable: {
635
- [CONFIG_KEY_CHECKPOINTER]: subgraphCheckpointer,
636
- thread_id: saved.config.configurable?.thread_id,
637
- checkpoint_ns: taskNs,
638
- },
639
- };
640
- const pregel = matchingSubgraph[1];
641
- taskStates[task.id] = await pregel.getState(subgraphConfig, {
642
- subgraphs: true,
643
- });
644
- }
645
- }
646
- // Apply pending writes to tasks and then to channels if applyPendingWrites is true
647
- if (applyPendingWrites && saved.pendingWrites?.length) {
648
- // Map task IDs to task objects for easy lookup
649
- const nextTaskById = Object.fromEntries(nextTasks.map((task) => [task.id, task]));
650
- // Apply pending writes to the appropriate tasks
651
- for (const [taskId, channel, value] of saved.pendingWrites) {
652
- // Skip special channels and tasks not in nextTasks
653
- if ([ERROR, INTERRUPT, SCHEDULED].includes(channel)) {
654
- continue;
655
- }
656
- if (!(taskId in nextTaskById)) {
657
- continue;
658
- }
659
- // Add the write to the task
660
- nextTaskById[taskId].writes.push([String(channel), value]);
661
- }
662
- // Apply writes from tasks that have writes
663
- const tasksWithWrites = nextTasks.filter((task) => task.writes.length > 0);
664
- if (tasksWithWrites.length > 0) {
665
- _applyWrites(saved.checkpoint, channels, tasksWithWrites, undefined, this.triggerToNodes);
666
- }
667
- }
668
- // Preserve thread_id from the config in metadata
669
- let metadata = saved?.metadata;
670
- if (metadata && saved?.config?.configurable?.thread_id) {
671
- metadata = {
672
- ...metadata,
673
- thread_id: saved.config.configurable.thread_id,
674
- };
675
- }
676
- // Filter next tasks - only include tasks without writes
677
- const nextList = nextTasks
678
- .filter((task) => task.writes.length === 0)
679
- .map((task) => task.name);
680
- // assemble the state snapshot
681
- return {
682
- values: readChannels(channels, this.streamChannelsAsIs),
683
- next: nextList,
684
- tasks: tasksWithWrites(nextTasks, saved?.pendingWrites ?? [], taskStates, this.streamChannelsAsIs),
685
- metadata,
686
- config: patchCheckpointMap(saved.config, saved.metadata),
687
- createdAt: saved.checkpoint.ts,
688
- parentConfig: saved.parentConfig,
689
- };
690
- }
691
- /**
692
- * Gets the current state of the graph.
693
- * Requires a checkpointer to be configured.
694
- *
695
- * @param config - Configuration for retrieving the state
696
- * @param options - Additional options
697
- * @returns A snapshot of the current graph state
698
- * @throws {GraphValueError} If no checkpointer is configured
699
- */
700
- async getState(config, options) {
701
- const checkpointer = config.configurable?.[CONFIG_KEY_CHECKPOINTER] ?? this.checkpointer;
702
- if (!checkpointer) {
703
- throw new GraphValueError("No checkpointer set");
704
- }
705
- const checkpointNamespace = config.configurable?.checkpoint_ns ?? "";
706
- if (checkpointNamespace !== "" &&
707
- config.configurable?.[CONFIG_KEY_CHECKPOINTER] === undefined) {
708
- // remove task_ids from checkpoint_ns
709
- const recastNamespace = recastCheckpointNamespace(checkpointNamespace);
710
- for await (const [name, subgraph] of this.getSubgraphsAsync(recastNamespace, true)) {
711
- if (name === recastNamespace) {
712
- return await subgraph.getState(patchConfigurable(config, {
713
- [CONFIG_KEY_CHECKPOINTER]: checkpointer,
714
- }), { subgraphs: options?.subgraphs });
715
- }
716
- }
717
- throw new Error(`Subgraph with namespace "${recastNamespace}" not found.`);
718
- }
719
- const mergedConfig = mergeConfigs(this.config, config);
720
- const saved = await checkpointer.getTuple(config);
721
- const snapshot = await this._prepareStateSnapshot({
722
- config: mergedConfig,
723
- saved,
724
- subgraphCheckpointer: options?.subgraphs ? checkpointer : undefined,
725
- applyPendingWrites: !config.configurable?.checkpoint_id,
726
- });
727
- return snapshot;
728
- }
729
- /**
730
- * Gets the history of graph states.
731
- * Requires a checkpointer to be configured.
732
- * Useful for:
733
- * - Debugging execution history
734
- * - Implementing time travel
735
- * - Analyzing graph behavior
736
- *
737
- * @param config - Configuration for retrieving the history
738
- * @param options - Options for filtering the history
739
- * @returns An async iterator of state snapshots
740
- * @throws {Error} If no checkpointer is configured
741
- */
742
- async *getStateHistory(config, options) {
743
- const checkpointer = config.configurable?.[CONFIG_KEY_CHECKPOINTER] ?? this.checkpointer;
744
- if (!checkpointer) {
745
- throw new GraphValueError("No checkpointer set");
746
- }
747
- const checkpointNamespace = config.configurable?.checkpoint_ns ?? "";
748
- if (checkpointNamespace !== "" &&
749
- config.configurable?.[CONFIG_KEY_CHECKPOINTER] === undefined) {
750
- const recastNamespace = recastCheckpointNamespace(checkpointNamespace);
751
- // find the subgraph with the matching name
752
- for await (const [name, pregel] of this.getSubgraphsAsync(recastNamespace, true)) {
753
- if (name === recastNamespace) {
754
- yield* pregel.getStateHistory(patchConfigurable(config, {
755
- [CONFIG_KEY_CHECKPOINTER]: checkpointer,
756
- }), options);
757
- return;
758
- }
759
- }
760
- throw new Error(`Subgraph with namespace "${recastNamespace}" not found.`);
761
- }
762
- const mergedConfig = mergeConfigs(this.config, config, {
763
- configurable: { checkpoint_ns: checkpointNamespace },
764
- });
765
- for await (const checkpointTuple of checkpointer.list(mergedConfig, options)) {
766
- yield this._prepareStateSnapshot({
767
- config: checkpointTuple.config,
768
- saved: checkpointTuple,
769
- });
770
- }
771
- }
772
- /**
773
- * Apply updates to the graph state in bulk.
774
- * Requires a checkpointer to be configured.
775
- *
776
- * This method is useful for recreating a thread
777
- * from a list of updates, especially if a checkpoint
778
- * is created as a result of multiple tasks.
779
- *
780
- * @internal The API might change in the future.
781
- *
782
- * @param startConfig - Configuration for the update
783
- * @param updates - The list of updates to apply to graph state
784
- * @returns Updated configuration
785
- * @throws {GraphValueError} If no checkpointer is configured
786
- * @throws {InvalidUpdateError} If the update cannot be attributed to a node or an update can be only applied in sequence.
787
- */
788
- async bulkUpdateState(startConfig, supersteps) {
789
- const checkpointer = startConfig.configurable?.[CONFIG_KEY_CHECKPOINTER] ?? this.checkpointer;
790
- if (!checkpointer) {
791
- throw new GraphValueError("No checkpointer set");
792
- }
793
- if (supersteps.length === 0) {
794
- throw new Error("No supersteps provided");
795
- }
796
- if (supersteps.some((s) => s.updates.length === 0)) {
797
- throw new Error("No updates provided");
798
- }
799
- // delegate to subgraph
800
- const checkpointNamespace = startConfig.configurable?.checkpoint_ns ?? "";
801
- if (checkpointNamespace !== "" &&
802
- startConfig.configurable?.[CONFIG_KEY_CHECKPOINTER] === undefined) {
803
- // remove task_ids from checkpoint_ns
804
- const recastNamespace = recastCheckpointNamespace(checkpointNamespace);
805
- // find the subgraph with the matching name
806
- // eslint-disable-next-line no-unreachable-loop
807
- for await (const [, pregel] of this.getSubgraphsAsync(recastNamespace, true)) {
808
- return await pregel.bulkUpdateState(patchConfigurable(startConfig, {
809
- [CONFIG_KEY_CHECKPOINTER]: checkpointer,
810
- }), supersteps);
811
- }
812
- throw new Error(`Subgraph "${recastNamespace}" not found`);
813
- }
814
- const updateSuperStep = async (inputConfig, updates) => {
815
- // get last checkpoint
816
- const config = this.config
817
- ? mergeConfigs(this.config, inputConfig)
818
- : inputConfig;
819
- const saved = await checkpointer.getTuple(config);
820
- const checkpoint = saved !== undefined
821
- ? copyCheckpoint(saved.checkpoint)
822
- : emptyCheckpoint();
823
- const checkpointPreviousVersions = {
824
- ...saved?.checkpoint.channel_versions,
825
- };
826
- const step = saved?.metadata?.step ?? -1;
827
- // merge configurable fields with previous checkpoint config
828
- let checkpointConfig = patchConfigurable(config, {
829
- checkpoint_ns: config.configurable?.checkpoint_ns ?? "",
830
- });
831
- let checkpointMetadata = config.metadata ?? {};
832
- if (saved?.config.configurable) {
833
- checkpointConfig = patchConfigurable(config, saved.config.configurable);
834
- checkpointMetadata = {
835
- ...saved.metadata,
836
- ...checkpointMetadata,
837
- };
838
- }
839
- // Find last node that updated the state, if not provided
840
- const { values, asNode } = updates[0];
841
- if (values == null && asNode === undefined) {
842
- if (updates.length > 1) {
843
- throw new InvalidUpdateError(`Cannot create empty checkpoint with multiple updates`);
844
- }
845
- const nextConfig = await checkpointer.put(checkpointConfig, createCheckpoint(checkpoint, undefined, step), {
846
- source: "update",
847
- step: step + 1,
848
- parents: saved?.metadata?.parents ?? {},
849
- }, {});
850
- return patchCheckpointMap(nextConfig, saved ? saved.metadata : undefined);
851
- }
852
- // update channels
853
- const channels = emptyChannels(this.channels, checkpoint);
854
- if (values === null && asNode === END) {
855
- if (updates.length > 1) {
856
- throw new InvalidUpdateError(`Cannot apply multiple updates when clearing state`);
857
- }
858
- if (saved) {
859
- // tasks for this checkpoint
860
- const nextTasks = _prepareNextTasks(checkpoint, saved.pendingWrites || [], this.nodes, channels, saved.config, true, {
861
- step: (saved.metadata?.step ?? -1) + 1,
862
- checkpointer,
863
- store: this.store,
864
- });
865
- // apply null writes
866
- const nullWrites = (saved.pendingWrites || [])
867
- .filter((w) => w[0] === NULL_TASK_ID)
868
- .map((w) => w.slice(1));
869
- if (nullWrites.length > 0) {
870
- _applyWrites(checkpoint, channels, [
871
- {
872
- name: INPUT,
873
- writes: nullWrites,
874
- triggers: [],
875
- },
876
- ], checkpointer.getNextVersion.bind(checkpointer), this.triggerToNodes);
877
- }
878
- // apply writes from tasks that already ran
879
- for (const [taskId, k, v] of saved.pendingWrites || []) {
880
- if ([ERROR, INTERRUPT, SCHEDULED].includes(k)) {
881
- continue;
882
- }
883
- if (!(taskId in nextTasks)) {
884
- continue;
885
- }
886
- nextTasks[taskId].writes.push([k, v]);
887
- }
888
- // clear all current tasks
889
- _applyWrites(checkpoint, channels, Object.values(nextTasks), checkpointer.getNextVersion.bind(checkpointer), this.triggerToNodes);
890
- }
891
- // save checkpoint
892
- const nextConfig = await checkpointer.put(checkpointConfig, createCheckpoint(checkpoint, channels, step), {
893
- ...checkpointMetadata,
894
- source: "update",
895
- step: step + 1,
896
- parents: saved?.metadata?.parents ?? {},
897
- }, getNewChannelVersions(checkpointPreviousVersions, checkpoint.channel_versions));
898
- return patchCheckpointMap(nextConfig, saved ? saved.metadata : undefined);
899
- }
900
- if (asNode === COPY) {
901
- if (updates.length > 1) {
902
- throw new InvalidUpdateError(`Cannot copy checkpoint with multiple updates`);
903
- }
904
- if (saved == null) {
905
- throw new InvalidUpdateError(`Cannot copy a non-existent checkpoint`);
906
- }
907
- const isCopyWithUpdates = (values) => {
908
- if (!Array.isArray(values))
909
- return false;
910
- if (values.length === 0)
911
- return false;
912
- return values.every((v) => Array.isArray(v) && v.length === 2);
913
- };
914
- const nextCheckpoint = createCheckpoint(checkpoint, undefined, step);
915
- const nextConfig = await checkpointer.put(saved.parentConfig ??
916
- patchConfigurable(saved.config, { checkpoint_id: undefined }), nextCheckpoint, {
917
- source: "fork",
918
- step: step + 1,
919
- parents: saved.metadata?.parents ?? {},
920
- }, {});
921
- // We want to both clone a checkpoint and update state in one go.
922
- // Reuse the same task ID if possible.
923
- if (isCopyWithUpdates(values)) {
924
- // figure out the task IDs for the next update checkpoint
925
- const nextTasks = _prepareNextTasks(nextCheckpoint, saved.pendingWrites, this.nodes, channels, nextConfig, false, { step: step + 2 });
926
- const tasksGroupBy = Object.values(nextTasks).reduce((acc, { name, id }) => {
927
- acc[name] ??= [];
928
- acc[name].push({ id });
929
- return acc;
930
- }, {});
931
- const userGroupBy = values.reduce((acc, item) => {
932
- const [values, asNode] = item;
933
- acc[asNode] ??= [];
934
- const targetIdx = acc[asNode].length;
935
- const taskId = tasksGroupBy[asNode]?.[targetIdx]?.id;
936
- acc[asNode].push({ values, asNode, taskId });
937
- return acc;
938
- }, {});
939
- return updateSuperStep(patchCheckpointMap(nextConfig, saved.metadata), Object.values(userGroupBy).flat());
940
- }
941
- return patchCheckpointMap(nextConfig, saved.metadata);
942
- }
943
- if (asNode === INPUT) {
944
- if (updates.length > 1) {
945
- throw new InvalidUpdateError(`Cannot apply multiple updates when updating as input`);
946
- }
947
- const inputWrites = await gatherIterator(mapInput(this.inputChannels, values));
948
- if (inputWrites.length === 0) {
949
- throw new InvalidUpdateError(`Received no input writes for ${JSON.stringify(this.inputChannels, null, 2)}`);
950
- }
951
- // apply to checkpoint
952
- _applyWrites(checkpoint, channels, [
953
- {
954
- name: INPUT,
955
- writes: inputWrites,
956
- triggers: [],
957
- },
958
- ], checkpointer.getNextVersion.bind(this.checkpointer), this.triggerToNodes);
959
- // apply input write to channels
960
- const nextStep = saved?.metadata?.step != null ? saved.metadata.step + 1 : -1;
961
- const nextConfig = await checkpointer.put(checkpointConfig, createCheckpoint(checkpoint, channels, nextStep), {
962
- source: "input",
963
- step: nextStep,
964
- parents: saved?.metadata?.parents ?? {},
965
- }, getNewChannelVersions(checkpointPreviousVersions, checkpoint.channel_versions));
966
- // Store the writes
967
- await checkpointer.putWrites(nextConfig, inputWrites, uuid5(INPUT, checkpoint.id));
968
- return patchCheckpointMap(nextConfig, saved ? saved.metadata : undefined);
969
- }
970
- // apply pending writes, if not on specific checkpoint
971
- if (config.configurable?.checkpoint_id === undefined &&
972
- saved?.pendingWrites !== undefined &&
973
- saved.pendingWrites.length > 0) {
974
- // tasks for this checkpoint
975
- const nextTasks = _prepareNextTasks(checkpoint, saved.pendingWrites, this.nodes, channels, saved.config, true, {
976
- store: this.store,
977
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
978
- checkpointer: this.checkpointer,
979
- step: (saved.metadata?.step ?? -1) + 1,
980
- });
981
- // apply null writes
982
- const nullWrites = (saved.pendingWrites ?? [])
983
- .filter((w) => w[0] === NULL_TASK_ID)
984
- .map((w) => w.slice(1));
985
- if (nullWrites.length > 0) {
986
- _applyWrites(saved.checkpoint, channels, [{ name: INPUT, writes: nullWrites, triggers: [] }], undefined, this.triggerToNodes);
987
- }
988
- // apply writes
989
- for (const [tid, k, v] of saved.pendingWrites) {
990
- if ([ERROR, INTERRUPT, SCHEDULED].includes(k) ||
991
- nextTasks[tid] === undefined) {
992
- continue;
993
- }
994
- nextTasks[tid].writes.push([k, v]);
995
- }
996
- const tasks = Object.values(nextTasks).filter((task) => {
997
- return task.writes.length > 0;
998
- });
999
- if (tasks.length > 0) {
1000
- _applyWrites(checkpoint, channels, tasks, undefined, this.triggerToNodes);
1001
- }
1002
- }
1003
- const nonNullVersion = Object.values(checkpoint.versions_seen)
1004
- .map((seenVersions) => {
1005
- return Object.values(seenVersions);
1006
- })
1007
- .flat()
1008
- .find((v) => !!v);
1009
- const validUpdates = [];
1010
- if (updates.length === 1) {
1011
- // eslint-disable-next-line prefer-const
1012
- let { values, asNode, taskId } = updates[0];
1013
- if (asNode === undefined && Object.keys(this.nodes).length === 1) {
1014
- // if only one node, use it
1015
- [asNode] = Object.keys(this.nodes);
1016
- }
1017
- else if (asNode === undefined && nonNullVersion === undefined) {
1018
- if (typeof this.inputChannels === "string" &&
1019
- this.nodes[this.inputChannels] !== undefined) {
1020
- asNode = this.inputChannels;
1021
- }
1022
- }
1023
- else if (asNode === undefined) {
1024
- const lastSeenByNode = Object.entries(checkpoint.versions_seen)
1025
- .map(([n, seen]) => {
1026
- return Object.values(seen).map((v) => {
1027
- return [v, n];
1028
- });
1029
- })
1030
- .flat()
1031
- .filter(([_, v]) => v !== INTERRUPT)
1032
- .sort(([aNumber], [bNumber]) => compareChannelVersions(aNumber, bNumber));
1033
- // if two nodes updated the state at the same time, it's ambiguous
1034
- if (lastSeenByNode) {
1035
- if (lastSeenByNode.length === 1) {
1036
- // eslint-disable-next-line prefer-destructuring
1037
- asNode = lastSeenByNode[0][1];
1038
- }
1039
- else if (lastSeenByNode[lastSeenByNode.length - 1][0] !==
1040
- lastSeenByNode[lastSeenByNode.length - 2][0]) {
1041
- // eslint-disable-next-line prefer-destructuring
1042
- asNode = lastSeenByNode[lastSeenByNode.length - 1][1];
1043
- }
1044
- }
1045
- }
1046
- if (asNode === undefined) {
1047
- throw new InvalidUpdateError(`Ambiguous update, specify "asNode"`);
1048
- }
1049
- validUpdates.push({ values, asNode, taskId });
1050
- }
1051
- else {
1052
- for (const { asNode, values, taskId } of updates) {
1053
- if (asNode == null) {
1054
- throw new InvalidUpdateError(`"asNode" is required when applying multiple updates`);
1055
- }
1056
- validUpdates.push({ values, asNode, taskId });
1057
- }
1058
- }
1059
- const tasks = [];
1060
- for (const { asNode, values, taskId } of validUpdates) {
1061
- if (this.nodes[asNode] === undefined) {
1062
- throw new InvalidUpdateError(`Node "${asNode.toString()}" does not exist`);
1063
- }
1064
- // run all writers of the chosen node
1065
- const writers = this.nodes[asNode].getWriters();
1066
- if (!writers.length) {
1067
- throw new InvalidUpdateError(`No writers found for node "${asNode.toString()}"`);
1068
- }
1069
- tasks.push({
1070
- name: asNode,
1071
- input: values,
1072
- proc: writers.length > 1
1073
- ? // eslint-disable-next-line @typescript-eslint/no-explicit-any
1074
- RunnableSequence.from(writers, {
1075
- omitSequenceTags: true,
1076
- })
1077
- : writers[0],
1078
- writes: [],
1079
- triggers: [INTERRUPT],
1080
- id: taskId ?? uuid5(INTERRUPT, checkpoint.id),
1081
- writers: [],
1082
- });
1083
- }
1084
- for (const task of tasks) {
1085
- // execute task
1086
- await task.proc.invoke(task.input, patchConfig({
1087
- ...config,
1088
- store: config?.store ?? this.store,
1089
- }, {
1090
- runName: config.runName ?? `${this.getName()}UpdateState`,
1091
- configurable: {
1092
- [CONFIG_KEY_SEND]: (items) => task.writes.push(...items),
1093
- [CONFIG_KEY_READ]: (select_, fresh_ = false) => _localRead(checkpoint, channels,
1094
- // TODO: Why does keyof StrRecord allow number and symbol?
1095
- task, select_, fresh_),
1096
- },
1097
- }));
1098
- }
1099
- for (const task of tasks) {
1100
- // channel writes are saved to current checkpoint
1101
- const channelWrites = task.writes.filter((w) => w[0] !== PUSH);
1102
- // save task writes
1103
- if (saved !== undefined && channelWrites.length > 0) {
1104
- await checkpointer.putWrites(checkpointConfig, channelWrites, task.id);
1105
- }
1106
- }
1107
- // apply to checkpoint
1108
- // TODO: Why does keyof StrRecord allow number and symbol?
1109
- _applyWrites(checkpoint, channels, tasks, checkpointer.getNextVersion.bind(this.checkpointer), this.triggerToNodes);
1110
- const newVersions = getNewChannelVersions(checkpointPreviousVersions, checkpoint.channel_versions);
1111
- const nextConfig = await checkpointer.put(checkpointConfig, createCheckpoint(checkpoint, channels, step + 1), {
1112
- source: "update",
1113
- step: step + 1,
1114
- parents: saved?.metadata?.parents ?? {},
1115
- }, newVersions);
1116
- for (const task of tasks) {
1117
- // push writes are saved to next checkpoint
1118
- const pushWrites = task.writes.filter((w) => w[0] === PUSH);
1119
- if (pushWrites.length > 0) {
1120
- await checkpointer.putWrites(nextConfig, pushWrites, task.id);
1121
- }
1122
- }
1123
- return patchCheckpointMap(nextConfig, saved ? saved.metadata : undefined);
1124
- };
1125
- let currentConfig = startConfig;
1126
- for (const { updates } of supersteps) {
1127
- currentConfig = await updateSuperStep(currentConfig, updates);
1128
- }
1129
- return currentConfig;
1130
- }
1131
- /**
1132
- * Updates the state of the graph with new values.
1133
- * Requires a checkpointer to be configured.
1134
- *
1135
- * This method can be used for:
1136
- * - Implementing human-in-the-loop workflows
1137
- * - Modifying graph state during breakpoints
1138
- * - Integrating external inputs into the graph
1139
- *
1140
- * @param inputConfig - Configuration for the update
1141
- * @param values - The values to update the state with
1142
- * @param asNode - Optional node name to attribute the update to
1143
- * @returns Updated configuration
1144
- * @throws {GraphValueError} If no checkpointer is configured
1145
- * @throws {InvalidUpdateError} If the update cannot be attributed to a node
1146
- */
1147
- async updateState(inputConfig, values, asNode) {
1148
- return this.bulkUpdateState(inputConfig, [
1149
- { updates: [{ values, asNode }] },
1150
- ]);
1151
- }
1152
- /**
1153
- * Gets the default values for various graph configuration options.
1154
- * This is an internal method used to process and normalize configuration options.
1155
- *
1156
- * @param config - The input configuration options
1157
- * @returns A tuple containing normalized values for:
1158
- * - debug mode
1159
- * - stream modes
1160
- * - input keys
1161
- * - output keys
1162
- * - remaining config
1163
- * - interrupt before nodes
1164
- * - interrupt after nodes
1165
- * - checkpointer
1166
- * - store
1167
- * - whether stream mode is single
1168
- * - node cache
1169
- * - whether checkpoint during is enabled
1170
- * @internal
1171
- */
1172
- _defaults(config) {
1173
- const { debug, streamMode, inputKeys, outputKeys, interruptAfter, interruptBefore, ...rest } = config;
1174
- let streamModeSingle = true;
1175
- const defaultDebug = debug !== undefined ? debug : this.debug;
1176
- let defaultOutputKeys = outputKeys;
1177
- if (defaultOutputKeys === undefined) {
1178
- defaultOutputKeys = this.streamChannelsAsIs;
1179
- }
1180
- else {
1181
- validateKeys(defaultOutputKeys, this.channels);
1182
- }
1183
- let defaultInputKeys = inputKeys;
1184
- if (defaultInputKeys === undefined) {
1185
- defaultInputKeys = this.inputChannels;
1186
- }
1187
- else {
1188
- validateKeys(defaultInputKeys, this.channels);
1189
- }
1190
- const defaultInterruptBefore = interruptBefore ?? this.interruptBefore ?? [];
1191
- const defaultInterruptAfter = interruptAfter ?? this.interruptAfter ?? [];
1192
- let defaultStreamMode;
1193
- if (streamMode !== undefined) {
1194
- defaultStreamMode = Array.isArray(streamMode) ? streamMode : [streamMode];
1195
- streamModeSingle = typeof streamMode === "string";
1196
- }
1197
- else {
1198
- // if being called as a node in another graph, default to values mode
1199
- // but don't overwrite `streamMode`if provided
1200
- if (config.configurable?.[CONFIG_KEY_TASK_ID] !== undefined) {
1201
- defaultStreamMode = ["values"];
1202
- }
1203
- else {
1204
- defaultStreamMode = this.streamMode;
1205
- }
1206
- streamModeSingle = true;
1207
- }
1208
- let defaultCheckpointer;
1209
- if (this.checkpointer === false) {
1210
- defaultCheckpointer = undefined;
1211
- }
1212
- else if (config !== undefined &&
1213
- config.configurable?.[CONFIG_KEY_CHECKPOINTER] !== undefined) {
1214
- defaultCheckpointer = config.configurable[CONFIG_KEY_CHECKPOINTER];
1215
- }
1216
- else if (this.checkpointer === true) {
1217
- throw new Error("checkpointer: true cannot be used for root graphs.");
1218
- }
1219
- else {
1220
- defaultCheckpointer = this.checkpointer;
1221
- }
1222
- const defaultStore = config.store ?? this.store;
1223
- const defaultCache = config.cache ?? this.cache;
1224
- if (config.durability != null && config.checkpointDuring != null) {
1225
- throw new Error("Cannot use both `durability` and `checkpointDuring` at the same time.");
1226
- }
1227
- const checkpointDuringDurability = (() => {
1228
- if (config.checkpointDuring == null)
1229
- return undefined;
1230
- if (config.checkpointDuring === false)
1231
- return "exit";
1232
- return "async";
1233
- })();
1234
- const defaultDurability = config.durability ??
1235
- checkpointDuringDurability ??
1236
- config?.configurable?.[CONFIG_KEY_DURABILITY] ??
1237
- "async";
1238
- return [
1239
- defaultDebug,
1240
- defaultStreamMode,
1241
- defaultInputKeys,
1242
- defaultOutputKeys,
1243
- rest,
1244
- defaultInterruptBefore,
1245
- defaultInterruptAfter,
1246
- defaultCheckpointer,
1247
- defaultStore,
1248
- streamModeSingle,
1249
- defaultCache,
1250
- defaultDurability,
1251
- ];
1252
- }
1253
- /**
1254
- * Streams the execution of the graph, emitting state updates as they occur.
1255
- * This is the primary method for observing graph execution in real-time.
1256
- *
1257
- * Stream modes:
1258
- * - "values": Emits complete state after each step
1259
- * - "updates": Emits only state changes after each step
1260
- * - "debug": Emits detailed debug information
1261
- * - "messages": Emits messages from within nodes
1262
- *
1263
- * For more details, see the [Streaming how-to guides](../../how-tos/#streaming_1).
1264
- *
1265
- * @param input - The input to start graph execution with
1266
- * @param options - Configuration options for streaming
1267
- * @returns An async iterable stream of graph state updates
1268
- */
1269
- async stream(input, options) {
1270
- // The ensureConfig method called internally defaults recursionLimit to 25 if not
1271
- // passed directly in `options`.
1272
- // There is currently no way in _streamIterator to determine whether this was
1273
- // set by by ensureConfig or manually by the user, so we specify the bound value here
1274
- // and override if it is passed as an explicit param in `options`.
1275
- const abortController = new AbortController();
1276
- const config = {
1277
- recursionLimit: this.config?.recursionLimit,
1278
- ...options,
1279
- signal: combineAbortSignals(options?.signal, abortController.signal)
1280
- .signal,
1281
- };
1282
- return new IterableReadableStreamWithAbortSignal((await super.stream(input, config)), abortController);
1283
- }
1284
- streamEvents(input, options, streamOptions) {
1285
- const abortController = new AbortController();
1286
- const config = {
1287
- recursionLimit: this.config?.recursionLimit,
1288
- ...options,
1289
- // Similar to `stream`, we need to pass the `config.callbacks` here,
1290
- // otherwise the user-provided callback will get lost in `ensureLangGraphConfig`.
1291
- // extend the callbacks with the ones from the config
1292
- callbacks: combineCallbacks(this.config?.callbacks, options?.callbacks),
1293
- signal: combineAbortSignals(options?.signal, abortController.signal)
1294
- .signal,
1295
- };
1296
- return new IterableReadableStreamWithAbortSignal(super.streamEvents(input, config, streamOptions), abortController);
1297
- }
1298
- /**
1299
- * Validates the input for the graph.
1300
- * @param input - The input to validate
1301
- * @returns The validated input
1302
- * @internal
1303
- */
1304
- async _validateInput(input) {
1305
- return input;
1306
- }
1307
- /**
1308
- * Validates the context options for the graph.
1309
- * @param context - The context options to validate
1310
- * @returns The validated context options
1311
- * @internal
1312
- */
1313
- async _validateContext(context) {
1314
- return context;
1315
- }
1316
- /**
1317
- * Internal iterator used by stream() to generate state updates.
1318
- * This method handles the core logic of graph execution and streaming.
1319
- *
1320
- * @param input - The input to start graph execution with
1321
- * @param options - Configuration options for streaming
1322
- * @returns AsyncGenerator yielding state updates
1323
- * @internal
1324
- */
1325
- async *_streamIterator(input, options) {
1326
- const streamSubgraphs = options?.subgraphs;
1327
- const inputConfig = ensureLangGraphConfig(this.config, options);
1328
- if (inputConfig.recursionLimit === undefined ||
1329
- inputConfig.recursionLimit < 1) {
1330
- throw new Error(`Passed "recursionLimit" must be at least 1.`);
1331
- }
1332
- if (this.checkpointer !== undefined &&
1333
- this.checkpointer !== false &&
1334
- inputConfig.configurable === undefined) {
1335
- throw new Error(`Checkpointer requires one or more of the following "configurable" keys: "thread_id", "checkpoint_ns", "checkpoint_id"`);
1336
- }
1337
- const validInput = await this._validateInput(input);
1338
- const { runId, ...restConfig } = inputConfig;
1339
- // assign defaults
1340
- const [debug, streamMode, , outputKeys, config, interruptBefore, interruptAfter, checkpointer, store, streamModeSingle, cache, durability,] = this._defaults(restConfig);
1341
- // At entrypoint, `configurable` is an alias for `context`.
1342
- if (typeof config.context !== "undefined") {
1343
- config.context = await this._validateContext(config.context);
1344
- }
1345
- else {
1346
- config.configurable = await this._validateContext(config.configurable);
1347
- }
1348
- const stream = new IterableReadableWritableStream({
1349
- modes: new Set(streamMode),
1350
- });
1351
- // set up subgraph checkpointing
1352
- if (this.checkpointer === true) {
1353
- config.configurable ??= {};
1354
- const ns = config.configurable[CONFIG_KEY_CHECKPOINT_NS] ?? "";
1355
- config.configurable[CONFIG_KEY_CHECKPOINT_NS] = ns
1356
- .split(CHECKPOINT_NAMESPACE_SEPARATOR)
1357
- .map((part) => part.split(CHECKPOINT_NAMESPACE_END)[0])
1358
- .join(CHECKPOINT_NAMESPACE_SEPARATOR);
1359
- }
1360
- // set up messages stream mode
1361
- if (streamMode.includes("messages")) {
1362
- const messageStreamer = new StreamMessagesHandler((chunk) => stream.push(chunk));
1363
- const { callbacks } = config;
1364
- if (callbacks === undefined) {
1365
- config.callbacks = [messageStreamer];
1366
- }
1367
- else if (Array.isArray(callbacks)) {
1368
- config.callbacks = callbacks.concat(messageStreamer);
1369
- }
1370
- else {
1371
- const copiedCallbacks = callbacks.copy();
1372
- copiedCallbacks.addHandler(messageStreamer, true);
1373
- config.callbacks = copiedCallbacks;
1374
- }
1375
- }
1376
- // setup custom stream mode
1377
- if (streamMode.includes("custom")) {
1378
- config.writer = (chunk) => {
1379
- const ns = getConfig()?.configurable?.[CONFIG_KEY_CHECKPOINT_NS]
1380
- ?.split(CHECKPOINT_NAMESPACE_SEPARATOR)
1381
- .slice(0, -1);
1382
- stream.push([ns ?? [], "custom", chunk]);
1383
- };
1384
- }
1385
- const callbackManager = await getCallbackManagerForConfig(config);
1386
- const runManager = await callbackManager?.handleChainStart(this.toJSON(), // chain
1387
- _coerceToDict(input, "input"), // inputs
1388
- runId, // run_id
1389
- undefined, // run_type
1390
- undefined, // tags
1391
- undefined, // metadata
1392
- config?.runName ?? this.getName() // run_name
1393
- );
1394
- const channelSpecs = getOnlyChannels(this.channels);
1395
- let loop;
1396
- let loopError;
1397
- /**
1398
- * The PregelLoop will yield events from concurrent tasks as soon as they are
1399
- * generated. Each task can push multiple events onto the stream in any order.
1400
- *
1401
- * We use a separate background method and stream here in order to yield events
1402
- * from the loop to the main stream and therefore back to the user as soon as
1403
- * they are available.
1404
- */
1405
- const createAndRunLoop = async () => {
1406
- try {
1407
- loop = await PregelLoop.initialize({
1408
- input: validInput,
1409
- config,
1410
- checkpointer,
1411
- nodes: this.nodes,
1412
- channelSpecs,
1413
- outputKeys,
1414
- streamKeys: this.streamChannelsAsIs,
1415
- store,
1416
- cache: cache,
1417
- stream,
1418
- interruptAfter,
1419
- interruptBefore,
1420
- manager: runManager,
1421
- debug: this.debug,
1422
- triggerToNodes: this.triggerToNodes,
1423
- durability,
1424
- });
1425
- const runner = new PregelRunner({
1426
- loop,
1427
- nodeFinished: config.configurable?.[CONFIG_KEY_NODE_FINISHED],
1428
- });
1429
- if (options?.subgraphs) {
1430
- loop.config.configurable = {
1431
- ...loop.config.configurable,
1432
- [CONFIG_KEY_STREAM]: loop.stream,
1433
- };
1434
- }
1435
- await this._runLoop({ loop, runner, debug, config });
1436
- // wait for checkpoints to be persisted
1437
- if (durability === "sync") {
1438
- await Promise.all(loop?.checkpointerPromises ?? []);
1439
- }
1440
- }
1441
- catch (e) {
1442
- loopError = e;
1443
- }
1444
- finally {
1445
- try {
1446
- // Call `.stop()` again incase it was not called in the loop, e.g due to an error.
1447
- if (loop) {
1448
- await loop.store?.stop();
1449
- await loop.cache?.stop();
1450
- }
1451
- await Promise.all(loop?.checkpointerPromises ?? []);
1452
- }
1453
- catch (e) {
1454
- loopError = loopError ?? e;
1455
- }
1456
- if (loopError) {
1457
- // "Causes any future interactions with the associated stream to error".
1458
- // Wraps ReadableStreamDefaultController#error:
1459
- // https://developer.mozilla.org/en-US/docs/Web/API/ReadableStreamDefaultController/error
1460
- stream.error(loopError);
1461
- }
1462
- else {
1463
- // Will end the iterator outside of this method,
1464
- // keeping previously enqueued chunks.
1465
- // Wraps ReadableStreamDefaultController#close:
1466
- // https://developer.mozilla.org/en-US/docs/Web/API/ReadableStreamDefaultController/close
1467
- stream.close();
1468
- }
1469
- }
1470
- };
1471
- const runLoopPromise = createAndRunLoop();
1472
- try {
1473
- for await (const chunk of stream) {
1474
- if (chunk === undefined) {
1475
- throw new Error("Data structure error.");
1476
- }
1477
- const [namespace, mode, payload] = chunk;
1478
- if (streamMode.includes(mode)) {
1479
- if (streamSubgraphs && !streamModeSingle) {
1480
- yield [namespace, mode, payload];
1481
- }
1482
- else if (!streamModeSingle) {
1483
- yield [mode, payload];
1484
- }
1485
- else if (streamSubgraphs) {
1486
- yield [namespace, payload];
1487
- }
1488
- else {
1489
- yield payload;
1490
- }
1491
- }
1492
- }
1493
- }
1494
- catch (e) {
1495
- await runManager?.handleChainError(loopError);
1496
- throw e;
1497
- }
1498
- finally {
1499
- await runLoopPromise;
1500
- }
1501
- await runManager?.handleChainEnd(loop?.output ?? {}, runId, // run_id
1502
- undefined, // run_type
1503
- undefined, // tags
1504
- undefined // metadata
1505
- );
1506
- }
1507
- /**
1508
- * Run the graph with a single input and config.
1509
- * @param input The input to the graph.
1510
- * @param options The configuration to use for the run.
1511
- */
1512
- async invoke(input, options) {
1513
- const streamMode = options?.streamMode ?? "values";
1514
- const config = {
1515
- ...options,
1516
- outputKeys: options?.outputKeys ?? this.outputChannels,
1517
- streamMode,
1518
- };
1519
- const chunks = [];
1520
- const stream = await this.stream(input, config);
1521
- const interruptChunks = [];
1522
- let latest;
1523
- for await (const chunk of stream) {
1524
- if (streamMode === "values") {
1525
- if (isInterrupted(chunk)) {
1526
- interruptChunks.push(chunk[INTERRUPT]);
1527
- }
1528
- else {
1529
- latest = chunk;
1530
- }
1531
- }
1532
- else {
1533
- chunks.push(chunk);
1534
- }
1535
- }
1536
- if (streamMode === "values") {
1537
- if (interruptChunks.length > 0) {
1538
- const interrupts = interruptChunks.flat(1);
1539
- if (latest == null)
1540
- return { [INTERRUPT]: interrupts };
1541
- if (typeof latest === "object") {
1542
- return { ...latest, [INTERRUPT]: interrupts };
1543
- }
1544
- }
1545
- return latest;
1546
- }
1547
- return chunks;
1548
- }
1549
- async _runLoop(params) {
1550
- const { loop, runner, debug, config } = params;
1551
- let tickError;
1552
- try {
1553
- while (await loop.tick({ inputKeys: this.inputChannels })) {
1554
- for (const { task } of await loop._matchCachedWrites()) {
1555
- loop._outputWrites(task.id, task.writes, true);
1556
- }
1557
- if (debug) {
1558
- printStepCheckpoint(loop.checkpointMetadata.step, loop.channels, this.streamChannelsList);
1559
- }
1560
- if (debug) {
1561
- printStepTasks(loop.step, Object.values(loop.tasks));
1562
- }
1563
- await runner.tick({
1564
- timeout: this.stepTimeout,
1565
- retryPolicy: this.retryPolicy,
1566
- onStepWrite: (step, writes) => {
1567
- if (debug) {
1568
- printStepWrites(step, writes, this.streamChannelsList);
1569
- }
1570
- },
1571
- maxConcurrency: config.maxConcurrency,
1572
- signal: config.signal,
1573
- });
1574
- }
1575
- if (loop.status === "out_of_steps") {
1576
- throw new GraphRecursionError([
1577
- `Recursion limit of ${config.recursionLimit} reached`,
1578
- "without hitting a stop condition. You can increase the",
1579
- `limit by setting the "recursionLimit" config key.`,
1580
- ].join(" "), {
1581
- lc_error_code: "GRAPH_RECURSION_LIMIT",
1582
- });
1583
- }
1584
- }
1585
- catch (e) {
1586
- tickError = e;
1587
- const suppress = await loop.finishAndHandleError(tickError);
1588
- if (!suppress) {
1589
- throw e;
1590
- }
1591
- }
1592
- finally {
1593
- if (tickError === undefined) {
1594
- await loop.finishAndHandleError();
1595
- }
1596
- }
1597
- }
1598
- async clearCache() {
1599
- await this.cache?.clear([]);
1600
- }
1601
- }
108
+ * The Pregel class is the core runtime engine of LangGraph, implementing a message-passing graph computation model
109
+ * inspired by [Google's Pregel system](https://research.google/pubs/pregel-a-system-for-large-scale-graph-processing/).
110
+ * It provides the foundation for building reliable, controllable agent workflows that can evolve state over time.
111
+ *
112
+ * Key features:
113
+ * - Message passing between nodes in discrete "supersteps"
114
+ * - Built-in persistence layer through checkpointers
115
+ * - First-class streaming support for values, updates, and events
116
+ * - Human-in-the-loop capabilities via interrupts
117
+ * - Support for parallel node execution within supersteps
118
+ *
119
+ * The Pregel class is not intended to be instantiated directly by consumers. Instead, use the following higher-level APIs:
120
+ * - {@link StateGraph}: The main graph class for building agent workflows
121
+ * - Compiling a {@link StateGraph} will return a {@link CompiledGraph} instance, which extends `Pregel`
122
+ * - Functional API: A declarative approach using tasks and entrypoints
123
+ * - A `Pregel` instance is returned by the {@link entrypoint} function
124
+ *
125
+ * @example
126
+ * ```typescript
127
+ * // Using StateGraph API
128
+ * const graph = new StateGraph(annotation)
129
+ * .addNode("nodeA", myNodeFunction)
130
+ * .addEdge("nodeA", "nodeB")
131
+ * .compile();
132
+ *
133
+ * // The compiled graph is a Pregel instance
134
+ * const result = await graph.invoke(input);
135
+ * ```
136
+ *
137
+ * @example
138
+ * ```typescript
139
+ * // Using Functional API
140
+ * import { task, entrypoint } from "@langchain/langgraph";
141
+ * import { MemorySaver } from "@langchain/langgraph-checkpoint";
142
+ *
143
+ * // Define tasks that can be composed
144
+ * const addOne = task("add", async (x: number) => x + 1);
145
+ *
146
+ * // Create a workflow using the entrypoint function
147
+ * const workflow = entrypoint({
148
+ * name: "workflow",
149
+ * checkpointer: new MemorySaver()
150
+ * }, async (numbers: number[]) => {
151
+ * // Tasks can be run in parallel
152
+ * const results = await Promise.all(numbers.map(n => addOne(n)));
153
+ * return results;
154
+ * });
155
+ *
156
+ * // The workflow is a Pregel instance
157
+ * const result = await workflow.invoke([1, 2, 3]); // Returns [2, 3, 4]
158
+ * ```
159
+ *
160
+ * @typeParam Nodes - Mapping of node names to their {@link PregelNode} implementations
161
+ * @typeParam Channels - Mapping of channel names to their {@link BaseChannel} or {@link ManagedValueSpec} implementations
162
+ * @typeParam ContextType - Type of context that can be passed to the graph
163
+ * @typeParam InputType - Type of input values accepted by the graph
164
+ * @typeParam OutputType - Type of output values produced by the graph
165
+ */
166
+ var Pregel = class extends PartialRunnable {
167
+ /**
168
+ * Name of the class when serialized
169
+ * @internal
170
+ */
171
+ static lc_name() {
172
+ return "LangGraph";
173
+ }
174
+ /** @internal LangChain namespace for serialization necessary because Pregel extends Runnable */
175
+ lc_namespace = ["langgraph", "pregel"];
176
+ /** @internal Flag indicating this is a Pregel instance - necessary for serialization */
177
+ lg_is_pregel = true;
178
+ /** The nodes in the graph, mapping node names to their PregelNode instances */
179
+ nodes;
180
+ /** The channels in the graph, mapping channel names to their BaseChannel or ManagedValueSpec instances */
181
+ channels;
182
+ /**
183
+ * The input channels for the graph. These channels receive the initial input when the graph is invoked.
184
+ * Can be a single channel key or an array of channel keys.
185
+ */
186
+ inputChannels;
187
+ /**
188
+ * The output channels for the graph. These channels contain the final output when the graph completes.
189
+ * Can be a single channel key or an array of channel keys.
190
+ */
191
+ outputChannels;
192
+ /** Whether to automatically validate the graph structure when it is compiled. Defaults to true. */
193
+ autoValidate = true;
194
+ /**
195
+ * The streaming modes enabled for this graph. Defaults to ["values"].
196
+ * Supported modes:
197
+ * - "values": Streams the full state after each step
198
+ * - "updates": Streams state updates after each step
199
+ * - "messages": Streams messages from within nodes
200
+ * - "custom": Streams custom events from within nodes
201
+ * - "debug": Streams events related to the execution of the graph - useful for tracing & debugging graph execution
202
+ */
203
+ streamMode = ["values"];
204
+ /**
205
+ * Optional channels to stream. If not specified, all channels will be streamed.
206
+ * Can be a single channel key or an array of channel keys.
207
+ */
208
+ streamChannels;
209
+ /**
210
+ * Optional array of node names or "all" to interrupt after executing these nodes.
211
+ * Used for implementing human-in-the-loop workflows.
212
+ */
213
+ interruptAfter;
214
+ /**
215
+ * Optional array of node names or "all" to interrupt before executing these nodes.
216
+ * Used for implementing human-in-the-loop workflows.
217
+ */
218
+ interruptBefore;
219
+ /** Optional timeout in milliseconds for the execution of each superstep */
220
+ stepTimeout;
221
+ /** Whether to enable debug logging. Defaults to false. */
222
+ debug = false;
223
+ /**
224
+ * Optional checkpointer for persisting graph state.
225
+ * When provided, saves a checkpoint of the graph state at every superstep.
226
+ * When false or undefined, checkpointing is disabled, and the graph will not be able to save or restore state.
227
+ */
228
+ checkpointer;
229
+ /** Optional retry policy for handling failures in node execution */
230
+ retryPolicy;
231
+ /** The default configuration for graph execution, can be overridden on a per-invocation basis */
232
+ config;
233
+ /**
234
+ * Optional long-term memory store for the graph, allows for persistence & retrieval of data across threads
235
+ */
236
+ store;
237
+ triggerToNodes = {};
238
+ /**
239
+ * Optional cache for the graph, useful for caching tasks.
240
+ */
241
+ cache;
242
+ /**
243
+ * Constructor for Pregel - meant for internal use only.
244
+ *
245
+ * @internal
246
+ */
247
+ constructor(fields) {
248
+ super(fields);
249
+ let { streamMode } = fields;
250
+ if (streamMode != null && !Array.isArray(streamMode)) streamMode = [streamMode];
251
+ this.nodes = fields.nodes;
252
+ this.channels = fields.channels;
253
+ if (TASKS in this.channels && "lc_graph_name" in this.channels[TASKS] && this.channels[TASKS].lc_graph_name !== "Topic") throw new Error(`Channel '${TASKS}' is reserved and cannot be used in the graph.`);
254
+ else this.channels[TASKS] = new Topic({ accumulate: false });
255
+ this.autoValidate = fields.autoValidate ?? this.autoValidate;
256
+ this.streamMode = streamMode ?? this.streamMode;
257
+ this.inputChannels = fields.inputChannels;
258
+ this.outputChannels = fields.outputChannels;
259
+ this.streamChannels = fields.streamChannels ?? this.streamChannels;
260
+ this.interruptAfter = fields.interruptAfter;
261
+ this.interruptBefore = fields.interruptBefore;
262
+ this.stepTimeout = fields.stepTimeout ?? this.stepTimeout;
263
+ this.debug = fields.debug ?? this.debug;
264
+ this.checkpointer = fields.checkpointer;
265
+ this.retryPolicy = fields.retryPolicy;
266
+ this.config = fields.config;
267
+ this.store = fields.store;
268
+ this.cache = fields.cache;
269
+ this.name = fields.name;
270
+ if (this.autoValidate) this.validate();
271
+ }
272
+ /**
273
+ * Creates a new instance of the Pregel graph with updated configuration.
274
+ * This method follows the immutable pattern - instead of modifying the current instance,
275
+ * it returns a new instance with the merged configuration.
276
+ *
277
+ * @example
278
+ * ```typescript
279
+ * // Create a new instance with debug enabled
280
+ * const debugGraph = graph.withConfig({ debug: true });
281
+ *
282
+ * // Create a new instance with a specific thread ID
283
+ * const threadGraph = graph.withConfig({
284
+ * configurable: { thread_id: "123" }
285
+ * });
286
+ * ```
287
+ *
288
+ * @param config - The configuration to merge with the current configuration
289
+ * @returns A new Pregel instance with the merged configuration
290
+ */
291
+ withConfig(config) {
292
+ const mergedConfig = mergeConfigs(this.config, config);
293
+ return new this.constructor({
294
+ ...this,
295
+ config: mergedConfig
296
+ });
297
+ }
298
+ /**
299
+ * Validates the graph structure to ensure it is well-formed.
300
+ * Checks for:
301
+ * - No orphaned nodes
302
+ * - Valid input/output channel configurations
303
+ * - Valid interrupt configurations
304
+ *
305
+ * @returns this - The Pregel instance for method chaining
306
+ * @throws {GraphValidationError} If the graph structure is invalid
307
+ */
308
+ validate() {
309
+ validateGraph({
310
+ nodes: this.nodes,
311
+ channels: this.channels,
312
+ outputChannels: this.outputChannels,
313
+ inputChannels: this.inputChannels,
314
+ streamChannels: this.streamChannels,
315
+ interruptAfterNodes: this.interruptAfter,
316
+ interruptBeforeNodes: this.interruptBefore
317
+ });
318
+ for (const [name, node] of Object.entries(this.nodes)) for (const trigger of node.triggers) {
319
+ this.triggerToNodes[trigger] ??= [];
320
+ this.triggerToNodes[trigger].push(name);
321
+ }
322
+ return this;
323
+ }
324
+ /**
325
+ * Gets a list of all channels that should be streamed.
326
+ * If streamChannels is specified, returns those channels.
327
+ * Otherwise, returns all channels in the graph.
328
+ *
329
+ * @returns Array of channel keys to stream
330
+ */
331
+ get streamChannelsList() {
332
+ if (Array.isArray(this.streamChannels)) return this.streamChannels;
333
+ else if (this.streamChannels) return [this.streamChannels];
334
+ else return Object.keys(this.channels);
335
+ }
336
+ /**
337
+ * Gets the channels to stream in their original format.
338
+ * If streamChannels is specified, returns it as-is (either single key or array).
339
+ * Otherwise, returns all channels in the graph as an array.
340
+ *
341
+ * @returns Channel keys to stream, either as a single key or array
342
+ */
343
+ get streamChannelsAsIs() {
344
+ if (this.streamChannels) return this.streamChannels;
345
+ else return Object.keys(this.channels);
346
+ }
347
+ /**
348
+ * Gets a drawable representation of the graph structure.
349
+ * This is an async version of getGraph() and is the preferred method to use.
350
+ *
351
+ * @param config - Configuration for generating the graph visualization
352
+ * @returns A representation of the graph that can be visualized
353
+ */
354
+ async getGraphAsync(config) {
355
+ return this.getGraph(config);
356
+ }
357
+ /**
358
+ * Gets all subgraphs within this graph.
359
+ * A subgraph is a Pregel instance that is nested within a node of this graph.
360
+ *
361
+ * @deprecated Use getSubgraphsAsync instead. The async method will become the default in the next minor release.
362
+ * @param namespace - Optional namespace to filter subgraphs
363
+ * @param recurse - Whether to recursively get subgraphs of subgraphs
364
+ * @returns Generator yielding tuples of [name, subgraph]
365
+ */
366
+ *getSubgraphs(namespace, recurse) {
367
+ for (const [name, node] of Object.entries(this.nodes)) {
368
+ if (namespace !== void 0) {
369
+ if (!namespace.startsWith(name)) continue;
370
+ }
371
+ const candidates = node.subgraphs?.length ? node.subgraphs : [node.bound];
372
+ for (const candidate of candidates) {
373
+ const graph = findSubgraphPregel(candidate);
374
+ if (graph !== void 0) {
375
+ if (name === namespace) {
376
+ yield [name, graph];
377
+ return;
378
+ }
379
+ if (namespace === void 0) yield [name, graph];
380
+ if (recurse) {
381
+ let newNamespace = namespace;
382
+ if (namespace !== void 0) newNamespace = namespace.slice(name.length + 1);
383
+ for (const [subgraphName, subgraph] of graph.getSubgraphs(newNamespace, recurse)) yield [`${name}${CHECKPOINT_NAMESPACE_SEPARATOR}${subgraphName}`, subgraph];
384
+ }
385
+ }
386
+ }
387
+ }
388
+ }
389
+ /**
390
+ * Gets all subgraphs within this graph asynchronously.
391
+ * A subgraph is a Pregel instance that is nested within a node of this graph.
392
+ *
393
+ * @param namespace - Optional namespace to filter subgraphs
394
+ * @param recurse - Whether to recursively get subgraphs of subgraphs
395
+ * @returns AsyncGenerator yielding tuples of [name, subgraph]
396
+ */
397
+ async *getSubgraphsAsync(namespace, recurse) {
398
+ yield* this.getSubgraphs(namespace, recurse);
399
+ }
400
+ /**
401
+ * Prepares a state snapshot from saved checkpoint data.
402
+ * This is an internal method used by getState and getStateHistory.
403
+ *
404
+ * @param config - Configuration for preparing the snapshot
405
+ * @param saved - Optional saved checkpoint data
406
+ * @param subgraphCheckpointer - Optional checkpointer for subgraphs
407
+ * @param applyPendingWrites - Whether to apply pending writes to tasks and then to channels
408
+ * @returns A snapshot of the graph state
409
+ * @internal
410
+ */
411
+ async _prepareStateSnapshot({ config, saved, subgraphCheckpointer, applyPendingWrites = false }) {
412
+ if (saved === void 0) return {
413
+ values: {},
414
+ next: [],
415
+ config,
416
+ tasks: []
417
+ };
418
+ const channels = emptyChannels(this.channels, saved.checkpoint);
419
+ if (saved.pendingWrites?.length) {
420
+ const nullWrites = saved.pendingWrites.filter(([taskId, _]) => taskId === NULL_TASK_ID).map(([_, channel, value]) => [String(channel), value]);
421
+ if (nullWrites.length > 0) _applyWrites(saved.checkpoint, channels, [{
422
+ name: INPUT,
423
+ writes: nullWrites,
424
+ triggers: []
425
+ }], void 0, this.triggerToNodes);
426
+ }
427
+ const nextTasks = Object.values(_prepareNextTasks(saved.checkpoint, saved.pendingWrites, this.nodes, channels, saved.config, true, {
428
+ step: (saved.metadata?.step ?? -1) + 1,
429
+ store: this.store
430
+ }));
431
+ const subgraphs = await gatherIterator(this.getSubgraphsAsync());
432
+ const parentNamespace = saved.config.configurable?.checkpoint_ns ?? "";
433
+ const taskStates = {};
434
+ for (const task of nextTasks) {
435
+ const matchingSubgraph = subgraphs.find(([name]) => name === task.name);
436
+ if (!matchingSubgraph) continue;
437
+ let taskNs = `${String(task.name)}${CHECKPOINT_NAMESPACE_END}${task.id}`;
438
+ if (parentNamespace) taskNs = `${parentNamespace}${CHECKPOINT_NAMESPACE_SEPARATOR}${taskNs}`;
439
+ if (subgraphCheckpointer === void 0) {
440
+ const config$1 = { configurable: {
441
+ thread_id: saved.config.configurable?.thread_id,
442
+ checkpoint_ns: taskNs
443
+ } };
444
+ taskStates[task.id] = config$1;
445
+ } else {
446
+ const subgraphConfig = { configurable: {
447
+ [CONFIG_KEY_CHECKPOINTER]: subgraphCheckpointer,
448
+ thread_id: saved.config.configurable?.thread_id,
449
+ checkpoint_ns: taskNs
450
+ } };
451
+ const pregel = matchingSubgraph[1];
452
+ taskStates[task.id] = await pregel.getState(subgraphConfig, { subgraphs: true });
453
+ }
454
+ }
455
+ if (applyPendingWrites && saved.pendingWrites?.length) {
456
+ const nextTaskById = Object.fromEntries(nextTasks.map((task) => [task.id, task]));
457
+ for (const [taskId, channel, value] of saved.pendingWrites) {
458
+ if ([
459
+ ERROR,
460
+ INTERRUPT,
461
+ SCHEDULED
462
+ ].includes(channel)) continue;
463
+ if (!(taskId in nextTaskById)) continue;
464
+ nextTaskById[taskId].writes.push([String(channel), value]);
465
+ }
466
+ const tasksWithWrites$1 = nextTasks.filter((task) => task.writes.length > 0);
467
+ if (tasksWithWrites$1.length > 0) _applyWrites(saved.checkpoint, channels, tasksWithWrites$1, void 0, this.triggerToNodes);
468
+ }
469
+ let metadata = saved?.metadata;
470
+ if (metadata && saved?.config?.configurable?.thread_id) metadata = {
471
+ ...metadata,
472
+ thread_id: saved.config.configurable.thread_id
473
+ };
474
+ const nextList = nextTasks.filter((task) => task.writes.length === 0).map((task) => task.name);
475
+ return {
476
+ values: readChannels(channels, this.streamChannelsAsIs),
477
+ next: nextList,
478
+ tasks: tasksWithWrites(nextTasks, saved?.pendingWrites ?? [], taskStates, this.streamChannelsAsIs),
479
+ metadata,
480
+ config: patchCheckpointMap(saved.config, saved.metadata),
481
+ createdAt: saved.checkpoint.ts,
482
+ parentConfig: saved.parentConfig
483
+ };
484
+ }
485
+ /**
486
+ * Gets the current state of the graph.
487
+ * Requires a checkpointer to be configured.
488
+ *
489
+ * @param config - Configuration for retrieving the state
490
+ * @param options - Additional options
491
+ * @returns A snapshot of the current graph state
492
+ * @throws {GraphValueError} If no checkpointer is configured
493
+ */
494
+ async getState(config, options) {
495
+ const checkpointer = config.configurable?.[CONFIG_KEY_CHECKPOINTER] ?? this.checkpointer;
496
+ if (!checkpointer) throw new GraphValueError("No checkpointer set");
497
+ const checkpointNamespace = config.configurable?.checkpoint_ns ?? "";
498
+ if (checkpointNamespace !== "" && config.configurable?.[CONFIG_KEY_CHECKPOINTER] === void 0) {
499
+ const recastNamespace = recastCheckpointNamespace(checkpointNamespace);
500
+ for await (const [name, subgraph] of this.getSubgraphsAsync(recastNamespace, true)) if (name === recastNamespace) return await subgraph.getState(patchConfigurable(config, { [CONFIG_KEY_CHECKPOINTER]: checkpointer }), { subgraphs: options?.subgraphs });
501
+ throw new Error(`Subgraph with namespace "${recastNamespace}" not found.`);
502
+ }
503
+ const mergedConfig = mergeConfigs(this.config, config);
504
+ const saved = await checkpointer.getTuple(config);
505
+ const snapshot = await this._prepareStateSnapshot({
506
+ config: mergedConfig,
507
+ saved,
508
+ subgraphCheckpointer: options?.subgraphs ? checkpointer : void 0,
509
+ applyPendingWrites: !config.configurable?.checkpoint_id
510
+ });
511
+ return snapshot;
512
+ }
513
+ /**
514
+ * Gets the history of graph states.
515
+ * Requires a checkpointer to be configured.
516
+ * Useful for:
517
+ * - Debugging execution history
518
+ * - Implementing time travel
519
+ * - Analyzing graph behavior
520
+ *
521
+ * @param config - Configuration for retrieving the history
522
+ * @param options - Options for filtering the history
523
+ * @returns An async iterator of state snapshots
524
+ * @throws {Error} If no checkpointer is configured
525
+ */
526
+ async *getStateHistory(config, options) {
527
+ const checkpointer = config.configurable?.[CONFIG_KEY_CHECKPOINTER] ?? this.checkpointer;
528
+ if (!checkpointer) throw new GraphValueError("No checkpointer set");
529
+ const checkpointNamespace = config.configurable?.checkpoint_ns ?? "";
530
+ if (checkpointNamespace !== "" && config.configurable?.[CONFIG_KEY_CHECKPOINTER] === void 0) {
531
+ const recastNamespace = recastCheckpointNamespace(checkpointNamespace);
532
+ for await (const [name, pregel] of this.getSubgraphsAsync(recastNamespace, true)) if (name === recastNamespace) {
533
+ yield* pregel.getStateHistory(patchConfigurable(config, { [CONFIG_KEY_CHECKPOINTER]: checkpointer }), options);
534
+ return;
535
+ }
536
+ throw new Error(`Subgraph with namespace "${recastNamespace}" not found.`);
537
+ }
538
+ const mergedConfig = mergeConfigs(this.config, config, { configurable: { checkpoint_ns: checkpointNamespace } });
539
+ for await (const checkpointTuple of checkpointer.list(mergedConfig, options)) yield this._prepareStateSnapshot({
540
+ config: checkpointTuple.config,
541
+ saved: checkpointTuple
542
+ });
543
+ }
544
+ /**
545
+ * Apply updates to the graph state in bulk.
546
+ * Requires a checkpointer to be configured.
547
+ *
548
+ * This method is useful for recreating a thread
549
+ * from a list of updates, especially if a checkpoint
550
+ * is created as a result of multiple tasks.
551
+ *
552
+ * @internal The API might change in the future.
553
+ *
554
+ * @param startConfig - Configuration for the update
555
+ * @param updates - The list of updates to apply to graph state
556
+ * @returns Updated configuration
557
+ * @throws {GraphValueError} If no checkpointer is configured
558
+ * @throws {InvalidUpdateError} If the update cannot be attributed to a node or an update can be only applied in sequence.
559
+ */
560
+ async bulkUpdateState(startConfig, supersteps) {
561
+ const checkpointer = startConfig.configurable?.[CONFIG_KEY_CHECKPOINTER] ?? this.checkpointer;
562
+ if (!checkpointer) throw new GraphValueError("No checkpointer set");
563
+ if (supersteps.length === 0) throw new Error("No supersteps provided");
564
+ if (supersteps.some((s) => s.updates.length === 0)) throw new Error("No updates provided");
565
+ const checkpointNamespace = startConfig.configurable?.checkpoint_ns ?? "";
566
+ if (checkpointNamespace !== "" && startConfig.configurable?.[CONFIG_KEY_CHECKPOINTER] === void 0) {
567
+ const recastNamespace = recastCheckpointNamespace(checkpointNamespace);
568
+ for await (const [, pregel] of this.getSubgraphsAsync(recastNamespace, true)) return await pregel.bulkUpdateState(patchConfigurable(startConfig, { [CONFIG_KEY_CHECKPOINTER]: checkpointer }), supersteps);
569
+ throw new Error(`Subgraph "${recastNamespace}" not found`);
570
+ }
571
+ const updateSuperStep = async (inputConfig, updates) => {
572
+ const config = this.config ? mergeConfigs(this.config, inputConfig) : inputConfig;
573
+ const saved = await checkpointer.getTuple(config);
574
+ const checkpoint = saved !== void 0 ? copyCheckpoint(saved.checkpoint) : emptyCheckpoint();
575
+ const checkpointPreviousVersions = { ...saved?.checkpoint.channel_versions };
576
+ const step = saved?.metadata?.step ?? -1;
577
+ let checkpointConfig = patchConfigurable(config, { checkpoint_ns: config.configurable?.checkpoint_ns ?? "" });
578
+ let checkpointMetadata = config.metadata ?? {};
579
+ if (saved?.config.configurable) {
580
+ checkpointConfig = patchConfigurable(config, saved.config.configurable);
581
+ checkpointMetadata = {
582
+ ...saved.metadata,
583
+ ...checkpointMetadata
584
+ };
585
+ }
586
+ const { values, asNode } = updates[0];
587
+ if (values == null && asNode === void 0) {
588
+ if (updates.length > 1) throw new InvalidUpdateError(`Cannot create empty checkpoint with multiple updates`);
589
+ const nextConfig$1 = await checkpointer.put(checkpointConfig, createCheckpoint(checkpoint, void 0, step), {
590
+ source: "update",
591
+ step: step + 1,
592
+ parents: saved?.metadata?.parents ?? {}
593
+ }, {});
594
+ return patchCheckpointMap(nextConfig$1, saved ? saved.metadata : void 0);
595
+ }
596
+ const channels = emptyChannels(this.channels, checkpoint);
597
+ if (values === null && asNode === END) {
598
+ if (updates.length > 1) throw new InvalidUpdateError(`Cannot apply multiple updates when clearing state`);
599
+ if (saved) {
600
+ const nextTasks = _prepareNextTasks(checkpoint, saved.pendingWrites || [], this.nodes, channels, saved.config, true, {
601
+ step: (saved.metadata?.step ?? -1) + 1,
602
+ checkpointer,
603
+ store: this.store
604
+ });
605
+ const nullWrites = (saved.pendingWrites || []).filter((w) => w[0] === NULL_TASK_ID).map((w) => w.slice(1));
606
+ if (nullWrites.length > 0) _applyWrites(checkpoint, channels, [{
607
+ name: INPUT,
608
+ writes: nullWrites,
609
+ triggers: []
610
+ }], checkpointer.getNextVersion.bind(checkpointer), this.triggerToNodes);
611
+ for (const [taskId, k, v] of saved.pendingWrites || []) {
612
+ if ([
613
+ ERROR,
614
+ INTERRUPT,
615
+ SCHEDULED
616
+ ].includes(k)) continue;
617
+ if (!(taskId in nextTasks)) continue;
618
+ nextTasks[taskId].writes.push([k, v]);
619
+ }
620
+ _applyWrites(checkpoint, channels, Object.values(nextTasks), checkpointer.getNextVersion.bind(checkpointer), this.triggerToNodes);
621
+ }
622
+ const nextConfig$1 = await checkpointer.put(checkpointConfig, createCheckpoint(checkpoint, channels, step), {
623
+ ...checkpointMetadata,
624
+ source: "update",
625
+ step: step + 1,
626
+ parents: saved?.metadata?.parents ?? {}
627
+ }, getNewChannelVersions(checkpointPreviousVersions, checkpoint.channel_versions));
628
+ return patchCheckpointMap(nextConfig$1, saved ? saved.metadata : void 0);
629
+ }
630
+ if (asNode === COPY) {
631
+ if (updates.length > 1) throw new InvalidUpdateError(`Cannot copy checkpoint with multiple updates`);
632
+ if (saved == null) throw new InvalidUpdateError(`Cannot copy a non-existent checkpoint`);
633
+ const isCopyWithUpdates = (values$1) => {
634
+ if (!Array.isArray(values$1)) return false;
635
+ if (values$1.length === 0) return false;
636
+ return values$1.every((v) => Array.isArray(v) && v.length === 2);
637
+ };
638
+ const nextCheckpoint = createCheckpoint(checkpoint, void 0, step);
639
+ const nextConfig$1 = await checkpointer.put(saved.parentConfig ?? patchConfigurable(saved.config, { checkpoint_id: void 0 }), nextCheckpoint, {
640
+ source: "fork",
641
+ step: step + 1,
642
+ parents: saved.metadata?.parents ?? {}
643
+ }, {});
644
+ if (isCopyWithUpdates(values)) {
645
+ const nextTasks = _prepareNextTasks(nextCheckpoint, saved.pendingWrites, this.nodes, channels, nextConfig$1, false, { step: step + 2 });
646
+ const tasksGroupBy = Object.values(nextTasks).reduce((acc, { name, id }) => {
647
+ acc[name] ??= [];
648
+ acc[name].push({ id });
649
+ return acc;
650
+ }, {});
651
+ const userGroupBy = values.reduce((acc, item) => {
652
+ const [values$1, asNode$1] = item;
653
+ acc[asNode$1] ??= [];
654
+ const targetIdx = acc[asNode$1].length;
655
+ const taskId = tasksGroupBy[asNode$1]?.[targetIdx]?.id;
656
+ acc[asNode$1].push({
657
+ values: values$1,
658
+ asNode: asNode$1,
659
+ taskId
660
+ });
661
+ return acc;
662
+ }, {});
663
+ return updateSuperStep(patchCheckpointMap(nextConfig$1, saved.metadata), Object.values(userGroupBy).flat());
664
+ }
665
+ return patchCheckpointMap(nextConfig$1, saved.metadata);
666
+ }
667
+ if (asNode === INPUT) {
668
+ if (updates.length > 1) throw new InvalidUpdateError(`Cannot apply multiple updates when updating as input`);
669
+ const inputWrites = await gatherIterator(mapInput(this.inputChannels, values));
670
+ if (inputWrites.length === 0) throw new InvalidUpdateError(`Received no input writes for ${JSON.stringify(this.inputChannels, null, 2)}`);
671
+ _applyWrites(checkpoint, channels, [{
672
+ name: INPUT,
673
+ writes: inputWrites,
674
+ triggers: []
675
+ }], checkpointer.getNextVersion.bind(this.checkpointer), this.triggerToNodes);
676
+ const nextStep = saved?.metadata?.step != null ? saved.metadata.step + 1 : -1;
677
+ const nextConfig$1 = await checkpointer.put(checkpointConfig, createCheckpoint(checkpoint, channels, nextStep), {
678
+ source: "input",
679
+ step: nextStep,
680
+ parents: saved?.metadata?.parents ?? {}
681
+ }, getNewChannelVersions(checkpointPreviousVersions, checkpoint.channel_versions));
682
+ await checkpointer.putWrites(nextConfig$1, inputWrites, uuid5(INPUT, checkpoint.id));
683
+ return patchCheckpointMap(nextConfig$1, saved ? saved.metadata : void 0);
684
+ }
685
+ if (config.configurable?.checkpoint_id === void 0 && saved?.pendingWrites !== void 0 && saved.pendingWrites.length > 0) {
686
+ const nextTasks = _prepareNextTasks(checkpoint, saved.pendingWrites, this.nodes, channels, saved.config, true, {
687
+ store: this.store,
688
+ checkpointer: this.checkpointer,
689
+ step: (saved.metadata?.step ?? -1) + 1
690
+ });
691
+ const nullWrites = (saved.pendingWrites ?? []).filter((w) => w[0] === NULL_TASK_ID).map((w) => w.slice(1));
692
+ if (nullWrites.length > 0) _applyWrites(saved.checkpoint, channels, [{
693
+ name: INPUT,
694
+ writes: nullWrites,
695
+ triggers: []
696
+ }], void 0, this.triggerToNodes);
697
+ for (const [tid, k, v] of saved.pendingWrites) {
698
+ if ([
699
+ ERROR,
700
+ INTERRUPT,
701
+ SCHEDULED
702
+ ].includes(k) || nextTasks[tid] === void 0) continue;
703
+ nextTasks[tid].writes.push([k, v]);
704
+ }
705
+ const tasks$1 = Object.values(nextTasks).filter((task) => {
706
+ return task.writes.length > 0;
707
+ });
708
+ if (tasks$1.length > 0) _applyWrites(checkpoint, channels, tasks$1, void 0, this.triggerToNodes);
709
+ }
710
+ const nonNullVersion = Object.values(checkpoint.versions_seen).map((seenVersions) => {
711
+ return Object.values(seenVersions);
712
+ }).flat().find((v) => !!v);
713
+ const validUpdates = [];
714
+ if (updates.length === 1) {
715
+ let { values: values$1, asNode: asNode$1, taskId } = updates[0];
716
+ if (asNode$1 === void 0 && Object.keys(this.nodes).length === 1) [asNode$1] = Object.keys(this.nodes);
717
+ else if (asNode$1 === void 0 && nonNullVersion === void 0) {
718
+ if (typeof this.inputChannels === "string" && this.nodes[this.inputChannels] !== void 0) asNode$1 = this.inputChannels;
719
+ } else if (asNode$1 === void 0) {
720
+ const lastSeenByNode = Object.entries(checkpoint.versions_seen).map(([n, seen]) => {
721
+ return Object.values(seen).map((v) => {
722
+ return [v, n];
723
+ });
724
+ }).flat().filter(([_, v]) => v !== INTERRUPT).sort(([aNumber], [bNumber]) => compareChannelVersions(aNumber, bNumber));
725
+ if (lastSeenByNode) {
726
+ if (lastSeenByNode.length === 1) asNode$1 = lastSeenByNode[0][1];
727
+ else if (lastSeenByNode[lastSeenByNode.length - 1][0] !== lastSeenByNode[lastSeenByNode.length - 2][0]) asNode$1 = lastSeenByNode[lastSeenByNode.length - 1][1];
728
+ }
729
+ }
730
+ if (asNode$1 === void 0) throw new InvalidUpdateError(`Ambiguous update, specify "asNode"`);
731
+ validUpdates.push({
732
+ values: values$1,
733
+ asNode: asNode$1,
734
+ taskId
735
+ });
736
+ } else for (const { asNode: asNode$1, values: values$1, taskId } of updates) {
737
+ if (asNode$1 == null) throw new InvalidUpdateError(`"asNode" is required when applying multiple updates`);
738
+ validUpdates.push({
739
+ values: values$1,
740
+ asNode: asNode$1,
741
+ taskId
742
+ });
743
+ }
744
+ const tasks = [];
745
+ for (const { asNode: asNode$1, values: values$1, taskId } of validUpdates) {
746
+ if (this.nodes[asNode$1] === void 0) throw new InvalidUpdateError(`Node "${asNode$1.toString()}" does not exist`);
747
+ const writers = this.nodes[asNode$1].getWriters();
748
+ if (!writers.length) throw new InvalidUpdateError(`No writers found for node "${asNode$1.toString()}"`);
749
+ tasks.push({
750
+ name: asNode$1,
751
+ input: values$1,
752
+ proc: writers.length > 1 ? RunnableSequence.from(writers, { omitSequenceTags: true }) : writers[0],
753
+ writes: [],
754
+ triggers: [INTERRUPT],
755
+ id: taskId ?? uuid5(INTERRUPT, checkpoint.id),
756
+ writers: []
757
+ });
758
+ }
759
+ for (const task of tasks) await task.proc.invoke(task.input, patchConfig({
760
+ ...config,
761
+ store: config?.store ?? this.store
762
+ }, {
763
+ runName: config.runName ?? `${this.getName()}UpdateState`,
764
+ configurable: {
765
+ [CONFIG_KEY_SEND]: (items) => task.writes.push(...items),
766
+ [CONFIG_KEY_READ]: (select_, fresh_ = false) => _localRead(checkpoint, channels, task, select_, fresh_)
767
+ }
768
+ }));
769
+ for (const task of tasks) {
770
+ const channelWrites = task.writes.filter((w) => w[0] !== PUSH);
771
+ if (saved !== void 0 && channelWrites.length > 0) await checkpointer.putWrites(checkpointConfig, channelWrites, task.id);
772
+ }
773
+ _applyWrites(checkpoint, channels, tasks, checkpointer.getNextVersion.bind(this.checkpointer), this.triggerToNodes);
774
+ const newVersions = getNewChannelVersions(checkpointPreviousVersions, checkpoint.channel_versions);
775
+ const nextConfig = await checkpointer.put(checkpointConfig, createCheckpoint(checkpoint, channels, step + 1), {
776
+ source: "update",
777
+ step: step + 1,
778
+ parents: saved?.metadata?.parents ?? {}
779
+ }, newVersions);
780
+ for (const task of tasks) {
781
+ const pushWrites = task.writes.filter((w) => w[0] === PUSH);
782
+ if (pushWrites.length > 0) await checkpointer.putWrites(nextConfig, pushWrites, task.id);
783
+ }
784
+ return patchCheckpointMap(nextConfig, saved ? saved.metadata : void 0);
785
+ };
786
+ let currentConfig = startConfig;
787
+ for (const { updates } of supersteps) currentConfig = await updateSuperStep(currentConfig, updates);
788
+ return currentConfig;
789
+ }
790
+ /**
791
+ * Updates the state of the graph with new values.
792
+ * Requires a checkpointer to be configured.
793
+ *
794
+ * This method can be used for:
795
+ * - Implementing human-in-the-loop workflows
796
+ * - Modifying graph state during breakpoints
797
+ * - Integrating external inputs into the graph
798
+ *
799
+ * @param inputConfig - Configuration for the update
800
+ * @param values - The values to update the state with
801
+ * @param asNode - Optional node name to attribute the update to
802
+ * @returns Updated configuration
803
+ * @throws {GraphValueError} If no checkpointer is configured
804
+ * @throws {InvalidUpdateError} If the update cannot be attributed to a node
805
+ */
806
+ async updateState(inputConfig, values, asNode) {
807
+ return this.bulkUpdateState(inputConfig, [{ updates: [{
808
+ values,
809
+ asNode
810
+ }] }]);
811
+ }
812
+ /**
813
+ * Gets the default values for various graph configuration options.
814
+ * This is an internal method used to process and normalize configuration options.
815
+ *
816
+ * @param config - The input configuration options
817
+ * @returns A tuple containing normalized values for:
818
+ * - debug mode
819
+ * - stream modes
820
+ * - input keys
821
+ * - output keys
822
+ * - remaining config
823
+ * - interrupt before nodes
824
+ * - interrupt after nodes
825
+ * - checkpointer
826
+ * - store
827
+ * - whether stream mode is single
828
+ * - node cache
829
+ * - whether checkpoint during is enabled
830
+ * @internal
831
+ */
832
+ _defaults(config) {
833
+ const { debug, streamMode, inputKeys, outputKeys, interruptAfter, interruptBefore,...rest } = config;
834
+ let streamModeSingle = true;
835
+ const defaultDebug = debug !== void 0 ? debug : this.debug;
836
+ let defaultOutputKeys = outputKeys;
837
+ if (defaultOutputKeys === void 0) defaultOutputKeys = this.streamChannelsAsIs;
838
+ else validateKeys(defaultOutputKeys, this.channels);
839
+ let defaultInputKeys = inputKeys;
840
+ if (defaultInputKeys === void 0) defaultInputKeys = this.inputChannels;
841
+ else validateKeys(defaultInputKeys, this.channels);
842
+ const defaultInterruptBefore = interruptBefore ?? this.interruptBefore ?? [];
843
+ const defaultInterruptAfter = interruptAfter ?? this.interruptAfter ?? [];
844
+ let defaultStreamMode;
845
+ if (streamMode !== void 0) {
846
+ defaultStreamMode = Array.isArray(streamMode) ? streamMode : [streamMode];
847
+ streamModeSingle = typeof streamMode === "string";
848
+ } else {
849
+ if (config.configurable?.[CONFIG_KEY_TASK_ID] !== void 0) defaultStreamMode = ["values"];
850
+ else defaultStreamMode = this.streamMode;
851
+ streamModeSingle = true;
852
+ }
853
+ let defaultCheckpointer;
854
+ if (this.checkpointer === false) defaultCheckpointer = void 0;
855
+ else if (config !== void 0 && config.configurable?.[CONFIG_KEY_CHECKPOINTER] !== void 0) defaultCheckpointer = config.configurable[CONFIG_KEY_CHECKPOINTER];
856
+ else if (this.checkpointer === true) throw new Error("checkpointer: true cannot be used for root graphs.");
857
+ else defaultCheckpointer = this.checkpointer;
858
+ const defaultStore = config.store ?? this.store;
859
+ const defaultCache = config.cache ?? this.cache;
860
+ if (config.durability != null && config.checkpointDuring != null) throw new Error("Cannot use both `durability` and `checkpointDuring` at the same time.");
861
+ const checkpointDuringDurability = (() => {
862
+ if (config.checkpointDuring == null) return void 0;
863
+ if (config.checkpointDuring === false) return "exit";
864
+ return "async";
865
+ })();
866
+ const defaultDurability = config.durability ?? checkpointDuringDurability ?? config?.configurable?.[CONFIG_KEY_DURABILITY] ?? "async";
867
+ return [
868
+ defaultDebug,
869
+ defaultStreamMode,
870
+ defaultInputKeys,
871
+ defaultOutputKeys,
872
+ rest,
873
+ defaultInterruptBefore,
874
+ defaultInterruptAfter,
875
+ defaultCheckpointer,
876
+ defaultStore,
877
+ streamModeSingle,
878
+ defaultCache,
879
+ defaultDurability
880
+ ];
881
+ }
882
+ /**
883
+ * Streams the execution of the graph, emitting state updates as they occur.
884
+ * This is the primary method for observing graph execution in real-time.
885
+ *
886
+ * Stream modes:
887
+ * - "values": Emits complete state after each step
888
+ * - "updates": Emits only state changes after each step
889
+ * - "debug": Emits detailed debug information
890
+ * - "messages": Emits messages from within nodes
891
+ *
892
+ * For more details, see the [Streaming how-to guides](../../how-tos/#streaming_1).
893
+ *
894
+ * @param input - The input to start graph execution with
895
+ * @param options - Configuration options for streaming
896
+ * @returns An async iterable stream of graph state updates
897
+ */
898
+ async stream(input, options) {
899
+ const abortController = new AbortController();
900
+ const config = {
901
+ recursionLimit: this.config?.recursionLimit,
902
+ ...options,
903
+ signal: combineAbortSignals(options?.signal, abortController.signal).signal
904
+ };
905
+ return new IterableReadableStreamWithAbortSignal(await super.stream(input, config), abortController);
906
+ }
907
+ streamEvents(input, options, streamOptions) {
908
+ const abortController = new AbortController();
909
+ const config = {
910
+ recursionLimit: this.config?.recursionLimit,
911
+ ...options,
912
+ callbacks: combineCallbacks(this.config?.callbacks, options?.callbacks),
913
+ signal: combineAbortSignals(options?.signal, abortController.signal).signal
914
+ };
915
+ return new IterableReadableStreamWithAbortSignal(super.streamEvents(input, config, streamOptions), abortController);
916
+ }
917
+ /**
918
+ * Validates the input for the graph.
919
+ * @param input - The input to validate
920
+ * @returns The validated input
921
+ * @internal
922
+ */
923
+ async _validateInput(input) {
924
+ return input;
925
+ }
926
+ /**
927
+ * Validates the context options for the graph.
928
+ * @param context - The context options to validate
929
+ * @returns The validated context options
930
+ * @internal
931
+ */
932
+ async _validateContext(context) {
933
+ return context;
934
+ }
935
+ /**
936
+ * Internal iterator used by stream() to generate state updates.
937
+ * This method handles the core logic of graph execution and streaming.
938
+ *
939
+ * @param input - The input to start graph execution with
940
+ * @param options - Configuration options for streaming
941
+ * @returns AsyncGenerator yielding state updates
942
+ * @internal
943
+ */
944
+ async *_streamIterator(input, options) {
945
+ const streamSubgraphs = options?.subgraphs;
946
+ const inputConfig = ensureLangGraphConfig(this.config, options);
947
+ if (inputConfig.recursionLimit === void 0 || inputConfig.recursionLimit < 1) throw new Error(`Passed "recursionLimit" must be at least 1.`);
948
+ if (this.checkpointer !== void 0 && this.checkpointer !== false && inputConfig.configurable === void 0) throw new Error(`Checkpointer requires one or more of the following "configurable" keys: "thread_id", "checkpoint_ns", "checkpoint_id"`);
949
+ const validInput = await this._validateInput(input);
950
+ const { runId,...restConfig } = inputConfig;
951
+ const [debug, streamMode, , outputKeys, config, interruptBefore, interruptAfter, checkpointer, store, streamModeSingle, cache, durability] = this._defaults(restConfig);
952
+ if (typeof config.context !== "undefined") config.context = await this._validateContext(config.context);
953
+ else config.configurable = await this._validateContext(config.configurable);
954
+ const stream = new IterableReadableWritableStream({ modes: new Set(streamMode) });
955
+ if (this.checkpointer === true) {
956
+ config.configurable ??= {};
957
+ const ns = config.configurable[CONFIG_KEY_CHECKPOINT_NS] ?? "";
958
+ config.configurable[CONFIG_KEY_CHECKPOINT_NS] = ns.split(CHECKPOINT_NAMESPACE_SEPARATOR).map((part) => part.split(CHECKPOINT_NAMESPACE_END)[0]).join(CHECKPOINT_NAMESPACE_SEPARATOR);
959
+ }
960
+ if (streamMode.includes("messages")) {
961
+ const messageStreamer = new StreamMessagesHandler((chunk) => stream.push(chunk));
962
+ const { callbacks } = config;
963
+ if (callbacks === void 0) config.callbacks = [messageStreamer];
964
+ else if (Array.isArray(callbacks)) config.callbacks = callbacks.concat(messageStreamer);
965
+ else {
966
+ const copiedCallbacks = callbacks.copy();
967
+ copiedCallbacks.addHandler(messageStreamer, true);
968
+ config.callbacks = copiedCallbacks;
969
+ }
970
+ }
971
+ if (streamMode.includes("custom")) config.writer = (chunk) => {
972
+ const ns = (getConfig()?.configurable?.[CONFIG_KEY_CHECKPOINT_NS])?.split(CHECKPOINT_NAMESPACE_SEPARATOR).slice(0, -1);
973
+ stream.push([
974
+ ns ?? [],
975
+ "custom",
976
+ chunk
977
+ ]);
978
+ };
979
+ const callbackManager = await getCallbackManagerForConfig(config);
980
+ const runManager = await callbackManager?.handleChainStart(this.toJSON(), _coerceToDict(input, "input"), runId, void 0, void 0, void 0, config?.runName ?? this.getName());
981
+ const channelSpecs = getOnlyChannels(this.channels);
982
+ let loop;
983
+ let loopError;
984
+ /**
985
+ * The PregelLoop will yield events from concurrent tasks as soon as they are
986
+ * generated. Each task can push multiple events onto the stream in any order.
987
+ *
988
+ * We use a separate background method and stream here in order to yield events
989
+ * from the loop to the main stream and therefore back to the user as soon as
990
+ * they are available.
991
+ */
992
+ const createAndRunLoop = async () => {
993
+ try {
994
+ loop = await PregelLoop.initialize({
995
+ input: validInput,
996
+ config,
997
+ checkpointer,
998
+ nodes: this.nodes,
999
+ channelSpecs,
1000
+ outputKeys,
1001
+ streamKeys: this.streamChannelsAsIs,
1002
+ store,
1003
+ cache,
1004
+ stream,
1005
+ interruptAfter,
1006
+ interruptBefore,
1007
+ manager: runManager,
1008
+ debug: this.debug,
1009
+ triggerToNodes: this.triggerToNodes,
1010
+ durability
1011
+ });
1012
+ const runner = new PregelRunner({
1013
+ loop,
1014
+ nodeFinished: config.configurable?.[CONFIG_KEY_NODE_FINISHED]
1015
+ });
1016
+ if (options?.subgraphs) loop.config.configurable = {
1017
+ ...loop.config.configurable,
1018
+ [CONFIG_KEY_STREAM]: loop.stream
1019
+ };
1020
+ await this._runLoop({
1021
+ loop,
1022
+ runner,
1023
+ debug,
1024
+ config
1025
+ });
1026
+ if (durability === "sync") await Promise.all(loop?.checkpointerPromises ?? []);
1027
+ } catch (e) {
1028
+ loopError = e;
1029
+ } finally {
1030
+ try {
1031
+ if (loop) {
1032
+ await loop.store?.stop();
1033
+ await loop.cache?.stop();
1034
+ }
1035
+ await Promise.all(loop?.checkpointerPromises ?? []);
1036
+ } catch (e) {
1037
+ loopError = loopError ?? e;
1038
+ }
1039
+ if (loopError) stream.error(loopError);
1040
+ else stream.close();
1041
+ }
1042
+ };
1043
+ const runLoopPromise = createAndRunLoop();
1044
+ try {
1045
+ for await (const chunk of stream) {
1046
+ if (chunk === void 0) throw new Error("Data structure error.");
1047
+ const [namespace, mode, payload] = chunk;
1048
+ if (streamMode.includes(mode)) if (streamSubgraphs && !streamModeSingle) yield [
1049
+ namespace,
1050
+ mode,
1051
+ payload
1052
+ ];
1053
+ else if (!streamModeSingle) yield [mode, payload];
1054
+ else if (streamSubgraphs) yield [namespace, payload];
1055
+ else yield payload;
1056
+ }
1057
+ } catch (e) {
1058
+ await runManager?.handleChainError(loopError);
1059
+ throw e;
1060
+ } finally {
1061
+ await runLoopPromise;
1062
+ }
1063
+ await runManager?.handleChainEnd(loop?.output ?? {}, runId, void 0, void 0, void 0);
1064
+ }
1065
+ /**
1066
+ * Run the graph with a single input and config.
1067
+ * @param input The input to the graph.
1068
+ * @param options The configuration to use for the run.
1069
+ */
1070
+ async invoke(input, options) {
1071
+ const streamMode = options?.streamMode ?? "values";
1072
+ const config = {
1073
+ ...options,
1074
+ outputKeys: options?.outputKeys ?? this.outputChannels,
1075
+ streamMode
1076
+ };
1077
+ const chunks = [];
1078
+ const stream = await this.stream(input, config);
1079
+ const interruptChunks = [];
1080
+ let latest;
1081
+ for await (const chunk of stream) if (streamMode === "values") if (isInterrupted(chunk)) interruptChunks.push(chunk[INTERRUPT]);
1082
+ else latest = chunk;
1083
+ else chunks.push(chunk);
1084
+ if (streamMode === "values") {
1085
+ if (interruptChunks.length > 0) {
1086
+ const interrupts = interruptChunks.flat(1);
1087
+ if (latest == null) return { [INTERRUPT]: interrupts };
1088
+ if (typeof latest === "object") return {
1089
+ ...latest,
1090
+ [INTERRUPT]: interrupts
1091
+ };
1092
+ }
1093
+ return latest;
1094
+ }
1095
+ return chunks;
1096
+ }
1097
+ async _runLoop(params) {
1098
+ const { loop, runner, debug, config } = params;
1099
+ let tickError;
1100
+ try {
1101
+ while (await loop.tick({ inputKeys: this.inputChannels })) {
1102
+ for (const { task } of await loop._matchCachedWrites()) loop._outputWrites(task.id, task.writes, true);
1103
+ if (debug) printStepCheckpoint(loop.checkpointMetadata.step, loop.channels, this.streamChannelsList);
1104
+ if (debug) printStepTasks(loop.step, Object.values(loop.tasks));
1105
+ await runner.tick({
1106
+ timeout: this.stepTimeout,
1107
+ retryPolicy: this.retryPolicy,
1108
+ onStepWrite: (step, writes) => {
1109
+ if (debug) printStepWrites(step, writes, this.streamChannelsList);
1110
+ },
1111
+ maxConcurrency: config.maxConcurrency,
1112
+ signal: config.signal
1113
+ });
1114
+ }
1115
+ if (loop.status === "out_of_steps") throw new GraphRecursionError([
1116
+ `Recursion limit of ${config.recursionLimit} reached`,
1117
+ "without hitting a stop condition. You can increase the",
1118
+ `limit by setting the "recursionLimit" config key.`
1119
+ ].join(" "), { lc_error_code: "GRAPH_RECURSION_LIMIT" });
1120
+ } catch (e) {
1121
+ tickError = e;
1122
+ const suppress = await loop.finishAndHandleError(tickError);
1123
+ if (!suppress) throw e;
1124
+ } finally {
1125
+ if (tickError === void 0) await loop.finishAndHandleError();
1126
+ }
1127
+ }
1128
+ async clearCache() {
1129
+ await this.cache?.clear([]);
1130
+ }
1131
+ };
1132
+
1133
+ //#endregion
1134
+ export { Channel, Pregel };
1602
1135
  //# sourceMappingURL=index.js.map