@langchain/langgraph-sdk 1.8.10 → 1.9.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (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,1368 @@
1
+ const require_subscription = require("./subscription.cjs");
2
+ const require_multi_cursor_buffer = require("./multi-cursor-buffer.cjs");
3
+ const require_messages = require("../../ui/messages.cjs");
4
+ const require_tools = require("./handles/tools.cjs");
5
+ const require_messages$1 = require("./messages.cjs");
6
+ const require_media = require("./media.cjs");
7
+ const require_subgraphs = require("./handles/subgraphs.cjs");
8
+ const require_subagents = require("./handles/subagents.cjs");
9
+ require("./handles/index.cjs");
10
+ const require_error = require("./error.cjs");
11
+ require("../../stream/constants.cjs");
12
+ const require_headless_tools = require("../../headless-tools.cjs");
13
+ //#region src/client/stream/index.ts
14
+ const MESSAGE_LIKE_TYPES = new Set([
15
+ "human",
16
+ "user",
17
+ "ai",
18
+ "assistant",
19
+ "tool",
20
+ "system",
21
+ "function",
22
+ "remove"
23
+ ]);
24
+ /**
25
+ * When the state payload has a `messages` array containing plain
26
+ * serialized messages (objects with a recognized `type` field), coerce
27
+ * them into `@langchain/core/messages` class instances so remote runs
28
+ * expose the same shape as in-process runs.
29
+ *
30
+ * Returns the input unchanged when the payload is not an object, does
31
+ * not include a `messages` key, or contains entries that are already
32
+ * class instances / not message-like.
33
+ */
34
+ function coerceStateMessages(value) {
35
+ if (value == null || typeof value !== "object" || Array.isArray(value)) return value;
36
+ const state = value;
37
+ const messages = state.messages;
38
+ if (!Array.isArray(messages) || messages.length === 0) return value;
39
+ if (!messages.some((msg) => {
40
+ if (msg == null || typeof msg !== "object") return false;
41
+ if (typeof msg.getType === "function") return false;
42
+ const type = msg.type;
43
+ return typeof type === "string" && MESSAGE_LIKE_TYPES.has(type);
44
+ })) return value;
45
+ return {
46
+ ...state,
47
+ messages: require_messages.ensureMessageInstances(messages)
48
+ };
49
+ }
50
+ function namespaceKey(ns) {
51
+ return ns.join("\0");
52
+ }
53
+ function maxSeq(current, next) {
54
+ if (next == null) return current;
55
+ if (current == null) return next;
56
+ return Math.max(current, next);
57
+ }
58
+ const ROOT_TERMINAL_LIFECYCLE_EVENTS = new Set([
59
+ "completed",
60
+ "failed",
61
+ "interrupted"
62
+ ]);
63
+ /**
64
+ * Detect a root-namespace terminal lifecycle event. Used by
65
+ * `#startProjection`'s `endOnRootTerminal` guard to settle per-run
66
+ * dispatchers regardless of whether the shared-stream pause logic
67
+ * applies to their underlying subscription.
68
+ */
69
+ function isRootTerminalLifecycle(event) {
70
+ if (event.method !== "lifecycle") return false;
71
+ if (event.params.namespace.length !== 0) return false;
72
+ const data = event.params.data;
73
+ return data?.event != null && ROOT_TERMINAL_LIFECYCLE_EVENTS.has(data.event);
74
+ }
75
+ function namespaceListsEqual(a, b) {
76
+ if (a === b) return true;
77
+ if (a === void 0 || b === void 0) return false;
78
+ if (a.length !== b.length) return false;
79
+ const aKeys = /* @__PURE__ */ new Set();
80
+ for (const ns of a) aKeys.add(namespaceKey(ns));
81
+ for (const ns of b) if (!aKeys.has(namespaceKey(ns))) return false;
82
+ return true;
83
+ }
84
+ /**
85
+ * Structural equality on filters. Two filters are equal iff they
86
+ * request the same channel set, the same namespace prefix set
87
+ * (with `undefined` meaning wildcard), and the same depth
88
+ * (with `undefined` meaning unbounded).
89
+ */
90
+ function filterEqual(a, b) {
91
+ if (a === b) return true;
92
+ if (a == null || b == null) return false;
93
+ if (a.channels.length !== b.channels.length) return false;
94
+ const aChannels = new Set(a.channels);
95
+ for (const ch of b.channels) if (!aChannels.has(ch)) return false;
96
+ if (!namespaceListsEqual(a.namespaces, b.namespaces)) return false;
97
+ if ((a.depth ?? null) !== (b.depth ?? null)) return false;
98
+ return true;
99
+ }
100
+ function isPrefix(prefix, candidate) {
101
+ if (prefix.length > candidate.length) return false;
102
+ for (let i = 0; i < prefix.length; i += 1) if (prefix[i] !== candidate[i]) return false;
103
+ return true;
104
+ }
105
+ /**
106
+ * Whether the `coverer` filter delivers every event a subscription
107
+ * opened with `target` could want.
108
+ *
109
+ * Rules:
110
+ * - Channels: target.channels must be a subset of coverer.channels.
111
+ * - Namespaces:
112
+ * - coverer wildcard (`undefined`) → coverer covers all prefixes.
113
+ * - coverer explicit + target wildcard → not covered.
114
+ * - both explicit → every target prefix must have some coverer
115
+ * prefix that is its ancestor (coverer's prefix delivers events
116
+ * for all descendants, modulo depth).
117
+ * - Depth:
118
+ * - coverer unbounded (`undefined`) → depth is covered.
119
+ * - otherwise, for each target prefix `tp` covered by coverer
120
+ * prefix `cp`, the maximum event depth target wants
121
+ * (`tp.length + (target.depth ?? ∞) - cp.length`) must be
122
+ * `<= coverer.depth`. For a wildcard target with bounded depth,
123
+ * target's max absolute depth is `target.depth` (prefix is `[]`).
124
+ */
125
+ function filterCovers(coverer, target) {
126
+ const covererChannels = new Set(coverer.channels);
127
+ for (const ch of target.channels) if (!covererChannels.has(ch)) return false;
128
+ const covererDepth = coverer.depth;
129
+ const targetDepth = target.depth;
130
+ if (coverer.namespaces == null) {
131
+ if (covererDepth == null) return true;
132
+ if (targetDepth == null) return false;
133
+ return targetDepth <= covererDepth;
134
+ }
135
+ if (target.namespaces == null) return false;
136
+ for (const tp of target.namespaces) if (!coverer.namespaces.some((cp) => {
137
+ if (!isPrefix(cp, tp)) return false;
138
+ if (covererDepth == null) return true;
139
+ if (targetDepth == null) return false;
140
+ return tp.length - cp.length + targetDepth <= covererDepth;
141
+ })) return false;
142
+ return true;
143
+ }
144
+ function normalizeSubscribeParams(paramsOrChannels, options = {}) {
145
+ if (typeof paramsOrChannels === "object" && !Array.isArray(paramsOrChannels) && "channels" in paramsOrChannels) return paramsOrChannels;
146
+ const channels = Array.isArray(paramsOrChannels) ? [...paramsOrChannels] : [paramsOrChannels];
147
+ return {
148
+ ...options,
149
+ channels
150
+ };
151
+ }
152
+ /**
153
+ * Async iterable handle for raw event subscriptions.
154
+ *
155
+ * An optional `transform` maps each incoming event before it is queued
156
+ * or delivered to a waiting consumer. This is used by named custom
157
+ * channel subscriptions (e.g. `"custom:a2a"`) to unwrap the payload
158
+ * so callers receive the raw emitted data instead of the protocol
159
+ * event envelope.
160
+ */
161
+ var SubscriptionHandle = class {
162
+ subscriptionId;
163
+ params;
164
+ queue = [];
165
+ waiters = [];
166
+ closed = false;
167
+ paused = false;
168
+ resumeResolve;
169
+ onUnsubscribe;
170
+ transform;
171
+ constructor(subscriptionId, params, onUnsubscribe, transform) {
172
+ this.subscriptionId = subscriptionId;
173
+ this.params = params;
174
+ this.onUnsubscribe = onUnsubscribe;
175
+ this.transform = transform ?? ((event) => event);
176
+ }
177
+ push(event) {
178
+ if (this.closed) return;
179
+ const value = this.transform(event);
180
+ const waiter = this.waiters.shift();
181
+ if (waiter) {
182
+ waiter({
183
+ done: false,
184
+ value
185
+ });
186
+ return;
187
+ }
188
+ this.queue.push(value);
189
+ }
190
+ /**
191
+ * Pause the subscription: resolve all waiting iterators with `done: true`
192
+ * so `for await` loops exit, but keep the subscription alive. New events
193
+ * arriving while paused are still buffered. Call `resume()` to allow
194
+ * iterators to consume again.
195
+ */
196
+ pause() {
197
+ if (this.closed) return;
198
+ this.paused = true;
199
+ while (this.waiters.length > 0) this.waiters.shift()?.({
200
+ done: true,
201
+ value: void 0
202
+ });
203
+ }
204
+ /**
205
+ * Resume a paused subscription so new `for await` loops can consume
206
+ * buffered and future events.
207
+ */
208
+ resume() {
209
+ this.paused = false;
210
+ this.resumeResolve?.();
211
+ this.resumeResolve = void 0;
212
+ }
213
+ /**
214
+ * Returns a promise that resolves when `resume()` is called. Resolves
215
+ * immediately if not currently paused.
216
+ */
217
+ waitForResume() {
218
+ if (!this.paused) return Promise.resolve();
219
+ return new Promise((resolve) => {
220
+ this.resumeResolve = resolve;
221
+ });
222
+ }
223
+ get isPaused() {
224
+ return this.paused;
225
+ }
226
+ close() {
227
+ this.closed = true;
228
+ this.paused = false;
229
+ while (this.waiters.length > 0) this.waiters.shift()?.({
230
+ done: true,
231
+ value: void 0
232
+ });
233
+ this.resumeResolve?.();
234
+ this.resumeResolve = void 0;
235
+ }
236
+ async unsubscribe() {
237
+ if (this.closed) return;
238
+ this.close();
239
+ await this.onUnsubscribe(this.subscriptionId);
240
+ }
241
+ [Symbol.asyncIterator]() {
242
+ return {
243
+ next: async () => {
244
+ if (this.queue.length > 0) return {
245
+ done: false,
246
+ value: this.queue.shift()
247
+ };
248
+ if (this.closed || this.paused) return {
249
+ done: true,
250
+ value: void 0
251
+ };
252
+ return await new Promise((resolve) => {
253
+ this.waiters.push(resolve);
254
+ });
255
+ },
256
+ return: async () => {
257
+ this.close();
258
+ return {
259
+ done: true,
260
+ value: void 0
261
+ };
262
+ }
263
+ };
264
+ }
265
+ };
266
+ /**
267
+ * High-level wrapper around a protocol connection to a specific thread.
268
+ *
269
+ * In the thread-centric protocol, threads are durable (backed by
270
+ * checkpoints) and connections are ephemeral. A `ThreadStream` is the
271
+ * client-side handle for interacting with a thread: starting runs,
272
+ * subscribing to events, consuming assembled projections (`messages`,
273
+ * `values`, `toolCalls`, etc.), and responding to interrupts.
274
+ *
275
+ * Construct via `client.threads.stream(threadId?, { assistantId? })`.
276
+ *
277
+ * @typeParam TExtensions - Optional map of `{ name: payload }` pairs
278
+ * describing the transformer projections the bound assistant exposes
279
+ * on `custom:<name>` channels. Narrows `thread.extensions.<name>` to
280
+ * `ThreadExtension<payload>`. Defaults to `Record<string, unknown>`.
281
+ */
282
+ var ThreadStream = class {
283
+ threadId;
284
+ ordering = {};
285
+ run;
286
+ agent;
287
+ input;
288
+ state;
289
+ /**
290
+ * Whether the run was interrupted (a lifecycle "interrupted" event
291
+ * was received). Mirrors the in-process `run.interrupted`.
292
+ */
293
+ interrupted = false;
294
+ /**
295
+ * Interrupt payloads collected during the run, if any.
296
+ * Mirrors the in-process `run.interrupts`.
297
+ */
298
+ interrupts = [];
299
+ assistantId;
300
+ #nextCommandId;
301
+ #transportAdapter;
302
+ #pending = /* @__PURE__ */ new Map();
303
+ #subscriptions = /* @__PURE__ */ new Map();
304
+ #seenEventIds = /* @__PURE__ */ new Set();
305
+ /**
306
+ * Headless tool interrupts can be auto-resumed by the React hook before
307
+ * the shared SSE content pump has processed the root `interrupted`
308
+ * lifecycle event. `respondInput()` clears `interrupts`, so keep a
309
+ * short-lived marker here until that stale terminal passes through the
310
+ * content pump and we can avoid pausing it.
311
+ */
312
+ #headlessInterruptsAwaitingTerminal = /* @__PURE__ */ new Set();
313
+ #closed = false;
314
+ #opened = false;
315
+ #openPromise;
316
+ #sharedStream = null;
317
+ #sharedStreamFilter = null;
318
+ #rotationState = "idle";
319
+ /** Pending `subscribe()` promises waiting for a covering rotation. */
320
+ #pendingSubResolves = [];
321
+ #terminalPauseTimer;
322
+ #terminalPauseSeq;
323
+ #lifecycleSubId = null;
324
+ #lifecycleStartPromise;
325
+ #lifecycleWatcherHandle = null;
326
+ #lifecycleWatcherStartPromise;
327
+ #onEventListeners = /* @__PURE__ */ new Set();
328
+ #messagesIterable;
329
+ #valuesProjection;
330
+ #toolCallsIterable;
331
+ #subgraphsIterable;
332
+ #subagentsIterable;
333
+ #outputPromise;
334
+ #extensionsProxy;
335
+ #extensionsCache = /* @__PURE__ */ new Map();
336
+ /**
337
+ * Shared state for the single `"custom"` channel subscription that
338
+ * backs every `thread.extensions.<name>` handle.
339
+ *
340
+ * One subscription is opened eagerly from {@link run.start} (mirroring
341
+ * the {@link values} eager-start pattern) so that per-name handles
342
+ * created before, during, or after the run can all resolve correctly.
343
+ *
344
+ * - `events` retains every custom event for backfill into
345
+ * late-constructed handles.
346
+ * - `eventListeners` fan new events out to live per-name handlers.
347
+ * - `endListeners` fire when the dispatcher's run terminates, so each
348
+ * handle can resolve its `PromiseLike` side with its last-seen
349
+ * payload.
350
+ */
351
+ #extensionsDispatcherStarted = false;
352
+ #extensionsEnded = false;
353
+ #extensionsEvents = [];
354
+ #extensionsEventListeners = [];
355
+ #extensionsEndListeners = [];
356
+ /**
357
+ * Shared state for the single `messages`-channel subscription that
358
+ * backs every media handle iterable (`thread.audio`, `thread.images`,
359
+ * `thread.video`, `thread.files`). One subscription serves all four
360
+ * iterables; per-type buffers track the handles already emitted so
361
+ * late attachers replay through {@link MultiCursorBuffer}.
362
+ */
363
+ #mediaDispatcherStarted = false;
364
+ #mediaAssembler;
365
+ /** Object URLs minted by media handles, tracked for {@link close} cleanup. */
366
+ #mediaHandles = /* @__PURE__ */ new Set();
367
+ #audioBuffer = new require_multi_cursor_buffer.MultiCursorBuffer();
368
+ #imagesBuffer = new require_multi_cursor_buffer.MultiCursorBuffer();
369
+ #videoBuffer = new require_multi_cursor_buffer.MultiCursorBuffer();
370
+ #filesBuffer = new require_multi_cursor_buffer.MultiCursorBuffer();
371
+ #fetchOption;
372
+ constructor(transportAdapter, options) {
373
+ if (!options?.assistantId) throw new Error("ThreadStream requires an assistantId option.");
374
+ this.#transportAdapter = transportAdapter;
375
+ this.threadId = transportAdapter.threadId;
376
+ this.assistantId = options.assistantId;
377
+ this.#nextCommandId = options.startingCommandId ?? 1;
378
+ this.#fetchOption = options.fetch;
379
+ this.run = { start: async (params) => {
380
+ this.#prepareForNextRun();
381
+ this.#ensureLifecycleTracking();
382
+ this.values;
383
+ return await this.#send("run.start", {
384
+ ...params,
385
+ assistant_id: this.assistantId
386
+ });
387
+ } };
388
+ this.agent = { getTree: async (params = {}) => await this.#send("agent.getTree", params) };
389
+ this.input = {
390
+ respond: async (params) => {
391
+ this.#prepareForNextRun();
392
+ this.#ensureLifecycleTracking();
393
+ this.values;
394
+ await this.#send("input.respond", params);
395
+ },
396
+ inject: async (params) => {
397
+ await this.#send("input.inject", params);
398
+ }
399
+ };
400
+ this.state = {
401
+ get: async (params) => await this.#send("state.get", params),
402
+ listCheckpoints: async (params) => await this.#send("state.listCheckpoints", params),
403
+ fork: async (params) => await this.#send("state.fork", params)
404
+ };
405
+ if (this.#transportAdapter.openEventStream == null) this.#consumeEvents();
406
+ }
407
+ /**
408
+ * Ensure the underlying transport is connected.
409
+ *
410
+ * For HTTP/SSE this is a no-op. For WebSocket this performs the
411
+ * handshake. Called lazily on first command; safe to call multiple times.
412
+ */
413
+ async #ensureOpen() {
414
+ if (this.#opened) return;
415
+ if (this.#openPromise == null) this.#openPromise = this.#transportAdapter.open().then(() => {
416
+ this.#opened = true;
417
+ });
418
+ await this.#openPromise;
419
+ }
420
+ /**
421
+ * Channels bundled into every lazy getter's SSE filter so that
422
+ * interrupt tracking works without a separate lifecycle subscription.
423
+ */
424
+ #lifecycleChannels() {
425
+ return ["lifecycle", "input"];
426
+ }
427
+ /**
428
+ * Lazily start a dedicated lifecycle+input subscription so that
429
+ * `thread.interrupted` / `thread.interrupts` work even when the
430
+ * caller never accesses a lazy getter (e.g. they only call
431
+ * `run.start` and `subscribe({ channels: ["custom:..."] })`).
432
+ *
433
+ * Idempotent and fire-and-forget — invoked from `run.start` and
434
+ * `input.respond`.
435
+ */
436
+ #ensureLifecycleTracking() {
437
+ if (this.#lifecycleStartPromise != null) return;
438
+ this.#lifecycleStartPromise = (async () => {
439
+ this.#lifecycleSubId = (await this.#subscribeRaw({ channels: this.#lifecycleChannels() })).subscriptionId;
440
+ })().catch(() => void 0);
441
+ }
442
+ /**
443
+ * Reset interrupt state and resume all paused user subscriptions.
444
+ * Called before `run.start()` and `input.respond()` so that
445
+ * iterators on the same handle pick up the next run's events.
446
+ */
447
+ #prepareForNextRun() {
448
+ this.interrupted = false;
449
+ this.interrupts.length = 0;
450
+ if (this.#terminalPauseTimer != null) {
451
+ clearTimeout(this.#terminalPauseTimer);
452
+ this.#terminalPauseTimer = void 0;
453
+ }
454
+ this.#terminalPauseSeq = void 0;
455
+ for (const [id, subscription] of this.#subscriptions) if (id !== this.#lifecycleSubId) subscription.resume();
456
+ }
457
+ /**
458
+ * Streaming messages. Each `for await` loop gets an independent cursor
459
+ * over the shared buffer; late consumers see all previously emitted
460
+ * messages. Mirrors the in-process `run.messages`.
461
+ */
462
+ get messages() {
463
+ if (this.#messagesIterable) return this.#messagesIterable;
464
+ const buffer = new require_multi_cursor_buffer.MultiCursorBuffer();
465
+ this.#messagesIterable = buffer;
466
+ const assembler = new require_messages$1.StreamingMessageAssembler();
467
+ this.#startProjection(["messages", ...this.#lifecycleChannels()], (event) => {
468
+ if (event.method !== "messages") return;
469
+ const msg = assembler.consume(event);
470
+ if (msg) buffer.push(require_messages$1.toStreamingMessageHandle(msg));
471
+ }, () => buffer.close());
472
+ return buffer;
473
+ }
474
+ /**
475
+ * State values. Iterable for intermediate snapshots; also
476
+ * `PromiseLike` — `await thread.values` resolves with the final
477
+ * state. Mirrors the in-process `run.values`.
478
+ */
479
+ get values() {
480
+ if (this.#valuesProjection) return this.#valuesProjection;
481
+ const buffer = new require_multi_cursor_buffer.MultiCursorBuffer();
482
+ let lastValue;
483
+ let resolveOutput;
484
+ const outputPromise = new Promise((resolve) => {
485
+ resolveOutput = resolve;
486
+ });
487
+ this.#outputPromise = outputPromise;
488
+ const projection = Object.assign(buffer, { then: (onfulfilled, onrejected) => outputPromise.then(onfulfilled, onrejected) });
489
+ this.#valuesProjection = projection;
490
+ this.#startProjection(["values", ...this.#lifecycleChannels()], (event) => {
491
+ if (event.method !== "values") return;
492
+ const data = coerceStateMessages(event.params.data);
493
+ lastValue = data;
494
+ buffer.push(data);
495
+ }, () => {
496
+ resolveOutput(lastValue);
497
+ buffer.close();
498
+ });
499
+ return projection;
500
+ }
501
+ /**
502
+ * Tool calls with promise-based output/status/error.
503
+ * Mirrors the in-process `run.toolCalls`.
504
+ */
505
+ get toolCalls() {
506
+ if (this.#toolCallsIterable) return this.#toolCallsIterable;
507
+ const buffer = new require_multi_cursor_buffer.MultiCursorBuffer();
508
+ this.#toolCallsIterable = buffer;
509
+ const assembler = new require_tools.ToolCallAssembler();
510
+ this.#startProjection(["tools", ...this.#lifecycleChannels()], (event) => {
511
+ if (event.method !== "tools") return;
512
+ const tc = assembler.consume(event);
513
+ if (tc) buffer.push(tc);
514
+ }, () => buffer.close());
515
+ return buffer;
516
+ }
517
+ /**
518
+ * Discovered subgraphs. Mirrors the in-process `run.subgraphs`.
519
+ */
520
+ get subgraphs() {
521
+ if (this.#subgraphsIterable) return this.#subgraphsIterable;
522
+ const buffer = new require_multi_cursor_buffer.MultiCursorBuffer();
523
+ this.#subgraphsIterable = buffer;
524
+ (async () => {
525
+ const discovery = new require_subgraphs.SubgraphDiscoveryHandle(await this.#subscribeRaw({ channels: ["tools", ...this.#lifecycleChannels()] }), this, []);
526
+ for await (const sub of discovery) buffer.push(sub);
527
+ buffer.close();
528
+ })();
529
+ return buffer;
530
+ }
531
+ /**
532
+ * Discovered subagents.
533
+ */
534
+ get subagents() {
535
+ if (this.#subagentsIterable) return this.#subagentsIterable;
536
+ const buffer = new require_multi_cursor_buffer.MultiCursorBuffer();
537
+ this.#subagentsIterable = buffer;
538
+ (async () => {
539
+ const discovery = new require_subagents.SubagentDiscoveryHandle(await this.#subscribeRaw({ channels: ["tools", ...this.#lifecycleChannels()] }), this);
540
+ for await (const sub of discovery) buffer.push(sub);
541
+ buffer.close();
542
+ })();
543
+ return buffer;
544
+ }
545
+ /**
546
+ * Audio media handles, one per message containing at least one
547
+ * `AudioBlock`. Each `for await` opens an independent cursor over
548
+ * the shared buffer; late consumers replay every previously emitted
549
+ * audio handle.
550
+ *
551
+ * Yields one item per message on the first matching
552
+ * `content-block-start` — messages with no audio blocks are skipped.
553
+ */
554
+ get audio() {
555
+ this.#ensureMediaDispatcher();
556
+ return this.#audioBuffer;
557
+ }
558
+ /**
559
+ * Image media handles, one per message containing at least one
560
+ * `ImageBlock`. See {@link audio} for shared semantics.
561
+ */
562
+ get images() {
563
+ this.#ensureMediaDispatcher();
564
+ return this.#imagesBuffer;
565
+ }
566
+ /**
567
+ * Video media handles, one per message containing at least one
568
+ * `VideoBlock`. See {@link audio} for shared semantics.
569
+ */
570
+ get video() {
571
+ this.#ensureMediaDispatcher();
572
+ return this.#videoBuffer;
573
+ }
574
+ /**
575
+ * File media handles, one per message containing at least one
576
+ * `FileBlock`. See {@link audio} for shared semantics.
577
+ */
578
+ get files() {
579
+ this.#ensureMediaDispatcher();
580
+ return this.#filesBuffer;
581
+ }
582
+ /**
583
+ * Promise that resolves with the final state value when the run
584
+ * completes. Shares the `values` getter's SSE connection.
585
+ * Mirrors the in-process `run.output`.
586
+ */
587
+ get output() {
588
+ this.values;
589
+ return this.#outputPromise;
590
+ }
591
+ /**
592
+ * Proxy over compile-time {@link StreamTransformer} projections
593
+ * exposed by the bound assistant on `custom:<name>` channels.
594
+ *
595
+ * Each access (e.g. `thread.extensions.toolActivity`) lazily opens a
596
+ * dedicated `custom:<name>` subscription, returns a cached
597
+ * {@link ThreadExtension} handle that is both `AsyncIterable<T>`
598
+ * (streaming items as they arrive) and `PromiseLike<T>` (resolves
599
+ * with the final value when the run terminates), and reuses the same
600
+ * handle on subsequent access.
601
+ *
602
+ * Mirrors the in-process `run.extensions.<name>` shape.
603
+ */
604
+ get extensions() {
605
+ if (this.#extensionsProxy) return this.#extensionsProxy;
606
+ const cache = this.#extensionsCache;
607
+ const createExtension = (name) => this.#createExtension(name);
608
+ this.#extensionsProxy = new Proxy(Object.create(null), {
609
+ get: (_target, prop) => {
610
+ if (typeof prop !== "string") return void 0;
611
+ const cached = cache.get(prop);
612
+ if (cached) return cached;
613
+ const extension = createExtension(prop);
614
+ cache.set(prop, extension);
615
+ return extension;
616
+ },
617
+ has: (_target, prop) => typeof prop === "string"
618
+ });
619
+ return this.#extensionsProxy;
620
+ }
621
+ /**
622
+ * Lazily open one shared subscription on the `custom` channel that
623
+ * buffers every custom event for this run and fans it out to any
624
+ * per-name extension handles.
625
+ *
626
+ * Deliberately **lazy**: the dispatcher only starts on first access
627
+ * to `thread.extensions.<name>`. Runs that never touch extensions
628
+ * pay no subscription cost. Runs that touch extensions after events
629
+ * have already fired rely on the server's per-session event buffer,
630
+ * which replays matching events to new subscriptions.
631
+ *
632
+ * Each handle retains a PromiseLike that resolves with the
633
+ * transformer's last-observed payload, independent of when the
634
+ * caller grabs the handle (before, during, or after the run), as
635
+ * long as the server still has the events buffered.
636
+ *
637
+ * Idempotent. Invoked only from {@link #createExtension}.
638
+ */
639
+ #ensureExtensionsDispatcher() {
640
+ if (this.#extensionsDispatcherStarted) return;
641
+ this.#extensionsDispatcherStarted = true;
642
+ this.#startProjection(["custom", ...this.#lifecycleChannels()], (event) => {
643
+ if (event.method !== "custom") return;
644
+ this.#extensionsEvents.push(event);
645
+ for (const listener of this.#extensionsEventListeners) listener(event);
646
+ }, () => {
647
+ this.#extensionsEnded = true;
648
+ const listeners = this.#extensionsEndListeners.splice(0);
649
+ for (const listener of listeners) listener();
650
+ }, { endOnRootTerminal: true });
651
+ }
652
+ /**
653
+ * Open the single shared `messages`-channel subscription that backs
654
+ * every media iterable (audio/images/video/files). Idempotent.
655
+ *
656
+ * The {@link MediaAssembler} fans out to four per-type
657
+ * {@link MultiCursorBuffer}s; each buffer feeds its corresponding
658
+ * lazy getter. One handle is yielded per `(messageId, blockType)` on
659
+ * the first matching `content-block-start`, so messages without any
660
+ * media blocks of a given type never appear on that iterable.
661
+ */
662
+ #ensureMediaDispatcher() {
663
+ if (this.#mediaDispatcherStarted) return;
664
+ this.#mediaDispatcherStarted = true;
665
+ const assembler = new require_media.MediaAssembler({
666
+ fetch: this.#fetchOption,
667
+ onAudio: (m) => {
668
+ this.#mediaHandles.add(m);
669
+ this.#audioBuffer.push(m);
670
+ },
671
+ onImage: (m) => {
672
+ this.#mediaHandles.add(m);
673
+ this.#imagesBuffer.push(m);
674
+ },
675
+ onVideo: (m) => {
676
+ this.#mediaHandles.add(m);
677
+ this.#videoBuffer.push(m);
678
+ },
679
+ onFile: (m) => {
680
+ this.#mediaHandles.add(m);
681
+ this.#filesBuffer.push(m);
682
+ }
683
+ });
684
+ this.#mediaAssembler = assembler;
685
+ this.#startProjection(["messages", ...this.#lifecycleChannels()], (event) => {
686
+ if (event.method !== "messages") return;
687
+ assembler.consume(event);
688
+ }, () => {
689
+ assembler.close();
690
+ this.#audioBuffer.close();
691
+ this.#imagesBuffer.close();
692
+ this.#videoBuffer.close();
693
+ this.#filesBuffer.close();
694
+ });
695
+ }
696
+ /**
697
+ * Build a single {@link ThreadExtension} handle for a named
698
+ * `custom:<name>` projection.
699
+ *
700
+ * The handle reads from the shared extensions dispatcher: past events
701
+ * matching {@link name} are backfilled on construction, future events
702
+ * arrive via a registered listener, and the handle's `PromiseLike`
703
+ * side resolves with its last-seen payload once the run terminates
704
+ * (which may already have happened, in which case it resolves on the
705
+ * next microtask).
706
+ */
707
+ #createExtension(name) {
708
+ this.#ensureExtensionsDispatcher();
709
+ const buffer = new require_multi_cursor_buffer.MultiCursorBuffer();
710
+ let lastValue;
711
+ let resolveFinal;
712
+ const finalPromise = new Promise((resolve) => {
713
+ resolveFinal = resolve;
714
+ });
715
+ const handleEvent = (event) => {
716
+ const data = event.params.data;
717
+ if (data?.name !== name) return;
718
+ lastValue = data.payload;
719
+ buffer.push(data.payload);
720
+ };
721
+ for (const event of this.#extensionsEvents) handleEvent(event);
722
+ this.#extensionsEventListeners.push(handleEvent);
723
+ const settle = () => {
724
+ resolveFinal(lastValue);
725
+ buffer.close();
726
+ };
727
+ if (this.#extensionsEnded) settle();
728
+ else this.#extensionsEndListeners.push(settle);
729
+ return Object.assign(buffer, { then: (onfulfilled, onrejected) => finalPromise.then(onfulfilled, onrejected) });
730
+ }
731
+ /**
732
+ * Generic projection starter: opens a raw subscription with the given
733
+ * channels, feeds events through the consumer, and calls onDone when
734
+ * the stream ends.
735
+ *
736
+ * When `endOnRootTerminal` is set, the projection unsubscribes its
737
+ * own handle one macrotask after observing a root-namespace terminal
738
+ * lifecycle event. This is needed by projections that may be opened
739
+ * AFTER a run already terminated: the shared-stream pause logic
740
+ * skips subscriptions whose `registeredAfterSeq` is past the
741
+ * terminal so raw `subscribe()` callers can keep draining replayed
742
+ * descendants — but a per-run dispatcher (e.g. the extensions
743
+ * pipeline) needs the projection to settle so its `PromiseLike`
744
+ * surface resolves. The macrotask deferral mirrors the deferred
745
+ * pause in `#handleIncoming`, giving trailing same-tick custom
746
+ * events (transformer `finalize()` flushes) a chance to drain.
747
+ */
748
+ async #startProjection(channels, onEvent, onDone, options = {}) {
749
+ let endTimer;
750
+ let rawHandle;
751
+ try {
752
+ rawHandle = await this.#subscribeRaw({ channels });
753
+ const handle = rawHandle;
754
+ for await (const event of handle) {
755
+ onEvent(event);
756
+ if (options.endOnRootTerminal && endTimer == null && isRootTerminalLifecycle(event)) endTimer = setTimeout(() => {
757
+ endTimer = void 0;
758
+ handle.unsubscribe().catch(() => void 0);
759
+ }, 0);
760
+ }
761
+ } catch {} finally {
762
+ if (endTimer != null) clearTimeout(endTimer);
763
+ onDone();
764
+ }
765
+ }
766
+ /**
767
+ * Start a run without the v1 eager lazy-getter shims.
768
+ *
769
+ * `run.start` (the v1 entry point) eagerly opens a wildcard `values`
770
+ * projection so `thread.output` / `thread.values` resolve regardless
771
+ * of access order, and calls `#ensureLifecycleTracking` which opens
772
+ * another wildcard `["lifecycle", "input"]` subscription. Both
773
+ * subscriptions widen `#computeUnionFilter` to wildcard, defeating
774
+ * the progressive-expansion rotation strategy.
775
+ *
776
+ * `submitRun` skips those shims — callers that manage their own
777
+ * content subscriptions (such as `StreamController`) get the narrow
778
+ * union filter they asked for. Lifecycle / interrupt tracking is
779
+ * instead served by the dedicated `#startLifecycleWatcher`, which
780
+ * opens a wildcard `["lifecycle", "input"]` stream alongside the
781
+ * narrow content pump on both SSE and WebSocket transports.
782
+ */
783
+ async submitRun(params) {
784
+ this.#prepareForNextRun();
785
+ this.#startLifecycleWatcher();
786
+ return await this.#send("run.start", {
787
+ ...params,
788
+ assistant_id: this.assistantId
789
+ });
790
+ }
791
+ /**
792
+ * Respond to an interrupt without the v1 eager lazy-getter shims.
793
+ * See {@link submitRun} for why this exists alongside
794
+ * {@link input.respond}.
795
+ */
796
+ async respondInput(params) {
797
+ this.#prepareForNextRun();
798
+ this.#startLifecycleWatcher();
799
+ await this.#send("input.respond", params);
800
+ }
801
+ /**
802
+ * Register a listener for every globally-unique event on the thread.
803
+ *
804
+ * Fires exactly once per `event_id` across both the content pump
805
+ * (user `subscribe()` calls) and the lifecycle watcher. Events
806
+ * without an `event_id` always fire through (dedup is best-effort).
807
+ *
808
+ * Returns an unsubscribe function. Primary consumer is
809
+ * `StreamController`, which uses the listener to feed discovery
810
+ * runners and pick up deeply-nested interrupts that the narrow
811
+ * content pump wouldn't deliver.
812
+ */
813
+ onEvent(listener) {
814
+ this.#onEventListeners.add(listener);
815
+ return () => {
816
+ this.#onEventListeners.delete(listener);
817
+ };
818
+ }
819
+ /**
820
+ * Lazily open the wildcard discovery watcher stream.
821
+ *
822
+ * Idempotent. Used by both transports, but through different
823
+ * mechanisms:
824
+ *
825
+ * - **SSE**: opens a dedicated event stream via
826
+ * {@link TransportAdapter.openEventStream}. The stream runs
827
+ * outside `#computeUnionFilter`, so the shared SSE stream's
828
+ * content pump can stay narrow (e.g. `depth: 1`) while we still
829
+ * capture every lifecycle/input event at any depth.
830
+ * - **WebSocket**: opens a wildcard watcher subscription
831
+ * subscription via the normal command path. The WS server
832
+ * delivers matching events on the shared command connection and
833
+ * `#handleIncoming` dispatches them through `#fireOnEvent` and
834
+ * the thread-level effects — same downstream semantics as the
835
+ * SSE watcher, just reusing the transport that's already open.
836
+ *
837
+ * Why this matters: consumers of {@link onEvent} (notably
838
+ * `StreamController`'s subgraph/subagent discovery runners and
839
+ * nested interrupt capture) depend on observing namespaced
840
+ * lifecycle events at any depth. Without this watcher, WS clients
841
+ * would only ever receive events matching the content pump's
842
+ * narrow filter (depth 1 from the root), breaking inference rules
843
+ * that require deeper descendants (e.g. the "has-descendants"
844
+ * signal used to promote a subgraph host).
845
+ */
846
+ #startLifecycleWatcher() {
847
+ if (this.#lifecycleWatcherStartPromise != null) return;
848
+ if (this.#transportAdapter.openEventStream != null) {
849
+ this.#lifecycleWatcherStartPromise = this.#startLifecycleWatcherSse();
850
+ return;
851
+ }
852
+ this.#lifecycleWatcherStartPromise = this.#startLifecycleWatcherWebSocket();
853
+ }
854
+ async #startLifecycleWatcherSse() {
855
+ const filter = { channels: ["lifecycle", "input"] };
856
+ let handle;
857
+ try {
858
+ handle = this.#transportAdapter.openEventStream(filter);
859
+ } catch {
860
+ return;
861
+ }
862
+ try {
863
+ await handle.ready;
864
+ } catch {
865
+ try {
866
+ handle.close();
867
+ } catch {}
868
+ return;
869
+ }
870
+ if (this.#closed) {
871
+ try {
872
+ handle.close();
873
+ } catch {}
874
+ return;
875
+ }
876
+ this.#lifecycleWatcherHandle = handle;
877
+ try {
878
+ for await (const message of handle.events) {
879
+ if (this.#closed) break;
880
+ this.#handleLifecycleWatcherMessage(message);
881
+ }
882
+ } catch {}
883
+ }
884
+ async #startLifecycleWatcherWebSocket() {
885
+ let handle;
886
+ try {
887
+ handle = await this.#subscribeRaw({ channels: ["lifecycle", "input"] });
888
+ } catch {
889
+ return;
890
+ }
891
+ if (this.#closed) {
892
+ try {
893
+ handle.close();
894
+ } catch {}
895
+ return;
896
+ }
897
+ try {
898
+ for await (const _event of handle) if (this.#closed) break;
899
+ } catch {}
900
+ }
901
+ /**
902
+ * Process an event from the dedicated lifecycle watcher stream.
903
+ *
904
+ * Unlike `#handleIncoming`, this does NOT fan out to user
905
+ * subscriptions — user subs with namespace wildcards already widen
906
+ * `#computeUnionFilter` and therefore receive the event on the
907
+ * content pump. Delivering via both streams would only add per-sub
908
+ * dedup churn without expanding what the user can observe.
909
+ *
910
+ * We still run global-dedup thread-level side effects (interrupt
911
+ * capture, `onEvent` fan-out) so deeply-nested interrupts outside
912
+ * the content pump's narrow scope are recorded.
913
+ */
914
+ #handleLifecycleWatcherMessage(message) {
915
+ if (message.type !== "event") return;
916
+ if (typeof message.seq === "number") this.ordering.lastSeenSeq = maxSeq(this.ordering.lastSeenSeq, message.seq);
917
+ if (message.event_id) this.ordering.lastEventId = message.event_id;
918
+ const eventId = message.event_id ?? void 0;
919
+ const globallyProcessed = eventId != null && this.#seenEventIds.has(eventId);
920
+ if (eventId != null) this.#seenEventIds.add(eventId);
921
+ if (globallyProcessed) return;
922
+ this.#applyThreadLevelEffects(message);
923
+ this.#fireOnEvent(message);
924
+ }
925
+ #applyThreadLevelEffects(event) {
926
+ if (event.method === "lifecycle") {
927
+ if (event.params.data.event === "interrupted") this.interrupted = true;
928
+ }
929
+ if (event.method === "input.requested") {
930
+ const data = event.params.data;
931
+ const interruptId = data.interrupt_id ?? `interrupt_${this.interrupts.length}`;
932
+ this.interrupts.push({
933
+ interruptId,
934
+ payload: data.payload,
935
+ namespace: [...event.params.namespace]
936
+ });
937
+ if (require_headless_tools.isHeadlessToolInterrupt(data.payload)) this.#headlessInterruptsAwaitingTerminal.add(interruptId);
938
+ }
939
+ }
940
+ #fireOnEvent(event) {
941
+ if (this.#onEventListeners.size === 0) return;
942
+ for (const listener of this.#onEventListeners) try {
943
+ listener(event);
944
+ } catch {}
945
+ }
946
+ async close() {
947
+ if (this.#closed) return;
948
+ this.#closed = true;
949
+ if (this.#terminalPauseTimer != null) {
950
+ clearTimeout(this.#terminalPauseTimer);
951
+ this.#terminalPauseTimer = void 0;
952
+ }
953
+ this.#terminalPauseSeq = void 0;
954
+ for (const pending of this.#pendingSubResolves) pending.reject(/* @__PURE__ */ new Error("ThreadStream closed"));
955
+ this.#pendingSubResolves.length = 0;
956
+ if (this.#sharedStream != null) {
957
+ try {
958
+ this.#sharedStream.close();
959
+ } catch {}
960
+ this.#sharedStream = null;
961
+ this.#sharedStreamFilter = null;
962
+ }
963
+ if (this.#lifecycleWatcherHandle != null) {
964
+ try {
965
+ this.#lifecycleWatcherHandle.close();
966
+ } catch {}
967
+ this.#lifecycleWatcherHandle = null;
968
+ }
969
+ const lifecycleWatcherStartPromise = this.#lifecycleWatcherStartPromise;
970
+ this.#lifecycleWatcherStartPromise = void 0;
971
+ this.#onEventListeners.clear();
972
+ for (const subscription of this.#subscriptions.values()) subscription.close();
973
+ this.#subscriptions.clear();
974
+ try {
975
+ await lifecycleWatcherStartPromise;
976
+ } catch {}
977
+ for (const handle of this.#mediaHandles) try {
978
+ handle.revoke();
979
+ } catch {}
980
+ this.#mediaHandles.clear();
981
+ this.#mediaAssembler?.close();
982
+ this.#audioBuffer.close();
983
+ this.#imagesBuffer.close();
984
+ this.#videoBuffer.close();
985
+ this.#filesBuffer.close();
986
+ await this.#transportAdapter.close();
987
+ }
988
+ async subscribe(paramsOrChannels, options = {}) {
989
+ const isParamsObject = typeof paramsOrChannels === "object" && !Array.isArray(paramsOrChannels) && "channels" in paramsOrChannels;
990
+ const params = normalizeSubscribeParams(paramsOrChannels, options);
991
+ return await this.#subscribeRaw(params, { unwrapNamedCustom: !isParamsObject });
992
+ }
993
+ async #subscribeRaw(params, options = {}) {
994
+ await this.#ensureOpen();
995
+ const { unwrapNamedCustom = true } = options;
996
+ const hasOnlyNamedCustom = params.channels.length > 0 && params.channels.every((ch) => ch.startsWith("custom:"));
997
+ const transform = unwrapNamedCustom && hasOnlyNamedCustom ? (event) => event.params.data?.payload ?? event : void 0;
998
+ if (this.#transportAdapter.openEventStream != null) return this.#subscribeViaSharedStream(params, transform);
999
+ return this.#subscribeViaCommand(params, transform);
1000
+ }
1001
+ /**
1002
+ * Subscribe via the single shared SSE connection.
1003
+ *
1004
+ * The subscription is registered immediately in `#subscriptions` so
1005
+ * fan-out can reach it the moment events begin flowing. The returned
1006
+ * promise resolves after a stream rotation completes whose union
1007
+ * filter covers this subscription's channels — mirroring the per-sub
1008
+ * `await streamHandle.ready` semantics callers depended on.
1009
+ *
1010
+ * Every subscribe schedules a stream rotation, even when the current
1011
+ * stream's filter already covers `params`. Rotating opens a fresh
1012
+ * server-side session that replays the run's full history from
1013
+ * `seq=0`; without it a late-joining sub would only see events that
1014
+ * arrive after it registered, because the shared pump's dedup drops
1015
+ * events the existing sub already consumed. Per-sub dedup
1016
+ * (`seenEventIds`) protects existing subs from receiving the
1017
+ * replay as duplicates. Rapid subscribes in the same microtask are
1018
+ * coalesced by `#scheduleReconcile` into a single rotation.
1019
+ */
1020
+ async #subscribeViaSharedStream(params, transform) {
1021
+ const subscriptionId = `sse-${this.#nextCommandId++}`;
1022
+ const handle = new SubscriptionHandle(subscriptionId, params, async (id) => {
1023
+ this.#subscriptions.delete(id);
1024
+ this.#scheduleReconcile();
1025
+ }, transform);
1026
+ const subscription = Object.assign(handle, {
1027
+ filter: params,
1028
+ registeredAfterSeq: this.ordering.lastSeenSeq,
1029
+ seenEventIds: /* @__PURE__ */ new Set()
1030
+ });
1031
+ this.#subscriptions.set(subscriptionId, subscription);
1032
+ const covered = new Promise((resolve, reject) => {
1033
+ this.#pendingSubResolves.push({
1034
+ filter: params,
1035
+ resolve,
1036
+ reject
1037
+ });
1038
+ });
1039
+ this.#scheduleReconcile();
1040
+ try {
1041
+ await covered;
1042
+ } catch (err) {
1043
+ this.#subscriptions.delete(subscriptionId);
1044
+ throw err;
1045
+ }
1046
+ return handle;
1047
+ }
1048
+ /**
1049
+ * Progressive-expansion union of every currently-registered
1050
+ * subscription's filter. The server receives the narrowest filter
1051
+ * that still covers every active sub so deeply-namespaced or
1052
+ * selectively-opened projections don't pull down the entire thread's
1053
+ * event firehose.
1054
+ *
1055
+ * Unioning rules (matching the server's matching semantics in
1056
+ * `matchesSinkFilter`):
1057
+ * - Channels: set union.
1058
+ * - Namespaces: if any subscription requests a wildcard
1059
+ * (`namespaces === undefined`) the union is wildcard; otherwise
1060
+ * the union is the deduplicated list of every explicit prefix.
1061
+ * - Depth: if any subscription is unbounded (`depth === undefined`)
1062
+ * the union is unbounded; otherwise the union is the maximum
1063
+ * depth across all subscriptions (matching the per-sub "max
1064
+ * reach below the prefix" semantics).
1065
+ *
1066
+ * Returns `null` when there are no subscriptions.
1067
+ */
1068
+ #computeUnionFilter() {
1069
+ if (this.#subscriptions.size === 0) return null;
1070
+ const channels = /* @__PURE__ */ new Set();
1071
+ let wildcardNamespaces = false;
1072
+ const namespaceMap = /* @__PURE__ */ new Map();
1073
+ let unboundedDepth = false;
1074
+ let maxDepth = 0;
1075
+ for (const sub of this.#subscriptions.values()) {
1076
+ for (const ch of sub.filter.channels) channels.add(ch);
1077
+ if (sub.filter.namespaces == null) wildcardNamespaces = true;
1078
+ else if (!wildcardNamespaces) for (const ns of sub.filter.namespaces) namespaceMap.set(namespaceKey(ns), ns);
1079
+ if (sub.filter.depth == null) unboundedDepth = true;
1080
+ else if (!unboundedDepth && sub.filter.depth > maxDepth) maxDepth = sub.filter.depth;
1081
+ }
1082
+ const result = { channels: [...channels] };
1083
+ if (!wildcardNamespaces) result.namespaces = [...namespaceMap.values()];
1084
+ if (!unboundedDepth) result.depth = maxDepth;
1085
+ return result;
1086
+ }
1087
+ /**
1088
+ * Schedule a stream reconciliation for the next microtask.
1089
+ *
1090
+ * Coalesces multiple subscribe/unsubscribe calls in the same tick
1091
+ * into a single rotation, and serializes across ticks (no two
1092
+ * rotations ever run concurrently).
1093
+ */
1094
+ #scheduleReconcile() {
1095
+ if (this.#closed) return;
1096
+ if (this.#rotationState !== "idle") return;
1097
+ this.#rotationState = "scheduled";
1098
+ queueMicrotask(() => {
1099
+ if (this.#closed) {
1100
+ this.#rotationState = "idle";
1101
+ return;
1102
+ }
1103
+ this.#rotationState = "idle";
1104
+ this.#reconcileStream().catch(() => {
1105
+ this.#rotationState = "idle";
1106
+ });
1107
+ });
1108
+ }
1109
+ /**
1110
+ * Reconcile the shared SSE stream to match the desired union filter.
1111
+ *
1112
+ * Rotation strategy: open the new stream first, await its `ready`,
1113
+ * then close the old one. Overlap is absorbed by `#seenEventIds`
1114
+ * dedup in `#handleIncoming`.
1115
+ *
1116
+ * Error handling:
1117
+ * - Failure before `ready` resolves: reject all pending `subscribe`
1118
+ * promises whose filter isn't covered by the existing stream,
1119
+ * and keep the existing stream running for other subscriptions.
1120
+ * - Failure mid-pump on the active stream: close the thread via
1121
+ * {@link #failThreadWithError} so higher layers can rebind.
1122
+ */
1123
+ async #reconcileStream() {
1124
+ if (this.#closed) return;
1125
+ if (this.#rotationState === "rotating") return;
1126
+ const desired = this.#computeUnionFilter();
1127
+ if (desired == null) return;
1128
+ if (this.#sharedStreamFilter != null && filterEqual(desired, this.#sharedStreamFilter) && this.#pendingSubResolves.length === 0) {
1129
+ this.#resolvePending();
1130
+ return;
1131
+ }
1132
+ this.#rotationState = "rotating";
1133
+ let newHandle;
1134
+ try {
1135
+ newHandle = this.#transportAdapter.openEventStream(desired);
1136
+ } catch (err) {
1137
+ this.#rotationState = "idle";
1138
+ this.#rejectUncoveredPending(err);
1139
+ return;
1140
+ }
1141
+ try {
1142
+ await newHandle.ready;
1143
+ } catch (err) {
1144
+ this.#rotationState = "idle";
1145
+ try {
1146
+ newHandle.close();
1147
+ } catch {}
1148
+ this.#rejectUncoveredPending(err);
1149
+ return;
1150
+ }
1151
+ if (this.#closed) {
1152
+ try {
1153
+ newHandle.close();
1154
+ } catch {}
1155
+ this.#rotationState = "idle";
1156
+ return;
1157
+ }
1158
+ this.#pumpStream(newHandle);
1159
+ const oldHandle = this.#sharedStream;
1160
+ this.#sharedStream = newHandle;
1161
+ this.#sharedStreamFilter = desired;
1162
+ if (oldHandle != null) try {
1163
+ oldHandle.close();
1164
+ } catch {}
1165
+ this.#rotationState = "idle";
1166
+ this.#resolvePending();
1167
+ const next = this.#computeUnionFilter();
1168
+ if (next != null && !filterEqual(next, this.#sharedStreamFilter)) this.#scheduleReconcile();
1169
+ }
1170
+ /**
1171
+ * Pump events from a shared-stream handle into `#handleIncoming`.
1172
+ * One pump task runs per open stream; during rotation overlap two
1173
+ * pumps may be active briefly, with `#seenEventIds` deduping.
1174
+ */
1175
+ async #pumpStream(handle) {
1176
+ try {
1177
+ for await (const message of handle.events) {
1178
+ if (this.#closed) break;
1179
+ this.#handleIncoming(message);
1180
+ }
1181
+ } catch (err) {
1182
+ if (handle === this.#sharedStream && !this.#closed) this.#failThreadWithError(err);
1183
+ }
1184
+ }
1185
+ /**
1186
+ * Resolve any pending `subscribe()` promises whose filter is now
1187
+ * covered by the active shared stream. Called after every successful
1188
+ * rotation (and after no-op reconciliations).
1189
+ */
1190
+ #resolvePending() {
1191
+ if (this.#sharedStreamFilter == null) return;
1192
+ const current = this.#sharedStreamFilter;
1193
+ if (this.#pendingSubResolves.length === 0) return;
1194
+ const stillPending = [];
1195
+ for (const pending of this.#pendingSubResolves) if (filterCovers(current, pending.filter)) pending.resolve();
1196
+ else stillPending.push(pending);
1197
+ this.#pendingSubResolves.length = 0;
1198
+ this.#pendingSubResolves.push(...stillPending);
1199
+ }
1200
+ /**
1201
+ * Reject pending `subscribe()` promises whose filter isn't covered
1202
+ * by the existing stream (they're the ones that triggered the
1203
+ * failed rotation). Covered pending subs are resolved normally —
1204
+ * they didn't need the new stream.
1205
+ */
1206
+ #rejectUncoveredPending(err) {
1207
+ if (this.#pendingSubResolves.length === 0) return;
1208
+ const current = this.#sharedStreamFilter;
1209
+ const stillPending = [];
1210
+ for (const pending of this.#pendingSubResolves) if (current != null && filterCovers(current, pending.filter)) pending.resolve();
1211
+ else stillPending.push(pending);
1212
+ this.#pendingSubResolves.length = 0;
1213
+ for (const pending of stillPending) pending.reject(err);
1214
+ }
1215
+ /**
1216
+ * Terminate the thread due to an unrecoverable shared-stream error.
1217
+ * Rejects pending commands, closes subscriptions, and marks the
1218
+ * thread closed so no further rotations occur.
1219
+ */
1220
+ #failThreadWithError(err) {
1221
+ const normalized = err instanceof Error ? err : new Error(String(err));
1222
+ for (const pending of this.#pending.values()) pending.reject(normalized);
1223
+ this.#pending.clear();
1224
+ for (const pending of this.#pendingSubResolves) pending.reject(normalized);
1225
+ this.#pendingSubResolves.length = 0;
1226
+ for (const subscription of this.#subscriptions.values()) subscription.close();
1227
+ }
1228
+ /**
1229
+ * Command-based subscription (WebSocket fallback). The server replays
1230
+ * matching buffered events on subscribe via the same WebSocket stream.
1231
+ */
1232
+ async #subscribeViaCommand(params, transform) {
1233
+ const result = await this.#send("subscription.subscribe", params);
1234
+ const handle = new SubscriptionHandle(result.subscription_id, params, async (id) => {
1235
+ this.#subscriptions.delete(id);
1236
+ if (!this.#closed) await this.#send("subscription.unsubscribe", { subscription_id: id }).catch((err) => {
1237
+ if (err instanceof require_error.ProtocolError && err.code === "no_such_subscription") return;
1238
+ throw err;
1239
+ });
1240
+ }, transform);
1241
+ const subscription = Object.assign(handle, {
1242
+ filter: params,
1243
+ registeredAfterSeq: this.ordering.lastSeenSeq,
1244
+ seenEventIds: /* @__PURE__ */ new Set()
1245
+ });
1246
+ this.#subscriptions.set(result.subscription_id, subscription);
1247
+ return handle;
1248
+ }
1249
+ async #consumeEvents() {
1250
+ try {
1251
+ for await (const message of this.#transportAdapter.events()) this.#handleIncoming(message);
1252
+ for (const subscription of this.#subscriptions.values()) subscription.close();
1253
+ } catch (error) {
1254
+ const normalized = error instanceof Error ? error : new Error(String(error));
1255
+ for (const pending of this.#pending.values()) pending.reject(normalized);
1256
+ for (const subscription of this.#subscriptions.values()) subscription.close();
1257
+ this.#pending.clear();
1258
+ }
1259
+ }
1260
+ /**
1261
+ * Pause non-lifecycle subscriptions after a root terminal lifecycle.
1262
+ *
1263
+ * The pause is deferred one macrotask so same-run trailing events
1264
+ * emitted immediately after terminal (for example final `values`)
1265
+ * can still drain. `terminalSeq` lets replay attachers skip terminals
1266
+ * that happened before they registered, so late subscribers can keep
1267
+ * consuming the replayed history they joined for.
1268
+ */
1269
+ #scheduleTerminalPause(terminalSeq) {
1270
+ if (this.#terminalPauseTimer != null) clearTimeout(this.#terminalPauseTimer);
1271
+ this.#terminalPauseSeq = terminalSeq ?? null;
1272
+ this.#terminalPauseTimer = setTimeout(() => {
1273
+ this.#terminalPauseTimer = void 0;
1274
+ if (this.#closed) return;
1275
+ for (const [id, subscription] of this.#subscriptions) {
1276
+ if (id === this.#lifecycleSubId) continue;
1277
+ if (terminalSeq != null && subscription.registeredAfterSeq != null && subscription.registeredAfterSeq >= terminalSeq) continue;
1278
+ subscription.pause();
1279
+ }
1280
+ }, 0);
1281
+ }
1282
+ #handleIncoming(message) {
1283
+ if (message.type === "event") {
1284
+ if (typeof message.seq === "number") this.ordering.lastSeenSeq = maxSeq(this.ordering.lastSeenSeq, message.seq);
1285
+ if (message.event_id) this.ordering.lastEventId = message.event_id;
1286
+ const eventId = message.event_id ?? void 0;
1287
+ const globallyProcessed = eventId != null && this.#seenEventIds.has(eventId);
1288
+ if (eventId != null) this.#seenEventIds.add(eventId);
1289
+ const TERMINAL_LIFECYCLE_EVENTS = new Set([
1290
+ "interrupted",
1291
+ "completed",
1292
+ "failed"
1293
+ ]);
1294
+ if (!globallyProcessed) {
1295
+ this.#applyThreadLevelEffects(message);
1296
+ this.#fireOnEvent(message);
1297
+ }
1298
+ let fannedToAny = false;
1299
+ for (const subscription of this.#subscriptions.values()) {
1300
+ if (!require_subscription.matchesSubscription(message, subscription.filter)) continue;
1301
+ if (eventId != null) {
1302
+ if (subscription.seenEventIds.has(eventId)) continue;
1303
+ subscription.seenEventIds.add(eventId);
1304
+ }
1305
+ subscription.push(message);
1306
+ fannedToAny = true;
1307
+ }
1308
+ if (fannedToAny && this.#terminalPauseSeq !== void 0 && !(message.method === "lifecycle" && message.params.namespace.length === 0)) {
1309
+ const eventSeq = typeof message.seq === "number" ? message.seq : void 0;
1310
+ const terminalSeq = this.#terminalPauseSeq;
1311
+ if (terminalSeq === null || eventSeq == null || eventSeq > terminalSeq) {
1312
+ if (this.#terminalPauseTimer != null) {
1313
+ clearTimeout(this.#terminalPauseTimer);
1314
+ this.#terminalPauseTimer = void 0;
1315
+ }
1316
+ for (const [id, subscription] of this.#subscriptions) if (id !== this.#lifecycleSubId) subscription.resume();
1317
+ this.#scheduleTerminalPause(terminalSeq === null ? void 0 : terminalSeq);
1318
+ }
1319
+ }
1320
+ if (fannedToAny && message.method === "lifecycle" && message.params.namespace.length === 0 && TERMINAL_LIFECYCLE_EVENTS.has(message.params.data.event)) {
1321
+ if (message.params.data.event === "interrupted" && this.#headlessInterruptsAwaitingTerminal.size > 0) {
1322
+ this.#headlessInterruptsAwaitingTerminal.clear();
1323
+ return;
1324
+ }
1325
+ this.#scheduleTerminalPause(typeof message.seq === "number" ? message.seq : void 0);
1326
+ }
1327
+ return;
1328
+ }
1329
+ const messageId = typeof message.id === "number" ? message.id : void 0;
1330
+ const pending = messageId === void 0 ? void 0 : this.#pending.get(messageId);
1331
+ if (!pending) return;
1332
+ if (messageId !== void 0) this.#pending.delete(messageId);
1333
+ if (message.type === "error") {
1334
+ pending.reject(new require_error.ProtocolError(message));
1335
+ return;
1336
+ }
1337
+ if (typeof message.meta?.applied_through_seq === "number") this.ordering.lastAppliedThroughSeq = message.meta.applied_through_seq;
1338
+ pending.resolve(message);
1339
+ }
1340
+ async #send(method, params) {
1341
+ await this.#ensureOpen();
1342
+ const id = this.#nextCommandId++;
1343
+ const command = {
1344
+ id,
1345
+ method,
1346
+ params
1347
+ };
1348
+ const responsePromise = new Promise((resolve, reject) => {
1349
+ this.#pending.set(id, {
1350
+ resolve,
1351
+ reject
1352
+ });
1353
+ });
1354
+ const immediate = await this.#transportAdapter.send(command);
1355
+ if (immediate) {
1356
+ this.#pending.delete(id);
1357
+ if (immediate.type === "error") throw new require_error.ProtocolError(immediate);
1358
+ if (typeof immediate.meta?.applied_through_seq === "number") this.ordering.lastAppliedThroughSeq = immediate.meta.applied_through_seq;
1359
+ return immediate.result;
1360
+ }
1361
+ return (await responsePromise).result;
1362
+ }
1363
+ };
1364
+ //#endregion
1365
+ exports.SubscriptionHandle = SubscriptionHandle;
1366
+ exports.ThreadStream = ThreadStream;
1367
+
1368
+ //# sourceMappingURL=index.cjs.map