windows-development-sandbox 1.10.0 → 1.11.4

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 (383) 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 +194 -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 +959 -4
  32. package/dist/app/features/defs.js +151 -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 +297 -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 +220 -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 +224 -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 +35 -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/host-memory.d.ts +18 -0
  263. package/dist/host/life/host-memory.js +66 -0
  264. package/dist/host/life/watchdog.d.ts +9 -0
  265. package/dist/host/life/watchdog.js +17 -1
  266. package/dist/host/sandbox/tasklist.d.ts +6 -0
  267. package/dist/host/sandbox/tasklist.js +37 -0
  268. package/dist/host/secrets/launch-secrets.d.ts +2 -1
  269. package/dist/host/secrets/launch-secrets.js +4 -2
  270. package/dist/host/vpn/status.js +13 -3
  271. package/dist/host/web/backend.d.ts +1 -3
  272. package/dist/host/web/index.d.ts +2 -1
  273. package/dist/host/web/index.js +2 -1
  274. package/dist/host/web/live.d.ts +23 -0
  275. package/dist/host/web/live.js +107 -0
  276. package/dist/host/web/rpc.d.ts +6 -1
  277. package/dist/host/web/rpc.js +23 -31
  278. package/dist/host/web/runner.d.ts +4 -0
  279. package/dist/host/web/runner.js +12 -1
  280. package/dist/host/web/server.d.ts +30 -2
  281. package/dist/host/web/server.js +87 -29
  282. package/dist/host/web/state.d.ts +1 -0
  283. package/dist/host/web/state.js +2 -0
  284. package/dist/runtime/agent.js +30 -6
  285. package/dist/runtime/daemon.js +337 -177
  286. package/dist/runtime/db.js +30 -6
  287. package/dist/runtime/main.js +389 -77
  288. package/dist/runtime/netproxy.js +30 -6
  289. package/dist/runtime/view.js +495 -146
  290. package/dist/selftest/app.test.js +632 -12
  291. package/dist/selftest/channel.test.js +18 -1
  292. package/dist/selftest/cli.test.js +1 -1
  293. package/dist/selftest/config.test.js +1 -1
  294. package/dist/selftest/contained.test.js +1 -1
  295. package/dist/selftest/data.test.js +1 -2
  296. package/dist/selftest/engine.test.js +3 -1
  297. package/dist/selftest/github.test.d.ts +2 -0
  298. package/dist/selftest/github.test.js +243 -0
  299. package/dist/selftest/hcs.test.js +105 -8
  300. package/dist/selftest/health.test.js +71 -0
  301. package/dist/selftest/heavy-load.test.js +132 -72
  302. package/dist/selftest/index.js +4 -0
  303. package/dist/selftest/layout.test.js +8 -0
  304. package/dist/selftest/live-terminal.test.js +74 -0
  305. package/dist/selftest/menu-screens.js +171 -56
  306. package/dist/selftest/menu.test.js +54 -37
  307. package/dist/selftest/migrate.test.js +14 -12
  308. package/dist/selftest/powershell-variables.test.d.ts +2 -0
  309. package/dist/selftest/powershell-variables.test.js +61 -0
  310. package/dist/selftest/support/engine-golden.js +1 -0
  311. package/dist/selftest/support/fixtures.d.ts +4 -0
  312. package/dist/selftest/support/web-preview.d.ts +1 -0
  313. package/dist/selftest/support/web-preview.js +856 -0
  314. package/dist/selftest/update-service.test.js +15 -8
  315. package/dist/selftest/vpn.test.js +86 -2
  316. package/dist/selftest/web.test.js +58 -11
  317. package/dist/shared/channel/run-dir.d.ts +2 -0
  318. package/dist/shared/channel/run-dir.js +3 -0
  319. package/dist/shared/channel/schema.d.ts +7 -0
  320. package/dist/shared/channel/schema.js +9 -1
  321. package/dist/shared/channel/secrets.d.ts +1 -0
  322. package/dist/shared/channel/secrets.js +3 -0
  323. package/dist/shared/github/index.d.ts +1 -0
  324. package/dist/shared/github/index.js +2 -0
  325. package/dist/shared/github/token.d.ts +29 -0
  326. package/dist/shared/github/token.js +89 -0
  327. package/dist/shared/memory/policy.d.ts +33 -12
  328. package/dist/shared/memory/policy.js +50 -19
  329. package/dist/shared/pty/ctrl-c.d.ts +18 -0
  330. package/dist/shared/pty/ctrl-c.js +36 -0
  331. package/dist/shared/pty/index.d.ts +1 -0
  332. package/dist/shared/pty/index.js +1 -0
  333. package/dist/shared/pty/terminal.d.ts +2 -0
  334. package/dist/shared/pty/terminal.js +21 -2
  335. package/dist/shared/vpn/kill-switch.d.ts +13 -2
  336. package/dist/shared/vpn/kill-switch.js +88 -8
  337. package/dist/shared/web/protocol.d.ts +0 -4
  338. package/dist/sync/watcher.d.ts +2 -0
  339. package/dist/sync/watcher.js +8 -3
  340. package/dist/web/index.html +2 -2
  341. package/dist/web/{main-T5DMCHYV.css → main-MU5XWZMS.css} +1 -1
  342. package/dist/web/main-SLQNJRXD.js +219 -0
  343. package/native/csharp/HcsHost/AssemblyInfo.cs +3 -3
  344. package/native/csharp/HostTools/AssemblyInfo.cs +3 -3
  345. package/native/csharp/HostTools/MemoryStatus.cs +58 -2
  346. package/native/csharp/HostTools/Program.cs +7 -1
  347. package/package.json +10 -3
  348. package/sandbox/csharp/MemGov.cs +240 -38
  349. package/sandbox/csharp/PtyHost.cs +104 -15
  350. package/sandbox/csharp/SandboxTools/CpuCap.cs +50 -1
  351. package/sandbox/csharp/SandboxTools/Program.cs +1 -1
  352. package/sandbox/scripts/repair-wmi-services.ps1 +26 -0
  353. package/schemas/config.schema.json +19 -5
  354. package/schemas/sandbox-config.schema.json +7 -3
  355. package/dist/cli/commands/accounts.d.ts +0 -2
  356. package/dist/cli/commands/accounts.js +0 -96
  357. package/dist/cli/commands/data/clean.d.ts +0 -3
  358. package/dist/cli/commands/data/clean.js +0 -60
  359. package/dist/cli/commands/data/index.d.ts +0 -4
  360. package/dist/cli/commands/data/index.js +0 -62
  361. package/dist/cli/commands/maintenance/clean.d.ts +0 -2
  362. package/dist/cli/commands/maintenance/clean.js +0 -24
  363. package/dist/cli/commands/maintenance/config-share.d.ts +0 -12
  364. package/dist/cli/commands/maintenance/config-share.js +0 -80
  365. package/dist/cli/commands/projects/projects.d.ts +0 -2
  366. package/dist/cli/commands/projects/projects.js +0 -162
  367. package/dist/cli/commands/storage/contained.d.ts +0 -3
  368. package/dist/cli/commands/storage/contained.js +0 -179
  369. package/dist/cli/commands/storage/storage.d.ts +0 -8
  370. package/dist/cli/commands/storage/storage.js +0 -179
  371. package/dist/cli/menu/add-agent.d.ts +0 -47
  372. package/dist/cli/menu/add-agent.js +0 -168
  373. package/dist/cli/menu/apps.d.ts +0 -69
  374. package/dist/cli/menu/apps.js +0 -214
  375. package/dist/cli/menu/data-folder.d.ts +0 -18
  376. package/dist/cli/menu/data-folder.js +0 -99
  377. package/dist/cli/menu/share-settings.d.ts +0 -21
  378. package/dist/cli/menu/share-settings.js +0 -112
  379. package/dist/cli/menu/vpn-login.d.ts +0 -16
  380. package/dist/cli/menu/vpn-login.js +0 -74
  381. package/dist/web/main-NRRS5O6Z.js +0 -157
  382. /package/dist/cli/{commands/data/collect.d.ts → services/data-collect.d.ts} +0 -0
  383. /package/dist/cli/{commands/data/remove.d.ts → services/data-remove.d.ts} +0 -0
@@ -1,3 +1,9 @@
1
+ // The memory governor's decisions (pure): given a memory sample and what it did before, how far to turn the dial and
2
+ // what that means for the build programs in the agents' job. Like a PC that gets slower instead of failing: lower
3
+ // priority, lower memory priority (their pages are trimmed first), less CPU, fewer compilers at a time (the others wait
4
+ // their turn, suspended and always resumed), waiting compilers trimmed to the paging file. Agents, shells and Windows
5
+ // are never touched. Nothing here touches Windows; governor.ts carries the actions out through a port.
6
+ import { compilersAllowed, DIAL_CALM_SAMPLES, DIAL_CPU_RATE, DIAL_EXIT_MARGIN, DIAL_STEPS, } from '../../shared/memory/index.js';
1
7
  /** Programs that compile or link: they may be slowed down and, as the last resort, paused for a few seconds. */
2
8
  const COMPILERS = new Set([
3
9
  'rustc',
@@ -25,8 +31,8 @@ const COMPILERS = new Set([
25
31
  'javac',
26
32
  ]);
27
33
  /** Build tools and workers: slowed down but never paused (a node process may be a dev server or an agent). */
34
+ // Not node: agents such as Codex and Gemini run as node.exe, and the agents are never slowed down.
28
35
  const BUILD_TOOLS = new Set([
29
- 'node',
30
36
  'dotnet',
31
37
  'msbuild',
32
38
  'vbcscompiler',
@@ -97,112 +103,160 @@ const HEAVY = new Set([
97
103
  export const isHeavyCompiler = (name) => !isNeverTouched(name) && HEAVY.has(key(name));
98
104
  export const canPause = (name) => !isNeverTouched(name) && COMPILERS.has(key(name));
99
105
  export const INITIAL_STATE = {
100
- pressure: false,
106
+ step: 0,
101
107
  calm: 0,
102
- samples: 0,
103
108
  lowered: {},
104
- pausedUntil: 0,
105
- nextPauseAt: 0,
109
+ memLow: [],
110
+ throttled: [],
111
+ trimmed: [],
112
+ cpuRate: 100,
113
+ lastCommitMb: 0,
114
+ lastAt: 0,
115
+ growth: 0,
106
116
  hostUntil: 0,
117
+ hostStep: 0,
107
118
  };
108
- /** How long a held compiler waits before it gets a turn again (the governor repeats the hold while over the cap). */
119
+ /** How much the newest sample counts in the smoothed commit growth. */
120
+ const GROWTH_WEIGHT = 0.3;
121
+ /** How long a held compiler waits before it may get a turn again (the governor repeats the hold while it waits). */
109
122
  export const HOLD_MS = 3000;
110
- export const PAUSE_MS = 5000;
111
- const PAUSE_COOLDOWN_MS = 10000;
112
- /** Samples under pressure before programs go from below-normal to idle, and before one is paused. */
113
- const IDLE_AFTER = 3;
114
- const PAUSE_AFTER = 4;
115
- /** Only a program this big is worth pausing. */
116
- const PAUSE_MIN_MB = 300;
123
+ /** Which compilers wait their turn changes this often, so none waits for ever. */
124
+ export const ROTATE_MS = 20000;
117
125
  /**
118
- * One step. `gentle` (vGPU on): compilers start below normal even without pressure. Programs go back to their normal
119
- * priority only when pressure ends (several calm samples in a row).
126
+ * "Full soon" only counts this close (in commit percent) to a step's own threshold: a build that grabs a few GB in a
127
+ * burst while most of the memory is free is normal, not a reason to pause compilers.
120
128
  */
121
- export function decide(prev, sample, nowMs, thresholds, profile, maxCompilers = null) {
129
+ const SOON_WITHIN_PERCENT = 12;
130
+ /** The step a sample calls for on its own: the highest step whose threshold it crosses. */
131
+ export function stepFor(ramFree, commit, secondsToLimit, profile) {
132
+ let step = 0;
133
+ DIAL_STEPS[profile].forEach((t, i) => {
134
+ const near = commit > t.commitPercent - SOON_WITHIN_PERCENT;
135
+ const soon = near && t.secondsToLimit !== undefined && secondsToLimit < t.secondsToLimit;
136
+ if (ramFree < t.availablePercent || commit > t.commitPercent || soon)
137
+ step = i + 1;
138
+ });
139
+ return step;
140
+ }
141
+ /** Is the sample clear of `step` by the exit margins (so the dial may turn down from it)? */
142
+ function clearOf(step, ramFree, commit, profile) {
143
+ if (step === 0)
144
+ return true;
145
+ const t = DIAL_STEPS[profile][step - 1];
146
+ return (ramFree > t.availablePercent + DIAL_EXIT_MARGIN.availablePercent &&
147
+ commit < t.commitPercent - DIAL_EXIT_MARGIN.commitPercent);
148
+ }
149
+ /**
150
+ * One step of the governor. The dial turns up at once and down one step at a time after calm samples. `gentle` (vGPU
151
+ * on): compilers rest below normal priority, and `maxCompilers` caps how many heavy compilers run at any step.
152
+ */
153
+ export function decide(prev, sample, nowMs, profile, maxCompilers = null) {
122
154
  const ramFree = (sample.ramAvailMb / Math.max(1, sample.ramTotalMb)) * 100;
123
- const commit = ((sample.commitLimitMb - sample.commitAvailMb) / Math.max(1, sample.commitLimitMb)) * 100;
155
+ const usedMb = sample.commitLimitMb - sample.commitAvailMb;
156
+ const commit = (usedMb / Math.max(1, sample.commitLimitMb)) * 100;
157
+ const seconds = (nowMs - prev.lastAt) / 1000;
158
+ const instant = prev.lastAt > 0 && seconds > 0 ? (usedMb - prev.lastCommitMb) / seconds : 0;
159
+ // Smoothed over the last samples, so one burst between two samples is not read as a trend.
160
+ const growth = prev.lastAt > 0 ? prev.growth * (1 - GROWTH_WEIGHT) + instant * GROWTH_WEIGHT : 0;
161
+ const secondsToLimit = growth > 0 ? sample.commitAvailMb / growth : Number.POSITIVE_INFINITY;
124
162
  const pcLow = nowMs < prev.hostUntil;
125
- const low = ramFree < thresholds.enterAvailablePercent || commit > thresholds.enterCommitPercent || pcLow;
126
- const recovered = ramFree > thresholds.exitAvailablePercent && commit < thresholds.exitCommitPercent && !pcLow;
127
- let pressure = prev.pressure;
128
- let calm = prev.calm;
129
- let samples = prev.samples;
130
- if (low) {
131
- pressure = true;
132
- calm = 0;
133
- samples = prev.samples + 1;
134
- }
135
- else if (prev.pressure) {
136
- calm = recovered ? prev.calm + 1 : 0;
137
- if (calm >= thresholds.calmSamples) {
138
- pressure = false;
163
+ const wanted = Math.max(stepFor(ramFree, commit, secondsToLimit, profile), pcLow ? prev.hostStep : 0);
164
+ let step = prev.step;
165
+ let calm = 0;
166
+ if (wanted > prev.step)
167
+ step = wanted;
168
+ else if (prev.step > 0 && wanted < prev.step && clearOf(prev.step, ramFree, commit, profile)) {
169
+ calm = prev.calm + 1;
170
+ if (calm >= DIAL_CALM_SAMPLES) {
171
+ step = prev.step - 1;
139
172
  calm = 0;
140
- samples = 0;
141
173
  }
142
174
  }
143
175
  const actions = [];
144
176
  const present = new Set(sample.procs.map((p) => p.pid));
177
+ const keep = (pids) => pids.filter((pid) => present.has(pid));
145
178
  const lowered = {};
146
179
  for (const [pid, to] of Object.entries(prev.lowered))
147
180
  if (present.has(Number(pid)))
148
181
  lowered[Number(pid)] = to;
149
- if (pressure) {
150
- const target = samples > IDLE_AFTER ? 'idle' : 'below';
151
- for (const p of sample.procs) {
152
- if (!canLower(p.name) || lowered[p.pid] === target)
153
- continue;
154
- // Already as low as asked (or lower): only remember it.
155
- if (p.prio !== target && !(target === 'below' && p.prio === 'idle'))
156
- actions.push({ kind: 'priority', pid: p.pid, name: p.name, to: target });
182
+ const memLow = new Set(keep(prev.memLow));
183
+ const throttled = new Set(keep(prev.throttled));
184
+ const trimmed = new Set(keep(prev.trimmed));
185
+ // CPU priority: where a program rests (normal; compilers below in the gentle profile), below from step 1, idle
186
+ // from step 2. Only changes are sent.
187
+ for (const p of sample.procs) {
188
+ if (!canLower(p.name))
189
+ continue;
190
+ const rest = profile === 'gentle' && canPause(p.name) ? 'below' : 'normal';
191
+ const target = step >= 2 ? 'idle' : step === 1 ? 'below' : rest;
192
+ const was = lowered[p.pid];
193
+ const touched = was !== undefined || target !== 'normal';
194
+ if (touched && was !== target && p.prio !== target)
195
+ actions.push({ kind: 'priority', pid: p.pid, name: p.name, to: target });
196
+ if (target === 'normal')
197
+ delete lowered[p.pid];
198
+ else
157
199
  lowered[p.pid] = target;
158
- }
159
200
  }
160
- else {
161
- for (const p of sample.procs) {
162
- if (!canLower(p.name))
163
- continue;
164
- // Where a program rests when nothing is wrong: compilers below normal in the gentle profile.
165
- const base = profile === 'gentle' && canPause(p.name) ? 'below' : 'normal';
166
- const was = lowered[p.pid];
167
- if (prev.pressure && was !== undefined && was !== base) {
168
- if (p.prio !== base)
169
- actions.push({ kind: 'priority', pid: p.pid, name: p.name, to: base });
170
- if (base === 'normal')
171
- delete lowered[p.pid];
172
- else
173
- lowered[p.pid] = base;
201
+ // Memory priority: low from step 1, so Windows trims the builds' pages before the agents'.
202
+ const lowMemory = step >= 1;
203
+ for (const p of sample.procs) {
204
+ if (!canLower(p.name) || lowMemory === memLow.has(p.pid))
205
+ continue;
206
+ actions.push({ kind: 'memory', pid: p.pid, name: p.name, low: lowMemory });
207
+ if (lowMemory)
208
+ memLow.add(p.pid);
209
+ else
210
+ memLow.delete(p.pid);
211
+ }
212
+ // CPU share of the compilers: they join the throttle job once (from step 2); its cap follows the dial.
213
+ if (step >= 2)
214
+ for (const p of sample.procs)
215
+ if (canPause(p.name) && !throttled.has(p.pid)) {
216
+ actions.push({ kind: 'throttle', pid: p.pid, name: p.name });
217
+ throttled.add(p.pid);
174
218
  }
175
- else if (!prev.pressure && base === 'below' && was === undefined) {
176
- if (p.prio === 'normal')
177
- actions.push({ kind: 'priority', pid: p.pid, name: p.name, to: 'below' });
178
- lowered[p.pid] = 'below';
219
+ const cpuRate = DIAL_CPU_RATE[step] ?? 100;
220
+ if (cpuRate !== prev.cpuRate)
221
+ actions.push({ kind: 'cpu', percent: cpuRate });
222
+ // Turns: of the heavy compilers only so many go on; the rest wait, and who waits changes every ROTATE_MS.
223
+ const heavy = sample.procs.filter((p) => isHeavyCompiler(p.name)).sort((a, b) => a.pid - b.pid);
224
+ let allowed = compilersAllowed(step, heavy.length);
225
+ // The cap is a memory measure: with memory to spare, Windows shares the CPU (the priorities above) and no compiler
226
+ // waits. A waiting rustc also holds cargo's job tokens, which stalls the whole build.
227
+ if (maxCompilers !== null && step >= 2)
228
+ allowed = Math.min(allowed, Math.max(1, maxCompilers));
229
+ if (allowed < heavy.length) {
230
+ const turn = Math.floor(nowMs / ROTATE_MS) % heavy.length;
231
+ const order = [...heavy.slice(turn), ...heavy.slice(0, turn)];
232
+ for (const p of order.slice(allowed)) {
233
+ actions.push({ kind: 'hold', pid: p.pid, name: p.name, ms: HOLD_MS });
234
+ if (step >= 3 && !trimmed.has(p.pid)) {
235
+ actions.push({ kind: 'trim', pid: p.pid, name: p.name });
236
+ trimmed.add(p.pid);
179
237
  }
180
238
  }
239
+ for (const p of order.slice(0, allowed))
240
+ trimmed.delete(p.pid);
181
241
  }
182
- let pausedUntil = prev.pausedUntil;
183
- let nextPauseAt = prev.nextPauseAt;
184
- if (pressure && samples >= PAUSE_AFTER && nowMs >= prev.nextPauseAt && nowMs >= prev.pausedUntil) {
185
- const victim = [...sample.procs]
186
- .filter((p) => canPause(p.name) && p.mb >= PAUSE_MIN_MB)
187
- .sort((a, b) => b.mb - a.mb)[0];
188
- if (victim) {
189
- actions.push({ kind: 'pause', pid: victim.pid, name: victim.name, ms: PAUSE_MS });
190
- pausedUntil = nowMs + PAUSE_MS;
191
- nextPauseAt = pausedUntil + PAUSE_COOLDOWN_MS;
192
- }
193
- }
194
- // Concurrency cap (vGPU profile): the oldest N heavy compilers run, the newer ones wait a few seconds at a time.
195
- if (maxCompilers !== null) {
196
- const heavy = sample.procs
197
- .filter((p) => isHeavyCompiler(p.name) &&
198
- !(nowMs < pausedUntil && actions.some((a) => a.kind === 'pause' && a.pid === p.pid)))
199
- .sort((a, b) => a.pid - b.pid);
200
- for (const p of heavy.slice(Math.max(1, maxCompilers)))
201
- actions.push({ kind: 'hold', pid: p.pid, name: p.name, ms: HOLD_MS });
202
- }
203
- const level = nowMs < pausedUntil ? 'suspending' : pressure ? 'throttled' : 'ok';
242
+ else
243
+ trimmed.clear();
244
+ const level = step >= 3 ? 'suspending' : step >= 1 ? 'throttled' : 'ok';
204
245
  return {
205
- state: { pressure, calm, samples, lowered, pausedUntil, nextPauseAt, hostUntil: prev.hostUntil },
246
+ state: {
247
+ step,
248
+ calm,
249
+ lowered,
250
+ memLow: [...memLow],
251
+ throttled: [...throttled],
252
+ trimmed: [...trimmed],
253
+ cpuRate,
254
+ lastCommitMb: usedMb,
255
+ lastAt: nowMs,
256
+ growth,
257
+ hostUntil: prev.hostUntil,
258
+ hostStep: prev.hostStep,
259
+ },
206
260
  actions,
207
261
  level,
208
262
  ramFreePercent: Math.round(ramFree),
@@ -1,45 +1,9 @@
1
- import type { PressureStatus } from '../../shared/channel/schema.js';
2
- import { type LoadProfile } from '../../shared/memory/index.js';
3
- import { type GovernorState, type MemSample } from './decide.js';
4
- /** What the governor needs from Windows (injectable: the tests use a fake). */
5
- export interface GovernorPort {
6
- setPriority(pid: number, to: 'idle' | 'below' | 'normal'): void;
7
- pause(pid: number, ms: number): void;
8
- }
9
- /** Everything a step changes outside the decision, behind injectable functions. */
10
- export interface GovernorDeps {
11
- readonly port: GovernorPort;
12
- readonly profile: LoadProfile;
13
- /** At most this many heavy compilers run at once (null = no cap). */
14
- readonly maxCompilers?: number | null;
15
- readonly now: () => number;
16
- /** A line in the memory log. */
17
- readonly logLine: (line: string) => void;
18
- /** run\pressure.json. */
19
- readonly saveStatus: (status: PressureStatus) => void;
20
- }
21
- /** The governor's logic over a port: feed it samples; the host's "slow down" requests go to hostPressure. */
22
- export declare class GovernorCore {
23
- private readonly deps;
24
- private state;
25
- private lastAction;
26
- private lastWrite;
27
- private lastWriteAt;
28
- private pausedName;
29
- private pausedPid;
30
- private held;
31
- constructor(deps: GovernorDeps);
32
- hostPressure(seconds: number, reason: string): void;
33
- get current(): GovernorState;
34
- onSample(sample: MemSample): void;
35
- private apply;
36
- }
37
1
  /** The daemon's governor: on unless sandbox.pressureResponse is off. */
38
2
  export declare class Governor {
39
3
  private core;
40
4
  describe(): string;
41
5
  start(): void;
42
- /** The host's watchdog: this PC is low for a while. */
43
- hostPressure(seconds: number, reason: string): void;
6
+ /** The host's watchdog: this PC is low (or nearly out of memory) for a while. */
7
+ hostPressure(seconds: number, reason: string, level?: 'slow' | 'severe'): void;
44
8
  }
45
9
  export declare const governor: Governor;
@@ -1,22 +1,21 @@
1
- // The memory governor: samples the sandbox's memory every 2 seconds (memgov.exe, sandbox/csharp/MemGov.cs) and, when it
2
- // runs low, slows the heaviest build programs the agents started down and, as a last resort, pauses the biggest
3
- // compiler for a few seconds (decide.ts). What it does goes to the memory log and run\pressure.json, for the host.
1
+ // The memory governor: samples the sandbox's memory every 2 seconds (memgov.exe, sandbox/csharp/MemGov.cs) and turns
2
+ // a dial as it fills: the build programs the agents started get lower priority, lower memory priority, less CPU, and
3
+ // take turns (decide.ts). Builds slow down; nothing fails. What it does goes to the memory log and run\pressure.json.
4
4
  import fs from 'node:fs';
5
5
  import os from 'node:os';
6
6
  import path from 'node:path';
7
7
  import { spawn } from 'node:child_process';
8
8
  import { createInterface } from 'node:readline';
9
9
  import { z } from 'zod';
10
- import { now } from '../../shared/channel/run-dir.js';
11
10
  import { writeJsonAtomic } from '../../shared/io/json.js';
12
- import { GUEST_THRESHOLDS, maxCompilers } from '../../shared/memory/index.js';
11
+ import { DIAL_STEPS, maxCompilers } from '../../shared/memory/index.js';
13
12
  import { ensureCompiled } from '../runtime/csc.js';
14
13
  import { dataDir } from '../runtime/paths.js';
15
14
  import { warn } from '../runtime/log.js';
16
15
  import { run } from '../runtime/paths.js';
17
16
  import { session } from '../runtime/session.js';
18
17
  import { errMsg } from '../../core/util/errors.js';
19
- import { decide, INITIAL_STATE } from './decide.js';
18
+ import { GovernorCore } from './core.js';
20
19
  const SampleSchema = z.object({
21
20
  ramTotalMb: z.number(),
22
21
  ramAvailMb: z.number(),
@@ -31,101 +30,6 @@ const SampleSchema = z.object({
31
30
  }))
32
31
  .max(1024),
33
32
  });
34
- /** The governor's logic over a port: feed it samples; the host's "slow down" requests go to hostPressure. */
35
- export class GovernorCore {
36
- deps;
37
- state = INITIAL_STATE;
38
- lastAction = '';
39
- lastWrite = '';
40
- lastWriteAt = 0;
41
- pausedName = '';
42
- pausedPid = 0;
43
- held = new Set();
44
- constructor(deps) {
45
- this.deps = deps;
46
- }
47
- hostPressure(seconds, reason) {
48
- const until = this.deps.now() + seconds * 1000;
49
- if (until > this.state.hostUntil) {
50
- if (this.state.hostUntil <= this.deps.now())
51
- this.deps.logLine('governor: this PC is low (' + reason + '); slowing builds down');
52
- this.state = { ...this.state, hostUntil: until };
53
- }
54
- }
55
- get current() {
56
- return this.state;
57
- }
58
- onSample(sample) {
59
- const nowMs = this.deps.now();
60
- const before = this.state.pressure;
61
- const seen = new Set(sample.procs.map((p) => p.pid));
62
- for (const pid of this.held)
63
- if (!seen.has(pid))
64
- this.held.delete(pid);
65
- const d = decide(this.state, sample, nowMs, GUEST_THRESHOLDS[this.deps.profile], this.deps.profile, this.deps.maxCompilers ?? null);
66
- this.state = d.state;
67
- for (const action of d.actions)
68
- this.apply(action);
69
- if (d.state.pressure !== before)
70
- this.deps.logLine(d.state.pressure
71
- ? 'governor: memory is low (' +
72
- d.ramFreePercent +
73
- '% RAM free, commit ' +
74
- d.commitPercent +
75
- '% used): slowing builds down'
76
- : 'governor: memory is fine again: builds back to normal');
77
- const paused = nowMs < d.state.pausedUntil && this.pausedPid
78
- ? [{ name: this.pausedName, pid: this.pausedPid, seconds: Math.ceil((d.state.pausedUntil - nowMs) / 1000) }]
79
- : [];
80
- const status = {
81
- level: d.level,
82
- profile: this.deps.profile,
83
- ramFreePercent: Math.max(0, Math.min(100, d.ramFreePercent)),
84
- commitPercent: Math.max(0, Math.min(100, d.commitPercent)),
85
- lowered: Object.keys(d.state.lowered).length,
86
- paused,
87
- pcLow: nowMs < d.state.hostUntil,
88
- lastAction: this.lastAction,
89
- updatedAt: now(),
90
- };
91
- // Written when something changed, else once a minute (the host reads it, never polls it hard).
92
- const shape = JSON.stringify({ ...status, updatedAt: '', paused: paused.map((p) => p.pid) });
93
- if (shape !== this.lastWrite || nowMs - this.lastWriteAt > 60000) {
94
- this.lastWrite = shape;
95
- this.lastWriteAt = nowMs;
96
- this.deps.saveStatus(status);
97
- }
98
- }
99
- apply(action) {
100
- try {
101
- if (action.kind === 'hold') {
102
- this.deps.port.pause(action.pid, action.ms);
103
- if (!this.held.has(action.pid)) {
104
- this.held.add(action.pid);
105
- this.lastAction = 'holding ' + action.name + ' (' + action.pid + ') until another compiler ends';
106
- this.deps.logLine('governor: ' + this.lastAction);
107
- }
108
- return;
109
- }
110
- if (action.kind === 'priority') {
111
- this.deps.port.setPriority(action.pid, action.to);
112
- this.lastAction = action.name + ' (' + action.pid + ') priority ' + action.to;
113
- }
114
- else {
115
- this.deps.port.pause(action.pid, action.ms);
116
- this.pausedName = action.name;
117
- this.pausedPid = action.pid;
118
- this.lastAction = 'paused ' + action.name + ' (' + action.pid + ') for ' + action.ms / 1000 + ' s';
119
- this.deps.logLine('governor: ' + this.lastAction);
120
- return;
121
- }
122
- this.deps.logLine('governor: ' + this.lastAction);
123
- }
124
- catch (e) {
125
- warn('governor: ' + errMsg(e));
126
- }
127
- }
128
- }
129
33
  /** memgov.exe as a child process: samples come out of its stdout, commands go into its stdin. */
130
34
  class MemGovProcess {
131
35
  onSample;
@@ -160,10 +64,25 @@ class MemGovProcess {
160
64
  }
161
65
  }
162
66
  setPriority(pid, to) {
163
- this.child?.stdin?.write('priority ' + pid + ' ' + to + '\n');
67
+ this.send('priority ' + pid + ' ' + to);
68
+ }
69
+ hold(pid, ms) {
70
+ this.send('suspend ' + pid + ' ' + ms);
71
+ }
72
+ setMemoryPriority(pid, low) {
73
+ this.send('memprio ' + pid + ' ' + (low ? 'low' : 'normal'));
74
+ }
75
+ throttle(pid) {
76
+ this.send('throttle ' + pid);
77
+ }
78
+ setCpuRate(percent) {
79
+ this.send('cpurate ' + Math.round(percent));
80
+ }
81
+ trim(pid) {
82
+ this.send('trim ' + pid);
164
83
  }
165
- pause(pid, ms) {
166
- this.child?.stdin?.write('suspend ' + pid + ' ' + ms + '\n');
84
+ send(line) {
85
+ this.child?.stdin?.write(line + '\n');
167
86
  }
168
87
  }
169
88
  /** The newest memory log SandboxTools writes, to add the governor's lines to it. */
@@ -190,15 +109,15 @@ export class Governor {
190
109
  core = null;
191
110
  describe() {
192
111
  const profile = session.loadProfile === 'gentle' ? 'gentle' : 'normal';
193
- const t = GUEST_THRESHOLDS[profile];
112
+ const first = DIAL_STEPS[profile][0];
194
113
  return session.pressureResponse === false
195
114
  ? 'off (sandbox.pressureResponse)'
196
115
  : profile +
197
- ' profile: slows builds down below ' +
198
- t.enterAvailablePercent +
199
- '% free RAM or above ' +
200
- t.enterCommitPercent +
201
- '% commit';
116
+ ' profile: slows builds down from ' +
117
+ first.availablePercent +
118
+ '% free RAM or ' +
119
+ first.commitPercent +
120
+ '% commit, in steps';
202
121
  }
203
122
  start() {
204
123
  if (session.pressureResponse === false)
@@ -211,6 +130,7 @@ export class Governor {
211
130
  maxCompilers: maxCompilers(os.cpus().length, profile),
212
131
  now: () => Date.now(),
213
132
  logLine: appendToMemoryLog,
133
+ warn,
214
134
  saveStatus: (status) => {
215
135
  try {
216
136
  writeJsonAtomic(run.pressureFile, status);
@@ -222,9 +142,9 @@ export class Governor {
222
142
  });
223
143
  proc.start();
224
144
  }
225
- /** The host's watchdog: this PC is low for a while. */
226
- hostPressure(seconds, reason) {
227
- this.core?.hostPressure(seconds, reason);
145
+ /** The host's watchdog: this PC is low (or nearly out of memory) for a while. */
146
+ hostPressure(seconds, reason, level = 'slow') {
147
+ this.core?.hostPressure(seconds, reason, level);
228
148
  }
229
149
  }
230
150
  export const governor = new Governor();
@@ -1,2 +1,3 @@
1
1
  export * from './decide.js';
2
+ export * from './core.js';
2
3
  export * from './governor.js';
@@ -1,2 +1,3 @@
1
1
  export * from './decide.js';
2
+ export * from './core.js';
2
3
  export * from './governor.js';
@@ -1,6 +1,8 @@
1
1
  /** What the agent's manifest says about the LAN. */
2
2
  export type LanState = 'blocked' | 'open' | 'offline';
3
3
  export declare function networkProblems(): readonly string[];
4
+ /** netsh needs the long form of a path: the sandbox's TEMP is an 8.3 short path (WDAGUT~1). */
5
+ export declare function longPath(file: string): string;
4
6
  export declare function run(commands: string[][]): void;
5
7
  /**
6
8
  * Applies the LAN block. Internet is checked first; if it works before the rules but not after, the rules (not the
@@ -56,16 +56,16 @@ export function networkProblems() {
56
56
  return problems;
57
57
  }
58
58
  /** netsh needs the long form of a path: the sandbox's TEMP is an 8.3 short path (WDAGUT~1). */
59
- const longPath = (file) => {
59
+ export function longPath(file) {
60
60
  if (!hasShortName(file))
61
61
  return file;
62
62
  try {
63
63
  return fs.realpathSync.native(file);
64
64
  }
65
65
  catch {
66
- return file;
66
+ return file; // netsh then says the program cannot be found, which is reported where the rule was wanted
67
67
  }
68
- };
68
+ }
69
69
  /**
70
70
  * The inbound rule for ptyhost (the attach channel). A rule that cannot be added is a missing protection, so it is
71
71
  * tried again a few times and then reported loudly instead of being skipped.
@@ -1,5 +1,6 @@
1
1
  import { connect, runTerminalClient } from '../../shared/pty/index.js';
2
2
  import { run } from '../runtime/paths.js';
3
+ import { session as sandboxSession } from '../runtime/session.js';
3
4
  /**
4
5
  * A session that is still being set up (its project provisioning, its agent installing): show the progress until it
5
6
  * runs.
@@ -32,7 +33,10 @@ export async function viewSession(id) {
32
33
  const socket = await connect({ ...session.attach, addresses: ['127.0.0.1'] });
33
34
  // The sandbox's own terminal: a copy in the agent reaches the sandbox's clipboard (and yours only through
34
35
  // sandbox.clipboard, which already shares it).
35
- const result = await runTerminalClient(socket, session.attach.token, { clipboardWrites: true });
36
+ const result = await runTerminalClient(socket, session.attach.token, {
37
+ clipboardWrites: true,
38
+ confirmCtrlC: sandboxSession.attach.confirmCtrlC !== false,
39
+ });
36
40
  if (result.reason === 'exit')
37
41
  console.log(session.harness + ' exited with code ' + result.exitCode + '.');
38
42
  else if (result.reason === 'error')
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Before the tools are set up: the folder gh uses for a handed-over token exists only when one arrived (gh's setup
3
+ * points GH_CONFIG_DIR at it while it exists). Without one, gh keeps the login you made in the sandbox.
4
+ */
5
+ export declare function prepareGithubFolder(token: string | undefined): boolean;
6
+ /** gh logs in with the token (stdin) in the sandbox-only folder, then https git to github.com asks gh. */
7
+ export declare function loginGithub(token: string, env: NodeJS.ProcessEnv): void;
@@ -0,0 +1,65 @@
1
+ // The GitHub token the host handed over (github.shareToken, only with git access "full"): gh logs in with it in a
2
+ // folder on the sandbox's own disk (gone with the sandbox, never in the persistent state), and https git asks gh. The
3
+ // token goes to gh on stdin, never in an argument, a file of ours or a log line.
4
+ import fs from 'node:fs';
5
+ import { spawnSync } from 'node:child_process';
6
+ import { ghLoginCommand, ghOutputText, ghSetupGitCommand } from '../../shared/github/index.js';
7
+ import { deliveredGhConfigDir, ghConfigDir, ghExePath } from '../toolchains/tools/cli.js';
8
+ import { addMachineEnvironment } from './environment.js';
9
+ import { dryRun } from '../runtime/paths.js';
10
+ import { exists, mkdirp } from '../runtime/fs.js';
11
+ import { log } from '../runtime/log.js';
12
+ const GH_TIMEOUT_MS = 60_000;
13
+ /**
14
+ * Before the tools are set up: the folder gh uses for a handed-over token exists only when one arrived (gh's setup
15
+ * points GH_CONFIG_DIR at it while it exists). Without one, gh keeps the login you made in the sandbox.
16
+ */
17
+ export function prepareGithubFolder(token) {
18
+ const dir = deliveredGhConfigDir();
19
+ fs.rmSync(dir, { recursive: true, force: true });
20
+ if (!token)
21
+ return false;
22
+ mkdirp(dir);
23
+ return true;
24
+ }
25
+ function runGh(command, token, what) {
26
+ const result = spawnSync(command.file, [...command.args], {
27
+ env: command.env,
28
+ encoding: 'utf8',
29
+ windowsHide: true,
30
+ timeout: GH_TIMEOUT_MS,
31
+ stdio: ['pipe', 'pipe', 'pipe'],
32
+ ...(command.input !== undefined ? { input: command.input } : {}),
33
+ });
34
+ if (result.error)
35
+ throw new Error(what + ' could not run: ' + ghOutputText(result.error.message, token));
36
+ if (result.status !== 0)
37
+ throw new Error(what + ' failed: ' + ghOutputText(String(result.stderr ?? '') || String(result.stdout ?? ''), token));
38
+ }
39
+ /** gh logs in with the token (stdin) in the sandbox-only folder, then https git to github.com asks gh. */
40
+ export function loginGithub(token, env) {
41
+ if (dryRun) {
42
+ log('(dry run) would log gh in with the GitHub token from your PC');
43
+ return;
44
+ }
45
+ const gh = ghExePath();
46
+ const dir = deliveredGhConfigDir();
47
+ if (!exists(gh) || env.GH_CONFIG_DIR !== dir) {
48
+ // Gone again, so gh set up later (a project added afterwards) keeps the login you make in the sandbox.
49
+ fs.rmSync(dir, { recursive: true, force: true });
50
+ log('A GitHub token arrived, but gh is not set up in this sandbox (toolchains.cli.gh), so it is not used.');
51
+ return;
52
+ }
53
+ try {
54
+ runGh(ghLoginCommand(gh, dir, token, env), token, 'gh auth login');
55
+ runGh(ghSetupGitCommand(gh, dir, env), token, 'gh auth setup-git');
56
+ }
57
+ catch (e) {
58
+ // gh goes back to the persistent folder (and a `gh auth login` you make inside is kept), for every session.
59
+ fs.rmSync(dir, { recursive: true, force: true });
60
+ env.GH_CONFIG_DIR = mkdirp(ghConfigDir());
61
+ addMachineEnvironment({ GH_CONFIG_DIR: env.GH_CONFIG_DIR }, []);
62
+ throw e;
63
+ }
64
+ log('gh and https git to github.com use the GitHub token from your PC (github.shareToken); the agent can read it.');
65
+ }