@langchain/langgraph-sdk 1.8.10 → 1.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (435) hide show
  1. package/README.md +90 -43
  2. package/dist/client/assistants/index.cjs +180 -0
  3. package/dist/client/assistants/index.cjs.map +1 -0
  4. package/dist/client/assistants/index.d.cts +155 -0
  5. package/dist/client/assistants/index.d.cts.map +1 -0
  6. package/dist/client/assistants/index.d.ts +155 -0
  7. package/dist/client/assistants/index.d.ts.map +1 -0
  8. package/dist/client/assistants/index.js +180 -0
  9. package/dist/client/assistants/index.js.map +1 -0
  10. package/dist/client/base.cjs +190 -0
  11. package/dist/client/base.cjs.map +1 -0
  12. package/dist/client/base.d.cts +84 -0
  13. package/dist/client/base.d.cts.map +1 -0
  14. package/dist/client/base.d.ts +84 -0
  15. package/dist/client/base.d.ts.map +1 -0
  16. package/dist/client/base.js +188 -0
  17. package/dist/client/base.js.map +1 -0
  18. package/dist/client/crons/index.cjs +159 -0
  19. package/dist/client/crons/index.cjs.map +1 -0
  20. package/dist/client/crons/index.d.cts +71 -0
  21. package/dist/client/crons/index.d.cts.map +1 -0
  22. package/dist/client/crons/index.d.ts +71 -0
  23. package/dist/client/crons/index.d.ts.map +1 -0
  24. package/dist/client/crons/index.js +159 -0
  25. package/dist/client/crons/index.js.map +1 -0
  26. package/dist/client/index.cjs +84 -0
  27. package/dist/client/index.cjs.map +1 -0
  28. package/dist/client/index.d.cts +63 -0
  29. package/dist/client/index.d.cts.map +1 -0
  30. package/dist/client/index.d.ts +63 -0
  31. package/dist/client/index.d.ts.map +1 -0
  32. package/dist/client/index.js +83 -0
  33. package/dist/client/index.js.map +1 -0
  34. package/dist/client/runs/index.cjs +275 -0
  35. package/dist/client/runs/index.cjs.map +1 -0
  36. package/dist/client/runs/index.d.cts +123 -0
  37. package/dist/client/runs/index.d.cts.map +1 -0
  38. package/dist/client/runs/index.d.ts +123 -0
  39. package/dist/client/runs/index.d.ts.map +1 -0
  40. package/dist/client/runs/index.js +275 -0
  41. package/dist/client/runs/index.js.map +1 -0
  42. package/dist/client/store/index.cjs +128 -0
  43. package/dist/client/store/index.cjs.map +1 -0
  44. package/dist/client/store/index.d.cts +75 -0
  45. package/dist/client/store/index.d.cts.map +1 -0
  46. package/dist/client/store/index.d.ts +75 -0
  47. package/dist/client/store/index.d.ts.map +1 -0
  48. package/dist/client/store/index.js +128 -0
  49. package/dist/client/store/index.js.map +1 -0
  50. package/dist/client/stream/error.cjs +18 -0
  51. package/dist/client/stream/error.cjs.map +1 -0
  52. package/dist/client/stream/error.d.cts +14 -0
  53. package/dist/client/stream/error.d.cts.map +1 -0
  54. package/dist/client/stream/error.d.ts +14 -0
  55. package/dist/client/stream/error.d.ts.map +1 -0
  56. package/dist/client/stream/error.js +18 -0
  57. package/dist/client/stream/error.js.map +1 -0
  58. package/dist/client/stream/handles/index.cjs +3 -0
  59. package/dist/client/stream/handles/index.d.ts +3 -0
  60. package/dist/client/stream/handles/index.js +4 -0
  61. package/dist/client/stream/handles/subagents.cjs +263 -0
  62. package/dist/client/stream/handles/subagents.cjs.map +1 -0
  63. package/dist/client/stream/handles/subagents.d.cts +45 -0
  64. package/dist/client/stream/handles/subagents.d.cts.map +1 -0
  65. package/dist/client/stream/handles/subagents.d.ts +45 -0
  66. package/dist/client/stream/handles/subagents.d.ts.map +1 -0
  67. package/dist/client/stream/handles/subagents.js +262 -0
  68. package/dist/client/stream/handles/subagents.js.map +1 -0
  69. package/dist/client/stream/handles/subgraphs.cjs +352 -0
  70. package/dist/client/stream/handles/subgraphs.cjs.map +1 -0
  71. package/dist/client/stream/handles/subgraphs.d.cts +82 -0
  72. package/dist/client/stream/handles/subgraphs.d.cts.map +1 -0
  73. package/dist/client/stream/handles/subgraphs.d.ts +82 -0
  74. package/dist/client/stream/handles/subgraphs.d.ts.map +1 -0
  75. package/dist/client/stream/handles/subgraphs.js +351 -0
  76. package/dist/client/stream/handles/subgraphs.js.map +1 -0
  77. package/dist/client/stream/handles/tools.cjs +92 -0
  78. package/dist/client/stream/handles/tools.cjs.map +1 -0
  79. package/dist/client/stream/handles/tools.d.cts +26 -0
  80. package/dist/client/stream/handles/tools.d.cts.map +1 -0
  81. package/dist/client/stream/handles/tools.d.ts +26 -0
  82. package/dist/client/stream/handles/tools.d.ts.map +1 -0
  83. package/dist/client/stream/handles/tools.js +92 -0
  84. package/dist/client/stream/handles/tools.js.map +1 -0
  85. package/dist/client/stream/index.cjs +1368 -0
  86. package/dist/client/stream/index.cjs.map +1 -0
  87. package/dist/client/stream/index.d.cts +238 -0
  88. package/dist/client/stream/index.d.cts.map +1 -0
  89. package/dist/client/stream/index.d.ts +238 -0
  90. package/dist/client/stream/index.d.ts.map +1 -0
  91. package/dist/client/stream/index.js +1367 -0
  92. package/dist/client/stream/index.js.map +1 -0
  93. package/dist/client/stream/media.cjs +506 -0
  94. package/dist/client/stream/media.cjs.map +1 -0
  95. package/dist/client/stream/media.d.cts +164 -0
  96. package/dist/client/stream/media.d.cts.map +1 -0
  97. package/dist/client/stream/media.d.ts +164 -0
  98. package/dist/client/stream/media.d.ts.map +1 -0
  99. package/dist/client/stream/media.js +505 -0
  100. package/dist/client/stream/media.js.map +1 -0
  101. package/dist/client/stream/messages.cjs +635 -0
  102. package/dist/client/stream/messages.cjs.map +1 -0
  103. package/dist/client/stream/messages.d.cts +139 -0
  104. package/dist/client/stream/messages.d.cts.map +1 -0
  105. package/dist/client/stream/messages.d.ts +139 -0
  106. package/dist/client/stream/messages.d.ts.map +1 -0
  107. package/dist/client/stream/messages.js +631 -0
  108. package/dist/client/stream/messages.js.map +1 -0
  109. package/dist/client/stream/multi-cursor-buffer.cjs +55 -0
  110. package/dist/client/stream/multi-cursor-buffer.cjs.map +1 -0
  111. package/dist/client/stream/multi-cursor-buffer.js +55 -0
  112. package/dist/client/stream/multi-cursor-buffer.js.map +1 -0
  113. package/dist/client/stream/subscription.cjs +85 -0
  114. package/dist/client/stream/subscription.cjs.map +1 -0
  115. package/dist/client/stream/subscription.d.cts +22 -0
  116. package/dist/client/stream/subscription.d.cts.map +1 -0
  117. package/dist/client/stream/subscription.d.ts +22 -0
  118. package/dist/client/stream/subscription.d.ts.map +1 -0
  119. package/dist/client/stream/subscription.js +84 -0
  120. package/dist/client/stream/subscription.js.map +1 -0
  121. package/dist/client/stream/transport/agent-server.cjs +45 -0
  122. package/dist/client/stream/transport/agent-server.cjs.map +1 -0
  123. package/dist/client/stream/transport/agent-server.d.cts +39 -0
  124. package/dist/client/stream/transport/agent-server.d.cts.map +1 -0
  125. package/dist/client/stream/transport/agent-server.d.ts +39 -0
  126. package/dist/client/stream/transport/agent-server.d.ts.map +1 -0
  127. package/dist/client/stream/transport/agent-server.js +45 -0
  128. package/dist/client/stream/transport/agent-server.js.map +1 -0
  129. package/dist/client/stream/transport/constants.cjs +10 -0
  130. package/dist/client/stream/transport/constants.cjs.map +1 -0
  131. package/dist/client/stream/transport/constants.js +10 -0
  132. package/dist/client/stream/transport/constants.js.map +1 -0
  133. package/dist/client/stream/transport/decoder.cjs +115 -0
  134. package/dist/client/stream/transport/decoder.cjs.map +1 -0
  135. package/dist/client/stream/transport/decoder.js +114 -0
  136. package/dist/client/stream/transport/decoder.js.map +1 -0
  137. package/dist/client/stream/transport/http.cjs +183 -0
  138. package/dist/client/stream/transport/http.cjs.map +1 -0
  139. package/dist/client/stream/transport/http.d.cts +45 -0
  140. package/dist/client/stream/transport/http.d.cts.map +1 -0
  141. package/dist/client/stream/transport/http.d.ts +45 -0
  142. package/dist/client/stream/transport/http.d.ts.map +1 -0
  143. package/dist/client/stream/transport/http.js +183 -0
  144. package/dist/client/stream/transport/http.js.map +1 -0
  145. package/dist/client/stream/transport/index.cjs +3 -0
  146. package/dist/client/stream/transport/index.js +4 -0
  147. package/dist/client/stream/transport/queue.cjs +55 -0
  148. package/dist/client/stream/transport/queue.cjs.map +1 -0
  149. package/dist/client/stream/transport/queue.js +55 -0
  150. package/dist/client/stream/transport/queue.js.map +1 -0
  151. package/dist/client/stream/transport/stream.cjs +79 -0
  152. package/dist/client/stream/transport/stream.cjs.map +1 -0
  153. package/dist/client/stream/transport/stream.js +79 -0
  154. package/dist/client/stream/transport/stream.js.map +1 -0
  155. package/dist/client/stream/transport/types.d.cts +29 -0
  156. package/dist/client/stream/transport/types.d.cts.map +1 -0
  157. package/dist/client/stream/transport/types.d.ts +29 -0
  158. package/dist/client/stream/transport/types.d.ts.map +1 -0
  159. package/dist/client/stream/transport/utils.cjs +45 -0
  160. package/dist/client/stream/transport/utils.cjs.map +1 -0
  161. package/dist/client/stream/transport/utils.js +39 -0
  162. package/dist/client/stream/transport/utils.js.map +1 -0
  163. package/dist/client/stream/transport/websocket.cjs +155 -0
  164. package/dist/client/stream/transport/websocket.cjs.map +1 -0
  165. package/dist/client/stream/transport/websocket.d.cts +36 -0
  166. package/dist/client/stream/transport/websocket.d.cts.map +1 -0
  167. package/dist/client/stream/transport/websocket.d.ts +36 -0
  168. package/dist/client/stream/transport/websocket.d.ts.map +1 -0
  169. package/dist/client/stream/transport/websocket.js +155 -0
  170. package/dist/client/stream/transport/websocket.js.map +1 -0
  171. package/dist/client/stream/transport.d.cts +104 -0
  172. package/dist/client/stream/transport.d.cts.map +1 -0
  173. package/dist/client/stream/transport.d.ts +104 -0
  174. package/dist/client/stream/transport.d.ts.map +1 -0
  175. package/dist/client/stream/types.d.cts +208 -0
  176. package/dist/client/stream/types.d.cts.map +1 -0
  177. package/dist/client/stream/types.d.ts +208 -0
  178. package/dist/client/stream/types.d.ts.map +1 -0
  179. package/dist/client/threads/index.cjs +271 -0
  180. package/dist/client/threads/index.cjs.map +1 -0
  181. package/dist/client/threads/index.d.cts +235 -0
  182. package/dist/client/threads/index.d.cts.map +1 -0
  183. package/dist/client/threads/index.d.ts +235 -0
  184. package/dist/client/threads/index.d.ts.map +1 -0
  185. package/dist/client/threads/index.js +270 -0
  186. package/dist/client/threads/index.js.map +1 -0
  187. package/dist/client/ui-internal/index.cjs +29 -0
  188. package/dist/client/ui-internal/index.cjs.map +1 -0
  189. package/dist/client/ui-internal/index.d.cts +11 -0
  190. package/dist/client/ui-internal/index.d.cts.map +1 -0
  191. package/dist/client/ui-internal/index.d.ts +11 -0
  192. package/dist/client/ui-internal/index.d.ts.map +1 -0
  193. package/dist/client/ui-internal/index.js +29 -0
  194. package/dist/client/ui-internal/index.js.map +1 -0
  195. package/dist/client.cjs +35 -1308
  196. package/dist/client.d.cts +19 -857
  197. package/dist/client.d.ts +19 -857
  198. package/dist/client.js +16 -1301
  199. package/dist/index.cjs +25 -4
  200. package/dist/index.d.cts +15 -3
  201. package/dist/index.d.ts +15 -3
  202. package/dist/index.js +14 -3
  203. package/dist/react/stream.cjs.map +1 -1
  204. package/dist/react/stream.custom.cjs +1 -1
  205. package/dist/react/stream.custom.js +1 -1
  206. package/dist/react/stream.d.cts +2 -1
  207. package/dist/react/stream.d.cts.map +1 -1
  208. package/dist/react/stream.d.ts +2 -1
  209. package/dist/react/stream.d.ts.map +1 -1
  210. package/dist/react/stream.js.map +1 -1
  211. package/dist/react/stream.lgp.cjs +6 -5
  212. package/dist/react/stream.lgp.cjs.map +1 -1
  213. package/dist/react/stream.lgp.js +4 -3
  214. package/dist/react/stream.lgp.js.map +1 -1
  215. package/dist/react/types.d.cts +1 -1
  216. package/dist/react/types.d.ts +1 -1
  217. package/dist/react/types.d.ts.map +1 -1
  218. package/dist/react-ui/server/server.cjs +1 -1
  219. package/dist/react-ui/server/server.cjs.map +1 -1
  220. package/dist/react-ui/server/server.js +1 -1
  221. package/dist/react-ui/server/server.js.map +1 -1
  222. package/dist/react-ui/types.cjs.map +1 -1
  223. package/dist/react-ui/types.d.cts +1 -1
  224. package/dist/react-ui/types.d.cts.map +1 -1
  225. package/dist/react-ui/types.d.ts +1 -1
  226. package/dist/react-ui/types.d.ts.map +1 -1
  227. package/dist/react-ui/types.js.map +1 -1
  228. package/dist/stream/assembled-to-message.cjs +121 -0
  229. package/dist/stream/assembled-to-message.cjs.map +1 -0
  230. package/dist/stream/assembled-to-message.d.cts +35 -0
  231. package/dist/stream/assembled-to-message.d.cts.map +1 -0
  232. package/dist/stream/assembled-to-message.d.ts +35 -0
  233. package/dist/stream/assembled-to-message.d.ts.map +1 -0
  234. package/dist/stream/assembled-to-message.js +119 -0
  235. package/dist/stream/assembled-to-message.js.map +1 -0
  236. package/dist/stream/channel-registry.cjs +224 -0
  237. package/dist/stream/channel-registry.cjs.map +1 -0
  238. package/dist/stream/channel-registry.d.cts +102 -0
  239. package/dist/stream/channel-registry.d.cts.map +1 -0
  240. package/dist/stream/channel-registry.d.ts +102 -0
  241. package/dist/stream/channel-registry.d.ts.map +1 -0
  242. package/dist/stream/channel-registry.js +224 -0
  243. package/dist/stream/channel-registry.js.map +1 -0
  244. package/dist/stream/constants.cjs +11 -0
  245. package/dist/stream/constants.cjs.map +1 -0
  246. package/dist/stream/constants.d.cts +10 -0
  247. package/dist/stream/constants.d.cts.map +1 -0
  248. package/dist/stream/constants.d.ts +10 -0
  249. package/dist/stream/constants.d.ts.map +1 -0
  250. package/dist/stream/constants.js +11 -0
  251. package/dist/stream/constants.js.map +1 -0
  252. package/dist/stream/controller.cjs +933 -0
  253. package/dist/stream/controller.cjs.map +1 -0
  254. package/dist/stream/controller.d.cts +135 -0
  255. package/dist/stream/controller.d.cts.map +1 -0
  256. package/dist/stream/controller.d.ts +135 -0
  257. package/dist/stream/controller.d.ts.map +1 -0
  258. package/dist/stream/controller.js +910 -0
  259. package/dist/stream/controller.js.map +1 -0
  260. package/dist/stream/discovery/index.d.ts +2 -0
  261. package/dist/stream/discovery/subagents.cjs +235 -0
  262. package/dist/stream/discovery/subagents.cjs.map +1 -0
  263. package/dist/stream/discovery/subagents.d.cts +18 -0
  264. package/dist/stream/discovery/subagents.d.cts.map +1 -0
  265. package/dist/stream/discovery/subagents.d.ts +18 -0
  266. package/dist/stream/discovery/subagents.d.ts.map +1 -0
  267. package/dist/stream/discovery/subagents.js +235 -0
  268. package/dist/stream/discovery/subagents.js.map +1 -0
  269. package/dist/stream/discovery/subgraphs.cjs +153 -0
  270. package/dist/stream/discovery/subgraphs.cjs.map +1 -0
  271. package/dist/stream/discovery/subgraphs.d.cts +19 -0
  272. package/dist/stream/discovery/subgraphs.d.cts.map +1 -0
  273. package/dist/stream/discovery/subgraphs.d.ts +19 -0
  274. package/dist/stream/discovery/subgraphs.d.ts.map +1 -0
  275. package/dist/stream/discovery/subgraphs.js +153 -0
  276. package/dist/stream/discovery/subgraphs.js.map +1 -0
  277. package/dist/stream/index.cjs +36 -0
  278. package/dist/stream/index.d.cts +25 -0
  279. package/dist/stream/index.d.ts +25 -0
  280. package/dist/stream/index.js +16 -0
  281. package/dist/stream/lifecycle-loading-tracker.cjs +83 -0
  282. package/dist/stream/lifecycle-loading-tracker.cjs.map +1 -0
  283. package/dist/stream/lifecycle-loading-tracker.js +83 -0
  284. package/dist/stream/lifecycle-loading-tracker.js.map +1 -0
  285. package/dist/stream/message-metadata-tracker.cjs +165 -0
  286. package/dist/stream/message-metadata-tracker.cjs.map +1 -0
  287. package/dist/stream/message-metadata-tracker.d.cts +24 -0
  288. package/dist/stream/message-metadata-tracker.d.cts.map +1 -0
  289. package/dist/stream/message-metadata-tracker.d.ts +24 -0
  290. package/dist/stream/message-metadata-tracker.d.ts.map +1 -0
  291. package/dist/stream/message-metadata-tracker.js +165 -0
  292. package/dist/stream/message-metadata-tracker.js.map +1 -0
  293. package/dist/stream/message-reconciliation.cjs +118 -0
  294. package/dist/stream/message-reconciliation.cjs.map +1 -0
  295. package/dist/stream/message-reconciliation.js +115 -0
  296. package/dist/stream/message-reconciliation.js.map +1 -0
  297. package/dist/stream/namespace.cjs +54 -0
  298. package/dist/stream/namespace.cjs.map +1 -0
  299. package/dist/stream/namespace.js +49 -0
  300. package/dist/stream/namespace.js.map +1 -0
  301. package/dist/stream/projections/channel.cjs +53 -0
  302. package/dist/stream/projections/channel.cjs.map +1 -0
  303. package/dist/stream/projections/channel.d.cts +22 -0
  304. package/dist/stream/projections/channel.d.cts.map +1 -0
  305. package/dist/stream/projections/channel.d.ts +22 -0
  306. package/dist/stream/projections/channel.d.ts.map +1 -0
  307. package/dist/stream/projections/channel.js +53 -0
  308. package/dist/stream/projections/channel.js.map +1 -0
  309. package/dist/stream/projections/extension.cjs +29 -0
  310. package/dist/stream/projections/extension.cjs.map +1 -0
  311. package/dist/stream/projections/extension.d.cts +7 -0
  312. package/dist/stream/projections/extension.d.cts.map +1 -0
  313. package/dist/stream/projections/extension.d.ts +7 -0
  314. package/dist/stream/projections/extension.d.ts.map +1 -0
  315. package/dist/stream/projections/extension.js +29 -0
  316. package/dist/stream/projections/extension.js.map +1 -0
  317. package/dist/stream/projections/index.cjs +6 -0
  318. package/dist/stream/projections/index.d.ts +6 -0
  319. package/dist/stream/projections/index.js +7 -0
  320. package/dist/stream/projections/media.cjs +81 -0
  321. package/dist/stream/projections/media.cjs.map +1 -0
  322. package/dist/stream/projections/media.d.cts +18 -0
  323. package/dist/stream/projections/media.d.cts.map +1 -0
  324. package/dist/stream/projections/media.d.ts +18 -0
  325. package/dist/stream/projections/media.d.ts.map +1 -0
  326. package/dist/stream/projections/media.js +78 -0
  327. package/dist/stream/projections/media.js.map +1 -0
  328. package/dist/stream/projections/messages.cjs +121 -0
  329. package/dist/stream/projections/messages.cjs.map +1 -0
  330. package/dist/stream/projections/messages.d.cts +8 -0
  331. package/dist/stream/projections/messages.d.cts.map +1 -0
  332. package/dist/stream/projections/messages.d.ts +8 -0
  333. package/dist/stream/projections/messages.d.ts.map +1 -0
  334. package/dist/stream/projections/messages.js +121 -0
  335. package/dist/stream/projections/messages.js.map +1 -0
  336. package/dist/stream/projections/runtime.cjs +44 -0
  337. package/dist/stream/projections/runtime.cjs.map +1 -0
  338. package/dist/stream/projections/runtime.js +44 -0
  339. package/dist/stream/projections/runtime.js.map +1 -0
  340. package/dist/stream/projections/tool-calls.cjs +50 -0
  341. package/dist/stream/projections/tool-calls.cjs.map +1 -0
  342. package/dist/stream/projections/tool-calls.d.cts +8 -0
  343. package/dist/stream/projections/tool-calls.d.cts.map +1 -0
  344. package/dist/stream/projections/tool-calls.d.ts +8 -0
  345. package/dist/stream/projections/tool-calls.d.ts.map +1 -0
  346. package/dist/stream/projections/tool-calls.js +50 -0
  347. package/dist/stream/projections/tool-calls.js.map +1 -0
  348. package/dist/stream/projections/values.cjs +52 -0
  349. package/dist/stream/projections/values.cjs.map +1 -0
  350. package/dist/stream/projections/values.d.cts +7 -0
  351. package/dist/stream/projections/values.d.cts.map +1 -0
  352. package/dist/stream/projections/values.d.ts +6 -0
  353. package/dist/stream/projections/values.d.ts.map +1 -0
  354. package/dist/stream/projections/values.js +52 -0
  355. package/dist/stream/projections/values.js.map +1 -0
  356. package/dist/stream/root-message-projection.cjs +256 -0
  357. package/dist/stream/root-message-projection.cjs.map +1 -0
  358. package/dist/stream/root-message-projection.js +256 -0
  359. package/dist/stream/root-message-projection.js.map +1 -0
  360. package/dist/stream/store.cjs +32 -0
  361. package/dist/stream/store.cjs.map +1 -0
  362. package/dist/stream/store.d.cts +37 -0
  363. package/dist/stream/store.d.cts.map +1 -0
  364. package/dist/stream/store.d.ts +37 -0
  365. package/dist/stream/store.d.ts.map +1 -0
  366. package/dist/stream/store.js +32 -0
  367. package/dist/stream/store.js.map +1 -0
  368. package/dist/stream/submit-coordinator.cjs +399 -0
  369. package/dist/stream/submit-coordinator.cjs.map +1 -0
  370. package/dist/stream/submit-coordinator.d.cts +27 -0
  371. package/dist/stream/submit-coordinator.d.cts.map +1 -0
  372. package/dist/stream/submit-coordinator.d.ts +27 -0
  373. package/dist/stream/submit-coordinator.d.ts.map +1 -0
  374. package/dist/stream/submit-coordinator.js +397 -0
  375. package/dist/stream/submit-coordinator.js.map +1 -0
  376. package/dist/stream/tool-calls.cjs +15 -0
  377. package/dist/stream/tool-calls.cjs.map +1 -0
  378. package/dist/stream/tool-calls.js +15 -0
  379. package/dist/stream/tool-calls.js.map +1 -0
  380. package/dist/stream/types-inference.d.cts +43 -0
  381. package/dist/stream/types-inference.d.cts.map +1 -0
  382. package/dist/stream/types-inference.d.ts +43 -0
  383. package/dist/stream/types-inference.d.ts.map +1 -0
  384. package/dist/stream/types.d.cts +354 -0
  385. package/dist/stream/types.d.cts.map +1 -0
  386. package/dist/stream/types.d.ts +354 -0
  387. package/dist/stream/types.d.ts.map +1 -0
  388. package/dist/types.d.cts +2 -1
  389. package/dist/types.d.cts.map +1 -1
  390. package/dist/types.d.ts +2 -1
  391. package/dist/types.d.ts.map +1 -1
  392. package/dist/ui/index.cjs +1 -1
  393. package/dist/ui/index.d.cts +3 -3
  394. package/dist/ui/index.d.ts +3 -3
  395. package/dist/ui/index.js +1 -1
  396. package/dist/ui/manager.cjs +1 -1
  397. package/dist/ui/manager.js +1 -1
  398. package/dist/ui/messages.cjs +50 -7
  399. package/dist/ui/messages.cjs.map +1 -1
  400. package/dist/ui/messages.d.cts.map +1 -1
  401. package/dist/ui/messages.d.ts.map +1 -1
  402. package/dist/ui/messages.js +51 -9
  403. package/dist/ui/messages.js.map +1 -1
  404. package/dist/ui/orchestrator-custom.cjs +1 -1
  405. package/dist/ui/orchestrator-custom.js +1 -1
  406. package/dist/ui/orchestrator.cjs +2 -2
  407. package/dist/ui/orchestrator.d.cts +1 -1
  408. package/dist/ui/orchestrator.d.ts +1 -1
  409. package/dist/ui/orchestrator.d.ts.map +1 -1
  410. package/dist/ui/orchestrator.js +2 -2
  411. package/dist/ui/stream/agent.d.cts +1 -1
  412. package/dist/ui/stream/agent.d.cts.map +1 -1
  413. package/dist/ui/stream/agent.d.ts +1 -1
  414. package/dist/ui/stream/agent.d.ts.map +1 -1
  415. package/dist/ui/stream/base.d.cts +7 -6
  416. package/dist/ui/stream/base.d.cts.map +1 -1
  417. package/dist/ui/stream/base.d.ts +7 -6
  418. package/dist/ui/stream/base.d.ts.map +1 -1
  419. package/dist/ui/stream/deep-agent.d.cts +1 -1
  420. package/dist/ui/stream/deep-agent.d.cts.map +1 -1
  421. package/dist/ui/stream/deep-agent.d.ts +1 -1
  422. package/dist/ui/stream/deep-agent.d.ts.map +1 -1
  423. package/dist/ui/stream/index.d.cts +4 -4
  424. package/dist/ui/stream/index.d.cts.map +1 -1
  425. package/dist/ui/stream/index.d.ts +4 -4
  426. package/dist/ui/stream/index.d.ts.map +1 -1
  427. package/dist/ui/types.d.cts +3 -2
  428. package/dist/ui/types.d.cts.map +1 -1
  429. package/dist/ui/types.d.ts +2 -1
  430. package/dist/ui/types.d.ts.map +1 -1
  431. package/package.json +18 -8
  432. package/dist/client.cjs.map +0 -1
  433. package/dist/client.d.cts.map +0 -1
  434. package/dist/client.d.ts.map +0 -1
  435. package/dist/client.js.map +0 -1
@@ -0,0 +1,165 @@
1
+ import { StreamStore } from "./store.js";
2
+ import { namespaceKey } from "./namespace.js";
3
+ //#region src/stream/message-metadata-tracker.ts
4
+ /**
5
+ * Per-message checkpoint metadata projection.
6
+ *
7
+ * # What this module is
8
+ *
9
+ * The protocol emits a `checkpoints` event immediately *before* its
10
+ * companion `values` event for the same superstep:
11
+ *
12
+ * 1. `checkpoints` — `{ id, parent_id?, step?, source? }`
13
+ * 2. `values` — `{ messages, ... }` (same namespace)
14
+ *
15
+ * Both events carry the same `seq` ordering but live on different
16
+ * channels, so the controller can't atomically observe them. This
17
+ * tracker bridges the gap by buffering each `checkpoints` envelope
18
+ * keyed on its namespace, then consuming it when the matching values
19
+ * payload arrives. Once paired, the consumer (typically the
20
+ * controller) writes a {@link MessageMetadata} record under each
21
+ * message id.
22
+ *
23
+ * # Why fork / edit flows need this
24
+ *
25
+ * Surfacing `parentCheckpointId` per-message lets UI flows like
26
+ * "edit a message and re-run" call
27
+ * `submit(input, { forkFrom: { checkpointId } })` without making the
28
+ * caller juggle thread state. Each message remembers the checkpoint
29
+ * it was first observed at, so a "fork from this message" UI can read
30
+ * `useMessageMetadata(stream, msg.id)` directly.
31
+ *
32
+ * # Lifecycle
33
+ *
34
+ * - `bufferCheckpoint(ns, data)` — store the envelope until the
35
+ * companion values event arrives.
36
+ * - `consumeCheckpoint(ns)` — read-and-clear the envelope when
37
+ * the values event lands. Returning `undefined` signals "no
38
+ * metadata to attach" — older snapshots without a paired
39
+ * checkpoint are still applied to the store, just without
40
+ * `parentCheckpointId`.
41
+ * - `recordMessages(msgs, meta)` — write metadata for the supplied
42
+ * message ids if it differs from what's already stored.
43
+ * - `reset()` — clear everything (called on
44
+ * thread rebind / dispose).
45
+ *
46
+ * The buffer is read-and-cleared on consumption so a values event that
47
+ * arrives without a fresh checkpoint envelope doesn't reuse stale
48
+ * metadata from a previous superstep.
49
+ */
50
+ /**
51
+ * Frozen empty map used as the store's initial value. Keeping the
52
+ * reference stable avoids spurious `setSnapshot` notifications on
53
+ * `reset()` for consumers that haven't observed any metadata yet.
54
+ */
55
+ const EMPTY_METADATA_MAP = /* @__PURE__ */ new Map();
56
+ /**
57
+ * Tracks checkpoint-derived metadata for messages.
58
+ *
59
+ * Owns one {@link StreamStore} mapping `messageId → MessageMetadata`
60
+ * plus a per-namespace buffer of pending checkpoint envelopes. The
61
+ * controller wires it up via three call sites:
62
+ *
63
+ * 1. `controller.#onRootEvent("checkpoints")`
64
+ * → `bufferCheckpoint(namespace, data)`
65
+ * 2. `controller.#onRootEvent("values")`
66
+ * → `consumeCheckpoint(namespace)` then
67
+ * `recordMessages(values.messages, { parentCheckpointId })`
68
+ * 3. `controller.#teardownThread`
69
+ * → `reset()`
70
+ *
71
+ * @see useMessageMetadata - The framework hook that reads from
72
+ * {@link MessageMetadataTracker.store}.
73
+ */
74
+ var MessageMetadataTracker = class {
75
+ /** Observable map of messageId → metadata for framework consumers. */
76
+ store = new StreamStore(EMPTY_METADATA_MAP);
77
+ /**
78
+ * Pending checkpoint envelopes awaiting their companion values
79
+ * event. Keyed by `namespaceKey(namespace)` so a deeply-nested
80
+ * checkpoint at one namespace doesn't collide with a root-level
81
+ * checkpoint emitted in the same tick.
82
+ */
83
+ #pendingCheckpointByNamespace = /* @__PURE__ */ new Map();
84
+ /**
85
+ * Drop all buffered checkpoints and reset the metadata map to the
86
+ * shared empty instance. Called on thread rebind / dispose so a new
87
+ * thread's metadata can't bleed into the old one.
88
+ */
89
+ reset() {
90
+ this.#pendingCheckpointByNamespace.clear();
91
+ this.store.setState(() => EMPTY_METADATA_MAP);
92
+ }
93
+ /**
94
+ * Buffer a `checkpoints` event for later pairing with its values
95
+ * companion.
96
+ *
97
+ * Defensive against missing / malformed payloads:
98
+ *
99
+ * - `data == null` → no-op (some upstream nodes elide the
100
+ * payload entirely; we keep the previous buffered envelope so
101
+ * the next consume call still wins).
102
+ * - `id` not a string → no-op.
103
+ * - `parent_id` not a string → omitted from the envelope.
104
+ *
105
+ * @param namespace - Event namespace (used as the buffer key).
106
+ * @param data - Raw checkpoints payload.
107
+ */
108
+ bufferCheckpoint(namespace, data) {
109
+ if (data == null || typeof data.id !== "string") return;
110
+ const envelope = { id: data.id };
111
+ if (typeof data.parent_id === "string") envelope.parent_id = data.parent_id;
112
+ this.#pendingCheckpointByNamespace.set(namespaceKey(namespace), envelope);
113
+ }
114
+ /**
115
+ * Read-and-clear the buffered checkpoint envelope for `namespace`.
116
+ *
117
+ * Always pairs with a single {@link bufferCheckpoint} call: a values
118
+ * event without a matching buffered checkpoint returns `undefined`
119
+ * (meaning "no metadata to attach"), and the next checkpoint event
120
+ * starts fresh rather than reusing stale data.
121
+ *
122
+ * @param namespace - Event namespace to consume.
123
+ * @returns The buffered envelope, or `undefined` when none was buffered.
124
+ */
125
+ consumeCheckpoint(namespace) {
126
+ const key = namespaceKey(namespace);
127
+ const checkpoint = this.#pendingCheckpointByNamespace.get(key);
128
+ if (checkpoint != null) this.#pendingCheckpointByNamespace.delete(key);
129
+ return checkpoint;
130
+ }
131
+ /**
132
+ * Record metadata for a list of messages.
133
+ *
134
+ * Skips messages whose existing entry already matches `metadata`;
135
+ * those without an `id` (or with a non-string id) are silently
136
+ * ignored — there's nothing to key the metadata on. The store is
137
+ * only updated when at least one entry actually changed, so
138
+ * reapplying the same values snapshot is cheap.
139
+ *
140
+ * @param messages - Messages from the latest values payload.
141
+ * @param metadata - Metadata to attach (currently just
142
+ * `parentCheckpointId`).
143
+ */
144
+ recordMessages(messages, metadata) {
145
+ const current = this.store.getSnapshot();
146
+ let changed = false;
147
+ const next = new Map(current);
148
+ for (const msg of messages) {
149
+ const id = msg?.id;
150
+ if (typeof id !== "string" || id.length === 0) continue;
151
+ const prev = next.get(id);
152
+ if (prev != null && prev.parentCheckpointId === metadata.parentCheckpointId) continue;
153
+ next.set(id, {
154
+ ...prev,
155
+ ...metadata
156
+ });
157
+ changed = true;
158
+ }
159
+ if (changed) this.store.setState(() => next);
160
+ }
161
+ };
162
+ //#endregion
163
+ export { MessageMetadataTracker };
164
+
165
+ //# sourceMappingURL=message-metadata-tracker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"message-metadata-tracker.js","names":["#pendingCheckpointByNamespace"],"sources":["../../src/stream/message-metadata-tracker.ts"],"sourcesContent":["/**\n * Per-message checkpoint metadata projection.\n *\n * # What this module is\n *\n * The protocol emits a `checkpoints` event immediately *before* its\n * companion `values` event for the same superstep:\n *\n * 1. `checkpoints` — `{ id, parent_id?, step?, source? }`\n * 2. `values` — `{ messages, ... }` (same namespace)\n *\n * Both events carry the same `seq` ordering but live on different\n * channels, so the controller can't atomically observe them. This\n * tracker bridges the gap by buffering each `checkpoints` envelope\n * keyed on its namespace, then consuming it when the matching values\n * payload arrives. Once paired, the consumer (typically the\n * controller) writes a {@link MessageMetadata} record under each\n * message id.\n *\n * # Why fork / edit flows need this\n *\n * Surfacing `parentCheckpointId` per-message lets UI flows like\n * \"edit a message and re-run\" call\n * `submit(input, { forkFrom: { checkpointId } })` without making the\n * caller juggle thread state. Each message remembers the checkpoint\n * it was first observed at, so a \"fork from this message\" UI can read\n * `useMessageMetadata(stream, msg.id)` directly.\n *\n * # Lifecycle\n *\n * - `bufferCheckpoint(ns, data)` — store the envelope until the\n * companion values event arrives.\n * - `consumeCheckpoint(ns)` — read-and-clear the envelope when\n * the values event lands. Returning `undefined` signals \"no\n * metadata to attach\" — older snapshots without a paired\n * checkpoint are still applied to the store, just without\n * `parentCheckpointId`.\n * - `recordMessages(msgs, meta)` — write metadata for the supplied\n * message ids if it differs from what's already stored.\n * - `reset()` — clear everything (called on\n * thread rebind / dispose).\n *\n * The buffer is read-and-cleared on consumption so a values event that\n * arrives without a fresh checkpoint envelope doesn't reuse stale\n * metadata from a previous superstep.\n */\nimport { StreamStore } from \"./store.js\";\nimport { namespaceKey } from \"./namespace.js\";\n\n/**\n * Metadata tracked per message id. Surfaced to applications via\n * `useMessageMetadata(stream, messageId)`.\n */\nexport interface MessageMetadata {\n /**\n * Checkpoint id the message's *parent* was at when this message was\n * observed. Drives fork / edit flows\n * (`submit(input, { forkFrom: { checkpointId } })`).\n *\n * `undefined` when the message was observed without a paired\n * checkpoint envelope (e.g. before checkpoints rolled out, or when\n * the caller stripped them upstream).\n */\n readonly parentCheckpointId: string | undefined;\n}\n\n/**\n * Read-only map exposed via {@link MessageMetadataTracker.store}.\n */\nexport type MessageMetadataMap = ReadonlyMap<string, MessageMetadata>;\n\n/**\n * Lightweight envelope mirroring the on-wire `checkpoints` event.\n *\n * The protocol payload may include additional fields (`step`,\n * `source`, etc.) — we only carry what the per-message metadata\n * actually needs.\n */\nexport interface CheckpointEnvelope {\n /** Checkpoint id this superstep wrote. */\n readonly id: string;\n /**\n * Parent checkpoint id, when present. Becomes\n * {@link MessageMetadata.parentCheckpointId} on the next values event.\n */\n readonly parent_id?: string;\n}\n\n/**\n * Frozen empty map used as the store's initial value. Keeping the\n * reference stable avoids spurious `setSnapshot` notifications on\n * `reset()` for consumers that haven't observed any metadata yet.\n */\nconst EMPTY_METADATA_MAP: MessageMetadataMap = new Map();\n\n/**\n * Tracks checkpoint-derived metadata for messages.\n *\n * Owns one {@link StreamStore} mapping `messageId → MessageMetadata`\n * plus a per-namespace buffer of pending checkpoint envelopes. The\n * controller wires it up via three call sites:\n *\n * 1. `controller.#onRootEvent(\"checkpoints\")`\n * → `bufferCheckpoint(namespace, data)`\n * 2. `controller.#onRootEvent(\"values\")`\n * → `consumeCheckpoint(namespace)` then\n * `recordMessages(values.messages, { parentCheckpointId })`\n * 3. `controller.#teardownThread`\n * → `reset()`\n *\n * @see useMessageMetadata - The framework hook that reads from\n * {@link MessageMetadataTracker.store}.\n */\nexport class MessageMetadataTracker {\n /** Observable map of messageId → metadata for framework consumers. */\n readonly store = new StreamStore<MessageMetadataMap>(EMPTY_METADATA_MAP);\n\n /**\n * Pending checkpoint envelopes awaiting their companion values\n * event. Keyed by `namespaceKey(namespace)` so a deeply-nested\n * checkpoint at one namespace doesn't collide with a root-level\n * checkpoint emitted in the same tick.\n */\n readonly #pendingCheckpointByNamespace = new Map<\n string,\n CheckpointEnvelope\n >();\n\n /**\n * Drop all buffered checkpoints and reset the metadata map to the\n * shared empty instance. Called on thread rebind / dispose so a new\n * thread's metadata can't bleed into the old one.\n */\n reset(): void {\n this.#pendingCheckpointByNamespace.clear();\n this.store.setState(() => EMPTY_METADATA_MAP);\n }\n\n /**\n * Buffer a `checkpoints` event for later pairing with its values\n * companion.\n *\n * Defensive against missing / malformed payloads:\n *\n * - `data == null` → no-op (some upstream nodes elide the\n * payload entirely; we keep the previous buffered envelope so\n * the next consume call still wins).\n * - `id` not a string → no-op.\n * - `parent_id` not a string → omitted from the envelope.\n *\n * @param namespace - Event namespace (used as the buffer key).\n * @param data - Raw checkpoints payload.\n */\n bufferCheckpoint(\n namespace: readonly string[],\n data: { id?: unknown; parent_id?: unknown } | null\n ): void {\n if (data == null || typeof data.id !== \"string\") return;\n const envelope: CheckpointEnvelope = { id: data.id };\n if (typeof data.parent_id === \"string\") {\n (envelope as { parent_id?: string }).parent_id = data.parent_id;\n }\n this.#pendingCheckpointByNamespace.set(namespaceKey(namespace), envelope);\n }\n\n /**\n * Read-and-clear the buffered checkpoint envelope for `namespace`.\n *\n * Always pairs with a single {@link bufferCheckpoint} call: a values\n * event without a matching buffered checkpoint returns `undefined`\n * (meaning \"no metadata to attach\"), and the next checkpoint event\n * starts fresh rather than reusing stale data.\n *\n * @param namespace - Event namespace to consume.\n * @returns The buffered envelope, or `undefined` when none was buffered.\n */\n consumeCheckpoint(\n namespace: readonly string[]\n ): CheckpointEnvelope | undefined {\n const key = namespaceKey(namespace);\n const checkpoint = this.#pendingCheckpointByNamespace.get(key);\n if (checkpoint != null) this.#pendingCheckpointByNamespace.delete(key);\n return checkpoint;\n }\n\n /**\n * Record metadata for a list of messages.\n *\n * Skips messages whose existing entry already matches `metadata`;\n * those without an `id` (or with a non-string id) are silently\n * ignored — there's nothing to key the metadata on. The store is\n * only updated when at least one entry actually changed, so\n * reapplying the same values snapshot is cheap.\n *\n * @param messages - Messages from the latest values payload.\n * @param metadata - Metadata to attach (currently just\n * `parentCheckpointId`).\n */\n recordMessages(\n messages: Array<{ id?: string }>,\n metadata: MessageMetadata\n ): void {\n const current = this.store.getSnapshot();\n let changed = false;\n const next = new Map(current);\n for (const msg of messages) {\n const id = msg?.id;\n if (typeof id !== \"string\" || id.length === 0) continue;\n const prev = next.get(id);\n if (\n prev != null &&\n prev.parentCheckpointId === metadata.parentCheckpointId\n ) {\n continue;\n }\n next.set(id, { ...prev, ...metadata });\n changed = true;\n }\n if (changed) this.store.setState(() => next);\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA6FA,MAAM,qCAAyC,IAAI,KAAK;;;;;;;;;;;;;;;;;;;AAoBxD,IAAa,yBAAb,MAAoC;;CAElC,QAAiB,IAAI,YAAgC,mBAAmB;;;;;;;CAQxE,gDAAyC,IAAI,KAG1C;;;;;;CAOH,QAAc;AACZ,QAAA,6BAAmC,OAAO;AAC1C,OAAK,MAAM,eAAe,mBAAmB;;;;;;;;;;;;;;;;;CAkB/C,iBACE,WACA,MACM;AACN,MAAI,QAAQ,QAAQ,OAAO,KAAK,OAAO,SAAU;EACjD,MAAM,WAA+B,EAAE,IAAI,KAAK,IAAI;AACpD,MAAI,OAAO,KAAK,cAAc,SAC3B,UAAoC,YAAY,KAAK;AAExD,QAAA,6BAAmC,IAAI,aAAa,UAAU,EAAE,SAAS;;;;;;;;;;;;;CAc3E,kBACE,WACgC;EAChC,MAAM,MAAM,aAAa,UAAU;EACnC,MAAM,aAAa,MAAA,6BAAmC,IAAI,IAAI;AAC9D,MAAI,cAAc,KAAM,OAAA,6BAAmC,OAAO,IAAI;AACtE,SAAO;;;;;;;;;;;;;;;CAgBT,eACE,UACA,UACM;EACN,MAAM,UAAU,KAAK,MAAM,aAAa;EACxC,IAAI,UAAU;EACd,MAAM,OAAO,IAAI,IAAI,QAAQ;AAC7B,OAAK,MAAM,OAAO,UAAU;GAC1B,MAAM,KAAK,KAAK;AAChB,OAAI,OAAO,OAAO,YAAY,GAAG,WAAW,EAAG;GAC/C,MAAM,OAAO,KAAK,IAAI,GAAG;AACzB,OACE,QAAQ,QACR,KAAK,uBAAuB,SAAS,mBAErC;AAEF,QAAK,IAAI,IAAI;IAAE,GAAG;IAAM,GAAG;IAAU,CAAC;AACtC,aAAU;;AAEZ,MAAI,QAAS,MAAK,MAAM,eAAe,KAAK"}
@@ -0,0 +1,118 @@
1
+ //#region src/stream/message-reconciliation.ts
2
+ /**
3
+ * Merge an authoritative `values.messages` snapshot with the current streamed
4
+ * message projection.
5
+ *
6
+ * Values remain authoritative for ordering and removals. Streamed messages
7
+ * remain authoritative for in-flight content until the server echoes them in a
8
+ * values snapshot, and stream-only messages are preserved until they either
9
+ * appear in values or are known to have been removed.
10
+ */
11
+ function reconcileMessagesFromValues({ valueMessages, currentMessages, currentIndexById, previousValueMessageIds, streamedMessageIds, preferValuesMessage }) {
12
+ const valueMessageIds = /* @__PURE__ */ new Set();
13
+ const merged = [];
14
+ for (const valuesMessage of valueMessages) {
15
+ const id = normalizedMessageId(valuesMessage);
16
+ if (id == null) {
17
+ merged.push(valuesMessage);
18
+ continue;
19
+ }
20
+ valueMessageIds.add(id);
21
+ const streamIdx = currentIndexById.get(id);
22
+ const streamedMessage = streamIdx != null && (streamedMessageIds == null || streamedMessageIds.has(id)) ? currentMessages[streamIdx] : void 0;
23
+ if (streamedMessage != null && preferValuesMessage?.(valuesMessage, streamedMessage) !== true) merged.push(streamedMessage);
24
+ else merged.push(valuesMessage);
25
+ }
26
+ for (const existing of currentMessages) {
27
+ const id = normalizedMessageId(existing);
28
+ if (id == null) continue;
29
+ if (valueMessageIds.has(id)) continue;
30
+ if (previousValueMessageIds.has(id)) continue;
31
+ if (streamedMessageIds != null && !streamedMessageIds.has(id)) continue;
32
+ merged.push(existing);
33
+ }
34
+ return {
35
+ messages: messagesEqualList(currentMessages, merged) ? currentMessages : merged,
36
+ valueMessageIds
37
+ };
38
+ }
39
+ /**
40
+ * Build a position index for keyed messages.
41
+ */
42
+ function buildMessageIndex(messages) {
43
+ const index = /* @__PURE__ */ new Map();
44
+ messages.forEach((message, idx) => {
45
+ const id = normalizedMessageId(message);
46
+ if (id != null) index.set(id, idx);
47
+ });
48
+ return index;
49
+ }
50
+ /**
51
+ * Decide whether a values message carries tool-call data missing from the
52
+ * streamed message.
53
+ */
54
+ function shouldPreferValuesMessageForToolCalls(valuesMessage, streamedMessage) {
55
+ const valuesToolCalls = getMessageToolCalls(valuesMessage);
56
+ if (valuesToolCalls.length === 0) return false;
57
+ const streamedToolCalls = getMessageToolCalls(streamedMessage);
58
+ if (streamedToolCalls.length < valuesToolCalls.length) return true;
59
+ const streamedIds = new Set(streamedToolCalls.map((toolCall) => toolCall.id).filter((id) => typeof id === "string" && id.length > 0));
60
+ return valuesToolCalls.some((toolCall) => {
61
+ return typeof toolCall.id === "string" && !streamedIds.has(toolCall.id);
62
+ });
63
+ }
64
+ function messagesEqualList(previous, next) {
65
+ if (previous === next) return true;
66
+ if (previous.length !== next.length) return false;
67
+ for (let i = 0; i < previous.length; i += 1) if (!messagesEqual(previous[i], next[i])) return false;
68
+ return true;
69
+ }
70
+ function messagesEqual(previous, next) {
71
+ if (previous === next) return true;
72
+ if (previous == null || next == null) return false;
73
+ const previousRecord = previous;
74
+ const nextRecord = next;
75
+ const previousType = typeof previous.getType === "function" ? previous.getType() : previousRecord.type;
76
+ const nextType = typeof next.getType === "function" ? next.getType() : nextRecord.type;
77
+ return previous.id === next.id && previousType === nextType && jsonishEqual(previous.content, next.content) && previousRecord.tool_call_id === nextRecord.tool_call_id && previousRecord.status === nextRecord.status && jsonishEqual(previousRecord.additional_kwargs, nextRecord.additional_kwargs) && jsonishEqual(previousRecord.response_metadata, nextRecord.response_metadata) && jsonishEqual(previousRecord.tool_calls, nextRecord.tool_calls) && jsonishEqual(previousRecord.tool_call_chunks, nextRecord.tool_call_chunks) && jsonishEqual(previousRecord.usage_metadata, nextRecord.usage_metadata);
78
+ }
79
+ function normalizedMessageId(message) {
80
+ return typeof message.id === "string" && message.id.length > 0 ? message.id : void 0;
81
+ }
82
+ function getMessageToolCalls(message) {
83
+ const raw = message.tool_calls;
84
+ if (!Array.isArray(raw)) return [];
85
+ return raw.filter((toolCall) => toolCall != null && typeof toolCall === "object");
86
+ }
87
+ function jsonishEqual(previous, next) {
88
+ return jsonishEqualAtDepth(previous, next, 0);
89
+ }
90
+ function jsonishEqualAtDepth(previous, next, depth) {
91
+ if (Object.is(previous, next)) return true;
92
+ if (previous == null || next == null) return false;
93
+ if (typeof previous !== "object" || typeof next !== "object") return false;
94
+ if (depth >= 4) return false;
95
+ if (Array.isArray(previous) || Array.isArray(next)) {
96
+ if (!Array.isArray(previous) || !Array.isArray(next)) return false;
97
+ if (previous.length !== next.length) return false;
98
+ for (let i = 0; i < previous.length; i += 1) if (!jsonishEqualAtDepth(previous[i], next[i], depth + 1)) return false;
99
+ return true;
100
+ }
101
+ const previousRecord = previous;
102
+ const nextRecord = next;
103
+ const previousKeys = Object.keys(previousRecord).filter((key) => typeof previousRecord[key] !== "function");
104
+ const nextKeys = Object.keys(nextRecord).filter((key) => typeof nextRecord[key] !== "function");
105
+ if (previousKeys.length !== nextKeys.length) return false;
106
+ for (const key of previousKeys) {
107
+ if (!Object.prototype.hasOwnProperty.call(nextRecord, key)) return false;
108
+ if (!jsonishEqualAtDepth(previousRecord[key], nextRecord[key], depth + 1)) return false;
109
+ }
110
+ return true;
111
+ }
112
+ //#endregion
113
+ exports.buildMessageIndex = buildMessageIndex;
114
+ exports.messagesEqual = messagesEqual;
115
+ exports.reconcileMessagesFromValues = reconcileMessagesFromValues;
116
+ exports.shouldPreferValuesMessageForToolCalls = shouldPreferValuesMessageForToolCalls;
117
+
118
+ //# sourceMappingURL=message-reconciliation.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"message-reconciliation.cjs","names":[],"sources":["../../src/stream/message-reconciliation.ts"],"sourcesContent":["import type { BaseMessage } from \"@langchain/core/messages\";\n\nexport interface ReconcileMessagesFromValuesOptions {\n /**\n * Messages from the authoritative `values.messages` snapshot.\n */\n readonly valueMessages: readonly BaseMessage[];\n /**\n * Current message projection, including stream-assembled in-flight messages.\n */\n readonly currentMessages: readonly BaseMessage[];\n /**\n * Index from message id to current message position.\n */\n readonly currentIndexById: ReadonlyMap<string, number>;\n /**\n * Ids observed in the most recent previous `values.messages` snapshot.\n * If one of these ids is missing from the next snapshot, it is treated as\n * an explicit server-side removal.\n */\n readonly previousValueMessageIds: ReadonlySet<string>;\n /**\n * Optional stream-id filter. When supplied, only these current ids are\n * eligible to override the values snapshot. When omitted, any id present in\n * `currentIndexById` is eligible, preserving the root controller's historic\n * behavior.\n */\n readonly streamedMessageIds?: ReadonlySet<string>;\n /**\n * Allows callers to keep a values message even when a streamed message with\n * the same id exists. Used by the root controller when the values message\n * carries finalized tool-call data missing from the streamed message.\n */\n readonly preferValuesMessage?: (\n valuesMessage: BaseMessage,\n streamedMessage: BaseMessage\n ) => boolean;\n}\n\nexport interface ReconciledMessages {\n readonly messages: readonly BaseMessage[];\n readonly valueMessageIds: Set<string>;\n}\n\n/**\n * Merge an authoritative `values.messages` snapshot with the current streamed\n * message projection.\n *\n * Values remain authoritative for ordering and removals. Streamed messages\n * remain authoritative for in-flight content until the server echoes them in a\n * values snapshot, and stream-only messages are preserved until they either\n * appear in values or are known to have been removed.\n */\nexport function reconcileMessagesFromValues({\n valueMessages,\n currentMessages,\n currentIndexById,\n previousValueMessageIds,\n streamedMessageIds,\n preferValuesMessage,\n}: ReconcileMessagesFromValuesOptions): ReconciledMessages {\n const valueMessageIds = new Set<string>();\n const merged: BaseMessage[] = [];\n\n for (const valuesMessage of valueMessages) {\n const id = normalizedMessageId(valuesMessage);\n if (id == null) {\n merged.push(valuesMessage);\n continue;\n }\n\n valueMessageIds.add(id);\n const streamIdx = currentIndexById.get(id);\n const canUseStreamed =\n streamIdx != null &&\n (streamedMessageIds == null || streamedMessageIds.has(id));\n const streamedMessage = canUseStreamed\n ? currentMessages[streamIdx]\n : undefined;\n\n if (\n streamedMessage != null &&\n preferValuesMessage?.(valuesMessage, streamedMessage) !== true\n ) {\n merged.push(streamedMessage);\n } else {\n merged.push(valuesMessage);\n }\n }\n\n for (const existing of currentMessages) {\n const id = normalizedMessageId(existing);\n if (id == null) continue;\n if (valueMessageIds.has(id)) continue;\n if (previousValueMessageIds.has(id)) continue;\n if (streamedMessageIds != null && !streamedMessageIds.has(id)) continue;\n merged.push(existing);\n }\n\n return {\n messages: messagesEqualList(currentMessages, merged)\n ? currentMessages\n : merged,\n valueMessageIds,\n };\n}\n\n/**\n * Build a position index for keyed messages.\n */\nexport function buildMessageIndex(\n messages: readonly BaseMessage[]\n): Map<string, number> {\n const index = new Map<string, number>();\n messages.forEach((message, idx) => {\n const id = normalizedMessageId(message);\n if (id != null) index.set(id, idx);\n });\n return index;\n}\n\n/**\n * Decide whether a values message carries tool-call data missing from the\n * streamed message.\n */\nexport function shouldPreferValuesMessageForToolCalls(\n valuesMessage: BaseMessage,\n streamedMessage: BaseMessage\n): boolean {\n const valuesToolCalls = getMessageToolCalls(valuesMessage);\n if (valuesToolCalls.length === 0) return false;\n\n const streamedToolCalls = getMessageToolCalls(streamedMessage);\n if (streamedToolCalls.length < valuesToolCalls.length) return true;\n\n const streamedIds = new Set(\n streamedToolCalls\n .map((toolCall) => toolCall.id)\n .filter((id): id is string => typeof id === \"string\" && id.length > 0)\n );\n return valuesToolCalls.some((toolCall) => {\n return typeof toolCall.id === \"string\" && !streamedIds.has(toolCall.id);\n });\n}\n\nexport function messagesEqualList(\n previous: readonly BaseMessage[],\n next: readonly BaseMessage[]\n): boolean {\n if (previous === next) return true;\n if (previous.length !== next.length) return false;\n for (let i = 0; i < previous.length; i += 1) {\n if (!messagesEqual(previous[i], next[i])) return false;\n }\n return true;\n}\n\nexport function messagesEqual(\n previous: BaseMessage | undefined,\n next: BaseMessage | undefined\n): boolean {\n if (previous === next) return true;\n if (previous == null || next == null) return false;\n const previousRecord = previous as unknown as Record<string, unknown>;\n const nextRecord = next as unknown as Record<string, unknown>;\n const previousType =\n typeof previous.getType === \"function\"\n ? previous.getType()\n : previousRecord.type;\n const nextType =\n typeof next.getType === \"function\" ? next.getType() : nextRecord.type;\n\n return (\n previous.id === next.id &&\n previousType === nextType &&\n jsonishEqual(previous.content, next.content) &&\n previousRecord.tool_call_id === nextRecord.tool_call_id &&\n previousRecord.status === nextRecord.status &&\n jsonishEqual(\n previousRecord.additional_kwargs,\n nextRecord.additional_kwargs\n ) &&\n jsonishEqual(\n previousRecord.response_metadata,\n nextRecord.response_metadata\n ) &&\n jsonishEqual(previousRecord.tool_calls, nextRecord.tool_calls) &&\n jsonishEqual(\n previousRecord.tool_call_chunks,\n nextRecord.tool_call_chunks\n ) &&\n jsonishEqual(previousRecord.usage_metadata, nextRecord.usage_metadata)\n );\n}\n\nfunction normalizedMessageId(message: BaseMessage): string | undefined {\n return typeof message.id === \"string\" && message.id.length > 0\n ? message.id\n : undefined;\n}\n\nfunction getMessageToolCalls(\n message: BaseMessage\n): Array<{ id?: string; name?: string }> {\n const raw = (message as unknown as { tool_calls?: unknown }).tool_calls;\n if (!Array.isArray(raw)) return [];\n return raw.filter(\n (toolCall): toolCall is { id?: string; name?: string } =>\n toolCall != null && typeof toolCall === \"object\"\n );\n}\n\nfunction jsonishEqual(previous: unknown, next: unknown): boolean {\n return jsonishEqualAtDepth(previous, next, 0);\n}\n\nfunction jsonishEqualAtDepth(\n previous: unknown,\n next: unknown,\n depth: number\n): boolean {\n if (Object.is(previous, next)) return true;\n if (previous == null || next == null) return false;\n if (typeof previous !== \"object\" || typeof next !== \"object\") return false;\n if (depth >= 4) return false;\n\n if (Array.isArray(previous) || Array.isArray(next)) {\n if (!Array.isArray(previous) || !Array.isArray(next)) return false;\n if (previous.length !== next.length) return false;\n for (let i = 0; i < previous.length; i += 1) {\n if (!jsonishEqualAtDepth(previous[i], next[i], depth + 1)) return false;\n }\n return true;\n }\n\n const previousRecord = previous as Record<string, unknown>;\n const nextRecord = next as Record<string, unknown>;\n const previousKeys = Object.keys(previousRecord).filter(\n (key) => typeof previousRecord[key] !== \"function\"\n );\n const nextKeys = Object.keys(nextRecord).filter(\n (key) => typeof nextRecord[key] !== \"function\"\n );\n if (previousKeys.length !== nextKeys.length) return false;\n\n for (const key of previousKeys) {\n if (!Object.prototype.hasOwnProperty.call(nextRecord, key)) return false;\n if (!jsonishEqualAtDepth(previousRecord[key], nextRecord[key], depth + 1)) {\n return false;\n }\n }\n return true;\n}\n"],"mappings":"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"}
@@ -0,0 +1,115 @@
1
+ //#region src/stream/message-reconciliation.ts
2
+ /**
3
+ * Merge an authoritative `values.messages` snapshot with the current streamed
4
+ * message projection.
5
+ *
6
+ * Values remain authoritative for ordering and removals. Streamed messages
7
+ * remain authoritative for in-flight content until the server echoes them in a
8
+ * values snapshot, and stream-only messages are preserved until they either
9
+ * appear in values or are known to have been removed.
10
+ */
11
+ function reconcileMessagesFromValues({ valueMessages, currentMessages, currentIndexById, previousValueMessageIds, streamedMessageIds, preferValuesMessage }) {
12
+ const valueMessageIds = /* @__PURE__ */ new Set();
13
+ const merged = [];
14
+ for (const valuesMessage of valueMessages) {
15
+ const id = normalizedMessageId(valuesMessage);
16
+ if (id == null) {
17
+ merged.push(valuesMessage);
18
+ continue;
19
+ }
20
+ valueMessageIds.add(id);
21
+ const streamIdx = currentIndexById.get(id);
22
+ const streamedMessage = streamIdx != null && (streamedMessageIds == null || streamedMessageIds.has(id)) ? currentMessages[streamIdx] : void 0;
23
+ if (streamedMessage != null && preferValuesMessage?.(valuesMessage, streamedMessage) !== true) merged.push(streamedMessage);
24
+ else merged.push(valuesMessage);
25
+ }
26
+ for (const existing of currentMessages) {
27
+ const id = normalizedMessageId(existing);
28
+ if (id == null) continue;
29
+ if (valueMessageIds.has(id)) continue;
30
+ if (previousValueMessageIds.has(id)) continue;
31
+ if (streamedMessageIds != null && !streamedMessageIds.has(id)) continue;
32
+ merged.push(existing);
33
+ }
34
+ return {
35
+ messages: messagesEqualList(currentMessages, merged) ? currentMessages : merged,
36
+ valueMessageIds
37
+ };
38
+ }
39
+ /**
40
+ * Build a position index for keyed messages.
41
+ */
42
+ function buildMessageIndex(messages) {
43
+ const index = /* @__PURE__ */ new Map();
44
+ messages.forEach((message, idx) => {
45
+ const id = normalizedMessageId(message);
46
+ if (id != null) index.set(id, idx);
47
+ });
48
+ return index;
49
+ }
50
+ /**
51
+ * Decide whether a values message carries tool-call data missing from the
52
+ * streamed message.
53
+ */
54
+ function shouldPreferValuesMessageForToolCalls(valuesMessage, streamedMessage) {
55
+ const valuesToolCalls = getMessageToolCalls(valuesMessage);
56
+ if (valuesToolCalls.length === 0) return false;
57
+ const streamedToolCalls = getMessageToolCalls(streamedMessage);
58
+ if (streamedToolCalls.length < valuesToolCalls.length) return true;
59
+ const streamedIds = new Set(streamedToolCalls.map((toolCall) => toolCall.id).filter((id) => typeof id === "string" && id.length > 0));
60
+ return valuesToolCalls.some((toolCall) => {
61
+ return typeof toolCall.id === "string" && !streamedIds.has(toolCall.id);
62
+ });
63
+ }
64
+ function messagesEqualList(previous, next) {
65
+ if (previous === next) return true;
66
+ if (previous.length !== next.length) return false;
67
+ for (let i = 0; i < previous.length; i += 1) if (!messagesEqual(previous[i], next[i])) return false;
68
+ return true;
69
+ }
70
+ function messagesEqual(previous, next) {
71
+ if (previous === next) return true;
72
+ if (previous == null || next == null) return false;
73
+ const previousRecord = previous;
74
+ const nextRecord = next;
75
+ const previousType = typeof previous.getType === "function" ? previous.getType() : previousRecord.type;
76
+ const nextType = typeof next.getType === "function" ? next.getType() : nextRecord.type;
77
+ return previous.id === next.id && previousType === nextType && jsonishEqual(previous.content, next.content) && previousRecord.tool_call_id === nextRecord.tool_call_id && previousRecord.status === nextRecord.status && jsonishEqual(previousRecord.additional_kwargs, nextRecord.additional_kwargs) && jsonishEqual(previousRecord.response_metadata, nextRecord.response_metadata) && jsonishEqual(previousRecord.tool_calls, nextRecord.tool_calls) && jsonishEqual(previousRecord.tool_call_chunks, nextRecord.tool_call_chunks) && jsonishEqual(previousRecord.usage_metadata, nextRecord.usage_metadata);
78
+ }
79
+ function normalizedMessageId(message) {
80
+ return typeof message.id === "string" && message.id.length > 0 ? message.id : void 0;
81
+ }
82
+ function getMessageToolCalls(message) {
83
+ const raw = message.tool_calls;
84
+ if (!Array.isArray(raw)) return [];
85
+ return raw.filter((toolCall) => toolCall != null && typeof toolCall === "object");
86
+ }
87
+ function jsonishEqual(previous, next) {
88
+ return jsonishEqualAtDepth(previous, next, 0);
89
+ }
90
+ function jsonishEqualAtDepth(previous, next, depth) {
91
+ if (Object.is(previous, next)) return true;
92
+ if (previous == null || next == null) return false;
93
+ if (typeof previous !== "object" || typeof next !== "object") return false;
94
+ if (depth >= 4) return false;
95
+ if (Array.isArray(previous) || Array.isArray(next)) {
96
+ if (!Array.isArray(previous) || !Array.isArray(next)) return false;
97
+ if (previous.length !== next.length) return false;
98
+ for (let i = 0; i < previous.length; i += 1) if (!jsonishEqualAtDepth(previous[i], next[i], depth + 1)) return false;
99
+ return true;
100
+ }
101
+ const previousRecord = previous;
102
+ const nextRecord = next;
103
+ const previousKeys = Object.keys(previousRecord).filter((key) => typeof previousRecord[key] !== "function");
104
+ const nextKeys = Object.keys(nextRecord).filter((key) => typeof nextRecord[key] !== "function");
105
+ if (previousKeys.length !== nextKeys.length) return false;
106
+ for (const key of previousKeys) {
107
+ if (!Object.prototype.hasOwnProperty.call(nextRecord, key)) return false;
108
+ if (!jsonishEqualAtDepth(previousRecord[key], nextRecord[key], depth + 1)) return false;
109
+ }
110
+ return true;
111
+ }
112
+ //#endregion
113
+ export { buildMessageIndex, messagesEqual, reconcileMessagesFromValues, shouldPreferValuesMessageForToolCalls };
114
+
115
+ //# sourceMappingURL=message-reconciliation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"message-reconciliation.js","names":[],"sources":["../../src/stream/message-reconciliation.ts"],"sourcesContent":["import type { BaseMessage } from \"@langchain/core/messages\";\n\nexport interface ReconcileMessagesFromValuesOptions {\n /**\n * Messages from the authoritative `values.messages` snapshot.\n */\n readonly valueMessages: readonly BaseMessage[];\n /**\n * Current message projection, including stream-assembled in-flight messages.\n */\n readonly currentMessages: readonly BaseMessage[];\n /**\n * Index from message id to current message position.\n */\n readonly currentIndexById: ReadonlyMap<string, number>;\n /**\n * Ids observed in the most recent previous `values.messages` snapshot.\n * If one of these ids is missing from the next snapshot, it is treated as\n * an explicit server-side removal.\n */\n readonly previousValueMessageIds: ReadonlySet<string>;\n /**\n * Optional stream-id filter. When supplied, only these current ids are\n * eligible to override the values snapshot. When omitted, any id present in\n * `currentIndexById` is eligible, preserving the root controller's historic\n * behavior.\n */\n readonly streamedMessageIds?: ReadonlySet<string>;\n /**\n * Allows callers to keep a values message even when a streamed message with\n * the same id exists. Used by the root controller when the values message\n * carries finalized tool-call data missing from the streamed message.\n */\n readonly preferValuesMessage?: (\n valuesMessage: BaseMessage,\n streamedMessage: BaseMessage\n ) => boolean;\n}\n\nexport interface ReconciledMessages {\n readonly messages: readonly BaseMessage[];\n readonly valueMessageIds: Set<string>;\n}\n\n/**\n * Merge an authoritative `values.messages` snapshot with the current streamed\n * message projection.\n *\n * Values remain authoritative for ordering and removals. Streamed messages\n * remain authoritative for in-flight content until the server echoes them in a\n * values snapshot, and stream-only messages are preserved until they either\n * appear in values or are known to have been removed.\n */\nexport function reconcileMessagesFromValues({\n valueMessages,\n currentMessages,\n currentIndexById,\n previousValueMessageIds,\n streamedMessageIds,\n preferValuesMessage,\n}: ReconcileMessagesFromValuesOptions): ReconciledMessages {\n const valueMessageIds = new Set<string>();\n const merged: BaseMessage[] = [];\n\n for (const valuesMessage of valueMessages) {\n const id = normalizedMessageId(valuesMessage);\n if (id == null) {\n merged.push(valuesMessage);\n continue;\n }\n\n valueMessageIds.add(id);\n const streamIdx = currentIndexById.get(id);\n const canUseStreamed =\n streamIdx != null &&\n (streamedMessageIds == null || streamedMessageIds.has(id));\n const streamedMessage = canUseStreamed\n ? currentMessages[streamIdx]\n : undefined;\n\n if (\n streamedMessage != null &&\n preferValuesMessage?.(valuesMessage, streamedMessage) !== true\n ) {\n merged.push(streamedMessage);\n } else {\n merged.push(valuesMessage);\n }\n }\n\n for (const existing of currentMessages) {\n const id = normalizedMessageId(existing);\n if (id == null) continue;\n if (valueMessageIds.has(id)) continue;\n if (previousValueMessageIds.has(id)) continue;\n if (streamedMessageIds != null && !streamedMessageIds.has(id)) continue;\n merged.push(existing);\n }\n\n return {\n messages: messagesEqualList(currentMessages, merged)\n ? currentMessages\n : merged,\n valueMessageIds,\n };\n}\n\n/**\n * Build a position index for keyed messages.\n */\nexport function buildMessageIndex(\n messages: readonly BaseMessage[]\n): Map<string, number> {\n const index = new Map<string, number>();\n messages.forEach((message, idx) => {\n const id = normalizedMessageId(message);\n if (id != null) index.set(id, idx);\n });\n return index;\n}\n\n/**\n * Decide whether a values message carries tool-call data missing from the\n * streamed message.\n */\nexport function shouldPreferValuesMessageForToolCalls(\n valuesMessage: BaseMessage,\n streamedMessage: BaseMessage\n): boolean {\n const valuesToolCalls = getMessageToolCalls(valuesMessage);\n if (valuesToolCalls.length === 0) return false;\n\n const streamedToolCalls = getMessageToolCalls(streamedMessage);\n if (streamedToolCalls.length < valuesToolCalls.length) return true;\n\n const streamedIds = new Set(\n streamedToolCalls\n .map((toolCall) => toolCall.id)\n .filter((id): id is string => typeof id === \"string\" && id.length > 0)\n );\n return valuesToolCalls.some((toolCall) => {\n return typeof toolCall.id === \"string\" && !streamedIds.has(toolCall.id);\n });\n}\n\nexport function messagesEqualList(\n previous: readonly BaseMessage[],\n next: readonly BaseMessage[]\n): boolean {\n if (previous === next) return true;\n if (previous.length !== next.length) return false;\n for (let i = 0; i < previous.length; i += 1) {\n if (!messagesEqual(previous[i], next[i])) return false;\n }\n return true;\n}\n\nexport function messagesEqual(\n previous: BaseMessage | undefined,\n next: BaseMessage | undefined\n): boolean {\n if (previous === next) return true;\n if (previous == null || next == null) return false;\n const previousRecord = previous as unknown as Record<string, unknown>;\n const nextRecord = next as unknown as Record<string, unknown>;\n const previousType =\n typeof previous.getType === \"function\"\n ? previous.getType()\n : previousRecord.type;\n const nextType =\n typeof next.getType === \"function\" ? next.getType() : nextRecord.type;\n\n return (\n previous.id === next.id &&\n previousType === nextType &&\n jsonishEqual(previous.content, next.content) &&\n previousRecord.tool_call_id === nextRecord.tool_call_id &&\n previousRecord.status === nextRecord.status &&\n jsonishEqual(\n previousRecord.additional_kwargs,\n nextRecord.additional_kwargs\n ) &&\n jsonishEqual(\n previousRecord.response_metadata,\n nextRecord.response_metadata\n ) &&\n jsonishEqual(previousRecord.tool_calls, nextRecord.tool_calls) &&\n jsonishEqual(\n previousRecord.tool_call_chunks,\n nextRecord.tool_call_chunks\n ) &&\n jsonishEqual(previousRecord.usage_metadata, nextRecord.usage_metadata)\n );\n}\n\nfunction normalizedMessageId(message: BaseMessage): string | undefined {\n return typeof message.id === \"string\" && message.id.length > 0\n ? message.id\n : undefined;\n}\n\nfunction getMessageToolCalls(\n message: BaseMessage\n): Array<{ id?: string; name?: string }> {\n const raw = (message as unknown as { tool_calls?: unknown }).tool_calls;\n if (!Array.isArray(raw)) return [];\n return raw.filter(\n (toolCall): toolCall is { id?: string; name?: string } =>\n toolCall != null && typeof toolCall === \"object\"\n );\n}\n\nfunction jsonishEqual(previous: unknown, next: unknown): boolean {\n return jsonishEqualAtDepth(previous, next, 0);\n}\n\nfunction jsonishEqualAtDepth(\n previous: unknown,\n next: unknown,\n depth: number\n): boolean {\n if (Object.is(previous, next)) return true;\n if (previous == null || next == null) return false;\n if (typeof previous !== \"object\" || typeof next !== \"object\") return false;\n if (depth >= 4) return false;\n\n if (Array.isArray(previous) || Array.isArray(next)) {\n if (!Array.isArray(previous) || !Array.isArray(next)) return false;\n if (previous.length !== next.length) return false;\n for (let i = 0; i < previous.length; i += 1) {\n if (!jsonishEqualAtDepth(previous[i], next[i], depth + 1)) return false;\n }\n return true;\n }\n\n const previousRecord = previous as Record<string, unknown>;\n const nextRecord = next as Record<string, unknown>;\n const previousKeys = Object.keys(previousRecord).filter(\n (key) => typeof previousRecord[key] !== \"function\"\n );\n const nextKeys = Object.keys(nextRecord).filter(\n (key) => typeof nextRecord[key] !== \"function\"\n );\n if (previousKeys.length !== nextKeys.length) return false;\n\n for (const key of previousKeys) {\n if (!Object.prototype.hasOwnProperty.call(nextRecord, key)) return false;\n if (!jsonishEqualAtDepth(previousRecord[key], nextRecord[key], depth + 1)) {\n return false;\n }\n }\n return true;\n}\n"],"mappings":"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"}
@@ -0,0 +1,54 @@
1
+ require("./constants.cjs");
2
+ //#region src/stream/namespace.ts
3
+ /**
4
+ * Stable string key for a protocol namespace tuple.
5
+ */
6
+ function namespaceKey(namespace) {
7
+ return namespace.join("\0");
8
+ }
9
+ /**
10
+ * True when an event is scoped to the root namespace.
11
+ */
12
+ function isRootNamespace(namespace) {
13
+ return namespace.length === 0;
14
+ }
15
+ /**
16
+ * True when a namespace segment points at a tool execution namespace.
17
+ */
18
+ function isToolNamespaceSegment(segment) {
19
+ return segment.startsWith("tools:");
20
+ }
21
+ /**
22
+ * True when a namespace segment points at a legacy task/subagent namespace.
23
+ */
24
+ function isTaskNamespaceSegment(segment) {
25
+ return segment.startsWith("task:");
26
+ }
27
+ /**
28
+ * True when a namespace belongs to tool/subagent-internal work.
29
+ */
30
+ function isInternalWorkNamespace(namespace) {
31
+ return namespace.some((segment) => isTaskNamespaceSegment(segment) || isToolNamespaceSegment(segment));
32
+ }
33
+ /**
34
+ * True when a namespace includes the legacy task/subagent convention.
35
+ */
36
+ function isLegacySubagentNamespace(namespace) {
37
+ return namespace.some(isTaskNamespaceSegment);
38
+ }
39
+ /**
40
+ * True when the namespace itself is a concrete tool execution namespace.
41
+ */
42
+ function isConcreteToolNamespace(namespace) {
43
+ const last = namespace.at(-1);
44
+ return last != null && isToolNamespaceSegment(last);
45
+ }
46
+ //#endregion
47
+ exports.isConcreteToolNamespace = isConcreteToolNamespace;
48
+ exports.isInternalWorkNamespace = isInternalWorkNamespace;
49
+ exports.isLegacySubagentNamespace = isLegacySubagentNamespace;
50
+ exports.isRootNamespace = isRootNamespace;
51
+ exports.isToolNamespaceSegment = isToolNamespaceSegment;
52
+ exports.namespaceKey = namespaceKey;
53
+
54
+ //# sourceMappingURL=namespace.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"namespace.cjs","names":[],"sources":["../../src/stream/namespace.ts"],"sourcesContent":["import { NAMESPACE_SEPARATOR } from \"./constants.js\";\n\n/**\n * Stable string key for a protocol namespace tuple.\n */\nexport function namespaceKey(namespace: readonly string[]): string {\n return namespace.join(NAMESPACE_SEPARATOR);\n}\n\n/**\n * True when an event is scoped to the root namespace.\n */\nexport function isRootNamespace(namespace: readonly string[]): boolean {\n return namespace.length === 0;\n}\n\n/**\n * True when a namespace segment points at a tool execution namespace.\n */\nexport function isToolNamespaceSegment(segment: string): boolean {\n return segment.startsWith(\"tools:\");\n}\n\n/**\n * True when a namespace segment points at a legacy task/subagent namespace.\n */\nexport function isTaskNamespaceSegment(segment: string): boolean {\n return segment.startsWith(\"task:\");\n}\n\n/**\n * True when a namespace belongs to tool/subagent-internal work.\n */\nexport function isInternalWorkNamespace(namespace: readonly string[]): boolean {\n return namespace.some(\n (segment) =>\n isTaskNamespaceSegment(segment) || isToolNamespaceSegment(segment)\n );\n}\n\n/**\n * True when a namespace includes the legacy task/subagent convention.\n */\nexport function isLegacySubagentNamespace(\n namespace: readonly string[]\n): boolean {\n return namespace.some(isTaskNamespaceSegment);\n}\n\n/**\n * True when the namespace itself is a concrete tool execution namespace.\n */\nexport function isConcreteToolNamespace(namespace: readonly string[]): boolean {\n const last = namespace.at(-1);\n return last != null && isToolNamespaceSegment(last);\n}\n"],"mappings":";;;;;AAKA,SAAgB,aAAa,WAAsC;AACjE,QAAO,UAAU,KAAA,KAAyB;;;;;AAM5C,SAAgB,gBAAgB,WAAuC;AACrE,QAAO,UAAU,WAAW;;;;;AAM9B,SAAgB,uBAAuB,SAA0B;AAC/D,QAAO,QAAQ,WAAW,SAAS;;;;;AAMrC,SAAgB,uBAAuB,SAA0B;AAC/D,QAAO,QAAQ,WAAW,QAAQ;;;;;AAMpC,SAAgB,wBAAwB,WAAuC;AAC7E,QAAO,UAAU,MACd,YACC,uBAAuB,QAAQ,IAAI,uBAAuB,QAAQ,CACrE;;;;;AAMH,SAAgB,0BACd,WACS;AACT,QAAO,UAAU,KAAK,uBAAuB;;;;;AAM/C,SAAgB,wBAAwB,WAAuC;CAC7E,MAAM,OAAO,UAAU,GAAG,GAAG;AAC7B,QAAO,QAAQ,QAAQ,uBAAuB,KAAK"}
@@ -0,0 +1,49 @@
1
+ import "./constants.js";
2
+ //#region src/stream/namespace.ts
3
+ /**
4
+ * Stable string key for a protocol namespace tuple.
5
+ */
6
+ function namespaceKey(namespace) {
7
+ return namespace.join("\0");
8
+ }
9
+ /**
10
+ * True when an event is scoped to the root namespace.
11
+ */
12
+ function isRootNamespace(namespace) {
13
+ return namespace.length === 0;
14
+ }
15
+ /**
16
+ * True when a namespace segment points at a tool execution namespace.
17
+ */
18
+ function isToolNamespaceSegment(segment) {
19
+ return segment.startsWith("tools:");
20
+ }
21
+ /**
22
+ * True when a namespace segment points at a legacy task/subagent namespace.
23
+ */
24
+ function isTaskNamespaceSegment(segment) {
25
+ return segment.startsWith("task:");
26
+ }
27
+ /**
28
+ * True when a namespace belongs to tool/subagent-internal work.
29
+ */
30
+ function isInternalWorkNamespace(namespace) {
31
+ return namespace.some((segment) => isTaskNamespaceSegment(segment) || isToolNamespaceSegment(segment));
32
+ }
33
+ /**
34
+ * True when a namespace includes the legacy task/subagent convention.
35
+ */
36
+ function isLegacySubagentNamespace(namespace) {
37
+ return namespace.some(isTaskNamespaceSegment);
38
+ }
39
+ /**
40
+ * True when the namespace itself is a concrete tool execution namespace.
41
+ */
42
+ function isConcreteToolNamespace(namespace) {
43
+ const last = namespace.at(-1);
44
+ return last != null && isToolNamespaceSegment(last);
45
+ }
46
+ //#endregion
47
+ export { isConcreteToolNamespace, isInternalWorkNamespace, isLegacySubagentNamespace, isRootNamespace, isToolNamespaceSegment, namespaceKey };
48
+
49
+ //# sourceMappingURL=namespace.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"namespace.js","names":[],"sources":["../../src/stream/namespace.ts"],"sourcesContent":["import { NAMESPACE_SEPARATOR } from \"./constants.js\";\n\n/**\n * Stable string key for a protocol namespace tuple.\n */\nexport function namespaceKey(namespace: readonly string[]): string {\n return namespace.join(NAMESPACE_SEPARATOR);\n}\n\n/**\n * True when an event is scoped to the root namespace.\n */\nexport function isRootNamespace(namespace: readonly string[]): boolean {\n return namespace.length === 0;\n}\n\n/**\n * True when a namespace segment points at a tool execution namespace.\n */\nexport function isToolNamespaceSegment(segment: string): boolean {\n return segment.startsWith(\"tools:\");\n}\n\n/**\n * True when a namespace segment points at a legacy task/subagent namespace.\n */\nexport function isTaskNamespaceSegment(segment: string): boolean {\n return segment.startsWith(\"task:\");\n}\n\n/**\n * True when a namespace belongs to tool/subagent-internal work.\n */\nexport function isInternalWorkNamespace(namespace: readonly string[]): boolean {\n return namespace.some(\n (segment) =>\n isTaskNamespaceSegment(segment) || isToolNamespaceSegment(segment)\n );\n}\n\n/**\n * True when a namespace includes the legacy task/subagent convention.\n */\nexport function isLegacySubagentNamespace(\n namespace: readonly string[]\n): boolean {\n return namespace.some(isTaskNamespaceSegment);\n}\n\n/**\n * True when the namespace itself is a concrete tool execution namespace.\n */\nexport function isConcreteToolNamespace(namespace: readonly string[]): boolean {\n const last = namespace.at(-1);\n return last != null && isToolNamespaceSegment(last);\n}\n"],"mappings":";;;;;AAKA,SAAgB,aAAa,WAAsC;AACjE,QAAO,UAAU,KAAA,KAAyB;;;;;AAM5C,SAAgB,gBAAgB,WAAuC;AACrE,QAAO,UAAU,WAAW;;;;;AAM9B,SAAgB,uBAAuB,SAA0B;AAC/D,QAAO,QAAQ,WAAW,SAAS;;;;;AAMrC,SAAgB,uBAAuB,SAA0B;AAC/D,QAAO,QAAQ,WAAW,QAAQ;;;;;AAMpC,SAAgB,wBAAwB,WAAuC;AAC7E,QAAO,UAAU,MACd,YACC,uBAAuB,QAAQ,IAAI,uBAAuB,QAAQ,CACrE;;;;;AAMH,SAAgB,0BACd,WACS;AACT,QAAO,UAAU,KAAK,uBAAuB;;;;;AAM/C,SAAgB,wBAAwB,WAAuC;CAC7E,MAAM,OAAO,UAAU,GAAG,GAAG;AAC7B,QAAO,QAAQ,QAAQ,uBAAuB,KAAK"}
@@ -0,0 +1,53 @@
1
+ const require_namespace = require("../namespace.cjs");
2
+ const require_runtime = require("./runtime.cjs");
3
+ //#region src/stream/projections/channel.ts
4
+ /** Max events retained per raw subscription. Older events are dropped. */
5
+ const DEFAULT_BUFFER = 4096;
6
+ function channelProjection(channels, namespace, options = {}) {
7
+ const chs = [...channels].sort();
8
+ const ns = [...namespace];
9
+ const bufferSize = options.bufferSize ?? DEFAULT_BUFFER;
10
+ const replay = options.replay ?? true;
11
+ return {
12
+ key: `channel|${bufferSize}|${replay ? "replay" : "live"}|${chs.join(",")}|${require_namespace.namespaceKey(ns)}`,
13
+ namespace: ns,
14
+ initial: [],
15
+ open({ thread, store, rootBus }) {
16
+ if (!replay && require_namespace.isRootNamespace(ns) && chs.every((c) => rootBus.channels.includes(c))) {
17
+ const requestedSet = new Set(chs);
18
+ const namedCustom = /* @__PURE__ */ new Set();
19
+ for (const channel of chs) if (channel.startsWith("custom:")) namedCustom.add(channel.slice(7));
20
+ const matches = (event) => {
21
+ if (requestedSet.has(event.method)) return true;
22
+ if (event.method !== "custom" || namedCustom.size === 0) return false;
23
+ const data = event.params.data;
24
+ return typeof data?.name === "string" && namedCustom.has(data.name);
25
+ };
26
+ const push = (event) => {
27
+ if (!matches(event)) return;
28
+ const current = store.getSnapshot();
29
+ const next = current.length >= bufferSize ? [...current.slice(current.length - bufferSize + 1), event] : [...current, event];
30
+ store.setValue(next);
31
+ };
32
+ const unsubscribe = rootBus.subscribe(push);
33
+ return { dispose() {
34
+ unsubscribe();
35
+ } };
36
+ }
37
+ return require_runtime.openProjectionSubscription({
38
+ thread,
39
+ channels: chs,
40
+ namespace: ns,
41
+ onEvent(event) {
42
+ const current = store.getSnapshot();
43
+ const next = current.length >= bufferSize ? [...current.slice(current.length - bufferSize + 1), event] : [...current, event];
44
+ store.setValue(next);
45
+ }
46
+ });
47
+ }
48
+ };
49
+ }
50
+ //#endregion
51
+ exports.channelProjection = channelProjection;
52
+
53
+ //# sourceMappingURL=channel.cjs.map