@graftland/plugin-remote 0.0.0-stage → 0.3.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 (380) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +76 -2
  3. package/README.zh-CN.md +71 -0
  4. package/README.zh-TW.md +71 -0
  5. package/dist/Auth-BElTC9_X.js +6 -0
  6. package/dist/Auth.d.ts +49 -0
  7. package/dist/Auth.d.ts.map +1 -0
  8. package/dist/Auth.js +8 -0
  9. package/dist/Auth.js.map +1 -0
  10. package/dist/Bootstrap-MCwivGN1.js +9 -0
  11. package/dist/ConfigDirectory-BCC6q2R4.js +5 -0
  12. package/dist/Contract-CcpSIJm4.js +121 -0
  13. package/dist/Contract.d.ts +71 -0
  14. package/dist/Contract.d.ts.map +1 -0
  15. package/dist/Contract.js +1 -0
  16. package/dist/Contract.js.map +1 -0
  17. package/dist/Errors-oPsTLY7l.js +45 -0
  18. package/dist/Errors.d.ts +67 -0
  19. package/dist/Errors.d.ts.map +1 -0
  20. package/dist/Errors.js +47 -0
  21. package/dist/Errors.js.map +1 -0
  22. package/dist/FailureGroup-BcH0XOBi.js +53 -0
  23. package/dist/Framing-zaYdOJnT.js +61 -0
  24. package/dist/Graft-BsYq3F-J.js +985 -0
  25. package/dist/Instance.d.ts +7 -0
  26. package/dist/Instance.d.ts.map +1 -0
  27. package/dist/Instance.js +14 -0
  28. package/dist/Instance.js.map +1 -0
  29. package/dist/Packages-B1TPk8pa.js +111 -0
  30. package/dist/Peer-IJgFK6mD.js +342 -0
  31. package/dist/ProcessObservation-DEGrEMfP.js +38 -0
  32. package/dist/ServeLifecycle-CJM0gG5B.js +24 -0
  33. package/dist/Testing.d.ts +26 -0
  34. package/dist/Testing.d.ts.map +1 -0
  35. package/dist/Testing.js +69 -0
  36. package/dist/Testing.js.map +1 -0
  37. package/dist/Transport-DULzpsgR.js +6 -0
  38. package/dist/Transport.d.ts +39 -0
  39. package/dist/Transport.d.ts.map +1 -0
  40. package/dist/Transport.js +8 -0
  41. package/dist/Transport.js.map +1 -0
  42. package/dist/WatchdogProtocol-BZmVxrBP.js +17 -0
  43. package/dist/_virtual/_rolldown/runtime.js +12 -0
  44. package/dist/bin.d.ts +1 -0
  45. package/dist/bin.js +28275 -0
  46. package/dist/bin.js.map +1 -0
  47. package/dist/childRuntime-DSqtFN9o.js +188 -0
  48. package/dist/cleanup-BPWr-5U9.js +13 -0
  49. package/dist/command-9zrHdbwT.js +7 -0
  50. package/dist/connectionEnded-DUgcobEd.js +9 -0
  51. package/dist/directTransport-DrexuPSm.js +5 -0
  52. package/dist/entry-SYsx9VNb.js +708 -0
  53. package/dist/host/auth/bearer.d.ts +5 -0
  54. package/dist/host/auth/bearer.d.ts.map +1 -0
  55. package/dist/host/auth/bearer.js +4 -0
  56. package/dist/host/auth/bearer.js.map +1 -0
  57. package/dist/host/auth/jwt.d.ts +5 -0
  58. package/dist/host/auth/jwt.d.ts.map +1 -0
  59. package/dist/host/auth/jwt.js +4 -0
  60. package/dist/host/auth/jwt.js.map +1 -0
  61. package/dist/host/auth/mtls.d.ts +8 -0
  62. package/dist/host/auth/mtls.d.ts.map +1 -0
  63. package/dist/host/auth/mtls.js +34 -0
  64. package/dist/host/auth/mtls.js.map +1 -0
  65. package/dist/host/auth/none.d.ts +3 -0
  66. package/dist/host/auth/none.d.ts.map +1 -0
  67. package/dist/host/auth/none.js +13 -0
  68. package/dist/host/auth/none.js.map +1 -0
  69. package/dist/host/command.d.ts +22 -0
  70. package/dist/host/command.d.ts.map +1 -0
  71. package/dist/host/command.js +61 -0
  72. package/dist/host/command.js.map +1 -0
  73. package/dist/host/local.d.ts +4 -0
  74. package/dist/host/local.d.ts.map +1 -0
  75. package/dist/host/local.js +52 -0
  76. package/dist/host/local.js.map +1 -0
  77. package/dist/host/unix.d.ts +11 -0
  78. package/dist/host/unix.d.ts.map +1 -0
  79. package/dist/host/unix.js +39 -0
  80. package/dist/host/unix.js.map +1 -0
  81. package/dist/host/websocket.d.ts +13 -0
  82. package/dist/host/websocket.d.ts.map +1 -0
  83. package/dist/host/websocket.js +36 -0
  84. package/dist/host/websocket.js.map +1 -0
  85. package/dist/host/worker.d.ts +4 -0
  86. package/dist/host/worker.d.ts.map +1 -0
  87. package/dist/host/worker.js +52 -0
  88. package/dist/host/worker.js.map +1 -0
  89. package/dist/importer-D7zSgqxq.js +347 -0
  90. package/dist/index.d.ts +29 -0
  91. package/dist/index.d.ts.map +1 -0
  92. package/dist/index.js +86 -0
  93. package/dist/index.js.map +1 -0
  94. package/dist/internal/Certificates.js +182 -0
  95. package/dist/internal/Certificates.js.map +1 -0
  96. package/dist/internal/FailureGroup.js +55 -0
  97. package/dist/internal/FailureGroup.js.map +1 -0
  98. package/dist/internal/Limits.d.ts +1 -0
  99. package/dist/internal/Limits.js +17 -0
  100. package/dist/internal/Limits.js.map +1 -0
  101. package/dist/internal/Peer.js +6 -0
  102. package/dist/internal/Peer.js.map +1 -0
  103. package/dist/internal/ServeLifecycle.js +26 -0
  104. package/dist/internal/ServeLifecycle.js.map +1 -0
  105. package/dist/internal/Supervisor.js +7 -0
  106. package/dist/internal/Supervisor.js.map +1 -0
  107. package/dist/internal/assembly.d.ts +5 -0
  108. package/dist/internal/assembly.js +138 -0
  109. package/dist/internal/assembly.js.map +1 -0
  110. package/dist/internal/auth/mtls.js +23 -0
  111. package/dist/internal/auth/mtls.js.map +1 -0
  112. package/dist/internal/auth/token.js +19 -0
  113. package/dist/internal/auth/token.js.map +1 -0
  114. package/dist/internal/auth/tokenCredentials.d.ts +8 -0
  115. package/dist/internal/auth/tokenCredentials.d.ts.map +1 -0
  116. package/dist/internal/auth/tokenCredentials.js +33 -0
  117. package/dist/internal/auth/tokenCredentials.js.map +1 -0
  118. package/dist/internal/child.js +125 -0
  119. package/dist/internal/child.js.map +1 -0
  120. package/dist/internal/childErrors.d.ts +33 -0
  121. package/dist/internal/childErrors.d.ts.map +1 -0
  122. package/dist/internal/childErrors.js +29 -0
  123. package/dist/internal/childErrors.js.map +1 -0
  124. package/dist/internal/childRuntime.js +59 -0
  125. package/dist/internal/childRuntime.js.map +1 -0
  126. package/dist/internal/cleanup.js +15 -0
  127. package/dist/internal/cleanup.js.map +1 -0
  128. package/dist/internal/config.js +6 -0
  129. package/dist/internal/config.js.map +1 -0
  130. package/dist/internal/control.js +42 -0
  131. package/dist/internal/control.js.map +1 -0
  132. package/dist/internal/credentials.d.ts +44 -0
  133. package/dist/internal/credentials.d.ts.map +1 -0
  134. package/dist/internal/credentials.js +54 -0
  135. package/dist/internal/credentials.js.map +1 -0
  136. package/dist/internal/directTransport.d.ts +3 -0
  137. package/dist/internal/directTransport.js +7 -0
  138. package/dist/internal/directTransport.js.map +1 -0
  139. package/dist/internal/entry.d.ts +9 -0
  140. package/dist/internal/entry.d.ts.map +1 -0
  141. package/dist/internal/entry.js +144 -0
  142. package/dist/internal/entry.js.map +1 -0
  143. package/dist/internal/entryConfig.d.ts +202 -0
  144. package/dist/internal/entryConfig.d.ts.map +1 -0
  145. package/dist/internal/entryConfig.js +176 -0
  146. package/dist/internal/entryConfig.js.map +1 -0
  147. package/dist/internal/execution.d.ts +5 -0
  148. package/dist/internal/execution.js +43 -0
  149. package/dist/internal/execution.js.map +1 -0
  150. package/dist/internal/follow.js +11 -0
  151. package/dist/internal/follow.js.map +1 -0
  152. package/dist/internal/forkTree.js +7 -0
  153. package/dist/internal/forkTree.js.map +1 -0
  154. package/dist/internal/host/local.js +28 -0
  155. package/dist/internal/host/local.js.map +1 -0
  156. package/dist/internal/host/runner.js +100 -0
  157. package/dist/internal/host/runner.js.map +1 -0
  158. package/dist/internal/host.js +71 -0
  159. package/dist/internal/host.js.map +1 -0
  160. package/dist/internal/importer.js +18 -0
  161. package/dist/internal/importer.js.map +1 -0
  162. package/dist/internal/listenerStartup.js +17 -0
  163. package/dist/internal/listenerStartup.js.map +1 -0
  164. package/dist/internal/loadModule.js +20 -0
  165. package/dist/internal/loadModule.js.map +1 -0
  166. package/dist/internal/platform.js +9 -0
  167. package/dist/internal/platform.js.map +1 -0
  168. package/dist/internal/port.d.ts +13 -0
  169. package/dist/internal/port.d.ts.map +1 -0
  170. package/dist/internal/port.js +275 -0
  171. package/dist/internal/port.js.map +1 -0
  172. package/dist/internal/release.js +25 -0
  173. package/dist/internal/release.js.map +1 -0
  174. package/dist/internal/runner/Bootstrap.js +11 -0
  175. package/dist/internal/runner/Bootstrap.js.map +1 -0
  176. package/dist/internal/runner/Connection.d.ts +11 -0
  177. package/dist/internal/runner/Connection.js +56 -0
  178. package/dist/internal/runner/Connection.js.map +1 -0
  179. package/dist/internal/runner/Execution.js +115 -0
  180. package/dist/internal/runner/Execution.js.map +1 -0
  181. package/dist/internal/runner/Framing.d.ts +11 -0
  182. package/dist/internal/runner/Framing.d.ts.map +1 -0
  183. package/dist/internal/runner/Framing.js +63 -0
  184. package/dist/internal/runner/Framing.js.map +1 -0
  185. package/dist/internal/runner/Local.js +46 -0
  186. package/dist/internal/runner/Local.js.map +1 -0
  187. package/dist/internal/runner/Lock.js +25 -0
  188. package/dist/internal/runner/Lock.js.map +1 -0
  189. package/dist/internal/runner/Multiplex.d.ts +5 -0
  190. package/dist/internal/runner/Multiplex.js +49 -0
  191. package/dist/internal/runner/Multiplex.js.map +1 -0
  192. package/dist/internal/runner/Packages.d.ts +3 -0
  193. package/dist/internal/runner/Packages.js +108 -0
  194. package/dist/internal/runner/Packages.js.map +1 -0
  195. package/dist/internal/runner/ProcessObservation.js +40 -0
  196. package/dist/internal/runner/ProcessObservation.js.map +1 -0
  197. package/dist/internal/runner/Processes.js +83 -0
  198. package/dist/internal/runner/Processes.js.map +1 -0
  199. package/dist/internal/runner/Retention.js +13 -0
  200. package/dist/internal/runner/Retention.js.map +1 -0
  201. package/dist/internal/runner/Store.js +78 -0
  202. package/dist/internal/runner/Store.js.map +1 -0
  203. package/dist/internal/runner/Supervisor.js +375 -0
  204. package/dist/internal/runner/Supervisor.js.map +1 -0
  205. package/dist/internal/runner/Watchdog.js +47 -0
  206. package/dist/internal/runner/Watchdog.js.map +1 -0
  207. package/dist/internal/runner/WatchdogProtocol.js +19 -0
  208. package/dist/internal/runner/WatchdogProtocol.js.map +1 -0
  209. package/dist/internal/runner/Wire.d.ts +5 -0
  210. package/dist/internal/runner/Wire.js +64 -0
  211. package/dist/internal/runner/Wire.js.map +1 -0
  212. package/dist/internal/runner/accept.js +57 -0
  213. package/dist/internal/runner/accept.js.map +1 -0
  214. package/dist/internal/runner/command.js +9 -0
  215. package/dist/internal/runner/command.js.map +1 -0
  216. package/dist/internal/runner/connectionEnded.js +11 -0
  217. package/dist/internal/runner/connectionEnded.js.map +1 -0
  218. package/dist/internal/runner/model.d.ts +17 -0
  219. package/dist/internal/runner/model.d.ts.map +1 -0
  220. package/dist/internal/runner/model.js +231 -0
  221. package/dist/internal/runner/model.js.map +1 -0
  222. package/dist/internal/serve.js +60 -0
  223. package/dist/internal/serve.js.map +1 -0
  224. package/dist/internal/services.d.ts +18 -0
  225. package/dist/internal/services.d.ts.map +1 -0
  226. package/dist/internal/services.js +22 -0
  227. package/dist/internal/services.js.map +1 -0
  228. package/dist/internal/socketChannel.js +24 -0
  229. package/dist/internal/socketChannel.js.map +1 -0
  230. package/dist/internal/stdioChannel.js +23 -0
  231. package/dist/internal/stdioChannel.js.map +1 -0
  232. package/dist/internal/supervisorPlugin.js +1 -0
  233. package/dist/internal/supervisorPlugin.js.map +1 -0
  234. package/dist/internal/transportOptions.d.ts +18 -0
  235. package/dist/internal/transportOptions.d.ts.map +1 -0
  236. package/dist/internal/watchdogMain.d.ts +1 -0
  237. package/dist/internal/watchdogMain.js +55 -0
  238. package/dist/internal/watchdogMain.js.map +1 -0
  239. package/dist/internal/websocket.js +46 -0
  240. package/dist/internal/websocket.js.map +1 -0
  241. package/dist/internal/websocketServer.js +61 -0
  242. package/dist/internal/websocketServer.js.map +1 -0
  243. package/dist/internal/workerBootstrap.js +9 -0
  244. package/dist/internal/workerBootstrap.js.map +1 -0
  245. package/dist/internal/workerChannel.js +24 -0
  246. package/dist/internal/workerChannel.js.map +1 -0
  247. package/dist/internal/workerMain.d.ts +1 -0
  248. package/dist/internal/workerMain.js +18 -0
  249. package/dist/internal/workerMain.js.map +1 -0
  250. package/dist/port-Blbh8tms.js +285 -0
  251. package/dist/release-BY4Mlluy.js +23 -0
  252. package/dist/rolldown-runtime-DYf_mQCB.js +34 -0
  253. package/dist/runner/auth/bearer.d.ts +7 -0
  254. package/dist/runner/auth/bearer.d.ts.map +1 -0
  255. package/dist/runner/auth/bearer.js +42 -0
  256. package/dist/runner/auth/bearer.js.map +1 -0
  257. package/dist/runner/auth/jwt.d.ts +19 -0
  258. package/dist/runner/auth/jwt.d.ts.map +1 -0
  259. package/dist/runner/auth/jwt.js +65 -0
  260. package/dist/runner/auth/jwt.js.map +1 -0
  261. package/dist/runner/auth/mtls.d.ts +11 -0
  262. package/dist/runner/auth/mtls.d.ts.map +1 -0
  263. package/dist/runner/auth/mtls.js +48 -0
  264. package/dist/runner/auth/mtls.js.map +1 -0
  265. package/dist/runner/auth/none.d.ts +3 -0
  266. package/dist/runner/auth/none.d.ts.map +1 -0
  267. package/dist/runner/auth/none.js +13 -0
  268. package/dist/runner/auth/none.js.map +1 -0
  269. package/dist/runner/index.d.ts +3 -0
  270. package/dist/runner/index.d.ts.map +1 -0
  271. package/dist/runner/index.js +71 -0
  272. package/dist/runner/index.js.map +1 -0
  273. package/dist/runner/stdio.d.ts +7 -0
  274. package/dist/runner/stdio.d.ts.map +1 -0
  275. package/dist/runner/stdio.js +39 -0
  276. package/dist/runner/stdio.js.map +1 -0
  277. package/dist/runner/unix.d.ts +7 -0
  278. package/dist/runner/unix.d.ts.map +1 -0
  279. package/dist/runner/unix.js +42 -0
  280. package/dist/runner/unix.js.map +1 -0
  281. package/dist/runner/websocket.d.ts +28 -0
  282. package/dist/runner/websocket.d.ts.map +1 -0
  283. package/dist/runner/websocket.js +77 -0
  284. package/dist/runner/websocket.js.map +1 -0
  285. package/dist/socketChannel-KmtzF-9G.js +3658 -0
  286. package/dist/supervisorPlugin-Inb1S5IV.js +737 -0
  287. package/dist/token-v5ne2I0-.js +17 -0
  288. package/dist/tokenCredentials-WUJm2AKm.js +31 -0
  289. package/dist/websocketServer-MXcCJx0v.js +58 -0
  290. package/dist/workerChannel-P82YdNjh.js +27 -0
  291. package/package.json +69 -3
  292. package/src/Auth.ts +62 -0
  293. package/src/Contract.ts +100 -0
  294. package/src/Errors.ts +82 -0
  295. package/src/Instance.ts +12 -0
  296. package/src/Testing.ts +135 -0
  297. package/src/Transport.ts +52 -0
  298. package/src/bin.ts +145 -0
  299. package/src/host/auth/bearer.ts +10 -0
  300. package/src/host/auth/jwt.ts +10 -0
  301. package/src/host/auth/mtls.ts +48 -0
  302. package/src/host/auth/none.ts +13 -0
  303. package/src/host/command.ts +131 -0
  304. package/src/host/local.ts +41 -0
  305. package/src/host/unix.ts +65 -0
  306. package/src/host/websocket.ts +66 -0
  307. package/src/host/worker.ts +90 -0
  308. package/src/index.ts +115 -0
  309. package/src/internal/Certificates.ts +330 -0
  310. package/src/internal/FailureGroup.ts +176 -0
  311. package/src/internal/Limits.ts +12 -0
  312. package/src/internal/Peer.ts +4 -0
  313. package/src/internal/ServeLifecycle.ts +53 -0
  314. package/src/internal/Supervisor.ts +14 -0
  315. package/src/internal/assembly.ts +337 -0
  316. package/src/internal/auth/mtls.ts +40 -0
  317. package/src/internal/auth/token.ts +26 -0
  318. package/src/internal/auth/tokenCredentials.ts +65 -0
  319. package/src/internal/child.ts +323 -0
  320. package/src/internal/childErrors.ts +44 -0
  321. package/src/internal/childRuntime.ts +111 -0
  322. package/src/internal/cleanup.ts +34 -0
  323. package/src/internal/config.ts +8 -0
  324. package/src/internal/control.ts +49 -0
  325. package/src/internal/credentials.ts +112 -0
  326. package/src/internal/directTransport.ts +38 -0
  327. package/src/internal/entry.ts +288 -0
  328. package/src/internal/entryConfig.ts +190 -0
  329. package/src/internal/execution.ts +121 -0
  330. package/src/internal/follow.ts +17 -0
  331. package/src/internal/forkTree.ts +13 -0
  332. package/src/internal/host/local.ts +53 -0
  333. package/src/internal/host/runner.ts +187 -0
  334. package/src/internal/host.ts +209 -0
  335. package/src/internal/importer.ts +27 -0
  336. package/src/internal/listenerStartup.ts +55 -0
  337. package/src/internal/loadModule.ts +23 -0
  338. package/src/internal/platform.ts +12 -0
  339. package/src/internal/port.ts +623 -0
  340. package/src/internal/release.ts +71 -0
  341. package/src/internal/runner/Bootstrap.ts +9 -0
  342. package/src/internal/runner/Connection.ts +184 -0
  343. package/src/internal/runner/Execution.ts +244 -0
  344. package/src/internal/runner/Framing.ts +122 -0
  345. package/src/internal/runner/Local.ts +73 -0
  346. package/src/internal/runner/Lock.ts +29 -0
  347. package/src/internal/runner/Multiplex.ts +120 -0
  348. package/src/internal/runner/Packages.ts +178 -0
  349. package/src/internal/runner/ProcessObservation.ts +63 -0
  350. package/src/internal/runner/Processes.ts +109 -0
  351. package/src/internal/runner/Retention.ts +49 -0
  352. package/src/internal/runner/Store.ts +160 -0
  353. package/src/internal/runner/Supervisor.ts +901 -0
  354. package/src/internal/runner/Watchdog.ts +83 -0
  355. package/src/internal/runner/WatchdogProtocol.ts +12 -0
  356. package/src/internal/runner/Wire.ts +99 -0
  357. package/src/internal/runner/accept.ts +103 -0
  358. package/src/internal/runner/command.ts +15 -0
  359. package/src/internal/runner/connectionEnded.ts +28 -0
  360. package/src/internal/runner/model.ts +364 -0
  361. package/src/internal/serve.ts +117 -0
  362. package/src/internal/services.ts +74 -0
  363. package/src/internal/socketChannel.ts +64 -0
  364. package/src/internal/stdioChannel.ts +25 -0
  365. package/src/internal/supervisorPlugin.ts +67 -0
  366. package/src/internal/transportOptions.ts +17 -0
  367. package/src/internal/watchdogMain.ts +72 -0
  368. package/src/internal/websocket.ts +81 -0
  369. package/src/internal/websocketServer.ts +152 -0
  370. package/src/internal/workerBootstrap.ts +6 -0
  371. package/src/internal/workerChannel.ts +54 -0
  372. package/src/internal/workerMain.ts +23 -0
  373. package/src/runner/auth/bearer.ts +66 -0
  374. package/src/runner/auth/jwt.ts +114 -0
  375. package/src/runner/auth/mtls.ts +37 -0
  376. package/src/runner/auth/none.ts +13 -0
  377. package/src/runner/index.ts +97 -0
  378. package/src/runner/stdio.ts +76 -0
  379. package/src/runner/unix.ts +53 -0
  380. package/src/runner/websocket.ts +143 -0
@@ -0,0 +1,737 @@
1
+ import { a as provide, l as make$2, o as fork, u as optional } from "./Graft-BsYq3F-J.js";
2
+ import { a as PositiveDuration, i as Supervisor$1, t as resolve } from "./Packages-B1TPk8pa.js";
3
+ import { t as ConfigDirectory } from "./ConfigDirectory-BCC6q2R4.js";
4
+ import { C as negotiate, E as make$3, S as keyOf, T as stoppingRecord, _ as StateStorageError, a as ExecutionError, d as SessionAccessDenied, f as SessionConflict, g as StateDirectoryLocked, h as StaleSession, i as Execution, m as SessionStopped, n as Session$1, o as Key, p as SessionRecord, r as channel, s as LeaseExpired, t as Peer, u as RunnerClosing, v as Store, w as stoppedRecord, x as childOf, y as TerminationUnconfirmed } from "./Peer-IJgFK6mD.js";
5
+ import { t as observe } from "./ProcessObservation-DEGrEMfP.js";
6
+ import { t as make$4 } from "./FailureGroup-BcH0XOBi.js";
7
+ import { t as CommandJson } from "./WatchdogProtocol-BZmVxrBP.js";
8
+ import { c as TransportError } from "./Errors-oPsTLY7l.js";
9
+ import { t as Bootstrap } from "./Bootstrap-MCwivGN1.js";
10
+ import { t as command } from "./command-9zrHdbwT.js";
11
+ import { n as close } from "./release-BY4Mlluy.js";
12
+ import { n as cleanupCause } from "./cleanup-BPWr-5U9.js";
13
+ import { n as make$5, o as defaults } from "./port-Blbh8tms.js";
14
+ import { i as resources, t as ServeLifecycle } from "./ServeLifecycle-CJM0gG5B.js";
15
+ import { Array, Cause, Clock, Context, Data, Deferred, Duration, Effect, Equal, Exit, FiberHandle, FiberSet, FileSystem, HashMap, HashSet, Layer, Option, Path, Queue, RcMap, Ref, Result, Schedule, Schema, Scope, Semaphore, Sink, Stream, String, SynchronizedRef } from "effect";
16
+ import process from "node:process";
17
+ import { Digest, SecureRandom } from "effect/crypto";
18
+ import { RpcServer } from "effect/rpc";
19
+ import { ChildProcess, ChildProcessSpawner } from "effect/process";
20
+ // packages/remote/src/internal/runner/Lock.ts
21
+ /** SQLite owns the local directory lock for the enclosing scope, including failed startup. */
22
+ const acquire = (directory) => Effect.gen(function* () {
23
+ const fs = yield* FileSystem.FileSystem;
24
+ const path = yield* Path.Path;
25
+ yield* fs.makeDirectory(directory, { recursive: true }).pipe(Effect.uninterruptible);
26
+ const { DatabaseSync } = yield* Effect.promise(() => import("node:sqlite")).pipe(Effect.uninterruptible);
27
+ const locked = (cause) => StateDirectoryLocked.make({
28
+ detail: "The runner state directory is already owned or cannot be locked",
29
+ cause: Cause.die(cause)
30
+ });
31
+ const db = yield* Effect.acquireRelease(Effect.try({
32
+ try: () => new DatabaseSync(path.join(directory, "owner.sqlite")),
33
+ catch: locked
34
+ }), (db) => Effect.sync(() => db.close()));
35
+ yield* Effect.try({
36
+ try: () => db.exec("BEGIN EXCLUSIVE"),
37
+ catch: locked
38
+ });
39
+ });
40
+ // packages/remote/src/internal/runner/Retention.ts
41
+ /** A terminal high-water record fences every older Open, even after its request id is forgotten. */
42
+ const retain = (records) => {
43
+ const highWater = Array.reduce(records, HashMap.empty(), (water, record) => HashMap.set(water, keyOf(record.handle.key), Math.max(Option.getOrElse(HashMap.get(water, keyOf(record.handle.key)), () => 0), record.handle.generation)));
44
+ return Array.filter(records, (record) => record.phase !== "Stopped" || record.handle.generation === Option.getOrUndefined(HashMap.get(highWater, keyOf(record.handle.key))));
45
+ };
46
+ /** Apply the same retention rule to both in-memory stores. */
47
+ const save = (records, record) => HashMap.fromIterable(Array.map(retain(Array.fromIterable(HashMap.values(HashMap.set(records, record.handle.token, record)))), (record) => [record.handle.token, record]));
48
+ // packages/remote/src/internal/runner/Store.ts
49
+ /** Injectable store used by deterministic supervisor tests. */
50
+ const memory = Effect.gen(function* () {
51
+ const records = yield* Ref.make(HashMap.empty());
52
+ return Store.of({
53
+ list: Ref.get(records).pipe(Effect.map((records) => Array.fromIterable(HashMap.values(records)))),
54
+ save: (record) => Ref.update(records, (all) => save(all, record))
55
+ });
56
+ });
57
+ /**
58
+ * Atomically replaced records retain unfinished sessions and each key's high-water mark.
59
+ * Older terminal request ids expire; Open fences their retries with expectedGeneration.
60
+ * Requires exclusive directory ownership; it is not a multi-writer database.
61
+ */
62
+ const directory = (root) => Effect.gen(function* () {
63
+ const fs = yield* FileSystem.FileSystem;
64
+ const path = yield* Path.Path;
65
+ const digest = yield* Digest.Digest;
66
+ const json = Schema.fromJsonString(Schema.toCodecJson(SessionRecord));
67
+ const random = yield* SecureRandom.SecureRandom;
68
+ const storage = (effect) => effect.pipe(Effect.mapError((error) => error._tag === "StateStorageError" ? error : StateStorageError.make({
69
+ detail: "Runner state storage failed",
70
+ cause: Cause.fail(error)
71
+ })));
72
+ yield* storage(fs.makeDirectory(root, { recursive: true }).pipe(Effect.uninterruptible));
73
+ const mutex = yield* Semaphore.make(1);
74
+ const read = Effect.gen(function* () {
75
+ const files = yield* fs.readDirectory(root);
76
+ return yield* Effect.forEach(Array.filter(files, String.endsWith(".json")), (file) => fs.readFileString(path.join(root, file)).pipe(Effect.flatMap(Schema.decodeEffect(json)), Effect.map((record) => ({
77
+ file,
78
+ record
79
+ }))));
80
+ });
81
+ const compact = Effect.scoped(Effect.gen(function* () {
82
+ const rows = yield* read;
83
+ const retained = retain(Array.map(rows, (row) => row.record));
84
+ const tokens = HashSet.fromIterable(Array.map(retained, (record) => record.handle.token));
85
+ const obsolete = Array.filter(rows, (row) => !HashSet.has(tokens, row.record.handle.token));
86
+ yield* Effect.forEach(obsolete, (row) => fs.remove(path.join(root, row.file)).pipe(Effect.uninterruptible), { discard: true });
87
+ if (obsolete.length > 0) yield* (yield* fs.open(root, { flag: "r" })).sync.pipe(Effect.uninterruptible);
88
+ }));
89
+ yield* storage(compact);
90
+ return Store.of({
91
+ list: storage(mutex.withPermit(read.pipe(Effect.map((rows) => Array.map(rows, (row) => row.record))))),
92
+ save: (record) => storage(mutex.withPermit(Effect.scoped(Effect.gen(function* () {
93
+ const encoded = yield* Schema.encodeEffect(json)(record);
94
+ const address = yield* Schema.encodeEffect(Schema.fromJsonString(Schema.Struct({
95
+ key: Key,
96
+ generation: Schema.Int
97
+ })))({
98
+ key: record.handle.key,
99
+ generation: record.handle.generation
100
+ });
101
+ const name = yield* digest.digestHex(Digest.sha256, new TextEncoder().encode(address));
102
+ const nonce = yield* random.uuidV4();
103
+ const temporary = path.join(root, `.${name}.${nonce}.tmp`);
104
+ const destination = path.join(root, name + ".json");
105
+ yield* Effect.acquireRelease(fs.open(temporary, {
106
+ flag: "wx",
107
+ mode: 384
108
+ }), () => fs.remove(temporary, { force: true }).pipe(Effect.orDie)).pipe(Effect.flatMap((file) => file.writeAll(new TextEncoder().encode(encoded)).pipe(Effect.uninterruptible, Effect.andThen(file.sync.pipe(Effect.uninterruptible)))));
109
+ yield* Effect.uninterruptible(Effect.gen(function* () {
110
+ yield* fs.rename(temporary, destination);
111
+ yield* (yield* fs.open(root, { flag: "r" })).sync.pipe(Effect.uninterruptible);
112
+ }));
113
+ yield* compact;
114
+ }))))
115
+ });
116
+ });
117
+ Layer.effect(Store, memory);
118
+ const layerDirectory = (root) => Layer.effect(Store, directory(root));
119
+ // packages/remote/src/internal/runner/Processes.ts
120
+ const inspect = (pid) => Effect.scoped(Effect.gen(function* () {
121
+ const child = yield* (yield* ChildProcessSpawner.ChildProcessSpawner).spawn(ChildProcess.make("ps", [
122
+ "-p",
123
+ `${pid}`,
124
+ "-o",
125
+ "lstart=",
126
+ "-o",
127
+ "stat="
128
+ ], {
129
+ env: {
130
+ ...process.env,
131
+ LC_ALL: "C"
132
+ },
133
+ stdin: "ignore"
134
+ }));
135
+ const [code, output, stderr] = yield* Effect.all([
136
+ child.exitCode,
137
+ child.stdout.pipe(Stream.decodeText(), Stream.mkString),
138
+ child.stderr.pipe(Stream.decodeText(), Stream.mkString)
139
+ ], { concurrency: "unbounded" });
140
+ if (code === 1 && String.trim(output) === "") return Option.none();
141
+ const [, born, status] = /^(.{24})\s+(\S+)$/m.exec(String.trim(output)) ?? [];
142
+ if (code !== 0 || born === void 0 || status === void 0) return yield* ExecutionError.make({ detail: "Cannot inspect process identity: " + stderr });
143
+ if (String.startsWith("Z")(status)) return Option.none();
144
+ return Option.some({ born });
145
+ })).pipe(Effect.mapError((error) => error._tag === "ExecutionError" ? error : ExecutionError.make({
146
+ detail: "Inspecting process identity failed",
147
+ cause: Cause.fail(error)
148
+ })));
149
+ const identity = (pid) => Effect.gen(function* () {
150
+ const current = yield* inspect(pid);
151
+ if (Option.isNone(current)) return yield* ExecutionError.make({ detail: "The child exited before its identity could be recorded" });
152
+ return {
153
+ pid,
154
+ start: current.value
155
+ };
156
+ });
157
+ const matches = (child) => Effect.gen(function* () {
158
+ const current = yield* inspect(child.pid);
159
+ if (Option.isNone(current) || current.value.born !== child.start.born) return false;
160
+ return true;
161
+ });
162
+ const recover$1 = (child) => Effect.gen(function* () {
163
+ if (!(yield* matches(child))) return {
164
+ kind: "Exited",
165
+ exit: {
166
+ code: null,
167
+ signal: null
168
+ },
169
+ cause: Cause.empty
170
+ };
171
+ const sent = yield* Effect.exit(Effect.try({
172
+ try: () => process.kill(child.pid, "SIGKILL"),
173
+ catch: (cause) => ExecutionError.make({
174
+ detail: "Signaling the orphan failed",
175
+ cause: Cause.die(cause)
176
+ })
177
+ }));
178
+ const confirmed = yield* matches(child).pipe(Effect.repeat({
179
+ schedule: Schedule.spaced("50 millis"),
180
+ while: (value) => value
181
+ }), Effect.timeoutOption("10 seconds"));
182
+ if (Option.isNone(confirmed)) return yield* TerminationUnconfirmed.make({
183
+ detail: "The orphan did not exit after recovery",
184
+ cause: sent._tag === "Failure" ? sent.cause : Cause.empty
185
+ });
186
+ return {
187
+ kind: "Killed",
188
+ exit: {
189
+ code: null,
190
+ signal: "SIGKILL"
191
+ },
192
+ cause: sent._tag === "Failure" ? sent.cause : Cause.empty
193
+ };
194
+ });
195
+ // packages/remote/src/internal/runner/Execution.ts
196
+ var Channels = class extends Context.Service()("@graftland/plugin-remote/internal/runner/Execution/Channels") {};
197
+ const make$1 = (root) => Effect.gen(function* () {
198
+ const spawner = yield* ChildProcessSpawner.ChildProcessSpawner;
199
+ const fs = yield* FileSystem.FileSystem;
200
+ const path = yield* Path.Path;
201
+ const platform = Context.make(ChildProcessSpawner.ChildProcessSpawner, spawner).pipe(Context.add(FileSystem.FileSystem, fs), Context.add(Path.Path, path));
202
+ const peers = yield* Ref.make(HashMap.empty());
203
+ const claimed = yield* Ref.make(HashSet.empty());
204
+ return {
205
+ driver: Execution.of({
206
+ recover: (child) => recover$1(child).pipe(Effect.provideContext(platform)),
207
+ spawn: (handle, request, limits) => Effect.gen(function* () {
208
+ const resolved = yield* resolve(root, request.specifier, request.digest);
209
+ const argv = yield* command();
210
+ const child = yield* spawner.spawn(ChildProcess.make(argv[0], [
211
+ ...Array.drop(argv, 1),
212
+ "child",
213
+ resolved.entry,
214
+ handle.token,
215
+ yield* Schema.encodeEffect(Schema.fromJsonString(Bootstrap))({
216
+ identity: {
217
+ id: handle.key.instance,
218
+ generation: handle.generation
219
+ },
220
+ limits
221
+ })
222
+ ], {
223
+ stdin: "pipe",
224
+ stdout: "pipe",
225
+ stderr: "pipe",
226
+ additionalFds: {
227
+ fd3: { type: "output" },
228
+ fd4: { type: "input" }
229
+ },
230
+ forceKillAfter: "1 second"
231
+ }));
232
+ const observation = yield* observe(child);
233
+ const exited = observation.exited.pipe(Effect.mapError((error) => ExecutionError.make({
234
+ detail: "Observing child exit failed",
235
+ cause: Cause.fail(error)
236
+ })));
237
+ const failures = yield* make$4();
238
+ yield* failures.run(observation.failure.pipe(Effect.mapError((error) => ExecutionError.make({
239
+ detail: "Reading child output failed",
240
+ cause: Cause.fail(error)
241
+ }))));
242
+ const controls = yield* Queue.bounded(4);
243
+ yield* failures.run(Stream.fromQueue(controls).pipe(Stream.map((line) => new TextEncoder().encode(line + "\n")), Stream.run(child.getInputFd(4)), Effect.mapError((error) => ExecutionError.make({
244
+ detail: "Child supervision channel failed",
245
+ cause: Cause.fail(error)
246
+ }))));
247
+ const send = (value) => Effect.raceFirst(Schema.encodeEffect(CommandJson)(value).pipe(Effect.flatMap((line) => Queue.offer(controls, line)), Effect.asVoid, Effect.mapError((error) => ExecutionError.make({
248
+ detail: "Encoding watchdog command failed",
249
+ cause: Cause.fail(error)
250
+ }))), failures.await);
251
+ const peer = yield* make$3({
252
+ input: child.getOutputFd(3).pipe(Stream.mapError((error) => TransportError.make({ cause: Cause.fail(error) }))),
253
+ output: child.stdin.pipe(Sink.mapError((error) => TransportError.make({ cause: Cause.fail(error) })))
254
+ });
255
+ const identity$1 = yield* identity(child.pid);
256
+ yield* Ref.update(peers, HashMap.set(handle.token, peer));
257
+ yield* Effect.addFinalizer(() => Ref.update(peers, HashMap.remove(handle.token)));
258
+ return {
259
+ code: resolved.identity,
260
+ start: send({ kind: "start" }),
261
+ identity: identity$1,
262
+ exited,
263
+ interrupt: send({ kind: "stop" }),
264
+ kill: child.kill({ killSignal: "SIGKILL" }).pipe(Effect.mapError((error) => ExecutionError.make({
265
+ detail: "Killing the child failed",
266
+ cause: Cause.fail(error)
267
+ }))),
268
+ renew: (millis) => send({
269
+ kind: "renew",
270
+ millis
271
+ })
272
+ };
273
+ }).pipe(Effect.provideContext(platform), Effect.catchTags({
274
+ PlatformError: (error) => Effect.fail(ExecutionError.make({
275
+ detail: "Starting the child failed",
276
+ cause: Cause.fail(error)
277
+ })),
278
+ SchemaError: (error) => Effect.fail(ExecutionError.make({
279
+ detail: "Encoding child bootstrap failed",
280
+ cause: Cause.fail(error)
281
+ }))
282
+ }))
283
+ }),
284
+ peer: (token) => Effect.acquireRelease(Effect.gen(function* () {
285
+ const peer = yield* Ref.get(peers).pipe(Effect.flatMap((all) => {
286
+ const peer = HashMap.get(all, token);
287
+ return peer._tag === "Some" ? Effect.succeed(peer.value) : Effect.fail(SessionStopped.make({ detail: "The execution channel is no longer available" }));
288
+ }));
289
+ if (yield* Ref.modify(claimed, (all) => [HashSet.has(all, token), HashSet.add(all, token)])) return yield* SessionConflict.make({ detail: "The instance channel is already attached" });
290
+ return peer;
291
+ }), () => Ref.update(claimed, HashSet.remove(token)))
292
+ };
293
+ });
294
+ const layer$1 = (root) => Layer.effectContext(make$1(root).pipe(Effect.map((execution) => Context.make(Execution, execution.driver).pipe(Context.add(Channels, { peer: execution.peer })))));
295
+ // packages/remote/src/internal/runner/Supervisor.ts
296
+ var Supervisor = class extends Context.Service()("@graftland/plugin-remote/internal/runner/Supervisor") {};
297
+ const Launch = Data.taggedEnum();
298
+ const ExecutionState = Data.taggedEnum();
299
+ const Session = Data.taggedEnum();
300
+ function snapshot(state) {
301
+ return state._tag === "Loading" ? {
302
+ ...state.record,
303
+ phase: "Loading",
304
+ load: state.request,
305
+ launch: state.launch._tag === "Starting" ? { _tag: "Starting" } : {
306
+ _tag: "Registered",
307
+ child: state.launch.unit.identity
308
+ }
309
+ } : state.record;
310
+ }
311
+ const live = (state, now) => {
312
+ if (state._tag === "Stopping" || state._tag === "Stopped") return Result.fail(state.record.reason._tag === "Expired" ? LeaseExpired.make({ detail: "The session lease has expired" }) : SessionStopped.make({ detail: "The session is stopping or stopped" }));
313
+ return now >= state.deadline ? Result.fail(LeaseExpired.make({ detail: "The session lease has expired" })) : Result.succeed(state);
314
+ };
315
+ const executionOf = (state) => {
316
+ switch (state._tag) {
317
+ case "Open": return ExecutionState.Absent();
318
+ case "Loading": return state.launch._tag === "Registered" ? ExecutionState.Running({ unit: state.launch.unit }) : ExecutionState.Absent();
319
+ case "Loaded": return ExecutionState.Running({ unit: state.unit });
320
+ }
321
+ };
322
+ /** All state transitions are pure; the caller serializes persistence and publication. */
323
+ const beginLoad = (state, request, reply) => Session.Loading({
324
+ record: state.record,
325
+ deadline: state.deadline,
326
+ request,
327
+ reply,
328
+ launch: Launch.Starting()
329
+ });
330
+ const registerUnit = (state, unit) => {
331
+ if (state._tag !== "Loading") return Result.fail(SessionStopped.make({ detail: "The session is stopping or stopped" }));
332
+ if (state.launch._tag === "Registered") return Result.fail(ExecutionError.make({ detail: "An execution adapter registered more than one child" }));
333
+ return Result.succeed(Session.Loading({
334
+ ...state,
335
+ launch: Launch.Registered({ unit })
336
+ }));
337
+ };
338
+ const loaded = (state, code) => {
339
+ if (state._tag !== "Loading") return Result.fail(SessionStopped.make({ detail: "The session is stopping or stopped" }));
340
+ if (state.launch._tag !== "Registered") return Result.fail(ExecutionError.make({ detail: "Execution adapter returned without registering its child" }));
341
+ return Result.succeed(Session.Loaded({
342
+ deadline: state.deadline,
343
+ unit: state.launch.unit,
344
+ record: {
345
+ ...state.record,
346
+ phase: "Loaded",
347
+ load: state.request,
348
+ code,
349
+ child: state.launch.unit.identity
350
+ }
351
+ }));
352
+ };
353
+ const beginStop = (state, reason, reply, exit) => Session.Stopping({
354
+ record: stoppingRecord(snapshot(state), reason),
355
+ reply,
356
+ execution: Option.match(exit, {
357
+ onNone: () => executionOf(state),
358
+ onSome: (exit) => ExecutionState.Exited({ exit })
359
+ })
360
+ });
361
+ const nanos = (millis) => BigInt(Math.ceil(millis * 1e6));
362
+ const emptyTermination = {
363
+ kind: "Exited",
364
+ exit: {
365
+ code: 0,
366
+ signal: null
367
+ },
368
+ cause: Cause.empty
369
+ };
370
+ const exitCause = (exit) => Exit.isFailure(exit) ? exit.cause : Cause.empty;
371
+ /** A signal is a request; only the exited effect confirms that the execution has stopped. */
372
+ const terminate = (execution, grace, confirmation) => {
373
+ if (execution._tag === "Absent") return Effect.succeed(emptyTermination);
374
+ if (execution._tag === "Exited") return Effect.succeed({
375
+ ...emptyTermination,
376
+ exit: execution.exit
377
+ });
378
+ const child = execution.unit;
379
+ return Effect.gen(function* () {
380
+ const graceful = yield* child.interrupt.pipe(Effect.andThen(child.exited), Effect.timeoutOption(grace), Effect.exit);
381
+ if (Exit.isSuccess(graceful) && Option.isSome(graceful.value)) return {
382
+ ...emptyTermination,
383
+ exit: graceful.value.value
384
+ };
385
+ const killed = yield* Effect.exit(child.kill);
386
+ const forced = yield* child.exited.pipe(Effect.timeoutOption(confirmation), Effect.exit);
387
+ const cause = Cause.combine(Cause.combine(exitCause(graceful), exitCause(killed)), exitCause(forced));
388
+ if (Exit.isFailure(forced) || Option.isNone(forced.value)) return yield* TerminationUnconfirmed.make({
389
+ detail: "The child exit could not be confirmed",
390
+ cause
391
+ });
392
+ return {
393
+ kind: "Killed",
394
+ exit: forced.value.value,
395
+ cause
396
+ };
397
+ });
398
+ };
399
+ const initialize = (options = {}) => Effect.gen(function* () {
400
+ const store = yield* Store;
401
+ const execution = yield* Execution;
402
+ const random = yield* SecureRandom.SecureRandom;
403
+ const parent = yield* Effect.scope;
404
+ const owner = yield* Scope.fork(parent);
405
+ return {
406
+ store,
407
+ execution,
408
+ random,
409
+ owner,
410
+ workers: yield* FiberSet.make().pipe(Scope.provide(owner)),
411
+ locks: yield* RcMap.make({ lookup: (_key) => Semaphore.make(1) }).pipe(Scope.provide(owner)),
412
+ lease: Duration.toMillis(options.lease ?? "15 seconds"),
413
+ grace: Duration.toMillis(options.grace ?? "5 seconds"),
414
+ confirmation: Duration.toMillis(options.confirmationTimeout ?? "5 seconds"),
415
+ limits: options.limits ?? defaults,
416
+ records: yield* Ref.make(HashMap.empty()),
417
+ entries: yield* Ref.make(HashMap.empty()),
418
+ health: yield* make$4().pipe(Scope.provide(owner)),
419
+ closing: yield* Ref.make(false)
420
+ };
421
+ });
422
+ const operations = (runtime) => {
423
+ const { store, execution, workers, grace, confirmation, records, entries, health, closing } = runtime;
424
+ const poison = health.failCause;
425
+ const observe = (effect) => effect.pipe(Effect.asVoid, Effect.catchCause(poison));
426
+ const healthy = health.check.pipe(Effect.andThen(Effect.gen(function* () {
427
+ if (yield* Ref.get(closing)) return yield* RunnerClosing.make({ detail: "The runner is closing" });
428
+ })));
429
+ const persist = (record) => store.save(record).pipe(Effect.tapCause(poison), Effect.andThen(Ref.update(records, (all) => save(all, record))));
430
+ const status = (handle) => Ref.get(records).pipe(Effect.flatMap((all) => {
431
+ const found = HashMap.get(all, handle.token);
432
+ return Option.isSome(found) && Equal.equals(keyOf(found.value.handle.key), keyOf(handle.key)) && found.value.handle.generation === handle.generation ? Effect.succeed(found.value) : Effect.fail(StaleSession.make({ detail: "Unknown session or generation" }));
433
+ }));
434
+ const latest = (key) => Ref.get(records).pipe(Effect.map((all) => Array.reduce(Array.fromIterable(HashMap.values(all)), 0, (value, record) => Equal.equals(keyOf(record.handle.key), keyOf(key)) ? Math.max(value, record.handle.generation) : value)));
435
+ const entryFor = (handle) => Effect.gen(function* () {
436
+ yield* status(handle);
437
+ const all = yield* Ref.get(entries);
438
+ const found = HashMap.get(all, handle.token);
439
+ if (Option.isNone(found)) return yield* SessionStopped.make({ detail: "The session was retired during recovery" });
440
+ return found.value;
441
+ });
442
+ const commit = (entry, transition) => SynchronizedRef.updateEffect(entry.state, (state) => Effect.gen(function* () {
443
+ const next = yield* Effect.fromResult(transition(state));
444
+ yield* persist(snapshot(next));
445
+ return next;
446
+ }));
447
+ const finishStop = (entry, state, saved) => Effect.gen(function* () {
448
+ yield* FiberHandle.clear(entry.loading);
449
+ const result = yield* terminate(state.execution, grace, confirmation);
450
+ const closed = yield* Effect.exit(close(entry.unitScope, Exit.void));
451
+ const termination = {
452
+ ...result,
453
+ cause: Cause.combine(result.cause, exitCause(closed))
454
+ };
455
+ const record = stoppedRecord(state.record.previous, state.record.reason, termination);
456
+ yield* SynchronizedRef.updateEffect(entry.state, () => persist(record).pipe(Effect.as(Session.Stopped({
457
+ record,
458
+ reply: state.reply
459
+ }))));
460
+ if (Exit.isFailure(saved)) return yield* Effect.failCause(saved.cause);
461
+ return termination;
462
+ });
463
+ /** Called with the session ref locked; the worker starts after its transition is published. */
464
+ const stopLocked = (entry, state, reason, exit) => Effect.gen(function* () {
465
+ if (state._tag === "Stopping" || state._tag === "Stopped") return [state.reply, state];
466
+ const reply = yield* Deferred.make();
467
+ const next = beginStop(state, reason, reply, exit);
468
+ const saved = yield* Effect.exit(persist(next.record));
469
+ yield* FiberSet.run(workers, finishStop(entry, next, saved).pipe(Effect.onExit((result) => Deferred.done(reply, result)), observe), { startImmediately: false });
470
+ return [reply, next];
471
+ });
472
+ const stop = (entry, reason, exit = Option.none()) => SynchronizedRef.modifyEffect(entry.state, (state) => stopLocked(entry, state, reason, exit)).pipe(Effect.uninterruptible);
473
+ const scheduleLease = (entry, deadline) => FiberHandle.run(entry.timer, observe(Effect.gen(function* () {
474
+ const now = yield* Clock.monotonicTimeNanos;
475
+ yield* Effect.sleep(Duration.nanos(deadline > now ? deadline - now : 0n));
476
+ yield* SynchronizedRef.updateEffect(entry.state, (state) => {
477
+ if (state._tag === "Stopping" || state._tag === "Stopped" || state.deadline !== deadline) return Effect.succeed(state);
478
+ return stopLocked(entry, state, { _tag: "Expired" }, Option.none()).pipe(Effect.map(([, next]) => next));
479
+ });
480
+ })), { startImmediately: false });
481
+ const register = (entry, unit) => SynchronizedRef.updateEffect(entry.state, (state) => Effect.gen(function* () {
482
+ const now = yield* Clock.monotonicTimeNanos;
483
+ const current = yield* Effect.fromResult(live(state, now));
484
+ const next = yield* Effect.fromResult(registerUnit(current, unit));
485
+ yield* unit.renew(Number(current.deadline - (yield* Clock.monotonicTimeNanos)) / 1e6);
486
+ yield* persist(snapshot(next));
487
+ yield* FiberSet.run(workers, observe(unit.exited.pipe(Effect.flatMap((exit) => stop(entry, { _tag: "Exited" }, Option.some(exit))))));
488
+ return next;
489
+ })).pipe(Effect.uninterruptible);
490
+ const runLoad = (entry, state) => execution.spawn(state.record.handle, state.request, state.record.limits).pipe(Scope.provide(entry.unitScope), Effect.flatMap((unit) => register(entry, unit).pipe(Effect.andThen(unit.start), Effect.as(unit.code))), Effect.tap((code) => commit(entry, (current) => loaded(current, code))), Effect.onExit((result) => Effect.gen(function* () {
491
+ if (Exit.isSuccess(result)) {
492
+ yield* Deferred.done(state.reply, result);
493
+ return;
494
+ }
495
+ if ((yield* SynchronizedRef.get(entry.state))._tag === "Loading") yield* stop(entry, {
496
+ _tag: "LoadFailed",
497
+ cause: result.cause
498
+ });
499
+ const healthCause = yield* health.cause;
500
+ yield* Deferred.failCause(state.reply, Cause.combine(result.cause, healthCause));
501
+ })), Effect.exit, Effect.asVoid);
502
+ return {
503
+ persist,
504
+ status,
505
+ latest,
506
+ entryFor,
507
+ stop,
508
+ scheduleLease,
509
+ runLoad,
510
+ healthy
511
+ };
512
+ };
513
+ const recover = (runtime, actions) => Effect.gen(function* () {
514
+ const { store, execution, confirmation, records } = runtime;
515
+ const { persist } = actions;
516
+ const stored = yield* store.list;
517
+ yield* Ref.set(records, HashMap.fromIterable(Array.map(stored, (record) => [record.handle.token, record])));
518
+ for (const record of stored) {
519
+ if (record.phase === "Stopped") continue;
520
+ const child = childOf(record);
521
+ const termination = Option.isNone(child) ? emptyTermination : yield* execution.recover(child.value).pipe(Effect.timeout(confirmation), Effect.catchTags({
522
+ ExecutionError: (error) => Effect.fail(TerminationUnconfirmed.make({
523
+ detail: "Orphan recovery did not confirm exit",
524
+ cause: Cause.fail(error)
525
+ })),
526
+ TimeoutError: (error) => Effect.fail(TerminationUnconfirmed.make({
527
+ detail: "Orphan recovery did not confirm exit",
528
+ cause: Cause.fail(error)
529
+ }))
530
+ }));
531
+ yield* persist(stoppedRecord(record.phase === "Stopping" ? record.previous : record, { _tag: "Recovery" }, termination));
532
+ }
533
+ });
534
+ const ownShutdown = (runtime, actions) => Effect.gen(function* () {
535
+ const { entries, health, closing } = runtime;
536
+ const { stop } = actions;
537
+ yield* Effect.addFinalizer(() => Effect.gen(function* () {
538
+ yield* Ref.set(closing, true);
539
+ const all = yield* Ref.get(entries);
540
+ const exits = yield* Effect.forEach(HashMap.values(all), (entry) => stop(entry, { _tag: "Shutdown" }).pipe(Effect.flatMap(Deferred.await), Effect.exit));
541
+ const initial = yield* health.cause;
542
+ const cause = Array.reduce(exits, initial, (cause, exit) => Cause.combine(cause, Exit.isFailure(exit) ? exit.cause : exit.value.cause));
543
+ if (cause.reasons.length > 0) return yield* Effect.failCause(cleanupCause(cause));
544
+ }));
545
+ });
546
+ const protocol = (runtime, actions) => Effect.gen(function* () {
547
+ const { random, owner, locks, lease, limits, records, entries, health } = runtime;
548
+ const { persist, status, latest, entryFor, stop, scheduleLease, runLoad, healthy } = actions;
549
+ return Supervisor.of({
550
+ await: health.await,
551
+ status,
552
+ highWater: (key) => latest(key).pipe(Effect.map((value) => value === 0 ? null : value)),
553
+ open: (request) => Effect.scoped(Effect.gen(function* () {
554
+ yield* healthy;
555
+ const leaseMillis = Duration.toMillis(request.lease ?? lease);
556
+ const negotiated = negotiate(limits, request.limits ?? defaults);
557
+ return yield* (yield* RcMap.get(locks, keyOf(request.key))).withPermit(Effect.gen(function* () {
558
+ yield* healthy;
559
+ const allRecords = yield* Ref.get(records);
560
+ const same = Array.filter(Array.fromIterable(HashMap.values(allRecords)), (row) => Equal.equals(keyOf(row.handle.key), keyOf(request.key)));
561
+ const prior = Array.findFirst(same, (row) => row.requestId === request.requestId);
562
+ if (Option.isSome(prior)) return prior.value;
563
+ const generation = yield* latest(request.key);
564
+ if (generation !== (request.expectedGeneration ?? 0)) return yield* StaleSession.make({ detail: "Open expectedGeneration does not match the generation high-water mark" });
565
+ for (const record of same) {
566
+ const allEntries = yield* Ref.get(entries);
567
+ const entry = HashMap.get(allEntries, record.handle.token);
568
+ if (Option.isSome(entry)) yield* stop(entry.value, { _tag: "Superseded" }).pipe(Effect.flatMap(Deferred.await), Effect.tap((result) => result.cause.reasons.length === 0 ? Effect.void : Effect.logWarning("Superseded remote execution cleanup failed", result.cause).pipe(Effect.annotateLogs({
569
+ "remote.identity": record.handle.key.identity,
570
+ "remote.instance": record.handle.key.instance,
571
+ "remote.generation": record.handle.generation
572
+ }))));
573
+ }
574
+ yield* healthy;
575
+ const token = yield* random.uuidV4();
576
+ const record = {
577
+ version: 1,
578
+ phase: "Open",
579
+ handle: {
580
+ key: request.key,
581
+ token,
582
+ generation: generation + 1
583
+ },
584
+ requestId: request.requestId,
585
+ leaseMillis,
586
+ limits: negotiated
587
+ };
588
+ return yield* Effect.uninterruptible(Effect.gen(function* () {
589
+ yield* persist(record);
590
+ const deadline = (yield* Clock.monotonicTimeNanos) + nanos(leaseMillis);
591
+ const scope = yield* Scope.fork(owner);
592
+ const entry = {
593
+ state: yield* SynchronizedRef.make(Session.Open({
594
+ record,
595
+ deadline
596
+ })),
597
+ scope,
598
+ unitScope: yield* Scope.fork(scope),
599
+ timer: yield* FiberHandle.make().pipe(Scope.provide(scope)),
600
+ loading: yield* FiberHandle.make().pipe(Scope.provide(scope))
601
+ };
602
+ const retained = yield* Ref.get(records);
603
+ const old = yield* Ref.modify(entries, (all) => [Array.filter(Array.fromIterable(HashMap.entries(all)), ([key]) => !HashMap.has(retained, key)), HashMap.set(HashMap.filter(all, (_, key) => HashMap.has(retained, key)), token, entry)]);
604
+ for (const [, retired] of old) yield* close(retired.scope, Exit.void);
605
+ yield* scheduleLease(entry, deadline);
606
+ return record;
607
+ }));
608
+ }));
609
+ })),
610
+ renew: (handle) => Effect.gen(function* () {
611
+ yield* healthy;
612
+ const entry = yield* entryFor(handle);
613
+ return yield* SynchronizedRef.modifyEffect(entry.state, (state) => Effect.gen(function* () {
614
+ const now = yield* Clock.monotonicTimeNanos;
615
+ const current = yield* Effect.fromResult(live(state, now));
616
+ const running = executionOf(current);
617
+ if (running._tag === "Running") yield* running.unit.renew(current.record.leaseMillis);
618
+ const deadline = now + nanos(current.record.leaseMillis);
619
+ yield* scheduleLease(entry, deadline);
620
+ return [current.record.leaseMillis, {
621
+ ...current,
622
+ deadline
623
+ }];
624
+ }));
625
+ }),
626
+ load: (handle, request) => Effect.gen(function* () {
627
+ yield* healthy;
628
+ const entry = yield* entryFor(handle);
629
+ return yield* yield* SynchronizedRef.modifyEffect(entry.state, (state) => Effect.gen(function* () {
630
+ const now = yield* Clock.monotonicTimeNanos;
631
+ const current = yield* Effect.fromResult(live(state, now));
632
+ if (current._tag !== "Open") {
633
+ if ((current._tag === "Loading" ? current.request : current.record.load).specifier !== request.specifier) return yield* SessionConflict.make({ detail: "Load was already requested with a different specifier" });
634
+ return [current._tag === "Loading" ? Deferred.await(current.reply) : Effect.succeed(current.record.code), current];
635
+ }
636
+ const done = yield* Deferred.make();
637
+ const next = beginLoad(current, request, done);
638
+ yield* persist(snapshot(next));
639
+ if (next._tag === "Loading") yield* FiberHandle.run(entry.loading, runLoad(entry, next), { startImmediately: false });
640
+ return [Deferred.await(done), next];
641
+ })).pipe(Effect.uninterruptible);
642
+ }),
643
+ dispose: (handle) => Effect.gen(function* () {
644
+ const record = yield* status(handle);
645
+ if (record.phase === "Stopped") return record.termination;
646
+ const entry = yield* entryFor(handle);
647
+ return yield* stop(entry, { _tag: "Disposed" }).pipe(Effect.flatMap(Deferred.await));
648
+ })
649
+ });
650
+ });
651
+ const make = (options = {}) => Effect.gen(function* () {
652
+ const runtime = yield* initialize(options);
653
+ const actions = operations(runtime);
654
+ yield* recover(runtime, actions);
655
+ yield* ownShutdown(runtime, actions);
656
+ return yield* protocol(runtime, actions);
657
+ });
658
+ const layer = (options = {}) => Layer.effect(Supervisor, make(options));
659
+ // packages/remote/src/internal/runner/accept.ts
660
+ const accept = (supervisor, execution, channel$1) => Effect.gen(function* () {
661
+ const identity = yield* Peer;
662
+ const scope = yield* Effect.scope;
663
+ const mux = yield* make$3(channel$1);
664
+ const peer = yield* make$5(channel(mux, 0), {
665
+ session: "session-v1",
666
+ serve: { session: Session$1 },
667
+ call: {}
668
+ });
669
+ const attached = yield* Ref.make(Option.none());
670
+ const loading = yield* Semaphore.make(1);
671
+ const authorize = (handle) => handle.key.identity === identity ? Effect.void : Effect.fail(SessionAccessDenied.make({ detail: "The session belongs to another authenticated identity" }));
672
+ const handlers = yield* Session$1.toHandlers({
673
+ HighWater: ({ instance }) => supervisor.highWater({
674
+ identity,
675
+ instance
676
+ }),
677
+ Open: ({ instance, requestId, expectedGeneration, leaseMillis, limits }) => supervisor.open({
678
+ key: {
679
+ identity,
680
+ instance
681
+ },
682
+ requestId,
683
+ expectedGeneration,
684
+ ...leaseMillis === void 0 ? {} : { lease: leaseMillis },
685
+ limits
686
+ }),
687
+ Load: ({ handle, ...request }) => Effect.gen(function* () {
688
+ yield* authorize(handle);
689
+ const attachment = yield* Ref.get(attached);
690
+ if (Option.isSome(attachment) && attachment.value !== handle.token) return yield* SessionConflict.make({ detail: "A connection can attach only one execution" });
691
+ const code = yield* supervisor.load(handle, request);
692
+ if (Option.isNone(attachment)) {
693
+ const child = yield* execution.peer(handle.token).pipe(Scope.provide(scope));
694
+ yield* Ref.set(attached, Option.some(handle.token));
695
+ yield* Effect.all([Effect.forever(Effect.flatMap(mux.take(1), (bytes) => child.send(1, bytes))), Effect.forever(Effect.flatMap(child.take(1), (bytes) => mux.send(1, bytes)))], { concurrency: "unbounded" }).pipe(Effect.catchCause((cause) => Cause.hasInterruptsOnly(cause) ? Effect.void : child.fail(TransportError.make({ cause }))), Effect.forkIn(scope));
696
+ }
697
+ return code;
698
+ }).pipe(loading.withPermit),
699
+ Renew: (handle) => authorize(handle).pipe(Effect.andThen(supervisor.renew(handle))),
700
+ Dispose: (handle) => authorize(handle).pipe(Effect.andThen(supervisor.dispose(handle))),
701
+ Status: (handle) => authorize(handle).pipe(Effect.andThen(supervisor.status(handle)))
702
+ });
703
+ return yield* RpcServer.make(Session$1, { disableFatalDefects: true }).pipe(Effect.provideContext(handlers), Effect.provideService(RpcServer.Protocol, peer.serverProtocol("session")), Effect.raceFirst(mux.await));
704
+ });
705
+ // packages/remote/src/internal/supervisorPlugin.ts
706
+ const Config$1 = Schema.Struct({
707
+ root: Schema.String,
708
+ state: Schema.String,
709
+ lease: Schema.optionalKey(PositiveDuration),
710
+ grace: Schema.optionalKey(PositiveDuration)
711
+ });
712
+ var supervisorPlugin_default = make$2({
713
+ name: "remote-supervisor",
714
+ config: Config$1,
715
+ inject: [
716
+ optional(ServeLifecycle),
717
+ FileSystem.FileSystem,
718
+ Path.Path,
719
+ ChildProcessSpawner.ChildProcessSpawner,
720
+ SecureRandom.SecureRandom,
721
+ Digest.Digest
722
+ ],
723
+ apply: Effect.fnUntraced(function* (options) {
724
+ const lifecycle = yield* Effect.serviceOption(ServeLifecycle);
725
+ const resources$1 = yield* resources(lifecycle);
726
+ const path = yield* Path.Path;
727
+ const directory = yield* ConfigDirectory.pipe(Effect.map(Option.getOrElse(() => ".")));
728
+ const state = path.resolve(directory, options.state);
729
+ yield* acquire(state).pipe(Scope.provide(resources$1));
730
+ const services = yield* Layer.build(layer(options).pipe(Layer.provideMerge(Layer.merge(layerDirectory(state), layer$1(path.resolve(directory, options.root)))))).pipe(Scope.provide(resources$1));
731
+ const engine = Context.get(services, Supervisor);
732
+ const execution = Context.get(services, Channels);
733
+ yield* fork(engine.await);
734
+ yield* provide(Supervisor$1, { accept: (channel) => accept(engine, execution, channel) });
735
+ })
736
+ });
737
+ export { supervisorPlugin_default as n, Config$1 as t };