windows-development-sandbox 1.9.0 → 1.11.3

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 (398) hide show
  1. package/README.md +64 -17
  2. package/config.example.json +7 -2
  3. package/dist/app/features/accounts/accounts.def.d.ts +122 -0
  4. package/dist/app/features/accounts/accounts.def.js +243 -0
  5. package/dist/app/features/accounts/accounts.run.d.ts +51 -0
  6. package/dist/app/features/accounts/accounts.run.js +125 -0
  7. package/dist/app/features/accounts/index.d.ts +2 -0
  8. package/dist/app/features/accounts/index.js +3 -0
  9. package/dist/app/features/agents/agent-entry.d.ts +17 -0
  10. package/dist/app/features/agents/agent-entry.js +50 -0
  11. package/dist/app/features/agents/agents.def.d.ts +65 -0
  12. package/dist/app/features/agents/agents.def.js +142 -0
  13. package/dist/app/features/agents/agents.run.d.ts +31 -0
  14. package/dist/app/features/agents/agents.run.js +189 -0
  15. package/dist/app/features/agents/index.d.ts +3 -0
  16. package/dist/app/features/agents/index.js +4 -0
  17. package/dist/app/features/apps/apps-rows.d.ts +31 -0
  18. package/dist/app/features/apps/apps-rows.js +73 -0
  19. package/dist/app/features/apps/apps.def.d.ts +181 -0
  20. package/dist/app/features/apps/apps.def.js +264 -0
  21. package/dist/app/features/apps/apps.run.d.ts +58 -0
  22. package/dist/app/features/apps/apps.run.js +76 -0
  23. package/dist/app/features/apps/index.d.ts +3 -0
  24. package/dist/app/features/apps/index.js +4 -0
  25. package/dist/app/features/data/data.def.d.ts +154 -0
  26. package/dist/app/features/data/data.def.js +201 -0
  27. package/dist/app/features/data/data.run.d.ts +46 -0
  28. package/dist/app/features/data/data.run.js +141 -0
  29. package/dist/app/features/data/index.d.ts +2 -0
  30. package/dist/app/features/data/index.js +3 -0
  31. package/dist/app/features/defs.d.ts +952 -4
  32. package/dist/app/features/defs.js +147 -10
  33. package/dist/app/features/engine/engine.def.d.ts +228 -0
  34. package/dist/app/features/engine/engine.def.js +194 -0
  35. package/dist/app/features/engine/engine.run.d.ts +72 -0
  36. package/dist/app/features/engine/engine.run.js +77 -0
  37. package/dist/app/features/engine/index.d.ts +2 -0
  38. package/dist/app/features/engine/index.js +4 -0
  39. package/dist/app/features/files/files.def.d.ts +51 -0
  40. package/dist/app/features/files/files.def.js +38 -0
  41. package/dist/app/features/files/files.run.d.ts +20 -0
  42. package/dist/app/features/files/files.run.js +59 -0
  43. package/dist/app/features/files/index.d.ts +2 -0
  44. package/dist/app/features/files/index.js +3 -0
  45. package/dist/app/features/github/github.def.d.ts +80 -0
  46. package/dist/app/features/github/github.def.js +142 -0
  47. package/dist/app/features/github/github.run.d.ts +36 -0
  48. package/dist/app/features/github/github.run.js +59 -0
  49. package/dist/app/features/github/index.d.ts +2 -0
  50. package/dist/app/features/github/index.js +3 -0
  51. package/dist/app/features/health/health.def.d.ts +275 -0
  52. package/dist/app/features/health/health.def.js +281 -0
  53. package/dist/app/features/health/health.run.d.ts +125 -0
  54. package/dist/app/features/health/health.run.js +204 -0
  55. package/dist/app/features/health/index.d.ts +2 -0
  56. package/dist/app/features/health/index.js +3 -0
  57. package/dist/app/features/logs/index.d.ts +2 -0
  58. package/dist/app/features/logs/index.js +3 -0
  59. package/dist/app/features/logs/logs.def.d.ts +78 -0
  60. package/dist/app/features/logs/logs.def.js +115 -0
  61. package/dist/app/features/logs/logs.run.d.ts +20 -0
  62. package/dist/app/features/logs/logs.run.js +42 -0
  63. package/dist/app/features/projects/index.d.ts +2 -0
  64. package/dist/app/features/projects/index.js +3 -0
  65. package/dist/app/features/projects/projects.def.d.ts +101 -0
  66. package/dist/app/features/projects/projects.def.js +208 -0
  67. package/dist/app/features/projects/projects.run.d.ts +56 -0
  68. package/dist/app/features/projects/projects.run.js +155 -0
  69. package/dist/app/features/sandbox/sandbox.def.js +11 -5
  70. package/dist/app/features/sessions/sessions.def.js +3 -0
  71. package/dist/app/features/settings/categories.def.js +3 -2
  72. package/dist/{cli/menu/settings/share.d.ts → app/features/settings/settings-share.d.ts} +1 -1
  73. package/dist/{cli/menu/settings/share.js → app/features/settings/settings-share.js} +3 -2
  74. package/dist/app/features/settings/settings.def.d.ts +22 -5
  75. package/dist/app/features/settings/settings.def.js +81 -6
  76. package/dist/app/features/settings/settings.run.d.ts +17 -0
  77. package/dist/app/features/settings/settings.run.js +89 -4
  78. package/dist/app/features/storage/index.d.ts +2 -0
  79. package/dist/app/features/storage/index.js +3 -0
  80. package/dist/app/features/storage/storage.def.d.ts +133 -0
  81. package/dist/app/features/storage/storage.def.js +225 -0
  82. package/dist/app/features/storage/storage.run.d.ts +62 -0
  83. package/dist/app/features/storage/storage.run.js +370 -0
  84. package/dist/app/features/updates/index.d.ts +3 -0
  85. package/dist/app/features/updates/index.js +4 -0
  86. package/dist/app/features/updates/update-lines.d.ts +13 -0
  87. package/dist/app/features/updates/update-lines.js +61 -0
  88. package/dist/app/features/updates/updates.def.d.ts +89 -0
  89. package/dist/app/features/updates/updates.def.js +225 -0
  90. package/dist/app/features/updates/updates.run.d.ts +48 -0
  91. package/dist/app/features/updates/updates.run.js +154 -0
  92. package/dist/app/features/vpn/index.d.ts +2 -0
  93. package/dist/app/features/vpn/index.js +3 -0
  94. package/dist/app/features/vpn/vpn.def.d.ts +112 -0
  95. package/dist/app/features/vpn/vpn.def.js +174 -0
  96. package/dist/app/features/vpn/vpn.run.d.ts +37 -0
  97. package/dist/app/features/vpn/vpn.run.js +54 -0
  98. package/dist/app/features/web/index.d.ts +2 -0
  99. package/dist/app/features/web/index.js +3 -0
  100. package/dist/app/features/web/web.def.d.ts +33 -0
  101. package/dist/app/features/web/web.def.js +90 -0
  102. package/dist/app/features/web/web.run.d.ts +24 -0
  103. package/dist/app/features/web/web.run.js +93 -0
  104. package/dist/app/kernel/define.d.ts +10 -1
  105. package/dist/app/kernel/io.d.ts +34 -0
  106. package/dist/app/kernel/io.js +9 -0
  107. package/dist/app/kernel/rpc.d.ts +17 -0
  108. package/dist/app/kernel/text.d.ts +2 -0
  109. package/dist/app/kernel/text.js +7 -0
  110. package/dist/app/kernel/view.d.ts +24 -1
  111. package/dist/app/kernel/view.js +1 -1
  112. package/dist/app/registry.js +74 -1
  113. package/dist/cli/args.js +1 -1
  114. package/dist/cli/commands/context.d.ts +7 -0
  115. package/dist/cli/commands/context.js +29 -2
  116. package/dist/cli/commands/engine.js +5 -58
  117. package/dist/cli/commands/github.d.ts +2 -0
  118. package/dist/cli/commands/github.js +11 -0
  119. package/dist/cli/commands/index.d.ts +3 -5
  120. package/dist/cli/commands/index.js +3 -5
  121. package/dist/cli/commands/launch/launch.js +23 -4
  122. package/dist/cli/commands/launch/running.js +4 -1
  123. package/dist/cli/commands/maintenance/config.js +1 -6
  124. package/dist/cli/commands/maintenance/index.d.ts +0 -1
  125. package/dist/cli/commands/maintenance/index.js +1 -2
  126. package/dist/cli/commands/maintenance/logs.js +27 -32
  127. package/dist/cli/commands/maintenance/migrate.d.ts +0 -8
  128. package/dist/cli/commands/maintenance/migrate.js +2 -44
  129. package/dist/cli/commands/maintenance/update.d.ts +0 -19
  130. package/dist/cli/commands/maintenance/update.js +1 -99
  131. package/dist/cli/commands/projects/index.d.ts +0 -1
  132. package/dist/cli/commands/projects/index.js +0 -1
  133. package/dist/cli/commands/registry.d.ts +1 -1
  134. package/dist/cli/commands/registry.js +29 -11
  135. package/dist/cli/commands/repair/checks/data.js +1 -1
  136. package/dist/cli/commands/repair/checks/hcs.js +28 -1
  137. package/dist/cli/commands/repair/checks/sandbox.js +1 -1
  138. package/dist/cli/commands/repair/health-run.d.ts +30 -0
  139. package/dist/cli/commands/repair/health-run.js +32 -0
  140. package/dist/cli/commands/repair/printer.d.ts +2 -2
  141. package/dist/cli/commands/repair/printer.js +2 -11
  142. package/dist/cli/commands/repair/run.d.ts +1 -21
  143. package/dist/cli/commands/repair/run.js +13 -70
  144. package/dist/cli/commands/storage/index.d.ts +0 -1
  145. package/dist/cli/commands/storage/index.js +0 -1
  146. package/dist/cli/commands/storage/offer.js +6 -2
  147. package/dist/cli/commands/vpn.d.ts +1 -3
  148. package/dist/cli/commands/vpn.js +8 -88
  149. package/dist/cli/commands/web.d.ts +7 -1
  150. package/dist/cli/commands/web.js +45 -71
  151. package/dist/cli/index.js +3 -2
  152. package/dist/cli/manifest.d.ts +16 -153
  153. package/dist/cli/manifest.js +20 -50
  154. package/dist/cli/menu/command-form.js +1 -2
  155. package/dist/cli/menu/io-menu.d.ts +2 -2
  156. package/dist/cli/menu/io-menu.js +6 -4
  157. package/dist/cli/menu/menu.js +1 -1
  158. package/dist/cli/menu/pages/accounts-page.d.ts +5 -17
  159. package/dist/cli/menu/pages/accounts-page.js +28 -170
  160. package/dist/cli/menu/pages/agents-page.d.ts +17 -18
  161. package/dist/cli/menu/pages/agents-page.js +67 -124
  162. package/dist/cli/menu/pages/apps-page.d.ts +15 -8
  163. package/dist/cli/menu/pages/apps-page.js +121 -29
  164. package/dist/cli/menu/pages/list-page.js +10 -1
  165. package/dist/cli/menu/pages/maintenance-page.d.ts +51 -52
  166. package/dist/cli/menu/pages/maintenance-page.js +246 -427
  167. package/dist/cli/menu/pages/sandbox-page.d.ts +3 -5
  168. package/dist/cli/menu/pages/sandbox-page.js +34 -112
  169. package/dist/cli/menu/pages/settings-page.d.ts +21 -3
  170. package/dist/cli/menu/pages/settings-page.js +89 -17
  171. package/dist/cli/menu/render-view.js +2 -1
  172. package/dist/cli/menu/settings/index.d.ts +0 -1
  173. package/dist/cli/menu/settings/index.js +3 -3
  174. package/dist/cli/menu/views.js +28 -0
  175. package/dist/cli/operations/handler.js +7 -3
  176. package/dist/cli/operations/input.d.ts +1 -1
  177. package/dist/cli/operations/input.js +29 -5
  178. package/dist/cli/operations/io-cli.js +9 -1
  179. package/dist/cli/operations/spec.js +8 -2
  180. package/dist/cli/output/render-view.js +2 -0
  181. package/dist/cli/{commands/data/collect.js → services/data-collect.js} +2 -2
  182. package/dist/cli/{commands/data/remove.js → services/data-remove.js} +2 -2
  183. package/dist/cli/services/data-service.d.ts +1 -1
  184. package/dist/cli/services/data-service.js +2 -2
  185. package/dist/cli/services/databases-service.d.ts +5 -0
  186. package/dist/cli/services/databases-service.js +15 -0
  187. package/dist/cli/services/health-service.d.ts +8 -4
  188. package/dist/cli/services/health-service.js +10 -8
  189. package/dist/cli/services/index.d.ts +4 -1
  190. package/dist/cli/services/index.js +4 -1
  191. package/dist/cli/services/logs-service.d.ts +7 -0
  192. package/dist/cli/services/logs-service.js +13 -0
  193. package/dist/cli/services/storage-service.d.ts +19 -0
  194. package/dist/cli/services/storage-service.js +71 -0
  195. package/dist/cli/services/vpn-service.d.ts +6 -4
  196. package/dist/cli/services/vpn-service.js +5 -11
  197. package/dist/cli/services/web-service.d.ts +4 -3
  198. package/dist/cli/services/web-service.js +12 -32
  199. package/dist/core/config/defaults.js +3 -2
  200. package/dist/core/schema/config.d.ts +6 -0
  201. package/dist/core/schema/config.js +2 -0
  202. package/dist/core/schema/github.d.ts +4 -0
  203. package/dist/core/schema/github.js +7 -0
  204. package/dist/core/schema/index.d.ts +1 -0
  205. package/dist/core/schema/index.js +1 -0
  206. package/dist/core/schema/profile.d.ts +1 -0
  207. package/dist/core/schema/profile.js +3 -0
  208. package/dist/core/schema/sandbox.js +3 -3
  209. package/dist/core/schema/toolchains.js +2 -2
  210. package/dist/core/schema/vpn.js +1 -1
  211. package/dist/core/schema/web.d.ts +1 -0
  212. package/dist/core/schema/web.js +4 -1
  213. package/dist/core/types.d.ts +6 -3
  214. package/dist/guest/boot/boot.js +11 -1
  215. package/dist/guest/daemon/daemon.js +1 -1
  216. package/dist/guest/daemon/sessions.d.ts +3 -2
  217. package/dist/guest/daemon/sessions.js +38 -7
  218. package/dist/guest/governor/core.d.ts +44 -0
  219. package/dist/guest/governor/core.js +124 -0
  220. package/dist/guest/governor/decide.d.ts +53 -15
  221. package/dist/guest/governor/decide.js +155 -72
  222. package/dist/guest/governor/governor.d.ts +2 -35
  223. package/dist/guest/governor/governor.js +35 -99
  224. package/dist/guest/governor/index.d.ts +1 -0
  225. package/dist/guest/governor/index.js +1 -0
  226. package/dist/guest/network/firewall.d.ts +3 -0
  227. package/dist/guest/network/firewall.js +65 -23
  228. package/dist/guest/runtime/process.js +53 -5
  229. package/dist/guest/sessions/viewer.js +5 -1
  230. package/dist/guest/setup/claude-mem.js +12 -4
  231. package/dist/guest/setup/github-token.d.ts +7 -0
  232. package/dist/guest/setup/github-token.js +65 -0
  233. package/dist/guest/toolchains/languages/node.js +40 -4
  234. package/dist/guest/toolchains/native/rust-extras.js +2 -2
  235. package/dist/guest/toolchains/tools/cli.d.ts +8 -0
  236. package/dist/guest/toolchains/tools/cli.js +16 -2
  237. package/dist/guest/vpn/openvpn.d.ts +5 -0
  238. package/dist/guest/vpn/openvpn.js +14 -1
  239. package/dist/guest/vpn/vpn.js +55 -16
  240. package/dist/guest/vpn/wireguard.js +2 -0
  241. package/dist/host/channel/attach.d.ts +1 -0
  242. package/dist/host/channel/attach.js +1 -0
  243. package/dist/host/channel/channel.d.ts +1 -1
  244. package/dist/host/channel/channel.js +2 -2
  245. package/dist/host/engines/hcs/check.d.ts +1 -0
  246. package/dist/host/engines/hcs/check.js +1 -1
  247. package/dist/host/engines/hcs/engine.d.ts +1 -1
  248. package/dist/host/engines/hcs/engine.js +6 -4
  249. package/dist/host/engines/hcs/helper.d.ts +11 -0
  250. package/dist/host/engines/hcs/helper.js +31 -2
  251. package/dist/host/engines/hcs/leftovers.d.ts +42 -0
  252. package/dist/host/engines/hcs/leftovers.js +101 -0
  253. package/dist/host/engines/index.d.ts +1 -0
  254. package/dist/host/engines/index.js +1 -0
  255. package/dist/host/github/deliver.d.ts +13 -0
  256. package/dist/host/github/deliver.js +51 -0
  257. package/dist/host/github/index.d.ts +2 -0
  258. package/dist/host/github/index.js +3 -0
  259. package/dist/host/github/token.d.ts +21 -0
  260. package/dist/host/github/token.js +74 -0
  261. package/dist/host/launch/generate.js +11 -5
  262. package/dist/host/launch/index.d.ts +1 -1
  263. package/dist/host/launch/index.js +1 -1
  264. package/dist/host/launch/session-file.js +1 -2
  265. package/dist/host/launch/wsb-file.d.ts +11 -7
  266. package/dist/host/launch/wsb-file.js +30 -12
  267. package/dist/host/life/host-memory.d.ts +1 -0
  268. package/dist/host/life/host-memory.js +4 -1
  269. package/dist/host/life/watchdog.d.ts +11 -0
  270. package/dist/host/life/watchdog.js +36 -4
  271. package/dist/host/sandbox/tasklist.d.ts +6 -0
  272. package/dist/host/sandbox/tasklist.js +37 -0
  273. package/dist/host/secrets/launch-secrets.d.ts +2 -1
  274. package/dist/host/secrets/launch-secrets.js +4 -2
  275. package/dist/host/vpn/status.js +13 -3
  276. package/dist/host/web/backend.d.ts +1 -3
  277. package/dist/host/web/index.d.ts +2 -1
  278. package/dist/host/web/index.js +2 -1
  279. package/dist/host/web/live.d.ts +23 -0
  280. package/dist/host/web/live.js +107 -0
  281. package/dist/host/web/rpc.d.ts +6 -1
  282. package/dist/host/web/rpc.js +23 -31
  283. package/dist/host/web/runner.d.ts +4 -0
  284. package/dist/host/web/runner.js +12 -1
  285. package/dist/host/web/server.d.ts +30 -2
  286. package/dist/host/web/server.js +87 -29
  287. package/dist/host/web/state.d.ts +1 -0
  288. package/dist/host/web/state.js +2 -0
  289. package/dist/runtime/agent.js +44 -16
  290. package/dist/runtime/daemon.js +1154 -857
  291. package/dist/runtime/db.js +44 -16
  292. package/dist/runtime/main.js +532 -115
  293. package/dist/runtime/netproxy.js +34 -9
  294. package/dist/runtime/view.js +499 -149
  295. package/dist/selftest/app.test.js +620 -12
  296. package/dist/selftest/channel.test.js +18 -1
  297. package/dist/selftest/cli.test.js +1 -1
  298. package/dist/selftest/config.test.js +1 -1
  299. package/dist/selftest/contained.test.js +1 -1
  300. package/dist/selftest/data.test.js +1 -2
  301. package/dist/selftest/engine.test.js +3 -1
  302. package/dist/selftest/github.test.d.ts +2 -0
  303. package/dist/selftest/github.test.js +243 -0
  304. package/dist/selftest/guest-boot.test.js +47 -1
  305. package/dist/selftest/hcs.test.js +105 -8
  306. package/dist/selftest/health.test.js +71 -0
  307. package/dist/selftest/heavy-load.test.js +152 -66
  308. package/dist/selftest/index.js +4 -0
  309. package/dist/selftest/layout.test.js +8 -0
  310. package/dist/selftest/live-terminal.test.js +74 -0
  311. package/dist/selftest/menu-screens.js +171 -56
  312. package/dist/selftest/menu.test.js +54 -37
  313. package/dist/selftest/migrate.test.js +14 -12
  314. package/dist/selftest/network.test.js +20 -1
  315. package/dist/selftest/powershell-variables.test.d.ts +2 -0
  316. package/dist/selftest/powershell-variables.test.js +61 -0
  317. package/dist/selftest/support/engine-golden.js +1 -0
  318. package/dist/selftest/support/fixtures.d.ts +5 -0
  319. package/dist/selftest/support/web-preview.d.ts +1 -0
  320. package/dist/selftest/support/web-preview.js +856 -0
  321. package/dist/selftest/update-service.test.js +15 -8
  322. package/dist/selftest/vpn.test.js +86 -2
  323. package/dist/selftest/web.test.js +58 -11
  324. package/dist/shared/channel/run-dir.d.ts +2 -0
  325. package/dist/shared/channel/run-dir.js +3 -0
  326. package/dist/shared/channel/schema.d.ts +7 -0
  327. package/dist/shared/channel/schema.js +9 -1
  328. package/dist/shared/channel/secrets.d.ts +1 -0
  329. package/dist/shared/channel/secrets.js +3 -0
  330. package/dist/shared/github/index.d.ts +1 -0
  331. package/dist/shared/github/index.js +2 -0
  332. package/dist/shared/github/token.d.ts +29 -0
  333. package/dist/shared/github/token.js +89 -0
  334. package/dist/shared/io/copy-tree.d.ts +7 -0
  335. package/dist/shared/io/copy-tree.js +45 -0
  336. package/dist/shared/io/index.d.ts +2 -0
  337. package/dist/shared/io/index.js +2 -0
  338. package/dist/shared/io/robocopy-result.d.ts +6 -0
  339. package/dist/shared/io/robocopy-result.js +23 -0
  340. package/dist/shared/memory/policy.d.ts +38 -12
  341. package/dist/shared/memory/policy.js +58 -19
  342. package/dist/shared/network/firewall-rules.d.ts +8 -0
  343. package/dist/shared/network/firewall-rules.js +28 -0
  344. package/dist/shared/pty/ctrl-c.d.ts +18 -0
  345. package/dist/shared/pty/ctrl-c.js +36 -0
  346. package/dist/shared/pty/index.d.ts +1 -0
  347. package/dist/shared/pty/index.js +1 -0
  348. package/dist/shared/pty/terminal.d.ts +2 -0
  349. package/dist/shared/pty/terminal.js +21 -2
  350. package/dist/shared/vpn/kill-switch.d.ts +13 -2
  351. package/dist/shared/vpn/kill-switch.js +88 -8
  352. package/dist/shared/web/protocol.d.ts +0 -4
  353. package/dist/sync/watcher.js +1 -1
  354. package/dist/web/index.html +2 -2
  355. package/dist/web/{main-T5DMCHYV.css → main-6JF3ASB5.css} +1 -1
  356. package/dist/web/main-Z645W45E.js +219 -0
  357. package/native/csharp/HcsHost/AssemblyInfo.cs +3 -3
  358. package/native/csharp/HostTools/AssemblyInfo.cs +3 -3
  359. package/native/csharp/HostTools/MemoryStatus.cs +128 -107
  360. package/native/scripts/memory-status.ps1 +10 -2
  361. package/package.json +10 -3
  362. package/sandbox/csharp/MemGov.cs +668 -398
  363. package/sandbox/csharp/PtyHost.cs +104 -15
  364. package/sandbox/csharp/SandboxTools/CpuCap.cs +50 -1
  365. package/sandbox/csharp/SandboxTools/Program.cs +1 -1
  366. package/sandbox/scripts/new-shortcuts.ps1 +3 -1
  367. package/sandbox/scripts/repair-wmi-services.ps1 +26 -0
  368. package/schemas/config.schema.json +25 -7
  369. package/schemas/sandbox-config.schema.json +7 -3
  370. package/dist/cli/commands/accounts.d.ts +0 -2
  371. package/dist/cli/commands/accounts.js +0 -96
  372. package/dist/cli/commands/data/clean.d.ts +0 -3
  373. package/dist/cli/commands/data/clean.js +0 -60
  374. package/dist/cli/commands/data/index.d.ts +0 -4
  375. package/dist/cli/commands/data/index.js +0 -62
  376. package/dist/cli/commands/maintenance/clean.d.ts +0 -2
  377. package/dist/cli/commands/maintenance/clean.js +0 -24
  378. package/dist/cli/commands/maintenance/config-share.d.ts +0 -12
  379. package/dist/cli/commands/maintenance/config-share.js +0 -80
  380. package/dist/cli/commands/projects/projects.d.ts +0 -2
  381. package/dist/cli/commands/projects/projects.js +0 -162
  382. package/dist/cli/commands/storage/contained.d.ts +0 -3
  383. package/dist/cli/commands/storage/contained.js +0 -179
  384. package/dist/cli/commands/storage/storage.d.ts +0 -8
  385. package/dist/cli/commands/storage/storage.js +0 -179
  386. package/dist/cli/menu/add-agent.d.ts +0 -47
  387. package/dist/cli/menu/add-agent.js +0 -168
  388. package/dist/cli/menu/apps.d.ts +0 -69
  389. package/dist/cli/menu/apps.js +0 -214
  390. package/dist/cli/menu/data-folder.d.ts +0 -18
  391. package/dist/cli/menu/data-folder.js +0 -99
  392. package/dist/cli/menu/share-settings.d.ts +0 -21
  393. package/dist/cli/menu/share-settings.js +0 -112
  394. package/dist/cli/menu/vpn-login.d.ts +0 -16
  395. package/dist/cli/menu/vpn-login.js +0 -74
  396. package/dist/web/main-NRRS5O6Z.js +0 -157
  397. /package/dist/cli/{commands/data/collect.d.ts → services/data-collect.d.ts} +0 -0
  398. /package/dist/cli/{commands/data/remove.d.ts → services/data-remove.d.ts} +0 -0
@@ -1363,11 +1363,11 @@ var require_lodash = __commonJS({
1363
1363
  return isFunction(object2[key2]);
1364
1364
  });
1365
1365
  }
1366
- function baseGet(object2, path69) {
1367
- path69 = castPath(path69, object2);
1368
- var index = 0, length = path69.length;
1366
+ function baseGet(object2, path70) {
1367
+ path70 = castPath(path70, object2);
1368
+ var index = 0, length = path70.length;
1369
1369
  while (object2 != null && index < length) {
1370
- object2 = object2[toKey(path69[index++])];
1370
+ object2 = object2[toKey(path70[index++])];
1371
1371
  }
1372
1372
  return index && index == length ? object2 : undefined2;
1373
1373
  }
@@ -1431,10 +1431,10 @@ var require_lodash = __commonJS({
1431
1431
  });
1432
1432
  return accumulator;
1433
1433
  }
1434
- function baseInvoke(object2, path69, args) {
1435
- path69 = castPath(path69, object2);
1436
- object2 = parent(object2, path69);
1437
- var func = object2 == null ? object2 : object2[toKey(last(path69))];
1434
+ function baseInvoke(object2, path70, args) {
1435
+ path70 = castPath(path70, object2);
1436
+ object2 = parent(object2, path70);
1437
+ var func = object2 == null ? object2 : object2[toKey(last(path70))];
1438
1438
  return func == null ? undefined2 : apply(func, object2, args);
1439
1439
  }
1440
1440
  function baseIsArguments(value) {
@@ -1590,13 +1590,13 @@ var require_lodash = __commonJS({
1590
1590
  return object2 === source || baseIsMatch(object2, source, matchData);
1591
1591
  };
1592
1592
  }
1593
- function baseMatchesProperty(path69, srcValue) {
1594
- if (isKey(path69) && isStrictComparable(srcValue)) {
1595
- return matchesStrictComparable(toKey(path69), srcValue);
1593
+ function baseMatchesProperty(path70, srcValue) {
1594
+ if (isKey(path70) && isStrictComparable(srcValue)) {
1595
+ return matchesStrictComparable(toKey(path70), srcValue);
1596
1596
  }
1597
1597
  return function(object2) {
1598
- var objValue = get(object2, path69);
1599
- return objValue === undefined2 && objValue === srcValue ? hasIn(object2, path69) : baseIsEqual(srcValue, objValue, COMPARE_PARTIAL_FLAG | COMPARE_UNORDERED_FLAG);
1598
+ var objValue = get(object2, path70);
1599
+ return objValue === undefined2 && objValue === srcValue ? hasIn(object2, path70) : baseIsEqual(srcValue, objValue, COMPARE_PARTIAL_FLAG | COMPARE_UNORDERED_FLAG);
1600
1600
  };
1601
1601
  }
1602
1602
  function baseMerge(object2, source, srcIndex, customizer, stack) {
@@ -1693,23 +1693,23 @@ var require_lodash = __commonJS({
1693
1693
  });
1694
1694
  }
1695
1695
  function basePick(object2, paths) {
1696
- return basePickBy(object2, paths, function(value, path69) {
1697
- return hasIn(object2, path69);
1696
+ return basePickBy(object2, paths, function(value, path70) {
1697
+ return hasIn(object2, path70);
1698
1698
  });
1699
1699
  }
1700
1700
  function basePickBy(object2, paths, predicate) {
1701
1701
  var index = -1, length = paths.length, result2 = {};
1702
1702
  while (++index < length) {
1703
- var path69 = paths[index], value = baseGet(object2, path69);
1704
- if (predicate(value, path69)) {
1705
- baseSet(result2, castPath(path69, object2), value);
1703
+ var path70 = paths[index], value = baseGet(object2, path70);
1704
+ if (predicate(value, path70)) {
1705
+ baseSet(result2, castPath(path70, object2), value);
1706
1706
  }
1707
1707
  }
1708
1708
  return result2;
1709
1709
  }
1710
- function basePropertyDeep(path69) {
1710
+ function basePropertyDeep(path70) {
1711
1711
  return function(object2) {
1712
- return baseGet(object2, path69);
1712
+ return baseGet(object2, path70);
1713
1713
  };
1714
1714
  }
1715
1715
  function basePullAll(array2, values2, iteratee2, comparator) {
@@ -1783,14 +1783,14 @@ var require_lodash = __commonJS({
1783
1783
  var array2 = values(collection);
1784
1784
  return shuffleSelf(array2, baseClamp(n, 0, array2.length));
1785
1785
  }
1786
- function baseSet(object2, path69, value, customizer) {
1786
+ function baseSet(object2, path70, value, customizer) {
1787
1787
  if (!isObject2(object2)) {
1788
1788
  return object2;
1789
1789
  }
1790
- path69 = castPath(path69, object2);
1791
- var index = -1, length = path69.length, lastIndex = length - 1, nested = object2;
1790
+ path70 = castPath(path70, object2);
1791
+ var index = -1, length = path70.length, lastIndex = length - 1, nested = object2;
1792
1792
  while (nested != null && ++index < length) {
1793
- var key2 = toKey(path69[index]), newValue = value;
1793
+ var key2 = toKey(path70[index]), newValue = value;
1794
1794
  if (key2 === "__proto__" || key2 === "constructor" || key2 === "prototype") {
1795
1795
  return object2;
1796
1796
  }
@@ -1798,7 +1798,7 @@ var require_lodash = __commonJS({
1798
1798
  var objValue = nested[key2];
1799
1799
  newValue = customizer ? customizer(objValue, key2, nested) : undefined2;
1800
1800
  if (newValue === undefined2) {
1801
- newValue = isObject2(objValue) ? objValue : isIndex(path69[index + 1]) ? [] : {};
1801
+ newValue = isObject2(objValue) ? objValue : isIndex(path70[index + 1]) ? [] : {};
1802
1802
  }
1803
1803
  }
1804
1804
  assignValue(nested, key2, newValue);
@@ -1964,14 +1964,14 @@ var require_lodash = __commonJS({
1964
1964
  }
1965
1965
  return result2;
1966
1966
  }
1967
- function baseUnset(object2, path69) {
1968
- path69 = castPath(path69, object2);
1969
- var index = -1, length = path69.length;
1967
+ function baseUnset(object2, path70) {
1968
+ path70 = castPath(path70, object2);
1969
+ var index = -1, length = path70.length;
1970
1970
  if (!length) {
1971
1971
  return true;
1972
1972
  }
1973
1973
  while (++index < length) {
1974
- var key2 = toKey(path69[index]);
1974
+ var key2 = toKey(path70[index]);
1975
1975
  if (key2 === "__proto__" && !hasOwnProperty.call(object2, "__proto__")) {
1976
1976
  return false;
1977
1977
  }
@@ -1979,11 +1979,11 @@ var require_lodash = __commonJS({
1979
1979
  return false;
1980
1980
  }
1981
1981
  }
1982
- var obj = parent(object2, path69);
1983
- return obj == null || delete obj[toKey(last(path69))];
1982
+ var obj = parent(object2, path70);
1983
+ return obj == null || delete obj[toKey(last(path70))];
1984
1984
  }
1985
- function baseUpdate(object2, path69, updater, customizer) {
1986
- return baseSet(object2, path69, updater(baseGet(object2, path69)), customizer);
1985
+ function baseUpdate(object2, path70, updater, customizer) {
1986
+ return baseSet(object2, path70, updater(baseGet(object2, path70)), customizer);
1987
1987
  }
1988
1988
  function baseWhile(array2, predicate, isDrop, fromRight) {
1989
1989
  var length = array2.length, index = fromRight ? length : -1;
@@ -2866,11 +2866,11 @@ var require_lodash = __commonJS({
2866
2866
  var match = source.match(reWrapDetails);
2867
2867
  return match ? match[1].split(reSplitDetails) : [];
2868
2868
  }
2869
- function hasPath(object2, path69, hasFunc) {
2870
- path69 = castPath(path69, object2);
2871
- var index = -1, length = path69.length, result2 = false;
2869
+ function hasPath(object2, path70, hasFunc) {
2870
+ path70 = castPath(path70, object2);
2871
+ var index = -1, length = path70.length, result2 = false;
2872
2872
  while (++index < length) {
2873
- var key2 = toKey(path69[index]);
2873
+ var key2 = toKey(path70[index]);
2874
2874
  if (!(result2 = object2 != null && hasFunc(object2, key2))) {
2875
2875
  break;
2876
2876
  }
@@ -3072,8 +3072,8 @@ var require_lodash = __commonJS({
3072
3072
  return apply(func, this, otherArgs);
3073
3073
  };
3074
3074
  }
3075
- function parent(object2, path69) {
3076
- return path69.length < 2 ? object2 : baseGet(object2, baseSlice(path69, 0, -1));
3075
+ function parent(object2, path70) {
3076
+ return path70.length < 2 ? object2 : baseGet(object2, baseSlice(path70, 0, -1));
3077
3077
  }
3078
3078
  function reorder(array2, indexes) {
3079
3079
  var arrLength = array2.length, length = nativeMin(indexes.length, arrLength), oldArray = copyArray(array2);
@@ -3708,10 +3708,10 @@ var require_lodash = __commonJS({
3708
3708
  }
3709
3709
  return isString(collection) ? fromIndex <= length && collection.indexOf(value, fromIndex) > -1 : !!length && baseIndexOf(collection, value, fromIndex) > -1;
3710
3710
  }
3711
- var invokeMap = baseRest(function(collection, path69, args) {
3712
- var index = -1, isFunc = typeof path69 == "function", result2 = isArrayLike(collection) ? Array2(collection.length) : [];
3711
+ var invokeMap = baseRest(function(collection, path70, args) {
3712
+ var index = -1, isFunc = typeof path70 == "function", result2 = isArrayLike(collection) ? Array2(collection.length) : [];
3713
3713
  baseEach(collection, function(value) {
3714
- result2[++index] = isFunc ? apply(path69, value, args) : baseInvoke(value, path69, args);
3714
+ result2[++index] = isFunc ? apply(path70, value, args) : baseInvoke(value, path70, args);
3715
3715
  });
3716
3716
  return result2;
3717
3717
  });
@@ -4363,15 +4363,15 @@ var require_lodash = __commonJS({
4363
4363
  function functionsIn(object2) {
4364
4364
  return object2 == null ? [] : baseFunctions(object2, keysIn(object2));
4365
4365
  }
4366
- function get(object2, path69, defaultValue) {
4367
- var result2 = object2 == null ? undefined2 : baseGet(object2, path69);
4366
+ function get(object2, path70, defaultValue) {
4367
+ var result2 = object2 == null ? undefined2 : baseGet(object2, path70);
4368
4368
  return result2 === undefined2 ? defaultValue : result2;
4369
4369
  }
4370
- function has(object2, path69) {
4371
- return object2 != null && hasPath(object2, path69, baseHas);
4370
+ function has(object2, path70) {
4371
+ return object2 != null && hasPath(object2, path70, baseHas);
4372
4372
  }
4373
- function hasIn(object2, path69) {
4374
- return object2 != null && hasPath(object2, path69, baseHasIn);
4373
+ function hasIn(object2, path70) {
4374
+ return object2 != null && hasPath(object2, path70, baseHasIn);
4375
4375
  }
4376
4376
  var invert = createInverter(function(result2, value, key2) {
4377
4377
  if (value != null && typeof value.toString != "function") {
@@ -4424,10 +4424,10 @@ var require_lodash = __commonJS({
4424
4424
  return result2;
4425
4425
  }
4426
4426
  var isDeep = false;
4427
- paths = arrayMap(paths, function(path69) {
4428
- path69 = castPath(path69, object2);
4429
- isDeep || (isDeep = path69.length > 1);
4430
- return path69;
4427
+ paths = arrayMap(paths, function(path70) {
4428
+ path70 = castPath(path70, object2);
4429
+ isDeep || (isDeep = path70.length > 1);
4430
+ return path70;
4431
4431
  });
4432
4432
  copyObject(object2, getAllKeysIn(object2), result2);
4433
4433
  if (isDeep) {
@@ -4453,19 +4453,19 @@ var require_lodash = __commonJS({
4453
4453
  return [prop];
4454
4454
  });
4455
4455
  predicate = getIteratee(predicate);
4456
- return basePickBy(object2, props, function(value, path69) {
4457
- return predicate(value, path69[0]);
4456
+ return basePickBy(object2, props, function(value, path70) {
4457
+ return predicate(value, path70[0]);
4458
4458
  });
4459
4459
  }
4460
- function result(object2, path69, defaultValue) {
4461
- path69 = castPath(path69, object2);
4462
- var index = -1, length = path69.length;
4460
+ function result(object2, path70, defaultValue) {
4461
+ path70 = castPath(path70, object2);
4462
+ var index = -1, length = path70.length;
4463
4463
  if (!length) {
4464
4464
  length = 1;
4465
4465
  object2 = undefined2;
4466
4466
  }
4467
4467
  while (++index < length) {
4468
- var value = object2 == null ? undefined2 : object2[toKey(path69[index])];
4468
+ var value = object2 == null ? undefined2 : object2[toKey(path70[index])];
4469
4469
  if (value === undefined2) {
4470
4470
  index = length;
4471
4471
  value = defaultValue;
@@ -4474,12 +4474,12 @@ var require_lodash = __commonJS({
4474
4474
  }
4475
4475
  return object2;
4476
4476
  }
4477
- function set2(object2, path69, value) {
4478
- return object2 == null ? object2 : baseSet(object2, path69, value);
4477
+ function set2(object2, path70, value) {
4478
+ return object2 == null ? object2 : baseSet(object2, path70, value);
4479
4479
  }
4480
- function setWith(object2, path69, value, customizer) {
4480
+ function setWith(object2, path70, value, customizer) {
4481
4481
  customizer = typeof customizer == "function" ? customizer : undefined2;
4482
- return object2 == null ? object2 : baseSet(object2, path69, value, customizer);
4482
+ return object2 == null ? object2 : baseSet(object2, path70, value, customizer);
4483
4483
  }
4484
4484
  var toPairs = createToPairs(keys);
4485
4485
  var toPairsIn = createToPairs(keysIn);
@@ -4501,15 +4501,15 @@ var require_lodash = __commonJS({
4501
4501
  });
4502
4502
  return accumulator;
4503
4503
  }
4504
- function unset(object2, path69) {
4505
- return object2 == null ? true : baseUnset(object2, path69);
4504
+ function unset(object2, path70) {
4505
+ return object2 == null ? true : baseUnset(object2, path70);
4506
4506
  }
4507
- function update(object2, path69, updater) {
4508
- return object2 == null ? object2 : baseUpdate(object2, path69, castFunction(updater));
4507
+ function update(object2, path70, updater) {
4508
+ return object2 == null ? object2 : baseUpdate(object2, path70, castFunction(updater));
4509
4509
  }
4510
- function updateWith(object2, path69, updater, customizer) {
4510
+ function updateWith(object2, path70, updater, customizer) {
4511
4511
  customizer = typeof customizer == "function" ? customizer : undefined2;
4512
- return object2 == null ? object2 : baseUpdate(object2, path69, castFunction(updater), customizer);
4512
+ return object2 == null ? object2 : baseUpdate(object2, path70, castFunction(updater), customizer);
4513
4513
  }
4514
4514
  function values(object2) {
4515
4515
  return object2 == null ? [] : baseValues(object2, keys(object2));
@@ -4895,17 +4895,17 @@ var require_lodash = __commonJS({
4895
4895
  function matches(source) {
4896
4896
  return baseMatches(baseClone(source, CLONE_DEEP_FLAG));
4897
4897
  }
4898
- function matchesProperty(path69, srcValue) {
4899
- return baseMatchesProperty(path69, baseClone(srcValue, CLONE_DEEP_FLAG));
4898
+ function matchesProperty(path70, srcValue) {
4899
+ return baseMatchesProperty(path70, baseClone(srcValue, CLONE_DEEP_FLAG));
4900
4900
  }
4901
- var method = baseRest(function(path69, args) {
4901
+ var method = baseRest(function(path70, args) {
4902
4902
  return function(object2) {
4903
- return baseInvoke(object2, path69, args);
4903
+ return baseInvoke(object2, path70, args);
4904
4904
  };
4905
4905
  });
4906
4906
  var methodOf = baseRest(function(object2, args) {
4907
- return function(path69) {
4908
- return baseInvoke(object2, path69, args);
4907
+ return function(path70) {
4908
+ return baseInvoke(object2, path70, args);
4909
4909
  };
4910
4910
  });
4911
4911
  function mixin(object2, source, options) {
@@ -4952,12 +4952,12 @@ var require_lodash = __commonJS({
4952
4952
  var over = createOver(arrayMap);
4953
4953
  var overEvery = createOver(arrayEvery);
4954
4954
  var overSome = createOver(arraySome);
4955
- function property(path69) {
4956
- return isKey(path69) ? baseProperty(toKey(path69)) : basePropertyDeep(path69);
4955
+ function property(path70) {
4956
+ return isKey(path70) ? baseProperty(toKey(path70)) : basePropertyDeep(path70);
4957
4957
  }
4958
4958
  function propertyOf(object2) {
4959
- return function(path69) {
4960
- return object2 == null ? undefined2 : baseGet(object2, path69);
4959
+ return function(path70) {
4960
+ return object2 == null ? undefined2 : baseGet(object2, path70);
4961
4961
  };
4962
4962
  }
4963
4963
  var range = createRange();
@@ -5410,12 +5410,12 @@ var require_lodash = __commonJS({
5410
5410
  LazyWrapper.prototype.findLast = function(predicate) {
5411
5411
  return this.reverse().find(predicate);
5412
5412
  };
5413
- LazyWrapper.prototype.invokeMap = baseRest(function(path69, args) {
5414
- if (typeof path69 == "function") {
5413
+ LazyWrapper.prototype.invokeMap = baseRest(function(path70, args) {
5414
+ if (typeof path70 == "function") {
5415
5415
  return new LazyWrapper(this);
5416
5416
  }
5417
5417
  return this.map(function(value) {
5418
- return baseInvoke(value, path69, args);
5418
+ return baseInvoke(value, path70, args);
5419
5419
  });
5420
5420
  });
5421
5421
  LazyWrapper.prototype.reject = function(predicate) {
@@ -5540,15 +5540,15 @@ function relayPort(index) {
5540
5540
  }
5541
5541
 
5542
5542
  // src/guest/runtime/log.ts
5543
- import fs5 from "node:fs";
5544
- import path8 from "node:path";
5543
+ import fs6 from "node:fs";
5544
+ import path9 from "node:path";
5545
5545
 
5546
5546
  // src/guest/runtime/paths.ts
5547
- import path7 from "node:path";
5547
+ import path8 from "node:path";
5548
5548
 
5549
5549
  // src/shared/channel/run-dir.ts
5550
- import fs4 from "node:fs";
5551
- import path6 from "node:path";
5550
+ import fs5 from "node:fs";
5551
+ import path7 from "node:path";
5552
5552
 
5553
5553
  // node_modules/zod/v4/classic/external.js
5554
5554
  var external_exports = {};
@@ -6366,10 +6366,10 @@ function mergeDefs(...defs) {
6366
6366
  function cloneDef(schema) {
6367
6367
  return mergeDefs(schema._zod.def);
6368
6368
  }
6369
- function getElementAtPath(obj, path69) {
6370
- if (!path69)
6369
+ function getElementAtPath(obj, path70) {
6370
+ if (!path70)
6371
6371
  return obj;
6372
- return path69.reduce((acc, key2) => acc?.[key2], obj);
6372
+ return path70.reduce((acc, key2) => acc?.[key2], obj);
6373
6373
  }
6374
6374
  function promiseAllObject(promisesObj) {
6375
6375
  const keys = Object.keys(promisesObj);
@@ -6709,11 +6709,11 @@ function explicitlyAborted(x, startIndex = 0) {
6709
6709
  }
6710
6710
  return false;
6711
6711
  }
6712
- function prefixIssues(path69, issues) {
6712
+ function prefixIssues(path70, issues) {
6713
6713
  return issues.map((iss) => {
6714
6714
  var _a3;
6715
6715
  (_a3 = iss).path ?? (_a3.path = []);
6716
- iss.path.unshift(path69);
6716
+ iss.path.unshift(path70);
6717
6717
  return iss;
6718
6718
  });
6719
6719
  }
@@ -7163,16 +7163,16 @@ function flattenError(error62, mapper = (issue2) => issue2.message) {
7163
7163
  }
7164
7164
  function formatError(error62, mapper = (issue2) => issue2.message) {
7165
7165
  const fieldErrors = { _errors: [] };
7166
- const processError = (error63, path69 = []) => {
7166
+ const processError = (error63, path70 = []) => {
7167
7167
  for (const issue2 of error63.issues) {
7168
7168
  if (issue2.code === "invalid_union" && issue2.errors.length) {
7169
- issue2.errors.map((issues) => processError({ issues }, [...path69, ...issue2.path]));
7169
+ issue2.errors.map((issues) => processError({ issues }, [...path70, ...issue2.path]));
7170
7170
  } else if (issue2.code === "invalid_key") {
7171
- processError({ issues: issue2.issues }, [...path69, ...issue2.path]);
7171
+ processError({ issues: issue2.issues }, [...path70, ...issue2.path]);
7172
7172
  } else if (issue2.code === "invalid_element") {
7173
- processError({ issues: issue2.issues }, [...path69, ...issue2.path]);
7173
+ processError({ issues: issue2.issues }, [...path70, ...issue2.path]);
7174
7174
  } else {
7175
- const fullpath = [...path69, ...issue2.path];
7175
+ const fullpath = [...path70, ...issue2.path];
7176
7176
  if (fullpath.length === 0) {
7177
7177
  fieldErrors._errors.push(mapper(issue2));
7178
7178
  } else {
@@ -7211,17 +7211,17 @@ function formatError(error62, mapper = (issue2) => issue2.message) {
7211
7211
  }
7212
7212
  function treeifyError(error62, mapper = (issue2) => issue2.message) {
7213
7213
  const result = { errors: [] };
7214
- const processError = (error63, path69 = []) => {
7214
+ const processError = (error63, path70 = []) => {
7215
7215
  var _a3;
7216
7216
  for (const issue2 of error63.issues) {
7217
7217
  if (issue2.code === "invalid_union" && issue2.errors.length) {
7218
- issue2.errors.map((issues) => processError({ issues }, [...path69, ...issue2.path]));
7218
+ issue2.errors.map((issues) => processError({ issues }, [...path70, ...issue2.path]));
7219
7219
  } else if (issue2.code === "invalid_key") {
7220
- processError({ issues: issue2.issues }, [...path69, ...issue2.path]);
7220
+ processError({ issues: issue2.issues }, [...path70, ...issue2.path]);
7221
7221
  } else if (issue2.code === "invalid_element") {
7222
- processError({ issues: issue2.issues }, [...path69, ...issue2.path]);
7222
+ processError({ issues: issue2.issues }, [...path70, ...issue2.path]);
7223
7223
  } else {
7224
- const fullpath = [...path69, ...issue2.path];
7224
+ const fullpath = [...path70, ...issue2.path];
7225
7225
  if (fullpath.length === 0) {
7226
7226
  result.errors.push(mapper(issue2));
7227
7227
  continue;
@@ -7260,8 +7260,8 @@ function treeifyError(error62, mapper = (issue2) => issue2.message) {
7260
7260
  }
7261
7261
  function toDotPath(_path) {
7262
7262
  const segs = [];
7263
- const path69 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
7264
- for (const seg of path69) {
7263
+ const path70 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
7264
+ for (const seg of path70) {
7265
7265
  if (typeof seg === "number")
7266
7266
  segs.push(`[${seg}]`);
7267
7267
  else if (typeof seg === "symbol")
@@ -24363,13 +24363,13 @@ function resolveRef(ref, ctx) {
24363
24363
  if (!ref.startsWith("#")) {
24364
24364
  throw new Error("External $ref is not supported, only local refs (#/...) are allowed");
24365
24365
  }
24366
- const path69 = ref.slice(1).split("/").filter(Boolean);
24367
- if (path69.length === 0) {
24366
+ const path70 = ref.slice(1).split("/").filter(Boolean);
24367
+ if (path70.length === 0) {
24368
24368
  return ctx.rootSchema;
24369
24369
  }
24370
24370
  const defsKey = ctx.version === "draft-2020-12" ? "$defs" : "definitions";
24371
- if (path69[0] === defsKey) {
24372
- const key2 = path69[1] === void 0 ? void 0 : decodeJSONPointerSegment(path69[1]);
24371
+ if (path70[0] === defsKey) {
24372
+ const key2 = path70[1] === void 0 ? void 0 : decodeJSONPointerSegment(path70[1]);
24373
24373
  if (!key2 || !ctx.defs[key2]) {
24374
24374
  throw new Error(`Reference not found: ${ref}`);
24375
24375
  }
@@ -25437,6 +25437,9 @@ var AttachSchema = external_exports.strictObject({
25437
25437
  ),
25438
25438
  autoHide: external_exports.boolean().describe(
25439
25439
  "Hide the Windows Sandbox window whenever this terminal attaches; it keeps running (sandbox show brings it back)."
25440
+ ),
25441
+ confirmCtrlC: external_exports.boolean().describe(
25442
+ 'In an attached terminal and the sandbox window, a single Ctrl+C is held back (the title says so) and only a second one within 1.5 seconds reaches the agent: a Ctrl+C meant as "copy" no longer stops it. Esc still stops an agent.'
25440
25443
  )
25441
25444
  });
25442
25445
  var AgentCommandsSchema = external_exports.strictObject({
@@ -25481,7 +25484,9 @@ var SandboxSchema = external_exports.strictObject({
25481
25484
  engine: external_exports.enum(["windows-sandbox", "hcs"]).describe(
25482
25485
  '(alpha) What runs the sandbox. "windows-sandbox" = Windows Sandbox (the default: desktop, Windows Terminal, GPU, clipboard, audio, printers). "hcs" = a headless Hyper-V isolated Server Core container for agents (no desktop, GPU or clipboard); it needs Windows features and an image on this PC (sandbox engine check hcs lists what is missing), and starting it is not enabled yet in this alpha. sandbox engine shows what each engine can do. Yours only: a project file (.sandbox-config.json) cannot set it.'
25483
25486
  ),
25484
- memoryMb: external_exports.union([external_exports.literal("auto"), external_exports.number().int().min(2048)]).describe('Sandbox RAM in MB (>= 2048), or "auto": free RAM minus reserveHostMb, capped at maxMemoryMb.'),
25487
+ memoryMb: external_exports.union([external_exports.literal("auto"), external_exports.number().int().min(2048)]).describe(
25488
+ 'Sandbox RAM in MB (>= 2048), or "auto": free RAM minus reserveHostMb, capped at maxMemoryMb. Never more than this PC can keep in RAM for it (its RAM minus the larger of reserveHostMb and 25 %, 2 GB more with vGPU): a bigger value is lowered.'
25489
+ ),
25485
25490
  maxMemoryMb: external_exports.number().int().positive().describe('Upper limit for memoryMb "auto".'),
25486
25491
  maxMemoryPercent: external_exports.number().int().min(10).max(100).describe(`memoryMb "auto" never takes more than this share of this PC's total RAM (percent).`),
25487
25492
  cpuLimit: external_exports.union([external_exports.literal("none"), external_exports.number().int().min(5).max(100)]).describe(
@@ -25494,10 +25499,10 @@ var SandboxSchema = external_exports.strictObject({
25494
25499
  'Memory always left for this PC when memoryMb is "auto": the sandbox gets at most (free RAM, and RAM plus paging file still unused) minus this.'
25495
25500
  ),
25496
25501
  agentMemoryHeadroomMb: external_exports.union([external_exports.literal("auto"), external_exports.literal("none"), external_exports.number().int().min(0)]).describe(
25497
- 'Memory kept out of the agents reach inside the sandbox, in MB: everything the agents start (their builds, tests, tools) together may use at most the sandbox memory minus this; a runaway parallel build then gets out-of-memory errors in its own session instead of freezing or crashing the whole sandbox. "auto" = the larger of 2048 MB and 10 % of the sandbox memory; "none" = no limit. Yours only: a project file cannot change it.'
25502
+ 'The last resort that keeps the sandbox up, in MB below its commit limit (RAM plus paging file): builds are slowed down long before (sandbox.pressureResponse); only if everything the agents start together would take the sandbox to the very edge of its memory, where Windows inside it would start failing, is a build refused memory instead of Windows. "auto" = the larger of 1536 MB and 3 % of the commit limit; "none" = no backstop. Yours only: a project file cannot change it.'
25498
25503
  ),
25499
25504
  pressureResponse: external_exports.boolean().describe(
25500
- "When the sandbox (or this PC) runs low on memory, slow the heaviest build programs down (lower priority) and, if that is not enough, pause the biggest compiler for a few seconds at a time, so heavy parallel builds slow down instead of closing the sandbox. Never touches the agents themselves. Yours only: a project file cannot change it."
25505
+ "When the sandbox (or this PC) runs low on memory, slow builds down in steps, like a PC that gets slower instead of failing: build programs get lower CPU and memory priority, then less CPU, then compilers take turns (the waiting ones briefly suspended and trimmed to the paging file). Nothing is stopped or killed, and the agents themselves are never touched. Yours only: a project file cannot change it."
25501
25506
  ),
25502
25507
  vGpu: external_exports.boolean().describe(
25503
25508
  "Virtual GPU. Off by default: Microsoft notes it widens the sandbox attack surface. The sandbox then uses this PC's graphics card, and with some graphics drivers heavy use can freeze the whole PC: turn it on only when a program in the sandbox needs the GPU (the mesa toolchain gives software OpenGL without it)."
@@ -25643,7 +25648,7 @@ var ToolchainsSchema = external_exports.strictObject({
25643
25648
  `GNU host: "lld" links with Rust's own lld through MinGW's gcc (much less memory than GNU ld), "gnu" with GNU ld.`
25644
25649
  ),
25645
25650
  linkSlots: external_exports.union([external_exports.literal("auto"), external_exports.number().int().min(1).max(32)]).describe(
25646
- 'GNU host: how many programs may link at the same time in the whole sandbox (other links wait). "auto" = one per 8 GB of sandbox memory, 2 to 4. Several agents linking big programs at once can take Windows down.'
25651
+ 'GNU host: how many programs may link at the same time in the whole sandbox (other links wait). "auto" = one per 3 GB of sandbox memory after 6 GB, 2 to 8 (the memory governor slows links down too when memory runs short).'
25647
25652
  )
25648
25653
  }),
25649
25654
  msvc: external_exports.strictObject({
@@ -25718,7 +25723,7 @@ var ToolchainsSchema = external_exports.strictObject({
25718
25723
  }),
25719
25724
  cli: external_exports.strictObject({
25720
25725
  gh: EnabledSchema.describe(
25721
- 'GitHub CLI (gh). Only with provisioning.git.access "full": gh can push and merge through the GitHub API, past a read-only git. Your PC\'s gh login is never copied; `gh auth login` inside persists (GH_CONFIG_DIR). "auto" = when the project has a .github folder.'
25726
+ 'GitHub CLI (gh). Only with provisioning.git.access "full": gh can push and merge through the GitHub API, past a read-only git. Your PC\'s gh login is never copied; `gh auth login` inside persists (GH_CONFIG_DIR), unless a token you saved for sandboxes is handed over (github.shareToken). "auto" = when the project has a .github folder.'
25722
25727
  ),
25723
25728
  zstd: EnabledSchema.describe('Zstandard (zstd). "auto" = off; set true to get it.'),
25724
25729
  openssl: EnabledSchema.describe(
@@ -26621,16 +26626,17 @@ var ResumeSchema = external_exports.strictObject({
26621
26626
  // src/core/schema/web.ts
26622
26627
  var WebSchema = external_exports.strictObject({
26623
26628
  enabled: external_exports.boolean().describe(
26624
- "(Beta) Allow the web UI: your sandbox sessions in a browser on this PC. Off by default, and nothing starts it by itself yet: sandbox web start works either way and runs it until sandbox web stop (or a restart of the PC)."
26629
+ "(Beta) The web UI: your sandbox sessions in a browser on this PC (http://127.0.0.1:<port>, this PC only). On: every sandbox start also starts it in the background (it keeps running until sandbox web stop or a restart of the PC). Off: only sandbox web start runs it. Open it signed in with sandbox web open."
26625
26630
  ),
26626
- port: external_exports.number().int().min(1024).max(65535).describe("Port of the web UI on 127.0.0.1 (this PC only). Pick another when it is taken.")
26631
+ port: external_exports.number().int().min(1024).max(65535).describe("Port of the web UI on 127.0.0.1 (this PC only). Pick another when it is taken."),
26632
+ openOnLaunch: external_exports.boolean().describe("(Beta) With the web UI on: open it in your browser, already signed in, every time a sandbox starts.")
26627
26633
  });
26628
26634
 
26629
26635
  // src/core/schema/vpn.ts
26630
26636
  var VPN_PROVIDERS = ["nordvpn", "openvpn-file", "wireguard-file"];
26631
26637
  var VpnSchema = external_exports.strictObject({
26632
26638
  enabled: external_exports.boolean().describe(
26633
- "Send the sandbox's traffic through a VPN. Only the sandbox: your PC's own connection is untouched. Needs a saved login first (sandbox vpn login). The agent in the sandbox can read that login and can turn the tunnel off (it is the administrator there)."
26639
+ "(Alpha: not yet tried on a real PC) Send the sandbox's traffic through a VPN. Only the sandbox: your PC's own connection is untouched. Needs a saved login first (sandbox vpn login). The agent in the sandbox can read that login and can turn the tunnel off (it is the administrator there)."
26634
26640
  ),
26635
26641
  provider: external_exports.enum(VPN_PROVIDERS).describe(
26636
26642
  "nordvpn: a recommended NordVPN server is picked at every launch. openvpn-file: your own .ovpn file (configFile). wireguard-file: your own WireGuard .conf (configFile), e.g. from your company."
@@ -26645,6 +26651,13 @@ var VpnSchema = external_exports.strictObject({
26645
26651
  )
26646
26652
  });
26647
26653
 
26654
+ // src/core/schema/github.ts
26655
+ var GithubSchema = external_exports.strictObject({
26656
+ shareToken: external_exports.boolean().describe(
26657
+ 'Give each sandbox the GitHub token you saved with `sandbox github login` (best a fine-grained token limited to some repositories and permissions), so gh and https git work there without logging in. Only with provisioning.git.access "full". The agent in the sandbox can read the token and use it for whatever it allows. A project file (.sandbox-config.json) cannot turn this on.'
26658
+ )
26659
+ });
26660
+
26648
26661
  // src/core/schema/config.ts
26649
26662
  var ConfigSchema = external_exports.strictObject({
26650
26663
  $schema: SchemaRefSchema.optional(),
@@ -26675,6 +26688,7 @@ var ConfigSchema = external_exports.strictObject({
26675
26688
  }),
26676
26689
  network: NetworkSchema,
26677
26690
  vpn: VpnSchema,
26691
+ github: GithubSchema,
26678
26692
  provisioning: ProvisioningSchema,
26679
26693
  downloads: DownloadsSchema,
26680
26694
  toolchains: ToolchainsSchema,
@@ -26837,19 +26851,25 @@ var GuestRequestSchema = external_exports.discriminatedUnion("kind", [
26837
26851
  id: IdSchema,
26838
26852
  reason: Text(300),
26839
26853
  seconds: external_exports.number().int().min(10).max(300),
26854
+ /** "severe": the PC is nearly out of memory; builds go to the governor's last step at once. */
26855
+ level: external_exports.enum(["slow", "severe"]).optional(),
26840
26856
  createdAt: TimeSchema
26841
26857
  })
26842
26858
  ]);
26843
26859
  var PressureStatusSchema = external_exports.object({
26844
26860
  level: external_exports.enum(["ok", "throttled", "suspending"]),
26861
+ /** The governor's dial, 0 (nothing wrong) to 4 (one compiler at a time). */
26862
+ step: external_exports.number().int().min(0).max(4).optional(),
26845
26863
  profile: external_exports.enum(["normal", "gentle"]),
26846
26864
  /** Share of the sandbox's RAM still free and of its commit limit in use (percent). */
26847
26865
  ramFreePercent: external_exports.number().int().min(0).max(100),
26848
26866
  commitPercent: external_exports.number().int().min(0).max(100),
26849
26867
  /** Programs running at lower priority because of it. */
26850
26868
  lowered: external_exports.number().int().min(0).max(1024),
26851
- /** Programs paused right now (name, process id, seconds left). */
26869
+ /** Compilers waiting their turn right now (name, process id, seconds until they may go on). */
26852
26870
  paused: external_exports.array(external_exports.object({ name: Text(64), pid: external_exports.number().int(), seconds: external_exports.number().int().min(0).max(60) })).max(8),
26871
+ /** The CPU share the compilers get together (percent; 100 = no cap). */
26872
+ cpuPercent: external_exports.number().int().min(0).max(100).optional(),
26853
26873
  /** The PC itself asked for slowing down (its memory or CPU is low). */
26854
26874
  pcLow: external_exports.boolean(),
26855
26875
  lastAction: Text(300),
@@ -26893,6 +26913,8 @@ var VpnStatusSchema = external_exports.object({
26893
26913
  state: external_exports.enum(["off", "starting", "up", "failed"]),
26894
26914
  message: Text(2e3),
26895
26915
  killSwitch: external_exports.boolean(),
26916
+ /** A direct connection was tried after the kill switch was applied: false = it still got out. */
26917
+ killSwitchHeld: external_exports.boolean().optional(),
26896
26918
  /** The server's name, e.g. uk2201.nordvpn.com. */
26897
26919
  server: Text(128).optional(),
26898
26920
  /** What the sandbox's traffic looks like from outside, once the tunnel is up. */
@@ -27040,6 +27062,59 @@ function safeRemove(target, root) {
27040
27062
  fs3.rmSync(target, { recursive: true, force: true, maxRetries: 2 });
27041
27063
  }
27042
27064
 
27065
+ // src/shared/io/robocopy-result.ts
27066
+ function robocopyFailed(code) {
27067
+ return code === null || code >= 8;
27068
+ }
27069
+ function robocopyMeaning(code) {
27070
+ if (code === null) return "robocopy did not finish";
27071
+ if (code >= 16) return "robocopy stopped with a fatal error (bad path or no access)";
27072
+ if (code >= 8) return code & 1 ? "some files were copied and some could not be" : "files could not be copied";
27073
+ return code === 0 ? "nothing to copy" : "copied";
27074
+ }
27075
+ function robocopyErrors(output2, max = 3) {
27076
+ const lines = output2.split(/\r?\n/).map((l) => l.trim()).filter((l) => /\bERROR\b/.test(l) || /^The (process|system) cannot/i.test(l));
27077
+ return lines.slice(0, max).map((l) => l.length > 220 ? l.slice(0, 217) + "..." : l);
27078
+ }
27079
+
27080
+ // src/shared/io/copy-tree.ts
27081
+ import fs4 from "node:fs";
27082
+ import path6 from "node:path";
27083
+ var isGone = (e) => e?.code === "ENOENT";
27084
+ function copyTreeTolerant(from, to, skip = () => false) {
27085
+ let copied = 0;
27086
+ let vanished = 0;
27087
+ const walk = (src, dest) => {
27088
+ fs4.mkdirSync(dest, { recursive: true });
27089
+ let entries2;
27090
+ try {
27091
+ entries2 = fs4.readdirSync(src, { withFileTypes: true });
27092
+ } catch (e) {
27093
+ if (!isGone(e)) throw e;
27094
+ vanished++;
27095
+ return;
27096
+ }
27097
+ for (const entry of entries2) {
27098
+ if (skip(entry.name)) continue;
27099
+ const source = path6.join(src, entry.name);
27100
+ const target = path6.join(dest, entry.name);
27101
+ try {
27102
+ if (entry.isDirectory()) walk(source, target);
27103
+ else if (entry.isFile()) {
27104
+ fs4.copyFileSync(source, target);
27105
+ copied++;
27106
+ }
27107
+ } catch (e) {
27108
+ if (!isGone(e)) throw e;
27109
+ vanished++;
27110
+ fs4.rmSync(target, { force: true });
27111
+ }
27112
+ }
27113
+ };
27114
+ walk(from, to);
27115
+ return { copied, vanished };
27116
+ }
27117
+
27043
27118
  // src/shared/channel/run-dir.ts
27044
27119
  function safeId(id) {
27045
27120
  return IdSchema.parse(id);
@@ -27048,14 +27123,14 @@ function now() {
27048
27123
  return (/* @__PURE__ */ new Date()).toISOString();
27049
27124
  }
27050
27125
  var scan = (schema, dir) => {
27051
- if (!fs4.existsSync(dir)) return { valid: [], invalid: [] };
27126
+ if (!fs5.existsSync(dir)) return { valid: [], invalid: [] };
27052
27127
  const valid = [];
27053
27128
  const invalid = [];
27054
- for (const name of fs4.readdirSync(dir)) {
27129
+ for (const name of fs5.readdirSync(dir)) {
27055
27130
  if (name.endsWith(".tmp")) continue;
27056
- const message = /^[A-Za-z0-9_-]{1,64}\.json$/.test(name) ? readValid(schema, path6.join(dir, name)) : null;
27131
+ const message = /^[A-Za-z0-9_-]{1,64}\.json$/.test(name) ? readValid(schema, path7.join(dir, name)) : null;
27057
27132
  if (message) valid.push(message);
27058
- else invalid.push(path6.join(dir, name));
27133
+ else invalid.push(path7.join(dir, name));
27059
27134
  }
27060
27135
  return { valid, invalid };
27061
27136
  };
@@ -27065,6 +27140,8 @@ var RunDir = class {
27065
27140
  vpnFile;
27066
27141
  /** What the memory governor in the sandbox is doing (pressure.json). */
27067
27142
  pressureFile;
27143
+ /** What the sandbox's programs may really use (budget.json): processors, memory, build jobs, link slots. */
27144
+ budgetFile;
27068
27145
  requestsDir;
27069
27146
  responsesDir;
27070
27147
  sessionsDir;
@@ -27074,31 +27151,32 @@ var RunDir = class {
27074
27151
  /** One-shot secrets the host hands over (see secrets.ts). Next to run, not in it: shared-use users can change run. */
27075
27152
  secretsDir;
27076
27153
  constructor(dataDir2) {
27077
- this.root = path6.join(dataDir2, "run");
27078
- this.sandboxFile = path6.join(this.root, "sandbox.json");
27079
- this.vpnFile = path6.join(this.root, "vpn.json");
27080
- this.pressureFile = path6.join(this.root, "pressure.json");
27081
- this.requestsDir = path6.join(this.root, "requests");
27082
- this.responsesDir = path6.join(this.root, "responses");
27083
- this.sessionsDir = path6.join(this.root, "sessions");
27084
- this.projectsDir = path6.join(this.root, "projects");
27085
- this.auditDir = path6.join(this.root, "audit");
27086
- this.secretsDir = path6.join(dataDir2, "secrets");
27154
+ this.root = path7.join(dataDir2, "run");
27155
+ this.sandboxFile = path7.join(this.root, "sandbox.json");
27156
+ this.vpnFile = path7.join(this.root, "vpn.json");
27157
+ this.pressureFile = path7.join(this.root, "pressure.json");
27158
+ this.budgetFile = path7.join(this.root, "budget.json");
27159
+ this.requestsDir = path7.join(this.root, "requests");
27160
+ this.responsesDir = path7.join(this.root, "responses");
27161
+ this.sessionsDir = path7.join(this.root, "sessions");
27162
+ this.projectsDir = path7.join(this.root, "projects");
27163
+ this.auditDir = path7.join(this.root, "audit");
27164
+ this.secretsDir = path7.join(dataDir2, "secrets");
27087
27165
  }
27088
27166
  requestFile(id) {
27089
- return path6.join(this.requestsDir, safeId(id) + ".json");
27167
+ return path7.join(this.requestsDir, safeId(id) + ".json");
27090
27168
  }
27091
27169
  responseFile(id) {
27092
- return path6.join(this.responsesDir, safeId(id) + ".json");
27170
+ return path7.join(this.responsesDir, safeId(id) + ".json");
27093
27171
  }
27094
27172
  sessionFile(id) {
27095
- return path6.join(this.sessionsDir, safeId(id) + ".json");
27173
+ return path7.join(this.sessionsDir, safeId(id) + ".json");
27096
27174
  }
27097
27175
  projectFile(name) {
27098
- return path6.join(this.projectsDir, safeId(name) + ".json");
27176
+ return path7.join(this.projectsDir, safeId(name) + ".json");
27099
27177
  }
27100
27178
  secretFile(id) {
27101
- return path6.join(this.secretsDir, safeId(id) + ".json");
27179
+ return path7.join(this.secretsDir, safeId(id) + ".json");
27102
27180
  }
27103
27181
  readSandboxStatus() {
27104
27182
  return readValid(SandboxStatusSchema, this.sandboxFile);
@@ -27137,19 +27215,19 @@ var launchDir = process.env.AGENT_LAUNCH_DIR ?? "C:\\AgentLaunch";
27137
27215
  var dataDir = process.env.AGENT_DATA_DIR ?? "C:\\AgentData";
27138
27216
  var hostToolsDir = process.env.AGENT_HOST_TOOLS_DIR ?? "C:\\HostTools";
27139
27217
  var localDir = process.env.AGENT_LOCAL_DIR ?? "C:\\nvm";
27140
- var toolsDir = path7.join(dataDir, "tools");
27141
- var logsDir = path7.join(dataDir, "logs");
27218
+ var toolsDir = path8.join(dataDir, "tools");
27219
+ var logsDir = path8.join(dataDir, "logs");
27142
27220
  var run = new RunDir(dataDir);
27143
27221
 
27144
27222
  // src/guest/runtime/log.ts
27145
- fs5.mkdirSync(logsDir, { recursive: true });
27146
- var logFile = path8.join(
27223
+ fs6.mkdirSync(logsDir, { recursive: true });
27224
+ var logFile = path9.join(
27147
27225
  logsDir,
27148
27226
  (process.env.AGENT_LOG_PREFIX ?? "guest") + "-" + (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-") + ".log"
27149
27227
  );
27150
27228
  var append = (line) => {
27151
27229
  try {
27152
- fs5.appendFileSync(logFile, line + "\n");
27230
+ fs6.appendFileSync(logFile, line + "\n");
27153
27231
  } catch {
27154
27232
  }
27155
27233
  };
@@ -27163,8 +27241,8 @@ function warn(message) {
27163
27241
  }
27164
27242
 
27165
27243
  // src/guest/runtime/session.ts
27166
- import fs9 from "node:fs";
27167
- import path13 from "node:path";
27244
+ import fs10 from "node:fs";
27245
+ import path14 from "node:path";
27168
27246
 
27169
27247
  // src/shared/download/http.ts
27170
27248
  var USER_AGENT = "windows-development-sandbox";
@@ -27195,15 +27273,15 @@ async function fetchText(url2) {
27195
27273
  }
27196
27274
 
27197
27275
  // src/shared/download/archive.ts
27198
- import fs7 from "node:fs";
27199
- import path11 from "node:path";
27276
+ import fs8 from "node:fs";
27277
+ import path12 from "node:path";
27200
27278
  import crypto from "node:crypto";
27201
27279
 
27202
27280
  // src/shared/system.ts
27203
- import path9 from "node:path";
27281
+ import path10 from "node:path";
27204
27282
  var systemRoot = () => process.env.SystemRoot ?? process.env.WINDIR ?? "C:\\Windows";
27205
27283
  function system32(exe) {
27206
- return path9.join(systemRoot(), "System32", exe);
27284
+ return path10.join(systemRoot(), "System32", exe);
27207
27285
  }
27208
27286
  var SYSTEM = {
27209
27287
  cmd: () => system32("cmd.exe"),
@@ -27223,17 +27301,17 @@ var SYSTEM = {
27223
27301
  msiexec: () => system32("msiexec.exe"),
27224
27302
  sc: () => system32("sc.exe"),
27225
27303
  /** The .NET Framework C# compiler that ships with Windows (C# 5). */
27226
- csc: () => path9.join(systemRoot(), "Microsoft.NET", "Framework64", "v4.0.30319", "csc.exe")
27304
+ csc: () => path10.join(systemRoot(), "Microsoft.NET", "Framework64", "v4.0.30319", "csc.exe")
27227
27305
  };
27228
27306
 
27229
27307
  // src/shared/scripts.ts
27230
- import fs6 from "node:fs";
27231
- import path10 from "node:path";
27308
+ import fs7 from "node:fs";
27309
+ import path11 from "node:path";
27232
27310
  import { fileURLToPath } from "node:url";
27233
- var HERE = path10.dirname(fileURLToPath(import.meta.url));
27311
+ var HERE = path11.dirname(fileURLToPath(import.meta.url));
27234
27312
  function sandboxScriptsDir() {
27235
- const candidates = [path10.resolve(HERE, "..", "sandbox"), path10.resolve(HERE, "..", "..", "sandbox")];
27236
- return candidates.find((dir) => fs6.existsSync(path10.join(dir, "boot", "bootstrap.ps1"))) ?? candidates[candidates.length - 1];
27313
+ const candidates = [path11.resolve(HERE, "..", "sandbox"), path11.resolve(HERE, "..", "..", "sandbox")];
27314
+ return candidates.find((dir) => fs7.existsSync(path11.join(dir, "boot", "bootstrap.ps1"))) ?? candidates[candidates.length - 1];
27237
27315
  }
27238
27316
  function scriptArgs(name, args = []) {
27239
27317
  return [
@@ -27243,7 +27321,7 @@ function scriptArgs(name, args = []) {
27243
27321
  "-ExecutionPolicy",
27244
27322
  "Bypass",
27245
27323
  "-File",
27246
- path10.join(sandboxScriptsDir(), "scripts", name),
27324
+ path11.join(sandboxScriptsDir(), "scripts", name),
27247
27325
  ...args
27248
27326
  ];
27249
27327
  }
@@ -27263,16 +27341,16 @@ function stagingFolder(destination) {
27263
27341
  return destination + ".staging-" + crypto.randomBytes(3).toString("hex");
27264
27342
  }
27265
27343
  function moveIntoPlace(work, destination) {
27266
- safeRemove(destination, path11.dirname(destination));
27267
- fs7.mkdirSync(path11.dirname(destination), { recursive: true });
27268
- fs7.renameSync(work, destination);
27344
+ safeRemove(destination, path12.dirname(destination));
27345
+ fs8.mkdirSync(path12.dirname(destination), { recursive: true });
27346
+ fs8.renameSync(work, destination);
27269
27347
  }
27270
27348
  async function extractArchive(archive, destination, members2 = []) {
27271
- fs7.mkdirSync(destination, { recursive: true });
27349
+ fs8.mkdirSync(destination, { recursive: true });
27272
27350
  let status = await spawnAsync(SYSTEM.tar(), ["-xf", archive, "-C", destination, ...members2]);
27273
27351
  if (status !== 0 && /\.(zip|nupkg)$/i.test(archive)) {
27274
27352
  const zip = archive.endsWith(".zip") ? archive : archive + ".zip";
27275
- if (zip !== archive) fs7.copyFileSync(archive, zip);
27353
+ if (zip !== archive) fs8.copyFileSync(archive, zip);
27276
27354
  status = await spawnAsync(
27277
27355
  SYSTEM.powershell(),
27278
27356
  scriptArgs("expand-archive.ps1", ["-Archive", zip, "-Destination", destination])
@@ -27281,21 +27359,21 @@ async function extractArchive(archive, destination, members2 = []) {
27281
27359
  if (status !== 0) throw new Error("Could not extract " + archive);
27282
27360
  }
27283
27361
  function findFile(root, name, maxDepth = 4) {
27284
- if (maxDepth < 0 || !fs7.existsSync(root)) return null;
27285
- const entries2 = fs7.readdirSync(root, { withFileTypes: true });
27362
+ if (maxDepth < 0 || !fs8.existsSync(root)) return null;
27363
+ const entries2 = fs8.readdirSync(root, { withFileTypes: true });
27286
27364
  for (const entry of entries2)
27287
- if (entry.isFile() && entry.name.toLowerCase() === name.toLowerCase()) return path11.join(root, entry.name);
27365
+ if (entry.isFile() && entry.name.toLowerCase() === name.toLowerCase()) return path12.join(root, entry.name);
27288
27366
  for (const entry of entries2)
27289
27367
  if (entry.isDirectory()) {
27290
- const found = findFile(path11.join(root, entry.name), name, maxDepth - 1);
27368
+ const found = findFile(path12.join(root, entry.name), name, maxDepth - 1);
27291
27369
  if (found) return found;
27292
27370
  }
27293
27371
  return null;
27294
27372
  }
27295
27373
 
27296
27374
  // src/shared/download/downloader.ts
27297
- import fs8 from "node:fs";
27298
- import path12 from "node:path";
27375
+ import fs9 from "node:fs";
27376
+ import path13 from "node:path";
27299
27377
  import crypto2 from "node:crypto";
27300
27378
  import { Readable, Transform } from "node:stream";
27301
27379
  import { pipeline } from "node:stream/promises";
@@ -27316,12 +27394,12 @@ var Downloader = class {
27316
27394
  const sums = typeof expected === "string" || expected === null ? { sha256: expected } : expected;
27317
27395
  if (this.requireChecksum && !sums.sha256?.trim() && !sums.sha512?.trim()) {
27318
27396
  throw new Error(
27319
- "Refusing to download " + path12.basename(destination) + " (" + url2 + "): no checksum is published for it, and downloads.requireChecksum is on. Turn that setting off to allow downloads that cannot be verified."
27397
+ "Refusing to download " + path13.basename(destination) + " (" + url2 + "): no checksum is published for it, and downloads.requireChecksum is on. Turn that setting off to allow downloads that cannot be verified."
27320
27398
  );
27321
27399
  }
27322
27400
  const response = await fetchRetry(url2, {}, 3, 20 * 60 * 1e3);
27323
27401
  if (!response.body) throw new Error("Empty response for " + url2);
27324
- fs8.mkdirSync(path12.dirname(destination), { recursive: true });
27402
+ fs9.mkdirSync(path13.dirname(destination), { recursive: true });
27325
27403
  const checks = ["sha256", "sha512"].flatMap((kind) => {
27326
27404
  const want = sums[kind]?.trim().toLowerCase();
27327
27405
  return want ? [{ want, hash: crypto2.createHash(kind) }] : [];
@@ -27351,12 +27429,12 @@ var Downloader = class {
27351
27429
  });
27352
27430
  const partial2 = destination + ".part";
27353
27431
  try {
27354
- await pipeline(Readable.fromWeb(response.body), tap, fs8.createWriteStream(partial2));
27432
+ await pipeline(Readable.fromWeb(response.body), tap, fs9.createWriteStream(partial2));
27355
27433
  if (checks.some((c) => c.hash.digest("hex") !== c.want)) throw new Error("Checksum mismatch for " + url2);
27356
- fs8.rmSync(destination, { force: true });
27357
- fs8.renameSync(partial2, destination);
27434
+ fs9.rmSync(destination, { force: true });
27435
+ fs9.renameSync(partial2, destination);
27358
27436
  } finally {
27359
- fs8.rmSync(partial2, { force: true });
27437
+ fs9.rmSync(partial2, { force: true });
27360
27438
  }
27361
27439
  }
27362
27440
  /**
@@ -27366,21 +27444,21 @@ var Downloader = class {
27366
27444
  async archive(url2, destination, options = {}) {
27367
27445
  const work = stagingFolder(destination);
27368
27446
  try {
27369
- const archive = path12.join(work, options.fileName ?? path12.basename(new URL(url2).pathname));
27447
+ const archive = path13.join(work, options.fileName ?? path13.basename(new URL(url2).pathname));
27370
27448
  await this.file(url2, archive, { sha256: options.sha256, sha512: options.sha512 });
27371
- const extracted = path12.join(work, "x");
27449
+ const extracted = path13.join(work, "x");
27372
27450
  await extractArchive(archive, extracted, options.members);
27373
27451
  let root = extracted;
27374
27452
  if (options.locate) {
27375
27453
  const found = findFile(extracted, options.locate);
27376
27454
  if (!found) throw new Error(options.locate + " not found in " + url2);
27377
- root = path12.dirname(found);
27378
- for (let i = 0; i < (options.up ?? 0) && path12.dirname(root).startsWith(extracted); i++)
27379
- root = path12.dirname(root);
27455
+ root = path13.dirname(found);
27456
+ for (let i = 0; i < (options.up ?? 0) && path13.dirname(root).startsWith(extracted); i++)
27457
+ root = path13.dirname(root);
27380
27458
  }
27381
27459
  moveIntoPlace(root, destination);
27382
27460
  } finally {
27383
- safeRemove(work, path12.dirname(work));
27461
+ safeRemove(work, path13.dirname(work));
27384
27462
  }
27385
27463
  }
27386
27464
  };
@@ -27458,12 +27536,12 @@ var githubAssetFromPage = async (repo, pattern, searchOlder) => {
27458
27536
 
27459
27537
  // src/guest/runtime/session.ts
27460
27538
  var session = JSON.parse(
27461
- fs9.readFileSync(path13.join(launchDir, "session.json"), "utf8").replace(/^\uFEFF/, "")
27539
+ fs10.readFileSync(path14.join(launchDir, "session.json"), "utf8").replace(/^\uFEFF/, "")
27462
27540
  );
27463
27541
  downloader.requireChecksum = session.downloads?.requireChecksum === true;
27464
27542
  var workspace = process.env.AGENT_WORKSPACE ?? session.workspace;
27465
- var stateDir = path13.join(dataDir, session.persistAgentState ? "state" : "state-session");
27466
- var claudeDir = path13.join(stateDir, "claude");
27543
+ var stateDir = path14.join(dataDir, session.persistAgentState ? "state" : "state-session");
27544
+ var claudeDir = path14.join(stateDir, "claude");
27467
27545
 
27468
27546
  // src/core/util/errors.ts
27469
27547
  function errMsg(e) {
@@ -27489,12 +27567,12 @@ function startRelays() {
27489
27567
  }
27490
27568
 
27491
27569
  // src/guest/audit/process-audit.ts
27492
- import fs11 from "node:fs";
27493
- import path15 from "node:path";
27570
+ import fs12 from "node:fs";
27571
+ import path16 from "node:path";
27494
27572
  import { spawnSync } from "node:child_process";
27495
27573
 
27496
27574
  // src/guest/audit/parse.ts
27497
- import path14 from "node:path";
27575
+ import path15 from "node:path";
27498
27576
  var NOISE = /* @__PURE__ */ new Set([
27499
27577
  "conhost.exe",
27500
27578
  "svchost.exe",
@@ -27531,7 +27609,7 @@ function parseProcessEvents(xml) {
27531
27609
  if (!id) continue;
27532
27610
  last = Math.max(last, id);
27533
27611
  const program = field(event, "NewProcessName");
27534
- if (!program || NOISE.has(path14.win32.basename(program).toLowerCase())) continue;
27612
+ if (!program || NOISE.has(path15.win32.basename(program).toLowerCase())) continue;
27535
27613
  const t = /SystemTime='([^']+)'/.exec(event)?.[1] ?? (/* @__PURE__ */ new Date()).toISOString();
27536
27614
  lines.push(
27537
27615
  JSON.stringify({
@@ -27547,19 +27625,19 @@ function parseProcessEvents(xml) {
27547
27625
  }
27548
27626
 
27549
27627
  // src/guest/runtime/fs.ts
27550
- import fs10 from "node:fs";
27628
+ import fs11 from "node:fs";
27551
27629
  function exists(p) {
27552
- return fs10.existsSync(p);
27630
+ return fs11.existsSync(p);
27553
27631
  }
27554
27632
  function mkdirp(p) {
27555
- fs10.mkdirSync(p, { recursive: true });
27633
+ fs11.mkdirSync(p, { recursive: true });
27556
27634
  return p;
27557
27635
  }
27558
27636
 
27559
27637
  // src/guest/audit/process-audit.ts
27560
27638
  var MAX_PER_PASS = 2e3;
27561
27639
  var auditOn = () => Boolean(session.auditProcesses) && isWin && !dryRun;
27562
- var wevtutil = () => path15.join(process.env.WINDIR ?? "C:\\Windows", "System32", "wevtutil.exe");
27640
+ var wevtutil = () => path16.join(process.env.WINDIR ?? "C:\\Windows", "System32", "wevtutil.exe");
27563
27641
  var newestRecord = () => {
27564
27642
  const r = spawnSync(wevtutil(), ["qe", "Security", "/q:*[System[(EventID=4688)]]", "/f:xml", "/c:1", "/rd:true"], {
27565
27643
  encoding: "utf8",
@@ -27586,8 +27664,8 @@ function startProcessCollector() {
27586
27664
  const { lines, last: newest } = parseProcessEvents(r.stdout ?? "");
27587
27665
  if (newest) last = newest;
27588
27666
  if (lines.length)
27589
- fs11.writeFileSync(
27590
- path15.join(mkdirp(run.auditDir), Date.now() + "-" + process.pid + ".jsonl"),
27667
+ fs12.writeFileSync(
27668
+ path16.join(mkdirp(run.auditDir), Date.now() + "-" + process.pid + ".jsonl"),
27591
27669
  lines.join("\n") + "\n"
27592
27670
  );
27593
27671
  } catch (e) {
@@ -27598,14 +27676,14 @@ function startProcessCollector() {
27598
27676
  }
27599
27677
 
27600
27678
  // src/guest/daemon/state.ts
27601
- import path16 from "node:path";
27679
+ import path17 from "node:path";
27602
27680
  var MAX_MESSAGE = 3500;
27603
27681
  function insidePrimary(cwd) {
27604
- const rel = path16.relative(workspace.toLowerCase(), path16.resolve(cwd).toLowerCase());
27605
- return rel === "" || !rel.startsWith("..") && !path16.isAbsolute(rel);
27682
+ const rel = path17.relative(workspace.toLowerCase(), path17.resolve(cwd).toLowerCase());
27683
+ return rel === "" || !rel.startsWith("..") && !path17.isAbsolute(rel);
27606
27684
  }
27607
27685
  function insideWorkspace(cwd) {
27608
- return insidePrimary(cwd) || session.projectsDir !== void 0 && insideProjects(path16.resolve(cwd), session.roots ?? [], session.projectsDir);
27686
+ return insidePrimary(cwd) || session.projectsDir !== void 0 && insideProjects(path17.resolve(cwd), session.roots ?? [], session.projectsDir);
27609
27687
  }
27610
27688
  function tryWrite(file3, value) {
27611
27689
  try {
@@ -27629,7 +27707,13 @@ function safely(what, work) {
27629
27707
  }
27630
27708
 
27631
27709
  // src/guest/runtime/secrets.ts
27632
- import fs12 from "node:fs";
27710
+ import fs13 from "node:fs";
27711
+
27712
+ // src/shared/github/token.ts
27713
+ var MIN_LENGTH = 20;
27714
+ var MAX_LENGTH = 255;
27715
+ var PRINTABLE = /^[\x21-\x7e]+$/;
27716
+ var GithubTokenSchema = external_exports.string().min(MIN_LENGTH).max(MAX_LENGTH).regex(PRINTABLE);
27633
27717
 
27634
27718
  // src/shared/channel/secrets.ts
27635
27719
  var Environment = external_exports.record(external_exports.string().max(256), external_exports.string().max(65536));
@@ -27645,7 +27729,9 @@ var SecretsFileSchema = external_exports.strictObject({
27645
27729
  /** VPN service credentials (vpn.provider's login), only for the launch's own sandbox. */
27646
27730
  vpn: external_exports.strictObject({ username: external_exports.string().min(1).max(256), password: external_exports.string().min(1).max(1024) }).optional(),
27647
27731
  /** The checked WireGuard config of vpn.provider wireguard-file (holds the private key). */
27648
- wireguardConfig: external_exports.string().min(1).max(32 * 1024).optional()
27732
+ wireguardConfig: external_exports.string().min(1).max(32 * 1024).optional(),
27733
+ /** The GitHub token you saved for sandboxes (github.shareToken), only with git access "full". */
27734
+ githubToken: GithubTokenSchema.optional()
27649
27735
  });
27650
27736
  var withEnvironment = (harness, environment) => environment ? { ...harness, environment: { ...harness.environment, ...environment } } : harness;
27651
27737
  function mergeRequestSecrets(request, secrets) {
@@ -27674,12 +27760,12 @@ function takeSecrets(id) {
27674
27760
  const file3 = run.secretFile(id);
27675
27761
  let text;
27676
27762
  try {
27677
- if (fs12.statSync(file3).size > MAX_BYTES) throw new Error("too big");
27678
- text = fs12.readFileSync(file3, "utf8").replace(/^\uFEFF/, "");
27763
+ if (fs13.statSync(file3).size > MAX_BYTES) throw new Error("too big");
27764
+ text = fs13.readFileSync(file3, "utf8").replace(/^\uFEFF/, "");
27679
27765
  } catch {
27680
27766
  return {};
27681
27767
  } finally {
27682
- fs12.rmSync(file3, { force: true });
27768
+ fs13.rmSync(file3, { force: true });
27683
27769
  }
27684
27770
  try {
27685
27771
  const parsed = SecretsFileSchema.safeParse(JSON.parse(text));
@@ -27709,95 +27795,127 @@ function withRequestSecrets(req) {
27709
27795
  }
27710
27796
 
27711
27797
  // src/guest/daemon/daemon.ts
27712
- import fs53 from "node:fs";
27798
+ import fs54 from "node:fs";
27713
27799
 
27714
27800
  // src/guest/setup/claude-mem.ts
27715
- import fs14 from "node:fs";
27801
+ import fs15 from "node:fs";
27716
27802
  import os4 from "node:os";
27717
- import path18 from "node:path";
27803
+ import path19 from "node:path";
27718
27804
 
27719
27805
  // src/guest/runtime/process.ts
27720
- import fs13 from "node:fs";
27806
+ import fs14 from "node:fs";
27721
27807
  import os3 from "node:os";
27722
- import path17 from "node:path";
27808
+ import path18 from "node:path";
27723
27809
  import { spawnSync as spawnSync2 } from "node:child_process";
27724
- function exec(file3, args, options = {}) {
27725
- const result = spawnSync2(file3, args, { stdio: "inherit", windowsHide: true, ...options });
27726
- if (result.error) throw result.error;
27727
- if (result.status !== 0)
27728
- throw new Error(path17.basename(file3) + " " + args.slice(0, 3).join(" ") + " failed with exit code " + result.status);
27729
- }
27730
27810
  async function execAsync(file3, args, options = {}) {
27731
27811
  const code = await spawnAsync(file3, args, { stdio: "inherit", ...options });
27732
27812
  if (code !== 0)
27733
- throw new Error(path17.basename(file3) + " " + args.slice(0, 3).join(" ") + " failed with exit code " + code);
27813
+ throw new Error(path18.basename(file3) + " " + args.slice(0, 3).join(" ") + " failed with exit code " + code);
27734
27814
  }
27735
27815
  function execOutput(file3, args, options = {}) {
27736
27816
  const result = spawnSync2(file3, args, { encoding: "utf8", windowsHide: true, ...options });
27737
27817
  return result.status === 0 ? String(result.stdout ?? "").trim() : "";
27738
27818
  }
27739
27819
  function runScript(name, args = []) {
27740
- exec(SYSTEM.powershell(), scriptArgs(name, args));
27820
+ const result = spawnSync2(SYSTEM.powershell(), scriptArgs(name, args), {
27821
+ stdio: ["inherit", "inherit", "pipe"],
27822
+ encoding: "utf8",
27823
+ windowsHide: true
27824
+ });
27825
+ if (result.error) throw result.error;
27826
+ const errors = String(result.stderr ?? "").trim();
27827
+ if (errors) process.stderr.write(errors + "\n");
27828
+ if (result.status !== 0)
27829
+ throw new Error(name + " failed with exit code " + result.status + (errors ? ": " + errors.slice(0, 400) : ""));
27741
27830
  }
27742
27831
  function scriptOutput(name, args = [], options = {}) {
27743
27832
  return execOutput(SYSTEM.powershell(), scriptArgs(name, args), options);
27744
27833
  }
27745
27834
  function runScriptWithJson(name, param, data, args = []) {
27746
- const dir = fs13.mkdtempSync(path17.join(os3.tmpdir(), "sbx-"));
27747
- const file3 = path17.join(dir, "input.json");
27835
+ const dir = fs14.mkdtempSync(path18.join(os3.tmpdir(), "sbx-"));
27836
+ const file3 = path18.join(dir, "input.json");
27748
27837
  try {
27749
- fs13.writeFileSync(file3, JSON.stringify(data), "utf8");
27838
+ fs14.writeFileSync(file3, JSON.stringify(data), "utf8");
27750
27839
  runScript(name, ["-" + param, file3, ...args]);
27751
27840
  } finally {
27752
- fs13.rmSync(dir, { recursive: true, force: true });
27841
+ fs14.rmSync(dir, { recursive: true, force: true });
27753
27842
  }
27754
27843
  }
27755
27844
  function robocopy(from, to, files = []) {
27756
27845
  if (!isWin) {
27757
27846
  if (!files.length) {
27758
- fs13.cpSync(from, to, { recursive: true });
27847
+ fs14.cpSync(from, to, { recursive: true });
27759
27848
  return;
27760
27849
  }
27761
- fs13.mkdirSync(to, { recursive: true });
27762
- for (const f of files.filter((f2) => fs13.existsSync(path17.join(from, f2))))
27763
- fs13.copyFileSync(path17.join(from, f), path17.join(to, f));
27850
+ fs14.mkdirSync(to, { recursive: true });
27851
+ for (const f of files.filter((f2) => fs14.existsSync(path18.join(from, f2))))
27852
+ fs14.copyFileSync(path18.join(from, f), path18.join(to, f));
27764
27853
  return;
27765
27854
  }
27766
- const what = files.length ? files : ["/E", "/MT:16"];
27767
- const result = spawnSync2(
27768
- SYSTEM.robocopy(),
27769
- [from, to, ...what, "/NFL", "/NDL", "/NJH", "/NJS", "/NP", "/R:1", "/W:1", "/XJ"],
27770
- { stdio: "ignore", windowsHide: true }
27855
+ const what = files.length ? files : ["/E"];
27856
+ const passes = [
27857
+ ["/MT:16", "/R:1", "/W:1"],
27858
+ ["/MT:1", "/R:4", "/W:3"]
27859
+ ];
27860
+ let code = null;
27861
+ let output2 = "";
27862
+ for (const pass of passes) {
27863
+ const result = spawnSync2(
27864
+ SYSTEM.robocopy(),
27865
+ [
27866
+ from,
27867
+ to,
27868
+ ...what,
27869
+ ...files.length ? [] : [pass[0]],
27870
+ pass[1],
27871
+ pass[2],
27872
+ "/NFL",
27873
+ "/NDL",
27874
+ "/NJH",
27875
+ "/NJS",
27876
+ "/NP",
27877
+ "/XJ"
27878
+ ],
27879
+ { encoding: "utf8", windowsHide: true }
27880
+ );
27881
+ code = result.status;
27882
+ output2 = String(result.stdout ?? "") + String(result.stderr ?? "");
27883
+ if (!robocopyFailed(code)) return;
27884
+ }
27885
+ const why = robocopyErrors(output2);
27886
+ throw new Error(
27887
+ "robocopy " + from + " -> " + to + " failed (exit " + code + ": " + robocopyMeaning(code) + ")" + (why.length ? ": " + why.join(" | ") : "")
27771
27888
  );
27772
- if ((result.status ?? 16) >= 8)
27773
- throw new Error("robocopy " + from + " -> " + to + " failed (exit " + result.status + ")");
27774
27889
  }
27775
27890
  function copyNode(from, to) {
27776
27891
  const work = stagingFolder(to);
27777
27892
  try {
27778
27893
  robocopy(from, work, ["node.exe", "npm", "npm.cmd", "npx", "npx.cmd"]);
27779
- robocopy(path17.join(from, "node_modules", "npm"), path17.join(work, "node_modules", "npm"));
27894
+ robocopy(path18.join(from, "node_modules", "npm"), path18.join(work, "node_modules", "npm"));
27780
27895
  moveIntoPlace(work, to);
27781
27896
  } finally {
27782
- safeRemove(work, path17.dirname(work));
27897
+ safeRemove(work, path18.dirname(work));
27783
27898
  }
27784
27899
  }
27785
27900
 
27786
27901
  // src/guest/setup/claude-mem.ts
27787
27902
  var claudeMemPaths = {
27788
- store: path18.join(stateDir, "claude-mem"),
27789
- local: path18.join(os4.homedir(), ".claude-mem")
27903
+ store: path19.join(stateDir, "claude-mem"),
27904
+ local: path19.join(os4.homedir(), ".claude-mem")
27790
27905
  };
27791
27906
  var claudeMemEnabled = () => session.claudeProfile.syncClaudeMem && !dryRun;
27792
27907
  var databaseFingerprint = (dir) => {
27793
27908
  const parts2 = [];
27794
27909
  const walk = (folder) => {
27795
- for (const entry of fs14.readdirSync(folder, { withFileTypes: true })) {
27796
- const full = path18.join(folder, entry.name);
27910
+ for (const entry of fs15.readdirSync(folder, { withFileTypes: true })) {
27911
+ const full = path19.join(folder, entry.name);
27797
27912
  if (entry.isDirectory()) walk(full);
27798
27913
  else if (entry.isFile() && /\.(db|sqlite3?)(-wal)?$/i.test(entry.name)) {
27799
- const s = fs14.statSync(full);
27800
- parts2.push(full + ":" + s.size + ":" + s.mtimeMs);
27914
+ try {
27915
+ const s = fs15.statSync(full);
27916
+ parts2.push(full + ":" + s.size + ":" + s.mtimeMs);
27917
+ } catch {
27918
+ }
27801
27919
  }
27802
27920
  }
27803
27921
  };
@@ -27808,34 +27926,34 @@ var lastSaved = null;
27808
27926
  var SQLITE_HEADER = "SQLite format 3\0";
27809
27927
  var looksLikeSqlite = (file3) => {
27810
27928
  if (!exists(file3)) return true;
27811
- const fd = fs14.openSync(file3, "r");
27929
+ const fd = fs15.openSync(file3, "r");
27812
27930
  try {
27813
27931
  const head = Buffer.alloc(16);
27814
- return fs14.readSync(fd, head, 0, 16, 0) === 16 && head.toString("latin1") === SQLITE_HEADER;
27932
+ return fs15.readSync(fd, head, 0, 16, 0) === 16 && head.toString("latin1") === SQLITE_HEADER;
27815
27933
  } finally {
27816
- fs14.closeSync(fd);
27934
+ fs15.closeSync(fd);
27817
27935
  }
27818
27936
  };
27819
27937
  var MAX_BACKUPS = 3;
27820
27938
  var BACKUP_EVERY_MS = 6 * 3600 * 1e3;
27821
27939
  var keepBackup = (previous, dir) => {
27822
27940
  if (!exists(previous)) return;
27823
- const backups = exists(dir) ? fs14.readdirSync(dir).filter((n) => /^\d{13}$/.test(n)).sort() : [];
27941
+ const backups = exists(dir) ? fs15.readdirSync(dir).filter((n) => /^\d{13}$/.test(n)).sort() : [];
27824
27942
  const newest = Number(backups[backups.length - 1] ?? 0);
27825
27943
  if (Date.now() - newest < BACKUP_EVERY_MS) {
27826
- fs14.rmSync(previous, { recursive: true, force: true });
27944
+ fs15.rmSync(previous, { recursive: true, force: true });
27827
27945
  return;
27828
27946
  }
27829
- fs14.renameSync(previous, path18.join(mkdirp(dir), String(Date.now())));
27947
+ fs15.renameSync(previous, path19.join(mkdirp(dir), String(Date.now())));
27830
27948
  for (const old of [...backups, String(Date.now())].slice(0, -MAX_BACKUPS))
27831
- fs14.rmSync(path18.join(dir, old), { recursive: true, force: true });
27949
+ fs15.rmSync(path19.join(dir, old), { recursive: true, force: true });
27832
27950
  };
27833
27951
  function saveClaudeMem() {
27834
27952
  if (!claudeMemEnabled() || !exists(claudeMemPaths.local)) return;
27835
27953
  const { store: store2, local } = claudeMemPaths;
27836
27954
  const fingerprint2 = databaseFingerprint(local);
27837
27955
  if (fingerprint2 === lastSaved && exists(store2)) return;
27838
- if (!looksLikeSqlite(path18.join(local, "claude-mem.db"))) {
27956
+ if (!looksLikeSqlite(path19.join(local, "claude-mem.db"))) {
27839
27957
  warn(
27840
27958
  "claude-mem: the local database does not look valid, so it was not saved over the stored copy (" + local + ")."
27841
27959
  );
@@ -27843,14 +27961,14 @@ function saveClaudeMem() {
27843
27961
  }
27844
27962
  const incoming = store2 + ".incoming";
27845
27963
  const previous = store2 + ".previous";
27846
- fs14.rmSync(incoming, { recursive: true, force: true });
27847
- fs14.cpSync(local, incoming, { recursive: true, filter: (src) => !/\.(pid|lock)$/i.test(src) });
27848
- fs14.rmSync(previous, { recursive: true, force: true });
27849
- if (exists(store2)) fs14.renameSync(store2, previous);
27964
+ fs15.rmSync(incoming, { recursive: true, force: true });
27965
+ copyTreeTolerant(local, incoming, (name) => /\.(pid|lock)$|-journal$|-shm$/i.test(name));
27966
+ fs15.rmSync(previous, { recursive: true, force: true });
27967
+ if (exists(store2)) fs15.renameSync(store2, previous);
27850
27968
  try {
27851
- fs14.renameSync(incoming, store2);
27969
+ fs15.renameSync(incoming, store2);
27852
27970
  } catch (e) {
27853
- if (exists(previous)) fs14.renameSync(previous, store2);
27971
+ if (exists(previous)) fs15.renameSync(previous, store2);
27854
27972
  throw e;
27855
27973
  }
27856
27974
  keepBackup(previous, store2 + ".backups");
@@ -27858,18 +27976,18 @@ function saveClaudeMem() {
27858
27976
  }
27859
27977
 
27860
27978
  // src/guest/agents/local-state.ts
27861
- import fs15 from "node:fs";
27862
- import path20 from "node:path";
27979
+ import fs16 from "node:fs";
27980
+ import path21 from "node:path";
27863
27981
 
27864
27982
  // src/guest/agents/agent-files.ts
27865
- import path19 from "node:path";
27983
+ import path20 from "node:path";
27866
27984
  function agentPaths(toolsDir2, name, harness) {
27867
- const dir = path19.join(toolsDir2, "agents", name);
27985
+ const dir = path20.join(toolsDir2, "agents", name);
27868
27986
  const exe = harness.hostExecutable ?? (harness.uvBin ? harness.uvBin + ".exe" : null);
27869
27987
  return {
27870
27988
  dir,
27871
- exe: exe ? path19.join(dir, exe) : null,
27872
- cmd: harness.npmBin ? path19.join(dir, harness.npmBin + ".cmd") : null
27989
+ exe: exe ? path20.join(dir, exe) : null,
27990
+ cmd: harness.npmBin ? path20.join(dir, harness.npmBin + ".cmd") : null
27873
27991
  };
27874
27992
  }
27875
27993
  function agentCommand(name, harness) {
@@ -27880,10 +27998,10 @@ function localStateEntries(agents2, stateDir2, localRoot2) {
27880
27998
  ([agent, harness]) => Object.entries(harness.localState ?? {}).map(([env, folder]) => ({
27881
27999
  agent,
27882
28000
  env,
27883
- store: path19.join(stateDir2, agent, folder),
27884
- local: path19.join(localRoot2, agent, folder),
28001
+ store: path20.join(stateDir2, agent, folder),
28002
+ local: path20.join(localRoot2, agent, folder),
27885
28003
  processes: [agentCommand(agent, harness) + ".exe"],
27886
- legacy: path19.join(stateDir2, agent)
28004
+ legacy: path20.join(stateDir2, agent)
27887
28005
  }))
27888
28006
  );
27889
28007
  }
@@ -27892,39 +28010,39 @@ var isCopyableDatabaseFile = (name) => isDatabaseFile(name) && !/-shm$/i.test(na
27892
28010
 
27893
28011
  // src/guest/agents/local-state.ts
27894
28012
  var SQLITE_HEADER2 = "SQLite format 3\0";
27895
- var localRoot = () => path20.join(localDir, "agent-state");
28013
+ var localRoot = () => path21.join(localDir, "agent-state");
27896
28014
  function agentLocalStates() {
27897
28015
  return localStateEntries(session.agents ?? {}, stateDir, localRoot());
27898
28016
  }
27899
28017
  function localStateVars() {
27900
28018
  return Object.fromEntries(agentLocalStates().map((s) => [s.env, s.local]));
27901
28019
  }
27902
- var databaseFiles = (dir, keep) => exists(dir) ? fs15.readdirSync(dir, { withFileTypes: true }).flatMap((e) => e.isFile() && keep(e.name) ? [e.name] : []) : [];
28020
+ var databaseFiles = (dir, keep) => exists(dir) ? fs16.readdirSync(dir, { withFileTypes: true }).flatMap((e) => e.isFile() && keep(e.name) ? [e.name] : []) : [];
27903
28021
  var looksLikeSqlite2 = (file3) => {
27904
- const fd = fs15.openSync(file3, "r");
28022
+ const fd = fs16.openSync(file3, "r");
27905
28023
  try {
27906
28024
  const head = Buffer.alloc(16);
27907
- return fs15.readSync(fd, head, 0, 16, 0) === 16 && head.toString("latin1") === SQLITE_HEADER2;
28025
+ return fs16.readSync(fd, head, 0, 16, 0) === 16 && head.toString("latin1") === SQLITE_HEADER2;
27908
28026
  } finally {
27909
- fs15.closeSync(fd);
28027
+ fs16.closeSync(fd);
27910
28028
  }
27911
28029
  };
27912
28030
  var copyFiles = (from, to, names) => {
27913
- fs15.rmSync(to, { recursive: true, force: true });
28031
+ fs16.rmSync(to, { recursive: true, force: true });
27914
28032
  mkdirp(to);
27915
- for (const name of names) fs15.copyFileSync(path20.join(from, name), path20.join(to, name));
28033
+ for (const name of names) fs16.copyFileSync(path21.join(from, name), path21.join(to, name));
27916
28034
  };
27917
28035
  var swapIn = (incoming, store2) => {
27918
28036
  const previous = store2 + ".previous";
27919
- fs15.rmSync(previous, { recursive: true, force: true });
27920
- if (exists(store2)) fs15.renameSync(store2, previous);
28037
+ fs16.rmSync(previous, { recursive: true, force: true });
28038
+ if (exists(store2)) fs16.renameSync(store2, previous);
27921
28039
  try {
27922
- fs15.renameSync(incoming, store2);
28040
+ fs16.renameSync(incoming, store2);
27923
28041
  } catch (e) {
27924
- if (exists(previous)) fs15.renameSync(previous, store2);
28042
+ if (exists(previous)) fs16.renameSync(previous, store2);
27925
28043
  throw e;
27926
28044
  }
27927
- fs15.rmSync(previous, { recursive: true, force: true });
28045
+ fs16.rmSync(previous, { recursive: true, force: true });
27928
28046
  };
27929
28047
  function held(s) {
27930
28048
  if (!isWin) return false;
@@ -27933,7 +28051,7 @@ function held(s) {
27933
28051
  );
27934
28052
  }
27935
28053
  var fingerprint = (dir) => databaseFiles(dir, isCopyableDatabaseFile).sort().map((n) => {
27936
- const st = fs15.statSync(path20.join(dir, n));
28054
+ const st = fs16.statSync(path21.join(dir, n));
27937
28055
  return n + ":" + st.size + ":" + st.mtimeMs;
27938
28056
  }).join("|");
27939
28057
  var saved = /* @__PURE__ */ new Map();
@@ -27952,12 +28070,12 @@ function snapshotWhileRunning(s, print) {
27952
28070
  return;
27953
28071
  }
27954
28072
  const incoming = s.store + ".incoming";
27955
- fs15.rmSync(incoming, { recursive: true, force: true });
28073
+ fs16.rmSync(incoming, { recursive: true, force: true });
27956
28074
  mkdirp(incoming);
27957
28075
  for (const name of databaseFiles(s.local, (n) => isCopyableDatabaseFile(n) && !/-wal$/i.test(n))) {
27958
- const db = new sqlite.DatabaseSync(path20.join(s.local, name), { readOnly: true });
28076
+ const db = new sqlite.DatabaseSync(path21.join(s.local, name), { readOnly: true });
27959
28077
  try {
27960
- await sqlite.backup(db, path20.join(incoming, name));
28078
+ await sqlite.backup(db, path21.join(incoming, name));
27961
28079
  } finally {
27962
28080
  db.close();
27963
28081
  }
@@ -27983,7 +28101,7 @@ function saveLocalState() {
27983
28101
  continue;
27984
28102
  }
27985
28103
  const names = databaseFiles(s.local, isCopyableDatabaseFile);
27986
- const bad = names.filter((n) => !/-wal$/i.test(n) && !looksLikeSqlite2(path20.join(s.local, n)));
28104
+ const bad = names.filter((n) => !/-wal$/i.test(n) && !looksLikeSqlite2(path21.join(s.local, n)));
27987
28105
  if (bad.length) {
27988
28106
  warn(s.agent + ": " + bad.join(", ") + " do not look like SQLite databases, so they were not saved.");
27989
28107
  continue;
@@ -28002,10 +28120,10 @@ function saveLocalState() {
28002
28120
  import { spawn as spawn5 } from "node:child_process";
28003
28121
 
28004
28122
  // src/guest/setup/environment.ts
28005
- import path22 from "node:path";
28123
+ import path23 from "node:path";
28006
28124
 
28007
28125
  // src/guest/setup/path-plan.ts
28008
- import path21 from "node:path";
28126
+ import path22 from "node:path";
28009
28127
  function pathKey(folder) {
28010
28128
  const slashes = folder.trim().replace(/^"|"$/g, "").replace(/\//g, "\\");
28011
28129
  return (slashes.length > 3 ? slashes.replace(/\\+$/, "") : slashes).toLowerCase();
@@ -28045,13 +28163,13 @@ function parseRegPath(output2) {
28045
28163
  function isPinnedNodeDir(folder, nvmHome2) {
28046
28164
  const key2 = pathKey(folder);
28047
28165
  const home = pathKey(nvmHome2);
28048
- return key2.startsWith(home + "\\") && /^v\d/.test(path21.win32.basename(key2));
28166
+ return key2.startsWith(home + "\\") && /^v\d/.test(path22.win32.basename(key2));
28049
28167
  }
28050
28168
 
28051
28169
  // src/guest/setup/environment.ts
28052
28170
  var LEGACY_HOMES = { CODEX_HOME: "codex", GEMINI_CLI_HOME: "gemini" };
28053
28171
  var agentHomes = () => Object.fromEntries(
28054
- Object.entries(session.agentHomes ?? LEGACY_HOMES).filter(([name]) => name !== "CLAUDE_CONFIG_DIR").map(([name, sub]) => [name, path22.join(stateDir, sub)])
28172
+ Object.entries(session.agentHomes ?? LEGACY_HOMES).filter(([name]) => name !== "CLAUDE_CONFIG_DIR").map(([name, sub]) => [name, path23.join(stateDir, sub)])
28055
28173
  );
28056
28174
  function agentEnv(tools, target = { workspace, project: session.project, base: process.env }) {
28057
28175
  const homes = agentHomes();
@@ -28061,7 +28179,7 @@ function agentEnv(tools, target = { workspace, project: session.project, base: p
28061
28179
  CLAUDE_CONFIG_DIR: claudeDir,
28062
28180
  ...homes,
28063
28181
  ...localStateVars(),
28064
- npm_config_cache: path22.join(toolsDir, "npm-cache"),
28182
+ npm_config_cache: path23.join(toolsDir, "npm-cache"),
28065
28183
  npm_config_update_notifier: "false",
28066
28184
  AGENT_WORKSPACE: target.workspace,
28067
28185
  AGENT_DATA: dataDir,
@@ -28079,9 +28197,9 @@ function agentEnv(tools, target = { workspace, project: session.project, base: p
28079
28197
  ...local.map((n) => env[n])
28080
28198
  ])
28081
28199
  mkdirp(dir);
28082
- const runners = [path22.join(toolsDir, "node"), path22.dirname(process.execPath)].map((d) => d.toLowerCase());
28083
- const base = (target.base.PATH ?? "").split(path22.delimiter).filter((d) => d && !runners.includes(d.toLowerCase()));
28084
- env.PATH = [.../* @__PURE__ */ new Set([...tools.prepend, ...base, ...tools.append])].join(path22.delimiter);
28200
+ const runners = [path23.join(toolsDir, "node"), path23.dirname(process.execPath)].map((d) => d.toLowerCase());
28201
+ const base = (target.base.PATH ?? "").split(path23.delimiter).filter((d) => d && !runners.includes(d.toLowerCase()));
28202
+ env.PATH = [.../* @__PURE__ */ new Set([...tools.prepend, ...base, ...tools.append])].join(path23.delimiter);
28085
28203
  return env;
28086
28204
  }
28087
28205
  function addMachineEnvironment(vars, dirs, additive = false) {
@@ -28093,7 +28211,7 @@ function addMachineEnvironment(vars, dirs, additive = false) {
28093
28211
  warn("Could not add to the environment: " + errMsg(e));
28094
28212
  }
28095
28213
  }
28096
- var nvmHome = () => path22.join(toolsDir, "nvm");
28214
+ var nvmHome = () => path23.join(toolsDir, "nvm");
28097
28215
  var MACHINE_ENVIRONMENT_KEY = "HKLM\\SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment";
28098
28216
  var USER_ENVIRONMENT_KEY = "HKCU\\Environment";
28099
28217
  var registryPath = (key2) => parseRegPath(execOutput(SYSTEM.reg(), ["query", key2, "/v", "Path"]));
@@ -28101,7 +28219,7 @@ function withRegistryPath(env) {
28101
28219
  if (!isWin || dryRun || testMode) return env;
28102
28220
  try {
28103
28221
  const registry2 = expandVars(registryPath(MACHINE_ENVIRONMENT_KEY) + ";" + registryPath(USER_ENVIRONMENT_KEY), env);
28104
- const runner = pathKey(path22.join(toolsDir, "node"));
28222
+ const runner = pathKey(path23.join(toolsDir, "node"));
28105
28223
  const pathName = Object.keys(env).find((k) => k.toLowerCase() === "path") ?? "PATH";
28106
28224
  return {
28107
28225
  ...env,
@@ -28118,12 +28236,12 @@ function withRegistryPath(env) {
28118
28236
  }
28119
28237
 
28120
28238
  // src/guest/daemon/project-provisioner.ts
28121
- import fs48 from "node:fs";
28122
- import path62 from "node:path";
28239
+ import fs49 from "node:fs";
28240
+ import path63 from "node:path";
28123
28241
 
28124
28242
  // src/guest/boot/boot-env.ts
28125
- import fs16 from "node:fs";
28126
- import path23 from "node:path";
28243
+ import fs17 from "node:fs";
28244
+ import path24 from "node:path";
28127
28245
 
28128
28246
  // src/guest/boot/project-env.ts
28129
28247
  var EnvSchema = external_exports.object({
@@ -28153,22 +28271,22 @@ function baseEnvFor(boot, current = process.env) {
28153
28271
  }
28154
28272
 
28155
28273
  // src/guest/boot/boot-env.ts
28156
- var file2 = () => path23.join(localDir, "boot-env.json");
28274
+ var file2 = () => path24.join(localDir, "boot-env.json");
28157
28275
  function readBootEnv() {
28158
28276
  try {
28159
- return BootEnvSchema.safeParse(JSON.parse(fs16.readFileSync(file2(), "utf8"))).data ?? null;
28277
+ return BootEnvSchema.safeParse(JSON.parse(fs17.readFileSync(file2(), "utf8"))).data ?? null;
28160
28278
  } catch {
28161
28279
  return null;
28162
28280
  }
28163
28281
  }
28164
28282
 
28165
28283
  // src/guest/boot/guide.ts
28166
- import fs17 from "node:fs";
28167
- import path24 from "node:path";
28284
+ import fs18 from "node:fs";
28285
+ import path25 from "node:path";
28168
28286
  var BEGIN = "<!-- agent-sandbox:begin (generated every boot, do not edit) -->";
28169
28287
  var END = "<!-- agent-sandbox:end -->";
28170
28288
  var mirrorLine = () => {
28171
- const drives = (session.substDrives ?? []).filter((d) => fs17.existsSync(d.letter + ":\\"));
28289
+ const drives = (session.substDrives ?? []).filter((d) => fs18.existsSync(d.letter + ":\\"));
28172
28290
  if (!drives.length) return [];
28173
28291
  return [
28174
28292
  "- " + drives.map((d) => d.letter + ":").join(", ") + " = mapped folders at their PC paths (subst onto `" + drives.map((d) => d.target).join("`, `") + "`; real-path tools may print that form)."
@@ -28184,8 +28302,8 @@ function sandboxGuide(toolSummary, lan = "blocked", projects = []) {
28184
28302
  ...projects.map(
28185
28303
  (p) => "- RW, persists: `" + p.guest + "` = host folder " + p.host + " (another project in this sandbox; your own is `%AGENT_WORKSPACE%`)"
28186
28304
  ),
28187
- "- RW, persists: `" + toolsDir + "` (toolchains) \u2014 put portable exes in `" + path24.join(toolsDir, "bin") + "` (on PATH)",
28188
- "- RW, persists: `" + stateDir + "` (agent config/history; do not edit logins) \xB7 logs: `" + path24.join(dataDir, "logs") + "`",
28305
+ "- RW, persists: `" + toolsDir + "` (toolchains) \u2014 put portable exes in `" + path25.join(toolsDir, "bin") + "` (on PATH)",
28306
+ "- RW, persists: `" + stateDir + "` (agent config/history; do not edit logins) \xB7 logs: `" + path25.join(dataDir, "logs") + "`",
28189
28307
  "- RO: `" + launchDir + "` (this boot's scripts) \xB7 lost on close: everything else, incl. `C:\\nvm` (Node symlink)",
28190
28308
  ...mirrorLine(),
28191
28309
  "- Tools: " + toolSummary.join(" \xB7 "),
@@ -28196,37 +28314,37 @@ function sandboxGuide(toolSummary, lan = "blocked", projects = []) {
28196
28314
  ].join("\n");
28197
28315
  }
28198
28316
  function upsertGuide(file3, guide) {
28199
- fs17.mkdirSync(path24.dirname(file3), { recursive: true });
28200
- const current = fs17.existsSync(file3) ? fs17.readFileSync(file3, "utf8") : "";
28317
+ fs18.mkdirSync(path25.dirname(file3), { recursive: true });
28318
+ const current = fs18.existsSync(file3) ? fs18.readFileSync(file3, "utf8") : "";
28201
28319
  const start = current.indexOf(BEGIN);
28202
28320
  const end = current.indexOf(END);
28203
28321
  const without = start >= 0 && end > start ? current.slice(0, start) + current.slice(end + END.length) : current;
28204
- fs17.writeFileSync(file3, without.trimEnd() + (without.trim() ? "\n\n" : "") + guide + "\n", "utf8");
28322
+ fs18.writeFileSync(file3, without.trimEnd() + (without.trim() ? "\n\n" : "") + guide + "\n", "utf8");
28205
28323
  }
28206
28324
  function managedClaudeMd() {
28207
- return path24.join(
28208
- process.env.AGENT_MANAGED_DIR ?? path24.join(process.env.ProgramFiles ?? "C:\\Program Files", "ClaudeCode"),
28325
+ return path25.join(
28326
+ process.env.AGENT_MANAGED_DIR ?? path25.join(process.env.ProgramFiles ?? "C:\\Program Files", "ClaudeCode"),
28209
28327
  "CLAUDE.md"
28210
28328
  );
28211
28329
  }
28212
28330
  function writeGuides(toolSummary, lan, projects = []) {
28213
28331
  const guide = sandboxGuide(toolSummary, lan, projects);
28214
28332
  const managed = managedClaudeMd();
28215
- fs17.mkdirSync(path24.dirname(managed), { recursive: true });
28216
- fs17.writeFileSync(managed, guide + "\n", "utf8");
28217
- fs17.writeFileSync(path24.join(dataDir, "SANDBOX.md"), guide + "\n", "utf8");
28218
- upsertGuide(path24.join(stateDir, "codex", "AGENTS.md"), guide);
28219
- upsertGuide(path24.join(stateDir, "gemini", ".gemini", "GEMINI.md"), guide);
28220
- removeGuide(path24.join(claudeDir, "CLAUDE.md"));
28333
+ fs18.mkdirSync(path25.dirname(managed), { recursive: true });
28334
+ fs18.writeFileSync(managed, guide + "\n", "utf8");
28335
+ fs18.writeFileSync(path25.join(dataDir, "SANDBOX.md"), guide + "\n", "utf8");
28336
+ upsertGuide(path25.join(stateDir, "codex", "AGENTS.md"), guide);
28337
+ upsertGuide(path25.join(stateDir, "gemini", ".gemini", "GEMINI.md"), guide);
28338
+ removeGuide(path25.join(claudeDir, "CLAUDE.md"));
28221
28339
  return managed;
28222
28340
  }
28223
28341
  var removeGuide = (file3) => {
28224
- if (!fs17.existsSync(file3)) return;
28225
- const current = fs17.readFileSync(file3, "utf8");
28342
+ if (!fs18.existsSync(file3)) return;
28343
+ const current = fs18.readFileSync(file3, "utf8");
28226
28344
  const start = current.indexOf(BEGIN);
28227
28345
  const end = current.indexOf(END);
28228
28346
  if (start >= 0 && end > start)
28229
- fs17.writeFileSync(file3, (current.slice(0, start) + current.slice(end + END.length)).trim() + "\n", "utf8");
28347
+ fs18.writeFileSync(file3, (current.slice(0, start) + current.slice(end + END.length)).trim() + "\n", "utf8");
28230
28348
  };
28231
28349
 
28232
28350
  // src/guest/runtime/project-context.ts
@@ -28263,11 +28381,11 @@ function saveProjectStatus(name, workspace2, phase, message, databases, summary)
28263
28381
  }
28264
28382
 
28265
28383
  // src/guest/setup/hooks.ts
28266
- import fs18 from "node:fs";
28267
- import path25 from "node:path";
28384
+ import fs19 from "node:fs";
28385
+ import path26 from "node:path";
28268
28386
  import { spawnSync as spawnSync3 } from "node:child_process";
28269
28387
  var commandFor = (file3) => {
28270
- const ext = path25.extname(file3).toLowerCase();
28388
+ const ext = path26.extname(file3).toLowerCase();
28271
28389
  if (ext === ".mjs" || ext === ".js") return [process.execPath, [file3]];
28272
28390
  if (!isWin) return null;
28273
28391
  if (ext === ".ps1")
@@ -28275,18 +28393,18 @@ var commandFor = (file3) => {
28275
28393
  if (ext === ".cmd" || ext === ".bat") return [SYSTEM.cmd(), ["/d", "/c", file3]];
28276
28394
  return null;
28277
28395
  };
28278
- var BOOT = { root: path25.join(launchDir, "hooks"), cwd: workspace };
28396
+ var BOOT = { root: path26.join(launchDir, "hooks"), cwd: workspace };
28279
28397
  function projectHooks(name, cwd) {
28280
28398
  return {
28281
- root: path25.join(launchDir, "projects", name, "hooks"),
28399
+ root: path26.join(launchDir, "projects", name, "hooks"),
28282
28400
  cwd
28283
28401
  };
28284
28402
  }
28285
28403
  var hooksOf = (stage, target) => {
28286
- const dir = path25.join(target.root, stage);
28404
+ const dir = path26.join(target.root, stage);
28287
28405
  if (!exists(dir)) return [];
28288
- return fs18.readdirSync(dir).sort().flatMap((name) => {
28289
- const command = commandFor(path25.join(dir, name));
28406
+ return fs19.readdirSync(dir).sort().flatMap((name) => {
28407
+ const command = commandFor(path26.join(dir, name));
28290
28408
  return command ? [{ name, command }] : [];
28291
28409
  });
28292
28410
  };
@@ -28316,25 +28434,25 @@ async function runHooksAsync(stage, env, target) {
28316
28434
  }
28317
28435
 
28318
28436
  // src/guest/toolchains/tool-env.ts
28319
- import path26 from "node:path";
28437
+ import path27 from "node:path";
28320
28438
  function emptyEnv() {
28321
28439
  return { vars: {}, prepend: [], append: [], summary: [] };
28322
28440
  }
28323
28441
  var arch = process.arch === "arm64" ? "arm64" : "x64";
28324
28442
  function tool(...parts2) {
28325
- return path26.join(toolsDir, ...parts2);
28443
+ return path27.join(toolsDir, ...parts2);
28326
28444
  }
28327
28445
  function versionOf(exe, args = ["--version"], options = {}) {
28328
28446
  return /\d+\.\d+\.\d+\S*/.exec(execOutput(exe, args, options))?.[0] ?? "installed";
28329
28447
  }
28330
28448
 
28331
28449
  // src/guest/apps/app-installer.ts
28332
- import fs22 from "node:fs";
28333
- import path31 from "node:path";
28450
+ import fs23 from "node:fs";
28451
+ import path32 from "node:path";
28334
28452
 
28335
28453
  // src/guest/apps/after-install.ts
28336
- import fs19 from "node:fs";
28337
- import path27 from "node:path";
28454
+ import fs20 from "node:fs";
28455
+ import path28 from "node:path";
28338
28456
  var SYSINTERNALS_TOOLS = [
28339
28457
  "Process Explorer",
28340
28458
  "Process Monitor",
@@ -28355,16 +28473,16 @@ var SYSINTERNALS_TOOLS = [
28355
28473
  "ZoomIt"
28356
28474
  ];
28357
28475
  async function afterInstall(entry, exe) {
28358
- const dir = path27.dirname(exe);
28476
+ const dir = path28.dirname(exe);
28359
28477
  if (entry.needs?.includes("mesa")) {
28360
28478
  const mesa = tool("mesa", arch === "arm64" ? "arm64" : "x64");
28361
28479
  for (const dll of ["opengl32.dll", "libgallium_wgl.dll", "dxil.dll"]) {
28362
- if (exists(path27.join(mesa, dll)) && !exists(path27.join(dir, dll)))
28363
- fs19.copyFileSync(path27.join(mesa, dll), path27.join(dir, dll));
28480
+ if (exists(path28.join(mesa, dll)) && !exists(path28.join(dir, dll)))
28481
+ fs20.copyFileSync(path28.join(mesa, dll), path28.join(dir, dll));
28364
28482
  }
28365
28483
  }
28366
- if (entry.id === "godot" && !exists(path27.join(dir, "._sc_"))) fs19.writeFileSync(path27.join(dir, "._sc_"), "");
28367
- if (entry.id === "sublime") mkdirp(path27.join(dir, "Data"));
28484
+ if (entry.id === "godot" && !exists(path28.join(dir, "._sc_"))) fs20.writeFileSync(path28.join(dir, "._sc_"), "");
28485
+ if (entry.id === "sublime") mkdirp(path28.join(dir, "Data"));
28368
28486
  if (entry.id === "sysinternals") {
28369
28487
  for (const name of SYSINTERNALS_TOOLS) {
28370
28488
  await execAsync(
@@ -28377,14 +28495,14 @@ async function afterInstall(entry, exe) {
28377
28495
  }
28378
28496
 
28379
28497
  // src/guest/apps/find-exe.ts
28380
- import fs20 from "node:fs";
28381
- import path28 from "node:path";
28498
+ import fs21 from "node:fs";
28499
+ import path29 from "node:path";
28382
28500
  var MAX_DEPTH = 7;
28383
28501
  var MAX_ENTRIES = 5e4;
28384
28502
  var X64_FOLDER = /(^|[\\/])(amd64|x64|x86_64|win64)([\\/]|$)/i;
28385
28503
  function findExe(root, exe) {
28386
28504
  const match = exeMatcher(exe);
28387
- const best = (hits) => hits.find((h) => X64_FOLDER.test(path28.relative(root, h))) ?? hits[0] ?? null;
28505
+ const best = (hits) => hits.find((h) => X64_FOLDER.test(path29.relative(root, h))) ?? hits[0] ?? null;
28388
28506
  let queue = [root];
28389
28507
  let seen = 0;
28390
28508
  for (let depth = 0; depth < MAX_DEPTH && queue.length; depth++) {
@@ -28393,14 +28511,14 @@ function findExe(root, exe) {
28393
28511
  for (const dir of queue) {
28394
28512
  let entries2;
28395
28513
  try {
28396
- entries2 = fs20.readdirSync(dir, { withFileTypes: true });
28514
+ entries2 = fs21.readdirSync(dir, { withFileTypes: true });
28397
28515
  } catch {
28398
28516
  continue;
28399
28517
  }
28400
28518
  const hit = entries2.find((e) => e.isFile() && match(e.name));
28401
- if (hit) hits.push(path28.join(dir, hit.name));
28519
+ if (hit) hits.push(path29.join(dir, hit.name));
28402
28520
  else
28403
- next.push(...entries2.filter((e) => e.isDirectory() && !e.isSymbolicLink()).map((e) => path28.join(dir, e.name)));
28521
+ next.push(...entries2.filter((e) => e.isDirectory() && !e.isSymbolicLink()).map((e) => path29.join(dir, e.name)));
28404
28522
  if ((seen += entries2.length) > MAX_ENTRIES) return best(hits);
28405
28523
  }
28406
28524
  if (hits.length) return best(hits);
@@ -28411,12 +28529,12 @@ function findExe(root, exe) {
28411
28529
 
28412
28530
  // src/guest/apps/shortcuts.ts
28413
28531
  import os5 from "node:os";
28414
- import path29 from "node:path";
28532
+ import path30 from "node:path";
28415
28533
  function shortcuts(apps) {
28416
28534
  if (!apps.length) return;
28417
- const desktop = path29.join(os5.homedir(), "Desktop");
28418
- const start = path29.join(
28419
- process.env.APPDATA ?? path29.join(os5.homedir(), "AppData", "Roaming"),
28535
+ const desktop = path30.join(os5.homedir(), "Desktop");
28536
+ const start = path30.join(
28537
+ process.env.APPDATA ?? path30.join(os5.homedir(), "AppData", "Roaming"),
28420
28538
  "Microsoft",
28421
28539
  "Windows",
28422
28540
  "Start Menu",
@@ -28426,9 +28544,9 @@ function shortcuts(apps) {
28426
28544
  const links = apps.flatMap((app) => {
28427
28545
  const name = app.name.replace(/[\\/:*?"<>|]/g, "");
28428
28546
  return [desktop, start].map((folder) => ({
28429
- link: path29.join(folder, name + ".lnk"),
28547
+ link: path30.join(folder, name + ".lnk"),
28430
28548
  target: app.exe,
28431
- workingDirectory: path29.dirname(app.exe)
28549
+ workingDirectory: path30.dirname(app.exe)
28432
28550
  }));
28433
28551
  });
28434
28552
  runScriptWithJson("new-shortcuts.ps1", "ListFile", links);
@@ -28560,12 +28678,12 @@ async function resolve(entry) {
28560
28678
  }
28561
28679
 
28562
28680
  // src/guest/apps/unpack.ts
28563
- import fs21 from "node:fs";
28564
- import path30 from "node:path";
28681
+ import fs22 from "node:fs";
28682
+ import path31 from "node:path";
28565
28683
  var sevenZip = () => tool("apps", "7zip", "7z.exe");
28566
28684
  async function unpack(entry, file3, out, d) {
28567
28685
  if (entry.id === "7zip") {
28568
- const sevenZr = path30.join(path30.dirname(file3), "7zr.exe");
28686
+ const sevenZr = path31.join(path31.dirname(file3), "7zr.exe");
28569
28687
  const zr = await githubAsset("ip7z/7zip", /^7zr\.exe$/);
28570
28688
  await downloader.file(zr.url, sevenZr, zr.sha256);
28571
28689
  await execAsync(sevenZr, ["x", "-y", "-o" + out, file3], { stdio: "ignore" });
@@ -28574,17 +28692,17 @@ async function unpack(entry, file3, out, d) {
28574
28692
  switch (entry.unpack ?? "archive") {
28575
28693
  case "file": {
28576
28694
  mkdirp(out);
28577
- fs21.renameSync(file3, path30.join(out, /^\//.test(entry.exe) ? path30.basename(file3) : entry.exe));
28695
+ fs22.renameSync(file3, path31.join(out, /^\//.test(entry.exe) ? path31.basename(file3) : entry.exe));
28578
28696
  return;
28579
28697
  }
28580
28698
  case "nsis": {
28581
28699
  if (!exists(sevenZip()))
28582
28700
  throw new Error("7-Zip is needed to unpack " + entry.name + " and could not be installed");
28583
- const raw = path30.join(path30.dirname(out), "raw");
28701
+ const raw = path31.join(path31.dirname(out), "raw");
28584
28702
  await execAsync(sevenZip(), ["x", "-y", "-o" + raw, file3], { stdio: "ignore" });
28585
28703
  const inner = findExe(raw, "/^app-64\\.7z$/");
28586
28704
  if (inner) await execAsync(sevenZip(), ["x", "-y", "-o" + out, inner], { stdio: "ignore" });
28587
- else fs21.renameSync(raw, out);
28705
+ else fs22.renameSync(raw, out);
28588
28706
  return;
28589
28707
  }
28590
28708
  case "msi": {
@@ -28634,11 +28752,11 @@ var AppInstaller = class {
28634
28752
  async installOne(entry) {
28635
28753
  try {
28636
28754
  const dest = tool("apps", ...entry.id.split("/"));
28637
- if (!exists(path31.join(dest, MARKER)) || this.options.refresh) await this.download(entry, dest);
28755
+ if (!exists(path32.join(dest, MARKER)) || this.options.refresh) await this.download(entry, dest);
28638
28756
  const exe = findExe(dest, entry.exe);
28639
28757
  if (!exe) throw new Error(entry.exe + " not found in the download");
28640
28758
  await afterInstall(entry, exe);
28641
- if (entry.cli || entry.id === "sysinternals") this.env.prepend.push(path31.dirname(exe));
28759
+ if (entry.cli || entry.id === "sysinternals") this.env.prepend.push(path32.dirname(exe));
28642
28760
  if (!entry.cli) this.gui.push({ name: entry.name, exe });
28643
28761
  this.installed.push(entry.name);
28644
28762
  } catch (e) {
@@ -28651,10 +28769,10 @@ var AppInstaller = class {
28651
28769
  /** Downloads and unpacks one entry into its folder (replaced in one step: never half there). */
28652
28770
  async download(entry, dest) {
28653
28771
  const work = stagingFolder(dest);
28654
- const out = path31.join(work, "out");
28772
+ const out = path32.join(work, "out");
28655
28773
  try {
28656
28774
  if ("npm" in entry.source) {
28657
- const npmCli = path31.join(path31.dirname(process.execPath), "node_modules", "npm", "bin", "npm-cli.js");
28775
+ const npmCli = path32.join(path32.dirname(process.execPath), "node_modules", "npm", "bin", "npm-cli.js");
28658
28776
  log("Installing " + entry.name + " (npm) ...");
28659
28777
  await execAsync(process.execPath, [
28660
28778
  npmCli,
@@ -28669,14 +28787,14 @@ var AppInstaller = class {
28669
28787
  } else {
28670
28788
  const d = await resolve(entry);
28671
28789
  log("Downloading " + entry.name + " (" + d.fileName + ", ~" + entry.size + " once) ...");
28672
- const file3 = path31.join(mkdirp(work), d.fileName.replace(/[\\/:*?"<>|]/g, "_"));
28790
+ const file3 = path32.join(mkdirp(work), d.fileName.replace(/[\\/:*?"<>|]/g, "_"));
28673
28791
  await downloader.file(d.url, file3, { sha256: d.sha256 ?? null });
28674
28792
  await unpack(entry, file3, out, d);
28675
28793
  }
28676
- fs22.writeFileSync(path31.join(out, MARKER), JSON.stringify({ id: entry.id, at: (/* @__PURE__ */ new Date()).toISOString() }));
28794
+ fs23.writeFileSync(path32.join(out, MARKER), JSON.stringify({ id: entry.id, at: (/* @__PURE__ */ new Date()).toISOString() }));
28677
28795
  moveIntoPlace(out, dest);
28678
28796
  } finally {
28679
- safeRemove(work, path31.dirname(work));
28797
+ safeRemove(work, path32.dirname(work));
28680
28798
  }
28681
28799
  }
28682
28800
  };
@@ -28691,8 +28809,8 @@ async function setupApps(env, apps, o) {
28691
28809
  }
28692
28810
 
28693
28811
  // src/guest/toolchains/detect.ts
28694
- import fs23 from "node:fs";
28695
- import path32 from "node:path";
28812
+ import fs24 from "node:fs";
28813
+ import path33 from "node:path";
28696
28814
 
28697
28815
  // src/core/detect/versions.ts
28698
28816
  function pickNodeVersion(releases, spec) {
@@ -28824,14 +28942,14 @@ function workspaceEntries() {
28824
28942
  if (known) return known;
28825
28943
  const list = (dir) => {
28826
28944
  try {
28827
- return fs23.readdirSync(dir, { withFileTypes: true });
28945
+ return fs24.readdirSync(dir, { withFileTypes: true });
28828
28946
  } catch {
28829
28947
  return [];
28830
28948
  }
28831
28949
  };
28832
28950
  const top = list(workspace2);
28833
28951
  const below = top.filter((d) => d.isDirectory() && !d.name.startsWith(".") && !SKIP_DIRS.has(d.name.toLowerCase())).flatMap(
28834
- (d) => list(path32.join(workspace2, d.name)).filter((f) => f.isFile()).map((f) => d.name + "/" + f.name)
28952
+ (d) => list(path33.join(workspace2, d.name)).filter((f) => f.isFile()).map((f) => d.name + "/" + f.name)
28835
28953
  );
28836
28954
  const found = [...top.filter((d) => d.isFile()).map((d) => d.name), ...below];
28837
28955
  entries.set(workspace2.toLowerCase(), found);
@@ -28842,9 +28960,9 @@ function wanted(setting, toolchain) {
28842
28960
  }
28843
28961
  function versionFromFiles(files, parse5 = (t) => specFromVersionFile(t)) {
28844
28962
  for (const name of files) {
28845
- const file3 = path32.join(projectWorkspace(), name);
28963
+ const file3 = path33.join(projectWorkspace(), name);
28846
28964
  if (!exists(file3)) continue;
28847
- const spec = parse5(fs23.readFileSync(file3, "utf8"), name);
28965
+ const spec = parse5(fs24.readFileSync(file3, "utf8"), name);
28848
28966
  if (spec) return { spec, source: name };
28849
28967
  }
28850
28968
  return null;
@@ -28917,22 +29035,22 @@ var DatabaseServer = class {
28917
29035
  };
28918
29036
 
28919
29037
  // src/guest/databases/dynamodb.ts
28920
- import fs28 from "node:fs";
28921
- import path35 from "node:path";
29038
+ import fs29 from "node:fs";
29039
+ import path36 from "node:path";
28922
29040
  import { spawn as spawn3 } from "node:child_process";
28923
29041
 
28924
29042
  // src/guest/toolchains/languages/java.ts
28925
- import fs26 from "node:fs";
28926
- import path33 from "node:path";
29043
+ import fs27 from "node:fs";
29044
+ import path34 from "node:path";
28927
29045
 
28928
29046
  // src/guest/toolchains/version-cache.ts
28929
- import fs25 from "node:fs";
29047
+ import fs26 from "node:fs";
28930
29048
 
28931
29049
  // src/guest/toolchains/state-file.ts
28932
- import fs24 from "node:fs";
29050
+ import fs25 from "node:fs";
28933
29051
  function readState(file3, schema, empty) {
28934
29052
  try {
28935
- return schema.safeParse(JSON.parse(fs24.readFileSync(file3, "utf8").replace(/^\uFEFF/, ""))).data ?? empty;
29053
+ return schema.safeParse(JSON.parse(fs25.readFileSync(file3, "utf8").replace(/^\uFEFF/, ""))).data ?? empty;
28936
29054
  } catch {
28937
29055
  return empty;
28938
29056
  }
@@ -28967,7 +29085,7 @@ var VersionCache = class {
28967
29085
  return cached2.value;
28968
29086
  try {
28969
29087
  const value = await resolve2();
28970
- fs25.mkdirSync(toolsDir, { recursive: true });
29088
+ fs26.mkdirSync(toolsDir, { recursive: true });
28971
29089
  writeJsonAtomic(this.file(), { ...this.remembered(), [key2]: { value, at: Date.now() } });
28972
29090
  return value;
28973
29091
  } catch (e) {
@@ -29020,7 +29138,7 @@ var setupJdk = async (env, config2) => {
29020
29138
  const { major, source } = await javaMajor(config2);
29021
29139
  const release = await resolveCached("java:" + major, async () => (await temurin(major)).release_name);
29022
29140
  const home = tool("java", release.replace(/[^A-Za-z0-9.-]/g, "_"));
29023
- if (!exists(path33.join(home, "bin", "java.exe"))) {
29141
+ if (!exists(path34.join(home, "bin", "java.exe"))) {
29024
29142
  const asset = await temurin(major);
29025
29143
  log("Downloading Java " + release + " (JDK, ~200 MB once) ...");
29026
29144
  await downloader.archive(asset.binary.package.link, home, {
@@ -29030,13 +29148,13 @@ var setupJdk = async (env, config2) => {
29030
29148
  });
29031
29149
  }
29032
29150
  env.vars.JAVA_HOME = home;
29033
- env.prepend.push(path33.join(home, "bin"));
29151
+ env.prepend.push(path34.join(home, "bin"));
29034
29152
  env.summary.push("java: " + release + " (Temurin, from " + source + ")");
29035
29153
  };
29036
29154
  async function ensureJdk() {
29037
29155
  const root = tool("java");
29038
- const installed = exists(root) ? fs26.readdirSync(root).filter((d) => exists(path33.join(root, d, "bin", "java.exe"))).sort((a, b) => b.localeCompare(a, void 0, { numeric: true })) : [];
29039
- if (installed.length) return path33.join(root, installed[0]);
29156
+ const installed = exists(root) ? fs27.readdirSync(root).filter((d) => exists(path34.join(root, d, "bin", "java.exe"))).sort((a, b) => b.localeCompare(a, void 0, { numeric: true })) : [];
29157
+ if (installed.length) return path34.join(root, installed[0]);
29040
29158
  const scratch = emptyEnv();
29041
29159
  await setupJdk(scratch, { enabled: true, version: "lts", maven: false, gradle: false });
29042
29160
  return scratch.vars.JAVA_HOME;
@@ -29049,7 +29167,7 @@ var setupMaven = async (env) => {
29049
29167
  return pickPackageVersion(versions, "3") ?? Promise.reject(new Error("No Maven 3 release found"));
29050
29168
  });
29051
29169
  const home = tool("maven", version2);
29052
- if (!exists(path33.join(home, "bin", "mvn.cmd"))) {
29170
+ if (!exists(path34.join(home, "bin", "mvn.cmd"))) {
29053
29171
  const url2 = MAVEN + version2 + "/apache-maven-" + version2 + "-bin.zip";
29054
29172
  log("Downloading Maven " + version2 + " (~10 MB once) ...");
29055
29173
  await downloader.archive(url2, home, {
@@ -29059,7 +29177,7 @@ var setupMaven = async (env) => {
29059
29177
  }
29060
29178
  const repo = tool("maven-repository");
29061
29179
  Object.assign(env.vars, { MAVEN_HOME: home, M2_HOME: home, MAVEN_OPTS: "-Dmaven.repo.local=" + repo });
29062
- env.prepend.push(path33.join(home, "bin"));
29180
+ env.prepend.push(path34.join(home, "bin"));
29063
29181
  env.summary.push("maven: " + version2);
29064
29182
  };
29065
29183
  var setupGradle = async (env) => {
@@ -29071,7 +29189,7 @@ var setupGradle = async (env) => {
29071
29189
  async () => current?.version ?? Promise.reject(new Error("Gradle version lookup failed"))
29072
29190
  );
29073
29191
  const home = tool("gradle", version2);
29074
- if (!exists(path33.join(home, "bin", "gradle.bat"))) {
29192
+ if (!exists(path34.join(home, "bin", "gradle.bat"))) {
29075
29193
  if (!current || current.version !== version2)
29076
29194
  throw new Error("Gradle " + version2 + " is not installed and cannot be downloaded right now");
29077
29195
  log("Downloading Gradle " + version2 + " (~130 MB once) ...");
@@ -29082,13 +29200,13 @@ var setupGradle = async (env) => {
29082
29200
  });
29083
29201
  }
29084
29202
  const userHome = tool("gradle-home");
29085
- fs26.mkdirSync(userHome, { recursive: true });
29203
+ fs27.mkdirSync(userHome, { recursive: true });
29086
29204
  Object.assign(env.vars, {
29087
29205
  GRADLE_HOME: home,
29088
29206
  GRADLE_USER_HOME: userHome,
29089
29207
  GRADLE_OPTS: "-Dorg.gradle.vfs.watch=false"
29090
29208
  });
29091
- env.prepend.push(path33.join(home, "bin"));
29209
+ env.prepend.push(path34.join(home, "bin"));
29092
29210
  env.summary.push("gradle: " + version2);
29093
29211
  };
29094
29212
  async function setupJava(env, config2) {
@@ -29112,29 +29230,29 @@ async function setupJava(env, config2) {
29112
29230
  }
29113
29231
 
29114
29232
  // src/guest/databases/server.ts
29115
- import fs27 from "node:fs";
29116
- import path34 from "node:path";
29233
+ import fs28 from "node:fs";
29234
+ import path35 from "node:path";
29117
29235
  import { spawn as spawn2 } from "node:child_process";
29118
29236
  function dataFor(name) {
29119
- return path34.join(dataDir, "databases", name);
29237
+ return path35.join(dataDir, "databases", name);
29120
29238
  }
29121
29239
  async function startServer(name, exe, args, port) {
29122
29240
  if (await portOpen(port)) throw new Error("port " + port + " is already in use (change databases." + name + ".port)");
29123
- const logFile2 = path34.join(logsDir, name + ".log");
29124
- const out = fs27.openSync(logFile2, "a");
29241
+ const logFile2 = path35.join(logsDir, name + ".log");
29242
+ const out = fs28.openSync(logFile2, "a");
29125
29243
  spawn2(exe, args, { detached: true, stdio: ["ignore", out, out], windowsHide: true }).unref();
29126
- fs27.closeSync(out);
29244
+ fs28.closeSync(out);
29127
29245
  if (!await waitForPort(port, 60))
29128
29246
  throw new Error(name + " did not start listening on port " + port + "; see " + logFile2);
29129
29247
  }
29130
29248
  async function clearStaleLocks(dir, files, port) {
29131
29249
  if (await portOpen(port)) return;
29132
- for (const f of files) fs27.rmSync(path34.join(dir, f), { force: true });
29250
+ for (const f of files) fs28.rmSync(path35.join(dir, f), { force: true });
29133
29251
  }
29134
29252
  async function createOnce(data, marker, create) {
29135
- if (exists(path34.join(data, marker))) return;
29253
+ if (exists(path35.join(data, marker))) return;
29136
29254
  const existed = exists(data);
29137
- mkdirp(path34.dirname(data));
29255
+ mkdirp(path35.dirname(data));
29138
29256
  try {
29139
29257
  await create();
29140
29258
  } catch (e) {
@@ -29158,9 +29276,9 @@ var DynamoServer = class extends DatabaseServer {
29158
29276
  * local endpoint up from AWS_ENDPOINT_URL_DYNAMODB, with dummy credentials (real ones never reach the sandbox).
29159
29277
  */
29160
29278
  async start(env, plan2) {
29161
- const java = path35.join(await ensureJdk(), "bin", "java.exe");
29279
+ const java = path36.join(await ensureJdk(), "bin", "java.exe");
29162
29280
  const home = tool("dynamodb-local");
29163
- if (!exists(path35.join(home, "DynamoDBLocal.jar"))) {
29281
+ if (!exists(path36.join(home, "DynamoDBLocal.jar"))) {
29164
29282
  log("Downloading DynamoDB Local (~60 MB once) ...");
29165
29283
  const sha256 = (await fetchText(DYNAMO_ZIP + ".sha256")).trim().split(/\s+/)[0];
29166
29284
  await downloader.archive(DYNAMO_ZIP, home, {
@@ -29174,9 +29292,9 @@ var DynamoServer = class extends DatabaseServer {
29174
29292
  "dynamodb",
29175
29293
  java,
29176
29294
  [
29177
- "-Djava.library.path=" + path35.join(home, "DynamoDBLocal_lib"),
29295
+ "-Djava.library.path=" + path36.join(home, "DynamoDBLocal_lib"),
29178
29296
  "-jar",
29179
- path35.join(home, "DynamoDBLocal.jar"),
29297
+ path36.join(home, "DynamoDBLocal.jar"),
29180
29298
  "-sharedDb",
29181
29299
  "-dbPath",
29182
29300
  data,
@@ -29200,10 +29318,10 @@ var DynamoServer = class extends DatabaseServer {
29200
29318
  );
29201
29319
  if (!plan2.adminPort) return;
29202
29320
  const prefix = tool("dynamodb-admin");
29203
- const script = path35.join(prefix, "node_modules", "dynamodb-admin", "dist", "dynamodb-admin.js");
29321
+ const script = path36.join(prefix, "node_modules", "dynamodb-admin", "dist", "dynamodb-admin.js");
29204
29322
  if (!exists(script)) {
29205
29323
  log("Installing dynamodb-admin, the DynamoDB web UI (~20 MB once) ...");
29206
- const npmCli = path35.join(path35.dirname(process.execPath), "node_modules", "npm", "bin", "npm-cli.js");
29324
+ const npmCli = path36.join(path36.dirname(process.execPath), "node_modules", "npm", "bin", "npm-cli.js");
29207
29325
  await execAsync(
29208
29326
  process.execPath,
29209
29327
  [npmCli, "install", "--global", "--prefix", prefix, "dynamodb-admin", "--no-fund", "--no-audit"],
@@ -29216,15 +29334,15 @@ var DynamoServer = class extends DatabaseServer {
29216
29334
  );
29217
29335
  return;
29218
29336
  }
29219
- const out = fs28.openSync(path35.join(logsDir, "dynamodb-admin.log"), "a");
29337
+ const out = fs29.openSync(path36.join(logsDir, "dynamodb-admin.log"), "a");
29220
29338
  spawn3(
29221
29339
  process.execPath,
29222
29340
  [script, "--port", String(plan2.adminPort), "--dynamo-endpoint", endpoint, "--skip-default-credentials"],
29223
29341
  { detached: true, stdio: ["ignore", out, out], windowsHide: true, env: { ...process.env, ...aws } }
29224
29342
  ).unref();
29225
- fs28.closeSync(out);
29343
+ fs29.closeSync(out);
29226
29344
  if (!await waitForPort(plan2.adminPort, 30))
29227
- throw new Error("dynamodb-admin did not start; see " + path35.join(logsDir, "dynamodb-admin.log"));
29345
+ throw new Error("dynamodb-admin did not start; see " + path36.join(logsDir, "dynamodb-admin.log"));
29228
29346
  env.summary.push(
29229
29347
  "dynamodb-admin: http://localhost:" + plan2.adminPort + " (browse and edit tables in the sandbox's browser)"
29230
29348
  );
@@ -29232,18 +29350,18 @@ var DynamoServer = class extends DatabaseServer {
29232
29350
  };
29233
29351
 
29234
29352
  // src/guest/databases/mongodb.ts
29235
- import path36 from "node:path";
29353
+ import path37 from "node:path";
29236
29354
 
29237
29355
  // src/guest/toolchains/install.ts
29238
- import fs29 from "node:fs";
29356
+ import fs30 from "node:fs";
29239
29357
  async function downloadFile(url2, file3, sha256 = null) {
29240
29358
  const part = file3 + ".part";
29241
29359
  try {
29242
29360
  await downloader.file(url2, part, sha256);
29243
- fs29.rmSync(file3, { force: true });
29244
- fs29.renameSync(part, file3);
29361
+ fs30.rmSync(file3, { force: true });
29362
+ fs30.renameSync(part, file3);
29245
29363
  } finally {
29246
- fs29.rmSync(part, { force: true });
29364
+ fs30.rmSync(part, { force: true });
29247
29365
  }
29248
29366
  }
29249
29367
  async function installFromGithub(repo, pattern, o) {
@@ -29272,13 +29390,13 @@ var MongoServer = class extends DatabaseServer {
29272
29390
  };
29273
29391
  const version2 = await resolveCached("mongodb:" + plan2.version, async () => (await find()).version);
29274
29392
  const home = tool("mongodb", version2);
29275
- if (!exists(path36.join(home, "bin", "mongod.exe"))) {
29393
+ if (!exists(path37.join(home, "bin", "mongod.exe"))) {
29276
29394
  const { archive } = await find();
29277
29395
  log("Downloading MongoDB " + version2 + " (~400 MB once) ...");
29278
29396
  await downloader.archive(archive.url, home, { sha256: archive.sha256, locate: "mongod.exe", up: 1 });
29279
29397
  }
29280
29398
  const shell = tool("mongosh");
29281
- if (!exists(path36.join(shell, "mongosh.exe"))) {
29399
+ if (!exists(path37.join(shell, "mongosh.exe"))) {
29282
29400
  await installFromGithub("mongodb-js/mongosh", /^mongosh-[\d.]+-win32-x64\.zip$/, {
29283
29401
  dest: shell,
29284
29402
  what: "mongosh, the MongoDB shell (~50 MB once)",
@@ -29289,17 +29407,17 @@ var MongoServer = class extends DatabaseServer {
29289
29407
  await clearStaleLocks(data, ["mongod.lock"], plan2.port);
29290
29408
  await startServer(
29291
29409
  "mongodb",
29292
- path36.join(home, "bin", "mongod.exe"),
29410
+ path37.join(home, "bin", "mongod.exe"),
29293
29411
  ["--dbpath", data, "--bind_ip", "127.0.0.1", "--port", String(plan2.port)],
29294
29412
  plan2.port
29295
29413
  );
29296
- env.prepend.push(path36.join(home, "bin"), shell);
29414
+ env.prepend.push(path37.join(home, "bin"), shell);
29297
29415
  env.summary.push("mongodb " + version2 + ": mongodb://127.0.0.1:" + plan2.port + " (mongosh on PATH)");
29298
29416
  }
29299
29417
  };
29300
29418
 
29301
29419
  // src/guest/databases/mysql.ts
29302
- import path37 from "node:path";
29420
+ import path38 from "node:path";
29303
29421
  var MARIA = "https://downloads.mariadb.org/rest-api/mariadb/";
29304
29422
  var MysqlServer = class extends DatabaseServer {
29305
29423
  id = "mysql";
@@ -29317,8 +29435,8 @@ var MysqlServer = class extends DatabaseServer {
29317
29435
  };
29318
29436
  const version2 = await resolveCached("mariadb-version:" + series, async () => (await latest()).version);
29319
29437
  const home = tool("mariadb", version2);
29320
- const bin = path37.join(home, "bin");
29321
- if (!exists(path37.join(bin, "mariadbd.exe"))) {
29438
+ const bin = path38.join(home, "bin");
29439
+ if (!exists(path38.join(bin, "mariadbd.exe"))) {
29322
29440
  const { zip } = await latest();
29323
29441
  log("Downloading MariaDB " + version2 + " (~90 MB once) ...");
29324
29442
  await downloader.archive(zip.file_download_url.replace(/^http:/, "https:"), home, {
@@ -29331,13 +29449,13 @@ var MysqlServer = class extends DatabaseServer {
29331
29449
  const data = dataFor("mariadb");
29332
29450
  await createOnce(data, "mysql", async () => {
29333
29451
  log("Creating the MariaDB database (first start) ...");
29334
- await execAsync(path37.join(bin, "mariadb-install-db.exe"), ["--datadir=" + data, "--port=" + plan2.port], {
29452
+ await execAsync(path38.join(bin, "mariadb-install-db.exe"), ["--datadir=" + data, "--port=" + plan2.port], {
29335
29453
  stdio: "ignore"
29336
29454
  });
29337
29455
  });
29338
29456
  await startServer(
29339
29457
  "mysql",
29340
- path37.join(bin, "mariadbd.exe"),
29458
+ path38.join(bin, "mariadbd.exe"),
29341
29459
  ["--datadir=" + data, "--port=" + plan2.port, "--bind-address=127.0.0.1", "--console"],
29342
29460
  plan2.port
29343
29461
  );
@@ -29350,8 +29468,8 @@ var MysqlServer = class extends DatabaseServer {
29350
29468
  };
29351
29469
 
29352
29470
  // src/guest/databases/postgres.ts
29353
- import fs30 from "node:fs";
29354
- import path38 from "node:path";
29471
+ import fs31 from "node:fs";
29472
+ import path39 from "node:path";
29355
29473
  function postgresData(version2) {
29356
29474
  return dataFor("postgres-" + version2.split(".")[0]);
29357
29475
  }
@@ -29366,8 +29484,8 @@ var PostgresServer = class extends DatabaseServer {
29366
29484
  return hit ? hit.major + "." + hit.latestMinor : Promise.reject(new Error("No supported PostgreSQL " + plan2.version));
29367
29485
  });
29368
29486
  const home = tool("postgres", exact);
29369
- const bin = path38.join(home, "bin");
29370
- if (!exists(path38.join(bin, "pg_ctl.exe"))) {
29487
+ const bin = path39.join(home, "bin");
29488
+ if (!exists(path39.join(bin, "pg_ctl.exe"))) {
29371
29489
  log("Downloading PostgreSQL " + exact + " (~330 MB once) ...");
29372
29490
  await downloader.archive(
29373
29491
  "https://get.enterprisedb.com/postgresql/postgresql-" + exact + "-1-windows-x64-binaries.zip",
@@ -29384,7 +29502,7 @@ var PostgresServer = class extends DatabaseServer {
29384
29502
  await createOnce(data, "PG_VERSION", async () => {
29385
29503
  log("Creating the PostgreSQL database (first start) ...");
29386
29504
  await execAsync(
29387
- path38.join(bin, "initdb.exe"),
29505
+ path39.join(bin, "initdb.exe"),
29388
29506
  ["-D", data, "-U", "postgres", "-A", "trust", "-E", "UTF8", "--locale=C"],
29389
29507
  { stdio: "ignore" }
29390
29508
  );
@@ -29393,7 +29511,7 @@ var PostgresServer = class extends DatabaseServer {
29393
29511
  throw new Error("port " + plan2.port + " is already in use (change databases.postgres.port)");
29394
29512
  await clearStaleLocks(data, ["postmaster.pid"], plan2.port);
29395
29513
  await execAsync(
29396
- path38.join(bin, "pg_ctl.exe"),
29514
+ path39.join(bin, "pg_ctl.exe"),
29397
29515
  [
29398
29516
  "start",
29399
29517
  "-D",
@@ -29402,7 +29520,7 @@ var PostgresServer = class extends DatabaseServer {
29402
29520
  "-t",
29403
29521
  "60",
29404
29522
  "-l",
29405
- path38.join(logsDir, "postgres.log"),
29523
+ path39.join(logsDir, "postgres.log"),
29406
29524
  "-o",
29407
29525
  "-p " + plan2.port + " -c listen_addresses=localhost"
29408
29526
  ],
@@ -29417,10 +29535,10 @@ var PostgresServer = class extends DatabaseServer {
29417
29535
  /** Every installed version's cluster shuts down cleanly through pg_ctl first. */
29418
29536
  async stop(plan2) {
29419
29537
  if (exists(tool("postgres"))) {
29420
- for (const version2 of fs30.readdirSync(tool("postgres"))) {
29538
+ for (const version2 of fs31.readdirSync(tool("postgres"))) {
29421
29539
  const data = postgresData(version2);
29422
- const pgCtl = path38.join(tool("postgres", version2), "bin", "pg_ctl.exe");
29423
- if (exists(path38.join(data, "postmaster.pid")) && exists(pgCtl))
29540
+ const pgCtl = path39.join(tool("postgres", version2), "bin", "pg_ctl.exe");
29541
+ if (exists(path39.join(data, "postmaster.pid")) && exists(pgCtl))
29424
29542
  await execAsync(pgCtl, ["stop", "-D", data, "-m", "fast", "-w"], { stdio: "ignore" });
29425
29543
  }
29426
29544
  }
@@ -29429,12 +29547,12 @@ var PostgresServer = class extends DatabaseServer {
29429
29547
  };
29430
29548
 
29431
29549
  // src/guest/databases/redis.ts
29432
- import path39 from "node:path";
29550
+ import path40 from "node:path";
29433
29551
  var RedisServer = class extends DatabaseServer {
29434
29552
  id = "redis";
29435
29553
  async start(env, plan2) {
29436
29554
  const home = tool("redis");
29437
- if (!exists(path39.join(home, "redis-server.exe"))) {
29555
+ if (!exists(path40.join(home, "redis-server.exe"))) {
29438
29556
  await installFromGithub("redis-windows/redis-windows", /^Redis-[\d.]+-Windows-x64-msys2\.zip$/, {
29439
29557
  dest: home,
29440
29558
  what: (a) => "Redis (" + a.name + ", ~10 MB once)",
@@ -29444,7 +29562,7 @@ var RedisServer = class extends DatabaseServer {
29444
29562
  const data = mkdirp(dataFor("redis"));
29445
29563
  await startServer(
29446
29564
  "redis",
29447
- path39.join(home, "redis-server.exe"),
29565
+ path40.join(home, "redis-server.exe"),
29448
29566
  ["--port", String(plan2.port), "--bind", "127.0.0.1", "--dir", data.replace(/\\/g, "/"), "--appendonly", "yes"],
29449
29567
  plan2.port
29450
29568
  );
@@ -29482,16 +29600,16 @@ async function setupDatabase(env, plan2) {
29482
29600
  }
29483
29601
 
29484
29602
  // src/guest/toolchains/tools/git.ts
29485
- import fs32 from "node:fs";
29486
- import path41 from "node:path";
29603
+ import fs33 from "node:fs";
29604
+ import path42 from "node:path";
29487
29605
 
29488
29606
  // src/guest/runtime/csc.ts
29489
- import fs31 from "node:fs";
29607
+ import fs32 from "node:fs";
29490
29608
  import os6 from "node:os";
29491
- import path40 from "node:path";
29609
+ import path41 from "node:path";
29492
29610
  import crypto3 from "node:crypto";
29493
29611
  import { spawnSync as spawnSync5 } from "node:child_process";
29494
- var CSC = path40.join(process.env.WINDIR ?? "C:\\Windows", "Microsoft.NET", "Framework64", "v4.0.30319", "csc.exe");
29612
+ var CSC = path41.join(process.env.WINDIR ?? "C:\\Windows", "Microsoft.NET", "Framework64", "v4.0.30319", "csc.exe");
29495
29613
  var SOURCES = {
29496
29614
  ptyhost: "PtyHost.cs",
29497
29615
  gitshim: "GitShim.cs",
@@ -29503,17 +29621,17 @@ var SOURCES = {
29503
29621
  memgov: "MemGov.cs"
29504
29622
  };
29505
29623
  function sourceOf(name) {
29506
- return path40.join(launchDir, "sandbox", "csharp", SOURCES[name]);
29624
+ return path41.join(launchDir, "sandbox", "csharp", SOURCES[name]);
29507
29625
  }
29508
29626
  function sourceHash(name) {
29509
- return crypto3.createHash("sha256").update(fs31.readFileSync(sourceOf(name))).digest("hex").slice(0, 12);
29627
+ return crypto3.createHash("sha256").update(fs32.readFileSync(sourceOf(name))).digest("hex").slice(0, 12);
29510
29628
  }
29511
29629
  function ensureCompiled(name) {
29512
- const exe = path40.join(os6.tmpdir(), "agent-sandbox", name + "-" + sourceHash(name) + ".exe");
29630
+ const exe = path41.join(os6.tmpdir(), "agent-sandbox", name + "-" + sourceHash(name) + ".exe");
29513
29631
  if (exists(exe)) return exe;
29514
29632
  if (!exists(CSC))
29515
29633
  throw new Error("The .NET Framework C# compiler was not found at " + CSC + " (it ships with Windows 10/11).");
29516
- mkdirp(path40.dirname(exe));
29634
+ mkdirp(path41.dirname(exe));
29517
29635
  const result = spawnSync5(CSC, ["/nologo", "/optimize", "/target:exe", "/out:" + exe, sourceOf(name)], {
29518
29636
  encoding: "utf8",
29519
29637
  windowsHide: true
@@ -29547,23 +29665,23 @@ var installPortableGit = async (root) => {
29547
29665
  await downloader.file(asset.url, sfx, asset.sha256);
29548
29666
  await execAsync(sfx, ["-o" + root, "-y"], { stdio: "ignore" });
29549
29667
  } finally {
29550
- fs32.rmSync(sfx, { force: true });
29668
+ fs33.rmSync(sfx, { force: true });
29551
29669
  }
29552
29670
  };
29553
29671
  var installGuard = (env, access, realGit) => {
29554
29672
  const dir = mkdirp(tool("gitguard"));
29555
- const guard = path41.join(launchDir, "runtime", "gitguard.js");
29556
- if (duringSession() && (exists(path41.join(dir, "git.exe")) || exists(path41.join(dir, "git.cmd")))) {
29673
+ const guard = path42.join(launchDir, "runtime", "gitguard.js");
29674
+ if (duringSession() && (exists(path42.join(dir, "git.exe")) || exists(path42.join(dir, "git.cmd")))) {
29557
29675
  } else
29558
29676
  try {
29559
- fs32.copyFileSync(ensureCompiled("gitshim"), path41.join(dir, "git.exe"));
29560
- fs32.rmSync(path41.join(dir, "git.cmd"), { force: true });
29677
+ fs33.copyFileSync(ensureCompiled("gitshim"), path42.join(dir, "git.exe"));
29678
+ fs33.rmSync(path42.join(dir, "git.cmd"), { force: true });
29561
29679
  } catch (e) {
29562
29680
  warn("git guard: falling back to git.cmd (" + errMsg(e) + ")");
29563
- fs32.writeFileSync(path41.join(dir, "git.cmd"), '@"' + process.execPath + '" "' + guard + '" %*\r\n');
29681
+ fs33.writeFileSync(path42.join(dir, "git.cmd"), '@"' + process.execPath + '" "' + guard + '" %*\r\n');
29564
29682
  }
29565
- fs32.writeFileSync(
29566
- path41.join(dir, "bashenv.sh"),
29683
+ fs33.writeFileSync(
29684
+ path42.join(dir, "bashenv.sh"),
29567
29685
  'git() { "' + posix(process.execPath) + '" "' + posix(guard) + '" "$@"; }\nexport -f git\n'
29568
29686
  );
29569
29687
  env.prepend.unshift(dir);
@@ -29572,13 +29690,13 @@ var installGuard = (env, access, realGit) => {
29572
29690
  AGENT_REAL_GIT: access === "readonly" ? realGit : "",
29573
29691
  AGENT_GUARD_NODE: process.execPath,
29574
29692
  AGENT_GUARD_SCRIPT: guard,
29575
- BASH_ENV: posix(path41.join(dir, "bashenv.sh"))
29693
+ BASH_ENV: posix(path42.join(dir, "bashenv.sh"))
29576
29694
  });
29577
29695
  if (access === "readonly") {
29578
- const hooks = mkdirp(path41.join(dir, "hooks"));
29696
+ const hooks = mkdirp(path42.join(dir, "hooks"));
29579
29697
  for (const hook of BLOCKED_HOOKS)
29580
- fs32.writeFileSync(
29581
- path41.join(hooks, hook),
29698
+ fs33.writeFileSync(
29699
+ path42.join(hooks, hook),
29582
29700
  '#!/bin/sh\necho "git is read-only in this sandbox: ' + hook + ' refused." >&2\nexit 1\n'
29583
29701
  );
29584
29702
  Object.assign(env.vars, {
@@ -29587,22 +29705,22 @@ var installGuard = (env, access, realGit) => {
29587
29705
  GIT_CONFIG_VALUE_0: posix(hooks)
29588
29706
  });
29589
29707
  } else {
29590
- env.vars.GIT_DIR = path41.join(dataDir, "git-disabled");
29708
+ env.vars.GIT_DIR = path42.join(dataDir, "git-disabled");
29591
29709
  }
29592
29710
  };
29593
29711
  var pointAtOwnCertificates = (root) => {
29594
- const config2 = path41.join(root, "etc", "gitconfig");
29595
- const bundle = path41.join(root, "mingw64", "etc", "ssl", "certs", "ca-bundle.crt");
29712
+ const config2 = path42.join(root, "etc", "gitconfig");
29713
+ const bundle = path42.join(root, "mingw64", "etc", "ssl", "certs", "ca-bundle.crt");
29596
29714
  if (!exists(config2) || !exists(bundle)) return;
29597
- const text = fs32.readFileSync(config2, "utf8");
29715
+ const text = fs33.readFileSync(config2, "utf8");
29598
29716
  const fixed = text.replace(/^(\s*sslCAInfo\s*=\s*).*$/gim, (_m, key2) => key2 + posix(bundle));
29599
- if (fixed !== text) fs32.writeFileSync(config2, fixed);
29717
+ if (fixed !== text) fs33.writeFileSync(config2, fixed);
29600
29718
  };
29601
29719
  async function setupGit(env, hostCopy, refresh, access) {
29602
29720
  const root = tool("git");
29603
- const bash = path41.join(root, "bin", "bash.exe");
29604
- const gitExe = path41.join(root, "cmd", "git.exe");
29605
- const hostGit = path41.join(hostToolsDir, "git");
29721
+ const bash = path42.join(root, "bin", "bash.exe");
29722
+ const gitExe = path42.join(root, "cmd", "git.exe");
29723
+ const hostGit = path42.join(hostToolsDir, "git");
29606
29724
  if (exists(root) && !exists(bash)) {
29607
29725
  log("Replacing the old MinGit (no bash) with full Git for Windows.");
29608
29726
  safeRemove(root, toolsDir);
@@ -29616,11 +29734,11 @@ async function setupGit(env, hostCopy, refresh, access) {
29616
29734
  }
29617
29735
  const work = stagingFolder(root);
29618
29736
  try {
29619
- if (hostCopy && exists(path41.join(hostGit, "bin", "bash.exe"))) {
29737
+ if (hostCopy && exists(path42.join(hostGit, "bin", "bash.exe"))) {
29620
29738
  log("Copying Git for Windows from this PC ...");
29621
29739
  robocopy(hostGit, work);
29622
29740
  } else await installPortableGit(work);
29623
- if (!exists(path41.join(work, "bin", "bash.exe"))) throw new Error("bash.exe missing after installing Git");
29741
+ if (!exists(path42.join(work, "bin", "bash.exe"))) throw new Error("bash.exe missing after installing Git");
29624
29742
  moveIntoPlace(work, root);
29625
29743
  } finally {
29626
29744
  safeRemove(work, toolsDir);
@@ -29629,10 +29747,10 @@ async function setupGit(env, hostCopy, refresh, access) {
29629
29747
  if (!exists(bash)) throw new Error("bash.exe missing after installing Git");
29630
29748
  pointAtOwnCertificates(root);
29631
29749
  env.vars.CLAUDE_CODE_GIT_BASH_PATH = bash;
29632
- env.append.push(path41.join(root, "usr", "bin"));
29750
+ env.append.push(path42.join(root, "usr", "bin"));
29633
29751
  const version2 = execOutput(gitExe, ["--version"]).replace(/^git version /, "");
29634
29752
  if (access === "full") {
29635
- env.prepend.push(path41.join(root, "cmd"));
29753
+ env.prepend.push(path42.join(root, "cmd"));
29636
29754
  env.summary.push("git: " + version2);
29637
29755
  return;
29638
29756
  }
@@ -29643,8 +29761,8 @@ async function setupGit(env, hostCopy, refresh, access) {
29643
29761
  }
29644
29762
 
29645
29763
  // src/guest/toolchains/languages/go.ts
29646
- import fs33 from "node:fs";
29647
- import path42 from "node:path";
29764
+ import fs34 from "node:fs";
29765
+ import path43 from "node:path";
29648
29766
 
29649
29767
  // src/guest/toolchains/package-ledger.ts
29650
29768
  var LedgerSchema = external_exports.record(external_exports.string(), external_exports.string());
@@ -29698,7 +29816,7 @@ async function setupGo(env, config2) {
29698
29816
  }
29699
29817
  const version2 = await resolveCached("go:" + config2.version, async () => (await findRelease(config2.version)).version);
29700
29818
  const root = tool("go", version2);
29701
- if (!exists(path42.join(root, "bin", "go.exe"))) {
29819
+ if (!exists(path43.join(root, "bin", "go.exe"))) {
29702
29820
  const goArch = arch === "arm64" ? "arm64" : "amd64";
29703
29821
  const file3 = (await findRelease(version2)).files.find(
29704
29822
  (f) => f.os === "windows" && f.arch === goArch && f.kind === "archive"
@@ -29715,16 +29833,16 @@ async function setupGo(env, config2) {
29715
29833
  const vars = {
29716
29834
  GOROOT: root,
29717
29835
  GOPATH,
29718
- GOBIN: path42.join(GOPATH, "bin"),
29719
- GOMODCACHE: path42.join(GOPATH, "pkg", "mod"),
29836
+ GOBIN: path43.join(GOPATH, "bin"),
29837
+ GOMODCACHE: path43.join(GOPATH, "pkg", "mod"),
29720
29838
  GOCACHE: tool("go-cache"),
29721
29839
  GOTOOLCHAIN: "auto",
29722
29840
  GOTELEMETRY: "off"
29723
29841
  };
29724
- fs33.mkdirSync(vars.GOBIN, { recursive: true });
29842
+ fs34.mkdirSync(vars.GOBIN, { recursive: true });
29725
29843
  Object.assign(env.vars, vars);
29726
- env.prepend.push(path42.join(root, "bin"), vars.GOBIN);
29727
- const go = path42.join(root, "bin", "go.exe");
29844
+ env.prepend.push(path43.join(root, "bin"), vars.GOBIN);
29845
+ const go = path43.join(root, "bin", "go.exe");
29728
29846
  env.summary.push("go: " + versionOf(go, ["version"]));
29729
29847
  await installOnce(
29730
29848
  env,
@@ -29735,8 +29853,8 @@ async function setupGo(env, config2) {
29735
29853
  }
29736
29854
 
29737
29855
  // src/guest/toolchains/tools/cli.ts
29738
- import fs34 from "node:fs";
29739
- import path44 from "node:path";
29856
+ import fs35 from "node:fs";
29857
+ import path45 from "node:path";
29740
29858
 
29741
29859
  // src/guest/toolchains/catalogue.ts
29742
29860
  function pwshAsset(arch2) {
@@ -29783,14 +29901,14 @@ function decideCli(settings, ctx) {
29783
29901
  }
29784
29902
 
29785
29903
  // src/guest/toolchains/runtimes.ts
29786
- import path43 from "node:path";
29904
+ import path44 from "node:path";
29787
29905
  async function setupSingleExe(env, name, repo, pattern, exeName, dir, options = {}) {
29788
29906
  if (dryRun) {
29789
29907
  log("(dry run) would provision " + name);
29790
29908
  return;
29791
29909
  }
29792
- const bin = options.subdir ? path43.join(dir, options.subdir) : dir;
29793
- const exe = path43.join(bin, exeName);
29910
+ const bin = options.subdir ? path44.join(dir, options.subdir) : dir;
29911
+ const exe = path44.join(bin, exeName);
29794
29912
  if (!exists(exe) || options.refresh) {
29795
29913
  const size = options.size ? ", ~" + options.size : "";
29796
29914
  await installFromGithub(repo, pattern, {
@@ -29815,8 +29933,8 @@ async function setupBun(env) {
29815
29933
  );
29816
29934
  Object.assign(env.vars, {
29817
29935
  BUN_INSTALL: tool("bun"),
29818
- BUN_INSTALL_CACHE_DIR: path43.join(localDir, "bun-cache"),
29819
- BUN_TMPDIR: path43.join(localDir, "bun-tmp")
29936
+ BUN_INSTALL_CACHE_DIR: path44.join(localDir, "bun-cache"),
29937
+ BUN_TMPDIR: path44.join(localDir, "bun-tmp")
29820
29938
  });
29821
29939
  }
29822
29940
  async function setupDeno(env) {
@@ -29855,11 +29973,14 @@ async function setupUv(env) {
29855
29973
 
29856
29974
  // src/guest/toolchains/tools/cli.ts
29857
29975
  function ghConfigDir() {
29858
- return path44.join(stateDir, "gh");
29976
+ return path45.join(stateDir, "gh");
29977
+ }
29978
+ function deliveredGhConfigDir() {
29979
+ return path45.join(localDir, "gh-token");
29859
29980
  }
29860
29981
  var toolVars = {
29861
29982
  gh: () => ({
29862
- GH_CONFIG_DIR: mkdirp(ghConfigDir()),
29983
+ GH_CONFIG_DIR: exists(deliveredGhConfigDir()) ? deliveredGhConfigDir() : mkdirp(ghConfigDir()),
29863
29984
  GH_NO_UPDATE_NOTIFIER: "1",
29864
29985
  GH_NO_EXTENSION_UPDATE_NOTIFIER: "1"
29865
29986
  })
@@ -29870,16 +29991,16 @@ var shimOpenssl = (env) => {
29870
29991
  return;
29871
29992
  }
29872
29993
  const shims = mkdirp(tool("shims"));
29873
- fs34.copyFileSync(ensureCompiled("openssl"), path44.join(shims, "openssl.exe"));
29874
- fs34.rmSync(path44.join(shims, "openssl.cmd"), { force: true });
29994
+ fs35.copyFileSync(ensureCompiled("openssl"), path45.join(shims, "openssl.exe"));
29995
+ fs35.rmSync(path45.join(shims, "openssl.cmd"), { force: true });
29875
29996
  env.prepend.push(shims);
29876
29997
  env.summary.push("openssl: Git for Windows' copy");
29877
29998
  };
29878
29999
  async function setupCli(env, settings, gitAccess, refresh = false) {
29879
- const decisions = decideCli(settings, { gitAccess, hasGithubDir: exists(path44.join(projectWorkspace(), ".github")) });
30000
+ const decisions = decideCli(settings, { gitAccess, hasGithubDir: exists(path45.join(projectWorkspace(), ".github")) });
29880
30001
  if (settings.gh && !decisions.gh.on) {
29881
30002
  env.summary.push("gh: off (" + decisions.gh.reason + ")");
29882
- if (exists(path44.join(ghConfigDir(), "hosts.yml")))
30003
+ if (exists(path45.join(ghConfigDir(), "hosts.yml")))
29883
30004
  warn(
29884
30005
  'gh is off (git access is not "full"), but an earlier gh login is still stored in ' + ghConfigDir() + " and readable by the agent. Run `gh auth logout` in a full-access sandbox, or delete that folder."
29885
30006
  );
@@ -29916,12 +30037,12 @@ async function setupCli(env, settings, gitAccess, refresh = false) {
29916
30037
  }
29917
30038
 
29918
30039
  // src/guest/toolchains/managers.ts
29919
- import fs35 from "node:fs";
29920
- import path45 from "node:path";
30040
+ import fs36 from "node:fs";
30041
+ import path46 from "node:path";
29921
30042
  function voltaPins() {
29922
30043
  try {
29923
30044
  const pkg = JSON.parse(
29924
- fs35.readFileSync(path45.join(projectWorkspace(), "package.json"), "utf8").replace(/^\uFEFF/, "")
30045
+ fs36.readFileSync(path46.join(projectWorkspace(), "package.json"), "utf8").replace(/^\uFEFF/, "")
29925
30046
  );
29926
30047
  return Object.fromEntries(
29927
30048
  Object.entries(pkg.volta ?? {}).filter(
@@ -29944,7 +30065,7 @@ async function setupVolta(env) {
29944
30065
  return;
29945
30066
  }
29946
30067
  const dir = tool("volta");
29947
- if (!exists(path45.join(dir, "volta.exe"))) {
30068
+ if (!exists(path46.join(dir, "volta.exe"))) {
29948
30069
  const pattern = arch === "arm64" ? /^volta-[\d.]+-windows-arm64\.zip$/ : /^volta-[\d.]+-windows\.zip$/;
29949
30070
  await installFromGithub("volta-cli/volta", pattern, {
29950
30071
  dest: dir,
@@ -29953,17 +30074,17 @@ async function setupVolta(env) {
29953
30074
  });
29954
30075
  }
29955
30076
  for (const shim3 of ["node", "npm", "npx", "pnpm", "pnpx", "yarn", "yarnpkg"]) {
29956
- const target = path45.join(dir, shim3 + ".exe");
29957
- if (!exists(target)) fs35.copyFileSync(path45.join(dir, "volta-shim.exe"), target);
30077
+ const target = path46.join(dir, shim3 + ".exe");
30078
+ if (!exists(target)) fs36.copyFileSync(path46.join(dir, "volta-shim.exe"), target);
29958
30079
  }
29959
30080
  const home = mkdirp(tool("volta-home"));
29960
- const shims = mkdirp(path45.join(home, "bin"));
30081
+ const shims = mkdirp(path46.join(home, "bin"));
29961
30082
  const vars = { VOLTA_HOME: home, VOLTA_FEATURE_PNPM: "1" };
29962
30083
  Object.assign(env.vars, vars);
29963
30084
  const pins = voltaPins();
29964
30085
  if (Object.keys(pins).length) env.prepend.push(dir, shims);
29965
30086
  else env.append.push(dir, shims);
29966
- const volta = path45.join(dir, "volta.exe");
30087
+ const volta = path46.join(dir, "volta.exe");
29967
30088
  for (const [toolName, version2] of Object.entries(pins)) {
29968
30089
  try {
29969
30090
  await execAsync(volta, ["install", toolName + "@" + version2], {
@@ -29985,7 +30106,7 @@ async function setupPyenv(env) {
29985
30106
  return;
29986
30107
  }
29987
30108
  const root = tool("pyenv", "pyenv-win");
29988
- if (!exists(path45.join(root, "bin", "pyenv.bat"))) {
30109
+ if (!exists(path46.join(root, "bin", "pyenv.bat"))) {
29989
30110
  const tag = await resolveCached("pyenv-win", () => latestGithubTag("pyenv-win/pyenv-win"));
29990
30111
  log("Downloading pyenv-win " + tag + " (~5 MB once) ...");
29991
30112
  await downloader.archive(
@@ -29994,17 +30115,17 @@ async function setupPyenv(env) {
29994
30115
  { locate: "pyenv.bat", up: 1, fileName: "pyenv-win.zip" }
29995
30116
  );
29996
30117
  }
29997
- const home = root + path45.sep;
30118
+ const home = root + path46.sep;
29998
30119
  Object.assign(env.vars, { PYENV: home, PYENV_ROOT: home, PYENV_HOME: home });
29999
- env.append.push(path45.join(root, "bin"), path45.join(root, "shims"));
30120
+ env.append.push(path46.join(root, "bin"), path46.join(root, "shims"));
30000
30121
  env.summary.push("pyenv-win: pyenv install <version> / pyenv local <version> (versions persist)");
30001
30122
  }
30002
30123
 
30003
30124
  // src/guest/toolchains/native/cpp.ts
30004
- import path46 from "node:path";
30125
+ import path47 from "node:path";
30005
30126
  async function setupCpp(env, config2) {
30006
30127
  const bin = tool("mingw", "mingw64", "bin");
30007
- const gcc = path46.join(bin, "gcc.exe");
30128
+ const gcc = path47.join(bin, "gcc.exe");
30008
30129
  if (dryRun) {
30009
30130
  log("(dry run) would provision MinGW-w64 GCC");
30010
30131
  return;
@@ -30020,7 +30141,7 @@ async function setupCpp(env, config2) {
30020
30141
  if (!exists(gcc)) throw new Error("gcc.exe missing after installing MinGW");
30021
30142
  env.append.unshift(bin);
30022
30143
  env.vars.CARGO_TARGET_X86_64_PC_WINDOWS_GNU_LINKER = gcc;
30023
- const cmake = versionOf(path46.join(bin, "cmake.exe"));
30144
+ const cmake = versionOf(path47.join(bin, "cmake.exe"));
30024
30145
  if (cmakeTooOld(cmake))
30025
30146
  warn(
30026
30147
  "The bundled CMake " + cmake + " is older than " + CMAKE_FLOOR + ", which many projects need; set toolchains.cpp.enabled to refresh it, or install a newer CMake into C:\\AgentData\\tools\\bin."
@@ -30030,7 +30151,7 @@ async function setupCpp(env, config2) {
30030
30151
  }
30031
30152
  var setupFlexBison = async (env) => {
30032
30153
  const dir = tool("winflexbison");
30033
- if (!exists(path46.join(dir, "win_bison.exe"))) {
30154
+ if (!exists(path47.join(dir, "win_bison.exe"))) {
30034
30155
  await installFromGithub("lexxmark/winflexbison", /^win_flex_bison-[\d.]+\.zip$/, {
30035
30156
  dest: dir,
30036
30157
  what: "win_flex / win_bison (~1 MB once)",
@@ -30038,16 +30159,16 @@ var setupFlexBison = async (env) => {
30038
30159
  });
30039
30160
  }
30040
30161
  env.append.push(dir);
30041
- env.summary.push("win_flex/win_bison: " + versionOf(path46.join(dir, "win_bison.exe")));
30162
+ env.summary.push("win_flex/win_bison: " + versionOf(path47.join(dir, "win_bison.exe")));
30042
30163
  };
30043
30164
 
30044
30165
  // src/guest/toolchains/native/dotnet.ts
30045
- import fs36 from "node:fs";
30046
- import path47 from "node:path";
30166
+ import fs37 from "node:fs";
30167
+ import path48 from "node:path";
30047
30168
  var DotnetMarkerSchema = external_exports.record(external_exports.string(), external_exports.boolean());
30048
30169
  async function setupDotnet(env, config2, refresh) {
30049
30170
  const root = tool("dotnet");
30050
- const marker = path47.join(root, ".agent-sandbox-installed.json");
30171
+ const marker = path48.join(root, ".agent-sandbox-installed.json");
30051
30172
  const script = tool("dotnet-install.ps1");
30052
30173
  if (dryRun) {
30053
30174
  log("(dry run) would provision .NET SDK channels " + config2.channels.join(", "));
@@ -30055,11 +30176,11 @@ async function setupDotnet(env, config2, refresh) {
30055
30176
  }
30056
30177
  const recorded = DotnetMarkerSchema.safeParse(exists(marker) && !refresh ? readJsonFile(marker) : {});
30057
30178
  const done = recorded.success ? recorded.data : {};
30058
- const globalJson = path47.join(projectWorkspace(), "global.json");
30179
+ const globalJson = path48.join(projectWorkspace(), "global.json");
30059
30180
  const installs = [
30060
30181
  ...config2.channels.map((c) => ["channel:" + c, ["-Channel", c]]),
30061
30182
  ...exists(globalJson) ? [
30062
- ["global.json:" + fs36.readFileSync(globalJson, "utf8").replace(/\s+/g, ""), ["-JSonFile", globalJson]]
30183
+ ["global.json:" + fs37.readFileSync(globalJson, "utf8").replace(/\s+/g, ""), ["-JSonFile", globalJson]]
30063
30184
  ] : []
30064
30185
  ];
30065
30186
  for (const [key2, args] of installs.filter(([k]) => !done[k])) {
@@ -30091,12 +30212,12 @@ async function setupDotnet(env, config2, refresh) {
30091
30212
  DOTNET_SKIP_FIRST_TIME_EXPERIENCE: "1",
30092
30213
  NUGET_PACKAGES: tool("nuget", "packages")
30093
30214
  });
30094
- env.prepend.push(root, path47.join(home, ".dotnet", "tools"));
30215
+ env.prepend.push(root, path48.join(home, ".dotnet", "tools"));
30095
30216
  env.summary.push(
30096
- "dotnet: " + execOutput(path47.join(root, "dotnet.exe"), ["--list-sdks"]).split(/\r?\n/).map((l) => l.split(" ")[0]).filter(Boolean).join(", ")
30217
+ "dotnet: " + execOutput(path48.join(root, "dotnet.exe"), ["--list-sdks"]).split(/\r?\n/).map((l) => l.split(" ")[0]).filter(Boolean).join(", ")
30097
30218
  );
30098
- const dotnet = path47.join(root, "dotnet.exe");
30099
- const dotnetEnv = { env: { ...process.env, ...env.vars, PATH: root + path47.delimiter + (process.env.PATH ?? "") } };
30219
+ const dotnet = path48.join(root, "dotnet.exe");
30220
+ const dotnetEnv = { env: { ...process.env, ...env.vars, PATH: root + path48.delimiter + (process.env.PATH ?? "") } };
30100
30221
  await installOnce(
30101
30222
  env,
30102
30223
  "dotnet workload",
@@ -30117,7 +30238,7 @@ var setupFrameworkReferences = async (env, targets) => {
30117
30238
  const root = tool("netfx-references");
30118
30239
  for (const target of targets) {
30119
30240
  const id = "microsoft.netframework.referenceassemblies." + target.toLowerCase();
30120
- const marker = path47.join(root, ".installed-" + target.toLowerCase());
30241
+ const marker = path48.join(root, ".installed-" + target.toLowerCase());
30121
30242
  if (exists(marker)) continue;
30122
30243
  const staging = tool("netfx-references-" + target.toLowerCase());
30123
30244
  try {
@@ -30132,8 +30253,8 @@ var setupFrameworkReferences = async (env, targets) => {
30132
30253
  staging,
30133
30254
  { fileName: id + ".zip" }
30134
30255
  );
30135
- fs36.cpSync(path47.join(staging, "build", ".NETFramework"), path47.join(root, ".NETFramework"), { recursive: true });
30136
- fs36.writeFileSync(marker, version2);
30256
+ fs37.cpSync(path48.join(staging, "build", ".NETFramework"), path48.join(root, ".NETFramework"), { recursive: true });
30257
+ fs37.writeFileSync(marker, version2);
30137
30258
  } catch (e) {
30138
30259
  warn(
30139
30260
  ".NET Framework " + target + " reference assemblies could not be installed (projects targeting it will not build): " + errMsg(e)
@@ -30142,9 +30263,9 @@ var setupFrameworkReferences = async (env, targets) => {
30142
30263
  safeRemove(staging, dataDir);
30143
30264
  }
30144
30265
  }
30145
- if (!exists(path47.join(root, ".NETFramework"))) return;
30146
- env.vars.TargetFrameworkRootPath = root + path47.sep;
30147
- env.summary.push(".NET Framework targeting: " + fs36.readdirSync(path47.join(root, ".NETFramework")).join(", "));
30266
+ if (!exists(path48.join(root, ".NETFramework"))) return;
30267
+ env.vars.TargetFrameworkRootPath = root + path48.sep;
30268
+ env.summary.push(".NET Framework targeting: " + fs37.readdirSync(path48.join(root, ".NETFramework")).join(", "));
30148
30269
  };
30149
30270
  var setupNetFx35 = async (env) => {
30150
30271
  if (execOutput(SYSTEM.reg(), [
@@ -30171,15 +30292,15 @@ var setupNetFx35 = async (env) => {
30171
30292
  };
30172
30293
 
30173
30294
  // src/guest/toolchains/native/mesa.ts
30174
- import path48 from "node:path";
30295
+ import path49 from "node:path";
30175
30296
  async function setupMesa(env, config2) {
30176
30297
  if (dryRun) {
30177
30298
  log("(dry run) would provision Mesa 3D");
30178
30299
  return;
30179
30300
  }
30180
30301
  const root = tool("mesa");
30181
- const dir = path48.join(root, arch === "arm64" ? "arm64" : "x64");
30182
- if (!exists(path48.join(dir, "opengl32.dll"))) {
30302
+ const dir = path49.join(root, arch === "arm64" ? "arm64" : "x64");
30303
+ if (!exists(path49.join(dir, "opengl32.dll"))) {
30183
30304
  await installFromGithub("pal1000/mesa-dist-win", /^mesa3d-[\d.]+-release-msvc\.7z$/, {
30184
30305
  dest: root,
30185
30306
  what: "Mesa 3D for software OpenGL (~100 MB once)",
@@ -30195,10 +30316,10 @@ async function setupMesa(env, config2) {
30195
30316
  }
30196
30317
  var VULKAN_RUNTIME = "https://sdk.lunarg.com/sdk/download/latest/windows/vulkan-runtime-components.zip";
30197
30318
  var setupLavapipe = async (env, mesaDir) => {
30198
- const icd = path48.join(mesaDir, arch === "arm64" ? "lvp_icd.aarch64.json" : "lvp_icd.x86_64.json");
30199
- if (!exists(icd)) throw new Error("this Mesa build has no lavapipe (" + path48.basename(icd) + ")");
30319
+ const icd = path49.join(mesaDir, arch === "arm64" ? "lvp_icd.aarch64.json" : "lvp_icd.x86_64.json");
30320
+ if (!exists(icd)) throw new Error("this Mesa build has no lavapipe (" + path49.basename(icd) + ")");
30200
30321
  const dir = tool("vulkan");
30201
- if (!exists(path48.join(dir, "vulkan-1.dll"))) {
30322
+ if (!exists(path49.join(dir, "vulkan-1.dll"))) {
30202
30323
  log("Downloading the Vulkan loader (~10 MB once) ...");
30203
30324
  await downloader.archive(VULKAN_RUNTIME, dir, {
30204
30325
  locate: "vulkan-1.dll",
@@ -30212,7 +30333,7 @@ var setupLavapipe = async (env, mesaDir) => {
30212
30333
  { stdio: "ignore" }
30213
30334
  );
30214
30335
  await register(icd);
30215
- const dozen = path48.join(mesaDir, arch === "arm64" ? "dzn_icd.aarch64.json" : "dzn_icd.x86_64.json");
30336
+ const dozen = path49.join(mesaDir, arch === "arm64" ? "dzn_icd.aarch64.json" : "dzn_icd.x86_64.json");
30216
30337
  const gpu = hasGpu();
30217
30338
  if (gpu && exists(dozen)) await register(dozen);
30218
30339
  env.prepend.push(dir);
@@ -30223,20 +30344,20 @@ var setupLavapipe = async (env, mesaDir) => {
30223
30344
  var hasGpu = () => scriptOutput("get-gpu-names.ps1", [], { timeout: 3e4 }).split(/\r?\n/).map((n) => n.trim()).some((n) => n && !/^Microsoft (Remote Display|Basic (Render|Display))/i.test(n));
30224
30345
 
30225
30346
  // src/guest/toolchains/native/msvc/index.ts
30226
- import fs40 from "node:fs";
30227
- import path52 from "node:path";
30347
+ import fs41 from "node:fs";
30348
+ import path53 from "node:path";
30228
30349
 
30229
30350
  // src/guest/toolchains/native/msvc/environment.ts
30230
- import fs38 from "node:fs";
30231
- import path50 from "node:path";
30351
+ import fs39 from "node:fs";
30352
+ import path51 from "node:path";
30232
30353
 
30233
30354
  // src/guest/toolchains/native/msvc/tree.ts
30234
- import fs37 from "node:fs";
30235
- import path49 from "node:path";
30355
+ import fs38 from "node:fs";
30356
+ import path50 from "node:path";
30236
30357
  var ROOT = tool("msvc");
30237
- var MARKER2 = path49.join(ROOT, ".installed.json");
30358
+ var MARKER2 = path50.join(ROOT, ".installed.json");
30238
30359
  function msvcTools(msvc, ...parts2) {
30239
- return path49.join(ROOT, "VC", "Tools", "MSVC", msvc, ...parts2);
30360
+ return path50.join(ROOT, "VC", "Tools", "MSVC", msvc, ...parts2);
30240
30361
  }
30241
30362
  function hostBin(msvc, ...parts2) {
30242
30363
  return msvcTools(msvc, "bin", "Hostx64", "x64", ...parts2);
@@ -30247,27 +30368,27 @@ function hasCompiler(msvc) {
30247
30368
  var InstalledSchema = external_exports.object({ msvc: external_exports.string().min(1), sdk: external_exports.string().min(1), want: external_exports.string() });
30248
30369
  function readInstalled() {
30249
30370
  try {
30250
- return InstalledSchema.safeParse(JSON.parse(fs37.readFileSync(MARKER2, "utf8"))).data ?? null;
30371
+ return InstalledSchema.safeParse(JSON.parse(fs38.readFileSync(MARKER2, "utf8"))).data ?? null;
30251
30372
  } catch {
30252
30373
  return null;
30253
30374
  }
30254
30375
  }
30255
30376
 
30256
30377
  // src/guest/toolchains/native/msvc/environment.ts
30257
- var VSWHERE_DIR = path50.join(
30378
+ var VSWHERE_DIR = path51.join(
30258
30379
  process.env["ProgramFiles(x86)"] ?? "C:\\Program Files (x86)",
30259
30380
  "Microsoft Visual Studio",
30260
30381
  "Installer"
30261
30382
  );
30262
30383
  function vcvars(root, msvc, sdk) {
30263
- const vc = path50.join(root, "VC", "Tools", "MSVC", msvc);
30264
- const kits = path50.join(root, "Windows Kits", "10");
30265
- const inc = (...p) => path50.join(kits, "Include", sdk, ...p);
30266
- const lib = (...p) => path50.join(kits, "Lib", sdk, ...p);
30384
+ const vc = path51.join(root, "VC", "Tools", "MSVC", msvc);
30385
+ const kits = path51.join(root, "Windows Kits", "10");
30386
+ const inc = (...p) => path51.join(kits, "Include", sdk, ...p);
30387
+ const lib = (...p) => path51.join(kits, "Lib", sdk, ...p);
30267
30388
  return {
30268
30389
  vars: {
30269
30390
  VSINSTALLDIR: root + "\\",
30270
- VCINSTALLDIR: path50.join(root, "VC") + "\\",
30391
+ VCINSTALLDIR: path51.join(root, "VC") + "\\",
30271
30392
  VCToolsInstallDir: vc + "\\",
30272
30393
  VCToolsVersion: msvc,
30273
30394
  VisualStudioVersion: "17.0",
@@ -30279,17 +30400,17 @@ function vcvars(root, msvc, sdk) {
30279
30400
  VSCMD_ARG_HOST_ARCH: "x64",
30280
30401
  VSCMD_ARG_TGT_ARCH: "x64",
30281
30402
  Platform: "x64",
30282
- INCLUDE: [path50.join(vc, "include"), inc("ucrt"), inc("shared"), inc("um"), inc("winrt"), inc("cppwinrt")].join(
30403
+ INCLUDE: [path51.join(vc, "include"), inc("ucrt"), inc("shared"), inc("um"), inc("winrt"), inc("cppwinrt")].join(
30283
30404
  ";"
30284
30405
  ),
30285
- LIB: [path50.join(vc, "lib", "x64"), lib("ucrt", "x64"), lib("um", "x64")].join(";"),
30286
- LIBPATH: [path50.join(vc, "lib", "x64"), path50.join(vc, "lib", "x86", "store", "references")].join(";")
30406
+ LIB: [path51.join(vc, "lib", "x64"), lib("ucrt", "x64"), lib("um", "x64")].join(";"),
30407
+ LIBPATH: [path51.join(vc, "lib", "x64"), path51.join(vc, "lib", "x86", "store", "references")].join(";")
30287
30408
  },
30288
- path: [path50.join(vc, "bin", "Hostx64", "x64"), path50.join(kits, "bin", sdk, "x64")]
30409
+ path: [path51.join(vc, "bin", "Hostx64", "x64"), path51.join(kits, "bin", sdk, "x64")]
30289
30410
  };
30290
30411
  }
30291
30412
  function writeVcvars(env) {
30292
- const dir = mkdirp(path50.join(ROOT, "VC", "Auxiliary", "Build"));
30413
+ const dir = mkdirp(path51.join(ROOT, "VC", "Auxiliary", "Build"));
30293
30414
  const lines = [
30294
30415
  "@echo off",
30295
30416
  "rem Written by Windows Development Sandbox for its portable MSVC (host x64, target x64).",
@@ -30297,9 +30418,9 @@ function writeVcvars(env) {
30297
30418
  'set "PATH=' + env.path.join(";") + ';%PATH%"',
30298
30419
  "exit /b 0"
30299
30420
  ];
30300
- fs38.writeFileSync(path50.join(dir, "vcvars64.bat"), lines.join("\r\n") + "\r\n");
30301
- fs38.writeFileSync(
30302
- path50.join(dir, "vcvarsall.bat"),
30421
+ fs39.writeFileSync(path51.join(dir, "vcvars64.bat"), lines.join("\r\n") + "\r\n");
30422
+ fs39.writeFileSync(
30423
+ path51.join(dir, "vcvarsall.bat"),
30303
30424
  ["@echo off", "rem Only x64 (amd64) is installed.", 'call "%~dp0vcvars64.bat"', "exit /b %errorlevel%"].join(
30304
30425
  "\r\n"
30305
30426
  ) + "\r\n"
@@ -30307,24 +30428,24 @@ function writeVcvars(env) {
30307
30428
  }
30308
30429
  function installVswhere(msvc) {
30309
30430
  mkdirp(VSWHERE_DIR);
30310
- fs38.copyFileSync(ensureCompiled("vswhere"), path50.join(VSWHERE_DIR, "vswhere.exe"));
30431
+ fs39.copyFileSync(ensureCompiled("vswhere"), path51.join(VSWHERE_DIR, "vswhere.exe"));
30311
30432
  const [major, minor] = msvc.split(".").slice(2);
30312
- fs38.writeFileSync(
30313
- path50.join(VSWHERE_DIR, "vswhere.json"),
30433
+ fs39.writeFileSync(
30434
+ path51.join(VSWHERE_DIR, "vswhere.json"),
30314
30435
  JSON.stringify({ installationPath: ROOT, installationVersion: "17." + (minor ?? "0") + ".0." + (major ?? "0") })
30315
30436
  );
30316
30437
  }
30317
30438
  function removeTelemetry(msvc) {
30318
30439
  try {
30319
- fs38.rmSync(hostBin(msvc, "vctip.exe"), { force: true });
30440
+ fs39.rmSync(hostBin(msvc, "vctip.exe"), { force: true });
30320
30441
  } catch (e) {
30321
30442
  warn("Could not remove MSVC's telemetry helper (vctip.exe); it may keep tools\\msvc locked: " + errMsg(e));
30322
30443
  }
30323
30444
  }
30324
30445
 
30325
30446
  // src/guest/toolchains/native/msvc/packages.ts
30326
- import fs39 from "node:fs";
30327
- import path51 from "node:path";
30447
+ import fs40 from "node:fs";
30448
+ import path52 from "node:path";
30328
30449
  var CHANNEL = "https://aka.ms/vs/17/release/channel";
30329
30450
  var MANIFEST_DAY_MS = 24 * 60 * 60 * 1e3;
30330
30451
  var MSVC_PARTS = [
@@ -30350,10 +30471,10 @@ var SDK_MSIS = [
30350
30471
  "Windows SDK Desktop Tools x64-x86_en-us.msi"
30351
30472
  ];
30352
30473
  var manifest = async () => {
30353
- const cached2 = path51.join(ROOT, ".manifest.json");
30354
- if (exists(cached2) && Date.now() - fs39.statSync(cached2).mtimeMs < MANIFEST_DAY_MS) {
30474
+ const cached2 = path52.join(ROOT, ".manifest.json");
30475
+ if (exists(cached2) && Date.now() - fs40.statSync(cached2).mtimeMs < MANIFEST_DAY_MS) {
30355
30476
  try {
30356
- return JSON.parse(fs39.readFileSync(cached2, "utf8"));
30477
+ return JSON.parse(fs40.readFileSync(cached2, "utf8"));
30357
30478
  } catch {
30358
30479
  }
30359
30480
  }
@@ -30362,26 +30483,26 @@ var manifest = async () => {
30362
30483
  if (!item) throw new Error("the Visual Studio channel has no package manifest");
30363
30484
  mkdirp(ROOT);
30364
30485
  await downloader.file(item.url, cached2);
30365
- return JSON.parse(fs39.readFileSync(cached2, "utf8"));
30486
+ return JSON.parse(fs40.readFileSync(cached2, "utf8"));
30366
30487
  };
30367
30488
  var unpackVsix = async (vsix, work) => {
30368
- const out = mkdirp(path51.join(work, "vsix-" + path51.basename(vsix)));
30489
+ const out = mkdirp(path52.join(work, "vsix-" + path52.basename(vsix)));
30369
30490
  await extractArchive(vsix, out, ["Contents"]);
30370
30491
  const decode4 = (dir) => {
30371
- for (const entry of fs39.readdirSync(dir, { withFileTypes: true })) {
30372
- const from = path51.join(dir, entry.name);
30492
+ for (const entry of fs40.readdirSync(dir, { withFileTypes: true })) {
30493
+ const from = path52.join(dir, entry.name);
30373
30494
  let name = entry.name;
30374
30495
  try {
30375
30496
  if (name.includes("%")) name = decodeURIComponent(name);
30376
30497
  } catch {
30377
30498
  }
30378
- const to = path51.join(dir, name);
30379
- if (to !== from) fs39.renameSync(from, to);
30499
+ const to = path52.join(dir, name);
30500
+ if (to !== from) fs40.renameSync(from, to);
30380
30501
  if (entry.isDirectory()) decode4(to);
30381
30502
  }
30382
30503
  };
30383
30504
  decode4(out);
30384
- fs39.cpSync(path51.join(out, "Contents"), ROOT, { recursive: true, force: true });
30505
+ fs40.cpSync(path52.join(out, "Contents"), ROOT, { recursive: true, force: true });
30385
30506
  safeRemove(out, work);
30386
30507
  };
30387
30508
  var unpackMsi = async (msi) => {
@@ -30391,9 +30512,9 @@ var unpackMsi = async (msi) => {
30391
30512
  stdio: "ignore"
30392
30513
  });
30393
30514
  } catch (e) {
30394
- const lines = exists(logFile2) ? fs39.readFileSync(logFile2, "utf16le").split(/\r?\n/).filter((l) => /error|return value 3|failed/i.test(l)).slice(-4).join(" | ") : "";
30515
+ const lines = exists(logFile2) ? fs40.readFileSync(logFile2, "utf16le").split(/\r?\n/).filter((l) => /error|return value 3|failed/i.test(l)).slice(-4).join(" | ") : "";
30395
30516
  throw new Error(
30396
- path51.basename(msi) + " did not unpack: " + (e instanceof Error ? e.message : String(e)) + (lines ? " (" + lines.slice(0, 600) + ")" : "")
30517
+ path52.basename(msi) + " did not unpack: " + (e instanceof Error ? e.message : String(e)) + (lines ? " (" + lines.slice(0, 600) + ")" : "")
30397
30518
  );
30398
30519
  }
30399
30520
  };
@@ -30406,13 +30527,13 @@ var catalogue = (m) => {
30406
30527
  };
30407
30528
  };
30408
30529
  var payloadFetcher = (work) => async (p) => {
30409
- const file3 = path51.join(work, path51.basename(p.fileName.replace(/\\/g, "/")));
30530
+ const file3 = path52.join(work, path52.basename(p.fileName.replace(/\\/g, "/")));
30410
30531
  if (!exists(file3)) await downloader.file(p.url, file3, p.sha256);
30411
30532
  return file3;
30412
30533
  };
30413
30534
  var unpackedToolset = () => {
30414
- const toolsRoot = path51.join(ROOT, "VC", "Tools", "MSVC");
30415
- return fs39.readdirSync(toolsRoot).filter((d) => exists(hostBin(d, "cl.exe"))).sort((a, b) => a.localeCompare(b, void 0, { numeric: true })).pop();
30535
+ const toolsRoot = path52.join(ROOT, "VC", "Tools", "MSVC");
30536
+ return fs40.readdirSync(toolsRoot).filter((d) => exists(hostBin(d, "cl.exe"))).sort((a, b) => a.localeCompare(b, void 0, { numeric: true })).pop();
30416
30537
  };
30417
30538
  async function installPackages(config2) {
30418
30539
  const { ids, pick: pick2 } = catalogue(await manifest());
@@ -30420,7 +30541,7 @@ async function installPackages(config2) {
30420
30541
  if (!version2) throw new Error("no MSVC " + config2.msvcVersion + " in the Visual Studio manifest");
30421
30542
  const sdk = pickWindowsSdk(ids, config2.sdkVersion);
30422
30543
  if (!sdk) throw new Error("no Windows SDK " + config2.sdkVersion + " in the Visual Studio manifest");
30423
- const work = mkdirp(path51.join(ROOT, ".download"));
30544
+ const work = mkdirp(path52.join(ROOT, ".download"));
30424
30545
  const fetchPayload = payloadFetcher(work);
30425
30546
  log("Downloading the MSVC " + version2 + " compiler and C/C++ libraries ...");
30426
30547
  for (const part of MSVC_PARTS) {
@@ -30440,17 +30561,17 @@ async function installPackages(config2) {
30440
30561
  if (!p) throw new Error("the Windows SDK package has no " + name);
30441
30562
  const file3 = await fetchPayload(p);
30442
30563
  msis.push(file3);
30443
- for (const cab of msiCabs(fs39.readFileSync(file3))) {
30564
+ for (const cab of msiCabs(fs40.readFileSync(file3))) {
30444
30565
  const c = payload(cab);
30445
30566
  if (c) await fetchPayload(c);
30446
30567
  }
30447
30568
  }
30448
30569
  log("Unpacking the Windows SDK (a few minutes) ...");
30449
30570
  for (const msi of msis) await unpackMsi(msi);
30450
- for (const name of fs39.readdirSync(ROOT).filter((n) => n.toLowerCase().endsWith(".msi")))
30451
- fs39.rmSync(path51.join(ROOT, name), { force: true });
30571
+ for (const name of fs40.readdirSync(ROOT).filter((n) => n.toLowerCase().endsWith(".msi")))
30572
+ fs40.rmSync(path52.join(ROOT, name), { force: true });
30452
30573
  safeRemove(work, ROOT);
30453
- const sdkVersion = fs39.readdirSync(path51.join(ROOT, "Windows Kits", "10", "Include")).filter((d) => d.startsWith("10.0." + sdk.build)).sort().pop();
30574
+ const sdkVersion = fs40.readdirSync(path52.join(ROOT, "Windows Kits", "10", "Include")).filter((d) => d.startsWith("10.0." + sdk.build)).sort().pop();
30454
30575
  if (!sdkVersion) throw new Error("the Windows SDK did not unpack (no Include\\10.0." + sdk.build + ".*)");
30455
30576
  const toolset = unpackedToolset();
30456
30577
  if (!toolset) throw new Error("MSVC " + version2 + " did not unpack (no cl.exe under VC\\Tools\\MSVC)");
@@ -30464,8 +30585,8 @@ function installedMsvcEnv() {
30464
30585
  }
30465
30586
  var clearTree = () => {
30466
30587
  if (!exists(ROOT)) return;
30467
- for (const name of fs40.readdirSync(ROOT).filter((n) => n !== ".manifest.json" && n !== ".download"))
30468
- safeRemove(path52.join(ROOT, name), ROOT);
30588
+ for (const name of fs41.readdirSync(ROOT).filter((n) => n !== ".manifest.json" && n !== ".download"))
30589
+ safeRemove(path53.join(ROOT, name), ROOT);
30469
30590
  };
30470
30591
  async function setupMsvc(env, config2) {
30471
30592
  if (!config2.acceptLicense) {
@@ -30495,24 +30616,24 @@ async function setupMsvc(env, config2) {
30495
30616
  }
30496
30617
 
30497
30618
  // src/guest/toolchains/native/rust.ts
30498
- import path54 from "node:path";
30619
+ import path55 from "node:path";
30499
30620
 
30500
30621
  // src/guest/toolchains/native/binstall.ts
30501
- import fs41 from "node:fs";
30502
- import path53 from "node:path";
30622
+ import fs42 from "node:fs";
30623
+ import path54 from "node:path";
30503
30624
  var ensureBinstall = async (cargoBin) => {
30504
- const target = path53.join(cargoBin, "cargo-binstall.exe");
30625
+ const target = path54.join(cargoBin, "cargo-binstall.exe");
30505
30626
  if (exists(target)) return true;
30506
30627
  try {
30507
30628
  const dir = tool("cargo-binstall");
30508
- if (!exists(path53.join(dir, "cargo-binstall.exe"))) {
30629
+ if (!exists(path54.join(dir, "cargo-binstall.exe"))) {
30509
30630
  await installFromGithub("cargo-bins/cargo-binstall", binstallAsset(arch), {
30510
30631
  dest: dir,
30511
30632
  what: "cargo-binstall for prebuilt Rust tools (~10 MB once)",
30512
30633
  locate: "cargo-binstall.exe"
30513
30634
  });
30514
30635
  }
30515
- fs41.copyFileSync(path53.join(dir, "cargo-binstall.exe"), target);
30636
+ fs42.copyFileSync(path54.join(dir, "cargo-binstall.exe"), target);
30516
30637
  return true;
30517
30638
  } catch (e) {
30518
30639
  warn("cargo-binstall unavailable, compiling crates with cargo install instead: " + errMsg(e));
@@ -30520,14 +30641,14 @@ var ensureBinstall = async (cargoBin) => {
30520
30641
  }
30521
30642
  };
30522
30643
  function crateInstaller(cargoHome, cargoEnv) {
30523
- const cargo = path53.join(cargoHome, "bin", "cargo.exe");
30644
+ const cargo = path54.join(cargoHome, "bin", "cargo.exe");
30524
30645
  let binstall = null;
30525
30646
  const binstallEnv = {
30526
30647
  ...cargoEnv,
30527
30648
  env: { ...cargoEnv.env ?? process.env, BINSTALL_DISABLE_TELEMETRY: "true" }
30528
30649
  };
30529
30650
  return async (crate) => {
30530
- binstall ??= ensureBinstall(path53.join(cargoHome, "bin"));
30651
+ binstall ??= ensureBinstall(path54.join(cargoHome, "bin"));
30531
30652
  if (await binstall) {
30532
30653
  try {
30533
30654
  await execAsync(
@@ -30549,7 +30670,7 @@ async function setupRust(env, config2, refresh) {
30549
30670
  const RUSTUP_HOME = tool("rust", "rustup");
30550
30671
  const CARGO_HOME = tool("rust", "cargo");
30551
30672
  const rustEnv = { env: { ...process.env, RUSTUP_HOME, CARGO_HOME } };
30552
- const rustup = path54.join(CARGO_HOME, "bin", "rustup.exe");
30673
+ const rustup = path55.join(CARGO_HOME, "bin", "rustup.exe");
30553
30674
  if (dryRun) {
30554
30675
  log("(dry run) would provision Rust " + config2.toolchain + " (" + config2.host + ")");
30555
30676
  return;
@@ -30585,9 +30706,9 @@ async function setupRust(env, config2, refresh) {
30585
30706
  if (refresh) await execAsync(rustup, ["update"], rustEnv);
30586
30707
  }
30587
30708
  Object.assign(env.vars, { RUSTUP_HOME, CARGO_HOME });
30588
- env.prepend.push(path54.join(CARGO_HOME, "bin"));
30709
+ env.prepend.push(path55.join(CARGO_HOME, "bin"));
30589
30710
  env.summary.push(
30590
- "rust: " + versionOf(path54.join(CARGO_HOME, "bin", "rustc.exe"), ["--version"], rustEnv) + " [" + config2.host + "]"
30711
+ "rust: " + versionOf(path55.join(CARGO_HOME, "bin", "rustc.exe"), ["--version"], rustEnv) + " [" + config2.host + "]"
30591
30712
  );
30592
30713
  const toolchainKey = "rustup@" + config2.toolchain;
30593
30714
  await installOnce(
@@ -30608,36 +30729,36 @@ async function setupRust(env, config2, refresh) {
30608
30729
  env: {
30609
30730
  ...rustEnv.env,
30610
30731
  ...msvc.vars,
30611
- PATH: [path54.join(CARGO_HOME, "bin"), ...msvc.path, process.env.PATH ?? ""].join(path54.delimiter)
30732
+ PATH: [path55.join(CARGO_HOME, "bin"), ...msvc.path, process.env.PATH ?? ""].join(path55.delimiter)
30612
30733
  }
30613
30734
  } : {
30614
30735
  env: {
30615
30736
  ...rustEnv.env,
30616
- CARGO_TARGET_X86_64_PC_WINDOWS_GNU_LINKER: path54.join(mingw, "gcc.exe"),
30617
- PATH: [path54.join(CARGO_HOME, "bin"), mingw, process.env.PATH ?? ""].join(path54.delimiter)
30737
+ CARGO_TARGET_X86_64_PC_WINDOWS_GNU_LINKER: path55.join(mingw, "gcc.exe"),
30738
+ PATH: [path55.join(CARGO_HOME, "bin"), mingw, process.env.PATH ?? ""].join(path55.delimiter)
30618
30739
  }
30619
30740
  };
30620
30741
  await installOnce(env, "cargo", config2.crates, crateInstaller(CARGO_HOME, cargoEnv));
30621
30742
  }
30622
30743
 
30623
30744
  // src/guest/toolchains/languages/node.ts
30624
- import fs42 from "node:fs";
30625
- import path55 from "node:path";
30745
+ import fs43 from "node:fs";
30746
+ import path56 from "node:path";
30626
30747
  import { spawn as spawn4 } from "node:child_process";
30627
30748
  var NVM_HOME = tool("nvm");
30628
- var NVM_SYMLINK = path55.join(localDir, "nodejs");
30629
- var HOST_NVM = path55.join(hostToolsDir, "nvm");
30749
+ var NVM_SYMLINK = path56.join(localDir, "nodejs");
30750
+ var HOST_NVM = path56.join(hostToolsDir, "nvm");
30630
30751
  var HOST_VERSIONS_MAX = 3;
30631
- var hostNvmVersions = () => exists(HOST_NVM) ? fs42.readdirSync(HOST_NVM).filter((d) => /^v\d+\.\d+\.\d+$/.test(d) && exists(path55.join(HOST_NVM, d, "node.exe"))).map((d) => d.slice(1)) : [];
30752
+ var hostNvmVersions = () => exists(HOST_NVM) ? fs43.readdirSync(HOST_NVM).filter((d) => /^v\d+\.\d+\.\d+$/.test(d) && exists(path56.join(HOST_NVM, d, "node.exe"))).map((d) => d.slice(1)) : [];
30632
30753
  var resolveNode = (spec) => resolveCached("node:" + spec, async () => {
30633
30754
  const exact = spec.replace(/^v/, "");
30634
30755
  if (/^\d+\.\d+\.\d+$/.test(exact)) return exact;
30635
30756
  const releases = await fetchJson("https://nodejs.org/dist/index.json");
30636
30757
  return pickNodeVersion(releases, spec) ?? Promise.reject(new Error('No Node.js release matches "' + spec + '"'));
30637
30758
  });
30638
- var NVM_TEMP = path55.join(NVM_HOME, ".tmp");
30759
+ var NVM_TEMP = path56.join(NVM_HOME, ".tmp");
30639
30760
  var nvm = (args) => new Promise((resolve2) => {
30640
- const child = spawn4(path55.join(NVM_HOME, "nvm.exe"), args, {
30761
+ const child = spawn4(path56.join(NVM_HOME, "nvm.exe"), args, {
30641
30762
  windowsHide: true,
30642
30763
  env: { ...process.env, NVM_HOME, NVM_SYMLINK, TEMP: NVM_TEMP, TMP: NVM_TEMP }
30643
30764
  });
@@ -30652,27 +30773,37 @@ var nvm = (args) => new Promise((resolve2) => {
30652
30773
  child.once("close", () => resolve2(out));
30653
30774
  });
30654
30775
  var ensureNvm = async () => {
30655
- if (exists(path55.join(NVM_HOME, "nvm.exe"))) return;
30656
- if (exists(path55.join(HOST_NVM, "nvm.exe"))) {
30776
+ if (exists(path56.join(NVM_HOME, "nvm.exe"))) return;
30777
+ if (exists(path56.join(HOST_NVM, "nvm.exe"))) {
30657
30778
  log("Copying nvm from this PC ...");
30658
30779
  mkdirp(NVM_HOME);
30659
- const files = fs42.readdirSync(HOST_NVM).filter((f) => /\.(exe|cmd|vbs)$/i.test(f)).sort((a, b) => Number(a.toLowerCase() === "nvm.exe") - Number(b.toLowerCase() === "nvm.exe"));
30660
- for (const file3 of files) fs42.copyFileSync(path55.join(HOST_NVM, file3), path55.join(NVM_HOME, file3));
30780
+ const files = fs43.readdirSync(HOST_NVM).filter((f) => /\.(exe|cmd|vbs)$/i.test(f)).sort((a, b) => Number(a.toLowerCase() === "nvm.exe") - Number(b.toLowerCase() === "nvm.exe"));
30781
+ for (const file3 of files) fs43.copyFileSync(path56.join(HOST_NVM, file3), path56.join(NVM_HOME, file3));
30661
30782
  return;
30662
30783
  }
30663
30784
  const asset = await githubAsset("coreybutler/nvm-windows", /^nvm-noinstall\.zip$/, true);
30664
30785
  log("Downloading nvm-windows (" + asset.url.split("/").slice(-2, -1)[0] + ") ...");
30665
30786
  await downloader.archive(asset.url, NVM_HOME, { sha256: asset.sha256, locate: "nvm.exe", fileName: asset.name });
30666
30787
  };
30788
+ var hostNodeFolder = (version2) => {
30789
+ const dir = path56.join(hostToolsDir, "node");
30790
+ return session.hostTools.nodeVersion?.replace(/^v/, "") === version2 && exists(path56.join(dir, "node.exe")) ? dir : null;
30791
+ };
30667
30792
  var installNodeVersion = async (version2) => {
30668
- const dir = path55.join(NVM_HOME, "v" + version2);
30669
- const fromHost = path55.join(HOST_NVM, "v" + version2);
30670
- if (exists(path55.join(dir, "node.exe"))) return;
30671
- if (exists(path55.join(fromHost, "node.exe"))) {
30793
+ const dir = path56.join(NVM_HOME, "v" + version2);
30794
+ const fromHost = path56.join(HOST_NVM, "v" + version2);
30795
+ if (exists(path56.join(dir, "node.exe"))) return;
30796
+ if (exists(path56.join(fromHost, "node.exe"))) {
30672
30797
  log("Copying Node " + version2 + " from this PC's nvm (without global packages) ...");
30673
30798
  copyNode(fromHost, dir);
30674
30799
  return;
30675
30800
  }
30801
+ const hostNode = hostNodeFolder(version2);
30802
+ if (hostNode) {
30803
+ log("Copying Node " + version2 + " from this PC (without global packages) ...");
30804
+ copyNode(hostNode, dir);
30805
+ return;
30806
+ }
30676
30807
  log("Downloading Node " + version2 + " (~30 MB once) ...");
30677
30808
  mkdirp(NVM_TEMP);
30678
30809
  let out;
@@ -30681,23 +30812,32 @@ var installNodeVersion = async (version2) => {
30681
30812
  } finally {
30682
30813
  safeRemove(NVM_TEMP, NVM_HOME);
30683
30814
  }
30684
- if (!exists(path55.join(dir, "node.exe")))
30685
- throw new Error("nvm install " + version2 + " failed: " + out.trim().split("\n").slice(-2).join(" "));
30815
+ if (!exists(path56.join(dir, "node.exe"))) {
30816
+ const tail = out.trim().split(/\r?\n/).filter(Boolean).slice(-3).join(" ");
30817
+ const why = /complete/i.test(out) ? "nvm said it finished, but its move into the data folder did not happen" : "nvm could not download or unpack it: check the internet connection and the free disk space";
30818
+ throw new Error(
30819
+ "nvm install " + version2 + " did not leave " + path56.join(dir, "node.exe") + " (" + why + ")" + (tail ? ". nvm printed: " + tail : "")
30820
+ );
30821
+ }
30686
30822
  };
30687
30823
  var activate = async (version2) => {
30688
30824
  await nvm(["use", version2]);
30689
- if (exists(path55.join(NVM_SYMLINK, "node.exe"))) return;
30690
- fs42.rmSync(NVM_SYMLINK, { recursive: true, force: true });
30691
- fs42.symlinkSync(path55.join(NVM_HOME, "v" + version2), NVM_SYMLINK, "junction");
30825
+ if (exists(path56.join(NVM_SYMLINK, "node.exe"))) return;
30826
+ fs43.rmSync(NVM_SYMLINK, { recursive: true, force: true });
30827
+ fs43.symlinkSync(path56.join(NVM_HOME, "v" + version2), NVM_SYMLINK, "junction");
30692
30828
  };
30829
+ var PLAYWRIGHT_VARS = () => ({
30830
+ PLAYWRIGHT_BROWSERS_PATH: tool("ms-playwright"),
30831
+ PLAYWRIGHT_MCP_BROWSER: "msedge"
30832
+ });
30693
30833
  async function setupNode(env, versions, config2) {
30694
30834
  if (dryRun) {
30695
30835
  log("(dry run) would provision nvm and Node " + versions.node.spec + " (from " + versions.node.source + ")");
30696
30836
  return;
30697
30837
  }
30698
30838
  await ensureNvm();
30699
- fs42.writeFileSync(
30700
- path55.join(NVM_HOME, "settings.txt"),
30839
+ fs43.writeFileSync(
30840
+ path56.join(NVM_HOME, "settings.txt"),
30701
30841
  [
30702
30842
  "root: " + NVM_HOME,
30703
30843
  "path: " + NVM_SYMLINK,
@@ -30723,23 +30863,24 @@ async function setupNode(env, versions, config2) {
30723
30863
  warn("Node " + version2 + " from this PC: " + errMsg(e));
30724
30864
  }
30725
30865
  }
30726
- Object.assign(env.vars, { NVM_HOME, NVM_SYMLINK });
30727
- if (duringSession()) env.prepend.push(path55.join(NVM_HOME, "v" + main), NVM_HOME, NVM_SYMLINK);
30866
+ Object.assign(env.vars, { NVM_HOME, NVM_SYMLINK, ...PLAYWRIGHT_VARS() });
30867
+ if (duringSession()) env.prepend.push(path56.join(NVM_HOME, "v" + main), NVM_HOME, NVM_SYMLINK);
30728
30868
  else {
30729
30869
  await activate(main);
30730
30870
  env.prepend.push(NVM_HOME, NVM_SYMLINK);
30731
30871
  }
30732
30872
  env.summary.push("node: " + main + " (from " + versions.node.source + ", switch with nvm use)");
30873
+ env.summary.push("playwright: ready (Edge; browsers it downloads are kept; in tests use channel: 'msedge')");
30733
30874
  await packageManagers(env, config2, main);
30734
30875
  }
30735
30876
  var packageManagers = async (env, config2, version2) => {
30736
- const dir = path55.join(NVM_HOME, "v" + version2);
30737
- const nodeEnv = { ...process.env, PATH: dir + path55.delimiter + (process.env.PATH ?? "") };
30738
- const npm = (args) => execAsync(path55.join(dir, "node.exe"), [path55.join(dir, "node_modules", "npm", "bin", "npm-cli.js"), ...args], {
30877
+ const dir = path56.join(NVM_HOME, "v" + version2);
30878
+ const nodeEnv = { ...process.env, PATH: dir + path56.delimiter + (process.env.PATH ?? "") };
30879
+ const npm = (args) => execAsync(path56.join(dir, "node.exe"), [path56.join(dir, "node_modules", "npm", "bin", "npm-cli.js"), ...args], {
30739
30880
  env: nodeEnv,
30740
30881
  stdio: "ignore"
30741
30882
  });
30742
- const corepackJs = path55.join(dir, "node_modules", "corepack", "dist", "corepack.js");
30883
+ const corepackJs = path56.join(dir, "node_modules", "corepack", "dist", "corepack.js");
30743
30884
  const extra = config2.corepack && !exists(corepackJs) ? ["corepack"] : [];
30744
30885
  await installOnce(
30745
30886
  env,
@@ -30760,7 +30901,7 @@ var packageManagers = async (env, config2, version2) => {
30760
30901
  }
30761
30902
  try {
30762
30903
  await execAsync(
30763
- path55.join(dir, "node.exe"),
30904
+ path56.join(dir, "node.exe"),
30764
30905
  [corepackJs, "enable", "--install-directory", mkdirp(tool("bin")), "pnpm", "yarn"],
30765
30906
  { env: nodeEnv, stdio: "ignore" }
30766
30907
  );
@@ -30785,8 +30926,8 @@ async function setupPwsh(env, refresh = false) {
30785
30926
  }
30786
30927
 
30787
30928
  // src/guest/toolchains/languages/python.ts
30788
- import fs43 from "node:fs";
30789
- import path56 from "node:path";
30929
+ import fs44 from "node:fs";
30930
+ import path57 from "node:path";
30790
30931
  var installPython = async (pkg, spec) => {
30791
30932
  const version2 = await resolveCached(pkg + ":" + spec, async () => {
30792
30933
  const { versions } = await fetchJson(
@@ -30795,7 +30936,7 @@ var installPython = async (pkg, spec) => {
30795
30936
  return pickPackageVersion(versions, spec) ?? Promise.reject(new Error("No " + pkg + ' release matches "' + spec + '"'));
30796
30937
  });
30797
30938
  const dir = tool("python", pkg + "-" + version2);
30798
- const exe = path56.join(dir, "python.exe");
30939
+ const exe = path57.join(dir, "python.exe");
30799
30940
  if (!exists(exe)) {
30800
30941
  log("Downloading Python " + version2 + (pkg === "python2" ? " (Python 2, " : " (") + "~30 MB once) ...");
30801
30942
  await downloader.archive(
@@ -30804,32 +30945,32 @@ var installPython = async (pkg, spec) => {
30804
30945
  { locate: "python.exe", fileName: pkg + "." + version2 + ".zip" }
30805
30946
  );
30806
30947
  }
30807
- if (!exists(path56.join(dir, "Scripts", "pip.exe")) && !exists(path56.join(dir, "Scripts", "pip2.exe")))
30948
+ if (!exists(path57.join(dir, "Scripts", "pip.exe")) && !exists(path57.join(dir, "Scripts", "pip2.exe")))
30808
30949
  await execAsync(exe, ["-m", "ensurepip", "--default-pip"], { stdio: "ignore" });
30809
30950
  return dir;
30810
30951
  };
30811
- var shimDir = (dir) => duringSession() ? tool("shims", path56.basename(dir)) : tool("shims");
30952
+ var shimDir = (dir) => duringSession() ? tool("shims", path57.basename(dir)) : tool("shims");
30812
30953
  var shim = (folder, name, program, args = []) => {
30813
30954
  const fixed = [program, ...args];
30814
- fs43.writeFileSync(
30815
- path56.join(mkdirp(folder), name + ".cmd"),
30955
+ fs44.writeFileSync(
30956
+ path57.join(mkdirp(folder), name + ".cmd"),
30816
30957
  "@echo off\r\n" + fixed.map((a) => '"' + a + '"').join(" ") + " %*\r\n"
30817
30958
  );
30818
30959
  const sh = fixed.map((a) => "'" + a.replace(/\\/g, "/").replace(/'/g, "'\\''") + "'").join(" ");
30819
- fs43.writeFileSync(path56.join(folder, name), "#!/bin/sh\nexec " + sh + ' "$@"\n');
30960
+ fs44.writeFileSync(path57.join(folder, name), "#!/bin/sh\nexec " + sh + ' "$@"\n');
30820
30961
  };
30821
30962
  var shimPair = (folder, version2, dir) => {
30822
- const python = path56.join(dir, "python.exe");
30963
+ const python = path57.join(dir, "python.exe");
30823
30964
  shim(folder, "python" + version2, python);
30824
30965
  shim(folder, "pip" + version2, python, ["-m", "pip"]);
30825
30966
  };
30826
30967
  var pyLauncher = (folder, py3, py2) => {
30827
- const script = path56.join(mkdirp(folder), "py-launcher.py");
30828
- fs43.writeFileSync(
30968
+ const script = path57.join(mkdirp(folder), "py-launcher.py");
30969
+ fs44.writeFileSync(
30829
30970
  script,
30830
30971
  [
30831
30972
  "import subprocess, sys",
30832
- "PY3, PY2 = " + JSON.stringify(path56.join(py3, "python.exe")) + ", " + JSON.stringify(py2 ? path56.join(py2, "python.exe") : null),
30973
+ "PY3, PY2 = " + JSON.stringify(path57.join(py3, "python.exe")) + ", " + JSON.stringify(py2 ? path57.join(py2, "python.exe") : null),
30833
30974
  "args = sys.argv[1:]",
30834
30975
  "exe = PY3",
30835
30976
  "if args and args[0].startswith('-2'):",
@@ -30841,7 +30982,7 @@ var pyLauncher = (folder, py3, py2) => {
30841
30982
  ""
30842
30983
  ].join("\n")
30843
30984
  );
30844
- shim(folder, "py", path56.join(py3, "python.exe"), [script]);
30985
+ shim(folder, "py", path57.join(py3, "python.exe"), [script]);
30845
30986
  };
30846
30987
  async function setupPython(env, config2, versions) {
30847
30988
  if (dryRun) {
@@ -30851,10 +30992,10 @@ async function setupPython(env, config2, versions) {
30851
30992
  const py3 = await installPython("python", versions.python.spec);
30852
30993
  const shims = shimDir(py3);
30853
30994
  shimPair(shims, "3", py3);
30854
- env.prepend.push(py3, mkdirp(path56.join(py3, "Scripts")), shims);
30995
+ env.prepend.push(py3, mkdirp(path57.join(py3, "Scripts")), shims);
30855
30996
  env.vars.PYTHONIOENCODING = "utf-8";
30856
30997
  env.summary.push(
30857
- "python: " + path56.basename(py3).replace("python-", "") + " (from " + versions.python.source + "; py works too)"
30998
+ "python: " + path57.basename(py3).replace("python-", "") + " (from " + versions.python.source + "; py works too)"
30858
30999
  );
30859
31000
  if (!config2.python2) {
30860
31001
  pyLauncher(shims, py3, null);
@@ -30863,16 +31004,16 @@ async function setupPython(env, config2, versions) {
30863
31004
  const py2 = await installPython("python2", "2.7");
30864
31005
  shimPair(shims, "2", py2);
30865
31006
  pyLauncher(shims, py3, py2);
30866
- env.summary.push("python2: " + path56.basename(py2).replace("python2-", ""));
31007
+ env.summary.push("python2: " + path57.basename(py2).replace("python2-", ""));
30867
31008
  }
30868
31009
 
30869
31010
  // src/guest/toolchains/languages/php.ts
30870
- import fs45 from "node:fs";
30871
- import path58 from "node:path";
31011
+ import fs46 from "node:fs";
31012
+ import path59 from "node:path";
30872
31013
 
30873
31014
  // src/guest/toolchains/native/vcruntime.ts
30874
- import fs44 from "node:fs";
30875
- import path57 from "node:path";
31015
+ import fs45 from "node:fs";
31016
+ import path58 from "node:path";
30876
31017
  var VC_REDIST = "https://aka.ms/vs/17/release/vc_redist.x64.exe";
30877
31018
  var MICROSOFT_SIGNER = "CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US";
30878
31019
  var OK_EXIT_CODES = [0, 1638, 3010];
@@ -30882,8 +31023,8 @@ async function setupVcRuntime(env, summary = true) {
30882
31023
  log("(dry run) would install the Visual C++ runtime");
30883
31024
  return false;
30884
31025
  }
30885
- const system322 = path57.join(process.env.WINDIR ?? "C:\\Windows", "System32");
30886
- const missing = !exists(path57.join(system322, "vcruntime140.dll")) || !exists(path57.join(system322, "msvcp140.dll"));
31026
+ const system322 = path58.join(process.env.WINDIR ?? "C:\\Windows", "System32");
31027
+ const missing = !exists(path58.join(system322, "vcruntime140.dll")) || !exists(path58.join(system322, "msvcp140.dll"));
30887
31028
  if (missing) {
30888
31029
  const installer = tool("vcredist", "vc_redist.x64.exe");
30889
31030
  if (!exists(installer)) {
@@ -30891,12 +31032,12 @@ async function setupVcRuntime(env, summary = true) {
30891
31032
  await downloadFile(VC_REDIST, installer);
30892
31033
  }
30893
31034
  if (signerOf(installer) !== MICROSOFT_SIGNER) {
30894
- fs44.rmSync(installer, { force: true });
31035
+ fs45.rmSync(installer, { force: true });
30895
31036
  throw new Error("vc_redist.x64.exe is not signed by Microsoft; deleted it (it is downloaded again next boot)");
30896
31037
  }
30897
31038
  log("Installing the Visual C++ runtime ...");
30898
31039
  const code = await spawnAsync(installer, ["/install", "/quiet", "/norestart"]);
30899
- if (!OK_EXIT_CODES.includes(code ?? -1) || !exists(path57.join(system322, "vcruntime140.dll")))
31040
+ if (!OK_EXIT_CODES.includes(code ?? -1) || !exists(path58.join(system322, "vcruntime140.dll")))
30900
31041
  throw new Error("the Visual C++ runtime installer failed (exit " + code + ")");
30901
31042
  }
30902
31043
  if (summary) env.summary.push("vc++ runtime: installed");
@@ -30934,16 +31075,16 @@ var phpBuild = async (spec) => {
30934
31075
  return { version: release.version, ...build.zip };
30935
31076
  };
30936
31077
  var writePhpIni = (home) => {
30937
- const ini = path58.join(home, "php.ini");
30938
- if (exists(ini) || !exists(path58.join(home, "php.ini-development"))) return;
30939
- let text = fs45.readFileSync(path58.join(home, "php.ini-development"), "utf8").replace(/^;\s*extension_dir\s*=\s*"ext"/m, 'extension_dir = "' + path58.join(home, "ext") + '"');
30940
- for (const ext of PHP_EXTENSIONS.filter((e) => exists(path58.join(home, "ext", "php_" + e + ".dll"))))
31078
+ const ini = path59.join(home, "php.ini");
31079
+ if (exists(ini) || !exists(path59.join(home, "php.ini-development"))) return;
31080
+ let text = fs46.readFileSync(path59.join(home, "php.ini-development"), "utf8").replace(/^;\s*extension_dir\s*=\s*"ext"/m, 'extension_dir = "' + path59.join(home, "ext") + '"');
31081
+ for (const ext of PHP_EXTENSIONS.filter((e) => exists(path59.join(home, "ext", "php_" + e + ".dll"))))
30941
31082
  text = text.replace(new RegExp("^;(extension=" + ext + ")\\s*$", "m"), "$1");
30942
- fs45.writeFileSync(ini + ".tmp", text);
30943
- fs45.renameSync(ini + ".tmp", ini);
31083
+ fs46.writeFileSync(ini + ".tmp", text);
31084
+ fs46.renameSync(ini + ".tmp", ini);
30944
31085
  };
30945
31086
  var shim2 = (env, name, command) => {
30946
- fs45.writeFileSync(path58.join(mkdirp(tool("shims")), name + ".cmd"), "@echo off\r\n" + command + " %*\r\n");
31087
+ fs46.writeFileSync(path59.join(mkdirp(tool("shims")), name + ".cmd"), "@echo off\r\n" + command + " %*\r\n");
30947
31088
  env.prepend.push(tool("shims"));
30948
31089
  };
30949
31090
  var setupComposer = async (env, php) => {
@@ -30955,7 +31096,7 @@ var setupComposer = async (env, php) => {
30955
31096
  }
30956
31097
  const composerHome = tool("composer-home");
30957
31098
  env.vars.COMPOSER_HOME = composerHome;
30958
- env.prepend.push(path58.join(composerHome, "vendor", "bin"));
31099
+ env.prepend.push(path59.join(composerHome, "vendor", "bin"));
30959
31100
  shim2(env, "composer", '"' + php + '" "' + phar + '"');
30960
31101
  env.summary.push(
30961
31102
  "composer: " + (/\d+\.\d+\.\d+/.exec(execOutput(php, [phar, "--version", "--no-ansi"]))?.[0] ?? "installed")
@@ -30970,7 +31111,7 @@ async function setupPhp(env, config2) {
30970
31111
  await setupVcRuntime(env, false);
30971
31112
  const version2 = await resolveCached("php:" + wantedSpec.spec, async () => (await phpBuild(wantedSpec.spec)).version);
30972
31113
  const home = tool("php", version2);
30973
- if (!exists(path58.join(home, "php.exe"))) {
31114
+ if (!exists(path59.join(home, "php.exe"))) {
30974
31115
  const build = await phpBuild(version2);
30975
31116
  log("Downloading PHP " + version2 + " (~30 MB once) ...");
30976
31117
  await downloader.archive("https://windows.php.net/downloads/releases/" + build.path, home, {
@@ -30982,11 +31123,11 @@ async function setupPhp(env, config2) {
30982
31123
  writePhpIni(home);
30983
31124
  env.prepend.push(home);
30984
31125
  env.summary.push("php: " + version2 + " (from " + wantedSpec.source + ")");
30985
- if (config2.composer) await setupComposer(env, path58.join(home, "php.exe"));
31126
+ if (config2.composer) await setupComposer(env, path59.join(home, "php.exe"));
30986
31127
  }
30987
31128
 
30988
31129
  // src/guest/toolchains/languages/ruby.ts
30989
- import path59 from "node:path";
31130
+ import path60 from "node:path";
30990
31131
  var RUBY_ASSET = /^rubyinstaller-(\d+\.\d+\.\d+)-(\d+)-x64\.7z$/;
30991
31132
  var buildNumber = (asset) => Number(RUBY_ASSET.exec(asset.name)?.[2] ?? 0);
30992
31133
  var rubyBuilds = async () => {
@@ -31014,7 +31155,7 @@ async function setupRuby(env, config2) {
31014
31155
  async () => pickPackageVersion([...(await rubyBuilds()).keys()], wantedSpec.spec) ?? Promise.reject(new Error('No RubyInstaller build matches "' + wantedSpec.spec + '"'))
31015
31156
  );
31016
31157
  const home = tool("ruby", version2);
31017
- if (!exists(path59.join(home, "bin", "ruby.exe"))) {
31158
+ if (!exists(path60.join(home, "bin", "ruby.exe"))) {
31018
31159
  const asset = (await rubyBuilds()).get(version2);
31019
31160
  if (!asset) throw new Error("RubyInstaller " + version2 + " is no longer published");
31020
31161
  log("Downloading Ruby " + version2 + " (~100 MB once) ...");
@@ -31027,11 +31168,11 @@ async function setupRuby(env, config2) {
31027
31168
  }
31028
31169
  const gems = tool("ruby-gems", version2.split(".").slice(0, 2).join("."));
31029
31170
  Object.assign(env.vars, { GEM_HOME: gems, BUNDLE_USER_HOME: tool("bundle-home") });
31030
- env.prepend.push(path59.join(home, "bin"), path59.join(gems, "bin"));
31171
+ env.prepend.push(path60.join(home, "bin"), path60.join(gems, "bin"));
31031
31172
  env.summary.push(
31032
- "ruby: " + versionOf(path59.join(home, "bin", "ruby.exe")) + " (from " + wantedSpec.source + "; gems with C extensions need MSYS2, not included)"
31173
+ "ruby: " + versionOf(path60.join(home, "bin", "ruby.exe")) + " (from " + wantedSpec.source + "; gems with C extensions need MSYS2, not included)"
31033
31174
  );
31034
- const gem = path59.join(home, "bin", "gem.cmd");
31175
+ const gem = path60.join(home, "bin", "gem.cmd");
31035
31176
  await installOnce(
31036
31177
  env,
31037
31178
  "gem@" + version2,
@@ -31043,9 +31184,9 @@ async function setupRuby(env, config2) {
31043
31184
  }
31044
31185
 
31045
31186
  // src/guest/toolchains/tools/vscode.ts
31046
- import fs46 from "node:fs";
31187
+ import fs47 from "node:fs";
31047
31188
  import os7 from "node:os";
31048
- import path60 from "node:path";
31189
+ import path61 from "node:path";
31049
31190
 
31050
31191
  // node_modules/jsonc-parser/lib/esm/impl/scanner.js
31051
31192
  var CharacterCodes;
@@ -31225,14 +31366,14 @@ var ParseErrorCode;
31225
31366
  var VERSION_MARKER = ".agent-sandbox-version";
31226
31367
  var desktopShortcut = (exe) => {
31227
31368
  if (!isWin) return;
31228
- const link = path60.join(os7.homedir(), "Desktop", "Visual Studio Code.lnk");
31369
+ const link = path61.join(os7.homedir(), "Desktop", "Visual Studio Code.lnk");
31229
31370
  runScriptWithJson("new-shortcuts.ps1", "ListFile", [
31230
31371
  { link, target: exe, arguments: '"' + (process.env.AGENT_WORKSPACE ?? "") + '"' }
31231
31372
  ]);
31232
31373
  };
31233
31374
  async function setupVscode(env, refresh) {
31234
31375
  const root = tool("vscode");
31235
- const exe = path60.join(root, "Code.exe");
31376
+ const exe = path61.join(root, "Code.exe");
31236
31377
  if (dryRun) {
31237
31378
  log("(dry run) would provision VS Code");
31238
31379
  return;
@@ -31242,11 +31383,11 @@ async function setupVscode(env, refresh) {
31242
31383
  "https://update.code.visualstudio.com/api/update/win32-" + (arch === "arm64" ? "arm64" : "x64") + "-archive/stable/latest"
31243
31384
  );
31244
31385
  log("Downloading VS Code " + release.productVersion + " (~150 MB once) ...");
31245
- const keep = path60.join(root, "data");
31386
+ const keep = path61.join(root, "data");
31246
31387
  const parked = root + "-data";
31247
31388
  if (exists(keep)) {
31248
- fs46.rmSync(parked, { recursive: true, force: true });
31249
- fs46.renameSync(keep, parked);
31389
+ fs47.rmSync(parked, { recursive: true, force: true });
31390
+ fs47.renameSync(keep, parked);
31250
31391
  }
31251
31392
  try {
31252
31393
  await downloader.archive(release.url, root, {
@@ -31254,89 +31395,109 @@ async function setupVscode(env, refresh) {
31254
31395
  locate: "Code.exe",
31255
31396
  fileName: "vscode.zip"
31256
31397
  });
31257
- fs46.writeFileSync(path60.join(root, VERSION_MARKER), release.productVersion);
31398
+ fs47.writeFileSync(path61.join(root, VERSION_MARKER), release.productVersion);
31258
31399
  } finally {
31259
31400
  if (exists(parked)) {
31260
31401
  mkdirp(root);
31261
- fs46.rmSync(keep, { recursive: true, force: true });
31262
- fs46.renameSync(parked, keep);
31402
+ fs47.rmSync(keep, { recursive: true, force: true });
31403
+ fs47.renameSync(parked, keep);
31263
31404
  }
31264
31405
  }
31265
31406
  }
31266
- mkdirp(path60.join(root, "data"));
31267
- env.prepend.push(path60.join(root, "bin"));
31407
+ mkdirp(path61.join(root, "data"));
31408
+ env.prepend.push(path61.join(root, "bin"));
31268
31409
  desktopShortcut(exe);
31269
- const version2 = exists(path60.join(root, VERSION_MARKER)) ? fs46.readFileSync(path60.join(root, VERSION_MARKER), "utf8").trim() : "installed";
31410
+ const version2 = exists(path61.join(root, VERSION_MARKER)) ? fs47.readFileSync(path61.join(root, VERSION_MARKER), "utf8").trim() : "installed";
31270
31411
  env.summary.push("vscode: " + version2 + " (portable; run code . or use the desktop shortcut)");
31271
31412
  }
31272
31413
 
31273
31414
  // src/guest/toolchains/native/rust-extras.ts
31274
- import fs47 from "node:fs";
31415
+ import fs48 from "node:fs";
31275
31416
  import os8 from "node:os";
31276
- import path61 from "node:path";
31417
+ import path62 from "node:path";
31277
31418
 
31278
31419
  // src/shared/memory/policy.ts
31279
- var GUEST_THRESHOLDS = {
31280
- normal: {
31281
- enterAvailablePercent: 8,
31282
- enterCommitPercent: 92,
31283
- exitAvailablePercent: 12,
31284
- exitCommitPercent: 88,
31285
- calmSamples: 3
31286
- },
31287
- gentle: {
31288
- enterAvailablePercent: 15,
31289
- enterCommitPercent: 85,
31290
- exitAvailablePercent: 20,
31291
- exitCommitPercent: 80,
31292
- calmSamples: 3
31293
- }
31420
+ var DIAL_STEPS = {
31421
+ normal: [
31422
+ { availablePercent: 15, commitPercent: 80 },
31423
+ { availablePercent: 10, commitPercent: 88 },
31424
+ { availablePercent: 6, commitPercent: 94, secondsToLimit: 20 },
31425
+ { availablePercent: 4, commitPercent: 97, secondsToLimit: 8 }
31426
+ ],
31427
+ gentle: [
31428
+ { availablePercent: 20, commitPercent: 75 },
31429
+ { availablePercent: 15, commitPercent: 85 },
31430
+ { availablePercent: 8, commitPercent: 92, secondsToLimit: 25 },
31431
+ { availablePercent: 5, commitPercent: 96, secondsToLimit: 10 }
31432
+ ]
31294
31433
  };
31434
+ var DIAL_EXIT_MARGIN = { availablePercent: 5, commitPercent: 4 };
31435
+ var DIAL_CALM_SAMPLES = 3;
31436
+ var DIAL_CPU_RATE = [100, 100, 60, 35, 15];
31437
+ function compilersAllowed(step, running) {
31438
+ if (step <= 1 || running <= 1) return running;
31439
+ if (step === 2) return Math.max(1, Math.ceil(running * 0.6));
31440
+ if (step === 3) return Math.max(1, Math.ceil(running / 3));
31441
+ return 1;
31442
+ }
31443
+ function buildJobs(cpus, memoryGb) {
31444
+ return Math.max(2, Math.min(cpus, Math.floor((memoryGb - 6) / 3)));
31445
+ }
31446
+ function linkSlotsFor(memoryGb) {
31447
+ return Math.max(2, Math.min(8, Math.floor((memoryGb - 6) / 3)));
31448
+ }
31449
+ function usableCpus(cpus, percent) {
31450
+ if (percent === null || percent >= 100) return cpus;
31451
+ return Math.max(2, Math.min(cpus, Math.floor(cpus * percent / 100)));
31452
+ }
31295
31453
  function cargoJobs(cpus, memoryGb, sessions2) {
31296
- const byCpu = Math.max(2, Math.min(4, Math.floor(cpus / 4)));
31454
+ const byCpu = Math.max(2, Math.min(8, Math.floor(cpus / 4)));
31297
31455
  const byMemory = Math.max(1, Math.floor(memoryGb / 4));
31298
31456
  const jobs = Math.min(byCpu, byMemory);
31299
- return Math.max(1, Math.min(jobs, Math.floor(8 / Math.max(1, sessions2))));
31457
+ return Math.max(1, Math.min(jobs, Math.floor(buildJobs(cpus, memoryGb) / Math.max(1, sessions2))));
31458
+ }
31459
+ function maxCompilers(cpus, profile) {
31460
+ return profile === "gentle" ? Math.max(2, Math.floor(cpus / 4)) : null;
31300
31461
  }
31301
31462
 
31302
31463
  // src/guest/toolchains/native/rust-extras.ts
31303
31464
  var cargoTarget = (targetDir) => {
31304
31465
  if (targetDir === "shared" || targetDir === "separate") return null;
31305
- if (targetDir === "local") return path61.join(localDir, "cargo-target");
31466
+ if (targetDir === "local") return path62.join(localDir, "cargo-target");
31306
31467
  return targetDir;
31307
31468
  };
31308
31469
  function cargoShim(env, rust) {
31309
- const real = path61.join(tool("rust", "cargo", "bin"), "cargo.exe");
31470
+ const real = path62.join(tool("rust", "cargo", "bin"), "cargo.exe");
31310
31471
  if (rust.targetDir !== "separate" || !exists(real)) return;
31311
31472
  const dir = mkdirp(tool("shims", "cargo"));
31312
- fs47.copyFileSync(ensureCompiled("cargoshim"), path61.join(dir, "cargo.exe"));
31473
+ fs48.copyFileSync(ensureCompiled("cargoshim"), path62.join(dir, "cargo.exe"));
31313
31474
  env.prepend.unshift(dir);
31314
31475
  env.vars.AGENT_REAL_CARGO = real;
31315
31476
  }
31316
31477
  function linkGate(env, rust, host) {
31317
31478
  const gcc = tool("mingw", "mingw64", "bin", "gcc.exe");
31318
31479
  if (!host.endsWith("-pc-windows-gnu") || !exists(gcc)) return;
31319
- const gate = path61.join(mkdirp(tool("shims")), "linkgate.exe");
31320
- fs47.copyFileSync(ensureCompiled("linkgate"), gate);
31480
+ const gate = path62.join(mkdirp(tool("shims")), "linkgate.exe");
31481
+ fs48.copyFileSync(ensureCompiled("linkgate"), gate);
31321
31482
  const memoryGb = os8.totalmem() / 1024 ** 3;
31322
- const slots = rust.linkSlots === "auto" ? Math.max(2, Math.min(4, Math.floor(memoryGb / 8))) : rust.linkSlots;
31483
+ const slots = rust.linkSlots === "auto" ? linkSlotsFor(memoryGb) : rust.linkSlots;
31323
31484
  env.vars.AGENT_LINK_SLOTS = String(slots);
31324
31485
  env.vars.AGENT_REAL_LINKER = gcc;
31325
31486
  env.vars.CARGO_TARGET_X86_64_PC_WINDOWS_GNU_LINKER = gate;
31326
31487
  const rustEnv = { ...process.env, RUSTUP_HOME: tool("rust", "rustup"), CARGO_HOME: tool("rust", "cargo") };
31327
31488
  const sysroot = rust.linker === "lld" ? execOutput(tool("rust", "cargo", "bin", "rustc.exe"), ["--print", "sysroot"], { env: rustEnv }) : "";
31328
- const lld = sysroot ? path61.join(sysroot, "lib", "rustlib", host, "bin", "gcc-ld") : "";
31329
- if (lld && exists(path61.join(lld, "ld.lld.exe"))) env.vars.AGENT_LLD_DIR = lld;
31489
+ const lld = sysroot ? path62.join(sysroot, "lib", "rustlib", host, "bin", "gcc-ld") : "";
31490
+ if (lld && exists(path62.join(lld, "ld.lld.exe"))) env.vars.AGENT_LLD_DIR = lld;
31330
31491
  env.summary.push(
31331
31492
  "rust linking: " + (env.vars.AGENT_LLD_DIR ? "lld" : "GNU ld") + ", at most " + env.vars.AGENT_LINK_SLOTS + " at once"
31332
31493
  );
31333
31494
  }
31334
31495
  function cargoDefaults(host) {
31335
31496
  const file3 = tool("rust", "cargo", "config.toml");
31336
- if (exists(file3) || !exists(path61.dirname(file3))) return;
31497
+ if (exists(file3) || !exists(path62.dirname(file3))) return;
31337
31498
  const jobs = cargoJobs(os8.cpus().length, os8.totalmem() / 1024 ** 3, 1);
31338
31499
  const gnu = host.endsWith("-gnu");
31339
- fs47.writeFileSync(
31500
+ fs48.writeFileSync(
31340
31501
  file3,
31341
31502
  [
31342
31503
  "# Written by windows-development-sandbox once; edit freely, it is never overwritten.",
@@ -31351,7 +31512,7 @@ function rustCaches(rust) {
31351
31512
  const target = cargoTarget(rust.targetDir);
31352
31513
  return {
31353
31514
  ...target ? { CARGO_TARGET_DIR: target } : {},
31354
- ...process.env.SCCACHE_DIR ? {} : { SCCACHE_DIR: path61.join(dataDir, "cache", "sccache") }
31515
+ ...process.env.SCCACHE_DIR ? {} : { SCCACHE_DIR: path62.join(dataDir, "cache", "sccache") }
31355
31516
  };
31356
31517
  }
31357
31518
  function rustHost(config2) {
@@ -31655,21 +31816,21 @@ function cmdSet(env, names) {
31655
31816
  return names.filter((n) => env[n] !== void 0 && !/[\r\n]/.test(String(env[n]))).map((n) => '@set "' + n + "=" + String(env[n]).replace(/%/g, "%%") + '"');
31656
31817
  }
31657
31818
  function writeShell(spec, env, names) {
31658
- const dir = mkdirp(path62.join(localDir, "projects", spec.name));
31659
- fs48.writeFileSync(path62.join(dir, "env.cmd"), [...cmdSet(env, [...names, "PATH"]), ""].join("\r\n"));
31660
- fs48.writeFileSync(
31661
- path62.join(dir, "shell.cmd"),
31662
- ['@call "' + path62.join(dir, "env.cmd") + '"', '@cd /d "' + spec.workspace + '"', "@title " + spec.name, ""].join(
31819
+ const dir = mkdirp(path63.join(localDir, "projects", spec.name));
31820
+ fs49.writeFileSync(path63.join(dir, "env.cmd"), [...cmdSet(env, [...names, "PATH"]), ""].join("\r\n"));
31821
+ fs49.writeFileSync(
31822
+ path63.join(dir, "shell.cmd"),
31823
+ ['@call "' + path63.join(dir, "env.cmd") + '"', '@cd /d "' + spec.workspace + '"', "@title " + spec.name, ""].join(
31663
31824
  "\r\n"
31664
31825
  )
31665
31826
  );
31666
- const bin = mkdirp(path62.join(localDir, "bin"));
31667
- fs48.writeFileSync(
31668
- path62.join(bin, "sbx-shell.cmd"),
31827
+ const bin = mkdirp(path63.join(localDir, "bin"));
31828
+ fs49.writeFileSync(
31829
+ path63.join(bin, "sbx-shell.cmd"),
31669
31830
  [
31670
- '@if "%~1"=="" (echo Usage: sbx-shell ^<project^> ^(a terminal in that project with its tools^) & dir /b "' + path62.join(localDir, "projects") + '" & exit /b 2)',
31671
- '@if not exist "' + path62.join(localDir, "projects") + '\\%~1\\shell.cmd" (echo No project %~1 in this sandbox. & exit /b 2)',
31672
- '@cmd /k ""' + path62.join(localDir, "projects") + '\\%~1\\shell.cmd""',
31831
+ '@if "%~1"=="" (echo Usage: sbx-shell ^<project^> ^(a terminal in that project with its tools^) & dir /b "' + path63.join(localDir, "projects") + '" & exit /b 2)',
31832
+ '@if not exist "' + path63.join(localDir, "projects") + '\\%~1\\shell.cmd" (echo No project %~1 in this sandbox. & exit /b 2)',
31833
+ '@cmd /k ""' + path63.join(localDir, "projects") + '\\%~1\\shell.cmd""',
31673
31834
  ""
31674
31835
  ].join("\r\n")
31675
31836
  );
@@ -31722,10 +31883,10 @@ async function setUp(spec, say) {
31722
31883
  }
31723
31884
  )
31724
31885
  );
31725
- tools.prepend.push(path62.join(localDir, "bin"));
31886
+ tools.prepend.push(path63.join(localDir, "bin"));
31726
31887
  const env = agentEnv(tools, { workspace: spec.workspace, project: spec.name, base });
31727
- const specFile = path62.join(mkdirp(path62.join(localDir, "projects", spec.name)), "project.json");
31728
- fs48.writeFileSync(specFile, JSON.stringify(spec));
31888
+ const specFile = path63.join(mkdirp(path63.join(localDir, "projects", spec.name)), "project.json");
31889
+ fs49.writeFileSync(specFile, JSON.stringify(spec));
31729
31890
  env.AGENT_PROJECT_FILE = specFile;
31730
31891
  addMachineEnvironment(tools.vars, [...tools.prepend, ...tools.append], true);
31731
31892
  try {
@@ -31842,7 +32003,7 @@ function execCommand(req) {
31842
32003
  }
31843
32004
 
31844
32005
  // src/guest/daemon/sessions.ts
31845
- import path67 from "node:path";
32006
+ import path68 from "node:path";
31846
32007
  import crypto4 from "node:crypto";
31847
32008
  import os11 from "node:os";
31848
32009
  import { spawn as spawn7 } from "node:child_process";
@@ -31919,7 +32080,7 @@ async function sendControl(endpoint, type) {
31919
32080
  var MAX_CLIPBOARD_STRING = 1024 * 1024;
31920
32081
 
31921
32082
  // src/guest/sessions/cmdline.ts
31922
- import path63 from "node:path";
32083
+ import path64 from "node:path";
31923
32084
  var quoted = (arg) => '"' + arg.replace(/(\\*)"/g, '$1$1\\"').replace(/(\\+)$/, "$1$1") + '"';
31924
32085
  function quoteArg(arg) {
31925
32086
  return arg !== "" && !/[\s"]/.test(arg) ? arg : quoted(arg);
@@ -31933,12 +32094,12 @@ function cmdArgs(args) {
31933
32094
  }).join("");
31934
32095
  }
31935
32096
  function commandLine(file3, args) {
31936
- return path63.win32.basename(file3).toLowerCase() === "cmd.exe" ? [quoteArg(file3), cmdArgs(args)].filter(Boolean).join(" ") : [file3, ...args].map(quoteArg).join(" ");
32097
+ return path64.win32.basename(file3).toLowerCase() === "cmd.exe" ? [quoteArg(file3), cmdArgs(args)].filter(Boolean).join(" ") : [file3, ...args].map(quoteArg).join(" ");
31937
32098
  }
31938
32099
 
31939
32100
  // src/guest/sessions/pty-host.ts
31940
- import fs49 from "node:fs";
31941
- import path64 from "node:path";
32101
+ import fs50 from "node:fs";
32102
+ import path65 from "node:path";
31942
32103
  import { spawn as spawn6 } from "node:child_process";
31943
32104
  function ensurePtyHost() {
31944
32105
  return ensureCompiled("ptyhost");
@@ -31957,18 +32118,18 @@ async function waitForPtyHost(child, port, timeoutMs) {
31957
32118
  throw new Error("the session host did not start listening on port " + port);
31958
32119
  }
31959
32120
  function ptyHostLog(id) {
31960
- return path64.join(logsDir, "ptyhost-" + id + ".log");
32121
+ return path65.join(logsDir, "ptyhost-" + id + ".log");
31961
32122
  }
31962
32123
  function ptyHostLogTail(id, lines = 12) {
31963
32124
  try {
31964
- return fs49.readFileSync(ptyHostLog(id), "utf8").trim().split(/\r?\n/).slice(-lines).join("\n");
32125
+ return fs50.readFileSync(ptyHostLog(id), "utf8").trim().split(/\r?\n/).slice(-lines).join("\n");
31965
32126
  } catch {
31966
32127
  return "";
31967
32128
  }
31968
32129
  }
31969
32130
  var conptyDll = () => {
31970
- const dll = path64.join(toolsDir, "conpty", "conpty.dll");
31971
- return session.provisioning.conpty?.enabled !== false && fs49.existsSync(dll) && fs49.existsSync(path64.join(toolsDir, "conpty", "OpenConsole.exe")) ? dll : null;
32131
+ const dll = path65.join(toolsDir, "conpty", "conpty.dll");
32132
+ return session.provisioning.conpty?.enabled !== false && fs50.existsSync(dll) && fs50.existsSync(path65.join(toolsDir, "conpty", "OpenConsole.exe")) ? dll : null;
31972
32133
  };
31973
32134
  function startPtyHost(o) {
31974
32135
  const env = { ...o.env, PTYHOST_BIND: o.remote ? "any" : "loopback" };
@@ -31983,8 +32144,8 @@ function startPtyHost(o) {
31983
32144
  }
31984
32145
 
31985
32146
  // src/guest/agents/agent-installer.ts
31986
- import fs50 from "node:fs";
31987
- import path65 from "node:path";
32147
+ import fs51 from "node:fs";
32148
+ import path66 from "node:path";
31988
32149
 
31989
32150
  // src/guest/agents/profile-links.ts
31990
32151
  var profileRoot = () => process.env.USERPROFILE ?? "";
@@ -32010,7 +32171,7 @@ var agentPaths2 = (name, harness) => agentPaths(toolsDir, name, harness);
32010
32171
  async function installViaNpm(name, harness, dir, env) {
32011
32172
  if (!harness.npmPackage)
32012
32173
  throw new Error("No npmPackage configured for " + name + " and no host executable was available.");
32013
- const npmCli = path65.join(path65.dirname(process.execPath), "node_modules", "npm", "bin", "npm-cli.js");
32174
+ const npmCli = path66.join(path66.dirname(process.execPath), "node_modules", "npm", "bin", "npm-cli.js");
32014
32175
  const args = [npmCli, "install", "--global", "--prefix", dir, harness.npmPackage, "--no-fund", "--no-audit"];
32015
32176
  log("Installing " + harness.npmPackage + " (this can take a minute)...");
32016
32177
  if (dryRun) {
@@ -32021,7 +32182,7 @@ async function installViaNpm(name, harness, dir, env) {
32021
32182
  await execAsync(process.execPath, args, { env });
32022
32183
  }
32023
32184
  async function installViaUv(name, harness, dir, env) {
32024
- const uv = path65.join(toolsDir, "uv", "uv.exe");
32185
+ const uv = path66.join(toolsDir, "uv", "uv.exe");
32025
32186
  log("Installing " + harness.uvPackage + " with uv (this can take a minute)...");
32026
32187
  if (dryRun) {
32027
32188
  log("(dry run) uv tool install " + harness.uvPackage);
@@ -32036,8 +32197,8 @@ async function installViaUv(name, harness, dir, env) {
32036
32197
  });
32037
32198
  }
32038
32199
  function putOnPath(dir, env) {
32039
- const parts2 = (env.PATH ?? "").split(path65.delimiter);
32040
- if (!parts2.some((p) => p.toLowerCase() === dir.toLowerCase())) env.PATH = [...parts2, dir].join(path65.delimiter);
32200
+ const parts2 = (env.PATH ?? "").split(path66.delimiter);
32201
+ if (!parts2.some((p) => p.toLowerCase() === dir.toLowerCase())) env.PATH = [...parts2, dir].join(path66.delimiter);
32041
32202
  addMachineEnvironment({}, [dir], true);
32042
32203
  }
32043
32204
  var AgentInstaller = class {
@@ -32078,9 +32239,9 @@ var AgentInstaller = class {
32078
32239
  }
32079
32240
  mkdirp(p.dir);
32080
32241
  if (this.sourceOf(name, harness) === "host") {
32081
- const source = path65.join(hostToolsDir, "agents", name, harness.hostExecutable);
32242
+ const source = path66.join(hostToolsDir, "agents", name, harness.hostExecutable);
32082
32243
  if (exists(source) && p.exe) {
32083
- fs50.copyFileSync(source, p.exe);
32244
+ fs51.copyFileSync(source, p.exe);
32084
32245
  log("Copied " + name + " from this PC: " + source);
32085
32246
  return;
32086
32247
  }
@@ -32101,22 +32262,22 @@ function guestAddresses() {
32101
32262
  }
32102
32263
 
32103
32264
  // src/guest/sessions/conversation.ts
32104
- import fs51 from "node:fs";
32105
- import path66 from "node:path";
32265
+ import fs52 from "node:fs";
32266
+ import path67 from "node:path";
32106
32267
  var MAX_FILES = 2e3;
32107
32268
  function conversationFiles(claudeDir2, cwd) {
32108
32269
  const names = /* @__PURE__ */ new Set([projectFolderName(cwd), projectFolderName(sandboxFolder(cwd))]);
32109
32270
  return [...names].flatMap((name) => {
32110
- const dir = path66.join(claudeDir2, "projects", name);
32271
+ const dir = path67.join(claudeDir2, "projects", name);
32111
32272
  let entries2;
32112
32273
  try {
32113
- entries2 = fs51.readdirSync(dir);
32274
+ entries2 = fs52.readdirSync(dir);
32114
32275
  } catch {
32115
32276
  return [];
32116
32277
  }
32117
32278
  return entries2.filter((e) => e.endsWith(".jsonl") && isConversationId(e.slice(0, -".jsonl".length))).slice(0, MAX_FILES).flatMap((e) => {
32118
32279
  try {
32119
- return [{ id: e.slice(0, -".jsonl".length), createdMs: fs51.statSync(path66.join(dir, e)).birthtimeMs }];
32280
+ return [{ id: e.slice(0, -".jsonl".length), createdMs: fs52.statSync(path67.join(dir, e)).birthtimeMs }];
32120
32281
  } catch {
32121
32282
  return [];
32122
32283
  }
@@ -32155,8 +32316,8 @@ var IdleShutdown = class {
32155
32316
 
32156
32317
  // src/guest/daemon/sessions.ts
32157
32318
  function terminalTab(id, title, cwd) {
32158
- const view = [process.execPath, path67.join(path67.dirname(process.argv[1]), "view.js"), id];
32159
- const wt = path67.join(toolsDir, "terminal", "wt.exe");
32319
+ const view = [process.execPath, path68.join(path68.dirname(process.argv[1]), "view.js"), id];
32320
+ const wt = path68.join(toolsDir, "terminal", "wt.exe");
32160
32321
  if (exists(wt))
32161
32322
  spawn7(wt, ["-w", "0", "nt", "--title", title, "-d", cwd, ...view], { detached: true, stdio: "ignore" }).unref();
32162
32323
  else spawn7(SYSTEM.cmd(), ["/d", "/c", "start", title, ...view], { detached: true, stdio: "ignore", cwd }).unref();
@@ -32171,11 +32332,33 @@ var harnessFor = (req) => {
32171
32332
  };
32172
32333
  function memoryEnv(env, sessions2) {
32173
32334
  const out = {};
32174
- if (session.agentMemoryLimitMb) out.PTYHOST_JOB_MB = String(session.agentMemoryLimitMb);
32175
- if (!env.CARGO_BUILD_JOBS)
32176
- out.CARGO_BUILD_JOBS = String(cargoJobs(os11.cpus().length, os11.totalmem() / 1024 ** 3, sessions2));
32335
+ out.PTYHOST_BACKSTOP_MB = String(session.agentBackstop ?? "auto");
32336
+ const cpus = usableCpus(os11.cpus().length, session.cpuLimitPercent ?? null);
32337
+ const memoryGb = os11.totalmem() / 1024 ** 3;
32338
+ const jobs = cargoJobs(cpus, memoryGb, sessions2);
32339
+ out.NUMBER_OF_PROCESSORS = String(cpus);
32340
+ if (!env.CARGO_BUILD_JOBS) out.CARGO_BUILD_JOBS = String(jobs);
32341
+ if (!env.CMAKE_BUILD_PARALLEL_LEVEL) out.CMAKE_BUILD_PARALLEL_LEVEL = String(jobs);
32342
+ out.SANDBOX_BUDGET_FILE = run.budgetFile;
32343
+ writeBudget(cpus, memoryGb, jobs, env);
32177
32344
  return out;
32178
32345
  }
32346
+ function writeBudget(cpus, memoryGb, jobs, env) {
32347
+ try {
32348
+ writeJsonAtomic(run.budgetFile, {
32349
+ processors: cpus,
32350
+ memoryMb: Math.round(memoryGb * 1024),
32351
+ buildJobs: buildJobs(cpus, memoryGb),
32352
+ cargoJobsPerSession: jobs,
32353
+ linkSlots: Number(env.AGENT_LINK_SLOTS) || linkSlotsFor(memoryGb),
32354
+ cpuLimitPercent: session.cpuLimitPercent ?? null,
32355
+ governor: run.pressureFile,
32356
+ note: "Plan builds with these numbers. When memory runs short the sandbox slows builds down in steps (governor); nothing fails."
32357
+ });
32358
+ } catch (e) {
32359
+ warn("budget.json could not be written: " + errMsg(e));
32360
+ }
32361
+ }
32179
32362
  var launchPtyHost = async (req, remote, env, say, sessions2) => {
32180
32363
  const harness = harnessFor(req);
32181
32364
  say("Preparing " + req.harness);
@@ -32202,7 +32385,7 @@ var launchPtyHost = async (req, remote, env, say, sessions2) => {
32202
32385
  } catch (e) {
32203
32386
  const tail = ptyHostLogTail(req.id);
32204
32387
  throw new Error(
32205
- errMsg(e) + (tail ? ". From its log:\n" + tail : "") + "\nLog: " + path67.join(dataDir, "logs", "ptyhost-" + req.id + ".log")
32388
+ errMsg(e) + (tail ? ". From its log:\n" + tail : "") + "\nLog: " + path68.join(dataDir, "logs", "ptyhost-" + req.id + ".log")
32206
32389
  );
32207
32390
  }
32208
32391
  return { child, port, token };
@@ -32260,7 +32443,7 @@ var SessionManager = class {
32260
32443
  };
32261
32444
  this.starting++;
32262
32445
  if (req.id !== session.launchId && process.env.AGENT_NO_TABS !== "1")
32263
- safely("terminal tab", () => terminalTab(req.id, req.harness + " " + path67.basename(req.cwd), req.cwd));
32446
+ safely("terminal tab", () => terminalTab(req.id, req.harness + " " + path68.basename(req.cwd), req.cwd));
32264
32447
  try {
32265
32448
  const place = await placeFor(req, say);
32266
32449
  const remote = session.networking && session.attach.enabled;
@@ -32400,7 +32583,6 @@ var COMPILERS = /* @__PURE__ */ new Set([
32400
32583
  "javac"
32401
32584
  ]);
32402
32585
  var BUILD_TOOLS = /* @__PURE__ */ new Set([
32403
- "node",
32404
32586
  "dotnet",
32405
32587
  "msbuild",
32406
32588
  "vbcscompiler",
@@ -32450,82 +32632,142 @@ var NEVER2 = /* @__PURE__ */ new Set([
32450
32632
  var key = (name) => name.toLowerCase().replace(/\.exe$/, "");
32451
32633
  var isNeverTouched = (name) => NEVER2.has(key(name));
32452
32634
  var canLower = (name) => !isNeverTouched(name) && (COMPILERS.has(key(name)) || BUILD_TOOLS.has(key(name)));
32635
+ var HEAVY = /* @__PURE__ */ new Set([
32636
+ "rustc",
32637
+ "clippy-driver",
32638
+ "rustdoc",
32639
+ "cc1",
32640
+ "cc1plus",
32641
+ "clang",
32642
+ "clang++",
32643
+ "clang-cl",
32644
+ "cl",
32645
+ "link",
32646
+ "lld",
32647
+ "lld-link",
32648
+ "ld",
32649
+ "ld.lld"
32650
+ ]);
32651
+ var isHeavyCompiler = (name) => !isNeverTouched(name) && HEAVY.has(key(name));
32453
32652
  var canPause = (name) => !isNeverTouched(name) && COMPILERS.has(key(name));
32454
32653
  var INITIAL_STATE = {
32455
- pressure: false,
32654
+ step: 0,
32456
32655
  calm: 0,
32457
- samples: 0,
32458
32656
  lowered: {},
32459
- pausedUntil: 0,
32460
- nextPauseAt: 0,
32461
- hostUntil: 0
32657
+ memLow: [],
32658
+ throttled: [],
32659
+ trimmed: [],
32660
+ cpuRate: 100,
32661
+ lastCommitMb: 0,
32662
+ lastAt: 0,
32663
+ growth: 0,
32664
+ hostUntil: 0,
32665
+ hostStep: 0
32462
32666
  };
32463
- var PAUSE_MS = 5e3;
32464
- var PAUSE_COOLDOWN_MS = 1e4;
32465
- var IDLE_AFTER = 3;
32466
- var PAUSE_AFTER = 4;
32467
- var PAUSE_MIN_MB = 300;
32468
- function decide(prev, sample, nowMs, thresholds, profile) {
32667
+ var GROWTH_WEIGHT = 0.3;
32668
+ var HOLD_MS = 3e3;
32669
+ var ROTATE_MS = 2e4;
32670
+ var SOON_WITHIN_PERCENT = 12;
32671
+ function stepFor(ramFree, commit, secondsToLimit, profile) {
32672
+ let step = 0;
32673
+ DIAL_STEPS[profile].forEach((t, i) => {
32674
+ const near = commit > t.commitPercent - SOON_WITHIN_PERCENT;
32675
+ const soon = near && t.secondsToLimit !== void 0 && secondsToLimit < t.secondsToLimit;
32676
+ if (ramFree < t.availablePercent || commit > t.commitPercent || soon) step = i + 1;
32677
+ });
32678
+ return step;
32679
+ }
32680
+ function clearOf(step, ramFree, commit, profile) {
32681
+ if (step === 0) return true;
32682
+ const t = DIAL_STEPS[profile][step - 1];
32683
+ return ramFree > t.availablePercent + DIAL_EXIT_MARGIN.availablePercent && commit < t.commitPercent - DIAL_EXIT_MARGIN.commitPercent;
32684
+ }
32685
+ function decide(prev, sample, nowMs, profile, maxCompilers2 = null) {
32469
32686
  const ramFree = sample.ramAvailMb / Math.max(1, sample.ramTotalMb) * 100;
32470
- const commit = (sample.commitLimitMb - sample.commitAvailMb) / Math.max(1, sample.commitLimitMb) * 100;
32687
+ const usedMb = sample.commitLimitMb - sample.commitAvailMb;
32688
+ const commit = usedMb / Math.max(1, sample.commitLimitMb) * 100;
32689
+ const seconds = (nowMs - prev.lastAt) / 1e3;
32690
+ const instant = prev.lastAt > 0 && seconds > 0 ? (usedMb - prev.lastCommitMb) / seconds : 0;
32691
+ const growth = prev.lastAt > 0 ? prev.growth * (1 - GROWTH_WEIGHT) + instant * GROWTH_WEIGHT : 0;
32692
+ const secondsToLimit = growth > 0 ? sample.commitAvailMb / growth : Number.POSITIVE_INFINITY;
32471
32693
  const pcLow = nowMs < prev.hostUntil;
32472
- const low = ramFree < thresholds.enterAvailablePercent || commit > thresholds.enterCommitPercent || pcLow;
32473
- const recovered = ramFree > thresholds.exitAvailablePercent && commit < thresholds.exitCommitPercent && !pcLow;
32474
- let pressure = prev.pressure;
32475
- let calm = prev.calm;
32476
- let samples = prev.samples;
32477
- if (low) {
32478
- pressure = true;
32479
- calm = 0;
32480
- samples = prev.samples + 1;
32481
- } else if (prev.pressure) {
32482
- calm = recovered ? prev.calm + 1 : 0;
32483
- if (calm >= thresholds.calmSamples) {
32484
- pressure = false;
32694
+ const wanted2 = Math.max(stepFor(ramFree, commit, secondsToLimit, profile), pcLow ? prev.hostStep : 0);
32695
+ let step = prev.step;
32696
+ let calm = 0;
32697
+ if (wanted2 > prev.step) step = wanted2;
32698
+ else if (prev.step > 0 && wanted2 < prev.step && clearOf(prev.step, ramFree, commit, profile)) {
32699
+ calm = prev.calm + 1;
32700
+ if (calm >= DIAL_CALM_SAMPLES) {
32701
+ step = prev.step - 1;
32485
32702
  calm = 0;
32486
- samples = 0;
32487
32703
  }
32488
32704
  }
32489
32705
  const actions = [];
32490
32706
  const present2 = new Set(sample.procs.map((p) => p.pid));
32707
+ const keep = (pids) => pids.filter((pid) => present2.has(pid));
32491
32708
  const lowered = {};
32492
32709
  for (const [pid, to] of Object.entries(prev.lowered)) if (present2.has(Number(pid))) lowered[Number(pid)] = to;
32493
- if (pressure) {
32494
- const target = samples > IDLE_AFTER ? "idle" : "below";
32495
- for (const p of sample.procs) {
32496
- if (!canLower(p.name) || lowered[p.pid] === target) continue;
32497
- if (p.prio !== target && !(target === "below" && p.prio === "idle"))
32498
- actions.push({ kind: "priority", pid: p.pid, name: p.name, to: target });
32499
- lowered[p.pid] = target;
32500
- }
32501
- } else {
32502
- for (const p of sample.procs) {
32503
- if (!canLower(p.name)) continue;
32504
- const base = profile === "gentle" && canPause(p.name) ? "below" : "normal";
32505
- const was = lowered[p.pid];
32506
- if (prev.pressure && was !== void 0 && was !== base) {
32507
- if (p.prio !== base) actions.push({ kind: "priority", pid: p.pid, name: p.name, to: base });
32508
- if (base === "normal") delete lowered[p.pid];
32509
- else lowered[p.pid] = base;
32510
- } else if (!prev.pressure && base === "below" && was === void 0) {
32511
- if (p.prio === "normal") actions.push({ kind: "priority", pid: p.pid, name: p.name, to: "below" });
32512
- lowered[p.pid] = "below";
32513
- }
32514
- }
32515
- }
32516
- let pausedUntil = prev.pausedUntil;
32517
- let nextPauseAt = prev.nextPauseAt;
32518
- if (pressure && samples >= PAUSE_AFTER && nowMs >= prev.nextPauseAt && nowMs >= prev.pausedUntil) {
32519
- const victim = [...sample.procs].filter((p) => canPause(p.name) && p.mb >= PAUSE_MIN_MB).sort((a, b) => b.mb - a.mb)[0];
32520
- if (victim) {
32521
- actions.push({ kind: "pause", pid: victim.pid, name: victim.name, ms: PAUSE_MS });
32522
- pausedUntil = nowMs + PAUSE_MS;
32523
- nextPauseAt = pausedUntil + PAUSE_COOLDOWN_MS;
32524
- }
32525
- }
32526
- const level = nowMs < pausedUntil ? "suspending" : pressure ? "throttled" : "ok";
32710
+ const memLow = new Set(keep(prev.memLow));
32711
+ const throttled = new Set(keep(prev.throttled));
32712
+ const trimmed = new Set(keep(prev.trimmed));
32713
+ for (const p of sample.procs) {
32714
+ if (!canLower(p.name)) continue;
32715
+ const rest = profile === "gentle" && canPause(p.name) ? "below" : "normal";
32716
+ const target = step >= 2 ? "idle" : step === 1 ? "below" : rest;
32717
+ const was = lowered[p.pid];
32718
+ const touched = was !== void 0 || target !== "normal";
32719
+ if (touched && was !== target && p.prio !== target)
32720
+ actions.push({ kind: "priority", pid: p.pid, name: p.name, to: target });
32721
+ if (target === "normal") delete lowered[p.pid];
32722
+ else lowered[p.pid] = target;
32723
+ }
32724
+ const lowMemory = step >= 1;
32725
+ for (const p of sample.procs) {
32726
+ if (!canLower(p.name) || lowMemory === memLow.has(p.pid)) continue;
32727
+ actions.push({ kind: "memory", pid: p.pid, name: p.name, low: lowMemory });
32728
+ if (lowMemory) memLow.add(p.pid);
32729
+ else memLow.delete(p.pid);
32730
+ }
32731
+ if (step >= 2) {
32732
+ for (const p of sample.procs)
32733
+ if (canPause(p.name) && !throttled.has(p.pid)) {
32734
+ actions.push({ kind: "throttle", pid: p.pid, name: p.name });
32735
+ throttled.add(p.pid);
32736
+ }
32737
+ }
32738
+ const cpuRate = DIAL_CPU_RATE[step] ?? 100;
32739
+ if (cpuRate !== prev.cpuRate) actions.push({ kind: "cpu", percent: cpuRate });
32740
+ const heavy = sample.procs.filter((p) => isHeavyCompiler(p.name)).sort((a, b) => a.pid - b.pid);
32741
+ let allowed = compilersAllowed(step, heavy.length);
32742
+ if (maxCompilers2 !== null && step >= 2) allowed = Math.min(allowed, Math.max(1, maxCompilers2));
32743
+ if (allowed < heavy.length) {
32744
+ const turn = Math.floor(nowMs / ROTATE_MS) % heavy.length;
32745
+ const order = [...heavy.slice(turn), ...heavy.slice(0, turn)];
32746
+ for (const p of order.slice(allowed)) {
32747
+ actions.push({ kind: "hold", pid: p.pid, name: p.name, ms: HOLD_MS });
32748
+ if (step >= 3 && !trimmed.has(p.pid)) {
32749
+ actions.push({ kind: "trim", pid: p.pid, name: p.name });
32750
+ trimmed.add(p.pid);
32751
+ }
32752
+ }
32753
+ for (const p of order.slice(0, allowed)) trimmed.delete(p.pid);
32754
+ } else trimmed.clear();
32755
+ const level = step >= 3 ? "suspending" : step >= 1 ? "throttled" : "ok";
32527
32756
  return {
32528
- state: { pressure, calm, samples, lowered, pausedUntil, nextPauseAt, hostUntil: prev.hostUntil },
32757
+ state: {
32758
+ step,
32759
+ calm,
32760
+ lowered,
32761
+ memLow: [...memLow],
32762
+ throttled: [...throttled],
32763
+ trimmed: [...trimmed],
32764
+ cpuRate,
32765
+ lastCommitMb: usedMb,
32766
+ lastAt: nowMs,
32767
+ growth,
32768
+ hostUntil: prev.hostUntil,
32769
+ hostStep: prev.hostStep
32770
+ },
32529
32771
  actions,
32530
32772
  level,
32531
32773
  ramFreePercent: Math.round(ramFree),
@@ -32533,25 +32775,14 @@ function decide(prev, sample, nowMs, thresholds, profile) {
32533
32775
  };
32534
32776
  }
32535
32777
 
32536
- // src/guest/governor/governor.ts
32537
- import fs52 from "node:fs";
32538
- import path68 from "node:path";
32539
- import { spawn as spawn8 } from "node:child_process";
32540
- import { createInterface } from "node:readline";
32541
- var SampleSchema = external_exports.object({
32542
- ramTotalMb: external_exports.number(),
32543
- ramAvailMb: external_exports.number(),
32544
- commitLimitMb: external_exports.number(),
32545
- commitAvailMb: external_exports.number(),
32546
- procs: external_exports.array(
32547
- external_exports.object({
32548
- pid: external_exports.number().int(),
32549
- name: external_exports.string().max(128),
32550
- mb: external_exports.number(),
32551
- prio: external_exports.enum(["idle", "below", "normal"]).catch("normal")
32552
- })
32553
- ).max(1024)
32554
- });
32778
+ // src/guest/governor/core.ts
32779
+ var STEP_TEXT = [
32780
+ "builds back to normal",
32781
+ "build programs at lower priority",
32782
+ "builds get less CPU and take turns",
32783
+ "builds take turns, waiting ones go to the paging file",
32784
+ "one compiler at a time"
32785
+ ];
32555
32786
  var GovernorCore = class {
32556
32787
  constructor(deps) {
32557
32788
  this.deps = deps;
@@ -32561,42 +32792,51 @@ var GovernorCore = class {
32561
32792
  lastAction = "";
32562
32793
  lastWrite = "";
32563
32794
  lastWriteAt = 0;
32564
- pausedName = "";
32565
- pausedPid = 0;
32566
- hostPressure(seconds, reason) {
32567
- const until = this.deps.now() + seconds * 1e3;
32568
- if (until > this.state.hostUntil) {
32569
- if (this.state.hostUntil <= this.deps.now())
32570
- this.deps.logLine("governor: this PC is low (" + reason + "); slowing builds down");
32571
- this.state = { ...this.state, hostUntil: until };
32572
- }
32795
+ /** Compilers waiting their turn now, by pid (name), to log a hold once. */
32796
+ held = /* @__PURE__ */ new Map();
32797
+ hostPressure(seconds, reason, level = "slow") {
32798
+ const nowMs = this.deps.now();
32799
+ const until = nowMs + seconds * 1e3;
32800
+ const active = this.state.hostUntil > nowMs;
32801
+ const step = Math.max(level === "severe" ? 4 : 2, active ? this.state.hostStep : 0);
32802
+ if (!active || step > this.state.hostStep)
32803
+ this.deps.logLine(
32804
+ "governor: this PC is " + (level === "severe" ? "nearly out of memory" : "low") + " (" + reason + "); builds to step " + step
32805
+ );
32806
+ this.state = { ...this.state, hostUntil: Math.max(until, this.state.hostUntil), hostStep: step };
32573
32807
  }
32574
32808
  get current() {
32575
32809
  return this.state;
32576
32810
  }
32577
32811
  onSample(sample) {
32578
32812
  const nowMs = this.deps.now();
32579
- const before = this.state.pressure;
32580
- const d = decide(this.state, sample, nowMs, GUEST_THRESHOLDS[this.deps.profile], this.deps.profile);
32813
+ const before = this.state.step;
32814
+ const d = decide(this.state, sample, nowMs, this.deps.profile, this.deps.maxCompilers ?? null);
32581
32815
  this.state = d.state;
32582
- for (const action of d.actions) this.apply(action);
32583
- if (d.state.pressure !== before)
32816
+ const holding = /* @__PURE__ */ new Set();
32817
+ for (const action of d.actions) {
32818
+ if (action.kind === "hold") holding.add(action.pid);
32819
+ this.apply(action);
32820
+ }
32821
+ for (const pid of [...this.held.keys()]) if (!holding.has(pid)) this.held.delete(pid);
32822
+ if (d.state.step !== before)
32584
32823
  this.deps.logLine(
32585
- d.state.pressure ? "governor: memory is low (" + d.ramFreePercent + "% RAM free, commit " + d.commitPercent + "% used): slowing builds down" : "governor: memory is fine again: builds back to normal"
32824
+ "governor: step " + d.state.step + " (" + d.ramFreePercent + "% RAM free, commit " + d.commitPercent + "% used): " + STEP_TEXT[d.state.step]
32586
32825
  );
32587
- const paused = nowMs < d.state.pausedUntil && this.pausedPid ? [{ name: this.pausedName, pid: this.pausedPid, seconds: Math.ceil((d.state.pausedUntil - nowMs) / 1e3) }] : [];
32588
32826
  const status = {
32589
32827
  level: d.level,
32828
+ step: d.state.step,
32590
32829
  profile: this.deps.profile,
32591
32830
  ramFreePercent: Math.max(0, Math.min(100, d.ramFreePercent)),
32592
32831
  commitPercent: Math.max(0, Math.min(100, d.commitPercent)),
32593
32832
  lowered: Object.keys(d.state.lowered).length,
32594
- paused,
32833
+ paused: [...this.held].slice(0, 8).map(([pid, name]) => ({ name: name.slice(0, 64), pid, seconds: HOLD_MS / 1e3 })),
32834
+ cpuPercent: d.state.cpuRate,
32595
32835
  pcLow: nowMs < d.state.hostUntil,
32596
- lastAction: this.lastAction,
32836
+ lastAction: this.lastAction.slice(0, 300),
32597
32837
  updatedAt: now()
32598
32838
  };
32599
- const shape = JSON.stringify({ ...status, updatedAt: "", paused: paused.map((p) => p.pid) });
32839
+ const shape = JSON.stringify({ ...status, updatedAt: "", paused: status.paused.map((p) => p.pid) });
32600
32840
  if (shape !== this.lastWrite || nowMs - this.lastWriteAt > 6e4) {
32601
32841
  this.lastWrite = shape;
32602
32842
  this.lastWriteAt = nowMs;
@@ -32604,24 +32844,64 @@ var GovernorCore = class {
32604
32844
  }
32605
32845
  }
32606
32846
  apply(action) {
32847
+ const port = this.deps.port;
32607
32848
  try {
32608
- if (action.kind === "priority") {
32609
- this.deps.port.setPriority(action.pid, action.to);
32610
- this.lastAction = action.name + " (" + action.pid + ") priority " + action.to;
32611
- } else {
32612
- this.deps.port.pause(action.pid, action.ms);
32613
- this.pausedName = action.name;
32614
- this.pausedPid = action.pid;
32615
- this.lastAction = "paused " + action.name + " (" + action.pid + ") for " + action.ms / 1e3 + " s";
32616
- this.deps.logLine("governor: " + this.lastAction);
32617
- return;
32849
+ switch (action.kind) {
32850
+ case "hold":
32851
+ port.hold(action.pid, action.ms);
32852
+ if (!this.held.has(action.pid)) {
32853
+ this.held.set(action.pid, action.name);
32854
+ this.note(action.name + " (" + action.pid + ") waits its turn");
32855
+ }
32856
+ return;
32857
+ case "priority":
32858
+ port.setPriority(action.pid, action.to);
32859
+ this.note(action.name + " (" + action.pid + ") priority " + action.to);
32860
+ return;
32861
+ case "memory":
32862
+ port.setMemoryPriority(action.pid, action.low);
32863
+ return;
32864
+ case "throttle":
32865
+ port.throttle(action.pid);
32866
+ return;
32867
+ case "cpu":
32868
+ port.setCpuRate(action.percent);
32869
+ this.note(action.percent >= 100 ? "compilers: no CPU cap" : "compilers: at most " + action.percent + "% CPU");
32870
+ return;
32871
+ case "trim":
32872
+ port.trim(action.pid);
32873
+ return;
32618
32874
  }
32619
- this.deps.logLine("governor: " + this.lastAction);
32620
32875
  } catch (e) {
32621
- warn("governor: " + errMsg(e));
32876
+ this.deps.warn("governor: " + errMsg(e));
32622
32877
  }
32623
32878
  }
32879
+ note(text) {
32880
+ this.lastAction = text;
32881
+ this.deps.logLine("governor: " + text);
32882
+ }
32624
32883
  };
32884
+
32885
+ // src/guest/governor/governor.ts
32886
+ import fs53 from "node:fs";
32887
+ import os12 from "node:os";
32888
+ import path69 from "node:path";
32889
+ import { spawn as spawn8 } from "node:child_process";
32890
+ import { createInterface } from "node:readline";
32891
+ var SampleSchema = external_exports.object({
32892
+ ramTotalMb: external_exports.number(),
32893
+ ramAvailMb: external_exports.number(),
32894
+ commitLimitMb: external_exports.number(),
32895
+ commitAvailMb: external_exports.number(),
32896
+ procs: external_exports.array(
32897
+ external_exports.object({
32898
+ pid: external_exports.number().int(),
32899
+ name: external_exports.string().max(128),
32900
+ mb: external_exports.number(),
32901
+ prio: external_exports.enum(["idle", "below", "normal"]).catch("normal")
32902
+ })
32903
+ ).max(1024)
32904
+ });
32625
32905
  var MemGovProcess = class {
32626
32906
  constructor(onSample) {
32627
32907
  this.onSample = onSample;
@@ -32652,20 +32932,35 @@ var MemGovProcess = class {
32652
32932
  }
32653
32933
  }
32654
32934
  setPriority(pid, to) {
32655
- this.child?.stdin?.write("priority " + pid + " " + to + "\n");
32935
+ this.send("priority " + pid + " " + to);
32936
+ }
32937
+ hold(pid, ms) {
32938
+ this.send("suspend " + pid + " " + ms);
32939
+ }
32940
+ setMemoryPriority(pid, low) {
32941
+ this.send("memprio " + pid + " " + (low ? "low" : "normal"));
32942
+ }
32943
+ throttle(pid) {
32944
+ this.send("throttle " + pid);
32945
+ }
32946
+ setCpuRate(percent) {
32947
+ this.send("cpurate " + Math.round(percent));
32948
+ }
32949
+ trim(pid) {
32950
+ this.send("trim " + pid);
32656
32951
  }
32657
- pause(pid, ms) {
32658
- this.child?.stdin?.write("suspend " + pid + " " + ms + "\n");
32952
+ send(line) {
32953
+ this.child?.stdin?.write(line + "\n");
32659
32954
  }
32660
32955
  };
32661
32956
  function appendToMemoryLog(line) {
32662
32957
  try {
32663
- const logs = path68.join(dataDir, "logs");
32664
- const newest = fs52.readdirSync(logs).filter((f) => /^memory-\d{8}-\d{6}\.log$/.test(f)).sort().pop();
32958
+ const logs = path69.join(dataDir, "logs");
32959
+ const newest = fs53.readdirSync(logs).filter((f) => /^memory-\d{8}-\d{6}\.log$/.test(f)).sort().pop();
32665
32960
  if (!newest) return;
32666
32961
  const t = /* @__PURE__ */ new Date();
32667
32962
  const stamp = [t.getHours(), t.getMinutes(), t.getSeconds()].map((n) => String(n).padStart(2, "0")).join(":");
32668
- fs52.appendFileSync(path68.join(logs, newest), stamp + " | " + line + "\r\n");
32963
+ fs53.appendFileSync(path69.join(logs, newest), stamp + " | " + line + "\r\n");
32669
32964
  } catch {
32670
32965
  }
32671
32966
  }
@@ -32673,8 +32968,8 @@ var Governor = class {
32673
32968
  core = null;
32674
32969
  describe() {
32675
32970
  const profile = session.loadProfile === "gentle" ? "gentle" : "normal";
32676
- const t = GUEST_THRESHOLDS[profile];
32677
- return session.pressureResponse === false ? "off (sandbox.pressureResponse)" : profile + " profile: slows builds down below " + t.enterAvailablePercent + "% free RAM or above " + t.enterCommitPercent + "% commit";
32971
+ const first = DIAL_STEPS[profile][0];
32972
+ return session.pressureResponse === false ? "off (sandbox.pressureResponse)" : profile + " profile: slows builds down from " + first.availablePercent + "% free RAM or " + first.commitPercent + "% commit, in steps";
32678
32973
  }
32679
32974
  start() {
32680
32975
  if (session.pressureResponse === false) return;
@@ -32683,8 +32978,10 @@ var Governor = class {
32683
32978
  this.core = new GovernorCore({
32684
32979
  port: proc,
32685
32980
  profile,
32981
+ maxCompilers: maxCompilers(os12.cpus().length, profile),
32686
32982
  now: () => Date.now(),
32687
32983
  logLine: appendToMemoryLog,
32984
+ warn,
32688
32985
  saveStatus: (status) => {
32689
32986
  try {
32690
32987
  writeJsonAtomic(run.pressureFile, status);
@@ -32695,9 +32992,9 @@ var Governor = class {
32695
32992
  });
32696
32993
  proc.start();
32697
32994
  }
32698
- /** The host's watchdog: this PC is low for a while. */
32699
- hostPressure(seconds, reason) {
32700
- this.core?.hostPressure(seconds, reason);
32995
+ /** The host's watchdog: this PC is low (or nearly out of memory) for a while. */
32996
+ hostPressure(seconds, reason, level = "slow") {
32997
+ this.core?.hostPressure(seconds, reason, level);
32701
32998
  }
32702
32999
  };
32703
33000
  var governor = new Governor();
@@ -32720,9 +33017,9 @@ var Daemon = class {
32720
33017
  tick() {
32721
33018
  const { valid, invalid } = run.scanRequests();
32722
33019
  for (const file3 of invalid)
32723
- safely("removing an invalid request", () => fs53.rmSync(file3, { recursive: true, force: true }));
33020
+ safely("removing an invalid request", () => fs54.rmSync(file3, { recursive: true, force: true }));
32724
33021
  for (const req of valid) {
32725
- safely("claiming a request", () => fs53.rmSync(run.requestFile(req.id), { force: true }));
33022
+ safely("claiming a request", () => fs54.rmSync(run.requestFile(req.id), { force: true }));
32726
33023
  if (run.readSession(req.id)) continue;
32727
33024
  void Promise.resolve(this.handle(withRequestSecrets(req))).catch(
32728
33025
  (e) => respond(req.id, { ok: false, message: errMsg(e) })
@@ -32745,7 +33042,7 @@ var Daemon = class {
32745
33042
  case "restart":
32746
33043
  return sessions.restart(req);
32747
33044
  case "pressure":
32748
- return governor.hostPressure(req.seconds, req.reason);
33045
+ return governor.hostPressure(req.seconds, req.reason, req.level ?? "slow");
32749
33046
  case "ping":
32750
33047
  return respond(req.id, { ok: true, message: "pong (" + sessions.count + " session(s) running)" });
32751
33048
  }