@theokit/sdk 5.14.0 → 5.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (212) hide show
  1. package/CHANGELOG.md +23 -0
  2. package/dist/{agent-Dfw3VsIX.d.ts → agent-B6C9i_qu.d.ts} +23 -213
  3. package/dist/{agent-DExqjqYy.d.cts → agent-B6FQad6P.d.cts} +23 -213
  4. package/dist/{agent-T34LCGQM.js → agent-DRDGUU6T.js} +18 -17
  5. package/dist/{agent-T34LCGQM.js.map → agent-DRDGUU6T.js.map} +1 -1
  6. package/dist/{agent-TL4K7BTG.cjs → agent-VI2HITPT.cjs} +19 -18
  7. package/dist/{agent-TL4K7BTG.cjs.map → agent-VI2HITPT.cjs.map} +1 -1
  8. package/dist/agent.d.ts +2 -3
  9. package/dist/{batch-EP3FCL6D.js → batch-N2XDYZED.js} +4 -4
  10. package/dist/{batch-EP3FCL6D.js.map → batch-N2XDYZED.js.map} +1 -1
  11. package/dist/{batch-IZ5EDKJ5.cjs → batch-VFR2MAUE.cjs} +7 -7
  12. package/dist/{batch-IZ5EDKJ5.cjs.map → batch-VFR2MAUE.cjs.map} +1 -1
  13. package/dist/{chunk-3ONIVO2I.js → chunk-23SS4ID4.js} +3 -3
  14. package/dist/{chunk-3ONIVO2I.js.map → chunk-23SS4ID4.js.map} +1 -1
  15. package/dist/{chunk-2C24NSNV.js → chunk-3BBTHFGJ.js} +3 -3
  16. package/dist/{chunk-2C24NSNV.js.map → chunk-3BBTHFGJ.js.map} +1 -1
  17. package/dist/{chunk-NP362THY.cjs → chunk-3F53FLQ7.cjs} +5 -7
  18. package/dist/chunk-3F53FLQ7.cjs.map +1 -0
  19. package/dist/{chunk-SXH37C7X.cjs → chunk-55LLQFHW.cjs} +6 -6
  20. package/dist/{chunk-SXH37C7X.cjs.map → chunk-55LLQFHW.cjs.map} +1 -1
  21. package/dist/{chunk-GARVAUCU.js → chunk-5M5GQYBM.js} +534 -236
  22. package/dist/chunk-5M5GQYBM.js.map +1 -0
  23. package/dist/{chunk-2WY2OFSC.cjs → chunk-64ECM3XM.cjs} +616 -318
  24. package/dist/chunk-64ECM3XM.cjs.map +1 -0
  25. package/dist/{chunk-ZJAYFSVI.js → chunk-7ACS6P5Z.js} +5 -7
  26. package/dist/chunk-7ACS6P5Z.js.map +1 -0
  27. package/dist/{chunk-NAVUTK6X.js → chunk-ARC2V7NY.js} +3 -3
  28. package/dist/{chunk-NAVUTK6X.js.map → chunk-ARC2V7NY.js.map} +1 -1
  29. package/dist/{chunk-WDVG5R2Q.cjs → chunk-AUH2EVWY.cjs} +4 -3
  30. package/dist/chunk-AUH2EVWY.cjs.map +1 -0
  31. package/dist/chunk-BNEUB52I.cjs +55 -0
  32. package/dist/chunk-BNEUB52I.cjs.map +1 -0
  33. package/dist/chunk-BPL5CVZ5.js +53 -0
  34. package/dist/chunk-BPL5CVZ5.js.map +1 -0
  35. package/dist/{chunk-NVQSBRG6.js → chunk-CBBT42VX.js} +3 -3
  36. package/dist/{chunk-NVQSBRG6.js.map → chunk-CBBT42VX.js.map} +1 -1
  37. package/dist/chunk-CHKV2L2Y.cjs +416 -0
  38. package/dist/chunk-CHKV2L2Y.cjs.map +1 -0
  39. package/dist/{chunk-SNVYOX46.cjs → chunk-DJKGDLYZ.cjs} +91 -61
  40. package/dist/chunk-DJKGDLYZ.cjs.map +1 -0
  41. package/dist/{chunk-354F3OF5.js → chunk-FGGVSHDW.js} +3 -3
  42. package/dist/{chunk-354F3OF5.js.map → chunk-FGGVSHDW.js.map} +1 -1
  43. package/dist/{chunk-6OCJWGVD.cjs → chunk-FTXY4D44.cjs} +4 -4
  44. package/dist/{chunk-6OCJWGVD.cjs.map → chunk-FTXY4D44.cjs.map} +1 -1
  45. package/dist/chunk-INVEGVGO.js +405 -0
  46. package/dist/chunk-INVEGVGO.js.map +1 -0
  47. package/dist/{chunk-ZOL3L4EH.js → chunk-IOBHFP2E.js} +49 -19
  48. package/dist/chunk-IOBHFP2E.js.map +1 -0
  49. package/dist/{chunk-BZK5QL3N.cjs → chunk-KMFBNKCT.cjs} +4 -4
  50. package/dist/{chunk-BZK5QL3N.cjs.map → chunk-KMFBNKCT.cjs.map} +1 -1
  51. package/dist/{chunk-DF77RBF4.js → chunk-LCCT5ZXJ.js} +6 -6
  52. package/dist/{chunk-DF77RBF4.js.map → chunk-LCCT5ZXJ.js.map} +1 -1
  53. package/dist/{chunk-G7XBVM3T.cjs → chunk-MHUOVS5I.cjs} +5 -5
  54. package/dist/{chunk-G7XBVM3T.cjs.map → chunk-MHUOVS5I.cjs.map} +1 -1
  55. package/dist/{chunk-CWQPQTUZ.cjs → chunk-NEH3BPFD.cjs} +15 -15
  56. package/dist/{chunk-CWQPQTUZ.cjs.map → chunk-NEH3BPFD.cjs.map} +1 -1
  57. package/dist/{chunk-5AR6O7GW.js → chunk-NK5EOTDY.js} +3 -3
  58. package/dist/{chunk-5AR6O7GW.js.map → chunk-NK5EOTDY.js.map} +1 -1
  59. package/dist/{chunk-4TEGFMSP.cjs → chunk-P7QYG4RZ.cjs} +23 -15
  60. package/dist/chunk-P7QYG4RZ.cjs.map +1 -0
  61. package/dist/chunk-PPU2D4FZ.js +19 -0
  62. package/dist/chunk-PPU2D4FZ.js.map +1 -0
  63. package/dist/{chunk-AB4OPJLD.js → chunk-RGVMJU57.js} +3 -3
  64. package/dist/{chunk-AB4OPJLD.js.map → chunk-RGVMJU57.js.map} +1 -1
  65. package/dist/{chunk-4KBI37F3.cjs → chunk-RTDVSHJR.cjs} +5 -5
  66. package/dist/{chunk-4KBI37F3.cjs.map → chunk-RTDVSHJR.cjs.map} +1 -1
  67. package/dist/{chunk-CJN5CEI3.js → chunk-RZL2W4C3.js} +23 -15
  68. package/dist/chunk-RZL2W4C3.js.map +1 -0
  69. package/dist/chunk-SPEN7RJU.cjs +18 -0
  70. package/dist/{chunk-R5UQL2R5.cjs.map → chunk-SPEN7RJU.cjs.map} +1 -1
  71. package/dist/{chunk-ZF2LDKQQ.cjs → chunk-U3DW3WDE.cjs} +9 -8
  72. package/dist/chunk-U3DW3WDE.cjs.map +1 -0
  73. package/dist/{chunk-LXG6VL6R.cjs → chunk-U7PRI3XM.cjs} +3 -3
  74. package/dist/{chunk-LXG6VL6R.cjs.map → chunk-U7PRI3XM.cjs.map} +1 -1
  75. package/dist/{chunk-H7G65PNI.js → chunk-VCQ37TC5.js} +3 -3
  76. package/dist/{chunk-H7G65PNI.js.map → chunk-VCQ37TC5.js.map} +1 -1
  77. package/dist/{chunk-SDZ4XDWS.cjs → chunk-VWYFGE27.cjs} +9 -9
  78. package/dist/{chunk-SDZ4XDWS.cjs.map → chunk-VWYFGE27.cjs.map} +1 -1
  79. package/dist/{chunk-RN3XDZGS.js → chunk-WM646HEN.js} +4 -3
  80. package/dist/chunk-WM646HEN.js.map +1 -0
  81. package/dist/chunk-X7CE7Y5W.js +305 -0
  82. package/dist/chunk-X7CE7Y5W.js.map +1 -0
  83. package/dist/{chunk-CGH4BCIY.cjs → chunk-XE3CAY6Z.cjs} +5 -5
  84. package/dist/{chunk-CGH4BCIY.cjs.map → chunk-XE3CAY6Z.cjs.map} +1 -1
  85. package/dist/chunk-XOU3CL7S.cjs +312 -0
  86. package/dist/chunk-XOU3CL7S.cjs.map +1 -0
  87. package/dist/{chunk-ULEK4OM4.js → chunk-YKNBTHMD.js} +3 -3
  88. package/dist/{chunk-ULEK4OM4.js.map → chunk-YKNBTHMD.js.map} +1 -1
  89. package/dist/{compact-session-D2MQDB6G.cjs → compact-session-NX7HUNTB.cjs} +16 -16
  90. package/dist/{compact-session-D2MQDB6G.cjs.map → compact-session-NX7HUNTB.cjs.map} +1 -1
  91. package/dist/{compact-session-N2PPHQO6.js → compact-session-Q5IGNFPW.js} +7 -7
  92. package/dist/{compact-session-N2PPHQO6.js.map → compact-session-Q5IGNFPW.js.map} +1 -1
  93. package/dist/{cron-CK2v0VWA.d.cts → cron-Bh3aWgQ2.d.cts} +2 -2
  94. package/dist/{cron-BubDpFJG.d.ts → cron-CCDxeeFZ.d.ts} +2 -2
  95. package/dist/cron.cjs +18 -17
  96. package/dist/cron.d.cts +4 -3
  97. package/dist/cron.d.ts +4 -3
  98. package/dist/cron.js +17 -16
  99. package/dist/eval.cjs +17 -16
  100. package/dist/eval.cjs.map +1 -1
  101. package/dist/eval.js +16 -15
  102. package/dist/eval.js.map +1 -1
  103. package/dist/fs-session-store-CYNTEPJZ.cjs +20 -0
  104. package/dist/{fs-session-store-S2AXVJIX.cjs.map → fs-session-store-CYNTEPJZ.cjs.map} +1 -1
  105. package/dist/fs-session-store-MYQEVUFL.js +11 -0
  106. package/dist/{fs-session-store-6ZCCJX3K.js.map → fs-session-store-MYQEVUFL.js.map} +1 -1
  107. package/dist/{index-manager-HO456AVW.cjs → index-manager-2KH75BRW.cjs} +7 -7
  108. package/dist/{index-manager-HO456AVW.cjs.map → index-manager-2KH75BRW.cjs.map} +1 -1
  109. package/dist/{index-manager-QDH56FER.js → index-manager-NF2WRLOU.js} +6 -6
  110. package/dist/{index-manager-QDH56FER.js.map → index-manager-NF2WRLOU.js.map} +1 -1
  111. package/dist/index.cjs +66 -262
  112. package/dist/index.cjs.map +1 -1
  113. package/dist/index.d.cts +10 -46
  114. package/dist/index.d.ts +10 -46
  115. package/dist/index.js +27 -227
  116. package/dist/index.js.map +1 -1
  117. package/dist/{inject-session-J26SHHIO.js → inject-session-4ROYLZHY.js} +3 -3
  118. package/dist/{inject-session-J26SHHIO.js.map → inject-session-4ROYLZHY.js.map} +1 -1
  119. package/dist/{inject-session-3ICZIJ2N.cjs → inject-session-AWKDCGHV.cjs} +4 -4
  120. package/dist/{inject-session-3ICZIJ2N.cjs.map → inject-session-AWKDCGHV.cjs.map} +1 -1
  121. package/dist/internal/agent-loop/doom-loop-tracker.d.ts +3 -0
  122. package/dist/internal/agent-loop/types.d.ts +6 -0
  123. package/dist/internal/error-mappers/anthropic.d.ts +3 -0
  124. package/dist/internal/error-mappers/openai-compatible.d.ts +2 -3
  125. package/dist/internal/local-agent/local-agent-dispatch.d.ts +3 -1
  126. package/dist/internal/local-agent/send-queue.d.ts +31 -0
  127. package/dist/internal/mcp/client.d.ts +2 -0
  128. package/dist/internal/mcp/oauth-bearer.d.ts +2 -0
  129. package/dist/internal/memory/adapters/index.cjs +3 -3
  130. package/dist/internal/memory/adapters/index.js +2 -2
  131. package/dist/internal/memory/dreaming/phases.d.ts +15 -0
  132. package/dist/internal/memory/dreaming/run.d.ts +29 -0
  133. package/dist/internal/memory/sdk-memory-peer-loader.d.ts +2 -0
  134. package/dist/internal/memory/storage/index.cjs +51 -35
  135. package/dist/internal/memory/storage/index.d.cts +2 -0
  136. package/dist/internal/memory/storage/index.d.ts +2 -0
  137. package/dist/internal/memory/storage/index.js +4 -4
  138. package/dist/internal/persistence/cwd-mutex.d.cts +4 -2
  139. package/dist/internal/persistence/cwd-mutex.d.ts +4 -2
  140. package/dist/internal/persistence/index.cjs +4 -4
  141. package/dist/internal/persistence/index.js +2 -2
  142. package/dist/internal/persistence/sqlite-session-store.d.cts +25 -0
  143. package/dist/internal/persistence/sqlite-session-store.d.ts +25 -0
  144. package/dist/internal/providers/registry.d.ts +5 -1
  145. package/dist/mcp-auth.cjs +25 -307
  146. package/dist/mcp-auth.cjs.map +1 -1
  147. package/dist/mcp-auth.js +5 -305
  148. package/dist/mcp-auth.js.map +1 -1
  149. package/dist/models.cjs +9 -9
  150. package/dist/models.js +2 -2
  151. package/dist/persistence.cjs +9 -4
  152. package/dist/persistence.cjs.map +1 -1
  153. package/dist/persistence.d.cts +744 -40
  154. package/dist/persistence.d.ts +744 -40
  155. package/dist/persistence.js +3 -2
  156. package/dist/persistence.js.map +1 -1
  157. package/dist/providers.cjs +4 -4
  158. package/dist/providers.js +2 -2
  159. package/dist/sandbox/docker-sandbox.d.cts +58 -0
  160. package/dist/sandbox/docker-sandbox.d.ts +58 -0
  161. package/dist/sandbox/index.cjs +129 -1
  162. package/dist/sandbox/index.cjs.map +1 -1
  163. package/dist/sandbox/index.d.cts +1 -0
  164. package/dist/sandbox/index.d.ts +1 -0
  165. package/dist/sandbox/index.js +132 -5
  166. package/dist/sandbox/index.js.map +1 -1
  167. package/dist/{sdk-agent-DwzHcuxy.d.cts → sdk-agent-BA_6_wtc.d.cts} +30 -2
  168. package/dist/{sdk-agent-a3fW1xUK.d.ts → sdk-agent-CnwPODYH.d.ts} +30 -2
  169. package/dist/session-store-Dh07jr9N.d.cts +209 -0
  170. package/dist/session-store-Dh07jr9N.d.ts +209 -0
  171. package/dist/sqlite-session-store-BbcpKY1L.d.ts +64 -0
  172. package/dist/sqlite-session-store-TKXtT4ON.d.cts +64 -0
  173. package/dist/subagents-loader-KLWF4QPD.cjs +16 -0
  174. package/dist/{subagents-loader-TXOA5EJJ.cjs.map → subagents-loader-KLWF4QPD.cjs.map} +1 -1
  175. package/dist/subagents-loader-SXETS2F2.js +7 -0
  176. package/dist/{subagents-loader-Z744TAKD.js.map → subagents-loader-SXETS2F2.js.map} +1 -1
  177. package/dist/subagents-loader.cjs +2 -2
  178. package/dist/subagents-loader.d.cts +3 -2
  179. package/dist/subagents-loader.d.ts +3 -2
  180. package/dist/subagents-loader.js +1 -1
  181. package/dist/types/agent.d.ts +14 -1
  182. package/dist/types/budget-tracker.d.ts +6 -2
  183. package/dist/types/mcp.d.ts +14 -0
  184. package/dist/types/run.d.ts +15 -1
  185. package/dist/workflow.d.cts +1 -1
  186. package/dist/workflow.d.ts +1 -1
  187. package/docs/adr/mutation-testing-scope.md +12 -2
  188. package/docs/error-codes.md +41 -40
  189. package/docs/harness-capability-map.md +32 -6
  190. package/package.json +1 -1
  191. package/dist/chunk-2WY2OFSC.cjs.map +0 -1
  192. package/dist/chunk-4TEGFMSP.cjs.map +0 -1
  193. package/dist/chunk-6CXRYPG7.cjs +0 -211
  194. package/dist/chunk-6CXRYPG7.cjs.map +0 -1
  195. package/dist/chunk-CJN5CEI3.js.map +0 -1
  196. package/dist/chunk-GARVAUCU.js.map +0 -1
  197. package/dist/chunk-MSEL5E5P.js +0 -204
  198. package/dist/chunk-MSEL5E5P.js.map +0 -1
  199. package/dist/chunk-NP362THY.cjs.map +0 -1
  200. package/dist/chunk-Q5EWJPRY.js +0 -18
  201. package/dist/chunk-Q5EWJPRY.js.map +0 -1
  202. package/dist/chunk-R5UQL2R5.cjs +0 -18
  203. package/dist/chunk-RN3XDZGS.js.map +0 -1
  204. package/dist/chunk-SNVYOX46.cjs.map +0 -1
  205. package/dist/chunk-WDVG5R2Q.cjs.map +0 -1
  206. package/dist/chunk-ZF2LDKQQ.cjs.map +0 -1
  207. package/dist/chunk-ZJAYFSVI.js.map +0 -1
  208. package/dist/chunk-ZOL3L4EH.js.map +0 -1
  209. package/dist/fs-session-store-6ZCCJX3K.js +0 -11
  210. package/dist/fs-session-store-S2AXVJIX.cjs +0 -20
  211. package/dist/subagents-loader-TXOA5EJJ.cjs +0 -16
  212. package/dist/subagents-loader-Z744TAKD.js +0 -7
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/sandbox/deny-read.ts","../../src/sandbox/bwrap.ts","../../src/sandbox/seccomp.ts","../../src/sandbox/seccomp-delivery.ts","../../src/sandbox/linux-sandbox.ts","../../src/sandbox/provision.ts"],"names":["path","resolve","dirname"],"mappings":";;;;;;;;;;AAMA,IAAM,iBAAA,GAAoB,CAAC,MAAM,CAAA;AAGjC,SAAS,cAAA,CAAe,OAAe,KAAA,EAAwB;AAC7D,EAAA,MAAM,GAAA,GAAM,IAAA,CAAK,QAAA,CAAS,KAAA,EAAO,KAAK,CAAA;AACtC,EAAA,OAAO,GAAA,KAAQ,EAAA,IAAO,CAAC,GAAA,CAAI,UAAA,CAAW,IAAI,CAAA,IAAK,CAAC,IAAA,CAAK,UAAA,CAAW,GAAG,CAAA;AACrE;AAEA,SAAS,aAAa,KAAA,EAAuB;AAC3C,EAAA,IAAI,CAAC,IAAA,CAAK,UAAA,CAAW,KAAK,CAAA,EAAG;AAC3B,IAAA,MAAM,IAAI,SAAA,CAAU,CAAA,gBAAA,EAAmB,KAAK,CAAA,yBAAA,CAA2B,CAAA;AAAA,EACzE;AACA,EAAA,IAAI;AACF,IAAA,OAAO,aAAa,KAAK,CAAA;AAAA,EAC3B,SAAS,KAAA,EAAO;AACd,IAAA,MAAM,IAAI,UAAU,CAAA,gBAAA,EAAmB,KAAK,yBAAyB,MAAA,CAAO,KAAK,CAAC,CAAA,CAAE,CAAA;AAAA,EACtF;AACF;AAEA,SAAS,UAAU,GAAA,EAAuB;AACxC,EAAA,IAAI,IAAA,GAAO,GAAA;AACX,EAAA,IAAI;AACF,IAAA,IAAA,GAAO,aAAa,GAAG,CAAA;AAAA,EACzB,CAAA,CAAA,MAAQ;AAAA,EAER;AACA,EAAA,OAAO,CAAC,mBAAG,IAAI,GAAA,CAAI,CAAC,KAAK,IAAA,EAAM,GAAG,iBAAiB,CAAC,CAAC,CAAA;AACvD;AAeO,SAAS,aAAA,CACd,OACA,MAAA,EACU;AACV,EAAA,IAAI,UAAU,MAAA,IAAa,KAAA,CAAM,MAAA,KAAW,CAAA,SAAU,EAAC;AACvD,EAAA,IAAI,MAAA,CAAO,SAAS,oBAAA,EAAsB;AACxC,IAAA,MAAM,IAAI,SAAA;AAAA,MACR;AAAA,KACF;AAAA,EACF;AACA,EAAA,MAAM,KAAA,GAAQ,SAAA,CAAU,MAAA,CAAO,GAAG,CAAA;AAClC,EAAA,MAAM,QAAA,uBAAe,GAAA,EAAY;AACjC,EAAA,KAAA,MAAW,SAAS,KAAA,EAAO;AACzB,IAAA,MAAM,MAAA,GAAS,aAAa,KAAK,CAAA;AACjC,IAAA,MAAM,OAAA,GAAU,MAAM,IAAA,CAAK,CAAC,SAAS,cAAA,CAAe,MAAA,EAAQ,IAAI,CAAC,CAAA;AACjE,IAAA,IAAI,YAAY,MAAA,EAAW;AACzB,MAAA,MAAM,IAAI,SAAA;AAAA,QACR,CAAA,gBAAA,EAAmB,KAAK,CAAA,cAAA,EAAiB,OAAO,CAAA,0BAAA;AAAA,OAClD;AAAA,IACF;AACA,IAAA,QAAA,CAAS,IAAI,MAAM,CAAA;AAAA,EACrB;AACA,EAAA,OAAO,CAAC,GAAG,QAAQ,CAAA,CAAE,OAAA;AAAA,IAAQ,CAAC,MAAA,KAC5B,QAAA,CAAS,MAAM,EAAE,WAAA,EAAY,GAAI,CAAC,SAAA,EAAW,MAAM,CAAA,GAAI,CAAC,WAAA,EAAa,aAAa,MAAM;AAAA,GAC1F;AACF;AAOO,SAAS,0BAAA,CACd,KAAA,EACA,IAAA,EACA,MAAA,EACM;AACN,EAAA,IAAI,KAAA,KAAU,MAAA,IAAa,KAAA,CAAM,MAAA,KAAW,CAAA,EAAG;AAC/C,EAAA,IAAI,IAAA,KAAS,sBAAsB,aAAA,CAAc,KAAA,EAAO,EAAE,IAAA,EAAM,GAAA,EAAK,KAAK,CAAA;AAC1E,EAAA,MAAM,YAAY,MAAA,EAAO;AACzB,EAAA,IAAI,CAAC,UAAU,EAAA,EAAI;AACjB,IAAA,MAAM,IAAI,wBAAA;AAAA,MACR,CAAA,8DAAA,EAAiE,UAAU,MAAM,CAAA,6BAAA;AAAA,KACnF;AAAA,EACF;AACF;;;ACzDA,SAAS,kBAAA,CAAmB,IAAA,EAAgB,GAAA,EAAa,MAAA,EAAiB,MAAA,EAAsB;AAC9F,EAAA,KAAA,MAAW,IAAA,IAAQ,oBAAoB,GAAG,CAAA,OAAQ,IAAA,CAAK,QAAA,EAAU,MAAM,IAAI,CAAA;AAC3E,EAAA,IAAI,MAAA,EAAQ,IAAA,CAAK,IAAA,CAAK,WAAA,EAAa,QAAQ,MAAM,CAAA;AACnD;AAGA,SAAS,oBAAoB,GAAA,EAAgC;AAC3D,EAAA,OAAO,CAAC,KAAK,MAAM,CAAA;AACrB;AAeO,SAAS,gBAAA,CAAiB,MAAmB,GAAA,EAAuC;AACzF,EAAA,QAAQ,IAAA;AAAM,IACZ,KAAK,WAAA;AACH,MAAA,OAAO,EAAC;AAAA,IACV,KAAK,iBAAA;AACH,MAAA,OAAO,oBAAoB,GAAG,CAAA;AAAA,IAChC,KAAK,oBAAA;AACH,MAAA,OAAO,IAAA;AAAA;AAEb;AAqCO,SAAS,cAAA,CAAe,MAAmB,IAAA,EAAyC;AACzF,EAAA,MAAM,GAAA,GAAMA,IAAAA,CAAK,OAAA,CAAQ,IAAA,CAAK,GAAG,CAAA;AACjC,EAAA,MAAM,YAAY,aAAA,CAAc,IAAA,CAAK,eAAe,EAAE,IAAA,EAAM,KAAK,CAAA;AACjE,EAAA,IAAI,IAAA,KAAS,sBAAsB,OAAO,IAAA;AAE1C,EAAA,MAAM,MAAA,GAASA,IAAAA,CAAK,IAAA,CAAK,GAAA,EAAK,MAAM,CAAA;AACpC,EAAA,MAAM,MAAA,GAAS,IAAA,CAAK,YAAA,IAAgB,UAAA,CAAW,MAAM,CAAA;AAErD,EAAA,MAAM,IAAA,GAAiB;AAAA;AAAA,IAErB,eAAA;AAAA,IACA,mBAAA;AAAA,IACA,gBAAA;AAAA,IACA,eAAA;AAAA;AAAA,IAEA,WAAA;AAAA,IACA,GAAA;AAAA,IACA,GAAA;AAAA,IACA,OAAA;AAAA,IACA,MAAA;AAAA,IACA,QAAA;AAAA,IACA;AAAA,GACF;AAEA,EAAA,IAAI,CAAC,IAAA,CAAK,OAAA,EAAS,IAAA,CAAK,KAAK,eAAe,CAAA;AAI5C,EAAA,IAAI,IAAA,CAAK,GAAA,EAAK,IAAA,CAAK,IAAA,CAAK,YAAY,CAAA;AACpC,EAAA,MAAM,MAAA,GAAiC;AAAA,IACrC,GAAI,IAAA,CAAK,GAAA,IAAO,EAAC;AAAA;AAAA,IAEjB,GAAI,IAAA,CAAK,OAAA,GAAU,EAAC,GAAI,EAAE,gCAAgC,GAAA;AAAI,GAChE;AACA,EAAA,KAAA,MAAW,CAAC,CAAA,EAAG,CAAC,CAAA,IAAK,MAAA,CAAO,OAAA,CAAQ,MAAM,CAAA,EAAG,IAAA,CAAK,IAAA,CAAK,UAAA,EAAY,CAAA,EAAG,CAAC,CAAA;AAEvE,EAAA,IAAI,SAAS,iBAAA,EAAmB,kBAAA,CAAmB,IAAA,EAAM,GAAA,EAAK,QAAQ,MAAM,CAAA;AAE5E,EAAA,IAAA,CAAK,IAAA,CAAK,GAAG,SAAS,CAAA;AAEtB,EAAA,IAAA,CAAK,IAAA,CAAK,SAAA,EAAW,GAAA,EAAK,IAAI,CAAA;AAC9B,EAAA,OAAO,IAAA;AACT;AAiCO,SAAS,WAAA,CAAY,SAAsB,UAAA,EAA4B;AAC5E,EAAA,IAAI;AACF,IAAA,MAAM,GAAA,GAAM,OAAO,KAAA,EAAM;AACzB,IAAA,IAAI,CAAC,GAAA,EAAK,OAAO,EAAE,EAAA,EAAI,KAAA,EAAO,QAAQ,yBAAA,EAA0B;AAChE,IAAA,MAAM,IAAA,GAAO,MAAA,CAAO,QAAA,CAAS,GAAG,CAAA;AAChC,IAAA,IAAI,CAAC,IAAA,EAAM,QAAA,CAAS,SAAS,CAAA,EAAG;AAC9B,MAAA,OAAO,EAAE,EAAA,EAAI,KAAA,EAAO,MAAA,EAAQ,CAAA,SAAA,EAAY,GAAG,CAAA,gCAAA,CAAA,EAAmC;AAAA,IAChF;AACA,IAAA,IAAI,CAAC,MAAA,CAAO,MAAA,CAAO,GAAG,CAAA,EAAG;AACvB,MAAA,OAAO,EAAE,EAAA,EAAI,KAAA,EAAO,MAAA,EAAQ,4DAAA,EAA6D;AAAA,IAC3F;AACA,IAAA,OAAO,EAAE,EAAA,EAAI,IAAA,EAAM,GAAA,EAAI;AAAA,EACzB,SAAS,GAAA,EAAK;AACZ,IAAA,OAAO;AAAA,MACL,EAAA,EAAI,KAAA;AAAA,MACJ,MAAA,EAAQ,uBAAuB,GAAA,YAAe,KAAA,GAAQ,IAAI,OAAA,GAAU,MAAA,CAAO,GAAG,CAAC,CAAA;AAAA,KACjF;AAAA,EACF;AACF;AASA,IAAI,aAAA,GAAgB,CAAA;AAGb,SAAS,cAAA,GAAyB;AACvC,EAAA,OAAO,aAAA;AACT;AAGO,IAAM,UAAA,GAA0B;AAAA,EACrC,OAAO,MAAM;AACX,IAAA,aAAA,EAAA;AACA,IAAA,IAAI;AACF,MAAA,MAAM,GAAA,GAAM,YAAA,CAAa,OAAA,EAAS,CAAC,OAAO,CAAA,EAAG,EAAE,QAAA,EAAU,MAAA,EAAQ,OAAA,EAAS,GAAA,EAAO,EAAE,IAAA,EAAK;AAExF,MAAA,IAAI,CAAC,GAAA,IAAO,GAAA,CAAI,UAAA,CAAW,OAAA,CAAQ,KAAI,GAAIA,IAAAA,CAAK,GAAG,CAAA,EAAG,OAAO,IAAA;AAC7D,MAAA,OAAO,GAAA;AAAA,IACT,CAAA,CAAA,MAAQ;AACN,MAAA,OAAO,IAAA;AAAA,IACT;AAAA,EACF,CAAA;AAAA,EACA,QAAA,EAAU,CAAC,GAAA,KAAQ;AACjB,IAAA,IAAI;AAEF,MAAA,OAAO,YAAA,CAAa,GAAA,EAAK,CAAC,QAAQ,CAAA,EAAG,EAAE,QAAA,EAAU,MAAA,EAAQ,OAAA,EAAS,GAAA,EAAO,CAAA;AAAA,IAC3E,SAAS,GAAA,EAAK;AACZ,MAAA,MAAM,CAAA,GAAI,GAAA;AACV,MAAA,OAAO,CAAC,CAAA,CAAE,MAAA,EAAQ,CAAA,CAAE,MAAM,CAAA,CAAE,MAAA,CAAO,OAAO,CAAA,CAAE,IAAA,CAAK,IAAI,CAAA,IAAK,IAAA;AAAA,IAC5D;AAAA,EACF,CAAA;AAAA,EACA,MAAA,EAAQ,CAAC,GAAA,KAAQ;AACf,IAAA,IAAI;AAEF,MAAA,YAAA,CAAa,GAAA,EAAK,CAAC,gBAAA,EAAkB,eAAA,EAAiB,aAAa,GAAA,EAAK,GAAA,EAAK,WAAW,CAAA,EAAG;AAAA,QACzF,OAAA,EAAS,GAAA;AAAA,QACT,KAAA,EAAO;AAAA,OACR,CAAA;AACD,MAAA,OAAO,IAAA;AAAA,IACT,CAAA,CAAA,MAAQ;AACN,MAAA,OAAO,KAAA;AAAA,IACT;AAAA,EACF;AACF;AAqCA,IAAI,IAAA;AAaG,SAAS,mBAAA,CAAoB,SAAsB,UAAA,EAA4B;AACpF,EAAA,IAAA,KAAS,YAAY,MAAM,CAAA;AAC3B,EAAA,IAAI,KAAK,EAAA,IAAM,CAAC,UAAA,CAAW,IAAA,CAAK,GAAG,CAAA,EAAG;AACpC,IAAA,IAAA,GAAO,EAAE,EAAA,EAAI,KAAA,EAAO,QAAQ,CAAA,uBAAA,EAA0B,IAAA,CAAK,GAAG,CAAA,gBAAA,CAAA,EAAmB;AAAA,EACnF;AACA,EAAA,OAAO,IAAA;AACT;AAaO,SAAS,cAAA,GAAuB;AACrC,EAAA,IAAA,GAAO,MAAA;AACT;;;ACjTA,IAAM,MAAA,GAAS,CAAA;AACf,IAAM,KAAA,GAAQ,CAAA;AACd,IAAM,OAAA,GAAU,EAAA;AAChB,IAAM,OAAA,GAAU,CAAA;AAChB,IAAM,OAAA,GAAU,EAAA;AAChB,IAAM,OAAA,GAAU,EAAA;AAChB,IAAM,KAAA,GAAQ,CAAA;AACd,IAAM,OAAA,GAAU,CAAA;AAEhB,IAAM,QAAA,GAAW,SAAS,KAAA,GAAQ,OAAA;AAClC,IAAM,KAAA,GAAQ,UAAU,OAAA,GAAU,KAAA;AAClC,IAAM,KAAA,GAAQ,UAAU,OAAA,GAAU,KAAA;AAClC,IAAM,QAAQ,OAAA,GAAU,KAAA;AAGxB,IAAM,MAAA,GAAS,CAAA;AACf,IAAM,QAAA,GAAW,CAAA;AACjB,IAAM,QAAA,GAAW,EAAA;AAEjB,IAAM,iBAAA,GAAoB,UAAA;AAC1B,IAAM,OAAA,GAAU,UAAA;AAGhB,IAAM,iBAAA,GAAoB,UAAA;AAC1B,IAAM,iBAAA,GAAoB,MAAA;AAC1B,IAAM,KAAA,GAAQ,CAAA;AACd,IAAM,SAAA,GAAY,oBAAqB,KAAA,GAAQ,KAAA;AAC/C,IAAM,wBAAA,GAA2B,UAAA;AAEjC,IAAM,OAAA,GAAU,CAAA;AAGhB,IAAM,gBAAgB,CAAC,GAAA,EAAK,KAAK,GAAA,EAAK,GAAA,EAAK,KAAK,GAAG,CAAA;AAwBnD,IAAM,cAAA,GAAiB,CAAC,EAAA,EAAI,EAAA,EAAI,GAAA,EAAK,IAAI,EAAA,EAAI,EAAA,EAAI,EAAA,EAAI,GAAA,EAAK,GAAG,CAAA;AAE7D,IAAM,eAAA,GAAkB,CAAC,EAAA,EAAI,EAAE,CAAA;AAS/B,IAAM,IAAA,GAAO,CAAC,IAAA,EAAc,CAAA,MAAqB,EAAE,MAAM,EAAA,EAAI,CAAA,EAAG,EAAA,EAAI,CAAA,EAAG,CAAA,EAAE,CAAA;AACzE,IAAM,GAAA,GAAM,CAAC,IAAA,EAAc,CAAA,EAAW,EAAA,EAAY,QAAsB,EAAE,IAAA,EAAM,EAAA,EAAI,EAAA,EAAI,CAAA,EAAE,CAAA;AAkBnF,SAAS,mBAAmB,IAAA,EAA8B;AAI/D,EAAA,MAAM,QAAgB,EAAC;AAKvB,EAAA,MAAM,KAAA,0BAAe,OAAO,CAAA;AAC5B,EAAA,MAAM,IAAA,0BAAc,MAAM,CAAA;AAC1B,EAAA,MAAM,IAAA,0BAAc,MAAM,CAAA;AAQ1B,EAAA,MAAM,OAAgB,EAAC;AACvB,EAAA,MAAM,OAAO,CAAC,IAAA,EAAc,GAAW,EAAA,GAAa,CAAA,EAAG,KAAa,CAAA,KAAY;AAC9E,IAAA,IAAA,CAAK,KAAK,EAAE,IAAA,EAAM,CAAA,EAAG,EAAA,EAAI,IAAI,CAAA;AAAA,EAC/B,CAAA;AAGA,EAAA,IAAA,CAAK,UAAU,QAAQ,CAAA;AACvB,EAAA,IAAA,CAAK,KAAA,EAAO,iBAAA,EAAmB,CAAA,EAAG,IAAI,CAAA;AAEtC,EAAA,IAAA,CAAK,UAAU,MAAM,CAAA;AACrB,EAAA,IAAA,CAAK,KAAA,EAAO,OAAA,EAAS,IAAA,EAAM,CAAC,CAAA;AAI5B,EAAA,MAAM,MAAA,GAAS,IAAA,CAAK,iBAAA,GAChB,CAAC,GAAG,aAAA,EAAe,GAAG,cAAc,CAAA,GACpC,CAAC,GAAG,aAAa,CAAA;AACrB,EAAA,KAAA,MAAW,MAAM,MAAA,EAAQ,IAAA,CAAK,KAAA,EAAO,EAAA,EAAI,MAAM,CAAC,CAAA;AAGhD,EAAA,IAAI,KAAK,iBAAA,EAAmB;AAC1B,IAAA,KAAA,MAAW,SAAS,eAAA,EAAiB;AAEnC,MAAA,IAAA,CAAK,KAAA,EAAO,KAAA,EAAO,CAAA,EAAG,CAAC,CAAA;AACvB,MAAA,IAAA,CAAK,UAAU,QAAQ,CAAA;AACvB,MAAA,IAAA,CAAK,KAAA,EAAO,OAAA,EAAS,KAAA,EAAO,IAAI,CAAA;AAAA,IAIlC;AAAA,EACF;AAGA,EAAA,IAAA,CAAK,OAAO,iBAAiB,CAAA;AAC7B,EAAA,MAAM,QAAA,GAAW,KAAK,MAAA,GAAS,CAAA;AAC/B,EAAA,IAAA,CAAK,OAAO,SAAS,CAAA;AACrB,EAAA,MAAM,OAAA,GAAU,KAAK,MAAA,GAAS,CAAA;AAC9B,EAAA,IAAA,CAAK,OAAO,wBAAwB,CAAA;AACpC,EAAA,MAAM,OAAA,GAAU,KAAK,MAAA,GAAS,CAAA;AAa9B,EAAA,MAAMC,QAAAA,GAAU,CAAC,CAAA,EAAW,CAAA,KAAsB;AAChD,IAAA,MAAM,GAAA,GAAM,CAAA,KAAM,KAAA,GAAQ,QAAA,GAAW,CAAA,KAAM,IAAA,GAAO,OAAA,GAAU,CAAA,KAAM,IAAA,GAAO,OAAA,GAAU,CAAA,GAAI,CAAA,GAAI,CAAA;AAE3F,IAAA,MAAM,GAAA,GAAM,OAAO,CAAA,GAAI,CAAA,CAAA;AACvB,IAAA,IAAI,GAAA,GAAM,CAAA,IAAK,GAAA,GAAM,GAAA,EAAK,MAAM,IAAI,UAAA,CAAW,CAAA,6BAAA,EAAgC,CAAC,CAAA,EAAA,EAAK,GAAG,CAAA,CAAE,CAAA;AAC1F,IAAA,OAAO,GAAA;AAAA,EACT,CAAA;AAIA,EAAA,KAAA,MAAW,CAAC,CAAA,EAAG,CAAC,CAAA,IAAK,IAAA,CAAK,SAAQ,EAAG;AACnC,IAAA,IAAI,CAAA,CAAE,IAAA,KAAS,KAAA,IAAS,CAAA,CAAE,SAAS,KAAA,EAAO;AACxC,MAAA,KAAA,CAAM,KAAK,GAAA,CAAI,CAAA,CAAE,IAAA,EAAM,CAAA,CAAE,GAAGA,QAAAA,CAAQ,CAAA,EAAG,CAAA,CAAE,EAAE,GAAGA,QAAAA,CAAQ,CAAA,EAAG,CAAA,CAAE,EAAE,CAAC,CAAC,CAAA;AAAA,IACjE,CAAA,MAAO;AACL,MAAA,KAAA,CAAM,KAAK,IAAA,CAAK,CAAA,CAAE,IAAA,EAAM,CAAA,CAAE,CAAC,CAAC,CAAA;AAAA,IAC9B;AAAA,EACF;AAEA,EAAA,MAAM,GAAA,GAAM,MAAA,CAAO,KAAA,CAAM,KAAA,CAAM,SAAS,CAAC,CAAA;AACzC,EAAA,KAAA,CAAM,OAAA,CAAQ,CAAC,GAAA,EAAK,CAAA,KAAM;AACxB,IAAA,GAAA,CAAI,aAAA,CAAc,GAAA,CAAI,IAAA,EAAM,CAAA,GAAI,CAAC,CAAA;AACjC,IAAA,GAAA,CAAI,UAAA,CAAW,GAAA,CAAI,EAAA,EAAI,CAAA,GAAI,IAAI,CAAC,CAAA;AAChC,IAAA,GAAA,CAAI,UAAA,CAAW,GAAA,CAAI,EAAA,EAAI,CAAA,GAAI,IAAI,CAAC,CAAA;AAChC,IAAA,GAAA,CAAI,cAAc,GAAA,CAAI,CAAA,KAAM,CAAA,EAAG,CAAA,GAAI,IAAI,CAAC,CAAA;AAAA,EAC1C,CAAC,CAAA;AACD,EAAA,OAAO,GAAA;AACT;ACpLO,SAAS,qBAAqB,IAAA,EAAsB;AACzD,EAAA,OACE,mDAAmD,IAAI,CAAA,mGAAA,CAAA;AAG3D;AAEA,IAAI,mBAAA,GAAsB,KAAA;AASnB,SAAS,qBAAA,CAAsB,MAAc,IAAA,EAA+C;AACjG,EAAA,IAAI,SAAS,KAAA,EAAO;AAClB,IAAA,IAAI,CAAC,mBAAA,EAAqB;AACxB,MAAA,mBAAA,GAAsB,IAAA;AACtB,MAAA,IAAA,CAAK,oBAAA,CAAqB,IAAI,CAAC,CAAA;AAAA,IACjC;AACA,IAAA,OAAO,MAAA;AAAA,EACT;AACA,EAAA,OAAO,kBAAA,CAAmB,EAAE,iBAAA,EAAmB,IAAA,EAAM,CAAA;AACvD;AAEA,IAAI,eAAA;AAGG,SAAS,yBAAyB,IAAA,EAA+C;AACtF,EAAA,IAAI,eAAA,KAAoB,MAAA;AACtB,IAAA,eAAA,GAAkB,qBAAA,CAAsB,OAAA,CAAQ,IAAA,EAAM,IAAI,CAAA,IAAK,IAAA;AACjE,EAAA,OAAO,eAAA,IAAmB,MAAA;AAC5B;AAMA,SAAS,eAAe,OAAA,EAA6B;AACnD,EAAA,IAAI,GAAA,GAAM,EAAA;AACV,EAAA,KAAA,MAAW,IAAA,IAAQ,OAAA,EAAS,GAAA,IAAO,CAAA,EAAA,EAAK,IAAA,CAAK,QAAA,CAAS,CAAC,CAAA,CAAE,QAAA,CAAS,CAAA,EAAG,GAAG,CAAC,CAAA,CAAA;AACzE,EAAA,OAAO,GAAA;AACT;AAGA,SAAS,0BAA0B,OAAA,EAA2B;AAC5D,EAAA,IAAI,QAAQ,MAAA,KAAW,CAAA,IAAK,OAAA,CAAQ,MAAA,GAAS,MAAM,CAAA,EAAG;AACpD,IAAA,MAAM,IAAI,SAAA;AAAA,MACR,CAAA,2DAAA,EAA8D,QAAQ,MAAM,CAAA;AAAA,KAC9E;AAAA,EACF;AACF;AAYA,IAAM,WAAA,GAAc,+DAAA;AAUb,SAAS,sBAAA,CACd,SAAA,EACA,OAAA,EACA,OAAA,EACQ;AACR,EAAA,yBAAA,CAA0B,OAAO,CAAA;AACjC,EAAA,MAAM,KAAA,GAAQ,CAAC,cAAA,CAAe,OAAO,CAAA,EAAG,GAAG,SAAA,EAAW,WAAA,EAAa,GAAA,EAAK,IAAA,EAAM,SAAA,EAAW,IAAI,CAAA;AAC7F,EAAA,OAAO,CAAA,gBAAA,EAAmB,gBAAA,CAAiB,WAAW,CAAC,OAAO,CAAC,GAAG,KAAA,EAAO,OAAO,EAAE,GAAA,CAAI,gBAAgB,CAAA,CAAE,IAAA,CAAK,GAAG,CAAC,CAAA,CAAA;AACnH;AAGA,IAAM,eAAA,uBAAsB,GAAA,EAAoB;AAMzC,SAAS,mBAAA,CAAoBD,OAAc,OAAA,EAAuB;AACvE,EAAA,eAAA,CAAgB,IAAI,OAAA,CAAQA,KAAI,GAAG,MAAA,CAAO,IAAA,CAAK,OAAO,CAAC,CAAA;AACzD;AAUO,SAAS,gBAAgB,GAAA,EAAmB;AACjD,EAAA,MAAM,OAAA,GAAU,MAAY,MAAA,CAAO,GAAA,EAAK,EAAE,SAAA,EAAW,IAAA,EAAM,KAAA,EAAO,IAAA,EAAM,CAAA;AACxE,EAAA,OAAA,CAAQ,IAAA,CAAK,QAAQ,OAAO,CAAA;AAC5B,EAAA,KAAA,MAAW,MAAA,IAAU,CAAC,QAAA,EAAU,SAAS,CAAA,EAAY;AACnD,IAAA,OAAA,CAAQ,mBAAA,CAAoB,QAAQ,MAAM;AACxC,MAAA,OAAA,EAAQ;AACR,MAAA,IAAI,OAAA,CAAQ,cAAc,MAAM,CAAA,KAAM,GAAG,OAAA,CAAQ,IAAA,CAAK,OAAA,CAAQ,GAAA,EAAK,MAAM,CAAA;AAAA,IAC3E,CAAC,CAAA;AAAA,EACH;AACF;AAWO,SAAS,mBAAA,CACd,SAAA,EACA,MAAA,EACA,OAAA,EACA,WAAA,EACQ;AACR,EAAA,MAAM,OAAA,GAAU,eAAA,CAAgB,GAAA,CAAI,OAAA,CAAQ,WAAW,CAAC,CAAA;AAExD,EAAA,MAAM,IAAA,GAAO,OAAA,KAAY,MAAA,GAAY,WAAA,GAAc,eAAA;AACnD,EAAA,MAAM,KAAA,GAAQ;AAAA,IACZ,GAAG,SAAA,CAAU,KAAA,CAAM,CAAA,EAAG,EAAE,CAAA;AAAA,IACxB,GAAG,0BAAA,CAA2B,MAAA,CAAO,MAAM,MAAA,CAAO,GAAA,EAAK,aAAa,IAAI,CAAA;AAAA,IACxE,GAAG,SAAA,CAAU,KAAA,CAAM,EAAA,EAAI,EAAE;AAAA,GAC3B;AACA,EAAA,IAAI,YAAY,MAAA,EAAW,OAAO,sBAAA,CAAuB,KAAA,EAAO,SAAS,OAAO,CAAA;AAChF,EAAA,OAAO,CAAA,EAAG,CAAC,GAAG,KAAA,EAAO,aAAa,GAAA,EAAK,IAAI,EAAE,GAAA,CAAI,gBAAgB,EAAE,IAAA,CAAK,GAAG,CAAC,CAAA,YAAA,EAAe,gBAAA,CAAiB,OAAO,CAAC,CAAA,IAAA,EAAO,gBAAA,CAAiB,WAAW,CAAC,CAAA,CAAA;AAC1J;AAUA,SAAS,0BAAA,CACP,IAAA,EACA,GAAA,EACA,WAAA,EACA,IAAA,EACU;AACV,EAAA,MAAM,IAAA,GAAO,QAAQ,WAAW,CAAA;AAChC,EAAA,MAAM,GAAA,GAAM,QAAQ,IAAI,CAAA;AACxB,EAAA,MAAM,QAAQ,gBAAA,CAAiB,IAAA,EAAM,QAAQ,GAAG,CAAC,KAAK,EAAC;AACvD,EAAA,MAAM,MAAA,GAAS,CAAC,IAAA,KACd,GAAA,KAAQ,GAAA,IAAO,IAAA,KAAS,GAAA,IAAO,IAAA,CAAK,UAAA,CAAW,CAAA,EAAG,GAAG,CAAA,CAAA,CAAG,CAAA;AAC1D,EAAA,MAAM,MAAA,GAAS,KAAA,CAAM,IAAA,CAAK,MAAM,IAAI,IAAA,GAAO,GAAA;AAC3C,EAAA,OAAO,CAAC,IAAA,EAAM,MAAA,EAAQ,MAAM,CAAA;AAC9B;;;AC1IO,SAAS,qBAAA,CACd,IAAA,EACA,IAAA,EAoBA,OAAA,EACe;AACf,EAAA,MAAM,IAAA,GAAO,cAAA,CAAe,IAAA,EAAM,IAAI,CAAA;AACtC,EAAA,IAAI,IAAA,KAAS,MAAM,OAAO,IAAA;AAC1B,EAAA,MAAM,GAAA,GAAM,KAAK,GAAA,IAAO,OAAA;AACxB,EAAA,IAAI,IAAA,CAAK,mBAAmB,MAAA,EAAW;AACrC,IAAA,OAAO,sBAAA,CAAuB,CAAC,GAAA,EAAK,GAAG,IAAA,CAAK,KAAA,CAAM,CAAA,EAAG,EAAE,CAAC,CAAA,EAAG,OAAA,EAAS,IAAA,CAAK,cAAc,CAAA;AAAA,EACzF;AACA,EAAA,IAAI,IAAA,CAAK,gBAAgB,MAAA,EAAW;AAClC,IAAA,OAAO,CAAA,EAAG,CAAC,GAAA,EAAK,GAAG,IAAI,CAAA,CAAE,GAAA,CAAI,gBAAgB,CAAA,CAAE,KAAK,GAAG,CAAC,CAAA,YAAA,EAAe,gBAAA,CAAiB,OAAO,CAAC,CAAA,CAAA;AAAA,EAClG;AACA,EAAA,OAAO,mBAAA,CAAoB,CAAC,GAAA,EAAK,GAAG,IAAI,CAAA,EAAG,EAAE,IAAA,EAAM,GAAA,EAAK,IAAA,CAAK,GAAA,EAAI,EAAG,OAAA,EAAS,KAAK,WAAW,CAAA;AAC/F;AAQA,IAAM,aAAA,GAAgB;AAAA,EACpB,MAAA;AAAA,EACA,MAAA;AAAA,EACA,MAAA;AAAA,EACA,QAAA;AAAA,EACA,UAAA;AAAA,EACA,MAAA;AAAA,EACA,MAAA;AAAA,EACA,QAAA;AAAA,EACA;AACF,CAAA;AAiBO,SAAS,cAAA,CAAe,MAAA,GAA4B,OAAA,CAAQ,GAAA,EAA6B;AAC9F,EAAA,MAAM,MAA8B,EAAC;AACrC,EAAA,KAAA,MAAW,KAAK,aAAA,EAAe;AAC7B,IAAA,MAAM,CAAA,GAAI,OAAO,CAAC,CAAA;AAClB,IAAA,IAAI,CAAA,KAAM,MAAA,EAAW,GAAA,CAAI,CAAC,CAAA,GAAI,CAAA;AAAA,EAChC;AACA,EAAA,OAAO,GAAA;AACT;AAyBO,IAAM,YAAA,GAAN,cAA2B,YAAA,CAAa;AAAA,EAC5B,IAAA;AAAA,EACA,OAAA;AAAA,EACA,GAAA;AAAA,EACA,GAAA;AAAA,EACA,GAAA;AAAA;AAAA;AAAA;AAAA,EAIA,cAAA;AAAA,EACA,aAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMC,aAAA;AAAA;AAAA,EAGlB,WAAA,CACE,QACA,IAAA,EAOA;AACA,IAAA,KAAA,CAAM,MAAM,CAAA;AACZ,IAAA,IAAA,CAAK,OAAO,IAAA,CAAK,IAAA;AACjB,IAAA,IAAA,CAAK,OAAA,GAAU,KAAK,OAAA,IAAW,KAAA;AAC/B,IAAA,IAAA,CAAK,aAAA,GACH,IAAA,CAAK,OAAA,IAAW,IAAA,CAAK,IAAA,KAAS,oBAAA,GAC1B,EAAE,IAAA,EAAM,cAAA,EAAe,GACvB,EAAE,IAAA,EAAM,MAAA,EAAO;AACrB,IAAA,IAAA,CAAK,GAAA,GAAM,MAAA,CAAO,OAAA,IAAW,OAAA,CAAQ,GAAA,EAAI;AAGzC,IAAA,IAAA,CAAK,GAAA,GAAM,KAAK,GAAA,IAAO,OAAA;AACvB,IAAA,IAAA,CAAK,GAAA,GAAM,IAAA,CAAK,GAAA,IAAO,cAAA,EAAe;AACtC,IAAA,IAAA,CAAK,cAAA,GAAiB,wBAAA,CAAyB,IAAA,CAAK,OAAO,CAAA;AAC3D,IAAA,IAAA,CAAK,gBAAgB,IAAA,CAAK,aAAA;AAC1B,IAAA,aAAA,CAAc,IAAA,CAAK,eAAe,EAAE,IAAA,EAAM,KAAK,IAAA,EAAM,GAAA,EAAK,IAAA,CAAK,GAAA,EAAK,CAAA;AAAA,EACtE;AAAA;AAAA,EAGA,YAAY,OAAA,EAAgC;AAC1C,IAAA,OAAO,qBAAA;AAAA,MACL,IAAA,CAAK,IAAA;AAAA,MACL;AAAA,QACE,KAAK,IAAA,CAAK,GAAA;AAAA,QACV,SAAS,IAAA,CAAK,OAAA;AAAA,QACd,KAAK,IAAA,CAAK,GAAA;AAAA,QACV,KAAK,IAAA,CAAK,GAAA;AAAA,QACV,gBAAgB,IAAA,CAAK,cAAA;AAAA,QACrB,eAAe,IAAA,CAAK;AAAA,OACtB;AAAA,MACA;AAAA,KACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAeA,MAAe,UAAA,CAAWA,KAAAA,EAAc,OAAA,EAAyC;AAC/E,IAAA,IAAI,KAAK,IAAA,KAAS,oBAAA,SAA6B,KAAA,CAAM,UAAA,CAAWA,OAAM,OAAO,CAAA;AAE7E,IAAA,MAAM,MAAA,GAASA,KAAAA,CAAK,UAAA,CAAW,GAAG,CAAA,GAAIA,QAAO,CAAA,EAAG,IAAA,CAAK,GAAG,CAAA,CAAA,EAAIA,KAAI,CAAA,CAAA;AAChE,IAAA,MAAM,MAAM,MAAA,CAAO,IAAA,CAAK,OAAO,CAAA,CAAE,SAAS,QAAQ,CAAA;AAGlD,IAAA,MAAM,CAAA,GAAI,MAAM,IAAA,CAAK,OAAA;AAAA,MACnB,CAAA,SAAA,EAAY,gBAAA,CAAiBE,OAAAA,CAAQ,MAAM,CAAC,CAAC,CAAA,cAAA,EAAiB,gBAAA,CAAiB,GAAG,CAAC,CAAA,eAAA,EAAkB,gBAAA,CAAiB,MAAM,CAAC,CAAA;AAAA,KAC/H;AACA,IAAA,IAAI,CAAA,CAAE,aAAa,CAAA,EAAG;AACpB,MAAA,MAAM,IAAI,KAAA;AAAA,QACR,CAAA,gDAAA,EAAmD,MAAM,CAAA,GAAA,EAAM,CAAA,CAAE,MAAA,CAAO,MAAK,IAAK,CAAA,KAAA,EAAQ,CAAA,CAAE,QAAQ,CAAA,CAAE,CAAA;AAAA,OACxG;AAAA,IACF;AAAA,EACF;AAAA,EAES,OAAA,CAAQ,SAAiB,IAAA,EAA+B;AAC/D,IAAA,MAAM,OAAA,GAAU,IAAA,CAAK,WAAA,CAAY,OAAO,CAAA;AACxC,IAAA,IAAI,YAAY,IAAA,EAAM,OAAO,KAAA,CAAM,OAAA,CAAQ,SAAS,IAAI,CAAA;AACxD,IAAA,OAAO,KAAA,CAAM,OAAA,CAAQ,OAAA,EAAS,IAAI,CAAA;AAAA,EACpC;AACF;AAEA,IAAI,YAAA,GAAe,KAAA;AAgBZ,SAAS,kBAAA,CAAmB,MAAc,IAAA,EAA+C;AAC9F,EAAA,IAAI,SAAS,KAAA,EAAO;AAClB,IAAA,IAAI,CAAC,YAAA,EAAc;AACjB,MAAA,YAAA,GAAe,IAAA;AACf,MAAA,IAAA,CAAK,oBAAA,CAAqB,IAAI,CAAC,CAAA;AAAA,IACjC;AACA,IAAA,OAAO,MAAA;AAAA,EACT;AACA,EAAA,IAAI;AACF,IAAA,MAAM,MAAM,WAAA,CAAY,IAAA,CAAK,MAAA,EAAO,EAAG,aAAa,CAAC,CAAA;AACrD,IAAA,MAAMF,KAAAA,GAAO,IAAA,CAAK,GAAA,EAAK,YAAY,CAAA;AACnC,IAAA,MAAM,OAAA,GAAU,kBAAA,CAAmB,EAAE,iBAAA,EAAmB,MAAM,CAAA;AAC9D,IAAA,aAAA,CAAcA,OAAM,OAAO,CAAA;AAC3B,IAAA,mBAAA,CAAoBA,OAAM,OAAO,CAAA;AACjC,IAAA,eAAA,CAAgB,GAAG,CAAA;AACnB,IAAA,OAAOA,KAAAA;AAAA,EACT,SAAS,GAAA,EAAK;AACZ,IAAA,IAAA;AAAA,MACE,yCAAyC,GAAA,YAAe,KAAA,GAAQ,IAAI,OAAA,GAAU,MAAA,CAAO,GAAG,CAAC,CAAA,qFAAA;AAAA,KAE3F;AACA,IAAA,OAAO,MAAA;AAAA,EACT;AACF;AAEA,IAAI,iBAAA;AAOG,SAAS,qBAAA,GAA4C;AAC1D,EAAA,IAAI,iBAAA,KAAsB,MAAA,EAAW,OAAO,iBAAA,IAAqB,MAAA;AACjE,EAAA,MAAMA,KAAAA,GAAO,kBAAA,CAAmB,OAAA,CAAQ,IAAA,EAAM,CAAC,CAAA,KAAM,OAAA,CAAQ,IAAA,CAAK,aAAA,CAAc,CAAC,CAAC,CAAC,CAAA;AACnF,EAAA,iBAAA,GAAoBA,KAAAA,IAAQ,IAAA;AAC5B,EAAA,OAAOA,KAAAA;AACT;AAEA,IAAI,iBAAA,GAAoB,KAAA;AAcjB,SAAS,+BAAA,GAAwC;AACtD,EAAA,iBAAA,GAAoB,KAAA;AACtB;AAcO,SAAS,sBAAsB,IAAA,EAGnB;AACjB,EAAA,IAAI,IAAA,CAAK,SAAS,oBAAA,EAAsB;AACtC,IAAA,OAAO,EAAE,IAAA,EAAM,IAAA,CAAK,MAAM,QAAA,EAAU,KAAA,EAAO,QAAQ,qCAAA,EAAsC;AAAA,EAC3F;AACA,EAAA,MAAM,SAAA,GAAA,CAAa,IAAA,CAAK,MAAA,IAAU,mBAAA,GAAqB;AACvD,EAAA,IAAI,CAAC,UAAU,EAAA,EAAI;AACjB,IAAA,OAAO,EAAE,IAAA,EAAM,IAAA,CAAK,IAAA,EAAM,QAAA,EAAU,OAAO,MAAA,EAAQ,CAAA,wBAAA,EAAsB,SAAA,CAAU,MAAM,CAAA,CAAA,EAAG;AAAA,EAC9F;AACA,EAAA,OAAO,EAAE,IAAA,EAAM,IAAA,CAAK,MAAM,QAAA,EAAU,IAAA,EAAM,QAAQ,gBAAA,EAAiB;AACrE;AAqCO,SAAS,qBAAqB,IAAA,EAAmD;AACtF,EAAA,MAAM,SAAwB,EAAE,OAAA,EAAS,KAAK,OAAA,EAAS,SAAA,EAAW,KAAK,SAAA,EAAU;AACjF,EAAA,0BAAA,CAA2B,KAAK,aAAA,EAAe,IAAA,CAAK,IAAA,EAAM,IAAA,CAAK,UAAU,mBAAmB,CAAA;AAC5F,EAAA,IAAI,KAAK,IAAA,KAAS,oBAAA,EAAsB,OAAO,IAAI,aAAa,MAAM,CAAA;AAEtE,EAAA,MAAM,SAAA,GAAA,CAAa,IAAA,CAAK,MAAA,IAAU,mBAAA,GAAqB;AACvD,EAAA,IAAI,CAAC,UAAU,EAAA,EAAI;AACjB,IAAA,IAAI,CAAC,iBAAA,EAAmB;AACtB,MAAA,iBAAA,GAAoB,IAAA;AACpB,MAAA,MAAM,IAAA,GAAO,KAAK,IAAA,KAAS,CAAC,MAAc,OAAA,CAAQ,IAAA,CAAK,aAAA,CAAc,CAAC,CAAC,CAAA,CAAA;AACvE,MAAA,IAAA;AAAA,QACE,CAAA,4CAAA,EAA+C,SAAA,CAAU,MAAM,CAAA,8DAAA,EACL,KAAK,IAAI,CAAA,EAAA;AAAA,OACrE;AAAA,IACF;AACA,IAAA,OAAO,IAAI,aAAa,MAAM,CAAA;AAAA,EAChC;AACA,EAAA,OAAO,IAAI,aAAa,MAAA,EAAQ,EAAE,GAAG,IAAA,EAAM,GAAA,EAAK,SAAA,CAAU,GAAA,EAAK,CAAA;AACjE;AAUA,IAAI,iBAAA,GAAoB,KAAA;AAQjB,SAAS,mCAAA,GAA4C;AAC1D,EAAA,iBAAA,GAAoB,KAAA;AACtB;AAgBA,SAAS,yBAAyB,WAAA,EAA8C;AAC9E,EAAA,OAAO,WAAA,GAAc,MAAA,GAAY,wBAAA,CAAyB,CAAC,CAAA,KAAM,QAAQ,IAAA,CAAK,aAAA,CAAc,CAAC,CAAC,CAAC,CAAA;AACjG;AA2CA,SAAS,kBAAkB,IAAA,EAA6C;AACtE,EAAA,0BAAA,CAA2B,KAAK,aAAA,EAAe,IAAA,CAAK,IAAA,EAAM,IAAA,CAAK,UAAU,mBAAmB,CAAA;AAC5F,EAAA,IAAI,IAAA,CAAK,IAAA,KAAS,oBAAA,EAAsB,OAAO,IAAA;AAE/C,EAAA,MAAM,SAAA,GAAA,CAAa,IAAA,CAAK,MAAA,IAAU,mBAAA,GAAqB;AACvD,EAAA,IAAI,SAAA,CAAU,EAAA,EAAI,OAAO,SAAA,CAAU,GAAA;AAEnC,EAAA,IAAI,CAAC,iBAAA,EAAmB;AACtB,IAAA,iBAAA,GAAoB,IAAA;AACpB,IAAA,MAAM,IAAA,GAAO,KAAK,IAAA,KAAS,CAAC,MAAc,OAAA,CAAQ,IAAA,CAAK,aAAA,CAAc,CAAC,CAAC,CAAA,CAAA;AACvE,IAAA,IAAA;AAAA,MACE,CAAA,4CAAA,EAA+C,SAAA,CAAU,MAAM,CAAA,2EAAA,EACZ,KAAK,IAAI,CAAA,EAAA;AAAA,KAC9D;AAAA,EACF;AACA,EAAA,OAAO,IAAA;AACT;AAkBO,SAAS,uBACd,IAAA,EACiD;AACjD,EAAA,OAAO,CAAC,SAAiB,GAAA,KAA+B;AACtD,IAAA,MAAM,GAAA,GAAM,kBAAkB,IAAI,CAAA;AAClC,IAAA,IAAI,GAAA,KAAQ,MAAM,OAAO,IAAA;AAEzB,IAAA,OAAO,qBAAA;AAAA,MACL,IAAA,CAAK,IAAA;AAAA,MACL;AAAA,QACE,GAAA;AAAA,QACA,OAAA,EAAS,KAAK,OAAA,IAAW,KAAA;AAAA,QACzB,KAAK,cAAA,EAAe;AAAA,QACpB,GAAA;AAAA,QACA,cAAA,EAAgB,wBAAA,CAAyB,IAAA,CAAK,OAAA,IAAW,KAAK,CAAA;AAAA,QAC9D,eAAe,IAAA,CAAK;AAAA,OACtB;AAAA,MACA;AAAA,KACF;AAAA,EACF,CAAA;AACF;;;ACxfO,IAAM,kBAAA,GAAN,cAAiC,iBAAA,CAAkB;AAAA,EAGxD,WAAA,CACW,UAAA,EACT,OAAA,EACA,OAAA,GAA+B,EAAC,EAChC;AACA,IAAA,KAAA,CAAM,CAAA,CAAA,EAAI,UAAU,CAAA,EAAA,EAAK,OAAO,CAAA,CAAA,EAAI;AAAA,MAClC,IAAA,EAAM,uBAAA;AAAA,MACN,WAAA,EAAa,KAAA;AAAA,MACb,GAAI,QAAQ,KAAA,KAAU,MAAA,GAAY,EAAE,KAAA,EAAO,OAAA,CAAQ,KAAA,EAAM,GAAI;AAAC,KAC/D,CAAA;AARQ,IAAA,IAAA,CAAA,UAAA,GAAA,UAAA;AAAA,EASX;AAAA,EATW,UAAA;AAAA,EAHO,IAAA,GAAO,oBAAA;AAa3B;AAyBA,IAAM,gBAAA,GAAmB,8BAAA;AAiBzB,eAAsB,aAAA,CACpB,eACA,SAAA,EAC8B;AAC9B,EAAA,MAAM,OAAA,GAAU,SAAA,KAAc,MAAA,GAAa,aAAA,GAAmC,IAAI,YAAA,EAAa;AAC/F,EAAA,MAAM,OAAO,SAAA,IAAc,aAAA;AAC3B,EAAA,MAAM,EAAE,OAAA,EAAS,GAAA,EAAK,UAAA,EAAW,GAAI,IAAA;AAGrC,EAAA,IAAI,CAAC,gBAAA,CAAiB,IAAA,CAAK,UAAU,CAAA,EAAG;AACtC,IAAA,MAAM,IAAI,kBAAA;AAAA,MACR,UAAA;AAAA,MACA;AAAA,KACF;AAAA,EACF;AACA,EAAA,IAAI,GAAA,CAAI,UAAA,CAAW,GAAG,CAAA,EAAG;AACvB,IAAA,MAAM,IAAI,kBAAA,CAAmB,UAAA,EAAY,CAAA,0CAAA,EAA6C,GAAG,CAAA,CAAA,CAAG,CAAA;AAAA,EAC9F;AAIA,EAAA,MAAM,KAAA,GAAQ,MAAM,OAAA,CAAQ,OAAA;AAAA,IAC1B,oDAAoD,gBAAA,CAAiB,OAAO,CAAC,CAAA,CAAA,EAAI,gBAAA,CAAiB,UAAU,CAAC,CAAA;AAAA,GAC/G;AACA,EAAA,IAAI,KAAA,CAAM,aAAa,CAAA,EAAG;AACxB,IAAA,MAAM,IAAI,mBAAmB,UAAA,EAAY,CAAA,cAAA,EAAiB,MAAM,MAAA,CAAO,IAAA,EAAM,CAAA,CAAE,CAAA;AAAA,EACjF;AAEA,EAAA,MAAM,GAAA,GAAM,MAAM,OAAA,CAAQ,OAAA;AAAA,IACxB,CAAA,OAAA,EAAU,gBAAA,CAAiB,UAAU,CAAC,CAAA,0BAAA;AAAA,GACxC;AACA,EAAA,IAAI,GAAA,CAAI,aAAa,CAAA,EAAG;AACtB,IAAA,MAAM,IAAI,mBAAmB,UAAA,EAAY,CAAA,wBAAA,EAA2B,IAAI,MAAA,CAAO,IAAA,EAAM,CAAA,CAAE,CAAA;AAAA,EACzF;AACA,EAAA,MAAM,OAAA,GAAU,GAAA,CAAI,MAAA,CAAO,IAAA,EAAK;AAGhC,EAAA,MAAM,QAAA,GAAW,MAAM,OAAA,CAAQ,OAAA;AAAA,IAC7B,UAAU,gBAAA,CAAiB,OAAO,CAAC,CAAA,kBAAA,EAAqB,gBAAA,CAAiB,GAAG,CAAC,CAAA;AAAA,GAC/E;AACA,EAAA,IAAI,QAAA,CAAS,aAAa,CAAA,EAAG;AAC3B,IAAA,MAAM,IAAI,kBAAA,CAAmB,UAAA,EAAY,CAAA,SAAA,EAAY,GAAG,YAAY,QAAA,CAAS,MAAA,CAAO,IAAA,EAAM,CAAA,CAAE,CAAA;AAAA,EAC9F;AAEA,EAAA,OAAO,EAAE,OAAA,EAAQ;AACnB","file":"index.js","sourcesContent":["import { realpathSync, statSync } from \"node:fs\";\nimport path from \"node:path\";\nimport type { BwrapDetection, SandboxMode } from \"./types.js\";\nimport { SandboxNotAvailableError } from \"./types.js\";\n\n/** Paths the confined shell must keep: masking one would remove the command's own working ground. */\nconst KEPT_ROOTS_ALWAYS = [\"/tmp\"] as const;\n\n/** True when `inner` is `outer` or lies under it. */\nfunction isSameOrInside(outer: string, inner: string): boolean {\n const rel = path.relative(outer, inner);\n return rel === \"\" || (!rel.startsWith(\"..\") && !path.isAbsolute(rel));\n}\n\nfunction resolveEntry(entry: string): string {\n if (!path.isAbsolute(entry)) {\n throw new TypeError(`denyReadPaths: \"${entry}\" is not an absolute path`);\n }\n try {\n return realpathSync(entry);\n } catch (cause) {\n throw new TypeError(`denyReadPaths: \"${entry}\" cannot be resolved: ${String(cause)}`);\n }\n}\n\nfunction keptRoots(cwd: string): string[] {\n let real = cwd;\n try {\n real = realpathSync(cwd);\n } catch {\n // cwd does not exist yet: the resolved spelling is the only one there is\n }\n return [...new Set([cwd, real, ...KEPT_ROOTS_ALWAYS])];\n}\n\n/**\n * The bwrap flags that make each path in `paths` unreadable inside the sandbox: `--tmpfs` for a\n * directory, `--ro-bind /dev/null` for a file. Callers place them after the writable binds so the\n * mask wins over a path inside the workspace or `/tmp`.\n *\n * Every entry is resolved through symlinks first, so reading through a link is denied too, and\n * duplicates collapse in list order. A masked file is still listed in its directory; only reading it\n * fails.\n *\n * Throws `TypeError` (never skips) for a relative or missing entry, an entry that equals or contains\n * the working directory, `/tmp` or `/`, and any non-empty list under `danger-full-access`, where no\n * mask can be applied.\n */\nexport function denyReadFlags(\n paths: readonly string[] | undefined,\n policy: { mode: SandboxMode; cwd: string },\n): string[] {\n if (paths === undefined || paths.length === 0) return [];\n if (policy.mode === \"danger-full-access\") {\n throw new TypeError(\n \"denyReadPaths cannot be honoured under danger-full-access: no sandbox is applied\",\n );\n }\n const roots = keptRoots(policy.cwd);\n const resolved = new Set<string>();\n for (const entry of paths) {\n const target = resolveEntry(entry);\n const covered = roots.find((root) => isSameOrInside(target, root));\n if (covered !== undefined) {\n throw new TypeError(\n `denyReadPaths: \"${entry}\" would hide \"${covered}\", which the command needs`,\n );\n }\n resolved.add(target);\n }\n return [...resolved].flatMap((target) =>\n statSync(target).isDirectory() ? [\"--tmpfs\", target] : [\"--ro-bind\", \"/dev/null\", target],\n );\n}\n\n/**\n * Refuses a non-empty deny list that no confinement can honour, before a backend or a wrap exists:\n * `danger-full-access` applies no sandbox (`TypeError`), and an undetected bubblewrap would fall back\n * to an unconfined run, which is the leak the list exists to stop (`SandboxNotAvailableError`).\n */\nexport function refuseUnhonourableDenyRead(\n paths: readonly string[] | undefined,\n mode: SandboxMode,\n detect: () => BwrapDetection,\n): void {\n if (paths === undefined || paths.length === 0) return;\n if (mode === \"danger-full-access\") denyReadFlags(paths, { mode, cwd: \"/\" }); // throws TypeError\n const detection = detect();\n if (!detection.ok) {\n throw new SandboxNotAvailableError(\n `denyReadPaths needs kernel confinement and it is unavailable (${detection.reason}); refusing to run unconfined`,\n );\n }\n}\n","// Promoted out of the agent-builder in M75 (plan m75-sandbox-kernel-no-framework, D1): kernel\n// confinement is framework infrastructure, not the consumer's. Measured cost of the promotion: ZERO\n// dependencies — only node:child_process, node:fs and node:path. The cBPF filter is a pure-JS Buffer.\n\nimport { execFileSync } from \"node:child_process\";\nimport { existsSync } from \"node:fs\";\nimport path from \"node:path\";\n\nimport { denyReadFlags } from \"./deny-read.js\";\nimport type { BwrapDetection, SandboxMode } from \"./types.js\";\n\n/*\n * M53 — bubblewrap argv + honest detection.\n *\n * HONEST SCOPE: filesystem confinement + network isolation via bwrap, PLUS the second stage —\n * a cBPF seccomp syscall filter (`agents/sandbox/seccomp.ts`), wired in `agents/sandbox/backend.ts`\n * via `restrictedSeccompPath()`. Ported in M63; this block claimed the opposite until M67 and\n * UNDER-DECLARED the real security posture. The honest limit that remains: the filter is **x86_64**\n * (an architecture guard refuses to install it on any other arch, with a WARN, and bwrap's FS/network\n * confinement still applies) **and** it is only installed when the network is restricted\n * (`backend.ts:87`, faithful to `landlock.rs:96-117`): with the network on there is no syscall\n * filter, only bwrap's FS confinement. `danger-full-access` skips bwrap entirely, mirroring\n * `bwrap.rs:245-252`. Deltas versus Codex remain documented in docs/CODEX-PARITY.md.\n */\n\n/**\n * Codex's three canonical modes. Defined HERE because they are sandbox vocabulary, not consumer\n * configuration: `danger-full-access` means \"do not wrap\", and that is a decision belonging to the\n * confinement subsystem.\n */\nexport type { SandboxMode } from \"./types.js\";\n\n/**\n * The RW binds `workspace-write` installs (protocol.rs:1189-1214), plus the metadata protection that\n * must sit ON TOP of them — order matters (permissions.rs:22-31; bwrap.rs:571-597).\n */\nfunction pushWorkspaceBinds(argv: string[], cwd: string, hasGit: boolean, gitDir: string): void {\n for (const root of workspaceWriteRoots(cwd)) argv.push(\"--bind\", root, root);\n if (hasGit) argv.push(\"--ro-bind\", gitDir, gitDir);\n}\n\n/** The RW binds `workspace-write` installs (protocol.rs:1189-1214): the workspace itself, and /tmp. */\nfunction workspaceWriteRoots(cwd: string): readonly string[] {\n return [cwd, \"/tmp\"];\n}\n\n/**\n * U-6 — the roots a mode may write to, answerable WITHOUT spawning anything.\n *\n * `[]` means nothing is writable; `null` means unrestricted — which is not the same as `[\"/\"]`,\n * because unrestricted is the absence of a root rather than a root that happens to be `/`.\n *\n * The SDK already knew this: `buildBwrapArgv` binds these exact paths. It only knew it while\n * BUILDING an argv, and a consumer needs the answer earlier — tools are scoped at agent\n * construction, before any process exists, and a file-write tool has to be told its root then. With\n * nothing to ask, consumers keep a second encoding of this three-mode vocabulary and it drifts from\n * the argv builder with nothing to catch it. This reads from the same helper the builder uses, so\n * the two cannot disagree.\n */\nexport function writableRootsFor(mode: SandboxMode, cwd: string): readonly string[] | null {\n switch (mode) {\n case \"read-only\":\n return [];\n case \"workspace-write\":\n return workspaceWriteRoots(cwd);\n case \"danger-full-access\":\n return null;\n }\n}\n\n/**\n * Everything {@link buildBwrapArgv} needs besides the {@link SandboxMode}.\n *\n * Only `cwd` is required, and it is resolved to an absolute path before any bind\n * is emitted. The defaults are the restrictive ones in one direction and the\n * permissive one in the other: omitting `network` emits `--unshare-net` (no\n * network), while omitting `env` means the child INHERITS the parent\n * environment — bwrap only clears it when an allowlist is supplied.\n */\nexport interface BwrapArgvOptions {\n /** Workspace root — the single RW bind under `workspace-write` (protocol.rs:1189-1200). */\n cwd: string;\n /** `true` removes `--unshare-net` (policy `network_access`, default false). */\n network?: boolean;\n /** Injectable for tests; defaults to a real `existsSync` check on `<cwd>/.git`. */\n gitDirExists?: boolean;\n /**\n * When present, emit `--clearenv` and re-inject ONLY these vars (Codex env_clear model,\n * `exec_env.rs:25-31`). Closes the denylist gap: a secret in an oddly-named var never reaches the\n * sandboxed child. Omitted ⇒ inherit the parent env (backward-compatible; SDK scrub still applies).\n */\n env?: Record<string, string>;\n /**\n * Absolute paths the confined command must not read. Each is resolved through symlinks and masked\n * after the writable binds: a directory becomes empty, a file reads as permission denied. A masked\n * file still shows in the listing of its directory. Throws `TypeError` for a relative or missing\n * path, one that contains the workspace, `/tmp` or `/`, and any list under `danger-full-access`.\n */\n denyReadPaths?: readonly string[];\n}\n\n/**\n * Pure argv builder. Returns the bwrap flags ending in `--` (caller appends `/bin/sh -c <cmd>`),\n * or `null` when the policy skips the sandbox entirely (`danger-full-access`).\n */\nexport function buildBwrapArgv(mode: SandboxMode, opts: BwrapArgvOptions): string[] | null {\n const cwd = path.resolve(opts.cwd);\n const denyFlags = denyReadFlags(opts.denyReadPaths, { mode, cwd }); // throws before the null below\n if (mode === \"danger-full-access\") return null; // bwrap skipped entirely (bwrap.rs:245-252)\n\n const gitDir = path.join(cwd, \".git\");\n const hasGit = opts.gitDirExists ?? existsSync(gitDir);\n\n const argv: string[] = [\n // core, always (bwrap.rs:318-332; user+pid namespaces explicit so it works as root in containers)\n \"--new-session\",\n \"--die-with-parent\",\n \"--unshare-user\",\n \"--unshare-pid\",\n // full-read filesystem base (bwrap.rs:446-452)\n \"--ro-bind\",\n \"/\",\n \"/\",\n \"--dev\",\n \"/dev\",\n \"--proc\",\n \"/proc\",\n ];\n\n if (!opts.network) argv.push(\"--unshare-net\"); // network off by default (bwrap.rs:325-327)\n\n // env confinement — `--clearenv` MUST precede every `--setenv` or the clear wipes them\n // (exec_env.rs:25-31 clears then rebuilds). Only when an explicit allowlist is provided.\n if (opts.env) argv.push(\"--clearenv\");\n const setenv: Record<string, string> = {\n ...(opts.env ?? {}),\n // the flag signals the child that network is unshared (spawn.rs:20,79)\n ...(opts.network ? {} : { CODEX_SANDBOX_NETWORK_DISABLED: \"1\" }),\n };\n for (const [k, v] of Object.entries(setenv)) argv.push(\"--setenv\", k, v);\n\n if (mode === \"workspace-write\") pushWorkspaceBinds(argv, cwd, hasGit, gitDir);\n // read-only: zero writable roots (protocol.rs:1176) — nothing to add\n argv.push(...denyFlags); // after the writable binds so a mask inside the workspace or /tmp wins\n\n argv.push(\"--chdir\", cwd, \"--\");\n return argv;\n}\n\n/** Injectable probes — each mirrors one Codex availability check. */\nexport interface BwrapProbes {\n /** `which bwrap` outside the cwd (anti-hijack, sandboxing/src/bwrap.rs:168-191). */\n which: () => string | null;\n /** `bwrap --help` text — must advertise `--perms` (launcher.rs:108-124). */\n helpText: (bin: string) => string | null;\n /** Active user-namespace probe with timeout (sandboxing/src/bwrap.rs:74-136). */\n userns: (bin: string) => boolean;\n}\n\n/**\n * Result of {@link detectBwrap} / {@link detectBwrapMemoized}, discriminated on\n * `ok`: `{ ok: true, bin }` carries the absolute path of the validated `bwrap`,\n * `{ ok: false, reason }` a human-readable cause — \"bwrap not found in PATH\",\n * \"bwrap at <bin> lacks --perms support (too old)\",\n * \"user namespaces unavailable (container/kernel restriction)\",\n * \"bwrap probe failed: <err>\", or (memoized only)\n * \"bwrap disappeared from <bin> after detection\".\n *\n * `reason` is prose for a warning line. It is not a stable code — do not branch\n * on it.\n *\n * `ok: false` is an ordinary outcome rather than an error: bubblewrap is\n * Linux-only, so failing detection on macOS, on Windows, or inside a container\n * without user namespaces is expected. Detection NEVER throws, so wrapping it in\n * `try`/`catch` catches nothing; callers warn and fall back to an unconfined\n * `LocalSandbox`.\n */\nexport type { BwrapDetection } from \"./types.js\";\n\n/** Honest detection — fail-closed on every probe; NEVER throws (callers WARN + fall back). */\nexport function detectBwrap(probes: BwrapProbes = realProbes): BwrapDetection {\n try {\n const bin = probes.which();\n if (!bin) return { ok: false, reason: \"bwrap not found in PATH\" };\n const help = probes.helpText(bin);\n if (!help?.includes(\"--perms\")) {\n return { ok: false, reason: `bwrap at ${bin} lacks --perms support (too old)` };\n }\n if (!probes.userns(bin)) {\n return { ok: false, reason: \"user namespaces unavailable (container/kernel restriction)\" };\n }\n return { ok: true, bin };\n } catch (err) {\n return {\n ok: false,\n reason: `bwrap probe failed: ${err instanceof Error ? err.message : String(err)}`,\n };\n }\n}\n\n/**\n * How many times the REAL probe ran in this process.\n *\n * Instrumented here rather than in a wrapper, because this is where the cost is: every `which`\n * spawns a subprocess (`which bwrap`), and the full probe cost 22.2 ms. A gate counting INJECTED\n * probes does not see the real one — that was the M71 gate's first mistake, and a mutant exposed it.\n */\nlet realProbeRuns = 0;\n\n/** How many real probes ran. TEST seam — the performance gate counts this. */\nexport function realProbeCount(): number {\n return realProbeRuns;\n}\n\n/** Real probes used in production. */\nexport const realProbes: BwrapProbes = {\n which: () => {\n realProbeRuns++;\n try {\n const out = execFileSync(\"which\", [\"bwrap\"], { encoding: \"utf8\", timeout: 2_000 }).trim();\n // anti-hijack: never accept a bwrap that lives inside the workspace (bwrap.rs:168-191)\n if (!out || out.startsWith(process.cwd() + path.sep)) return null;\n return out;\n } catch {\n return null;\n }\n },\n helpText: (bin) => {\n try {\n // bwrap --help exits 0/1 depending on version; capture output either way\n return execFileSync(bin, [\"--help\"], { encoding: \"utf8\", timeout: 2_000 });\n } catch (err) {\n const e = err as { stdout?: string; stderr?: string };\n return [e.stdout, e.stderr].filter(Boolean).join(\"\\n\") || null;\n }\n },\n userns: (bin) => {\n try {\n // active probe, 500ms budget like Codex (sandboxing/src/bwrap.rs:74-136)\n execFileSync(bin, [\"--unshare-user\", \"--unshare-net\", \"--ro-bind\", \"/\", \"/\", \"/bin/true\"], {\n timeout: 500,\n stdio: \"ignore\",\n });\n return true;\n } catch {\n return false;\n }\n },\n};\n\n/**\n * The probe result, memoized for the lifetime of the PROCESS.\n *\n * Measured before M71: `detectBwrap()` costs **22.2 ms** and was not memoized — the second call\n * cost 19.4 ms. `buildChatAgent` on the headless path fired **two** (one from\n * `createSandboxBackend`, another from `resolveSandboxPosture`, which M70 added), totalling 46.4 ms\n * per construction — and construction happens per turn. Under `strace`, ~90% of the 182 syscalls of\n * an already-warm construction came from here: `which` sweeping the PATH, `/proc/filesystems`,\n * `/newroot`, and the `.so` files the two probe subprocesses load.\n *\n * ## Why there is no invalidation\n *\n * The milestone called for invalidating on `SessionStart`. That does not work:\n * `agents/lib/hooks/hooks.ts:28-30` documents — as a **measured** correction of an earlier\n * assumption — that the event fires **once per TURN**, not per session. Invalidating there would\n * re-probe every turn, exactly the behavior memoization exists to eliminate.\n *\n * A write-once cache is sufficient here: the expensive probe runs once per process,\n * only to print a UI warning.\n *\n * **The price, stated plainly — in BOTH directions.** The original m71-cost-per-turn#ADR-1 declared\n * only one of them; the M71 review (F-perf-9) showed the omitted one was precisely the one with a\n * security consequence:\n *\n * - **Stale negative** (`bwrap` installed AFTERWARDS): not detected until restart. The system fails\n * CLOSED — the posture reports `enforced: false` and M70's veto **refuses**. Cost: annoyance (the\n * message tells you to install the bwrap you just installed). Accepted.\n * - **Stale positive** (`bwrap` removed/renamed AFTERWARDS): the posture would keep asserting\n * `enforced: true / \"kernel (bwrap)\"` and the veto would **approve**, citing a confinement that no\n * longer exists. That is the literal reintroduction of the defect M70 fixed — *\"telling the\n * operator they are protected when they are not is worse than saying nothing\"*. Before M71 the\n * per-turn re-probe closed that window on the next turn; memoization would leave it open for the\n * whole process. **That is why the positive is revalidated** below, at 1 syscall — 3 orders of\n * magnitude below the 22.2 ms of the full probe, which is the cost memoization exists to remove.\n */\nlet memo: BwrapDetection | undefined;\n\n/**\n * `detectBwrap` with memoization — what production should call.\n *\n * Note that `detectBwrap` itself does **not** memoize, on purpose: it accepts injected probes, and\n * memoizing there would let a test with fake probes poison the process cache for everyone else.\n *\n * Revalidating the positive is NOT a re-probe: `detectBwrap` spends three probes (a `which`\n * subprocess + `--help` + a user namespace). Here we only confirm the validated binary is still in\n * place. If it vanished, the memo is downgraded to a negative with the reason stated — never\n * promoted to a positive, which would require the expensive probe back.\n */\nexport function detectBwrapMemoized(probes: BwrapProbes = realProbes): BwrapDetection {\n memo ??= detectBwrap(probes);\n if (memo.ok && !existsSync(memo.bin)) {\n memo = { ok: false, reason: `bwrap disappeared from ${memo.bin} after detection` };\n }\n return memo;\n}\n\n/**\n * Clears the `detectBwrapMemoized` memo.\n *\n * Kept PUBLIC, unlike the two warn-latch resets that moved to the `__…ForTests` convention, because\n * this one has a use outside a test that the others do not: a long-lived host that probed before\n * `bwrap` was installed is memoized on the wrong answer forever, and this is the only way to make it\n * re-probe. It is the companion to `detectBwrapMemoized` and is documented as such rather than as a\n * seam. Production inside this package never calls it (see m71-cost-per-turn#ADR-1).\n *\n * @public\n */\nexport function resetBwrapMemo(): void {\n memo = undefined;\n}\n","// Promoted from agent-builder in M75 (plan m75-sandbox-kernel-no-framework, D1): confinement with\n// kernel confinement is framework infrastructure, not the consumer's. Measured cost of the promotion: ZERO\n// no dependencies — only node:child_process, node:fs and node:path. The cBPF filter is a Buffer in pure JS.\n\n/**\n * M63 — cBPF seccomp filter generator. Produces a raw `sock_filter[]` program (the exact\n * shape `bwrap --seccomp <fd>` consumes) so syscall confinement needs no\n * native helper — bwrap applies `PR_SET_NO_NEW_PRIVS` + the filter before `execve`.\n *\n * Semantics (landlock.rs:252-253): default action = ALLOW; per-syscall match = ERRNO(EPERM). KILL is\n * used ONLY by the architecture/x32 guard. x86_64 only in v1 (aarch64 is a documented delta).\n */\n\n// BPF opcodes (linux/bpf_common.h)\nconst BPF_LD = 0x00;\nconst BPF_W = 0x00;\nconst BPF_ABS = 0x20;\nconst BPF_JMP = 0x05;\nconst BPF_JEQ = 0x10;\nconst BPF_JGE = 0x30;\nconst BPF_K = 0x00;\nconst BPF_RET = 0x06;\n\nconst LD_ABS_W = BPF_LD | BPF_W | BPF_ABS; // 0x20\nconst JEQ_K = BPF_JMP | BPF_JEQ | BPF_K; // 0x15\nconst JGE_K = BPF_JMP | BPF_JGE | BPF_K; // 0x35\nconst RET_K = BPF_RET | BPF_K; // 0x06\n\n// seccomp_data offsets (little-endian): nr@0, arch@4, args[0] low dword @16\nconst OFF_NR = 0;\nconst OFF_ARCH = 4;\nconst OFF_ARG0 = 16;\n\nconst AUDIT_ARCH_X86_64 = 0xc000003e;\nconst X32_BIT = 0x40000000; // nr >= this ⇒ x32 ABI ⇒ reject\n\n// seccomp return actions (linux/seccomp.h)\nconst SECCOMP_RET_ALLOW = 0x7fff0000;\nconst SECCOMP_RET_ERRNO = 0x00050000;\nconst EPERM = 1;\nconst RET_EPERM = SECCOMP_RET_ERRNO | (EPERM & 0xffff); // 0x00050001\nconst SECCOMP_RET_KILL_PROCESS = 0x80000000;\n\nconst AF_UNIX = 1;\n\n/** Always-denied, network-independent (landlock.rs:179-184). */\nconst ALWAYS_DENIED = [101, 310, 311, 425, 426, 427]; // ptrace, process_vm_readv/writev, io_uring_setup/enter/register\n/**\n * Denied only when the network is restricted (landlock.rs:188-204). recvfrom(45)/sendmsg(46) are\n * NOT here — and, since #385, neither are `getsockname`(51), `getpeername`(52), `setsockopt`(54)\n * and `getsockopt`(55).\n *\n * Those four take an ALREADY-OPEN fd rather than an address, and cBPF cannot dereference an fd to\n * learn the family behind it. Denying them therefore denied them on AF_UNIX as well — which is\n * exactly what libuv calls on a child's IPC channel, so any command that spawned a child died.\n * Measured: `node --test` returned 0 lines under the filter and 38 without it, and the parent's\n * own stdout vanished with it (killed mid-flight, its buffered pipe write never flushed, while the\n * child's already-written bytes survived). The AF_UNIX exemption on `socket`/`socketpair` below\n * shows breaking local IPC was never the intent.\n *\n * They cannot reach a network on their own. Everything that takes an address or changes an fd's\n * role — `connect`, `bind`, `listen`, `accept`, `accept4`, `sendto`, `sendmmsg`, `recvmmsg`,\n * `shutdown` — stays denied, and `socket()` still refuses every family but AF_UNIX. Measured\n * unchanged across the fix: an AF_INET socket is `EPERM` before and after, an AF_UNIX socketpair\n * works before and after.\n *\n * The blunt alternative — dropping the whole set, on the grounds that `--unshare-net` already\n * removes the network — would restore the output AND let a confined command open a connection the\n * moment a future mode runs the filter with the network on. This keeps the belt.\n */\nconst NETWORK_DENIED = [42, 43, 288, 49, 50, 48, 44, 307, 299];\n/** socket(2) / socketpair(2) — conditional on domain != AF_UNIX (landlock.rs:206-216). */\nconst SOCKET_SYSCALLS = [41, 53];\n\n/** One `sock_filter` instruction: `{u16 code, u8 jt, u8 jf, u32 k}`. */\ninterface Insn {\n code: number;\n jt: number;\n jf: number;\n k: number;\n}\nconst stmt = (code: number, k: number): Insn => ({ code, jt: 0, jf: 0, k });\nconst jmp = (code: number, k: number, jt: number, jf: number): Insn => ({ code, jt, jf, k });\n\n/**\n * Input to {@link buildSeccompFilter} — the one axis the generated cBPF program varies on.\n *\n * `networkRestricted: true` adds the socket-family denials on top of the always-denied syscall set;\n * `false` emits the base program, which is NOT \"no filter\". The always-denied set applies either way.\n */\nexport interface SeccompOptions {\n /** When true (network off), also deny the socket set + non-AF_UNIX socket(). */\n networkRestricted: boolean;\n}\n\n/**\n * Build the cBPF seccomp program as a `Buffer` (each `sock_filter` = 8 bytes). Jump targets are\n * expressed against labels and back-patched to relative offsets, so the layout is deterministic and\n * unit-testable against the authoritative syscall list.\n */\nexport function buildSeccompFilter(opts: SeccompOptions): Buffer {\n // We assemble with symbolic targets, then resolve to relative jumps. To keep the classic\n // \"deny → jump to a single DENY return; else fall through\" shape, DENY and ALLOW live at the END and\n // every JEQ jumps FORWARD to them. jt/jf carry the DISTANCE (in instructions) to the target.\n const insns: Insn[] = [];\n\n // Placeholder labels resolved after we know total length.\n // Layout: [arch guard][x32 guard][LD nr][deny checks...][socket checks...][ALLOW][DENY][KILL]\n // We build the body first with jumps to ALLOW/DENY/KILL as sentinel indices, then patch.\n const ALLOW = Symbol(\"ALLOW\");\n const DENY = Symbol(\"DENY\");\n const KILL = Symbol(\"KILL\");\n type Target = typeof ALLOW | typeof DENY | typeof KILL | number;\n interface SInsn {\n code: number;\n k: number;\n jt: Target;\n jf: Target;\n }\n const body: SInsn[] = [];\n const push = (code: number, k: number, jt: Target = 0, jf: Target = 0): void => {\n body.push({ code, k, jt, jf });\n };\n\n // --- arch guard: arch == x86_64 ? continue : KILL ---\n push(LD_ABS_W, OFF_ARCH);\n push(JEQ_K, AUDIT_ARCH_X86_64, 0, KILL); // if != → KILL\n // --- x32 guard: nr >= 0x40000000 ? KILL : continue ---\n push(LD_ABS_W, OFF_NR);\n push(JGE_K, X32_BIT, KILL, 0); // if >= → KILL\n // nr already loaded; keep it loaded for the deny checks.\n\n // --- unconditional denials → DENY ---\n const denied = opts.networkRestricted\n ? [...ALWAYS_DENIED, ...NETWORK_DENIED]\n : [...ALWAYS_DENIED];\n for (const nr of denied) push(JEQ_K, nr, DENY, 0); // if nr == syscall → DENY\n\n // --- socket-family: socket(41)/socketpair(53) → allow only AF_UNIX (only when restricted) ---\n if (opts.networkRestricted) {\n for (const sysno of SOCKET_SYSCALLS) {\n // if nr == socket → check domain; else skip the 2 domain-check instructions\n push(JEQ_K, sysno, 0, 2); // match: fall through to the LD/JEQ; no-match: jump +2 (past them)\n push(LD_ABS_W, OFF_ARG0); // load domain (args[0] low dword)\n push(JEQ_K, AF_UNIX, ALLOW, DENY); // AF_UNIX → ALLOW, else DENY\n // NOTE: after these, nr is NO LONGER in the accumulator — but every remaining syscall check\n // reloads via a fresh LD? No: the remaining path is only ALLOW. socket checks are LAST before\n // the tail, so a fall-through (non-socket syscall that reached here) goes straight to ALLOW.\n }\n }\n\n // --- tail ---\n push(RET_K, SECCOMP_RET_ALLOW); // ALLOW label target\n const allowIdx = body.length - 1;\n push(RET_K, RET_EPERM); // DENY\n const denyIdx = body.length - 1;\n push(RET_K, SECCOMP_RET_KILL_PROCESS); // KILL\n const killIdx = body.length - 1;\n\n // --- resolve symbolic targets to relative offsets ---\n // The branching IS the cBPF program: ALLOW/DENY/KILL are symbolic targets resolved to an\n // offset RELATIVE to the next instruction. Breaking it into helpers does not reduce real complexity —\n // it moves the jump arithmetic to another file and makes auditing against landlock.rs harder, the\n // the authoritative source.\n //\n // Not refactoring NOW is an M75 process decision: this function is being MIGRATED without behavior\n // change (plan m75, D4) and there is still no byte-for-byte equivalence oracle against the\n // original version. Refactoring security without that oracle is changing the lock in the dark.\n // Revisit when the parity gate (T4.2) is green — the oracle exists then.\n // biome-ignore lint/complexity/noExcessiveCognitiveComplexity: see the reason just above\n const resolve = (i: number, t: Target): number => {\n const abs = t === ALLOW ? allowIdx : t === DENY ? denyIdx : t === KILL ? killIdx : i + 1 + t;\n // BPF jump offset is relative to the NEXT instruction: target - (i + 1)\n const off = abs - (i + 1);\n if (off < 0 || off > 255) throw new RangeError(`seccomp jump out of range at ${i}: ${off}`);\n return off;\n };\n // `for...of` over entries instead of a raw index: the SDK compiles with `noUncheckedIndexedAccess`, which\n // (correctly) types `body[i]` as possibly undefined. Iterating gives the guarantee in the type instead\n // requiring a `!` — the code already could not leave the range, and now the compiler knows it.\n for (const [i, b] of body.entries()) {\n if (b.code === JEQ_K || b.code === JGE_K) {\n insns.push(jmp(b.code, b.k, resolve(i, b.jt), resolve(i, b.jf)));\n } else {\n insns.push(stmt(b.code, b.k));\n }\n }\n\n const buf = Buffer.alloc(insns.length * 8);\n insns.forEach((ins, i) => {\n buf.writeUInt16LE(ins.code, i * 8);\n buf.writeUInt8(ins.jt, i * 8 + 2);\n buf.writeUInt8(ins.jf, i * 8 + 3);\n buf.writeUInt32LE(ins.k >>> 0, i * 8 + 4);\n });\n return buf;\n}\n","// B-600 — how the seccomp program reaches bwrap without ever sitting in a file.\n//\n// The program used to be written to `/tmp/ab-seccomp-*/filter.bpf` and read per command through\n// `3< <path>`. `/tmp` is a writable root under `workspace-write`, so one confined command could\n// overwrite that file, or rename its directory away and recreate it, and every LATER command loaded\n// an allow-all program. Every read-only-bind variant left a rename route for some placement of the\n// temp dir; a pipe fed from memory leaves nothing on disk to replace.\n\nimport { rmSync } from \"node:fs\";\nimport { dirname, resolve } from \"node:path\";\n\nimport { type SandboxMode, writableRootsFor } from \"./bwrap.js\";\nimport { buildSeccompFilter } from \"./seccomp.js\";\nimport { shellEscapePosix } from \"./shell-escape.js\";\n\n/** The warning both arch guards print, the path route's and this one: one text, two latches. */\nexport function nonX64SeccompWarning(arch: string): string {\n return (\n `[sandbox] seccomp syscall filter unsupported on ${arch} (x86_64 only in v1) — running without ` +\n \"the filter; bwrap FS/network confinement still applies.\"\n );\n}\n\nlet warnedNonX64Program = false;\n\n/**\n * The restricted-network program for `arch`, or `undefined` where it must not be installed.\n *\n * Same ARCH GUARD as `seccompPathForArch`: the program is x86_64 and KILLs every syscall from\n * another architecture, so on any other arch it is refused with one warning. The latch is this\n * function's own, so a process that also calls the deprecated path helper warns once from each.\n */\nexport function seccompProgramForArch(arch: string, warn: (m: string) => void): Buffer | undefined {\n if (arch !== \"x64\") {\n if (!warnedNonX64Program) {\n warnedNonX64Program = true;\n warn(nonX64SeccompWarning(arch));\n }\n return undefined;\n }\n return buildSeccompFilter({ networkRestricted: true });\n}\n\nlet memoizedProgram: Buffer | null | undefined; // undefined = not built yet; null = resolved absent\n\n/** The restricted-network program, built once per process and x64-gated. Never mutated. */\nexport function restrictedSeccompProgram(warn: (m: string) => void): Buffer | undefined {\n if (memoizedProgram === undefined)\n memoizedProgram = seccompProgramForArch(process.arch, warn) ?? null;\n return memoizedProgram ?? undefined;\n}\n\n/**\n * `program` as a `printf` format of three-digit octal escapes. Always three digits, so a digit that\n * follows is never absorbed into the escape; no `%` appears, so printf prints it verbatim.\n */\nfunction octalPrintfArg(program: Uint8Array): string {\n let out = \"\";\n for (const byte of program) out += `\\\\${byte.toString(8).padStart(3, \"0\")}`;\n return out;\n}\n\n/** A cBPF program is a non-empty list of 8-byte instructions; bwrap refuses anything else. */\nfunction assertSeccompProgramShape(program: Uint8Array): void {\n if (program.length === 0 || program.length % 8 !== 0) {\n throw new TypeError(\n `seccompProgram must be a positive multiple of 8 bytes, got ${program.length}`,\n );\n }\n}\n\n/**\n * The script the piped wrap runs. It is a constant: the program, bwrap's argv and the command reach\n * it as positional arguments, so each is shell-escaped exactly once. Escaping a word twice put a\n * backslash inside single quotes before a quote, which fish reads as an escaped quote.\n *\n * fd 4 saves the command's stdin before the pipe replaces fd 0 in the last stage; `3<&0` moves the\n * pipe to fd 3, `0<&4` restores stdin and `4<&-` closes the copy. Both `exec`s are required: they\n * make the process a timeout kills bwrap's direct parent, so `--die-with-parent` ends the confined\n * command with it. Without them a timeout left the command running.\n */\nconst PIPE_SCRIPT = '{ p=$1; shift; printf \"$p\" | exec \"$@\" 3<&0 0<&4 4<&-; } 4<&0';\n\n/**\n * Wrap `command` so bwrap reads `program` on fd 3 from a pipe:\n *\n * exec /bin/sh -c '<PIPE_SCRIPT>' sh <octal> <bwrap...> --seccomp 3 -- /bin/sh -c <cmd>\n *\n * The pipeline's grammar is always `/bin/sh`'s, whatever shell runs the outer words.\n * `bwrapArgv` is the binary and flags, unescaped, without `--seccomp` and the trailing `--`.\n */\nexport function wrapWithSeccompProgram(\n bwrapArgv: readonly string[],\n command: string,\n program: Uint8Array,\n): string {\n assertSeccompProgramShape(program);\n const words = [octalPrintfArg(program), ...bwrapArgv, \"--seccomp\", \"3\", \"--\", \"/bin/sh\", \"-c\"];\n return `exec /bin/sh -c ${shellEscapePosix(PIPE_SCRIPT)} sh ${[...words, command].map(shellEscapePosix).join(\" \")}`;\n}\n\n/** The programs `seccompPathForArch` wrote, by resolved path: the wrap loads these, never the file. */\nconst programsWritten = new Map<string, Buffer>();\n\n/**\n * Remember that `path` was written with `program`, so a wrap naming that file pipes the program\n * from memory: a sandbox that does not load the filter mounts `/tmp` writable and can replace it.\n */\nexport function rememberSeccompFile(path: string, program: Buffer): void {\n programsWritten.set(resolve(path), Buffer.from(program));\n}\n\n/**\n * Remove `dir` when the process exits or is told to stop. A SIGINT or SIGTERM listener cancels\n * Node's default termination, so once the directory is gone the signal is raised again when no other\n * listener remains: the process ends as it would have, and a host's own handler still decides.\n * The signal listener is prepended (B-648): run first, it still counts a host's `process.once`\n * handler, which Node unregisters before calling it, whether the host registered before or after.\n * A host that itself prepends a `once` handler after the filter still runs first and is not counted.\n */\nexport function removeDirOnExit(dir: string): void {\n const cleanup = (): void => rmSync(dir, { recursive: true, force: true });\n process.once(\"exit\", cleanup);\n for (const signal of [\"SIGINT\", \"SIGTERM\"] as const) {\n process.prependOnceListener(signal, () => {\n cleanup();\n if (process.listenerCount(signal) === 0) process.kill(process.pid, signal);\n });\n }\n}\n\n/**\n * The deprecated path route, with the filter bound read-only on top of every writable bind so the\n * confined command can neither overwrite it nor rename its directory away (B-600). A path\n * `seccompPathForArch` wrote is piped from memory instead of read, because another sandbox, one with\n * no filter, can still replace that file; any other path is read through `3< <path>`.\n *\n * `bwrapArgv` is the binary followed by `buildBwrapArgv`'s output, which ends `--chdir <cwd> --`;\n * the bind goes before `--chdir`, after every writable bind.\n */\nexport function wrapWithSeccompPath(\n bwrapArgv: readonly string[],\n policy: { mode: SandboxMode; cwd: string },\n command: string,\n seccompPath: string,\n): string {\n const program = programsWritten.get(resolve(seccompPath));\n // A remembered file is never read, so bwrap must not need it on disk: `--ro-bind-try`.\n const bind = program === undefined ? \"--ro-bind\" : \"--ro-bind-try\";\n const flags = [\n ...bwrapArgv.slice(0, -3),\n ...readOnlyBindForSeccompPath(policy.mode, policy.cwd, seccompPath, bind),\n ...bwrapArgv.slice(-3, -1),\n ];\n if (program !== undefined) return wrapWithSeccompProgram(flags, command, program);\n return `${[...flags, \"--seccomp\", \"3\", \"--\"].map(shellEscapePosix).join(\" \")} /bin/sh -c ${shellEscapePosix(command)} 3< ${shellEscapePosix(seccompPath)}`;\n}\n\n/**\n * The read-only bind for the filter. The DIRECTORY is bound, because binding only the file leaves\n * its parent renamable. Where that directory is a writable root or contains one (a filter at\n * `/x.bpf`, or directly in the workspace or `/tmp`), binding it would take a root's write access\n * away, so only the file is bound and a parent rename stays open there. A filter in a SUBdirectory\n * of a writable root makes that subdirectory read-only, and its ancestors stay renamable. Paths are\n * compared resolved, not through symlinks. `seccompProgram` has none of these gaps.\n */\nfunction readOnlyBindForSeccompPath(\n mode: SandboxMode,\n cwd: string,\n seccompPath: string,\n bind: \"--ro-bind\" | \"--ro-bind-try\",\n): string[] {\n const file = resolve(seccompPath);\n const dir = dirname(file);\n const roots = writableRootsFor(mode, resolve(cwd)) ?? [];\n const covers = (root: string): boolean =>\n dir === \"/\" || root === dir || root.startsWith(`${dir}/`);\n const target = roots.some(covers) ? file : dir;\n return [bind, target, target];\n}\n","// Promoted from agent-builder in M75 (plan m75-sandbox-kernel-no-framework, D1). Renamed from\n// `BwrapSandbox` to `LinuxSandbox`: bwrap is the IMPLEMENTATION, Linux is the contract — swapping the\n// mechanism (landlock, for example) should not change the name the consumer imports.\n\nimport { mkdtempSync, writeFileSync } from \"node:fs\";\nimport { tmpdir } from \"node:os\";\nimport { dirname, join } from \"node:path\";\n\nimport { redactSecrets } from \"../internal/security/redact.js\";\nimport type { BwrapDetection, SandboxMode } from \"./bwrap.js\";\nimport { buildBwrapArgv, detectBwrapMemoized } from \"./bwrap.js\";\nimport { denyReadFlags, refuseUnhonourableDenyRead } from \"./deny-read.js\";\nimport { LocalSandbox } from \"./local-sandbox.js\";\nimport { buildSeccompFilter } from \"./seccomp.js\";\nimport {\n nonX64SeccompWarning,\n rememberSeccompFile,\n removeDirOnExit,\n restrictedSeccompProgram,\n wrapWithSeccompPath,\n wrapWithSeccompProgram,\n} from \"./seccomp-delivery.js\";\nimport { shellEscapePosix } from \"./shell-escape.js\";\nimport type { SandboxBackend, SandboxConfig, SandboxNetworkPolicy } from \"./types.js\";\n\n/*\n * M53 — kernel-enforced sandbox backend, injected into `createShellTool({ sandbox })`.\n *\n * `LinuxSandbox extends LocalSandbox` and only REWRITES the command: `<bwrap-bin> <policy flags> --\n * /bin/sh -c '<original>'`. Everything else (spawn, output caps, timeout, ExecuteResult shape, file\n * ops) is inherited — the SDK backend stays the single execution engine. Mirrors Codex's\n * `SandboxManager::transform` (argv prefixing before spawn, never in-process).\n */\n\n/**\n * M57 — the single source of truth for the sandbox command wrap. Turns `command` into\n * `<bin> <bwrap flags> [--seccomp 3] -- /bin/sh -c '<command>' [3< <bpf>]`, or `null` when the policy\n * skips the sandbox (`danger-full-access`). Extracted from `LinuxSandbox.wrapCommand` so the interactive\n * PTY backend (M57) can reuse the EXACT wrap the one-shot `run_shell` already uses (DRY) — faithful to\n * Codex, where the sandbox transforms the argv before the PTY spawns it (`sandboxing/src/manager.rs:321`).\n */\nexport function wrapCommandForSandbox(\n mode: SandboxMode,\n opts: {\n cwd: string;\n network?: boolean;\n env?: Record<string, string>;\n bin?: string;\n /**\n * @deprecated Pass `seccompProgram`: a confined command may replace a file before a later one\n * loads it (B-600). A path `seccompPathForArch` or `restrictedSeccompPath` returned is piped\n * from the bytes this process wrote; any other path is read from the file, bound read-only (see\n * `wrapWithSeccompPath` for what that leaves open). Ignored when `seccompProgram` is given.\n */\n seccompPath?: string;\n /**\n * The cBPF seccomp program, piped to bwrap's fd 3 from memory so no file holds it. Must be a\n * positive multiple of 8 bytes (a `TypeError` otherwise). Wins over `seccompPath`.\n */\n seccompProgram?: Uint8Array;\n /** See `BwrapArgvOptions.denyReadPaths`. */\n denyReadPaths?: readonly string[];\n },\n command: string,\n): string | null {\n const argv = buildBwrapArgv(mode, opts);\n if (argv === null) return null; // danger-full-access: bwrap skipped\n const bin = opts.bin ?? \"bwrap\";\n if (opts.seccompProgram !== undefined) {\n return wrapWithSeccompProgram([bin, ...argv.slice(0, -1)], command, opts.seccompProgram);\n }\n if (opts.seccompPath === undefined) {\n return `${[bin, ...argv].map(shellEscapePosix).join(\" \")} /bin/sh -c ${shellEscapePosix(command)}`;\n }\n return wrapWithSeccompPath([bin, ...argv], { mode, cwd: opts.cwd }, command, opts.seccompPath);\n}\n\n/**\n * Env allowlist re-injected inside the sandbox after `--clearenv`. Codex env_clear model: the child\n * gets exactly what it needs to run a shell, never the parent's full env (which may hold oddly-named\n * secrets the SDK name-pattern scrub misses). `CODEX_SANDBOX_NETWORK_DISABLED` is added by the argv\n * builder when network is unshared.\n */\nconst ENV_ALLOWLIST = [\n \"PATH\",\n \"HOME\",\n \"LANG\",\n \"LC_ALL\",\n \"LC_CTYPE\",\n \"TERM\",\n \"USER\",\n \"TMPDIR\",\n \"SHELL\",\n];\n\n/**\n * Build the environment a confined command runs with after `--clearenv`: `PATH`, `HOME`, `LANG`,\n * `LC_ALL`, `LC_CTYPE`, `TERM`, `USER`, `TMPDIR` and `SHELL`, copied from `source` (default\n * `process.env`) and omitted where unset.\n *\n * The allowlist shape is the point, and it is what separates this from the other env control in the\n * package. `SandboxConfig.env: \"inherit-scrubbed\"` is a denylist: it drops variables whose NAME looks\n * secret-ish, so an oddly named secret survives. Here the child gets these nine names and nothing\n * else, and a secret's name stops mattering.\n *\n * Call it when you compose the wrap yourself and need an `env` for `wrapCommandForSandbox`;\n * {@link LinuxSandbox} already applies it when its `env` option is omitted. Passing a different\n * `source` changes the VALUES, never the set of names — to give a confined command an extra variable,\n * extend the returned object, which is a fresh one on every call.\n */\nexport function allowlistedEnv(source: NodeJS.ProcessEnv = process.env): Record<string, string> {\n const out: Record<string, string> = {};\n for (const k of ENV_ALLOWLIST) {\n const v = source[k];\n if (v !== undefined) out[k] = v;\n }\n return out;\n}\n/**\n * Kernel-confined backend for Linux hosts: a `LocalSandbox` whose commands are rewritten as\n * `bwrap <policy flags> -- /bin/sh -c '<command>'` before they are spawned. Spawning, output caps,\n * timeouts and the `ExecuteResult` shape are all inherited, so confinement is a change to the argv\n * and never an in-process one.\n *\n * Prefer `createSandboxBackend` over constructing this directly. The class assumes bubblewrap is\n * present and never probes for it, so on a host without it every command comes back failed rather\n * than confined; the factory probes first and degrades to a plain `LocalSandbox` with a warning.\n *\n * What the confinement actually covers: the filesystem is bound read-only in full, and\n * `mode: \"workspace-write\"` adds the workspace root plus `/tmp` as the only writable paths, while\n * `\"read-only\"` adds none. The network is unshared unless `network: true`. The environment is cleared\n * and repopulated from {@link allowlistedEnv} unless an explicit `env` is passed. The seccomp syscall\n * filter is a second stage with two conditions on it — x86_64 only, and only when the network is\n * restricted — so `network: true` gives you bwrap's filesystem confinement and no syscall filter.\n * `mode: \"danger-full-access\"` skips the wrap entirely and this class behaves as plain\n * `LocalSandbox`.\n *\n * `uploadFile` is overridden so that writes go through the confined `execute` (base64 over stdin,\n * keeping arbitrary content out of the shell command line). A write the policy forbids therefore\n * fails, throwing a plain `Error` naming the target path and the stderr, instead of quietly landing\n * on the host as the inherited implementation would.\n */\nexport class LinuxSandbox extends LocalSandbox {\n private readonly mode: SandboxMode;\n private readonly network: boolean;\n private readonly cwd: string;\n private readonly bin: string;\n private readonly env: Record<string, string>;\n /** B-600 — the cBPF seccomp program, piped to `bwrap --seccomp 3` from memory (never a file a\n * confined command could replace). `undefined` when the network is unrestricted or the arch is not\n * x86_64 (honest fallback). */\n private readonly seccompProgram: Uint8Array | undefined;\n private readonly denyReadPaths: readonly string[] | undefined;\n /**\n * `\"none\"` exactly when the wrap passes `--unshare-net` (see `buildBwrapArgv`): a confined mode and\n * `network` not set. With `network: true`, or under `danger-full-access` where nothing is wrapped,\n * the command reaches whatever the host does.\n */\n override readonly networkPolicy: SandboxNetworkPolicy;\n\n /** `denyReadPaths`: see `BwrapArgvOptions`; a list that cannot be honoured throws `TypeError` here. */\n constructor(\n config: SandboxConfig,\n opts: {\n mode: SandboxMode;\n network?: boolean;\n bin?: string;\n env?: Record<string, string>;\n denyReadPaths?: readonly string[];\n },\n ) {\n super(config);\n this.mode = opts.mode;\n this.network = opts.network ?? false;\n this.networkPolicy =\n this.network || this.mode === \"danger-full-access\"\n ? { mode: \"unrestricted\" }\n : { mode: \"none\" };\n this.cwd = config.workDir ?? process.cwd();\n // MEDIUM-1: run the VALIDATED absolute binary from detection (anti-hijack), never bare `bwrap`\n // which the outer shell would re-resolve via $PATH at spawn time (TOCTOU / hijack window).\n this.bin = opts.bin ?? \"bwrap\";\n this.env = opts.env ?? allowlistedEnv();\n this.seccompProgram = seccompProgramForNetwork(this.network);\n this.denyReadPaths = opts.denyReadPaths;\n denyReadFlags(this.denyReadPaths, { mode: this.mode, cwd: this.cwd }); // fail fast, not per command\n }\n\n /** Extracted for test visibility — delegates to the pure `wrapCommandForSandbox` (M57, single wrap SoT). */\n wrapCommand(command: string): string | null {\n return wrapCommandForSandbox(\n this.mode,\n {\n cwd: this.cwd,\n network: this.network,\n env: this.env,\n bin: this.bin,\n seccompProgram: this.seccompProgram,\n denyReadPaths: this.denyReadPaths,\n },\n command,\n );\n }\n\n /**\n * M75 review (architecture, HIGH) — without this override the class LIED.\n *\n * `LinuxSandbox` documents itself as a \"kernel-enforced sandbox backend\", but it overrode only\n * `execute`. `uploadFile` stayed the one inherited from `LocalSandbox`, which writes straight to\n * the host via `fs/promises` and accepts an ABSOLUTE path — no bwrap, no seccomp, no path\n * restriction. And `SandboxBackend.writeFile` delegates to it. The result was an incoherent class:\n * reading, searching and listing went through the confinement; writing did not.\n *\n * Routing through the wrapped `execute` fixes it at the root: writes come to live under the SAME\n * policy as everything else — if bwrap denies the path, the write fails, as it should. The content\n * goes over stdin (not argv) because argv has a size limit and file content does not.\n */\n override async uploadFile(path: string, content: string | Buffer): Promise<void> {\n if (this.mode === \"danger-full-access\") return super.uploadFile(path, content);\n\n const target = path.startsWith(\"/\") ? path : `${this.cwd}/${path}`;\n const b64 = Buffer.from(content).toString(\"base64\");\n // base64 on a single line: avoids any shell quoting over arbitrary content, which is exactly\n // where a \"confined\" write would turn into command injection.\n const r = await this.execute(\n `mkdir -p ${shellEscapePosix(dirname(target))} && printf %s ${shellEscapePosix(b64)} | base64 -d > ${shellEscapePosix(target)}`,\n );\n if (r.exitCode !== 0) {\n throw new Error(\n `uploadFile blocked or failed under confinement (${target}): ${r.stderr.trim() || `exit ${r.exitCode}`}`,\n );\n }\n }\n\n override execute(command: string, opts?: { timeoutMs?: number }) {\n const wrapped = this.wrapCommand(command);\n if (wrapped === null) return super.execute(command, opts); // danger-full-access: plain local\n return super.execute(wrapped, opts);\n }\n}\n\nlet warnedNonX64 = false;\n\n/**\n * M63 — the restricted-network seccomp program is DETERMINISTIC, so write it ONCE per process and\n * reuse the path across every LinuxSandbox (no per-instance temp accumulation).\n *\n * ARCH GUARD (review HIGH): `buildSeccompFilter` emits an x86_64 program whose arch guard KILLs every\n * syscall whose `seccomp_data.arch != AUDIT_ARCH_X86_64`. On a non-x86_64 host that would brick EVERY\n * sandboxed command (the first execve is killed) — and silently, because generation succeeds and bwrap\n * accepts it. So we REFUSE to install on non-x64 and WARN through the honest-downgrade channel (bwrap\n * FS/network confinement still applies), exactly like the bwrap-missing fallback. `arch` is injectable\n * for tests. Cleaned on exit AND on SIGINT/SIGTERM (TUI Ctrl+C would otherwise leak the temp dir).\n *\n * @deprecated Writes the program to a temp file a confined command may be able to replace (B-600).\n * Use `wrapCommandForSandbox`'s `seccompProgram`, which keeps the program in memory.\n */\nexport function seccompPathForArch(arch: string, warn: (m: string) => void): string | undefined {\n if (arch !== \"x64\") {\n if (!warnedNonX64) {\n warnedNonX64 = true;\n warn(nonX64SeccompWarning(arch));\n }\n return undefined;\n }\n try {\n const dir = mkdtempSync(join(tmpdir(), \"ab-seccomp-\"));\n const path = join(dir, \"filter.bpf\");\n const program = buildSeccompFilter({ networkRestricted: true });\n writeFileSync(path, program);\n rememberSeccompFile(path, program); // the wraps pipe these bytes, never the file's (B-600)\n removeDirOnExit(dir);\n return path;\n } catch (err) {\n warn(\n `[sandbox] seccomp filter unavailable (${err instanceof Error ? err.message : String(err)}) — ` +\n \"running without syscall filter (bwrap FS/network confinement still applies).\",\n );\n return undefined;\n }\n}\n\nlet seccompFilterPath: string | undefined | null; // undefined = not tried; null = resolved absent\n/**\n * M57 — the memoized x64-gated seccomp program, written once per process to a temp file.\n *\n * @deprecated The SDK's own wraps no longer read this file (B-600): a file under `/tmp` is one a\n * `workspace-write` command can replace. Use `wrapCommandForSandbox`'s `seccompProgram`.\n */\nexport function restrictedSeccompPath(): string | undefined {\n if (seccompFilterPath !== undefined) return seccompFilterPath ?? undefined;\n const path = seccompPathForArch(process.arch, (m) => console.warn(redactSecrets(m)));\n seccompFilterPath = path ?? null;\n return path;\n}\n\nlet warnedUnavailable = false;\n\n/**\n * Test seam: reset the WARN-once latch.\n *\n * Named for what it is. It was `resetSandboxWarnLatch`, plain camelCase, re-exported from the public\n * `@theokit/sdk/sandbox` barrel — indistinguishable from ordinary API, while 22 sibling test seams in\n * this package carry an unmistakable `__…ForTests` marker and stay out of their barrels.\n *\n * Deliberately NOT tagged internal-visibility: the barrel still re-exports it under the old name as a\n * deprecated alias until the next major, so the symbol has to survive `stripInternal` into the\n * emitted declarations. Tagging it removed it from the `.d.ts` and the declaration rollup failed —\n * `tsc --noEmit` never sees that.\n */\nexport function __resetSandboxWarnLatchForTests(): void {\n warnedUnavailable = false;\n}\n\n/** Durable sandbox posture for the UI — the honest answer to \"am I kernel-enforced right now?\". */\nexport interface SandboxPosture {\n mode: SandboxMode;\n enforced: boolean;\n detail: string;\n}\n\n/**\n * MEDIUM-2: compute the posture so a surface (TUI footer) can show enforcement DURABLY instead of a\n * one-shot warn. `danger-full-access` is honestly reported as unenforced; an unavailable bwrap reports\n * the downgrade reason so the user never believes they are confined when they are not.\n */\nexport function resolveSandboxPosture(opts: {\n mode: SandboxMode;\n detect?: () => BwrapDetection;\n}): SandboxPosture {\n if (opts.mode === \"danger-full-access\") {\n return { mode: opts.mode, enforced: false, detail: \"no confinement (danger-full-access)\" };\n }\n const detection = (opts.detect ?? detectBwrapMemoized)();\n if (!detection.ok) {\n return { mode: opts.mode, enforced: false, detail: `tool-gating only — ${detection.reason}` };\n }\n return { mode: opts.mode, enforced: true, detail: \"kernel (bwrap)\" };\n}\n\n/**\n * Options for `createSandboxBackend`, which probes for bubblewrap and returns a {@link LinuxSandbox}\n * when confinement is genuinely available or a `LocalSandbox` when it is not — warning once when the\n * absence is a failure, and silently when `mode` is `\"danger-full-access\"`, since that is an explicit\n * opt-out rather than a degradation.\n *\n * The declared return type is `SandboxBackend` either way, so it does not tell you which one you got.\n * Call `resolveSandboxPosture({ mode })` for that, and surface it durably — the warning fires once\n * per process and a user who missed it has no way to tell they are unconfined.\n *\n * `workDir` and `timeoutMs` are forwarded into the backend's `SandboxConfig`; `maxOutputBytes` and\n * the env policy are not, and keep their defaults. `network` only reaches the confined path, being\n * meaningless on a fallback where the network was never restricted. `detect` and `warn` exist so\n * tests can drive both branches without a real bubblewrap.\n */\nexport interface CreateSandboxBackendOptions {\n mode: SandboxMode;\n workDir?: string;\n network?: boolean;\n timeoutMs?: number;\n /** Paths the shell cannot read. Never degrades to unconfined: throws `TypeError` or `SandboxNotAvailableError`. */\n denyReadPaths?: readonly string[];\n /** Injectable for tests; defaults to the real 3-probe detection. */\n detect?: () => BwrapDetection;\n /** Injectable for tests; defaults to console.warn. */\n warn?: (message: string) => void;\n}\n\n/**\n * Honest factory: bwrap available + mode wants confinement → `LinuxSandbox` (kernel enforcement,\n * running the VALIDATED absolute bin); `danger-full-access` → plain `LocalSandbox` silently (explicit\n * opt-out, `bwrap.rs:245-252`); bwrap unavailable → WARN once + `LocalSandbox` (the declarative M23\n * gating remains the guard). NEVER pretends to sandbox — the fallback is loud, mirroring Codex's\n * MISSING_BWRAP_WARNING. The durable posture lives in `resolveSandboxPosture` for the UI.\n */\nexport function createSandboxBackend(opts: CreateSandboxBackendOptions): SandboxBackend {\n const config: SandboxConfig = { workDir: opts.workDir, timeoutMs: opts.timeoutMs };\n refuseUnhonourableDenyRead(opts.denyReadPaths, opts.mode, opts.detect ?? detectBwrapMemoized);\n if (opts.mode === \"danger-full-access\") return new LocalSandbox(config);\n\n const detection = (opts.detect ?? detectBwrapMemoized)();\n if (!detection.ok) {\n if (!warnedUnavailable) {\n warnedUnavailable = true;\n const warn = opts.warn ?? ((m: string) => console.warn(redactSecrets(m)));\n warn(\n `[sandbox] OS-level enforcement unavailable (${detection.reason}) — ` +\n `falling back to tool-level gating only (sandbox_mode=${opts.mode}).`,\n );\n }\n return new LocalSandbox(config);\n }\n return new LinuxSandbox(config, { ...opts, bin: detection.bin }); // the class reads mode, network, denyReadPaths\n}\n\n/**\n * M75 T3.2 — warning latch for the INTERACTIVE path.\n *\n * Kept separate from `createSandboxBackend`'s latch on purpose: they are two distinct decisions\n * taken at distinct moments, and a user who only ever runs an interactive shell needs to see the\n * warning even if the non-interactive path already emitted it — otherwise the session where they\n * actually type commands would be the one without the alert.\n */\nlet interactiveWarned = false;\n\n/**\n * Reset for tests — the latch is module state and tests need isolation.\n *\n * See `__resetSandboxWarnLatchForTests` for why the name changed, and for why neither carries an\n * internal-visibility tag while the deprecated public alias exists.\n */\nexport function __resetInteractiveWarnLatchForTests(): void {\n interactiveWarned = false;\n}\n\n/**\n * The rule \"seccomp ONLY with restricted network\" — in ONE place.\n *\n * Codex installs the filter only when the network is closed (`landlock.rs:96-117`), and that is not\n * a detail: the cBPF program **denies the network syscalls** (`NETWORK_DENIED`). Applying it with\n * the network open produces the worst possible combination — bwrap **allows** the network (no\n * `--unshare-net`) and seccomp **denies** it with EPERM. The user asked for network, got the bind,\n * and the calls die.\n *\n * It existed duplicated: the constructor decided conditionally, `interactiveWrapCommand` installed\n * unconditionally. They had already diverged in the first version (M75 architecture review, proven\n * at runtime: `network:true` gave `--seccomp` interactively and not one-shot). Two copies of a\n * security rule is not duplicated form — it is duplicated KNOWLEDGE, and it had already diverged.\n */\nfunction seccompProgramForNetwork(networkOpen: boolean): Uint8Array | undefined {\n return networkOpen ? undefined : restrictedSeccompProgram((m) => console.warn(redactSecrets(m)));\n}\n\n/**\n * Options for `interactiveWrapCommand`, the PTY counterpart of `createSandboxBackend`.\n *\n * They differ in what they hand back, and that is how you choose. A PTY owns its own spawn and\n * accepts no backend object, so this path returns a `(command, cwd) => string | null` transform: the\n * wrapped command line, or `null` meaning run it as-is. Use it when something else does the spawning;\n * use `createSandboxBackend` when you want an object that executes.\n *\n * Detection is consulted on every wrap instead of being frozen at construction, because an\n * interactive session outlives the probe — a bubblewrap binary that disappears mid-session stops\n * being asserted as present.\n *\n * `network` defaults to `false`, matching the non-interactive path, and carries the same consequence:\n * the seccomp filter is installed only when the network is restricted. The warn-once latch is\n * deliberately separate from the one `createSandboxBackend` keeps, so a user who only ever opens an\n * interactive shell still sees the \"runs WITHOUT kernel confinement\" warning in the session where\n * they type commands.\n */\nexport interface InteractiveWrapOptions {\n mode: SandboxMode;\n /** `true` keeps the network. Default `false`, same as non-interactive `run_shell`. */\n network?: boolean;\n /** Paths the command cannot read. Throws on the wrap, never runs unconfined (as `CreateSandboxBackendOptions`). */\n denyReadPaths?: readonly string[];\n /** Injectable for tests; defaults to the real memoized detection. */\n detect?: () => BwrapDetection;\n /** Injectable for tests; defaults to `console.warn` with redaction. */\n warn?: (message: string) => void;\n}\n\n/**\n * The decision to confine or degrade, separated from the wrap itself.\n *\n * Extracted because they are two responsibilities and the SDK's complexity gate separated them for\n * us: DECIDING (is confinement available? did the user opt out?) and APPLYING (assembling the argv).\n * Keeping them together pushed the closure past 10 cognitive complexity — and the linter was right:\n * the deciding part is the one with security consequences and deserves to be read on its own.\n *\n * Returns the validated binary when confinement exists, or `null` when it does not — warning ONCE,\n * and only when the absence is a failure (not when it is an opt-out).\n */\nfunction decideConfinement(opts: InteractiveWrapOptions): string | null {\n refuseUnhonourableDenyRead(opts.denyReadPaths, opts.mode, opts.detect ?? detectBwrapMemoized);\n if (opts.mode === \"danger-full-access\") return null;\n\n const detection = (opts.detect ?? detectBwrapMemoized)();\n if (detection.ok) return detection.bin;\n\n if (!interactiveWarned) {\n interactiveWarned = true;\n const warn = opts.warn ?? ((m: string) => console.warn(redactSecrets(m)));\n warn(\n `[sandbox] OS-level enforcement unavailable (${detection.reason}) — interactive session ` +\n `runs WITHOUT kernel confinement (sandbox_mode=${opts.mode}).`,\n );\n }\n return null;\n}\n\n/**\n * The composition the interactive path needs — the counterpart of `createSandboxBackend`.\n *\n * `createSandboxBackend` solves this for the non-interactive path by returning a ready BACKEND. The\n * PTY accepts no backend: it owns the spawn and only allows transforming the command. This function\n * delivers the SAME decision in the shape the PTY accepts — `(command, cwd) => string | null` —\n * ready for `new PtyInteractiveBackend({ wrapCommand: interactiveWrapCommand({ mode }) })`.\n *\n * Detection is consulted on **every wrap**, not frozen at construction: an interactive session lives\n * for hours, and a stale positive detection would keep asserting confinement after the binary\n * disappeared (the `existsSync` revalidation lives inside `detectBwrapMemoized`).\n *\n * The two routes returning `null` are semantically different and the code does not merge them:\n * `danger-full-access` is an explicit opt-out and does NOT warn; bwrap being unavailable is a\n * failure and warns once.\n */\nexport function interactiveWrapCommand(\n opts: InteractiveWrapOptions,\n): (command: string, cwd: string) => string | null {\n return (command: string, cwd: string): string | null => {\n const bin = decideConfinement(opts);\n if (bin === null) return null;\n\n return wrapCommandForSandbox(\n opts.mode,\n {\n cwd,\n network: opts.network ?? false,\n env: allowlistedEnv(),\n bin,\n seccompProgram: seccompProgramForNetwork(opts.network ?? false),\n denyReadPaths: opts.denyReadPaths,\n },\n command,\n );\n };\n}\n","/**\n * M6-3 — portable repo provisioner for the eval harness.\n *\n * Clones a repository and checks out a ref into an isolated working dir, issuing\n * every git command through {@link SandboxBackend.execute} (ADR D2 — same code\n * runs on Local/Docker/E2B; never a direct `child_process` import). Promotes\n * theocode's `prepareRepo` (`swebench-provision.ts:37`) onto the SDK's sandbox\n * abstraction.\n *\n * reference: knowledge-base/references/theocode-eval/lib/swebench-provision.ts:37\n * (clone+checkout), :13 (ProvisionError with instanceId).\n *\n * @public\n */\n\nimport { TheokitAgentError } from \"../errors.js\";\nimport { LocalSandbox } from \"./local-sandbox.js\";\nimport { shellEscapePosix } from \"./shell-escape.js\";\nimport type { SandboxBackend } from \"./types.js\";\n\n/**\n * Raised when cloning or checking out a repo fails. Carries the `instanceId`\n * so a batch run can attribute the failure to the offending dataset row.\n */\nexport class RepoProvisionError extends TheokitAgentError {\n override readonly name = \"RepoProvisionError\";\n\n constructor(\n readonly instanceId: string,\n message: string,\n options: { cause?: unknown } = {},\n ) {\n super(`[${instanceId}] ${message}`, {\n code: \"repo_provision_failed\",\n isRetryable: false,\n ...(options.cause !== undefined ? { cause: options.cause } : {}),\n });\n }\n}\n\n/** Options for {@link provisionRepo}. */\nexport interface ProvisionRepoOptions {\n /**\n * Clonable repo URL or local path. SECURITY: when this comes from an\n * untrusted dataset, the value is passed to `git clone` after a `--`\n * end-of-options terminator (no flag injection) and with the `ext::`\n * transport disabled (no arbitrary-command transport).\n */\n readonly repoUrl: string;\n /** Branch, tag, or commit SHA to check out. Rejected if it begins with `-`. */\n readonly ref: string;\n /**\n * Unique id for this row — names the target dir and any error. Validated to\n * `[A-Za-z0-9._-]` (no path traversal) since it becomes a directory name.\n */\n readonly instanceId: string;\n}\n\n/**\n * Reject ids that would escape the workdir or be parsed as a git flag. Must\n * start with an alphanumeric (blocks `.`, `..`, `-foo`, leading-dot names) and\n * thereafter allow only `[A-Za-z0-9._-]`.\n */\nconst SAFE_INSTANCE_ID = /^[A-Za-z0-9][A-Za-z0-9._-]*$/;\n\n/**\n * Clone `repoUrl` into `<sandbox workdir>/<instanceId>` and check out `ref`.\n * Returns the absolute `repoDir` (resolved via `git rev-parse --show-toplevel`,\n * which is portable across backends). Throws {@link RepoProvisionError} naming\n * the `instanceId` when clone or checkout exits non-zero.\n *\n * The `sandbox` is optional (V3-5): when omitted, a default {@link LocalSandbox}\n * is used (clones into the process cwd's `<instanceId>`) — pass an explicit\n * sandbox (e.g. `LocalSandbox({ workDir })` / Docker / E2B) to control the workdir.\n */\nexport function provisionRepo(opts: ProvisionRepoOptions): Promise<{ repoDir: string }>;\nexport function provisionRepo(\n sandbox: SandboxBackend,\n opts: ProvisionRepoOptions,\n): Promise<{ repoDir: string }>;\nexport async function provisionRepo(\n sandboxOrOpts: SandboxBackend | ProvisionRepoOptions,\n maybeOpts?: ProvisionRepoOptions,\n): Promise<{ repoDir: string }> {\n const sandbox = maybeOpts !== undefined ? (sandboxOrOpts as SandboxBackend) : new LocalSandbox();\n const opts = maybeOpts ?? (sandboxOrOpts as ProvisionRepoOptions);\n const { repoUrl, ref, instanceId } = opts;\n\n // Validate untrusted-derivable inputs before they reach git/the shell.\n if (!SAFE_INSTANCE_ID.test(instanceId)) {\n throw new RepoProvisionError(\n instanceId,\n \"invalid instanceId: must match [A-Za-z0-9._-] (no path traversal)\",\n );\n }\n if (ref.startsWith(\"-\")) {\n throw new RepoProvisionError(instanceId, `invalid ref: must not begin with '-' (got ${ref})`);\n }\n\n // `--` terminates options (no `--upload-pack=` flag injection); `protocol.ext.allow=never`\n // blocks the `ext::` arbitrary-command transport. `file`/`https` stay allowed.\n const clone = await sandbox.execute(\n `git -c protocol.ext.allow=never clone --quiet -- ${shellEscapePosix(repoUrl)} ${shellEscapePosix(instanceId)}`,\n );\n if (clone.exitCode !== 0) {\n throw new RepoProvisionError(instanceId, `clone failed: ${clone.stderr.trim()}`);\n }\n\n const top = await sandbox.execute(\n `git -C ${shellEscapePosix(instanceId)} rev-parse --show-toplevel`,\n );\n if (top.exitCode !== 0) {\n throw new RepoProvisionError(instanceId, `resolve repoDir failed: ${top.stderr.trim()}`);\n }\n const repoDir = top.stdout.trim();\n\n // `ref` is validated above not to begin with `-`, so it cannot be parsed as a flag.\n const checkout = await sandbox.execute(\n `git -C ${shellEscapePosix(repoDir)} checkout --quiet ${shellEscapePosix(ref)}`,\n );\n if (checkout.exitCode !== 0) {\n throw new RepoProvisionError(instanceId, `checkout ${ref} failed: ${checkout.stderr.trim()}`);\n }\n\n return { repoDir };\n}\n"]}
1
+ {"version":3,"sources":["../../src/sandbox/deny-read.ts","../../src/sandbox/bwrap.ts","../../src/sandbox/docker-sandbox.ts","../../src/sandbox/seccomp.ts","../../src/sandbox/seccomp-delivery.ts","../../src/sandbox/linux-sandbox.ts","../../src/sandbox/provision.ts"],"names":["path","resolve","resolveHost","dirname","mkdtempSync","join","tmpdir"],"mappings":"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","file":"index.js","sourcesContent":["import { realpathSync, statSync } from \"node:fs\";\nimport path from \"node:path\";\nimport type { BwrapDetection, SandboxMode } from \"./types.js\";\nimport { SandboxNotAvailableError } from \"./types.js\";\n\n/** Paths the confined shell must keep: masking one would remove the command's own working ground. */\nconst KEPT_ROOTS_ALWAYS = [\"/tmp\"] as const;\n\n/** True when `inner` is `outer` or lies under it. */\nfunction isSameOrInside(outer: string, inner: string): boolean {\n const rel = path.relative(outer, inner);\n return rel === \"\" || (!rel.startsWith(\"..\") && !path.isAbsolute(rel));\n}\n\nfunction resolveEntry(entry: string): string {\n if (!path.isAbsolute(entry)) {\n throw new TypeError(`denyReadPaths: \"${entry}\" is not an absolute path`);\n }\n try {\n return realpathSync(entry);\n } catch (cause) {\n throw new TypeError(`denyReadPaths: \"${entry}\" cannot be resolved: ${String(cause)}`);\n }\n}\n\nfunction keptRoots(cwd: string): string[] {\n let real = cwd;\n try {\n real = realpathSync(cwd);\n } catch {\n // cwd does not exist yet: the resolved spelling is the only one there is\n }\n return [...new Set([cwd, real, ...KEPT_ROOTS_ALWAYS])];\n}\n\n/**\n * The bwrap flags that make each path in `paths` unreadable inside the sandbox: `--tmpfs` for a\n * directory, `--ro-bind /dev/null` for a file. Callers place them after the writable binds so the\n * mask wins over a path inside the workspace or `/tmp`.\n *\n * Every entry is resolved through symlinks first, so reading through a link is denied too, and\n * duplicates collapse in list order. A masked file is still listed in its directory; only reading it\n * fails.\n *\n * Throws `TypeError` (never skips) for a relative or missing entry, an entry that equals or contains\n * the working directory, `/tmp` or `/`, and any non-empty list under `danger-full-access`, where no\n * mask can be applied.\n */\nexport function denyReadFlags(\n paths: readonly string[] | undefined,\n policy: { mode: SandboxMode; cwd: string },\n): string[] {\n if (paths === undefined || paths.length === 0) return [];\n if (policy.mode === \"danger-full-access\") {\n throw new TypeError(\n \"denyReadPaths cannot be honoured under danger-full-access: no sandbox is applied\",\n );\n }\n const roots = keptRoots(policy.cwd);\n const resolved = new Set<string>();\n for (const entry of paths) {\n const target = resolveEntry(entry);\n const covered = roots.find((root) => isSameOrInside(target, root));\n if (covered !== undefined) {\n throw new TypeError(\n `denyReadPaths: \"${entry}\" would hide \"${covered}\", which the command needs`,\n );\n }\n resolved.add(target);\n }\n return [...resolved].flatMap((target) =>\n statSync(target).isDirectory() ? [\"--tmpfs\", target] : [\"--ro-bind\", \"/dev/null\", target],\n );\n}\n\n/**\n * Refuses a non-empty deny list that no confinement can honour, before a backend or a wrap exists:\n * `danger-full-access` applies no sandbox (`TypeError`), and an undetected bubblewrap would fall back\n * to an unconfined run, which is the leak the list exists to stop (`SandboxNotAvailableError`).\n */\nexport function refuseUnhonourableDenyRead(\n paths: readonly string[] | undefined,\n mode: SandboxMode,\n detect: () => BwrapDetection,\n): void {\n if (paths === undefined || paths.length === 0) return;\n if (mode === \"danger-full-access\") denyReadFlags(paths, { mode, cwd: \"/\" }); // throws TypeError\n const detection = detect();\n if (!detection.ok) {\n throw new SandboxNotAvailableError(\n `denyReadPaths needs kernel confinement and it is unavailable (${detection.reason}); refusing to run unconfined`,\n );\n }\n}\n","// Promoted out of the agent-builder in M75 (plan m75-sandbox-kernel-no-framework, D1): kernel\n// confinement is framework infrastructure, not the consumer's. Measured cost of the promotion: ZERO\n// dependencies — only node:child_process, node:fs and node:path. The cBPF filter is a pure-JS Buffer.\n\nimport { execFileSync } from \"node:child_process\";\nimport { existsSync } from \"node:fs\";\nimport path from \"node:path\";\n\nimport { denyReadFlags } from \"./deny-read.js\";\nimport type { BwrapDetection, SandboxMode } from \"./types.js\";\n\n/*\n * M53 — bubblewrap argv + honest detection.\n *\n * HONEST SCOPE: filesystem confinement + network isolation via bwrap, PLUS the second stage —\n * a cBPF seccomp syscall filter (`agents/sandbox/seccomp.ts`), wired in `agents/sandbox/backend.ts`\n * via `restrictedSeccompPath()`. Ported in M63; this block claimed the opposite until M67 and\n * UNDER-DECLARED the real security posture. The honest limit that remains: the filter is **x86_64**\n * (an architecture guard refuses to install it on any other arch, with a WARN, and bwrap's FS/network\n * confinement still applies) **and** it is only installed when the network is restricted\n * (`backend.ts:87`, faithful to `landlock.rs:96-117`): with the network on there is no syscall\n * filter, only bwrap's FS confinement. `danger-full-access` skips bwrap entirely, mirroring\n * `bwrap.rs:245-252`. Deltas versus Codex remain documented in docs/CODEX-PARITY.md.\n */\n\n/**\n * Codex's three canonical modes. Defined HERE because they are sandbox vocabulary, not consumer\n * configuration: `danger-full-access` means \"do not wrap\", and that is a decision belonging to the\n * confinement subsystem.\n */\nexport type { SandboxMode } from \"./types.js\";\n\n/**\n * The RW binds `workspace-write` installs (protocol.rs:1189-1214), plus the metadata protection that\n * must sit ON TOP of them — order matters (permissions.rs:22-31; bwrap.rs:571-597).\n */\nfunction pushWorkspaceBinds(argv: string[], cwd: string, hasGit: boolean, gitDir: string): void {\n for (const root of workspaceWriteRoots(cwd)) argv.push(\"--bind\", root, root);\n if (hasGit) argv.push(\"--ro-bind\", gitDir, gitDir);\n}\n\n/** The RW binds `workspace-write` installs (protocol.rs:1189-1214): the workspace itself, and /tmp. */\nfunction workspaceWriteRoots(cwd: string): readonly string[] {\n return [cwd, \"/tmp\"];\n}\n\n/**\n * U-6 — the roots a mode may write to, answerable WITHOUT spawning anything.\n *\n * `[]` means nothing is writable; `null` means unrestricted — which is not the same as `[\"/\"]`,\n * because unrestricted is the absence of a root rather than a root that happens to be `/`.\n *\n * The SDK already knew this: `buildBwrapArgv` binds these exact paths. It only knew it while\n * BUILDING an argv, and a consumer needs the answer earlier — tools are scoped at agent\n * construction, before any process exists, and a file-write tool has to be told its root then. With\n * nothing to ask, consumers keep a second encoding of this three-mode vocabulary and it drifts from\n * the argv builder with nothing to catch it. This reads from the same helper the builder uses, so\n * the two cannot disagree.\n */\nexport function writableRootsFor(mode: SandboxMode, cwd: string): readonly string[] | null {\n switch (mode) {\n case \"read-only\":\n return [];\n case \"workspace-write\":\n return workspaceWriteRoots(cwd);\n case \"danger-full-access\":\n return null;\n }\n}\n\n/**\n * Everything {@link buildBwrapArgv} needs besides the {@link SandboxMode}.\n *\n * Only `cwd` is required, and it is resolved to an absolute path before any bind\n * is emitted. The defaults are the restrictive ones in one direction and the\n * permissive one in the other: omitting `network` emits `--unshare-net` (no\n * network), while omitting `env` means the child INHERITS the parent\n * environment — bwrap only clears it when an allowlist is supplied.\n */\nexport interface BwrapArgvOptions {\n /** Workspace root — the single RW bind under `workspace-write` (protocol.rs:1189-1200). */\n cwd: string;\n /** `true` removes `--unshare-net` (policy `network_access`, default false). */\n network?: boolean;\n /** Injectable for tests; defaults to a real `existsSync` check on `<cwd>/.git`. */\n gitDirExists?: boolean;\n /**\n * When present, emit `--clearenv` and re-inject ONLY these vars (Codex env_clear model,\n * `exec_env.rs:25-31`). Closes the denylist gap: a secret in an oddly-named var never reaches the\n * sandboxed child. Omitted ⇒ inherit the parent env (backward-compatible; SDK scrub still applies).\n */\n env?: Record<string, string>;\n /**\n * Absolute paths the confined command must not read. Each is resolved through symlinks and masked\n * after the writable binds: a directory becomes empty, a file reads as permission denied. A masked\n * file still shows in the listing of its directory. Throws `TypeError` for a relative or missing\n * path, one that contains the workspace, `/tmp` or `/`, and any list under `danger-full-access`.\n */\n denyReadPaths?: readonly string[];\n}\n\n/**\n * Pure argv builder. Returns the bwrap flags ending in `--` (caller appends `/bin/sh -c <cmd>`),\n * or `null` when the policy skips the sandbox entirely (`danger-full-access`).\n */\nexport function buildBwrapArgv(mode: SandboxMode, opts: BwrapArgvOptions): string[] | null {\n const cwd = path.resolve(opts.cwd);\n const denyFlags = denyReadFlags(opts.denyReadPaths, { mode, cwd }); // throws before the null below\n if (mode === \"danger-full-access\") return null; // bwrap skipped entirely (bwrap.rs:245-252)\n\n const gitDir = path.join(cwd, \".git\");\n const hasGit = opts.gitDirExists ?? existsSync(gitDir);\n\n const argv: string[] = [\n // core, always (bwrap.rs:318-332; user+pid namespaces explicit so it works as root in containers)\n \"--new-session\",\n \"--die-with-parent\",\n \"--unshare-user\",\n \"--unshare-pid\",\n // full-read filesystem base (bwrap.rs:446-452)\n \"--ro-bind\",\n \"/\",\n \"/\",\n \"--dev\",\n \"/dev\",\n \"--proc\",\n \"/proc\",\n ];\n\n if (!opts.network) argv.push(\"--unshare-net\"); // network off by default (bwrap.rs:325-327)\n\n // env confinement — `--clearenv` MUST precede every `--setenv` or the clear wipes them\n // (exec_env.rs:25-31 clears then rebuilds). Only when an explicit allowlist is provided.\n if (opts.env) argv.push(\"--clearenv\");\n const setenv: Record<string, string> = {\n ...(opts.env ?? {}),\n // the flag signals the child that network is unshared (spawn.rs:20,79)\n ...(opts.network ? {} : { CODEX_SANDBOX_NETWORK_DISABLED: \"1\" }),\n };\n for (const [k, v] of Object.entries(setenv)) argv.push(\"--setenv\", k, v);\n\n if (mode === \"workspace-write\") pushWorkspaceBinds(argv, cwd, hasGit, gitDir);\n // read-only: zero writable roots (protocol.rs:1176) — nothing to add\n argv.push(...denyFlags); // after the writable binds so a mask inside the workspace or /tmp wins\n\n argv.push(\"--chdir\", cwd, \"--\");\n return argv;\n}\n\n/** Injectable probes — each mirrors one Codex availability check. */\nexport interface BwrapProbes {\n /** `which bwrap` outside the cwd (anti-hijack, sandboxing/src/bwrap.rs:168-191). */\n which: () => string | null;\n /** `bwrap --help` text — must advertise `--perms` (launcher.rs:108-124). */\n helpText: (bin: string) => string | null;\n /** Active user-namespace probe with timeout (sandboxing/src/bwrap.rs:74-136). */\n userns: (bin: string) => boolean;\n}\n\n/**\n * Result of {@link detectBwrap} / {@link detectBwrapMemoized}, discriminated on\n * `ok`: `{ ok: true, bin }` carries the absolute path of the validated `bwrap`,\n * `{ ok: false, reason }` a human-readable cause — \"bwrap not found in PATH\",\n * \"bwrap at <bin> lacks --perms support (too old)\",\n * \"user namespaces unavailable (container/kernel restriction)\",\n * \"bwrap probe failed: <err>\", or (memoized only)\n * \"bwrap disappeared from <bin> after detection\".\n *\n * `reason` is prose for a warning line. It is not a stable code — do not branch\n * on it.\n *\n * `ok: false` is an ordinary outcome rather than an error: bubblewrap is\n * Linux-only, so failing detection on macOS, on Windows, or inside a container\n * without user namespaces is expected. Detection NEVER throws, so wrapping it in\n * `try`/`catch` catches nothing; callers warn and fall back to an unconfined\n * `LocalSandbox`.\n */\nexport type { BwrapDetection } from \"./types.js\";\n\n/** Honest detection — fail-closed on every probe; NEVER throws (callers WARN + fall back). */\nexport function detectBwrap(probes: BwrapProbes = realProbes): BwrapDetection {\n try {\n const bin = probes.which();\n if (!bin) return { ok: false, reason: \"bwrap not found in PATH\" };\n const help = probes.helpText(bin);\n if (!help?.includes(\"--perms\")) {\n return { ok: false, reason: `bwrap at ${bin} lacks --perms support (too old)` };\n }\n if (!probes.userns(bin)) {\n return { ok: false, reason: \"user namespaces unavailable (container/kernel restriction)\" };\n }\n return { ok: true, bin };\n } catch (err) {\n return {\n ok: false,\n reason: `bwrap probe failed: ${err instanceof Error ? err.message : String(err)}`,\n };\n }\n}\n\n/**\n * How many times the REAL probe ran in this process.\n *\n * Instrumented here rather than in a wrapper, because this is where the cost is: every `which`\n * spawns a subprocess (`which bwrap`), and the full probe cost 22.2 ms. A gate counting INJECTED\n * probes does not see the real one — that was the M71 gate's first mistake, and a mutant exposed it.\n */\nlet realProbeRuns = 0;\n\n/** How many real probes ran. TEST seam — the performance gate counts this. */\nexport function realProbeCount(): number {\n return realProbeRuns;\n}\n\n/** Real probes used in production. */\nexport const realProbes: BwrapProbes = {\n which: () => {\n realProbeRuns++;\n try {\n const out = execFileSync(\"which\", [\"bwrap\"], { encoding: \"utf8\", timeout: 2_000 }).trim();\n // anti-hijack: never accept a bwrap that lives inside the workspace (bwrap.rs:168-191)\n if (!out || out.startsWith(process.cwd() + path.sep)) return null;\n return out;\n } catch {\n return null;\n }\n },\n helpText: (bin) => {\n try {\n // bwrap --help exits 0/1 depending on version; capture output either way\n return execFileSync(bin, [\"--help\"], { encoding: \"utf8\", timeout: 2_000 });\n } catch (err) {\n const e = err as { stdout?: string; stderr?: string };\n return [e.stdout, e.stderr].filter(Boolean).join(\"\\n\") || null;\n }\n },\n userns: (bin) => {\n try {\n // active probe, 500ms budget like Codex (sandboxing/src/bwrap.rs:74-136)\n execFileSync(bin, [\"--unshare-user\", \"--unshare-net\", \"--ro-bind\", \"/\", \"/\", \"/bin/true\"], {\n timeout: 500,\n stdio: \"ignore\",\n });\n return true;\n } catch {\n return false;\n }\n },\n};\n\n/**\n * The probe result, memoized for the lifetime of the PROCESS.\n *\n * Measured before M71: `detectBwrap()` costs **22.2 ms** and was not memoized — the second call\n * cost 19.4 ms. `buildChatAgent` on the headless path fired **two** (one from\n * `createSandboxBackend`, another from `resolveSandboxPosture`, which M70 added), totalling 46.4 ms\n * per construction — and construction happens per turn. Under `strace`, ~90% of the 182 syscalls of\n * an already-warm construction came from here: `which` sweeping the PATH, `/proc/filesystems`,\n * `/newroot`, and the `.so` files the two probe subprocesses load.\n *\n * ## Why there is no invalidation\n *\n * The milestone called for invalidating on `SessionStart`. That does not work:\n * `agents/lib/hooks/hooks.ts:28-30` documents — as a **measured** correction of an earlier\n * assumption — that the event fires **once per TURN**, not per session. Invalidating there would\n * re-probe every turn, exactly the behavior memoization exists to eliminate.\n *\n * A write-once cache is sufficient here: the expensive probe runs once per process,\n * only to print a UI warning.\n *\n * **The price, stated plainly — in BOTH directions.** The original m71-cost-per-turn#ADR-1 declared\n * only one of them; the M71 review (F-perf-9) showed the omitted one was precisely the one with a\n * security consequence:\n *\n * - **Stale negative** (`bwrap` installed AFTERWARDS): not detected until restart. The system fails\n * CLOSED — the posture reports `enforced: false` and M70's veto **refuses**. Cost: annoyance (the\n * message tells you to install the bwrap you just installed). Accepted.\n * - **Stale positive** (`bwrap` removed/renamed AFTERWARDS): the posture would keep asserting\n * `enforced: true / \"kernel (bwrap)\"` and the veto would **approve**, citing a confinement that no\n * longer exists. That is the literal reintroduction of the defect M70 fixed — *\"telling the\n * operator they are protected when they are not is worse than saying nothing\"*. Before M71 the\n * per-turn re-probe closed that window on the next turn; memoization would leave it open for the\n * whole process. **That is why the positive is revalidated** below, at 1 syscall — 3 orders of\n * magnitude below the 22.2 ms of the full probe, which is the cost memoization exists to remove.\n */\nlet memo: BwrapDetection | undefined;\n\n/**\n * `detectBwrap` with memoization — what production should call.\n *\n * Note that `detectBwrap` itself does **not** memoize, on purpose: it accepts injected probes, and\n * memoizing there would let a test with fake probes poison the process cache for everyone else.\n *\n * Revalidating the positive is NOT a re-probe: `detectBwrap` spends three probes (a `which`\n * subprocess + `--help` + a user namespace). Here we only confirm the validated binary is still in\n * place. If it vanished, the memo is downgraded to a negative with the reason stated — never\n * promoted to a positive, which would require the expensive probe back.\n */\nexport function detectBwrapMemoized(probes: BwrapProbes = realProbes): BwrapDetection {\n memo ??= detectBwrap(probes);\n if (memo.ok && !existsSync(memo.bin)) {\n memo = { ok: false, reason: `bwrap disappeared from ${memo.bin} after detection` };\n }\n return memo;\n}\n\n/**\n * Clears the `detectBwrapMemoized` memo.\n *\n * Kept PUBLIC, unlike the two warn-latch resets that moved to the `__…ForTests` convention, because\n * this one has a use outside a test that the others do not: a long-lived host that probed before\n * `bwrap` was installed is memoized on the wrong answer forever, and this is the only way to make it\n * re-probe. It is the companion to `detectBwrapMemoized` and is documented as such rather than as a\n * seam. Production inside this package never calls it (see m71-cost-per-turn#ADR-1).\n *\n * @public\n */\nexport function resetBwrapMemo(): void {\n memo = undefined;\n}\n","/**\n * DockerSandbox — runs each command in a throwaway container whose only writable path is the\n * workspace bind mount. The root filesystem is read-only, the network is off by default, all\n * capabilities are dropped and the process runs as the host user, so a shell command cannot write\n * outside `workDir` (it can still change files inside it).\n *\n * Without `workDir` a fresh temp directory is mounted. `exitCode` follows the protocol (0, 1, or 124\n * on timeout), not the command's own code.\n *\n * Needs a reachable Docker daemon and an image with a POSIX `sh`. A missing Docker surfaces as\n * `SandboxNotAvailableError` from `execute`/`uploadFile` instead of silently running on the host.\n *\n * @public\n */\n\nimport { spawn } from \"node:child_process\";\nimport { randomBytes } from \"node:crypto\";\nimport { mkdtempSync } from \"node:fs\";\nimport { tmpdir } from \"node:os\";\nimport { join, posix, resolve as resolveHost } from \"node:path\";\n\nimport {\n type ExecuteResult,\n SandboxBackend,\n type SandboxConfig,\n type SandboxNetworkPolicy,\n SandboxNotAvailableError,\n SandboxSecurityError,\n} from \"./types.js\";\n\n/** Where the host `workDir` appears inside the container. */\nconst CONTAINER_WORKDIR = \"/workspace\";\n\n/** Result of one `docker` invocation: captured output, exit code and whether it timed out. */\nexport interface DockerRunResult {\n stdout: string;\n stderr: string;\n code: number | null;\n timedOut: boolean;\n}\n\n/** Seam for tests: runs `docker <args>`, optionally feeding `input` to stdin. */\nexport type DockerRunner = (\n args: readonly string[],\n opts: { input?: string | Buffer; timeoutMs: number; maxOutputBytes: number },\n) => Promise<DockerRunResult>;\n\n/** Configuration for {@link DockerSandbox}. */\nexport interface DockerSandboxConfig extends SandboxConfig {\n /** Image to run. Must contain `sh`. Default `alpine:3`. */\n image?: string;\n /** Allow outbound network. Default `false` (`--network none`). */\n network?: boolean;\n /** Docker binary. Default `docker`. */\n dockerBin?: string;\n /** Replaces the real `docker` process (tests). */\n runner?: DockerRunner;\n /** `uid:gid` the container runs as. Default: the host user. */\n user?: string;\n}\n\nfunction defaultRunner(bin: string): DockerRunner {\n return (args, { input, timeoutMs, maxOutputBytes }) =>\n new Promise((resolve, reject) => {\n const child = spawn(bin, [...args], { stdio: [\"pipe\", \"pipe\", \"pipe\"] });\n let stdout = \"\";\n let stderr = \"\";\n let timedOut = false;\n const cap = (s: string, chunk: Buffer) =>\n s.length >= maxOutputBytes ? s : s + chunk.toString(\"utf-8\");\n child.stdout.on(\"data\", (c: Buffer) => {\n stdout = cap(stdout, c);\n });\n child.stderr.on(\"data\", (c: Buffer) => {\n stderr = cap(stderr, c);\n });\n const timer = setTimeout(() => {\n timedOut = true;\n child.kill(\"SIGKILL\");\n }, timeoutMs);\n child.on(\"error\", (e) => {\n clearTimeout(timer);\n reject(e);\n });\n child.on(\"close\", (code) => {\n clearTimeout(timer);\n resolve({ stdout, stderr, code, timedOut });\n });\n child.stdin.on(\"error\", () => {});\n child.stdin.end(input);\n });\n}\n\n/** Sandbox backend that runs each command in a throwaway Docker container. */\nexport class DockerSandbox extends SandboxBackend {\n override readonly networkPolicy: SandboxNetworkPolicy;\n private readonly image: string;\n private readonly network: boolean;\n private readonly runner: DockerRunner;\n private readonly hostDir: string;\n private readonly user: string | undefined;\n\n constructor(config: DockerSandboxConfig = {}) {\n // No workDir ⇒ a fresh private directory, never the host /tmp.\n super({\n ...config,\n workDir: config.workDir ?? mkdtempSync(join(tmpdir(), \"theokit-docker-ws-\")),\n });\n this.image = config.image ?? \"alpine:3\";\n this.network = config.network ?? false;\n this.networkPolicy = { mode: this.network ? \"unrestricted\" : \"none\" };\n this.runner = config.runner ?? defaultRunner(config.dockerBin ?? \"docker\");\n this.hostDir = resolveHost(this.config.workDir ?? \"/tmp\");\n this.user =\n config.user ??\n (typeof process.getuid === \"function\" && typeof process.getgid === \"function\"\n ? `${process.getuid()}:${process.getgid()}`\n : undefined);\n }\n\n /** The `docker run` argv for one command; exposed shape is covered by tests. */\n private runArgs(name: string, interactive: boolean, argv: readonly string[]): string[] {\n return [\n \"run\",\n \"--rm\",\n ...(interactive ? [\"-i\"] : []),\n \"--name\",\n name,\n \"--read-only\",\n \"--tmpfs\",\n \"/tmp\",\n \"--cap-drop\",\n \"ALL\",\n \"--security-opt\",\n \"no-new-privileges\",\n \"--pids-limit\",\n \"512\",\n \"--network\",\n this.network ? \"bridge\" : \"none\",\n ...(this.user ? [\"--user\", this.user] : []),\n \"-v\",\n `${this.hostDir}:${CONTAINER_WORKDIR}:rw`,\n \"-w\",\n CONTAINER_WORKDIR,\n \"-e\",\n \"HOME=/tmp\",\n this.image,\n ...argv,\n ];\n }\n\n private async run(\n interactive: boolean,\n argv: readonly string[],\n timeoutMs: number,\n input?: string | Buffer,\n ): Promise<DockerRunResult> {\n const name = `theokit-sbx-${randomBytes(6).toString(\"hex\")}`;\n const max = this.config.maxOutputBytes ?? 5 * 1024 * 1024;\n let r: DockerRunResult;\n try {\n r = await this.runner(this.runArgs(name, interactive, argv), {\n input,\n timeoutMs,\n maxOutputBytes: max,\n });\n } catch (e) {\n throw new SandboxNotAvailableError(\n `docker could not be started: ${e instanceof Error ? e.message : String(e)}`,\n );\n }\n if (r.timedOut) {\n // Killing the CLI does not stop the container; remove it explicitly.\n await this.runner([\"rm\", \"-f\", name], { timeoutMs: 10_000, maxOutputBytes: 4096 }).catch(\n () => undefined,\n );\n }\n return r;\n }\n\n async execute(command: string, opts?: { timeoutMs?: number }): Promise<ExecuteResult> {\n const timeoutMs = opts?.timeoutMs ?? this.config.timeoutMs ?? 30_000;\n const r = await this.run(false, [\"sh\", \"-c\", command], timeoutMs);\n return {\n stdout: this.truncateOutput(r.stdout),\n stderr: this.truncateOutput(r.stderr),\n exitCode: r.timedOut ? 124 : r.code === 0 ? 0 : 1,\n timedOut: r.timedOut,\n };\n }\n\n async uploadFile(path: string, content: string | Buffer): Promise<void> {\n const target = path.startsWith(\"/\")\n ? posix.normalize(path)\n : posix.normalize(`${CONTAINER_WORKDIR}/${path}`);\n if (target !== CONTAINER_WORKDIR && !target.startsWith(`${CONTAINER_WORKDIR}/`)) {\n throw new SandboxSecurityError(`uploadFile path escapes the workspace: ${path}`);\n }\n const r = await this.run(\n true,\n [\"sh\", \"-c\", 'mkdir -p \"$(dirname \"$1\")\" && cat > \"$1\"', \"sh\", target],\n this.config.timeoutMs ?? 30_000,\n content,\n );\n if (r.code !== 0) throw new Error(`uploadFile failed: ${r.stderr.trim() || \"docker error\"}`);\n }\n}\n","// Promoted from agent-builder in M75 (plan m75-sandbox-kernel-no-framework, D1): confinement with\n// kernel confinement is framework infrastructure, not the consumer's. Measured cost of the promotion: ZERO\n// no dependencies — only node:child_process, node:fs and node:path. The cBPF filter is a Buffer in pure JS.\n\n/**\n * M63 — cBPF seccomp filter generator. Produces a raw `sock_filter[]` program (the exact\n * shape `bwrap --seccomp <fd>` consumes) so syscall confinement needs no\n * native helper — bwrap applies `PR_SET_NO_NEW_PRIVS` + the filter before `execve`.\n *\n * Semantics (landlock.rs:252-253): default action = ALLOW; per-syscall match = ERRNO(EPERM). KILL is\n * used ONLY by the architecture/x32 guard. x86_64 only in v1 (aarch64 is a documented delta).\n */\n\n// BPF opcodes (linux/bpf_common.h)\nconst BPF_LD = 0x00;\nconst BPF_W = 0x00;\nconst BPF_ABS = 0x20;\nconst BPF_JMP = 0x05;\nconst BPF_JEQ = 0x10;\nconst BPF_JGE = 0x30;\nconst BPF_K = 0x00;\nconst BPF_RET = 0x06;\n\nconst LD_ABS_W = BPF_LD | BPF_W | BPF_ABS; // 0x20\nconst JEQ_K = BPF_JMP | BPF_JEQ | BPF_K; // 0x15\nconst JGE_K = BPF_JMP | BPF_JGE | BPF_K; // 0x35\nconst RET_K = BPF_RET | BPF_K; // 0x06\n\n// seccomp_data offsets (little-endian): nr@0, arch@4, args[0] low dword @16\nconst OFF_NR = 0;\nconst OFF_ARCH = 4;\nconst OFF_ARG0 = 16;\n\nconst AUDIT_ARCH_X86_64 = 0xc000003e;\nconst X32_BIT = 0x40000000; // nr >= this ⇒ x32 ABI ⇒ reject\n\n// seccomp return actions (linux/seccomp.h)\nconst SECCOMP_RET_ALLOW = 0x7fff0000;\nconst SECCOMP_RET_ERRNO = 0x00050000;\nconst EPERM = 1;\nconst RET_EPERM = SECCOMP_RET_ERRNO | (EPERM & 0xffff); // 0x00050001\nconst SECCOMP_RET_KILL_PROCESS = 0x80000000;\n\nconst AF_UNIX = 1;\n\n/** Always-denied, network-independent (landlock.rs:179-184). */\nconst ALWAYS_DENIED = [101, 310, 311, 425, 426, 427]; // ptrace, process_vm_readv/writev, io_uring_setup/enter/register\n/**\n * Denied only when the network is restricted (landlock.rs:188-204). recvfrom(45)/sendmsg(46) are\n * NOT here — and, since #385, neither are `getsockname`(51), `getpeername`(52), `setsockopt`(54)\n * and `getsockopt`(55).\n *\n * Those four take an ALREADY-OPEN fd rather than an address, and cBPF cannot dereference an fd to\n * learn the family behind it. Denying them therefore denied them on AF_UNIX as well — which is\n * exactly what libuv calls on a child's IPC channel, so any command that spawned a child died.\n * Measured: `node --test` returned 0 lines under the filter and 38 without it, and the parent's\n * own stdout vanished with it (killed mid-flight, its buffered pipe write never flushed, while the\n * child's already-written bytes survived). The AF_UNIX exemption on `socket`/`socketpair` below\n * shows breaking local IPC was never the intent.\n *\n * They cannot reach a network on their own. Everything that takes an address or changes an fd's\n * role — `connect`, `bind`, `listen`, `accept`, `accept4`, `sendto`, `sendmmsg`, `recvmmsg`,\n * `shutdown` — stays denied, and `socket()` still refuses every family but AF_UNIX. Measured\n * unchanged across the fix: an AF_INET socket is `EPERM` before and after, an AF_UNIX socketpair\n * works before and after.\n *\n * The blunt alternative — dropping the whole set, on the grounds that `--unshare-net` already\n * removes the network — would restore the output AND let a confined command open a connection the\n * moment a future mode runs the filter with the network on. This keeps the belt.\n */\nconst NETWORK_DENIED = [42, 43, 288, 49, 50, 48, 44, 307, 299];\n/** socket(2) / socketpair(2) — conditional on domain != AF_UNIX (landlock.rs:206-216). */\nconst SOCKET_SYSCALLS = [41, 53];\n\n/** One `sock_filter` instruction: `{u16 code, u8 jt, u8 jf, u32 k}`. */\ninterface Insn {\n code: number;\n jt: number;\n jf: number;\n k: number;\n}\nconst stmt = (code: number, k: number): Insn => ({ code, jt: 0, jf: 0, k });\nconst jmp = (code: number, k: number, jt: number, jf: number): Insn => ({ code, jt, jf, k });\n\n/**\n * Input to {@link buildSeccompFilter} — the one axis the generated cBPF program varies on.\n *\n * `networkRestricted: true` adds the socket-family denials on top of the always-denied syscall set;\n * `false` emits the base program, which is NOT \"no filter\". The always-denied set applies either way.\n */\nexport interface SeccompOptions {\n /** When true (network off), also deny the socket set + non-AF_UNIX socket(). */\n networkRestricted: boolean;\n}\n\n/**\n * Build the cBPF seccomp program as a `Buffer` (each `sock_filter` = 8 bytes). Jump targets are\n * expressed against labels and back-patched to relative offsets, so the layout is deterministic and\n * unit-testable against the authoritative syscall list.\n */\nexport function buildSeccompFilter(opts: SeccompOptions): Buffer {\n // We assemble with symbolic targets, then resolve to relative jumps. To keep the classic\n // \"deny → jump to a single DENY return; else fall through\" shape, DENY and ALLOW live at the END and\n // every JEQ jumps FORWARD to them. jt/jf carry the DISTANCE (in instructions) to the target.\n const insns: Insn[] = [];\n\n // Placeholder labels resolved after we know total length.\n // Layout: [arch guard][x32 guard][LD nr][deny checks...][socket checks...][ALLOW][DENY][KILL]\n // We build the body first with jumps to ALLOW/DENY/KILL as sentinel indices, then patch.\n const ALLOW = Symbol(\"ALLOW\");\n const DENY = Symbol(\"DENY\");\n const KILL = Symbol(\"KILL\");\n type Target = typeof ALLOW | typeof DENY | typeof KILL | number;\n interface SInsn {\n code: number;\n k: number;\n jt: Target;\n jf: Target;\n }\n const body: SInsn[] = [];\n const push = (code: number, k: number, jt: Target = 0, jf: Target = 0): void => {\n body.push({ code, k, jt, jf });\n };\n\n // --- arch guard: arch == x86_64 ? continue : KILL ---\n push(LD_ABS_W, OFF_ARCH);\n push(JEQ_K, AUDIT_ARCH_X86_64, 0, KILL); // if != → KILL\n // --- x32 guard: nr >= 0x40000000 ? KILL : continue ---\n push(LD_ABS_W, OFF_NR);\n push(JGE_K, X32_BIT, KILL, 0); // if >= → KILL\n // nr already loaded; keep it loaded for the deny checks.\n\n // --- unconditional denials → DENY ---\n const denied = opts.networkRestricted\n ? [...ALWAYS_DENIED, ...NETWORK_DENIED]\n : [...ALWAYS_DENIED];\n for (const nr of denied) push(JEQ_K, nr, DENY, 0); // if nr == syscall → DENY\n\n // --- socket-family: socket(41)/socketpair(53) → allow only AF_UNIX (only when restricted) ---\n if (opts.networkRestricted) {\n for (const sysno of SOCKET_SYSCALLS) {\n // if nr == socket → check domain; else skip the 2 domain-check instructions\n push(JEQ_K, sysno, 0, 2); // match: fall through to the LD/JEQ; no-match: jump +2 (past them)\n push(LD_ABS_W, OFF_ARG0); // load domain (args[0] low dword)\n push(JEQ_K, AF_UNIX, ALLOW, DENY); // AF_UNIX → ALLOW, else DENY\n // NOTE: after these, nr is NO LONGER in the accumulator — but every remaining syscall check\n // reloads via a fresh LD? No: the remaining path is only ALLOW. socket checks are LAST before\n // the tail, so a fall-through (non-socket syscall that reached here) goes straight to ALLOW.\n }\n }\n\n // --- tail ---\n push(RET_K, SECCOMP_RET_ALLOW); // ALLOW label target\n const allowIdx = body.length - 1;\n push(RET_K, RET_EPERM); // DENY\n const denyIdx = body.length - 1;\n push(RET_K, SECCOMP_RET_KILL_PROCESS); // KILL\n const killIdx = body.length - 1;\n\n // --- resolve symbolic targets to relative offsets ---\n // The branching IS the cBPF program: ALLOW/DENY/KILL are symbolic targets resolved to an\n // offset RELATIVE to the next instruction. Breaking it into helpers does not reduce real complexity —\n // it moves the jump arithmetic to another file and makes auditing against landlock.rs harder, the\n // the authoritative source.\n //\n // Not refactoring NOW is an M75 process decision: this function is being MIGRATED without behavior\n // change (plan m75, D4) and there is still no byte-for-byte equivalence oracle against the\n // original version. Refactoring security without that oracle is changing the lock in the dark.\n // Revisit when the parity gate (T4.2) is green — the oracle exists then.\n // biome-ignore lint/complexity/noExcessiveCognitiveComplexity: see the reason just above\n const resolve = (i: number, t: Target): number => {\n const abs = t === ALLOW ? allowIdx : t === DENY ? denyIdx : t === KILL ? killIdx : i + 1 + t;\n // BPF jump offset is relative to the NEXT instruction: target - (i + 1)\n const off = abs - (i + 1);\n if (off < 0 || off > 255) throw new RangeError(`seccomp jump out of range at ${i}: ${off}`);\n return off;\n };\n // `for...of` over entries instead of a raw index: the SDK compiles with `noUncheckedIndexedAccess`, which\n // (correctly) types `body[i]` as possibly undefined. Iterating gives the guarantee in the type instead\n // requiring a `!` — the code already could not leave the range, and now the compiler knows it.\n for (const [i, b] of body.entries()) {\n if (b.code === JEQ_K || b.code === JGE_K) {\n insns.push(jmp(b.code, b.k, resolve(i, b.jt), resolve(i, b.jf)));\n } else {\n insns.push(stmt(b.code, b.k));\n }\n }\n\n const buf = Buffer.alloc(insns.length * 8);\n insns.forEach((ins, i) => {\n buf.writeUInt16LE(ins.code, i * 8);\n buf.writeUInt8(ins.jt, i * 8 + 2);\n buf.writeUInt8(ins.jf, i * 8 + 3);\n buf.writeUInt32LE(ins.k >>> 0, i * 8 + 4);\n });\n return buf;\n}\n","// B-600 — how the seccomp program reaches bwrap without ever sitting in a file.\n//\n// The program used to be written to `/tmp/ab-seccomp-*/filter.bpf` and read per command through\n// `3< <path>`. `/tmp` is a writable root under `workspace-write`, so one confined command could\n// overwrite that file, or rename its directory away and recreate it, and every LATER command loaded\n// an allow-all program. Every read-only-bind variant left a rename route for some placement of the\n// temp dir; a pipe fed from memory leaves nothing on disk to replace.\n\nimport { rmSync } from \"node:fs\";\nimport { dirname, resolve } from \"node:path\";\n\nimport { type SandboxMode, writableRootsFor } from \"./bwrap.js\";\nimport { buildSeccompFilter } from \"./seccomp.js\";\nimport { shellEscapePosix } from \"./shell-escape.js\";\n\n/** The warning both arch guards print, the path route's and this one: one text, two latches. */\nexport function nonX64SeccompWarning(arch: string): string {\n return (\n `[sandbox] seccomp syscall filter unsupported on ${arch} (x86_64 only in v1) — running without ` +\n \"the filter; bwrap FS/network confinement still applies.\"\n );\n}\n\nlet warnedNonX64Program = false;\n\n/**\n * The restricted-network program for `arch`, or `undefined` where it must not be installed.\n *\n * Same ARCH GUARD as `seccompPathForArch`: the program is x86_64 and KILLs every syscall from\n * another architecture, so on any other arch it is refused with one warning. The latch is this\n * function's own, so a process that also calls the deprecated path helper warns once from each.\n */\nexport function seccompProgramForArch(arch: string, warn: (m: string) => void): Buffer | undefined {\n if (arch !== \"x64\") {\n if (!warnedNonX64Program) {\n warnedNonX64Program = true;\n warn(nonX64SeccompWarning(arch));\n }\n return undefined;\n }\n return buildSeccompFilter({ networkRestricted: true });\n}\n\nlet memoizedProgram: Buffer | null | undefined; // undefined = not built yet; null = resolved absent\n\n/** The restricted-network program, built once per process and x64-gated. Never mutated. */\nexport function restrictedSeccompProgram(warn: (m: string) => void): Buffer | undefined {\n if (memoizedProgram === undefined)\n memoizedProgram = seccompProgramForArch(process.arch, warn) ?? null;\n return memoizedProgram ?? undefined;\n}\n\n/**\n * `program` as a `printf` format of three-digit octal escapes. Always three digits, so a digit that\n * follows is never absorbed into the escape; no `%` appears, so printf prints it verbatim.\n */\nfunction octalPrintfArg(program: Uint8Array): string {\n let out = \"\";\n for (const byte of program) out += `\\\\${byte.toString(8).padStart(3, \"0\")}`;\n return out;\n}\n\n/** A cBPF program is a non-empty list of 8-byte instructions; bwrap refuses anything else. */\nfunction assertSeccompProgramShape(program: Uint8Array): void {\n if (program.length === 0 || program.length % 8 !== 0) {\n throw new TypeError(\n `seccompProgram must be a positive multiple of 8 bytes, got ${program.length}`,\n );\n }\n}\n\n/**\n * The script the piped wrap runs. It is a constant: the program, bwrap's argv and the command reach\n * it as positional arguments, so each is shell-escaped exactly once. Escaping a word twice put a\n * backslash inside single quotes before a quote, which fish reads as an escaped quote.\n *\n * fd 4 saves the command's stdin before the pipe replaces fd 0 in the last stage; `3<&0` moves the\n * pipe to fd 3, `0<&4` restores stdin and `4<&-` closes the copy. Both `exec`s are required: they\n * make the process a timeout kills bwrap's direct parent, so `--die-with-parent` ends the confined\n * command with it. If fd 0 is closed `4<&0` would fail, so fd 4 then reads /dev/null. Without them a timeout left the command running.\n */\nconst PIPE_SCRIPT =\n 'r() { p=$1; shift; printf \"$p\" | exec \"$@\" 3<&0 0<&4 4<&-; }; if { true 5<&0; } 2>/dev/null; then r \"$@\" 4<&0; else r \"$@\" 4</dev/null; fi';\n\n/**\n * Wrap `command` so bwrap reads `program` on fd 3 from a pipe:\n *\n * exec /bin/sh -c '<PIPE_SCRIPT>' sh <octal> <bwrap...> --seccomp 3 -- /bin/sh -c <cmd>\n *\n * The pipeline's grammar is always `/bin/sh`'s, whatever shell runs the outer words.\n * `bwrapArgv` is the binary and flags, unescaped, without `--seccomp` and the trailing `--`.\n */\nexport function wrapWithSeccompProgram(\n bwrapArgv: readonly string[],\n command: string,\n program: Uint8Array,\n): string {\n assertSeccompProgramShape(program);\n const words = [octalPrintfArg(program), ...bwrapArgv, \"--seccomp\", \"3\", \"--\", \"/bin/sh\", \"-c\"];\n return `exec /bin/sh -c ${shellEscapePosix(PIPE_SCRIPT)} sh ${[...words, command].map(shellEscapePosix).join(\" \")}`;\n}\n\n/** The programs `seccompPathForArch` wrote, by resolved path: the wrap loads these, never the file. */\nconst programsWritten = new Map<string, Buffer>();\n\n/**\n * Remember that `path` was written with `program`, so a wrap naming that file pipes the program\n * from memory: a sandbox that does not load the filter mounts `/tmp` writable and can replace it.\n */\nexport function rememberSeccompFile(path: string, program: Buffer): void {\n programsWritten.set(resolve(path), Buffer.from(program));\n}\n\n/**\n * Remove `dir` when the process exits or is told to stop. A SIGINT or SIGTERM listener cancels\n * Node's default termination, so once the directory is gone the signal is raised again when no other\n * listener remains: the process ends as it would have, and a host's own handler still decides.\n * The signal listener is prepended (B-648): run first, it still counts a host's `process.once`\n * handler, which Node unregisters before calling it, whether the host registered before or after.\n * A host that itself prepends a `once` handler after the filter still runs first and is not counted.\n */\nexport function removeDirOnExit(dir: string): void {\n const cleanup = (): void => rmSync(dir, { recursive: true, force: true });\n process.once(\"exit\", cleanup);\n for (const signal of [\"SIGINT\", \"SIGTERM\"] as const) {\n process.prependOnceListener(signal, () => {\n cleanup();\n if (process.listenerCount(signal) === 0) process.kill(process.pid, signal);\n });\n }\n}\n\n/**\n * The deprecated path route, with the filter bound read-only on top of every writable bind so the\n * confined command can neither overwrite it nor rename its directory away (B-600). A path\n * `seccompPathForArch` wrote is piped from memory instead of read, because another sandbox, one with\n * no filter, can still replace that file; any other path is read through `3< <path>`.\n *\n * `bwrapArgv` is the binary followed by `buildBwrapArgv`'s output, which ends `--chdir <cwd> --`;\n * the bind goes before `--chdir`, after every writable bind.\n */\nexport function wrapWithSeccompPath(\n bwrapArgv: readonly string[],\n policy: { mode: SandboxMode; cwd: string },\n command: string,\n seccompPath: string,\n): string {\n const program = programsWritten.get(resolve(seccompPath));\n // A remembered file is never read, so bwrap must not need it on disk: `--ro-bind-try`.\n const bind = program === undefined ? \"--ro-bind\" : \"--ro-bind-try\";\n const flags = [\n ...bwrapArgv.slice(0, -3),\n ...readOnlyBindForSeccompPath(policy.mode, policy.cwd, seccompPath, bind),\n ...bwrapArgv.slice(-3, -1),\n ];\n if (program !== undefined) return wrapWithSeccompProgram(flags, command, program);\n return `${[...flags, \"--seccomp\", \"3\", \"--\"].map(shellEscapePosix).join(\" \")} /bin/sh -c ${shellEscapePosix(command)} 3< ${shellEscapePosix(seccompPath)}`;\n}\n\n/**\n * The read-only bind for the filter. The DIRECTORY is bound, because binding only the file leaves\n * its parent renamable. Where that directory is a writable root or contains one (a filter at\n * `/x.bpf`, or directly in the workspace or `/tmp`), binding it would take a root's write access\n * away, so only the file is bound and a parent rename stays open there. A filter in a SUBdirectory\n * of a writable root makes that subdirectory read-only, and its ancestors stay renamable. Paths are\n * compared resolved, not through symlinks. `seccompProgram` has none of these gaps.\n */\nfunction readOnlyBindForSeccompPath(\n mode: SandboxMode,\n cwd: string,\n seccompPath: string,\n bind: \"--ro-bind\" | \"--ro-bind-try\",\n): string[] {\n const file = resolve(seccompPath);\n const dir = dirname(file);\n const roots = writableRootsFor(mode, resolve(cwd)) ?? [];\n const covers = (root: string): boolean =>\n dir === \"/\" || root === dir || root.startsWith(`${dir}/`);\n const target = roots.some(covers) ? file : dir;\n return [bind, target, target];\n}\n","// Promoted from agent-builder in M75 (plan m75-sandbox-kernel-no-framework, D1). Renamed from\n// `BwrapSandbox` to `LinuxSandbox`: bwrap is the IMPLEMENTATION, Linux is the contract — swapping the\n// mechanism (landlock, for example) should not change the name the consumer imports.\n\nimport { mkdtempSync, writeFileSync } from \"node:fs\";\nimport { tmpdir } from \"node:os\";\nimport { dirname, join } from \"node:path\";\n\nimport { redactSecrets } from \"../internal/security/redact.js\";\nimport type { BwrapDetection, SandboxMode } from \"./bwrap.js\";\nimport { buildBwrapArgv, detectBwrapMemoized } from \"./bwrap.js\";\nimport { denyReadFlags, refuseUnhonourableDenyRead } from \"./deny-read.js\";\nimport { LocalSandbox } from \"./local-sandbox.js\";\nimport { buildSeccompFilter } from \"./seccomp.js\";\nimport {\n nonX64SeccompWarning,\n rememberSeccompFile,\n removeDirOnExit,\n restrictedSeccompProgram,\n wrapWithSeccompPath,\n wrapWithSeccompProgram,\n} from \"./seccomp-delivery.js\";\nimport { shellEscapePosix } from \"./shell-escape.js\";\nimport type { SandboxBackend, SandboxConfig, SandboxNetworkPolicy } from \"./types.js\";\n\n/*\n * M53 — kernel-enforced sandbox backend, injected into `createShellTool({ sandbox })`.\n *\n * `LinuxSandbox extends LocalSandbox` and only REWRITES the command: `<bwrap-bin> <policy flags> --\n * /bin/sh -c '<original>'`. Everything else (spawn, output caps, timeout, ExecuteResult shape, file\n * ops) is inherited — the SDK backend stays the single execution engine. Mirrors Codex's\n * `SandboxManager::transform` (argv prefixing before spawn, never in-process).\n */\n\n/**\n * M57 — the single source of truth for the sandbox command wrap. Turns `command` into\n * `<bin> <bwrap flags> [--seccomp 3] -- /bin/sh -c '<command>' [3< <bpf>]`, or `null` when the policy\n * skips the sandbox (`danger-full-access`). Extracted from `LinuxSandbox.wrapCommand` so the interactive\n * PTY backend (M57) can reuse the EXACT wrap the one-shot `run_shell` already uses (DRY) — faithful to\n * Codex, where the sandbox transforms the argv before the PTY spawns it (`sandboxing/src/manager.rs:321`).\n */\nexport function wrapCommandForSandbox(\n mode: SandboxMode,\n opts: {\n cwd: string;\n network?: boolean;\n env?: Record<string, string>;\n bin?: string;\n /**\n * @deprecated Pass `seccompProgram`: a confined command may replace a file before a later one\n * loads it (B-600). A path `seccompPathForArch` or `restrictedSeccompPath` returned is piped\n * from the bytes this process wrote; any other path is read from the file, bound read-only (see\n * `wrapWithSeccompPath` for what that leaves open). Ignored when `seccompProgram` is given.\n */\n seccompPath?: string;\n /**\n * The cBPF seccomp program, piped to bwrap's fd 3 from memory so no file holds it. Must be a\n * positive multiple of 8 bytes (a `TypeError` otherwise). Wins over `seccompPath`.\n */\n seccompProgram?: Uint8Array;\n /** See `BwrapArgvOptions.denyReadPaths`. */\n denyReadPaths?: readonly string[];\n },\n command: string,\n): string | null {\n const argv = buildBwrapArgv(mode, opts);\n if (argv === null) return null; // danger-full-access: bwrap skipped\n const bin = opts.bin ?? \"bwrap\";\n if (opts.seccompProgram !== undefined) {\n return wrapWithSeccompProgram([bin, ...argv.slice(0, -1)], command, opts.seccompProgram);\n }\n if (opts.seccompPath === undefined) {\n return `${[bin, ...argv].map(shellEscapePosix).join(\" \")} /bin/sh -c ${shellEscapePosix(command)}`;\n }\n return wrapWithSeccompPath([bin, ...argv], { mode, cwd: opts.cwd }, command, opts.seccompPath);\n}\n\n/**\n * Env allowlist re-injected inside the sandbox after `--clearenv`. Codex env_clear model: the child\n * gets exactly what it needs to run a shell, never the parent's full env (which may hold oddly-named\n * secrets the SDK name-pattern scrub misses). `CODEX_SANDBOX_NETWORK_DISABLED` is added by the argv\n * builder when network is unshared.\n */\nconst ENV_ALLOWLIST = [\n \"PATH\",\n \"HOME\",\n \"LANG\",\n \"LC_ALL\",\n \"LC_CTYPE\",\n \"TERM\",\n \"USER\",\n \"TMPDIR\",\n \"SHELL\",\n];\n\n/**\n * Build the environment a confined command runs with after `--clearenv`: `PATH`, `HOME`, `LANG`,\n * `LC_ALL`, `LC_CTYPE`, `TERM`, `USER`, `TMPDIR` and `SHELL`, copied from `source` (default\n * `process.env`) and omitted where unset.\n *\n * The allowlist shape is the point, and it is what separates this from the other env control in the\n * package. `SandboxConfig.env: \"inherit-scrubbed\"` is a denylist: it drops variables whose NAME looks\n * secret-ish, so an oddly named secret survives. Here the child gets these nine names and nothing\n * else, and a secret's name stops mattering.\n *\n * Call it when you compose the wrap yourself and need an `env` for `wrapCommandForSandbox`;\n * {@link LinuxSandbox} already applies it when its `env` option is omitted. Passing a different\n * `source` changes the VALUES, never the set of names — to give a confined command an extra variable,\n * extend the returned object, which is a fresh one on every call.\n */\nexport function allowlistedEnv(source: NodeJS.ProcessEnv = process.env): Record<string, string> {\n const out: Record<string, string> = {};\n for (const k of ENV_ALLOWLIST) {\n const v = source[k];\n if (v !== undefined) out[k] = v;\n }\n return out;\n}\n/**\n * Kernel-confined backend for Linux hosts: a `LocalSandbox` whose commands are rewritten as\n * `bwrap <policy flags> -- /bin/sh -c '<command>'` before they are spawned. Spawning, output caps,\n * timeouts and the `ExecuteResult` shape are all inherited, so confinement is a change to the argv\n * and never an in-process one.\n *\n * Prefer `createSandboxBackend` over constructing this directly. The class assumes bubblewrap is\n * present and never probes for it, so on a host without it every command comes back failed rather\n * than confined; the factory probes first and degrades to a plain `LocalSandbox` with a warning.\n *\n * What the confinement actually covers: the filesystem is bound read-only in full, and\n * `mode: \"workspace-write\"` adds the workspace root plus `/tmp` as the only writable paths, while\n * `\"read-only\"` adds none. The network is unshared unless `network: true`. The environment is cleared\n * and repopulated from {@link allowlistedEnv} unless an explicit `env` is passed. The seccomp syscall\n * filter is a second stage with two conditions on it — x86_64 only, and only when the network is\n * restricted — so `network: true` gives you bwrap's filesystem confinement and no syscall filter.\n * `mode: \"danger-full-access\"` skips the wrap entirely and this class behaves as plain\n * `LocalSandbox`.\n *\n * `uploadFile` is overridden so that writes go through the confined `execute` (base64 over stdin,\n * keeping arbitrary content out of the shell command line). A write the policy forbids therefore\n * fails, throwing a plain `Error` naming the target path and the stderr, instead of quietly landing\n * on the host as the inherited implementation would.\n */\nexport class LinuxSandbox extends LocalSandbox {\n private readonly mode: SandboxMode;\n private readonly network: boolean;\n private readonly cwd: string;\n private readonly bin: string;\n private readonly env: Record<string, string>;\n /** B-600 — the cBPF seccomp program, piped to `bwrap --seccomp 3` from memory (never a file a\n * confined command could replace). `undefined` when the network is unrestricted or the arch is not\n * x86_64 (honest fallback). */\n private readonly seccompProgram: Uint8Array | undefined;\n private readonly denyReadPaths: readonly string[] | undefined;\n /**\n * `\"none\"` exactly when the wrap passes `--unshare-net` (see `buildBwrapArgv`): a confined mode and\n * `network` not set. With `network: true`, or under `danger-full-access` where nothing is wrapped,\n * the command reaches whatever the host does.\n */\n override readonly networkPolicy: SandboxNetworkPolicy;\n\n /** `denyReadPaths`: see `BwrapArgvOptions`; a list that cannot be honoured throws `TypeError` here. */\n constructor(\n config: SandboxConfig,\n opts: {\n mode: SandboxMode;\n network?: boolean;\n bin?: string;\n env?: Record<string, string>;\n denyReadPaths?: readonly string[];\n },\n ) {\n super(config);\n this.mode = opts.mode;\n this.network = opts.network ?? false;\n this.networkPolicy =\n this.network || this.mode === \"danger-full-access\"\n ? { mode: \"unrestricted\" }\n : { mode: \"none\" };\n this.cwd = config.workDir ?? process.cwd();\n // MEDIUM-1: run the VALIDATED absolute binary from detection (anti-hijack), never bare `bwrap`\n // which the outer shell would re-resolve via $PATH at spawn time (TOCTOU / hijack window).\n this.bin = opts.bin ?? \"bwrap\";\n this.env = opts.env ?? allowlistedEnv();\n this.seccompProgram = seccompProgramForNetwork(this.network);\n this.denyReadPaths = opts.denyReadPaths;\n denyReadFlags(this.denyReadPaths, { mode: this.mode, cwd: this.cwd }); // fail fast, not per command\n }\n\n /** Extracted for test visibility — delegates to the pure `wrapCommandForSandbox` (M57, single wrap SoT). */\n wrapCommand(command: string): string | null {\n return wrapCommandForSandbox(\n this.mode,\n {\n cwd: this.cwd,\n network: this.network,\n env: this.env,\n bin: this.bin,\n seccompProgram: this.seccompProgram,\n denyReadPaths: this.denyReadPaths,\n },\n command,\n );\n }\n\n /**\n * M75 review (architecture, HIGH) — without this override the class LIED.\n *\n * `LinuxSandbox` documents itself as a \"kernel-enforced sandbox backend\", but it overrode only\n * `execute`. `uploadFile` stayed the one inherited from `LocalSandbox`, which writes straight to\n * the host via `fs/promises` and accepts an ABSOLUTE path — no bwrap, no seccomp, no path\n * restriction. And `SandboxBackend.writeFile` delegates to it. The result was an incoherent class:\n * reading, searching and listing went through the confinement; writing did not.\n *\n * Routing through the wrapped `execute` fixes it at the root: writes come to live under the SAME\n * policy as everything else — if bwrap denies the path, the write fails, as it should. The content\n * goes over stdin (not argv) because argv has a size limit and file content does not.\n */\n override async uploadFile(path: string, content: string | Buffer): Promise<void> {\n if (this.mode === \"danger-full-access\") return super.uploadFile(path, content);\n\n const target = path.startsWith(\"/\") ? path : `${this.cwd}/${path}`;\n const b64 = Buffer.from(content).toString(\"base64\");\n // base64 on a single line: avoids any shell quoting over arbitrary content, which is exactly\n // where a \"confined\" write would turn into command injection.\n const r = await this.execute(\n `mkdir -p ${shellEscapePosix(dirname(target))} && printf %s ${shellEscapePosix(b64)} | base64 -d > ${shellEscapePosix(target)}`,\n );\n if (r.exitCode !== 0) {\n throw new Error(\n `uploadFile blocked or failed under confinement (${target}): ${r.stderr.trim() || `exit ${r.exitCode}`}`,\n );\n }\n }\n\n override execute(command: string, opts?: { timeoutMs?: number }) {\n const wrapped = this.wrapCommand(command);\n if (wrapped === null) return super.execute(command, opts); // danger-full-access: plain local\n return super.execute(wrapped, opts);\n }\n}\n\nlet warnedNonX64 = false;\n\n/**\n * M63 — the restricted-network seccomp program is DETERMINISTIC, so write it ONCE per process and\n * reuse the path across every LinuxSandbox (no per-instance temp accumulation).\n *\n * ARCH GUARD (review HIGH): `buildSeccompFilter` emits an x86_64 program whose arch guard KILLs every\n * syscall whose `seccomp_data.arch != AUDIT_ARCH_X86_64`. On a non-x86_64 host that would brick EVERY\n * sandboxed command (the first execve is killed) — and silently, because generation succeeds and bwrap\n * accepts it. So we REFUSE to install on non-x64 and WARN through the honest-downgrade channel (bwrap\n * FS/network confinement still applies), exactly like the bwrap-missing fallback. `arch` is injectable\n * for tests. Cleaned on exit AND on SIGINT/SIGTERM (TUI Ctrl+C would otherwise leak the temp dir).\n *\n * @deprecated Writes the program to a temp file a confined command may be able to replace (B-600).\n * Use `wrapCommandForSandbox`'s `seccompProgram`, which keeps the program in memory.\n */\nexport function seccompPathForArch(arch: string, warn: (m: string) => void): string | undefined {\n if (arch !== \"x64\") {\n if (!warnedNonX64) {\n warnedNonX64 = true;\n warn(nonX64SeccompWarning(arch));\n }\n return undefined;\n }\n try {\n const dir = mkdtempSync(join(tmpdir(), \"ab-seccomp-\"));\n const path = join(dir, \"filter.bpf\");\n const program = buildSeccompFilter({ networkRestricted: true });\n writeFileSync(path, program);\n rememberSeccompFile(path, program); // the wraps pipe these bytes, never the file's (B-600)\n removeDirOnExit(dir);\n return path;\n } catch (err) {\n warn(\n `[sandbox] seccomp filter unavailable (${err instanceof Error ? err.message : String(err)}) — ` +\n \"running without syscall filter (bwrap FS/network confinement still applies).\",\n );\n return undefined;\n }\n}\n\nlet seccompFilterPath: string | undefined | null; // undefined = not tried; null = resolved absent\n/**\n * M57 — the memoized x64-gated seccomp program, written once per process to a temp file.\n *\n * @deprecated The SDK's own wraps no longer read this file (B-600): a file under `/tmp` is one a\n * `workspace-write` command can replace. Use `wrapCommandForSandbox`'s `seccompProgram`.\n */\nexport function restrictedSeccompPath(): string | undefined {\n if (seccompFilterPath !== undefined) return seccompFilterPath ?? undefined;\n const path = seccompPathForArch(process.arch, (m) => console.warn(redactSecrets(m)));\n seccompFilterPath = path ?? null;\n return path;\n}\n\nlet warnedUnavailable = false;\n\n/**\n * Test seam: reset the WARN-once latch.\n *\n * Named for what it is. It was `resetSandboxWarnLatch`, plain camelCase, re-exported from the public\n * `@theokit/sdk/sandbox` barrel — indistinguishable from ordinary API, while 22 sibling test seams in\n * this package carry an unmistakable `__…ForTests` marker and stay out of their barrels.\n *\n * Deliberately NOT tagged internal-visibility: the barrel still re-exports it under the old name as a\n * deprecated alias until the next major, so the symbol has to survive `stripInternal` into the\n * emitted declarations. Tagging it removed it from the `.d.ts` and the declaration rollup failed —\n * `tsc --noEmit` never sees that.\n */\nexport function __resetSandboxWarnLatchForTests(): void {\n warnedUnavailable = false;\n}\n\n/** Durable sandbox posture for the UI — the honest answer to \"am I kernel-enforced right now?\". */\nexport interface SandboxPosture {\n mode: SandboxMode;\n enforced: boolean;\n detail: string;\n}\n\n/**\n * MEDIUM-2: compute the posture so a surface (TUI footer) can show enforcement DURABLY instead of a\n * one-shot warn. `danger-full-access` is honestly reported as unenforced; an unavailable bwrap reports\n * the downgrade reason so the user never believes they are confined when they are not.\n */\nexport function resolveSandboxPosture(opts: {\n mode: SandboxMode;\n detect?: () => BwrapDetection;\n}): SandboxPosture {\n if (opts.mode === \"danger-full-access\") {\n return { mode: opts.mode, enforced: false, detail: \"no confinement (danger-full-access)\" };\n }\n const detection = (opts.detect ?? detectBwrapMemoized)();\n if (!detection.ok) {\n return { mode: opts.mode, enforced: false, detail: `tool-gating only — ${detection.reason}` };\n }\n return { mode: opts.mode, enforced: true, detail: \"kernel (bwrap)\" };\n}\n\n/**\n * Options for `createSandboxBackend`, which probes for bubblewrap and returns a {@link LinuxSandbox}\n * when confinement is genuinely available or a `LocalSandbox` when it is not — warning once when the\n * absence is a failure, and silently when `mode` is `\"danger-full-access\"`, since that is an explicit\n * opt-out rather than a degradation.\n *\n * The declared return type is `SandboxBackend` either way, so it does not tell you which one you got.\n * Call `resolveSandboxPosture({ mode })` for that, and surface it durably — the warning fires once\n * per process and a user who missed it has no way to tell they are unconfined.\n *\n * `workDir` and `timeoutMs` are forwarded into the backend's `SandboxConfig`; `maxOutputBytes` and\n * the env policy are not, and keep their defaults. `network` only reaches the confined path, being\n * meaningless on a fallback where the network was never restricted. `detect` and `warn` exist so\n * tests can drive both branches without a real bubblewrap.\n */\nexport interface CreateSandboxBackendOptions {\n mode: SandboxMode;\n workDir?: string;\n network?: boolean;\n timeoutMs?: number;\n /** Paths the shell cannot read. Never degrades to unconfined: throws `TypeError` or `SandboxNotAvailableError`. */\n denyReadPaths?: readonly string[];\n /** Injectable for tests; defaults to the real 3-probe detection. */\n detect?: () => BwrapDetection;\n /** Injectable for tests; defaults to console.warn. */\n warn?: (message: string) => void;\n}\n\n/**\n * Honest factory: bwrap available + mode wants confinement → `LinuxSandbox` (kernel enforcement,\n * running the VALIDATED absolute bin); `danger-full-access` → plain `LocalSandbox` silently (explicit\n * opt-out, `bwrap.rs:245-252`); bwrap unavailable → WARN once + `LocalSandbox` (the declarative M23\n * gating remains the guard). NEVER pretends to sandbox — the fallback is loud, mirroring Codex's\n * MISSING_BWRAP_WARNING. The durable posture lives in `resolveSandboxPosture` for the UI.\n */\nexport function createSandboxBackend(opts: CreateSandboxBackendOptions): SandboxBackend {\n const config: SandboxConfig = { workDir: opts.workDir, timeoutMs: opts.timeoutMs };\n refuseUnhonourableDenyRead(opts.denyReadPaths, opts.mode, opts.detect ?? detectBwrapMemoized);\n if (opts.mode === \"danger-full-access\") return new LocalSandbox(config);\n\n const detection = (opts.detect ?? detectBwrapMemoized)();\n if (!detection.ok) {\n if (!warnedUnavailable) {\n warnedUnavailable = true;\n const warn = opts.warn ?? ((m: string) => console.warn(redactSecrets(m)));\n warn(\n `[sandbox] OS-level enforcement unavailable (${detection.reason}) — ` +\n `falling back to tool-level gating only (sandbox_mode=${opts.mode}).`,\n );\n }\n return new LocalSandbox(config);\n }\n return new LinuxSandbox(config, { ...opts, bin: detection.bin }); // the class reads mode, network, denyReadPaths\n}\n\n/**\n * M75 T3.2 — warning latch for the INTERACTIVE path.\n *\n * Kept separate from `createSandboxBackend`'s latch on purpose: they are two distinct decisions\n * taken at distinct moments, and a user who only ever runs an interactive shell needs to see the\n * warning even if the non-interactive path already emitted it — otherwise the session where they\n * actually type commands would be the one without the alert.\n */\nlet interactiveWarned = false;\n\n/**\n * Reset for tests — the latch is module state and tests need isolation.\n *\n * See `__resetSandboxWarnLatchForTests` for why the name changed, and for why neither carries an\n * internal-visibility tag while the deprecated public alias exists.\n */\nexport function __resetInteractiveWarnLatchForTests(): void {\n interactiveWarned = false;\n}\n\n/**\n * The rule \"seccomp ONLY with restricted network\" — in ONE place.\n *\n * Codex installs the filter only when the network is closed (`landlock.rs:96-117`), and that is not\n * a detail: the cBPF program **denies the network syscalls** (`NETWORK_DENIED`). Applying it with\n * the network open produces the worst possible combination — bwrap **allows** the network (no\n * `--unshare-net`) and seccomp **denies** it with EPERM. The user asked for network, got the bind,\n * and the calls die.\n *\n * It existed duplicated: the constructor decided conditionally, `interactiveWrapCommand` installed\n * unconditionally. They had already diverged in the first version (M75 architecture review, proven\n * at runtime: `network:true` gave `--seccomp` interactively and not one-shot). Two copies of a\n * security rule is not duplicated form — it is duplicated KNOWLEDGE, and it had already diverged.\n */\nfunction seccompProgramForNetwork(networkOpen: boolean): Uint8Array | undefined {\n return networkOpen ? undefined : restrictedSeccompProgram((m) => console.warn(redactSecrets(m)));\n}\n\n/**\n * Options for `interactiveWrapCommand`, the PTY counterpart of `createSandboxBackend`.\n *\n * They differ in what they hand back, and that is how you choose. A PTY owns its own spawn and\n * accepts no backend object, so this path returns a `(command, cwd) => string | null` transform: the\n * wrapped command line, or `null` meaning run it as-is. Use it when something else does the spawning;\n * use `createSandboxBackend` when you want an object that executes.\n *\n * Detection is consulted on every wrap instead of being frozen at construction, because an\n * interactive session outlives the probe — a bubblewrap binary that disappears mid-session stops\n * being asserted as present.\n *\n * `network` defaults to `false`, matching the non-interactive path, and carries the same consequence:\n * the seccomp filter is installed only when the network is restricted. The warn-once latch is\n * deliberately separate from the one `createSandboxBackend` keeps, so a user who only ever opens an\n * interactive shell still sees the \"runs WITHOUT kernel confinement\" warning in the session where\n * they type commands.\n */\nexport interface InteractiveWrapOptions {\n mode: SandboxMode;\n /** `true` keeps the network. Default `false`, same as non-interactive `run_shell`. */\n network?: boolean;\n /** Paths the command cannot read. Throws on the wrap, never runs unconfined (as `CreateSandboxBackendOptions`). */\n denyReadPaths?: readonly string[];\n /** Injectable for tests; defaults to the real memoized detection. */\n detect?: () => BwrapDetection;\n /** Injectable for tests; defaults to `console.warn` with redaction. */\n warn?: (message: string) => void;\n}\n\n/**\n * The decision to confine or degrade, separated from the wrap itself.\n *\n * Extracted because they are two responsibilities and the SDK's complexity gate separated them for\n * us: DECIDING (is confinement available? did the user opt out?) and APPLYING (assembling the argv).\n * Keeping them together pushed the closure past 10 cognitive complexity — and the linter was right:\n * the deciding part is the one with security consequences and deserves to be read on its own.\n *\n * Returns the validated binary when confinement exists, or `null` when it does not — warning ONCE,\n * and only when the absence is a failure (not when it is an opt-out).\n */\nfunction decideConfinement(opts: InteractiveWrapOptions): string | null {\n refuseUnhonourableDenyRead(opts.denyReadPaths, opts.mode, opts.detect ?? detectBwrapMemoized);\n if (opts.mode === \"danger-full-access\") return null;\n\n const detection = (opts.detect ?? detectBwrapMemoized)();\n if (detection.ok) return detection.bin;\n\n if (!interactiveWarned) {\n interactiveWarned = true;\n const warn = opts.warn ?? ((m: string) => console.warn(redactSecrets(m)));\n warn(\n `[sandbox] OS-level enforcement unavailable (${detection.reason}) — interactive session ` +\n `runs WITHOUT kernel confinement (sandbox_mode=${opts.mode}).`,\n );\n }\n return null;\n}\n\n/**\n * The composition the interactive path needs — the counterpart of `createSandboxBackend`.\n *\n * `createSandboxBackend` solves this for the non-interactive path by returning a ready BACKEND. The\n * PTY accepts no backend: it owns the spawn and only allows transforming the command. This function\n * delivers the SAME decision in the shape the PTY accepts — `(command, cwd) => string | null` —\n * ready for `new PtyInteractiveBackend({ wrapCommand: interactiveWrapCommand({ mode }) })`.\n *\n * Detection is consulted on **every wrap**, not frozen at construction: an interactive session lives\n * for hours, and a stale positive detection would keep asserting confinement after the binary\n * disappeared (the `existsSync` revalidation lives inside `detectBwrapMemoized`).\n *\n * The two routes returning `null` are semantically different and the code does not merge them:\n * `danger-full-access` is an explicit opt-out and does NOT warn; bwrap being unavailable is a\n * failure and warns once.\n */\nexport function interactiveWrapCommand(\n opts: InteractiveWrapOptions,\n): (command: string, cwd: string) => string | null {\n return (command: string, cwd: string): string | null => {\n const bin = decideConfinement(opts);\n if (bin === null) return null;\n\n return wrapCommandForSandbox(\n opts.mode,\n {\n cwd,\n network: opts.network ?? false,\n env: allowlistedEnv(),\n bin,\n seccompProgram: seccompProgramForNetwork(opts.network ?? false),\n denyReadPaths: opts.denyReadPaths,\n },\n command,\n );\n };\n}\n","/**\n * M6-3 — portable repo provisioner for the eval harness.\n *\n * Clones a repository and checks out a ref into an isolated working dir, issuing\n * every git command through {@link SandboxBackend.execute} (ADR D2 — same code\n * runs on Local/Docker/E2B; never a direct `child_process` import). Promotes\n * theocode's `prepareRepo` (`swebench-provision.ts:37`) onto the SDK's sandbox\n * abstraction.\n *\n * reference: knowledge-base/references/theocode-eval/lib/swebench-provision.ts:37\n * (clone+checkout), :13 (ProvisionError with instanceId).\n *\n * @public\n */\n\nimport { TheokitAgentError } from \"../errors.js\";\nimport { LocalSandbox } from \"./local-sandbox.js\";\nimport { shellEscapePosix } from \"./shell-escape.js\";\nimport type { SandboxBackend } from \"./types.js\";\n\n/**\n * Raised when cloning or checking out a repo fails. Carries the `instanceId`\n * so a batch run can attribute the failure to the offending dataset row.\n */\nexport class RepoProvisionError extends TheokitAgentError {\n override readonly name = \"RepoProvisionError\";\n\n constructor(\n readonly instanceId: string,\n message: string,\n options: { cause?: unknown } = {},\n ) {\n super(`[${instanceId}] ${message}`, {\n code: \"repo_provision_failed\",\n isRetryable: false,\n ...(options.cause !== undefined ? { cause: options.cause } : {}),\n });\n }\n}\n\n/** Options for {@link provisionRepo}. */\nexport interface ProvisionRepoOptions {\n /**\n * Clonable repo URL or local path. SECURITY: when this comes from an\n * untrusted dataset, the value is passed to `git clone` after a `--`\n * end-of-options terminator (no flag injection) and with the `ext::`\n * transport disabled (no arbitrary-command transport).\n */\n readonly repoUrl: string;\n /** Branch, tag, or commit SHA to check out. Rejected if it begins with `-`. */\n readonly ref: string;\n /**\n * Unique id for this row — names the target dir and any error. Validated to\n * `[A-Za-z0-9._-]` (no path traversal) since it becomes a directory name.\n */\n readonly instanceId: string;\n}\n\n/**\n * Reject ids that would escape the workdir or be parsed as a git flag. Must\n * start with an alphanumeric (blocks `.`, `..`, `-foo`, leading-dot names) and\n * thereafter allow only `[A-Za-z0-9._-]`.\n */\nconst SAFE_INSTANCE_ID = /^[A-Za-z0-9][A-Za-z0-9._-]*$/;\n\n/**\n * Clone `repoUrl` into `<sandbox workdir>/<instanceId>` and check out `ref`.\n * Returns the absolute `repoDir` (resolved via `git rev-parse --show-toplevel`,\n * which is portable across backends). Throws {@link RepoProvisionError} naming\n * the `instanceId` when clone or checkout exits non-zero.\n *\n * The `sandbox` is optional (V3-5): when omitted, a default {@link LocalSandbox}\n * is used (clones into the process cwd's `<instanceId>`) — pass an explicit\n * sandbox (e.g. `LocalSandbox({ workDir })` / Docker / E2B) to control the workdir.\n */\nexport function provisionRepo(opts: ProvisionRepoOptions): Promise<{ repoDir: string }>;\nexport function provisionRepo(\n sandbox: SandboxBackend,\n opts: ProvisionRepoOptions,\n): Promise<{ repoDir: string }>;\nexport async function provisionRepo(\n sandboxOrOpts: SandboxBackend | ProvisionRepoOptions,\n maybeOpts?: ProvisionRepoOptions,\n): Promise<{ repoDir: string }> {\n const sandbox = maybeOpts !== undefined ? (sandboxOrOpts as SandboxBackend) : new LocalSandbox();\n const opts = maybeOpts ?? (sandboxOrOpts as ProvisionRepoOptions);\n const { repoUrl, ref, instanceId } = opts;\n\n // Validate untrusted-derivable inputs before they reach git/the shell.\n if (!SAFE_INSTANCE_ID.test(instanceId)) {\n throw new RepoProvisionError(\n instanceId,\n \"invalid instanceId: must match [A-Za-z0-9._-] (no path traversal)\",\n );\n }\n if (ref.startsWith(\"-\")) {\n throw new RepoProvisionError(instanceId, `invalid ref: must not begin with '-' (got ${ref})`);\n }\n\n // `--` terminates options (no `--upload-pack=` flag injection); `protocol.ext.allow=never`\n // blocks the `ext::` arbitrary-command transport. `file`/`https` stay allowed.\n const clone = await sandbox.execute(\n `git -c protocol.ext.allow=never clone --quiet -- ${shellEscapePosix(repoUrl)} ${shellEscapePosix(instanceId)}`,\n );\n if (clone.exitCode !== 0) {\n throw new RepoProvisionError(instanceId, `clone failed: ${clone.stderr.trim()}`);\n }\n\n const top = await sandbox.execute(\n `git -C ${shellEscapePosix(instanceId)} rev-parse --show-toplevel`,\n );\n if (top.exitCode !== 0) {\n throw new RepoProvisionError(instanceId, `resolve repoDir failed: ${top.stderr.trim()}`);\n }\n const repoDir = top.stdout.trim();\n\n // `ref` is validated above not to begin with `-`, so it cannot be parsed as a flag.\n const checkout = await sandbox.execute(\n `git -C ${shellEscapePosix(repoDir)} checkout --quiet ${shellEscapePosix(ref)}`,\n );\n if (checkout.exitCode !== 0) {\n throw new RepoProvisionError(instanceId, `checkout ${ref} failed: ${checkout.stderr.trim()}`);\n }\n\n return { repoDir };\n}\n"]}
@@ -431,6 +431,13 @@ type McpStdioServerConfig = {
431
431
  * policy and always wins. Pass `"all"` to restore full inheritance.
432
432
  */
433
433
  envPolicy?: EnvPolicy;
434
+ /**
435
+ * Run the calls a model makes to this server's tools in ONE step one at a time, in the order the
436
+ * model listed them, instead of at once. Set it for a stateful server whose tools act on shared
437
+ * state, such as a browser MCP server where a snapshot must wait for the navigation before it.
438
+ * Calls to other servers or non-MCP tools in the same step are not held behind it. Default `false`.
439
+ */
440
+ sequential?: boolean;
434
441
  };
435
442
  /**
436
443
  * OAuth-style auth bundle for HTTP/SSE MCP servers.
@@ -482,6 +489,13 @@ type McpHttpServerConfig = {
482
489
  * `NetworkError` (`code: "mcp_timeout"`). Default 30_000.
483
490
  */
484
491
  requestTimeoutMs?: number;
492
+ /**
493
+ * Run the calls a model makes to this server's tools in ONE step one at a time, in the order the
494
+ * model listed them, instead of at once. Set it for a stateful server whose tools act on shared
495
+ * state, such as a browser MCP server where a snapshot must wait for the navigation before it.
496
+ * Calls to other servers or non-MCP tools in the same step are not held behind it. Default `false`.
497
+ */
498
+ sequential?: boolean;
485
499
  };
486
500
  /**
487
501
  * Union of MCP server configs.
@@ -1864,6 +1878,8 @@ type SDKImage = {
1864
1878
  mimeType: string;
1865
1879
  dimension?: SDKImageDimension;
1866
1880
  };
1881
+ /** How a message sent during a running turn is queued. See {@link SendOptions.queueMode}. @public */
1882
+ type QueueMode = "followup" | "steer" | "collect";
1867
1883
  /**
1868
1884
  * Structured form of `agent.send()`'s message argument. Use it to send images
1869
1885
  * alongside text.
@@ -1891,7 +1907,7 @@ interface SDKUserMessage {
1891
1907
  * | rendering a live UI | `onDelta`, `onStep`, `onRunEvent` |
1892
1908
  * | applying a policy | `permissionMode`, `activeTools`, `toolChoice`, `toolResultGuard`, `pruneToolResults`, `perToolTimeoutMs` |
1893
1909
  * | running an eval or a harness | `maxIterations`, `completionCheck`, `doomLoop`, `signal` |
1894
- * | orchestrating agents | `origin`, `task`, `context` |
1910
+ * | orchestrating agents | `origin`, `task`, `context`, `queueMode` |
1895
1911
  * | overriding this one send | `model`, `systemPrompt`, `tools`, `mcpServers`, `contextPaths`, `local` |
1896
1912
  *
1897
1913
  * Every field appears in exactly one row, and
@@ -1902,6 +1918,18 @@ interface SDKUserMessage {
1902
1918
  * @public
1903
1919
  */
1904
1920
  interface SendOptions {
1921
+ /**
1922
+ * What to do with this message when the agent is ALREADY running a turn (local runtime only; a
1923
+ * cloud agent always queues as `"followup"`). With no turn running, every mode just starts one.
1924
+ *
1925
+ * - `"followup"` (default) — wait for the running turn, then run as its own turn.
1926
+ * - `"steer"` — inject the text into the RUNNING turn as a user message, picked up before the
1927
+ * model's next call (after the current tool round). Resolves to the running turn's `Run`. If
1928
+ * the turn ends before it can pick the message up, it runs as a followup turn instead.
1929
+ * - `"collect"` — batch every `"collect"` message sent while a turn runs into ONE followup turn
1930
+ * (texts joined by a blank line). Every collecting caller resolves to that same batched `Run`.
1931
+ */
1932
+ queueMode?: QueueMode;
1905
1933
  /**
1906
1934
  * Per-send model override. SE8 — accepts a bare-string id shorthand
1907
1935
  * (`"openai/gpt-4o-mini"`, normalized to `{ id }`) OR a {@link ModelSelection}
@@ -2582,4 +2610,4 @@ interface InvalidateCacheOptions {
2582
2610
  applyNow?: boolean;
2583
2611
  }
2584
2612
 
2585
- export type { OutputProcessorContext as $, AgentConversationTurn as A, GenerateRunResult as B, ContextSettings as C, DoomLoopThresholds as D, EnvPolicy as E, ForkOptions as F, GoalOptions as G, InteractionUpdate as H, InputProcessorContext as I, JudgeResult as J, InvalidateCacheOptions as K, McpAuthConfig as L, McpServerConfig as M, McpHttpServerConfig as N, McpOAuthConfig as O, ProviderRoutingSettings as P, McpStdioServerConfig as Q, RunResult as R, SDKAgent as S, MemoryAdapter as T, MemoryAdapterCapabilities as U, MemoryContext as V, MemoryFact as W, MemoryRevision as X, MemoryToolSchema as Y, MemoryTurnMessage as Z, MessageOrigin as _, PluginsSettings as a, TokenUsage as a$, PartialToolCallUpdate as a0, PersonalityPreset as a1, ProcessorControls as a2, ProcessorTripwire as a3, ProcessorViolation as a4, ProviderCapability as a5, ProviderRoute as a6, PruneToolResultsOptions as a7, ResolvedProviderRoute as a8, RunCompactBoundaryEvent as a9, SDKPluginMetadata as aA, SDKProvidersManager as aB, SDKRequestMessage as aC, SDKStatusMessage as aD, SDKSystemMessage as aE, SDKTaskMessage as aF, SDKThinkingMessage as aG, SDKToolUseMessage as aH, SDKUserMessage as aI, SDKUserMessageEvent as aJ, SendOptions as aK, ShellCommand as aL, ShellConversationTurn as aM, ShellOutput as aN, ShellOutputDeltaUpdate as aO, StepCompletedUpdate as aP, StepStartedUpdate as aQ, StreamToCompletionResult as aR, SummaryCompletedUpdate as aS, SummaryStartedUpdate as aT, SummaryUpdate as aU, SystemPromptSkillRef as aV, TextDeltaUpdate as aW, ThinkingCompletedUpdate as aX, ThinkingDeltaUpdate as aY, ThinkingMessage as aZ, TokenDeltaUpdate as a_, RunCompletionCheckEvent as aa, RunErrorDetail as ab, RunEvent as ac, RunGitInfo as ad, RunMemoryDegradedEvent as ae, RunPermissionDeniedEvent as af, RunRateLimitEvent as ag, RunStatus as ah, RunTaskCompletedEvent as ai, RunTaskStartedEvent as aj, RunTaskUpdatedEvent as ak, RunTimelineEvent as al, RunToCompletionOptions as am, RunToCompletionResult as an, RunToolProgressEvent as ao, RunTripwireEvent as ap, RunUntilIterator as aq, SDKAgentPlugins as ar, SDKAgentSkillDetail as as, SDKAgentSkills as at, SDKArtifact as au, SDKAssistantMessage as av, SDKContextManager as aw, SDKImage as ax, SDKImageDimension as ay, SDKObjectDelta as az, Run as b, ToolCall as b0, ToolCallCompletedUpdate as b1, ToolCallStartedUpdate as b2, ToolResult as b3, ToolResultGuardOptions as b4, ToolUseBlock as b5, TurnEndedUpdate as b6, UserMessage as b7, UserMessageAppendedUpdate as b8, Verdict as b9, Processor as c, GoalEvent as d, GoalResult as e, MemoryId as f, RunEventSink as g, SDKProvider as h, SDKMessage as i, AgentMemory as j, AgentOperation as k, AssistantMessage as l, CompletionCheck as m, CompletionCheckResult as n, ContextBudget as o, ContextManagerKind as p, ContextSnapshot as q, ContextSource as r, ContextSourceStatus as s, ConversationStep as t, ConversationTurn as u, CostBreakdown as v, CostSource as w, CostStatus as x, ForkResult as y, GenerateOptions as z };
2613
+ export type { OutputProcessorContext as $, AgentConversationTurn as A, GenerateRunResult as B, ContextSettings as C, DoomLoopThresholds as D, EnvPolicy as E, ForkOptions as F, GoalOptions as G, InteractionUpdate as H, InputProcessorContext as I, JudgeResult as J, InvalidateCacheOptions as K, McpAuthConfig as L, McpServerConfig as M, McpHttpServerConfig as N, McpOAuthConfig as O, ProviderRoutingSettings as P, McpStdioServerConfig as Q, RunResult as R, SDKAgent as S, MemoryAdapter as T, MemoryAdapterCapabilities as U, MemoryContext as V, MemoryFact as W, MemoryRevision as X, MemoryToolSchema as Y, MemoryTurnMessage as Z, MessageOrigin as _, PluginsSettings as a, TokenDeltaUpdate as a$, PartialToolCallUpdate as a0, PersonalityPreset as a1, ProcessorControls as a2, ProcessorTripwire as a3, ProcessorViolation as a4, ProviderCapability as a5, ProviderRoute as a6, PruneToolResultsOptions as a7, QueueMode as a8, ResolvedProviderRoute as a9, SDKObjectDelta as aA, SDKPluginMetadata as aB, SDKProvidersManager as aC, SDKRequestMessage as aD, SDKStatusMessage as aE, SDKSystemMessage as aF, SDKTaskMessage as aG, SDKThinkingMessage as aH, SDKToolUseMessage as aI, SDKUserMessage as aJ, SDKUserMessageEvent as aK, SendOptions as aL, ShellCommand as aM, ShellConversationTurn as aN, ShellOutput as aO, ShellOutputDeltaUpdate as aP, StepCompletedUpdate as aQ, StepStartedUpdate as aR, StreamToCompletionResult as aS, SummaryCompletedUpdate as aT, SummaryStartedUpdate as aU, SummaryUpdate as aV, SystemPromptSkillRef as aW, TextDeltaUpdate as aX, ThinkingCompletedUpdate as aY, ThinkingDeltaUpdate as aZ, ThinkingMessage as a_, RunCompactBoundaryEvent as aa, RunCompletionCheckEvent as ab, RunErrorDetail as ac, RunEvent as ad, RunGitInfo as ae, RunMemoryDegradedEvent as af, RunPermissionDeniedEvent as ag, RunRateLimitEvent as ah, RunStatus as ai, RunTaskCompletedEvent as aj, RunTaskStartedEvent as ak, RunTaskUpdatedEvent as al, RunTimelineEvent as am, RunToCompletionOptions as an, RunToCompletionResult as ao, RunToolProgressEvent as ap, RunTripwireEvent as aq, RunUntilIterator as ar, SDKAgentPlugins as as, SDKAgentSkillDetail as at, SDKAgentSkills as au, SDKArtifact as av, SDKAssistantMessage as aw, SDKContextManager as ax, SDKImage as ay, SDKImageDimension as az, Run as b, TokenUsage as b0, ToolCall as b1, ToolCallCompletedUpdate as b2, ToolCallStartedUpdate as b3, ToolResult as b4, ToolResultGuardOptions as b5, ToolUseBlock as b6, TurnEndedUpdate as b7, UserMessage as b8, UserMessageAppendedUpdate as b9, Verdict as ba, Processor as c, GoalEvent as d, GoalResult as e, MemoryId as f, RunEventSink as g, SDKProvider as h, SDKMessage as i, AgentMemory as j, AgentOperation as k, AssistantMessage as l, CompletionCheck as m, CompletionCheckResult as n, ContextBudget as o, ContextManagerKind as p, ContextSnapshot as q, ContextSource as r, ContextSourceStatus as s, ConversationStep as t, ConversationTurn as u, CostBreakdown as v, CostSource as w, CostStatus as x, ForkResult as y, GenerateOptions as z };