@langchain/langgraph-sdk 1.8.10 → 1.9.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 (435) hide show
  1. package/README.md +90 -43
  2. package/dist/client/assistants/index.cjs +180 -0
  3. package/dist/client/assistants/index.cjs.map +1 -0
  4. package/dist/client/assistants/index.d.cts +155 -0
  5. package/dist/client/assistants/index.d.cts.map +1 -0
  6. package/dist/client/assistants/index.d.ts +155 -0
  7. package/dist/client/assistants/index.d.ts.map +1 -0
  8. package/dist/client/assistants/index.js +180 -0
  9. package/dist/client/assistants/index.js.map +1 -0
  10. package/dist/client/base.cjs +190 -0
  11. package/dist/client/base.cjs.map +1 -0
  12. package/dist/client/base.d.cts +84 -0
  13. package/dist/client/base.d.cts.map +1 -0
  14. package/dist/client/base.d.ts +84 -0
  15. package/dist/client/base.d.ts.map +1 -0
  16. package/dist/client/base.js +188 -0
  17. package/dist/client/base.js.map +1 -0
  18. package/dist/client/crons/index.cjs +159 -0
  19. package/dist/client/crons/index.cjs.map +1 -0
  20. package/dist/client/crons/index.d.cts +71 -0
  21. package/dist/client/crons/index.d.cts.map +1 -0
  22. package/dist/client/crons/index.d.ts +71 -0
  23. package/dist/client/crons/index.d.ts.map +1 -0
  24. package/dist/client/crons/index.js +159 -0
  25. package/dist/client/crons/index.js.map +1 -0
  26. package/dist/client/index.cjs +84 -0
  27. package/dist/client/index.cjs.map +1 -0
  28. package/dist/client/index.d.cts +63 -0
  29. package/dist/client/index.d.cts.map +1 -0
  30. package/dist/client/index.d.ts +63 -0
  31. package/dist/client/index.d.ts.map +1 -0
  32. package/dist/client/index.js +83 -0
  33. package/dist/client/index.js.map +1 -0
  34. package/dist/client/runs/index.cjs +275 -0
  35. package/dist/client/runs/index.cjs.map +1 -0
  36. package/dist/client/runs/index.d.cts +123 -0
  37. package/dist/client/runs/index.d.cts.map +1 -0
  38. package/dist/client/runs/index.d.ts +123 -0
  39. package/dist/client/runs/index.d.ts.map +1 -0
  40. package/dist/client/runs/index.js +275 -0
  41. package/dist/client/runs/index.js.map +1 -0
  42. package/dist/client/store/index.cjs +128 -0
  43. package/dist/client/store/index.cjs.map +1 -0
  44. package/dist/client/store/index.d.cts +75 -0
  45. package/dist/client/store/index.d.cts.map +1 -0
  46. package/dist/client/store/index.d.ts +75 -0
  47. package/dist/client/store/index.d.ts.map +1 -0
  48. package/dist/client/store/index.js +128 -0
  49. package/dist/client/store/index.js.map +1 -0
  50. package/dist/client/stream/error.cjs +18 -0
  51. package/dist/client/stream/error.cjs.map +1 -0
  52. package/dist/client/stream/error.d.cts +14 -0
  53. package/dist/client/stream/error.d.cts.map +1 -0
  54. package/dist/client/stream/error.d.ts +14 -0
  55. package/dist/client/stream/error.d.ts.map +1 -0
  56. package/dist/client/stream/error.js +18 -0
  57. package/dist/client/stream/error.js.map +1 -0
  58. package/dist/client/stream/handles/index.cjs +3 -0
  59. package/dist/client/stream/handles/index.d.ts +3 -0
  60. package/dist/client/stream/handles/index.js +4 -0
  61. package/dist/client/stream/handles/subagents.cjs +263 -0
  62. package/dist/client/stream/handles/subagents.cjs.map +1 -0
  63. package/dist/client/stream/handles/subagents.d.cts +45 -0
  64. package/dist/client/stream/handles/subagents.d.cts.map +1 -0
  65. package/dist/client/stream/handles/subagents.d.ts +45 -0
  66. package/dist/client/stream/handles/subagents.d.ts.map +1 -0
  67. package/dist/client/stream/handles/subagents.js +262 -0
  68. package/dist/client/stream/handles/subagents.js.map +1 -0
  69. package/dist/client/stream/handles/subgraphs.cjs +352 -0
  70. package/dist/client/stream/handles/subgraphs.cjs.map +1 -0
  71. package/dist/client/stream/handles/subgraphs.d.cts +82 -0
  72. package/dist/client/stream/handles/subgraphs.d.cts.map +1 -0
  73. package/dist/client/stream/handles/subgraphs.d.ts +82 -0
  74. package/dist/client/stream/handles/subgraphs.d.ts.map +1 -0
  75. package/dist/client/stream/handles/subgraphs.js +351 -0
  76. package/dist/client/stream/handles/subgraphs.js.map +1 -0
  77. package/dist/client/stream/handles/tools.cjs +92 -0
  78. package/dist/client/stream/handles/tools.cjs.map +1 -0
  79. package/dist/client/stream/handles/tools.d.cts +26 -0
  80. package/dist/client/stream/handles/tools.d.cts.map +1 -0
  81. package/dist/client/stream/handles/tools.d.ts +26 -0
  82. package/dist/client/stream/handles/tools.d.ts.map +1 -0
  83. package/dist/client/stream/handles/tools.js +92 -0
  84. package/dist/client/stream/handles/tools.js.map +1 -0
  85. package/dist/client/stream/index.cjs +1368 -0
  86. package/dist/client/stream/index.cjs.map +1 -0
  87. package/dist/client/stream/index.d.cts +238 -0
  88. package/dist/client/stream/index.d.cts.map +1 -0
  89. package/dist/client/stream/index.d.ts +238 -0
  90. package/dist/client/stream/index.d.ts.map +1 -0
  91. package/dist/client/stream/index.js +1367 -0
  92. package/dist/client/stream/index.js.map +1 -0
  93. package/dist/client/stream/media.cjs +506 -0
  94. package/dist/client/stream/media.cjs.map +1 -0
  95. package/dist/client/stream/media.d.cts +164 -0
  96. package/dist/client/stream/media.d.cts.map +1 -0
  97. package/dist/client/stream/media.d.ts +164 -0
  98. package/dist/client/stream/media.d.ts.map +1 -0
  99. package/dist/client/stream/media.js +505 -0
  100. package/dist/client/stream/media.js.map +1 -0
  101. package/dist/client/stream/messages.cjs +635 -0
  102. package/dist/client/stream/messages.cjs.map +1 -0
  103. package/dist/client/stream/messages.d.cts +139 -0
  104. package/dist/client/stream/messages.d.cts.map +1 -0
  105. package/dist/client/stream/messages.d.ts +139 -0
  106. package/dist/client/stream/messages.d.ts.map +1 -0
  107. package/dist/client/stream/messages.js +631 -0
  108. package/dist/client/stream/messages.js.map +1 -0
  109. package/dist/client/stream/multi-cursor-buffer.cjs +55 -0
  110. package/dist/client/stream/multi-cursor-buffer.cjs.map +1 -0
  111. package/dist/client/stream/multi-cursor-buffer.js +55 -0
  112. package/dist/client/stream/multi-cursor-buffer.js.map +1 -0
  113. package/dist/client/stream/subscription.cjs +85 -0
  114. package/dist/client/stream/subscription.cjs.map +1 -0
  115. package/dist/client/stream/subscription.d.cts +22 -0
  116. package/dist/client/stream/subscription.d.cts.map +1 -0
  117. package/dist/client/stream/subscription.d.ts +22 -0
  118. package/dist/client/stream/subscription.d.ts.map +1 -0
  119. package/dist/client/stream/subscription.js +84 -0
  120. package/dist/client/stream/subscription.js.map +1 -0
  121. package/dist/client/stream/transport/agent-server.cjs +45 -0
  122. package/dist/client/stream/transport/agent-server.cjs.map +1 -0
  123. package/dist/client/stream/transport/agent-server.d.cts +39 -0
  124. package/dist/client/stream/transport/agent-server.d.cts.map +1 -0
  125. package/dist/client/stream/transport/agent-server.d.ts +39 -0
  126. package/dist/client/stream/transport/agent-server.d.ts.map +1 -0
  127. package/dist/client/stream/transport/agent-server.js +45 -0
  128. package/dist/client/stream/transport/agent-server.js.map +1 -0
  129. package/dist/client/stream/transport/constants.cjs +10 -0
  130. package/dist/client/stream/transport/constants.cjs.map +1 -0
  131. package/dist/client/stream/transport/constants.js +10 -0
  132. package/dist/client/stream/transport/constants.js.map +1 -0
  133. package/dist/client/stream/transport/decoder.cjs +115 -0
  134. package/dist/client/stream/transport/decoder.cjs.map +1 -0
  135. package/dist/client/stream/transport/decoder.js +114 -0
  136. package/dist/client/stream/transport/decoder.js.map +1 -0
  137. package/dist/client/stream/transport/http.cjs +183 -0
  138. package/dist/client/stream/transport/http.cjs.map +1 -0
  139. package/dist/client/stream/transport/http.d.cts +45 -0
  140. package/dist/client/stream/transport/http.d.cts.map +1 -0
  141. package/dist/client/stream/transport/http.d.ts +45 -0
  142. package/dist/client/stream/transport/http.d.ts.map +1 -0
  143. package/dist/client/stream/transport/http.js +183 -0
  144. package/dist/client/stream/transport/http.js.map +1 -0
  145. package/dist/client/stream/transport/index.cjs +3 -0
  146. package/dist/client/stream/transport/index.js +4 -0
  147. package/dist/client/stream/transport/queue.cjs +55 -0
  148. package/dist/client/stream/transport/queue.cjs.map +1 -0
  149. package/dist/client/stream/transport/queue.js +55 -0
  150. package/dist/client/stream/transport/queue.js.map +1 -0
  151. package/dist/client/stream/transport/stream.cjs +79 -0
  152. package/dist/client/stream/transport/stream.cjs.map +1 -0
  153. package/dist/client/stream/transport/stream.js +79 -0
  154. package/dist/client/stream/transport/stream.js.map +1 -0
  155. package/dist/client/stream/transport/types.d.cts +29 -0
  156. package/dist/client/stream/transport/types.d.cts.map +1 -0
  157. package/dist/client/stream/transport/types.d.ts +29 -0
  158. package/dist/client/stream/transport/types.d.ts.map +1 -0
  159. package/dist/client/stream/transport/utils.cjs +45 -0
  160. package/dist/client/stream/transport/utils.cjs.map +1 -0
  161. package/dist/client/stream/transport/utils.js +39 -0
  162. package/dist/client/stream/transport/utils.js.map +1 -0
  163. package/dist/client/stream/transport/websocket.cjs +155 -0
  164. package/dist/client/stream/transport/websocket.cjs.map +1 -0
  165. package/dist/client/stream/transport/websocket.d.cts +36 -0
  166. package/dist/client/stream/transport/websocket.d.cts.map +1 -0
  167. package/dist/client/stream/transport/websocket.d.ts +36 -0
  168. package/dist/client/stream/transport/websocket.d.ts.map +1 -0
  169. package/dist/client/stream/transport/websocket.js +155 -0
  170. package/dist/client/stream/transport/websocket.js.map +1 -0
  171. package/dist/client/stream/transport.d.cts +104 -0
  172. package/dist/client/stream/transport.d.cts.map +1 -0
  173. package/dist/client/stream/transport.d.ts +104 -0
  174. package/dist/client/stream/transport.d.ts.map +1 -0
  175. package/dist/client/stream/types.d.cts +208 -0
  176. package/dist/client/stream/types.d.cts.map +1 -0
  177. package/dist/client/stream/types.d.ts +208 -0
  178. package/dist/client/stream/types.d.ts.map +1 -0
  179. package/dist/client/threads/index.cjs +271 -0
  180. package/dist/client/threads/index.cjs.map +1 -0
  181. package/dist/client/threads/index.d.cts +235 -0
  182. package/dist/client/threads/index.d.cts.map +1 -0
  183. package/dist/client/threads/index.d.ts +235 -0
  184. package/dist/client/threads/index.d.ts.map +1 -0
  185. package/dist/client/threads/index.js +270 -0
  186. package/dist/client/threads/index.js.map +1 -0
  187. package/dist/client/ui-internal/index.cjs +29 -0
  188. package/dist/client/ui-internal/index.cjs.map +1 -0
  189. package/dist/client/ui-internal/index.d.cts +11 -0
  190. package/dist/client/ui-internal/index.d.cts.map +1 -0
  191. package/dist/client/ui-internal/index.d.ts +11 -0
  192. package/dist/client/ui-internal/index.d.ts.map +1 -0
  193. package/dist/client/ui-internal/index.js +29 -0
  194. package/dist/client/ui-internal/index.js.map +1 -0
  195. package/dist/client.cjs +35 -1308
  196. package/dist/client.d.cts +19 -857
  197. package/dist/client.d.ts +19 -857
  198. package/dist/client.js +16 -1301
  199. package/dist/index.cjs +25 -4
  200. package/dist/index.d.cts +15 -3
  201. package/dist/index.d.ts +15 -3
  202. package/dist/index.js +14 -3
  203. package/dist/react/stream.cjs.map +1 -1
  204. package/dist/react/stream.custom.cjs +1 -1
  205. package/dist/react/stream.custom.js +1 -1
  206. package/dist/react/stream.d.cts +2 -1
  207. package/dist/react/stream.d.cts.map +1 -1
  208. package/dist/react/stream.d.ts +2 -1
  209. package/dist/react/stream.d.ts.map +1 -1
  210. package/dist/react/stream.js.map +1 -1
  211. package/dist/react/stream.lgp.cjs +6 -5
  212. package/dist/react/stream.lgp.cjs.map +1 -1
  213. package/dist/react/stream.lgp.js +4 -3
  214. package/dist/react/stream.lgp.js.map +1 -1
  215. package/dist/react/types.d.cts +1 -1
  216. package/dist/react/types.d.ts +1 -1
  217. package/dist/react/types.d.ts.map +1 -1
  218. package/dist/react-ui/server/server.cjs +1 -1
  219. package/dist/react-ui/server/server.cjs.map +1 -1
  220. package/dist/react-ui/server/server.js +1 -1
  221. package/dist/react-ui/server/server.js.map +1 -1
  222. package/dist/react-ui/types.cjs.map +1 -1
  223. package/dist/react-ui/types.d.cts +1 -1
  224. package/dist/react-ui/types.d.cts.map +1 -1
  225. package/dist/react-ui/types.d.ts +1 -1
  226. package/dist/react-ui/types.d.ts.map +1 -1
  227. package/dist/react-ui/types.js.map +1 -1
  228. package/dist/stream/assembled-to-message.cjs +121 -0
  229. package/dist/stream/assembled-to-message.cjs.map +1 -0
  230. package/dist/stream/assembled-to-message.d.cts +35 -0
  231. package/dist/stream/assembled-to-message.d.cts.map +1 -0
  232. package/dist/stream/assembled-to-message.d.ts +35 -0
  233. package/dist/stream/assembled-to-message.d.ts.map +1 -0
  234. package/dist/stream/assembled-to-message.js +119 -0
  235. package/dist/stream/assembled-to-message.js.map +1 -0
  236. package/dist/stream/channel-registry.cjs +224 -0
  237. package/dist/stream/channel-registry.cjs.map +1 -0
  238. package/dist/stream/channel-registry.d.cts +102 -0
  239. package/dist/stream/channel-registry.d.cts.map +1 -0
  240. package/dist/stream/channel-registry.d.ts +102 -0
  241. package/dist/stream/channel-registry.d.ts.map +1 -0
  242. package/dist/stream/channel-registry.js +224 -0
  243. package/dist/stream/channel-registry.js.map +1 -0
  244. package/dist/stream/constants.cjs +11 -0
  245. package/dist/stream/constants.cjs.map +1 -0
  246. package/dist/stream/constants.d.cts +10 -0
  247. package/dist/stream/constants.d.cts.map +1 -0
  248. package/dist/stream/constants.d.ts +10 -0
  249. package/dist/stream/constants.d.ts.map +1 -0
  250. package/dist/stream/constants.js +11 -0
  251. package/dist/stream/constants.js.map +1 -0
  252. package/dist/stream/controller.cjs +933 -0
  253. package/dist/stream/controller.cjs.map +1 -0
  254. package/dist/stream/controller.d.cts +135 -0
  255. package/dist/stream/controller.d.cts.map +1 -0
  256. package/dist/stream/controller.d.ts +135 -0
  257. package/dist/stream/controller.d.ts.map +1 -0
  258. package/dist/stream/controller.js +910 -0
  259. package/dist/stream/controller.js.map +1 -0
  260. package/dist/stream/discovery/index.d.ts +2 -0
  261. package/dist/stream/discovery/subagents.cjs +235 -0
  262. package/dist/stream/discovery/subagents.cjs.map +1 -0
  263. package/dist/stream/discovery/subagents.d.cts +18 -0
  264. package/dist/stream/discovery/subagents.d.cts.map +1 -0
  265. package/dist/stream/discovery/subagents.d.ts +18 -0
  266. package/dist/stream/discovery/subagents.d.ts.map +1 -0
  267. package/dist/stream/discovery/subagents.js +235 -0
  268. package/dist/stream/discovery/subagents.js.map +1 -0
  269. package/dist/stream/discovery/subgraphs.cjs +153 -0
  270. package/dist/stream/discovery/subgraphs.cjs.map +1 -0
  271. package/dist/stream/discovery/subgraphs.d.cts +19 -0
  272. package/dist/stream/discovery/subgraphs.d.cts.map +1 -0
  273. package/dist/stream/discovery/subgraphs.d.ts +19 -0
  274. package/dist/stream/discovery/subgraphs.d.ts.map +1 -0
  275. package/dist/stream/discovery/subgraphs.js +153 -0
  276. package/dist/stream/discovery/subgraphs.js.map +1 -0
  277. package/dist/stream/index.cjs +36 -0
  278. package/dist/stream/index.d.cts +25 -0
  279. package/dist/stream/index.d.ts +25 -0
  280. package/dist/stream/index.js +16 -0
  281. package/dist/stream/lifecycle-loading-tracker.cjs +83 -0
  282. package/dist/stream/lifecycle-loading-tracker.cjs.map +1 -0
  283. package/dist/stream/lifecycle-loading-tracker.js +83 -0
  284. package/dist/stream/lifecycle-loading-tracker.js.map +1 -0
  285. package/dist/stream/message-metadata-tracker.cjs +165 -0
  286. package/dist/stream/message-metadata-tracker.cjs.map +1 -0
  287. package/dist/stream/message-metadata-tracker.d.cts +24 -0
  288. package/dist/stream/message-metadata-tracker.d.cts.map +1 -0
  289. package/dist/stream/message-metadata-tracker.d.ts +24 -0
  290. package/dist/stream/message-metadata-tracker.d.ts.map +1 -0
  291. package/dist/stream/message-metadata-tracker.js +165 -0
  292. package/dist/stream/message-metadata-tracker.js.map +1 -0
  293. package/dist/stream/message-reconciliation.cjs +118 -0
  294. package/dist/stream/message-reconciliation.cjs.map +1 -0
  295. package/dist/stream/message-reconciliation.js +115 -0
  296. package/dist/stream/message-reconciliation.js.map +1 -0
  297. package/dist/stream/namespace.cjs +54 -0
  298. package/dist/stream/namespace.cjs.map +1 -0
  299. package/dist/stream/namespace.js +49 -0
  300. package/dist/stream/namespace.js.map +1 -0
  301. package/dist/stream/projections/channel.cjs +53 -0
  302. package/dist/stream/projections/channel.cjs.map +1 -0
  303. package/dist/stream/projections/channel.d.cts +22 -0
  304. package/dist/stream/projections/channel.d.cts.map +1 -0
  305. package/dist/stream/projections/channel.d.ts +22 -0
  306. package/dist/stream/projections/channel.d.ts.map +1 -0
  307. package/dist/stream/projections/channel.js +53 -0
  308. package/dist/stream/projections/channel.js.map +1 -0
  309. package/dist/stream/projections/extension.cjs +29 -0
  310. package/dist/stream/projections/extension.cjs.map +1 -0
  311. package/dist/stream/projections/extension.d.cts +7 -0
  312. package/dist/stream/projections/extension.d.cts.map +1 -0
  313. package/dist/stream/projections/extension.d.ts +7 -0
  314. package/dist/stream/projections/extension.d.ts.map +1 -0
  315. package/dist/stream/projections/extension.js +29 -0
  316. package/dist/stream/projections/extension.js.map +1 -0
  317. package/dist/stream/projections/index.cjs +6 -0
  318. package/dist/stream/projections/index.d.ts +6 -0
  319. package/dist/stream/projections/index.js +7 -0
  320. package/dist/stream/projections/media.cjs +81 -0
  321. package/dist/stream/projections/media.cjs.map +1 -0
  322. package/dist/stream/projections/media.d.cts +18 -0
  323. package/dist/stream/projections/media.d.cts.map +1 -0
  324. package/dist/stream/projections/media.d.ts +18 -0
  325. package/dist/stream/projections/media.d.ts.map +1 -0
  326. package/dist/stream/projections/media.js +78 -0
  327. package/dist/stream/projections/media.js.map +1 -0
  328. package/dist/stream/projections/messages.cjs +121 -0
  329. package/dist/stream/projections/messages.cjs.map +1 -0
  330. package/dist/stream/projections/messages.d.cts +8 -0
  331. package/dist/stream/projections/messages.d.cts.map +1 -0
  332. package/dist/stream/projections/messages.d.ts +8 -0
  333. package/dist/stream/projections/messages.d.ts.map +1 -0
  334. package/dist/stream/projections/messages.js +121 -0
  335. package/dist/stream/projections/messages.js.map +1 -0
  336. package/dist/stream/projections/runtime.cjs +44 -0
  337. package/dist/stream/projections/runtime.cjs.map +1 -0
  338. package/dist/stream/projections/runtime.js +44 -0
  339. package/dist/stream/projections/runtime.js.map +1 -0
  340. package/dist/stream/projections/tool-calls.cjs +50 -0
  341. package/dist/stream/projections/tool-calls.cjs.map +1 -0
  342. package/dist/stream/projections/tool-calls.d.cts +8 -0
  343. package/dist/stream/projections/tool-calls.d.cts.map +1 -0
  344. package/dist/stream/projections/tool-calls.d.ts +8 -0
  345. package/dist/stream/projections/tool-calls.d.ts.map +1 -0
  346. package/dist/stream/projections/tool-calls.js +50 -0
  347. package/dist/stream/projections/tool-calls.js.map +1 -0
  348. package/dist/stream/projections/values.cjs +52 -0
  349. package/dist/stream/projections/values.cjs.map +1 -0
  350. package/dist/stream/projections/values.d.cts +7 -0
  351. package/dist/stream/projections/values.d.cts.map +1 -0
  352. package/dist/stream/projections/values.d.ts +6 -0
  353. package/dist/stream/projections/values.d.ts.map +1 -0
  354. package/dist/stream/projections/values.js +52 -0
  355. package/dist/stream/projections/values.js.map +1 -0
  356. package/dist/stream/root-message-projection.cjs +256 -0
  357. package/dist/stream/root-message-projection.cjs.map +1 -0
  358. package/dist/stream/root-message-projection.js +256 -0
  359. package/dist/stream/root-message-projection.js.map +1 -0
  360. package/dist/stream/store.cjs +32 -0
  361. package/dist/stream/store.cjs.map +1 -0
  362. package/dist/stream/store.d.cts +37 -0
  363. package/dist/stream/store.d.cts.map +1 -0
  364. package/dist/stream/store.d.ts +37 -0
  365. package/dist/stream/store.d.ts.map +1 -0
  366. package/dist/stream/store.js +32 -0
  367. package/dist/stream/store.js.map +1 -0
  368. package/dist/stream/submit-coordinator.cjs +399 -0
  369. package/dist/stream/submit-coordinator.cjs.map +1 -0
  370. package/dist/stream/submit-coordinator.d.cts +27 -0
  371. package/dist/stream/submit-coordinator.d.cts.map +1 -0
  372. package/dist/stream/submit-coordinator.d.ts +27 -0
  373. package/dist/stream/submit-coordinator.d.ts.map +1 -0
  374. package/dist/stream/submit-coordinator.js +397 -0
  375. package/dist/stream/submit-coordinator.js.map +1 -0
  376. package/dist/stream/tool-calls.cjs +15 -0
  377. package/dist/stream/tool-calls.cjs.map +1 -0
  378. package/dist/stream/tool-calls.js +15 -0
  379. package/dist/stream/tool-calls.js.map +1 -0
  380. package/dist/stream/types-inference.d.cts +43 -0
  381. package/dist/stream/types-inference.d.cts.map +1 -0
  382. package/dist/stream/types-inference.d.ts +43 -0
  383. package/dist/stream/types-inference.d.ts.map +1 -0
  384. package/dist/stream/types.d.cts +354 -0
  385. package/dist/stream/types.d.cts.map +1 -0
  386. package/dist/stream/types.d.ts +354 -0
  387. package/dist/stream/types.d.ts.map +1 -0
  388. package/dist/types.d.cts +2 -1
  389. package/dist/types.d.cts.map +1 -1
  390. package/dist/types.d.ts +2 -1
  391. package/dist/types.d.ts.map +1 -1
  392. package/dist/ui/index.cjs +1 -1
  393. package/dist/ui/index.d.cts +3 -3
  394. package/dist/ui/index.d.ts +3 -3
  395. package/dist/ui/index.js +1 -1
  396. package/dist/ui/manager.cjs +1 -1
  397. package/dist/ui/manager.js +1 -1
  398. package/dist/ui/messages.cjs +50 -7
  399. package/dist/ui/messages.cjs.map +1 -1
  400. package/dist/ui/messages.d.cts.map +1 -1
  401. package/dist/ui/messages.d.ts.map +1 -1
  402. package/dist/ui/messages.js +51 -9
  403. package/dist/ui/messages.js.map +1 -1
  404. package/dist/ui/orchestrator-custom.cjs +1 -1
  405. package/dist/ui/orchestrator-custom.js +1 -1
  406. package/dist/ui/orchestrator.cjs +2 -2
  407. package/dist/ui/orchestrator.d.cts +1 -1
  408. package/dist/ui/orchestrator.d.ts +1 -1
  409. package/dist/ui/orchestrator.d.ts.map +1 -1
  410. package/dist/ui/orchestrator.js +2 -2
  411. package/dist/ui/stream/agent.d.cts +1 -1
  412. package/dist/ui/stream/agent.d.cts.map +1 -1
  413. package/dist/ui/stream/agent.d.ts +1 -1
  414. package/dist/ui/stream/agent.d.ts.map +1 -1
  415. package/dist/ui/stream/base.d.cts +7 -6
  416. package/dist/ui/stream/base.d.cts.map +1 -1
  417. package/dist/ui/stream/base.d.ts +7 -6
  418. package/dist/ui/stream/base.d.ts.map +1 -1
  419. package/dist/ui/stream/deep-agent.d.cts +1 -1
  420. package/dist/ui/stream/deep-agent.d.cts.map +1 -1
  421. package/dist/ui/stream/deep-agent.d.ts +1 -1
  422. package/dist/ui/stream/deep-agent.d.ts.map +1 -1
  423. package/dist/ui/stream/index.d.cts +4 -4
  424. package/dist/ui/stream/index.d.cts.map +1 -1
  425. package/dist/ui/stream/index.d.ts +4 -4
  426. package/dist/ui/stream/index.d.ts.map +1 -1
  427. package/dist/ui/types.d.cts +3 -2
  428. package/dist/ui/types.d.cts.map +1 -1
  429. package/dist/ui/types.d.ts +2 -1
  430. package/dist/ui/types.d.ts.map +1 -1
  431. package/package.json +18 -8
  432. package/dist/client.cjs.map +0 -1
  433. package/dist/client.d.cts.map +0 -1
  434. package/dist/client.d.ts.map +0 -1
  435. package/dist/client.js.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"messages.cjs","names":["namespaceKey","MessageAssembler","isRootNamespace","reconcileMessagesFromValues","ensureMessageInstances","shouldPreferValuesMessageForToolCalls","buildMessageIndex","assembledMessageToBaseMessage","openProjectionSubscription"],"sources":["../../../src/stream/projections/messages.ts"],"sourcesContent":["/**\n * Namespace-scoped `messages` projection.\n *\n * Opens `thread.subscribe({ channels: [\"messages\"], namespaces: [ns] })`\n * and folds each `messages` event through {@link MessageAssembler}.\n * Every update — start, block delta, block finish, message finish —\n * re-derives a `BaseMessage` class instance for the currently-active\n * message and updates its slot in the store.\n *\n * The projection emits `BaseMessage[]` (class instances from\n * `@langchain/core/messages`), never plain serialized objects.\n */\nimport type {\n MessagesEvent,\n MessageRole,\n MessageStartData,\n ValuesEvent,\n} from \"@langchain/protocol\";\nimport type { BaseMessage } from \"@langchain/core/messages\";\nimport { MessageAssembler } from \"../../client/stream/messages.js\";\nimport {\n assembledMessageToBaseMessage,\n type ExtendedMessageRole,\n} from \"../assembled-to-message.js\";\nimport { ensureMessageInstances } from \"../../ui/messages.js\";\nimport type { Message } from \"../../types.messages.js\";\nimport type { ProjectionSpec, ProjectionRuntime } from \"../types.js\";\nimport { isRootNamespace, namespaceKey } from \"../namespace.js\";\nimport {\n buildMessageIndex,\n reconcileMessagesFromValues,\n shouldPreferValuesMessageForToolCalls,\n} from \"../message-reconciliation.js\";\nimport { openProjectionSubscription } from \"./runtime.js\";\n\nexport function messagesProjection(\n namespace: readonly string[]\n): ProjectionSpec<BaseMessage[]> {\n const ns = [...namespace];\n const key = `messages|${namespaceKey(ns)}`;\n\n return {\n key,\n namespace: ns,\n initial: [],\n open({ thread, store, rootBus }): ProjectionRuntime {\n const assembler = new MessageAssembler();\n // Per-messageId state needed for BaseMessage projection:\n // - `role` is only in the `message-start` event; we cache it\n // so subsequent delta events still produce a typed message.\n // - `toolCallId` is pulled from message-start extras when role\n // is `tool` (a convention we keep compatible with serialized\n // v1 tool messages).\n const roleByKey = new Map<\n string,\n { role: ExtendedMessageRole; toolCallId?: string }\n >();\n const indexById = new Map<string, number>();\n // Ids this projection has observed via the `messages` channel\n // (token-level deltas). Used by `applyValuesEvent` to prefer the\n // stream-assembled version over the values-coerced shape while a\n // turn is streaming, matching the root controller's policy.\n const streamMessageIds = new Set<string>();\n // Ids observed in the most recent `values.messages` snapshot.\n // Messages that were present in a prior snapshot but are absent\n // from this one are treated as explicit removals (server-side\n // `RemoveMessage` reducer deltas). Stream-only messages (seen on\n // the messages channel but never echoed in a values snapshot)\n // are preserved — their enclosing superstep may simply not have\n // committed yet.\n let valuesMessageIds = new Set<string>();\n\n // Root-scoped projections whose channels are already covered by\n // the controller's root pump attach to the shared fan-out\n // instead of opening a second server subscription. The root\n // pump runs at `{namespaces: [[]], depth: 1}`, which is exactly\n // the scope a root-namespace `messagesProjection` wants.\n const rootShortCircuit =\n isRootNamespace(ns) && rootBus.channels.includes(\"messages\");\n\n if (rootShortCircuit) {\n const unsubscribe = rootBus.subscribe((event) => {\n if (event.method !== \"messages\") return;\n if (!isRootNamespace(event.params.namespace)) return;\n applyEvent(event as MessagesEvent);\n });\n return {\n dispose() {\n unsubscribe();\n },\n };\n }\n\n let disposed = false;\n\n // Local mirror of the store contents. Every `applyEvent` /\n // `applyValuesEvent` mutates this synchronously; a coalesced\n // `scheduleFlush` copies it to `store` once per macrotask.\n //\n // Why the indirection? When a namespace-scoped projection\n // (e.g. a subagent modal opened after the run finished) first\n // subscribes, the server replays the entire history from\n // `seq=0`. Dozens of `messages`-channel events can land in a\n // single SSE parse — they drain through the `for await` loop\n // as a long microtask chain. Microtasks run before any\n // macrotask, so React's concurrent scheduler never gets a\n // chance to commit between updates. Calling `store.setValue`\n // per event in that burst overflows React's\n // `nestedUpdateCount` guard and throws \"Maximum update depth\n // exceeded\", permanently killing the projection and\n // leaving the store stuck at its first few messages.\n //\n // Batching via `MessageChannel` (macrotask) coalesces the\n // replay burst into one `setValue` call and lets React\n // commit between flushes for live token streaming too.\n const pendingMessages: BaseMessage[] = [];\n let dirty = false;\n let flushScheduled = false;\n const flushChannel =\n typeof MessageChannel !== \"undefined\" ? new MessageChannel() : null;\n\n const flush = (): void => {\n flushScheduled = false;\n if (!dirty || disposed) return;\n dirty = false;\n // `.slice()` breaks identity so React's `Object.is` bail-out\n // in `StreamStore.setValue` propagates the change.\n store.setValue(pendingMessages.slice());\n };\n if (flushChannel != null) {\n flushChannel.port1.onmessage = flush;\n }\n\n const scheduleFlush = (): void => {\n dirty = true;\n if (flushScheduled) return;\n flushScheduled = true;\n if (flushChannel != null) {\n flushChannel.port2.postMessage(null);\n } else {\n setTimeout(flush, 0);\n }\n };\n\n // Rebuild the store from `values.messages` snapshots.\n //\n // `values` events carry the full, committed state of the\n // thread's `messages` channel at a checkpoint — they fire\n // on node completion, AFTER every `messages`-channel delta\n // for that turn has been emitted. They are the authoritative\n // source of truth for ORDER and for non-streamed messages\n // (human turns, serialised tool results, subagent echoes, …).\n //\n // Why rebuild rather than merge-by-id?\n //\n // In practice the server may emit the same logical message\n // with DIFFERENT ids across successive `values` snapshots at\n // the same namespace — e.g. a subagent first surfaces its\n // seed prompt with a synthetic id like\n // `subagent:<tool_call_id>:human`, then a later superstep\n // echoes the same prompt back with a real UUID (or vice\n // versa). A naive \"match-or-append by id\" strategy treats\n // each fresh id as a new entry and the list grows\n // monotonically, showing the same content twice (or more)\n // in the UI.\n //\n // Policy (mirrors the root controller's `#applyValues`):\n //\n // 1. Walk `values.messages` in order. For each id, prefer\n // the stream-assembled entry if we have one for that id\n // (keeps in-progress token streaming visible); otherwise\n // take the values-coerced instance. This self-heals the\n // two classes of glitch the old merge-by-id handler\n // targeted:\n // - tool messages arriving without `tool_call_id` on\n // the messages channel — the values snapshot always\n // carries it;\n // - AI messages whose finalized `tool_calls` didn't\n // fully land via the messages channel — the values\n // snapshot's AI message has them populated.\n //\n // 2. Append any stream-only ids (seen on the messages\n // channel but never echoed in ANY values snapshot yet)\n // — their enclosing superstep hasn't committed yet, so\n // dropping them would flash the UI.\n //\n // 3. Ids that WERE in a prior values snapshot but are gone\n // from this one are treated as explicit removals\n // (`RemoveMessage` reducer deltas) and dropped.\n //\n // Unkeyed messages (no stable id) are passed through in\n // their values order because we can't dedupe them safely.\n const applyValuesEvent = (event: ValuesEvent): void => {\n const data = event.params.data;\n if (data == null || typeof data !== \"object\" || Array.isArray(data)) {\n return;\n }\n const state = data as Record<string, unknown>;\n const rawMessages = state.messages;\n if (!Array.isArray(rawMessages) || rawMessages.length === 0) return;\n\n const coerced = ensureMessageInstances(\n rawMessages as (Message | BaseMessage)[]\n );\n\n const reconciliation = reconcileMessagesFromValues({\n valueMessages: coerced,\n currentMessages: pendingMessages,\n currentIndexById: indexById,\n previousValueMessageIds: valuesMessageIds,\n streamedMessageIds: streamMessageIds,\n preferValuesMessage: shouldPreferValuesMessageForToolCalls,\n });\n valuesMessageIds = reconciliation.valueMessageIds;\n const reconciledMessages = [...reconciliation.messages];\n\n pendingMessages.length = 0;\n for (const message of reconciledMessages) pendingMessages.push(message);\n indexById.clear();\n for (const [id, idx] of buildMessageIndex(pendingMessages)) {\n indexById.set(id, idx);\n }\n scheduleFlush();\n };\n\n const applyEvent = (event: MessagesEvent): void => {\n const data = event.params.data;\n\n if (data.event === \"message-start\") {\n const startData = data as MessageStartData;\n const role = (startData.role ?? \"ai\") as MessageRole;\n // \"tool\" role is a v1 convention not represented in the\n // protocol enum but common in practice — keep it working\n // for graphs that emit it as an extensible field.\n const extendedRole =\n (startData as { role?: ExtendedMessageRole }).role ?? role;\n const maybeToolCallId = (startData as { tool_call_id?: string })\n .tool_call_id;\n if (startData.id != null) {\n roleByKey.set(startData.id, {\n role: extendedRole,\n toolCallId: maybeToolCallId,\n });\n }\n }\n\n const update = assembler.consume(event);\n if (update == null) return;\n const msg = update.message;\n const id = msg.id;\n if (id == null) return;\n const captured = roleByKey.get(id) ?? { role: \"ai\" as const };\n const base = assembledMessageToBaseMessage(msg, captured.role, {\n toolCallId: captured.toolCallId,\n });\n\n streamMessageIds.add(id);\n const existingIdx = indexById.get(id);\n if (existingIdx == null) {\n indexById.set(id, pendingMessages.length);\n pendingMessages.push(base);\n } else {\n pendingMessages[existingIdx] = base;\n }\n scheduleFlush();\n };\n\n const runtime = openProjectionSubscription({\n thread,\n // Subscribe to both `messages` (live token deltas that drive\n // the in-flight assistant bubble) and `values` (periodic full-\n // state snapshots). Consuming values lets late-mounted scoped\n // projections backfill history after the run has finished.\n channels: [\"messages\", \"values\"],\n namespace: ns,\n onEvent(event) {\n if (event.method === \"messages\") {\n applyEvent(event as MessagesEvent);\n } else if (event.method === \"values\") {\n applyValuesEvent(event as ValuesEvent);\n }\n },\n });\n\n return {\n async dispose() {\n disposed = true;\n if (flushChannel != null) {\n flushChannel.port1.onmessage = null;\n flushChannel.port1.close();\n flushChannel.port2.close();\n }\n await runtime.dispose();\n },\n };\n },\n };\n}\n"],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ import { ProjectionSpec } from "../types.cjs";
2
+ import { BaseMessage } from "@langchain/core/messages";
3
+
4
+ //#region src/stream/projections/messages.d.ts
5
+ declare function messagesProjection(namespace: readonly string[]): ProjectionSpec<BaseMessage[]>;
6
+ //#endregion
7
+ export { messagesProjection };
8
+ //# sourceMappingURL=messages.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"messages.d.cts","names":[],"sources":["../../../src/stream/projections/messages.ts"],"mappings":";;;;iBAmCgB,kBAAA,CACd,SAAA,sBACC,cAAA,CAAe,WAAA"}
@@ -0,0 +1,8 @@
1
+ import { ProjectionSpec } from "../types.js";
2
+ import { BaseMessage } from "@langchain/core/messages";
3
+
4
+ //#region src/stream/projections/messages.d.ts
5
+ declare function messagesProjection(namespace: readonly string[]): ProjectionSpec<BaseMessage[]>;
6
+ //#endregion
7
+ export { messagesProjection };
8
+ //# sourceMappingURL=messages.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"messages.d.ts","names":[],"sources":["../../../src/stream/projections/messages.ts"],"mappings":";;;;iBAmCgB,kBAAA,CACd,SAAA,sBACC,cAAA,CAAe,WAAA"}
@@ -0,0 +1,121 @@
1
+ import { ensureMessageInstances } from "../../ui/messages.js";
2
+ import { MessageAssembler } from "../../client/stream/messages.js";
3
+ import { isRootNamespace, namespaceKey } from "../namespace.js";
4
+ import { assembledMessageToBaseMessage } from "../assembled-to-message.js";
5
+ import { buildMessageIndex, reconcileMessagesFromValues, shouldPreferValuesMessageForToolCalls } from "../message-reconciliation.js";
6
+ import { openProjectionSubscription } from "./runtime.js";
7
+ //#region src/stream/projections/messages.ts
8
+ function messagesProjection(namespace) {
9
+ const ns = [...namespace];
10
+ return {
11
+ key: `messages|${namespaceKey(ns)}`,
12
+ namespace: ns,
13
+ initial: [],
14
+ open({ thread, store, rootBus }) {
15
+ const assembler = new MessageAssembler();
16
+ const roleByKey = /* @__PURE__ */ new Map();
17
+ const indexById = /* @__PURE__ */ new Map();
18
+ const streamMessageIds = /* @__PURE__ */ new Set();
19
+ let valuesMessageIds = /* @__PURE__ */ new Set();
20
+ if (isRootNamespace(ns) && rootBus.channels.includes("messages")) {
21
+ const unsubscribe = rootBus.subscribe((event) => {
22
+ if (event.method !== "messages") return;
23
+ if (!isRootNamespace(event.params.namespace)) return;
24
+ applyEvent(event);
25
+ });
26
+ return { dispose() {
27
+ unsubscribe();
28
+ } };
29
+ }
30
+ let disposed = false;
31
+ const pendingMessages = [];
32
+ let dirty = false;
33
+ let flushScheduled = false;
34
+ const flushChannel = typeof MessageChannel !== "undefined" ? new MessageChannel() : null;
35
+ const flush = () => {
36
+ flushScheduled = false;
37
+ if (!dirty || disposed) return;
38
+ dirty = false;
39
+ store.setValue(pendingMessages.slice());
40
+ };
41
+ if (flushChannel != null) flushChannel.port1.onmessage = flush;
42
+ const scheduleFlush = () => {
43
+ dirty = true;
44
+ if (flushScheduled) return;
45
+ flushScheduled = true;
46
+ if (flushChannel != null) flushChannel.port2.postMessage(null);
47
+ else setTimeout(flush, 0);
48
+ };
49
+ const applyValuesEvent = (event) => {
50
+ const data = event.params.data;
51
+ if (data == null || typeof data !== "object" || Array.isArray(data)) return;
52
+ const rawMessages = data.messages;
53
+ if (!Array.isArray(rawMessages) || rawMessages.length === 0) return;
54
+ const reconciliation = reconcileMessagesFromValues({
55
+ valueMessages: ensureMessageInstances(rawMessages),
56
+ currentMessages: pendingMessages,
57
+ currentIndexById: indexById,
58
+ previousValueMessageIds: valuesMessageIds,
59
+ streamedMessageIds: streamMessageIds,
60
+ preferValuesMessage: shouldPreferValuesMessageForToolCalls
61
+ });
62
+ valuesMessageIds = reconciliation.valueMessageIds;
63
+ const reconciledMessages = [...reconciliation.messages];
64
+ pendingMessages.length = 0;
65
+ for (const message of reconciledMessages) pendingMessages.push(message);
66
+ indexById.clear();
67
+ for (const [id, idx] of buildMessageIndex(pendingMessages)) indexById.set(id, idx);
68
+ scheduleFlush();
69
+ };
70
+ const applyEvent = (event) => {
71
+ const data = event.params.data;
72
+ if (data.event === "message-start") {
73
+ const startData = data;
74
+ const role = startData.role ?? "ai";
75
+ const extendedRole = startData.role ?? role;
76
+ const maybeToolCallId = startData.tool_call_id;
77
+ if (startData.id != null) roleByKey.set(startData.id, {
78
+ role: extendedRole,
79
+ toolCallId: maybeToolCallId
80
+ });
81
+ }
82
+ const update = assembler.consume(event);
83
+ if (update == null) return;
84
+ const msg = update.message;
85
+ const id = msg.id;
86
+ if (id == null) return;
87
+ const captured = roleByKey.get(id) ?? { role: "ai" };
88
+ const base = assembledMessageToBaseMessage(msg, captured.role, { toolCallId: captured.toolCallId });
89
+ streamMessageIds.add(id);
90
+ const existingIdx = indexById.get(id);
91
+ if (existingIdx == null) {
92
+ indexById.set(id, pendingMessages.length);
93
+ pendingMessages.push(base);
94
+ } else pendingMessages[existingIdx] = base;
95
+ scheduleFlush();
96
+ };
97
+ const runtime = openProjectionSubscription({
98
+ thread,
99
+ channels: ["messages", "values"],
100
+ namespace: ns,
101
+ onEvent(event) {
102
+ if (event.method === "messages") applyEvent(event);
103
+ else if (event.method === "values") applyValuesEvent(event);
104
+ }
105
+ });
106
+ return { async dispose() {
107
+ disposed = true;
108
+ if (flushChannel != null) {
109
+ flushChannel.port1.onmessage = null;
110
+ flushChannel.port1.close();
111
+ flushChannel.port2.close();
112
+ }
113
+ await runtime.dispose();
114
+ } };
115
+ }
116
+ };
117
+ }
118
+ //#endregion
119
+ export { messagesProjection };
120
+
121
+ //# sourceMappingURL=messages.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"messages.js","names":[],"sources":["../../../src/stream/projections/messages.ts"],"sourcesContent":["/**\n * Namespace-scoped `messages` projection.\n *\n * Opens `thread.subscribe({ channels: [\"messages\"], namespaces: [ns] })`\n * and folds each `messages` event through {@link MessageAssembler}.\n * Every update — start, block delta, block finish, message finish —\n * re-derives a `BaseMessage` class instance for the currently-active\n * message and updates its slot in the store.\n *\n * The projection emits `BaseMessage[]` (class instances from\n * `@langchain/core/messages`), never plain serialized objects.\n */\nimport type {\n MessagesEvent,\n MessageRole,\n MessageStartData,\n ValuesEvent,\n} from \"@langchain/protocol\";\nimport type { BaseMessage } from \"@langchain/core/messages\";\nimport { MessageAssembler } from \"../../client/stream/messages.js\";\nimport {\n assembledMessageToBaseMessage,\n type ExtendedMessageRole,\n} from \"../assembled-to-message.js\";\nimport { ensureMessageInstances } from \"../../ui/messages.js\";\nimport type { Message } from \"../../types.messages.js\";\nimport type { ProjectionSpec, ProjectionRuntime } from \"../types.js\";\nimport { isRootNamespace, namespaceKey } from \"../namespace.js\";\nimport {\n buildMessageIndex,\n reconcileMessagesFromValues,\n shouldPreferValuesMessageForToolCalls,\n} from \"../message-reconciliation.js\";\nimport { openProjectionSubscription } from \"./runtime.js\";\n\nexport function messagesProjection(\n namespace: readonly string[]\n): ProjectionSpec<BaseMessage[]> {\n const ns = [...namespace];\n const key = `messages|${namespaceKey(ns)}`;\n\n return {\n key,\n namespace: ns,\n initial: [],\n open({ thread, store, rootBus }): ProjectionRuntime {\n const assembler = new MessageAssembler();\n // Per-messageId state needed for BaseMessage projection:\n // - `role` is only in the `message-start` event; we cache it\n // so subsequent delta events still produce a typed message.\n // - `toolCallId` is pulled from message-start extras when role\n // is `tool` (a convention we keep compatible with serialized\n // v1 tool messages).\n const roleByKey = new Map<\n string,\n { role: ExtendedMessageRole; toolCallId?: string }\n >();\n const indexById = new Map<string, number>();\n // Ids this projection has observed via the `messages` channel\n // (token-level deltas). Used by `applyValuesEvent` to prefer the\n // stream-assembled version over the values-coerced shape while a\n // turn is streaming, matching the root controller's policy.\n const streamMessageIds = new Set<string>();\n // Ids observed in the most recent `values.messages` snapshot.\n // Messages that were present in a prior snapshot but are absent\n // from this one are treated as explicit removals (server-side\n // `RemoveMessage` reducer deltas). Stream-only messages (seen on\n // the messages channel but never echoed in a values snapshot)\n // are preserved — their enclosing superstep may simply not have\n // committed yet.\n let valuesMessageIds = new Set<string>();\n\n // Root-scoped projections whose channels are already covered by\n // the controller's root pump attach to the shared fan-out\n // instead of opening a second server subscription. The root\n // pump runs at `{namespaces: [[]], depth: 1}`, which is exactly\n // the scope a root-namespace `messagesProjection` wants.\n const rootShortCircuit =\n isRootNamespace(ns) && rootBus.channels.includes(\"messages\");\n\n if (rootShortCircuit) {\n const unsubscribe = rootBus.subscribe((event) => {\n if (event.method !== \"messages\") return;\n if (!isRootNamespace(event.params.namespace)) return;\n applyEvent(event as MessagesEvent);\n });\n return {\n dispose() {\n unsubscribe();\n },\n };\n }\n\n let disposed = false;\n\n // Local mirror of the store contents. Every `applyEvent` /\n // `applyValuesEvent` mutates this synchronously; a coalesced\n // `scheduleFlush` copies it to `store` once per macrotask.\n //\n // Why the indirection? When a namespace-scoped projection\n // (e.g. a subagent modal opened after the run finished) first\n // subscribes, the server replays the entire history from\n // `seq=0`. Dozens of `messages`-channel events can land in a\n // single SSE parse — they drain through the `for await` loop\n // as a long microtask chain. Microtasks run before any\n // macrotask, so React's concurrent scheduler never gets a\n // chance to commit between updates. Calling `store.setValue`\n // per event in that burst overflows React's\n // `nestedUpdateCount` guard and throws \"Maximum update depth\n // exceeded\", permanently killing the projection and\n // leaving the store stuck at its first few messages.\n //\n // Batching via `MessageChannel` (macrotask) coalesces the\n // replay burst into one `setValue` call and lets React\n // commit between flushes for live token streaming too.\n const pendingMessages: BaseMessage[] = [];\n let dirty = false;\n let flushScheduled = false;\n const flushChannel =\n typeof MessageChannel !== \"undefined\" ? new MessageChannel() : null;\n\n const flush = (): void => {\n flushScheduled = false;\n if (!dirty || disposed) return;\n dirty = false;\n // `.slice()` breaks identity so React's `Object.is` bail-out\n // in `StreamStore.setValue` propagates the change.\n store.setValue(pendingMessages.slice());\n };\n if (flushChannel != null) {\n flushChannel.port1.onmessage = flush;\n }\n\n const scheduleFlush = (): void => {\n dirty = true;\n if (flushScheduled) return;\n flushScheduled = true;\n if (flushChannel != null) {\n flushChannel.port2.postMessage(null);\n } else {\n setTimeout(flush, 0);\n }\n };\n\n // Rebuild the store from `values.messages` snapshots.\n //\n // `values` events carry the full, committed state of the\n // thread's `messages` channel at a checkpoint — they fire\n // on node completion, AFTER every `messages`-channel delta\n // for that turn has been emitted. They are the authoritative\n // source of truth for ORDER and for non-streamed messages\n // (human turns, serialised tool results, subagent echoes, …).\n //\n // Why rebuild rather than merge-by-id?\n //\n // In practice the server may emit the same logical message\n // with DIFFERENT ids across successive `values` snapshots at\n // the same namespace — e.g. a subagent first surfaces its\n // seed prompt with a synthetic id like\n // `subagent:<tool_call_id>:human`, then a later superstep\n // echoes the same prompt back with a real UUID (or vice\n // versa). A naive \"match-or-append by id\" strategy treats\n // each fresh id as a new entry and the list grows\n // monotonically, showing the same content twice (or more)\n // in the UI.\n //\n // Policy (mirrors the root controller's `#applyValues`):\n //\n // 1. Walk `values.messages` in order. For each id, prefer\n // the stream-assembled entry if we have one for that id\n // (keeps in-progress token streaming visible); otherwise\n // take the values-coerced instance. This self-heals the\n // two classes of glitch the old merge-by-id handler\n // targeted:\n // - tool messages arriving without `tool_call_id` on\n // the messages channel — the values snapshot always\n // carries it;\n // - AI messages whose finalized `tool_calls` didn't\n // fully land via the messages channel — the values\n // snapshot's AI message has them populated.\n //\n // 2. Append any stream-only ids (seen on the messages\n // channel but never echoed in ANY values snapshot yet)\n // — their enclosing superstep hasn't committed yet, so\n // dropping them would flash the UI.\n //\n // 3. Ids that WERE in a prior values snapshot but are gone\n // from this one are treated as explicit removals\n // (`RemoveMessage` reducer deltas) and dropped.\n //\n // Unkeyed messages (no stable id) are passed through in\n // their values order because we can't dedupe them safely.\n const applyValuesEvent = (event: ValuesEvent): void => {\n const data = event.params.data;\n if (data == null || typeof data !== \"object\" || Array.isArray(data)) {\n return;\n }\n const state = data as Record<string, unknown>;\n const rawMessages = state.messages;\n if (!Array.isArray(rawMessages) || rawMessages.length === 0) return;\n\n const coerced = ensureMessageInstances(\n rawMessages as (Message | BaseMessage)[]\n );\n\n const reconciliation = reconcileMessagesFromValues({\n valueMessages: coerced,\n currentMessages: pendingMessages,\n currentIndexById: indexById,\n previousValueMessageIds: valuesMessageIds,\n streamedMessageIds: streamMessageIds,\n preferValuesMessage: shouldPreferValuesMessageForToolCalls,\n });\n valuesMessageIds = reconciliation.valueMessageIds;\n const reconciledMessages = [...reconciliation.messages];\n\n pendingMessages.length = 0;\n for (const message of reconciledMessages) pendingMessages.push(message);\n indexById.clear();\n for (const [id, idx] of buildMessageIndex(pendingMessages)) {\n indexById.set(id, idx);\n }\n scheduleFlush();\n };\n\n const applyEvent = (event: MessagesEvent): void => {\n const data = event.params.data;\n\n if (data.event === \"message-start\") {\n const startData = data as MessageStartData;\n const role = (startData.role ?? \"ai\") as MessageRole;\n // \"tool\" role is a v1 convention not represented in the\n // protocol enum but common in practice — keep it working\n // for graphs that emit it as an extensible field.\n const extendedRole =\n (startData as { role?: ExtendedMessageRole }).role ?? role;\n const maybeToolCallId = (startData as { tool_call_id?: string })\n .tool_call_id;\n if (startData.id != null) {\n roleByKey.set(startData.id, {\n role: extendedRole,\n toolCallId: maybeToolCallId,\n });\n }\n }\n\n const update = assembler.consume(event);\n if (update == null) return;\n const msg = update.message;\n const id = msg.id;\n if (id == null) return;\n const captured = roleByKey.get(id) ?? { role: \"ai\" as const };\n const base = assembledMessageToBaseMessage(msg, captured.role, {\n toolCallId: captured.toolCallId,\n });\n\n streamMessageIds.add(id);\n const existingIdx = indexById.get(id);\n if (existingIdx == null) {\n indexById.set(id, pendingMessages.length);\n pendingMessages.push(base);\n } else {\n pendingMessages[existingIdx] = base;\n }\n scheduleFlush();\n };\n\n const runtime = openProjectionSubscription({\n thread,\n // Subscribe to both `messages` (live token deltas that drive\n // the in-flight assistant bubble) and `values` (periodic full-\n // state snapshots). Consuming values lets late-mounted scoped\n // projections backfill history after the run has finished.\n channels: [\"messages\", \"values\"],\n namespace: ns,\n onEvent(event) {\n if (event.method === \"messages\") {\n applyEvent(event as MessagesEvent);\n } else if (event.method === \"values\") {\n applyValuesEvent(event as ValuesEvent);\n }\n },\n });\n\n return {\n async dispose() {\n disposed = true;\n if (flushChannel != null) {\n flushChannel.port1.onmessage = null;\n flushChannel.port1.close();\n flushChannel.port2.close();\n }\n await runtime.dispose();\n },\n };\n },\n };\n}\n"],"mappings":"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"}
@@ -0,0 +1,44 @@
1
+ //#region src/stream/projections/runtime.ts
2
+ /**
3
+ * Shared async subscription lifecycle for projection runtimes.
4
+ */
5
+ function openProjectionSubscription({ thread, channels, namespace, depth = 1, resumeOnPause = false, onSubscribe, onEvent, onFinally }) {
6
+ let handle;
7
+ let disposed = false;
8
+ const start = async () => {
9
+ try {
10
+ const subscription = await thread.subscribe({
11
+ channels: [...channels],
12
+ namespaces: namespace.length > 0 ? [[...namespace]] : [[]],
13
+ depth
14
+ });
15
+ handle = subscription;
16
+ if (disposed) {
17
+ await subscription.unsubscribe();
18
+ return;
19
+ }
20
+ onSubscribe?.();
21
+ do {
22
+ for await (const event of subscription) {
23
+ if (disposed) break;
24
+ onEvent(event);
25
+ }
26
+ if (disposed || !resumeOnPause || !subscription.isPaused) break;
27
+ await subscription.waitForResume();
28
+ } while (!disposed);
29
+ } catch {} finally {
30
+ onFinally?.();
31
+ }
32
+ };
33
+ start();
34
+ return { async dispose() {
35
+ disposed = true;
36
+ try {
37
+ await handle?.unsubscribe();
38
+ } catch {}
39
+ } };
40
+ }
41
+ //#endregion
42
+ exports.openProjectionSubscription = openProjectionSubscription;
43
+
44
+ //# sourceMappingURL=runtime.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtime.cjs","names":[],"sources":["../../../src/stream/projections/runtime.ts"],"sourcesContent":["import type { Channel, Event } from \"@langchain/protocol\";\nimport type { SubscriptionHandle } from \"../../client/stream/index.js\";\nimport type { ProjectionRuntime, ThreadStream } from \"../types.js\";\n\ninterface ProjectionSubscriptionOptions {\n thread: ThreadStream;\n channels: readonly Channel[];\n namespace: readonly string[];\n depth?: number;\n /**\n * Some transports pause a subscription between runs. Most projections\n * intentionally preserve their historical one-pass behavior; opt in when\n * the projection already handled resume loops.\n */\n resumeOnPause?: boolean;\n onSubscribe?: () => void;\n onEvent(event: Event): void;\n onFinally?: () => void;\n}\n\n/**\n * Shared async subscription lifecycle for projection runtimes.\n */\nexport function openProjectionSubscription({\n thread,\n channels,\n namespace,\n depth = 1,\n resumeOnPause = false,\n onSubscribe,\n onEvent,\n onFinally,\n}: ProjectionSubscriptionOptions): ProjectionRuntime {\n let handle: SubscriptionHandle<Event> | undefined;\n let disposed = false;\n\n const start = async () => {\n try {\n const subscription = await thread.subscribe({\n channels: [...channels],\n namespaces: namespace.length > 0 ? [[...namespace]] : [[]],\n depth,\n });\n handle = subscription;\n if (disposed) {\n await subscription.unsubscribe();\n return;\n }\n onSubscribe?.();\n\n do {\n for await (const event of subscription) {\n if (disposed) break;\n onEvent(event);\n }\n if (disposed || !resumeOnPause || !subscription.isPaused) break;\n await subscription.waitForResume();\n } while (!disposed);\n } catch {\n // Thread closed / errored; projections expose their last good snapshot.\n } finally {\n onFinally?.();\n }\n };\n\n void start();\n\n return {\n async dispose() {\n disposed = true;\n try {\n await handle?.unsubscribe();\n } catch {\n // already closed\n }\n },\n };\n}\n"],"mappings":";;;;AAuBA,SAAgB,2BAA2B,EACzC,QACA,UACA,WACA,QAAQ,GACR,gBAAgB,OAChB,aACA,SACA,aACmD;CACnD,IAAI;CACJ,IAAI,WAAW;CAEf,MAAM,QAAQ,YAAY;AACxB,MAAI;GACF,MAAM,eAAe,MAAM,OAAO,UAAU;IAC1C,UAAU,CAAC,GAAG,SAAS;IACvB,YAAY,UAAU,SAAS,IAAI,CAAC,CAAC,GAAG,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;IAC1D;IACD,CAAC;AACF,YAAS;AACT,OAAI,UAAU;AACZ,UAAM,aAAa,aAAa;AAChC;;AAEF,kBAAe;AAEf,MAAG;AACD,eAAW,MAAM,SAAS,cAAc;AACtC,SAAI,SAAU;AACd,aAAQ,MAAM;;AAEhB,QAAI,YAAY,CAAC,iBAAiB,CAAC,aAAa,SAAU;AAC1D,UAAM,aAAa,eAAe;YAC3B,CAAC;UACJ,WAEE;AACR,gBAAa;;;AAIZ,QAAO;AAEZ,QAAO,EACL,MAAM,UAAU;AACd,aAAW;AACX,MAAI;AACF,SAAM,QAAQ,aAAa;UACrB;IAIX"}
@@ -0,0 +1,44 @@
1
+ //#region src/stream/projections/runtime.ts
2
+ /**
3
+ * Shared async subscription lifecycle for projection runtimes.
4
+ */
5
+ function openProjectionSubscription({ thread, channels, namespace, depth = 1, resumeOnPause = false, onSubscribe, onEvent, onFinally }) {
6
+ let handle;
7
+ let disposed = false;
8
+ const start = async () => {
9
+ try {
10
+ const subscription = await thread.subscribe({
11
+ channels: [...channels],
12
+ namespaces: namespace.length > 0 ? [[...namespace]] : [[]],
13
+ depth
14
+ });
15
+ handle = subscription;
16
+ if (disposed) {
17
+ await subscription.unsubscribe();
18
+ return;
19
+ }
20
+ onSubscribe?.();
21
+ do {
22
+ for await (const event of subscription) {
23
+ if (disposed) break;
24
+ onEvent(event);
25
+ }
26
+ if (disposed || !resumeOnPause || !subscription.isPaused) break;
27
+ await subscription.waitForResume();
28
+ } while (!disposed);
29
+ } catch {} finally {
30
+ onFinally?.();
31
+ }
32
+ };
33
+ start();
34
+ return { async dispose() {
35
+ disposed = true;
36
+ try {
37
+ await handle?.unsubscribe();
38
+ } catch {}
39
+ } };
40
+ }
41
+ //#endregion
42
+ export { openProjectionSubscription };
43
+
44
+ //# sourceMappingURL=runtime.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtime.js","names":[],"sources":["../../../src/stream/projections/runtime.ts"],"sourcesContent":["import type { Channel, Event } from \"@langchain/protocol\";\nimport type { SubscriptionHandle } from \"../../client/stream/index.js\";\nimport type { ProjectionRuntime, ThreadStream } from \"../types.js\";\n\ninterface ProjectionSubscriptionOptions {\n thread: ThreadStream;\n channels: readonly Channel[];\n namespace: readonly string[];\n depth?: number;\n /**\n * Some transports pause a subscription between runs. Most projections\n * intentionally preserve their historical one-pass behavior; opt in when\n * the projection already handled resume loops.\n */\n resumeOnPause?: boolean;\n onSubscribe?: () => void;\n onEvent(event: Event): void;\n onFinally?: () => void;\n}\n\n/**\n * Shared async subscription lifecycle for projection runtimes.\n */\nexport function openProjectionSubscription({\n thread,\n channels,\n namespace,\n depth = 1,\n resumeOnPause = false,\n onSubscribe,\n onEvent,\n onFinally,\n}: ProjectionSubscriptionOptions): ProjectionRuntime {\n let handle: SubscriptionHandle<Event> | undefined;\n let disposed = false;\n\n const start = async () => {\n try {\n const subscription = await thread.subscribe({\n channels: [...channels],\n namespaces: namespace.length > 0 ? [[...namespace]] : [[]],\n depth,\n });\n handle = subscription;\n if (disposed) {\n await subscription.unsubscribe();\n return;\n }\n onSubscribe?.();\n\n do {\n for await (const event of subscription) {\n if (disposed) break;\n onEvent(event);\n }\n if (disposed || !resumeOnPause || !subscription.isPaused) break;\n await subscription.waitForResume();\n } while (!disposed);\n } catch {\n // Thread closed / errored; projections expose their last good snapshot.\n } finally {\n onFinally?.();\n }\n };\n\n void start();\n\n return {\n async dispose() {\n disposed = true;\n try {\n await handle?.unsubscribe();\n } catch {\n // already closed\n }\n },\n };\n}\n"],"mappings":";;;;AAuBA,SAAgB,2BAA2B,EACzC,QACA,UACA,WACA,QAAQ,GACR,gBAAgB,OAChB,aACA,SACA,aACmD;CACnD,IAAI;CACJ,IAAI,WAAW;CAEf,MAAM,QAAQ,YAAY;AACxB,MAAI;GACF,MAAM,eAAe,MAAM,OAAO,UAAU;IAC1C,UAAU,CAAC,GAAG,SAAS;IACvB,YAAY,UAAU,SAAS,IAAI,CAAC,CAAC,GAAG,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;IAC1D;IACD,CAAC;AACF,YAAS;AACT,OAAI,UAAU;AACZ,UAAM,aAAa,aAAa;AAChC;;AAEF,kBAAe;AAEf,MAAG;AACD,eAAW,MAAM,SAAS,cAAc;AACtC,SAAI,SAAU;AACd,aAAQ,MAAM;;AAEhB,QAAI,YAAY,CAAC,iBAAiB,CAAC,aAAa,SAAU;AAC1D,UAAM,aAAa,eAAe;YAC3B,CAAC;UACJ,WAEE;AACR,gBAAa;;;AAIZ,QAAO;AAEZ,QAAO,EACL,MAAM,UAAU;AACd,aAAW;AACX,MAAI;AACF,SAAM,QAAQ,aAAa;UACrB;IAIX"}
@@ -0,0 +1,50 @@
1
+ const require_tools = require("../../client/stream/handles/tools.cjs");
2
+ const require_namespace = require("../namespace.cjs");
3
+ const require_tool_calls = require("../tool-calls.cjs");
4
+ const require_runtime = require("./runtime.cjs");
5
+ //#region src/stream/projections/tool-calls.ts
6
+ function toolCallsProjection(namespace) {
7
+ const ns = [...namespace];
8
+ return {
9
+ key: `toolCalls|${require_namespace.namespaceKey(ns)}`,
10
+ namespace: ns,
11
+ initial: [],
12
+ open({ thread, store, rootBus }) {
13
+ const assembler = new require_tools.ToolCallAssembler();
14
+ const applyToolsEvent = (event) => {
15
+ const data = event.params.data;
16
+ if (ns.length > 0 && event.params.namespace.length === ns.length && data.tool_name === "task") return;
17
+ const tc = assembler.consume(event);
18
+ if (tc == null) return;
19
+ const next = require_tool_calls.upsertToolCall(store.getSnapshot(), tc);
20
+ store.setValue(next);
21
+ };
22
+ if (require_namespace.isRootNamespace(ns) && rootBus.channels.includes("tools")) {
23
+ const unsubscribe = rootBus.subscribe((event) => {
24
+ if (event.method !== "tools") return;
25
+ if (!require_namespace.isRootNamespace(event.params.namespace)) return;
26
+ applyToolsEvent(event);
27
+ });
28
+ return { dispose() {
29
+ unsubscribe();
30
+ } };
31
+ }
32
+ const runtime = require_runtime.openProjectionSubscription({
33
+ thread,
34
+ channels: ["tools"],
35
+ namespace: ns,
36
+ onEvent(event) {
37
+ if (event.method !== "tools") return;
38
+ applyToolsEvent(event);
39
+ }
40
+ });
41
+ return { async dispose() {
42
+ await runtime.dispose();
43
+ } };
44
+ }
45
+ };
46
+ }
47
+ //#endregion
48
+ exports.toolCallsProjection = toolCallsProjection;
49
+
50
+ //# sourceMappingURL=tool-calls.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tool-calls.cjs","names":["namespaceKey","ToolCallAssembler","upsertToolCall","isRootNamespace","openProjectionSubscription"],"sources":["../../../src/stream/projections/tool-calls.ts"],"sourcesContent":["/**\n * Namespace-scoped `tools` projection.\n *\n * Opens `thread.subscribe({ channels: [\"tools\"], namespaces: [ns] })`,\n * feeds events through {@link ToolCallAssembler}, and surfaces an\n * array of {@link AssembledToolCall}s that grows as calls are\n * discovered. Each assembled call carries `output`/`status`/`error`\n * promises for consumers that want to await completion without\n * re-subscribing.\n */\nimport type { ToolsEvent } from \"@langchain/protocol\";\nimport { ToolCallAssembler } from \"../../client/stream/handles/tools.js\";\nimport type { AssembledToolCall } from \"../../client/stream/handles/tools.js\";\nimport type { ProjectionSpec, ProjectionRuntime } from \"../types.js\";\nimport { isRootNamespace, namespaceKey } from \"../namespace.js\";\nimport { upsertToolCall } from \"../tool-calls.js\";\nimport { openProjectionSubscription } from \"./runtime.js\";\n\nexport function toolCallsProjection(\n namespace: readonly string[]\n): ProjectionSpec<AssembledToolCall[]> {\n const ns = [...namespace];\n const key = `toolCalls|${namespaceKey(ns)}`;\n\n return {\n key,\n namespace: ns,\n initial: [],\n open({ thread, store, rootBus }): ProjectionRuntime {\n const assembler = new ToolCallAssembler();\n\n const applyToolsEvent = (event: ToolsEvent): void => {\n const data = event.params.data;\n if (\n ns.length > 0 &&\n event.params.namespace.length === ns.length &&\n data.tool_name === \"task\"\n ) {\n return;\n }\n const tc = assembler.consume(event);\n if (tc == null) return;\n const next = upsertToolCall(store.getSnapshot(), tc);\n store.setValue(next);\n };\n\n // See `messagesProjection` — root-scoped projections short-\n // circuit onto the root bus when the requested channels are\n // covered by the controller's root pump.\n const rootShortCircuit =\n isRootNamespace(ns) && rootBus.channels.includes(\"tools\");\n\n if (rootShortCircuit) {\n const unsubscribe = rootBus.subscribe((event) => {\n if (event.method !== \"tools\") return;\n if (!isRootNamespace(event.params.namespace)) return;\n applyToolsEvent(event as ToolsEvent);\n });\n return {\n dispose() {\n unsubscribe();\n },\n };\n }\n\n const runtime = openProjectionSubscription({\n thread,\n channels: [\"tools\"],\n namespace: ns,\n onEvent(event) {\n if (event.method !== \"tools\") return;\n applyToolsEvent(event as ToolsEvent);\n },\n });\n\n return {\n async dispose() {\n await runtime.dispose();\n },\n };\n },\n };\n}\n"],"mappings":";;;;;AAkBA,SAAgB,oBACd,WACqC;CACrC,MAAM,KAAK,CAAC,GAAG,UAAU;AAGzB,QAAO;EACL,KAHU,aAAaA,kBAAAA,aAAa,GAAG;EAIvC,WAAW;EACX,SAAS,EAAE;EACX,KAAK,EAAE,QAAQ,OAAO,WAA8B;GAClD,MAAM,YAAY,IAAIC,cAAAA,mBAAmB;GAEzC,MAAM,mBAAmB,UAA4B;IACnD,MAAM,OAAO,MAAM,OAAO;AAC1B,QACE,GAAG,SAAS,KACZ,MAAM,OAAO,UAAU,WAAW,GAAG,UACrC,KAAK,cAAc,OAEnB;IAEF,MAAM,KAAK,UAAU,QAAQ,MAAM;AACnC,QAAI,MAAM,KAAM;IAChB,MAAM,OAAOC,mBAAAA,eAAe,MAAM,aAAa,EAAE,GAAG;AACpD,UAAM,SAAS,KAAK;;AAStB,OAFEC,kBAAAA,gBAAgB,GAAG,IAAI,QAAQ,SAAS,SAAS,QAAQ,EAErC;IACpB,MAAM,cAAc,QAAQ,WAAW,UAAU;AAC/C,SAAI,MAAM,WAAW,QAAS;AAC9B,SAAI,CAACA,kBAAAA,gBAAgB,MAAM,OAAO,UAAU,CAAE;AAC9C,qBAAgB,MAAoB;MACpC;AACF,WAAO,EACL,UAAU;AACR,kBAAa;OAEhB;;GAGH,MAAM,UAAUC,gBAAAA,2BAA2B;IACzC;IACA,UAAU,CAAC,QAAQ;IACnB,WAAW;IACX,QAAQ,OAAO;AACb,SAAI,MAAM,WAAW,QAAS;AAC9B,qBAAgB,MAAoB;;IAEvC,CAAC;AAEF,UAAO,EACL,MAAM,UAAU;AACd,UAAM,QAAQ,SAAS;MAE1B;;EAEJ"}
@@ -0,0 +1,8 @@
1
+ import { AssembledToolCall } from "../../client/stream/handles/tools.cjs";
2
+ import { ProjectionSpec } from "../types.cjs";
3
+
4
+ //#region src/stream/projections/tool-calls.d.ts
5
+ declare function toolCallsProjection(namespace: readonly string[]): ProjectionSpec<AssembledToolCall[]>;
6
+ //#endregion
7
+ export { toolCallsProjection };
8
+ //# sourceMappingURL=tool-calls.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tool-calls.d.cts","names":[],"sources":["../../../src/stream/projections/tool-calls.ts"],"mappings":";;;;iBAkBgB,mBAAA,CACd,SAAA,sBACC,cAAA,CAAe,iBAAA"}
@@ -0,0 +1,8 @@
1
+ import { AssembledToolCall } from "../../client/stream/handles/tools.js";
2
+ import { ProjectionSpec } from "../types.js";
3
+
4
+ //#region src/stream/projections/tool-calls.d.ts
5
+ declare function toolCallsProjection(namespace: readonly string[]): ProjectionSpec<AssembledToolCall[]>;
6
+ //#endregion
7
+ export { toolCallsProjection };
8
+ //# sourceMappingURL=tool-calls.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tool-calls.d.ts","names":[],"sources":["../../../src/stream/projections/tool-calls.ts"],"mappings":";;;;iBAkBgB,mBAAA,CACd,SAAA,sBACC,cAAA,CAAe,iBAAA"}
@@ -0,0 +1,50 @@
1
+ import { ToolCallAssembler } from "../../client/stream/handles/tools.js";
2
+ import { isRootNamespace, namespaceKey } from "../namespace.js";
3
+ import { upsertToolCall } from "../tool-calls.js";
4
+ import { openProjectionSubscription } from "./runtime.js";
5
+ //#region src/stream/projections/tool-calls.ts
6
+ function toolCallsProjection(namespace) {
7
+ const ns = [...namespace];
8
+ return {
9
+ key: `toolCalls|${namespaceKey(ns)}`,
10
+ namespace: ns,
11
+ initial: [],
12
+ open({ thread, store, rootBus }) {
13
+ const assembler = new ToolCallAssembler();
14
+ const applyToolsEvent = (event) => {
15
+ const data = event.params.data;
16
+ if (ns.length > 0 && event.params.namespace.length === ns.length && data.tool_name === "task") return;
17
+ const tc = assembler.consume(event);
18
+ if (tc == null) return;
19
+ const next = upsertToolCall(store.getSnapshot(), tc);
20
+ store.setValue(next);
21
+ };
22
+ if (isRootNamespace(ns) && rootBus.channels.includes("tools")) {
23
+ const unsubscribe = rootBus.subscribe((event) => {
24
+ if (event.method !== "tools") return;
25
+ if (!isRootNamespace(event.params.namespace)) return;
26
+ applyToolsEvent(event);
27
+ });
28
+ return { dispose() {
29
+ unsubscribe();
30
+ } };
31
+ }
32
+ const runtime = openProjectionSubscription({
33
+ thread,
34
+ channels: ["tools"],
35
+ namespace: ns,
36
+ onEvent(event) {
37
+ if (event.method !== "tools") return;
38
+ applyToolsEvent(event);
39
+ }
40
+ });
41
+ return { async dispose() {
42
+ await runtime.dispose();
43
+ } };
44
+ }
45
+ };
46
+ }
47
+ //#endregion
48
+ export { toolCallsProjection };
49
+
50
+ //# sourceMappingURL=tool-calls.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tool-calls.js","names":[],"sources":["../../../src/stream/projections/tool-calls.ts"],"sourcesContent":["/**\n * Namespace-scoped `tools` projection.\n *\n * Opens `thread.subscribe({ channels: [\"tools\"], namespaces: [ns] })`,\n * feeds events through {@link ToolCallAssembler}, and surfaces an\n * array of {@link AssembledToolCall}s that grows as calls are\n * discovered. Each assembled call carries `output`/`status`/`error`\n * promises for consumers that want to await completion without\n * re-subscribing.\n */\nimport type { ToolsEvent } from \"@langchain/protocol\";\nimport { ToolCallAssembler } from \"../../client/stream/handles/tools.js\";\nimport type { AssembledToolCall } from \"../../client/stream/handles/tools.js\";\nimport type { ProjectionSpec, ProjectionRuntime } from \"../types.js\";\nimport { isRootNamespace, namespaceKey } from \"../namespace.js\";\nimport { upsertToolCall } from \"../tool-calls.js\";\nimport { openProjectionSubscription } from \"./runtime.js\";\n\nexport function toolCallsProjection(\n namespace: readonly string[]\n): ProjectionSpec<AssembledToolCall[]> {\n const ns = [...namespace];\n const key = `toolCalls|${namespaceKey(ns)}`;\n\n return {\n key,\n namespace: ns,\n initial: [],\n open({ thread, store, rootBus }): ProjectionRuntime {\n const assembler = new ToolCallAssembler();\n\n const applyToolsEvent = (event: ToolsEvent): void => {\n const data = event.params.data;\n if (\n ns.length > 0 &&\n event.params.namespace.length === ns.length &&\n data.tool_name === \"task\"\n ) {\n return;\n }\n const tc = assembler.consume(event);\n if (tc == null) return;\n const next = upsertToolCall(store.getSnapshot(), tc);\n store.setValue(next);\n };\n\n // See `messagesProjection` — root-scoped projections short-\n // circuit onto the root bus when the requested channels are\n // covered by the controller's root pump.\n const rootShortCircuit =\n isRootNamespace(ns) && rootBus.channels.includes(\"tools\");\n\n if (rootShortCircuit) {\n const unsubscribe = rootBus.subscribe((event) => {\n if (event.method !== \"tools\") return;\n if (!isRootNamespace(event.params.namespace)) return;\n applyToolsEvent(event as ToolsEvent);\n });\n return {\n dispose() {\n unsubscribe();\n },\n };\n }\n\n const runtime = openProjectionSubscription({\n thread,\n channels: [\"tools\"],\n namespace: ns,\n onEvent(event) {\n if (event.method !== \"tools\") return;\n applyToolsEvent(event as ToolsEvent);\n },\n });\n\n return {\n async dispose() {\n await runtime.dispose();\n },\n };\n },\n };\n}\n"],"mappings":";;;;;AAkBA,SAAgB,oBACd,WACqC;CACrC,MAAM,KAAK,CAAC,GAAG,UAAU;AAGzB,QAAO;EACL,KAHU,aAAa,aAAa,GAAG;EAIvC,WAAW;EACX,SAAS,EAAE;EACX,KAAK,EAAE,QAAQ,OAAO,WAA8B;GAClD,MAAM,YAAY,IAAI,mBAAmB;GAEzC,MAAM,mBAAmB,UAA4B;IACnD,MAAM,OAAO,MAAM,OAAO;AAC1B,QACE,GAAG,SAAS,KACZ,MAAM,OAAO,UAAU,WAAW,GAAG,UACrC,KAAK,cAAc,OAEnB;IAEF,MAAM,KAAK,UAAU,QAAQ,MAAM;AACnC,QAAI,MAAM,KAAM;IAChB,MAAM,OAAO,eAAe,MAAM,aAAa,EAAE,GAAG;AACpD,UAAM,SAAS,KAAK;;AAStB,OAFE,gBAAgB,GAAG,IAAI,QAAQ,SAAS,SAAS,QAAQ,EAErC;IACpB,MAAM,cAAc,QAAQ,WAAW,UAAU;AAC/C,SAAI,MAAM,WAAW,QAAS;AAC9B,SAAI,CAAC,gBAAgB,MAAM,OAAO,UAAU,CAAE;AAC9C,qBAAgB,MAAoB;MACpC;AACF,WAAO,EACL,UAAU;AACR,kBAAa;OAEhB;;GAGH,MAAM,UAAU,2BAA2B;IACzC;IACA,UAAU,CAAC,QAAQ;IACnB,WAAW;IACX,QAAQ,OAAO;AACb,SAAI,MAAM,WAAW,QAAS;AAC9B,qBAAgB,MAAoB;;IAEvC,CAAC;AAEF,UAAO,EACL,MAAM,UAAU;AACd,UAAM,QAAQ,SAAS;MAE1B;;EAEJ"}
@@ -0,0 +1,52 @@
1
+ const require_messages = require("../../ui/messages.cjs");
2
+ const require_namespace = require("../namespace.cjs");
3
+ const require_runtime = require("./runtime.cjs");
4
+ //#region src/stream/projections/values.ts
5
+ function valuesProjection(namespace, messagesKey = "messages") {
6
+ const ns = [...namespace];
7
+ return {
8
+ key: `values|${messagesKey}|${require_namespace.namespaceKey(ns)}`,
9
+ namespace: ns,
10
+ initial: void 0,
11
+ open({ thread, store, rootBus }) {
12
+ const applyValuesEvent = (event) => {
13
+ const coerced = coerceMessagesInState(event.params.data, messagesKey);
14
+ store.setValue(coerced);
15
+ };
16
+ if (require_namespace.isRootNamespace(ns) && rootBus.channels.includes("values")) {
17
+ const unsubscribe = rootBus.subscribe((event) => {
18
+ if (event.method !== "values") return;
19
+ if (!require_namespace.isRootNamespace(event.params.namespace)) return;
20
+ applyValuesEvent(event);
21
+ });
22
+ return { dispose() {
23
+ unsubscribe();
24
+ } };
25
+ }
26
+ return require_runtime.openProjectionSubscription({
27
+ thread,
28
+ channels: ["values"],
29
+ namespace: ns,
30
+ onEvent(event) {
31
+ if (event.method !== "values") return;
32
+ applyValuesEvent(event);
33
+ }
34
+ });
35
+ }
36
+ };
37
+ }
38
+ function coerceMessagesInState(value, messagesKey) {
39
+ if (value == null || typeof value !== "object" || Array.isArray(value)) return value;
40
+ const state = value;
41
+ const maybeMessages = state[messagesKey];
42
+ if (!Array.isArray(maybeMessages) || maybeMessages.length === 0) return value;
43
+ if (!maybeMessages.some((m) => m != null && typeof m.getType !== "function")) return value;
44
+ return {
45
+ ...state,
46
+ [messagesKey]: require_messages.ensureMessageInstances(maybeMessages)
47
+ };
48
+ }
49
+ //#endregion
50
+ exports.valuesProjection = valuesProjection;
51
+
52
+ //# sourceMappingURL=values.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"values.cjs","names":["namespaceKey","isRootNamespace","openProjectionSubscription","ensureMessageInstances"],"sources":["../../../src/stream/projections/values.ts"],"sourcesContent":["/**\n * Namespace-scoped `values` projection.\n *\n * Opens `thread.subscribe({ channels: [\"values\"], namespaces: [ns] })`\n * and stores the most-recent `values.data` payload. Mirrors\n * {@link ThreadStream.values} but scoped to an arbitrary namespace so\n * subgraphs and subagents can expose their own state.\n *\n * When the state payload carries a `messages` array of serialized\n * messages, those are coerced to `BaseMessage` class instances so the\n * surface shape matches the root snapshot.\n */\nimport type { ValuesEvent } from \"@langchain/protocol\";\nimport type { BaseMessage } from \"@langchain/core/messages\";\nimport {\n ensureMessageInstances,\n tryCoerceMessageLikeToMessage,\n} from \"../../ui/messages.js\";\nimport type { Message } from \"../../types.messages.js\";\nimport type { ProjectionSpec, ProjectionRuntime } from \"../types.js\";\nimport { isRootNamespace, namespaceKey } from \"../namespace.js\";\nimport { openProjectionSubscription } from \"./runtime.js\";\n\nexport function valuesProjection<T = unknown>(\n namespace: readonly string[],\n messagesKey: string = \"messages\"\n): ProjectionSpec<T | undefined> {\n const ns = [...namespace];\n const key = `values|${messagesKey}|${namespaceKey(ns)}`;\n\n return {\n key,\n namespace: ns,\n initial: undefined,\n open({ thread, store, rootBus }): ProjectionRuntime {\n const applyValuesEvent = (event: ValuesEvent): void => {\n const coerced = coerceMessagesInState(event.params.data, messagesKey);\n store.setValue(coerced as T);\n };\n\n // See `messagesProjection` — root-scoped projections attach to\n // the controller's root bus instead of opening a duplicate\n // server subscription.\n const rootShortCircuit =\n isRootNamespace(ns) && rootBus.channels.includes(\"values\");\n\n if (rootShortCircuit) {\n const unsubscribe = rootBus.subscribe((event) => {\n if (event.method !== \"values\") return;\n if (!isRootNamespace(event.params.namespace)) return;\n applyValuesEvent(event as ValuesEvent);\n });\n return {\n dispose() {\n unsubscribe();\n },\n };\n }\n\n return openProjectionSubscription({\n thread,\n channels: [\"values\"],\n namespace: ns,\n onEvent(event) {\n if (event.method !== \"values\") return;\n applyValuesEvent(event as ValuesEvent);\n },\n });\n },\n };\n}\n\nfunction coerceMessagesInState(value: unknown, messagesKey: string): unknown {\n if (value == null || typeof value !== \"object\" || Array.isArray(value)) {\n return value;\n }\n const state = value as Record<string, unknown>;\n const maybeMessages = state[messagesKey];\n if (!Array.isArray(maybeMessages) || maybeMessages.length === 0) {\n return value;\n }\n // Fast path: array already contains class instances.\n const hasPlain = maybeMessages.some(\n (m) => m != null && typeof (m as BaseMessage).getType !== \"function\"\n );\n if (!hasPlain) return value;\n return {\n ...state,\n [messagesKey]: ensureMessageInstances(\n maybeMessages as (Message | BaseMessage)[]\n ),\n };\n}\n\nexport { tryCoerceMessageLikeToMessage };\n"],"mappings":";;;;AAuBA,SAAgB,iBACd,WACA,cAAsB,YACS;CAC/B,MAAM,KAAK,CAAC,GAAG,UAAU;AAGzB,QAAO;EACL,KAHU,UAAU,YAAY,GAAGA,kBAAAA,aAAa,GAAG;EAInD,WAAW;EACX,SAAS,KAAA;EACT,KAAK,EAAE,QAAQ,OAAO,WAA8B;GAClD,MAAM,oBAAoB,UAA6B;IACrD,MAAM,UAAU,sBAAsB,MAAM,OAAO,MAAM,YAAY;AACrE,UAAM,SAAS,QAAa;;AAS9B,OAFEC,kBAAAA,gBAAgB,GAAG,IAAI,QAAQ,SAAS,SAAS,SAAS,EAEtC;IACpB,MAAM,cAAc,QAAQ,WAAW,UAAU;AAC/C,SAAI,MAAM,WAAW,SAAU;AAC/B,SAAI,CAACA,kBAAAA,gBAAgB,MAAM,OAAO,UAAU,CAAE;AAC9C,sBAAiB,MAAqB;MACtC;AACF,WAAO,EACL,UAAU;AACR,kBAAa;OAEhB;;AAGH,UAAOC,gBAAAA,2BAA2B;IAChC;IACA,UAAU,CAAC,SAAS;IACpB,WAAW;IACX,QAAQ,OAAO;AACb,SAAI,MAAM,WAAW,SAAU;AAC/B,sBAAiB,MAAqB;;IAEzC,CAAC;;EAEL;;AAGH,SAAS,sBAAsB,OAAgB,aAA8B;AAC3E,KAAI,SAAS,QAAQ,OAAO,UAAU,YAAY,MAAM,QAAQ,MAAM,CACpE,QAAO;CAET,MAAM,QAAQ;CACd,MAAM,gBAAgB,MAAM;AAC5B,KAAI,CAAC,MAAM,QAAQ,cAAc,IAAI,cAAc,WAAW,EAC5D,QAAO;AAMT,KAAI,CAHa,cAAc,MAC5B,MAAM,KAAK,QAAQ,OAAQ,EAAkB,YAAY,WAC3D,CACc,QAAO;AACtB,QAAO;EACL,GAAG;GACF,cAAcC,iBAAAA,uBACb,cACD;EACF"}
@@ -0,0 +1,7 @@
1
+ import { ProjectionSpec } from "../types.cjs";
2
+
3
+ //#region src/stream/projections/values.d.ts
4
+ declare function valuesProjection<T = unknown>(namespace: readonly string[], messagesKey?: string): ProjectionSpec<T | undefined>;
5
+ //#endregion
6
+ export { valuesProjection };
7
+ //# sourceMappingURL=values.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"values.d.cts","names":[],"sources":["../../../src/stream/projections/values.ts"],"mappings":";;;iBAuBgB,gBAAA,aAAA,CACd,SAAA,qBACA,WAAA,YACC,cAAA,CAAe,CAAA"}
@@ -0,0 +1,6 @@
1
+ import { ProjectionSpec } from "../types.js";
2
+ //#region src/stream/projections/values.d.ts
3
+ declare function valuesProjection<T = unknown>(namespace: readonly string[], messagesKey?: string): ProjectionSpec<T | undefined>;
4
+ //#endregion
5
+ export { valuesProjection };
6
+ //# sourceMappingURL=values.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"values.d.ts","names":[],"sources":["../../../src/stream/projections/values.ts"],"mappings":";;iBAuBgB,gBAAA,aAAA,CACd,SAAA,qBACA,WAAA,YACC,cAAA,CAAe,CAAA"}
@@ -0,0 +1,52 @@
1
+ import { ensureMessageInstances } from "../../ui/messages.js";
2
+ import { isRootNamespace, namespaceKey } from "../namespace.js";
3
+ import { openProjectionSubscription } from "./runtime.js";
4
+ //#region src/stream/projections/values.ts
5
+ function valuesProjection(namespace, messagesKey = "messages") {
6
+ const ns = [...namespace];
7
+ return {
8
+ key: `values|${messagesKey}|${namespaceKey(ns)}`,
9
+ namespace: ns,
10
+ initial: void 0,
11
+ open({ thread, store, rootBus }) {
12
+ const applyValuesEvent = (event) => {
13
+ const coerced = coerceMessagesInState(event.params.data, messagesKey);
14
+ store.setValue(coerced);
15
+ };
16
+ if (isRootNamespace(ns) && rootBus.channels.includes("values")) {
17
+ const unsubscribe = rootBus.subscribe((event) => {
18
+ if (event.method !== "values") return;
19
+ if (!isRootNamespace(event.params.namespace)) return;
20
+ applyValuesEvent(event);
21
+ });
22
+ return { dispose() {
23
+ unsubscribe();
24
+ } };
25
+ }
26
+ return openProjectionSubscription({
27
+ thread,
28
+ channels: ["values"],
29
+ namespace: ns,
30
+ onEvent(event) {
31
+ if (event.method !== "values") return;
32
+ applyValuesEvent(event);
33
+ }
34
+ });
35
+ }
36
+ };
37
+ }
38
+ function coerceMessagesInState(value, messagesKey) {
39
+ if (value == null || typeof value !== "object" || Array.isArray(value)) return value;
40
+ const state = value;
41
+ const maybeMessages = state[messagesKey];
42
+ if (!Array.isArray(maybeMessages) || maybeMessages.length === 0) return value;
43
+ if (!maybeMessages.some((m) => m != null && typeof m.getType !== "function")) return value;
44
+ return {
45
+ ...state,
46
+ [messagesKey]: ensureMessageInstances(maybeMessages)
47
+ };
48
+ }
49
+ //#endregion
50
+ export { valuesProjection };
51
+
52
+ //# sourceMappingURL=values.js.map