@langchain/langgraph-sdk 1.8.9 → 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 (444) 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 +8 -6
  212. package/dist/react/stream.lgp.cjs.map +1 -1
  213. package/dist/react/stream.lgp.js +6 -4
  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 +2 -2
  397. package/dist/ui/manager.cjs.map +1 -1
  398. package/dist/ui/manager.d.cts +1 -0
  399. package/dist/ui/manager.d.cts.map +1 -1
  400. package/dist/ui/manager.d.ts +1 -0
  401. package/dist/ui/manager.d.ts.map +1 -1
  402. package/dist/ui/manager.js +2 -2
  403. package/dist/ui/manager.js.map +1 -1
  404. package/dist/ui/messages.cjs +50 -7
  405. package/dist/ui/messages.cjs.map +1 -1
  406. package/dist/ui/messages.d.cts.map +1 -1
  407. package/dist/ui/messages.d.ts.map +1 -1
  408. package/dist/ui/messages.js +51 -9
  409. package/dist/ui/messages.js.map +1 -1
  410. package/dist/ui/orchestrator-custom.cjs +1 -1
  411. package/dist/ui/orchestrator-custom.js +1 -1
  412. package/dist/ui/orchestrator.cjs +4 -3
  413. package/dist/ui/orchestrator.cjs.map +1 -1
  414. package/dist/ui/orchestrator.d.cts +1 -1
  415. package/dist/ui/orchestrator.d.cts.map +1 -1
  416. package/dist/ui/orchestrator.d.ts +1 -1
  417. package/dist/ui/orchestrator.d.ts.map +1 -1
  418. package/dist/ui/orchestrator.js +4 -3
  419. package/dist/ui/orchestrator.js.map +1 -1
  420. package/dist/ui/stream/agent.d.cts +1 -1
  421. package/dist/ui/stream/agent.d.cts.map +1 -1
  422. package/dist/ui/stream/agent.d.ts +1 -1
  423. package/dist/ui/stream/agent.d.ts.map +1 -1
  424. package/dist/ui/stream/base.d.cts +7 -6
  425. package/dist/ui/stream/base.d.cts.map +1 -1
  426. package/dist/ui/stream/base.d.ts +7 -6
  427. package/dist/ui/stream/base.d.ts.map +1 -1
  428. package/dist/ui/stream/deep-agent.d.cts +1 -1
  429. package/dist/ui/stream/deep-agent.d.cts.map +1 -1
  430. package/dist/ui/stream/deep-agent.d.ts +1 -1
  431. package/dist/ui/stream/deep-agent.d.ts.map +1 -1
  432. package/dist/ui/stream/index.d.cts +4 -4
  433. package/dist/ui/stream/index.d.cts.map +1 -1
  434. package/dist/ui/stream/index.d.ts +4 -4
  435. package/dist/ui/stream/index.d.ts.map +1 -1
  436. package/dist/ui/types.d.cts +3 -2
  437. package/dist/ui/types.d.cts.map +1 -1
  438. package/dist/ui/types.d.ts +2 -1
  439. package/dist/ui/types.d.ts.map +1 -1
  440. package/package.json +18 -8
  441. package/dist/client.cjs.map +0 -1
  442. package/dist/client.d.cts.map +0 -1
  443. package/dist/client.d.ts.map +0 -1
  444. package/dist/client.js.map +0 -1
@@ -0,0 +1,506 @@
1
+ //#region src/client/stream/media.ts
2
+ const MEDIA_BLOCK_TYPES = new Set([
3
+ "audio",
4
+ "image",
5
+ "video",
6
+ "file"
7
+ ]);
8
+ /**
9
+ * Typed error thrown through `media.stream` / rejected from
10
+ * `media.blob` / `media.objectURL` when a handle fails before its
11
+ * message completes. Carries the bytes accumulated up to the failure
12
+ * point on `partialBytes` for callers that want to salvage or diagnose.
13
+ */
14
+ var MediaAssemblyError = class extends Error {
15
+ kind;
16
+ messageId;
17
+ partialBytes;
18
+ cause;
19
+ constructor(kind, messageId, partialBytes, message, options) {
20
+ super(message ?? `media ${kind} for message ${messageId}`);
21
+ this.name = "MediaAssemblyError";
22
+ this.kind = kind;
23
+ this.messageId = messageId;
24
+ this.partialBytes = partialBytes;
25
+ this.cause = options?.cause;
26
+ }
27
+ };
28
+ function base64ToBytes(b64) {
29
+ const binary = atob(b64);
30
+ const bytes = new Uint8Array(binary.length);
31
+ for (let i = 0; i < binary.length; i++) bytes[i] = binary.charCodeAt(i);
32
+ return bytes;
33
+ }
34
+ function concatBytes(parts, totalLength) {
35
+ const out = new Uint8Array(totalLength);
36
+ let offset = 0;
37
+ for (const part of parts) {
38
+ out.set(part, offset);
39
+ offset += part.byteLength;
40
+ }
41
+ return out;
42
+ }
43
+ /**
44
+ * Concrete handle implementation shared by all four media types.
45
+ *
46
+ * One instance per `(messageId, blockType)` pair created by the
47
+ * assembler on first matching `content-block-start`.
48
+ */
49
+ var MediaHandleImpl = class {
50
+ type;
51
+ messageId;
52
+ namespace;
53
+ node;
54
+ id;
55
+ mimeType;
56
+ url;
57
+ width;
58
+ height;
59
+ filename;
60
+ monotonic = true;
61
+ error;
62
+ #parts = [];
63
+ #totalBytes = 0;
64
+ #partialSnapshot = new Uint8Array(0);
65
+ #stream;
66
+ #streamController;
67
+ #blobResolve;
68
+ #blobReject;
69
+ #blobPromise;
70
+ #transcriptParts = [];
71
+ #transcriptResolve;
72
+ #transcriptReject;
73
+ #transcriptPromise;
74
+ #cachedObjectURL;
75
+ #urlSourced = false;
76
+ #urlFetchPromise;
77
+ #lastIndex = -1;
78
+ #finished = false;
79
+ #settled = false;
80
+ #fetchImpl;
81
+ constructor(options) {
82
+ this.type = options.type;
83
+ this.messageId = options.messageId;
84
+ this.namespace = options.namespace;
85
+ this.node = options.node;
86
+ this.id = options.id;
87
+ this.mimeType = options.mimeType;
88
+ this.url = options.url;
89
+ this.#fetchImpl = options.fetch;
90
+ this.#blobPromise = new Promise((resolve, reject) => {
91
+ this.#blobResolve = resolve;
92
+ this.#blobReject = reject;
93
+ });
94
+ this.#blobPromise.catch(() => void 0);
95
+ this.#transcriptPromise = new Promise((resolve, reject) => {
96
+ this.#transcriptResolve = resolve;
97
+ this.#transcriptReject = reject;
98
+ });
99
+ this.#transcriptPromise.catch(() => void 0);
100
+ }
101
+ /** Track a block index for the monotonic-ordering diagnostic. */
102
+ observeIndex(index) {
103
+ if (index !== this.#lastIndex + 1 && index !== this.#lastIndex) this.monotonic = false;
104
+ if (index > this.#lastIndex) this.#lastIndex = index;
105
+ }
106
+ /** Absorb `mime_type` / per-type extras carried on an incoming block. */
107
+ absorbBlock(block) {
108
+ if (this.#urlSourced) return;
109
+ if (block.type === "audio") this.#absorbAudio(block);
110
+ else if (block.type === "image") this.#absorbImage(block);
111
+ else if (block.type === "video") this.#absorbVideo(block);
112
+ else if (block.type === "file") this.#absorbFile(block);
113
+ }
114
+ /** Record that the originating block arrived with `url` not `data`. */
115
+ enterUrlMode(url) {
116
+ this.#urlSourced = true;
117
+ this.url = url;
118
+ }
119
+ /** Push a fresh chunk of bytes into the handle. */
120
+ pushBytes(bytes) {
121
+ if (this.#finished || this.#settled) return;
122
+ if (bytes.byteLength === 0) return;
123
+ this.#parts.push(bytes);
124
+ this.#totalBytes += bytes.byteLength;
125
+ this.#partialSnapshot = concatBytes(this.#parts, this.#totalBytes);
126
+ if (this.#streamController != null) try {
127
+ this.#streamController.enqueue(bytes);
128
+ } catch {}
129
+ }
130
+ /** Append a transcript fragment from an audio block. */
131
+ pushTranscript(fragment) {
132
+ if (this.type !== "audio") return;
133
+ if (this.#finished || this.#settled) return;
134
+ if (fragment.length === 0) return;
135
+ this.#transcriptParts.push(fragment);
136
+ }
137
+ /** Called on `message-finish`. Settles blob/transcript/stream. */
138
+ finish() {
139
+ if (this.#finished || this.#settled) return;
140
+ this.#finished = true;
141
+ this.#settled = true;
142
+ const blob = new Blob([this.#partialSnapshot], { type: this.mimeType ?? "" });
143
+ this.#blobResolve(blob);
144
+ this.#transcriptResolve(this.#transcriptParts.length === 0 ? void 0 : this.#transcriptParts.join(""));
145
+ try {
146
+ this.#streamController?.close();
147
+ } catch {}
148
+ }
149
+ /** Propagate an error through blob/transcript/stream. */
150
+ fail(kind, reason, cause) {
151
+ if (this.#settled) return this.error ?? new MediaAssemblyError(kind, this.messageId, this.#partialSnapshot, reason, { cause });
152
+ this.#settled = true;
153
+ const err = new MediaAssemblyError(kind, this.messageId, this.#partialSnapshot, reason, { cause });
154
+ this.error = err;
155
+ this.#blobReject(err);
156
+ this.#transcriptReject(err);
157
+ try {
158
+ this.#streamController?.error(err);
159
+ } catch {}
160
+ return err;
161
+ }
162
+ get partialBytes() {
163
+ return this.#partialSnapshot;
164
+ }
165
+ get blob() {
166
+ if (this.#urlSourced) return this.#fetchUrlSourced().then((bytes) => new Blob([bytes], { type: this.mimeType ?? "" }));
167
+ return this.#blobPromise;
168
+ }
169
+ get transcript() {
170
+ return this.#transcriptPromise;
171
+ }
172
+ get objectURL() {
173
+ if (this.#cachedObjectURL != null) {
174
+ const cached = this.#cachedObjectURL;
175
+ return Promise.resolve(cached);
176
+ }
177
+ return this.blob.then((blob) => {
178
+ if (this.#cachedObjectURL != null) return this.#cachedObjectURL;
179
+ const url = URL.createObjectURL(blob);
180
+ this.#cachedObjectURL = url;
181
+ return url;
182
+ });
183
+ }
184
+ revoke() {
185
+ const url = this.#cachedObjectURL;
186
+ if (url == null) return;
187
+ this.#cachedObjectURL = void 0;
188
+ try {
189
+ URL.revokeObjectURL(url);
190
+ } catch {}
191
+ }
192
+ get stream() {
193
+ if (this.#stream != null) return this.#stream;
194
+ if (this.#urlSourced) return this.#buildUrlStream();
195
+ return this.#buildInlineStream();
196
+ }
197
+ #absorbAudio(block) {
198
+ const mimeType = block.mime_type ?? block.mimeType;
199
+ if (this.mimeType == null && mimeType != null) this.mimeType = mimeType;
200
+ if (block.transcript != null && block.transcript.length > 0) this.pushTranscript(block.transcript);
201
+ }
202
+ #absorbImage(block) {
203
+ const mimeType = block.mime_type ?? block.mimeType;
204
+ if (this.mimeType == null && mimeType != null) this.mimeType = mimeType;
205
+ if (this.width == null && block.width != null) this.width = block.width;
206
+ if (this.height == null && block.height != null) this.height = block.height;
207
+ }
208
+ #absorbVideo(block) {
209
+ const mimeType = block.mime_type ?? block.mimeType;
210
+ if (this.mimeType == null && mimeType != null) this.mimeType = mimeType;
211
+ }
212
+ #absorbFile(block) {
213
+ const mimeType = block.mime_type ?? block.mimeType;
214
+ if (this.mimeType == null && mimeType != null) this.mimeType = mimeType;
215
+ if (this.filename == null && block.filename != null) this.filename = block.filename;
216
+ }
217
+ #buildInlineStream() {
218
+ const seed = this.#partialSnapshot;
219
+ const alreadyFinished = this.#finished;
220
+ const alreadyErrored = this.error;
221
+ this.#stream = new ReadableStream({
222
+ start: (controller) => {
223
+ this.#streamController = controller;
224
+ if (seed.byteLength > 0) controller.enqueue(seed);
225
+ if (alreadyErrored != null) {
226
+ controller.error(alreadyErrored);
227
+ return;
228
+ }
229
+ if (alreadyFinished) controller.close();
230
+ },
231
+ cancel: () => {
232
+ this.#streamController = void 0;
233
+ }
234
+ });
235
+ return this.#stream;
236
+ }
237
+ #buildUrlStream() {
238
+ const urlSourceFetch = this.#startUrlFetch();
239
+ this.#stream = new ReadableStream({
240
+ start: async (controller) => {
241
+ try {
242
+ const response = await urlSourceFetch;
243
+ if (response.body == null) {
244
+ const bytes = new Uint8Array(await response.arrayBuffer());
245
+ if (bytes.byteLength > 0) controller.enqueue(bytes);
246
+ controller.close();
247
+ return;
248
+ }
249
+ const reader = response.body.getReader();
250
+ while (true) {
251
+ const { done, value } = await reader.read();
252
+ if (done) break;
253
+ if (value != null) controller.enqueue(value);
254
+ }
255
+ controller.close();
256
+ } catch (err) {
257
+ controller.error(this.fail("fetch-failed", err?.message, err));
258
+ }
259
+ },
260
+ cancel: () => {
261
+ this.#streamController = void 0;
262
+ }
263
+ });
264
+ return this.#stream;
265
+ }
266
+ /** Memoised fetch for URL-sourced blocks — returns one `Response`. */
267
+ #startUrlFetch() {
268
+ const url = this.url;
269
+ return this.#fetchImpl(url).then((response) => {
270
+ if (!response.ok) throw new Error(`fetch(${url}) failed: ${response.status} ${response.statusText}`);
271
+ return response;
272
+ });
273
+ }
274
+ /** Fetch + buffer for URL-sourced `blob` access. Memoised. */
275
+ #fetchUrlSourced() {
276
+ if (this.#urlFetchPromise != null) return this.#urlFetchPromise;
277
+ this.#urlFetchPromise = (async () => {
278
+ try {
279
+ const response = await this.#startUrlFetch();
280
+ const bytes = new Uint8Array(await response.arrayBuffer());
281
+ this.#parts.length = 0;
282
+ this.#parts.push(bytes);
283
+ this.#totalBytes = bytes.byteLength;
284
+ this.#partialSnapshot = bytes;
285
+ this.#finished = true;
286
+ this.#settled = true;
287
+ return bytes;
288
+ } catch (err) {
289
+ throw this.fail("fetch-failed", err?.message, err);
290
+ }
291
+ })();
292
+ return this.#urlFetchPromise;
293
+ }
294
+ };
295
+ var MediaAssembler = class {
296
+ #callbacks;
297
+ #fetch;
298
+ #active = /* @__PURE__ */ new Map();
299
+ #activeByNamespaceNode = /* @__PURE__ */ new Map();
300
+ #syntheticCounter = 0;
301
+ constructor(options = {}) {
302
+ this.#callbacks = options;
303
+ if (options.fetch != null) this.#fetch = options.fetch;
304
+ else if (typeof fetch === "function") this.#fetch = fetch;
305
+ else this.#fetch = () => {
306
+ throw new Error("MediaAssembler: no fetch implementation available. Pass `fetch` in options.");
307
+ };
308
+ }
309
+ /**
310
+ * Fold a single `messages` event. Non-media blocks and
311
+ * informational events (e.g. `content-block-finish`) are no-ops.
312
+ */
313
+ consume(event) {
314
+ const data = event.params.data;
315
+ const namespace = event.params.namespace;
316
+ const node = event.params.node;
317
+ const nsNodeKey = `${namespace.join("/")}::${node ?? ""}`;
318
+ if (data.event === "message-start") {
319
+ this.#flushSlot(nsNodeKey, "finish");
320
+ this.#activeByNamespaceNode.set(nsNodeKey, {
321
+ messageId: data.id ?? "",
322
+ keys: /* @__PURE__ */ new Set(),
323
+ indexKeys: /* @__PURE__ */ new Map()
324
+ });
325
+ return;
326
+ }
327
+ if (data.event === "message-finish") {
328
+ this.#flushSlot(nsNodeKey, "finish");
329
+ this.#activeByNamespaceNode.delete(nsNodeKey);
330
+ return;
331
+ }
332
+ if (data.event === "error") {
333
+ this.#flushSlot(nsNodeKey, "error", data.message);
334
+ this.#activeByNamespaceNode.delete(nsNodeKey);
335
+ return;
336
+ }
337
+ if (data.event !== "content-block-start" && data.event !== "content-block-delta" && data.event !== "content-block-finish") return;
338
+ const block = data.content;
339
+ const blockIndex = data.index ?? 0;
340
+ let active = this.#activeByNamespaceNode.get(nsNodeKey);
341
+ if (active == null) {
342
+ active = {
343
+ messageId: `__synthetic_${++this.#syntheticCounter}`,
344
+ keys: /* @__PURE__ */ new Set(),
345
+ indexKeys: /* @__PURE__ */ new Map()
346
+ };
347
+ this.#activeByNamespaceNode.set(nsNodeKey, active);
348
+ }
349
+ if (block == null && data.event === "content-block-delta") {
350
+ const delta = data.delta;
351
+ const deltaKey = active.indexKeys.get(blockIndex);
352
+ const deltaHandle = deltaKey != null ? this.#active.get(deltaKey) : void 0;
353
+ if (delta == null || typeof delta !== "object") return;
354
+ const record = delta;
355
+ if (deltaHandle == null) {
356
+ if (record.type !== "block-delta" || record.fields == null || typeof record.fields !== "object") return;
357
+ const fields = record.fields;
358
+ if (!MEDIA_BLOCK_TYPES.has(fields.type)) return;
359
+ this.#consumeMediaBlock({
360
+ active,
361
+ block: fields,
362
+ blockIndex,
363
+ dataEvent: data.event,
364
+ namespace,
365
+ node,
366
+ terminal: false,
367
+ createIfMissing: true
368
+ });
369
+ return;
370
+ }
371
+ deltaHandle.observeIndex(blockIndex);
372
+ if (record.type === "data-delta" && typeof record.data === "string") {
373
+ try {
374
+ deltaHandle.pushBytes(base64ToBytes(record.data));
375
+ } catch (err) {
376
+ deltaHandle.fail("message-error", "invalid base64 on delta", err);
377
+ }
378
+ return;
379
+ }
380
+ if (record.type === "block-delta" && record.fields != null && typeof record.fields === "object") {
381
+ const fields = record.fields;
382
+ deltaHandle.absorbBlock(fields);
383
+ if (!deltaHandle.error && fields.data != null) try {
384
+ deltaHandle.pushBytes(base64ToBytes(fields.data));
385
+ } catch (err) {
386
+ deltaHandle.fail("message-error", "invalid base64 on delta", err);
387
+ }
388
+ }
389
+ return;
390
+ }
391
+ if (block == null) return;
392
+ const blockType = block.type;
393
+ if (!MEDIA_BLOCK_TYPES.has(blockType)) return;
394
+ this.#consumeMediaBlock({
395
+ active,
396
+ block,
397
+ blockIndex,
398
+ dataEvent: data.event,
399
+ namespace,
400
+ node,
401
+ terminal: data.event === "content-block-finish",
402
+ createIfMissing: data.event === "content-block-start" || data.event === "content-block-finish"
403
+ });
404
+ }
405
+ #consumeMediaBlock({ active, block, blockIndex, dataEvent, namespace, node, terminal, createIfMissing }) {
406
+ const blockType = block.type;
407
+ if (!MEDIA_BLOCK_TYPES.has(blockType)) return;
408
+ const mediaType = blockType;
409
+ const key = `${active.messageId}::${mediaType}::${blockIndex}`;
410
+ let handle = this.#active.get(key);
411
+ const isStart = dataEvent === "content-block-start";
412
+ if (handle == null) {
413
+ const isTerminalBlock = terminal;
414
+ if (!isStart && !isTerminalBlock && !createIfMissing) return;
415
+ const mediaBlock = block;
416
+ handle = new MediaHandleImpl({
417
+ type: mediaType,
418
+ messageId: active.messageId,
419
+ namespace: [...namespace],
420
+ node,
421
+ id: mediaBlock.id,
422
+ mimeType: mediaBlock.mime_type ?? mediaBlock.mimeType,
423
+ url: mediaBlock.url != null && mediaBlock.data == null ? mediaBlock.url : void 0,
424
+ fetch: this.#fetch
425
+ });
426
+ if (mediaBlock.url != null && mediaBlock.data == null) handle.enterUrlMode(mediaBlock.url);
427
+ handle.observeIndex(blockIndex);
428
+ handle.absorbBlock(block);
429
+ if (mediaBlock.data != null) try {
430
+ handle.pushBytes(base64ToBytes(mediaBlock.data));
431
+ } catch (err) {
432
+ handle.fail("message-error", "invalid base64 on initial block", err);
433
+ }
434
+ this.#active.set(key, handle);
435
+ active.keys.add(key);
436
+ active.indexKeys.set(blockIndex, key);
437
+ this.#emit(handle);
438
+ if (isTerminalBlock) {
439
+ handle.finish();
440
+ this.#active.delete(key);
441
+ active.keys.delete(key);
442
+ active.indexKeys.delete(blockIndex);
443
+ }
444
+ return;
445
+ }
446
+ if (terminal) return;
447
+ const mediaBlock = block;
448
+ handle.observeIndex(blockIndex);
449
+ handle.absorbBlock(block);
450
+ if (!handle.error && mediaBlock.data != null) try {
451
+ handle.pushBytes(base64ToBytes(mediaBlock.data));
452
+ } catch (err) {
453
+ handle.fail("message-error", "invalid base64 on delta", err);
454
+ }
455
+ }
456
+ /**
457
+ * Finish or fail every media handle currently active under the
458
+ * given `(namespace, node)` slot and clear its bookkeeping. Called
459
+ * on `message-finish`, `error`, and when a new `message-start`
460
+ * rebinds a still-open slot.
461
+ */
462
+ #flushSlot(nsNodeKey, mode, errorMessage) {
463
+ const active = this.#activeByNamespaceNode.get(nsNodeKey);
464
+ if (active == null) return;
465
+ for (const key of active.keys) {
466
+ const handle = this.#active.get(key);
467
+ if (handle != null) if (mode === "finish") handle.finish();
468
+ else handle.fail("message-error", errorMessage);
469
+ this.#active.delete(key);
470
+ }
471
+ active.keys.clear();
472
+ active.indexKeys.clear();
473
+ }
474
+ /**
475
+ * Abort all outstanding handles with a `stream-closed` error.
476
+ * Called when the upstream event source terminates before the
477
+ * messages it was assembling had a chance to finish.
478
+ */
479
+ close() {
480
+ for (const handle of this.#active.values()) handle.fail("stream-closed", "upstream event stream closed");
481
+ this.#active.clear();
482
+ this.#activeByNamespaceNode.clear();
483
+ }
484
+ #emit(handle) {
485
+ switch (handle.type) {
486
+ case "audio":
487
+ this.#callbacks.onAudio?.(handle);
488
+ break;
489
+ case "image":
490
+ this.#callbacks.onImage?.(handle);
491
+ break;
492
+ case "video":
493
+ this.#callbacks.onVideo?.(handle);
494
+ break;
495
+ case "file":
496
+ this.#callbacks.onFile?.(handle);
497
+ break;
498
+ }
499
+ this.#callbacks.onMedia?.(handle);
500
+ }
501
+ };
502
+ //#endregion
503
+ exports.MediaAssembler = MediaAssembler;
504
+ exports.MediaAssemblyError = MediaAssemblyError;
505
+
506
+ //# sourceMappingURL=media.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"media.cjs","names":["#parts","#blobPromise","#transcriptPromise","#fetchImpl","#blobResolve","#blobReject","#transcriptResolve","#transcriptReject","#lastIndex","#urlSourced","#absorbAudio","#absorbImage","#absorbVideo","#absorbFile","#finished","#settled","#totalBytes","#partialSnapshot","#streamController","#transcriptParts","#fetchUrlSourced","#cachedObjectURL","#stream","#buildUrlStream","#buildInlineStream","#startUrlFetch","#urlFetchPromise","#callbacks","#fetch","#active","#activeByNamespaceNode","#flushSlot","#syntheticCounter","#consumeMediaBlock","#emit"],"sources":["../../../src/client/stream/media.ts"],"sourcesContent":["import type {\n AudioContentBlock,\n ContentBlock,\n FileContentBlock,\n ImageContentBlock,\n MessagesEvent,\n VideoContentBlock,\n} from \"@langchain/protocol\";\n\n/**\n * Block types this assembler knows how to reassemble into media handles.\n */\nexport type MediaBlockType = \"audio\" | \"image\" | \"video\" | \"file\";\n\nconst MEDIA_BLOCK_TYPES: ReadonlySet<string> = new Set<MediaBlockType>([\n \"audio\",\n \"image\",\n \"video\",\n \"file\",\n]);\n\n/**\n * Kinds of failure that can terminate a media handle prematurely.\n *\n * - `\"message-error\"` — the upstream message emitted an `error` event\n * before completion.\n * - `\"stream-closed\"` — the transport stream closed before\n * `message-finish` arrived (thread closed, transport dropped, etc.).\n * - `\"fetch-failed\"` — the block was `url`-sourced and the lazy\n * `fetch()` rejected (CORS, 404, 5xx, network).\n */\nexport type MediaAssemblyErrorKind =\n | \"message-error\"\n | \"stream-closed\"\n | \"fetch-failed\";\n\n/**\n * Typed error thrown through `media.stream` / rejected from\n * `media.blob` / `media.objectURL` when a handle fails before its\n * message completes. Carries the bytes accumulated up to the failure\n * point on `partialBytes` for callers that want to salvage or diagnose.\n */\nexport class MediaAssemblyError extends Error {\n readonly kind: MediaAssemblyErrorKind;\n readonly messageId: string;\n readonly partialBytes: Uint8Array;\n // oxlint-disable-next-line typescript/no-explicit-any\n readonly cause?: unknown;\n\n constructor(\n kind: MediaAssemblyErrorKind,\n messageId: string,\n partialBytes: Uint8Array,\n message?: string,\n options?: { cause?: unknown }\n ) {\n super(message ?? `media ${kind} for message ${messageId}`);\n this.name = \"MediaAssemblyError\";\n this.kind = kind;\n this.messageId = messageId;\n this.partialBytes = partialBytes;\n this.cause = options?.cause;\n }\n}\n\n/**\n * Shared surface across every media handle returned by\n * {@link MediaAssembler}.\n *\n * The handle is live while its parent message is active:\n * - `partialBytes` is a snapshot of all bytes received so far.\n * - `stream` is a lazy, single-consumer byte stream (see\n * accessor docstring).\n * - `blob` / `objectURL` settle on `message-finish`.\n * - `error` becomes set if the handle terminates in any of the\n * {@link MediaAssemblyErrorKind} failure modes.\n */\nexport interface MediaBase {\n readonly messageId: string;\n readonly namespace: string[];\n readonly node?: string;\n /** `id` from the originating content block, if the provider sent one. */\n readonly id?: string;\n readonly mimeType?: string;\n /**\n * Present iff the originating block carried `url` (not `data`).\n * When set, `blob` / `stream` / `objectURL` lazily fetch from here\n * on first access.\n */\n readonly url?: string;\n\n /**\n * Live byte stream.\n *\n * Lazy: not materialised unless accessed. On first access the\n * stream is seeded with every byte already accumulated\n * (`partialBytes`) and then wired to future chunks. For URL-sourced\n * blocks, first access triggers `fetch()` and pipes the response\n * body through.\n *\n * Repeated access returns the same {@link ReadableStream} reference\n * — you can safely read it once, release the lock, and re-acquire a\n * reader later (e.g. React StrictMode effect re-invokes). The\n * standard `ReadableStream.locked` semantics prevent concurrent\n * readers; use `stream.tee()` when you truly need multiple live\n * consumers.\n */\n readonly stream: ReadableStream<Uint8Array>;\n\n /** Resolves on `message-finish` with the concatenated {@link Blob}. */\n readonly blob: Promise<Blob>;\n\n /**\n * Lazy {@link URL.createObjectURL} over {@link blob}. Cached: first\n * access creates the URL, subsequent accesses return the same one.\n * Call {@link revoke} to free the URL slot; the next access creates\n * a fresh URL. `ThreadStream.close()` auto-revokes as a safety net.\n */\n readonly objectURL: Promise<string>;\n\n /** Live view of accumulated bytes. Settles with final bytes on finish. */\n readonly partialBytes: Uint8Array;\n\n /** Set iff the handle settled in an error state. */\n readonly error?: MediaAssemblyError;\n\n /** Diagnostic: `false` if block indices arrived out of order. */\n readonly monotonic: boolean;\n\n /**\n * Revoke the currently-cached object URL (if any). Subsequent\n * accesses to {@link objectURL} create a fresh URL from the Blob.\n * Idempotent.\n */\n revoke(): void;\n}\n\nexport interface AudioMedia extends MediaBase {\n readonly type: \"audio\";\n /**\n * Concatenated transcript across every audio block in this message.\n * Resolves on `message-finish` with the joined string, or `undefined`\n * when no block carried a transcript.\n */\n readonly transcript: Promise<string | undefined>;\n}\n\nexport interface ImageMedia extends MediaBase {\n readonly type: \"image\";\n /** Pixel width, if the provider sent it on the originating block. */\n readonly width?: number;\n /** Pixel height, if the provider sent it on the originating block. */\n readonly height?: number;\n}\n\nexport interface VideoMedia extends MediaBase {\n readonly type: \"video\";\n}\n\nexport interface FileMedia extends MediaBase {\n readonly type: \"file\";\n /** File name hint, if the provider sent it on the originating block. */\n readonly filename?: string;\n}\n\nexport type AnyMediaHandle = AudioMedia | ImageMedia | VideoMedia | FileMedia;\n\nfunction base64ToBytes(b64: string): Uint8Array {\n // atob is standard in all modern browsers and Node >= 16. Works on\n // standard base64 only (no `-`/`_` URL-safe variants; the protocol\n // uses standard base64).\n const binary = atob(b64);\n const bytes = new Uint8Array(binary.length);\n for (let i = 0; i < binary.length; i++) bytes[i] = binary.charCodeAt(i);\n return bytes;\n}\n\nfunction concatBytes(parts: Uint8Array[], totalLength: number): Uint8Array {\n const out = new Uint8Array(totalLength);\n let offset = 0;\n for (const part of parts) {\n out.set(part, offset);\n offset += part.byteLength;\n }\n return out;\n}\n\n/**\n * Concrete handle implementation shared by all four media types.\n *\n * One instance per `(messageId, blockType)` pair created by the\n * assembler on first matching `content-block-start`.\n */\nclass MediaHandleImpl {\n readonly type: MediaBlockType;\n readonly messageId: string;\n readonly namespace: string[];\n readonly node: string | undefined;\n readonly id: string | undefined;\n\n mimeType: string | undefined;\n url: string | undefined;\n width?: number;\n height?: number;\n filename?: string;\n\n monotonic = true;\n error: MediaAssemblyError | undefined;\n\n // Byte accumulation --------------------------------------------------\n\n readonly #parts: Uint8Array[] = [];\n #totalBytes = 0;\n #partialSnapshot: Uint8Array = new Uint8Array(0);\n\n // Stream (lazy, idempotent getter) ----------------------------------\n //\n // First access creates the `ReadableStream` and wires it to future\n // chunks; subsequent accesses return the SAME reference. Consumers\n // that want to fan-out must call `.tee()` explicitly — the native\n // `ReadableStream.locked` flag prevents two concurrent readers.\n\n #stream: ReadableStream<Uint8Array> | undefined;\n #streamController: ReadableStreamDefaultController<Uint8Array> | undefined;\n\n // Blob / URL settlement ---------------------------------------------\n\n #blobResolve!: (value: Blob) => void;\n #blobReject!: (reason: unknown) => void;\n readonly #blobPromise: Promise<Blob>;\n\n #transcriptParts: string[] = [];\n #transcriptResolve!: (value: string | undefined) => void;\n #transcriptReject!: (reason: unknown) => void;\n readonly #transcriptPromise: Promise<string | undefined>;\n\n #cachedObjectURL: string | undefined;\n\n // URL-sourced mode ---------------------------------------------------\n\n #urlSourced = false;\n #urlFetchPromise: Promise<Uint8Array> | undefined;\n\n // Index tracking -----------------------------------------------------\n\n #lastIndex = -1;\n\n // Lifecycle flags ----------------------------------------------------\n\n #finished = false;\n #settled = false;\n\n // Injected dependencies ---------------------------------------------\n\n readonly #fetchImpl: typeof fetch;\n\n constructor(options: {\n type: MediaBlockType;\n messageId: string;\n namespace: string[];\n node: string | undefined;\n id: string | undefined;\n mimeType: string | undefined;\n url: string | undefined;\n fetch: typeof fetch;\n }) {\n this.type = options.type;\n this.messageId = options.messageId;\n this.namespace = options.namespace;\n this.node = options.node;\n this.id = options.id;\n this.mimeType = options.mimeType;\n this.url = options.url;\n this.#fetchImpl = options.fetch;\n\n this.#blobPromise = new Promise<Blob>((resolve, reject) => {\n this.#blobResolve = resolve;\n this.#blobReject = reject;\n });\n // Swallow rejections here so the async promise doesn't surface as\n // an unhandled rejection when callers never touch `.blob`. Any\n // consumer that does await it still observes the original reason.\n this.#blobPromise.catch(() => undefined);\n\n this.#transcriptPromise = new Promise<string | undefined>(\n (resolve, reject) => {\n this.#transcriptResolve = resolve;\n this.#transcriptReject = reject;\n }\n );\n this.#transcriptPromise.catch(() => undefined);\n }\n\n // ---------- Input side (driven by the assembler) ----------\n\n /** Track a block index for the monotonic-ordering diagnostic. */\n observeIndex(index: number): void {\n if (index !== this.#lastIndex + 1 && index !== this.#lastIndex) {\n this.monotonic = false;\n }\n if (index > this.#lastIndex) this.#lastIndex = index;\n }\n\n /** Absorb `mime_type` / per-type extras carried on an incoming block. */\n absorbBlock(block: ContentBlock): void {\n if (this.#urlSourced) return;\n // `Extensible` widens `block.type` from a literal to `string` in\n // the union, defeating TS's discriminated-union narrowing. Cast\n // after the runtime tag check.\n if (block.type === \"audio\") this.#absorbAudio(block as AudioContentBlock);\n else if (block.type === \"image\")\n this.#absorbImage(block as ImageContentBlock);\n else if (block.type === \"video\")\n this.#absorbVideo(block as VideoContentBlock);\n else if (block.type === \"file\") this.#absorbFile(block as FileContentBlock);\n }\n\n /** Record that the originating block arrived with `url` not `data`. */\n enterUrlMode(url: string): void {\n this.#urlSourced = true;\n this.url = url;\n }\n\n /** Push a fresh chunk of bytes into the handle. */\n pushBytes(bytes: Uint8Array): void {\n if (this.#finished || this.#settled) return;\n if (bytes.byteLength === 0) return;\n this.#parts.push(bytes);\n this.#totalBytes += bytes.byteLength;\n this.#partialSnapshot = concatBytes(this.#parts, this.#totalBytes);\n if (this.#streamController != null) {\n try {\n this.#streamController.enqueue(bytes);\n } catch {\n // Reader detached; ignore — `partialBytes`/`blob` still work.\n }\n }\n }\n\n /** Append a transcript fragment from an audio block. */\n pushTranscript(fragment: string): void {\n if (this.type !== \"audio\") return;\n if (this.#finished || this.#settled) return;\n if (fragment.length === 0) return;\n this.#transcriptParts.push(fragment);\n }\n\n /** Called on `message-finish`. Settles blob/transcript/stream. */\n finish(): void {\n if (this.#finished || this.#settled) return;\n this.#finished = true;\n this.#settled = true;\n // Cast: the lib types reject `Uint8Array<ArrayBufferLike>` because\n // `BlobPart` requires `Uint8Array<ArrayBuffer>` specifically. Our\n // accumulator is allocated with `new Uint8Array(len)`, so it is\n // backed by an `ArrayBuffer` (not `SharedArrayBuffer`).\n const blob = new Blob([this.#partialSnapshot as unknown as BlobPart], {\n type: this.mimeType ?? \"\",\n });\n this.#blobResolve(blob);\n this.#transcriptResolve(\n this.#transcriptParts.length === 0\n ? undefined\n : this.#transcriptParts.join(\"\")\n );\n try {\n this.#streamController?.close();\n } catch {\n // Reader may have detached already.\n }\n }\n\n /** Propagate an error through blob/transcript/stream. */\n fail(\n kind: MediaAssemblyErrorKind,\n reason?: string,\n cause?: unknown\n ): MediaAssemblyError {\n if (this.#settled) {\n return (\n this.error ??\n new MediaAssemblyError(\n kind,\n this.messageId,\n this.#partialSnapshot,\n reason,\n { cause }\n )\n );\n }\n this.#settled = true;\n const err = new MediaAssemblyError(\n kind,\n this.messageId,\n this.#partialSnapshot,\n reason,\n { cause }\n );\n this.error = err;\n this.#blobReject(err);\n this.#transcriptReject(err);\n try {\n this.#streamController?.error(err);\n } catch {\n // Reader may have detached already.\n }\n return err;\n }\n\n // ---------- Public surface read by consumers ----------\n\n get partialBytes(): Uint8Array {\n return this.#partialSnapshot;\n }\n\n get blob(): Promise<Blob> {\n if (this.#urlSourced)\n return this.#fetchUrlSourced().then(\n (bytes) =>\n new Blob([bytes as unknown as BlobPart], {\n type: this.mimeType ?? \"\",\n })\n );\n return this.#blobPromise;\n }\n\n get transcript(): Promise<string | undefined> {\n return this.#transcriptPromise;\n }\n\n get objectURL(): Promise<string> {\n if (this.#cachedObjectURL != null) {\n const cached = this.#cachedObjectURL;\n return Promise.resolve(cached);\n }\n return this.blob.then((blob) => {\n // Race-safe: if revoke() fired before we got here, we cache the\n // freshly-created URL for the next reader.\n if (this.#cachedObjectURL != null) return this.#cachedObjectURL;\n const url = URL.createObjectURL(blob);\n this.#cachedObjectURL = url;\n return url;\n });\n }\n\n revoke(): void {\n const url = this.#cachedObjectURL;\n if (url == null) return;\n this.#cachedObjectURL = undefined;\n try {\n URL.revokeObjectURL(url);\n } catch {\n // URL.revokeObjectURL is side-effect-only; very unlikely to throw\n // but keep the handle usable if a polyfill misbehaves.\n }\n }\n\n get stream(): ReadableStream<Uint8Array> {\n if (this.#stream != null) return this.#stream;\n if (this.#urlSourced) return this.#buildUrlStream();\n return this.#buildInlineStream();\n }\n\n // ---------- Internals ----------\n\n #absorbAudio(block: AudioContentBlock): void {\n const mimeType =\n block.mime_type ?? (block as { mimeType?: string }).mimeType;\n if (this.mimeType == null && mimeType != null) this.mimeType = mimeType;\n if (block.transcript != null && block.transcript.length > 0) {\n this.pushTranscript(block.transcript);\n }\n }\n\n #absorbImage(block: ImageContentBlock): void {\n const mimeType =\n block.mime_type ?? (block as { mimeType?: string }).mimeType;\n if (this.mimeType == null && mimeType != null) this.mimeType = mimeType;\n if (this.width == null && block.width != null) this.width = block.width;\n if (this.height == null && block.height != null) this.height = block.height;\n }\n\n #absorbVideo(block: VideoContentBlock): void {\n const mimeType =\n block.mime_type ?? (block as { mimeType?: string }).mimeType;\n if (this.mimeType == null && mimeType != null) this.mimeType = mimeType;\n }\n\n #absorbFile(block: FileContentBlock): void {\n const mimeType =\n block.mime_type ?? (block as { mimeType?: string }).mimeType;\n if (this.mimeType == null && mimeType != null) this.mimeType = mimeType;\n if (this.filename == null && block.filename != null)\n this.filename = block.filename;\n }\n\n #buildInlineStream(): ReadableStream<Uint8Array> {\n const seed = this.#partialSnapshot;\n const alreadyFinished = this.#finished;\n const alreadyErrored = this.error;\n\n this.#stream = new ReadableStream<Uint8Array>({\n start: (controller) => {\n this.#streamController = controller;\n if (seed.byteLength > 0) controller.enqueue(seed);\n if (alreadyErrored != null) {\n controller.error(alreadyErrored);\n return;\n }\n if (alreadyFinished) {\n controller.close();\n }\n },\n cancel: () => {\n this.#streamController = undefined;\n },\n });\n return this.#stream;\n }\n\n #buildUrlStream(): ReadableStream<Uint8Array> {\n // For URL-sourced blocks, we pipe the fetch response body directly\n // through. `partialBytes` / `blob` share the same buffered bytes via\n // #fetchUrlSourced().\n const urlSourceFetch = this.#startUrlFetch();\n this.#stream = new ReadableStream<Uint8Array>({\n start: async (controller) => {\n try {\n const response = await urlSourceFetch;\n if (response.body == null) {\n const bytes = new Uint8Array(await response.arrayBuffer());\n if (bytes.byteLength > 0) controller.enqueue(bytes);\n controller.close();\n return;\n }\n const reader = response.body.getReader();\n // oxlint-disable-next-line no-constant-condition\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n if (value != null) controller.enqueue(value);\n }\n controller.close();\n } catch (err) {\n controller.error(\n this.fail(\"fetch-failed\", (err as Error)?.message, err)\n );\n }\n },\n cancel: () => {\n this.#streamController = undefined;\n },\n });\n return this.#stream;\n }\n\n /** Memoised fetch for URL-sourced blocks — returns one `Response`. */\n #startUrlFetch(): Promise<Response> {\n const url = this.url!;\n return this.#fetchImpl(url).then((response) => {\n if (!response.ok) {\n throw new Error(\n `fetch(${url}) failed: ${response.status} ${response.statusText}`\n );\n }\n return response;\n });\n }\n\n /** Fetch + buffer for URL-sourced `blob` access. Memoised. */\n #fetchUrlSourced(): Promise<Uint8Array> {\n if (this.#urlFetchPromise != null) return this.#urlFetchPromise;\n this.#urlFetchPromise = (async () => {\n try {\n const response = await this.#startUrlFetch();\n const bytes = new Uint8Array(await response.arrayBuffer());\n this.#parts.length = 0;\n this.#parts.push(bytes);\n this.#totalBytes = bytes.byteLength;\n this.#partialSnapshot = bytes;\n this.#finished = true;\n this.#settled = true;\n return bytes;\n } catch (err) {\n throw this.fail(\"fetch-failed\", (err as Error)?.message, err);\n }\n })();\n return this.#urlFetchPromise;\n }\n}\n\n/**\n * Dispatch callbacks receive a freshly-started handle on its first\n * matching `content-block-start`. Exactly one callback fires per\n * `(messageId, blockType)` pair.\n */\nexport interface MediaAssemblerCallbacks {\n onAudio?: (media: AudioMedia) => void;\n onImage?: (media: ImageMedia) => void;\n onVideo?: (media: VideoMedia) => void;\n onFile?: (media: FileMedia) => void;\n /**\n * Invoked for every type; receives the same handle as the typed\n * callback. Useful for writing one \"all media\" consumer without\n * registering four type-specific callbacks.\n */\n onMedia?: (media: AnyMediaHandle) => void;\n}\n\nexport interface MediaAssemblerOptions extends MediaAssemblerCallbacks {\n /**\n * Injected `fetch` used for URL-sourced blocks. Defaults to the\n * global `fetch`. Throws on first URL access if neither is present.\n */\n fetch?: typeof fetch;\n}\n\n/**\n * Incrementally folds `messages` events into typed media handles\n * (audio / image / video / file) that buffer bytes, expose a\n * {@link Blob}, and lazily mint an object URL for direct use in\n * `<audio>` / `<img>` / `<video>` tags.\n *\n * Semantics pinned during design:\n * - One handle per `(messageId, blockType)` pair. Mixed-type messages\n * surface on multiple iterables with the same `messageId`.\n * - Handle yielded on the **first matching `content-block-start`** —\n * messages with no matching blocks never yield an item (filters\n * `lc_run--` LangChain terminator noise automatically).\n * - Byte extraction: every `content-block-start` /\n * `content-block-delta` with a `data` field decodes base64 and\n * pushes into the accumulator. `content-block-finish` is a sync\n * point.\n * - URL-sourced blocks: if the initial block carries `url`, the\n * handle enters URL mode — `blob`/`stream`/`objectURL` lazy-fetch\n * on first access, subsequent data/url deltas are ignored.\n * - Fail loud: `message-error`, stream closure before finish, and\n * fetch failures all populate `handle.error`, reject `blob` /\n * `transcript` / `objectURL`, and error the stream.\n * - Diagnostic only: `handle.monotonic` flips false if block indices\n * arrive out of order (protocol guarantees in-order within a\n * subscription, so `false` indicates an upstream bug).\n */\n/**\n * Per-`(namespace, node)` bookkeeping for the active message the\n * assembler is currently folding.\n *\n * Protocol v2 only carries `id` on `message-start`; all\n * subsequent `content-block-*` / `message-finish` / `error` events\n * address the active message by position (same namespace + node). The\n * assembler therefore pins a message entry when `message-start`\n * arrives and resolves follow-ups by looking up `(namespace, node)`.\n */\ninterface ActiveMessage {\n /** `id` from `message-start`, or empty string when synthesized. */\n messageId: string;\n /** `${messageId}::${mediaType}::${index}` keys currently active under this message. */\n keys: Set<string>;\n /** Content-block index → active media key. */\n indexKeys: Map<number, string>;\n}\n\nexport class MediaAssembler {\n readonly #callbacks: MediaAssemblerCallbacks;\n readonly #fetch: typeof fetch;\n // Keyed by `${messageId}::${type}::${blockIndex}`.\n readonly #active = new Map<string, MediaHandleImpl>();\n // Maps `${namespace.join(\"/\")}::${node ?? \"\"}` → active message. One\n // entry per in-flight logical message; replaced on each\n // `message-start`, removed on `message-finish` / `error`.\n readonly #activeByNamespaceNode = new Map<string, ActiveMessage>();\n // Monotonically increasing counter used to mint stable synthetic\n // ids when a `content-block-*` arrives before any `message-start`\n // (e.g. late-attaching subscribers that missed the message-start).\n #syntheticCounter = 0;\n\n constructor(options: MediaAssemblerOptions = {}) {\n this.#callbacks = options;\n if (options.fetch != null) {\n this.#fetch = options.fetch;\n } else if (typeof fetch === \"function\") {\n this.#fetch = fetch;\n } else {\n // Throw lazily on URL access rather than construction, so\n // inline-only flows in Node without a global fetch still work.\n this.#fetch = () => {\n throw new Error(\n \"MediaAssembler: no fetch implementation available. Pass `fetch` in options.\"\n );\n };\n }\n }\n\n /**\n * Fold a single `messages` event. Non-media blocks and\n * informational events (e.g. `content-block-finish`) are no-ops.\n */\n consume(event: MessagesEvent): void {\n const data = event.params.data;\n const namespace = event.params.namespace;\n const node = event.params.node;\n const nsNodeKey = `${namespace.join(\"/\")}::${node ?? \"\"}`;\n\n if (data.event === \"message-start\") {\n // A new `message-start` may arrive before a prior message on\n // the same `(namespace, node)` emitted `message-finish` (the\n // protocol permits trimmed replays on late subscribers). Flush\n // any in-flight handles under that slot before rebinding.\n this.#flushSlot(nsNodeKey, \"finish\");\n this.#activeByNamespaceNode.set(nsNodeKey, {\n messageId: data.id ?? \"\",\n keys: new Set(),\n indexKeys: new Map(),\n });\n return;\n }\n\n if (data.event === \"message-finish\") {\n this.#flushSlot(nsNodeKey, \"finish\");\n this.#activeByNamespaceNode.delete(nsNodeKey);\n return;\n }\n\n if (data.event === \"error\") {\n this.#flushSlot(\n nsNodeKey,\n \"error\",\n (data as { message?: string }).message\n );\n this.#activeByNamespaceNode.delete(nsNodeKey);\n return;\n }\n\n if (\n data.event !== \"content-block-start\" &&\n data.event !== \"content-block-delta\" &&\n data.event !== \"content-block-finish\"\n ) {\n return;\n }\n\n const block = (data as { content?: ContentBlock; index?: number }).content;\n const blockIndex = (data as { index?: number }).index ?? 0;\n\n // Resolve the active message for this `(namespace, node)`. If the\n // subscriber attached mid-message and missed `message-start`,\n // synthesize one so downstream blocks still produce a handle.\n let active = this.#activeByNamespaceNode.get(nsNodeKey);\n if (active == null) {\n active = {\n messageId: `__synthetic_${++this.#syntheticCounter}`,\n keys: new Set(),\n indexKeys: new Map(),\n };\n this.#activeByNamespaceNode.set(nsNodeKey, active);\n }\n\n if (block == null && data.event === \"content-block-delta\") {\n const delta = (data as { delta?: unknown }).delta;\n const deltaKey = active.indexKeys.get(blockIndex);\n const deltaHandle =\n deltaKey != null ? this.#active.get(deltaKey) : undefined;\n if (delta == null || typeof delta !== \"object\") {\n return;\n }\n\n const record = delta as Record<string, unknown>;\n\n if (deltaHandle == null) {\n if (\n record.type !== \"block-delta\" ||\n record.fields == null ||\n typeof record.fields !== \"object\"\n ) {\n return;\n }\n\n const fields = record.fields as ContentBlock;\n if (!MEDIA_BLOCK_TYPES.has(fields.type)) {\n return;\n }\n\n this.#consumeMediaBlock({\n active,\n block: fields,\n blockIndex,\n dataEvent: data.event,\n namespace,\n node,\n terminal: false,\n createIfMissing: true,\n });\n return;\n }\n\n deltaHandle.observeIndex(blockIndex);\n if (record.type === \"data-delta\" && typeof record.data === \"string\") {\n try {\n deltaHandle.pushBytes(base64ToBytes(record.data));\n } catch (err) {\n deltaHandle.fail(\"message-error\", \"invalid base64 on delta\", err);\n }\n return;\n }\n\n if (\n record.type === \"block-delta\" &&\n record.fields != null &&\n typeof record.fields === \"object\"\n ) {\n const fields = record.fields as\n | AudioContentBlock\n | ImageContentBlock\n | VideoContentBlock\n | FileContentBlock;\n deltaHandle.absorbBlock(fields);\n if (!deltaHandle.error && fields.data != null) {\n try {\n deltaHandle.pushBytes(base64ToBytes(fields.data));\n } catch (err) {\n deltaHandle.fail(\"message-error\", \"invalid base64 on delta\", err);\n }\n }\n }\n return;\n }\n\n if (block == null) return;\n const blockType = block.type;\n if (!MEDIA_BLOCK_TYPES.has(blockType)) return;\n\n this.#consumeMediaBlock({\n active,\n block: block as ContentBlock,\n blockIndex,\n dataEvent: data.event,\n namespace,\n node,\n terminal: data.event === \"content-block-finish\",\n createIfMissing:\n data.event === \"content-block-start\" ||\n data.event === \"content-block-finish\",\n });\n }\n\n #consumeMediaBlock({\n active,\n block,\n blockIndex,\n dataEvent,\n namespace,\n node,\n terminal,\n createIfMissing,\n }: {\n active: ActiveMessage;\n block: ContentBlock;\n blockIndex: number;\n dataEvent: string;\n namespace: string[];\n node: string | undefined;\n terminal: boolean;\n createIfMissing: boolean;\n }): void {\n const blockType = block.type;\n if (!MEDIA_BLOCK_TYPES.has(blockType)) return;\n\n const mediaType = blockType as MediaBlockType;\n const key = `${active.messageId}::${mediaType}::${blockIndex}`;\n let handle = this.#active.get(key);\n const isStart = dataEvent === \"content-block-start\";\n\n if (handle == null) {\n const isTerminalBlock = terminal;\n if (!isStart && !isTerminalBlock && !createIfMissing) {\n return;\n }\n const mediaBlock = block as\n | AudioContentBlock\n | ImageContentBlock\n | VideoContentBlock\n | FileContentBlock;\n handle = new MediaHandleImpl({\n type: mediaType,\n messageId: active.messageId,\n namespace: [...namespace],\n node,\n id: (mediaBlock as { id?: string }).id,\n mimeType:\n mediaBlock.mime_type ??\n (mediaBlock as { mimeType?: string }).mimeType,\n url:\n mediaBlock.url != null && mediaBlock.data == null\n ? mediaBlock.url\n : undefined,\n fetch: this.#fetch,\n });\n if (mediaBlock.url != null && mediaBlock.data == null) {\n handle.enterUrlMode(mediaBlock.url);\n }\n handle.observeIndex(blockIndex);\n handle.absorbBlock(block);\n if (mediaBlock.data != null) {\n try {\n handle.pushBytes(base64ToBytes(mediaBlock.data));\n } catch (err) {\n handle.fail(\"message-error\", \"invalid base64 on initial block\", err);\n }\n }\n this.#active.set(key, handle);\n active.keys.add(key);\n active.indexKeys.set(blockIndex, key);\n this.#emit(handle);\n if (isTerminalBlock) {\n handle.finish();\n this.#active.delete(key);\n active.keys.delete(key);\n active.indexKeys.delete(blockIndex);\n }\n return;\n }\n\n // Subsequent event on an existing handle.\n // - `content-block-finish` is a sync point: skip to avoid\n // double-counting bytes when the server echoes the full block\n // on both start and finish (typical for atomic, non-delta\n // blocks such as whole audio frames or single-shot images).\n // A late subscriber may miss `content-block-start`; in that case a\n // terminal block with full content is handled above by creating and\n // immediately settling a one-block handle.\n if (terminal) return;\n\n const mediaBlock = block as\n | AudioContentBlock\n | ImageContentBlock\n | VideoContentBlock\n | FileContentBlock;\n handle.observeIndex(blockIndex);\n handle.absorbBlock(block);\n if (!handle.error && mediaBlock.data != null) {\n try {\n handle.pushBytes(base64ToBytes(mediaBlock.data));\n } catch (err) {\n handle.fail(\"message-error\", \"invalid base64 on delta\", err);\n }\n }\n }\n\n /**\n * Finish or fail every media handle currently active under the\n * given `(namespace, node)` slot and clear its bookkeeping. Called\n * on `message-finish`, `error`, and when a new `message-start`\n * rebinds a still-open slot.\n */\n #flushSlot(\n nsNodeKey: string,\n mode: \"finish\" | \"error\",\n errorMessage?: string\n ): void {\n const active = this.#activeByNamespaceNode.get(nsNodeKey);\n if (active == null) return;\n for (const key of active.keys) {\n const handle = this.#active.get(key);\n if (handle != null) {\n if (mode === \"finish\") handle.finish();\n else handle.fail(\"message-error\", errorMessage);\n }\n this.#active.delete(key);\n }\n active.keys.clear();\n active.indexKeys.clear();\n }\n\n /**\n * Abort all outstanding handles with a `stream-closed` error.\n * Called when the upstream event source terminates before the\n * messages it was assembling had a chance to finish.\n */\n close(): void {\n for (const handle of this.#active.values()) {\n handle.fail(\"stream-closed\", \"upstream event stream closed\");\n }\n this.#active.clear();\n this.#activeByNamespaceNode.clear();\n }\n\n #emit(handle: MediaHandleImpl): void {\n switch (handle.type) {\n case \"audio\":\n this.#callbacks.onAudio?.(handle as unknown as AudioMedia);\n break;\n case \"image\":\n this.#callbacks.onImage?.(handle as unknown as ImageMedia);\n break;\n case \"video\":\n this.#callbacks.onVideo?.(handle as unknown as VideoMedia);\n break;\n case \"file\":\n this.#callbacks.onFile?.(handle as unknown as FileMedia);\n break;\n }\n this.#callbacks.onMedia?.(handle as unknown as AnyMediaHandle);\n }\n}\n"],"mappings":"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"}