windows-development-sandbox 1.9.0 → 1.11.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (398) hide show
  1. package/README.md +64 -17
  2. package/config.example.json +7 -2
  3. package/dist/app/features/accounts/accounts.def.d.ts +122 -0
  4. package/dist/app/features/accounts/accounts.def.js +243 -0
  5. package/dist/app/features/accounts/accounts.run.d.ts +51 -0
  6. package/dist/app/features/accounts/accounts.run.js +125 -0
  7. package/dist/app/features/accounts/index.d.ts +2 -0
  8. package/dist/app/features/accounts/index.js +3 -0
  9. package/dist/app/features/agents/agent-entry.d.ts +17 -0
  10. package/dist/app/features/agents/agent-entry.js +50 -0
  11. package/dist/app/features/agents/agents.def.d.ts +65 -0
  12. package/dist/app/features/agents/agents.def.js +142 -0
  13. package/dist/app/features/agents/agents.run.d.ts +31 -0
  14. package/dist/app/features/agents/agents.run.js +189 -0
  15. package/dist/app/features/agents/index.d.ts +3 -0
  16. package/dist/app/features/agents/index.js +4 -0
  17. package/dist/app/features/apps/apps-rows.d.ts +31 -0
  18. package/dist/app/features/apps/apps-rows.js +73 -0
  19. package/dist/app/features/apps/apps.def.d.ts +181 -0
  20. package/dist/app/features/apps/apps.def.js +264 -0
  21. package/dist/app/features/apps/apps.run.d.ts +58 -0
  22. package/dist/app/features/apps/apps.run.js +76 -0
  23. package/dist/app/features/apps/index.d.ts +3 -0
  24. package/dist/app/features/apps/index.js +4 -0
  25. package/dist/app/features/data/data.def.d.ts +154 -0
  26. package/dist/app/features/data/data.def.js +201 -0
  27. package/dist/app/features/data/data.run.d.ts +46 -0
  28. package/dist/app/features/data/data.run.js +141 -0
  29. package/dist/app/features/data/index.d.ts +2 -0
  30. package/dist/app/features/data/index.js +3 -0
  31. package/dist/app/features/defs.d.ts +952 -4
  32. package/dist/app/features/defs.js +147 -10
  33. package/dist/app/features/engine/engine.def.d.ts +228 -0
  34. package/dist/app/features/engine/engine.def.js +194 -0
  35. package/dist/app/features/engine/engine.run.d.ts +72 -0
  36. package/dist/app/features/engine/engine.run.js +77 -0
  37. package/dist/app/features/engine/index.d.ts +2 -0
  38. package/dist/app/features/engine/index.js +4 -0
  39. package/dist/app/features/files/files.def.d.ts +51 -0
  40. package/dist/app/features/files/files.def.js +38 -0
  41. package/dist/app/features/files/files.run.d.ts +20 -0
  42. package/dist/app/features/files/files.run.js +59 -0
  43. package/dist/app/features/files/index.d.ts +2 -0
  44. package/dist/app/features/files/index.js +3 -0
  45. package/dist/app/features/github/github.def.d.ts +80 -0
  46. package/dist/app/features/github/github.def.js +142 -0
  47. package/dist/app/features/github/github.run.d.ts +36 -0
  48. package/dist/app/features/github/github.run.js +59 -0
  49. package/dist/app/features/github/index.d.ts +2 -0
  50. package/dist/app/features/github/index.js +3 -0
  51. package/dist/app/features/health/health.def.d.ts +275 -0
  52. package/dist/app/features/health/health.def.js +281 -0
  53. package/dist/app/features/health/health.run.d.ts +125 -0
  54. package/dist/app/features/health/health.run.js +204 -0
  55. package/dist/app/features/health/index.d.ts +2 -0
  56. package/dist/app/features/health/index.js +3 -0
  57. package/dist/app/features/logs/index.d.ts +2 -0
  58. package/dist/app/features/logs/index.js +3 -0
  59. package/dist/app/features/logs/logs.def.d.ts +78 -0
  60. package/dist/app/features/logs/logs.def.js +115 -0
  61. package/dist/app/features/logs/logs.run.d.ts +20 -0
  62. package/dist/app/features/logs/logs.run.js +42 -0
  63. package/dist/app/features/projects/index.d.ts +2 -0
  64. package/dist/app/features/projects/index.js +3 -0
  65. package/dist/app/features/projects/projects.def.d.ts +101 -0
  66. package/dist/app/features/projects/projects.def.js +208 -0
  67. package/dist/app/features/projects/projects.run.d.ts +56 -0
  68. package/dist/app/features/projects/projects.run.js +155 -0
  69. package/dist/app/features/sandbox/sandbox.def.js +11 -5
  70. package/dist/app/features/sessions/sessions.def.js +3 -0
  71. package/dist/app/features/settings/categories.def.js +3 -2
  72. package/dist/{cli/menu/settings/share.d.ts → app/features/settings/settings-share.d.ts} +1 -1
  73. package/dist/{cli/menu/settings/share.js → app/features/settings/settings-share.js} +3 -2
  74. package/dist/app/features/settings/settings.def.d.ts +22 -5
  75. package/dist/app/features/settings/settings.def.js +81 -6
  76. package/dist/app/features/settings/settings.run.d.ts +17 -0
  77. package/dist/app/features/settings/settings.run.js +89 -4
  78. package/dist/app/features/storage/index.d.ts +2 -0
  79. package/dist/app/features/storage/index.js +3 -0
  80. package/dist/app/features/storage/storage.def.d.ts +133 -0
  81. package/dist/app/features/storage/storage.def.js +225 -0
  82. package/dist/app/features/storage/storage.run.d.ts +62 -0
  83. package/dist/app/features/storage/storage.run.js +370 -0
  84. package/dist/app/features/updates/index.d.ts +3 -0
  85. package/dist/app/features/updates/index.js +4 -0
  86. package/dist/app/features/updates/update-lines.d.ts +13 -0
  87. package/dist/app/features/updates/update-lines.js +61 -0
  88. package/dist/app/features/updates/updates.def.d.ts +89 -0
  89. package/dist/app/features/updates/updates.def.js +225 -0
  90. package/dist/app/features/updates/updates.run.d.ts +48 -0
  91. package/dist/app/features/updates/updates.run.js +154 -0
  92. package/dist/app/features/vpn/index.d.ts +2 -0
  93. package/dist/app/features/vpn/index.js +3 -0
  94. package/dist/app/features/vpn/vpn.def.d.ts +112 -0
  95. package/dist/app/features/vpn/vpn.def.js +174 -0
  96. package/dist/app/features/vpn/vpn.run.d.ts +37 -0
  97. package/dist/app/features/vpn/vpn.run.js +54 -0
  98. package/dist/app/features/web/index.d.ts +2 -0
  99. package/dist/app/features/web/index.js +3 -0
  100. package/dist/app/features/web/web.def.d.ts +33 -0
  101. package/dist/app/features/web/web.def.js +90 -0
  102. package/dist/app/features/web/web.run.d.ts +24 -0
  103. package/dist/app/features/web/web.run.js +93 -0
  104. package/dist/app/kernel/define.d.ts +10 -1
  105. package/dist/app/kernel/io.d.ts +34 -0
  106. package/dist/app/kernel/io.js +9 -0
  107. package/dist/app/kernel/rpc.d.ts +17 -0
  108. package/dist/app/kernel/text.d.ts +2 -0
  109. package/dist/app/kernel/text.js +7 -0
  110. package/dist/app/kernel/view.d.ts +24 -1
  111. package/dist/app/kernel/view.js +1 -1
  112. package/dist/app/registry.js +74 -1
  113. package/dist/cli/args.js +1 -1
  114. package/dist/cli/commands/context.d.ts +7 -0
  115. package/dist/cli/commands/context.js +29 -2
  116. package/dist/cli/commands/engine.js +5 -58
  117. package/dist/cli/commands/github.d.ts +2 -0
  118. package/dist/cli/commands/github.js +11 -0
  119. package/dist/cli/commands/index.d.ts +3 -5
  120. package/dist/cli/commands/index.js +3 -5
  121. package/dist/cli/commands/launch/launch.js +23 -4
  122. package/dist/cli/commands/launch/running.js +4 -1
  123. package/dist/cli/commands/maintenance/config.js +1 -6
  124. package/dist/cli/commands/maintenance/index.d.ts +0 -1
  125. package/dist/cli/commands/maintenance/index.js +1 -2
  126. package/dist/cli/commands/maintenance/logs.js +27 -32
  127. package/dist/cli/commands/maintenance/migrate.d.ts +0 -8
  128. package/dist/cli/commands/maintenance/migrate.js +2 -44
  129. package/dist/cli/commands/maintenance/update.d.ts +0 -19
  130. package/dist/cli/commands/maintenance/update.js +1 -99
  131. package/dist/cli/commands/projects/index.d.ts +0 -1
  132. package/dist/cli/commands/projects/index.js +0 -1
  133. package/dist/cli/commands/registry.d.ts +1 -1
  134. package/dist/cli/commands/registry.js +29 -11
  135. package/dist/cli/commands/repair/checks/data.js +1 -1
  136. package/dist/cli/commands/repair/checks/hcs.js +28 -1
  137. package/dist/cli/commands/repair/checks/sandbox.js +1 -1
  138. package/dist/cli/commands/repair/health-run.d.ts +30 -0
  139. package/dist/cli/commands/repair/health-run.js +32 -0
  140. package/dist/cli/commands/repair/printer.d.ts +2 -2
  141. package/dist/cli/commands/repair/printer.js +2 -11
  142. package/dist/cli/commands/repair/run.d.ts +1 -21
  143. package/dist/cli/commands/repair/run.js +13 -70
  144. package/dist/cli/commands/storage/index.d.ts +0 -1
  145. package/dist/cli/commands/storage/index.js +0 -1
  146. package/dist/cli/commands/storage/offer.js +6 -2
  147. package/dist/cli/commands/vpn.d.ts +1 -3
  148. package/dist/cli/commands/vpn.js +8 -88
  149. package/dist/cli/commands/web.d.ts +7 -1
  150. package/dist/cli/commands/web.js +45 -71
  151. package/dist/cli/index.js +3 -2
  152. package/dist/cli/manifest.d.ts +16 -153
  153. package/dist/cli/manifest.js +20 -50
  154. package/dist/cli/menu/command-form.js +1 -2
  155. package/dist/cli/menu/io-menu.d.ts +2 -2
  156. package/dist/cli/menu/io-menu.js +6 -4
  157. package/dist/cli/menu/menu.js +1 -1
  158. package/dist/cli/menu/pages/accounts-page.d.ts +5 -17
  159. package/dist/cli/menu/pages/accounts-page.js +28 -170
  160. package/dist/cli/menu/pages/agents-page.d.ts +17 -18
  161. package/dist/cli/menu/pages/agents-page.js +67 -124
  162. package/dist/cli/menu/pages/apps-page.d.ts +15 -8
  163. package/dist/cli/menu/pages/apps-page.js +121 -29
  164. package/dist/cli/menu/pages/list-page.js +10 -1
  165. package/dist/cli/menu/pages/maintenance-page.d.ts +51 -52
  166. package/dist/cli/menu/pages/maintenance-page.js +246 -427
  167. package/dist/cli/menu/pages/sandbox-page.d.ts +3 -5
  168. package/dist/cli/menu/pages/sandbox-page.js +34 -112
  169. package/dist/cli/menu/pages/settings-page.d.ts +21 -3
  170. package/dist/cli/menu/pages/settings-page.js +89 -17
  171. package/dist/cli/menu/render-view.js +2 -1
  172. package/dist/cli/menu/settings/index.d.ts +0 -1
  173. package/dist/cli/menu/settings/index.js +3 -3
  174. package/dist/cli/menu/views.js +28 -0
  175. package/dist/cli/operations/handler.js +7 -3
  176. package/dist/cli/operations/input.d.ts +1 -1
  177. package/dist/cli/operations/input.js +29 -5
  178. package/dist/cli/operations/io-cli.js +9 -1
  179. package/dist/cli/operations/spec.js +8 -2
  180. package/dist/cli/output/render-view.js +2 -0
  181. package/dist/cli/{commands/data/collect.js → services/data-collect.js} +2 -2
  182. package/dist/cli/{commands/data/remove.js → services/data-remove.js} +2 -2
  183. package/dist/cli/services/data-service.d.ts +1 -1
  184. package/dist/cli/services/data-service.js +2 -2
  185. package/dist/cli/services/databases-service.d.ts +5 -0
  186. package/dist/cli/services/databases-service.js +15 -0
  187. package/dist/cli/services/health-service.d.ts +8 -4
  188. package/dist/cli/services/health-service.js +10 -8
  189. package/dist/cli/services/index.d.ts +4 -1
  190. package/dist/cli/services/index.js +4 -1
  191. package/dist/cli/services/logs-service.d.ts +7 -0
  192. package/dist/cli/services/logs-service.js +13 -0
  193. package/dist/cli/services/storage-service.d.ts +19 -0
  194. package/dist/cli/services/storage-service.js +71 -0
  195. package/dist/cli/services/vpn-service.d.ts +6 -4
  196. package/dist/cli/services/vpn-service.js +5 -11
  197. package/dist/cli/services/web-service.d.ts +4 -3
  198. package/dist/cli/services/web-service.js +12 -32
  199. package/dist/core/config/defaults.js +3 -2
  200. package/dist/core/schema/config.d.ts +6 -0
  201. package/dist/core/schema/config.js +2 -0
  202. package/dist/core/schema/github.d.ts +4 -0
  203. package/dist/core/schema/github.js +7 -0
  204. package/dist/core/schema/index.d.ts +1 -0
  205. package/dist/core/schema/index.js +1 -0
  206. package/dist/core/schema/profile.d.ts +1 -0
  207. package/dist/core/schema/profile.js +3 -0
  208. package/dist/core/schema/sandbox.js +3 -3
  209. package/dist/core/schema/toolchains.js +2 -2
  210. package/dist/core/schema/vpn.js +1 -1
  211. package/dist/core/schema/web.d.ts +1 -0
  212. package/dist/core/schema/web.js +4 -1
  213. package/dist/core/types.d.ts +6 -3
  214. package/dist/guest/boot/boot.js +11 -1
  215. package/dist/guest/daemon/daemon.js +1 -1
  216. package/dist/guest/daemon/sessions.d.ts +3 -2
  217. package/dist/guest/daemon/sessions.js +38 -7
  218. package/dist/guest/governor/core.d.ts +44 -0
  219. package/dist/guest/governor/core.js +124 -0
  220. package/dist/guest/governor/decide.d.ts +53 -15
  221. package/dist/guest/governor/decide.js +155 -72
  222. package/dist/guest/governor/governor.d.ts +2 -35
  223. package/dist/guest/governor/governor.js +35 -99
  224. package/dist/guest/governor/index.d.ts +1 -0
  225. package/dist/guest/governor/index.js +1 -0
  226. package/dist/guest/network/firewall.d.ts +3 -0
  227. package/dist/guest/network/firewall.js +65 -23
  228. package/dist/guest/runtime/process.js +53 -5
  229. package/dist/guest/sessions/viewer.js +5 -1
  230. package/dist/guest/setup/claude-mem.js +12 -4
  231. package/dist/guest/setup/github-token.d.ts +7 -0
  232. package/dist/guest/setup/github-token.js +65 -0
  233. package/dist/guest/toolchains/languages/node.js +40 -4
  234. package/dist/guest/toolchains/native/rust-extras.js +2 -2
  235. package/dist/guest/toolchains/tools/cli.d.ts +8 -0
  236. package/dist/guest/toolchains/tools/cli.js +16 -2
  237. package/dist/guest/vpn/openvpn.d.ts +5 -0
  238. package/dist/guest/vpn/openvpn.js +14 -1
  239. package/dist/guest/vpn/vpn.js +55 -16
  240. package/dist/guest/vpn/wireguard.js +2 -0
  241. package/dist/host/channel/attach.d.ts +1 -0
  242. package/dist/host/channel/attach.js +1 -0
  243. package/dist/host/channel/channel.d.ts +1 -1
  244. package/dist/host/channel/channel.js +2 -2
  245. package/dist/host/engines/hcs/check.d.ts +1 -0
  246. package/dist/host/engines/hcs/check.js +1 -1
  247. package/dist/host/engines/hcs/engine.d.ts +1 -1
  248. package/dist/host/engines/hcs/engine.js +6 -4
  249. package/dist/host/engines/hcs/helper.d.ts +11 -0
  250. package/dist/host/engines/hcs/helper.js +31 -2
  251. package/dist/host/engines/hcs/leftovers.d.ts +42 -0
  252. package/dist/host/engines/hcs/leftovers.js +101 -0
  253. package/dist/host/engines/index.d.ts +1 -0
  254. package/dist/host/engines/index.js +1 -0
  255. package/dist/host/github/deliver.d.ts +13 -0
  256. package/dist/host/github/deliver.js +51 -0
  257. package/dist/host/github/index.d.ts +2 -0
  258. package/dist/host/github/index.js +3 -0
  259. package/dist/host/github/token.d.ts +21 -0
  260. package/dist/host/github/token.js +74 -0
  261. package/dist/host/launch/generate.js +11 -5
  262. package/dist/host/launch/index.d.ts +1 -1
  263. package/dist/host/launch/index.js +1 -1
  264. package/dist/host/launch/session-file.js +1 -2
  265. package/dist/host/launch/wsb-file.d.ts +11 -7
  266. package/dist/host/launch/wsb-file.js +30 -12
  267. package/dist/host/life/host-memory.d.ts +1 -0
  268. package/dist/host/life/host-memory.js +4 -1
  269. package/dist/host/life/watchdog.d.ts +11 -0
  270. package/dist/host/life/watchdog.js +36 -4
  271. package/dist/host/sandbox/tasklist.d.ts +6 -0
  272. package/dist/host/sandbox/tasklist.js +37 -0
  273. package/dist/host/secrets/launch-secrets.d.ts +2 -1
  274. package/dist/host/secrets/launch-secrets.js +4 -2
  275. package/dist/host/vpn/status.js +13 -3
  276. package/dist/host/web/backend.d.ts +1 -3
  277. package/dist/host/web/index.d.ts +2 -1
  278. package/dist/host/web/index.js +2 -1
  279. package/dist/host/web/live.d.ts +23 -0
  280. package/dist/host/web/live.js +107 -0
  281. package/dist/host/web/rpc.d.ts +6 -1
  282. package/dist/host/web/rpc.js +23 -31
  283. package/dist/host/web/runner.d.ts +4 -0
  284. package/dist/host/web/runner.js +12 -1
  285. package/dist/host/web/server.d.ts +30 -2
  286. package/dist/host/web/server.js +87 -29
  287. package/dist/host/web/state.d.ts +1 -0
  288. package/dist/host/web/state.js +2 -0
  289. package/dist/runtime/agent.js +44 -16
  290. package/dist/runtime/daemon.js +1154 -857
  291. package/dist/runtime/db.js +44 -16
  292. package/dist/runtime/main.js +532 -115
  293. package/dist/runtime/netproxy.js +34 -9
  294. package/dist/runtime/view.js +499 -149
  295. package/dist/selftest/app.test.js +620 -12
  296. package/dist/selftest/channel.test.js +18 -1
  297. package/dist/selftest/cli.test.js +1 -1
  298. package/dist/selftest/config.test.js +1 -1
  299. package/dist/selftest/contained.test.js +1 -1
  300. package/dist/selftest/data.test.js +1 -2
  301. package/dist/selftest/engine.test.js +3 -1
  302. package/dist/selftest/github.test.d.ts +2 -0
  303. package/dist/selftest/github.test.js +243 -0
  304. package/dist/selftest/guest-boot.test.js +47 -1
  305. package/dist/selftest/hcs.test.js +105 -8
  306. package/dist/selftest/health.test.js +71 -0
  307. package/dist/selftest/heavy-load.test.js +152 -66
  308. package/dist/selftest/index.js +4 -0
  309. package/dist/selftest/layout.test.js +8 -0
  310. package/dist/selftest/live-terminal.test.js +74 -0
  311. package/dist/selftest/menu-screens.js +171 -56
  312. package/dist/selftest/menu.test.js +54 -37
  313. package/dist/selftest/migrate.test.js +14 -12
  314. package/dist/selftest/network.test.js +20 -1
  315. package/dist/selftest/powershell-variables.test.d.ts +2 -0
  316. package/dist/selftest/powershell-variables.test.js +61 -0
  317. package/dist/selftest/support/engine-golden.js +1 -0
  318. package/dist/selftest/support/fixtures.d.ts +5 -0
  319. package/dist/selftest/support/web-preview.d.ts +1 -0
  320. package/dist/selftest/support/web-preview.js +856 -0
  321. package/dist/selftest/update-service.test.js +15 -8
  322. package/dist/selftest/vpn.test.js +86 -2
  323. package/dist/selftest/web.test.js +58 -11
  324. package/dist/shared/channel/run-dir.d.ts +2 -0
  325. package/dist/shared/channel/run-dir.js +3 -0
  326. package/dist/shared/channel/schema.d.ts +7 -0
  327. package/dist/shared/channel/schema.js +9 -1
  328. package/dist/shared/channel/secrets.d.ts +1 -0
  329. package/dist/shared/channel/secrets.js +3 -0
  330. package/dist/shared/github/index.d.ts +1 -0
  331. package/dist/shared/github/index.js +2 -0
  332. package/dist/shared/github/token.d.ts +29 -0
  333. package/dist/shared/github/token.js +89 -0
  334. package/dist/shared/io/copy-tree.d.ts +7 -0
  335. package/dist/shared/io/copy-tree.js +45 -0
  336. package/dist/shared/io/index.d.ts +2 -0
  337. package/dist/shared/io/index.js +2 -0
  338. package/dist/shared/io/robocopy-result.d.ts +6 -0
  339. package/dist/shared/io/robocopy-result.js +23 -0
  340. package/dist/shared/memory/policy.d.ts +38 -12
  341. package/dist/shared/memory/policy.js +58 -19
  342. package/dist/shared/network/firewall-rules.d.ts +8 -0
  343. package/dist/shared/network/firewall-rules.js +28 -0
  344. package/dist/shared/pty/ctrl-c.d.ts +18 -0
  345. package/dist/shared/pty/ctrl-c.js +36 -0
  346. package/dist/shared/pty/index.d.ts +1 -0
  347. package/dist/shared/pty/index.js +1 -0
  348. package/dist/shared/pty/terminal.d.ts +2 -0
  349. package/dist/shared/pty/terminal.js +21 -2
  350. package/dist/shared/vpn/kill-switch.d.ts +13 -2
  351. package/dist/shared/vpn/kill-switch.js +88 -8
  352. package/dist/shared/web/protocol.d.ts +0 -4
  353. package/dist/sync/watcher.js +1 -1
  354. package/dist/web/index.html +2 -2
  355. package/dist/web/{main-T5DMCHYV.css → main-6JF3ASB5.css} +1 -1
  356. package/dist/web/main-Z645W45E.js +219 -0
  357. package/native/csharp/HcsHost/AssemblyInfo.cs +3 -3
  358. package/native/csharp/HostTools/AssemblyInfo.cs +3 -3
  359. package/native/csharp/HostTools/MemoryStatus.cs +128 -107
  360. package/native/scripts/memory-status.ps1 +10 -2
  361. package/package.json +10 -3
  362. package/sandbox/csharp/MemGov.cs +668 -398
  363. package/sandbox/csharp/PtyHost.cs +104 -15
  364. package/sandbox/csharp/SandboxTools/CpuCap.cs +50 -1
  365. package/sandbox/csharp/SandboxTools/Program.cs +1 -1
  366. package/sandbox/scripts/new-shortcuts.ps1 +3 -1
  367. package/sandbox/scripts/repair-wmi-services.ps1 +26 -0
  368. package/schemas/config.schema.json +25 -7
  369. package/schemas/sandbox-config.schema.json +7 -3
  370. package/dist/cli/commands/accounts.d.ts +0 -2
  371. package/dist/cli/commands/accounts.js +0 -96
  372. package/dist/cli/commands/data/clean.d.ts +0 -3
  373. package/dist/cli/commands/data/clean.js +0 -60
  374. package/dist/cli/commands/data/index.d.ts +0 -4
  375. package/dist/cli/commands/data/index.js +0 -62
  376. package/dist/cli/commands/maintenance/clean.d.ts +0 -2
  377. package/dist/cli/commands/maintenance/clean.js +0 -24
  378. package/dist/cli/commands/maintenance/config-share.d.ts +0 -12
  379. package/dist/cli/commands/maintenance/config-share.js +0 -80
  380. package/dist/cli/commands/projects/projects.d.ts +0 -2
  381. package/dist/cli/commands/projects/projects.js +0 -162
  382. package/dist/cli/commands/storage/contained.d.ts +0 -3
  383. package/dist/cli/commands/storage/contained.js +0 -179
  384. package/dist/cli/commands/storage/storage.d.ts +0 -8
  385. package/dist/cli/commands/storage/storage.js +0 -179
  386. package/dist/cli/menu/add-agent.d.ts +0 -47
  387. package/dist/cli/menu/add-agent.js +0 -168
  388. package/dist/cli/menu/apps.d.ts +0 -69
  389. package/dist/cli/menu/apps.js +0 -214
  390. package/dist/cli/menu/data-folder.d.ts +0 -18
  391. package/dist/cli/menu/data-folder.js +0 -99
  392. package/dist/cli/menu/share-settings.d.ts +0 -21
  393. package/dist/cli/menu/share-settings.js +0 -112
  394. package/dist/cli/menu/vpn-login.d.ts +0 -16
  395. package/dist/cli/menu/vpn-login.js +0 -74
  396. package/dist/web/main-NRRS5O6Z.js +0 -157
  397. /package/dist/cli/{commands/data/collect.d.ts → services/data-collect.d.ts} +0 -0
  398. /package/dist/cli/{commands/data/remove.d.ts → services/data-remove.d.ts} +0 -0
@@ -9,7 +9,7 @@ import { fail, UserError } from '../../../core/util/index.js';
9
9
  import { selfTestRunning } from '../../test-guard.js';
10
10
  import { checkHcs, realHcsProbes } from './check.js';
11
11
  import { buildDocuments, HCS_OWNER } from './documents.js';
12
- import { HcsHelper, hcsHostExe } from './helper.js';
12
+ import { HcsHelper, hcsHostExe, isMySystemId, userSystemPrefix } from './helper.js';
13
13
  import { findImage } from './images.js';
14
14
  export const HCS_CAPABILITIES = {
15
15
  desktop: false,
@@ -76,7 +76,7 @@ export class HcsEngine {
76
76
  const docs = buildDocuments({
77
77
  launch,
78
78
  image: this.image,
79
- id: 'agent-sandbox-' + slug,
79
+ id: userSystemPrefix() + slug,
80
80
  scratchVhdx,
81
81
  hostCpus: (this.deps.hostCpus ?? (() => os.cpus().length))(),
82
82
  });
@@ -147,10 +147,12 @@ export class HcsEngine {
147
147
  throw e; // a system that is already gone is fine
148
148
  }
149
149
  }
150
- /** Ours: the compute systems the helper lists with our owner name. */
150
+ /** Ours: the compute systems the helper lists with our owner name and this Windows user's id prefix. */
151
151
  ours(helper) {
152
152
  const parsed = SystemListSchema.safeParse(JSON.parse(helper.enumerate().json || '[]'));
153
- return parsed.success ? parsed.data.filter((s) => s.Owner === HCS_OWNER).map((s) => s.Id) : [];
153
+ return parsed.success
154
+ ? parsed.data.filter((s) => s.Owner === HCS_OWNER && isMySystemId(s.Id)).map((s) => s.Id)
155
+ : [];
154
156
  }
155
157
  running() {
156
158
  try {
@@ -1,4 +1,13 @@
1
1
  import { z } from 'zod';
2
+ /** Whether an id has the shape of the ones this tool gives its compute systems. */
3
+ export declare function isOurSystemId(id: string): boolean;
4
+ /**
5
+ * The start of the ids this Windows user's sandboxes get: the Owner is the same for everyone, so on a PC shared with
6
+ * other users this tag is what keeps one user from listing or stopping another's compute systems.
7
+ */
8
+ export declare function userSystemPrefix(user?: string, domain?: string): string;
9
+ /** One of this tool's ids, given by this Windows user. */
10
+ export declare function isMySystemId(id: string): boolean;
2
11
  export declare const HcsReplySchema: z.ZodObject<{
3
12
  ok: z.ZodBoolean;
4
13
  hresult: z.ZodString;
@@ -16,6 +25,8 @@ export type HelperRunner = (exe: string, args: readonly string[], timeoutMs: num
16
25
  export declare const spawnRunner: HelperRunner;
17
26
  /** Compiles the helper's sources to `exe` with the .NET Framework csc (C# 5). False when it cannot be built. */
18
27
  export declare function buildHcsHostTo(exe: string): boolean;
28
+ /** HcsHost.exe when it was built already (never builds it): a PC that never used HCS has none. */
29
+ export declare function builtHcsHostExe(storageRoot: string): string | null;
19
30
  /**
20
31
  * <storage>\bin\hcs\<hash of its sources>\HcsHost.exe, built the first time. Its own folder: HostTools' cleanup of old
21
32
  * builds only touches twelve-digit hash folders directly in bin. Null when it cannot be built.
@@ -15,6 +15,26 @@ const MAX_RESPONSE_BYTES = 2 * 1024 * 1024;
15
15
  const CALL_TIMEOUT_MS = 240000;
16
16
  /** Only ids this tool gives its compute systems (HcsHost.exe refuses any other, and checks the Owner too). */
17
17
  const SAFE_ID = /^agent-sandbox-[A-Za-z0-9._-]{1,100}$/;
18
+ /** Whether an id has the shape of the ones this tool gives its compute systems. */
19
+ export function isOurSystemId(id) {
20
+ return SAFE_ID.test(id);
21
+ }
22
+ /**
23
+ * The start of the ids this Windows user's sandboxes get: the Owner is the same for everyone, so on a PC shared with
24
+ * other users this tag is what keeps one user from listing or stopping another's compute systems.
25
+ */
26
+ export function userSystemPrefix(user = os.userInfo().username, domain = process.env.USERDOMAIN ?? '') {
27
+ const tag = crypto
28
+ .createHash('sha256')
29
+ .update((domain + '\\' + user).toLowerCase())
30
+ .digest('hex')
31
+ .slice(0, 8);
32
+ return 'agent-sandbox-' + tag + '-';
33
+ }
34
+ /** One of this tool's ids, given by this Windows user. */
35
+ export function isMySystemId(id) {
36
+ return isOurSystemId(id) && id.startsWith(userSystemPrefix());
37
+ }
18
38
  export const HcsReplySchema = z.object({
19
39
  ok: z.boolean(),
20
40
  hresult: z.string().max(16),
@@ -51,12 +71,22 @@ export function buildHcsHostTo(exe) {
51
71
  const r = spawnSync(SYSTEM.csc(), ['/nologo', '/optimize', '/target:exe', '/r:System.Web.Extensions.dll', '/out:' + exe, ...sources], { windowsHide: true, timeout: 120000 });
52
72
  return r.status === 0 && fs.existsSync(exe);
53
73
  }
74
+ /** HcsHost.exe when it was built already (never builds it): a PC that never used HCS has none. */
75
+ export function builtHcsHostExe(storageRoot) {
76
+ const exe = hcsHostPath(storageRoot);
77
+ return exe && fs.existsSync(exe) ? exe : null;
78
+ }
54
79
  /**
55
80
  * <storage>\bin\hcs\<hash of its sources>\HcsHost.exe, built the first time. Its own folder: HostTools' cleanup of old
56
81
  * builds only touches twelve-digit hash folders directly in bin. Null when it cannot be built.
57
82
  */
58
83
  export function hcsHostExe(storageRoot) {
59
84
  refuseInSelfTest('build HcsHost.exe');
85
+ const exe = hcsHostPath(storageRoot);
86
+ return exe && (fs.existsSync(exe) || buildHcsHostTo(exe)) ? exe : null;
87
+ }
88
+ /** Where HcsHost.exe is (or would be built): named by the hash of its sources. Null without the sources. */
89
+ function hcsHostPath(storageRoot) {
60
90
  const dir = nativeFile('csharp', 'HcsHost');
61
91
  const hash = crypto.createHash('sha256');
62
92
  try {
@@ -69,8 +99,7 @@ export function hcsHostExe(storageRoot) {
69
99
  catch {
70
100
  return null; // no sources
71
101
  }
72
- const exe = path.join(storageRoot, 'bin', 'hcs', hash.digest('hex').slice(0, 12), 'HcsHost.exe');
73
- return fs.existsSync(exe) || buildHcsHostTo(exe) ? exe : null;
102
+ return path.join(storageRoot, 'bin', 'hcs', hash.digest('hex').slice(0, 12), 'HcsHost.exe');
74
103
  }
75
104
  /** A path argument: absolute, not an option. Nothing else reaches the helper's command line. */
76
105
  function pathArg(value, what) {
@@ -0,0 +1,42 @@
1
+ import { type HcsProbes } from './check.js';
2
+ import { HcsHelper } from './helper.js';
3
+ export interface LeftoverSystem {
4
+ readonly id: string;
5
+ /** Container or VirtualMachine (the utility VM). */
6
+ readonly kind: string;
7
+ readonly state: string;
8
+ /** When it was created (ISO text), when HCS says. */
9
+ readonly since: string | null;
10
+ }
11
+ export type LeftoverLook = {
12
+ readonly available: true;
13
+ readonly systems: readonly LeftoverSystem[];
14
+ } | {
15
+ readonly available: false;
16
+ readonly reason: string;
17
+ };
18
+ export interface LeftoverOutcome {
19
+ readonly id: string;
20
+ readonly stopped: boolean;
21
+ /** Why not, in plain words. */
22
+ readonly problem?: string;
23
+ }
24
+ /** What the look runs on: replaceable by tests (probes of a pretend PC, a fake helper). */
25
+ export interface LeftoverDeps {
26
+ readonly probes: HcsProbes;
27
+ /** The helper, or null when HcsHost.exe was never built (then nothing of ours can be running). Never builds it. */
28
+ helper(storageRoot: string): HcsHelper | null;
29
+ }
30
+ export declare const LEFTOVER_DEPS: {
31
+ current: LeftoverDeps | null;
32
+ };
33
+ /**
34
+ * The compute systems of ours that exist now. Never builds HcsHost.exe: a PC that never used HCS has none, and
35
+ * nothing of ours can be running there.
36
+ */
37
+ export declare function lookForLeftovers(storageRoot: string): LeftoverLook;
38
+ /**
39
+ * Stops the named systems, containers before the utility VM that hosts them. Each id is looked up again first: one that
40
+ * is not one of ours (or is gone) never reaches the helper; the helper checks the Owner with HCS itself once more.
41
+ */
42
+ export declare function stopLeftovers(storageRoot: string, ids: readonly string[]): LeftoverOutcome[];
@@ -0,0 +1,101 @@
1
+ // HCS compute systems this tool left running (a crashed command: they are created to outlive their handle). Only
2
+ // systems with our id prefix AND our Owner are ever listed or stopped; HcsHost.exe checks both again before it
3
+ // terminates one. Nothing here runs unless the PC has the Host Compute Service.
4
+ import path from 'node:path';
5
+ import { z } from 'zod';
6
+ import { errMsg, fail } from '../../../core/util/index.js';
7
+ import { realHcsProbes, system32Dir } from './check.js';
8
+ import { HCS_OWNER } from './documents.js';
9
+ import { HcsHelper, builtHcsHostExe, isMySystemId } from './helper.js';
10
+ export const LEFTOVER_DEPS = { current: null };
11
+ function realDeps() {
12
+ return {
13
+ probes: realHcsProbes(),
14
+ helper: (root) => {
15
+ const exe = builtHcsHostExe(root);
16
+ return exe ? new HcsHelper(() => exe) : null;
17
+ },
18
+ };
19
+ }
20
+ const SystemListSchema = z.array(z
21
+ .object({
22
+ Id: z.string().max(300),
23
+ SystemType: z.string().max(100).optional(),
24
+ Owner: z.string().max(300).optional(),
25
+ State: z.string().max(100).optional(),
26
+ CreateTimestamp: z.string().max(100).optional(),
27
+ })
28
+ .passthrough());
29
+ /** The reason HCS cannot be there at all, or null. Looks only (service list, one file). */
30
+ function noHcsReason(p) {
31
+ if (!p.isWindows())
32
+ return 'HCS only exists on Windows.';
33
+ if (!p.fileExists(path.join(system32Dir(), 'computecore.dll')) || p.serviceInstalled('vmcompute') === false)
34
+ return 'The Host Compute Service is not on this PC.';
35
+ return null;
36
+ }
37
+ /** Ours only: the id has our prefix and the system names us as its Owner. Anything else is never shown or touched. */
38
+ function ownedSystems(helper) {
39
+ let list;
40
+ try {
41
+ list = JSON.parse(helper.enumerate().json || '[]');
42
+ }
43
+ catch (e) {
44
+ if (e instanceof SyntaxError)
45
+ return fail('The Host Compute Service answered with something that is not JSON.');
46
+ throw e;
47
+ }
48
+ const parsed = SystemListSchema.safeParse(list);
49
+ if (!parsed.success)
50
+ return [];
51
+ return parsed.data
52
+ .filter((s) => s.Owner === HCS_OWNER && isMySystemId(s.Id))
53
+ .map((s) => ({
54
+ id: s.Id,
55
+ kind: s.SystemType ?? 'unknown',
56
+ state: s.State ?? 'unknown',
57
+ since: s.CreateTimestamp && !Number.isNaN(Date.parse(s.CreateTimestamp)) ? s.CreateTimestamp : null,
58
+ }));
59
+ }
60
+ /**
61
+ * The compute systems of ours that exist now. Never builds HcsHost.exe: a PC that never used HCS has none, and
62
+ * nothing of ours can be running there.
63
+ */
64
+ export function lookForLeftovers(storageRoot) {
65
+ const deps = LEFTOVER_DEPS.current ?? realDeps();
66
+ const none = noHcsReason(deps.probes);
67
+ if (none)
68
+ return { available: false, reason: none };
69
+ try {
70
+ const helper = deps.helper(storageRoot);
71
+ if (!helper)
72
+ return { available: true, systems: [] };
73
+ return { available: true, systems: ownedSystems(helper) };
74
+ }
75
+ catch (e) {
76
+ return { available: false, reason: 'The Host Compute Service could not be asked: ' + errMsg(e) };
77
+ }
78
+ }
79
+ /**
80
+ * Stops the named systems, containers before the utility VM that hosts them. Each id is looked up again first: one that
81
+ * is not one of ours (or is gone) never reaches the helper; the helper checks the Owner with HCS itself once more.
82
+ */
83
+ export function stopLeftovers(storageRoot, ids) {
84
+ const deps = LEFTOVER_DEPS.current ?? realDeps();
85
+ const helper = deps.helper(storageRoot);
86
+ if (!helper)
87
+ return ids.map((id) => ({ id, stopped: false, problem: 'HcsHost.exe is not available.' }));
88
+ const now = ownedSystems(helper);
89
+ const wanted = [...ids].sort((a, b) => Number(b.endsWith('-c')) - Number(a.endsWith('-c')));
90
+ return wanted.map((id) => {
91
+ if (!now.some((s) => s.id === id))
92
+ return { id, stopped: false, problem: 'it is gone, or it is not one of ours' };
93
+ try {
94
+ helper.terminate(id);
95
+ return { id, stopped: true };
96
+ }
97
+ catch (e) {
98
+ return { id, stopped: false, problem: errMsg(e) };
99
+ }
100
+ });
101
+ }
@@ -5,3 +5,4 @@ export { WindowsSandboxEngine } from './windows-sandbox/engine.js';
5
5
  export { wsbText } from './windows-sandbox/wsb-text.js';
6
6
  export { HcsEngine, HCS_CAPABILITIES, hcsStartEnabled } from './hcs/engine.js';
7
7
  export { checkHcs, realHcsProbes, type HcsProbes } from './hcs/check.js';
8
+ export { lookForLeftovers, stopLeftovers, LEFTOVER_DEPS, type LeftoverDeps, type LeftoverLook, type LeftoverOutcome, type LeftoverSystem, } from './hcs/leftovers.js';
@@ -3,3 +3,4 @@ export { WindowsSandboxEngine } from './windows-sandbox/engine.js';
3
3
  export { wsbText } from './windows-sandbox/wsb-text.js';
4
4
  export { HcsEngine, HCS_CAPABILITIES, hcsStartEnabled } from './hcs/engine.js';
5
5
  export { checkHcs, realHcsProbes } from './hcs/check.js';
6
+ export { lookForLeftovers, stopLeftovers, LEFTOVER_DEPS, } from './hcs/leftovers.js';
@@ -0,0 +1,13 @@
1
+ import type { BootWant } from '../../core/local-config/index.js';
2
+ import type { Config } from '../../core/types.js';
3
+ import { GithubToken } from './token.js';
4
+ /** github.shareToken is on and git access is "full" for every project this sandbox boots with. */
5
+ export declare function githubTokenAllowed(config: Config, others?: readonly BootWant[]): boolean;
6
+ export interface GithubDelivery {
7
+ /** The token for the one-shot secrets file, when it is handed over. */
8
+ readonly token?: string;
9
+ /** What to tell you about it (never the token). */
10
+ readonly notes: readonly string[];
11
+ }
12
+ /** What this launch hands over. Never throws: a token that cannot be read is a note, and the launch goes on. */
13
+ export declare function prepareGithubToken(config: Config, storageRoot: string, store?: GithubToken, others?: readonly BootWant[]): GithubDelivery;
@@ -0,0 +1,51 @@
1
+ import { GithubToken } from './token.js';
2
+ /** The first project (the launch's own, then the others at boot) whose git access is not "full", or null. */
3
+ function stricterProject(config, others) {
4
+ if (config.provisioning.git.access !== 'full')
5
+ return { name: '', access: config.provisioning.git.access };
6
+ const other = others.find((o) => o.config.provisioning.git.access !== 'full');
7
+ return other ? { name: other.name, access: other.config.provisioning.git.access } : null;
8
+ }
9
+ /** github.shareToken is on and git access is "full" for every project this sandbox boots with. */
10
+ export function githubTokenAllowed(config, others = []) {
11
+ return config.github.shareToken && stricterProject(config, others) === null;
12
+ }
13
+ /** What this launch hands over. Never throws: a token that cannot be read is a note, and the launch goes on. */
14
+ export function prepareGithubToken(config, storageRoot, store, others = []) {
15
+ if (!config.github.shareToken)
16
+ return { notes: [] };
17
+ const stricter = stricterProject(config, others);
18
+ if (stricter)
19
+ return {
20
+ notes: [
21
+ 'github.shareToken is on, but git access is "' +
22
+ stricter.access +
23
+ '"' +
24
+ (stricter.name ? ' for ' + stricter.name + ' (also in this sandbox)' : ' in this sandbox') +
25
+ ', so your GitHub token was not handed over (it needs provisioning.git.access "full").',
26
+ ],
27
+ };
28
+ const tokens = store ?? new GithubToken(storageRoot);
29
+ let token;
30
+ try {
31
+ token = tokens.read();
32
+ }
33
+ catch {
34
+ // The reason may come from DPAPI or a damaged file; a fixed text is enough (and can never hold the token).
35
+ return {
36
+ notes: [
37
+ 'Your saved GitHub token could not be read (only the Windows user that saved it can), so it was not handed over. Save it again: sandbox github login',
38
+ ],
39
+ };
40
+ }
41
+ if (!token)
42
+ return {
43
+ notes: ['github.shareToken is on, but no GitHub token is saved. Save one: sandbox github login'],
44
+ };
45
+ return {
46
+ token,
47
+ notes: [
48
+ 'Your GitHub token is handed to this sandbox (github.shareToken): the agent can read it and use it for whatever it allows.',
49
+ ],
50
+ };
51
+ }
@@ -0,0 +1,2 @@
1
+ export { GithubToken, checkGithubToken, type TokenState } from './token.js';
2
+ export { githubTokenAllowed, prepareGithubToken, type GithubDelivery } from './deliver.js';
@@ -0,0 +1,3 @@
1
+ // The GitHub token for sandboxes: its encrypted store and whether a launch hands it over.
2
+ export { GithubToken, checkGithubToken } from './token.js';
3
+ export { githubTokenAllowed, prepareGithubToken } from './deliver.js';
@@ -0,0 +1,21 @@
1
+ import { type GithubTokenKind } from '../../shared/github/index.js';
2
+ import { SecretStore } from '../secrets/index.js';
3
+ /** What the status may say about the token: never its value. */
4
+ export type TokenState = 'none' | 'saved' | 'unreadable';
5
+ /** The token's kind, or a refusal that says what to do (the message never holds what was typed). */
6
+ export declare function checkGithubToken(token: string): GithubTokenKind;
7
+ export declare class GithubToken {
8
+ private readonly storageRoot;
9
+ private readonly secrets;
10
+ constructor(storageRoot: string, secrets?: SecretStore);
11
+ private file;
12
+ /** Checks, encrypts and saves the token (replacing an earlier one). Returns its kind. */
13
+ save(token: string): GithubTokenKind;
14
+ /** The token, decrypted. Only the launch calls this; throws when this Windows user cannot open it. */
15
+ read(): string | null;
16
+ /** Whether a token is saved and can be decrypted by this Windows user (the value is never returned). */
17
+ state(): TokenState;
18
+ savedAt(): string | null;
19
+ kind(): GithubTokenKind | null;
20
+ remove(): boolean;
21
+ }
@@ -0,0 +1,74 @@
1
+ // The GitHub token you saved for sandboxes (github.shareToken), kept encrypted with Windows DPAPI in host-only storage
2
+ // (<storage>\github\token.json). It is read only when a sandbox starts, to hand to the sandbox in a one-shot file, and
3
+ // is never printed, logged or returned to a surface: they only learn its state, kind and when it was saved.
4
+ import fs from 'node:fs';
5
+ import path from 'node:path';
6
+ import { z } from 'zod';
7
+ import { JsonFile } from '../../shared/io/index.js';
8
+ import { GITHUB_TOKEN_KINDS, GithubTokenSchema, githubTokenKind, githubTokenProblem, } from '../../shared/github/index.js';
9
+ import { fail } from '../../core/util/index.js';
10
+ import { SecretStore } from '../secrets/index.js';
11
+ const SavedSchema = z.object({
12
+ savedAt: z.string().max(64),
13
+ kind: z.enum(GITHUB_TOKEN_KINDS),
14
+ sealed: z.string().max(10000),
15
+ });
16
+ /** The token's kind, or a refusal that says what to do (the message never holds what was typed). */
17
+ export function checkGithubToken(token) {
18
+ const problem = githubTokenProblem(token);
19
+ if (problem)
20
+ fail(problem.message, problem.fix);
21
+ return githubTokenKind(token) ?? fail('That is not a GitHub personal access token.', 'Run: sandbox github login');
22
+ }
23
+ export class GithubToken {
24
+ storageRoot;
25
+ secrets;
26
+ constructor(storageRoot, secrets = SecretStore.standard()) {
27
+ this.storageRoot = storageRoot;
28
+ this.secrets = secrets;
29
+ }
30
+ file() {
31
+ return new JsonFile(SavedSchema, path.join(this.storageRoot, 'github', 'token.json'));
32
+ }
33
+ /** Checks, encrypts and saves the token (replacing an earlier one). Returns its kind. */
34
+ save(token) {
35
+ const kind = checkGithubToken(token);
36
+ this.file().write({ savedAt: new Date().toISOString(), kind, sealed: this.secrets.sealJson({ token }) });
37
+ return kind;
38
+ }
39
+ /** The token, decrypted. Only the launch calls this; throws when this Windows user cannot open it. */
40
+ read() {
41
+ const saved = this.file().read();
42
+ if (!saved)
43
+ return null;
44
+ const value = this.secrets.openJson(saved.sealed);
45
+ const token = GithubTokenSchema.safeParse(value?.token);
46
+ if (!token.success)
47
+ fail('The saved GitHub token is damaged.', 'Save it again with: sandbox github login');
48
+ return token.data;
49
+ }
50
+ /** Whether a token is saved and can be decrypted by this Windows user (the value is never returned). */
51
+ state() {
52
+ if (!this.file().read())
53
+ return 'none';
54
+ try {
55
+ return this.read() ? 'saved' : 'none';
56
+ }
57
+ catch {
58
+ return 'unreadable';
59
+ }
60
+ }
61
+ savedAt() {
62
+ return this.file().read()?.savedAt ?? null;
63
+ }
64
+ kind() {
65
+ return this.file().read()?.kind ?? null;
66
+ }
67
+ remove() {
68
+ const file = this.file().file;
69
+ if (!fs.existsSync(file))
70
+ return false;
71
+ fs.rmSync(file, { force: true });
72
+ return true;
73
+ }
74
+ }
@@ -9,6 +9,7 @@ import { dirExists, ensureDir, fail, writeJson } from '../../core/util/index.js'
9
9
  import { engineFor } from '../engines/index.js';
10
10
  import { capturePersonalization, stageClaudeProfile } from '../profile/index.js';
11
11
  import { clearSecrets, writeSecrets } from '../secrets/index.js';
12
+ import { githubTokenAllowed } from '../github/index.js';
12
13
  import { folderAttachment } from '../storage/providers/index.js';
13
14
  import { assertTestWritable } from '../test-guard.js';
14
15
  import { writeLoadSettings } from '../life/watchdog.js';
@@ -20,7 +21,7 @@ import { guestSession, logonEnv } from './session-file.js';
20
21
  import { copyRuntime, stageGitIdentity, stageHooks } from './stage.js';
21
22
  import { decideProjectToolchains } from './toolchains.js';
22
23
  import { buildLaunchPlan } from './launch-plan.js';
23
- import { decideMemory, GUEST, memoryNote, resolveMemoryMb } from './wsb-file.js';
24
+ import { cappedMemoryMb, decideMemory, GUEST, memoryNote, residentNote, resolveMemoryMb } from './wsb-file.js';
24
25
  const NO_PROFILE = { hostDir: null, staged: [], skipped: [], credentials: false, secretsRemoved: [] };
25
26
  /** Moves the staged copy of this PC's Claude login out of the launch folder; its text goes in the one-shot file. */
26
27
  function takeStagedCredentials(launchPath) {
@@ -59,7 +60,9 @@ opened) {
59
60
  assertTestWritable(dataPath);
60
61
  // Checked before anything is written, so a refusal leaves nothing behind.
61
62
  const commitAvailableMb = o.commitAvailableMb ?? null;
62
- const memoryMb = Math.max(resolveMemoryMb(config.sandbox, o.freeMemoryBytes, undefined, commitAvailableMb), ...others.map((p) => (typeof p.config.sandbox.memoryMb === 'number' ? p.config.sandbox.memoryMb : 0)));
63
+ const askedMb = Math.max(resolveMemoryMb(config.sandbox, o.freeMemoryBytes, undefined, commitAvailableMb), ...others.map((p) => (typeof p.config.sandbox.memoryMb === 'number' ? p.config.sandbox.memoryMb : 0)));
64
+ // Never more than this PC can keep in RAM for it, whatever was asked.
65
+ const memoryMb = cappedMemoryMb(askedMb, config.sandbox, Math.floor(os.totalmem() / 1048576));
63
66
  const launchId = Date.now() + '-' + crypto.randomBytes(3).toString('hex');
64
67
  const launchPath = path.join(storageRoot, 'launches', launchId);
65
68
  // Whatever must stay secret goes in a one-shot file in the data folder, never into the launch folder (the sandbox
@@ -104,6 +107,8 @@ opened) {
104
107
  ...(claudeCredentials ? { claudeCredentials } : {}),
105
108
  ...(o.vpn?.credentials ? { vpn: o.vpn.credentials } : {}),
106
109
  ...(o.vpn?.wireguardConfig ? { wireguardConfig: o.vpn.wireguardConfig } : {}),
110
+ // Checked again on the configs the sandbox boots with: never when a project in it has git access below "full".
111
+ ...(o.githubToken && githubTokenAllowed(config, others) ? { githubToken: o.githubToken } : {}),
107
112
  });
108
113
  fs.writeFileSync(path.join(launchPath, 'env.cmd'), logonEnv(session.workspace), 'utf8');
109
114
  copyRuntime(o.packageRoot, launchPath);
@@ -127,9 +132,10 @@ opened) {
127
132
  launchId,
128
133
  sessionPath,
129
134
  memoryMb,
130
- memoryNote: config.sandbox.memoryMb === 'auto'
131
- ? memoryNote(decideMemory(config.sandbox, Math.floor((o.freeMemoryBytes ?? os.freemem()) / 1048576), Math.floor(os.totalmem() / 1048576), commitAvailableMb))
132
- : null,
135
+ memoryNote: residentNote(askedMb, memoryMb) ??
136
+ (config.sandbox.memoryMb === 'auto'
137
+ ? memoryNote(decideMemory(config.sandbox, Math.floor((o.freeMemoryBytes ?? os.freemem()) / 1048576), Math.floor(os.totalmem() / 1048576), commitAvailableMb))
138
+ : null),
133
139
  bootConfig: config,
134
140
  widened: wide.widened,
135
141
  mappings,
@@ -1,7 +1,7 @@
1
1
  export { generateSandbox } from './generate.js';
2
2
  export { decideProjectToolchains } from './toolchains.js';
3
3
  export { hostToolsOf, logonEnv } from './session-file.js';
4
- export { agentMemoryLimitMb, decideMemory, GUEST, memoryNote, resolveMemoryMb } from './wsb-file.js';
4
+ export { cappedMemoryMb, decideMemory, GUEST, memoryNote, residentCapMb, residentNote, resolveMemoryMb, } from './wsb-file.js';
5
5
  export { GENTLE_NOTE, vgpuSource, vgpuWarning } from './risk-notes.js';
6
6
  export { buildLaunchPlan, buildWsb } from './launch-plan.js';
7
7
  export { MAX_BOOT_PROJECTS, planBootProjects, shownByRoot, type BootProjects } from './boot-projects.js';
@@ -1,7 +1,7 @@
1
1
  export { generateSandbox } from './generate.js';
2
2
  export { decideProjectToolchains } from './toolchains.js';
3
3
  export { hostToolsOf, logonEnv } from './session-file.js';
4
- export { agentMemoryLimitMb, decideMemory, GUEST, memoryNote, resolveMemoryMb } from './wsb-file.js';
4
+ export { cappedMemoryMb, decideMemory, GUEST, memoryNote, residentCapMb, residentNote, resolveMemoryMb, } from './wsb-file.js';
5
5
  export { GENTLE_NOTE, vgpuSource, vgpuWarning } from './risk-notes.js';
6
6
  export { buildLaunchPlan, buildWsb } from './launch-plan.js';
7
7
  export { MAX_BOOT_PROJECTS, planBootProjects, shownByRoot } from './boot-projects.js';
@@ -5,7 +5,6 @@ import { resolveToolchains } from '../../core/detect/index.js';
5
5
  import { hubName, PROJECTS_GUEST, substDrives } from '../../shared/paths/index.js';
6
6
  import { hostClaudeDir } from '../profile/index.js';
7
7
  import { databaseCatalog } from './database-plan.js';
8
- import { agentMemoryLimitMb } from './wsb-file.js';
9
8
  import { effectiveCpuLimit } from '../../shared/memory/index.js';
10
9
  import { loadProfileOf } from './risk-notes.js';
11
10
  /** What was found on this PC to copy instead of download. */
@@ -65,7 +64,7 @@ export function guestSession(o, parts) {
65
64
  cpuLimitPercent: effectiveCpuLimit(config.sandbox.cpuLimit, loadProfileOf(config)),
66
65
  loadProfile: loadProfileOf(config),
67
66
  pageFileMb: config.sandbox.pageFileMb,
68
- agentMemoryLimitMb: agentMemoryLimitMb(parts.memoryMb, config.sandbox.agentMemoryHeadroomMb),
67
+ agentBackstop: config.sandbox.agentMemoryHeadroomMb,
69
68
  pressureResponse: config.sandbox.pressureResponse,
70
69
  apps: config.apps,
71
70
  auditProcesses: config.audit.enabled && config.audit.processes,
@@ -6,7 +6,7 @@ export declare const GUEST: {
6
6
  readonly mirror: "C:\\Mirror";
7
7
  };
8
8
  type SandboxSettings = Config['sandbox'];
9
- export type MemoryLimit = 'free' | 'share' | 'max' | 'commit';
9
+ export type MemoryLimit = 'free' | 'share' | 'max' | 'commit' | 'resident';
10
10
  export interface MemoryDecision {
11
11
  readonly mb: number;
12
12
  /** What set the size. */
@@ -17,18 +17,22 @@ export interface MemoryDecision {
17
17
  readonly freeMb: number;
18
18
  readonly commitAvailableMb: number | null;
19
19
  }
20
+ /**
21
+ * The most memory this PC can keep in RAM for the sandbox (pure): its RAM minus max(reserveHostMb, 25 %), and 2 GB
22
+ * more with vGPU. Windows Sandbox's memory is this PC's memory taken as needed; beyond what the PC can keep resident it
23
+ * is paged to this PC's disk while the sandbox pages to its own, and that is what can freeze the whole PC.
24
+ */
25
+ export declare function residentCapMb(sandbox: SandboxSettings, totalMb: number): number;
26
+ /** A fixed memoryMb above what this PC can keep resident is lowered to that (never below 4 GB). */
27
+ export declare function cappedMemoryMb(memoryMb: number, sandbox: SandboxSettings, totalMb: number): number;
28
+ /** The launch note when a fixed memoryMb was lowered. */
29
+ export declare function residentNote(asked: number, given: number): string | null;
20
30
  /**
21
31
  * "auto" (pure): free RAM minus the reserve, never more than maxMemoryMb or maxMemoryPercent of the PC's total RAM,
22
32
  * and, when the PC's available commit (RAM plus paging file, what the sandbox's memory is charged against) is known,
23
33
  * never more than that minus the reserve either.
24
34
  */
25
35
  export declare function decideMemory(sandbox: SandboxSettings, freeMb: number, totalMb: number, commitAvailableMb: number | null): MemoryDecision;
26
- /**
27
- * The most memory everything the agents start may use together (pure): the sandbox's memory minus the headroom
28
- * ("auto" =
29
- * the larger of 2048 MB and 10 %), at least half of it so a tiny sandbox still works; null = no limit ("none").
30
- */
31
- export declare function agentMemoryLimitMb(memoryMb: number, headroom: SandboxSettings['agentMemoryHeadroomMb']): number | null;
32
36
  /** A plain-words note when the commit made the sandbox's memory much smaller (2 GB or more) than free RAM allowed. */
33
37
  export declare function memoryNote(decision: MemoryDecision): string | null;
34
38
  /** "auto": see decideMemory. commitAvailableMb: from HostTools memory-status (omitted = not checked). */
@@ -11,6 +11,34 @@ export const GUEST = {
11
11
  const MB = 1048576;
12
12
  const MIN_AUTO_MEMORY_MB = 4096;
13
13
  const roundDown = (mb) => Math.floor(mb / 1024) * 1024;
14
+ /** GPU-PV (vGPU) needs room of its own on this PC: memory the graphics driver pins for the sandbox. */
15
+ const VGPU_RESERVE_MB = 2048;
16
+ /**
17
+ * The most memory this PC can keep in RAM for the sandbox (pure): its RAM minus max(reserveHostMb, 25 %), and 2 GB
18
+ * more with vGPU. Windows Sandbox's memory is this PC's memory taken as needed; beyond what the PC can keep resident it
19
+ * is paged to this PC's disk while the sandbox pages to its own, and that is what can freeze the whole PC.
20
+ */
21
+ export function residentCapMb(sandbox, totalMb) {
22
+ const keep = Math.max(sandbox.reserveHostMb, Math.floor(totalMb / 4)) + (sandbox.vGpu ? VGPU_RESERVE_MB : 0);
23
+ return roundDown(totalMb - keep);
24
+ }
25
+ /** A fixed memoryMb above what this PC can keep resident is lowered to that (never below 4 GB). */
26
+ export function cappedMemoryMb(memoryMb, sandbox, totalMb) {
27
+ const cap = residentCapMb(sandbox, totalMb);
28
+ return cap >= MIN_AUTO_MEMORY_MB && memoryMb > cap ? cap : memoryMb;
29
+ }
30
+ /** The launch note when a fixed memoryMb was lowered. */
31
+ export function residentNote(asked, given) {
32
+ if (given >= asked)
33
+ return null;
34
+ return ('sandbox.memoryMb asks for ' +
35
+ asked +
36
+ ' MB; this PC can keep ' +
37
+ given +
38
+ ' MB in RAM for the sandbox (its RAM minus what it needs itself), so the sandbox gets ' +
39
+ given +
40
+ " MB. More would be paged to this PC's disk, which can freeze the whole PC.");
41
+ }
14
42
  /**
15
43
  * "auto" (pure): free RAM minus the reserve, never more than maxMemoryMb or maxMemoryPercent of the PC's total RAM,
16
44
  * and, when the PC's available commit (RAM plus paging file, what the sandbox's memory is charged against) is known,
@@ -25,22 +53,12 @@ export function decideMemory(sandbox, freeMb, totalMb, commitAvailableMb) {
25
53
  ['share', shareMb],
26
54
  ['free', byFree],
27
55
  ['commit', byCommit],
56
+ ['resident', residentCapMb(sandbox, totalMb)],
28
57
  ];
29
58
  const lowest = candidates.reduce((a, b) => (b[1] < a[1] ? b : a));
30
- const withoutCommit = roundDown(Math.min(sandbox.maxMemoryMb, shareMb, byFree));
59
+ const withoutCommit = roundDown(Math.min(sandbox.maxMemoryMb, shareMb, byFree, residentCapMb(sandbox, totalMb)));
31
60
  return { mb: roundDown(lowest[1]), limitedBy: lowest[0], withoutCommitMb: withoutCommit, freeMb, commitAvailableMb };
32
61
  }
33
- /**
34
- * The most memory everything the agents start may use together (pure): the sandbox's memory minus the headroom
35
- * ("auto" =
36
- * the larger of 2048 MB and 10 %), at least half of it so a tiny sandbox still works; null = no limit ("none").
37
- */
38
- export function agentMemoryLimitMb(memoryMb, headroom) {
39
- if (headroom === 'none')
40
- return null;
41
- const keep = headroom === 'auto' ? Math.max(2048, Math.floor(memoryMb / 10)) : headroom;
42
- return Math.max(Math.floor(memoryMb / 2), memoryMb - keep);
43
- }
44
62
  /** A plain-words note when the commit made the sandbox's memory much smaller (2 GB or more) than free RAM allowed. */
45
63
  export function memoryNote(decision) {
46
64
  if (decision.limitedBy !== 'commit' || decision.withoutCommitMb - decision.mb < 2048)
@@ -10,6 +10,7 @@ export declare const HostMemorySchema: z.ZodObject<{
10
10
  fixed: "fixed";
11
11
  }>>;
12
12
  pageFileMaxMb: z.ZodCatch<z.ZodNumber>;
13
+ diskQueue: z.ZodCatch<z.ZodOptional<z.ZodNumber>>;
13
14
  }, z.core.$strip>;
14
15
  export type HostMemory = z.output<typeof HostMemorySchema>;
15
16
  /** The parsed answer of memory-status, or null (not Windows, unreadable, nonsense). */