reeval 0.11.0 → 0.12.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 (283) hide show
  1. package/README.md +3 -1
  2. package/bin/mcp-timer.cjs +224 -0
  3. package/dist/{adapter-Bwy3QxAK.js → adapter-DigeVFWC.js} +3 -3
  4. package/dist/{adapter-Bwy3QxAK.js.map → adapter-DigeVFWC.js.map} +1 -1
  5. package/dist/{agent-DpE80WPz.js → agent-CatUEo5h.js} +21 -6
  6. package/dist/{agent-DpE80WPz.js.map → agent-CatUEo5h.js.map} +1 -1
  7. package/dist/{assemble-D9GWr-HS.js → assemble-CF063ms6.js} +19 -17
  8. package/dist/assemble-CF063ms6.js.map +1 -0
  9. package/dist/assemble-CJoD_Rzr.js +1 -0
  10. package/dist/bridge/index.mjs +2 -1
  11. package/dist/{capture-BQlGHiMC.js → capture-BiD7lVaM.js} +25 -17
  12. package/dist/{capture-BQlGHiMC.js.map → capture-BiD7lVaM.js.map} +1 -1
  13. package/dist/capture-Dp3q7K7Y.js +1 -0
  14. package/dist/{cli-ClpPT8kn.js → cli-B5zQCR2r.js} +161 -116
  15. package/dist/cli-B5zQCR2r.js.map +1 -0
  16. package/dist/{cli-spec-qmEnQ25_.js → cli-spec-BXIBUlaK.js} +34 -15
  17. package/dist/cli-spec-BXIBUlaK.js.map +1 -0
  18. package/dist/cli.js +2 -2
  19. package/dist/{command-TgbzPizb.js → command-BMHXHqMT.js} +15 -14
  20. package/dist/command-BMHXHqMT.js.map +1 -0
  21. package/dist/command-C94CQNh8.js +91 -0
  22. package/dist/command-C94CQNh8.js.map +1 -0
  23. package/dist/command-CVtgyqlM.js +335 -0
  24. package/dist/command-CVtgyqlM.js.map +1 -0
  25. package/dist/{command-DbAe1Rzb.js → command-CaZgCTIw.js} +14 -17
  26. package/dist/command-CaZgCTIw.js.map +1 -0
  27. package/dist/{command-BlM0y8jN.js → command-DTgBZR0k.js} +6 -6
  28. package/dist/{command-BlM0y8jN.js.map → command-DTgBZR0k.js.map} +1 -1
  29. package/dist/{commands-CthqwkAn.js → commands-BXzIDB3X.js} +1 -1
  30. package/dist/commands-CjpGBUWr.js +666 -0
  31. package/dist/commands-CjpGBUWr.js.map +1 -0
  32. package/dist/{config-DrVSEVN0.js → config-Dv5MG7Rp.js} +27 -48
  33. package/dist/config-Dv5MG7Rp.js.map +1 -0
  34. package/dist/{context-C1mxXh80.js → context-Dgn48BqT.js} +13 -2
  35. package/dist/context-Dgn48BqT.js.map +1 -0
  36. package/dist/{contrasts-5zsj32gk.js → contrasts-CcoMLC_y.js} +3 -3
  37. package/dist/{contrasts-5zsj32gk.js.map → contrasts-CcoMLC_y.js.map} +1 -1
  38. package/dist/db-BeqRiWLl.js +602 -0
  39. package/dist/db-BeqRiWLl.js.map +1 -0
  40. package/dist/db-CJDRVQal.js +2 -0
  41. package/dist/{dist-CuY4ehEk.js → dist-CMjp3qqF.js} +2 -2
  42. package/dist/{dist-CuY4ehEk.js.map → dist-CMjp3qqF.js.map} +1 -1
  43. package/dist/{docker-DOvjji9I.js → docker-BbTlMmYi.js} +2 -2
  44. package/dist/{docker-DOvjji9I.js.map → docker-BbTlMmYi.js.map} +1 -1
  45. package/dist/{docker-D1HZDS6q.js → docker-CCXdbREk.js} +20 -4
  46. package/dist/{docker-D1HZDS6q.js.map → docker-CCXdbREk.js.map} +1 -1
  47. package/dist/{docker-DNmMPOBb.js → docker-DC69dKxB.js} +1 -1
  48. package/dist/{doctor-D2MbNO8L.js → doctor-CqttrZcs.js} +57 -22
  49. package/dist/doctor-CqttrZcs.js.map +1 -0
  50. package/dist/{egress-2-qzPvGi.js → egress-BfK_O9ce.js} +435 -30
  51. package/dist/egress-BfK_O9ce.js.map +1 -0
  52. package/dist/env-BQqj93gu.js +21 -0
  53. package/dist/env-BQqj93gu.js.map +1 -0
  54. package/dist/{environment-Cca6a4wB.js → environment-BBz1Yes9.js} +224 -10
  55. package/dist/environment-BBz1Yes9.js.map +1 -0
  56. package/dist/{evaluate-DKIl54Hb.js → evaluate-CXQ1o-pd.js} +539 -559
  57. package/dist/evaluate-CXQ1o-pd.js.map +1 -0
  58. package/dist/{evaluate-DMyaGQEj.d.ts → evaluate-yjZKUexW.d.ts} +2 -2
  59. package/dist/facts-DtENlf9s.js +898 -0
  60. package/dist/facts-DtENlf9s.js.map +1 -0
  61. package/dist/{files-BpUYBwGu.js → files-B-eUpCZ1.js} +30 -7
  62. package/dist/files-B-eUpCZ1.js.map +1 -0
  63. package/dist/files-BsQbYz2i.js +65 -0
  64. package/dist/files-BsQbYz2i.js.map +1 -0
  65. package/dist/{files-BXHZFWmx.js → files-COHQLEHE.js} +6 -17
  66. package/dist/files-COHQLEHE.js.map +1 -0
  67. package/dist/files-DqCBW7i8.js +1 -0
  68. package/dist/files-Ha-jsQXf.js +1 -0
  69. package/dist/generate-Cs2TMH_k.js +1647 -0
  70. package/dist/generate-Cs2TMH_k.js.map +1 -0
  71. package/dist/{git-Crl3b87o.js → git-DhykwgKF.js} +2 -2
  72. package/dist/{git-Crl3b87o.js.map → git-DhykwgKF.js.map} +1 -1
  73. package/dist/{harness-CEuntrla.js → harness-BAjw1fcr.js} +2 -2
  74. package/dist/{harness-CEuntrla.js.map → harness-BAjw1fcr.js.map} +1 -1
  75. package/dist/harness.d.ts +1 -1
  76. package/dist/harness.js +1 -1
  77. package/dist/{header-DHQv_ZrF.js → header-kSmWatcO.js} +10 -3
  78. package/dist/{header-DHQv_ZrF.js.map → header-kSmWatcO.js.map} +1 -1
  79. package/dist/{images-Bi3aGxb9.js → images-BmJRuTpm.js} +61 -13
  80. package/dist/images-BmJRuTpm.js.map +1 -0
  81. package/dist/index.d.ts +3 -3
  82. package/dist/index.js +4 -4
  83. package/dist/init-Bwc9byQr.js +543 -0
  84. package/dist/init-Bwc9byQr.js.map +1 -0
  85. package/dist/init-D7Y1ny1z.js +1 -0
  86. package/dist/insights-B2Xmhz9o.js +64 -0
  87. package/dist/insights-B2Xmhz9o.js.map +1 -0
  88. package/dist/{invocations-BYDPe3fV.js → invocations-CQTbP092.js} +3 -3
  89. package/dist/{invocations-BYDPe3fV.js.map → invocations-CQTbP092.js.map} +1 -1
  90. package/dist/{judge-DW_GDOmB.js → judge-Dt6KW6_O.js} +5 -3
  91. package/dist/judge-Dt6KW6_O.js.map +1 -0
  92. package/dist/judge.d.ts +7 -6
  93. package/dist/judge.js +8 -7
  94. package/dist/judge.js.map +1 -1
  95. package/dist/{live-jlfszAbb.js → live-DYd2QEyR.js} +2 -2
  96. package/dist/{live-jlfszAbb.js.map → live-DYd2QEyR.js.map} +1 -1
  97. package/dist/{model-D0IcOQao.js → model-B-mel-Gv.js} +43 -18
  98. package/dist/model-B-mel-Gv.js.map +1 -0
  99. package/dist/model-BGKYVpoj.js +1 -0
  100. package/dist/{model-DaVCY3rb.js → model-C7tSwT7f.js} +2 -2
  101. package/dist/{model-DaVCY3rb.js.map → model-C7tSwT7f.js.map} +1 -1
  102. package/dist/{model-DaX4bNLZ.js → model-CWlAqmbU.js} +135 -40
  103. package/dist/model-CWlAqmbU.js.map +1 -0
  104. package/dist/model-DHY-dfoO.js +1 -0
  105. package/dist/{node-B3ydHo6t.js → node-D0mtjRAO.js} +3 -3
  106. package/dist/{node-B3ydHo6t.js.map → node-D0mtjRAO.js.map} +1 -1
  107. package/dist/{options-C0d0AzeR.js → options-CPUW97_7.js} +7 -9
  108. package/dist/options-CPUW97_7.js.map +1 -0
  109. package/dist/{pairs-CnInRu-G.js → pairs-DP6XOJby.js} +2 -2
  110. package/dist/{pairs-CnInRu-G.js.map → pairs-DP6XOJby.js.map} +1 -1
  111. package/dist/{patch-B1bnfhN-.js → patch-D4oluWzH.js} +2 -2
  112. package/dist/{patch-B1bnfhN-.js.map → patch-D4oluWzH.js.map} +1 -1
  113. package/dist/{plan-DgQxp9yy.js → plan-OkwUcJQ9.js} +21 -8
  114. package/dist/plan-OkwUcJQ9.js.map +1 -0
  115. package/dist/plugins-CUWMnSNb.js +654 -0
  116. package/dist/plugins-CUWMnSNb.js.map +1 -0
  117. package/dist/{preflight-DlQvbySb.js → preflight-B6pY89bF.js} +1 -1
  118. package/dist/{preflight-BRzD30L5.js → preflight-Bjm7_ylE.js} +14 -10
  119. package/dist/preflight-Bjm7_ylE.js.map +1 -0
  120. package/dist/{prepare-B_y-AFMv.js → prepare-CQmK3SBn.js} +70 -23
  121. package/dist/prepare-CQmK3SBn.js.map +1 -0
  122. package/dist/prepare-DbdgtZKe.js +2 -0
  123. package/dist/{provenance-DQ0AXn6c.js → provenance-B3Y17oCC.js} +3 -3
  124. package/dist/{provenance-DQ0AXn6c.js.map → provenance-B3Y17oCC.js.map} +1 -1
  125. package/dist/providers-CXN2RFz-.js +1 -0
  126. package/dist/{providers-DoTq1jHW.js → providers-eoniqK6w.js} +24 -10
  127. package/dist/providers-eoniqK6w.js.map +1 -0
  128. package/dist/{query-BO-ux7RB.js → query-CLRZmWBT.js} +3 -3
  129. package/dist/{query-BO-ux7RB.js.map → query-CLRZmWBT.js.map} +1 -1
  130. package/dist/query-CmBDYt0_.js +1 -0
  131. package/dist/{questions-C2dym2ce.js → questions-1XOulevV.js} +6 -6
  132. package/dist/{questions-C2dym2ce.js.map → questions-1XOulevV.js.map} +1 -1
  133. package/dist/{record-BKmMvZ6O.js → record-kk9M1hj-.js} +8 -4
  134. package/dist/record-kk9M1hj-.js.map +1 -0
  135. package/dist/remarks-1521zwfW.js +38 -0
  136. package/dist/remarks-1521zwfW.js.map +1 -0
  137. package/dist/remarks-BhAV1H4V.js +1 -0
  138. package/dist/remarks-DlJCqWRs.js +278 -0
  139. package/dist/remarks-DlJCqWRs.js.map +1 -0
  140. package/dist/{remote-CPPW86Q9.js → remote-cE2VWfkJ.js} +3 -3
  141. package/dist/{remote-CPPW86Q9.js.map → remote-cE2VWfkJ.js.map} +1 -1
  142. package/dist/resolve-C4zeccCH.js +724 -0
  143. package/dist/resolve-C4zeccCH.js.map +1 -0
  144. package/dist/resolve-D30yZYmB.js +1 -0
  145. package/dist/{results-BE2f-1XS.js → results-Drtt0uFl.js} +33 -8
  146. package/dist/results-Drtt0uFl.js.map +1 -0
  147. package/dist/{resume-Ca1c8vix.js → resume-BEFazUfy.js} +4 -4
  148. package/dist/{resume-Ca1c8vix.js.map → resume-BEFazUfy.js.map} +1 -1
  149. package/dist/rules-BFzQqPIm.js +317 -0
  150. package/dist/rules-BFzQqPIm.js.map +1 -0
  151. package/dist/run-BeMy92Us.js +88 -0
  152. package/dist/run-BeMy92Us.js.map +1 -0
  153. package/dist/{sandbox-DLrsvu7U.js → sandbox-CQaJj7n9.js} +2 -2
  154. package/dist/{sandbox-DLrsvu7U.js.map → sandbox-CQaJj7n9.js.map} +1 -1
  155. package/dist/sandbox.d.ts +1 -1
  156. package/dist/sandbox.js +1 -1
  157. package/dist/server-V4-2w0l8.js +1 -0
  158. package/dist/{server-TUY5xA_A.js → server-xK0les4f.js} +8 -8
  159. package/dist/{server-TUY5xA_A.js.map → server-xK0les4f.js.map} +1 -1
  160. package/dist/source-BDow_oW8.js +1 -0
  161. package/dist/{source-DJGS0a0u.js → source-Q1hEKbCs.js} +2 -2
  162. package/dist/{source-DJGS0a0u.js.map → source-Q1hEKbCs.js.map} +1 -1
  163. package/dist/src-B9L9yGKI.js +1 -0
  164. package/dist/{src-CLoOMVWI.js → src-Bcah6ZkT.js} +1 -1
  165. package/dist/{src-DvCg0NBs.js → src-BhmaorOU.js} +28 -6
  166. package/dist/{src-DvCg0NBs.js.map → src-BhmaorOU.js.map} +1 -1
  167. package/dist/{src-CF17Ug08.js → src-C0CeKiLU.js} +19 -4
  168. package/dist/{src-CF17Ug08.js.map → src-C0CeKiLU.js.map} +1 -1
  169. package/dist/src-C0xowZ3C.js +2 -0
  170. package/dist/src-CHIfIKUu.js +2 -0
  171. package/dist/src-DLtyz4w5.js +2 -0
  172. package/dist/src-DPIjmReZ.js +2 -0
  173. package/dist/{src-BxfCKA3_.js → src-DXNh5mTr.js} +1 -1
  174. package/dist/{src-FGXhkEkH.js → src-DiLMkIr9.js} +142 -13
  175. package/dist/src-DiLMkIr9.js.map +1 -0
  176. package/dist/{src-ftu5wPSt.js → src-LekQrr_S.js} +209 -29
  177. package/dist/src-LekQrr_S.js.map +1 -0
  178. package/dist/src-bCnsA6Vp.js +2 -0
  179. package/dist/{src-u8_ixn_F.js → src-cbCb-MPy.js} +20 -4
  180. package/dist/src-cbCb-MPy.js.map +1 -0
  181. package/dist/{src-DvK0EIZx.js → src-qGoFkuJF.js} +55 -6
  182. package/dist/{src-DvK0EIZx.js.map → src-qGoFkuJF.js.map} +1 -1
  183. package/dist/{src-DSYYPEOj.js → src-ynBVosfX.js} +1 -1
  184. package/dist/state-BQR_BCm4.js +1 -0
  185. package/dist/{state-DfpHox6b.js → state-BmZ8QVZ8.js} +12 -12
  186. package/dist/{state-DfpHox6b.js.map → state-BmZ8QVZ8.js.map} +1 -1
  187. package/dist/studio-app/assets/{index-CBkhNAv8.js → index-CnYJijyI.js} +9 -9
  188. package/dist/studio-app/index.html +1 -1
  189. package/dist/suite-BaHPmAGy.js +1 -0
  190. package/dist/{suite-Cw_7G2RM.js → suite-C8sw2pox.js} +80 -28
  191. package/dist/suite-C8sw2pox.js.map +1 -0
  192. package/dist/{summary-BUKfU-9l.js → summary-0oQNGskv.js} +273 -47
  193. package/dist/summary-0oQNGskv.js.map +1 -0
  194. package/dist/testing.d.ts +2 -2
  195. package/dist/testing.js +2 -2
  196. package/dist/{text-gEcKjAyp.js → text-CrVy5ioL.js} +18 -2
  197. package/dist/text-CrVy5ioL.js.map +1 -0
  198. package/dist/{transcript-BNNANU8A.js → transcript-BTxJpW4R.js} +2 -2
  199. package/dist/{transcript-BNNANU8A.js.map → transcript-BTxJpW4R.js.map} +1 -1
  200. package/dist/types-C5vI3g1C.js.map +1 -1
  201. package/dist/{types-BYdlwMwo.d.ts → types-GraZtfHN.d.ts} +848 -34
  202. package/dist/usage-BDo2q_yu.js +1 -0
  203. package/dist/{command-Bj39y-Wm.js → validate-BdoXUuL_.js} +15 -372
  204. package/dist/validate-BdoXUuL_.js.map +1 -0
  205. package/dist/view/index.d.ts +20 -257
  206. package/dist/view/index.js +7 -6
  207. package/dist/{views-B8w2J-gD.js → views-BoUoX4_A.js} +8 -98
  208. package/dist/views-BoUoX4_A.js.map +1 -0
  209. package/dist/views-noVQNCUP.js +2 -0
  210. package/dist/{worker-entry-DNnveLqx.js → worker-entry-D0-GErmU.js} +2 -2
  211. package/dist/{worker-entry-DNnveLqx.js.map → worker-entry-D0-GErmU.js.map} +1 -1
  212. package/dist/{workspace-C_X0tdv6.js → workspace-B90YDU_a.js} +1 -1
  213. package/dist/{workspace-C4RA3srV.js → workspace-tjZFkjxC.js} +4 -4
  214. package/dist/{workspace-C4RA3srV.js.map → workspace-tjZFkjxC.js.map} +1 -1
  215. package/package.json +3 -1
  216. package/skills/eval-rubric/SKILL.md +130 -0
  217. package/dist/agent-D483ru7D.js +0 -334
  218. package/dist/agent-D483ru7D.js.map +0 -1
  219. package/dist/assemble-D5KGrwnJ.js +0 -1
  220. package/dist/assemble-D9GWr-HS.js.map +0 -1
  221. package/dist/capture-CYGLpWxR.js +0 -1
  222. package/dist/cli-ClpPT8kn.js.map +0 -1
  223. package/dist/cli-spec-qmEnQ25_.js.map +0 -1
  224. package/dist/command-Bj39y-Wm.js.map +0 -1
  225. package/dist/command-C-cVjlny.js +0 -1
  226. package/dist/command-DbAe1Rzb.js.map +0 -1
  227. package/dist/command-TgbzPizb.js.map +0 -1
  228. package/dist/commands-YUwlyTbr.js +0 -228
  229. package/dist/commands-YUwlyTbr.js.map +0 -1
  230. package/dist/config-DrVSEVN0.js.map +0 -1
  231. package/dist/context-C1mxXh80.js.map +0 -1
  232. package/dist/db-CKg5NtiW.js +0 -2
  233. package/dist/db-DfhipHEF.js +0 -1416
  234. package/dist/db-DfhipHEF.js.map +0 -1
  235. package/dist/doctor-D2MbNO8L.js.map +0 -1
  236. package/dist/egress-2-qzPvGi.js.map +0 -1
  237. package/dist/environment-Cca6a4wB.js.map +0 -1
  238. package/dist/evaluate-DKIl54Hb.js.map +0 -1
  239. package/dist/files-BXHZFWmx.js.map +0 -1
  240. package/dist/files-BpUYBwGu.js.map +0 -1
  241. package/dist/files-Bw8lWEjg.js +0 -1
  242. package/dist/files-D6J0iSdx.js +0 -1
  243. package/dist/images-Bi3aGxb9.js.map +0 -1
  244. package/dist/init-Cl3f3NBT.js +0 -360
  245. package/dist/init-Cl3f3NBT.js.map +0 -1
  246. package/dist/init-fhOXED8F.js +0 -1
  247. package/dist/judge-DW_GDOmB.js.map +0 -1
  248. package/dist/model-CXhrziBe.js +0 -1
  249. package/dist/model-D0IcOQao.js.map +0 -1
  250. package/dist/model-DaX4bNLZ.js.map +0 -1
  251. package/dist/model-_bxNrk2h.js +0 -1
  252. package/dist/options-C0d0AzeR.js.map +0 -1
  253. package/dist/plan-DgQxp9yy.js.map +0 -1
  254. package/dist/preflight-BRzD30L5.js.map +0 -1
  255. package/dist/prepare-B_y-AFMv.js.map +0 -1
  256. package/dist/prepare-DCKTLHN3.js +0 -2
  257. package/dist/providers-B9yTdIqF.js +0 -1
  258. package/dist/providers-DoTq1jHW.js.map +0 -1
  259. package/dist/query-CRQfsw0e.js +0 -1
  260. package/dist/record-BKmMvZ6O.js.map +0 -1
  261. package/dist/results-BE2f-1XS.js.map +0 -1
  262. package/dist/server-Dp8eOeK5.js +0 -1
  263. package/dist/source-DdbLGR1M.js +0 -1
  264. package/dist/src-CcrQbpG8.js +0 -2
  265. package/dist/src-DCFtJRp0.js +0 -2
  266. package/dist/src-DYO3DdnQ.js +0 -1
  267. package/dist/src-FGXhkEkH.js.map +0 -1
  268. package/dist/src-WD-zgQYZ.js +0 -2
  269. package/dist/src-_oI9AePb.js +0 -2
  270. package/dist/src-ftu5wPSt.js.map +0 -1
  271. package/dist/src-qsKCqv7a.js +0 -2
  272. package/dist/src-u8_ixn_F.js.map +0 -1
  273. package/dist/state-DpAxYyED.js +0 -1
  274. package/dist/suite-Cw_7G2RM.js.map +0 -1
  275. package/dist/suite-DamAEnNF.js +0 -1
  276. package/dist/summary-BUKfU-9l.js.map +0 -1
  277. package/dist/summary-Baa4rTHS.js +0 -192
  278. package/dist/summary-Baa4rTHS.js.map +0 -1
  279. package/dist/text-gEcKjAyp.js.map +0 -1
  280. package/dist/tools-DLHgetpx.js +0 -249
  281. package/dist/tools-DLHgetpx.js.map +0 -1
  282. package/dist/views-B8w2J-gD.js.map +0 -1
  283. package/dist/views-DblnI3kA.js +0 -2
@@ -1,8 +1,9 @@
1
1
  import { n as UsageError } from "./errors-B6BSMs03.js";
2
- import { w as plannedSecrets } from "./environment-Cca6a4wB.js";
2
+ import { w as plannedSecrets } from "./environment-BBz1Yes9.js";
3
+ import { F as PACKAGE_HOSTS, N as DOCKER_EGRESS, P as HARNESS_HOSTS, lt as run, ut as shellQuote } from "./src-LekQrr_S.js";
4
+ import { D as pluginServerName, a as PLUGIN_PARTS, n as PLUGIN_DIR, r as PLUGIN_MANIFEST, t as PART_PATHS, y as localPluginServers } from "./plugins-CUWMnSNb.js";
3
5
  import { a as providerServedModel, i as providerModelResponses, n as providerEndpoints, r as providerHosts, s as resolveOpenCodeProvider } from "./opencode-providers-J9colP0-.js";
4
6
  import { t as InfraError } from "./types-C5vI3g1C.js";
5
- import { D as HARNESS_HOSTS, E as DOCKER_EGRESS, O as PACKAGE_HOSTS, nt as shellQuote, tt as run } from "./src-ftu5wPSt.js";
6
7
  import { existsSync } from "node:fs";
7
8
  import { tmpdir } from "node:os";
8
9
  import { dirname, join, win32 } from "node:path";
@@ -164,8 +165,20 @@ function opencodeMcpServers(servers) {
164
165
  }];
165
166
  }));
166
167
  }
168
+ /**
169
+ * The key Goose keeps an extension by (its `name_to_key`): whitespace dropped, anything but ASCII
170
+ * letters, digits, `_` and `-` made `_`, lower-cased. Of two extensions with one key it keeps one.
171
+ */
172
+ const gooseKey = (name) => name.replace(/\s/g, "").replace(/[^A-Za-z0-9_-]/g, "_").toLowerCase();
167
173
  /** Goose's extension shape (its `config.yaml`); it has no SSE transport. */
168
174
  function gooseMcpServers(servers) {
175
+ const byKey = /* @__PURE__ */ new Map();
176
+ for (const name of Object.keys(servers)) {
177
+ const key = gooseKey(name);
178
+ const other = byKey.get(key);
179
+ if (other !== void 0) throw new InfraError(`Goose keys the ${other} and ${name} MCP servers both as ${key}, and keeps only one: rename one`);
180
+ byKey.set(key, name);
181
+ }
169
182
  return Object.fromEntries(Object.entries(servers).map(([name, s]) => {
170
183
  if (s.transport === "sse") throw new InfraError(`Goose has no SSE MCP transport, so it can't use the ${name} server (mcp.sse): use mcp.http or mcp.stdio`);
171
184
  return s.transport === "stdio" ? [name, {
@@ -183,11 +196,18 @@ function gooseMcpServers(servers) {
183
196
  /**
184
197
  * pi's `mcp.json` shape, which the adapter escapes and sets `"exposure": "direct"` on. pi
185
198
  * skips a server whose name isn't letters, digits, `_` and `-`, so the plan refuses it instead.
199
+ * A plugin's server, `<plugin>:<server>`, is named `<plugin>_<server>`, so its tools are
200
+ * `mcp__<plugin>_<server>__<tool>`.
186
201
  */
187
202
  function piMcpServers(servers) {
188
- return Object.fromEntries(Object.entries(servers).map(([name, s]) => {
189
- if (!/^[A-Za-z0-9_-]+$/.test(name)) throw new InfraError(`pi takes MCP server names of letters, digits, "_" and "-" only, so it can't use the ${name} server: rename it`);
190
- if (s.transport === "sse") throw new InfraError(`pi has no SSE MCP transport, so it can't use the ${name} server (mcp.sse): use mcp.http or mcp.stdio`);
203
+ const named = /* @__PURE__ */ new Map();
204
+ return Object.fromEntries(Object.entries(servers).map(([key, s]) => {
205
+ const name = /^[a-z0-9-]+:[^:]+$/.test(key) ? key.replace(":", "_") : key;
206
+ if (!/^[A-Za-z0-9_-]+$/.test(name)) throw new InfraError(`pi takes MCP server names of letters, digits, "_" and "-" only, so it can't use the ${key} server: rename it`);
207
+ const other = named.get(name);
208
+ if (other) throw new InfraError(`pi names the ${key} MCP server ${name}, as it does the ${other} server, and keeps only one: rename one`);
209
+ named.set(name, key);
210
+ if (s.transport === "sse") throw new InfraError(`pi has no SSE MCP transport, so it can't use the ${key} server (mcp.sse): use mcp.http or mcp.stdio`);
191
211
  return s.transport === "stdio" ? [name, {
192
212
  command: s.command,
193
213
  args: s.args,
@@ -270,58 +290,236 @@ function cursorMcpServers(servers) {
270
290
  headers: s.headers
271
291
  }]));
272
292
  }
293
+ /** Claude Code's hook events as Cursor names them, as the Cursor SDK converts Claude Code's own. */
294
+ const CURSOR_HOOK_EVENTS = {
295
+ SessionStart: "sessionStart",
296
+ SessionEnd: "sessionEnd",
297
+ UserPromptSubmit: "beforeSubmitPrompt",
298
+ PreToolUse: "preToolUse",
299
+ PostToolUse: "postToolUse",
300
+ SubagentStop: "subagentStop",
301
+ PreCompact: "preCompact",
302
+ Stop: "stop"
303
+ };
304
+ /** Claude Code's tool names as Cursor's hooks match them; null for one Cursor has no tool for. */
305
+ const CURSOR_HOOK_TOOLS = {
306
+ Bash: "Shell",
307
+ Read: "Read",
308
+ Write: "Write",
309
+ Edit: "Write",
310
+ Glob: null,
311
+ Grep: "Grep",
312
+ WebFetch: "WebFetch",
313
+ WebSearch: "WebSearch",
314
+ Task: "Task"
315
+ };
316
+ /**
317
+ * A Claude Code hook group's tool matcher as Cursor's, on the tool events only: each name mapped,
318
+ * `mcp__<server>__<tool>` as `MCP:<tool>`; null when it names only tools Cursor lacks.
319
+ */
320
+ function cursorHookMatcher(event, matcher) {
321
+ if (event !== "PreToolUse" && event !== "PostToolUse") return void 0;
322
+ if (!matcher || matcher === "*") return void 0;
323
+ const out = [];
324
+ for (const raw of matcher.split("|")) {
325
+ const name = raw.trim();
326
+ const parts = name.split("__");
327
+ const tool = name.startsWith("mcp__") && parts.length >= 3 ? `MCP:${parts.slice(2).join("__")}` : CURSOR_HOOK_TOOLS[name] === void 0 ? name : CURSOR_HOOK_TOOLS[name];
328
+ if (tool && !out.includes(tool)) out.push(tool);
329
+ }
330
+ return out.length ? out.join("|") : null;
331
+ }
332
+ /** Where Cursor reads what reeval unpacks from a plugin, in the workspace (settingSources `project`). */
333
+ const CURSOR_PLUGIN_UNPACK = {
334
+ rules: ".cursor/rules",
335
+ agents: ".cursor/agents",
336
+ commands: ".cursor/commands",
337
+ hooks: {
338
+ file: ".cursor/hooks.json",
339
+ events: CURSOR_HOOK_EVENTS,
340
+ matcher: cursorHookMatcher
341
+ }
342
+ };
343
+ /**
344
+ * A plugin subagent's or command's frontmatter as OpenCode 2 takes it: the description, and a
345
+ * subagent's `mode`. OpenCode skips a file whose frontmatter its schema refuses, without saying,
346
+ * and Claude Code's `tools: Read, Grep`, `model: sonnet` and `allowed-tools` are such keys.
347
+ */
348
+ function opencodeFrontmatter(part, front) {
349
+ const d = front.description;
350
+ const description = typeof d === "string" || typeof d === "number" || typeof d === "boolean" ? String(d) : void 0;
351
+ return {
352
+ ...description ? { description } : {},
353
+ ...part === "agents" ? { mode: "subagent" } : {}
354
+ };
355
+ }
356
+ /** Where OpenCode reads plugin subagents and commands, in the workspace's config directory. */
357
+ const OPENCODE_PLUGIN_UNPACK = {
358
+ agents: ".opencode/agents",
359
+ commands: ".opencode/commands",
360
+ frontmatter: opencodeFrontmatter
361
+ };
362
+ /**
363
+ * Where pi reads plugin commands, as prompt templates (`/<name>`), in the workspace, which its
364
+ * `--approve` trusts. Its frontmatter takes `description` and `argument-hint`, and ignores the
365
+ * rest of Claude Code's.
366
+ */
367
+ const PI_PLUGIN_UNPACK = { commands: ".pi/prompts" };
368
+ /**
369
+ * What Claude Code's plugin format bundles, which Grok Build reads too: every part but rules,
370
+ * which neither loads from a plugin.
371
+ */
372
+ const CLAUDE_FORMAT_PARTS = PLUGIN_PARTS.filter((p) => p !== "rules");
373
+ /** The marketplace Claude Code's settings name for the session's plugins. */
374
+ const CLAUDE_PLUGIN_MARKETPLACE = "reeval";
375
+ /**
376
+ * Claude Code's settings for the session's plugins: a `directory` marketplace at the directory
377
+ * they were copied to, listing each, and each enabled as `<plugin>@reeval`. Claude Code installs
378
+ * and loads them as it starts, since the bridge leaves every settings source on.
379
+ */
380
+ function claudePluginFiles(plugins) {
381
+ const [first] = plugins;
382
+ if (!first) return [];
383
+ const json = (value) => `${JSON.stringify(value, null, 2)}\n`;
384
+ const marketplace = {
385
+ name: CLAUDE_PLUGIN_MARKETPLACE,
386
+ owner: { name: "reeval" },
387
+ plugins: plugins.map((p) => ({
388
+ name: p.name,
389
+ source: `./${p.name}`
390
+ }))
391
+ };
392
+ const settings = {
393
+ extraKnownMarketplaces: { [CLAUDE_PLUGIN_MARKETPLACE]: { source: {
394
+ source: "directory",
395
+ path: first.dir.slice(0, first.dir.lastIndexOf("/"))
396
+ } } },
397
+ enabledPlugins: Object.fromEntries(plugins.map((p) => [`${p.name}@${CLAUDE_PLUGIN_MARKETPLACE}`, true]))
398
+ };
399
+ return [{
400
+ path: `${PLUGIN_DIR}/.claude-plugin/marketplace.json`,
401
+ content: json(marketplace)
402
+ }, {
403
+ path: "~/.claude/settings.json",
404
+ content: json(settings),
405
+ merge: true
406
+ }];
407
+ }
408
+ const isObject = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
409
+ /**
410
+ * Writes the layout's plugin files into the sandbox and returns their paths. A `merge` file's keys
411
+ * go into the JSON object already at its path (an object-valued key merged one level down), so
412
+ * settings an environment's `files` wrote there stay.
413
+ */
414
+ async function writePluginFiles(sandbox, layout, plugins) {
415
+ const written = [];
416
+ for (const f of layout.pluginFiles?.(plugins) ?? []) {
417
+ const existing = f.merge ? await sandbox.readFile(f.path) : null;
418
+ let content = f.content;
419
+ if (existing?.trim()) {
420
+ let base;
421
+ try {
422
+ base = JSON.parse(existing);
423
+ } catch {}
424
+ if (!isObject(base)) throw new InfraError(`${f.path} isn't a JSON object, so reeval can't enable the session's plugins in it: write it as one in files, or leave it out`);
425
+ const ours = JSON.parse(f.content);
426
+ const merged = { ...base };
427
+ for (const [k, v] of Object.entries(ours)) {
428
+ const was = base[k];
429
+ merged[k] = isObject(v) && isObject(was) ? {
430
+ ...was,
431
+ ...v
432
+ } : v;
433
+ }
434
+ content = `${JSON.stringify(merged, null, 2)}\n`;
435
+ }
436
+ await sandbox.writeFile(f.path, content);
437
+ written.push(f.path);
438
+ }
439
+ return written;
440
+ }
441
+ /**
442
+ * The MCP servers the agent is given: all of them, less the plugins' own where it takes plugin
443
+ * items namespaced, since it loads those from the plugin and would otherwise start each twice.
444
+ */
445
+ function agentMcp(layout, mcp, plugins) {
446
+ if (layout.pluginPlacement !== "namespaced") return mcp;
447
+ const own = new Set(plugins.flatMap((p) => p.servers));
448
+ return Object.fromEntries(Object.entries(mcp).filter(([name]) => !own.has(name)));
449
+ }
273
450
  /** Where each agent with an image reads rules and skills. */
274
451
  const LAYOUTS = {
275
452
  cursor: {
276
453
  rulesFile: "AGENTS.md",
277
454
  workspaceSkillDir: ".cursor/skills",
278
- harnessSkillDir: ".agents/skills"
455
+ harnessSkillDir: ".agents/skills",
456
+ pluginPlacement: "flat",
457
+ pluginUnpack: CURSOR_PLUGIN_UNPACK,
458
+ pluginHookEvents: Object.keys(CURSOR_HOOK_EVENTS)
279
459
  },
280
460
  "claude-code": {
281
461
  rulesFile: "CLAUDE.md",
282
462
  workspaceSkillDir: ".claude/skills",
283
- harnessSkillDir: ".claude/skills"
463
+ harnessSkillDir: ".claude/skills",
464
+ pluginPlacement: "namespaced",
465
+ pluginFiles: claudePluginFiles
284
466
  },
285
467
  antigravity: {
286
468
  rulesFile: "AGENTS.md",
287
469
  workspaceSkillDir: ".agents/skills",
288
- harnessSkillDir: ".gemini/config/skills"
470
+ harnessSkillDir: ".gemini/config/skills",
471
+ pluginPlacement: "namespaced",
472
+ pluginHookEvents: [
473
+ "SessionStart",
474
+ "PreToolUse",
475
+ "PostToolUse",
476
+ "Stop"
477
+ ]
289
478
  },
290
479
  opencode: {
291
480
  rulesFile: "AGENTS.md",
292
481
  workspaceSkillDir: ".opencode/skills",
293
- harnessSkillDir: ".config/opencode/skills"
482
+ harnessSkillDir: ".config/opencode/skills",
483
+ pluginPlacement: "flat",
484
+ pluginUnpack: OPENCODE_PLUGIN_UNPACK
294
485
  },
295
486
  goose: {
296
487
  rulesFile: "AGENTS.md",
297
488
  workspaceSkillDir: ".goose/skills",
298
- harnessSkillDir: ".ai-sdk-harness/.harness-bootstrap/goose/implementation/home/.config/goose/skills"
489
+ harnessSkillDir: ".ai-sdk-harness/.harness-bootstrap/goose/implementation/home/.config/goose/skills",
490
+ pluginPlacement: "flat"
299
491
  },
300
492
  pi: {
301
493
  rulesFile: "AGENTS.md",
302
494
  workspaceSkillDir: ".pi/skills",
303
- harnessSkillDir: ".pi/agent/skills"
495
+ harnessSkillDir: ".pi/agent/skills",
496
+ pluginPlacement: "flat",
497
+ pluginUnpack: PI_PLUGIN_UNPACK
304
498
  },
305
499
  codex: {
306
500
  rulesFile: "AGENTS.md",
307
501
  workspaceSkillDir: ".agents/skills",
308
- harnessSkillDir: ".agents/skills"
502
+ harnessSkillDir: ".agents/skills",
503
+ pluginPlacement: "namespaced"
309
504
  },
310
505
  fx: {
311
506
  rulesFile: "AGENTS.md",
312
507
  workspaceSkillDir: ".fx/skills",
313
- harnessSkillDir: ".ai-sdk-harness/.harness-bootstrap/fx/implementation/home/.fx/skills"
508
+ harnessSkillDir: ".ai-sdk-harness/.harness-bootstrap/fx/implementation/home/.fx/skills",
509
+ pluginPlacement: "flat"
314
510
  },
315
511
  "grok-build": {
316
512
  rulesFile: "AGENTS.md",
317
513
  workspaceSkillDir: ".grok/skills",
318
- harnessSkillDir: ".ai-sdk-harness/.harness-bootstrap/grok-build/implementation/home/.grok/skills"
514
+ harnessSkillDir: ".ai-sdk-harness/.harness-bootstrap/grok-build/implementation/home/.grok/skills",
515
+ pluginPlacement: "namespaced"
319
516
  }
320
517
  };
321
518
  /** Every real agent reeval can drive, by harness kind. */
322
519
  const AGENTS = {
323
520
  cursor: {
324
521
  ...LAYOUTS.cursor,
522
+ pluginParts: PLUGIN_PARTS,
325
523
  name: "Cursor",
326
524
  factory: "cursor",
327
525
  credential: "CURSOR_API_KEY",
@@ -333,7 +531,7 @@ const AGENTS = {
333
531
  },
334
532
  unreported: cursorUnreported,
335
533
  mcpServers: cursorMcpServers,
336
- adapter: async ({ auth, mcpServers, descriptor }) => (await import("./src-WD-zgQYZ.js")).createCursorSdk({
534
+ adapter: async ({ auth, mcpServers, descriptor }) => (await import("./src-C0xowZ3C.js")).createCursorSdk({
337
535
  auth,
338
536
  ...mcpServers ? { mcpServers } : {},
339
537
  ...descriptor.kind === "cursor" && descriptor.params ? { modelParams: descriptor.params } : {},
@@ -343,6 +541,7 @@ const AGENTS = {
343
541
  },
344
542
  "claude-code": {
345
543
  ...LAYOUTS["claude-code"],
544
+ pluginParts: CLAUDE_FORMAT_PARTS,
346
545
  name: "Claude Code",
347
546
  factory: "claudeCode",
348
547
  credential: "ANTHROPIC_API_KEY",
@@ -369,7 +568,7 @@ const AGENTS = {
369
568
  }
370
569
  ],
371
570
  mcpServers: claudeMcpServers,
372
- adapter: async ({ auth, mcpServers, descriptor }) => (await import("./dist-CuY4ehEk.js")).createClaudeCode({
571
+ adapter: async ({ auth, mcpServers, descriptor }) => (await import("./dist-CMjp3qqF.js")).createClaudeCode({
373
572
  auth,
374
573
  ...mcpServers ? { mcpServers } : {},
375
574
  ...descriptor.kind === "claude-code" && descriptor.effort ? { effort: descriptor.effort } : {},
@@ -381,6 +580,13 @@ const AGENTS = {
381
580
  },
382
581
  antigravity: {
383
582
  ...LAYOUTS.antigravity,
583
+ pluginParts: PLUGIN_PARTS,
584
+ pluginManifestsFirst: [
585
+ "plugin.json",
586
+ ".antigravity-plugin/plugin.json",
587
+ ".gemini-plugin/plugin.json",
588
+ "gemini-extension.json"
589
+ ],
384
590
  name: "Antigravity",
385
591
  factory: "antigravity",
386
592
  credential: "GEMINI_API_KEY",
@@ -391,15 +597,25 @@ const AGENTS = {
391
597
  },
392
598
  servedModel: geminiServedModel,
393
599
  mcpServers: antigravityMcpServers,
394
- adapter: async ({ auth, mcpServers, descriptor }) => (await import("./src-_oI9AePb.js")).createAntigravity({
600
+ adapter: async ({ auth, mcpServers, descriptor, plugins }) => (await import("./src-bCnsA6Vp.js")).createAntigravity({
395
601
  auth,
396
602
  ...mcpServers ? { mcpServers } : {},
603
+ ...plugins.length ? { plugins: plugins.map(({ name, dir }) => ({
604
+ name,
605
+ dir
606
+ })) } : {},
397
607
  ...descriptor.kind === "antigravity" && descriptor.effort ? { effort: descriptor.effort } : {},
398
608
  requireCredentialBrokering: true
399
609
  })
400
610
  },
401
611
  opencode: {
402
612
  ...LAYOUTS.opencode,
613
+ pluginParts: [
614
+ "skills",
615
+ "agents",
616
+ "commands",
617
+ "mcp"
618
+ ],
403
619
  name: "OpenCode",
404
620
  factory: "opencode",
405
621
  credential: "GOOGLE_GENERATIVE_AI_API_KEY",
@@ -407,7 +623,7 @@ const AGENTS = {
407
623
  servedModel: geminiServedModel,
408
624
  forModel: opencodeForModel,
409
625
  mcpServers: opencodeMcpServers,
410
- adapter: async ({ auth, mcpServers, descriptor }) => (await import("./src-CLoOMVWI.js")).createOpenCode({
626
+ adapter: async ({ auth, mcpServers, descriptor }) => (await import("./src-Bcah6ZkT.js")).createOpenCode({
411
627
  auth,
412
628
  model: descriptor.model,
413
629
  vars: opencodeVars(descriptor.model),
@@ -418,13 +634,18 @@ const AGENTS = {
418
634
  },
419
635
  goose: {
420
636
  ...LAYOUTS.goose,
637
+ pluginParts: ["skills", "mcp"],
421
638
  name: "Goose",
422
639
  factory: "goose",
423
640
  credential: "GOOGLE_GENERATIVE_AI_API_KEY",
424
641
  endpoints: GOOSE_ENDPOINTS,
642
+ expectedBlocked: {
643
+ hosts: ["models.dev"],
644
+ why: "Goose's model catalogue refresh, which no setting turns off"
645
+ },
425
646
  servedModel: geminiServedModel,
426
647
  mcpServers: gooseMcpServers,
427
- adapter: async ({ auth, mcpServers, descriptor }) => (await import("./src-qsKCqv7a.js")).createGoose({
648
+ adapter: async ({ auth, mcpServers, descriptor }) => (await import("./src-DPIjmReZ.js")).createGoose({
428
649
  auth: { GOOGLE_API_KEY: auth.GOOGLE_GENERATIVE_AI_API_KEY ?? "" },
429
650
  model: descriptor.model,
430
651
  ...descriptor.kind === "goose" && descriptor.effort ? { effort: descriptor.effort } : {},
@@ -434,13 +655,18 @@ const AGENTS = {
434
655
  },
435
656
  pi: {
436
657
  ...LAYOUTS.pi,
658
+ pluginParts: [
659
+ "skills",
660
+ "commands",
661
+ "mcp"
662
+ ],
437
663
  name: "pi",
438
664
  factory: "pi",
439
665
  credential: "GOOGLE_GENERATIVE_AI_API_KEY",
440
666
  endpoints: GEMINI_ENDPOINTS,
441
667
  servedModel: geminiServedModel,
442
668
  mcpServers: piMcpServers,
443
- adapter: async ({ auth, mcpServers, descriptor }) => (await import("./src-DSYYPEOj.js")).createPi({
669
+ adapter: async ({ auth, mcpServers, descriptor }) => (await import("./src-ynBVosfX.js")).createPi({
444
670
  auth: { GEMINI_API_KEY: auth.GOOGLE_GENERATIVE_AI_API_KEY ?? "" },
445
671
  ...descriptor.kind === "pi" && descriptor.effort ? { effort: descriptor.effort } : {},
446
672
  ...mcpServers ? { mcpServers } : {},
@@ -449,28 +675,47 @@ const AGENTS = {
449
675
  },
450
676
  codex: {
451
677
  ...LAYOUTS.codex,
678
+ pluginParts: ["skills", "mcp"],
679
+ pluginApps: "they need a ChatGPT login",
680
+ pluginManifestsFirst: ["plugin.json", ".codex-plugin/plugin.json"],
681
+ pluginRootManifestNeedsSchema: true,
682
+ pluginServersByName: true,
452
683
  name: "Codex",
453
684
  factory: "codex",
454
685
  credential: "OPENAI_API_KEY",
455
686
  endpoints: OPENAI_ENDPOINTS,
456
687
  modelResponses: OPENAI_ENDPOINTS,
688
+ expectedBlocked: {
689
+ hosts: [
690
+ "github.com",
691
+ "api.github.com",
692
+ "chatgpt.com"
693
+ ],
694
+ why: "Codex's plugin sync, which it runs on every turn once plugins are on",
695
+ withPlugins: true
696
+ },
457
697
  servedModel: openaiServedModel,
458
698
  mcpServers: codexMcpServers,
459
- adapter: async ({ auth, mcpServers, descriptor }) => (await import("./src-DCFtJRp0.js")).createCodex({
699
+ adapter: async ({ auth, mcpServers, descriptor, plugins }) => (await import("./src-DLtyz4w5.js")).createCodex({
460
700
  auth,
461
701
  ...descriptor.kind === "codex" && descriptor.effort ? { effort: descriptor.effort } : {},
462
702
  ...mcpServers ? { mcpServers } : {},
703
+ ...plugins.length ? { plugins: plugins.map(({ name, dir }) => ({
704
+ name,
705
+ dir
706
+ })) } : {},
463
707
  requireCredentialBrokering: true
464
708
  })
465
709
  },
466
710
  fx: {
467
711
  ...LAYOUTS.fx,
712
+ pluginParts: ["skills", "mcp"],
468
713
  name: "fx",
469
714
  factory: "fx",
470
715
  ...fxForModel("provider/model"),
471
716
  forModel: fxForModel,
472
717
  mcpServers: acpMcpServers,
473
- adapter: async ({ auth, mcpServers, descriptor }) => (await import("./src-BxfCKA3_.js")).createFx({
718
+ adapter: async ({ auth, mcpServers, descriptor }) => (await import("./src-DXNh5mTr.js")).createFx({
474
719
  auth,
475
720
  model: descriptor.model,
476
721
  ...mcpServers ? { mcpServers } : {},
@@ -479,6 +724,8 @@ const AGENTS = {
479
724
  },
480
725
  "grok-build": {
481
726
  ...LAYOUTS["grok-build"],
727
+ pluginParts: CLAUDE_FORMAT_PARTS,
728
+ pluginServersByName: true,
482
729
  name: "Grok Build",
483
730
  factory: "grokBuild",
484
731
  credential: "XAI_API_KEY",
@@ -486,9 +733,13 @@ const AGENTS = {
486
733
  modelResponses: XAI_MODEL_RESPONSES,
487
734
  servedModel: xaiServedModel,
488
735
  mcpServers: acpMcpServers,
489
- adapter: async ({ auth, mcpServers, descriptor }) => (await import("./src-CcrQbpG8.js")).createGrokBuild({
736
+ adapter: async ({ auth, mcpServers, descriptor, plugins }) => (await import("./src-CHIfIKUu.js")).createGrokBuild({
490
737
  auth,
491
738
  model: descriptor.model,
739
+ ...plugins.length ? {
740
+ pluginDirs: plugins.map((p) => p.dir),
741
+ pluginMcpServers: plugins.flatMap((p) => p.servers.map((s) => s.slice(p.name.length + 1)))
742
+ } : {},
492
743
  ...descriptor.kind === "grok-build" && descriptor.effort ? { effort: descriptor.effort } : {},
493
744
  ...mcpServers ? { mcpServers } : {},
494
745
  requireCredentialBrokering: true
@@ -527,6 +778,139 @@ function refusedMcp(harness, layers) {
527
778
  throw error;
528
779
  }
529
780
  }
781
+ /** The first host variable a plugin MCP server reads (`${VAR}`), as `VAR`; undefined for none. */
782
+ function hostVariable(s) {
783
+ const values = Object.entries(s.transport === "stdio" ? s.env : s.headers);
784
+ for (const [key, v] of values) {
785
+ if (typeof v === "string") continue;
786
+ if (v.kind === "secret") return v.from ?? key;
787
+ return /\$\{([A-Za-z_][A-Za-z0-9_]*)\}/.exec(v.template)?.[1] ?? key;
788
+ }
789
+ }
790
+ const quoted = (parts) => parts.map((p) => `'${p}'`).join(", ");
791
+ /**
792
+ * Why a harness's agent can't take the plugins, in the agent's own words: a part it doesn't
793
+ * load, apps it can't take (`pluginApps`), a hook event or type it doesn't run, a plugin MCP
794
+ * server it refuses (named `<plugin>:<server>`) or whose `<plugin>:<server>` key `mcp` already has,
795
+ * or, where it takes plugin items flat, a skill or MCP server whose name another already has, or a
796
+ * subagent, command or rule another unpacks to the same file. `own` names the
797
+ * environment's own skills and MCP servers, and `unread` the plugins not fetched yet (git and
798
+ * npm ones, at plan time) by their call. Undefined when it can take them.
799
+ */
800
+ function refusedPlugins(harness, plugins, own, unread = []) {
801
+ if (plugins.length === 0 && unread.length === 0) return void 0;
802
+ const agent = isAgentKind(harness.kind) ? AGENTS[harness.kind] : void 0;
803
+ const mimics = harness.kind === "fake" && harness.layout ? AGENTS[harness.layout] : void 0;
804
+ const loads = (agent ?? mimics)?.pluginParts ?? PLUGIN_PARTS;
805
+ const name = agent?.name ?? (mimics ? `The fake agent with ${mimics.name}'s layout` : "The fake agent");
806
+ if (loads.length === 0) return `${name} can't load plugins yet: leave ${plugins[0] ? `the ${plugins[0].name} plugin` : unread[0]} out of this cell`;
807
+ for (const p of plugins) {
808
+ const refused = p.kept.filter((part) => !loads.includes(part));
809
+ if (refused.length === 0) continue;
810
+ const can = p.kept.filter((part) => loads.includes(part));
811
+ const what = refused.map((part) => `${part} (${PART_PATHS[part]})`).join(" and ");
812
+ const fix = can.length ? `use only: [${quoted(can)}], or leave` : "leave";
813
+ return `${name} can't load the ${p.name} plugin's ${what}: ${fix} the plugin out of this cell`;
814
+ }
815
+ const reads = agent ?? mimics;
816
+ const first = reads?.pluginManifestsFirst ?? [];
817
+ for (const p of plugins) {
818
+ const other = p.manifests.find((m) => first.includes(m) && (m !== "plugin.json" || !reads?.pluginRootManifestNeedsSchema || p.rootSchema));
819
+ if (other) return `${name} reads the ${p.name} plugin's ${other} in place of its ${PLUGIN_MANIFEST}, so reeval can't hold it to the parts it places: remove ${other} from the plugin, or leave the plugin out of this cell`;
820
+ }
821
+ const apps = (agent ?? mimics)?.pluginApps;
822
+ const withApps = apps ? plugins.find((p) => p.apps) : void 0;
823
+ if (withApps) return `${name} can't load the ${withApps.name} plugin's apps: ${apps}`;
824
+ const layout = layoutOf(harness);
825
+ const runs = layout.pluginHookEvents;
826
+ for (const p of runs ? plugins : []) {
827
+ const event = p.hooks.events.find((e) => !runs?.includes(e));
828
+ const type = p.hooks.otherTypes[0];
829
+ if (!event && !type) continue;
830
+ const rest = p.kept.filter((part) => part !== "hooks");
831
+ const fix = rest.length ? `use only: [${quoted(rest)}], or leave` : "leave";
832
+ return event ? `${name} can't run the ${p.name} plugin's ${event} hooks (hooks/hooks.json): it runs ${runs?.join(", ")} hooks; ${fix} the plugin out of this cell` : `${name} can't run the ${p.name} plugin's ${type} hooks (hooks/hooks.json): it runs only command hooks; ${fix} the plugin out of this cell`;
833
+ }
834
+ const servers = Object.fromEntries(plugins.flatMap((p) => Object.entries(p.mcp).map(([server, s]) => [pluginServerName(p.name, server), s.transport === "stdio" ? {
835
+ ...s,
836
+ env: {}
837
+ } : {
838
+ ...s,
839
+ headers: {}
840
+ }])));
841
+ if (agent && Object.keys(servers).length) {
842
+ const alongside = agent.pluginPlacement === "flat" ? Object.fromEntries(own.mcp.map((n) => [n, {
843
+ transport: "stdio",
844
+ command: "true",
845
+ args: [],
846
+ env: {}
847
+ }])) : {};
848
+ try {
849
+ agent.mcpServers({
850
+ ...alongside,
851
+ ...servers
852
+ });
853
+ } catch (error) {
854
+ if (error instanceof InfraError) return error.message;
855
+ throw error;
856
+ }
857
+ }
858
+ for (const p of plugins) for (const server of Object.keys(p.mcp)) {
859
+ const key = pluginServerName(p.name, server);
860
+ if (own.mcp.includes(key)) return `the ${p.name} plugin's MCP server "${server}" would join mcp as ${key}, which mcp already names: rename mcp["${key}"]`;
861
+ }
862
+ if (layout.pluginPlacement === "namespaced") {
863
+ for (const p of plugins) {
864
+ if (!p.kept.includes("mcp")) continue;
865
+ for (const [server, s] of Object.entries(p.mcp)) {
866
+ const secret = hostVariable(s);
867
+ if (!secret) continue;
868
+ const rest = p.kept.filter((part) => part !== "mcp");
869
+ return `${name} loads the ${p.name} plugin's MCP server "${server}" itself, so reeval can't give it ${secret} from the host: use only: [${quoted(rest)}] and declare the server in mcp, where reeval fills it in`;
870
+ }
871
+ }
872
+ if (!(agent ?? mimics)?.pluginServersByName) return void 0;
873
+ const byName = new Map(own.mcp.map((n) => [n, `mcp.${n}`]));
874
+ for (const p of plugins) for (const server of Object.keys(p.mcp)) {
875
+ const other = byName.get(server);
876
+ if (other) return `${name} names the ${p.name} plugin's MCP server "${server}" by its own name, as it does ${other}, and keeps only one: rename one, or leave mcp out of the plugin with only`;
877
+ byName.set(server, `the ${p.name} plugin's MCP server "${server}"`);
878
+ }
879
+ return;
880
+ }
881
+ const serverOwner = new Map(own.mcp.map((n) => [n, `mcp.${n}`]));
882
+ for (const p of plugins) for (const server of Object.keys(p.mcp)) {
883
+ const other = serverOwner.get(server);
884
+ if (other) return `the ${p.name} plugin's MCP server "${server}" clashes with ${other}`;
885
+ serverOwner.set(server, `the ${p.name} plugin's MCP server "${server}"`);
886
+ }
887
+ const skillOwner = new Map(own.skills.map((s) => [s.name, `${s.call}'s "${s.name}"`]));
888
+ for (const p of plugins) for (const { name: skill } of p.skills) {
889
+ const other = skillOwner.get(skill);
890
+ if (other) return `the ${p.name} plugin's skill "${skill}" and ${other} would both be placed at ~/${layout.harnessSkillDir}/${skill}: rename one, or narrow it with only or exclude`;
891
+ skillOwner.set(skill, `the ${p.name} plugin's skill "${skill}"`);
892
+ }
893
+ for (const part of ["agents", "commands"]) {
894
+ const dir = layout.pluginUnpack?.[part];
895
+ if (!dir) continue;
896
+ const owner = /* @__PURE__ */ new Map();
897
+ for (const p of plugins) for (const item of p[part]) {
898
+ const other = owner.get(item);
899
+ const what = part === "agents" ? "subagent" : "command";
900
+ if (other) return `the ${p.name} plugin's ${what} "${item}" and the ${other} plugin's would both be placed at ${dir}/${item}.md: rename one, or narrow one with only`;
901
+ owner.set(item, p.name);
902
+ }
903
+ }
904
+ const rules = layout.pluginUnpack?.rules;
905
+ const ruleOwner = /* @__PURE__ */ new Map();
906
+ for (const p of rules ? plugins : []) for (const rule of p.rules) {
907
+ const file = `${p.name}-${rule.replace(/\.mdc?$/, "")}.mdc`;
908
+ const what = `the ${p.name} plugin's rule "${rule}"`;
909
+ const other = ruleOwner.get(file);
910
+ if (other) return `${what} and ${other} would both be placed at ${rules}/${file}: rename one, or narrow one with only`;
911
+ ruleOwner.set(file, what);
912
+ }
913
+ }
530
914
  /** A real agent's catalog entry, with what its model's provider decides. */
531
915
  function agentFor(h) {
532
916
  const agent = AGENTS[h.kind];
@@ -543,17 +927,22 @@ const credentialOf = (h) => agentOf(h)?.credential;
543
927
  const FAKE_LAYOUT = {
544
928
  rulesFile: "AGENTS.md",
545
929
  workspaceSkillDir: ".agents/skills",
546
- harnessSkillDir: ".agents/skills"
930
+ harnessSkillDir: ".agents/skills",
931
+ pluginPlacement: "flat"
547
932
  };
548
933
  /** Where a harness's agent reads rules and skills; a fake one with `layout` mimics that agent. */
549
934
  function layoutOf(descriptor) {
550
935
  if (descriptor.kind !== "fake") return LAYOUTS[descriptor.kind];
551
936
  return descriptor.layout ? LAYOUTS[descriptor.layout] : FAKE_LAYOUT;
552
937
  }
553
- /** The hosts a harness's agent is known to try; a fake agent with `layout` expects that agent's. */
554
- function expectedBlockedFor(descriptor) {
938
+ /**
939
+ * The hosts a harness's agent is known to try in a session with or without plugins; a fake agent
940
+ * with `layout` expects that agent's.
941
+ */
942
+ function expectedBlockedFor(descriptor, plugins) {
555
943
  const kind = descriptor.kind === "fake" ? descriptor.layout : descriptor.kind;
556
- return kind ? AGENTS[kind].expectedBlocked : void 0;
944
+ const expected = kind ? AGENTS[kind].expectedBlocked : void 0;
945
+ return expected?.withPlugins && !plugins ? void 0 : expected;
557
946
  }
558
947
  /**
559
948
  * How the APIs behind the harnesses say they refused a key: an HTTP 401, Anthropic's and OpenAI's
@@ -701,10 +1090,21 @@ async function createFakeSandbox(descriptor, env = {}) {
701
1090
  const base = await mkdtemp(join(parent, "reeval-sandbox-"));
702
1091
  const workdir = join(base, "work");
703
1092
  await mkdir(workdir);
1093
+ const stateDir = `${base}.state`;
1094
+ await mkdir(stateDir);
704
1095
  let destroyed;
705
1096
  const resolve = (path) => path.startsWith("~/") ? join(base, path.slice(2)) : join(workdir, path);
706
1097
  return {
707
1098
  workdir,
1099
+ stateDir,
1100
+ execOwn: (command, { signal } = {}) => run(sh, ["-c", command], {
1101
+ cwd: workdir,
1102
+ env: {
1103
+ HOME: base,
1104
+ ...env
1105
+ },
1106
+ signal
1107
+ }),
708
1108
  exec: (command, { cwd, env: extra, signal } = {}) => {
709
1109
  const tag = process.platform === "win32" && signal ? randomUUID() : void 0;
710
1110
  const stop = () => killTagged(sh, tag);
@@ -730,6 +1130,10 @@ async function createFakeSandbox(descriptor, env = {}) {
730
1130
  },
731
1131
  destroy: () => {
732
1132
  destroyed ??= (async () => {
1133
+ await rm(stateDir, {
1134
+ recursive: true,
1135
+ force: true
1136
+ }).catch(() => {});
733
1137
  if (process.platform === "win32") {
734
1138
  if (existsSync(base)) await runSh(sh, KILL_UNDER, base);
735
1139
  await removeTree(base);
@@ -767,11 +1171,12 @@ function harnessHosts(harness) {
767
1171
  if (harness.kind !== "fake" && isAgentKind(harness.kind)) return agentFor(harness).hosts ?? HARNESS_HOSTS[harness.kind];
768
1172
  return harness.kind === "fake" && harness.layout ? HARNESS_HOSTS[harness.layout] : [];
769
1173
  }
770
- /** MCP `http`/`sse` servers' hosts: the agent connects to them from the sandbox. */
1174
+ /** MCP `http`/`sse` servers' hosts, local plugins' included: the agent connects to them from the sandbox. */
771
1175
  function mcpServerHosts(layers) {
772
1176
  const urls = /* @__PURE__ */ new Map();
773
1177
  for (const { spec } of layers) for (const [name, server] of Object.entries(spec.mcp ?? {})) if (server.transport === "stdio") urls.delete(name);
774
1178
  else urls.set(name, server.url);
1179
+ for (const [name, server] of localPluginServers(layers)) if (server.transport !== "stdio") urls.set(name, server.url);
775
1180
  return [...urls.values()].flatMap((url) => URL.parse(url)?.hostname ?? []);
776
1181
  }
777
1182
  /**
@@ -831,6 +1236,6 @@ function egressLabel({ policy, auto }) {
831
1236
  return auto.length ? `${own} + auto: ${auto.join(", ")}` : own;
832
1237
  }
833
1238
  //#endregion
834
- export { layoutOf as _, unenforceable as a, DEFAULT_HARNESS as c, agentFor as d, authHint as f, isAgentKind as g, expectedBlockedFor as h, plannedEgress as i, HARNESS_EXAMPLE as l, credentialOf as m, allowedHosts as n, createFakeSandbox as o, brokeringFor as p, egressLabel as r, AGENTS as s, DEFAULT_EGRESS_ALLOW as t, agentAuth as u, refusedMcp as v };
1239
+ export { writePluginFiles as S, expectedBlockedFor as _, unenforceable as a, refusedMcp as b, DEFAULT_HARNESS as c, agentFor as d, agentMcp as f, credentialOf as g, claudeMcpServers as h, plannedEgress as i, HARNESS_EXAMPLE as l, brokeringFor as m, allowedHosts as n, createFakeSandbox as o, authHint as p, egressLabel as r, AGENTS as s, DEFAULT_EGRESS_ALLOW as t, agentAuth as u, isAgentKind as v, refusedPlugins as x, layoutOf as y };
835
1240
 
836
- //# sourceMappingURL=egress-2-qzPvGi.js.map
1241
+ //# sourceMappingURL=egress-BfK_O9ce.js.map