@poe-platform/safe-bash 0.1.802 → 0.1.804

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 (748) hide show
  1. package/README.md +60 -33
  2. package/dist/image-ast/ast.d.ts +1 -0
  3. package/dist/image-ast/browser/ast.d.ts +1 -0
  4. package/dist/image-ast/browser/codecs/jpeg.d.ts +2 -2
  5. package/dist/image-ast/codecs/jpeg.d.ts +2 -2
  6. package/dist/image-ast/index.browser.js +692 -8355
  7. package/dist/image-ast/index.js +692 -8355
  8. package/dist/mp4-ast/codecs.d.ts +7 -2
  9. package/dist/safe-bash/chunks/{chunk-CHYGPFVM.js → chunk-22SX3F2R.js} +1 -1
  10. package/dist/safe-bash/chunks/{chunk-FBUCWVTE.js → chunk-2IVBJTBD.js} +1 -1
  11. package/dist/safe-bash/chunks/chunk-2POETUMB.js +190 -0
  12. package/dist/safe-bash/chunks/{chunk-XVOSKJE2.js → chunk-47D7WBJK.js} +1 -1
  13. package/dist/safe-bash/chunks/{chunk-VKNVHEX3.js → chunk-4ESI236Y.js} +1 -1
  14. package/dist/safe-bash/chunks/{chunk-74GHTNJA.js → chunk-4KTMKD5W.js} +1 -1
  15. package/dist/safe-bash/chunks/{chunk-55YJASTN.js → chunk-4T53AERN.js} +1 -1
  16. package/dist/safe-bash/chunks/{chunk-DQP3VHSB.js → chunk-5XIFJVOO.js} +1 -1
  17. package/dist/safe-bash/chunks/{chunk-NZQXYWA3.js → chunk-62BOHHJT.js} +1 -2
  18. package/dist/safe-bash/chunks/{chunk-HZAMGT5I.js → chunk-67WIFM3N.js} +17 -6
  19. package/dist/safe-bash/chunks/{chunk-4D4N7IU2.js → chunk-6LNFRPW5.js} +2 -2
  20. package/dist/safe-bash/chunks/{chunk-6O77NL2S.js → chunk-6SMICPI3.js} +1 -1
  21. package/dist/safe-bash/chunks/{chunk-4BSJLKNM.js → chunk-7O76UFQD.js} +1 -1
  22. package/dist/safe-bash/chunks/{chunk-44ALJ4QG.js → chunk-AW5KIT6V.js} +3549 -84
  23. package/dist/safe-bash/chunks/{chunk-RSTHLAF3.js → chunk-B2Z73HTZ.js} +52 -28
  24. package/dist/safe-bash/chunks/chunk-B3ZMOJVM.js +319 -0
  25. package/dist/safe-bash/chunks/{chunk-7ZBU7KYV.js → chunk-CFAWS3O4.js} +1 -1
  26. package/dist/safe-bash/chunks/{chunk-I5HZ4FGE.js → chunk-CL2FCTTO.js} +1 -1
  27. package/dist/safe-bash/chunks/{chunk-KDNSPLII.js → chunk-CTXNARJH.js} +2 -1
  28. package/dist/safe-bash/chunks/{chunk-TFIBK2GI.js → chunk-D5Q7NFWI.js} +1 -1
  29. package/dist/safe-bash/chunks/{chunk-OQRVVGR6.js → chunk-DSOOVZ6Q.js} +1 -1
  30. package/dist/safe-bash/chunks/{chunk-VTH3MLDU.js → chunk-DUTAG6ZD.js} +1 -1
  31. package/dist/safe-bash/chunks/{chunk-XAQMU6OY.js → chunk-EE5YGFIZ.js} +1 -1
  32. package/dist/safe-bash/chunks/{chunk-FZE4HW6G.js → chunk-EJOYT2ME.js} +1 -1
  33. package/dist/safe-bash/chunks/chunk-FAAIR6EJ.js +887 -0
  34. package/dist/safe-bash/chunks/{chunk-OV6IHKO6.js → chunk-FOB2FZR4.js} +2 -2
  35. package/dist/safe-bash/chunks/chunk-G6V4RRSQ.js +14 -0
  36. package/dist/safe-bash/chunks/{chunk-UTBUUFDM.js → chunk-GGQAGQXQ.js} +1 -1
  37. package/dist/safe-bash/chunks/{chunk-K6VCD7IY.js → chunk-HIIYIJ5G.js} +2 -4
  38. package/dist/safe-bash/chunks/chunk-IOHH2GTI.js +56 -0
  39. package/dist/safe-bash/chunks/{chunk-CTVWDACF.js → chunk-IQW34XQT.js} +1 -1
  40. package/dist/safe-bash/chunks/{chunk-HZ7BWKQ3.js → chunk-IS572AAT.js} +1 -1
  41. package/dist/safe-bash/chunks/{chunk-AUSNDQTJ.js → chunk-JPSUHHOA.js} +1 -1
  42. package/dist/safe-bash/chunks/{chunk-ZVD5IS4V.js → chunk-KBZ4UB2O.js} +2 -2
  43. package/dist/safe-bash/chunks/{chunk-AM5ESLPH.js → chunk-KU5CVWKA.js} +1 -1
  44. package/dist/safe-bash/chunks/{chunk-NQCM3TYR.js → chunk-LPOVNKNB.js} +225 -176
  45. package/dist/safe-bash/chunks/{chunk-46Z5E5EV.js → chunk-MBOC3LZ4.js} +1 -1
  46. package/dist/safe-bash/chunks/{chunk-6PAVEFT3.js → chunk-N4BQFD3P.js} +1 -1
  47. package/dist/safe-bash/chunks/{chunk-CS4MNM6I.js → chunk-NGKCVNWS.js} +1 -1
  48. package/dist/safe-bash/chunks/{chunk-7R5BDCG7.js → chunk-OHML2BEU.js} +1 -1
  49. package/dist/safe-bash/chunks/{chunk-C5OWC2TL.js → chunk-OQ3AGYCZ.js} +1 -1
  50. package/dist/safe-bash/chunks/{chunk-B7TAL7S5.js → chunk-PTAEWLSE.js} +0 -2
  51. package/dist/safe-bash/chunks/{chunk-LVOBFF4D.js → chunk-Q4FNLOTI.js} +1 -1
  52. package/dist/safe-bash/chunks/chunk-Q5XO3NAS.js +1036 -0
  53. package/dist/safe-bash/chunks/{chunk-GEG3BWGE.js → chunk-RHFRJIWQ.js} +1 -1
  54. package/dist/safe-bash/chunks/chunk-RUR6J33T.js +11 -0
  55. package/dist/safe-bash/chunks/{chunk-WDLGKIHD.js → chunk-S4RFUUXO.js} +841 -26
  56. package/dist/safe-bash/chunks/{chunk-RRR7AQ24.js → chunk-SD2ISU5L.js} +1 -1
  57. package/dist/safe-bash/chunks/{chunk-3NDIFSNM.js → chunk-SUJ3NTMH.js} +3 -3
  58. package/dist/safe-bash/chunks/{chunk-R3NAKOED.js → chunk-SZRUU5HS.js} +2 -2
  59. package/dist/safe-bash/chunks/{chunk-PH63PLPZ.js → chunk-TC3F4UFF.js} +1 -1
  60. package/dist/safe-bash/chunks/{chunk-3R3AANOR.js → chunk-TCKYOLUE.js} +1 -1
  61. package/dist/safe-bash/chunks/{chunk-D3ANYGMC.js → chunk-UV4X32QU.js} +1 -1
  62. package/dist/safe-bash/chunks/{chunk-E7OYNDGL.js → chunk-V7QT2RWC.js} +1 -1
  63. package/dist/safe-bash/chunks/{chunk-SHEMU2Z7.js → chunk-W2IYOVHK.js} +839 -1211
  64. package/dist/safe-bash/chunks/{chunk-3HQU4OJO.js → chunk-XNGVOSGI.js} +1 -1
  65. package/dist/safe-bash/chunks/{chunk-J42RIHHJ.js → chunk-XQWCQSRN.js} +1 -1
  66. package/dist/safe-bash/chunks/{chunk-BJA5XNP6.js → chunk-Y7FW6GLT.js} +6 -6
  67. package/dist/safe-bash/chunks/{chunk-QGUV42T5.js → chunk-YL3GBUG4.js} +1 -1
  68. package/dist/safe-bash/chunks/chunk-YOXUCJER.js +389 -0
  69. package/dist/safe-bash/chunks/{chunk-HBCN24ZA.js → chunk-Z2AAYYJN.js} +2 -2
  70. package/dist/safe-bash/chunks/chunk-ZKYKJCZZ.js +30 -0
  71. package/dist/safe-bash/chunks/core-IE3AFIDX.js +85806 -0
  72. package/dist/safe-bash/chunks/{ffmpeg-WTC3TEFI.js → ffmpeg-YANDK6HU.js} +2 -2
  73. package/dist/safe-bash/chunks/{gh-6WU6PXL4.js → gh-4MBJ2S5V.js} +2 -2
  74. package/dist/safe-bash/chunks/{git-EFZIGJW4.js → git-2QONJNRQ.js} +2 -2
  75. package/dist/safe-bash/chunks/{imagemagick-EIEYGWPF.js → imagemagick-JLEHGYSN.js} +2 -2
  76. package/dist/safe-bash/chunks/{mmdc-ROQJT5HQ.js → mmdc-6LD7A6ND.js} +2 -2
  77. package/dist/safe-bash/chunks/{pdfimages-DW7LWXFI.js → pdfimages-RSHL7LOP.js} +2 -2
  78. package/dist/safe-bash/chunks/{pdfinfo-TIP6XLUQ.js → pdfinfo-L3SGWPNG.js} +2 -2
  79. package/dist/safe-bash/chunks/{pdftk-DMG22ITZ.js → pdftk-LFBJNU5A.js} +2 -2
  80. package/dist/safe-bash/chunks/{pdftoppm-WNDYR72T.js → pdftoppm-NXXFUIHG.js} +2 -2
  81. package/dist/safe-bash/chunks/{pdftotext-5IPZ4NI7.js → pdftotext-4IHNWT6F.js} +2 -2
  82. package/dist/safe-bash/chunks/{qpdf-TTX2DIUA.js → qpdf-ZEIREV63.js} +2 -2
  83. package/dist/safe-bash/chunks/read-builtin-A4QKAT45.js +9 -0
  84. package/dist/safe-bash/chunks/{sips-XYS46JPJ.js → sips-D5YBG2V3.js} +2 -2
  85. package/dist/safe-bash/chunks/{soffice-TU73E5KL.js → soffice-RAJU3JUT.js} +2 -2
  86. package/dist/safe-bash/chunks/source-files-3XWRRHFA.js +7 -0
  87. package/dist/safe-bash/chunks/{wkhtmltopdf-FSZ2CHGE.js → wkhtmltopdf-7UE4FORZ.js} +2 -2
  88. package/dist/safe-bash/command-chunks/{chunk-7KWZXKY6.js → chunk-26RTBV2I.js} +1 -0
  89. package/dist/safe-bash/command-chunks/{chunk-AQJ2ROJO.js → chunk-2WYNMZR2.js} +10 -8
  90. package/dist/safe-bash/command-chunks/{chunk-BDSMROQZ.js → chunk-36GFRF2N.js} +2 -1
  91. package/dist/safe-bash/command-chunks/{chunk-GC5TJZOF.js → chunk-3VIA2IA7.js} +114 -31
  92. package/dist/safe-bash/command-chunks/{chunk-NKFYQSES.js → chunk-4CTI3ZTX.js} +1 -0
  93. package/dist/safe-bash/command-chunks/{chunk-WH627NJL.js → chunk-4MYP2FX4.js} +2 -1
  94. package/dist/safe-bash/command-chunks/chunk-4R5ADJM5.js +178 -0
  95. package/dist/safe-bash/command-chunks/{chunk-P2N33UMN.js → chunk-5MIKM54M.js} +4 -4
  96. package/dist/safe-bash/command-chunks/{chunk-DB453IE6.js → chunk-6FZQUOSJ.js} +1 -1
  97. package/dist/safe-bash/command-chunks/{chunk-WPYIOKE3.js → chunk-6GKYHPJG.js} +2 -2
  98. package/dist/safe-bash/command-chunks/{chunk-7K6JYKPJ.js → chunk-6M2ELGEN.js} +17 -15
  99. package/dist/safe-bash/command-chunks/{chunk-PXEIT2O4.js → chunk-6UR7V3ET.js} +8 -1
  100. package/dist/safe-bash/command-chunks/{chunk-6KJ3LPI2.js → chunk-6XBS5B46.js} +26 -3
  101. package/dist/safe-bash/command-chunks/{chunk-5PWJG2UK.js → chunk-6YXLZX7L.js} +2 -2
  102. package/dist/safe-bash/command-chunks/{chunk-EK6YNAXT.js → chunk-753YOR54.js} +31 -5
  103. package/dist/safe-bash/command-chunks/{chunk-RMWQAAO5.js → chunk-7IR4NRNE.js} +2 -2
  104. package/dist/safe-bash/command-chunks/{chunk-FZTK4MFI.js → chunk-7NM73SVK.js} +8 -8
  105. package/dist/safe-bash/command-chunks/{chunk-NXEQ3ESQ.js → chunk-7QD5YY4F.js} +6 -11
  106. package/dist/safe-bash/command-chunks/{chunk-EMPU65ZK.js → chunk-A5LBSJGH.js} +1 -0
  107. package/dist/safe-bash/command-chunks/chunk-A7MU7762.js +200 -0
  108. package/dist/safe-bash/command-chunks/{chunk-ORYGZYKW.js → chunk-ARZMP2L2.js} +3 -3
  109. package/dist/safe-bash/command-chunks/{chunk-OQKC5ZU2.js → chunk-BAKFZ477.js} +62 -20
  110. package/dist/safe-bash/command-chunks/{chunk-QRRYN2KO.js → chunk-BC7BK6R6.js} +0 -2424
  111. package/dist/safe-bash/command-chunks/{chunk-F4TEEZTL.js → chunk-BOEOJS2Q.js} +1 -1
  112. package/dist/safe-bash/command-chunks/{chunk-XS72HTMA.js → chunk-BWGGLYEB.js} +5 -22
  113. package/dist/safe-bash/command-chunks/{chunk-PMBFZXTK.js → chunk-C5ZZKP7V.js} +1 -1
  114. package/dist/safe-bash/command-chunks/{chunk-LHIOAFWW.js → chunk-C7SEB6WU.js} +1 -1
  115. package/dist/safe-bash/command-chunks/{chunk-XPT2UGBF.js → chunk-CHJKFRT7.js} +1 -1
  116. package/dist/safe-bash/command-chunks/{chunk-TIOCQVUQ.js → chunk-CON26Q2O.js} +1 -1
  117. package/dist/safe-bash/command-chunks/{chunk-E55UKBIE.js → chunk-DBAT3IK2.js} +1 -1
  118. package/dist/safe-bash/command-chunks/{chunk-Z45N42QC.js → chunk-DPAYAVMS.js} +15 -1
  119. package/dist/safe-bash/command-chunks/chunk-DS3NXVUM.js +368 -0
  120. package/dist/safe-bash/command-chunks/{chunk-5ZMZ573Q.js → chunk-DSJ3VRL3.js} +16 -4
  121. package/dist/safe-bash/command-chunks/{chunk-K2GDEMEU.js → chunk-EFRCFWVR.js} +4 -4
  122. package/dist/safe-bash/command-chunks/{chunk-DZCY63VJ.js → chunk-EV6HIJ5H.js} +6 -5
  123. package/dist/safe-bash/command-chunks/{chunk-JDYXY44P.js → chunk-FJURV46Y.js} +3 -3
  124. package/dist/safe-bash/command-chunks/{chunk-TZZ4WUKH.js → chunk-FZAWGKSE.js} +6 -4
  125. package/dist/safe-bash/command-chunks/{chunk-YHFXOX6U.js → chunk-GOCFQ6XV.js} +4 -4
  126. package/dist/safe-bash/command-chunks/{chunk-YOFC45RK.js → chunk-HH5O7DJI.js} +1 -1
  127. package/dist/safe-bash/command-chunks/{chunk-3HHCU5YU.js → chunk-HK7F5SDC.js} +13 -0
  128. package/dist/safe-bash/command-chunks/{chunk-JNZ3CVAE.js → chunk-HQBXIZC7.js} +8 -3
  129. package/dist/safe-bash/command-chunks/{chunk-2JRBIDAD.js → chunk-I63DBZXZ.js} +2 -2
  130. package/dist/safe-bash/command-chunks/{chunk-WNE7FPVR.js → chunk-I64TLTIW.js} +24 -16
  131. package/dist/safe-bash/command-chunks/{chunk-QKFSRZGQ.js → chunk-ICANWOXH.js} +7 -31
  132. package/dist/safe-bash/command-chunks/{chunk-SQRQW3CT.js → chunk-IJ6LGLXM.js} +1 -1
  133. package/dist/safe-bash/command-chunks/{chunk-5E4WAO4O.js → chunk-JD5QNRNO.js} +3 -3
  134. package/dist/safe-bash/command-chunks/{chunk-KJIMDLBB.js → chunk-JNANXVJV.js} +1 -1
  135. package/dist/safe-bash/command-chunks/{chunk-TGSNCQSR.js → chunk-JT4RYCA6.js} +1771 -1663
  136. package/dist/safe-bash/command-chunks/{chunk-II77KPZN.js → chunk-JWW6FYBN.js} +2 -2
  137. package/dist/safe-bash/command-chunks/{chunk-ZYXH3B66.js → chunk-LCJWKTCJ.js} +250 -203
  138. package/dist/safe-bash/command-chunks/{chunk-I237SNW5.js → chunk-LFJJQQND.js} +1 -1
  139. package/dist/safe-bash/command-chunks/chunk-LU4HBPP2.js +97 -0
  140. package/dist/safe-bash/command-chunks/{chunk-XJXU3VVH.js → chunk-LWOE65OE.js} +20 -5
  141. package/dist/safe-bash/command-chunks/{chunk-GMIHJYDG.js → chunk-M32HFSX7.js} +22 -6
  142. package/dist/safe-bash/command-chunks/{chunk-YG4EPFWC.js → chunk-M3NINRDU.js} +2880 -172
  143. package/dist/safe-bash/command-chunks/chunk-MQREDAL6.js +164 -0
  144. package/dist/safe-bash/command-chunks/{chunk-LWS62ISU.js → chunk-N6DIASO2.js} +1 -1
  145. package/dist/safe-bash/command-chunks/chunk-NGL7YK7O.js +188 -0
  146. package/dist/safe-bash/command-chunks/{chunk-PEF7K3UQ.js → chunk-NJYHWKIL.js} +40 -10
  147. package/dist/safe-bash/command-chunks/{chunk-VXSLJH7G.js → chunk-OJQRSCBP.js} +27 -7
  148. package/dist/safe-bash/command-chunks/{chunk-OQU6UT6X.js → chunk-OV3XREFN.js} +11 -0
  149. package/dist/safe-bash/command-chunks/{chunk-MIXBO6U7.js → chunk-PTZLF456.js} +2 -2
  150. package/dist/safe-bash/command-chunks/{chunk-ALDC4XP4.js → chunk-QILLRNES.js} +34 -10
  151. package/dist/safe-bash/command-chunks/{chunk-L22T3H7L.js → chunk-QR25JLKO.js} +1 -1
  152. package/dist/safe-bash/command-chunks/{chunk-7U7EXOXX.js → chunk-R7C4MGZ5.js} +17 -223
  153. package/dist/safe-bash/command-chunks/{chunk-LCF3OB7P.js → chunk-RBME3JEH.js} +1 -1
  154. package/dist/safe-bash/command-chunks/{chunk-2KG2QLJE.js → chunk-RFWGYT7G.js} +3 -0
  155. package/dist/safe-bash/command-chunks/{chunk-5TBUOBDE.js → chunk-RZMVRT26.js} +27 -13
  156. package/dist/safe-bash/command-chunks/chunk-TFR6B3WB.js +44 -0
  157. package/dist/safe-bash/command-chunks/chunk-TOH3OF3O.js +179 -0
  158. package/dist/safe-bash/command-chunks/{chunk-VGG2DL5Q.js → chunk-TRR4MYWF.js} +4 -0
  159. package/dist/safe-bash/command-chunks/chunk-TT4DAFBT.js +13621 -0
  160. package/dist/safe-bash/command-chunks/{chunk-LWSBAWLT.js → chunk-TXI64OAG.js} +1 -1
  161. package/dist/safe-bash/command-chunks/chunk-TZRI7BJZ.js +496 -0
  162. package/dist/safe-bash/command-chunks/{chunk-QOKBZFFD.js → chunk-U3MMODA5.js} +2 -7
  163. package/dist/safe-bash/command-chunks/{chunk-ZYHTWNAE.js → chunk-UAW423ZL.js} +11 -11
  164. package/dist/safe-bash/command-chunks/{chunk-C5YYCQHW.js → chunk-UXEEUGOV.js} +222 -12
  165. package/dist/safe-bash/command-chunks/{chunk-GY3BWK7K.js → chunk-VOZPMJRX.js} +87 -80
  166. package/dist/safe-bash/command-chunks/{chunk-MQFIPHIQ.js → chunk-WPANOB4A.js} +38 -35
  167. package/dist/safe-bash/command-chunks/{chunk-Y2WBSJG6.js → chunk-X4QZQI5Q.js} +65 -64
  168. package/dist/safe-bash/command-chunks/{chunk-FPVUD6TH.js → chunk-XGI57GCN.js} +10 -8
  169. package/dist/safe-bash/command-chunks/{chunk-5UBXNSFZ.js → chunk-XUCU7QQT.js} +1281 -1278
  170. package/dist/safe-bash/command-chunks/chunk-Y22VXJBD.js +296 -0
  171. package/dist/safe-bash/command-chunks/{chunk-WVHONVZ4.js → chunk-YMFUUPDX.js} +5 -3
  172. package/dist/safe-bash/command-chunks/{chunk-IR2BY7EL.js → chunk-YYGIBXFZ.js} +2 -2
  173. package/dist/safe-bash/command-chunks/{chunk-MSFXC3OC.js → chunk-Z4FO6OHE.js} +2 -2
  174. package/dist/safe-bash/command-chunks/{chunk-6GWJUQAV.js → chunk-Z5ZZVDUD.js} +181 -133
  175. package/dist/safe-bash/command-chunks/{chunk-W5DNF4JH.js → chunk-ZHN3QDCI.js} +1 -1
  176. package/dist/safe-bash/commands/alias/index.d.ts +2 -0
  177. package/dist/safe-bash/commands/alias/index.js +2 -0
  178. package/dist/safe-bash/commands/apply-patch/index.browser.js +2 -3
  179. package/dist/safe-bash/commands/apply-patch/index.d.ts +0 -1
  180. package/dist/safe-bash/commands/apply-patch/index.js +0 -1
  181. package/dist/safe-bash/commands/archive/index.browser.js +2 -3
  182. package/dist/safe-bash/commands/archive/index.d.ts +0 -1
  183. package/dist/safe-bash/commands/archive/index.js +0 -1
  184. package/dist/safe-bash/commands/bytes/compression/index.js +54 -51
  185. package/dist/safe-bash/commands/bytes/index.js +2 -1
  186. package/dist/safe-bash/commands/chmod/index.browser.js +14 -0
  187. package/dist/safe-bash/commands/chmod/index.d.ts +2 -0
  188. package/dist/safe-bash/commands/chmod/index.js +2 -0
  189. package/dist/safe-bash/commands/column/index.browser.js +2 -3
  190. package/dist/safe-bash/commands/column/index.d.ts +0 -1
  191. package/dist/safe-bash/commands/column/index.js +0 -1
  192. package/dist/safe-bash/commands/copy-source.js +1 -0
  193. package/dist/safe-bash/commands/csplit/index.browser.js +2 -2
  194. package/dist/safe-bash/commands/csvkit/index.browser.js +72 -0
  195. package/dist/safe-bash/commands/csvkit/index.d.ts +0 -5
  196. package/dist/safe-bash/commands/csvkit/index.js +0 -50
  197. package/dist/safe-bash/commands/docx/index.browser.js +5 -7
  198. package/dist/safe-bash/commands/du/index.browser.js +2 -3
  199. package/dist/safe-bash/commands/du/index.d.ts +0 -1
  200. package/dist/safe-bash/commands/du/index.js +0 -1
  201. package/dist/safe-bash/commands/expr/index.browser.js +2 -3
  202. package/dist/safe-bash/commands/expr/index.d.ts +0 -1
  203. package/dist/safe-bash/commands/expr/index.js +0 -1
  204. package/dist/safe-bash/commands/factor/index.browser.js +2 -2
  205. package/dist/safe-bash/commands/file/index.browser.js +2 -3
  206. package/dist/safe-bash/commands/file/index.d.ts +0 -1
  207. package/dist/safe-bash/commands/file/index.js +0 -1
  208. package/dist/safe-bash/commands/filesystem.js +1 -1
  209. package/dist/safe-bash/commands/getopt/index.browser.js +2 -2
  210. package/dist/safe-bash/commands/grep-aliases/index.browser.js +3 -3
  211. package/dist/safe-bash/commands/hexdump/index.browser.js +2 -2
  212. package/dist/safe-bash/commands/html-to-markdown/index.browser.js +2 -3
  213. package/dist/safe-bash/commands/html-to-markdown/index.d.ts +0 -1
  214. package/dist/safe-bash/commands/html-to-markdown/index.js +0 -1
  215. package/dist/safe-bash/commands/htmlq/index.d.ts +1 -5
  216. package/dist/safe-bash/commands/htmlq/index.js +1 -143
  217. package/dist/safe-bash/commands/iconv/index.browser.js +2 -2
  218. package/dist/safe-bash/commands/line-endings/index.browser.js +2 -2
  219. package/dist/safe-bash/commands/llm/index.browser.js +2 -2
  220. package/dist/safe-bash/commands/llm/providers/index.browser.js +1 -1
  221. package/dist/safe-bash/commands/mdq/index.browser.js +3 -3
  222. package/dist/safe-bash/commands/media/index.browser.js +4 -16314
  223. package/dist/safe-bash/commands/media/index.d.ts +1 -5
  224. package/dist/safe-bash/commands/media/index.js +1 -3
  225. package/dist/safe-bash/commands/media/plugin.d.ts +1 -18
  226. package/dist/safe-bash/commands/media/plugin.js +1 -90
  227. package/dist/safe-bash/commands/media/remote.d.ts +1 -63
  228. package/dist/safe-bash/commands/media/remote.js +1 -405
  229. package/dist/safe-bash/commands/media/settings.d.ts +1 -4
  230. package/dist/safe-bash/commands/media/settings.js +1 -26
  231. package/dist/safe-bash/commands/metadata/chmod.d.ts +1 -7
  232. package/dist/safe-bash/commands/metadata/chmod.js +1 -204
  233. package/dist/safe-bash/commands/metadata/index.browser.js +3 -8
  234. package/dist/safe-bash/commands/metadata/index.d.ts +0 -1
  235. package/dist/safe-bash/commands/metadata/index.js +2 -2
  236. package/dist/safe-bash/commands/metadata/internal.d.ts +1 -30
  237. package/dist/safe-bash/commands/metadata/internal.js +1 -76
  238. package/dist/safe-bash/commands/metadata/mktemp.d.ts +1 -3
  239. package/dist/safe-bash/commands/metadata/mktemp.js +1 -202
  240. package/dist/safe-bash/commands/metadata/stat.d.ts +1 -7
  241. package/dist/safe-bash/commands/metadata/stat.js +1 -530
  242. package/dist/safe-bash/commands/mktemp/index.browser.js +13 -0
  243. package/dist/safe-bash/commands/mktemp/index.d.ts +2 -0
  244. package/dist/safe-bash/commands/mktemp/index.js +2 -0
  245. package/dist/safe-bash/commands/network/curl.js +1 -3
  246. package/dist/safe-bash/commands/network/index.browser.js +3 -4
  247. package/dist/safe-bash/commands/network/public.d.ts +0 -1
  248. package/dist/safe-bash/commands/network/public.js +0 -1
  249. package/dist/safe-bash/commands/network/transport.js +2 -1
  250. package/dist/safe-bash/commands/network/wget.js +1 -3
  251. package/dist/safe-bash/commands/node/browser.d.ts +0 -1
  252. package/dist/safe-bash/commands/node/browser.js +0 -1
  253. package/dist/safe-bash/commands/node/default-runtime.d.ts +3 -0
  254. package/dist/safe-bash/commands/node/default-runtime.js +15 -0
  255. package/dist/safe-bash/commands/node/index.browser.js +7 -8
  256. package/dist/safe-bash/commands/node/index.js +3 -3
  257. package/dist/safe-bash/commands/node/path.js +1 -1
  258. package/dist/safe-bash/commands/node/preload.d.ts +1 -1
  259. package/dist/safe-bash/commands/node/preload.js +4 -1
  260. package/dist/safe-bash/commands/node/quickjs.d.ts +2 -0
  261. package/dist/safe-bash/commands/node/quickjs.js +2 -0
  262. package/dist/safe-bash/commands/node/safejs.js +26 -12
  263. package/dist/safe-bash/commands/op/index.browser.js +2 -3
  264. package/dist/safe-bash/commands/op/index.d.ts +0 -11
  265. package/dist/safe-bash/commands/op/index.js +0 -84
  266. package/dist/safe-bash/commands/pandoc/index.browser.js +44 -0
  267. package/dist/safe-bash/commands/pandoc/index.d.ts +0 -1
  268. package/dist/safe-bash/commands/pandoc/index.js +0 -1
  269. package/dist/safe-bash/commands/portable-random.d.ts +1 -1
  270. package/dist/safe-bash/commands/portable-random.js +1 -12
  271. package/dist/safe-bash/commands/pr/index.browser.js +2 -2
  272. package/dist/safe-bash/commands/python/docker-runner.js +4 -3
  273. package/dist/safe-bash/commands/python/docker.d.ts +1 -0
  274. package/dist/safe-bash/commands/python/docker.js +5 -2
  275. package/dist/safe-bash/commands/python/index.browser.js +17 -13
  276. package/dist/safe-bash/commands/python/index.d.ts +2 -1
  277. package/dist/safe-bash/commands/python/index.js +10 -8
  278. package/dist/safe-bash/commands/python/llm-capability.js +65 -2
  279. package/dist/safe-bash/commands/python/llm-dependencies.d.ts +27 -0
  280. package/dist/safe-bash/commands/python/llm-dependencies.js +66 -0
  281. package/dist/safe-bash/commands/python/llm-module.js +6 -4
  282. package/dist/safe-bash/commands/python/llm-reference-module.d.ts +3 -0
  283. package/dist/safe-bash/commands/python/llm-reference-module.js +690 -0
  284. package/dist/safe-bash/commands/python/worker.browser.js +2 -3
  285. package/dist/safe-bash/commands/python/worker.d.ts +0 -1
  286. package/dist/safe-bash/commands/python/worker.js +0 -1
  287. package/dist/safe-bash/commands/regex-execution/ere/transport/wire-engine.d.ts +1 -1
  288. package/dist/safe-bash/commands/regex-execution/ere/transport/wire-engine.js +3 -3
  289. package/dist/safe-bash/commands/regex-execution/public.browser.js +7 -7
  290. package/dist/safe-bash/commands/safejs/options.js +5 -1
  291. package/dist/safe-bash/commands/safejs/runtime.d.ts +1 -0
  292. package/dist/safe-bash/commands/safejs/runtime.js +1 -1
  293. package/dist/safe-bash/commands/split/index.browser.js +2 -3
  294. package/dist/safe-bash/commands/split/index.d.ts +0 -1
  295. package/dist/safe-bash/commands/split/index.js +0 -1
  296. package/dist/safe-bash/commands/ssconvert/index.browser.js +98 -0
  297. package/dist/safe-bash/commands/stat/index.browser.js +13 -0
  298. package/dist/safe-bash/commands/stat/index.d.ts +2 -0
  299. package/dist/safe-bash/commands/stat/index.js +2 -0
  300. package/dist/safe-bash/commands/stream-format/index.browser.js +3 -4
  301. package/dist/safe-bash/commands/stream-format/index.d.ts +0 -1
  302. package/dist/safe-bash/commands/stream-format/index.js +0 -1
  303. package/dist/safe-bash/commands/stream-inspection/index.browser.js +3 -4
  304. package/dist/safe-bash/commands/stream-inspection/index.d.ts +0 -1
  305. package/dist/safe-bash/commands/stream-inspection/index.js +0 -1
  306. package/dist/safe-bash/commands/streams.js +2 -1
  307. package/dist/safe-bash/commands/table-text/index.browser.js +3 -4
  308. package/dist/safe-bash/commands/table-text/index.d.ts +0 -1
  309. package/dist/safe-bash/commands/table-text/index.js +0 -1
  310. package/dist/safe-bash/commands/text.js +74 -34
  311. package/dist/safe-bash/commands/time-env/index.browser.js +3 -4
  312. package/dist/safe-bash/commands/time-env/index.d.ts +0 -1
  313. package/dist/safe-bash/commands/time-env/index.js +0 -1
  314. package/dist/safe-bash/commands/tree/index.browser.js +2 -3
  315. package/dist/safe-bash/commands/tree/index.d.ts +0 -1
  316. package/dist/safe-bash/commands/tree/index.js +0 -1
  317. package/dist/safe-bash/commands/tsort/index.browser.js +2 -2
  318. package/dist/safe-bash/commands/unalias/index.d.ts +2 -0
  319. package/dist/safe-bash/commands/unalias/index.js +2 -0
  320. package/dist/safe-bash/commands/xml/index.browser.js +2 -2
  321. package/dist/safe-bash/commands/yq/index.browser.js +2 -2
  322. package/dist/safe-bash/core.browser.js +2 -2
  323. package/dist/safe-bash/core.d.ts +7 -1
  324. package/dist/safe-bash/core.js +7 -1
  325. package/dist/safe-bash/execution-runtime.js +2 -1
  326. package/dist/safe-bash/fs/s3/http/index.d.ts +2 -2
  327. package/dist/safe-bash/fs/s3/http/index.js +1 -1
  328. package/dist/safe-bash/full-core.browser.js +254 -916
  329. package/dist/safe-bash/internal/op/types.d.ts +1 -0
  330. package/dist/safe-bash/jobs.browser.js +5 -5
  331. package/dist/safe-bash/lazy-optional.d.ts +3 -3
  332. package/dist/safe-bash/lazy-optional.js +1 -1
  333. package/dist/safe-bash/opt-in/commands/cmp/index.js +7 -6
  334. package/dist/safe-bash/opt-in/commands/dd/index.js +1 -1
  335. package/dist/safe-bash/opt-in/commands/dd/io.js +51 -5
  336. package/dist/safe-bash/opt-in/commands/truncate/index.js +2 -2
  337. package/dist/safe-bash/opt-in/commands/yq/native-work.js +3 -0
  338. package/dist/safe-bash/opt-in/optional/commands/shuf/input.js +2 -1
  339. package/dist/safe-bash/opt-in/optional/commands/shuf/shuf.js +4 -2
  340. package/dist/safe-bash/opt-in/optional.d.ts +1 -1
  341. package/dist/safe-bash/opt-in/optional.js +1 -1
  342. package/dist/safe-bash/opt-in/shell/extensions/read/index.js +2 -344
  343. package/dist/safe-bash/optional-host.browser.js +19 -14
  344. package/dist/safe-bash/optional-host.d.ts +1 -0
  345. package/dist/safe-bash/optional-host.js +1 -0
  346. package/dist/safe-bash/playwright/controller.js +41 -3
  347. package/dist/safe-bash/playwright/native-storage-targets.js +4 -2
  348. package/dist/safe-bash/plugins/base.d.ts +1 -1
  349. package/dist/safe-bash/plugins/base.js +3 -3
  350. package/dist/safe-bash/plugins/composition.d.ts +5 -2
  351. package/dist/safe-bash/plugins/composition.js +10 -7
  352. package/dist/safe-bash/plugins/index.browser.js +44 -41
  353. package/dist/safe-bash/plugins/index.js +3 -2
  354. package/dist/safe-bash/plugins/portable-commands.d.ts +3 -0
  355. package/dist/safe-bash/plugins/portable-commands.js +31 -0
  356. package/dist/safe-bash/registry-entry.browser.js +41 -42
  357. package/dist/safe-bash/search.browser.js +32 -33
  358. package/dist/safe-bash/shell/arithmetic.js +19 -6
  359. package/dist/safe-bash/shell/arrays/state.js +1 -1
  360. package/dist/safe-bash/shell/arrays/syntax.js +4 -3
  361. package/dist/safe-bash/shell/index.d.ts +0 -1
  362. package/dist/safe-bash/shell/index.js +0 -1
  363. package/dist/safe-bash/shell/parser.d.ts +2 -2
  364. package/dist/safe-bash/shell/parser.js +268 -64
  365. package/dist/safe-bash/shell/read-builtin.d.ts +3 -0
  366. package/dist/safe-bash/shell/read-builtin.js +344 -0
  367. package/dist/safe-bash/shell/runtime.d.ts +24 -4
  368. package/dist/safe-bash/shell/runtime.js +392 -414
  369. package/dist/safe-bash/shell/session-state.js +25 -0
  370. package/dist/safe-bash/shell/shell.js +76 -154
  371. package/dist/safe-bash/shell/tilde-expansion.d.ts +1 -1
  372. package/dist/safe-bash/shell/tilde-expansion.js +2 -2
  373. package/dist/safe-bash/shell/types.d.ts +7 -0
  374. package/dist/safe-bash/shell/value-state.js +1 -1
  375. package/dist/safe-bash/shell/worker-limits.js +1 -0
  376. package/dist/safe-bash/shell-entry.browser.js +32 -33
  377. package/dist/safe-bash/trap.browser.js +4 -4
  378. package/dist/safe-bash/worker/host.js +1 -1
  379. package/dist/safe-bash/yq-browser/index.js +1 -1
  380. package/dist/safe-bash-calendar-engine/time-env/calendar.d.ts +1 -1
  381. package/dist/safe-bash-calendar-engine/time-env/calendar.js +1 -1
  382. package/dist/safe-bash-calendar-engine/time-env/format.js +1 -1
  383. package/dist/safe-bash-command-alias/index.d.ts +13 -0
  384. package/dist/safe-bash-command-alias/index.js +88 -0
  385. package/dist/safe-bash-command-apply-patch/apply.js +3 -3
  386. package/dist/safe-bash-command-apply-patch/index.js +3 -3
  387. package/dist/safe-bash-command-apply-patch/matcher.js +1 -1
  388. package/dist/safe-bash-command-apply-patch/parser.js +1 -1
  389. package/dist/safe-bash-command-awk/awk-pipes.js +2 -2
  390. package/dist/safe-bash-command-awk/awk-reader.js +1 -1
  391. package/dist/safe-bash-command-awk/awk-runtime.js +3 -3
  392. package/dist/safe-bash-command-awk/awk.js +5 -5
  393. package/dist/safe-bash-command-awk/index.js +5 -5
  394. package/dist/safe-bash-command-bc/index.js +218 -65
  395. package/dist/safe-bash-command-bzip2/index.js +4 -3
  396. package/dist/safe-bash-command-chmod/LICENSE +21 -0
  397. package/dist/safe-bash-command-chmod/command.d.ts +7 -0
  398. package/dist/safe-bash-command-chmod/command.js +11 -0
  399. package/dist/safe-bash-command-chmod/index.d.ts +6 -0
  400. package/dist/safe-bash-command-chmod/index.js +27 -0
  401. package/dist/safe-bash-command-cmp/index.js +7 -6
  402. package/dist/safe-bash-command-column/column.js +3 -3
  403. package/dist/safe-bash-command-column/index.js +3 -3
  404. package/dist/safe-bash-command-column/layout.js +2 -2
  405. package/dist/safe-bash-command-csvkit/index.d.ts +1 -0
  406. package/dist/safe-bash-command-csvkit/index.js +1505 -7
  407. package/dist/safe-bash-command-csvkit/sync-support.js +2 -7
  408. package/dist/safe-bash-command-curl/curl.js +1 -1
  409. package/dist/safe-bash-command-curl/index.js +1 -1
  410. package/dist/safe-bash-command-date/date.js +1 -1
  411. package/dist/safe-bash-command-date/index.js +1 -1
  412. package/dist/safe-bash-command-dd/index.js +1 -1
  413. package/dist/safe-bash-command-dd/io.js +51 -5
  414. package/dist/safe-bash-command-diff/diff.js +1 -1
  415. package/dist/safe-bash-command-diff/index.js +1 -1
  416. package/dist/safe-bash-command-diff3/index.js +10 -13
  417. package/dist/safe-bash-command-exiftool/index.js +283 -55
  418. package/dist/safe-bash-command-exiftool/registry.d.ts +4 -2
  419. package/dist/safe-bash-command-factor/command.js +2 -2
  420. package/dist/safe-bash-command-factor/index.js +2 -2
  421. package/dist/safe-bash-command-fd/arguments.d.ts +2 -0
  422. package/dist/safe-bash-command-fd/index.js +42 -12
  423. package/dist/safe-bash-command-ffmpeg/index.js +356 -66
  424. package/dist/safe-bash-command-find/find-format.d.ts +3 -0
  425. package/dist/safe-bash-command-find/find-format.js +1 -1
  426. package/dist/safe-bash-command-find/find.js +2 -2
  427. package/dist/safe-bash-command-find/index.js +2 -2
  428. package/dist/safe-bash-command-fmt/index.js +10 -6
  429. package/dist/safe-bash-command-fold/engine.d.ts +1 -1
  430. package/dist/safe-bash-command-fold/family.js +2 -2
  431. package/dist/safe-bash-command-fold/index.js +1 -1
  432. package/dist/safe-bash-command-gzip/index.js +45 -42
  433. package/dist/safe-bash-command-hexdump/command.js +2 -2
  434. package/dist/safe-bash-command-hexdump/index.js +2 -2
  435. package/dist/safe-bash-command-html-to-markdown/entities.js +1 -1
  436. package/dist/safe-bash-command-html-to-markdown/index.js +4 -4
  437. package/dist/safe-bash-command-html-to-markdown/input.js +3 -3
  438. package/dist/safe-bash-command-html-to-markdown/parser.js +2 -2
  439. package/dist/safe-bash-command-html-to-markdown/render.js +3 -3
  440. package/dist/safe-bash-command-htmlq/contracts.d.ts +5 -2
  441. package/dist/safe-bash-command-htmlq/index.d.ts +2 -1
  442. package/dist/safe-bash-command-htmlq/index.js +175 -49
  443. package/dist/safe-bash-command-htmlq/sync.d.ts +1 -0
  444. package/dist/safe-bash-command-imagemagick/index.js +59 -7
  445. package/dist/safe-bash-command-install/arguments.d.ts +27 -0
  446. package/dist/safe-bash-command-install/arguments.js +224 -0
  447. package/dist/safe-bash-command-install/index.d.ts +7 -0
  448. package/dist/safe-bash-command-install/index.js +942 -0
  449. package/dist/safe-bash-command-install/mode.d.ts +6 -0
  450. package/dist/safe-bash-command-install/mode.js +71 -0
  451. package/dist/safe-bash-command-install/options.d.ts +40 -0
  452. package/dist/safe-bash-command-install/options.js +27 -0
  453. package/dist/safe-bash-command-jq/index.js +1 -1
  454. package/dist/safe-bash-command-jq/jq.js +1 -1
  455. package/dist/safe-bash-command-less/index.js +42 -57
  456. package/dist/safe-bash-command-llm/command.js +1 -1
  457. package/dist/safe-bash-command-llm/elevenlabs.js +2 -2
  458. package/dist/safe-bash-command-llm/index.js +4 -4
  459. package/dist/safe-bash-command-llm/openai.js +2 -2
  460. package/dist/safe-bash-command-llm/providers/elevenlabs.js +2 -2
  461. package/dist/safe-bash-command-llm/providers/index.js +3 -3
  462. package/dist/safe-bash-command-llm/providers/openai.js +2 -2
  463. package/dist/safe-bash-command-llm/providers/shared.js +1 -1
  464. package/dist/{safe-bash-mcp → safe-bash-command-mcp}/index.browser.d.ts +463 -46
  465. package/dist/safe-bash-command-mcp/index.browser.js +19308 -0
  466. package/dist/{safe-bash-mcp → safe-bash-command-mcp}/index.d.ts +15 -6
  467. package/dist/{safe-bash-mcp → safe-bash-command-mcp}/index.js +2835 -2783
  468. package/dist/safe-bash-command-media/LICENSE +21 -0
  469. package/dist/safe-bash-command-media/index.d.ts +6 -0
  470. package/dist/safe-bash-command-media/index.js +30 -0
  471. package/dist/safe-bash-command-media/plugin.d.ts +18 -0
  472. package/dist/safe-bash-command-media/plugin.js +11 -0
  473. package/dist/safe-bash-command-media/remote.d.ts +63 -0
  474. package/dist/safe-bash-command-media/remote.js +11 -0
  475. package/dist/safe-bash-command-media/settings.d.ts +4 -0
  476. package/dist/safe-bash-command-media/settings.js +41 -0
  477. package/dist/safe-bash-command-mktemp/LICENSE +21 -0
  478. package/dist/safe-bash-command-mktemp/command.d.ts +3 -0
  479. package/dist/safe-bash-command-mktemp/command.js +9 -0
  480. package/dist/safe-bash-command-mktemp/index.d.ts +6 -0
  481. package/dist/safe-bash-command-mktemp/index.js +25 -0
  482. package/dist/safe-bash-command-mmdc/arguments.d.ts +1 -0
  483. package/dist/safe-bash-command-mmdc/command.d.ts +2 -0
  484. package/dist/safe-bash-command-mmdc/contracts.d.ts +8 -1
  485. package/dist/safe-bash-command-mmdc/index.js +359 -7
  486. package/dist/safe-bash-command-nl/index.js +1 -1
  487. package/dist/safe-bash-command-nl/nl.js +1 -1
  488. package/dist/safe-bash-command-node/LICENSE +21 -0
  489. package/dist/safe-bash-command-node/index.d.ts +17 -0
  490. package/dist/safe-bash-command-node/index.js +328 -0
  491. package/dist/safe-bash-command-numfmt/index.js +1 -0
  492. package/dist/safe-bash-command-od/index.js +16 -8
  493. package/dist/safe-bash-command-op/index.js +62 -36
  494. package/dist/safe-bash-command-op/types.d.ts +1 -0
  495. package/dist/safe-bash-command-pandoc/command.js +3 -3
  496. package/dist/safe-bash-command-pandoc/index.d.ts +1 -0
  497. package/dist/safe-bash-command-pandoc/index.js +5 -3
  498. package/dist/safe-bash-command-pandoc/sync.d.ts +1 -0
  499. package/dist/safe-bash-command-patch/index.js +4 -4
  500. package/dist/safe-bash-command-patch/patch.js +4 -4
  501. package/dist/safe-bash-command-pdfimages/index.js +1 -1
  502. package/dist/safe-bash-command-pdfinfo/index.js +30 -5
  503. package/dist/safe-bash-command-pdftk/index.js +21 -23
  504. package/dist/safe-bash-command-pdftoppm/index.js +17 -4
  505. package/dist/safe-bash-command-pdftotext/index.js +11 -14
  506. package/dist/safe-bash-command-qpdf/index.d.ts +1 -0
  507. package/dist/safe-bash-command-qpdf/index.js +9 -6
  508. package/dist/safe-bash-command-rg/index.js +1 -1
  509. package/dist/safe-bash-command-rg/rg-command.js +1 -1
  510. package/dist/safe-bash-command-sed/index.js +1 -1
  511. package/dist/safe-bash-command-sed/sed.js +1 -1
  512. package/dist/safe-bash-command-shuf/input.d.ts +2 -2
  513. package/dist/safe-bash-command-shuf/input.js +2 -1
  514. package/dist/safe-bash-command-shuf/shuf.js +4 -2
  515. package/dist/safe-bash-command-sips/index.js +15 -7
  516. package/dist/safe-bash-command-soffice/index.js +97 -12
  517. package/dist/safe-bash-command-sponge/index.js +13 -3
  518. package/dist/safe-bash-command-sqlite3/engine.d.ts +1 -0
  519. package/dist/safe-bash-command-sqlite3/index.js +510 -70
  520. package/dist/safe-bash-command-ssconvert/formats/xlsx.js +2 -2
  521. package/dist/safe-bash-command-ssconvert/index.js +44 -22
  522. package/dist/safe-bash-command-stat/LICENSE +21 -0
  523. package/dist/safe-bash-command-stat/command.d.ts +7 -0
  524. package/dist/safe-bash-command-stat/command.js +9 -0
  525. package/dist/safe-bash-command-stat/index.d.ts +6 -0
  526. package/dist/safe-bash-command-stat/index.js +25 -0
  527. package/dist/safe-bash-command-tar/create.d.ts +1 -0
  528. package/dist/safe-bash-command-tar/create.js +2 -2
  529. package/dist/safe-bash-command-tar/extract.js +2 -2
  530. package/dist/safe-bash-command-tar/index.js +4 -4
  531. package/dist/safe-bash-command-tar/modes.js +4 -4
  532. package/dist/safe-bash-command-tar/options.js +1 -1
  533. package/dist/safe-bash-command-truncate/index.js +2 -2
  534. package/dist/safe-bash-command-tsort/command.js +2 -2
  535. package/dist/safe-bash-command-tsort/index.js +2 -2
  536. package/dist/safe-bash-command-unalias/index.d.ts +12 -0
  537. package/dist/safe-bash-command-unalias/index.js +67 -0
  538. package/dist/safe-bash-command-unrtf/index.js +37 -5
  539. package/dist/safe-bash-command-xan/argv.d.ts +1 -1
  540. package/dist/safe-bash-command-xan/argv.js +2 -2
  541. package/dist/safe-bash-command-xan/budget.d.ts +0 -1
  542. package/dist/safe-bash-command-xan/budget.js +1 -1
  543. package/dist/safe-bash-command-xan/commands.js +6 -6
  544. package/dist/safe-bash-command-xan/csv.js +2 -2
  545. package/dist/safe-bash-command-xan/index.js +8 -9
  546. package/dist/safe-bash-command-xan/io.js +4 -4
  547. package/dist/safe-bash-command-xan/options.js +1 -1
  548. package/dist/safe-bash-command-xan/selector.js +2 -2
  549. package/dist/safe-bash-command-xmllint/index.js +45 -23
  550. package/dist/safe-bash-command-xxd/index.js +47 -12
  551. package/dist/safe-bash-command-xz/command.d.ts +1 -1
  552. package/dist/safe-bash-command-xz/index.js +3 -2
  553. package/dist/safe-bash-command-yq/accounting.js +1 -1
  554. package/dist/safe-bash-command-yq/index.js +4 -2
  555. package/dist/safe-bash-command-yq/native-work.js +3 -0
  556. package/dist/safe-bash-command-yq/parser.js +2 -2
  557. package/dist/safe-bash-command-yq/query.js +8 -5
  558. package/dist/safe-bash-command-yq/toml.js +2 -2
  559. package/dist/safe-bash-command-zip/index.js +3 -3
  560. package/dist/safe-bash-compression-engine/bounded-codec.js +3 -3
  561. package/dist/safe-bash-compression-engine/codec-loader.js +2 -2
  562. package/dist/safe-bash-compression-engine/files.js +6 -6
  563. package/dist/safe-bash-compression-engine/index.js +5 -5
  564. package/dist/safe-bash-compression-engine/operand.js +6 -6
  565. package/dist/safe-bash-compression-engine/options.js +1 -1
  566. package/dist/safe-bash-compression-engine/stream.js +5 -5
  567. package/dist/safe-bash-compression-engine/zstd-decode.js +4 -4
  568. package/dist/safe-bash-contracts/command.js +3 -3
  569. package/dist/safe-bash-contracts/default-executor.js +2 -2
  570. package/dist/safe-bash-contracts/diagnostics.js +3 -3
  571. package/dist/safe-bash-contracts/escaping.js +6 -6
  572. package/dist/safe-bash-contracts/filesystem-descriptor.js +3 -3
  573. package/dist/safe-bash-contracts/filesystem-output.js +5 -5
  574. package/dist/safe-bash-contracts/http.d.ts +7 -0
  575. package/dist/safe-bash-contracts/index.js +8 -8
  576. package/dist/safe-bash-contracts/io.d.ts +2 -0
  577. package/dist/safe-bash-contracts/io.js +2 -2
  578. package/dist/safe-bash-contracts/output.js +3 -3
  579. package/dist/safe-bash-contracts/runtime-control.d.ts +2 -2
  580. package/dist/safe-bash-contracts/runtime-control.js +4 -2
  581. package/dist/safe-bash-contracts/signals.d.ts +2 -0
  582. package/dist/safe-bash-contracts/signals.js +3 -1
  583. package/dist/safe-bash-contracts/yield.js +1 -1
  584. package/dist/safe-bash-csv-engine/index.d.ts +2 -1
  585. package/dist/safe-bash-csv-engine/index.js +21 -15
  586. package/dist/safe-bash-io-engine/commands/search/requirements.js +2 -2
  587. package/dist/safe-bash-io-engine/commands/text-programs/shared.js +6 -6
  588. package/dist/safe-bash-io-engine/internal.js +1 -1
  589. package/dist/safe-bash-io-engine/shell/pattern.js +38 -18
  590. package/dist/safe-bash-line-ending-engine/convert.js +9 -204
  591. package/dist/safe-bash-line-ending-engine/encoding.js +9 -42
  592. package/dist/safe-bash-line-ending-engine/index.js +48 -0
  593. package/dist/safe-bash-line-ending-engine/info.js +9 -90
  594. package/dist/safe-bash-line-ending-engine/internal.js +15 -160
  595. package/dist/safe-bash-line-ending-engine/io.js +12 -289
  596. package/dist/safe-bash-line-ending-engine/stage.js +10 -160
  597. package/dist/safe-bash-markdown-engine/index.js +3 -3
  598. package/dist/safe-bash-metadata-engine/LICENSE +21 -0
  599. package/dist/safe-bash-metadata-engine/index.d.ts +30 -0
  600. package/dist/safe-bash-metadata-engine/index.js +82 -0
  601. package/dist/safe-bash-metadata-engine/random.d.ts +1 -0
  602. package/dist/safe-bash-metadata-engine/random.js +21 -0
  603. package/dist/safe-bash-network-engine/args.d.ts +6 -0
  604. package/dist/safe-bash-network-engine/args.js +4 -2
  605. package/dist/safe-bash-network-engine/body.js +1 -1
  606. package/dist/safe-bash-network-engine/fetch-transport.js +3 -1
  607. package/dist/safe-bash-network-engine/index.js +3 -1
  608. package/dist/safe-bash-network-engine/input.js +2 -2
  609. package/dist/safe-bash-network-engine/platform-portable.js +3 -1
  610. package/dist/safe-bash-query-engine/dates.d.ts +1 -1
  611. package/dist/safe-bash-query-engine/dates.js +1 -1
  612. package/dist/safe-bash-query-engine/index.js +6 -6
  613. package/dist/safe-bash-query-engine/interpreter.js +4 -4
  614. package/dist/safe-bash-query-engine/parser.js +1 -1
  615. package/dist/safe-bash-query-engine/query-core.js +6 -6
  616. package/dist/safe-bash-regex-engine/execution/bounded-provider.js +10 -0
  617. package/dist/safe-bash-regex-engine/index.js +1 -1
  618. package/dist/safe-bash-regex-engine/text/regex.d.ts +1 -1
  619. package/dist/safe-bash-regex-engine/text/regex.js +1 -1
  620. package/dist/safe-bash-search-engine/ergonomic-regex.d.ts +1 -0
  621. package/dist/safe-bash-search-engine/ergonomic-regex.js +2 -2
  622. package/dist/safe-bash-search-engine/glob.js +2 -2
  623. package/dist/safe-bash-search-engine/grep.js +17 -10
  624. package/dist/safe-bash-search-engine/matcher.d.ts +2 -2
  625. package/dist/safe-bash-search-engine/matcher.js +13 -9
  626. package/dist/safe-bash-search-engine/options.d.ts +2 -0
  627. package/dist/safe-bash-search-engine/options.js +1 -1
  628. package/dist/safe-bash-search-engine/output.js +1 -1
  629. package/dist/safe-bash-search-engine/shared.js +2 -2
  630. package/dist/safe-bash-search-engine/walk.js +15 -3
  631. package/dist/safe-bash-text-stream-engine/stream-format/shared.d.ts +1 -1
  632. package/dist/safe-bash-text-stream-engine/stream-format/shared.js +2 -1
  633. package/dist/safe-bash-xml-engine/document.js +3 -3
  634. package/dist/safe-bash-xml-engine/evaluate.js +2 -2
  635. package/dist/safe-bash-xml-engine/index.js +4 -4
  636. package/dist/safe-bash-xml-engine/io.js +7 -2
  637. package/dist/safe-bash-xml-engine/limits.d.ts +0 -2
  638. package/dist/safe-bash-xml-engine/limits.js +1 -1
  639. package/dist/safe-bash-xml-engine/query.js +3 -3
  640. package/dist/safe-bash-zip-engine/index.js +3 -3
  641. package/dist/safe-bash-zip-engine/zip/repair.js +3 -3
  642. package/dist/safe-bash-zip-engine/zip/safety.js +1 -1
  643. package/dist/safe-bash-zip-engine/zip/sfx.js +3 -3
  644. package/dist/safe-bash-zip-engine/zip/volumes.js +1 -1
  645. package/dist/safe-bash-zip-engine/zip-format.js +3 -3
  646. package/dist/safe-playwright-cloudflare/browser-snapshot-json.js +2 -2
  647. package/dist/safe-playwright-cloudflare/browser-snapshot-references.js +1 -1
  648. package/dist/safe-playwright-cloudflare/browser-socket-closure.js +18 -3
  649. package/dist/safe-playwright-cloudflare/shell-browser-resource.js +1 -1
  650. package/dist/xlsx-ast/xlsx.js +6 -5
  651. package/package.json +112 -98
  652. package/dist/media-cli/bytes.d.ts +0 -8
  653. package/dist/media-cli/bytes.js +0 -40
  654. package/dist/media-cli/concat.d.ts +0 -30
  655. package/dist/media-cli/concat.js +0 -197
  656. package/dist/media-cli/content.js +0 -66
  657. package/dist/media-cli/dependency-grammars.d.ts +0 -12
  658. package/dist/media-cli/dependency-grammars.js +0 -557
  659. package/dist/media-cli/discover.js +0 -286
  660. package/dist/media-cli/engine.js +0 -190
  661. package/dist/media-cli/filename-expression.js +0 -147
  662. package/dist/media-cli/filesystem.js +0 -35
  663. package/dist/media-cli/frontend-contract.js +0 -8
  664. package/dist/media-cli/frontend-issues.d.ts +0 -6
  665. package/dist/media-cli/frontend-issues.js +0 -9
  666. package/dist/media-cli/imagemagick-operand.d.ts +0 -42
  667. package/dist/media-cli/imagemagick-operand.js +0 -229
  668. package/dist/media-cli/imagemagick-references.d.ts +0 -7
  669. package/dist/media-cli/imagemagick-references.js +0 -42
  670. package/dist/media-cli/imagemagick.generated.js +0 -3254
  671. package/dist/media-cli/imagemagick.js +0 -615
  672. package/dist/media-cli/index.js +0 -12
  673. package/dist/media-cli/mvg.d.ts +0 -10
  674. package/dist/media-cli/mvg.js +0 -102
  675. package/dist/media-cli/network.js +0 -78
  676. package/dist/media-cli/options.generated.js +0 -3312
  677. package/dist/media-cli/preset.d.ts +0 -11
  678. package/dist/media-cli/preset.js +0 -57
  679. package/dist/media-cli/resolution-path.d.ts +0 -23
  680. package/dist/media-cli/resolution-path.js +0 -217
  681. package/dist/media-cli/resolver.js +0 -494
  682. package/dist/media-cli/resources.d.ts +0 -16
  683. package/dist/media-cli/resources.js +0 -187
  684. package/dist/media-cli/shim.js +0 -52
  685. package/dist/media-cli/tee.d.ts +0 -6
  686. package/dist/media-cli/tee.js +0 -38
  687. package/dist/office-package/zip-sync.js +0 -111
  688. package/dist/remote-execution/binary.js +0 -178
  689. package/dist/remote-execution/callback-result.js +0 -26
  690. package/dist/remote-execution/canonical-capabilities.d.ts +0 -5
  691. package/dist/remote-execution/canonical-capabilities.js +0 -45
  692. package/dist/remote-execution/canonical-metadata.d.ts +0 -4
  693. package/dist/remote-execution/canonical-metadata.js +0 -32
  694. package/dist/remote-execution/client.js +0 -824
  695. package/dist/remote-execution/deployment.js +0 -131
  696. package/dist/remote-execution/descriptors.js +0 -267
  697. package/dist/remote-execution/effects.js +0 -357
  698. package/dist/remote-execution/endpoint.js +0 -224
  699. package/dist/remote-execution/files.js +0 -291
  700. package/dist/remote-execution/hosting-operation.js +0 -26
  701. package/dist/remote-execution/hosting-request.d.ts +0 -4
  702. package/dist/remote-execution/hosting-request.js +0 -12
  703. package/dist/remote-execution/hosting-stream.d.ts +0 -8
  704. package/dist/remote-execution/hosting-stream.js +0 -64
  705. package/dist/remote-execution/index.js +0 -18
  706. package/dist/remote-execution/invocation-admission.d.ts +0 -3
  707. package/dist/remote-execution/invocation-admission.js +0 -17
  708. package/dist/remote-execution/job-binding.js +0 -1269
  709. package/dist/remote-execution/materializations.js +0 -284
  710. package/dist/remote-execution/modal-driver.js +0 -90
  711. package/dist/remote-execution/native-result.d.ts +0 -3
  712. package/dist/remote-execution/native-result.js +0 -16
  713. package/dist/remote-execution/output-freshness.d.ts +0 -4
  714. package/dist/remote-execution/output-freshness.js +0 -19
  715. package/dist/remote-execution/output-retrieval.js +0 -474
  716. package/dist/remote-execution/process-http.js +0 -607
  717. package/dist/remote-execution/process.js +0 -577
  718. package/dist/remote-execution/protocol.js +0 -208
  719. package/dist/remote-execution/relay.js +0 -91
  720. package/dist/remote-execution/rest-driver.js +0 -93
  721. package/dist/remote-execution/upload-descriptor.js +0 -201
  722. package/dist/remote-execution/upload-protocol.js +0 -62
  723. package/dist/remote-execution/uploads.js +0 -324
  724. package/dist/remote-execution/wire-json.d.ts +0 -4
  725. package/dist/remote-execution/wire-json.js +0 -44
  726. package/dist/remote-execution/wire-validation.js +0 -131
  727. package/dist/remote-execution/wire.generated.js +0 -4224
  728. package/dist/safe-bash/chunks/chunk-GETUOD5D.js +0 -161
  729. package/dist/safe-bash/chunks/chunk-IWDICZVK.js +0 -20
  730. package/dist/safe-bash/chunks/chunk-MHMMRCYC.js +0 -3464
  731. package/dist/safe-bash/chunks/chunk-UE5KZDEK.js +0 -77
  732. package/dist/safe-bash/chunks/chunk-VSAJ4OTM.js +0 -962
  733. package/dist/safe-bash/chunks/csvkit-TACDU7FC.js +0 -1618
  734. package/dist/safe-bash/chunks/implementation-MLFHUQ5M.js +0 -133
  735. package/dist/safe-bash/commands/csvkit/sync.js +0 -1639
  736. package/dist/safe-bash/commands/node/unconfigured.d.ts +0 -3
  737. package/dist/safe-bash/commands/node/unconfigured.js +0 -10
  738. package/dist/safe-bash/commands/pandoc/implementation.d.ts +0 -8
  739. package/dist/safe-bash/commands/pandoc/implementation.js +0 -94
  740. package/dist/safe-bash-mcp/index.browser.js +0 -9157
  741. package/dist/safe-bash/command-chunks/{chunk-ZRRBXU3M.js → chunk-GIN5GUDP.js} +4 -4
  742. package/dist/safe-bash/command-chunks/{chunk-LAOM65EE.js → chunk-IEO4XVN6.js} +3 -3
  743. package/dist/safe-bash/command-chunks/{chunk-364TMWBT.js → chunk-MWREVL44.js} +6 -6
  744. package/dist/safe-bash/command-chunks/{chunk-464RVBGB.js → chunk-Q5TDKFHK.js} +3 -3
  745. package/dist/safe-bash/command-chunks/{chunk-AJR3AQYA.js → chunk-UKX3LZHR.js} +0 -0
  746. package/dist/safe-bash/command-chunks/{chunk-XIIBTGC5.js → chunk-XPXEQKRW.js} +9 -9
  747. package/dist/safe-bash/command-chunks/{chunk-FDBUV4HJ.js → chunk-Y4HGTG3E.js} +3 -3
  748. /package/dist/{safe-bash/commands/csvkit → safe-bash-command-csvkit}/sync.d.ts +0 -0
@@ -1,1269 +0,0 @@
1
- import { EndpointCapabilityGap } from './endpoint.js';
2
- import { BytePath, decodeFileOffset, decodeObjectMetadata } from "@poe-platform/safe-fs/contracts/object";
3
- import { FsError } from "@poe-platform/safe-fs/contracts/errors";
4
- import { encodeFileMetadata } from './files.js';
5
- import { assertLogicalCwd } from './invocation-admission.js';
6
- import { createDescriptorMaterialization } from './descriptors.js';
7
- import { admitCanonicalMetadata } from './canonical-metadata.js';
8
- import { admitCanonicalCapabilities } from './canonical-capabilities.js';
9
- export class JobEffectsError extends Error {
10
- effects;
11
- constructor(cause, effects) {
12
- super(cause instanceof Error ? cause.message : String(cause), { cause });
13
- this.effects = effects;
14
- this.name = 'JobEffectsError';
15
- }
16
- }
17
- export class JobCallbackRecoveryError extends Error {
18
- sessionId;
19
- epoch;
20
- jobId;
21
- outcome = 'unknown';
22
- constructor(sessionId, epoch, jobId) {
23
- super('Job callback retention ended; inspect the job before recovery');
24
- this.sessionId = sessionId;
25
- this.epoch = epoch;
26
- this.jobId = jobId;
27
- this.name = 'JobCallbackRecoveryError';
28
- }
29
- }
30
- /** Replacing an observed data field with a getter cannot hide revoked work.
31
- * Existing metadata getters remain supported without a second invocation. */
32
- function unchangedMetadata(record, key, before, value) {
33
- const current = Object.getOwnPropertyDescriptor(record, key);
34
- if (!before || !current)
35
- return before === current;
36
- if ('value' in before)
37
- return 'value' in current && current.value === value;
38
- return !('value' in current) && current.get === before.get && current.set === before.set;
39
- }
40
- /** Own only admission metadata. Advisory acquisition/error payloads remain lazy;
41
- * neither an iterator nor an inherited slot can supply readiness evidence. */
42
- export function snapshotReadiness(work) {
43
- if (!Array.isArray(work))
44
- throw new Error('Incomplete required readiness');
45
- const length = work.length;
46
- const records = [];
47
- const descriptors = [];
48
- const slots = [];
49
- const snapshot = Array.from({ length }, (_, index) => {
50
- if (!Object.hasOwn(work, index))
51
- throw new Error('Incomplete required readiness');
52
- slots.push(Object.getOwnPropertyDescriptor(work, index));
53
- const item = work[index];
54
- if (!item)
55
- throw new Error('Incomplete required readiness');
56
- records.push(item);
57
- descriptors.push(Object.fromEntries(['kind', 'identity', 'state']
58
- .map(key => [key, Object.getOwnPropertyDescriptor(item, key)])));
59
- return { kind: item.kind, identity: item.identity, state: item.state };
60
- });
61
- if (work.length !== length)
62
- throw new Error('Incomplete required readiness');
63
- // Later metadata accessors can revoke an earlier obligation without changing
64
- // ledger length. Check descriptors and data values without invoking getters again
65
- // or touching advisory acquisition/error payloads.
66
- for (let index = 0; index < length; index++) {
67
- if (!unchangedMetadata(work, String(index), slots[index], records[index]))
68
- throw new Error('Incomplete required readiness');
69
- for (const key of ['kind', 'identity', 'state']) {
70
- if (!unchangedMetadata(records[index], key, descriptors[index][key], snapshot[index][key]))
71
- throw new Error('Incomplete required readiness');
72
- }
73
- }
74
- return snapshot;
75
- }
76
- export function assertRequiredReadiness(work, admitted) {
77
- work = snapshotReadiness(work);
78
- if (admitted !== undefined)
79
- admitted = snapshotReadiness(admitted);
80
- const identities = new Set();
81
- if (!work.some(item => item.kind === 'required')
82
- || work.some(item => {
83
- if (!item || typeof item.identity !== 'string' || !item.identity.length
84
- || identities.has(item.identity) || !['metadata-only', 'speculative', 'required'].includes(item.kind)
85
- || !['pending', 'complete', 'failed'].includes(item.state)
86
- || (item.kind === 'required' && item.state !== 'complete'))
87
- return true;
88
- identities.add(item.identity);
89
- return false;
90
- }))
91
- throw new Error('Incomplete required readiness');
92
- if (admitted !== undefined) {
93
- // Ledger order is bookkeeping, not authority. Keep the exact admitted set
94
- // of required identities while advisory records evolve independently.
95
- const required = new Set(work.filter(item => item.kind === 'required').map(item => item.identity));
96
- const expected = admitted.filter(item => item.kind === 'required');
97
- if (required.size !== expected.length || expected.some(item => !required.has(item.identity)))
98
- throw new Error('Incomplete or stale job materialization readiness');
99
- }
100
- }
101
- function completeStartingEntries(entries) {
102
- const indexes = new Set();
103
- return Array.isArray(entries) && Array.from(entries).every(entry => {
104
- if (!entry || !['pending', 'applied', 'failed', 'unknown'].includes(entry.state)
105
- || entry.kind !== undefined && !['metadata-only', 'speculative', 'required'].includes(entry.kind))
106
- return false;
107
- if (entry.kind !== undefined && entry.kind !== 'required')
108
- return true;
109
- if (entry.state !== 'applied')
110
- return false;
111
- if (entry.index === undefined)
112
- return true;
113
- if (!Number.isSafeInteger(entry.index) || entry.index < 0 || indexes.has(entry.index))
114
- return false;
115
- indexes.add(entry.index);
116
- return true;
117
- });
118
- }
119
- function requiredEntryIdentity(entries) {
120
- const required = entries.filter(entry => entry.kind === undefined || entry.kind === 'required');
121
- // Indexed manifest records name obligations independently of observation
122
- // order. Unindexed namespace work retains its ordered admission evidence.
123
- const indexed = required.filter(entry => entry.index !== undefined).sort((a, b) => a.index - b.index);
124
- const unindexed = required.filter(entry => entry.index === undefined);
125
- return JSON.stringify({ indexed, unindexed });
126
- }
127
- /** In-process source admission evidence. Capture methods and their receivers,
128
- * never dependency bytes, before asynchronous session/materialization binding.
129
- * Mutable filesystem containers cannot authorize a replacement scratch facet. */
130
- export function captureJobSource(fs) {
131
- const objects = fs.objects;
132
- return Object.freeze({ fs, objects, capabilities: fs.capabilities,
133
- objectMethods: Object.freeze({
134
- open: objects?.open, create: objects?.create, rename: objects?.rename,
135
- unlink: objects?.unlink, readdir: objects?.readdir,
136
- }),
137
- pathMethods: Object.freeze({
138
- access: fs.access, realpath: fs.realpath, stat: fs.stat, lstat: fs.lstat,
139
- mkdir: fs.mkdir, rmdir: fs.rmdir, readlink: fs.readlink,
140
- symlink: fs.symlink, capabilitiesFor: fs.capabilitiesFor,
141
- }),
142
- });
143
- }
144
- const fields = ['sessionId', 'epoch', 'buildId', 'sourceAuthorityId', 'bindingId', 'materializationId', 'manifestId', 'manifestRevision', 'directoryRevision'];
145
- function octets(value, empty = false) {
146
- if (!Array.isArray(value) || (!empty && !value.length) || value.length > 1048576)
147
- throw new TypeError('Invalid native octets');
148
- for (let index = 0; index < value.length; index++) {
149
- if (!Object.hasOwn(value, index))
150
- throw new TypeError('Invalid native octets');
151
- const n = value[index];
152
- if (!Number.isInteger(n) || n < 1 || n > 255)
153
- throw new TypeError('Invalid native octets');
154
- }
155
- }
156
- /** Includes one native NUL terminator per argument, including empty arguments. */
157
- export const nativeArgvByteLimit = 1048576;
158
- /** Validate the literal job description before handing it to a host adapter. */
159
- export function assertJobInvocation(input) {
160
- for (const field of fields)
161
- if (typeof input[field] !== 'string' || !input[field].length || input[field].length > 256)
162
- throw new TypeError('Incomplete job binding');
163
- assertNativeProcessView(input.cwd, input.originalArgv);
164
- }
165
- /** Admit literal process names independently of resource acquisition and session
166
- * binding. Dependency discovery must not run for an inadmissible process view. */
167
- export function assertNativeProcessView(cwd, originalArgv) {
168
- octets(cwd);
169
- assertLogicalCwd(cwd);
170
- if (!Array.isArray(originalArgv))
171
- throw new TypeError('Original argv required');
172
- if (originalArgv.length > nativeArgvByteLimit)
173
- throw new TypeError('Native argv limit');
174
- let remaining = nativeArgvByteLimit;
175
- for (let index = 0; index < originalArgv.length; index++) {
176
- if (!Object.hasOwn(originalArgv, index))
177
- throw new TypeError('Invalid native octets');
178
- const arg = originalArgv[index];
179
- octets(arg, true);
180
- if (arg.length >= remaining)
181
- throw new TypeError('Native argv limit');
182
- remaining -= arg.length + 1;
183
- }
184
- }
185
- /** Own the native indexed names, never advisory properties on their carriers.
186
- * Validate before allocation and again after observing caller-owned slots. */
187
- function ownNativeProcessView(cwd, originalArgv) {
188
- assertNativeProcessView(cwd, originalArgv);
189
- const argumentCount = originalArgv.length;
190
- const indexed = (bytes) => {
191
- const length = bytes.length;
192
- const owned = Array.from({ length }, (_, index) => {
193
- if (!Object.hasOwn(bytes, index))
194
- throw new TypeError('Invalid native octets');
195
- return bytes[index];
196
- });
197
- if (bytes.length !== length)
198
- throw new TypeError('Invalid native octets');
199
- return owned;
200
- };
201
- const owned = {
202
- cwd: indexed(cwd),
203
- originalArgv: Array.from({ length: argumentCount }, (_, index) => {
204
- if (!Object.hasOwn(originalArgv, index))
205
- throw new TypeError('Invalid native octets');
206
- return indexed(originalArgv[index]);
207
- }),
208
- };
209
- // Indexed accessors can append a late operand during copying. A prefix is
210
- // neither the original argv nor a complete process binding.
211
- if (originalArgv.length !== argumentCount)
212
- throw new TypeError('Invalid native octets');
213
- assertNativeProcessView(owned.cwd, owned.originalArgv);
214
- return owned;
215
- }
216
- /** Invocation-local live authority. No staged pathname is ever a fallback.
217
- * Callback replay is process-local; a lost ledger requires unknown-outcome
218
- * recovery, never retransmission against a new binding instance. */
219
- export function createJobBinding(options) {
220
- options = Object.freeze({ ...options });
221
- if (!options.credential || (typeof options.credential !== 'object' && typeof options.credential !== 'function'))
222
- throw new TypeError('Callback credential capability required');
223
- const endpointBuild = options.endpoints?.buildDigest;
224
- const endpointOpen = options.endpoints?.access.open.bind(options.endpoints.access);
225
- const maxIo = options.maxIoBytes ?? 1048576;
226
- const maxEntries = options.maxDirectoryEntries ?? 4096;
227
- for (const n of [options.maxCallbacks, options.maxHandles, maxIo, maxEntries])
228
- if (!Number.isSafeInteger(n) || n < 1)
229
- throw new TypeError('Invalid job bound');
230
- // Retain the canonical object facet when the host issues this capability,
231
- // before asynchronous engine binding can replace facets with scratch storage.
232
- // This retains authority, not bytes: each operation still observes live data.
233
- const sourceAdmission = captureJobSource(options.fs);
234
- const objects = sourceAdmission.objects;
235
- // Pin the mandatory acquisition capability as well as its receiver. A host
236
- // can mutate the facet during asynchronous engine binding; looking up open
237
- // again at execute would silently authorize its replacement scratch store.
238
- const open = sourceAdmission.objectMethods.open?.bind(objects);
239
- const source = {
240
- open,
241
- create: sourceAdmission.objectMethods.create?.bind(objects),
242
- rename: sourceAdmission.objectMethods.rename?.bind(objects),
243
- unlink: sourceAdmission.objectMethods.unlink?.bind(objects),
244
- readdir: sourceAdmission.objectMethods.readdir?.bind(objects),
245
- };
246
- const canonical = {
247
- access: sourceAdmission.pathMethods.access?.bind(options.fs),
248
- realpath: sourceAdmission.pathMethods.realpath?.bind(options.fs),
249
- stat: sourceAdmission.pathMethods.stat?.bind(options.fs),
250
- lstat: sourceAdmission.pathMethods.lstat?.bind(options.fs),
251
- mkdir: sourceAdmission.pathMethods.mkdir?.bind(options.fs),
252
- rmdir: sourceAdmission.pathMethods.rmdir?.bind(options.fs),
253
- readlink: sourceAdmission.pathMethods.readlink?.bind(options.fs),
254
- symlink: sourceAdmission.pathMethods.symlink?.bind(options.fs),
255
- capabilitiesFor: sourceAdmission.pathMethods.capabilitiesFor?.bind(options.fs),
256
- };
257
- const descriptorHandles = options.handles ? { acquire: options.handles.acquire.bind(options.handles) } : undefined;
258
- return {
259
- effects: options.effects,
260
- /** Engines pass their original scoped source capability to prevent reuse of
261
- * another invocation's binding. Direct callers use this binding's source. */
262
- async execute(input, signal, sourceCapability, admittedSource) {
263
- // The engine supplies its invocation's actual scoped capability. Serialized
264
- // authority IDs alone cannot detect a job borrowed from another invocation.
265
- if (sourceCapability !== undefined && sourceCapability !== options.fs)
266
- throw new Error('Job source capability mismatch');
267
- if (admittedSource && (admittedSource.fs !== sourceAdmission.fs
268
- || admittedSource.objects !== sourceAdmission.objects
269
- // Policy participates in canonical authority just like method facets.
270
- // Compare the issued facet, without freezing its live access guarantees.
271
- || admittedSource.capabilities !== sourceAdmission.capabilities
272
- || Object.keys(sourceAdmission.objectMethods).some(key => Reflect.get(admittedSource.objectMethods, key) !== Reflect.get(sourceAdmission.objectMethods, key))
273
- || Object.keys(sourceAdmission.pathMethods).some(key => Reflect.get(admittedSource.pathMethods, key) !== Reflect.get(sourceAdmission.pathMethods, key))))
274
- throw new Error('Job source capability mismatch');
275
- // Capture top-level observations once, then admit octets before retaining
276
- // their copy. Validate again after copying any caller-owned nested arrays.
277
- // Private staging and advisory discovery are not job admission fields.
278
- // Observing their getters could eagerly acquire dependencies or surface a
279
- // speculative failure before the process reaches its native access stage.
280
- const description = Object.fromEntries([...fields, 'cwd', 'originalArgv']
281
- .map(field => [field, Reflect.get(input, field)]));
282
- assertJobInvocation(description);
283
- const invocation = { ...description, ...ownNativeProcessView(description.cwd, description.originalArgv) };
284
- // Validate exactly the owned description passed to preparation and launch.
285
- // Local structural callers can expose getters; checking the caller and
286
- // copying it later would authorize a different session or source binding.
287
- assertJobInvocation(invocation);
288
- for (const field of ['sessionId', 'epoch', 'buildId', 'sourceAuthorityId', 'bindingId'])
289
- if (invocation[field] !== options[field])
290
- throw new Error('Job authority mismatch');
291
- signal.throwIfAborted();
292
- const jobId = crypto.randomUUID();
293
- const handles = new Map();
294
- const reads = new AbortController();
295
- const descriptors = descriptorHandles ? createDescriptorMaterialization({ handles: descriptorHandles, maxHandles: options.maxHandles, maxIoBytes: maxIo }) : undefined;
296
- const descriptorOwners = new Map();
297
- // Retiring handles still consume canonical retains until close settles.
298
- let closingHandles = 0;
299
- let acquiringHandles = 0;
300
- const namespaceChanges = [];
301
- options.effects?.settle({ state: 'running' });
302
- const outputIdentities = new Set();
303
- const identities = new Map();
304
- const callbacks = new Map();
305
- const queues = new Map();
306
- const pending = new Set();
307
- const endpointLeases = new Set();
308
- let endpointAcquisitions = 0;
309
- let endpointCallbacks = 0;
310
- let closed = false;
311
- const openEndpoint = async (credential, native) => {
312
- if (credential !== options.credential)
313
- throw new Error('Unauthorized endpoint callback');
314
- if (closed)
315
- throw new JobCallbackRecoveryError(invocation.sessionId, invocation.epoch, jobId);
316
- signal.throwIfAborted();
317
- if (!endpointOpen)
318
- throw new EndpointCapabilityGap();
319
- native = { ...native };
320
- const callerSignal = native.signal;
321
- native = { ...structuredClone({ ...native, signal: undefined }), signal: callerSignal };
322
- if (!endpointBuild || native.buildDigest !== endpointBuild)
323
- throw new Error('Endpoint build mismatch');
324
- if (endpointCallbacks >= options.maxCallbacks)
325
- throw new Error('Endpoint callback bound');
326
- if (endpointAcquisitions + endpointLeases.size >= options.maxHandles)
327
- throw new Error('Endpoint handle bound');
328
- endpointCallbacks++;
329
- endpointAcquisitions++;
330
- const acquisition = Promise.resolve().then(async () => {
331
- const lease = await endpointOpen({ ...native, signal: native.signal
332
- ? AbortSignal.any([signal, native.signal]) : signal });
333
- if (!lease || typeof lease.close !== 'function')
334
- throw new TypeError('Endpoint provider must return a retireable transport lease');
335
- const retire = lease.close.bind(lease);
336
- let closing;
337
- const owned = { close() {
338
- return closing ??= Promise.resolve().then(retire).then(() => { endpointLeases.delete(owned); });
339
- } };
340
- endpointLeases.add(owned);
341
- if (closed || signal.aborted) {
342
- await owned.close();
343
- signal.throwIfAborted();
344
- throw new JobCallbackRecoveryError(invocation.sessionId, invocation.epoch, jobId);
345
- }
346
- return owned;
347
- });
348
- // Drain unawaited acquisitions without replacing the primary outcome.
349
- const drained = acquisition.then(() => { }, () => { });
350
- pending.add(drained);
351
- try {
352
- return await acquisition;
353
- }
354
- finally {
355
- endpointAcquisitions--;
356
- pending.delete(drained);
357
- }
358
- };
359
- let workspace;
360
- let acquiredWorkspace;
361
- function path(value) {
362
- octets(value);
363
- return new BytePath(Uint8Array.from(value[0] === 47 ? value : [...invocation.cwd, ...(invocation.cwd.at(-1) === 47 ? [] : [47]), ...value]));
364
- }
365
- async function retainOutput(object, identity) {
366
- if (!options.effects || !options.retainOutput || outputIdentities.has(identity))
367
- return;
368
- // Reserve identity admission before yielding: links and independent
369
- // handles may settle concurrently against the same canonical object.
370
- outputIdentities.add(identity);
371
- let output;
372
- let closeOutput;
373
- try {
374
- output = await options.retainOutput(object);
375
- closeOutput = output.close.bind(output);
376
- const outputIdentity = output.identity;
377
- // Unqualified live retrieval cannot establish cache/resume authority.
378
- // An explicit identity must designate this exact canonical object;
379
- // accepting another retain would expose unrelated storage as output.
380
- if (outputIdentity !== undefined && outputIdentity !== object.identity)
381
- throw new Error('Output retain identity does not match canonical object');
382
- output = Object.freeze({ identity: outputIdentity, freshness: output.freshness?.bind(output),
383
- stat: output.stat.bind(output), read: output.read.bind(output), close: closeOutput });
384
- options.effects.retain(identity, output);
385
- identities.get(object.identity).retainedOutput = true;
386
- }
387
- catch (error) {
388
- const cleanup = await Promise.allSettled([Promise.resolve().then(() => closeOutput?.())]);
389
- options.effects.failRetrieval(identity, cleanup[0].status === 'rejected' ? new AggregateError([error, cleanup[0].reason], 'Output retain failed') : error);
390
- }
391
- }
392
- const access = async (credential, raw) => {
393
- function admit(raw) {
394
- if (credential !== options.credential || raw.sessionId !== invocation.sessionId || raw.epoch !== invocation.epoch || raw.jobId !== jobId)
395
- throw new Error('Unauthorized file callback');
396
- for (const value of [raw.callbackId, raw.fileId, raw.stage])
397
- if (typeof value !== 'string' || !value.length || value.length > 256)
398
- throw new TypeError('Incomplete file callback');
399
- if ('path' in raw)
400
- octets(raw.path);
401
- if ('destination' in raw)
402
- octets(raw.destination);
403
- if (raw.operation === 'descriptor-acquire') {
404
- if (!Array.isArray(raw.rights) || raw.rights.length > 4)
405
- throw new FsError('EINVAL');
406
- for (let index = 0; index < raw.rights.length; index++) {
407
- if (!Object.hasOwn(raw.rights, index) || !['read', 'write', 'seek', 'stat'].includes(raw.rights[index]))
408
- throw new FsError('EINVAL');
409
- }
410
- }
411
- if (raw.operation === 'symlink') {
412
- octets(raw.target);
413
- if (raw.target.length > maxIo)
414
- throw new FsError('EFBIG', { syscall: 'symlink' });
415
- }
416
- if (raw.operation === 'create' && raw.flag !== undefined && !['w', 'wx', 'a', 'ax'].includes(raw.flag))
417
- throw new FsError('EINVAL', { syscall: 'create' });
418
- if (raw.operation === 'create' || raw.operation === 'mkdir') {
419
- if (raw.mode !== undefined && (!Number.isSafeInteger(raw.mode) || raw.mode < 0 || raw.mode > 0o7777))
420
- throw new FsError('EINVAL', { syscall: raw.operation });
421
- }
422
- if (raw.operation === 'path-access' && raw.mode !== undefined
423
- && (!Number.isSafeInteger(raw.mode) || raw.mode < 0 || raw.mode > 7))
424
- throw new FsError('EINVAL', { syscall: 'access' });
425
- if (raw.operation === 'capabilities') {
426
- for (const value of [raw.create, raw.allowDirectory])
427
- if (value !== undefined && typeof value !== 'boolean')
428
- throw new FsError('EINVAL', { syscall: 'capabilities' });
429
- }
430
- // Enforce transfer admission before retaining/copying the caller's frame.
431
- // The authenticated transport still owns aggregate queue/wire budgets.
432
- if (raw.operation === 'write' || raw.operation === 'append' || raw.operation === 'descriptor-write') {
433
- if (!(raw.bytes instanceof Uint8Array) && (!Array.isArray(raw.bytes) || raw.operation === 'descriptor-write'))
434
- throw new FsError('EINVAL');
435
- const span = raw.bytes instanceof Uint8Array
436
- ? Object.getOwnPropertyDescriptor(Object.getPrototypeOf(Uint8Array.prototype), 'byteLength').get.call(raw.bytes)
437
- : raw.bytes.length;
438
- if (span > maxIo)
439
- throw new FsError('EINVAL');
440
- if (!(raw.bytes instanceof Uint8Array))
441
- for (let index = 0; index < span; index++) {
442
- if (!Object.hasOwn(raw.bytes, index))
443
- throw new FsError('EINVAL');
444
- const byte = raw.bytes[index];
445
- if (!Number.isInteger(byte) || byte < 0 || byte > 255)
446
- throw new FsError('EINVAL');
447
- }
448
- }
449
- if (raw.operation === 'read' || raw.operation === 'descriptor-read') {
450
- if (!Number.isSafeInteger(raw.maxBytes) || raw.maxBytes < 0 || raw.maxBytes > maxIo)
451
- throw new FsError('EINVAL');
452
- }
453
- }
454
- admit(raw);
455
- if (closed)
456
- throw new JobCallbackRecoveryError(invocation.sessionId, invocation.epoch, jobId);
457
- // Only callback contract fields participate in admission and replay.
458
- // Private driver extensions may lazily acquire scratch storage; copying
459
- // them would turn staging into authority or expose speculative failures.
460
- const callbackFields = ['sessionId', 'epoch', 'jobId', 'callbackId', 'fileId', 'stage',
461
- 'operation', 'fd', 'rights', 'handle', 'maxBytes', 'bytes', 'position', 'path',
462
- 'access', 'flag', 'mode', 'length', 'destination', 'create', 'allowDirectory', 'changes', 'target'];
463
- const request = structuredClone(Object.fromEntries(callbackFields
464
- .filter(field => Object.hasOwn(raw, field))
465
- .map(field => {
466
- const value = Reflect.get(raw, field);
467
- // Path/rights/payload carriers authorize only their own indexed
468
- // values. Private enumerable getters can acquire live dependencies;
469
- // structuredClone must never evaluate them at this access stage.
470
- if (['path', 'destination', 'target', 'rights', 'bytes'].includes(field) && Array.isArray(value)) {
471
- const length = value.length;
472
- const limit = field === 'rights' ? 4 : field === 'bytes' ? maxIo : 1048576;
473
- if (length > limit)
474
- throw new FsError('EINVAL');
475
- const owned = Array.from({ length }, (_, index) => {
476
- if (!Object.hasOwn(value, index))
477
- throw new FsError('EINVAL');
478
- return value[index];
479
- });
480
- // A late dependency or payload appended during indexed copying
481
- // cannot authorize its truncated prefix or enter the replay ledger.
482
- if (value.length !== length)
483
- throw new FsError('EINVAL');
484
- return [field, owned];
485
- }
486
- return [field, value];
487
- })));
488
- // Copying may observe accessor-backed structural host inputs again.
489
- // Only the owned, reauthorized frame may enter replay storage or queues.
490
- admit(request);
491
- // Binary payload identity is its octets, not the host carrier chosen by
492
- // a transport on replay. Keep all access metadata in the replay key.
493
- // Transport object-member order is not file/job identity. Normalize
494
- // records, including metadata changes, while preserving octet order.
495
- const body = JSON.stringify('bytes' in request
496
- ? { ...request, bytes: Array.from(request.bytes) } : request, (_key, value) => value && typeof value === 'object' && !Array.isArray(value)
497
- ? Object.fromEntries(Object.keys(value).sort().map(key => [key, value[key]])) : value);
498
- const previous = callbacks.get(request.callbackId);
499
- if (previous) {
500
- if (previous.body !== body)
501
- throw new Error('Callback identity conflict');
502
- return structuredClone(await previous.result);
503
- }
504
- if (callbacks.size >= options.maxCallbacks)
505
- throw new Error('Callback limit');
506
- // Independent open descriptions must be able to unblock each other.
507
- // Live observations and acquisitions must not block a writer that can
508
- // settle their upstream work. Serialize namespace changes and each handle;
509
- // descriptor duplicates additionally share their canonical cursor queue.
510
- const queue = 'handle' in request ? request.handle
511
- : ['open', 'create', 'descriptor-acquire', 'path-stat', 'path-lstat', 'path-access', 'realpath', 'readlink', 'readdir', 'capabilities'].includes(request.operation)
512
- ? `observation:${request.callbackId}` : 'namespace';
513
- const result = (queues.get(queue) ?? Promise.resolve()).then(async () => {
514
- let releaseEffect;
515
- let acquisitionReserved = false;
516
- const namespaceObservation = namespaceChanges.length;
517
- try {
518
- signal.throwIfAborted();
519
- if (request.operation === 'open' || request.operation === 'create' || request.operation === 'descriptor-acquire') {
520
- if (handles.size + descriptorOwners.size + closingHandles + acquiringHandles >= options.maxHandles)
521
- throw new FsError('EMFILE', { syscall: request.operation });
522
- acquiringHandles++;
523
- acquisitionReserved = true;
524
- }
525
- if (request.operation === 'descriptor-acquire') {
526
- if (!descriptors)
527
- throw new FsError('ENOTSUP');
528
- const opened = await descriptors.acquire(request.fd, request.rights, signal);
529
- descriptorOwners.set(opened.handle, request.fileId);
530
- acquiringHandles--;
531
- acquisitionReserved = false;
532
- return opened;
533
- }
534
- if (request.operation === 'descriptor-read' || request.operation === 'descriptor-write'
535
- || request.operation === 'descriptor-seek' || request.operation === 'descriptor-stat' || request.operation === 'descriptor-close') {
536
- if (!descriptors || descriptorOwners.get(request.handle) !== request.fileId)
537
- throw new FsError('EBADF');
538
- if (request.operation === 'descriptor-read')
539
- return descriptors.read(request.handle, request.maxBytes, signal);
540
- if (request.operation === 'descriptor-write')
541
- return descriptors.write(request.handle, request.bytes, signal);
542
- if (request.operation === 'descriptor-seek')
543
- return descriptors.seek(request.handle, request.position, signal);
544
- if (request.operation === 'descriptor-stat')
545
- return descriptors.stat(request.handle, signal);
546
- descriptorOwners.delete(request.handle);
547
- closingHandles++;
548
- try {
549
- return await descriptors.close(request.handle, signal);
550
- }
551
- finally {
552
- closingHandles--;
553
- }
554
- }
555
- const fs = source;
556
- const effect = (value) => options.effects?.record({ ...value, callbackId: request.callbackId, stage: request.stage });
557
- // Opens also publish identity observations. Reserve their receipt
558
- // before acquisition so concurrent observations cannot consume the
559
- // slot promised to an already admitted canonical mutation.
560
- if (['open', 'create', 'mkdir', 'rmdir', 'write', 'append', 'truncate', 'metadata', 'rename', 'unlink', 'link', 'symlink'].includes(request.operation)) {
561
- releaseEffect = options.effects?.reserve(request.operation === 'write' || request.operation === 'append' ? request.bytes.length : 0);
562
- }
563
- if (request.operation === 'rmdir') {
564
- if (!canonical.rmdir)
565
- throw new FsError('ENOTSUP', { syscall: 'rmdir' });
566
- const removedPath = Array.from(path(request.path).bytes());
567
- let logical;
568
- try {
569
- logical = new TextDecoder('utf-8', { fatal: true, ignoreBOM: true }).decode(Uint8Array.from(removedPath));
570
- }
571
- catch {
572
- throw new FsError('EILSEQ', { syscall: 'rmdir' });
573
- }
574
- const capabilities = canonical.capabilitiesFor
575
- ? await canonical.capabilitiesFor(logical, { signal, allowDirectory: true })
576
- : sourceAdmission.capabilities;
577
- let observed;
578
- // Retain the issued policy facet, but observe its live values at
579
- // access time. Invalid selected-mount responses must never fall
580
- // through to a weaker global profile or authorize removal.
581
- if (capabilities !== undefined || canonical.capabilitiesFor) {
582
- observed = admitCanonicalCapabilities(capabilities, 'rmdir', logical);
583
- }
584
- // Snapshot-marker removal cannot reproduce native empty-only rmdir.
585
- // A mount query selects the actual path's profile, not the summary.
586
- if (observed?.snapshotRmdir === true)
587
- throw new FsError('ENOTSUP', { syscall: 'rmdir', path: logical });
588
- signal.throwIfAborted();
589
- await canonical.rmdir(logical, { signal });
590
- namespaceChanges.push({ callbackId: request.callbackId, path: removedPath });
591
- effect({ operation: 'rmdir', path: removedPath });
592
- for (const value of handles.values())
593
- if (JSON.stringify(value.path) === JSON.stringify(removedPath))
594
- value.path = undefined;
595
- return;
596
- }
597
- if (request.operation === 'symlink') {
598
- if (!canonical.symlink)
599
- throw new FsError('ENOTSUP', { syscall: 'symlink' });
600
- const destination = path(request.path).bytes();
601
- let logical;
602
- let target;
603
- try {
604
- const decoder = new TextDecoder('utf-8', { fatal: true, ignoreBOM: true });
605
- logical = decoder.decode(destination);
606
- target = decoder.decode(Uint8Array.from(request.target));
607
- }
608
- catch {
609
- throw new FsError('EILSEQ', { syscall: 'symlink' });
610
- }
611
- await canonical.symlink(target, logical, { signal });
612
- const linkedPath = Array.from(destination);
613
- namespaceChanges.push({ callbackId: request.callbackId, path: linkedPath });
614
- for (const value of handles.values())
615
- if (JSON.stringify(value.path) === JSON.stringify(linkedPath))
616
- value.path = undefined;
617
- effect({ operation: 'symlink', path: linkedPath, target: request.target });
618
- return;
619
- }
620
- if (request.operation === 'mkdir') {
621
- if (!canonical.mkdir)
622
- throw new FsError('ENOTSUP', { syscall: 'mkdir' });
623
- let logical;
624
- try {
625
- logical = new TextDecoder('utf-8', { fatal: true, ignoreBOM: true }).decode(path(request.path).bytes());
626
- }
627
- catch {
628
- throw new FsError('EILSEQ', { syscall: 'mkdir' });
629
- }
630
- await canonical.mkdir(logical, { signal, ...(request.mode === undefined ? {} : { mode: request.mode }) });
631
- namespaceChanges.push({ callbackId: request.callbackId, path: Array.from(path(request.path).bytes()) });
632
- effect({ operation: 'mkdir', path: Array.from(path(request.path).bytes()), ...(request.mode === undefined ? {} : { mode: request.mode }) });
633
- return;
634
- }
635
- if (request.operation === 'open' || request.operation === 'create') {
636
- if (request.access !== undefined && !['read', 'write', 'readwrite'].includes(request.access))
637
- throw new TypeError('Invalid file access');
638
- let object;
639
- let creation;
640
- if (request.operation === 'open') {
641
- if (!open)
642
- throw new FsError('ENOTSUP', { syscall: 'open' });
643
- object = await open(path(request.path), { access: request.access ?? 'read', signal });
644
- }
645
- else if (fs.create) {
646
- const acquired = await fs.create(path(request.path), { flag: request.flag ?? 'w', access: request.access ?? 'read', ...(request.mode === undefined ? {} : { mode: request.mode }), signal });
647
- object = acquired;
648
- }
649
- else {
650
- // Native acquisition always requires the canonical flag/disposition
651
- // primitive, including the default truncating flag. A legacy hook
652
- // cannot prove creation, preserve exclusivity or acknowledge truncate.
653
- throw new FsError('ENOTSUP', { syscall: 'create' });
654
- }
655
- // Own cleanup before inspecting any backend admission properties.
656
- // A receipt/identity getter can fail after canonical truncation or
657
- // creation; neither that failure nor a changed method table may
658
- // abandon the acquired retain or redirect its cleanup.
659
- const close = object.close.bind(object);
660
- try {
661
- if (request.operation === 'create') {
662
- creation = object.creation;
663
- if (creation === 'created')
664
- namespaceChanges.push({ callbackId: request.callbackId, path: Array.from(path(request.path).bytes()) });
665
- // A disposition receipt must qualify this exact native flag.
666
- // Do not infer exclusivity or truncation from a later stat.
667
- // Rejected receipts still report completed canonical effects
668
- // through the acquisition cleanup below; nothing rolls back.
669
- const flag = request.flag ?? 'w';
670
- if (creation !== 'created' && !(flag === 'w' && creation === 'truncated')
671
- && !(flag === 'a' && creation === 'opened'))
672
- throw new FsError('EIO', { syscall: 'create' });
673
- }
674
- // Retain the acquired capability, not its mutable public method table.
675
- // Bound receivers keep live backend state; no content is snapshotted.
676
- const admittedAccess = request.access ?? 'read';
677
- object = Object.freeze({
678
- identity: object.identity, type: object.type,
679
- stat: object.stat?.bind(object), close,
680
- read: admittedAccess !== 'write' ? object.read?.bind(object) : undefined,
681
- write: admittedAccess !== 'read' ? object.write?.bind(object) : undefined,
682
- append: admittedAccess !== 'read' ? object.append?.bind(object) : undefined,
683
- truncate: admittedAccess !== 'read' ? object.truncate?.bind(object) : undefined,
684
- metadata: object.metadata?.bind(object), link: object.link?.bind(object),
685
- });
686
- if (object.identity === null || !['object', 'symbol'].includes(typeof object.identity)
687
- || !['file', 'directory', 'symlink'].includes(object.type))
688
- throw new FsError('ENOTSUP');
689
- }
690
- catch (error) {
691
- // Canonical acquisition can already have created or truncated the
692
- // entry. Refusing its returned retain does not undo that effect.
693
- // No admitted identity exists here; report only the native receipt.
694
- if (creation === 'truncated')
695
- effect({ operation: 'truncate', path: Array.from(path(request.path).bytes()), length: '0' });
696
- else if (creation === 'created')
697
- effect({ operation: 'created', path: Array.from(path(request.path).bytes()) });
698
- try {
699
- await close();
700
- }
701
- catch (cleanup) {
702
- throw new AggregateError([error, cleanup], 'Rejected object cleanup failed', { cause: error });
703
- }
704
- throw error;
705
- }
706
- const handle = crypto.randomUUID();
707
- let correlation = identities.get(object.identity);
708
- if (!correlation) {
709
- correlation = { id: crypto.randomUUID(), references: 0, retainedOutput: false };
710
- identities.set(object.identity, correlation);
711
- }
712
- correlation.references++;
713
- const identity = correlation.id;
714
- const openedPath = Array.from(path(request.path).bytes());
715
- // A delayed open retains its object even if the namespace changes
716
- // before it returns. Its former spelling cannot locate later writes.
717
- const changedDuringOpen = namespaceChanges.slice(namespaceObservation).some(change => change.callbackId !== request.callbackId && (change.path === undefined
718
- || change.path.every((byte, i) => openedPath[i] === byte)
719
- && (openedPath.length === change.path.length || openedPath[change.path.length] === 47)));
720
- // A fresh canonical open can prove that a prior retained object no
721
- // longer occupies this spelling. Its IO remains on the old identity.
722
- if (!changedDuringOpen)
723
- for (const value of handles.values())
724
- if (value.identity !== identity && JSON.stringify(value.path) === JSON.stringify(openedPath))
725
- value.path = undefined;
726
- handles.set(handle, { fileId: request.fileId, object, identity, access: request.access ?? 'read', path: changedDuringOpen ? undefined : openedPath, reads: new AbortController() });
727
- acquiringHandles--;
728
- acquisitionReserved = false;
729
- // Overlapping namespace callbacks retire the acquisition spelling;
730
- // the retain still proves the created/truncated/opened identity.
731
- const effectPath = changedDuringOpen ? undefined : openedPath;
732
- if (creation === 'truncated')
733
- effect({ operation: 'truncate', path: effectPath, object: identity, length: '0' });
734
- else if (creation === 'created')
735
- effect({ operation: 'created', path: effectPath, object: identity });
736
- // Preserve the initial namespace observation even before this
737
- // identity becomes an output. A later rename can retire the handle
738
- // spelling before its first write. Projection promotes only
739
- // identities with settled mutations, so untouched inputs stay out.
740
- else
741
- effect({ operation: 'open', path: effectPath, object: identity });
742
- if (request.operation === 'create' || (request.access && request.access !== 'read'))
743
- await retainOutput(object, identity);
744
- signal.throwIfAborted();
745
- return { handle, object: identity };
746
- }
747
- if (request.operation === 'rename') {
748
- if (!fs.rename)
749
- throw new FsError('ENOTSUP', { syscall: 'rename' });
750
- const receipt = await fs.rename(path(request.path), path(request.destination), { signal });
751
- // One canonical observation governs namespace retirement, effect
752
- // publication and the replayed acknowledgment. Backend accessors
753
- // cannot substitute another outcome between these stages.
754
- const moved = receipt?.moved;
755
- const source = Array.from(path(request.path).bytes());
756
- const destination = Array.from(path(request.destination).bytes());
757
- const samePath = JSON.stringify(source) === JSON.stringify(destination);
758
- if (!samePath && moved !== false)
759
- namespaceChanges.push({ callbackId: request.callbackId });
760
- // Namespace settlement does not identify the former pathname's
761
- // occupant. An external writer may have replaced it since our open.
762
- effect({ operation: 'rename', path: source, destination, ...(samePath ? { moved: false } : typeof moved === 'boolean' ? { moved } : {}) });
763
- // Literal paths cannot prove which aliases traverse a moved parent
764
- // or displaced entry. Keep every retain and its live methods, but
765
- // retire unverified path hints, including delayed acquisitions.
766
- if (!samePath && moved !== false)
767
- for (const value of handles.values())
768
- value.path = undefined;
769
- return typeof moved === 'boolean' ? { moved } : undefined;
770
- }
771
- if (request.operation === 'unlink') {
772
- if (!fs.unlink)
773
- throw new FsError('ENOTSUP', { syscall: 'unlink' });
774
- await fs.unlink(path(request.path), { signal });
775
- const source = Array.from(path(request.path).bytes());
776
- namespaceChanges.push({ callbackId: request.callbackId });
777
- effect({ operation: 'unlink', path: source });
778
- for (const value of handles.values())
779
- value.path = undefined;
780
- return;
781
- }
782
- if (request.operation === 'readdir') {
783
- if (!fs.readdir)
784
- throw new FsError('ENOTSUP', { syscall: 'readdir' });
785
- const entries = await fs.readdir(path(request.path), { signal, maxEntries });
786
- if (!Array.isArray(entries))
787
- throw new FsError('EIO', { syscall: 'readdir' });
788
- const length = entries.length;
789
- if (length > maxEntries)
790
- throw new FsError('EFBIG', { syscall: 'readdir' });
791
- let bytes = 0;
792
- const listing = Array.from({ length }, (_, index) => {
793
- if (!Object.hasOwn(entries, index))
794
- throw new FsError('EIO', { syscall: 'readdir' });
795
- const entry = entries[index];
796
- if (!entry)
797
- throw new FsError('EIO', { syscall: 'readdir' });
798
- const { name: component, type } = entry;
799
- if (!['file', 'directory', 'symlink', 'character', 'fifo', 'socket'].includes(type))
800
- throw new FsError('EIO', { syscall: 'readdir' });
801
- // Read the genuine owned carrier, not a public override that can
802
- // replace an authoritative byte name with another spelling.
803
- let carrier;
804
- try {
805
- carrier = BytePath.prototype.bytes.call(component);
806
- }
807
- catch {
808
- throw new FsError('EIO', { syscall: 'readdir' });
809
- }
810
- if (!(carrier instanceof Uint8Array))
811
- throw new FsError('EIO', { syscall: 'readdir' });
812
- // Admit against the remaining aggregate transfer budget before
813
- // retaining a backend-owned fragment in execution memory.
814
- const span = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(Uint8Array.prototype), 'byteLength').get.call(carrier);
815
- if (span > maxIo - bytes)
816
- throw new FsError('EFBIG', { syscall: 'readdir' });
817
- const name = new Uint8Array(carrier);
818
- bytes += name.length;
819
- if (!name.length || name.includes(0) || name.includes(47)
820
- || (name.length <= 2 && name.every(byte => byte === 46)))
821
- throw new FsError('EIO', { syscall: 'readdir' });
822
- if (bytes > maxIo)
823
- throw new FsError('EFBIG', { syscall: 'readdir' });
824
- return { name: Array.from(name), type };
825
- });
826
- // Never acknowledge a prefix after backend metadata access changed
827
- // the admitted listing. This is carrier validation, not a promise
828
- // of an atomic directory snapshot against external writers.
829
- if (entries.length !== length)
830
- throw new FsError('EIO', { syscall: 'readdir' });
831
- return listing;
832
- }
833
- if (request.operation === 'capabilities' || request.operation === 'readlink'
834
- || request.operation === 'path-access' || request.operation === 'realpath'
835
- || request.operation === 'path-stat' || request.operation === 'path-lstat') {
836
- const bytes = path(request.path).bytes();
837
- let logical;
838
- try {
839
- logical = new TextDecoder('utf-8', { fatal: true, ignoreBOM: true }).decode(bytes);
840
- }
841
- catch {
842
- throw new FsError('EILSEQ', { syscall: request.operation === 'path-access' ? 'access' : request.operation });
843
- }
844
- if (request.operation === 'path-access') {
845
- if (!canonical.access)
846
- throw new FsError('ENOTSUP', { syscall: 'access' });
847
- return canonical.access(logical, request.mode ?? 0, { signal });
848
- }
849
- if (request.operation === 'realpath') {
850
- if (!canonical.realpath)
851
- throw new FsError('ENOTSUP', { syscall: 'realpath' });
852
- const resolved = await canonical.realpath(logical, { signal });
853
- if (typeof resolved !== 'string' || !resolved.startsWith('/') || resolved.includes('\0'))
854
- throw new FsError('EIO', { syscall: 'realpath' });
855
- if (resolved.length > maxIo)
856
- throw new FsError('EFBIG', { syscall: 'realpath' });
857
- const encoded = new TextEncoder().encode(resolved);
858
- if (encoded.length > maxIo)
859
- throw new FsError('EFBIG', { syscall: 'realpath' });
860
- if (new TextDecoder('utf-8', { fatal: true, ignoreBOM: true }).decode(encoded) !== resolved)
861
- throw new FsError('EILSEQ', { syscall: 'realpath' });
862
- return Array.from(encoded);
863
- }
864
- if (request.operation === 'path-stat' || request.operation === 'path-lstat') {
865
- const method = request.operation === 'path-stat' ? 'stat' : 'lstat';
866
- if (!canonical[method])
867
- throw new FsError('ENOTSUP', { syscall: method });
868
- // Path metadata is an observation, never retained wire identity.
869
- return admitCanonicalMetadata(await canonical[method](logical, { signal }), method);
870
- }
871
- if (request.operation === 'capabilities') {
872
- if (!canonical.capabilitiesFor && sourceAdmission.capabilities === undefined)
873
- throw new FsError('ENOTSUP', { syscall: 'capabilities' });
874
- const capabilities = canonical.capabilitiesFor ? await canonical.capabilitiesFor(logical, { signal,
875
- ...(request.create === undefined ? {} : { create: request.create }),
876
- ...(request.allowDirectory === undefined ? {} : { allowDirectory: request.allowDirectory }) }) : sourceAdmission.capabilities;
877
- const observed = admitCanonicalCapabilities(capabilities, 'capabilities', logical, maxIo);
878
- // A legacy backend guarantee alone cannot admit an operation on
879
- // this retained-object route. Method presence is necessary, never
880
- // sufficient: keep unknown/false guarantees and only narrow true.
881
- // Do not acquire a file merely to probe its optional handle methods.
882
- const namespaceSupport = {
883
- // Descriptor-only jobs need no pathname acquisition. Legacy
884
- // read/resize guarantees cannot qualify a missing object route;
885
- // refuse at the actual access without consulting scratch files.
886
- read: !!fs.open,
887
- streamingRead: !!fs.open,
888
- retainedRead: !!fs.open,
889
- truncate: !!fs.open,
890
- retainedResize: !!fs.open,
891
- readdir: !!fs.readdir,
892
- // Ordinary writes and append streams may create a missing
893
- // file. Writable existing retains alone cannot supply those
894
- // routes, even if legacy pathname methods advertise them.
895
- write: !!fs.create,
896
- append: !!fs.create,
897
- streamingWrite: !!fs.create,
898
- streamingAppend: !!fs.create,
899
- descriptorWriteStream: !!fs.create,
900
- // safe-fs defines this legacy flag as eligibility for the
901
- // shell's bounded whole-file offset replacement strategy.
902
- // It cannot qualify retained positional writes, large offsets
903
- // or sparse allocation. Actual writes use the admitted object
904
- // operation and preserve its ENOTSUP/EFBIG/partial receipts.
905
- randomAccessWrite: false,
906
- exclusiveCreate: !!fs.create,
907
- rename: !!fs.rename,
908
- atomicRename: !!fs.rename,
909
- mkdir: !!canonical.mkdir,
910
- remove: !!fs.unlink,
911
- removeDirectory: !!canonical.rmdir && observed.snapshotRmdir !== true,
912
- readlink: !!canonical.readlink,
913
- symlinks: !!canonical.symlink,
914
- stat: !!canonical.stat && !!canonical.lstat,
915
- access: !!canonical.access,
916
- realpath: !!canonical.realpath,
917
- // The byte rename contract has no no-replace precondition.
918
- atomicRenameNoReplace: false,
919
- // These require canonical primitives absent from this route.
920
- // A sequence of retained writes or namespace callbacks cannot
921
- // inherit a legacy backend's compound/atomic guarantee.
922
- copy: false,
923
- exclusiveCopy: false,
924
- recursiveMkdir: false,
925
- recursiveRemove: false,
926
- atomicFileStaging: false,
927
- atomicFileMutation: false,
928
- atomicDirectoryMetadata: false,
929
- atomicResize: false,
930
- };
931
- for (const [capability, supported] of Object.entries(namespaceSupport)) {
932
- if (observed[capability] === true && !supported)
933
- observed[capability] = false;
934
- }
935
- if (observed.readOnly === true) {
936
- for (const capability of ['write', 'append', 'truncate', 'streamingWrite', 'streamingAppend', 'descriptorWriteStream', 'randomAccessWrite', 'exclusiveCreate', 'mkdir', 'recursiveMkdir', 'remove', 'removeDirectory', 'recursiveRemove', 'rename', 'copy', 'exclusiveCopy', 'symlinks', 'hardlinks', 'permissions', 'timestamps', 'atomicRename', 'atomicRenameNoReplace', 'atomicFileStaging', 'atomicFileMutation', 'atomicDirectoryMetadata', 'atomicResize', 'retainedResize']) {
937
- if (observed[capability] === true)
938
- observed[capability] = false;
939
- }
940
- }
941
- // Narrowing true guarantees to false adds one JSON octet per
942
- // member. Bound the final reply as well as backend admission.
943
- if (new TextEncoder().encode(JSON.stringify(observed)).length > maxIo)
944
- throw new FsError('EFBIG', { syscall: 'capabilities', path: logical });
945
- return observed;
946
- }
947
- if (!canonical.readlink)
948
- throw new FsError('ENOTSUP', { syscall: 'readlink' });
949
- const spelling = await canonical.readlink(logical, { signal });
950
- if (typeof spelling !== 'string' || !spelling.length || spelling.includes('\0'))
951
- throw new FsError('EIO', { syscall: 'readlink' });
952
- // UTF-8 encoding replaces unpaired UTF-16 surrogates. A legacy
953
- // string backend cannot authorize those manufactured target bytes.
954
- // Bound the string before allocating its binary representation.
955
- if (spelling.length > maxIo)
956
- throw new FsError('EFBIG', { syscall: 'readlink' });
957
- const target = new TextEncoder().encode(spelling);
958
- if (target.length > maxIo)
959
- throw new FsError('EFBIG', { syscall: 'readlink' });
960
- if (new TextDecoder('utf-8', { fatal: true, ignoreBOM: true }).decode(target) !== spelling)
961
- throw new FsError('EILSEQ', { syscall: 'readlink' });
962
- return Array.from(target);
963
- }
964
- const retained = handles.get(request.handle);
965
- if (!retained || retained.fileId !== request.fileId)
966
- throw new FsError('EBADF');
967
- const object = retained.object;
968
- if (request.operation === 'close') {
969
- handles.delete(request.handle);
970
- closingHandles++;
971
- try {
972
- return await object.close();
973
- }
974
- finally {
975
- closingHandles--;
976
- const correlation = identities.get(object.identity);
977
- if (--correlation.references === 0 && !correlation.retainedOutput)
978
- identities.delete(object.identity);
979
- }
980
- }
981
- if (request.operation === 'stat') {
982
- if (!object.stat)
983
- throw new FsError('ENOTSUP', { syscall: 'stat' });
984
- // ExactFileStat is structural: native backends may return prototype
985
- // accessors. Observe only contract fields, once, at this fstat stage;
986
- // enumerable private state is neither metadata nor wire authority.
987
- const { type, size, allocatedBytes, nlink, mode, uid, gid, atimeNs, mtimeNs, ctimeNs } = await object.stat({ signal });
988
- const observed = { type, size, allocatedBytes, nlink, mode, uid, gid, atimeNs, mtimeNs, ctimeNs };
989
- if (observed.type !== object.type)
990
- throw new FsError('EIO', { syscall: 'stat' });
991
- try {
992
- encodeFileMetadata(observed);
993
- }
994
- catch {
995
- throw new FsError('EIO', { syscall: 'stat' });
996
- }
997
- // Object correlation comes from the admitted retain. Backend identity
998
- // scopes and device/inode pairs cannot grant wire authority.
999
- return observed;
1000
- }
1001
- if (request.operation === 'read') {
1002
- if (retained.access === 'write')
1003
- throw new FsError('EBADF');
1004
- if (!Number.isSafeInteger(request.maxBytes) || request.maxBytes < 0 || request.maxBytes > maxIo)
1005
- throw new FsError('EINVAL');
1006
- if (!object.read)
1007
- throw new FsError('ENOTSUP', { syscall: 'read' });
1008
- const readSignal = AbortSignal.any([signal, reads.signal, retained.reads.signal]);
1009
- readSignal.throwIfAborted();
1010
- const bytes = await object.read(decodeFileOffset(request.position), request.maxBytes, { signal: readSignal });
1011
- if (!(bytes instanceof Uint8Array))
1012
- throw new FsError('EIO', { syscall: 'read' });
1013
- const span = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(Uint8Array.prototype), 'byteLength').get.call(bytes);
1014
- if (span > request.maxBytes)
1015
- throw new FsError('EIO', { syscall: 'read' });
1016
- return new Uint8Array(bytes);
1017
- }
1018
- if (request.operation === 'write' || request.operation === 'append') {
1019
- if (retained.access === 'read')
1020
- throw new FsError('EBADF');
1021
- if (!(request.bytes instanceof Uint8Array) && !Array.isArray(request.bytes))
1022
- throw new FsError('EINVAL');
1023
- if (request.bytes.length > maxIo)
1024
- throw new FsError('EINVAL');
1025
- if (!(request.bytes instanceof Uint8Array))
1026
- for (const n of request.bytes)
1027
- if (!Number.isInteger(n) || n < 0 || n > 255)
1028
- throw new FsError('EINVAL');
1029
- const owned = Uint8Array.from(request.bytes);
1030
- let count;
1031
- if (request.operation === 'append') {
1032
- if (!object.append)
1033
- throw new FsError('ENOTSUP', { syscall: 'append' });
1034
- count = await object.append(owned, { signal });
1035
- }
1036
- else {
1037
- if (!object.write)
1038
- throw new FsError('ENOTSUP', { syscall: 'write' });
1039
- count = await object.write(decodeFileOffset(request.position), owned, { signal });
1040
- }
1041
- if (!Number.isSafeInteger(count) || count < 0 || count > request.bytes.length)
1042
- throw new FsError('EIO', { syscall: request.operation });
1043
- effect({ operation: request.operation, object: retained.identity, path: retained.path, ...(request.operation === 'write' ? { position: request.position } : {}), bytes: Array.from(request.bytes).slice(0, count), count });
1044
- return count;
1045
- }
1046
- if (request.operation === 'truncate') {
1047
- if (retained.access === 'read')
1048
- throw new FsError('EBADF');
1049
- if (!object.truncate)
1050
- throw new FsError('ENOTSUP', { syscall: 'truncate' });
1051
- await object.truncate(decodeFileOffset(request.length), { signal });
1052
- effect({ operation: 'truncate', object: retained.identity, path: retained.path, length: request.length });
1053
- return;
1054
- }
1055
- if (request.operation === 'metadata') {
1056
- if (!object.metadata)
1057
- throw new FsError('ENOTSUP');
1058
- await object.metadata(decodeObjectMetadata(request.changes), { signal });
1059
- effect({ operation: 'metadata', object: retained.identity, path: retained.path, changes: request.changes });
1060
- await retainOutput(object, retained.identity);
1061
- return;
1062
- }
1063
- if (request.operation === 'link') {
1064
- if (!object.link)
1065
- throw new FsError('ENOTSUP', { syscall: 'link' });
1066
- const destination = path(request.destination);
1067
- await object.link(destination, { signal });
1068
- const linkedPath = Array.from(destination.bytes());
1069
- namespaceChanges.push({ callbackId: request.callbackId, path: linkedPath });
1070
- // A settled link proves which object occupies this new spelling.
1071
- // Other retained identities still live, but their old path hint may
1072
- // have become stale through an external namespace operation.
1073
- for (const value of handles.values())
1074
- if (value.identity !== retained.identity && JSON.stringify(value.path) === JSON.stringify(linkedPath))
1075
- value.path = undefined;
1076
- effect({ operation: 'link', object: retained.identity, destination: linkedPath });
1077
- await retainOutput(object, retained.identity);
1078
- return;
1079
- }
1080
- throw new FsError('ENOTSUP');
1081
- }
1082
- finally {
1083
- if (acquisitionReserved)
1084
- acquiringHandles--;
1085
- releaseEffect?.();
1086
- }
1087
- }).then(value => structuredClone(value));
1088
- callbacks.set(request.callbackId, { body, result });
1089
- const settled = result.catch(() => { });
1090
- queues.set(queue, settled);
1091
- pending.add(settled);
1092
- void settled.then(() => {
1093
- pending.delete(settled);
1094
- if (queues.get(queue) === settled)
1095
- queues.delete(queue);
1096
- });
1097
- // Publish replay and cursor barriers before abort listeners can reenter.
1098
- // Waiting to cancel inside the queued close deadlocks behind an idle
1099
- // upstream read. Only the authenticated owner can retire this consumer.
1100
- if (request.operation === 'descriptor-close' && descriptorOwners.get(request.handle) === request.fileId)
1101
- descriptors?.retireReads(request.handle);
1102
- if (request.operation === 'close') {
1103
- const retained = handles.get(request.handle);
1104
- if (retained?.fileId === request.fileId)
1105
- retained.reads.abort(new FsError('EBADF'));
1106
- }
1107
- return structuredClone(await result);
1108
- };
1109
- let primary;
1110
- const dispose = async () => {
1111
- closed = true;
1112
- reads.abort(new FsError('EBADF'));
1113
- descriptors?.retireReads();
1114
- await Promise.all([...pending]);
1115
- const cleanup = await Promise.allSettled([...handles.values()].map(({ object }) => Promise.resolve().then(() => object.close())));
1116
- cleanup.push(...await Promise.allSettled([...endpointLeases].map(lease => lease.close())));
1117
- cleanup.push(...await Promise.allSettled([descriptors?.dispose()]));
1118
- descriptorOwners.clear();
1119
- handles.clear();
1120
- callbacks.clear();
1121
- identities.clear();
1122
- queues.clear();
1123
- if (acquiredWorkspace)
1124
- cleanup.push(...await Promise.allSettled([Promise.resolve().then(() => options.release?.(workspace ?? acquiredWorkspace, acquiredWorkspace))]));
1125
- const failures = cleanup.filter(result => result.status === 'rejected');
1126
- if (failures.length) {
1127
- const error = new AggregateError([...(primary ? [primary.cause] : []), ...failures.map(result => result.reason)], 'Job handle cleanup failed', primary);
1128
- throw options.effects ? new JobEffectsError(error, options.effects.inspect()) : error;
1129
- }
1130
- };
1131
- try {
1132
- // Own the acquisition before snapshot admission can fail. Cancellation
1133
- // during preparation still retires the late workspace and keeps its cause.
1134
- acquiredWorkspace = await options.prepare(structuredClone(invocation), signal);
1135
- signal.throwIfAborted();
1136
- const acquired = acquiredWorkspace;
1137
- // Snapshot the public binding, not private driver capabilities. Retain
1138
- // those capabilities for release without letting mutable IDs redirect it.
1139
- const snapshot = () => {
1140
- // Observe each public field once. Reading it again after admission
1141
- // could replace a stale revision or incomplete tree with a ready one.
1142
- const publicFields = [...fields, 'cwd', 'originalArgv', 'state', 'entries', 'readiness'];
1143
- const publicDescriptors = Object.fromEntries(publicFields
1144
- .map(key => [key, Object.getOwnPropertyDescriptor(acquired, key)]));
1145
- const observed = Object.fromEntries(publicFields.map(key => [key, Reflect.get(acquired, key)]));
1146
- const entryCount = observed.entries?.length;
1147
- const entryRecords = [];
1148
- const entryDescriptors = [];
1149
- const entrySlots = [];
1150
- // Private driver accessors may acquire scratch storage or do advisory
1151
- // work. They are not admission evidence and must never run as part of
1152
- // startup or revalidation. Preserve inert extension values for cleanup;
1153
- // the exact acquired capability remains the second release argument.
1154
- const extensions = Object.fromEntries(Object.entries(Object.getOwnPropertyDescriptors(acquired))
1155
- .filter(([key, descriptor]) => !publicFields.includes(key) && descriptor.enumerable && 'value' in descriptor)
1156
- .map(([key, descriptor]) => [key, descriptor.value]));
1157
- const captured = { ...extensions, ...observed, ...structuredClone({
1158
- ...Object.fromEntries(fields.map(field => [field, observed[field]])),
1159
- ...ownNativeProcessView(observed.cwd, observed.originalArgv),
1160
- state: observed.state,
1161
- // Records may also contain lazy acquisition/failure capabilities.
1162
- // Read only the metadata used to admit the starting tree, both now
1163
- // and after live validation; speculative payloads are not evidence.
1164
- // Driver iterators and inherited slots cannot replace the records
1165
- // belonging to the acquired starting tree.
1166
- entries: Array.isArray(observed.entries) ? Array.from({ length: observed.entries.length }, (_, index) => {
1167
- if (!Object.hasOwn(observed.entries, index))
1168
- throw new Error('Incomplete or stale job materialization');
1169
- entrySlots.push(Object.getOwnPropertyDescriptor(observed.entries, index));
1170
- const entry = observed.entries[index];
1171
- entryRecords.push(entry);
1172
- if (!entry)
1173
- return entry;
1174
- entryDescriptors[index] = Object.fromEntries(['state', 'kind', 'index']
1175
- .map(key => [key, Object.getOwnPropertyDescriptor(entry, key)]));
1176
- const { state, kind } = entry;
1177
- // Manifest indexes are required-work identity, not advisory
1178
- // acquisition payload. Never inspect speculative index accessors.
1179
- const manifestIndex = kind === undefined || kind === 'required' ? entry.index : undefined;
1180
- return { state, ...(kind === undefined ? {} : { kind }), ...(manifestIndex === undefined ? {} : { index: manifestIndex }) };
1181
- }) : observed.entries,
1182
- readiness: snapshotReadiness(observed.readiness),
1183
- }) };
1184
- // Later metadata observations must not replace an earlier binding
1185
- // field or either ledger. Inspect property descriptors without invoking
1186
- // driver getters again: a second getter result is not fresh authority.
1187
- for (const key of publicFields) {
1188
- if (!unchangedMetadata(acquired, key, publicDescriptors[key], Reflect.get(observed, key)))
1189
- throw new Error('Incomplete or stale job materialization');
1190
- }
1191
- // A metadata accessor can add required work while either ledger is
1192
- // copied. Never admit a prefix as the complete installed tree.
1193
- if (observed.entries?.length !== entryCount)
1194
- throw new Error('Incomplete or stale job materialization');
1195
- for (let index = 0; index < entryRecords.length; index++) {
1196
- const record = entryRecords[index];
1197
- if (!unchangedMetadata(observed.entries, String(index), entrySlots[index], record))
1198
- throw new Error('Incomplete or stale job materialization');
1199
- if (!record)
1200
- continue;
1201
- const entry = captured.entries[index];
1202
- // Advisory indexes are acquisition payloads, not startup evidence.
1203
- const keys = entry.kind === undefined || entry.kind === 'required'
1204
- ? ['state', 'kind', 'index'] : ['state', 'kind'];
1205
- for (const key of keys) {
1206
- if (!unchangedMetadata(record, key, entryDescriptors[index][key], entry[key]))
1207
- throw new Error('Incomplete or stale job materialization');
1208
- }
1209
- }
1210
- return captured;
1211
- };
1212
- workspace = snapshot();
1213
- signal.throwIfAborted();
1214
- assertRequiredReadiness(workspace.readiness);
1215
- if (fields.some(field => workspace[field] !== invocation[field]) || workspace.state !== 'ready'
1216
- || !completeStartingEntries(workspace.entries)
1217
- || JSON.stringify(workspace.cwd) !== JSON.stringify(invocation.cwd)
1218
- || JSON.stringify(workspace.originalArgv) !== JSON.stringify(invocation.originalArgv))
1219
- throw new Error('Incomplete or stale job materialization');
1220
- if (options.validate) {
1221
- await options.validate({ workspace: acquired, invocation: structuredClone(invocation), signal });
1222
- signal.throwIfAborted();
1223
- const current = snapshot();
1224
- assertRequiredReadiness(current.readiness, workspace.readiness);
1225
- // Revalidation may observe drift, but cannot replace the pinned binding
1226
- // or remove required entries to manufacture a complete starting tree.
1227
- if (fields.some(field => current[field] !== workspace[field])
1228
- || current.state !== 'ready'
1229
- || !completeStartingEntries(current.entries)
1230
- || JSON.stringify(current.cwd) !== JSON.stringify(workspace.cwd)
1231
- || JSON.stringify(current.originalArgv) !== JSON.stringify(workspace.originalArgv)
1232
- || requiredEntryIdentity(current.entries) !== requiredEntryIdentity(workspace.entries))
1233
- throw new Error('Incomplete or stale job materialization');
1234
- workspace = current;
1235
- }
1236
- // Reading the driver's live readiness can itself observe lease loss.
1237
- // Finish that admission work before checking cancellation at launch.
1238
- signal.throwIfAborted();
1239
- const result = await options.run({ jobId, invocation: structuredClone(invocation), readiness: structuredClone(workspace.readiness), signal, access, openEndpoint });
1240
- const exitCode = result?.exitCode;
1241
- if (!Number.isInteger(exitCode) || exitCode < 0 || exitCode > 255)
1242
- throw new TypeError('Invalid native exit status');
1243
- // Completion is also the effect barrier: stop admitting callbacks before
1244
- // draining those already accepted. Their canonical effects remain live
1245
- // and acknowledged individually, regardless of the native exit code.
1246
- closed = true;
1247
- reads.abort(new FsError('EBADF'));
1248
- descriptors?.retireReads();
1249
- await Promise.all([...pending]);
1250
- options.effects?.settle({ state: 'exited', exitCode });
1251
- signal.throwIfAborted();
1252
- return { exitCode };
1253
- }
1254
- catch (cause) {
1255
- primary = { cause };
1256
- closed = true;
1257
- reads.abort(new FsError('EBADF'));
1258
- descriptors?.retireReads();
1259
- await Promise.all([...pending]);
1260
- if (options.effects?.inspect().native.state === 'running')
1261
- options.effects.settle({ state: signal.aborted ? 'cancelled' : 'failed', error: cause instanceof Error ? cause.message : String(cause) });
1262
- throw options.effects ? new JobEffectsError(cause, options.effects.inspect()) : cause;
1263
- }
1264
- finally {
1265
- await dispose();
1266
- }
1267
- },
1268
- };
1269
- }