windows-development-sandbox 1.5.0 → 1.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (709) hide show
  1. package/README.md +1 -0
  2. package/config.example.json +27 -1
  3. package/dist/app/context.d.ts +8 -0
  4. package/dist/app/context.js +12 -0
  5. package/dist/app/features/defs.d.ts +322 -0
  6. package/dist/app/features/defs.js +28 -0
  7. package/dist/app/features/sandbox/index.d.ts +2 -0
  8. package/dist/app/features/sandbox/index.js +3 -0
  9. package/dist/app/features/sandbox/sandbox.def.d.ts +193 -0
  10. package/dist/app/features/sandbox/sandbox.def.js +245 -0
  11. package/dist/app/features/sandbox/sandbox.run.d.ts +72 -0
  12. package/dist/app/features/sandbox/sandbox.run.js +98 -0
  13. package/dist/app/features/sessions/index.d.ts +2 -0
  14. package/dist/app/features/sessions/index.js +3 -0
  15. package/dist/app/features/sessions/sessions.def.d.ts +141 -0
  16. package/dist/app/features/sessions/sessions.def.js +176 -0
  17. package/dist/app/features/sessions/sessions.run.d.ts +39 -0
  18. package/dist/app/features/sessions/sessions.run.js +58 -0
  19. package/dist/{cli/menu/settings/categories.d.ts → app/features/settings/categories.def.d.ts} +4 -0
  20. package/dist/{cli/menu/settings/categories.js → app/features/settings/categories.def.js} +40 -46
  21. package/dist/app/features/settings/index.d.ts +5 -0
  22. package/dist/app/features/settings/index.js +6 -0
  23. package/dist/{cli/menu/settings/config-file.d.ts → app/features/settings/settings-file.d.ts} +1 -1
  24. package/dist/{cli/menu/settings/config-file.js → app/features/settings/settings-file.js} +1 -1
  25. package/dist/app/features/settings/settings-rows.d.ts +35 -0
  26. package/dist/app/features/settings/settings-rows.js +94 -0
  27. package/dist/app/features/settings/settings.def.d.ts +157 -0
  28. package/dist/app/features/settings/settings.def.js +179 -0
  29. package/dist/app/features/settings/settings.run.d.ts +67 -0
  30. package/dist/app/features/settings/settings.run.js +84 -0
  31. package/dist/app/kernel/define.d.ts +143 -0
  32. package/dist/app/kernel/define.js +42 -0
  33. package/dist/app/kernel/errors.d.ts +34 -0
  34. package/dist/app/kernel/errors.js +45 -0
  35. package/dist/app/kernel/fields.d.ts +70 -0
  36. package/dist/app/kernel/fields.js +243 -0
  37. package/dist/app/kernel/index.d.ts +8 -0
  38. package/dist/app/kernel/index.js +10 -0
  39. package/dist/app/kernel/io.d.ts +193 -0
  40. package/dist/app/kernel/io.js +126 -0
  41. package/dist/app/kernel/rpc.d.ts +156 -0
  42. package/dist/app/kernel/rpc.js +47 -0
  43. package/dist/{cli/menu/settings → app/kernel}/schema-node.d.ts +9 -0
  44. package/dist/{cli/menu/settings → app/kernel}/schema-node.js +26 -0
  45. package/dist/app/kernel/text.d.ts +6 -0
  46. package/dist/app/kernel/text.js +57 -0
  47. package/dist/app/kernel/view.d.ts +146 -0
  48. package/dist/app/kernel/view.js +28 -0
  49. package/dist/app/registry.d.ts +10 -0
  50. package/dist/app/registry.js +50 -0
  51. package/dist/cli/args.d.ts +18 -2
  52. package/dist/cli/args.js +101 -24
  53. package/dist/cli/commands/accounts.js +45 -17
  54. package/dist/cli/commands/context.d.ts +2 -0
  55. package/dist/cli/commands/context.js +9 -2
  56. package/dist/cli/commands/data/clean.js +32 -9
  57. package/dist/cli/commands/engine.d.ts +2 -0
  58. package/dist/cli/commands/engine.js +60 -0
  59. package/dist/cli/commands/index.d.ts +2 -1
  60. package/dist/cli/commands/index.js +2 -1
  61. package/dist/cli/commands/launch/add-root.d.ts +3 -2
  62. package/dist/cli/commands/launch/add-root.js +11 -10
  63. package/dist/cli/commands/launch/launch.js +102 -9
  64. package/dist/cli/commands/launch/prepare.js +6 -4
  65. package/dist/cli/commands/launch/running.js +2 -1
  66. package/dist/cli/commands/launch/summary.d.ts +2 -0
  67. package/dist/cli/commands/maintenance/audit.js +1 -1
  68. package/dist/cli/commands/maintenance/clean.d.ts +1 -1
  69. package/dist/cli/commands/maintenance/clean.js +17 -3
  70. package/dist/cli/commands/maintenance/config-share.d.ts +12 -0
  71. package/dist/cli/commands/maintenance/config-share.js +80 -0
  72. package/dist/cli/commands/maintenance/config.d.ts +1 -1
  73. package/dist/cli/commands/maintenance/config.js +38 -10
  74. package/dist/cli/commands/maintenance/doctor.d.ts +1 -1
  75. package/dist/cli/commands/maintenance/doctor.js +2 -4
  76. package/dist/cli/commands/maintenance/logs.js +14 -0
  77. package/dist/cli/commands/maintenance/migrate.d.ts +2 -1
  78. package/dist/cli/commands/maintenance/migrate.js +19 -4
  79. package/dist/cli/commands/maintenance/sync.js +2 -0
  80. package/dist/cli/commands/maintenance/update.d.ts +2 -0
  81. package/dist/cli/commands/maintenance/update.js +27 -4
  82. package/dist/cli/commands/projects/here.js +12 -7
  83. package/dist/cli/commands/projects/projects.js +26 -17
  84. package/dist/cli/commands/registry.js +10 -7
  85. package/dist/cli/commands/repair/checks/agents.d.ts +2 -0
  86. package/dist/cli/commands/repair/checks/agents.js +70 -0
  87. package/dist/cli/commands/repair/checks/common.d.ts +8 -0
  88. package/dist/cli/commands/repair/checks/common.js +22 -0
  89. package/dist/cli/commands/repair/checks/contained.d.ts +2 -0
  90. package/dist/cli/commands/repair/checks/contained.js +139 -0
  91. package/dist/cli/commands/repair/checks/data.d.ts +2 -0
  92. package/dist/cli/commands/repair/checks/data.js +241 -0
  93. package/dist/cli/commands/repair/checks/hcs.d.ts +7 -0
  94. package/dist/cli/commands/repair/checks/hcs.js +28 -0
  95. package/dist/cli/commands/repair/checks/index.d.ts +2 -0
  96. package/dist/cli/commands/repair/checks/index.js +24 -0
  97. package/dist/cli/commands/repair/checks/install.d.ts +5 -0
  98. package/dist/cli/commands/repair/checks/install.js +318 -0
  99. package/dist/cli/commands/repair/checks/machine.d.ts +2 -0
  100. package/dist/cli/commands/repair/checks/machine.js +232 -0
  101. package/dist/cli/commands/repair/checks/network.d.ts +6 -0
  102. package/dist/cli/commands/repair/checks/network.js +60 -0
  103. package/dist/cli/commands/repair/checks/pc.d.ts +4 -0
  104. package/dist/cli/commands/repair/checks/pc.js +86 -0
  105. package/dist/cli/commands/repair/checks/sandbox.d.ts +2 -0
  106. package/dist/cli/commands/repair/checks/sandbox.js +282 -0
  107. package/dist/cli/commands/repair/checks/settings.d.ts +2 -0
  108. package/dist/cli/commands/repair/checks/settings.js +169 -0
  109. package/dist/cli/commands/repair/checks/vpn.d.ts +2 -0
  110. package/dist/cli/commands/repair/checks/vpn.js +78 -0
  111. package/dist/cli/commands/repair/engine.d.ts +32 -0
  112. package/dist/cli/commands/repair/engine.js +127 -0
  113. package/dist/cli/commands/repair/env.d.ts +7 -0
  114. package/dist/cli/commands/repair/env.js +50 -0
  115. package/dist/cli/commands/repair/index.d.ts +1 -9
  116. package/dist/cli/commands/repair/index.js +2 -54
  117. package/dist/cli/commands/repair/log.d.ts +17 -0
  118. package/dist/cli/commands/repair/log.js +82 -0
  119. package/dist/cli/commands/repair/printer.d.ts +32 -0
  120. package/dist/cli/commands/repair/printer.js +132 -0
  121. package/dist/cli/commands/repair/run.d.ts +33 -0
  122. package/dist/cli/commands/repair/run.js +133 -0
  123. package/dist/cli/commands/repair/types.d.ts +97 -9
  124. package/dist/cli/commands/repair/types.js +11 -7
  125. package/dist/cli/commands/resume.js +2 -2
  126. package/dist/cli/commands/sessions/index.d.ts +0 -4
  127. package/dist/cli/commands/sessions/index.js +3 -7
  128. package/dist/cli/commands/setup/index.d.ts +5 -0
  129. package/dist/cli/commands/setup/index.js +25 -1
  130. package/dist/cli/commands/shared-use.d.ts +5 -2
  131. package/dist/cli/commands/shared-use.js +11 -8
  132. package/dist/cli/commands/storage/contained.d.ts +3 -0
  133. package/dist/cli/commands/storage/contained.js +179 -0
  134. package/dist/cli/commands/storage/index.d.ts +2 -0
  135. package/dist/cli/commands/storage/index.js +2 -0
  136. package/dist/cli/commands/storage/offer.d.ts +3 -0
  137. package/dist/cli/commands/storage/offer.js +91 -0
  138. package/dist/cli/commands/storage/storage.d.ts +8 -0
  139. package/dist/cli/commands/storage/storage.js +179 -0
  140. package/dist/cli/commands/user-config.js +2 -2
  141. package/dist/cli/commands/vpn.d.ts +4 -0
  142. package/dist/cli/commands/vpn.js +91 -0
  143. package/dist/cli/commands/web.d.ts +4 -0
  144. package/dist/cli/commands/web.js +97 -0
  145. package/dist/cli/history.js +1 -1
  146. package/dist/cli/index.js +48 -4
  147. package/dist/cli/manifest.d.ts +339 -97
  148. package/dist/cli/manifest.js +222 -67
  149. package/dist/cli/menu/add-agent.d.ts +47 -0
  150. package/dist/cli/menu/add-agent.js +168 -0
  151. package/dist/cli/menu/apps.d.ts +38 -3
  152. package/dist/cli/menu/apps.js +80 -5
  153. package/dist/cli/menu/command-fields.d.ts +18 -0
  154. package/dist/cli/menu/command-fields.js +61 -0
  155. package/dist/cli/menu/command-form.d.ts +22 -0
  156. package/dist/cli/menu/command-form.js +169 -46
  157. package/dist/cli/menu/data-folder.d.ts +18 -0
  158. package/dist/cli/menu/data-folder.js +99 -0
  159. package/dist/cli/menu/io-menu.d.ts +29 -0
  160. package/dist/cli/menu/io-menu.js +126 -0
  161. package/dist/cli/menu/live.d.ts +27 -0
  162. package/dist/cli/menu/live.js +69 -0
  163. package/dist/cli/menu/memory.d.ts +19 -0
  164. package/dist/cli/menu/memory.js +53 -0
  165. package/dist/cli/menu/menu.d.ts +11 -2
  166. package/dist/cli/menu/menu.js +36 -15
  167. package/dist/cli/menu/pages/accounts-page.js +55 -24
  168. package/dist/cli/menu/pages/agents-page.d.ts +68 -0
  169. package/dist/cli/menu/pages/agents-page.js +345 -0
  170. package/dist/cli/menu/pages/apps-page.d.ts +3 -1
  171. package/dist/cli/menu/pages/apps-page.js +20 -4
  172. package/dist/cli/menu/pages/list-page.d.ts +43 -3
  173. package/dist/cli/menu/pages/list-page.js +146 -12
  174. package/dist/cli/menu/pages/maintenance-page.d.ts +9 -5
  175. package/dist/cli/menu/pages/maintenance-page.js +172 -85
  176. package/dist/cli/menu/pages/sandbox-page.d.ts +7 -6
  177. package/dist/cli/menu/pages/sandbox-page.js +117 -120
  178. package/dist/cli/menu/pages/scopes.d.ts +1 -1
  179. package/dist/cli/menu/pages/sessions-page.d.ts +6 -8
  180. package/dist/cli/menu/pages/sessions-page.js +22 -75
  181. package/dist/cli/menu/pages/settings-page.d.ts +10 -14
  182. package/dist/cli/menu/pages/settings-page.js +95 -102
  183. package/dist/cli/menu/render-view.d.ts +28 -0
  184. package/dist/cli/menu/render-view.js +112 -0
  185. package/dist/cli/menu/settings/ask-path.d.ts +14 -0
  186. package/dist/cli/menu/settings/ask-path.js +14 -0
  187. package/dist/cli/menu/settings/collections/collection-editor.d.ts +8 -2
  188. package/dist/cli/menu/settings/collections/collection-editor.js +12 -8
  189. package/dist/cli/menu/settings/collections/map-editor.js +5 -1
  190. package/dist/cli/menu/settings/collections/object-list-editor.js +2 -2
  191. package/dist/cli/menu/settings/collections/object-map-editor.js +2 -2
  192. package/dist/cli/menu/settings/collections/string-list-editor.d.ts +10 -1
  193. package/dist/cli/menu/settings/collections/string-list-editor.js +23 -0
  194. package/dist/cli/menu/settings/draft.d.ts +1 -1
  195. package/dist/cli/menu/settings/format.d.ts +1 -3
  196. package/dist/cli/menu/settings/format.js +6 -36
  197. package/dist/cli/menu/settings/index.d.ts +1 -3
  198. package/dist/cli/menu/settings/index.js +3 -3
  199. package/dist/cli/menu/settings/object-editor.d.ts +6 -2
  200. package/dist/cli/menu/settings/object-editor.js +15 -4
  201. package/dist/cli/menu/settings/share.d.ts +36 -0
  202. package/dist/cli/menu/settings/share.js +131 -0
  203. package/dist/cli/menu/settings/value-editor.d.ts +10 -1
  204. package/dist/cli/menu/settings/value-editor.js +99 -63
  205. package/dist/cli/menu/several.js +7 -5
  206. package/dist/cli/menu/share-settings.d.ts +21 -0
  207. package/dist/cli/menu/share-settings.js +112 -0
  208. package/dist/cli/menu/shell.d.ts +53 -10
  209. package/dist/cli/menu/shell.js +115 -10
  210. package/dist/cli/menu/views.d.ts +7 -0
  211. package/dist/cli/menu/views.js +11 -0
  212. package/dist/cli/menu/vpn-login.d.ts +16 -0
  213. package/dist/cli/menu/vpn-login.js +74 -0
  214. package/dist/cli/operations/handler.d.ts +6 -0
  215. package/dist/cli/operations/handler.js +61 -0
  216. package/dist/cli/operations/index.d.ts +4 -0
  217. package/dist/cli/operations/index.js +5 -0
  218. package/dist/cli/operations/input.d.ts +6 -0
  219. package/dist/cli/operations/input.js +37 -0
  220. package/dist/cli/operations/io-cli.d.ts +7 -0
  221. package/dist/cli/operations/io-cli.js +62 -0
  222. package/dist/cli/operations/spec.d.ts +18 -0
  223. package/dist/cli/operations/spec.js +108 -0
  224. package/dist/cli/output/colors.d.ts +2 -2
  225. package/dist/cli/output/colors.js +2 -11
  226. package/dist/cli/output/index.d.ts +1 -0
  227. package/dist/cli/output/index.js +1 -0
  228. package/dist/cli/output/print.d.ts +5 -1
  229. package/dist/cli/output/print.js +15 -4
  230. package/dist/cli/output/progress.d.ts +15 -0
  231. package/dist/cli/output/progress.js +44 -0
  232. package/dist/cli/output/render-view.d.ts +4 -0
  233. package/dist/cli/output/render-view.js +63 -0
  234. package/dist/cli/services/accounts-service.d.ts +2 -0
  235. package/dist/cli/services/accounts-service.js +2 -2
  236. package/dist/cli/services/agent-commands-service.d.ts +2 -0
  237. package/dist/cli/services/agent-commands-service.js +11 -2
  238. package/dist/cli/services/health-service.d.ts +0 -6
  239. package/dist/cli/services/health-service.js +5 -42
  240. package/dist/cli/services/index.d.ts +3 -1
  241. package/dist/cli/services/index.js +3 -1
  242. package/dist/cli/services/logs-service.js +4 -3
  243. package/dist/cli/services/migrate-service.js +1 -1
  244. package/dist/cli/services/update-service.d.ts +2 -0
  245. package/dist/cli/services/update-service.js +13 -6
  246. package/dist/cli/services/vpn-service.d.ts +28 -0
  247. package/dist/cli/services/vpn-service.js +46 -0
  248. package/dist/cli/services/web-service.d.ts +22 -0
  249. package/dist/cli/services/web-service.js +111 -0
  250. package/dist/cli/tui/app.d.ts +12 -4
  251. package/dist/cli/tui/app.js +38 -9
  252. package/dist/cli/tui/dialogs/path-listing.d.ts +43 -0
  253. package/dist/cli/tui/dialogs/path-listing.js +127 -0
  254. package/dist/cli/tui/dialogs/path-picker.d.ts +67 -0
  255. package/dist/cli/tui/dialogs/path-picker.js +423 -0
  256. package/dist/cli/tui/dialogs/text-screen.d.ts +6 -0
  257. package/dist/cli/tui/dialogs/text-screen.js +10 -3
  258. package/dist/cli/tui/frame.d.ts +7 -10
  259. package/dist/cli/tui/frame.js +19 -10
  260. package/dist/cli/tui/index.d.ts +4 -3
  261. package/dist/cli/tui/index.js +2 -1
  262. package/dist/cli/tui/list/list-screen.d.ts +28 -2
  263. package/dist/cli/tui/list/list-screen.js +130 -66
  264. package/dist/cli/tui/list/list-types.d.ts +10 -4
  265. package/dist/cli/tui/nav.d.ts +29 -0
  266. package/dist/cli/tui/nav.js +67 -0
  267. package/dist/cli/tui/terminal.d.ts +7 -0
  268. package/dist/cli/tui/terminal.js +30 -10
  269. package/dist/cli/validate.d.ts +1 -1
  270. package/dist/cli/validate.js +3 -3
  271. package/dist/cli/version.d.ts +2 -0
  272. package/dist/cli/version.js +11 -0
  273. package/dist/core/config/defaults.js +13 -1
  274. package/dist/core/config/loader.js +12 -2
  275. package/dist/core/local-config/overrides.js +1 -0
  276. package/dist/core/prompt.d.ts +19 -0
  277. package/dist/core/prompt.js +43 -3
  278. package/dist/core/schema/common.d.ts +6 -0
  279. package/dist/core/schema/common.js +8 -0
  280. package/dist/core/schema/config.d.ts +36 -0
  281. package/dist/core/schema/config.js +26 -2
  282. package/dist/core/schema/harness.d.ts +2 -0
  283. package/dist/core/schema/harness.js +13 -2
  284. package/dist/core/schema/index.d.ts +3 -1
  285. package/dist/core/schema/index.js +3 -1
  286. package/dist/core/schema/profile.d.ts +1 -0
  287. package/dist/core/schema/profile.js +3 -0
  288. package/dist/core/schema/redact.d.ts +13 -0
  289. package/dist/core/schema/redact.js +75 -0
  290. package/dist/core/schema/sandbox.d.ts +6 -0
  291. package/dist/core/schema/sandbox.js +21 -3
  292. package/dist/core/schema/vpn.d.ts +18 -0
  293. package/dist/core/schema/vpn.js +22 -0
  294. package/dist/core/schema/web.d.ts +6 -0
  295. package/dist/core/schema/web.js +14 -0
  296. package/dist/core/types.d.ts +44 -0
  297. package/dist/core/util/fs.d.ts +2 -0
  298. package/dist/core/util/fs.js +9 -0
  299. package/dist/core/util/index.d.ts +1 -1
  300. package/dist/core/util/index.js +1 -1
  301. package/dist/guest/agents/agent-files.d.ts +54 -0
  302. package/dist/guest/agents/agent-files.js +67 -0
  303. package/dist/guest/agents/agent-installer.js +2 -9
  304. package/dist/guest/agents/local-state.d.ts +14 -0
  305. package/dist/guest/agents/local-state.js +218 -0
  306. package/dist/guest/agents/sbx-agent.d.ts +2 -0
  307. package/dist/guest/agents/sbx-agent.js +35 -0
  308. package/dist/guest/boot/boot.d.ts +4 -0
  309. package/dist/guest/boot/boot.js +51 -11
  310. package/dist/guest/daemon/daemon.js +8 -1
  311. package/dist/guest/daemon/exec.js +2 -1
  312. package/dist/guest/daemon/idle-shutdown.js +2 -0
  313. package/dist/guest/daemon/sessions.d.ts +5 -0
  314. package/dist/guest/daemon/sessions.js +20 -3
  315. package/dist/guest/entries/agent.d.ts +1 -0
  316. package/dist/guest/entries/agent.js +10 -0
  317. package/dist/guest/entries/daemon.js +5 -0
  318. package/dist/guest/governor/decide.d.ts +61 -0
  319. package/dist/guest/governor/decide.js +182 -0
  320. package/dist/guest/governor/governor.d.ts +42 -0
  321. package/dist/guest/governor/governor.js +214 -0
  322. package/dist/guest/governor/index.d.ts +2 -0
  323. package/dist/guest/governor/index.js +2 -0
  324. package/dist/guest/runtime/csc.d.ts +2 -0
  325. package/dist/guest/runtime/csc.js +2 -0
  326. package/dist/guest/runtime/secrets.d.ts +12 -0
  327. package/dist/guest/runtime/secrets.js +63 -0
  328. package/dist/guest/sessions/viewer.js +3 -1
  329. package/dist/guest/setup/claude-profile.d.ts +2 -1
  330. package/dist/guest/setup/claude-profile.js +12 -1
  331. package/dist/guest/setup/environment.d.ts +6 -0
  332. package/dist/guest/setup/environment.js +56 -6
  333. package/dist/guest/setup/path-plan.d.ts +32 -0
  334. package/dist/guest/setup/path-plan.js +67 -0
  335. package/dist/guest/setup/shell-path.d.ts +1 -0
  336. package/dist/guest/setup/shell-path.js +22 -0
  337. package/dist/guest/toolchains/languages/python.js +1 -1
  338. package/dist/guest/toolchains/native/rust-extras.js +4 -2
  339. package/dist/guest/toolchains/runtimes.js +2 -2
  340. package/dist/guest/vpn/index.d.ts +1 -0
  341. package/dist/guest/vpn/index.js +1 -0
  342. package/dist/guest/vpn/openvpn.d.ts +9 -0
  343. package/dist/guest/vpn/openvpn.js +47 -0
  344. package/dist/guest/vpn/tunnel.d.ts +17 -0
  345. package/dist/guest/vpn/tunnel.js +78 -0
  346. package/dist/guest/vpn/vpn.d.ts +6 -0
  347. package/dist/guest/vpn/vpn.js +174 -0
  348. package/dist/guest/vpn/wireguard.d.ts +32 -0
  349. package/dist/guest/vpn/wireguard.js +132 -0
  350. package/dist/host/agent-commands/commands.d.ts +4 -0
  351. package/dist/host/agent-commands/commands.js +31 -7
  352. package/dist/host/audit/log.d.ts +1 -1
  353. package/dist/host/channel/attach.d.ts +6 -2
  354. package/dist/host/channel/attach.js +6 -3
  355. package/dist/host/channel/channel.d.ts +9 -0
  356. package/dist/host/channel/channel.js +30 -2
  357. package/dist/host/engines/engine.d.ts +12 -0
  358. package/dist/host/engines/engine.js +1 -0
  359. package/dist/host/engines/hcs/check.d.ts +25 -0
  360. package/dist/host/engines/hcs/check.js +95 -0
  361. package/dist/host/engines/hcs/documents.d.ts +44 -0
  362. package/dist/host/engines/hcs/documents.js +155 -0
  363. package/dist/host/engines/hcs/engine.d.ts +39 -0
  364. package/dist/host/engines/hcs/engine.js +171 -0
  365. package/dist/host/engines/hcs/helper.d.ts +43 -0
  366. package/dist/host/engines/hcs/helper.js +173 -0
  367. package/dist/host/engines/hcs/images.d.ts +37 -0
  368. package/dist/host/engines/hcs/images.js +152 -0
  369. package/dist/host/engines/index.d.ts +7 -0
  370. package/dist/host/engines/index.js +5 -0
  371. package/dist/host/engines/registry.d.ts +16 -0
  372. package/dist/host/engines/registry.js +30 -0
  373. package/dist/host/engines/types.d.ts +58 -0
  374. package/dist/host/engines/types.js +1 -0
  375. package/dist/host/engines/windows-sandbox/engine.d.ts +16 -0
  376. package/dist/host/engines/windows-sandbox/engine.js +63 -0
  377. package/dist/host/engines/windows-sandbox/wsb-text.d.ts +2 -0
  378. package/dist/host/engines/windows-sandbox/wsb-text.js +29 -0
  379. package/dist/host/health/acl-read.d.ts +17 -0
  380. package/dist/host/health/acl-read.js +45 -0
  381. package/dist/host/health/config-backup.d.ts +11 -0
  382. package/dist/host/health/config-backup.js +73 -0
  383. package/dist/host/health/index.d.ts +6 -0
  384. package/dist/host/health/index.js +7 -0
  385. package/dist/host/health/install-state.d.ts +33 -0
  386. package/dist/host/health/install-state.js +110 -0
  387. package/dist/host/health/path-copies.d.ts +32 -0
  388. package/dist/host/health/path-copies.js +82 -0
  389. package/dist/host/health/stale.d.ts +45 -0
  390. package/dist/host/health/stale.js +120 -0
  391. package/dist/host/health/system.d.ts +37 -0
  392. package/dist/host/health/system.js +87 -0
  393. package/dist/host/install/copies.d.ts +13 -0
  394. package/dist/host/install/copies.js +63 -0
  395. package/dist/host/install/index.d.ts +1 -0
  396. package/dist/host/install/index.js +1 -0
  397. package/dist/host/launch/generate.d.ts +5 -1
  398. package/dist/host/launch/generate.js +73 -7
  399. package/dist/host/launch/index.d.ts +3 -1
  400. package/dist/host/launch/index.js +3 -1
  401. package/dist/host/launch/launch-plan.d.ts +13 -0
  402. package/dist/host/launch/launch-plan.js +26 -0
  403. package/dist/host/launch/mappings.js +2 -1
  404. package/dist/host/launch/risk-notes.d.ts +10 -0
  405. package/dist/host/launch/risk-notes.js +18 -0
  406. package/dist/host/launch/session-file.d.ts +2 -0
  407. package/dist/host/launch/session-file.js +11 -2
  408. package/dist/host/launch/stage.js +1 -1
  409. package/dist/host/launch/wsb-file.d.ts +28 -4
  410. package/dist/host/launch/wsb-file.js +61 -42
  411. package/dist/host/life/crash-report.d.ts +27 -1
  412. package/dist/host/life/crash-report.js +173 -7
  413. package/dist/host/life/host-memory.d.ts +40 -0
  414. package/dist/host/life/host-memory.js +137 -0
  415. package/dist/host/life/index.d.ts +2 -0
  416. package/dist/host/life/index.js +2 -0
  417. package/dist/host/life/stop-events.d.ts +2 -0
  418. package/dist/host/life/stop-events.js +20 -3
  419. package/dist/host/life/stop-warning.js +1 -1
  420. package/dist/host/life/watchdog.d.ts +54 -0
  421. package/dist/host/life/watchdog.js +108 -0
  422. package/dist/host/migrate/backup.js +3 -0
  423. package/dist/host/migrate/migrations/config-file.d.ts +2 -0
  424. package/dist/host/migrate/migrations/config-file.js +7 -0
  425. package/dist/host/migrate/migrations/follow-machine-storage.js +9 -1
  426. package/dist/host/migrate/migrations/pin-storage-root.d.ts +4 -0
  427. package/dist/host/migrate/migrations/pin-storage-root.js +46 -0
  428. package/dist/host/migrate/migrations/unpin-config-defaults.js +4 -1
  429. package/dist/host/migrate/registry.js +2 -1
  430. package/dist/host/native.d.ts +3 -2
  431. package/dist/host/native.js +22 -3
  432. package/dist/host/profile/accounts.d.ts +25 -1
  433. package/dist/host/profile/accounts.js +96 -13
  434. package/dist/host/profile/agent-accounts.d.ts +5 -1
  435. package/dist/host/profile/agent-accounts.js +35 -5
  436. package/dist/host/profile/claude-login.js +3 -2
  437. package/dist/host/profile/index.d.ts +2 -1
  438. package/dist/host/profile/index.js +1 -0
  439. package/dist/host/profile/plugin-share.d.ts +26 -0
  440. package/dist/host/profile/plugin-share.js +146 -0
  441. package/dist/host/projects/join.d.ts +7 -1
  442. package/dist/host/projects/join.js +21 -4
  443. package/dist/host/projects/registry.d.ts +16 -10
  444. package/dist/host/projects/registry.js +74 -6
  445. package/dist/host/sandbox/contained-deps.d.ts +2 -0
  446. package/dist/host/sandbox/contained-deps.js +17 -0
  447. package/dist/host/sandbox/index.d.ts +2 -0
  448. package/dist/host/sandbox/index.js +2 -0
  449. package/dist/host/sandbox/platform.d.ts +4 -0
  450. package/dist/host/sandbox/platform.js +23 -4
  451. package/dist/host/sandbox/tasklist.d.ts +13 -0
  452. package/dist/host/sandbox/tasklist.js +47 -0
  453. package/dist/host/secrets/index.d.ts +2 -0
  454. package/dist/host/secrets/index.js +2 -0
  455. package/dist/host/secrets/launch-secrets.d.ts +17 -0
  456. package/dist/host/secrets/launch-secrets.js +94 -0
  457. package/dist/host/secrets/secret-store.d.ts +25 -0
  458. package/dist/host/secrets/secret-store.js +89 -0
  459. package/dist/host/sharing/acl.d.ts +16 -2
  460. package/dist/host/sharing/acl.js +35 -10
  461. package/dist/host/sharing/current.js +8 -3
  462. package/dist/host/sharing/doctor.d.ts +2 -0
  463. package/dist/host/sharing/doctor.js +44 -0
  464. package/dist/host/sharing/group-access.d.ts +6 -0
  465. package/dist/host/sharing/group-access.js +24 -0
  466. package/dist/host/sharing/index.d.ts +2 -1
  467. package/dist/host/sharing/index.js +2 -1
  468. package/dist/host/sharing/lifecycle.d.ts +8 -2
  469. package/dist/host/sharing/lifecycle.js +16 -7
  470. package/dist/host/storage/cleanup.d.ts +2 -0
  471. package/dist/host/storage/cleanup.js +2 -1
  472. package/dist/host/storage/contained/check.d.ts +9 -0
  473. package/dist/host/storage/contained/check.js +37 -0
  474. package/dist/host/storage/contained/contained-storage.d.ts +66 -0
  475. package/dist/host/storage/contained/contained-storage.js +168 -0
  476. package/dist/host/storage/contained/disk-port.d.ts +43 -0
  477. package/dist/host/storage/contained/disk-port.js +122 -0
  478. package/dist/host/storage/contained/index.d.ts +9 -0
  479. package/dist/host/storage/contained/index.js +8 -0
  480. package/dist/host/storage/contained/layout.d.ts +28 -0
  481. package/dist/host/storage/contained/layout.js +45 -0
  482. package/dist/host/storage/contained/resolve.d.ts +4 -0
  483. package/dist/host/storage/contained/resolve.js +30 -0
  484. package/dist/host/storage/contained/setting.d.ts +1 -0
  485. package/dist/host/storage/contained/setting.js +5 -0
  486. package/dist/host/storage/contained/state.d.ts +89 -0
  487. package/dist/host/storage/contained/state.js +166 -0
  488. package/dist/host/storage/contained/transfer.d.ts +24 -0
  489. package/dist/host/storage/contained/transfer.js +121 -0
  490. package/dist/host/storage/history.d.ts +21 -0
  491. package/dist/host/storage/history.js +49 -0
  492. package/dist/host/storage/index.d.ts +6 -0
  493. package/dist/host/storage/index.js +6 -0
  494. package/dist/host/storage/move.d.ts +95 -0
  495. package/dist/host/storage/move.js +384 -0
  496. package/dist/host/storage/offer.d.ts +11 -0
  497. package/dist/host/storage/offer.js +36 -0
  498. package/dist/host/storage/providers/contained.d.ts +15 -0
  499. package/dist/host/storage/providers/contained.js +39 -0
  500. package/dist/host/storage/providers/folder.d.ts +12 -0
  501. package/dist/host/storage/providers/folder.js +20 -0
  502. package/dist/host/storage/providers/index.d.ts +4 -0
  503. package/dist/host/storage/providers/index.js +3 -0
  504. package/dist/host/storage/providers/registry.d.ts +9 -0
  505. package/dist/host/storage/providers/registry.js +14 -0
  506. package/dist/host/storage/providers/types.d.ts +33 -0
  507. package/dist/host/storage/providers/types.js +1 -0
  508. package/dist/host/storage/root.d.ts +18 -0
  509. package/dist/host/storage/root.js +77 -0
  510. package/dist/host/tools/conpty.js +3 -2
  511. package/dist/host/tools/windows-terminal.d.ts +2 -0
  512. package/dist/host/tools/windows-terminal.js +31 -12
  513. package/dist/host/update/index.d.ts +1 -1
  514. package/dist/host/update/index.js +1 -1
  515. package/dist/host/update/notice.d.ts +2 -0
  516. package/dist/host/update/notice.js +13 -1
  517. package/dist/host/update/update-state.d.ts +6 -0
  518. package/dist/host/update/update-state.js +2 -0
  519. package/dist/host/update/updater.d.ts +19 -0
  520. package/dist/host/update/updater.js +88 -12
  521. package/dist/host/vpn/index.d.ts +4 -0
  522. package/dist/host/vpn/index.js +4 -0
  523. package/dist/host/vpn/login.d.ts +24 -0
  524. package/dist/host/vpn/login.js +79 -0
  525. package/dist/host/vpn/nordvpn.d.ts +21 -0
  526. package/dist/host/vpn/nordvpn.js +77 -0
  527. package/dist/host/vpn/prepare.d.ts +19 -0
  528. package/dist/host/vpn/prepare.js +138 -0
  529. package/dist/host/vpn/status.d.ts +12 -0
  530. package/dist/host/vpn/status.js +53 -0
  531. package/dist/host/web/auth.d.ts +38 -0
  532. package/dist/host/web/auth.js +96 -0
  533. package/dist/host/web/backend.d.ts +14 -0
  534. package/dist/host/web/backend.js +1 -0
  535. package/dist/host/web/bridge.d.ts +27 -0
  536. package/dist/host/web/bridge.js +144 -0
  537. package/dist/host/web/browser.d.ts +3 -0
  538. package/dist/host/web/browser.js +23 -0
  539. package/dist/host/web/control.d.ts +17 -0
  540. package/dist/host/web/control.js +67 -0
  541. package/dist/host/web/index.d.ts +10 -0
  542. package/dist/host/web/index.js +9 -0
  543. package/dist/host/web/rpc.d.ts +24 -0
  544. package/dist/host/web/rpc.js +149 -0
  545. package/dist/host/web/runner.d.ts +16 -0
  546. package/dist/host/web/runner.js +44 -0
  547. package/dist/host/web/server.d.ts +47 -0
  548. package/dist/host/web/server.js +238 -0
  549. package/dist/host/web/state.d.ts +20 -0
  550. package/dist/host/web/state.js +41 -0
  551. package/dist/host/web/static-files.d.ts +13 -0
  552. package/dist/host/web/static-files.js +57 -0
  553. package/dist/runtime/agent.js +27675 -0
  554. package/dist/runtime/daemon.js +1950 -1122
  555. package/dist/runtime/db.js +302 -111
  556. package/dist/runtime/main.js +1560 -275
  557. package/dist/runtime/netproxy.js +168 -8
  558. package/dist/runtime/view.js +186 -13
  559. package/dist/selftest/accounts.test.js +40 -0
  560. package/dist/selftest/agent-paths.test.d.ts +2 -0
  561. package/dist/selftest/agent-paths.test.js +125 -0
  562. package/dist/selftest/app.test.d.ts +2 -0
  563. package/dist/selftest/app.test.js +324 -0
  564. package/dist/selftest/channel.test.js +18 -0
  565. package/dist/selftest/cli.test.js +35 -4
  566. package/dist/selftest/config.test.js +59 -0
  567. package/dist/selftest/contained.test.d.ts +2 -0
  568. package/dist/selftest/contained.test.js +544 -0
  569. package/dist/selftest/credentials.test.d.ts +2 -0
  570. package/dist/selftest/credentials.test.js +198 -0
  571. package/dist/selftest/engine.test.d.ts +2 -0
  572. package/dist/selftest/engine.test.js +127 -0
  573. package/dist/selftest/generate.test.js +1 -1
  574. package/dist/selftest/hcs.test.d.ts +2 -0
  575. package/dist/selftest/hcs.test.js +482 -0
  576. package/dist/selftest/health.test.d.ts +2 -0
  577. package/dist/selftest/health.test.js +470 -0
  578. package/dist/selftest/heavy-load.test.d.ts +2 -0
  579. package/dist/selftest/heavy-load.test.js +329 -0
  580. package/dist/selftest/host-sim.test.js +2 -0
  581. package/dist/selftest/index.js +31 -0
  582. package/dist/selftest/layout.test.js +14 -0
  583. package/dist/selftest/menu-perf.test.d.ts +2 -0
  584. package/dist/selftest/menu-perf.test.js +248 -0
  585. package/dist/selftest/menu-screens.d.ts +7 -0
  586. package/dist/selftest/menu-screens.js +68 -17
  587. package/dist/selftest/menu.test.js +603 -22
  588. package/dist/selftest/migrate.test.js +1 -1
  589. package/dist/selftest/personalization.test.js +3 -1
  590. package/dist/selftest/projects.test.js +39 -1
  591. package/dist/selftest/shared-use.test.js +64 -2
  592. package/dist/selftest/sharing.test.js +50 -1
  593. package/dist/selftest/storage.test.d.ts +2 -0
  594. package/dist/selftest/storage.test.js +363 -0
  595. package/dist/selftest/support/engine-cases.d.ts +8 -0
  596. package/dist/selftest/support/engine-cases.js +65 -0
  597. package/dist/selftest/support/engine-golden.d.ts +3 -0
  598. package/dist/selftest/support/engine-golden.js +66 -0
  599. package/dist/selftest/support/fixtures.d.ts +20 -0
  600. package/dist/selftest/support/hcs-probes.d.ts +17 -0
  601. package/dist/selftest/support/hcs-probes.js +41 -0
  602. package/dist/selftest/support/releases.js +1 -1
  603. package/dist/selftest/toolchains.test.js +21 -0
  604. package/dist/selftest/update-service.test.js +87 -3
  605. package/dist/selftest/vpn.test.d.ts +2 -0
  606. package/dist/selftest/vpn.test.js +412 -0
  607. package/dist/selftest/web.test.d.ts +2 -0
  608. package/dist/selftest/web.test.js +402 -0
  609. package/dist/shared/apps/catalogue.js +31 -0
  610. package/dist/shared/channel/index.d.ts +1 -0
  611. package/dist/shared/channel/index.js +1 -0
  612. package/dist/shared/channel/run-dir.d.ts +9 -1
  613. package/dist/shared/channel/run-dir.js +18 -1
  614. package/dist/shared/channel/schema.d.ts +53 -0
  615. package/dist/shared/channel/schema.js +38 -0
  616. package/dist/shared/channel/secrets.d.ts +29 -0
  617. package/dist/shared/channel/secrets.js +50 -0
  618. package/dist/shared/memory/index.d.ts +1 -0
  619. package/dist/shared/memory/index.js +1 -0
  620. package/dist/shared/memory/policy.d.ts +33 -0
  621. package/dist/shared/memory/policy.js +55 -0
  622. package/dist/shared/pty/output-filter.d.ts +14 -1
  623. package/dist/shared/pty/output-filter.js +22 -4
  624. package/dist/shared/pty/terminal.d.ts +4 -1
  625. package/dist/shared/pty/terminal.js +4 -2
  626. package/dist/shared/system.d.ts +1 -0
  627. package/dist/shared/system.js +1 -0
  628. package/dist/shared/vpn/download.d.ts +29 -0
  629. package/dist/shared/vpn/download.js +30 -0
  630. package/dist/shared/vpn/kill-switch.d.ts +18 -0
  631. package/dist/shared/vpn/kill-switch.js +81 -0
  632. package/dist/shared/vpn/ovpn.d.ts +23 -0
  633. package/dist/shared/vpn/ovpn.js +244 -0
  634. package/dist/shared/vpn/wireguard.d.ts +51 -0
  635. package/dist/shared/vpn/wireguard.js +227 -0
  636. package/dist/shared/web/index.d.ts +1 -0
  637. package/dist/shared/web/index.js +1 -0
  638. package/dist/shared/web/protocol.d.ts +61 -0
  639. package/dist/shared/web/protocol.js +35 -0
  640. package/dist/sync/sync-cycle.js +9 -5
  641. package/dist/sync/sync-state.d.ts +1 -0
  642. package/dist/sync/sync-state.js +1 -0
  643. package/dist/sync/watcher.d.ts +13 -0
  644. package/dist/sync/watcher.js +102 -3
  645. package/dist/web/index.html +14 -0
  646. package/dist/web/main-NRRS5O6Z.js +157 -0
  647. package/dist/web/main-T5DMCHYV.css +1 -0
  648. package/native/csharp/FolderSecurity.cs +29 -0
  649. package/native/csharp/HcsHost/AssemblyInfo.cs +14 -0
  650. package/native/csharp/HcsHost/Guard.cs +100 -0
  651. package/native/csharp/HcsHost/Hcs.cs +256 -0
  652. package/native/csharp/HcsHost/Json.cs +78 -0
  653. package/native/csharp/HcsHost/Program.cs +185 -0
  654. package/native/csharp/HcsHost/VirtualDisk.cs +95 -0
  655. package/native/csharp/HostTools/AssemblyInfo.cs +14 -0
  656. package/native/csharp/HostTools/MemoryStatus.cs +107 -0
  657. package/native/csharp/HostTools/Program.cs +58 -17
  658. package/native/scripts/check-contained.ps1 +28 -0
  659. package/native/scripts/contained-common.ps1 +241 -0
  660. package/native/scripts/dismount-contained.ps1 +66 -0
  661. package/native/scripts/memory-status.ps1 +34 -0
  662. package/native/scripts/mount-contained.ps1 +139 -0
  663. package/native/scripts/protect-data.ps1 +29 -0
  664. package/native/scripts/read-folder-sddl.ps1 +10 -0
  665. package/native/scripts/run-elevated.ps1 +17 -4
  666. package/native/scripts/set-folder-access.ps1 +49 -7
  667. package/native/scripts/stop-events.ps1 +23 -8
  668. package/node_modules/ws/LICENSE +20 -0
  669. package/node_modules/ws/README.md +548 -0
  670. package/node_modules/ws/browser.js +8 -0
  671. package/node_modules/ws/index.js +22 -0
  672. package/node_modules/ws/lib/buffer-util.js +131 -0
  673. package/node_modules/ws/lib/constants.js +19 -0
  674. package/node_modules/ws/lib/event-target.js +292 -0
  675. package/node_modules/ws/lib/extension.js +203 -0
  676. package/node_modules/ws/lib/limiter.js +55 -0
  677. package/node_modules/ws/lib/permessage-deflate.js +530 -0
  678. package/node_modules/ws/lib/receiver.js +743 -0
  679. package/node_modules/ws/lib/sender.js +607 -0
  680. package/node_modules/ws/lib/stream.js +161 -0
  681. package/node_modules/ws/lib/subprotocol.js +62 -0
  682. package/node_modules/ws/lib/validation.js +152 -0
  683. package/node_modules/ws/lib/websocket-server.js +562 -0
  684. package/node_modules/ws/lib/websocket.js +1421 -0
  685. package/node_modules/ws/package.json +74 -0
  686. package/node_modules/ws/wrapper.mjs +21 -0
  687. package/package.json +22 -5
  688. package/sandbox/csharp/EnvBroadcast.cs +33 -0
  689. package/sandbox/csharp/MemGov.cs +398 -0
  690. package/sandbox/csharp/PathSync.cs +90 -0
  691. package/sandbox/csharp/PtyHost.cs +111 -5
  692. package/sandbox/scripts/install-shell-path.ps1 +73 -0
  693. package/sandbox/scripts/set-machine-environment.ps1 +37 -4
  694. package/schemas/config.schema.json +136 -7
  695. package/schemas/sandbox-config.schema.json +17 -4
  696. package/dist/cli/commands/repair/checks.d.ts +0 -2
  697. package/dist/cli/commands/repair/checks.js +0 -246
  698. package/dist/cli/commands/sessions/control.d.ts +0 -4
  699. package/dist/cli/commands/sessions/control.js +0 -66
  700. package/dist/cli/commands/sessions/list.d.ts +0 -2
  701. package/dist/cli/commands/sessions/list.js +0 -45
  702. package/dist/cli/commands/sessions/status.d.ts +0 -2
  703. package/dist/cli/commands/sessions/status.js +0 -93
  704. package/dist/cli/commands/sessions/window.d.ts +0 -3
  705. package/dist/cli/commands/sessions/window.js +0 -18
  706. package/dist/cli/menu/pages/start-page.d.ts +0 -43
  707. package/dist/cli/menu/pages/start-page.js +0 -192
  708. package/dist/cli/tui/tab-bar.d.ts +0 -9
  709. package/dist/cli/tui/tab-bar.js +0 -33
@@ -0,0 +1,214 @@
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.
4
+ import fs from 'node:fs';
5
+ import path from 'node:path';
6
+ import { spawn } from 'node:child_process';
7
+ import { createInterface } from 'node:readline';
8
+ import { z } from 'zod';
9
+ import { now } from '../../shared/channel/run-dir.js';
10
+ import { writeJsonAtomic } from '../../shared/io/json.js';
11
+ import { GUEST_THRESHOLDS } from '../../shared/memory/index.js';
12
+ import { ensureCompiled } from '../runtime/csc.js';
13
+ import { dataDir } from '../runtime/paths.js';
14
+ import { warn } from '../runtime/log.js';
15
+ import { run } from '../runtime/paths.js';
16
+ import { session } from '../runtime/session.js';
17
+ import { errMsg } from '../../core/util/errors.js';
18
+ import { decide, INITIAL_STATE } from './decide.js';
19
+ const SampleSchema = z.object({
20
+ ramTotalMb: z.number(),
21
+ ramAvailMb: z.number(),
22
+ commitLimitMb: z.number(),
23
+ commitAvailMb: z.number(),
24
+ procs: z
25
+ .array(z.object({
26
+ pid: z.number().int(),
27
+ name: z.string().max(128),
28
+ mb: z.number(),
29
+ prio: z.enum(['idle', 'below', 'normal']).catch('normal'),
30
+ }))
31
+ .max(1024),
32
+ });
33
+ /** The governor's logic over a port: feed it samples; the host's "slow down" requests go to hostPressure. */
34
+ export class GovernorCore {
35
+ deps;
36
+ state = INITIAL_STATE;
37
+ lastAction = '';
38
+ lastWrite = '';
39
+ lastWriteAt = 0;
40
+ pausedName = '';
41
+ pausedPid = 0;
42
+ constructor(deps) {
43
+ this.deps = deps;
44
+ }
45
+ hostPressure(seconds, reason) {
46
+ const until = this.deps.now() + seconds * 1000;
47
+ if (until > this.state.hostUntil) {
48
+ if (this.state.hostUntil <= this.deps.now())
49
+ this.deps.logLine('governor: this PC is low (' + reason + '); slowing builds down');
50
+ this.state = { ...this.state, hostUntil: until };
51
+ }
52
+ }
53
+ get current() {
54
+ return this.state;
55
+ }
56
+ onSample(sample) {
57
+ const nowMs = this.deps.now();
58
+ const before = this.state.pressure;
59
+ const d = decide(this.state, sample, nowMs, GUEST_THRESHOLDS[this.deps.profile], this.deps.profile);
60
+ this.state = d.state;
61
+ for (const action of d.actions)
62
+ this.apply(action);
63
+ if (d.state.pressure !== before)
64
+ this.deps.logLine(d.state.pressure
65
+ ? 'governor: memory is low (' +
66
+ d.ramFreePercent +
67
+ '% RAM free, commit ' +
68
+ d.commitPercent +
69
+ '% used): slowing builds down'
70
+ : 'governor: memory is fine again: builds back to normal');
71
+ const paused = nowMs < d.state.pausedUntil && this.pausedPid
72
+ ? [{ name: this.pausedName, pid: this.pausedPid, seconds: Math.ceil((d.state.pausedUntil - nowMs) / 1000) }]
73
+ : [];
74
+ const status = {
75
+ level: d.level,
76
+ profile: this.deps.profile,
77
+ ramFreePercent: Math.max(0, Math.min(100, d.ramFreePercent)),
78
+ commitPercent: Math.max(0, Math.min(100, d.commitPercent)),
79
+ lowered: Object.keys(d.state.lowered).length,
80
+ paused,
81
+ pcLow: nowMs < d.state.hostUntil,
82
+ lastAction: this.lastAction,
83
+ updatedAt: now(),
84
+ };
85
+ // Written when something changed, else once a minute (the host reads it, never polls it hard).
86
+ const shape = JSON.stringify({ ...status, updatedAt: '', paused: paused.map((p) => p.pid) });
87
+ if (shape !== this.lastWrite || nowMs - this.lastWriteAt > 60000) {
88
+ this.lastWrite = shape;
89
+ this.lastWriteAt = nowMs;
90
+ this.deps.saveStatus(status);
91
+ }
92
+ }
93
+ apply(action) {
94
+ try {
95
+ if (action.kind === 'priority') {
96
+ this.deps.port.setPriority(action.pid, action.to);
97
+ this.lastAction = action.name + ' (' + action.pid + ') priority ' + action.to;
98
+ }
99
+ else {
100
+ this.deps.port.pause(action.pid, action.ms);
101
+ this.pausedName = action.name;
102
+ this.pausedPid = action.pid;
103
+ this.lastAction = 'paused ' + action.name + ' (' + action.pid + ') for ' + action.ms / 1000 + ' s';
104
+ this.deps.logLine('governor: ' + this.lastAction);
105
+ return;
106
+ }
107
+ this.deps.logLine('governor: ' + this.lastAction);
108
+ }
109
+ catch (e) {
110
+ warn('governor: ' + errMsg(e));
111
+ }
112
+ }
113
+ }
114
+ /** memgov.exe as a child process: samples come out of its stdout, commands go into its stdin. */
115
+ class MemGovProcess {
116
+ onSample;
117
+ child = null;
118
+ constructor(onSample) {
119
+ this.onSample = onSample;
120
+ }
121
+ start() {
122
+ try {
123
+ const child = spawn(ensureCompiled('memgov'), ['serve', '--interval', '2'], {
124
+ stdio: ['pipe', 'pipe', 'ignore'],
125
+ windowsHide: true,
126
+ });
127
+ this.child = child;
128
+ createInterface({ input: child.stdout }).on('line', (line) => {
129
+ try {
130
+ this.onSample(SampleSchema.parse(JSON.parse(line)));
131
+ }
132
+ catch (e) {
133
+ warn('governor: bad sample: ' + errMsg(e));
134
+ }
135
+ });
136
+ child.stdin.on('error', () => undefined);
137
+ child.once('exit', () => {
138
+ this.child = null;
139
+ // It ends only when something is wrong: try again in a while.
140
+ setTimeout(() => this.start(), 30000).unref();
141
+ });
142
+ }
143
+ catch (e) {
144
+ warn('governor: could not start memgov.exe (no memory governor): ' + errMsg(e));
145
+ }
146
+ }
147
+ setPriority(pid, to) {
148
+ this.child?.stdin?.write('priority ' + pid + ' ' + to + '\n');
149
+ }
150
+ pause(pid, ms) {
151
+ this.child?.stdin?.write('suspend ' + pid + ' ' + ms + '\n');
152
+ }
153
+ }
154
+ /** The newest memory log SandboxTools writes, to add the governor's lines to it. */
155
+ function appendToMemoryLog(line) {
156
+ try {
157
+ const logs = path.join(dataDir, 'logs');
158
+ const newest = fs
159
+ .readdirSync(logs)
160
+ .filter((f) => /^memory-\d{8}-\d{6}\.log$/.test(f))
161
+ .sort()
162
+ .pop();
163
+ if (!newest)
164
+ return;
165
+ const t = new Date();
166
+ const stamp = [t.getHours(), t.getMinutes(), t.getSeconds()].map((n) => String(n).padStart(2, '0')).join(':');
167
+ fs.appendFileSync(path.join(logs, newest), stamp + ' | ' + line + '\r\n');
168
+ }
169
+ catch {
170
+ // The log is for people; a missing or locked one never matters.
171
+ }
172
+ }
173
+ /** The daemon's governor: on unless sandbox.pressureResponse is off. */
174
+ export class Governor {
175
+ core = null;
176
+ describe() {
177
+ const profile = session.loadProfile === 'gentle' ? 'gentle' : 'normal';
178
+ const t = GUEST_THRESHOLDS[profile];
179
+ return session.pressureResponse === false
180
+ ? 'off (sandbox.pressureResponse)'
181
+ : profile +
182
+ ' profile: slows builds down below ' +
183
+ t.enterAvailablePercent +
184
+ '% free RAM or above ' +
185
+ t.enterCommitPercent +
186
+ '% commit';
187
+ }
188
+ start() {
189
+ if (session.pressureResponse === false)
190
+ return;
191
+ const profile = session.loadProfile === 'gentle' ? 'gentle' : 'normal';
192
+ const proc = new MemGovProcess((s) => this.core?.onSample(s));
193
+ this.core = new GovernorCore({
194
+ port: proc,
195
+ profile,
196
+ now: () => Date.now(),
197
+ logLine: appendToMemoryLog,
198
+ saveStatus: (status) => {
199
+ try {
200
+ writeJsonAtomic(run.pressureFile, status);
201
+ }
202
+ catch (e) {
203
+ warn('governor: could not write its status: ' + errMsg(e));
204
+ }
205
+ },
206
+ });
207
+ proc.start();
208
+ }
209
+ /** The host's watchdog: this PC is low for a while. */
210
+ hostPressure(seconds, reason) {
211
+ this.core?.hostPressure(seconds, reason);
212
+ }
213
+ }
214
+ export const governor = new Governor();
@@ -0,0 +1,2 @@
1
+ export * from './decide.js';
2
+ export * from './governor.js';
@@ -0,0 +1,2 @@
1
+ export * from './decide.js';
2
+ export * from './governor.js';
@@ -6,6 +6,8 @@ declare const SOURCES: {
6
6
  readonly openssl: "OpenSsl.cs";
7
7
  readonly cargoshim: "CargoShim.cs";
8
8
  readonly linkgate: "LinkGate.cs";
9
+ readonly pathsync: "PathSync.cs";
10
+ readonly memgov: "MemGov.cs";
9
11
  };
10
12
  export type Helper = keyof typeof SOURCES;
11
13
  /** %TEMP%\agent-sandbox\<name>-<hash>.exe, compiled from this launch's source the first time it is needed. */
@@ -19,6 +19,8 @@ const SOURCES = {
19
19
  openssl: 'OpenSsl.cs',
20
20
  cargoshim: 'CargoShim.cs',
21
21
  linkgate: 'LinkGate.cs',
22
+ pathsync: 'PathSync.cs',
23
+ memgov: 'MemGov.cs',
22
24
  };
23
25
  function sourceOf(name) {
24
26
  return path.join(launchDir, 'sandbox', 'csharp', SOURCES[name]);
@@ -0,0 +1,12 @@
1
+ import type { GuestRequest } from '../../core/types.js';
2
+ import { type SecretsFile } from '../../shared/channel/secrets.js';
3
+ /** Where the boot's secrets travel from main.js to the daemon. */
4
+ export declare const BOOT_SECRETS_VARIABLE = "SBX_BOOT_SECRETS";
5
+ /** Reads and deletes <data>\secrets\<id>.json; nothing (or an unreadable file) gives {}. */
6
+ export declare function takeSecrets(id: string): SecretsFile;
7
+ /** The agent the sandbox booted with gets its environment (in memory only). */
8
+ export declare function applyBootEnvironment(environment: Record<string, string> | undefined): void;
9
+ /** The daemon takes what main.js passed it, and removes it from its own environment before any session starts. */
10
+ export declare function adoptBootSecrets(): void;
11
+ /** A request with the agent environment values that travelled in its own secrets file put back (in memory only). */
12
+ export declare function withRequestSecrets(req: GuestRequest): GuestRequest;
@@ -0,0 +1,63 @@
1
+ // The one-shot secrets the host handed over (shared/channel/secrets.ts): read once, the file deleted at once. What the
2
+ // boot read for the agent is passed to the daemon in its own environment (SBX_BOOT_SECRETS, removed there at start), so
3
+ // nothing waits on disk.
4
+ import fs from 'node:fs';
5
+ import { mergeRequestSecrets, SecretsFileSchema } from '../../shared/channel/secrets.js';
6
+ import { run } from './paths.js';
7
+ import { warn } from './log.js';
8
+ import { session } from './session.js';
9
+ /** Where the boot's secrets travel from main.js to the daemon. */
10
+ export const BOOT_SECRETS_VARIABLE = 'SBX_BOOT_SECRETS';
11
+ const MAX_BYTES = 4 * 1024 * 1024;
12
+ /** Reads and deletes <data>\secrets\<id>.json; nothing (or an unreadable file) gives {}. */
13
+ export function takeSecrets(id) {
14
+ const file = run.secretFile(id);
15
+ let text;
16
+ try {
17
+ if (fs.statSync(file).size > MAX_BYTES)
18
+ throw new Error('too big');
19
+ text = fs.readFileSync(file, 'utf8').replace(/^\uFEFF/, '');
20
+ }
21
+ catch {
22
+ return {};
23
+ }
24
+ finally {
25
+ fs.rmSync(file, { force: true });
26
+ }
27
+ try {
28
+ const parsed = SecretsFileSchema.safeParse(JSON.parse(text));
29
+ if (parsed.success)
30
+ return parsed.data;
31
+ }
32
+ catch {
33
+ // Not JSON: treated like an invalid file below.
34
+ }
35
+ warn('The secrets file for ' + id + ' was not valid and was ignored.');
36
+ return {};
37
+ }
38
+ /** The agent the sandbox booted with gets its environment (in memory only). */
39
+ export function applyBootEnvironment(environment) {
40
+ if (session.harness && environment)
41
+ session.harness.environment = { ...environment };
42
+ }
43
+ /** The daemon takes what main.js passed it, and removes it from its own environment before any session starts. */
44
+ export function adoptBootSecrets() {
45
+ const text = process.env[BOOT_SECRETS_VARIABLE];
46
+ delete process.env[BOOT_SECRETS_VARIABLE];
47
+ if (!text)
48
+ return;
49
+ try {
50
+ const parsed = SecretsFileSchema.pick({ harnessEnvironment: true }).safeParse(JSON.parse(text));
51
+ if (parsed.success)
52
+ applyBootEnvironment(parsed.data.harnessEnvironment);
53
+ }
54
+ catch {
55
+ warn('The boot secrets given to the daemon were not valid.');
56
+ }
57
+ }
58
+ /** A request with the agent environment values that travelled in its own secrets file put back (in memory only). */
59
+ export function withRequestSecrets(req) {
60
+ if (req.kind !== 'session' && req.kind !== 'project')
61
+ return req;
62
+ return mergeRequestSecrets(req, takeSecrets(req.id));
63
+ }
@@ -30,7 +30,9 @@ export async function viewSession(id) {
30
30
  return 1;
31
31
  }
32
32
  const socket = await connect({ ...session.attach, addresses: ['127.0.0.1'] });
33
- const result = await runTerminalClient(socket, session.attach.token);
33
+ // The sandbox's own terminal: a copy in the agent reaches the sandbox's clipboard (and yours only through
34
+ // sandbox.clipboard, which already shares it).
35
+ const result = await runTerminalClient(socket, session.attach.token, { clipboardWrites: true });
34
36
  if (result.reason === 'exit')
35
37
  console.log(session.harness + ' exited with code ' + result.exitCode + '.');
36
38
  else if (result.reason === 'error')
@@ -4,4 +4,5 @@
4
4
  * Servers with the same name are replaced by this PC's definition; servers added inside the sandbox are kept.
5
5
  */
6
6
  export declare function mergeMcpServers(hostFile: string, guestFile: string, hostWorkspace: string, guestWorkspace: string): number;
7
- export declare function syncClaudeProfile(): void;
7
+ /** `credentials`: the text of this PC's .credentials.json, handed over in the one-shot secrets file. */
8
+ export declare function syncClaudeProfile(credentials?: string): void;
@@ -57,7 +57,8 @@ export function mergeMcpServers(hostFile, guestFile, hostWorkspace, guestWorkspa
57
57
  writeJsonAtomic(guestFile, merged);
58
58
  return Object.keys(host.mcpServers ?? {}).length + Object.keys(hostProject).length;
59
59
  }
60
- export function syncClaudeProfile() {
60
+ /** `credentials`: the text of this PC's .credentials.json, handed over in the one-shot secrets file. */
61
+ export function syncClaudeProfile(credentials) {
61
62
  const profile = session.claudeProfile;
62
63
  if (profile.items.length === 0) {
63
64
  log('No Claude settings were staged from this PC.');
@@ -68,6 +69,16 @@ export function syncClaudeProfile() {
68
69
  for (const name of profile.items) {
69
70
  const from = path.join(source, name);
70
71
  const to = path.join(claudeDir, name);
72
+ if (name === '.credentials.json') {
73
+ // Never staged in the launch folder: it came in the secrets file.
74
+ if (credentials && !exists(to)) {
75
+ fs.writeFileSync(to, credentials, 'utf8');
76
+ log('Claude settings: copied ' + name + ' from this PC');
77
+ }
78
+ else
79
+ log("Claude settings: kept the sandbox's " + name);
80
+ continue;
81
+ }
71
82
  if (!exists(from))
72
83
  continue;
73
84
  if ((KEEP_SANDBOX_COPY.includes(name) || !profile.overwrite) && exists(to)) {
@@ -14,3 +14,9 @@ export declare function persistEnvironment(env: NodeJS.ProcessEnv, toolVars: str
14
14
  * the boot project's terminals see never changes; the project's own sessions get its full environment anyway.
15
15
  */
16
16
  export declare function addMachineEnvironment(vars: Record<string, string>, dirs: string[], additive?: boolean): void;
17
+ /**
18
+ * The environment for a program the daemon starts (an agent session, `sandbox exec`): its own PATH, plus every machine
19
+ * and user PATH folder added since the daemon started (python, cargo, other agents ...) at the end. Never changes
20
+ * `env`; without Windows it is returned as it is.
21
+ */
22
+ export declare function withRegistryPath(env: NodeJS.ProcessEnv): NodeJS.ProcessEnv;
@@ -2,10 +2,14 @@
2
2
  import path from 'node:path';
3
3
  import { claudeDir, session, stateDir, workspace } from '../runtime/session.js';
4
4
  import { dataDir, dryRun, isWin, testMode, toolsDir } from '../runtime/paths.js';
5
- import { mkdirp } from '../runtime/fs.js';
6
- import { runScriptWithJson } from '../runtime/process.js';
5
+ import { exists, mkdirp } from '../runtime/fs.js';
6
+ import { execOutput, runScriptWithJson } from '../runtime/process.js';
7
+ import { SYSTEM } from '../../shared/system.js';
7
8
  import { warn } from '../runtime/log.js';
8
9
  import { errMsg } from '../../core/util/errors.js';
10
+ import { localStateVars } from '../agents/local-state.js';
11
+ import { agentPaths } from '../agents/agent-files.js';
12
+ import { appendMissing, expandVars, isPinnedNodeDir, parseRegPath, pathKey, planPath } from './path-plan.js';
9
13
  /** Older launch folders have no agentHomes: these two were always set. */
10
14
  const LEGACY_HOMES = { CODEX_HOME: 'codex', GEMINI_CLI_HOME: 'gemini' };
11
15
  /** Every agent's home variable (CODEX_HOME ...) with the folder it points to in the persistent state. */
@@ -31,6 +35,7 @@ export function agentEnv(tools, target = { workspace, project: session.project,
31
35
  ...tools.vars,
32
36
  CLAUDE_CONFIG_DIR: claudeDir,
33
37
  ...homes,
38
+ ...localStateVars(),
34
39
  npm_config_cache: path.join(toolsDir, 'npm-cache'),
35
40
  npm_config_update_notifier: 'false',
36
41
  AGENT_WORKSPACE: target.workspace,
@@ -41,7 +46,13 @@ export function agentEnv(tools, target = { workspace, project: session.project,
41
46
  AGENT_SANDBOX: '1',
42
47
  AGENT_SANDBOX_WORKSPACE: target.workspace,
43
48
  };
44
- for (const dir of [env.CLAUDE_CONFIG_DIR, ...Object.keys(homes).map((n) => env[n]), env.npm_config_cache])
49
+ const local = Object.keys(localStateVars());
50
+ for (const dir of [
51
+ env.CLAUDE_CONFIG_DIR,
52
+ ...Object.keys(homes).map((n) => env[n]),
53
+ env.npm_config_cache,
54
+ ...local.map((n) => env[n]),
55
+ ])
45
56
  mkdirp(dir);
46
57
  // The runner's own Node (bootstrap.ps1 puts it first on PATH) is not exposed: `node` is whatever nvm selected.
47
58
  const runners = [path.join(toolsDir, 'node'), path.dirname(process.execPath)].map((d) => d.toLowerCase());
@@ -53,13 +64,17 @@ export function agentEnv(tools, target = { workspace, project: session.project,
53
64
  export function persistEnvironment(env, toolVars) {
54
65
  if (!isWin || dryRun || testMode)
55
66
  return;
56
- const vars = Object.fromEntries([...toolVars, ...AGENT_VARS, ...Object.keys(agentHomes())]
67
+ const vars = Object.fromEntries([...toolVars, ...AGENT_VARS, ...Object.keys(agentHomes()), ...Object.keys(localStateVars())]
57
68
  .filter((n) => env[n] !== undefined)
58
69
  .map((n) => [n, env[n]]));
59
70
  try {
60
71
  runScriptWithJson('set-machine-environment.ps1', 'SettingsFile', {
61
72
  vars,
62
- path: env.PATH ?? '',
73
+ path: planPath({
74
+ entries: [env.PATH ?? '', ...installedAgentDirs()],
75
+ exists,
76
+ drop: (dir) => isPinnedNodeDir(dir, nvmHome()),
77
+ }).join(path.delimiter),
63
78
  add: [],
64
79
  additive: false,
65
80
  });
@@ -76,10 +91,45 @@ export function persistEnvironment(env, toolVars) {
76
91
  export function addMachineEnvironment(vars, dirs, additive = false) {
77
92
  if (!isWin || dryRun || testMode)
78
93
  return;
94
+ // Folders that do not exist stay out, and so does a pinned Node version (`nvm use` could not move it).
95
+ const planned = planPath({ entries: dirs, exists, drop: (dir) => isPinnedNodeDir(dir, nvmHome()) });
79
96
  try {
80
- runScriptWithJson('set-machine-environment.ps1', 'SettingsFile', { vars, path: null, add: dirs, additive });
97
+ runScriptWithJson('set-machine-environment.ps1', 'SettingsFile', { vars, path: null, add: planned, additive });
81
98
  }
82
99
  catch (e) {
83
100
  warn('Could not add to the environment: ' + errMsg(e));
84
101
  }
85
102
  }
103
+ const nvmHome = () => path.join(toolsDir, 'nvm');
104
+ /** The folder of every configured agent that is installed: its command works in any terminal. */
105
+ function installedAgentDirs() {
106
+ return Object.entries(session.agents ?? {}).flatMap(([name, harness]) => {
107
+ const p = agentPaths(toolsDir, name, harness);
108
+ return (p.exe && exists(p.exe)) || (p.cmd && exists(p.cmd)) ? [p.dir] : [];
109
+ });
110
+ }
111
+ const MACHINE_ENVIRONMENT_KEY = 'HKLM\\SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment';
112
+ const USER_ENVIRONMENT_KEY = 'HKCU\\Environment';
113
+ const registryPath = (key) => parseRegPath(execOutput(SYSTEM.reg(), ['query', key, '/v', 'Path']));
114
+ /**
115
+ * The environment for a program the daemon starts (an agent session, `sandbox exec`): its own PATH, plus every machine
116
+ * and user PATH folder added since the daemon started (python, cargo, other agents ...) at the end. Never changes
117
+ * `env`; without Windows it is returned as it is.
118
+ */
119
+ export function withRegistryPath(env) {
120
+ if (!isWin || dryRun || testMode)
121
+ return env;
122
+ try {
123
+ const registry = expandVars(registryPath(MACHINE_ENVIRONMENT_KEY) + ';' + registryPath(USER_ENVIRONMENT_KEY), env);
124
+ const runner = pathKey(path.join(toolsDir, 'node'));
125
+ const pathName = Object.keys(env).find((k) => k.toLowerCase() === 'path') ?? 'PATH';
126
+ return {
127
+ ...env,
128
+ [pathName]: appendMissing(env[pathName] ?? '', registry, (dir) => pathKey(dir) === runner || isPinnedNodeDir(dir, nvmHome())),
129
+ };
130
+ }
131
+ catch (e) {
132
+ warn('Could not read the machine PATH (the session keeps the one it has): ' + errMsg(e));
133
+ return env;
134
+ }
135
+ }
@@ -0,0 +1,32 @@
1
+ /** A folder as a comparison key: one slash style, no trailing slash (a drive root keeps its one), lower case. */
2
+ export declare function pathKey(folder: string): string;
3
+ /** The folders of a PATH string: no empty parts, no quotes around a folder. */
4
+ export declare function splitPath(value: string): string[];
5
+ /** Replaces %NAME% with the variable's value (any case); a name that is not set stays as written. */
6
+ export declare function expandVars(value: string, env: Readonly<Record<string, string | undefined>>): string;
7
+ export interface PathPlanInput {
8
+ /** In the order they should have: earlier entries win. */
9
+ readonly entries: readonly string[];
10
+ readonly exists: (folder: string) => boolean;
11
+ /** Entries to leave out (a folder that must not be machine-wide, matched like pathKey). */
12
+ readonly drop?: (folder: string) => boolean;
13
+ }
14
+ /** Ordered, de-duplicated (case, trailing slash) PATH folders; missing and dropped folders are left out. */
15
+ export declare function planPath(input: PathPlanInput): string[];
16
+ /** `base` with the folders of `extra` it lacks added at the end (a process keeps its own order and entries). */
17
+ export declare function appendMissing(base: string, extra: string, skip?: (folder: string) => boolean): string;
18
+ /**
19
+ * What a new shell gets: folders only this process has first (a parent put them there on purpose), then the machine
20
+ * and the user PATH with their %VARIABLES% expanded; no duplicates. `skip` leaves folders out (the runner's own Node).
21
+ */
22
+ export declare function rebuildPath(o: {
23
+ readonly machine: string;
24
+ readonly user: string;
25
+ readonly process: string;
26
+ readonly env: Readonly<Record<string, string | undefined>>;
27
+ readonly skip?: (folder: string) => boolean;
28
+ }): string;
29
+ /** The value of `Path` in the output of `reg query <key> /v Path` ('' when there is none). */
30
+ export declare function parseRegPath(output: string): string;
31
+ /** A folder of one pinned Node version (nvm's `v24.22.0`): never machine-wide, `nvm use` would not move it. */
32
+ export declare function isPinnedNodeDir(folder: string, nvmHome: string): boolean;
@@ -0,0 +1,67 @@
1
+ // The one place that decides which folders are on the machine PATH, in what order, and how a process's PATH is brought
2
+ // up to date with the registry. Pure (no side effects): the self-test imports this file. The shells' own start-up code
3
+ // (sandbox\csharp\PathSync.cs) follows the same rules.
4
+ import path from 'node:path';
5
+ /** A folder as a comparison key: one slash style, no trailing slash (a drive root keeps its one), lower case. */
6
+ export function pathKey(folder) {
7
+ const slashes = folder.trim().replace(/^"|"$/g, '').replace(/\//g, '\\');
8
+ return (slashes.length > 3 ? slashes.replace(/\\+$/, '') : slashes).toLowerCase();
9
+ }
10
+ /** The folders of a PATH string: no empty parts, no quotes around a folder. */
11
+ export function splitPath(value) {
12
+ return value
13
+ .split(';')
14
+ .map((part) => part.trim().replace(/^"|"$/g, ''))
15
+ .filter(Boolean);
16
+ }
17
+ /** Replaces %NAME% with the variable's value (any case); a name that is not set stays as written. */
18
+ export function expandVars(value, env) {
19
+ const lower = new Map(Object.entries(env).map(([k, v]) => [k.toLowerCase(), v]));
20
+ return value.replace(/%([^%;\\]+)%/g, (whole, name) => lower.get(name.toLowerCase()) ?? whole);
21
+ }
22
+ /** Ordered, de-duplicated (case, trailing slash) PATH folders; missing and dropped folders are left out. */
23
+ export function planPath(input) {
24
+ const seen = new Set();
25
+ const result = [];
26
+ for (const entry of input.entries.flatMap(splitPath)) {
27
+ const key = pathKey(entry);
28
+ if (seen.has(key) || input.drop?.(entry) || !input.exists(entry))
29
+ continue;
30
+ seen.add(key);
31
+ result.push(entry);
32
+ }
33
+ return result;
34
+ }
35
+ /** `base` with the folders of `extra` it lacks added at the end (a process keeps its own order and entries). */
36
+ export function appendMissing(base, extra, skip = () => false) {
37
+ const seen = new Set(splitPath(base).map(pathKey));
38
+ const added = splitPath(extra).filter((folder) => {
39
+ const key = pathKey(folder);
40
+ if (seen.has(key) || skip(folder))
41
+ return false;
42
+ seen.add(key);
43
+ return true;
44
+ });
45
+ return [...splitPath(base), ...added].join(';');
46
+ }
47
+ /**
48
+ * What a new shell gets: folders only this process has first (a parent put them there on purpose), then the machine
49
+ * and the user PATH with their %VARIABLES% expanded; no duplicates. `skip` leaves folders out (the runner's own Node).
50
+ */
51
+ export function rebuildPath(o) {
52
+ const registry = splitPath(expandVars(o.machine, o.env) + ';' + expandVars(o.user, o.env));
53
+ const known = new Set(registry.map(pathKey));
54
+ const only = splitPath(o.process).filter((f) => !known.has(pathKey(f)) && !o.skip?.(f));
55
+ return planPath({ entries: [...only, ...registry], exists: () => true }).join(';');
56
+ }
57
+ /** The value of `Path` in the output of `reg query <key> /v Path` ('' when there is none). */
58
+ export function parseRegPath(output) {
59
+ const line = output.split(/\r?\n/).find((l) => /^\s+Path\s+REG_(EXPAND_)?SZ\s/i.test(l));
60
+ return line ? line.replace(/^\s+Path\s+REG_(EXPAND_)?SZ\s+/i, '').trim() : '';
61
+ }
62
+ /** A folder of one pinned Node version (nvm's `v24.22.0`): never machine-wide, `nvm use` would not move it. */
63
+ export function isPinnedNodeDir(folder, nvmHome) {
64
+ const key = pathKey(folder);
65
+ const home = pathKey(nvmHome);
66
+ return key.startsWith(home + '\\') && /^v\d/.test(path.win32.basename(key));
67
+ }
@@ -0,0 +1 @@
1
+ export declare function installShellPath(): void;
@@ -0,0 +1,22 @@
1
+ // New shells (PowerShell, PowerShell 7, cmd, Git Bash) start with the current machine PATH, whatever their parent had:
2
+ // pathsync.exe is built and the shells' start-up files call it (sandbox\scripts\install-shell-path.ps1).
3
+ import fs from 'node:fs';
4
+ import path from 'node:path';
5
+ import { dryRun, isWin, localDir, testMode, toolsDir } from '../runtime/paths.js';
6
+ import { mkdirp } from '../runtime/fs.js';
7
+ import { ensureCompiled } from '../runtime/csc.js';
8
+ import { runScript } from '../runtime/process.js';
9
+ export function installShellPath() {
10
+ if (!isWin || dryRun || testMode)
11
+ return;
12
+ const helper = path.join(mkdirp(path.join(localDir, 'bin')), 'pathsync.exe');
13
+ fs.copyFileSync(ensureCompiled('pathsync'), helper);
14
+ runScript('install-shell-path.ps1', [
15
+ '-Helper',
16
+ helper,
17
+ '-PwshDir',
18
+ path.join(toolsDir, 'pwsh'),
19
+ '-GitRoot',
20
+ path.join(toolsDir, 'git'),
21
+ ]);
22
+ }
@@ -77,7 +77,7 @@ export async function setupPython(env, config, versions) {
77
77
  const py3 = await installPython('python', versions.python.spec);
78
78
  const shims = shimDir(py3);
79
79
  shimPair(shims, '3', py3);
80
- env.prepend.push(py3, path.join(py3, 'Scripts'), shims);
80
+ env.prepend.push(py3, mkdirp(path.join(py3, 'Scripts')), shims);
81
81
  env.vars.PYTHONIOENCODING = 'utf-8';
82
82
  env.summary.push('python: ' + path.basename(py3).replace('python-', '') + ' (from ' + versions.python.source + '; py works too)');
83
83
  if (!config.python2) {
@@ -7,6 +7,7 @@ import { execOutput } from '../../runtime/process.js';
7
7
  import { ensureCompiled } from '../../runtime/csc.js';
8
8
  import { arch, tool } from '../tool-env.js';
9
9
  import { wanted } from '../detect.js';
10
+ import { cargoJobs } from '../../../shared/memory/index.js';
10
11
  /**
11
12
  * Where cargo builds: shared with the PC's target\, one on the sandbox's disk, or a path. "separate" sets no variable:
12
13
  * the cargo shim (sandbox/csharp/CargoShim.cs) gives every checkout its own target\sandbox, so git worktrees of several
@@ -66,8 +67,9 @@ export function cargoDefaults(host) {
66
67
  const file = tool('rust', 'cargo', 'config.toml');
67
68
  if (exists(file) || !exists(path.dirname(file)))
68
69
  return;
69
- // Several agents often build at once: up to 4 jobs each (8 each crashed Windows inside the sandbox on 13 Oct 2026).
70
- const jobs = Math.max(2, Math.min(4, Math.floor(os.cpus().length / 4)));
70
+ // Several agents often build at once: up to 4 jobs each (8 each crashed Windows inside the sandbox on 13 Oct 2026),
71
+ // and about 4 GB of memory per job. The daemon lowers it further per session (CARGO_BUILD_JOBS) when several build.
72
+ const jobs = cargoJobs(os.cpus().length, os.totalmem() / 1024 ** 3, 1);
71
73
  const gnu = host.endsWith('-gnu');
72
74
  fs.writeFileSync(file, [
73
75
  '# Written by windows-development-sandbox once; edit freely, it is never overwritten.',