reeval 0.9.0 → 0.11.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 (336) hide show
  1. package/README.md +99 -64
  2. package/THIRD_PARTY_NOTICES.md +288 -112
  3. package/assets/package.json +1 -1
  4. package/assets/pnpm-lock.yaml +30 -30
  5. package/dist/adapter-Bwy3QxAK.js +279 -0
  6. package/dist/adapter-Bwy3QxAK.js.map +1 -0
  7. package/dist/{agent-6FefIhX7.js → agent-D483ru7D.js} +6 -6
  8. package/dist/{agent-6FefIhX7.js.map → agent-D483ru7D.js.map} +1 -1
  9. package/dist/{agent-WSmTaesf.js → agent-DpE80WPz.js} +46 -15
  10. package/dist/agent-DpE80WPz.js.map +1 -0
  11. package/dist/{analysis-DlGBDjTj.js → analysis-Bxub9LMT.js} +4 -4
  12. package/dist/{analysis-DlGBDjTj.js.map → analysis-Bxub9LMT.js.map} +1 -1
  13. package/dist/assemble-D5KGrwnJ.js +1 -0
  14. package/dist/{assemble-BCZzTyR7.js → assemble-D9GWr-HS.js} +69 -41
  15. package/dist/assemble-D9GWr-HS.js.map +1 -0
  16. package/dist/{client-Bbo9SPlK.js → assert-EUIoRdIt.js} +10 -113
  17. package/dist/assert-EUIoRdIt.js.map +1 -0
  18. package/dist/bridge/index.mjs +260 -60
  19. package/dist/{capture-Bp74Z6Fr.js → capture-BQlGHiMC.js} +146 -32
  20. package/dist/capture-BQlGHiMC.js.map +1 -0
  21. package/dist/capture-CYGLpWxR.js +1 -0
  22. package/dist/{cli-CVrMh_qz.js → cli-ClpPT8kn.js} +229 -537
  23. package/dist/cli-ClpPT8kn.js.map +1 -0
  24. package/dist/{cli-spec-CKEYa8V2.js → cli-spec-qmEnQ25_.js} +50 -22
  25. package/dist/cli-spec-qmEnQ25_.js.map +1 -0
  26. package/dist/cli.js +4 -2
  27. package/dist/cli.js.map +1 -1
  28. package/dist/client-fcwgwOAD.js +106 -0
  29. package/dist/client-fcwgwOAD.js.map +1 -0
  30. package/dist/{command-DUT5l13I.js → command-Bj39y-Wm.js} +329 -87
  31. package/dist/command-Bj39y-Wm.js.map +1 -0
  32. package/dist/{command-BFP0hKEb.js → command-BlM0y8jN.js} +14 -14
  33. package/dist/{command-BFP0hKEb.js.map → command-BlM0y8jN.js.map} +1 -1
  34. package/dist/command-C-cVjlny.js +1 -0
  35. package/dist/{command-CzIFp1JQ.js → command-DbAe1Rzb.js} +19 -19
  36. package/dist/command-DbAe1Rzb.js.map +1 -0
  37. package/dist/{command-C5xFPKHM.js → command-TgbzPizb.js} +378 -74
  38. package/dist/command-TgbzPizb.js.map +1 -0
  39. package/dist/commands-CthqwkAn.js +1 -0
  40. package/dist/{commands-CLmPBrTS.js → commands-YUwlyTbr.js} +14 -11
  41. package/dist/commands-YUwlyTbr.js.map +1 -0
  42. package/dist/config-DrVSEVN0.js +774 -0
  43. package/dist/config-DrVSEVN0.js.map +1 -0
  44. package/dist/{context-DbSMEVKs.js → context-C1mxXh80.js} +11 -3
  45. package/dist/context-C1mxXh80.js.map +1 -0
  46. package/dist/contrasts-5zsj32gk.js +101 -0
  47. package/dist/contrasts-5zsj32gk.js.map +1 -0
  48. package/dist/db-CKg5NtiW.js +2 -0
  49. package/dist/{db-CfQFwJtq.js → db-DfhipHEF.js} +467 -38
  50. package/dist/db-DfhipHEF.js.map +1 -0
  51. package/dist/debug-D7bEv_UV.js +1 -0
  52. package/dist/{dist-CTzThfu_.js → dist-CuY4ehEk.js} +95 -15
  53. package/dist/dist-CuY4ehEk.js.map +1 -0
  54. package/dist/{docker-CRQGQbIt.js → docker-D1HZDS6q.js} +22 -21
  55. package/dist/docker-D1HZDS6q.js.map +1 -0
  56. package/dist/docker-DNmMPOBb.js +1 -0
  57. package/dist/{docker-DV2GNgle.js → docker-DOvjji9I.js} +3 -3
  58. package/dist/docker-DOvjji9I.js.map +1 -0
  59. package/dist/{doctor-DlKycx5H.js → doctor-D2MbNO8L.js} +262 -84
  60. package/dist/doctor-D2MbNO8L.js.map +1 -0
  61. package/dist/{egress-BhzNh7Yi.js → egress-2-qzPvGi.js} +146 -15
  62. package/dist/egress-2-qzPvGi.js.map +1 -0
  63. package/dist/environment-Cca6a4wB.js +1132 -0
  64. package/dist/environment-Cca6a4wB.js.map +1 -0
  65. package/dist/{errors-yDAEwmZo.js → errors-B6BSMs03.js} +2 -2
  66. package/dist/errors-B6BSMs03.js.map +1 -0
  67. package/dist/{errors-C9w_ud7g.js → errors-r025B0Zb.js} +4 -4
  68. package/dist/errors-r025B0Zb.js.map +1 -0
  69. package/dist/evaluate-DKIl54Hb.js +2348 -0
  70. package/dist/evaluate-DKIl54Hb.js.map +1 -0
  71. package/dist/evaluate-DMyaGQEj.d.ts +92 -0
  72. package/dist/files-BAt0i00X.js +1 -0
  73. package/dist/{files-DJUFg-4e.js → files-BXHZFWmx.js} +5 -5
  74. package/dist/{files-DJUFg-4e.js.map → files-BXHZFWmx.js.map} +1 -1
  75. package/dist/files-Bk1mC3AN.js +43 -0
  76. package/dist/files-Bk1mC3AN.js.map +1 -0
  77. package/dist/{files-CSzVADHn.js → files-BpUYBwGu.js} +11 -10
  78. package/dist/{files-CSzVADHn.js.map → files-BpUYBwGu.js.map} +1 -1
  79. package/dist/files-Bw8lWEjg.js +1 -0
  80. package/dist/files-D6J0iSdx.js +1 -0
  81. package/dist/{git-DfG-YJ1u.js → git-Crl3b87o.js} +2 -2
  82. package/dist/{git-DfG-YJ1u.js.map → git-Crl3b87o.js.map} +1 -1
  83. package/dist/harness-CEuntrla.js +323 -0
  84. package/dist/harness-CEuntrla.js.map +1 -0
  85. package/dist/harness.d.ts +16 -30
  86. package/dist/harness.js +1 -2
  87. package/dist/{header-CALhmafp.js → header-DHQv_ZrF.js} +2 -2
  88. package/dist/{header-CALhmafp.js.map → header-DHQv_ZrF.js.map} +1 -1
  89. package/dist/{images-BMgdpMAX.js → images-Bi3aGxb9.js} +114 -45
  90. package/dist/images-Bi3aGxb9.js.map +1 -0
  91. package/dist/index.d.ts +9 -37
  92. package/dist/index.js +6 -2138
  93. package/dist/{init-BIdLF0F9.js → init-Cl3f3NBT.js} +26 -8
  94. package/dist/init-Cl3f3NBT.js.map +1 -0
  95. package/dist/init-fhOXED8F.js +1 -0
  96. package/dist/{invocations-CLaL8AuW.js → invocations-BYDPe3fV.js} +4 -4
  97. package/dist/{invocations-CLaL8AuW.js.map → invocations-BYDPe3fV.js.map} +1 -1
  98. package/dist/{judge-CeYPN8P_.js → judge-DW_GDOmB.js} +11 -19
  99. package/dist/{judge-CeYPN8P_.js.map → judge-DW_GDOmB.js.map} +1 -1
  100. package/dist/judge.d.ts +2 -2
  101. package/dist/judge.js +1 -1
  102. package/dist/{live-S0qODb6o.js → live-jlfszAbb.js} +9 -20
  103. package/dist/live-jlfszAbb.js.map +1 -0
  104. package/dist/matchers-Ddmc2z7H.js +118 -0
  105. package/dist/matchers-Ddmc2z7H.js.map +1 -0
  106. package/dist/model-CXhrziBe.js +1 -0
  107. package/dist/{model-B1BZoZ9b.js → model-D0IcOQao.js} +22 -20
  108. package/dist/model-D0IcOQao.js.map +1 -0
  109. package/dist/{model-DEQo3FkZ.js → model-DaVCY3rb.js} +2 -2
  110. package/dist/{model-DEQo3FkZ.js.map → model-DaVCY3rb.js.map} +1 -1
  111. package/dist/{model-BOnlAPzs.js → model-DaX4bNLZ.js} +123 -22
  112. package/dist/model-DaX4bNLZ.js.map +1 -0
  113. package/dist/model-_bxNrk2h.js +1 -0
  114. package/dist/{node-Co7EXge0.js → node-B3ydHo6t.js} +10 -47
  115. package/dist/node-B3ydHo6t.js.map +1 -0
  116. package/dist/object-CLf2-tNq.js +9 -0
  117. package/dist/object-CLf2-tNq.js.map +1 -0
  118. package/dist/{opencode-providers-ByD85Q0l.js → opencode-providers-J9colP0-.js} +96 -21
  119. package/dist/opencode-providers-J9colP0-.js.map +1 -0
  120. package/dist/options-C0d0AzeR.js +1118 -0
  121. package/dist/options-C0d0AzeR.js.map +1 -0
  122. package/dist/{pairs-DDsjgm5F.js → pairs-CnInRu-G.js} +76 -2
  123. package/dist/{pairs-DDsjgm5F.js.map → pairs-CnInRu-G.js.map} +1 -1
  124. package/dist/{patch-bDV8YFW0.js → patch-B1bnfhN-.js} +6 -6
  125. package/dist/{patch-bDV8YFW0.js.map → patch-B1bnfhN-.js.map} +1 -1
  126. package/dist/{plan-DUydFc_1.js → plan-DgQxp9yy.js} +34 -13
  127. package/dist/plan-DgQxp9yy.js.map +1 -0
  128. package/dist/{preflight-BkoSxf4C.js → preflight-BRzD30L5.js} +8 -7
  129. package/dist/preflight-BRzD30L5.js.map +1 -0
  130. package/dist/preflight-DlQvbySb.js +1 -0
  131. package/dist/{prepare-CUAWHebF.js → prepare-B_y-AFMv.js} +38 -30
  132. package/dist/prepare-B_y-AFMv.js.map +1 -0
  133. package/dist/prepare-DCKTLHN3.js +2 -0
  134. package/dist/{provenance-D7HK3vzt.js → provenance-DQ0AXn6c.js} +5 -5
  135. package/dist/{provenance-D7HK3vzt.js.map → provenance-DQ0AXn6c.js.map} +1 -1
  136. package/dist/provider-DehR4CMN.js +1 -0
  137. package/dist/providers-B9yTdIqF.js +1 -0
  138. package/dist/providers-DoTq1jHW.js +165 -0
  139. package/dist/providers-DoTq1jHW.js.map +1 -0
  140. package/dist/query-BO-ux7RB.js +139 -0
  141. package/dist/query-BO-ux7RB.js.map +1 -0
  142. package/dist/query-CRQfsw0e.js +1 -0
  143. package/dist/questions-C2dym2ce.js +524 -0
  144. package/dist/questions-C2dym2ce.js.map +1 -0
  145. package/dist/{record-BRP9vZrj.js → record-BKmMvZ6O.js} +9 -1
  146. package/dist/{record-BRP9vZrj.js.map → record-BKmMvZ6O.js.map} +1 -1
  147. package/dist/remote-CPPW86Q9.js +378 -0
  148. package/dist/remote-CPPW86Q9.js.map +1 -0
  149. package/dist/{results-Di7m8dQ3.js → results-BE2f-1XS.js} +6 -5
  150. package/dist/results-BE2f-1XS.js.map +1 -0
  151. package/dist/{resume-SUz1GskV.js → resume-Ca1c8vix.js} +10 -10
  152. package/dist/{resume-SUz1GskV.js.map → resume-Ca1c8vix.js.map} +1 -1
  153. package/dist/{root-CvdRlRZX.js → root-DICDHCtp.js} +4 -4
  154. package/dist/{root-CvdRlRZX.js.map → root-DICDHCtp.js.map} +1 -1
  155. package/dist/{runtime-DdsfnRz_.js → runtime-PX_oXiCS.js} +23 -71
  156. package/dist/runtime-PX_oXiCS.js.map +1 -0
  157. package/dist/sandbox-DLrsvu7U.js +70 -0
  158. package/dist/sandbox-DLrsvu7U.js.map +1 -0
  159. package/dist/sandbox.d.ts +19 -6
  160. package/dist/sandbox.js +1 -2
  161. package/dist/server-Dp8eOeK5.js +1 -0
  162. package/dist/{server-BNnXtmS8.js → server-TUY5xA_A.js} +11 -11
  163. package/dist/server-TUY5xA_A.js.map +1 -0
  164. package/dist/shared-CA61BuPJ.js +188 -0
  165. package/dist/shared-CA61BuPJ.js.map +1 -0
  166. package/dist/{source-Dof0NQBm.js → source-DJGS0a0u.js} +2 -2
  167. package/dist/{source-Dof0NQBm.js.map → source-DJGS0a0u.js.map} +1 -1
  168. package/dist/source-DdbLGR1M.js +1 -0
  169. package/dist/src-BxfCKA3_.js +2 -0
  170. package/dist/{src-C1E9HDWO.js → src-C7_1SqDP.js} +3 -3
  171. package/dist/{src-C1E9HDWO.js.map → src-C7_1SqDP.js.map} +1 -1
  172. package/dist/{src-DDNXsD9H.js → src-CF17Ug08.js} +5 -4
  173. package/dist/src-CF17Ug08.js.map +1 -0
  174. package/dist/{src-C_4Umgh2.js → src-CFp86GtV.js} +52 -51
  175. package/dist/src-CFp86GtV.js.map +1 -0
  176. package/dist/src-CLoOMVWI.js +3 -0
  177. package/dist/src-CcrQbpG8.js +2 -0
  178. package/dist/src-DCFtJRp0.js +2 -0
  179. package/dist/src-DIL0jST0.js +368 -0
  180. package/dist/src-DIL0jST0.js.map +1 -0
  181. package/dist/src-DSYYPEOj.js +2 -0
  182. package/dist/src-DYO3DdnQ.js +1 -0
  183. package/dist/src-DvCg0NBs.js +324 -0
  184. package/dist/src-DvCg0NBs.js.map +1 -0
  185. package/dist/{src-COgE7991.js → src-DvK0EIZx.js} +5 -5
  186. package/dist/{src-COgE7991.js.map → src-DvK0EIZx.js.map} +1 -1
  187. package/dist/{src-DVy58-zZ.js → src-FGXhkEkH.js} +5 -5
  188. package/dist/{src-DVy58-zZ.js.map → src-FGXhkEkH.js.map} +1 -1
  189. package/dist/src-WD-zgQYZ.js +2 -0
  190. package/dist/src-_oI9AePb.js +2 -0
  191. package/dist/{src-8rRXy4u9.js → src-ftu5wPSt.js} +1652 -182
  192. package/dist/src-ftu5wPSt.js.map +1 -0
  193. package/dist/src-qsKCqv7a.js +2 -0
  194. package/dist/{src-D95O-Smv.js → src-u8_ixn_F.js} +15 -11
  195. package/dist/src-u8_ixn_F.js.map +1 -0
  196. package/dist/state-CeR6oz0k.js +66 -0
  197. package/dist/state-CeR6oz0k.js.map +1 -0
  198. package/dist/{state-CiXyLqg0.js → state-DfpHox6b.js} +36 -24
  199. package/dist/state-DfpHox6b.js.map +1 -0
  200. package/dist/state-DpAxYyED.js +1 -0
  201. package/dist/studio-app/assets/index-CBkhNAv8.js +58 -0
  202. package/dist/studio-app/assets/index-CwQN3f_h.css +2 -0
  203. package/dist/studio-app/index.html +2 -2
  204. package/dist/suite-Cw_7G2RM.js +429 -0
  205. package/dist/suite-Cw_7G2RM.js.map +1 -0
  206. package/dist/suite-DamAEnNF.js +1 -0
  207. package/dist/summary-BUKfU-9l.js +611 -0
  208. package/dist/summary-BUKfU-9l.js.map +1 -0
  209. package/dist/{summary-2OAWF2N7.js → summary-Baa4rTHS.js} +7 -7
  210. package/dist/{summary-2OAWF2N7.js.map → summary-Baa4rTHS.js.map} +1 -1
  211. package/dist/testing.d.ts +3 -2
  212. package/dist/testing.js +3 -2
  213. package/dist/{tool-target-BU1JnSE9.js → tool-target-D2mcYlSQ.js} +14 -7
  214. package/dist/tool-target-D2mcYlSQ.js.map +1 -0
  215. package/dist/{tools-B10Uj7OI.js → tools-DLHgetpx.js} +6 -6
  216. package/dist/tools-DLHgetpx.js.map +1 -0
  217. package/dist/transcript-BNNANU8A.js +64 -0
  218. package/dist/transcript-BNNANU8A.js.map +1 -0
  219. package/dist/{types-D8RLfkFP.d.ts → types-BYdlwMwo.d.ts} +398 -46
  220. package/dist/{usage-DDF_6tkV.js → usage-CleNKkly.js} +4 -2
  221. package/dist/{usage-DDF_6tkV.js.map → usage-CleNKkly.js.map} +1 -1
  222. package/dist/view/index.d.ts +290 -8
  223. package/dist/view/index.js +7 -7
  224. package/dist/{views-Dqa5ojfZ.js → views-B8w2J-gD.js} +19 -24
  225. package/dist/views-B8w2J-gD.js.map +1 -0
  226. package/dist/views-DblnI3kA.js +2 -0
  227. package/dist/{worker-entry-BAikHl9F.js → worker-entry-DNnveLqx.js} +16 -229
  228. package/dist/worker-entry-DNnveLqx.js.map +1 -0
  229. package/dist/{workspace-C-TrNIUc.js → workspace-C4RA3srV.js} +7 -7
  230. package/dist/{workspace-C-TrNIUc.js.map → workspace-C4RA3srV.js.map} +1 -1
  231. package/dist/workspace-C_X0tdv6.js +1 -0
  232. package/package.json +12 -12
  233. package/dist/agent-WSmTaesf.js.map +0 -1
  234. package/dist/assemble-BCZzTyR7.js.map +0 -1
  235. package/dist/assemble-C5qq5yT2.js +0 -2
  236. package/dist/capture-Bp74Z6Fr.js.map +0 -1
  237. package/dist/capture-DS-cPyuE.js +0 -2
  238. package/dist/cli-CVrMh_qz.js.map +0 -1
  239. package/dist/cli-spec-CKEYa8V2.js.map +0 -1
  240. package/dist/client-Bbo9SPlK.js.map +0 -1
  241. package/dist/command-BrmXUC-W.js +0 -2
  242. package/dist/command-C5xFPKHM.js.map +0 -1
  243. package/dist/command-CzIFp1JQ.js.map +0 -1
  244. package/dist/command-DUT5l13I.js.map +0 -1
  245. package/dist/commands-CLmPBrTS.js.map +0 -1
  246. package/dist/commands-fI3G2Wnh.js +0 -2
  247. package/dist/config-CGvBeewH.js +0 -457
  248. package/dist/config-CGvBeewH.js.map +0 -1
  249. package/dist/context-DbSMEVKs.js.map +0 -1
  250. package/dist/db-CSSFtGcN.js +0 -3
  251. package/dist/db-CfQFwJtq.js.map +0 -1
  252. package/dist/debug-SEmW4w8f.js +0 -2
  253. package/dist/dist-CTzThfu_.js.map +0 -1
  254. package/dist/docker-CRQGQbIt.js.map +0 -1
  255. package/dist/docker-DV2GNgle.js.map +0 -1
  256. package/dist/docker-Df_YOxxB.js +0 -2
  257. package/dist/doctor-DlKycx5H.js.map +0 -1
  258. package/dist/duration-JsJrIWXq.js +0 -26
  259. package/dist/duration-JsJrIWXq.js.map +0 -1
  260. package/dist/egress-BhzNh7Yi.js.map +0 -1
  261. package/dist/env-BQqj93gu.js +0 -21
  262. package/dist/env-BQqj93gu.js.map +0 -1
  263. package/dist/environment-1jE-HhO-.js +0 -657
  264. package/dist/environment-1jE-HhO-.js.map +0 -1
  265. package/dist/errors-C9w_ud7g.js.map +0 -1
  266. package/dist/errors-yDAEwmZo.js.map +0 -1
  267. package/dist/fake-instructions-CUI33I_F.js +0 -32
  268. package/dist/fake-instructions-CUI33I_F.js.map +0 -1
  269. package/dist/family-D2b7WD10.js +0 -67
  270. package/dist/family-D2b7WD10.js.map +0 -1
  271. package/dist/files-AiEKuEZe.js +0 -2
  272. package/dist/files-BM78_nnF.js +0 -2
  273. package/dist/files-BMCvfB4X.js +0 -2
  274. package/dist/harness-CeCp2GSW.js +0 -171
  275. package/dist/harness-CeCp2GSW.js.map +0 -1
  276. package/dist/images-BMgdpMAX.js.map +0 -1
  277. package/dist/index.js.map +0 -1
  278. package/dist/init-B6vegaP_.js +0 -2
  279. package/dist/init-BIdLF0F9.js.map +0 -1
  280. package/dist/jiti-BcJHCtrb.js +0 -46
  281. package/dist/jiti-BcJHCtrb.js.map +0 -1
  282. package/dist/live-S0qODb6o.js.map +0 -1
  283. package/dist/model-B1BZoZ9b.js.map +0 -1
  284. package/dist/model-BOnlAPzs.js.map +0 -1
  285. package/dist/model-DWeg5J7z.js +0 -2
  286. package/dist/model-FXko2kl7.js +0 -2
  287. package/dist/node-Co7EXge0.js.map +0 -1
  288. package/dist/opencode-providers-ByD85Q0l.js.map +0 -1
  289. package/dist/options-CKqyPGxX.js +0 -739
  290. package/dist/options-CKqyPGxX.js.map +0 -1
  291. package/dist/plan-DUydFc_1.js.map +0 -1
  292. package/dist/preflight-BkoSxf4C.js.map +0 -1
  293. package/dist/preflight-D5LW7Oqi.js +0 -2
  294. package/dist/prepare-CUAWHebF.js.map +0 -1
  295. package/dist/prepare-oji2oO8W.js +0 -3
  296. package/dist/process-CSVO_jsc.js +0 -119
  297. package/dist/process-CSVO_jsc.js.map +0 -1
  298. package/dist/provider-BDbNOQhQ.js +0 -2
  299. package/dist/providers-B1DzMvmH.js +0 -107
  300. package/dist/providers-B1DzMvmH.js.map +0 -1
  301. package/dist/providers-CpEfNU1F.js +0 -2
  302. package/dist/query-BjBMLa-C.js +0 -91
  303. package/dist/query-BjBMLa-C.js.map +0 -1
  304. package/dist/query-oPO_XrTy.js +0 -2
  305. package/dist/questions-B8by4Bbt.js +0 -234
  306. package/dist/questions-B8by4Bbt.js.map +0 -1
  307. package/dist/results-Di7m8dQ3.js.map +0 -1
  308. package/dist/runtime-DdsfnRz_.js.map +0 -1
  309. package/dist/sandbox-D5v-of6d.js +0 -139
  310. package/dist/sandbox-D5v-of6d.js.map +0 -1
  311. package/dist/server-BNnXtmS8.js.map +0 -1
  312. package/dist/server-BNwoKzlm.js +0 -2
  313. package/dist/source-Bk_0ZaEY.js +0 -2
  314. package/dist/src-8rRXy4u9.js.map +0 -1
  315. package/dist/src-BGWuWp6I.js +0 -3
  316. package/dist/src-BRt0O02i.js +0 -3
  317. package/dist/src-Bx2x1ekD.js +0 -3
  318. package/dist/src-C_4Umgh2.js.map +0 -1
  319. package/dist/src-D95O-Smv.js.map +0 -1
  320. package/dist/src-DDNXsD9H.js.map +0 -1
  321. package/dist/src-DLa-ESW0.js +0 -4
  322. package/dist/src-cN0aB-WR.js +0 -3
  323. package/dist/src-cdIVjC5b.js +0 -2
  324. package/dist/src-sIsDHWYq.js +0 -3
  325. package/dist/state-Bo5zg4da.js +0 -2
  326. package/dist/state-CiXyLqg0.js.map +0 -1
  327. package/dist/studio-app/assets/index-B9MCTfuu.css +0 -2
  328. package/dist/studio-app/assets/index-CROH2NB3.js +0 -58
  329. package/dist/summary-BTksrIxn.js +0 -254
  330. package/dist/summary-BTksrIxn.js.map +0 -1
  331. package/dist/tool-target-BU1JnSE9.js.map +0 -1
  332. package/dist/tools-B10Uj7OI.js.map +0 -1
  333. package/dist/views-Cs2Oqayd.js +0 -3
  334. package/dist/views-Dqa5ojfZ.js.map +0 -1
  335. package/dist/worker-entry-BAikHl9F.js.map +0 -1
  336. package/dist/workspace-Do_SiWBs.js +0 -2
@@ -1,12 +1,12 @@
1
- import { u as ownFileURL } from "./root-CvdRlRZX.js";
2
- import { n as shellQuote, t as run } from "./process-CSVO_jsc.js";
3
- import { existsSync, lstatSync, readFileSync, readdirSync, readlinkSync } from "node:fs";
4
- import { basename, dirname, join, posix, relative } from "node:path";
1
+ import { u as ownFileURL } from "./root-DICDHCtp.js";
2
+ import { existsSync, lstatSync, readFileSync, readdirSync, readlinkSync, renameSync, writeFileSync } from "node:fs";
3
+ import { tmpdir } from "node:os";
4
+ import { basename, dirname, join, posix, relative, win32 } from "node:path";
5
5
  import net, { BlockList, isIP } from "node:net";
6
- import { fileURLToPath } from "node:url";
7
6
  import { createHash, generateKeyPairSync, randomBytes, randomInt, sign } from "node:crypto";
7
+ import { fileURLToPath } from "node:url";
8
+ import { execFileSync, spawn } from "node:child_process";
8
9
  import { createHarnessSandboxTemplate } from "@ai-sdk/harness/agent";
9
- import { spawn } from "node:child_process";
10
10
  import { isUtf8 } from "node:buffer";
11
11
  import { Duplex, Readable, Transform } from "node:stream";
12
12
  import http from "node:http";
@@ -14,6 +14,1073 @@ import http2 from "node:http2";
14
14
  import https from "node:https";
15
15
  import tls from "node:tls";
16
16
  import { lookup } from "node:dns/promises";
17
+ //#region ../sandbox-docker/src/seccomp-profile.ts
18
+ const DOCKER_SECCOMP_PROFILE = {
19
+ defaultAction: "SCMP_ACT_ERRNO",
20
+ defaultErrnoRet: 1,
21
+ archMap: [
22
+ {
23
+ architecture: "SCMP_ARCH_X86_64",
24
+ subArchitectures: ["SCMP_ARCH_X86", "SCMP_ARCH_X32"]
25
+ },
26
+ {
27
+ architecture: "SCMP_ARCH_AARCH64",
28
+ subArchitectures: ["SCMP_ARCH_ARM"]
29
+ },
30
+ {
31
+ architecture: "SCMP_ARCH_MIPS64",
32
+ subArchitectures: ["SCMP_ARCH_MIPS", "SCMP_ARCH_MIPS64N32"]
33
+ },
34
+ {
35
+ architecture: "SCMP_ARCH_MIPS64N32",
36
+ subArchitectures: ["SCMP_ARCH_MIPS", "SCMP_ARCH_MIPS64"]
37
+ },
38
+ {
39
+ architecture: "SCMP_ARCH_MIPSEL64",
40
+ subArchitectures: ["SCMP_ARCH_MIPSEL", "SCMP_ARCH_MIPSEL64N32"]
41
+ },
42
+ {
43
+ architecture: "SCMP_ARCH_MIPSEL64N32",
44
+ subArchitectures: ["SCMP_ARCH_MIPSEL", "SCMP_ARCH_MIPSEL64"]
45
+ },
46
+ {
47
+ architecture: "SCMP_ARCH_S390X",
48
+ subArchitectures: ["SCMP_ARCH_S390"]
49
+ },
50
+ {
51
+ architecture: "SCMP_ARCH_RISCV64",
52
+ subArchitectures: null
53
+ },
54
+ {
55
+ architecture: "SCMP_ARCH_LOONGARCH64",
56
+ subArchitectures: null
57
+ }
58
+ ],
59
+ syscalls: [
60
+ {
61
+ names: [
62
+ "accept",
63
+ "accept4",
64
+ "access",
65
+ "adjtimex",
66
+ "alarm",
67
+ "bind",
68
+ "brk",
69
+ "cachestat",
70
+ "capget",
71
+ "capset",
72
+ "chdir",
73
+ "chmod",
74
+ "chown",
75
+ "chown32",
76
+ "clock_adjtime",
77
+ "clock_adjtime64",
78
+ "clock_getres",
79
+ "clock_getres_time64",
80
+ "clock_gettime",
81
+ "clock_gettime64",
82
+ "clock_nanosleep",
83
+ "clock_nanosleep_time64",
84
+ "close",
85
+ "close_range",
86
+ "connect",
87
+ "copy_file_range",
88
+ "creat",
89
+ "dup",
90
+ "dup2",
91
+ "dup3",
92
+ "epoll_create",
93
+ "epoll_create1",
94
+ "epoll_ctl",
95
+ "epoll_ctl_old",
96
+ "epoll_pwait",
97
+ "epoll_pwait2",
98
+ "epoll_wait",
99
+ "epoll_wait_old",
100
+ "eventfd",
101
+ "eventfd2",
102
+ "execve",
103
+ "execveat",
104
+ "exit",
105
+ "exit_group",
106
+ "faccessat",
107
+ "faccessat2",
108
+ "fadvise64",
109
+ "fadvise64_64",
110
+ "fallocate",
111
+ "fanotify_mark",
112
+ "fchdir",
113
+ "fchmod",
114
+ "fchmodat",
115
+ "fchmodat2",
116
+ "fchown",
117
+ "fchown32",
118
+ "fchownat",
119
+ "fcntl",
120
+ "fcntl64",
121
+ "fdatasync",
122
+ "fgetxattr",
123
+ "flistxattr",
124
+ "flock",
125
+ "fork",
126
+ "fremovexattr",
127
+ "fsetxattr",
128
+ "fstat",
129
+ "fstat64",
130
+ "fstatat64",
131
+ "fstatfs",
132
+ "fstatfs64",
133
+ "fsync",
134
+ "ftruncate",
135
+ "ftruncate64",
136
+ "futex",
137
+ "futex_requeue",
138
+ "futex_time64",
139
+ "futex_wait",
140
+ "futex_waitv",
141
+ "futex_wake",
142
+ "futimesat",
143
+ "getcpu",
144
+ "getcwd",
145
+ "getdents",
146
+ "getdents64",
147
+ "getegid",
148
+ "getegid32",
149
+ "geteuid",
150
+ "geteuid32",
151
+ "getgid",
152
+ "getgid32",
153
+ "getgroups",
154
+ "getgroups32",
155
+ "getitimer",
156
+ "getpeername",
157
+ "getpgid",
158
+ "getpgrp",
159
+ "getpid",
160
+ "getppid",
161
+ "getpriority",
162
+ "getrandom",
163
+ "getresgid",
164
+ "getresgid32",
165
+ "getresuid",
166
+ "getresuid32",
167
+ "getrlimit",
168
+ "get_robust_list",
169
+ "getrusage",
170
+ "getsid",
171
+ "getsockname",
172
+ "getsockopt",
173
+ "get_thread_area",
174
+ "gettid",
175
+ "gettimeofday",
176
+ "getuid",
177
+ "getuid32",
178
+ "getxattr",
179
+ "getxattrat",
180
+ "inotify_add_watch",
181
+ "inotify_init",
182
+ "inotify_init1",
183
+ "inotify_rm_watch",
184
+ "io_cancel",
185
+ "ioctl",
186
+ "io_destroy",
187
+ "io_getevents",
188
+ "io_pgetevents",
189
+ "io_pgetevents_time64",
190
+ "ioprio_get",
191
+ "ioprio_set",
192
+ "io_setup",
193
+ "io_submit",
194
+ "ipc",
195
+ "kill",
196
+ "landlock_add_rule",
197
+ "landlock_create_ruleset",
198
+ "landlock_restrict_self",
199
+ "lchown",
200
+ "lchown32",
201
+ "lgetxattr",
202
+ "link",
203
+ "linkat",
204
+ "listen",
205
+ "listmount",
206
+ "listxattr",
207
+ "listxattrat",
208
+ "llistxattr",
209
+ "_llseek",
210
+ "lremovexattr",
211
+ "lseek",
212
+ "lsetxattr",
213
+ "lstat",
214
+ "lstat64",
215
+ "madvise",
216
+ "map_shadow_stack",
217
+ "membarrier",
218
+ "memfd_create",
219
+ "memfd_secret",
220
+ "mincore",
221
+ "mkdir",
222
+ "mkdirat",
223
+ "mknod",
224
+ "mknodat",
225
+ "mlock",
226
+ "mlock2",
227
+ "mlockall",
228
+ "mmap",
229
+ "mmap2",
230
+ "mprotect",
231
+ "mq_getsetattr",
232
+ "mq_notify",
233
+ "mq_open",
234
+ "mq_timedreceive",
235
+ "mq_timedreceive_time64",
236
+ "mq_timedsend",
237
+ "mq_timedsend_time64",
238
+ "mq_unlink",
239
+ "mremap",
240
+ "mseal",
241
+ "msgctl",
242
+ "msgget",
243
+ "msgrcv",
244
+ "msgsnd",
245
+ "msync",
246
+ "munlock",
247
+ "munlockall",
248
+ "munmap",
249
+ "name_to_handle_at",
250
+ "nanosleep",
251
+ "newfstatat",
252
+ "_newselect",
253
+ "open",
254
+ "openat",
255
+ "openat2",
256
+ "pause",
257
+ "pidfd_open",
258
+ "pidfd_send_signal",
259
+ "pipe",
260
+ "pipe2",
261
+ "pkey_alloc",
262
+ "pkey_free",
263
+ "pkey_mprotect",
264
+ "poll",
265
+ "ppoll",
266
+ "ppoll_time64",
267
+ "prctl",
268
+ "pread64",
269
+ "preadv",
270
+ "preadv2",
271
+ "prlimit64",
272
+ "process_mrelease",
273
+ "pselect6",
274
+ "pselect6_time64",
275
+ "pwrite64",
276
+ "pwritev",
277
+ "pwritev2",
278
+ "read",
279
+ "readahead",
280
+ "readlink",
281
+ "readlinkat",
282
+ "readv",
283
+ "recv",
284
+ "recvfrom",
285
+ "recvmmsg",
286
+ "recvmmsg_time64",
287
+ "recvmsg",
288
+ "remap_file_pages",
289
+ "removexattr",
290
+ "removexattrat",
291
+ "rename",
292
+ "renameat",
293
+ "renameat2",
294
+ "restart_syscall",
295
+ "riscv_hwprobe",
296
+ "rmdir",
297
+ "rseq",
298
+ "rt_sigaction",
299
+ "rt_sigpending",
300
+ "rt_sigprocmask",
301
+ "rt_sigqueueinfo",
302
+ "rt_sigreturn",
303
+ "rt_sigsuspend",
304
+ "rt_sigtimedwait",
305
+ "rt_sigtimedwait_time64",
306
+ "rt_tgsigqueueinfo",
307
+ "sched_getaffinity",
308
+ "sched_getattr",
309
+ "sched_getparam",
310
+ "sched_get_priority_max",
311
+ "sched_get_priority_min",
312
+ "sched_getscheduler",
313
+ "sched_rr_get_interval",
314
+ "sched_rr_get_interval_time64",
315
+ "sched_setaffinity",
316
+ "sched_setattr",
317
+ "sched_setparam",
318
+ "sched_setscheduler",
319
+ "sched_yield",
320
+ "seccomp",
321
+ "select",
322
+ "semctl",
323
+ "semget",
324
+ "semop",
325
+ "semtimedop",
326
+ "semtimedop_time64",
327
+ "send",
328
+ "sendfile",
329
+ "sendfile64",
330
+ "sendmmsg",
331
+ "sendmsg",
332
+ "sendto",
333
+ "setfsgid",
334
+ "setfsgid32",
335
+ "setfsuid",
336
+ "setfsuid32",
337
+ "setgid",
338
+ "setgid32",
339
+ "setgroups",
340
+ "setgroups32",
341
+ "setitimer",
342
+ "setpgid",
343
+ "setpriority",
344
+ "setregid",
345
+ "setregid32",
346
+ "setresgid",
347
+ "setresgid32",
348
+ "setresuid",
349
+ "setresuid32",
350
+ "setreuid",
351
+ "setreuid32",
352
+ "setrlimit",
353
+ "set_robust_list",
354
+ "setsid",
355
+ "setsockopt",
356
+ "set_thread_area",
357
+ "set_tid_address",
358
+ "setuid",
359
+ "setuid32",
360
+ "setxattr",
361
+ "setxattrat",
362
+ "shmat",
363
+ "shmctl",
364
+ "shmdt",
365
+ "shmget",
366
+ "shutdown",
367
+ "sigaltstack",
368
+ "signalfd",
369
+ "signalfd4",
370
+ "sigprocmask",
371
+ "sigreturn",
372
+ "socketcall",
373
+ "socketpair",
374
+ "splice",
375
+ "stat",
376
+ "stat64",
377
+ "statfs",
378
+ "statfs64",
379
+ "statmount",
380
+ "statx",
381
+ "symlink",
382
+ "symlinkat",
383
+ "sync",
384
+ "sync_file_range",
385
+ "syncfs",
386
+ "sysinfo",
387
+ "tee",
388
+ "tgkill",
389
+ "time",
390
+ "timer_create",
391
+ "timer_delete",
392
+ "timer_getoverrun",
393
+ "timer_gettime",
394
+ "timer_gettime64",
395
+ "timer_settime",
396
+ "timer_settime64",
397
+ "timerfd_create",
398
+ "timerfd_gettime",
399
+ "timerfd_gettime64",
400
+ "timerfd_settime",
401
+ "timerfd_settime64",
402
+ "times",
403
+ "tkill",
404
+ "truncate",
405
+ "truncate64",
406
+ "ugetrlimit",
407
+ "umask",
408
+ "uname",
409
+ "unlink",
410
+ "unlinkat",
411
+ "uretprobe",
412
+ "utime",
413
+ "utimensat",
414
+ "utimensat_time64",
415
+ "utimes",
416
+ "vfork",
417
+ "vmsplice",
418
+ "wait4",
419
+ "waitid",
420
+ "waitpid",
421
+ "write",
422
+ "writev"
423
+ ],
424
+ action: "SCMP_ACT_ALLOW"
425
+ },
426
+ {
427
+ names: [
428
+ "process_vm_readv",
429
+ "process_vm_writev",
430
+ "ptrace"
431
+ ],
432
+ action: "SCMP_ACT_ALLOW",
433
+ includes: { minKernel: "4.8" }
434
+ },
435
+ {
436
+ names: ["socket"],
437
+ action: "SCMP_ACT_ALLOW",
438
+ args: [{
439
+ index: 0,
440
+ value: 3,
441
+ op: "SCMP_CMP_LT"
442
+ }]
443
+ },
444
+ {
445
+ names: ["socket"],
446
+ action: "SCMP_ACT_ALLOW",
447
+ args: [{
448
+ index: 0,
449
+ value: 7,
450
+ op: "SCMP_CMP_EQ"
451
+ }]
452
+ },
453
+ {
454
+ names: ["socket"],
455
+ action: "SCMP_ACT_ALLOW",
456
+ args: [{
457
+ index: 0,
458
+ value: 8,
459
+ op: "SCMP_CMP_EQ"
460
+ }]
461
+ },
462
+ {
463
+ names: ["socket"],
464
+ action: "SCMP_ACT_ALLOW",
465
+ args: [{
466
+ index: 0,
467
+ value: 9,
468
+ op: "SCMP_CMP_EQ"
469
+ }]
470
+ },
471
+ {
472
+ names: ["socket"],
473
+ action: "SCMP_ACT_ALLOW",
474
+ args: [{
475
+ index: 0,
476
+ value: 10,
477
+ op: "SCMP_CMP_EQ"
478
+ }]
479
+ },
480
+ {
481
+ names: ["socket"],
482
+ action: "SCMP_ACT_ALLOW",
483
+ args: [{
484
+ index: 0,
485
+ value: 13,
486
+ op: "SCMP_CMP_EQ"
487
+ }]
488
+ },
489
+ {
490
+ names: ["socket"],
491
+ action: "SCMP_ACT_ALLOW",
492
+ args: [{
493
+ index: 0,
494
+ value: 14,
495
+ op: "SCMP_CMP_EQ"
496
+ }]
497
+ },
498
+ {
499
+ names: ["socket"],
500
+ action: "SCMP_ACT_ALLOW",
501
+ args: [{
502
+ index: 0,
503
+ value: 15,
504
+ op: "SCMP_CMP_EQ"
505
+ }]
506
+ },
507
+ {
508
+ names: ["socket"],
509
+ action: "SCMP_ACT_ALLOW",
510
+ args: [{
511
+ index: 0,
512
+ value: 16,
513
+ op: "SCMP_CMP_EQ"
514
+ }]
515
+ },
516
+ {
517
+ names: ["socket"],
518
+ action: "SCMP_ACT_ALLOW",
519
+ args: [{
520
+ index: 0,
521
+ value: 17,
522
+ op: "SCMP_CMP_EQ"
523
+ }]
524
+ },
525
+ {
526
+ names: ["socket"],
527
+ action: "SCMP_ACT_ALLOW",
528
+ args: [{
529
+ index: 0,
530
+ value: 18,
531
+ op: "SCMP_CMP_EQ"
532
+ }]
533
+ },
534
+ {
535
+ names: ["socket"],
536
+ action: "SCMP_ACT_ALLOW",
537
+ args: [{
538
+ index: 0,
539
+ value: 21,
540
+ op: "SCMP_CMP_EQ"
541
+ }]
542
+ },
543
+ {
544
+ names: ["socket"],
545
+ action: "SCMP_ACT_ALLOW",
546
+ args: [{
547
+ index: 0,
548
+ value: 22,
549
+ op: "SCMP_CMP_EQ"
550
+ }]
551
+ },
552
+ {
553
+ names: ["socket"],
554
+ action: "SCMP_ACT_ALLOW",
555
+ args: [{
556
+ index: 0,
557
+ value: 24,
558
+ op: "SCMP_CMP_EQ"
559
+ }]
560
+ },
561
+ {
562
+ names: ["socket"],
563
+ action: "SCMP_ACT_ALLOW",
564
+ args: [{
565
+ index: 0,
566
+ value: 26,
567
+ op: "SCMP_CMP_EQ"
568
+ }]
569
+ },
570
+ {
571
+ names: ["socket"],
572
+ action: "SCMP_ACT_ALLOW",
573
+ args: [{
574
+ index: 0,
575
+ value: 27,
576
+ op: "SCMP_CMP_EQ"
577
+ }]
578
+ },
579
+ {
580
+ names: ["socket"],
581
+ action: "SCMP_ACT_ALLOW",
582
+ args: [{
583
+ index: 0,
584
+ value: 28,
585
+ op: "SCMP_CMP_EQ"
586
+ }]
587
+ },
588
+ {
589
+ names: ["socket"],
590
+ action: "SCMP_ACT_ALLOW",
591
+ args: [{
592
+ index: 0,
593
+ value: 29,
594
+ op: "SCMP_CMP_EQ"
595
+ }]
596
+ },
597
+ {
598
+ names: ["socket"],
599
+ action: "SCMP_ACT_ALLOW",
600
+ args: [{
601
+ index: 0,
602
+ value: 30,
603
+ op: "SCMP_CMP_EQ"
604
+ }]
605
+ },
606
+ {
607
+ names: ["socket"],
608
+ action: "SCMP_ACT_ALLOW",
609
+ args: [{
610
+ index: 0,
611
+ value: 31,
612
+ op: "SCMP_CMP_EQ"
613
+ }]
614
+ },
615
+ {
616
+ names: ["socket"],
617
+ action: "SCMP_ACT_ALLOW",
618
+ args: [{
619
+ index: 0,
620
+ value: 32,
621
+ op: "SCMP_CMP_EQ"
622
+ }]
623
+ },
624
+ {
625
+ names: ["socket"],
626
+ action: "SCMP_ACT_ALLOW",
627
+ args: [{
628
+ index: 0,
629
+ value: 33,
630
+ op: "SCMP_CMP_EQ"
631
+ }]
632
+ },
633
+ {
634
+ names: ["socket"],
635
+ action: "SCMP_ACT_ALLOW",
636
+ args: [{
637
+ index: 0,
638
+ value: 35,
639
+ op: "SCMP_CMP_EQ"
640
+ }]
641
+ },
642
+ {
643
+ names: ["socket"],
644
+ action: "SCMP_ACT_ALLOW",
645
+ args: [{
646
+ index: 0,
647
+ value: 36,
648
+ op: "SCMP_CMP_EQ"
649
+ }]
650
+ },
651
+ {
652
+ names: ["socket"],
653
+ action: "SCMP_ACT_ALLOW",
654
+ args: [{
655
+ index: 0,
656
+ value: 39,
657
+ op: "SCMP_CMP_EQ"
658
+ }]
659
+ },
660
+ {
661
+ names: ["socket"],
662
+ action: "SCMP_ACT_ALLOW",
663
+ args: [{
664
+ index: 0,
665
+ value: 41,
666
+ op: "SCMP_CMP_EQ"
667
+ }]
668
+ },
669
+ {
670
+ names: ["socket"],
671
+ action: "SCMP_ACT_ALLOW",
672
+ args: [{
673
+ index: 0,
674
+ value: 42,
675
+ op: "SCMP_CMP_EQ"
676
+ }]
677
+ },
678
+ {
679
+ names: ["socket"],
680
+ action: "SCMP_ACT_ALLOW",
681
+ args: [{
682
+ index: 0,
683
+ value: 43,
684
+ op: "SCMP_CMP_EQ"
685
+ }]
686
+ },
687
+ {
688
+ names: ["socket"],
689
+ action: "SCMP_ACT_ALLOW",
690
+ args: [{
691
+ index: 0,
692
+ value: 44,
693
+ op: "SCMP_CMP_EQ"
694
+ }]
695
+ },
696
+ {
697
+ names: ["socket"],
698
+ action: "SCMP_ACT_ALLOW",
699
+ args: [{
700
+ index: 0,
701
+ value: 45,
702
+ op: "SCMP_CMP_EQ"
703
+ }]
704
+ },
705
+ {
706
+ names: ["personality"],
707
+ action: "SCMP_ACT_ALLOW",
708
+ args: [{
709
+ index: 0,
710
+ value: 0,
711
+ op: "SCMP_CMP_EQ"
712
+ }]
713
+ },
714
+ {
715
+ names: ["personality"],
716
+ action: "SCMP_ACT_ALLOW",
717
+ args: [{
718
+ index: 0,
719
+ value: 8,
720
+ op: "SCMP_CMP_EQ"
721
+ }]
722
+ },
723
+ {
724
+ names: ["personality"],
725
+ action: "SCMP_ACT_ALLOW",
726
+ args: [{
727
+ index: 0,
728
+ value: 131072,
729
+ op: "SCMP_CMP_EQ"
730
+ }]
731
+ },
732
+ {
733
+ names: ["personality"],
734
+ action: "SCMP_ACT_ALLOW",
735
+ args: [{
736
+ index: 0,
737
+ value: 131080,
738
+ op: "SCMP_CMP_EQ"
739
+ }]
740
+ },
741
+ {
742
+ names: ["personality"],
743
+ action: "SCMP_ACT_ALLOW",
744
+ args: [{
745
+ index: 0,
746
+ value: 4294967295,
747
+ op: "SCMP_CMP_EQ"
748
+ }]
749
+ },
750
+ {
751
+ names: ["sync_file_range2", "swapcontext"],
752
+ action: "SCMP_ACT_ALLOW",
753
+ includes: { arches: ["ppc64le"] }
754
+ },
755
+ {
756
+ names: [
757
+ "arm_fadvise64_64",
758
+ "arm_sync_file_range",
759
+ "sync_file_range2",
760
+ "breakpoint",
761
+ "cacheflush",
762
+ "set_tls"
763
+ ],
764
+ action: "SCMP_ACT_ALLOW",
765
+ includes: { arches: ["arm", "arm64"] }
766
+ },
767
+ {
768
+ names: ["arch_prctl"],
769
+ action: "SCMP_ACT_ALLOW",
770
+ includes: { arches: ["amd64", "x32"] }
771
+ },
772
+ {
773
+ names: ["modify_ldt"],
774
+ action: "SCMP_ACT_ALLOW",
775
+ includes: { arches: [
776
+ "amd64",
777
+ "x32",
778
+ "x86"
779
+ ] }
780
+ },
781
+ {
782
+ names: [
783
+ "s390_pci_mmio_read",
784
+ "s390_pci_mmio_write",
785
+ "s390_runtime_instr"
786
+ ],
787
+ action: "SCMP_ACT_ALLOW",
788
+ includes: { arches: ["s390", "s390x"] }
789
+ },
790
+ {
791
+ names: ["riscv_flush_icache"],
792
+ action: "SCMP_ACT_ALLOW",
793
+ includes: { arches: ["riscv64"] }
794
+ },
795
+ {
796
+ names: ["open_by_handle_at"],
797
+ action: "SCMP_ACT_ALLOW",
798
+ includes: { caps: ["CAP_DAC_READ_SEARCH"] }
799
+ },
800
+ {
801
+ names: [
802
+ "bpf",
803
+ "clone",
804
+ "clone3",
805
+ "fanotify_init",
806
+ "fsconfig",
807
+ "fsmount",
808
+ "fsopen",
809
+ "fspick",
810
+ "lookup_dcookie",
811
+ "lsm_get_self_attr",
812
+ "lsm_list_modules",
813
+ "lsm_set_self_attr",
814
+ "mount",
815
+ "mount_setattr",
816
+ "move_mount",
817
+ "open_tree",
818
+ "perf_event_open",
819
+ "quotactl",
820
+ "quotactl_fd",
821
+ "setdomainname",
822
+ "sethostname",
823
+ "setns",
824
+ "syslog",
825
+ "umount",
826
+ "umount2",
827
+ "unshare"
828
+ ],
829
+ action: "SCMP_ACT_ALLOW",
830
+ includes: { caps: ["CAP_SYS_ADMIN"] }
831
+ },
832
+ {
833
+ names: ["clone"],
834
+ action: "SCMP_ACT_ALLOW",
835
+ args: [{
836
+ index: 0,
837
+ value: 2114060288,
838
+ op: "SCMP_CMP_MASKED_EQ"
839
+ }],
840
+ excludes: {
841
+ caps: ["CAP_SYS_ADMIN"],
842
+ arches: ["s390", "s390x"]
843
+ }
844
+ },
845
+ {
846
+ names: ["clone"],
847
+ action: "SCMP_ACT_ALLOW",
848
+ args: [{
849
+ index: 1,
850
+ value: 2114060288,
851
+ op: "SCMP_CMP_MASKED_EQ"
852
+ }],
853
+ comment: "s390 parameter ordering for clone is different",
854
+ includes: { arches: ["s390", "s390x"] },
855
+ excludes: { caps: ["CAP_SYS_ADMIN"] }
856
+ },
857
+ {
858
+ names: ["clone3"],
859
+ action: "SCMP_ACT_ERRNO",
860
+ errnoRet: 38,
861
+ excludes: { caps: ["CAP_SYS_ADMIN"] }
862
+ },
863
+ {
864
+ names: ["reboot"],
865
+ action: "SCMP_ACT_ALLOW",
866
+ includes: { caps: ["CAP_SYS_BOOT"] }
867
+ },
868
+ {
869
+ names: ["chroot"],
870
+ action: "SCMP_ACT_ALLOW",
871
+ includes: { caps: ["CAP_SYS_CHROOT"] }
872
+ },
873
+ {
874
+ names: [
875
+ "delete_module",
876
+ "init_module",
877
+ "finit_module"
878
+ ],
879
+ action: "SCMP_ACT_ALLOW",
880
+ includes: { caps: ["CAP_SYS_MODULE"] }
881
+ },
882
+ {
883
+ names: ["acct"],
884
+ action: "SCMP_ACT_ALLOW",
885
+ includes: { caps: ["CAP_SYS_PACCT"] }
886
+ },
887
+ {
888
+ names: [
889
+ "kcmp",
890
+ "pidfd_getfd",
891
+ "process_madvise",
892
+ "process_vm_readv",
893
+ "process_vm_writev",
894
+ "ptrace"
895
+ ],
896
+ action: "SCMP_ACT_ALLOW",
897
+ includes: { caps: ["CAP_SYS_PTRACE"] }
898
+ },
899
+ {
900
+ names: ["iopl", "ioperm"],
901
+ action: "SCMP_ACT_ALLOW",
902
+ includes: { caps: ["CAP_SYS_RAWIO"] }
903
+ },
904
+ {
905
+ names: [
906
+ "settimeofday",
907
+ "stime",
908
+ "clock_settime",
909
+ "clock_settime64"
910
+ ],
911
+ action: "SCMP_ACT_ALLOW",
912
+ includes: { caps: ["CAP_SYS_TIME"] }
913
+ },
914
+ {
915
+ names: ["vhangup"],
916
+ action: "SCMP_ACT_ALLOW",
917
+ includes: { caps: ["CAP_SYS_TTY_CONFIG"] }
918
+ },
919
+ {
920
+ names: [
921
+ "get_mempolicy",
922
+ "mbind",
923
+ "set_mempolicy",
924
+ "set_mempolicy_home_node"
925
+ ],
926
+ action: "SCMP_ACT_ALLOW",
927
+ includes: { caps: ["CAP_SYS_NICE"] }
928
+ },
929
+ {
930
+ names: ["syslog"],
931
+ action: "SCMP_ACT_ALLOW",
932
+ includes: { caps: ["CAP_SYSLOG"] }
933
+ },
934
+ {
935
+ names: ["bpf"],
936
+ action: "SCMP_ACT_ALLOW",
937
+ includes: { caps: ["CAP_BPF"] }
938
+ },
939
+ {
940
+ names: ["perf_event_open"],
941
+ action: "SCMP_ACT_ALLOW",
942
+ includes: { caps: ["CAP_PERFMON"] }
943
+ }
944
+ ]
945
+ };
946
+ //#endregion
947
+ //#region ../sandbox-docker/src/engine.ts
948
+ let seccompFile;
949
+ /**
950
+ * Docker's default seccomp profile as a file Podman can read, written once per content under the
951
+ * temp directory (a compiled reeval has no real file of its own to point at).
952
+ */
953
+ function dockerSeccompFile() {
954
+ if (seccompFile && existsSync(seccompFile)) return seccompFile;
955
+ const json = JSON.stringify(DOCKER_SECCOMP_PROFILE);
956
+ const hash = createHash("sha256").update(json).digest("hex").slice(0, 16);
957
+ const path = join(tmpdir(), `reeval-seccomp-${hash}.json`);
958
+ if (!existsSync(path)) {
959
+ const partial = `${path}.${process.pid}.tmp`;
960
+ writeFileSync(partial, json);
961
+ renameSync(partial, path);
962
+ }
963
+ seccompFile = path;
964
+ return path;
965
+ }
966
+ const ENGINES = {
967
+ docker: {
968
+ bin: "docker",
969
+ name: "Docker",
970
+ fn: "docker",
971
+ stateFormat: "{{.ServerVersion}} {{.OSType}}",
972
+ capacityFormat: "{{.NCPU}} {{.MemTotal}}",
973
+ imageId: ".Id",
974
+ rmForce: ["rm", "-f"],
975
+ runArgs: () => [],
976
+ createsWorkdir: true
977
+ },
978
+ podman: {
979
+ bin: "podman",
980
+ name: "Podman",
981
+ fn: "podman",
982
+ stateFormat: "{{.Version.Version}} {{.Host.OS}}",
983
+ capacityFormat: "{{.Host.CPUs}} {{.Host.MemTotal}}",
984
+ imageId: ".ID",
985
+ rmForce: [
986
+ "rm",
987
+ "-f",
988
+ "--time",
989
+ "0"
990
+ ],
991
+ runArgs: () => [
992
+ "--network",
993
+ "bridge",
994
+ "--security-opt",
995
+ `seccomp=${dockerSeccompFile()}`
996
+ ],
997
+ createsWorkdir: false
998
+ }
999
+ };
1000
+ const engineSpec = (engine = "docker") => ENGINES[engine];
1001
+ /**
1002
+ * The `CONTAINER_HOST` that reaches a `podman machine` straight through its API socket (macOS) or
1003
+ * named pipe (Windows), from `podman machine inspect`'s JSON.
1004
+ */
1005
+ function machineHost(inspect, platform) {
1006
+ const machine = Array.isArray(inspect) ? inspect[0] : void 0;
1007
+ const info = machine?.ConnectionInfo;
1008
+ const name = machine?.Name ?? "podman-machine-default";
1009
+ if (platform === "darwin" && info?.PodmanSocket?.Path) {
1010
+ const path = info.PodmanSocket.Path;
1011
+ return {
1012
+ host: `unix://${path}`,
1013
+ path,
1014
+ name
1015
+ };
1016
+ }
1017
+ if (platform === "win32" && info?.PodmanPipe?.Path) {
1018
+ const path = info.PodmanPipe.Path;
1019
+ return {
1020
+ host: `npipe://${path.replaceAll("\\", "/")}`,
1021
+ path,
1022
+ name
1023
+ };
1024
+ }
1025
+ return null;
1026
+ }
1027
+ /**
1028
+ * The environment every podman command gets. On macOS and Windows the client talks to the
1029
+ * machine's VM over SSH, a connection per command, and sshd's `MaxStartups` drops some of a burst
1030
+ * (exit 125, `ssh: handshake failed`), so commands go through the machine's API socket instead.
1031
+ * Not when the user picked a host (`CONTAINER_HOST`, `CONTAINER_CONNECTION`, or a default
1032
+ * connection that isn't the machine's), or the socket isn't there.
1033
+ */
1034
+ function podmanHostEnv(inputs) {
1035
+ const { platform, env } = inputs;
1036
+ if (platform !== "darwin" && platform !== "win32") return {};
1037
+ if (env.CONTAINER_HOST || env.CONTAINER_CONNECTION) return {};
1038
+ const machine = machineHost(inputs.inspect(), platform);
1039
+ if (!machine || !inputs.exists(machine.path)) return {};
1040
+ const connections = inputs.connections();
1041
+ const chosen = Array.isArray(connections) ? connections.find((c) => c.Default)?.Name : void 0;
1042
+ if (chosen && chosen !== machine.name && chosen !== `${machine.name}-root`) return {};
1043
+ return { CONTAINER_HOST: machine.host };
1044
+ }
1045
+ const readJson = (bin, args) => {
1046
+ try {
1047
+ const out = execFileSync(bin, args, {
1048
+ encoding: "utf8",
1049
+ stdio: [
1050
+ "ignore",
1051
+ "pipe",
1052
+ "ignore"
1053
+ ],
1054
+ timeout: 1e4,
1055
+ windowsHide: true
1056
+ });
1057
+ return JSON.parse(out);
1058
+ } catch {
1059
+ return;
1060
+ }
1061
+ };
1062
+ let podmanEnv;
1063
+ /** What every command on `engine` adds to its environment; read once per process. */
1064
+ function engineEnv(engine = "docker") {
1065
+ if (engine !== "podman") return {};
1066
+ podmanEnv ??= podmanHostEnv({
1067
+ platform: process.platform,
1068
+ env: process.env,
1069
+ inspect: () => readJson("podman", ["machine", "inspect"]),
1070
+ connections: () => readJson("podman", [
1071
+ "system",
1072
+ "connection",
1073
+ "list",
1074
+ "--format",
1075
+ "json"
1076
+ ]),
1077
+ exists: existsSync
1078
+ });
1079
+ return podmanEnv;
1080
+ }
1081
+ /** Docker's ids are `sha256:…`; Podman's are the bare hex. */
1082
+ const normalizeImageId = (id) => id.includes(":") ? id : `sha256:${id}`;
1083
+ //#endregion
17
1084
  //#region ../sandbox-docker/src/build-failure.ts
18
1085
  var ImageBuildError = class extends Error {
19
1086
  name = "ImageBuildError";
@@ -27,6 +1094,7 @@ const stripAnsi = (text) => text.replace(/\x1b\[[0-9;]*[A-Za-z]/g, "");
27
1094
  /** The failing step and its output from `--progress plain` build output. */
28
1095
  function parseBuildOutput(text) {
29
1096
  const lines = stripAnsi(text).split(/\r?\n/);
1097
+ if (!lines.some((l) => /^(?:#\d+ )?ERROR: /.test(l)) && lines.some((l) => l.startsWith("Error: "))) return parseBuildahOutput(lines);
30
1098
  let step = null;
31
1099
  let error = null;
32
1100
  for (const line of lines) {
@@ -47,14 +1115,35 @@ function parseBuildOutput(text) {
47
1115
  exitCode: code ? Number(code) : null
48
1116
  };
49
1117
  }
1118
+ /**
1119
+ * buildah's output (`podman build`): `STEP n/m: …` headers, each step's output as is, then
1120
+ * `Error: building at STEP "…": …`. Its own warnings are `time="…" level=…` lines.
1121
+ */
1122
+ function parseBuildahOutput(lines) {
1123
+ let error = null;
1124
+ let output = [];
1125
+ for (const line of lines) if (/^STEP \d+\/\d+: /.test(line)) output = [];
1126
+ else if (line.startsWith("Error: ")) error = line.slice(7);
1127
+ else if (!error && line.trim() && !/^time="[^"]*" level=|^--> /.test(line)) output.push(line);
1128
+ error = (error ?? "").replace(/^building at STEP "(?:[^"\\]|\\.)*": /, "").replace(/ &imagebuilder\.Step\{.*$/, "").trim() || null;
1129
+ const code = /exit status (\d+)$/.exec(error ?? "")?.[1];
1130
+ return {
1131
+ error,
1132
+ output: output.slice(-8),
1133
+ exitCode: code ? Number(code) : null
1134
+ };
1135
+ }
50
1136
  /** ENOSPC or a SIGKILL (137, usually the out-of-memory killer), from anything the build printed. */
51
1137
  function failureCause(text, exitCode) {
52
1138
  if (/no space left on device|ENOSPC/i.test(text)) return "enospc";
53
- if (exitCode === 137 || /exit(?:ed| code:?) 137\b|signal: killed|OOMKilled/i.test(text)) return "oom";
1139
+ if (exitCode === 137 || /exit(?:ed| code:?| status) 137\b|signal: killed|OOMKilled/i.test(text)) return "oom";
54
1140
  return null;
55
1141
  }
56
- const causeLine = (cause) => cause === "enospc" ? "out of disk space (ENOSPC): free space for Docker (docker system df, reeval clean --images) and rerun" : "killed (exit 137): usually out of memory; give Docker more memory or lower the concurrency";
57
- const DETERMINISTIC = /did not complete successfully|dockerfile parse error|unknown instruction|should not be blank|pull access denied|repository does not exist|manifest unknown|not found: manifest|: not found\b|unauthorized|denied:|reeval needs a Debian or Ubuntu based image/i;
1142
+ const causeLine = (cause, engine) => {
1143
+ const { name, bin } = engineSpec(engine);
1144
+ return cause === "enospc" ? `out of disk space (ENOSPC): free space for ${name} (${bin} system df, reeval clean --images) and rerun` : `killed (exit 137): usually out of memory; give ${name} more memory or lower the concurrency`;
1145
+ };
1146
+ const DETERMINISTIC = /did not complete successfully|while running runtime: exit status|did not resolve to an alias|requested access to the resource is denied|dockerfile parse error|unknown instruction|should not be blank|pull access denied|repository does not exist|manifest unknown|not found: manifest|: not found\b|unauthorized|denied:|reeval needs a Debian or Ubuntu based image/i;
58
1147
  const TRANSIENT = /EAI_AGAIN|ECONNRESET|ETIMEDOUT|ECONNREFUSED|i\/o timeout|TLS handshake timeout|no such host|temporary failure in name resolution|connection reset by peer|dial tcp|net\/http: request canceled|unexpected EOF|\b(?:500|502|503|504) |429 Too Many Requests|toomanyrequests|Service Unavailable|Bad Gateway|Gateway Timeout|ENOTFOUND/i;
59
1148
  /** A registry or network error: a pull, a metadata lookup, or a download in the harness bootstrap. */
60
1149
  const isTransient = (text) => !DETERMINISTIC.test(text) && TRANSIENT.test(text);
@@ -77,7 +1166,7 @@ const RETRY_DELAYS = [2e3, 8e3];
77
1166
  */
78
1167
  function failureMessage(parts) {
79
1168
  const lines = [parts.headline];
80
- if (parts.cause) lines.push(causeLine(parts.cause));
1169
+ if (parts.cause) lines.push(causeLine(parts.cause, parts.engine));
81
1170
  if (parts.output.length) lines.push(...parts.output.map((l) => ` | ${l}`));
82
1171
  if (parts.log) lines.push(`(full log: ${parts.log})`);
83
1172
  return lines.join("\n");
@@ -87,6 +1176,119 @@ function outputTail(text, max = 8) {
87
1176
  return stripAnsi(text).split(/\r?\n/).map((l) => l.trimEnd()).filter((l) => l.trim()).slice(-max);
88
1177
  }
89
1178
  //#endregion
1179
+ //#region ../sandbox-docker/src/process.ts
1180
+ const CMD_META = /([()\][%!^"`<>&|;, *?])/g;
1181
+ const cmdEscape = (arg, twice) => {
1182
+ const quoted = `"${arg.replace(/(\\*)"/g, "$1$1\\\"").replace(/(\\*)$/, "$1$1")}"`.replace(CMD_META, "^$1");
1183
+ return twice ? quoted.replace(CMD_META, "^$1") : quoted;
1184
+ };
1185
+ /**
1186
+ * How to spawn `cmd` on Windows, where npm, npx and pnpm are `.cmd` scripts that only cmd.exe
1187
+ * runs: the program PATH and PATHEXT find, and for a script, cmd.exe with every argument escaped.
1188
+ */
1189
+ function windowsSpawn(cmd, args, env = process.env, exists = existsSync) {
1190
+ const exts = (env.PATHEXT ?? ".COM;.EXE;.BAT;.CMD").split(";").filter(Boolean);
1191
+ const file = (/[\\/]/.test(cmd) ? [""] : (env.PATH ?? env.Path ?? "").split(";").filter(Boolean)).flatMap((dir) => {
1192
+ const base = dir ? win32.join(dir, cmd) : cmd;
1193
+ return [...win32.extname(cmd) ? [base] : [], ...exts.map((ext) => base + ext.toLowerCase())];
1194
+ }).find(exists) ?? cmd;
1195
+ if (!/\.(cmd|bat)$/i.test(file)) return {
1196
+ file,
1197
+ args,
1198
+ verbatim: false
1199
+ };
1200
+ const twice = /node_modules[\\/]\.bin[\\/][^\\/]+\.cmd$/i.test(file);
1201
+ const line = [win32.normalize(file).replace(CMD_META, "^$1"), ...args.map((a) => cmdEscape(a, twice))].join(" ");
1202
+ return {
1203
+ file: env.ComSpec ?? "cmd.exe",
1204
+ args: [
1205
+ "/d",
1206
+ "/s",
1207
+ "/c",
1208
+ `"${line}"`
1209
+ ],
1210
+ verbatim: true
1211
+ };
1212
+ }
1213
+ /**
1214
+ * Kills a process and everything it started: its process group on POSIX (a detached child leads
1215
+ * one), its process tree with `taskkill` on Windows, which has neither groups nor signals.
1216
+ */
1217
+ function killTree(pid) {
1218
+ if (process.platform === "win32") {
1219
+ spawn("taskkill", [
1220
+ "/pid",
1221
+ String(pid),
1222
+ "/t",
1223
+ "/f"
1224
+ ], {
1225
+ stdio: "ignore",
1226
+ windowsHide: true
1227
+ }).on("error", () => {});
1228
+ return;
1229
+ }
1230
+ try {
1231
+ process.kill(-pid, "SIGKILL");
1232
+ } catch {
1233
+ try {
1234
+ process.kill(pid, "SIGKILL");
1235
+ } catch {}
1236
+ }
1237
+ }
1238
+ /** `s` as one single-quoted POSIX shell word. */
1239
+ const shellQuote = (s) => `'${s.replaceAll("'", `'\\''`)}'`;
1240
+ function run(cmd, args, options = {}) {
1241
+ const { signal } = options;
1242
+ return new Promise((resolve, reject) => {
1243
+ if (signal?.aborted) return reject(signal.reason);
1244
+ const detached = options.detached ?? true;
1245
+ const target = process.platform === "win32" ? windowsSpawn(cmd, args, options.env ? {
1246
+ ...process.env,
1247
+ ...options.env
1248
+ } : process.env) : {
1249
+ file: cmd,
1250
+ args,
1251
+ verbatim: false
1252
+ };
1253
+ const child = spawn(target.file, target.args, {
1254
+ cwd: options.cwd,
1255
+ stdio: "pipe",
1256
+ detached: detached && !target.verbatim,
1257
+ windowsHide: true,
1258
+ windowsVerbatimArguments: target.verbatim,
1259
+ env: options.env ? {
1260
+ ...process.env,
1261
+ ...options.env
1262
+ } : process.env
1263
+ });
1264
+ const out = [];
1265
+ let stderr = "";
1266
+ child.stdout.on("data", (d) => out.push(d));
1267
+ child.stderr.on("data", (d) => {
1268
+ stderr += d;
1269
+ });
1270
+ const onAbort = () => {
1271
+ if ((detached || process.platform === "win32") && child.pid) killTree(child.pid);
1272
+ else child.kill("SIGKILL");
1273
+ };
1274
+ signal?.addEventListener("abort", onAbort, { once: true });
1275
+ child.on("error", reject);
1276
+ child.on("close", (code) => {
1277
+ signal?.removeEventListener("abort", onAbort);
1278
+ if (signal?.aborted) return reject(signal.reason);
1279
+ const stdout = Buffer.concat(out);
1280
+ resolve({
1281
+ exitCode: code ?? 1,
1282
+ stdout: options.binary ? stdout : stdout.toString(),
1283
+ stderr
1284
+ });
1285
+ });
1286
+ if (child.pid) options.onSpawn?.(child.pid);
1287
+ child.stdin.on("error", () => {});
1288
+ child.stdin.end(options.input ?? "");
1289
+ });
1290
+ }
1291
+ //#endregion
90
1292
  //#region ../sandbox-docker/src/trace.ts
91
1293
  /** Most of each stream a trace keeps; the rest is counted. */
92
1294
  const MAX_STREAM = 4096;
@@ -104,9 +1306,10 @@ function streamPreview(data) {
104
1306
  if (data.includes(0) || !isUtf8(data)) return `<${data.length} bytes>`;
105
1307
  return clip(data.toString("utf8"), MAX_STREAM);
106
1308
  }
107
- function traceDocker(args, startedAt, result) {
1309
+ function traceDocker(args, startedAt, result, bin = "docker") {
108
1310
  if (!listener) return;
109
1311
  const base = {
1312
+ bin,
110
1313
  args: args.map((a) => clip(a, MAX_ARG)),
111
1314
  ms: Date.now() - startedAt
112
1315
  };
@@ -133,107 +1336,199 @@ function traceDocker(args, startedAt, result) {
133
1336
  }
134
1337
  //#endregion
135
1338
  //#region ../sandbox-docker/src/docker-cli.ts
136
- /** Runs the docker CLI. `env` values are passed via the CLI's environment, never argv. */
1339
+ /** How long to wait before each retry of a command that never reached Podman. */
1340
+ const CONNECTION_RETRY_MS = [
1341
+ 100,
1342
+ 250,
1343
+ 500,
1344
+ 1e3,
1345
+ 2e3
1346
+ ];
1347
+ /**
1348
+ * Whether a podman command failed before reaching the engine: the remote client's SSH handshake
1349
+ * or socket connection to `podman machine`, so running it again is safe.
1350
+ */
1351
+ const isConnectionFailure = (r) => r.exitCode === 125 && /ssh: handshake failed|unable to connect to Podman socket/.test(r.stderr);
1352
+ const sleep = (ms, signal) => new Promise((resolve) => {
1353
+ const timer = setTimeout(done, ms);
1354
+ function done() {
1355
+ clearTimeout(timer);
1356
+ signal?.removeEventListener("abort", done);
1357
+ resolve();
1358
+ }
1359
+ signal?.addEventListener("abort", done, { once: true });
1360
+ });
1361
+ /**
1362
+ * Runs `attempt` again, after each of `delays`, while its result is a connection failure (see
1363
+ * {@link isConnectionFailure}), and returns the last result.
1364
+ */
1365
+ async function retryConnection(attempt, options = {}) {
1366
+ const { delays = CONNECTION_RETRY_MS, signal, wait = sleep } = options;
1367
+ let r = await attempt();
1368
+ for (const ms of delays) {
1369
+ if (!isConnectionFailure(r) || signal?.aborted) break;
1370
+ await wait(ms, signal);
1371
+ r = await attempt();
1372
+ }
1373
+ return r;
1374
+ }
1375
+ /** Runs the docker (or podman) CLI. `env` values are passed via the CLI's environment, never argv. */
137
1376
  async function docker(args, options = {}) {
138
- const startedAt = Date.now();
1377
+ const { engine, ...rest } = options;
1378
+ const { bin } = engineSpec(engine);
139
1379
  const stdin = options.input?.length ?? 0;
140
- try {
141
- const r = await run("docker", args, {
142
- ...options,
143
- binary: true
144
- });
145
- traceDocker(args, startedAt, {
146
- ...r,
147
- stdin
148
- });
149
- return r;
150
- } catch (error) {
151
- traceDocker(args, startedAt, { error });
152
- throw error;
153
- }
1380
+ const env = {
1381
+ ...engineEnv(engine),
1382
+ ...rest.env
1383
+ };
1384
+ const once = async () => {
1385
+ const startedAt = Date.now();
1386
+ try {
1387
+ const r = await run(bin, args, {
1388
+ ...rest,
1389
+ env,
1390
+ binary: true
1391
+ });
1392
+ traceDocker(args, startedAt, {
1393
+ ...r,
1394
+ stdin
1395
+ }, bin);
1396
+ return r;
1397
+ } catch (error) {
1398
+ traceDocker(args, startedAt, { error }, bin);
1399
+ throw error;
1400
+ }
1401
+ };
1402
+ return engine === "podman" ? retryConnection(once, { signal: options.signal }) : once();
154
1403
  }
155
1404
  async function dockerOk(args, opts) {
156
1405
  const r = await docker(args, opts);
157
- if (r.exitCode !== 0) throw new Error(`docker ${args[0]} failed: ${r.stderr.trim()}`);
1406
+ if (r.exitCode !== 0) throw new Error(`${engineSpec(opts?.engine).bin} ${args[0]} failed: ${r.stderr.trim()}`);
158
1407
  return r.stdout.toString("utf8").trim();
159
1408
  }
160
- /** Removes a container in its own process group, so removal survives this process being killed. */
161
- function removeContainerDetached(id) {
162
- return new Promise((resolve) => {
1409
+ /** Whether `rm -f` left the container gone: it removed it, or it was already gone. */
1410
+ const removalDone = (r) => r.exitCode === 0 || /no such container/i.test(r.stderr);
1411
+ /** How long to wait before each retry of a removal that failed. */
1412
+ const REMOVAL_RETRY_MS = [
1413
+ 250,
1414
+ 500,
1415
+ 1e3,
1416
+ 2e3,
1417
+ 4e3
1418
+ ];
1419
+ /**
1420
+ * Removes a container in its own process group, so removal survives this process being killed,
1421
+ * and tries again while it fails. Resolves either way.
1422
+ */
1423
+ async function removeContainerDetached(id, engine, options = {}) {
1424
+ const { bin, rmForce } = engineSpec(engine);
1425
+ const { delays = REMOVAL_RETRY_MS, wait = sleep } = options;
1426
+ const args = [...rmForce, id];
1427
+ const env = {
1428
+ ...process.env,
1429
+ ...engineEnv(engine)
1430
+ };
1431
+ const once = () => new Promise((resolve) => {
163
1432
  const keepAlive = setInterval(() => {}, 1e3);
164
1433
  const startedAt = Date.now();
165
- const args = [
166
- "rm",
167
- "-f",
168
- id
169
- ];
1434
+ let stderr = "";
1435
+ let settled = false;
170
1436
  const done = (exitCode) => {
1437
+ if (settled) return;
1438
+ settled = true;
171
1439
  clearInterval(keepAlive);
172
- traceDocker(args, startedAt, { exitCode });
173
- resolve();
1440
+ traceDocker(args, startedAt, {
1441
+ exitCode,
1442
+ stderr
1443
+ }, bin);
1444
+ resolve({
1445
+ exitCode,
1446
+ stderr
1447
+ });
174
1448
  };
175
- const child = spawn("docker", args, {
1449
+ const child = spawn(bin, args, {
176
1450
  detached: true,
177
- stdio: "ignore",
178
- windowsHide: true
1451
+ stdio: [
1452
+ "ignore",
1453
+ "ignore",
1454
+ "pipe"
1455
+ ],
1456
+ windowsHide: true,
1457
+ env
1458
+ });
1459
+ child.stderr.on("data", (d) => {
1460
+ stderr += d;
1461
+ });
1462
+ child.on("error", (error) => {
1463
+ stderr += String(error);
1464
+ done(null);
179
1465
  });
180
- child.on("error", () => done(null));
181
1466
  child.on("close", done);
182
1467
  });
1468
+ let r = await once();
1469
+ for (const ms of delays) {
1470
+ if (removalDone(r) || r.exitCode === null) return;
1471
+ await wait(ms);
1472
+ r = await once();
1473
+ }
183
1474
  }
184
1475
  /**
185
1476
  * Removes every container with `label` (`key=value`) for the next few seconds, in its own process
186
1477
  * group so it outlives this process. For a `docker run` killed mid-way: the daemon may create the
187
1478
  * container after the CLI dies, and its id never came back.
188
1479
  */
189
- function sweepLabelDetached(label, seconds = 15) {
1480
+ function sweepLabelDetached(label, seconds = 15, engine) {
1481
+ const { bin, rmForce } = engineSpec(engine);
190
1482
  const child = spawn(process.execPath, [
191
1483
  "-e",
192
1484
  `const { execFileSync } = require('node:child_process')
193
- const [filter, seconds] = process.argv.slice(1)
1485
+ const [filter, seconds, bin, ...rm] = process.argv.slice(1)
194
1486
  const o = { encoding: 'utf8', stdio: ['ignore', 'pipe', 'ignore'], windowsHide: true }
195
1487
  for (let i = 0; i < Number(seconds); i++) {
196
1488
  try {
197
- const ids = execFileSync('docker', ['ps', '-aq', '--filter', filter], o).split(/\\s+/).filter(Boolean)
198
- if (ids.length) execFileSync('docker', ['rm', '-f', ...ids], o)
1489
+ const ids = execFileSync(bin, ['ps', '-aq', '--filter', filter], o).split(/\\s+/).filter(Boolean)
1490
+ if (ids.length) execFileSync(bin, [...rm, ...ids], o)
199
1491
  } catch {}
200
1492
  Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, 1000)
201
1493
  }`,
202
1494
  `label=${label}`,
203
- String(seconds)
1495
+ String(seconds),
1496
+ bin,
1497
+ ...rmForce
204
1498
  ], {
205
1499
  detached: true,
206
1500
  stdio: "ignore",
207
1501
  windowsHide: true,
208
1502
  env: {
209
1503
  ...process.env,
1504
+ ...engineEnv(engine),
210
1505
  BUN_BE_BUN: "1"
211
1506
  }
212
1507
  });
213
1508
  child.on("error", () => {});
214
1509
  child.unref();
215
1510
  }
216
- async function dockerState() {
1511
+ async function dockerState(engine) {
217
1512
  const r = await docker([
218
1513
  "info",
219
1514
  "--format",
220
- "{{.ServerVersion}} {{.OSType}}"
221
- ]).catch(() => null);
1515
+ engineSpec(engine).stateFormat
1516
+ ], { engine }).catch(() => null);
222
1517
  const [version, os] = r?.exitCode === 0 ? r.stdout.toString("utf8").trim().split(/\s+/) : [];
223
1518
  if (!version) return "down";
224
1519
  return os === "windows" ? "windows-containers" : "running";
225
1520
  }
226
- /** Whether Docker is running Linux containers, as every sandbox needs. */
227
- async function dockerAvailable() {
228
- return await dockerState() === "running";
1521
+ /** Whether Docker (or Podman) is running Linux containers, as every sandbox needs. */
1522
+ async function dockerAvailable(engine) {
1523
+ return await dockerState(engine) === "running";
229
1524
  }
230
- /** CPUs and memory of the machine containers run on (the VM, under Docker Desktop). */
231
- async function dockerCapacity() {
1525
+ /** CPUs and memory of the machine containers run on (the VM, under Docker Desktop or `podman machine`). */
1526
+ async function dockerCapacity(engine) {
232
1527
  const r = await docker([
233
1528
  "info",
234
1529
  "--format",
235
- "{{.NCPU}} {{.MemTotal}}"
236
- ]).catch(() => null);
1530
+ engineSpec(engine).capacityFormat
1531
+ ], { engine }).catch(() => null);
237
1532
  if (r?.exitCode !== 0) return null;
238
1533
  const [cpus, memoryBytes] = r.stdout.toString("utf8").trim().split(/\s+/).map(Number);
239
1534
  return cpus && memoryBytes ? {
@@ -247,23 +1542,51 @@ async function dockerCapacity() {
247
1542
  * their bare local name (`reeval-sandbox@sha256:…`). A bare name is Docker Hub's `library/`
248
1543
  * namespace, which only official images can push to, so only a digest whose name has a registry
249
1544
  * host or a namespace counts. Official images such as `busybox` count as local; no image with
250
- * the harness baked in is one.
1545
+ * the harness baked in is one. Podman names local images `localhost/…`, which no one pulls from.
1546
+ */
1547
+ const isRegistryDigest = (digest) => {
1548
+ const name = digest.split("@")[0] ?? "";
1549
+ return name.includes("/") && !name.startsWith("localhost/");
1550
+ };
1551
+ /** `repository:tag` of every local image in `repository`; none when the CLI fails. */
1552
+ async function imageTags(repository, engine) {
1553
+ const r = await docker([
1554
+ "image",
1555
+ "ls",
1556
+ "--format",
1557
+ "{{.Repository}}:{{.Tag}}",
1558
+ repository
1559
+ ], { engine }).catch(() => null);
1560
+ if (r?.exitCode !== 0) return [];
1561
+ return r.stdout.toString("utf8").split(/\r?\n/).filter(Boolean).map((t) => t.replace(/^localhost\//, ""));
1562
+ }
1563
+ /** `image inspect`'s answer when the engine has no such image (Docker's wording, then Podman's). */
1564
+ const isNoSuchImage = (stderr) => /no such image|image not known/i.test(stderr);
1565
+ /**
1566
+ * The image, or null when the engine says it has no such image. A CLI that can't start or a daemon
1567
+ * that doesn't answer throws instead, naming the error: that's not knowing, not a missing image.
251
1568
  */
252
- const isRegistryDigest = (digest) => (digest.split("@")[0] ?? "").includes("/");
253
- async function imageInfo(image) {
1569
+ async function imageInfo(image, engine) {
1570
+ const { bin, imageId } = engineSpec(engine);
254
1571
  const r = await docker([
255
1572
  "image",
256
1573
  "inspect",
257
1574
  "--format",
258
- "{\"config\":{{json .Config}},\"id\":{{json .Id}},\"repoDigests\":{{json .RepoDigests}}}",
1575
+ `{"config":{{json .Config}},"id":{{json ${imageId}}},"repoDigests":{{json .RepoDigests}}}`,
259
1576
  image
260
- ]).catch(() => null);
261
- if (r?.exitCode !== 0) return null;
1577
+ ], { engine }).catch((error) => {
1578
+ throw new Error(`${bin} image inspect ${image} couldn't run: ${error.message}`);
1579
+ });
1580
+ if (r.exitCode !== 0) {
1581
+ const stderr = r.stderr.trim();
1582
+ if (isNoSuchImage(stderr)) return null;
1583
+ throw new Error(`${bin} image inspect ${image} failed: ${stderr || `exit ${r.exitCode}`}`);
1584
+ }
262
1585
  const info = JSON.parse(r.stdout.toString("utf8"));
263
1586
  const repoDigests = (info.repoDigests ?? []).filter(isRegistryDigest);
264
1587
  return {
265
1588
  labels: info.config?.Labels ?? {},
266
- id: info.id,
1589
+ id: normalizeImageId(info.id),
267
1590
  repoDigests
268
1591
  };
269
1592
  }
@@ -278,32 +1601,40 @@ async function imageInfo(image) {
278
1601
  const HARNESS_PACKAGES = {
279
1602
  cursor: {
280
1603
  name: "@reeval/harness-cursor-sdk",
281
- version: "0.1.4"
1604
+ version: "0.1.5"
282
1605
  },
283
1606
  "claude-code": {
284
1607
  name: "@ai-sdk/harness-claude-code",
285
- version: "1.0.152",
286
- patch: "8edc594f"
1608
+ version: "1.0.160",
1609
+ patch: "907f9184"
287
1610
  },
288
1611
  antigravity: {
289
1612
  name: "@reeval/harness-antigravity",
290
- version: "0.1.6"
1613
+ version: "0.1.8"
291
1614
  },
292
1615
  opencode: {
293
1616
  name: "@reeval/harness-opencode",
294
- version: "0.2.7"
1617
+ version: "0.2.8"
295
1618
  },
296
1619
  goose: {
297
1620
  name: "@reeval/harness-goose",
298
- version: "0.1.2"
1621
+ version: "0.1.3"
299
1622
  },
300
1623
  pi: {
301
1624
  name: "@reeval/harness-pi",
302
- version: "0.2.6"
1625
+ version: "0.2.7"
303
1626
  },
304
1627
  codex: {
305
1628
  name: "@reeval/harness-codex",
306
- version: "0.1.6"
1629
+ version: "0.1.7"
1630
+ },
1631
+ fx: {
1632
+ name: "@reeval/harness-fx",
1633
+ version: "0.1.0"
1634
+ },
1635
+ "grok-build": {
1636
+ name: "@reeval/harness-grok-build",
1637
+ version: "0.1.0"
307
1638
  }
308
1639
  };
309
1640
  /** Every harness with an image, in {@link HARNESS_PACKAGES} order. */
@@ -668,7 +1999,9 @@ const HARNESS_HOSTS = {
668
1999
  opencode: ["generativelanguage.googleapis.com", "mcp.exa.ai"],
669
2000
  goose: ["generativelanguage.googleapis.com"],
670
2001
  pi: ["generativelanguage.googleapis.com"],
671
- codex: ["api.openai.com"]
2002
+ codex: ["api.openai.com"],
2003
+ fx: ["ai-gateway.vercel.sh"],
2004
+ "grok-build": ["api.x.ai"]
672
2005
  };
673
2006
  /** The package registries and GitHub, for a restricted policy that still installs. */
674
2007
  const PACKAGE_HOSTS = Object.freeze([
@@ -1782,14 +3115,14 @@ const PROXY_PORT = 43128;
1782
3115
  const CA_PATH = "/usr/local/share/ca-certificates/reeval-egress.crt";
1783
3116
  /** Debian's system bundle, which `update-ca-certificates` rebuilds with the gateway's CA in it. */
1784
3117
  const CA_BUNDLE = "/etc/ssl/certs/ca-certificates.crt";
1785
- const BUNDLED = "es:ca-bundle";
3118
+ const BUNDLED = "reeval:ca-bundle";
1786
3119
  const READY_TIMEOUT_MS = 15e3;
1787
3120
  /**
1788
3121
  * The gateway's side of the container runs as root, whoever the sandbox runs as: the sandbox user
1789
3122
  * can't signal, trace or replace the forwarder, or change the CA it installed.
1790
3123
  */
1791
3124
  const AS_ROOT = ["--user", "0:0"];
1792
- const installCa = (containerId, cert, signal) => docker([
3125
+ const installCa = (containerId, cert, signal, engine) => docker([
1793
3126
  "exec",
1794
3127
  "--interactive",
1795
3128
  ...AS_ROOT,
@@ -1799,15 +3132,16 @@ const installCa = (containerId, cert, signal) => docker([
1799
3132
  `umask 022 && mkdir -p "$(dirname ${CA_PATH})" && cat > ${CA_PATH} && { command -v update-ca-certificates >/dev/null && update-ca-certificates >/dev/null 2>&1 && grep -q "$(sed -n 2p ${CA_PATH})" ${CA_BUNDLE} && echo ${BUNDLED}; true; }`
1800
3133
  ], {
1801
3134
  input: cert,
1802
- signal
3135
+ signal,
3136
+ engine
1803
3137
  });
1804
3138
  /**
1805
3139
  * Starts the egress gateway for one container: a forwarder inside it, tunnelled over one
1806
3140
  * `docker exec -i`, and the proxy in this process, which holds the real credentials.
1807
3141
  */
1808
- async function startGateway(containerId, options, signal) {
3142
+ async function startGateway(containerId, options, signal, engine) {
1809
3143
  const ca = createCertificateAuthority();
1810
- const installed = await installCa(containerId, ca.cert, signal);
3144
+ const installed = await installCa(containerId, ca.cert, signal, engine);
1811
3145
  if (installed.exitCode !== 0) throw new Error(`couldn't install the gateway CA: ${installed.stderr.trim()}`);
1812
3146
  const bundled = installed.stdout.toString("utf8").includes(BUNDLED);
1813
3147
  const proxy = createEgressProxy({
@@ -1824,14 +3158,19 @@ async function startGateway(containerId, options, signal) {
1824
3158
  forwarderScript(PROXY_PORT)
1825
3159
  ];
1826
3160
  const startedAt = Date.now();
1827
- const child = spawn("docker", args, {
3161
+ const { bin } = engineSpec(engine);
3162
+ const child = spawn(bin, args, {
1828
3163
  stdio: "pipe",
1829
- detached: true
3164
+ detached: true,
3165
+ env: {
3166
+ ...process.env,
3167
+ ...engineEnv(engine)
3168
+ }
1830
3169
  });
1831
3170
  child.once("close", (code) => traceDocker(args, startedAt, {
1832
3171
  exitCode: code,
1833
3172
  stderr
1834
- }));
3173
+ }, bin));
1835
3174
  let stderr = "";
1836
3175
  child.stderr.on("data", (d) => {
1837
3176
  stderr += d;
@@ -1982,14 +3321,21 @@ const ROOT_CAPABILITIES = [
1982
3321
  "SETUID",
1983
3322
  "SETGID"
1984
3323
  ];
1985
- let hostCpus;
3324
+ const hostCpus = /* @__PURE__ */ new Map();
1986
3325
  /** Docker refuses `--cpus` above the host's count, so cap it there. */
1987
- async function cpuLimit(cpus) {
1988
- hostCpus ??= dockerCapacity().then((c) => c?.cpus, () => void 0);
1989
- const available = await hostCpus;
3326
+ async function cpuLimit(cpus, engine = "docker") {
3327
+ let known = hostCpus.get(engine);
3328
+ if (!known) {
3329
+ known = dockerCapacity(engine).then((c) => c?.cpus, () => void 0);
3330
+ hostCpus.set(engine, known);
3331
+ }
3332
+ const available = await known;
1990
3333
  return String(available ? Math.min(cpus, available) : cpus);
1991
3334
  }
1992
- /** The `docker run` flags that confine the container: its user, capabilities and limits. */
3335
+ /**
3336
+ * The `docker run` flags that confine the container: its user, capabilities and limits, and on
3337
+ * Podman the bridge network and Docker's seccomp profile.
3338
+ */
1993
3339
  async function confinementArgs(options) {
1994
3340
  const limits = {
1995
3341
  ...DEFAULT_LIMITS,
@@ -2011,7 +3357,8 @@ async function confinementArgs(options) {
2011
3357
  "--pids-limit",
2012
3358
  String(limits.pids),
2013
3359
  "--cpus",
2014
- await cpuLimit(limits.cpus)
3360
+ await cpuLimit(limits.cpus, options.engine),
3361
+ ...engineSpec(options.engine).runArgs()
2015
3362
  ];
2016
3363
  }
2017
3364
  /** Runtime `npm i -g` goes to the sandbox user's own prefix, whose `bin` the images put on PATH. */
@@ -2023,14 +3370,14 @@ const EXEC_MARKER = "REEVAL_EXEC_ID";
2023
3370
  * `memory.events` and v1's `memory.oom_control` both have an `oom_kill` line. Without either,
2024
3371
  * Docker's `OOMKilled` says only whether there was one.
2025
3372
  */
2026
- async function oomKills(id) {
3373
+ async function oomKills(id, engine) {
2027
3374
  const events = await docker([
2028
3375
  "exec",
2029
3376
  id,
2030
3377
  "sh",
2031
3378
  "-c",
2032
3379
  "cat /sys/fs/cgroup/memory.events 2>/dev/null || cat /sys/fs/cgroup/memory/memory.oom_control"
2033
- ]).catch(() => null);
3380
+ ], { engine }).catch(() => null);
2034
3381
  const count = events?.stdout.toString("utf8").match(/^oom_kill (\d+)$/m)?.[1];
2035
3382
  if (events?.exitCode === 0 && count !== void 0) return Number(count);
2036
3383
  const inspected = await docker([
@@ -2038,21 +3385,31 @@ async function oomKills(id) {
2038
3385
  "--format",
2039
3386
  "{{.State.OOMKilled}}",
2040
3387
  id
2041
- ]).catch(() => null);
3388
+ ], { engine }).catch(() => null);
2042
3389
  if (inspected?.exitCode !== 0) return null;
2043
3390
  const killed = inspected.stdout.toString("utf8").trim();
2044
3391
  return killed === "true" ? 1 : killed === "false" ? 0 : null;
2045
3392
  }
2046
3393
  /** The Docker networks a container is attached to. */
2047
- async function networksOf(id) {
3394
+ async function networksOf(id, engine) {
2048
3395
  const out = await dockerOk([
2049
3396
  "inspect",
2050
3397
  "--format",
2051
3398
  "{{json .NetworkSettings.Networks}}",
2052
3399
  id
2053
- ]);
3400
+ ], { engine });
2054
3401
  return Object.keys(JSON.parse(out) ?? {});
2055
3402
  }
3403
+ /** How the container is networked when it's on no network: `host`, `slirp4netns`, `pasta`… */
3404
+ async function networkMode(id, engine) {
3405
+ const r = await docker([
3406
+ "inspect",
3407
+ "--format",
3408
+ "{{.HostConfig.NetworkMode}}",
3409
+ id
3410
+ ], { engine }).catch(() => null);
3411
+ return r?.exitCode === 0 ? r.stdout.toString("utf8").trim() || "unknown" : "unknown";
3412
+ }
2056
3413
  /**
2057
3414
  * A harness sandbox session backed by one local Docker container. Commands and file I/O go
2058
3415
  * through `docker exec`. With the egress gateway, ports are reached through its tunnel whatever
@@ -2067,6 +3424,8 @@ async function createDockerSession(options) {
2067
3424
  };
2068
3425
  const lifetime = Math.ceil((options.lifetimeMs ?? 864e5) / 1e3);
2069
3426
  const signal = options.abortSignal;
3427
+ const { engine } = options;
3428
+ const spec = engineSpec(engine);
2070
3429
  const env = {
2071
3430
  ...userEnv(options),
2072
3431
  ...options.env
@@ -2081,20 +3440,21 @@ async function createDockerSession(options) {
2081
3440
  ...Object.keys(env).flatMap((k) => ["--env", k]),
2082
3441
  "--publish",
2083
3442
  `127.0.0.1::${BRIDGE_PORT}`,
2084
- "--workdir",
2085
- SANDBOX_ROOT,
3443
+ ...spec.createsWorkdir ? ["--workdir", SANDBOX_ROOT] : [],
2086
3444
  "--entrypoint",
2087
3445
  "sleep",
2088
3446
  options.image,
2089
3447
  String(lifetime)
2090
3448
  ], {
2091
3449
  signal,
2092
- env
3450
+ env,
3451
+ engine
2093
3452
  }).catch((error) => {
2094
- if (signal?.aborted) sweepLabelDetached(`${LABEL.session}=${nonce}`);
2095
- if (/unable to find user/i.test(error.message)) {
2096
- sweepLabelDetached(`${LABEL.session}=${nonce}`);
2097
- throw new Error(`${options.image} has no ${SANDBOX_USER} user to run the sandbox as. Images reeval builds have one: rebuild it (reeval image build), or start from reeval's image or docker({ from }). An eval that needs root at run time can opt in with docker({ root: true }).`);
3453
+ const sweep = () => sweepLabelDetached(`${LABEL.session}=${nonce}`, void 0, engine);
3454
+ if (signal?.aborted) sweep();
3455
+ if (/unable to find user|no matching entries in passwd/i.test(error.message)) {
3456
+ sweep();
3457
+ throw new Error(`${options.image} has no ${SANDBOX_USER} user to run the sandbox as. Images reeval builds have one: rebuild it (reeval image build), or start from reeval's image or ${spec.fn}({ from }). An eval that needs root at run time can opt in with ${spec.fn}({ root: true }).`);
2098
3458
  }
2099
3459
  throw error;
2100
3460
  });
@@ -2102,33 +3462,57 @@ async function createDockerSession(options) {
2102
3462
  let removed;
2103
3463
  const remove = () => {
2104
3464
  gateway?.close();
2105
- removed ??= removeContainerDetached(id);
3465
+ removed ??= removeContainerDetached(id, engine);
2106
3466
  return removed;
2107
3467
  };
2108
3468
  if (signal?.aborted) {
2109
3469
  await remove();
2110
3470
  throw signal.reason;
2111
3471
  }
3472
+ if (!spec.createsWorkdir) {
3473
+ const made = await docker([
3474
+ "exec",
3475
+ "--user",
3476
+ "0:0",
3477
+ id,
3478
+ "mkdir",
3479
+ "-p",
3480
+ SANDBOX_ROOT
3481
+ ], {
3482
+ engine,
3483
+ signal
3484
+ }).catch((error) => ({
3485
+ exitCode: 1,
3486
+ stderr: error.message
3487
+ }));
3488
+ if (made.exitCode !== 0) {
3489
+ await remove();
3490
+ if (signal?.aborted) throw signal.reason;
3491
+ throw new Error(`Couldn't create ${SANDBOX_ROOT} in the container: ${made.stderr.trim()}`);
3492
+ }
3493
+ }
2112
3494
  const egressOptions = options.egress === true ? {} : options.egress || void 0;
2113
3495
  let egress;
2114
3496
  let detached = [];
2115
3497
  const attach = async (policy) => {
2116
3498
  if (isRestricted(policy) && detached.length === 0) {
2117
- detached = await networksOf(id);
3499
+ detached = await networksOf(id, engine);
3500
+ const mode = detached.length === 0 ? await networkMode(id, engine) : "none";
3501
+ if (detached.length === 0 && mode !== "none") throw new Error(`the container's network is ${mode}, which ${spec.name} can't detach it from, so a restricted policy would still have a route out`);
2118
3502
  for (const n of detached) await dockerOk([
2119
3503
  "network",
2120
3504
  "disconnect",
2121
3505
  "--force",
2122
3506
  n,
2123
3507
  id
2124
- ]);
3508
+ ], { engine });
2125
3509
  } else if (!isRestricted(policy) && detached.length > 0) {
2126
3510
  for (const n of detached) await dockerOk([
2127
3511
  "network",
2128
3512
  "connect",
2129
3513
  n,
2130
3514
  id
2131
- ]);
3515
+ ], { engine });
2132
3516
  detached = [];
2133
3517
  }
2134
3518
  };
@@ -2139,7 +3523,7 @@ async function createDockerSession(options) {
2139
3523
  gateway = await startGateway(id, {
2140
3524
  ...rest,
2141
3525
  policy
2142
- }, signal);
3526
+ }, signal, engine);
2143
3527
  egress = { active: true };
2144
3528
  } catch (error) {
2145
3529
  if (signal?.aborted || isRestricted(policy)) {
@@ -2182,14 +3566,15 @@ async function createDockerSession(options) {
2182
3566
  "sh",
2183
3567
  "-c",
2184
3568
  `for e in /proc/[0-9]*/environ; do grep -qsxzF ${shellQuote(`${EXEC_MARKER}=${marker}`)} "$e" && kill -9 "$(basename "$(dirname "$e")")" 2>/dev/null; done; true`
2185
- ]).then(() => {}, () => {});
3569
+ ], { engine }).then(() => {}, () => {});
2186
3570
  const run = async (o) => {
2187
3571
  const env = envFor(o.env);
2188
3572
  const marker = nextMarker();
2189
3573
  try {
2190
3574
  const r = await docker(execArgs(o.command, marker, o.workingDirectory, env), {
2191
3575
  env,
2192
- signal: o.abortSignal
3576
+ signal: o.abortSignal,
3577
+ engine
2193
3578
  });
2194
3579
  return {
2195
3580
  exitCode: r.exitCode,
@@ -2208,7 +3593,10 @@ async function createDockerSession(options) {
2208
3593
  "cat",
2209
3594
  "--",
2210
3595
  posix.resolve(SANDBOX_ROOT, o.path)
2211
- ], { signal: o.abortSignal });
3596
+ ], {
3597
+ signal: o.abortSignal,
3598
+ engine
3599
+ });
2212
3600
  return r.exitCode === 0 ? new Uint8Array(r.stdout) : null;
2213
3601
  };
2214
3602
  const writeBinaryFile = async (o) => {
@@ -2222,7 +3610,8 @@ async function createDockerSession(options) {
2222
3610
  `mkdir -p ${shellQuote(posix.dirname(path))} && cat > ${shellQuote(path)}`
2223
3611
  ], {
2224
3612
  input: Buffer.from(o.content),
2225
- signal: o.abortSignal
3613
+ signal: o.abortSignal,
3614
+ engine
2226
3615
  });
2227
3616
  };
2228
3617
  const brokering = gateway ? {
@@ -2245,7 +3634,7 @@ async function createDockerSession(options) {
2245
3634
  } : {};
2246
3635
  const session = {
2247
3636
  id,
2248
- description: `Docker container ${id.slice(0, 12)} (${options.image})`,
3637
+ description: `${spec.name} container ${id.slice(0, 12)} (${options.image})`,
2249
3638
  defaultWorkingDirectory: SANDBOX_ROOT,
2250
3639
  ports: [BRIDGE_PORT],
2251
3640
  get egress() {
@@ -2257,30 +3646,31 @@ async function createDockerSession(options) {
2257
3646
  },
2258
3647
  ...brokering,
2259
3648
  ...substituting,
2260
- oomKills: () => oomKills(id),
3649
+ oomKills: () => oomKills(id, engine),
2261
3650
  run,
2262
3651
  async spawn(o) {
2263
3652
  const env = envFor(o.env);
2264
3653
  const marker = nextMarker();
2265
3654
  const args = execArgs(o.command, marker, o.workingDirectory, env);
2266
3655
  const startedAt = Date.now();
2267
- const child = spawn("docker", args, {
3656
+ const child = spawn(spec.bin, args, {
2268
3657
  stdio: [
2269
3658
  "ignore",
2270
3659
  "pipe",
2271
3660
  "pipe"
2272
3661
  ],
2273
3662
  detached: true,
2274
- env: env ? {
3663
+ env: {
2275
3664
  ...process.env,
3665
+ ...engineEnv(engine),
2276
3666
  ...env
2277
- } : process.env
3667
+ }
2278
3668
  });
2279
3669
  const exited = new Promise((resolve) => child.on("close", (code) => {
2280
3670
  traceDocker(args, startedAt, {
2281
3671
  exitCode: code,
2282
3672
  stdout: "<streamed>"
2283
- });
3673
+ }, spec.bin);
2284
3674
  resolve({ exitCode: code ?? 1 });
2285
3675
  }));
2286
3676
  const kill = async () => {
@@ -2329,10 +3719,10 @@ async function createDockerSession(options) {
2329
3719
  "port",
2330
3720
  id,
2331
3721
  `${port}/tcp`
2332
- ]);
3722
+ ], { engine });
2333
3723
  const hostPort = mapped.stdout.toString("utf8").split("\n")[0]?.split(":").at(-1);
2334
3724
  if (mapped.exitCode !== 0 || !hostPort) {
2335
- const reason = mapped.stderr.trim() || "Docker reports no host port for it";
3725
+ const reason = mapped.stderr.trim() || `${spec.name} reports no host port for it`;
2336
3726
  throw new Error(`Port ${port} of ${id.slice(0, 12)} isn't reachable: ${reason}`);
2337
3727
  }
2338
3728
  return { url: `${scheme}://127.0.0.1:${hostPort}` };
@@ -2363,7 +3753,7 @@ async function createDockerSession(options) {
2363
3753
  /** The session as an AI SDK harness sandbox provider. */
2364
3754
  const dockerSandboxProvider = (options) => ({
2365
3755
  specificationVersion: "harness-sandbox-v1",
2366
- providerId: "reeval-docker",
3756
+ providerId: options.engine === "podman" ? "reeval-podman" : "reeval-docker",
2367
3757
  async createSession(o) {
2368
3758
  const session = await createDockerSession({
2369
3759
  ...options,
@@ -2396,22 +3786,22 @@ const BOOTSTRAPS = {
2396
3786
  name: "Cursor",
2397
3787
  cli: "@cursor/sdk",
2398
3788
  version: `node -p "'@cursor/sdk ' + require(process.env.HOME + '/.ai-sdk-harness/.harness-bootstrap/cursor-sdk/node_modules/@cursor/sdk/package.json').version"`,
2399
- adapter: async () => (await import("./src-sIsDHWYq.js")).createCursorSdk()
3789
+ adapter: async () => (await import("./src-WD-zgQYZ.js")).createCursorSdk()
2400
3790
  },
2401
3791
  "claude-code": {
2402
3792
  name: "Claude Code",
2403
3793
  cli: "claude",
2404
- adapter: async () => (await import("./dist-CTzThfu_.js")).createClaudeCode()
3794
+ adapter: async () => (await import("./dist-CuY4ehEk.js")).createClaudeCode()
2405
3795
  },
2406
3796
  antigravity: {
2407
3797
  name: "Antigravity",
2408
3798
  cli: "agy",
2409
- adapter: async () => (await import("./src-BGWuWp6I.js")).createAntigravity()
3799
+ adapter: async () => (await import("./src-_oI9AePb.js")).createAntigravity()
2410
3800
  },
2411
3801
  opencode: {
2412
3802
  name: "OpenCode",
2413
3803
  cli: "opencode",
2414
- adapter: async () => (await import("./src-DLa-ESW0.js")).createOpenCode({
3804
+ adapter: async () => (await import("./src-CLoOMVWI.js")).createOpenCode({
2415
3805
  auth: { GOOGLE_GENERATIVE_AI_API_KEY: "unused" },
2416
3806
  model: "google/unused"
2417
3807
  })
@@ -2419,7 +3809,7 @@ const BOOTSTRAPS = {
2419
3809
  goose: {
2420
3810
  name: "Goose",
2421
3811
  cli: "goose",
2422
- adapter: async () => (await import("./src-Bx2x1ekD.js")).createGoose({
3812
+ adapter: async () => (await import("./src-qsKCqv7a.js")).createGoose({
2423
3813
  auth: { GOOGLE_API_KEY: "unused" },
2424
3814
  model: "unused"
2425
3815
  })
@@ -2427,12 +3817,28 @@ const BOOTSTRAPS = {
2427
3817
  pi: {
2428
3818
  name: "pi",
2429
3819
  cli: "pi",
2430
- adapter: async () => (await import("./src-BRt0O02i.js")).createPi({ auth: { GEMINI_API_KEY: "unused" } })
3820
+ adapter: async () => (await import("./src-DSYYPEOj.js")).createPi({ auth: { GEMINI_API_KEY: "unused" } })
2431
3821
  },
2432
3822
  codex: {
2433
3823
  name: "Codex",
2434
3824
  cli: "codex",
2435
- adapter: async () => (await import("./src-cN0aB-WR.js")).createCodex({ auth: { OPENAI_API_KEY: "unused" } })
3825
+ adapter: async () => (await import("./src-DCFtJRp0.js")).createCodex({ auth: { OPENAI_API_KEY: "unused" } })
3826
+ },
3827
+ fx: {
3828
+ name: "fx",
3829
+ cli: "fx",
3830
+ adapter: async () => (await import("./src-BxfCKA3_.js")).createFx({
3831
+ auth: { AI_GATEWAY_API_KEY: "unused" },
3832
+ model: "unused/unused"
3833
+ })
3834
+ },
3835
+ "grok-build": {
3836
+ name: "Grok Build",
3837
+ cli: "grok",
3838
+ adapter: async () => (await import("./src-CcrQbpG8.js")).createGrokBuild({
3839
+ auth: { XAI_API_KEY: "unused" },
3840
+ model: "unused"
3841
+ })
2436
3842
  }
2437
3843
  };
2438
3844
  /** Keeps the image's `PATH` in login shells, which Debian's `/etc/profile` resets. */
@@ -2464,10 +3870,10 @@ WORKDIR ${SANDBOX_ROOT}/${WORKSPACE_DIR}
2464
3870
  `;
2465
3871
  const tail = (text) => text.trim().split("\n").slice(-15).join("\n");
2466
3872
  const clipLine = (text, max = 300) => text.length > max ? `${text.slice(0, max - 1)}…` : text;
2467
- /** Why a `docker build` failed, in a line: the failing step's exit, or BuildKit's own error. */
2468
- function buildReason(error) {
2469
- if (!error) return "docker build failed";
2470
- const exit = /^process ".*" did not complete successfully: exit code: (\d+)$/s.exec(error);
3873
+ /** Why a `docker build` failed, in a line: the failing step's exit, or BuildKit's (or buildah's) own error. */
3874
+ function buildReason(error, engine) {
3875
+ if (!error) return `${engineSpec(engine).bin} build failed`;
3876
+ const exit = /^process ".*" did not complete successfully: exit code: (\d+)$/s.exec(error) ?? /^while running runtime: exit status (\d+)$/.exec(error);
2471
3877
  return exit ? `a RUN step exited ${exit[1]}` : clipLine(error.replace(/\s+/g, " "));
2472
3878
  }
2473
3879
  /**
@@ -2479,12 +3885,13 @@ function buildError(output, what, reason, keep = () => true) {
2479
3885
  const text = [parsed.error ?? "", ...parsed.output].join("\n");
2480
3886
  const cause = failureCause(text, parsed.exitCode);
2481
3887
  parsed.output = parsed.output.filter(keep);
2482
- const why = reason?.(parsed) ?? buildReason(parsed.error);
3888
+ const why = reason?.(parsed) ?? buildReason(parsed.error, what.engine);
2483
3889
  return new ImageBuildError(failureMessage({
2484
3890
  headline: `${what.headline} failed: ${why}`,
2485
3891
  cause,
2486
3892
  output: parsed.output,
2487
- log: what.log ?? null
3893
+ log: what.log ?? null,
3894
+ ...what.engine ? { engine: what.engine } : {}
2488
3895
  }), {
2489
3896
  stage: what.stage,
2490
3897
  ref: what.ref,
@@ -2499,12 +3906,12 @@ const BUILT_BY = ["--label", `${LABEL.managed}=image`];
2499
3906
  * Removes the images reeval built that nothing tags any more (a rebuild's old image) and the
2500
3907
  * intermediate `-base` tags of `from` builds. Returns how many it removed.
2501
3908
  */
2502
- async function pruneImages() {
3909
+ async function pruneImages(engine) {
2503
3910
  const list = async (args) => (await docker([
2504
3911
  "image",
2505
3912
  "ls",
2506
3913
  ...args
2507
- ])).stdout.toString("utf8").split("\n").map((l) => l.trim()).filter(Boolean);
3914
+ ], { engine })).stdout.toString("utf8").split("\n").map((l) => l.trim()).filter(Boolean);
2508
3915
  const dangling = [...await list([
2509
3916
  "-q",
2510
3917
  "--filter",
@@ -2528,46 +3935,93 @@ async function pruneImages() {
2528
3935
  "image",
2529
3936
  "rm",
2530
3937
  ref
2531
- ]).catch(() => null))?.exitCode === 0) removed++;
3938
+ ], { engine }).catch(() => null))?.exitCode === 0) removed++;
2532
3939
  return removed;
2533
3940
  }
3941
+ /** Docker's names for Node's architectures, as image indexes list platforms. */
3942
+ const OCI_ARCH = {
3943
+ x64: "amd64",
3944
+ arm64: "arm64",
3945
+ arm: "arm",
3946
+ ppc64: "ppc64le"
3947
+ };
3948
+ /**
3949
+ * A registry digest for `from` without Docker's buildx: skopeo's, which is the same digest
3950
+ * buildx gives, or else this platform's manifest from `podman manifest inspect`.
3951
+ */
3952
+ async function podmanRemoteDigest(from, signal) {
3953
+ const skopeo = await run("skopeo", [
3954
+ "inspect",
3955
+ "--format",
3956
+ "{{.Digest}}",
3957
+ `docker://${from}`
3958
+ ], { ...signal ? { signal } : {} }).catch(() => null);
3959
+ const digest = skopeo?.exitCode === 0 ? skopeo.stdout.trim() : "";
3960
+ if (digest.startsWith("sha256:")) return { digest };
3961
+ const r = await docker([
3962
+ "manifest",
3963
+ "inspect",
3964
+ from
3965
+ ], {
3966
+ signal,
3967
+ engine: "podman"
3968
+ }).catch(() => null);
3969
+ if (r?.exitCode === 0) {
3970
+ const manifest = JSON.parse(r.stdout.toString("utf8"));
3971
+ const arch = OCI_ARCH[process.arch] ?? process.arch;
3972
+ const own = manifest.manifests?.find((m) => m.platform?.os === "linux" && m.platform.architecture === arch)?.digest;
3973
+ if (own?.startsWith("sha256:")) return { digest: own };
3974
+ }
3975
+ return { error: (r?.stderr.trim() || skopeo?.stderr.trim() || "").replace(/^(?:Error|time="[^"]*" level=fatal msg=): ?/, "").replace(/\s+/g, " ") || `${from} doesn't resolve` };
3976
+ }
2534
3977
  /**
2535
3978
  * What a `from` names now, without pulling: its registry digest, or for an image that's only
2536
3979
  * local, its id (`local`). `error` when neither resolves, e.g. a typo or no network.
2537
3980
  */
2538
- async function resolveFrom(from, signal) {
3981
+ async function resolveFrom(from, signal, engine) {
2539
3982
  const pinned = /@(sha256:[0-9a-f]{64})$/.exec(from)?.[1];
2540
3983
  if (pinned) return {
2541
3984
  digest: pinned,
2542
3985
  local: false
2543
3986
  };
2544
- const remote = await docker([
2545
- "buildx",
2546
- "imagetools",
2547
- "inspect",
2548
- "--format",
2549
- "{{json .Manifest.Digest}}",
2550
- from
2551
- ], { signal }).catch(() => null);
2552
- const digest = remote?.exitCode === 0 ? JSON.parse(remote.stdout.toString("utf8").trim()) : null;
2553
- if (typeof digest === "string" && digest.startsWith("sha256:")) return {
2554
- digest,
2555
- local: false
2556
- };
2557
- const local = await imageInfo(from);
3987
+ let error = null;
3988
+ if (engine === "podman") {
3989
+ const remote = await podmanRemoteDigest(from, signal);
3990
+ if ("digest" in remote) return {
3991
+ digest: remote.digest,
3992
+ local: false
3993
+ };
3994
+ error = remote.error;
3995
+ } else {
3996
+ const remote = await docker([
3997
+ "buildx",
3998
+ "imagetools",
3999
+ "inspect",
4000
+ "--format",
4001
+ "{{json .Manifest.Digest}}",
4002
+ from
4003
+ ], { signal }).catch(() => null);
4004
+ const digest = remote?.exitCode === 0 ? JSON.parse(remote.stdout.toString("utf8").trim()) : null;
4005
+ if (typeof digest === "string" && digest.startsWith("sha256:")) return {
4006
+ digest,
4007
+ local: false
4008
+ };
4009
+ error = remote?.stderr.trim().replace(/^ERROR: /, "").replace(/\s+/g, " ") || null;
4010
+ }
4011
+ const local = await imageInfo(from, engine).catch(() => null);
2558
4012
  if (local) return {
2559
4013
  digest: local.id,
2560
4014
  local: true
2561
4015
  };
2562
- return { error: remote?.stderr.trim().replace(/^ERROR: /, "").replace(/\s+/g, " ") || `${from} doesn't resolve` };
4016
+ return { error: error || `${from} doesn't resolve` };
2563
4017
  }
2564
4018
  /** Removes a tag or an image reeval replaced, unless something still uses it. */
2565
- const removeQuietly = async (ref) => {
4019
+ const removeQuietly = async (ref, engine) => {
2566
4020
  await docker([
2567
4021
  "image",
2568
4022
  "rm",
2569
4023
  ref
2570
- ]).catch(() => {});
4024
+ ], { engine }).catch(() => {});
2571
4025
  };
2572
4026
  /** The hash of reeval's base image build context, which its images carry as a label. */
2573
4027
  function contextHash() {
@@ -2587,14 +4041,14 @@ function contextHash() {
2587
4041
  * intermediate `-base` tag of a `from` build, are removed once the new one is committed.
2588
4042
  */
2589
4043
  async function buildImage(log, options) {
2590
- const { harness, from, signal } = options;
2591
- const resolved = from ? await resolveFrom(from, signal) : null;
4044
+ const { harness, from, signal, engine } = options;
4045
+ const resolved = from ? await resolveFrom(from, signal, engine) : null;
2592
4046
  const digest = resolved && "digest" in resolved ? resolved.digest : null;
2593
4047
  const pinned = from && digest && resolved && "local" in resolved && !resolved.local && !from.includes("@") ? `${from}@${digest}` : from;
2594
4048
  const bootstrap = BOOTSTRAPS[harness];
2595
4049
  const base = from ? `${harnessImageFor(harness, from)}-base` : BASE_IMAGE;
2596
4050
  const target = from ? harnessImageFor(harness, from) : imageFor(harness);
2597
- const previous = [(await imageInfo(target))?.id, from ? null : (await imageInfo(base))?.id];
4051
+ const previous = [(await imageInfo(target, engine))?.id, from ? null : (await imageInfo(base, engine))?.id];
2598
4052
  log(`Building ${base}${from ? ` from ${from}` : ""}`);
2599
4053
  const build = from ? await docker([
2600
4054
  "build",
@@ -2607,7 +4061,8 @@ async function buildImage(log, options) {
2607
4061
  "-"
2608
4062
  ], {
2609
4063
  input: toolchainDockerfile(pinned ?? from),
2610
- signal
4064
+ signal,
4065
+ engine
2611
4066
  }) : await docker([
2612
4067
  "build",
2613
4068
  "--progress",
@@ -2620,20 +4075,25 @@ async function buildImage(log, options) {
2620
4075
  "--tag",
2621
4076
  base,
2622
4077
  DOCKER_CONTEXT
2623
- ], { signal });
4078
+ ], {
4079
+ signal,
4080
+ engine
4081
+ });
2624
4082
  const output = `${build.stdout.toString("utf8")}${build.stderr}`;
2625
4083
  options.output?.write(output);
2626
4084
  if (build.exitCode !== 0) throw buildError(output, {
2627
4085
  stage: from ? "from" : "harness",
2628
4086
  ref: target,
2629
4087
  headline: from ? `Building the toolchain layer FROM ${from}` : "Building reeval's base image",
2630
- log: options.output?.path ?? null
4088
+ log: options.output?.path ?? null,
4089
+ engine
2631
4090
  }, (parsed) => parsed.output.find((l) => l.startsWith("reeval needs a Debian")) ?? null);
2632
4091
  log(`Installing the ${bootstrap.name} harness bootstrap`);
2633
4092
  const session = await createDockerSession({
2634
4093
  image: base,
2635
4094
  lifetimeMs: 18e5,
2636
- ...signal ? { abortSignal: signal } : {}
4095
+ ...signal ? { abortSignal: signal } : {},
4096
+ ...engine ? { engine } : {}
2637
4097
  });
2638
4098
  let agentVersion;
2639
4099
  try {
@@ -2653,7 +4113,7 @@ async function buildImage(log, options) {
2653
4113
  "CMD [\"bash\"]",
2654
4114
  session.id,
2655
4115
  target
2656
- ]);
4116
+ ], { engine });
2657
4117
  } catch (error) {
2658
4118
  if (signal?.aborted || error instanceof ImageBuildError) throw error;
2659
4119
  const [first = "", ...rest] = error.message.split("\n");
@@ -2663,7 +4123,8 @@ async function buildImage(log, options) {
2663
4123
  headline: `Baking the ${bootstrap.name} CLI onto ${from ?? "reeval-sandbox-base:latest"} failed: ${clipLine(first)}`,
2664
4124
  cause,
2665
4125
  output: outputTail(rest.join("\n")),
2666
- log: options.output?.path ?? null
4126
+ log: options.output?.path ?? null,
4127
+ ...engine ? { engine } : {}
2667
4128
  }), {
2668
4129
  stage: "harness",
2669
4130
  ref: target,
@@ -2674,9 +4135,9 @@ async function buildImage(log, options) {
2674
4135
  } finally {
2675
4136
  await session.destroy();
2676
4137
  }
2677
- if (from) await removeQuietly(base);
2678
- const now = (await imageInfo(target))?.id;
2679
- for (const id of previous) if (id && id !== now) await removeQuietly(id);
4138
+ if (from) await removeQuietly(base, engine);
4139
+ const now = (await imageInfo(target, engine))?.id;
4140
+ for (const id of previous) if (id && id !== now) await removeQuietly(id, engine);
2680
4141
  return {
2681
4142
  image: target,
2682
4143
  agentVersion
@@ -2719,15 +4180,18 @@ function installScript(steps) {
2719
4180
  }
2720
4181
  /** Builds the install layer if it's missing. `output` gets the build's output, for a log file. */
2721
4182
  async function buildInstallLayer(parent, steps, options = {}) {
2722
- const { signal } = options;
4183
+ const { signal, engine } = options;
2723
4184
  const tag = installLayerTag(parent, steps);
2724
4185
  if ((await docker([
2725
4186
  "image",
2726
4187
  "inspect",
2727
4188
  "--format",
2728
- "{{.Id}}",
4189
+ "{{.Created}}",
2729
4190
  tag
2730
- ], { signal })).exitCode === 0) return tag;
4191
+ ], {
4192
+ signal,
4193
+ engine
4194
+ })).exitCode === 0) return tag;
2731
4195
  const script = installScript(steps);
2732
4196
  const encoded = Buffer.from(script).toString("base64");
2733
4197
  const home = `$(getent passwd ${SANDBOX_USER} | cut -d: -f6)`;
@@ -2750,7 +4214,8 @@ async function buildInstallLayer(parent, steps, options = {}) {
2750
4214
  "-"
2751
4215
  ], {
2752
4216
  input: dockerfile,
2753
- signal
4217
+ signal,
4218
+ engine
2754
4219
  });
2755
4220
  const output = `${build.stdout.toString("utf8")}${build.stderr}`;
2756
4221
  options.output?.write(`${script}\n${dockerfile}\n\n${output}`);
@@ -2760,7 +4225,8 @@ async function buildInstallLayer(parent, steps, options = {}) {
2760
4225
  stage: "install",
2761
4226
  ref: tag,
2762
4227
  headline: `Building the install layer (${`${steps.length} command${steps.length === 1 ? "" : "s"}`})`,
2763
- log: options.output?.path ?? null
4228
+ log: options.output?.path ?? null,
4229
+ engine
2764
4230
  }, () => failed ? `install ${failed[1]} exited ${failed[2]}: ${clipLine(failed[3] ?? "")}` : null, (line) => !line.startsWith("reeval: install "));
2765
4231
  }
2766
4232
  return tag;
@@ -2820,16 +4286,16 @@ function contextFiles(context, dockerfile) {
2820
4286
  return files.sort();
2821
4287
  }
2822
4288
  /** Whether the Dockerfile starts from reeval's sandbox image, which then has to exist first. */
2823
- const usesEsBase = (dockerfile) => new RegExp(`\\$\\{?${REEVAL_BASE_ARG}\\b`).test(readFileSync(dockerfile, "utf8"));
4289
+ const usesReevalBase = (dockerfile) => new RegExp(`\\$\\{?${REEVAL_BASE_ARG}\\b`).test(readFileSync(dockerfile, "utf8"));
2824
4290
  /**
2825
4291
  * The tag of a `docker({ dockerfile })` build for a harness: a hash of the Dockerfile, every file
2826
4292
  * of its build context (its directory, less `.dockerignore`) and, for a Dockerfile `FROM
2827
4293
  * ${REEVAL_BASE}`, the id of the harness's image it names, so an edit to any of them, or a rebuilt reeval
2828
- * image, builds anew. `esBase` is that id (null when it isn't built).
4294
+ * image, builds anew. `reevalBase` is that id (null when it isn't built).
2829
4295
  */
2830
- function dockerfileTag(dockerfile, harness, esBase = null) {
4296
+ function dockerfileTag(dockerfile, harness, reevalBase = null) {
2831
4297
  const context = dirname(dockerfile);
2832
- const base = usesEsBase(dockerfile) ? `${imageFor(harness)}@${esBase ?? "unbuilt"}` : "";
4298
+ const base = usesReevalBase(dockerfile) ? `${imageFor(harness)}@${reevalBase ?? "unbuilt"}` : "";
2833
4299
  const hash = createHash("sha256").update(`${REEVAL_BASE_ARG}=${base}\0`);
2834
4300
  for (const path of contextFiles(context, dockerfile)) {
2835
4301
  const full = join(context, path);
@@ -2846,14 +4312,14 @@ function dockerfileTag(dockerfile, harness, esBase = null) {
2846
4312
  }
2847
4313
  /**
2848
4314
  * Builds the user's Dockerfile with plain `docker build` (so Docker's layer cache applies), from
2849
- * its directory, with `REEVAL_BASE` set to the harness's sandbox image (whose id is `esBase`).
4315
+ * its directory, with `REEVAL_BASE` set to the harness's sandbox image (whose id is `reevalBase`).
2850
4316
  * Rebuilds even when the tag exists with `force`, as `reeval image build` does, and then removes the
2851
4317
  * image the tag pointed at before. `name` is the path failures name.
2852
4318
  */
2853
4319
  async function buildDockerfile(dockerfile, options) {
2854
- const { harness, signal } = options;
2855
- const { tag } = dockerfileTag(dockerfile, harness, options.esBase ?? null);
2856
- const previous = (await imageInfo(tag))?.id;
4320
+ const { harness, signal, engine } = options;
4321
+ const { tag } = dockerfileTag(dockerfile, harness, options.reevalBase ?? null);
4322
+ const previous = (await imageInfo(tag, engine))?.id;
2857
4323
  if (previous && !options.force) return tag;
2858
4324
  const build = await docker([
2859
4325
  "build",
@@ -2868,20 +4334,24 @@ async function buildDockerfile(dockerfile, options) {
2868
4334
  "--tag",
2869
4335
  tag,
2870
4336
  dirname(dockerfile)
2871
- ], { signal });
4337
+ ], {
4338
+ signal,
4339
+ engine
4340
+ });
2872
4341
  const output = `${build.stdout.toString("utf8")}${build.stderr}`;
2873
4342
  options.output?.write(output);
2874
4343
  if (build.exitCode !== 0) throw buildError(output, {
2875
4344
  stage: "dockerfile",
2876
4345
  ref: tag,
2877
4346
  headline: `Building ${options.name ?? dockerfile}`,
2878
- log: options.output?.path ?? null
4347
+ log: options.output?.path ?? null,
4348
+ engine
2879
4349
  });
2880
- const now = (await imageInfo(tag))?.id;
2881
- if (previous && previous !== now) await removeQuietly(previous);
4350
+ const now = (await imageInfo(tag, engine))?.id;
4351
+ if (previous && previous !== now) await removeQuietly(previous, engine);
2882
4352
  return tag;
2883
4353
  }
2884
4354
  //#endregion
2885
- export { onDockerCommand as $, hostAllowed as A, WORKSPACE_DIR as B, applyTransformations as C, HARNESS_HOSTS as D, DOCKER_EGRESS as E, HARNESS_PACKAGES as F, docker as G, harnessLabel as H, LABEL as I, dockerOk as J, dockerAvailable as K, SANDBOX_HOME as L, BASE_IMAGE as M, BRIDGE_PORT as N, PACKAGE_HOSTS as O, DEFAULT_IMAGE as P, removeContainerDetached as Q, SANDBOX_ROOT as R, placeholder as S, onEndpoint as T, imageFor as U, adapterVersion as V, isBakedHarness as W, imageInfo as X, dockerState as Y, isRegistryDigest as Z, ROOT_CAPABILITIES as _, buildInstallLayer as a, parseBuildOutput as at, CA_PATH as b, dockerfileTag as c, installLayerTag as d, ImageBuildError as et, installScript as f, DEFAULT_LIMITS as g, usesEsBase as h, buildImage as i, isTransient as it, BAKED_HARNESSES as j, defaultAllowedHosts as k, dockerignoreMatcher as l, resolveFrom as m, REEVAL_BASE_ARG as n, causeLine as nt, contextFiles as o, retryTransient as ot, pruneImages as p, dockerCapacity as q, buildDockerfile as r, failureCause as rt, contextHash as s, DOCKER_CONTEXT as t, RETRY_DELAYS as tt, harnessImageFor as u, createDockerSession as v, matches as w, PROXY_PORT as x, dockerSandboxProvider as y, SANDBOX_USER as z };
4355
+ export { removeContainerDetached as $, hostAllowed as A, WORKSPACE_DIR as B, applyTransformations as C, HARNESS_HOSTS as D, DOCKER_EGRESS as E, HARNESS_PACKAGES as F, docker as G, harnessLabel as H, LABEL as I, dockerOk as J, dockerAvailable as K, SANDBOX_HOME as L, BASE_IMAGE as M, BRIDGE_PORT as N, PACKAGE_HOSTS as O, DEFAULT_IMAGE as P, isRegistryDigest as Q, SANDBOX_ROOT as R, placeholder as S, onEndpoint as T, imageFor as U, adapterVersion as V, isBakedHarness as W, imageInfo as X, dockerState as Y, imageTags as Z, ROOT_CAPABILITIES as _, buildInstallLayer as a, causeLine as at, CA_PATH as b, dockerfileTag as c, parseBuildOutput as ct, installLayerTag as d, dockerSeccompFile as dt, onDockerCommand as et, installScript as f, engineSpec as ft, DEFAULT_LIMITS as g, usesReevalBase as h, buildImage as i, RETRY_DELAYS as it, BAKED_HARNESSES as j, defaultAllowedHosts as k, dockerignoreMatcher as l, retryTransient as lt, resolveFrom as m, REEVAL_BASE_ARG as n, shellQuote as nt, contextFiles as o, failureCause as ot, pruneImages as p, normalizeImageId as pt, dockerCapacity as q, buildDockerfile as r, ImageBuildError as rt, contextHash as s, isTransient as st, DOCKER_CONTEXT as t, run as tt, harnessImageFor as u, ENGINES as ut, createDockerSession as v, matches as w, PROXY_PORT as x, dockerSandboxProvider as y, SANDBOX_USER as z };
2886
4356
 
2887
- //# sourceMappingURL=src-8rRXy4u9.js.map
4357
+ //# sourceMappingURL=src-ftu5wPSt.js.map