reactor-effect-client 0.7.0 → 0.8.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 (514) hide show
  1. package/NOTICE +7 -2
  2. package/README.md +103 -141
  3. package/dist/Coordinator.d.ts +382 -0
  4. package/dist/Coordinator.d.ts.map +1 -0
  5. package/dist/Coordinator.js +732 -0
  6. package/dist/Coordinator.js.map +1 -0
  7. package/dist/H3.d.ts +159 -0
  8. package/dist/H3.d.ts.map +1 -0
  9. package/dist/H3.js +21 -0
  10. package/dist/H3.js.map +1 -0
  11. package/dist/H3Source.d.ts +93 -0
  12. package/dist/H3Source.d.ts.map +1 -0
  13. package/dist/H3Source.js +401 -0
  14. package/dist/H3Source.js.map +1 -0
  15. package/dist/LocalSource.d.ts +68 -0
  16. package/dist/LocalSource.d.ts.map +1 -0
  17. package/dist/LocalSource.js +354 -0
  18. package/dist/LocalSource.js.map +1 -0
  19. package/dist/Media.d.ts +106 -0
  20. package/dist/Media.d.ts.map +1 -0
  21. package/dist/Media.js +16 -0
  22. package/dist/Media.js.map +1 -0
  23. package/dist/Peer.d.ts +134 -0
  24. package/dist/Peer.d.ts.map +1 -0
  25. package/dist/Peer.js +57 -0
  26. package/dist/Peer.js.map +1 -0
  27. package/dist/Playout.d.ts +724 -0
  28. package/dist/Playout.d.ts.map +1 -0
  29. package/dist/Playout.js +28 -0
  30. package/dist/Playout.js.map +1 -0
  31. package/dist/Reactor.d.ts +135 -0
  32. package/dist/Reactor.d.ts.map +1 -0
  33. package/dist/Reactor.js +158 -0
  34. package/dist/Reactor.js.map +1 -0
  35. package/dist/ReactorError.d.ts +331 -0
  36. package/dist/ReactorError.d.ts.map +1 -0
  37. package/dist/ReactorError.js +316 -0
  38. package/dist/ReactorError.js.map +1 -0
  39. package/dist/ReactorTest.d.ts +383 -0
  40. package/dist/ReactorTest.d.ts.map +1 -0
  41. package/dist/ReactorTest.js +317 -0
  42. package/dist/ReactorTest.js.map +1 -0
  43. package/dist/Session.d.ts +314 -0
  44. package/dist/Session.d.ts.map +1 -0
  45. package/dist/Session.js +51 -0
  46. package/dist/Session.js.map +1 -0
  47. package/dist/index.d.ts +12 -22
  48. package/dist/index.d.ts.map +1 -1
  49. package/dist/index.js +12 -11
  50. package/dist/index.js.map +1 -1
  51. package/dist/internal/correlator.d.ts +46 -0
  52. package/dist/internal/correlator.d.ts.map +1 -0
  53. package/dist/internal/correlator.js +150 -0
  54. package/dist/internal/correlator.js.map +1 -0
  55. package/dist/internal/deadline.d.ts +24 -0
  56. package/dist/internal/deadline.d.ts.map +1 -0
  57. package/dist/internal/deadline.js +44 -0
  58. package/dist/internal/deadline.js.map +1 -0
  59. package/dist/{h3/_internal/contracts.d.ts → internal/h3/commands.d.ts} +39 -33
  60. package/dist/internal/h3/commands.d.ts.map +1 -0
  61. package/dist/internal/h3/commands.js +128 -0
  62. package/dist/internal/h3/commands.js.map +1 -0
  63. package/dist/{h3 → internal/h3}/messages.d.ts +16 -11
  64. package/dist/internal/h3/messages.d.ts.map +1 -0
  65. package/dist/{h3 → internal/h3}/messages.js +19 -31
  66. package/dist/internal/h3/messages.js.map +1 -0
  67. package/dist/internal/h3/operations.d.ts +145 -0
  68. package/dist/internal/h3/operations.d.ts.map +1 -0
  69. package/dist/internal/h3/operations.js +284 -0
  70. package/dist/internal/h3/operations.js.map +1 -0
  71. package/dist/{h3 → internal/h3}/profile.d.ts +63 -65
  72. package/dist/internal/h3/profile.d.ts.map +1 -0
  73. package/dist/{h3 → internal/h3}/profile.js +39 -39
  74. package/dist/internal/h3/profile.js.map +1 -0
  75. package/dist/internal/h3/provider.d.ts +14 -0
  76. package/dist/internal/h3/provider.d.ts.map +1 -0
  77. package/dist/internal/h3/provider.js +672 -0
  78. package/dist/internal/h3/provider.js.map +1 -0
  79. package/dist/internal/h3/references.d.ts +68 -0
  80. package/dist/internal/h3/references.d.ts.map +1 -0
  81. package/dist/internal/h3/references.js +339 -0
  82. package/dist/internal/h3/references.js.map +1 -0
  83. package/dist/internal/h3/request.d.ts +56 -0
  84. package/dist/internal/h3/request.d.ts.map +1 -0
  85. package/dist/internal/h3/request.js +70 -0
  86. package/dist/internal/h3/request.js.map +1 -0
  87. package/dist/internal/h3/state.d.ts +120 -0
  88. package/dist/internal/h3/state.d.ts.map +1 -0
  89. package/dist/internal/h3/state.js +270 -0
  90. package/dist/internal/h3/state.js.map +1 -0
  91. package/dist/{Submission.d.ts → internal/h3/submission.d.ts} +1 -3
  92. package/dist/internal/h3/submission.d.ts.map +1 -0
  93. package/dist/{Submission.js → internal/h3/submission.js} +1 -9
  94. package/dist/internal/h3/submission.js.map +1 -0
  95. package/dist/internal/hub.d.ts +32 -0
  96. package/dist/internal/hub.d.ts.map +1 -0
  97. package/dist/internal/hub.js +92 -0
  98. package/dist/internal/hub.js.map +1 -0
  99. package/dist/internal/playout/errors.d.ts +51 -0
  100. package/dist/internal/playout/errors.d.ts.map +1 -0
  101. package/dist/internal/playout/errors.js +40 -0
  102. package/dist/internal/playout/errors.js.map +1 -0
  103. package/dist/internal/playout/policy.d.ts +559 -0
  104. package/dist/internal/playout/policy.d.ts.map +1 -0
  105. package/dist/internal/playout/policy.js +2338 -0
  106. package/dist/internal/playout/policy.js.map +1 -0
  107. package/dist/internal/playout/runtime.d.ts +28 -0
  108. package/dist/internal/playout/runtime.d.ts.map +1 -0
  109. package/dist/internal/playout/runtime.js +766 -0
  110. package/dist/internal/playout/runtime.js.map +1 -0
  111. package/dist/internal/playout/tag.d.ts +14 -0
  112. package/dist/internal/playout/tag.d.ts.map +1 -0
  113. package/dist/internal/playout/tag.js +43 -0
  114. package/dist/internal/playout/tag.js.map +1 -0
  115. package/dist/internal/proto/reactor_wire/v1/common_pb.d.ts +55 -0
  116. package/dist/internal/proto/reactor_wire/v1/common_pb.d.ts.map +1 -0
  117. package/dist/internal/proto/reactor_wire/v1/common_pb.js +42 -0
  118. package/dist/internal/proto/reactor_wire/v1/common_pb.js.map +1 -0
  119. package/dist/internal/proto/reactor_wire/v1/control_pb.d.ts +160 -0
  120. package/dist/internal/proto/reactor_wire/v1/control_pb.d.ts.map +1 -0
  121. package/dist/internal/proto/reactor_wire/v1/control_pb.js +21 -0
  122. package/dist/internal/proto/reactor_wire/v1/control_pb.js.map +1 -0
  123. package/dist/internal/proto/reactor_wire/v1/data_pb.d.ts +89 -0
  124. package/dist/internal/proto/reactor_wire/v1/data_pb.d.ts.map +1 -0
  125. package/dist/internal/proto/reactor_wire/v1/data_pb.js +20 -0
  126. package/dist/internal/proto/reactor_wire/v1/data_pb.js.map +1 -0
  127. package/dist/internal/proto/reactor_wire/v1/model_pb.d.ts +85 -0
  128. package/dist/internal/proto/reactor_wire/v1/model_pb.d.ts.map +1 -0
  129. package/dist/internal/proto/reactor_wire/v1/model_pb.js +24 -0
  130. package/dist/internal/proto/reactor_wire/v1/model_pb.js.map +1 -0
  131. package/dist/internal/proto/reactor_wire/v1/platform_pb.d.ts +190 -0
  132. package/dist/internal/proto/reactor_wire/v1/platform_pb.d.ts.map +1 -0
  133. package/dist/internal/proto/reactor_wire/v1/platform_pb.js +54 -0
  134. package/dist/internal/proto/reactor_wire/v1/platform_pb.js.map +1 -0
  135. package/dist/internal/proto/reactor_wire/v1/track_pb.d.ts +88 -0
  136. package/dist/internal/proto/reactor_wire/v1/track_pb.d.ts.map +1 -0
  137. package/dist/internal/proto/reactor_wire/v1/track_pb.js +33 -0
  138. package/dist/internal/proto/reactor_wire/v1/track_pb.js.map +1 -0
  139. package/dist/internal/queue.d.ts +4 -0
  140. package/dist/internal/queue.d.ts.map +1 -0
  141. package/dist/{_internal → internal}/queue.js +0 -9
  142. package/dist/internal/queue.js.map +1 -0
  143. package/dist/internal/reactorTest/coordinator.d.ts +5 -0
  144. package/dist/internal/reactorTest/coordinator.d.ts.map +1 -0
  145. package/dist/internal/reactorTest/coordinator.js +178 -0
  146. package/dist/internal/reactorTest/coordinator.js.map +1 -0
  147. package/dist/internal/reactorTest/faults.d.ts +172 -0
  148. package/dist/internal/reactorTest/faults.d.ts.map +1 -0
  149. package/dist/internal/reactorTest/faults.js +23 -0
  150. package/dist/internal/reactorTest/faults.js.map +1 -0
  151. package/dist/internal/reactorTest/h3.d.ts +431 -0
  152. package/dist/internal/reactorTest/h3.d.ts.map +1 -0
  153. package/dist/internal/reactorTest/h3.js +625 -0
  154. package/dist/internal/reactorTest/h3.js.map +1 -0
  155. package/dist/internal/reactorTest/media.d.ts +22 -0
  156. package/dist/internal/reactorTest/media.d.ts.map +1 -0
  157. package/dist/internal/reactorTest/media.js +34 -0
  158. package/dist/internal/reactorTest/media.js.map +1 -0
  159. package/dist/internal/reactorTest/peer.d.ts +318 -0
  160. package/dist/internal/reactorTest/peer.d.ts.map +1 -0
  161. package/dist/internal/reactorTest/peer.js +206 -0
  162. package/dist/internal/reactorTest/peer.js.map +1 -0
  163. package/dist/internal/reactorTest/playout.d.ts +34 -0
  164. package/dist/internal/reactorTest/playout.d.ts.map +1 -0
  165. package/dist/internal/reactorTest/playout.js +340 -0
  166. package/dist/internal/reactorTest/playout.js.map +1 -0
  167. package/dist/internal/reactorTest/references.d.ts +25 -0
  168. package/dist/internal/reactorTest/references.d.ts.map +1 -0
  169. package/dist/{testing/Png.js → internal/reactorTest/references.js} +50 -12
  170. package/dist/internal/reactorTest/references.js.map +1 -0
  171. package/dist/internal/reactorTest/sessions.d.ts +364 -0
  172. package/dist/internal/reactorTest/sessions.d.ts.map +1 -0
  173. package/dist/internal/reactorTest/sessions.js +592 -0
  174. package/dist/internal/reactorTest/sessions.js.map +1 -0
  175. package/dist/internal/reactorTest/timing.d.ts +13 -0
  176. package/dist/internal/reactorTest/timing.d.ts.map +1 -0
  177. package/dist/internal/reactorTest/timing.js +20 -0
  178. package/dist/internal/reactorTest/timing.js.map +1 -0
  179. package/dist/internal/recording.d.ts +52 -0
  180. package/dist/internal/recording.d.ts.map +1 -0
  181. package/dist/internal/recording.js +141 -0
  182. package/dist/internal/recording.js.map +1 -0
  183. package/dist/internal/session/connect.d.ts +34 -0
  184. package/dist/internal/session/connect.d.ts.map +1 -0
  185. package/dist/internal/session/connect.js +502 -0
  186. package/dist/internal/session/connect.js.map +1 -0
  187. package/dist/internal/session/generation.d.ts +35 -0
  188. package/dist/internal/session/generation.d.ts.map +1 -0
  189. package/dist/internal/session/generation.js +185 -0
  190. package/dist/internal/session/generation.js.map +1 -0
  191. package/dist/internal/session/ice.d.ts +23 -0
  192. package/dist/internal/session/ice.d.ts.map +1 -0
  193. package/dist/internal/session/ice.js +57 -0
  194. package/dist/internal/session/ice.js.map +1 -0
  195. package/dist/internal/session/inbound.d.ts +50 -0
  196. package/dist/internal/session/inbound.d.ts.map +1 -0
  197. package/dist/internal/session/inbound.js +202 -0
  198. package/dist/internal/session/inbound.js.map +1 -0
  199. package/dist/internal/session/model.d.ts +163 -0
  200. package/dist/internal/session/model.d.ts.map +1 -0
  201. package/dist/internal/session/model.js +78 -0
  202. package/dist/internal/session/model.js.map +1 -0
  203. package/dist/internal/session/requests.d.ts +71 -0
  204. package/dist/internal/session/requests.d.ts.map +1 -0
  205. package/dist/internal/session/requests.js +240 -0
  206. package/dist/internal/session/requests.js.map +1 -0
  207. package/dist/internal/session/tracks.d.ts +21 -0
  208. package/dist/internal/session/tracks.d.ts.map +1 -0
  209. package/dist/internal/session/tracks.js +166 -0
  210. package/dist/internal/session/tracks.js.map +1 -0
  211. package/dist/internal/session/upload.d.ts +21 -0
  212. package/dist/internal/session/upload.d.ts.map +1 -0
  213. package/dist/internal/session/upload.js +68 -0
  214. package/dist/internal/session/upload.js.map +1 -0
  215. package/dist/internal/session.d.ts +66 -0
  216. package/dist/internal/session.d.ts.map +1 -0
  217. package/dist/internal/session.js +280 -0
  218. package/dist/internal/session.js.map +1 -0
  219. package/dist/{stats.d.ts → internal/stats.d.ts} +30 -16
  220. package/dist/internal/stats.d.ts.map +1 -0
  221. package/dist/internal/stats.js +201 -0
  222. package/dist/internal/stats.js.map +1 -0
  223. package/dist/internal/token.d.ts +22 -0
  224. package/dist/internal/token.d.ts.map +1 -0
  225. package/dist/internal/token.js +65 -0
  226. package/dist/internal/token.js.map +1 -0
  227. package/dist/internal/wire.d.ts +37 -0
  228. package/dist/internal/wire.d.ts.map +1 -0
  229. package/dist/internal/wire.js +49 -0
  230. package/dist/internal/wire.js.map +1 -0
  231. package/notices/bufbuild-protobuf-LICENSE +201 -0
  232. package/package.json +17 -38
  233. package/dist/FetchHttp.d.ts +0 -9
  234. package/dist/FetchHttp.d.ts.map +0 -1
  235. package/dist/FetchHttp.js +0 -63
  236. package/dist/FetchHttp.js.map +0 -1
  237. package/dist/PeerFactory.d.ts +0 -26
  238. package/dist/PeerFactory.d.ts.map +0 -1
  239. package/dist/PeerFactory.js +0 -4
  240. package/dist/PeerFactory.js.map +0 -1
  241. package/dist/PeerTypes.d.ts +0 -64
  242. package/dist/PeerTypes.d.ts.map +0 -1
  243. package/dist/PeerTypes.js +0 -2
  244. package/dist/PeerTypes.js.map +0 -1
  245. package/dist/Sequence.d.ts +0 -85
  246. package/dist/Sequence.d.ts.map +0 -1
  247. package/dist/Sequence.js +0 -210
  248. package/dist/Sequence.js.map +0 -1
  249. package/dist/SessionTypes.d.ts +0 -312
  250. package/dist/SessionTypes.d.ts.map +0 -1
  251. package/dist/SessionTypes.js +0 -19
  252. package/dist/SessionTypes.js.map +0 -1
  253. package/dist/Submission.d.ts.map +0 -1
  254. package/dist/Submission.js.map +0 -1
  255. package/dist/_internal/queue.d.ts +0 -6
  256. package/dist/_internal/queue.d.ts.map +0 -1
  257. package/dist/_internal/queue.js.map +0 -1
  258. package/dist/bytes.d.ts +0 -6
  259. package/dist/bytes.d.ts.map +0 -1
  260. package/dist/bytes.js +0 -32
  261. package/dist/bytes.js.map +0 -1
  262. package/dist/contract.d.ts +0 -149
  263. package/dist/contract.d.ts.map +0 -1
  264. package/dist/contract.js +0 -119
  265. package/dist/contract.js.map +0 -1
  266. package/dist/coordinator/_internal/client.d.ts +0 -215
  267. package/dist/coordinator/_internal/client.d.ts.map +0 -1
  268. package/dist/coordinator/_internal/client.js +0 -563
  269. package/dist/coordinator/_internal/client.js.map +0 -1
  270. package/dist/coordinator/_internal/recording.d.ts +0 -31
  271. package/dist/coordinator/_internal/recording.d.ts.map +0 -1
  272. package/dist/coordinator/_internal/recording.js +0 -123
  273. package/dist/coordinator/_internal/recording.js.map +0 -1
  274. package/dist/coordinator/_internal/response.d.ts +0 -15
  275. package/dist/coordinator/_internal/response.d.ts.map +0 -1
  276. package/dist/coordinator/_internal/response.js +0 -55
  277. package/dist/coordinator/_internal/response.js.map +0 -1
  278. package/dist/coordinator/_internal/schemas.d.ts +0 -73
  279. package/dist/coordinator/_internal/schemas.d.ts.map +0 -1
  280. package/dist/coordinator/_internal/schemas.js +0 -200
  281. package/dist/coordinator/_internal/schemas.js.map +0 -1
  282. package/dist/coordinator/index.d.ts +0 -40
  283. package/dist/coordinator/index.d.ts.map +0 -1
  284. package/dist/coordinator/index.js +0 -21
  285. package/dist/coordinator/index.js.map +0 -1
  286. package/dist/correlation.d.ts +0 -47
  287. package/dist/correlation.d.ts.map +0 -1
  288. package/dist/correlation.js +0 -131
  289. package/dist/correlation.js.map +0 -1
  290. package/dist/duration.d.ts +0 -27
  291. package/dist/duration.d.ts.map +0 -1
  292. package/dist/duration.js +0 -47
  293. package/dist/duration.js.map +0 -1
  294. package/dist/errors.d.ts +0 -1303
  295. package/dist/errors.d.ts.map +0 -1
  296. package/dist/errors.js +0 -745
  297. package/dist/errors.js.map +0 -1
  298. package/dist/h3/_internal/client.d.ts +0 -9
  299. package/dist/h3/_internal/client.d.ts.map +0 -1
  300. package/dist/h3/_internal/client.js +0 -652
  301. package/dist/h3/_internal/client.js.map +0 -1
  302. package/dist/h3/_internal/contracts.d.ts.map +0 -1
  303. package/dist/h3/_internal/contracts.js +0 -123
  304. package/dist/h3/_internal/contracts.js.map +0 -1
  305. package/dist/h3/_internal/deployment.d.ts +0 -8
  306. package/dist/h3/_internal/deployment.d.ts.map +0 -1
  307. package/dist/h3/_internal/deployment.js +0 -149
  308. package/dist/h3/_internal/deployment.js.map +0 -1
  309. package/dist/h3/_internal/evidence.d.ts +0 -17
  310. package/dist/h3/_internal/evidence.d.ts.map +0 -1
  311. package/dist/h3/_internal/evidence.js +0 -48
  312. package/dist/h3/_internal/evidence.js.map +0 -1
  313. package/dist/h3/_internal/operations.d.ts +0 -58
  314. package/dist/h3/_internal/operations.d.ts.map +0 -1
  315. package/dist/h3/_internal/operations.js +0 -268
  316. package/dist/h3/_internal/operations.js.map +0 -1
  317. package/dist/h3/_internal/references.d.ts +0 -24
  318. package/dist/h3/_internal/references.d.ts.map +0 -1
  319. package/dist/h3/_internal/references.js +0 -309
  320. package/dist/h3/_internal/references.js.map +0 -1
  321. package/dist/h3/_internal/request.d.ts +0 -21
  322. package/dist/h3/_internal/request.d.ts.map +0 -1
  323. package/dist/h3/_internal/request.js +0 -97
  324. package/dist/h3/_internal/request.js.map +0 -1
  325. package/dist/h3/_internal/retained.d.ts +0 -22
  326. package/dist/h3/_internal/retained.d.ts.map +0 -1
  327. package/dist/h3/_internal/retained.js +0 -89
  328. package/dist/h3/_internal/retained.js.map +0 -1
  329. package/dist/h3/_internal/state.d.ts +0 -44
  330. package/dist/h3/_internal/state.d.ts.map +0 -1
  331. package/dist/h3/_internal/state.js +0 -283
  332. package/dist/h3/_internal/state.js.map +0 -1
  333. package/dist/h3/index.d.ts +0 -10
  334. package/dist/h3/index.d.ts.map +0 -1
  335. package/dist/h3/index.js +0 -7
  336. package/dist/h3/index.js.map +0 -1
  337. package/dist/h3/messages.d.ts.map +0 -1
  338. package/dist/h3/messages.js.map +0 -1
  339. package/dist/h3/profile.d.ts.map +0 -1
  340. package/dist/h3/profile.js.map +0 -1
  341. package/dist/h3/types.d.ts +0 -291
  342. package/dist/h3/types.d.ts.map +0 -1
  343. package/dist/h3/types.js +0 -2
  344. package/dist/h3/types.js.map +0 -1
  345. package/dist/host.d.ts +0 -26
  346. package/dist/host.d.ts.map +0 -1
  347. package/dist/host.js +0 -20
  348. package/dist/host.js.map +0 -1
  349. package/dist/json.d.ts +0 -25
  350. package/dist/json.d.ts.map +0 -1
  351. package/dist/json.js +0 -143
  352. package/dist/json.js.map +0 -1
  353. package/dist/media-stream.d.ts +0 -10
  354. package/dist/media-stream.d.ts.map +0 -1
  355. package/dist/media-stream.js +0 -18
  356. package/dist/media-stream.js.map +0 -1
  357. package/dist/observation.d.ts +0 -38
  358. package/dist/observation.d.ts.map +0 -1
  359. package/dist/observation.js +0 -113
  360. package/dist/observation.js.map +0 -1
  361. package/dist/orchestration/elapsed.d.ts +0 -9
  362. package/dist/orchestration/elapsed.d.ts.map +0 -1
  363. package/dist/orchestration/elapsed.js +0 -8
  364. package/dist/orchestration/elapsed.js.map +0 -1
  365. package/dist/orchestration/h3-source.d.ts +0 -58
  366. package/dist/orchestration/h3-source.d.ts.map +0 -1
  367. package/dist/orchestration/h3-source.js +0 -362
  368. package/dist/orchestration/h3-source.js.map +0 -1
  369. package/dist/orchestration/index.d.ts +0 -17
  370. package/dist/orchestration/index.d.ts.map +0 -1
  371. package/dist/orchestration/index.js +0 -12
  372. package/dist/orchestration/index.js.map +0 -1
  373. package/dist/orchestration/media-buffer.d.ts +0 -32
  374. package/dist/orchestration/media-buffer.d.ts.map +0 -1
  375. package/dist/orchestration/media-buffer.js +0 -94
  376. package/dist/orchestration/media-buffer.js.map +0 -1
  377. package/dist/orchestration/open-h3.d.ts +0 -101
  378. package/dist/orchestration/open-h3.d.ts.map +0 -1
  379. package/dist/orchestration/open-h3.js +0 -127
  380. package/dist/orchestration/open-h3.js.map +0 -1
  381. package/dist/orchestration/queries.d.ts +0 -10
  382. package/dist/orchestration/queries.d.ts.map +0 -1
  383. package/dist/orchestration/queries.js +0 -43
  384. package/dist/orchestration/queries.js.map +0 -1
  385. package/dist/orchestration/references.d.ts +0 -18
  386. package/dist/orchestration/references.d.ts.map +0 -1
  387. package/dist/orchestration/references.js +0 -79
  388. package/dist/orchestration/references.js.map +0 -1
  389. package/dist/orchestration/renewal-state.d.ts +0 -84
  390. package/dist/orchestration/renewal-state.d.ts.map +0 -1
  391. package/dist/orchestration/renewal-state.js +0 -95
  392. package/dist/orchestration/renewal-state.js.map +0 -1
  393. package/dist/orchestration/renewal.d.ts +0 -103
  394. package/dist/orchestration/renewal.d.ts.map +0 -1
  395. package/dist/orchestration/renewal.js +0 -1088
  396. package/dist/orchestration/renewal.js.map +0 -1
  397. package/dist/orchestration/request.d.ts +0 -65
  398. package/dist/orchestration/request.d.ts.map +0 -1
  399. package/dist/orchestration/request.js +0 -134
  400. package/dist/orchestration/request.js.map +0 -1
  401. package/dist/orchestration/retention.d.ts +0 -100
  402. package/dist/orchestration/retention.d.ts.map +0 -1
  403. package/dist/orchestration/retention.js +0 -134
  404. package/dist/orchestration/retention.js.map +0 -1
  405. package/dist/orchestration/routing.d.ts +0 -21
  406. package/dist/orchestration/routing.d.ts.map +0 -1
  407. package/dist/orchestration/routing.js +0 -93
  408. package/dist/orchestration/routing.js.map +0 -1
  409. package/dist/orchestration/scheduler-key.d.ts +0 -14
  410. package/dist/orchestration/scheduler-key.d.ts.map +0 -1
  411. package/dist/orchestration/scheduler-key.js +0 -62
  412. package/dist/orchestration/scheduler-key.js.map +0 -1
  413. package/dist/orchestration/scheduler-policy.d.ts +0 -222
  414. package/dist/orchestration/scheduler-policy.d.ts.map +0 -1
  415. package/dist/orchestration/scheduler-policy.js +0 -582
  416. package/dist/orchestration/scheduler-policy.js.map +0 -1
  417. package/dist/orchestration/scheduler.d.ts +0 -383
  418. package/dist/orchestration/scheduler.d.ts.map +0 -1
  419. package/dist/orchestration/scheduler.js +0 -2597
  420. package/dist/orchestration/scheduler.js.map +0 -1
  421. package/dist/orchestration/source-slot.d.ts +0 -124
  422. package/dist/orchestration/source-slot.d.ts.map +0 -1
  423. package/dist/orchestration/source-slot.js +0 -348
  424. package/dist/orchestration/source-slot.js.map +0 -1
  425. package/dist/orchestration/types.d.ts +0 -1462
  426. package/dist/orchestration/types.d.ts.map +0 -1
  427. package/dist/orchestration/types.js +0 -135
  428. package/dist/orchestration/types.js.map +0 -1
  429. package/dist/protobuf.d.ts +0 -63
  430. package/dist/protobuf.d.ts.map +0 -1
  431. package/dist/protobuf.js +0 -252
  432. package/dist/protobuf.js.map +0 -1
  433. package/dist/session/_internal/acquire.d.ts +0 -21
  434. package/dist/session/_internal/acquire.d.ts.map +0 -1
  435. package/dist/session/_internal/acquire.js +0 -168
  436. package/dist/session/_internal/acquire.js.map +0 -1
  437. package/dist/session/_internal/cleanup.d.ts +0 -19
  438. package/dist/session/_internal/cleanup.d.ts.map +0 -1
  439. package/dist/session/_internal/cleanup.js +0 -102
  440. package/dist/session/_internal/cleanup.js.map +0 -1
  441. package/dist/session/_internal/lifecycle.d.ts +0 -67
  442. package/dist/session/_internal/lifecycle.d.ts.map +0 -1
  443. package/dist/session/_internal/lifecycle.js +0 -142
  444. package/dist/session/_internal/lifecycle.js.map +0 -1
  445. package/dist/session/_internal/remote.d.ts +0 -28
  446. package/dist/session/_internal/remote.d.ts.map +0 -1
  447. package/dist/session/_internal/remote.js +0 -71
  448. package/dist/session/_internal/remote.js.map +0 -1
  449. package/dist/session/_internal/uploads.d.ts +0 -7
  450. package/dist/session/_internal/uploads.d.ts.map +0 -1
  451. package/dist/session/_internal/uploads.js +0 -31
  452. package/dist/session/_internal/uploads.js.map +0 -1
  453. package/dist/session/commands.d.ts +0 -2
  454. package/dist/session/commands.d.ts.map +0 -1
  455. package/dist/session/commands.js +0 -2
  456. package/dist/session/commands.js.map +0 -1
  457. package/dist/session/files.d.ts +0 -21
  458. package/dist/session/files.d.ts.map +0 -1
  459. package/dist/session/files.js +0 -49
  460. package/dist/session/files.js.map +0 -1
  461. package/dist/session/index.d.ts +0 -84
  462. package/dist/session/index.d.ts.map +0 -1
  463. package/dist/session/index.js +0 -16
  464. package/dist/session/index.js.map +0 -1
  465. package/dist/session/media.d.ts +0 -114
  466. package/dist/session/media.d.ts.map +0 -1
  467. package/dist/session/media.js +0 -2
  468. package/dist/session/media.js.map +0 -1
  469. package/dist/session/recorder.d.ts +0 -24
  470. package/dist/session/recorder.d.ts.map +0 -1
  471. package/dist/session/recorder.js +0 -19
  472. package/dist/session/recorder.js.map +0 -1
  473. package/dist/session.d.ts +0 -105
  474. package/dist/session.d.ts.map +0 -1
  475. package/dist/session.js +0 -976
  476. package/dist/session.js.map +0 -1
  477. package/dist/simulation/_internal/source.d.ts +0 -12
  478. package/dist/simulation/_internal/source.d.ts.map +0 -1
  479. package/dist/simulation/_internal/source.js +0 -513
  480. package/dist/simulation/_internal/source.js.map +0 -1
  481. package/dist/simulation/index.d.ts +0 -13
  482. package/dist/simulation/index.d.ts.map +0 -1
  483. package/dist/simulation/index.js +0 -12
  484. package/dist/simulation/index.js.map +0 -1
  485. package/dist/simulation/types.d.ts +0 -39
  486. package/dist/simulation/types.d.ts.map +0 -1
  487. package/dist/simulation/types.js +0 -2
  488. package/dist/simulation/types.js.map +0 -1
  489. package/dist/stats.d.ts.map +0 -1
  490. package/dist/stats.js +0 -205
  491. package/dist/stats.js.map +0 -1
  492. package/dist/testing/Faults.d.ts +0 -4
  493. package/dist/testing/Faults.d.ts.map +0 -1
  494. package/dist/testing/Faults.js +0 -7
  495. package/dist/testing/Faults.js.map +0 -1
  496. package/dist/testing/Png.d.ts +0 -3
  497. package/dist/testing/Png.d.ts.map +0 -1
  498. package/dist/testing/Png.js.map +0 -1
  499. package/dist/testing/Wav.d.ts +0 -14
  500. package/dist/testing/Wav.d.ts.map +0 -1
  501. package/dist/testing/Wav.js +0 -37
  502. package/dist/testing/Wav.js.map +0 -1
  503. package/dist/testing/index.d.ts +0 -5
  504. package/dist/testing/index.d.ts.map +0 -1
  505. package/dist/testing/index.js +0 -4
  506. package/dist/testing/index.js.map +0 -1
  507. package/dist/wire.d.ts +0 -7
  508. package/dist/wire.d.ts.map +0 -1
  509. package/dist/wire.generated.d.ts +0 -305
  510. package/dist/wire.generated.d.ts.map +0 -1
  511. package/dist/wire.generated.js +0 -1257
  512. package/dist/wire.generated.js.map +0 -1
  513. package/dist/wire.js +0 -5
  514. package/dist/wire.js.map +0 -1
@@ -0,0 +1,732 @@
1
+ /**
2
+ * Reactor's HTTP API: pricing, tokens, inspection, termination, recordings,
3
+ * and the signaling a session runs. Built over the application's
4
+ * `HttpClient`; constructing it makes no request.
5
+ */
6
+ import * as Arr from "effect/Array";
7
+ import * as Clock from "effect/Clock";
8
+ import * as Config from "effect/Config";
9
+ import * as Context from "effect/Context";
10
+ import * as Duration from "effect/Duration";
11
+ import * as Effect from "effect/Effect";
12
+ import * as Layer from "effect/Layer";
13
+ import * as Option from "effect/Option";
14
+ import * as Predicate from "effect/Predicate";
15
+ import * as Redacted from "effect/Redacted";
16
+ import * as Ref from "effect/Ref";
17
+ import * as Schedule from "effect/Schedule";
18
+ import * as Schema from "effect/Schema";
19
+ import * as SchemaTransformation from "effect/SchemaTransformation";
20
+ import * as Stream from "effect/Stream";
21
+ import * as FetchHttpClient from "effect/unstable/http/FetchHttpClient";
22
+ import * as Headers from "effect/unstable/http/Headers";
23
+ import * as HttpClient from "effect/unstable/http/HttpClient";
24
+ import * as HttpClientRequest from "effect/unstable/http/HttpClientRequest";
25
+ import * as Recording from "./internal/recording.js";
26
+ import { FailureSummary, Http, ReactorError, summarize } from "./ReactorError.js";
27
+ export const defaultApiUrl = "https://api.reactor.inc";
28
+ const clientInfo = { sdk_version: "0.8.0", sdk_type: "typescript-effect-independent" };
29
+ /** A field the provider sends as `null` or omits for the same fact decodes as absent. */
30
+ const NullAsAbsent = (schema) => schema.pipe(Schema.NullOr, Schema.optionalKey, Schema.decodeTo(Schema.toType(schema).pipe(Schema.optionalKey), SchemaTransformation.transformOptional({
31
+ decode: Option.filter(Predicate.isNotNull),
32
+ encode: (value) => value,
33
+ })));
34
+ const Uint32 = Schema.Int.check(Schema.isBetween({ minimum: 0, maximum: 0xffffffff }));
35
+ const PositiveInt = Schema.Int.check(Schema.isGreaterThan(0));
36
+ export const Track = Schema.Struct({
37
+ name: Schema.NonEmptyString,
38
+ kind: Schema.Literals(["audio", "video"]),
39
+ direction: Schema.Literals(["recvonly", "sendonly"]),
40
+ });
41
+ /** A track and the media section a host negotiated for it. */
42
+ export const Mapping = Schema.Struct({ ...Track.fields, mid: Schema.String });
43
+ export const Capabilities = Schema.Struct({
44
+ protocol_version: Schema.NonEmptyString,
45
+ tracks: Schema.Array(Track).check(Schema.isMaxLength(64), Schema.makeFilter((tracks) => new Set(tracks.map((track) => track.name)).size === tracks.length
46
+ ? undefined
47
+ : "duplicate track names are ambiguous for named track operations")),
48
+ commands: Schema.Struct({
49
+ name: Schema.NonEmptyString,
50
+ description: NullAsAbsent(Schema.String),
51
+ schema: Schema.optionalKey(Schema.Json),
52
+ }).pipe(Schema.Array, NullAsAbsent),
53
+ emission_fps: NullAsAbsent(Schema.Finite),
54
+ });
55
+ export const Transport = Schema.Struct({
56
+ protocol: Schema.NonEmptyString,
57
+ version: Schema.NonEmptyString,
58
+ });
59
+ /** A session as the coordinator describes it; unknown states stay as they are. */
60
+ export const Descriptor = Schema.Struct({
61
+ session_id: Schema.NonEmptyString,
62
+ state: Schema.NonEmptyString,
63
+ capabilities: NullAsAbsent(Capabilities),
64
+ selected_transport: NullAsAbsent(Transport),
65
+ });
66
+ /**
67
+ * Whether a session state is final. Only `CLOSED` is: hosted Reactor reads
68
+ * `INACTIVE` for a session whose last connection dropped, and that session still
69
+ * runs (and bills) for the documented 30 s reconnect window. A paid run adopted
70
+ * one 9 s after its owner was killed, then ended it with a DELETE that
71
+ * answered 200 and moved it to `CLOSED`.
72
+ */
73
+ export const isTerminal = (state) => state === "CLOSED";
74
+ export const IceServer = Schema.Struct({
75
+ urls: Schema.Array(Schema.NonEmptyString),
76
+ username: Schema.optionalKey(Schema.String),
77
+ credential: Schema.optionalKey(Schema.String),
78
+ });
79
+ /** The coordinator's ICE server list, as it sends it. */
80
+ export const IceServersReply = Schema.Struct({
81
+ ice_servers: Schema.Array(Schema.Struct({
82
+ uris: Schema.Array(Schema.NonEmptyString),
83
+ credentials: NullAsAbsent(Schema.Struct({ username: Schema.String, password: Schema.String })),
84
+ })).check(Schema.isMaxLength(64)),
85
+ });
86
+ export const IceCandidate = Schema.Struct({
87
+ candidate: Schema.String,
88
+ sdp_mid: Schema.optionalKey(Schema.String),
89
+ sdp_mline_index: Schema.optionalKey(Schema.Int),
90
+ });
91
+ const Allocated = Schema.Struct({ session_id: Schema.NonEmptyString });
92
+ export const Registered = Schema.Struct({ connection_id: Uint32 });
93
+ export const SdpAnswer = Schema.Struct({
94
+ sdp_answer: Schema.NonEmptyString,
95
+ connection_id: NullAsAbsent(Uint32),
96
+ });
97
+ export const UploadSlot = Schema.Struct({
98
+ presigned_id: Schema.NonEmptyString,
99
+ presigned_url: Schema.NonEmptyString,
100
+ path: Schema.String,
101
+ });
102
+ /**
103
+ * A remote termination verdict. A DELETE response alone is never proof: an
104
+ * independent read confirms the session is gone or terminal.
105
+ */
106
+ export const Termination = Schema.Struct({
107
+ attempted: Schema.Boolean,
108
+ responseReceived: Schema.Boolean,
109
+ confirmed: Schema.Boolean,
110
+ evidence: Schema.NullOr(Schema.Literals(["absent", "terminal"])),
111
+ /** DELETE status; null means no response arrived. */
112
+ deleteStatus: Schema.NullOr(Schema.Int),
113
+ /** State from the independent confirmation, when it was valid. */
114
+ state: Schema.NullOr(Schema.String),
115
+ error: Schema.optionalKey(FailureSummary),
116
+ });
117
+ export const notTerminated = {
118
+ attempted: false,
119
+ responseReceived: false,
120
+ confirmed: false,
121
+ evidence: null,
122
+ deleteStatus: null,
123
+ state: null,
124
+ };
125
+ /** A termination verdict as span attributes: a successful terminate says nothing about billing. */
126
+ export const terminationAttributes = (termination) => ({
127
+ "reactor.termination.attempted": termination.attempted,
128
+ "reactor.termination.confirmed": termination.confirmed,
129
+ ...(termination.evidence === null
130
+ ? {}
131
+ : { "reactor.termination.evidence": termination.evidence }),
132
+ });
133
+ const Pricing = Schema.Struct({
134
+ settings: Schema.Struct({
135
+ currency_code: Schema.optional(Schema.Literal("USD")),
136
+ credits_per_dollar: PositiveInt,
137
+ }),
138
+ models: Schema.Unknown.pipe(Schema.Array, Schema.optional),
139
+ });
140
+ const PricedModel = Schema.Struct({ name: Schema.String, rate: Schema.Unknown });
141
+ const isPricedModel = Schema.is(PricedModel);
142
+ const CreditsRate = Schema.Union([
143
+ Schema.Struct({
144
+ amount_per_sec: PositiveInt,
145
+ unit: Schema.Literal("credits"),
146
+ denomination: Schema.Literal("second"),
147
+ }),
148
+ Schema.Struct({
149
+ amount_per_min: PositiveInt,
150
+ unit: Schema.Literal("credits"),
151
+ denomination: Schema.Literal("minute"),
152
+ }),
153
+ ]);
154
+ /**
155
+ * The rate of `model` in `pricing`, by its connect slug or bare name: the
156
+ * catalog lists `h3-reference-to-video-turbo-realtime` where sessions take
157
+ * `reactor/h3-reference-to-video-turbo-realtime`. Only the settings are read
158
+ * strictly, so an entry this client cannot price never stops it pricing another.
159
+ */
160
+ export const modelRate = Effect.fnUntraced(function* (pricing, model) {
161
+ const bare = model.slice(model.lastIndexOf("/") + 1);
162
+ const decoded = yield* Schema.decodeUnknownEffect(Pricing)(pricing);
163
+ const matches = (decoded.models ?? [])
164
+ .filter(isPricedModel)
165
+ .filter((entry) => entry.name === model || entry.name === bare);
166
+ const rate = yield* Schema.decodeUnknownEffect(CreditsRate)(matches.length === 1 ? matches[0]?.rate : undefined);
167
+ return {
168
+ creditsPerDollar: decoded.settings.credits_per_dollar,
169
+ creditsPerSecond: "amount_per_sec" in rate ? rate.amount_per_sec : rate.amount_per_min / 60,
170
+ per: rate.denomination,
171
+ };
172
+ }, Effect.mapError((cause) => ReactorError.fromCode("Protocol", "Reactor pricing has an unknown model, currency or rate unit", {
173
+ operation: "pricing",
174
+ outcome: "replied",
175
+ detail: cause,
176
+ })));
177
+ /**
178
+ * Tokens that are never refreshed, for a session shorter than its token: the
179
+ * same `token` creates the session and serves its every later call, and the
180
+ * session's calls fail once it expires.
181
+ */
182
+ export const fixedTokens = (token) => ({
183
+ create: Effect.succeed(token),
184
+ bind: () => Effect.succeed(token),
185
+ });
186
+ const Count = Schema.Int.check(Schema.isBetween({ minimum: 1, maximum: 500 }));
187
+ const Seconds = Schema.Int.check(Schema.isBetween({ minimum: 1, maximum: 86_400 }));
188
+ /** One `authorization_details` entry of a session-scoped token, as `POST /tokens` takes it. */
189
+ const SessionAuthorization = Schema.Struct({
190
+ type: Schema.Literal("session"),
191
+ resources: Schema.Struct({
192
+ models: Schema.Struct({ match: Schema.NonEmptyArray(Schema.NonEmptyString) }),
193
+ sessions: Schema.optionalKey(Schema.Struct({ bind: Schema.NonEmptyArray(Schema.NonEmptyString) })),
194
+ }),
195
+ constraints: Schema.optionalKey(Schema.Struct({
196
+ max_sessions: Schema.optionalKey(Count),
197
+ max_session_duration_seconds: Schema.optionalKey(Seconds),
198
+ })),
199
+ });
200
+ /** Reactor's echo of a grant: the request's shape, with the resolved count and bound set. */
201
+ const Stated = Schema.Int.pipe(Schema.NullOr, Schema.optionalKey);
202
+ const GrantEcho = Schema.Struct({
203
+ type: Schema.Literal("session"),
204
+ resources: Schema.Struct({
205
+ models: Schema.Struct({ match: Schema.Array(Schema.String) }),
206
+ sessions: Schema.Struct({
207
+ bind: Schema.String.pipe(Schema.Array, Schema.optionalKey),
208
+ }).pipe(Schema.NullOr, Schema.optionalKey),
209
+ }),
210
+ constraints: Schema.Struct({
211
+ max_sessions: Stated,
212
+ max_session_duration_seconds: Stated,
213
+ }).pipe(Schema.NullOr, Schema.optionalKey),
214
+ });
215
+ const TokenReply = Schema.Struct({
216
+ jwt: Schema.NonEmptyString,
217
+ expires_at: Schema.Finite,
218
+ authorization_details: GrantEcho.pipe(Schema.Array, Schema.optionalKey),
219
+ });
220
+ const TokenRequestBody = Schema.Struct({
221
+ authorization_details: Schema.Tuple([SessionAuthorization]),
222
+ expires_after: Schema.optionalKey(Schema.Int),
223
+ });
224
+ const ClientInfo = Schema.Struct({ sdk_version: Schema.String, sdk_type: Schema.String });
225
+ const CreateBody = Schema.Struct({
226
+ model: Schema.Struct({ name: Schema.NonEmptyString, version: Schema.optionalKey(Schema.String) }),
227
+ client_info: ClientInfo,
228
+ supported_transports: Schema.Array(Transport),
229
+ extra_args: Schema.optionalKey(Schema.Json),
230
+ });
231
+ const OfferBody = Schema.Struct({
232
+ sdp_offer: Schema.NonEmptyString,
233
+ client_info: ClientInfo,
234
+ track_mapping: Schema.Array(Mapping),
235
+ });
236
+ const IceBody = Schema.Struct({
237
+ candidates: Schema.Array(IceCandidate),
238
+ is_final: Schema.Boolean,
239
+ client_info: ClientInfo,
240
+ });
241
+ const UploadBody = Schema.Struct({
242
+ name: Schema.NonEmptyString,
243
+ mime_type: Schema.NonEmptyString,
244
+ size: PositiveInt,
245
+ });
246
+ export const Inspection = Schema.Struct({
247
+ observedAt: Schema.Finite,
248
+ state: Schema.String,
249
+ hasCapabilities: Schema.Boolean,
250
+ selectedTransport: Schema.NullOr(Transport),
251
+ cluster: Schema.NullOr(Schema.String),
252
+ zone: Schema.NullOr(Schema.String),
253
+ serverVersion: Schema.NullOr(Schema.String),
254
+ });
255
+ const SessionDescription = Schema.Struct({
256
+ session_id: Schema.NonEmptyString,
257
+ state: Schema.NonEmptyString,
258
+ capabilities: Schema.Unknown.pipe(Schema.NullOr, Schema.optionalKey),
259
+ selected_transport: Transport.pipe(Schema.NullOr, Schema.optionalKey),
260
+ cluster: Schema.String.pipe(Schema.NullOr, Schema.optionalKey),
261
+ zone: Schema.String.pipe(Schema.NullOr, Schema.optionalKey),
262
+ server_info: Schema.Struct({ server_version: Schema.String }).pipe(Schema.NullOr, Schema.optionalKey),
263
+ });
264
+ /** A termination probe promises state; when it names a session, it must be the one asked for. */
265
+ const TerminalState = Schema.Struct({
266
+ session_id: Schema.optionalKey(Schema.NonEmptyString),
267
+ state: Schema.NonEmptyString,
268
+ });
269
+ export const parsePlaylist = Recording.parsePlaylist;
270
+ export class Coordinator extends Context.Service()("reactor-effect-client/Coordinator") {
271
+ }
272
+ const checkedUrl = (url, base) => Effect.try({
273
+ try: () => new URL(url, base),
274
+ catch: (cause) => ReactorError.fromCode("Protocol", "HTTP URL is malformed", { detail: cause }),
275
+ }).pipe(Effect.filterOrFail((value) => (value.protocol === "https:" || value.protocol === "http:") &&
276
+ value.username === "" &&
277
+ value.password === "", () => ReactorError.fromCode("Protocol", "HTTP URL must use http(s) and contain no embedded credentials")));
278
+ /** A response's `Retry-After` when it names a delay in seconds; an HTTP date is not read. */
279
+ const retryAfterOf = (headers) => {
280
+ const raw = headers["retry-after"];
281
+ if (raw === undefined || !/^\s*(?:\d+(?:\.\d*)?|\.\d+)\s*$/.test(raw))
282
+ return undefined;
283
+ const seconds = Number(raw);
284
+ return Number.isFinite(seconds) ? Duration.seconds(seconds) : undefined;
285
+ };
286
+ /** The body within `maxBytes` and 16,384 chunks, since every chunk, even an empty one, costs memory. */
287
+ const bodyWithin = (response, maxBytes) => {
288
+ const overflow = ReactorError.fromCode("Overflow", `response exceeds its ${maxBytes} byte bound`, {
289
+ outcome: "replied",
290
+ });
291
+ const refused = Stream.fail(overflow);
292
+ return response.stream.pipe(Stream.catchIf((error) => error.reason._tag === "EmptyBodyError", () => Stream.empty), Stream.limitBytes(maxBytes, () => refused), Stream.zipWithIndex, Stream.mapEffect(([chunk, index]) => index < 16_384 ? Effect.succeed(chunk) : Effect.fail(overflow)), Stream.mkUint8Array);
293
+ };
294
+ /** A transport failure once a request may have reached the server: its outcome is unknown. */
295
+ const lost = (operation, status) => (cause) => ReactorError.is(cause)
296
+ ? cause
297
+ : ReactorError.make({
298
+ reason: Http.make({
299
+ message: `${operation}: network/read failure`,
300
+ ...(status === undefined ? {} : { status }),
301
+ }),
302
+ context: { operation, outcome: "unknown", detail: Redacted.make(cause) },
303
+ });
304
+ /** The reply when its call accepts the status; otherwise the failure the status says. */
305
+ const answered = (call, status, bytes, headers) => {
306
+ const retryAfter = retryAfterOf(headers);
307
+ if ((status >= 200 && status < 300) || call.accepted?.includes(status) === true)
308
+ return Effect.succeed({ status, bytes, retryAfter });
309
+ const message = `${call.operation}: HTTP ${String(status)}`;
310
+ const body = Redacted.make(new TextDecoder().decode(bytes));
311
+ const context = { operation: call.operation, outcome: "replied" };
312
+ return Effect.fail(status === 426 || status === 501
313
+ ? ReactorError.fromCode("VersionMismatch", message, { ...context, detail: { status, body } })
314
+ : ReactorError.make({
315
+ reason: Http.make({
316
+ message,
317
+ status,
318
+ body,
319
+ ...(retryAfter === undefined ? {} : { retryAfter }),
320
+ }),
321
+ context,
322
+ }));
323
+ };
324
+ const utf8 = new TextDecoder("utf-8", { fatal: true });
325
+ /** Decodes a JSON reply through its Schema; the SchemaError names a path, never the value. */
326
+ const decodeReply = (schema, operation) => {
327
+ const protocol = (message) => (detail) => ReactorError.fromCode("Protocol", message, { operation, outcome: "replied", detail });
328
+ const decode = Schema.decodeEffect(Schema.fromJsonString(schema));
329
+ return (reply) => Effect.try({
330
+ try: () => utf8.decode(reply.bytes),
331
+ catch: protocol(`${operation} reply is not UTF-8`),
332
+ }).pipe(Effect.flatMap((text) => Effect.mapError(decode(text), protocol(`invalid ${operation} reply`))));
333
+ };
334
+ /** `request` with `value` as its JSON body; a value its Schema refuses is never sent. */
335
+ const withBody = (schema, operation) => {
336
+ const encode = HttpClientRequest.schemaBodyJson(schema);
337
+ return (request, value) => Effect.mapError(encode(request, value), (cause) => ReactorError.fromCode("InvalidInput", `${operation} body cannot be encoded`, {
338
+ operation,
339
+ outcome: "not-submitted",
340
+ detail: cause,
341
+ }));
342
+ };
343
+ const sessionPath = (id) => `/sessions/${encodeURIComponent(id)}`;
344
+ const transportPath = (id) => `${sessionPath(id)}/transport/webrtc`;
345
+ const connectionPath = (id, cid) => `${transportPath(id)}/connections/${String(cid)}`;
346
+ /** Doubling waits from 200 ms, capped: at most 20 descriptor reads. */
347
+ const sessionPoll = Schedule.min([
348
+ Schedule.exponential("200 millis"),
349
+ Schedule.spaced("10 seconds"),
350
+ ]).pipe(Schedule.upTo({ times: 19 }));
351
+ /** Doubling waits from 200 ms up to 2 s; the caller's connect deadline bounds the whole wait. */
352
+ const sdpPoll = Schedule.min([Schedule.exponential("200 millis"), Schedule.spaced("2 seconds")]);
353
+ const createBody = withBody(CreateBody, "create session");
354
+ const offerBody = withBody(OfferBody, "SDP offer");
355
+ const iceBody = withBody(IceBody, "ICE candidates");
356
+ const uploadBody = withBody(UploadBody, "allocate upload");
357
+ const tokenBody = withBody(TokenRequestBody, "token");
358
+ /** A Coordinator over the current `HttpClient`. No request runs while it is built. */
359
+ export const make = Effect.fnUntraced(function* (options = {}) {
360
+ const base = yield* checkedUrl(options.apiUrl ?? defaultApiUrl).pipe(Effect.filterOrFail((url) => url.search === "" && url.hash === "", () => ReactorError.fromCode("InvalidInput", "apiUrl cannot contain a query or fragment")));
361
+ const apiUrl = base.href.replace(/\/$/, "");
362
+ const http = (yield* HttpClient.HttpClient).pipe(
363
+ // Never follow a redirect with a credential, never send ambient cookies, and trace the
364
+ // operations rather than each request.
365
+ HttpClient.transform((response) => response.pipe(Effect.provideService(FetchHttpClient.RequestInit, {
366
+ credentials: "omit",
367
+ redirect: "error",
368
+ }), Effect.provideService(HttpClient.TracerDisabledWhen, () => true), Effect.updateService(Headers.CurrentRedactedNames, (names) => [
369
+ ...names,
370
+ "reactor-api-key",
371
+ ]))));
372
+ const api = http.pipe(HttpClient.mapRequest(HttpClientRequest.prependUrl(apiUrl)));
373
+ const versioned = api.pipe(HttpClient.mapRequest(HttpClientRequest.setHeaders({
374
+ "reactor-api-version": "1",
375
+ "reactor-api-accept-version": "1",
376
+ })));
377
+ const clients = {
378
+ session: versioned,
379
+ signaling: versioned.pipe(HttpClient.mapRequest(HttpClientRequest.setHeader("reactor-webrtc-version", "1.0"))),
380
+ public: api,
381
+ recording: http,
382
+ upload: http,
383
+ };
384
+ const call = Effect.fnUntraced(function* (credential, spec) {
385
+ const { operation } = spec;
386
+ const route = spec.route ?? "session";
387
+ const deadline = spec.timeout ?? "15 seconds";
388
+ const url = route === "recording" || route === "upload" ? yield* checkedUrl(spec.request.url) : base;
389
+ // A request whose token could not be had, at all or in time, was never sent. The token
390
+ // has its own deadline, before the request's starts: a slow mint is not a request that
391
+ // may have landed.
392
+ const token = route === "public" || route === "upload" || url.origin !== base.origin
393
+ ? undefined
394
+ : yield* credential.pipe(Effect.timeoutOrElse({
395
+ duration: deadline,
396
+ orElse: () => Effect.fail(ReactorError.fromCode("Timeout", `${operation}: no token in time`)),
397
+ }), Effect.mapError((error) => ReactorError.make({
398
+ reason: error.reason,
399
+ context: { ...error.context, operation, outcome: "not-submitted" },
400
+ })));
401
+ const request = token === undefined ? spec.request : HttpClientRequest.bearerToken(spec.request, token);
402
+ return yield* clients[route].execute(request).pipe(
403
+ // Crossing execute is where a mutation may have reached the server: a transport
404
+ // failure after it cannot prove non-delivery.
405
+ Effect.mapError(lost(operation)), Effect.tap((response) => spec.onStatus?.(response.status) ?? Effect.void), Effect.flatMap((response) => bodyWithin(response, spec.maxBytes ?? 2_097_152).pipe(Effect.mapError(lost(operation, response.status)), Effect.flatMap((bytes) => answered(spec, response.status, bytes, response.headers)))), Effect.scoped, Effect.timeoutOrElse({
406
+ duration: deadline,
407
+ orElse: () => Effect.fail(ReactorError.fromCode("Timeout", `${operation}: deadline`, {
408
+ operation,
409
+ outcome: "unknown",
410
+ })),
411
+ }));
412
+ });
413
+ const signaling = (credential) => {
414
+ const request = (spec) => call(credential, spec);
415
+ const read = (sessionId) => request({
416
+ operation: "read session",
417
+ request: HttpClientRequest.get(sessionPath(sessionId)),
418
+ }).pipe(Effect.flatMap(decodeReply(Descriptor, "session descriptor")), Effect.filterOrFail((descriptor) => descriptor.session_id === sessionId, () => ReactorError.fromCode("Protocol", "session descriptor identity mismatch")));
419
+ const terminate = Effect.fnUntraced(function* (sessionId) {
420
+ const status = yield* Ref.make(null);
421
+ const path = sessionPath(sessionId);
422
+ const removal = yield* Effect.result(request({
423
+ operation: "terminate",
424
+ request: HttpClientRequest.delete(path),
425
+ accepted: [404],
426
+ timeout: "3 seconds",
427
+ onStatus: (value) => Ref.set(status, value),
428
+ }));
429
+ const deleteStatus = yield* Ref.get(status);
430
+ const base = {
431
+ attempted: removal._tag === "Success" || removal.failure.context.outcome !== "not-submitted",
432
+ responseReceived: deleteStatus !== null,
433
+ deleteStatus,
434
+ };
435
+ const failed = (error) => ({
436
+ ...base,
437
+ confirmed: false,
438
+ evidence: null,
439
+ state: null,
440
+ error: summarize(error),
441
+ });
442
+ const confirmation = yield* Effect.result(request({
443
+ operation: "terminate",
444
+ request: HttpClientRequest.get(path),
445
+ accepted: [404],
446
+ timeout: "3 seconds",
447
+ }));
448
+ if (confirmation._tag === "Failure")
449
+ return failed(confirmation.failure);
450
+ if (confirmation.success.status === 404)
451
+ return deleteStatus === 401 || deleteStatus === 403
452
+ ? failed(ReactorError.make({
453
+ reason: Http.make({
454
+ message: "remote termination could not be confirmed after authority refusal",
455
+ status: deleteStatus,
456
+ }),
457
+ context: { operation: "terminate", outcome: "replied" },
458
+ }))
459
+ : { ...base, confirmed: true, evidence: "absent", state: null };
460
+ const described = yield* Effect.result(decodeReply(TerminalState, "termination description")(confirmation.success).pipe(Effect.filterOrFail((value) => value.session_id === undefined || value.session_id === sessionId, () => ReactorError.fromCode("Protocol", "termination names another session"))));
461
+ if (described._tag === "Failure")
462
+ return failed(described.failure);
463
+ const state = described.success.state;
464
+ const terminal = isTerminal(state);
465
+ return {
466
+ ...base,
467
+ confirmed: terminal,
468
+ evidence: terminal ? "terminal" : null,
469
+ state,
470
+ ...(!terminal && removal._tag === "Failure" ? { error: summarize(removal.failure) } : {}),
471
+ };
472
+ }, Effect.tap((termination) => Effect.annotateCurrentSpan({
473
+ ...terminationAttributes(termination),
474
+ ...(termination.error === undefined ? {} : { "error.type": termination.error.reason }),
475
+ })), Effect.withSpan("Coordinator.terminate", (sessionId) => ({ kind: "client", attributes: { "reactor.session.id": sessionId } }), { captureStackTrace: false }));
476
+ return {
477
+ create: (model, extraArgs) => createBody(HttpClientRequest.post("/sessions"), {
478
+ model: {
479
+ name: model.name,
480
+ ...(model.version === undefined ? {} : { version: model.version }),
481
+ },
482
+ client_info: clientInfo,
483
+ supported_transports: [{ protocol: "webrtc", version: "1.0" }],
484
+ ...(extraArgs === undefined ? {} : { extra_args: extraArgs }),
485
+ }).pipe(Effect.flatMap((body) => request({ operation: "create session", request: body })),
486
+ // A refusal (4xx) proves nothing was allocated; a server error may follow an allocation.
487
+ Effect.mapError((error) => error.context.outcome === "replied" &&
488
+ error.reason._tag === "Http" &&
489
+ (error.reason.status ?? 0) >= 500
490
+ ? ReactorError.make({
491
+ reason: error.reason,
492
+ context: { ...error.context, outcome: "unknown" },
493
+ })
494
+ : error), Effect.flatMap(decodeReply(Schema.Unknown, "create session")), Effect.flatMap((reply) => Schema.decodeUnknownEffect(Allocated)(reply).pipe(Effect.map((allocated) => ({ sessionId: allocated.session_id, reply })),
495
+ // A session may have been made all the same: the reply's body goes with the
496
+ // failure, redacted as provider text is, for whoever must find that session.
497
+ Effect.mapError((cause) => ReactorError.fromCode("Protocol", "create reply names no session", {
498
+ operation: "create session",
499
+ outcome: "unknown",
500
+ detail: { body: reply, cause },
501
+ }))))),
502
+ describe: (allocation) => Schema.decodeUnknownEffect(Descriptor)(allocation.reply).pipe(Effect.mapError((cause) => ReactorError.fromCode("Protocol", "invalid session descriptor", {
503
+ operation: "create session",
504
+ sessionId: allocation.sessionId,
505
+ outcome: "replied",
506
+ detail: cause,
507
+ }))),
508
+ read,
509
+ ready: Effect.fnUntraced(function* (sessionId, initial) {
510
+ const first = yield* Ref.make(initial);
511
+ const poll = Ref.getAndSet(first, undefined).pipe(Effect.filterOrElse((cached) => cached !== undefined, () => read(sessionId)), Effect.filterOrFail((descriptor) => !isTerminal(descriptor.state), (descriptor) => ReactorError.fromCode("TerminalSession", descriptor.state, { sessionId })));
512
+ const ready = (descriptor) => descriptor.capabilities !== undefined && descriptor.selected_transport !== undefined;
513
+ return yield* poll.pipe(Effect.repeat({ schedule: sessionPoll, until: ready }), Effect.filterOrFail(ready, () => ReactorError.fromCode("Timeout", "session capabilities/transport not ready", {
514
+ sessionId,
515
+ })));
516
+ }),
517
+ iceServers: (sessionId) => request({
518
+ operation: "ICE servers",
519
+ route: "signaling",
520
+ request: HttpClientRequest.get(`${transportPath(sessionId)}/ice_servers`),
521
+ }).pipe(Effect.flatMap(decodeReply(IceServersReply, "ICE servers")), Effect.map((reply) => reply.ice_servers.map((server) => server.credentials === undefined
522
+ ? { urls: server.uris }
523
+ : {
524
+ urls: server.uris,
525
+ username: server.credentials.username,
526
+ credential: server.credentials.password,
527
+ }))),
528
+ register: (sessionId) => request({
529
+ operation: "register connection",
530
+ route: "signaling",
531
+ request: HttpClientRequest.post(`${transportPath(sessionId)}/connections`).pipe(HttpClientRequest.bodyText("{}", "application/json")),
532
+ }).pipe(Effect.flatMap(decodeReply(Registered, "connection")), Effect.map((reply) => reply.connection_id)),
533
+ offer: (sessionId, cid, sdp, mapping, replace) => offerBody(HttpClientRequest.make(replace ? "PUT" : "POST")(`${connectionPath(sessionId, cid)}/sdp_params`), { sdp_offer: sdp, client_info: clientInfo, track_mapping: mapping }).pipe(Effect.flatMap((body) => request({ operation: "SDP offer", route: "signaling", request: body })), Effect.asVoid),
534
+ answer: (sessionId, cid) => request({
535
+ operation: "SDP answer",
536
+ route: "signaling",
537
+ request: HttpClientRequest.get(`${connectionPath(sessionId, cid)}/sdp_params`),
538
+ }).pipe(Effect.repeat({ schedule: sdpPoll, until: (reply) => reply.status !== 202 }), Effect.flatMap(decodeReply(SdpAnswer, "SDP answer"))),
539
+ ice: (sessionId, cid, candidates, isFinal) => iceBody(HttpClientRequest.post(`${connectionPath(sessionId, cid)}/ice_candidates`), {
540
+ candidates,
541
+ is_final: isFinal,
542
+ client_info: clientInfo,
543
+ }).pipe(Effect.flatMap((body) => request({ operation: "ICE candidates", route: "signaling", request: body })), Effect.asVoid),
544
+ allocateUpload: (sessionId, name, mimeType, size) => uploadBody(HttpClientRequest.post(`${sessionPath(sessionId)}/uploads`), {
545
+ name,
546
+ mime_type: mimeType,
547
+ size,
548
+ }).pipe(Effect.flatMap((body) => request({ operation: "allocate upload", request: body })), Effect.flatMap(decodeReply(UploadSlot, "upload allocation")), Effect.tap((slot) => checkedUrl(slot.presigned_url))),
549
+ putUpload: (slot, bytes, mimeType) => request({
550
+ operation: "transfer upload",
551
+ route: "upload",
552
+ request: HttpClientRequest.put(slot.presigned_url).pipe(HttpClientRequest.bodyUint8Array(bytes, mimeType)),
553
+ }).pipe(Effect.asVoid),
554
+ terminate,
555
+ downloadClip: (clip, downloadOptions) => Recording.download({
556
+ fetcher: {
557
+ fetch: (operation, url, maxBytes) => request({
558
+ operation,
559
+ route: "recording",
560
+ request: HttpClientRequest.get(url),
561
+ maxBytes,
562
+ }),
563
+ read,
564
+ },
565
+ clip,
566
+ ...downloadOptions,
567
+ }),
568
+ };
569
+ };
570
+ // A server holding the key reads, ends and downloads any session of its account with the
571
+ // key as the bearer. It goes only to the API's own origin, as every credential does.
572
+ const configured = options.credential ??
573
+ (options.apiKey === undefined ? Effect.undefined : Effect.succeed(options.apiKey));
574
+ const app = (spec) => call(configured, spec);
575
+ const appSignaling = signaling(configured);
576
+ const mintToken = Effect.fn("Coordinator.mintToken")(function* (input) {
577
+ const invalid = (message) => ReactorError.fromCode("InvalidInput", message, {
578
+ operation: "token",
579
+ outcome: "not-submitted",
580
+ });
581
+ const apiKey = input.apiKey ?? options.apiKey;
582
+ if (apiKey === undefined || Redacted.value(apiKey).length === 0)
583
+ return yield* invalid("a token needs an API key");
584
+ if (input.modelName.length === 0)
585
+ return yield* invalid("a token needs a model");
586
+ const bind = input.bind ?? [];
587
+ if (bind.some((id) => id.length === 0))
588
+ return yield* invalid("a bound session needs an id");
589
+ const maxSessions = input.maxSessions ?? (bind.length === 0 ? 1 : undefined);
590
+ if (maxSessions !== undefined &&
591
+ !(Number.isInteger(maxSessions) &&
592
+ maxSessions >= Math.max(1, bind.length) &&
593
+ maxSessions <= 500))
594
+ return yield* invalid("maxSessions is an integer from 1, or the bound count, to 500");
595
+ // Reactor's default leaves a bound token no room to create; any other token creates.
596
+ const creates = maxSessions !== undefined && maxSessions > bind.length;
597
+ const cap = input.maxSessionDuration;
598
+ let seconds;
599
+ if (cap === undefined) {
600
+ if (creates)
601
+ return yield* invalid('a token that creates sessions needs a maxSessionDuration: a duration or "unlimited"');
602
+ }
603
+ else if (cap !== "unlimited") {
604
+ const duration = Duration.fromInput(cap);
605
+ seconds = Option.isSome(duration) ? Duration.toSeconds(duration.value) : Number.NaN;
606
+ if (!(Number.isInteger(seconds) && seconds >= 1 && seconds <= 86_400))
607
+ return yield* invalid("maxSessionDuration is whole seconds from one to a day");
608
+ }
609
+ let expiresAfter;
610
+ if (input.expiresAfter !== undefined) {
611
+ const expiry = Duration.fromInput(input.expiresAfter);
612
+ expiresAfter = Option.isSome(expiry) ? Duration.toSeconds(expiry.value) : Number.NaN;
613
+ if (!(Number.isSafeInteger(expiresAfter) && expiresAfter >= 1))
614
+ return yield* invalid("expiresAfter is whole seconds, at least one");
615
+ }
616
+ const request = yield* tokenBody(HttpClientRequest.post("/tokens").pipe(HttpClientRequest.setHeader("reactor-api-key", Redacted.value(apiKey))), {
617
+ authorization_details: [
618
+ {
619
+ type: "session",
620
+ resources: {
621
+ models: { match: [input.modelName] },
622
+ ...(Arr.isReadonlyArrayNonEmpty(bind) ? { sessions: { bind } } : {}),
623
+ },
624
+ ...(maxSessions === undefined && seconds === undefined
625
+ ? {}
626
+ : {
627
+ constraints: {
628
+ ...(maxSessions === undefined ? {} : { max_sessions: maxSessions }),
629
+ ...(seconds === undefined ? {} : { max_session_duration_seconds: seconds }),
630
+ },
631
+ }),
632
+ },
633
+ ],
634
+ ...(expiresAfter === undefined ? {} : { expires_after: expiresAfter }),
635
+ });
636
+ const token = yield* app({
637
+ operation: "token",
638
+ request,
639
+ route: "public",
640
+ timeout: "8 seconds",
641
+ }).pipe(Effect.flatMap(decodeReply(TokenReply, "token")));
642
+ const protocol = (message) => ReactorError.fromCode("Protocol", message, { operation: "token", outcome: "replied" });
643
+ if (token.expires_at * 1_000 <= (yield* Clock.currentTimeMillis))
644
+ return yield* protocol("the token has already expired");
645
+ const [entry, ...others] = token.authorization_details ?? [];
646
+ if (others.length > 0)
647
+ return yield* protocol("the token grants other authority than asked");
648
+ const stated = entry?.constraints?.max_session_duration_seconds;
649
+ const granted = entry === undefined
650
+ ? undefined
651
+ : {
652
+ models: entry.resources.models.match,
653
+ maxSessions: entry.constraints?.max_sessions ?? undefined,
654
+ // A null cap says there is none; an absent one says nothing.
655
+ maxSessionSeconds: stated === null ? "unlimited" : stated,
656
+ bound: entry.resources.sessions?.bind ?? [],
657
+ };
658
+ if (granted !== undefined &&
659
+ (granted.models.some((model) => model !== input.modelName) ||
660
+ granted.bound.some((id) => !bind.includes(id)) ||
661
+ (granted.maxSessions ?? 0) > (maxSessions ?? bind.length) ||
662
+ (seconds !== undefined &&
663
+ (granted.maxSessionSeconds === "unlimited" ||
664
+ (granted.maxSessionSeconds ?? 0) > seconds))))
665
+ return yield* protocol("the token grants more than was asked");
666
+ // A narrower grant caps each session at what it grants.
667
+ const narrower = Predicate.isNumber(granted?.maxSessionSeconds) &&
668
+ (seconds === undefined || granted.maxSessionSeconds < seconds);
669
+ return {
670
+ jwt: Redacted.make(token.jwt),
671
+ expiresAt: token.expires_at,
672
+ maxSessionSeconds: narrower ? granted.maxSessionSeconds : seconds,
673
+ ...(granted === undefined ? {} : { granted }),
674
+ };
675
+ });
676
+ return Coordinator.of({
677
+ apiUrl,
678
+ signaling,
679
+ mintToken,
680
+ tokens: (input) => ({
681
+ create: mintToken({ ...input, maxSessions: 1 }),
682
+ bind: (sessionId) => mintToken({
683
+ modelName: input.modelName,
684
+ bind: [sessionId],
685
+ ...(input.apiKey === undefined ? {} : { apiKey: input.apiKey }),
686
+ ...(input.expiresAfter === undefined ? {} : { expiresAfter: input.expiresAfter }),
687
+ }),
688
+ }),
689
+ pricing: app({
690
+ operation: "pricing",
691
+ request: HttpClientRequest.get("/pricing"),
692
+ route: "public",
693
+ timeout: "8 seconds",
694
+ }).pipe(Effect.flatMap(decodeReply(Schema.Json, "pricing")), Effect.withSpan("Coordinator.pricing", { kind: "client" }, { captureStackTrace: false })),
695
+ inspect: Effect.fn("Coordinator.inspect")(function* (sessionId) {
696
+ const value = yield* app({
697
+ operation: "inspect",
698
+ request: HttpClientRequest.get(sessionPath(sessionId)),
699
+ timeout: "1 second",
700
+ }).pipe(Effect.flatMap(decodeReply(SessionDescription, "inspect")));
701
+ if (value.session_id !== sessionId)
702
+ return yield* ReactorError.fromCode("Protocol", "inspection names another session", {
703
+ operation: "inspect",
704
+ outcome: "replied",
705
+ });
706
+ return {
707
+ observedAt: yield* Clock.currentTimeMillis,
708
+ state: value.state,
709
+ hasCapabilities: value.capabilities != null,
710
+ selectedTransport: value.selected_transport ?? null,
711
+ cluster: value.cluster ?? null,
712
+ zone: value.zone ?? null,
713
+ serverVersion: value.server_info?.server_version ?? null,
714
+ };
715
+ }),
716
+ terminate: appSignaling.terminate,
717
+ downloadClip: appSignaling.downloadClip,
718
+ });
719
+ });
720
+ /** A Coordinator service over the application's `HttpClient`. */
721
+ export const layer = (options = {}) => Layer.effect(Coordinator, make(options));
722
+ /**
723
+ * A Coordinator configured from the environment: `REACTOR_API_URL` (optional)
724
+ * and `REACTOR_API_KEY` (optional, for `mintToken`, `inspect`, `terminate`
725
+ * and `downloadClip`).
726
+ */
727
+ export const layerConfig = Layer.effect(Coordinator, Effect.gen(function* () {
728
+ const apiUrl = yield* Config.String("REACTOR_API_URL").pipe(Config.withDefault(defaultApiUrl));
729
+ const apiKey = yield* Config.Redacted("REACTOR_API_KEY").pipe(Config.option);
730
+ return yield* make({ apiUrl, ...(Option.isSome(apiKey) ? { apiKey: apiKey.value } : {}) });
731
+ }));
732
+ //# sourceMappingURL=Coordinator.js.map