windows-development-sandbox 1.10.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 (378) hide show
  1. package/README.md +64 -17
  2. package/config.example.json +5 -1
  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 +21 -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 -89
  149. package/dist/cli/commands/web.d.ts +2 -1
  150. package/dist/cli/commands/web.js +14 -78
  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 +2 -1
  200. package/dist/core/schema/config.d.ts +5 -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/types.d.ts +6 -3
  211. package/dist/guest/boot/boot.js +8 -0
  212. package/dist/guest/daemon/daemon.js +1 -1
  213. package/dist/guest/daemon/sessions.d.ts +3 -2
  214. package/dist/guest/daemon/sessions.js +38 -7
  215. package/dist/guest/governor/core.d.ts +44 -0
  216. package/dist/guest/governor/core.js +124 -0
  217. package/dist/guest/governor/decide.d.ts +46 -18
  218. package/dist/guest/governor/decide.js +136 -82
  219. package/dist/guest/governor/governor.d.ts +2 -38
  220. package/dist/guest/governor/governor.js +33 -113
  221. package/dist/guest/governor/index.d.ts +1 -0
  222. package/dist/guest/governor/index.js +1 -0
  223. package/dist/guest/network/firewall.d.ts +2 -0
  224. package/dist/guest/network/firewall.js +3 -3
  225. package/dist/guest/sessions/viewer.js +5 -1
  226. package/dist/guest/setup/github-token.d.ts +7 -0
  227. package/dist/guest/setup/github-token.js +65 -0
  228. package/dist/guest/toolchains/languages/node.js +11 -1
  229. package/dist/guest/toolchains/native/rust-extras.js +2 -2
  230. package/dist/guest/toolchains/tools/cli.d.ts +8 -0
  231. package/dist/guest/toolchains/tools/cli.js +16 -2
  232. package/dist/guest/vpn/openvpn.d.ts +5 -0
  233. package/dist/guest/vpn/openvpn.js +14 -1
  234. package/dist/guest/vpn/vpn.js +55 -16
  235. package/dist/guest/vpn/wireguard.js +2 -0
  236. package/dist/host/channel/attach.d.ts +1 -0
  237. package/dist/host/channel/attach.js +1 -0
  238. package/dist/host/channel/channel.d.ts +1 -1
  239. package/dist/host/channel/channel.js +2 -2
  240. package/dist/host/engines/hcs/check.d.ts +1 -0
  241. package/dist/host/engines/hcs/check.js +1 -1
  242. package/dist/host/engines/hcs/engine.d.ts +1 -1
  243. package/dist/host/engines/hcs/engine.js +6 -4
  244. package/dist/host/engines/hcs/helper.d.ts +11 -0
  245. package/dist/host/engines/hcs/helper.js +31 -2
  246. package/dist/host/engines/hcs/leftovers.d.ts +42 -0
  247. package/dist/host/engines/hcs/leftovers.js +101 -0
  248. package/dist/host/engines/index.d.ts +1 -0
  249. package/dist/host/engines/index.js +1 -0
  250. package/dist/host/github/deliver.d.ts +13 -0
  251. package/dist/host/github/deliver.js +51 -0
  252. package/dist/host/github/index.d.ts +2 -0
  253. package/dist/host/github/index.js +3 -0
  254. package/dist/host/github/token.d.ts +21 -0
  255. package/dist/host/github/token.js +74 -0
  256. package/dist/host/launch/generate.js +11 -5
  257. package/dist/host/launch/index.d.ts +1 -1
  258. package/dist/host/launch/index.js +1 -1
  259. package/dist/host/launch/session-file.js +1 -2
  260. package/dist/host/launch/wsb-file.d.ts +11 -7
  261. package/dist/host/launch/wsb-file.js +30 -12
  262. package/dist/host/life/watchdog.d.ts +9 -0
  263. package/dist/host/life/watchdog.js +17 -1
  264. package/dist/host/sandbox/tasklist.d.ts +6 -0
  265. package/dist/host/sandbox/tasklist.js +37 -0
  266. package/dist/host/secrets/launch-secrets.d.ts +2 -1
  267. package/dist/host/secrets/launch-secrets.js +4 -2
  268. package/dist/host/vpn/status.js +13 -3
  269. package/dist/host/web/backend.d.ts +1 -3
  270. package/dist/host/web/index.d.ts +2 -1
  271. package/dist/host/web/index.js +2 -1
  272. package/dist/host/web/live.d.ts +23 -0
  273. package/dist/host/web/live.js +107 -0
  274. package/dist/host/web/rpc.d.ts +6 -1
  275. package/dist/host/web/rpc.js +23 -31
  276. package/dist/host/web/runner.d.ts +4 -0
  277. package/dist/host/web/runner.js +12 -1
  278. package/dist/host/web/server.d.ts +30 -2
  279. package/dist/host/web/server.js +87 -29
  280. package/dist/host/web/state.d.ts +1 -0
  281. package/dist/host/web/state.js +2 -0
  282. package/dist/runtime/agent.js +30 -6
  283. package/dist/runtime/daemon.js +323 -176
  284. package/dist/runtime/db.js +30 -6
  285. package/dist/runtime/main.js +375 -76
  286. package/dist/runtime/netproxy.js +30 -6
  287. package/dist/runtime/view.js +495 -146
  288. package/dist/selftest/app.test.js +620 -12
  289. package/dist/selftest/channel.test.js +18 -1
  290. package/dist/selftest/cli.test.js +1 -1
  291. package/dist/selftest/config.test.js +1 -1
  292. package/dist/selftest/contained.test.js +1 -1
  293. package/dist/selftest/data.test.js +1 -2
  294. package/dist/selftest/engine.test.js +3 -1
  295. package/dist/selftest/github.test.d.ts +2 -0
  296. package/dist/selftest/github.test.js +243 -0
  297. package/dist/selftest/hcs.test.js +105 -8
  298. package/dist/selftest/health.test.js +71 -0
  299. package/dist/selftest/heavy-load.test.js +132 -72
  300. package/dist/selftest/index.js +4 -0
  301. package/dist/selftest/layout.test.js +8 -0
  302. package/dist/selftest/live-terminal.test.js +74 -0
  303. package/dist/selftest/menu-screens.js +171 -56
  304. package/dist/selftest/menu.test.js +54 -37
  305. package/dist/selftest/migrate.test.js +14 -12
  306. package/dist/selftest/powershell-variables.test.d.ts +2 -0
  307. package/dist/selftest/powershell-variables.test.js +61 -0
  308. package/dist/selftest/support/engine-golden.js +1 -0
  309. package/dist/selftest/support/fixtures.d.ts +4 -0
  310. package/dist/selftest/support/web-preview.d.ts +1 -0
  311. package/dist/selftest/support/web-preview.js +856 -0
  312. package/dist/selftest/update-service.test.js +15 -8
  313. package/dist/selftest/vpn.test.js +86 -2
  314. package/dist/selftest/web.test.js +58 -11
  315. package/dist/shared/channel/run-dir.d.ts +2 -0
  316. package/dist/shared/channel/run-dir.js +3 -0
  317. package/dist/shared/channel/schema.d.ts +7 -0
  318. package/dist/shared/channel/schema.js +9 -1
  319. package/dist/shared/channel/secrets.d.ts +1 -0
  320. package/dist/shared/channel/secrets.js +3 -0
  321. package/dist/shared/github/index.d.ts +1 -0
  322. package/dist/shared/github/index.js +2 -0
  323. package/dist/shared/github/token.d.ts +29 -0
  324. package/dist/shared/github/token.js +89 -0
  325. package/dist/shared/memory/policy.d.ts +33 -12
  326. package/dist/shared/memory/policy.js +50 -19
  327. package/dist/shared/pty/ctrl-c.d.ts +18 -0
  328. package/dist/shared/pty/ctrl-c.js +36 -0
  329. package/dist/shared/pty/index.d.ts +1 -0
  330. package/dist/shared/pty/index.js +1 -0
  331. package/dist/shared/pty/terminal.d.ts +2 -0
  332. package/dist/shared/pty/terminal.js +21 -2
  333. package/dist/shared/vpn/kill-switch.d.ts +13 -2
  334. package/dist/shared/vpn/kill-switch.js +88 -8
  335. package/dist/shared/web/protocol.d.ts +0 -4
  336. package/dist/sync/watcher.js +1 -1
  337. package/dist/web/index.html +2 -2
  338. package/dist/web/{main-T5DMCHYV.css → main-6JF3ASB5.css} +1 -1
  339. package/dist/web/main-Z645W45E.js +219 -0
  340. package/native/csharp/HcsHost/AssemblyInfo.cs +3 -3
  341. package/native/csharp/HostTools/AssemblyInfo.cs +3 -3
  342. package/package.json +10 -3
  343. package/sandbox/csharp/MemGov.cs +240 -38
  344. package/sandbox/csharp/PtyHost.cs +104 -15
  345. package/sandbox/csharp/SandboxTools/CpuCap.cs +50 -1
  346. package/sandbox/csharp/SandboxTools/Program.cs +1 -1
  347. package/sandbox/scripts/repair-wmi-services.ps1 +26 -0
  348. package/schemas/config.schema.json +19 -5
  349. package/schemas/sandbox-config.schema.json +7 -3
  350. package/dist/cli/commands/accounts.d.ts +0 -2
  351. package/dist/cli/commands/accounts.js +0 -96
  352. package/dist/cli/commands/data/clean.d.ts +0 -3
  353. package/dist/cli/commands/data/clean.js +0 -60
  354. package/dist/cli/commands/data/index.d.ts +0 -4
  355. package/dist/cli/commands/data/index.js +0 -62
  356. package/dist/cli/commands/maintenance/clean.d.ts +0 -2
  357. package/dist/cli/commands/maintenance/clean.js +0 -24
  358. package/dist/cli/commands/maintenance/config-share.d.ts +0 -12
  359. package/dist/cli/commands/maintenance/config-share.js +0 -80
  360. package/dist/cli/commands/projects/projects.d.ts +0 -2
  361. package/dist/cli/commands/projects/projects.js +0 -162
  362. package/dist/cli/commands/storage/contained.d.ts +0 -3
  363. package/dist/cli/commands/storage/contained.js +0 -179
  364. package/dist/cli/commands/storage/storage.d.ts +0 -8
  365. package/dist/cli/commands/storage/storage.js +0 -179
  366. package/dist/cli/menu/add-agent.d.ts +0 -47
  367. package/dist/cli/menu/add-agent.js +0 -168
  368. package/dist/cli/menu/apps.d.ts +0 -69
  369. package/dist/cli/menu/apps.js +0 -214
  370. package/dist/cli/menu/data-folder.d.ts +0 -18
  371. package/dist/cli/menu/data-folder.js +0 -99
  372. package/dist/cli/menu/share-settings.d.ts +0 -21
  373. package/dist/cli/menu/share-settings.js +0 -112
  374. package/dist/cli/menu/vpn-login.d.ts +0 -16
  375. package/dist/cli/menu/vpn-login.js +0 -74
  376. package/dist/web/main-NRRS5O6Z.js +0 -157
  377. /package/dist/cli/{commands/data/collect.d.ts → services/data-collect.d.ts} +0 -0
  378. /package/dist/cli/{commands/data/remove.d.ts → services/data-remove.d.ts} +0 -0
@@ -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(
@@ -26646,6 +26651,13 @@ var VpnSchema = external_exports.strictObject({
26646
26651
  )
26647
26652
  });
26648
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
+
26649
26661
  // src/core/schema/config.ts
26650
26662
  var ConfigSchema = external_exports.strictObject({
26651
26663
  $schema: SchemaRefSchema.optional(),
@@ -26676,6 +26688,7 @@ var ConfigSchema = external_exports.strictObject({
26676
26688
  }),
26677
26689
  network: NetworkSchema,
26678
26690
  vpn: VpnSchema,
26691
+ github: GithubSchema,
26679
26692
  provisioning: ProvisioningSchema,
26680
26693
  downloads: DownloadsSchema,
26681
26694
  toolchains: ToolchainsSchema,
@@ -26838,19 +26851,25 @@ var GuestRequestSchema = external_exports.discriminatedUnion("kind", [
26838
26851
  id: IdSchema,
26839
26852
  reason: Text(300),
26840
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(),
26841
26856
  createdAt: TimeSchema
26842
26857
  })
26843
26858
  ]);
26844
26859
  var PressureStatusSchema = external_exports.object({
26845
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(),
26846
26863
  profile: external_exports.enum(["normal", "gentle"]),
26847
26864
  /** Share of the sandbox's RAM still free and of its commit limit in use (percent). */
26848
26865
  ramFreePercent: external_exports.number().int().min(0).max(100),
26849
26866
  commitPercent: external_exports.number().int().min(0).max(100),
26850
26867
  /** Programs running at lower priority because of it. */
26851
26868
  lowered: external_exports.number().int().min(0).max(1024),
26852
- /** 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). */
26853
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(),
26854
26873
  /** The PC itself asked for slowing down (its memory or CPU is low). */
26855
26874
  pcLow: external_exports.boolean(),
26856
26875
  lastAction: Text(300),
@@ -26894,6 +26913,8 @@ var VpnStatusSchema = external_exports.object({
26894
26913
  state: external_exports.enum(["off", "starting", "up", "failed"]),
26895
26914
  message: Text(2e3),
26896
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(),
26897
26918
  /** The server's name, e.g. uk2201.nordvpn.com. */
26898
26919
  server: Text(128).optional(),
26899
26920
  /** What the sandbox's traffic looks like from outside, once the tunnel is up. */
@@ -27119,6 +27140,8 @@ var RunDir = class {
27119
27140
  vpnFile;
27120
27141
  /** What the memory governor in the sandbox is doing (pressure.json). */
27121
27142
  pressureFile;
27143
+ /** What the sandbox's programs may really use (budget.json): processors, memory, build jobs, link slots. */
27144
+ budgetFile;
27122
27145
  requestsDir;
27123
27146
  responsesDir;
27124
27147
  sessionsDir;
@@ -27132,6 +27155,7 @@ var RunDir = class {
27132
27155
  this.sandboxFile = path7.join(this.root, "sandbox.json");
27133
27156
  this.vpnFile = path7.join(this.root, "vpn.json");
27134
27157
  this.pressureFile = path7.join(this.root, "pressure.json");
27158
+ this.budgetFile = path7.join(this.root, "budget.json");
27135
27159
  this.requestsDir = path7.join(this.root, "requests");
27136
27160
  this.responsesDir = path7.join(this.root, "responses");
27137
27161
  this.sessionsDir = path7.join(this.root, "sessions");
@@ -27685,6 +27709,12 @@ function safely(what, work) {
27685
27709
  // src/guest/runtime/secrets.ts
27686
27710
  import fs13 from "node:fs";
27687
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);
27717
+
27688
27718
  // src/shared/channel/secrets.ts
27689
27719
  var Environment = external_exports.record(external_exports.string().max(256), external_exports.string().max(65536));
27690
27720
  var SecretsFileSchema = external_exports.strictObject({
@@ -27699,7 +27729,9 @@ var SecretsFileSchema = external_exports.strictObject({
27699
27729
  /** VPN service credentials (vpn.provider's login), only for the launch's own sandbox. */
27700
27730
  vpn: external_exports.strictObject({ username: external_exports.string().min(1).max(256), password: external_exports.string().min(1).max(1024) }).optional(),
27701
27731
  /** The checked WireGuard config of vpn.provider wireguard-file (holds the private key). */
27702
- 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()
27703
27735
  });
27704
27736
  var withEnvironment = (harness, environment) => environment ? { ...harness, environment: { ...harness.environment, ...environment } } : harness;
27705
27737
  function mergeRequestSecrets(request, secrets) {
@@ -29943,9 +29975,12 @@ async function setupUv(env) {
29943
29975
  function ghConfigDir() {
29944
29976
  return path45.join(stateDir, "gh");
29945
29977
  }
29978
+ function deliveredGhConfigDir() {
29979
+ return path45.join(localDir, "gh-token");
29980
+ }
29946
29981
  var toolVars = {
29947
29982
  gh: () => ({
29948
- GH_CONFIG_DIR: mkdirp(ghConfigDir()),
29983
+ GH_CONFIG_DIR: exists(deliveredGhConfigDir()) ? deliveredGhConfigDir() : mkdirp(ghConfigDir()),
29949
29984
  GH_NO_UPDATE_NOTIFIER: "1",
29950
29985
  GH_NO_EXTENSION_UPDATE_NOTIFIER: "1"
29951
29986
  })
@@ -30791,6 +30826,10 @@ var activate = async (version2) => {
30791
30826
  fs43.rmSync(NVM_SYMLINK, { recursive: true, force: true });
30792
30827
  fs43.symlinkSync(path56.join(NVM_HOME, "v" + version2), NVM_SYMLINK, "junction");
30793
30828
  };
30829
+ var PLAYWRIGHT_VARS = () => ({
30830
+ PLAYWRIGHT_BROWSERS_PATH: tool("ms-playwright"),
30831
+ PLAYWRIGHT_MCP_BROWSER: "msedge"
30832
+ });
30794
30833
  async function setupNode(env, versions, config2) {
30795
30834
  if (dryRun) {
30796
30835
  log("(dry run) would provision nvm and Node " + versions.node.spec + " (from " + versions.node.source + ")");
@@ -30824,13 +30863,14 @@ async function setupNode(env, versions, config2) {
30824
30863
  warn("Node " + version2 + " from this PC: " + errMsg(e));
30825
30864
  }
30826
30865
  }
30827
- Object.assign(env.vars, { NVM_HOME, NVM_SYMLINK });
30866
+ Object.assign(env.vars, { NVM_HOME, NVM_SYMLINK, ...PLAYWRIGHT_VARS() });
30828
30867
  if (duringSession()) env.prepend.push(path56.join(NVM_HOME, "v" + main), NVM_HOME, NVM_SYMLINK);
30829
30868
  else {
30830
30869
  await activate(main);
30831
30870
  env.prepend.push(NVM_HOME, NVM_SYMLINK);
30832
30871
  }
30833
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')");
30834
30874
  await packageManagers(env, config2, main);
30835
30875
  }
30836
30876
  var packageManagers = async (env, config2, version2) => {
@@ -31377,27 +31417,44 @@ import os8 from "node:os";
31377
31417
  import path62 from "node:path";
31378
31418
 
31379
31419
  // src/shared/memory/policy.ts
31380
- var GUEST_THRESHOLDS = {
31381
- normal: {
31382
- enterAvailablePercent: 8,
31383
- enterCommitPercent: 92,
31384
- exitAvailablePercent: 12,
31385
- exitCommitPercent: 88,
31386
- calmSamples: 3
31387
- },
31388
- gentle: {
31389
- enterAvailablePercent: 15,
31390
- enterCommitPercent: 85,
31391
- exitAvailablePercent: 20,
31392
- exitCommitPercent: 80,
31393
- calmSamples: 3
31394
- }
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
+ ]
31395
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
+ }
31396
31453
  function cargoJobs(cpus, memoryGb, sessions2) {
31397
- 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)));
31398
31455
  const byMemory = Math.max(1, Math.floor(memoryGb / 4));
31399
31456
  const jobs = Math.min(byCpu, byMemory);
31400
- 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))));
31401
31458
  }
31402
31459
  function maxCompilers(cpus, profile) {
31403
31460
  return profile === "gentle" ? Math.max(2, Math.floor(cpus / 4)) : null;
@@ -31423,7 +31480,7 @@ function linkGate(env, rust, host) {
31423
31480
  const gate = path62.join(mkdirp(tool("shims")), "linkgate.exe");
31424
31481
  fs48.copyFileSync(ensureCompiled("linkgate"), gate);
31425
31482
  const memoryGb = os8.totalmem() / 1024 ** 3;
31426
- 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;
31427
31484
  env.vars.AGENT_LINK_SLOTS = String(slots);
31428
31485
  env.vars.AGENT_REAL_LINKER = gcc;
31429
31486
  env.vars.CARGO_TARGET_X86_64_PC_WINDOWS_GNU_LINKER = gate;
@@ -32275,11 +32332,33 @@ var harnessFor = (req) => {
32275
32332
  };
32276
32333
  function memoryEnv(env, sessions2) {
32277
32334
  const out = {};
32278
- if (session.agentMemoryLimitMb) out.PTYHOST_JOB_MB = String(session.agentMemoryLimitMb);
32279
- if (!env.CARGO_BUILD_JOBS)
32280
- 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);
32281
32344
  return out;
32282
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
+ }
32283
32362
  var launchPtyHost = async (req, remote, env, say, sessions2) => {
32284
32363
  const harness = harnessFor(req);
32285
32364
  say("Preparing " + req.harness);
@@ -32504,7 +32583,6 @@ var COMPILERS = /* @__PURE__ */ new Set([
32504
32583
  "javac"
32505
32584
  ]);
32506
32585
  var BUILD_TOOLS = /* @__PURE__ */ new Set([
32507
- "node",
32508
32586
  "dotnet",
32509
32587
  "msbuild",
32510
32588
  "vbcscompiler",
@@ -32573,88 +32651,123 @@ var HEAVY = /* @__PURE__ */ new Set([
32573
32651
  var isHeavyCompiler = (name) => !isNeverTouched(name) && HEAVY.has(key(name));
32574
32652
  var canPause = (name) => !isNeverTouched(name) && COMPILERS.has(key(name));
32575
32653
  var INITIAL_STATE = {
32576
- pressure: false,
32654
+ step: 0,
32577
32655
  calm: 0,
32578
- samples: 0,
32579
32656
  lowered: {},
32580
- pausedUntil: 0,
32581
- nextPauseAt: 0,
32582
- 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
32583
32666
  };
32667
+ var GROWTH_WEIGHT = 0.3;
32584
32668
  var HOLD_MS = 3e3;
32585
- var PAUSE_MS = 5e3;
32586
- var PAUSE_COOLDOWN_MS = 1e4;
32587
- var IDLE_AFTER = 3;
32588
- var PAUSE_AFTER = 4;
32589
- var PAUSE_MIN_MB = 300;
32590
- function decide(prev, sample, nowMs, thresholds, profile, maxCompilers2 = null) {
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) {
32591
32686
  const ramFree = sample.ramAvailMb / Math.max(1, sample.ramTotalMb) * 100;
32592
- 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;
32593
32693
  const pcLow = nowMs < prev.hostUntil;
32594
- const low = ramFree < thresholds.enterAvailablePercent || commit > thresholds.enterCommitPercent || pcLow;
32595
- const recovered = ramFree > thresholds.exitAvailablePercent && commit < thresholds.exitCommitPercent && !pcLow;
32596
- let pressure = prev.pressure;
32597
- let calm = prev.calm;
32598
- let samples = prev.samples;
32599
- if (low) {
32600
- pressure = true;
32601
- calm = 0;
32602
- samples = prev.samples + 1;
32603
- } else if (prev.pressure) {
32604
- calm = recovered ? prev.calm + 1 : 0;
32605
- if (calm >= thresholds.calmSamples) {
32606
- 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;
32607
32702
  calm = 0;
32608
- samples = 0;
32609
32703
  }
32610
32704
  }
32611
32705
  const actions = [];
32612
32706
  const present2 = new Set(sample.procs.map((p) => p.pid));
32707
+ const keep = (pids) => pids.filter((pid) => present2.has(pid));
32613
32708
  const lowered = {};
32614
32709
  for (const [pid, to] of Object.entries(prev.lowered)) if (present2.has(Number(pid))) lowered[Number(pid)] = to;
32615
- if (pressure) {
32616
- const target = samples > IDLE_AFTER ? "idle" : "below";
32617
- for (const p of sample.procs) {
32618
- if (!canLower(p.name) || lowered[p.pid] === target) continue;
32619
- if (p.prio !== target && !(target === "below" && p.prio === "idle"))
32620
- actions.push({ kind: "priority", pid: p.pid, name: p.name, to: target });
32621
- lowered[p.pid] = target;
32622
- }
32623
- } else {
32624
- for (const p of sample.procs) {
32625
- if (!canLower(p.name)) continue;
32626
- const base = profile === "gentle" && canPause(p.name) ? "below" : "normal";
32627
- const was = lowered[p.pid];
32628
- if (prev.pressure && was !== void 0 && was !== base) {
32629
- if (p.prio !== base) actions.push({ kind: "priority", pid: p.pid, name: p.name, to: base });
32630
- if (base === "normal") delete lowered[p.pid];
32631
- else lowered[p.pid] = base;
32632
- } else if (!prev.pressure && base === "below" && was === void 0) {
32633
- if (p.prio === "normal") actions.push({ kind: "priority", pid: p.pid, name: p.name, to: "below" });
32634
- lowered[p.pid] = "below";
32635
- }
32636
- }
32637
- }
32638
- let pausedUntil = prev.pausedUntil;
32639
- let nextPauseAt = prev.nextPauseAt;
32640
- if (pressure && samples >= PAUSE_AFTER && nowMs >= prev.nextPauseAt && nowMs >= prev.pausedUntil) {
32641
- const victim = [...sample.procs].filter((p) => canPause(p.name) && p.mb >= PAUSE_MIN_MB).sort((a, b) => b.mb - a.mb)[0];
32642
- if (victim) {
32643
- actions.push({ kind: "pause", pid: victim.pid, name: victim.name, ms: PAUSE_MS });
32644
- pausedUntil = nowMs + PAUSE_MS;
32645
- nextPauseAt = pausedUntil + PAUSE_COOLDOWN_MS;
32646
- }
32647
- }
32648
- if (maxCompilers2 !== null) {
32649
- const heavy = sample.procs.filter(
32650
- (p) => isHeavyCompiler(p.name) && !(nowMs < pausedUntil && actions.some((a) => a.kind === "pause" && a.pid === p.pid))
32651
- ).sort((a, b) => a.pid - b.pid);
32652
- for (const p of heavy.slice(Math.max(1, maxCompilers2)))
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)) {
32653
32747
  actions.push({ kind: "hold", pid: p.pid, name: p.name, ms: HOLD_MS });
32654
- }
32655
- const level = nowMs < pausedUntil ? "suspending" : pressure ? "throttled" : "ok";
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";
32656
32756
  return {
32657
- 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
+ },
32658
32771
  actions,
32659
32772
  level,
32660
32773
  ramFreePercent: Math.round(ramFree),
@@ -32662,26 +32775,14 @@ function decide(prev, sample, nowMs, thresholds, profile, maxCompilers2 = null)
32662
32775
  };
32663
32776
  }
32664
32777
 
32665
- // src/guest/governor/governor.ts
32666
- import fs53 from "node:fs";
32667
- import os12 from "node:os";
32668
- import path69 from "node:path";
32669
- import { spawn as spawn8 } from "node:child_process";
32670
- import { createInterface } from "node:readline";
32671
- var SampleSchema = external_exports.object({
32672
- ramTotalMb: external_exports.number(),
32673
- ramAvailMb: external_exports.number(),
32674
- commitLimitMb: external_exports.number(),
32675
- commitAvailMb: external_exports.number(),
32676
- procs: external_exports.array(
32677
- external_exports.object({
32678
- pid: external_exports.number().int(),
32679
- name: external_exports.string().max(128),
32680
- mb: external_exports.number(),
32681
- prio: external_exports.enum(["idle", "below", "normal"]).catch("normal")
32682
- })
32683
- ).max(1024)
32684
- });
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
+ ];
32685
32786
  var GovernorCore = class {
32686
32787
  constructor(deps) {
32687
32788
  this.deps = deps;
@@ -32691,52 +32792,51 @@ var GovernorCore = class {
32691
32792
  lastAction = "";
32692
32793
  lastWrite = "";
32693
32794
  lastWriteAt = 0;
32694
- pausedName = "";
32695
- pausedPid = 0;
32696
- held = /* @__PURE__ */ new Set();
32697
- hostPressure(seconds, reason) {
32698
- const until = this.deps.now() + seconds * 1e3;
32699
- if (until > this.state.hostUntil) {
32700
- if (this.state.hostUntil <= this.deps.now())
32701
- this.deps.logLine("governor: this PC is low (" + reason + "); slowing builds down");
32702
- this.state = { ...this.state, hostUntil: until };
32703
- }
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 };
32704
32807
  }
32705
32808
  get current() {
32706
32809
  return this.state;
32707
32810
  }
32708
32811
  onSample(sample) {
32709
32812
  const nowMs = this.deps.now();
32710
- const before = this.state.pressure;
32711
- const seen = new Set(sample.procs.map((p) => p.pid));
32712
- for (const pid of this.held) if (!seen.has(pid)) this.held.delete(pid);
32713
- const d = decide(
32714
- this.state,
32715
- sample,
32716
- nowMs,
32717
- GUEST_THRESHOLDS[this.deps.profile],
32718
- this.deps.profile,
32719
- this.deps.maxCompilers ?? null
32720
- );
32813
+ const before = this.state.step;
32814
+ const d = decide(this.state, sample, nowMs, this.deps.profile, this.deps.maxCompilers ?? null);
32721
32815
  this.state = d.state;
32722
- for (const action of d.actions) this.apply(action);
32723
- 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)
32724
32823
  this.deps.logLine(
32725
- 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]
32726
32825
  );
32727
- const paused = nowMs < d.state.pausedUntil && this.pausedPid ? [{ name: this.pausedName, pid: this.pausedPid, seconds: Math.ceil((d.state.pausedUntil - nowMs) / 1e3) }] : [];
32728
32826
  const status = {
32729
32827
  level: d.level,
32828
+ step: d.state.step,
32730
32829
  profile: this.deps.profile,
32731
32830
  ramFreePercent: Math.max(0, Math.min(100, d.ramFreePercent)),
32732
32831
  commitPercent: Math.max(0, Math.min(100, d.commitPercent)),
32733
32832
  lowered: Object.keys(d.state.lowered).length,
32734
- 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,
32735
32835
  pcLow: nowMs < d.state.hostUntil,
32736
- lastAction: this.lastAction,
32836
+ lastAction: this.lastAction.slice(0, 300),
32737
32837
  updatedAt: now()
32738
32838
  };
32739
- 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) });
32740
32840
  if (shape !== this.lastWrite || nowMs - this.lastWriteAt > 6e4) {
32741
32841
  this.lastWrite = shape;
32742
32842
  this.lastWriteAt = nowMs;
@@ -32744,33 +32844,64 @@ var GovernorCore = class {
32744
32844
  }
32745
32845
  }
32746
32846
  apply(action) {
32847
+ const port = this.deps.port;
32747
32848
  try {
32748
- if (action.kind === "hold") {
32749
- this.deps.port.pause(action.pid, action.ms);
32750
- if (!this.held.has(action.pid)) {
32751
- this.held.add(action.pid);
32752
- this.lastAction = "holding " + action.name + " (" + action.pid + ") until another compiler ends";
32753
- this.deps.logLine("governor: " + this.lastAction);
32754
- }
32755
- return;
32756
- }
32757
- if (action.kind === "priority") {
32758
- this.deps.port.setPriority(action.pid, action.to);
32759
- this.lastAction = action.name + " (" + action.pid + ") priority " + action.to;
32760
- } else {
32761
- this.deps.port.pause(action.pid, action.ms);
32762
- this.pausedName = action.name;
32763
- this.pausedPid = action.pid;
32764
- this.lastAction = "paused " + action.name + " (" + action.pid + ") for " + action.ms / 1e3 + " s";
32765
- this.deps.logLine("governor: " + this.lastAction);
32766
- 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;
32767
32874
  }
32768
- this.deps.logLine("governor: " + this.lastAction);
32769
32875
  } catch (e) {
32770
- warn("governor: " + errMsg(e));
32876
+ this.deps.warn("governor: " + errMsg(e));
32771
32877
  }
32772
32878
  }
32879
+ note(text) {
32880
+ this.lastAction = text;
32881
+ this.deps.logLine("governor: " + text);
32882
+ }
32773
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
+ });
32774
32905
  var MemGovProcess = class {
32775
32906
  constructor(onSample) {
32776
32907
  this.onSample = onSample;
@@ -32801,10 +32932,25 @@ var MemGovProcess = class {
32801
32932
  }
32802
32933
  }
32803
32934
  setPriority(pid, to) {
32804
- 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);
32805
32951
  }
32806
- pause(pid, ms) {
32807
- this.child?.stdin?.write("suspend " + pid + " " + ms + "\n");
32952
+ send(line) {
32953
+ this.child?.stdin?.write(line + "\n");
32808
32954
  }
32809
32955
  };
32810
32956
  function appendToMemoryLog(line) {
@@ -32822,8 +32968,8 @@ var Governor = class {
32822
32968
  core = null;
32823
32969
  describe() {
32824
32970
  const profile = session.loadProfile === "gentle" ? "gentle" : "normal";
32825
- const t = GUEST_THRESHOLDS[profile];
32826
- 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";
32827
32973
  }
32828
32974
  start() {
32829
32975
  if (session.pressureResponse === false) return;
@@ -32835,6 +32981,7 @@ var Governor = class {
32835
32981
  maxCompilers: maxCompilers(os12.cpus().length, profile),
32836
32982
  now: () => Date.now(),
32837
32983
  logLine: appendToMemoryLog,
32984
+ warn,
32838
32985
  saveStatus: (status) => {
32839
32986
  try {
32840
32987
  writeJsonAtomic(run.pressureFile, status);
@@ -32845,9 +32992,9 @@ var Governor = class {
32845
32992
  });
32846
32993
  proc.start();
32847
32994
  }
32848
- /** The host's watchdog: this PC is low for a while. */
32849
- hostPressure(seconds, reason) {
32850
- 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);
32851
32998
  }
32852
32999
  };
32853
33000
  var governor = new Governor();
@@ -32895,7 +33042,7 @@ var Daemon = class {
32895
33042
  case "restart":
32896
33043
  return sessions.restart(req);
32897
33044
  case "pressure":
32898
- return governor.hostPressure(req.seconds, req.reason);
33045
+ return governor.hostPressure(req.seconds, req.reason, req.level ?? "slow");
32899
33046
  case "ping":
32900
33047
  return respond(req.id, { ok: true, message: "pong (" + sessions.count + " session(s) running)" });
32901
33048
  }