windows-development-sandbox 1.7.0 → 1.10.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 (432) hide show
  1. package/config.example.json +12 -1
  2. package/dist/app/context.d.ts +8 -0
  3. package/dist/app/context.js +12 -0
  4. package/dist/app/features/defs.d.ts +322 -0
  5. package/dist/app/features/defs.js +28 -0
  6. package/dist/app/features/sandbox/index.d.ts +2 -0
  7. package/dist/app/features/sandbox/index.js +3 -0
  8. package/dist/app/features/sandbox/sandbox.def.d.ts +193 -0
  9. package/dist/app/features/sandbox/sandbox.def.js +245 -0
  10. package/dist/app/features/sandbox/sandbox.run.d.ts +72 -0
  11. package/dist/app/features/sandbox/sandbox.run.js +98 -0
  12. package/dist/app/features/sessions/index.d.ts +2 -0
  13. package/dist/app/features/sessions/index.js +3 -0
  14. package/dist/app/features/sessions/sessions.def.d.ts +141 -0
  15. package/dist/app/features/sessions/sessions.def.js +176 -0
  16. package/dist/app/features/sessions/sessions.run.d.ts +39 -0
  17. package/dist/app/features/sessions/sessions.run.js +58 -0
  18. package/dist/{cli/menu/settings/categories.d.ts → app/features/settings/categories.def.d.ts} +2 -0
  19. package/dist/{cli/menu/settings/categories.js → app/features/settings/categories.def.js} +24 -5
  20. package/dist/app/features/settings/index.d.ts +5 -0
  21. package/dist/app/features/settings/index.js +6 -0
  22. package/dist/{cli/menu/settings/config-file.d.ts → app/features/settings/settings-file.d.ts} +1 -1
  23. package/dist/{cli/menu/settings/config-file.js → app/features/settings/settings-file.js} +1 -1
  24. package/dist/app/features/settings/settings-rows.d.ts +35 -0
  25. package/dist/app/features/settings/settings-rows.js +94 -0
  26. package/dist/app/features/settings/settings.def.d.ts +157 -0
  27. package/dist/app/features/settings/settings.def.js +179 -0
  28. package/dist/app/features/settings/settings.run.d.ts +67 -0
  29. package/dist/app/features/settings/settings.run.js +84 -0
  30. package/dist/app/kernel/define.d.ts +143 -0
  31. package/dist/app/kernel/define.js +42 -0
  32. package/dist/app/kernel/errors.d.ts +34 -0
  33. package/dist/app/kernel/errors.js +45 -0
  34. package/dist/app/kernel/fields.d.ts +70 -0
  35. package/dist/app/kernel/fields.js +243 -0
  36. package/dist/app/kernel/index.d.ts +8 -0
  37. package/dist/app/kernel/index.js +10 -0
  38. package/dist/app/kernel/io.d.ts +193 -0
  39. package/dist/app/kernel/io.js +126 -0
  40. package/dist/app/kernel/rpc.d.ts +156 -0
  41. package/dist/app/kernel/rpc.js +47 -0
  42. package/dist/app/kernel/text.d.ts +6 -0
  43. package/dist/app/kernel/text.js +57 -0
  44. package/dist/app/kernel/view.d.ts +146 -0
  45. package/dist/app/kernel/view.js +28 -0
  46. package/dist/app/registry.d.ts +10 -0
  47. package/dist/app/registry.js +50 -0
  48. package/dist/cli/args.d.ts +5 -0
  49. package/dist/cli/args.js +6 -0
  50. package/dist/cli/commands/engine.d.ts +2 -0
  51. package/dist/cli/commands/engine.js +60 -0
  52. package/dist/cli/commands/index.d.ts +1 -1
  53. package/dist/cli/commands/index.js +1 -1
  54. package/dist/cli/commands/launch/launch.js +49 -7
  55. package/dist/cli/commands/launch/prepare.js +3 -3
  56. package/dist/cli/commands/launch/running.js +2 -1
  57. package/dist/cli/commands/launch/summary.d.ts +2 -0
  58. package/dist/cli/commands/maintenance/config-share.d.ts +12 -0
  59. package/dist/cli/commands/maintenance/config-share.js +80 -0
  60. package/dist/cli/commands/maintenance/config.js +8 -82
  61. package/dist/cli/commands/maintenance/logs.js +14 -0
  62. package/dist/cli/commands/registry.js +3 -7
  63. package/dist/cli/commands/repair/checks/contained.d.ts +2 -0
  64. package/dist/cli/commands/repair/checks/contained.js +139 -0
  65. package/dist/cli/commands/repair/checks/hcs.d.ts +7 -0
  66. package/dist/cli/commands/repair/checks/hcs.js +28 -0
  67. package/dist/cli/commands/repair/checks/index.js +4 -0
  68. package/dist/cli/commands/repair/checks/pc.js +32 -1
  69. package/dist/cli/commands/repair/checks/sandbox.js +16 -1
  70. package/dist/cli/commands/repair/checks/vpn.js +34 -9
  71. package/dist/cli/commands/repair/env.js +2 -1
  72. package/dist/cli/commands/sessions/index.d.ts +0 -4
  73. package/dist/cli/commands/sessions/index.js +3 -7
  74. package/dist/cli/commands/shared-use.d.ts +5 -2
  75. package/dist/cli/commands/shared-use.js +11 -8
  76. package/dist/cli/commands/storage/contained.d.ts +3 -0
  77. package/dist/cli/commands/storage/contained.js +179 -0
  78. package/dist/cli/commands/storage/offer.js +7 -1
  79. package/dist/cli/commands/storage/storage.js +10 -2
  80. package/dist/cli/commands/user-config.js +1 -1
  81. package/dist/cli/commands/vpn.js +20 -3
  82. package/dist/cli/commands/web.d.ts +5 -0
  83. package/dist/cli/commands/web.js +40 -0
  84. package/dist/cli/index.js +2 -1
  85. package/dist/cli/manifest.d.ts +72 -104
  86. package/dist/cli/manifest.js +64 -39
  87. package/dist/cli/menu/add-agent.d.ts +1 -1
  88. package/dist/cli/menu/add-agent.js +1 -1
  89. package/dist/cli/menu/apps.d.ts +7 -1
  90. package/dist/cli/menu/apps.js +36 -0
  91. package/dist/cli/menu/command-fields.d.ts +1 -1
  92. package/dist/cli/menu/command-form.js +2 -2
  93. package/dist/cli/menu/io-menu.d.ts +29 -0
  94. package/dist/cli/menu/io-menu.js +126 -0
  95. package/dist/cli/menu/live.d.ts +27 -0
  96. package/dist/cli/menu/live.js +69 -0
  97. package/dist/cli/menu/memory.d.ts +19 -0
  98. package/dist/cli/menu/memory.js +53 -0
  99. package/dist/cli/menu/menu.d.ts +10 -1
  100. package/dist/cli/menu/menu.js +27 -9
  101. package/dist/cli/menu/pages/agents-page.d.ts +3 -1
  102. package/dist/cli/menu/pages/agents-page.js +12 -5
  103. package/dist/cli/menu/pages/apps-page.d.ts +3 -1
  104. package/dist/cli/menu/pages/apps-page.js +19 -2
  105. package/dist/cli/menu/pages/list-page.d.ts +27 -0
  106. package/dist/cli/menu/pages/list-page.js +109 -7
  107. package/dist/cli/menu/pages/maintenance-page.d.ts +0 -5
  108. package/dist/cli/menu/pages/maintenance-page.js +17 -19
  109. package/dist/cli/menu/pages/sandbox-page.d.ts +4 -6
  110. package/dist/cli/menu/pages/sandbox-page.js +26 -118
  111. package/dist/cli/menu/pages/scopes.d.ts +1 -1
  112. package/dist/cli/menu/pages/sessions-page.d.ts +5 -11
  113. package/dist/cli/menu/pages/sessions-page.js +19 -88
  114. package/dist/cli/menu/pages/settings-page.d.ts +2 -10
  115. package/dist/cli/menu/pages/settings-page.js +64 -94
  116. package/dist/cli/menu/render-view.d.ts +28 -0
  117. package/dist/cli/menu/render-view.js +112 -0
  118. package/dist/cli/menu/settings/{path-kind.d.ts → ask-path.d.ts} +1 -7
  119. package/dist/cli/menu/settings/ask-path.js +14 -0
  120. package/dist/cli/menu/settings/collections/collection-editor.d.ts +1 -1
  121. package/dist/cli/menu/settings/collections/string-list-editor.d.ts +1 -2
  122. package/dist/cli/menu/settings/collections/string-list-editor.js +1 -1
  123. package/dist/cli/menu/settings/draft.d.ts +1 -1
  124. package/dist/cli/menu/settings/format.d.ts +1 -3
  125. package/dist/cli/menu/settings/format.js +6 -36
  126. package/dist/cli/menu/settings/index.d.ts +1 -3
  127. package/dist/cli/menu/settings/index.js +3 -3
  128. package/dist/cli/menu/settings/object-editor.d.ts +1 -1
  129. package/dist/cli/menu/settings/share.d.ts +36 -0
  130. package/dist/cli/menu/settings/share.js +131 -0
  131. package/dist/cli/menu/settings/value-editor.d.ts +5 -1
  132. package/dist/cli/menu/settings/value-editor.js +57 -54
  133. package/dist/cli/menu/several.js +1 -1
  134. package/dist/cli/menu/share-settings.d.ts +21 -0
  135. package/dist/cli/menu/share-settings.js +112 -0
  136. package/dist/cli/menu/shell.d.ts +21 -5
  137. package/dist/cli/menu/shell.js +31 -6
  138. package/dist/cli/menu/views.d.ts +7 -0
  139. package/dist/cli/menu/views.js +11 -0
  140. package/dist/cli/menu/vpn-login.js +8 -0
  141. package/dist/cli/operations/handler.d.ts +6 -0
  142. package/dist/cli/operations/handler.js +61 -0
  143. package/dist/cli/operations/index.d.ts +4 -0
  144. package/dist/cli/operations/index.js +5 -0
  145. package/dist/cli/operations/input.d.ts +6 -0
  146. package/dist/cli/operations/input.js +37 -0
  147. package/dist/cli/operations/io-cli.d.ts +7 -0
  148. package/dist/cli/operations/io-cli.js +62 -0
  149. package/dist/cli/operations/spec.d.ts +18 -0
  150. package/dist/cli/operations/spec.js +108 -0
  151. package/dist/cli/output/colors.d.ts +2 -2
  152. package/dist/cli/output/colors.js +2 -11
  153. package/dist/cli/output/index.d.ts +1 -0
  154. package/dist/cli/output/index.js +1 -0
  155. package/dist/cli/output/print.d.ts +3 -1
  156. package/dist/cli/output/print.js +7 -3
  157. package/dist/cli/output/progress.d.ts +15 -0
  158. package/dist/cli/output/progress.js +44 -0
  159. package/dist/cli/output/render-view.d.ts +4 -0
  160. package/dist/cli/output/render-view.js +63 -0
  161. package/dist/cli/services/agent-commands-service.d.ts +2 -0
  162. package/dist/cli/services/agent-commands-service.js +11 -2
  163. package/dist/cli/services/logs-service.js +4 -3
  164. package/dist/cli/tui/app.d.ts +6 -1
  165. package/dist/cli/tui/app.js +26 -4
  166. package/dist/cli/tui/list/list-screen.d.ts +14 -0
  167. package/dist/cli/tui/list/list-screen.js +64 -36
  168. package/dist/cli/tui/list/list-types.d.ts +2 -0
  169. package/dist/cli/tui/terminal.d.ts +7 -0
  170. package/dist/cli/tui/terminal.js +30 -10
  171. package/dist/core/config/defaults.js +9 -1
  172. package/dist/core/schema/config.d.ts +14 -0
  173. package/dist/core/schema/config.js +16 -1
  174. package/dist/core/schema/harness.d.ts +1 -0
  175. package/dist/core/schema/harness.js +5 -0
  176. package/dist/core/schema/sandbox.d.ts +6 -0
  177. package/dist/core/schema/sandbox.js +20 -3
  178. package/dist/core/schema/vpn.d.ts +2 -1
  179. package/dist/core/schema/vpn.js +4 -4
  180. package/dist/core/schema/web.d.ts +1 -0
  181. package/dist/core/schema/web.js +4 -1
  182. package/dist/core/types.d.ts +23 -5
  183. package/dist/core/util/fs.d.ts +2 -0
  184. package/dist/core/util/fs.js +9 -0
  185. package/dist/core/util/index.d.ts +1 -1
  186. package/dist/core/util/index.js +1 -1
  187. package/dist/guest/agents/agent-files.d.ts +5 -0
  188. package/dist/guest/agents/agent-files.js +4 -0
  189. package/dist/guest/agents/local-state.d.ts +2 -0
  190. package/dist/guest/agents/local-state.js +21 -1
  191. package/dist/guest/boot/boot.js +5 -2
  192. package/dist/guest/daemon/daemon.js +4 -0
  193. package/dist/guest/daemon/sessions.d.ts +5 -0
  194. package/dist/guest/daemon/sessions.js +17 -3
  195. package/dist/guest/entries/daemon.js +3 -0
  196. package/dist/guest/governor/decide.d.ts +71 -0
  197. package/dist/guest/governor/decide.js +211 -0
  198. package/dist/guest/governor/governor.d.ts +45 -0
  199. package/dist/guest/governor/governor.js +230 -0
  200. package/dist/guest/governor/index.d.ts +2 -0
  201. package/dist/guest/governor/index.js +2 -0
  202. package/dist/guest/network/firewall.d.ts +1 -0
  203. package/dist/guest/network/firewall.js +65 -23
  204. package/dist/guest/runtime/csc.d.ts +1 -0
  205. package/dist/guest/runtime/csc.js +1 -0
  206. package/dist/guest/runtime/process.js +53 -5
  207. package/dist/guest/sessions/viewer.js +3 -1
  208. package/dist/guest/setup/claude-mem.js +12 -4
  209. package/dist/guest/toolchains/languages/node.js +29 -3
  210. package/dist/guest/toolchains/native/rust-extras.js +4 -2
  211. package/dist/guest/vpn/vpn.js +69 -21
  212. package/dist/guest/vpn/wireguard.d.ts +32 -0
  213. package/dist/guest/vpn/wireguard.js +132 -0
  214. package/dist/host/agent-commands/commands.d.ts +4 -0
  215. package/dist/host/agent-commands/commands.js +31 -7
  216. package/dist/host/audit/log.d.ts +1 -1
  217. package/dist/host/channel/attach.d.ts +3 -1
  218. package/dist/host/channel/attach.js +5 -2
  219. package/dist/host/channel/channel.d.ts +2 -0
  220. package/dist/host/channel/channel.js +4 -0
  221. package/dist/host/engines/engine.d.ts +12 -0
  222. package/dist/host/engines/engine.js +1 -0
  223. package/dist/host/engines/hcs/check.d.ts +25 -0
  224. package/dist/host/engines/hcs/check.js +95 -0
  225. package/dist/host/engines/hcs/documents.d.ts +44 -0
  226. package/dist/host/engines/hcs/documents.js +155 -0
  227. package/dist/host/engines/hcs/engine.d.ts +39 -0
  228. package/dist/host/engines/hcs/engine.js +171 -0
  229. package/dist/host/engines/hcs/helper.d.ts +43 -0
  230. package/dist/host/engines/hcs/helper.js +173 -0
  231. package/dist/host/engines/hcs/images.d.ts +37 -0
  232. package/dist/host/engines/hcs/images.js +152 -0
  233. package/dist/host/engines/index.d.ts +7 -0
  234. package/dist/host/engines/index.js +5 -0
  235. package/dist/host/engines/registry.d.ts +16 -0
  236. package/dist/host/engines/registry.js +30 -0
  237. package/dist/host/engines/types.d.ts +58 -0
  238. package/dist/host/engines/types.js +1 -0
  239. package/dist/host/engines/windows-sandbox/engine.d.ts +16 -0
  240. package/dist/host/engines/windows-sandbox/engine.js +63 -0
  241. package/dist/host/engines/windows-sandbox/wsb-text.d.ts +2 -0
  242. package/dist/host/engines/windows-sandbox/wsb-text.js +29 -0
  243. package/dist/host/launch/generate.d.ts +5 -1
  244. package/dist/host/launch/generate.js +50 -8
  245. package/dist/host/launch/index.d.ts +3 -1
  246. package/dist/host/launch/index.js +3 -1
  247. package/dist/host/launch/launch-plan.d.ts +13 -0
  248. package/dist/host/launch/launch-plan.js +26 -0
  249. package/dist/host/launch/mappings.js +2 -1
  250. package/dist/host/launch/risk-notes.d.ts +10 -0
  251. package/dist/host/launch/risk-notes.js +18 -0
  252. package/dist/host/launch/session-file.d.ts +2 -0
  253. package/dist/host/launch/session-file.js +7 -1
  254. package/dist/host/launch/wsb-file.d.ts +28 -4
  255. package/dist/host/launch/wsb-file.js +61 -42
  256. package/dist/host/life/crash-report.d.ts +27 -1
  257. package/dist/host/life/crash-report.js +173 -7
  258. package/dist/host/life/host-memory.d.ts +41 -0
  259. package/dist/host/life/host-memory.js +140 -0
  260. package/dist/host/life/index.d.ts +2 -0
  261. package/dist/host/life/index.js +2 -0
  262. package/dist/host/life/stop-events.d.ts +2 -0
  263. package/dist/host/life/stop-events.js +20 -3
  264. package/dist/host/life/stop-warning.js +1 -1
  265. package/dist/host/life/watchdog.d.ts +56 -0
  266. package/dist/host/life/watchdog.js +124 -0
  267. package/dist/host/native.d.ts +3 -2
  268. package/dist/host/native.js +22 -3
  269. package/dist/host/profile/claude-login.js +3 -2
  270. package/dist/host/sandbox/contained-deps.d.ts +2 -0
  271. package/dist/host/sandbox/contained-deps.js +17 -0
  272. package/dist/host/sandbox/index.d.ts +2 -0
  273. package/dist/host/sandbox/index.js +2 -0
  274. package/dist/host/sandbox/platform.d.ts +2 -0
  275. package/dist/host/sandbox/platform.js +7 -7
  276. package/dist/host/sandbox/tasklist.d.ts +13 -0
  277. package/dist/host/sandbox/tasklist.js +47 -0
  278. package/dist/host/secrets/launch-secrets.js +2 -1
  279. package/dist/host/sharing/current.js +2 -6
  280. package/dist/host/storage/contained/check.d.ts +9 -0
  281. package/dist/host/storage/contained/check.js +37 -0
  282. package/dist/host/storage/contained/contained-storage.d.ts +66 -0
  283. package/dist/host/storage/contained/contained-storage.js +168 -0
  284. package/dist/host/storage/contained/disk-port.d.ts +43 -0
  285. package/dist/host/storage/contained/disk-port.js +122 -0
  286. package/dist/host/storage/contained/index.d.ts +9 -0
  287. package/dist/host/storage/contained/index.js +8 -0
  288. package/dist/host/storage/contained/layout.d.ts +28 -0
  289. package/dist/host/storage/contained/layout.js +45 -0
  290. package/dist/host/storage/contained/resolve.d.ts +4 -0
  291. package/dist/host/storage/contained/resolve.js +30 -0
  292. package/dist/host/storage/contained/setting.d.ts +1 -0
  293. package/dist/host/storage/contained/setting.js +5 -0
  294. package/dist/host/storage/contained/state.d.ts +89 -0
  295. package/dist/host/storage/contained/state.js +166 -0
  296. package/dist/host/storage/contained/transfer.d.ts +24 -0
  297. package/dist/host/storage/contained/transfer.js +121 -0
  298. package/dist/host/storage/index.d.ts +2 -0
  299. package/dist/host/storage/index.js +2 -0
  300. package/dist/host/storage/providers/contained.d.ts +15 -0
  301. package/dist/host/storage/providers/contained.js +39 -0
  302. package/dist/host/storage/providers/folder.d.ts +12 -0
  303. package/dist/host/storage/providers/folder.js +20 -0
  304. package/dist/host/storage/providers/index.d.ts +4 -0
  305. package/dist/host/storage/providers/index.js +3 -0
  306. package/dist/host/storage/providers/registry.d.ts +9 -0
  307. package/dist/host/storage/providers/registry.js +14 -0
  308. package/dist/host/storage/providers/types.d.ts +33 -0
  309. package/dist/host/storage/providers/types.js +1 -0
  310. package/dist/host/tools/conpty.js +3 -2
  311. package/dist/host/tools/windows-terminal.js +8 -7
  312. package/dist/host/vpn/index.d.ts +1 -1
  313. package/dist/host/vpn/index.js +1 -1
  314. package/dist/host/vpn/prepare.d.ts +2 -0
  315. package/dist/host/vpn/prepare.js +63 -2
  316. package/dist/host/web/browser.d.ts +2 -0
  317. package/dist/host/web/browser.js +14 -1
  318. package/dist/host/web/index.d.ts +3 -2
  319. package/dist/host/web/index.js +3 -2
  320. package/dist/host/web/rpc.d.ts +24 -0
  321. package/dist/host/web/rpc.js +149 -0
  322. package/dist/host/web/runner.d.ts +2 -0
  323. package/dist/host/web/runner.js +1 -2
  324. package/dist/host/web/server.d.ts +7 -0
  325. package/dist/host/web/server.js +23 -3
  326. package/dist/runtime/agent.js +83 -18
  327. package/dist/runtime/daemon.js +1805 -1221
  328. package/dist/runtime/db.js +83 -18
  329. package/dist/runtime/main.js +779 -219
  330. package/dist/runtime/netproxy.js +73 -11
  331. package/dist/runtime/view.js +91 -16
  332. package/dist/selftest/agent-paths.test.js +11 -1
  333. package/dist/selftest/app.test.d.ts +2 -0
  334. package/dist/selftest/app.test.js +324 -0
  335. package/dist/selftest/channel.test.js +13 -0
  336. package/dist/selftest/cli.test.js +2 -1
  337. package/dist/selftest/config.test.js +59 -0
  338. package/dist/selftest/contained.test.d.ts +2 -0
  339. package/dist/selftest/contained.test.js +544 -0
  340. package/dist/selftest/credentials.test.js +1 -1
  341. package/dist/selftest/engine.test.d.ts +2 -0
  342. package/dist/selftest/engine.test.js +127 -0
  343. package/dist/selftest/guest-boot.test.js +47 -1
  344. package/dist/selftest/hcs.test.d.ts +2 -0
  345. package/dist/selftest/hcs.test.js +482 -0
  346. package/dist/selftest/heavy-load.test.d.ts +2 -0
  347. package/dist/selftest/heavy-load.test.js +355 -0
  348. package/dist/selftest/index.js +12 -0
  349. package/dist/selftest/layout.test.js +12 -0
  350. package/dist/selftest/menu-perf.test.d.ts +2 -0
  351. package/dist/selftest/menu-perf.test.js +248 -0
  352. package/dist/selftest/menu-screens.js +4 -2
  353. package/dist/selftest/menu.test.js +36 -8
  354. package/dist/selftest/network.test.js +20 -1
  355. package/dist/selftest/support/engine-cases.d.ts +8 -0
  356. package/dist/selftest/support/engine-cases.js +65 -0
  357. package/dist/selftest/support/engine-golden.d.ts +3 -0
  358. package/dist/selftest/support/engine-golden.js +66 -0
  359. package/dist/selftest/support/fixtures.d.ts +8 -1
  360. package/dist/selftest/support/hcs-probes.d.ts +17 -0
  361. package/dist/selftest/support/hcs-probes.js +41 -0
  362. package/dist/selftest/vpn.test.js +136 -3
  363. package/dist/selftest/web.test.js +101 -3
  364. package/dist/shared/channel/run-dir.d.ts +4 -1
  365. package/dist/shared/channel/run-dir.js +7 -1
  366. package/dist/shared/channel/schema.d.ts +35 -1
  367. package/dist/shared/channel/schema.js +27 -0
  368. package/dist/shared/channel/secrets.d.ts +1 -0
  369. package/dist/shared/channel/secrets.js +6 -0
  370. package/dist/shared/io/copy-tree.d.ts +7 -0
  371. package/dist/shared/io/copy-tree.js +45 -0
  372. package/dist/shared/io/index.d.ts +2 -0
  373. package/dist/shared/io/index.js +2 -0
  374. package/dist/shared/io/robocopy-result.d.ts +6 -0
  375. package/dist/shared/io/robocopy-result.js +23 -0
  376. package/dist/shared/memory/index.d.ts +1 -0
  377. package/dist/shared/memory/index.js +1 -0
  378. package/dist/shared/memory/policy.d.ts +38 -0
  379. package/dist/shared/memory/policy.js +63 -0
  380. package/dist/shared/network/firewall-rules.d.ts +8 -0
  381. package/dist/shared/network/firewall-rules.js +28 -0
  382. package/dist/shared/pty/output-filter.d.ts +14 -1
  383. package/dist/shared/pty/output-filter.js +22 -4
  384. package/dist/shared/pty/terminal.d.ts +4 -1
  385. package/dist/shared/pty/terminal.js +4 -2
  386. package/dist/shared/system.d.ts +1 -0
  387. package/dist/shared/system.js +1 -0
  388. package/dist/shared/vpn/download.d.ts +16 -0
  389. package/dist/shared/vpn/download.js +16 -0
  390. package/dist/shared/vpn/wireguard.d.ts +51 -0
  391. package/dist/shared/vpn/wireguard.js +227 -0
  392. package/dist/sync/sync-cycle.js +5 -5
  393. package/dist/sync/watcher.d.ts +13 -0
  394. package/dist/sync/watcher.js +92 -3
  395. package/dist/web/index.html +4 -3
  396. package/dist/web/main-NRRS5O6Z.js +157 -0
  397. package/dist/web/main-T5DMCHYV.css +1 -0
  398. package/native/csharp/HcsHost/AssemblyInfo.cs +14 -0
  399. package/native/csharp/HcsHost/Guard.cs +100 -0
  400. package/native/csharp/HcsHost/Hcs.cs +256 -0
  401. package/native/csharp/HcsHost/Json.cs +78 -0
  402. package/native/csharp/HcsHost/Program.cs +185 -0
  403. package/native/csharp/HcsHost/VirtualDisk.cs +95 -0
  404. package/native/csharp/HostTools/AssemblyInfo.cs +14 -0
  405. package/native/csharp/HostTools/MemoryStatus.cs +128 -0
  406. package/native/csharp/HostTools/Program.cs +58 -17
  407. package/native/scripts/check-contained.ps1 +28 -0
  408. package/native/scripts/contained-common.ps1 +241 -0
  409. package/native/scripts/dismount-contained.ps1 +66 -0
  410. package/native/scripts/memory-status.ps1 +42 -0
  411. package/native/scripts/mount-contained.ps1 +139 -0
  412. package/native/scripts/run-elevated.ps1 +17 -4
  413. package/native/scripts/stop-events.ps1 +23 -8
  414. package/package.json +9 -2
  415. package/sandbox/csharp/MemGov.cs +466 -0
  416. package/sandbox/csharp/PtyHost.cs +111 -5
  417. package/sandbox/scripts/new-shortcuts.ps1 +3 -1
  418. package/schemas/config.schema.json +66 -8
  419. package/schemas/sandbox-config.schema.json +3 -3
  420. package/dist/cli/commands/sessions/control.d.ts +0 -4
  421. package/dist/cli/commands/sessions/control.js +0 -66
  422. package/dist/cli/commands/sessions/list.d.ts +0 -2
  423. package/dist/cli/commands/sessions/list.js +0 -48
  424. package/dist/cli/commands/sessions/status.d.ts +0 -4
  425. package/dist/cli/commands/sessions/status.js +0 -114
  426. package/dist/cli/commands/sessions/window.d.ts +0 -3
  427. package/dist/cli/commands/sessions/window.js +0 -18
  428. package/dist/cli/menu/settings/path-kind.js +0 -44
  429. package/dist/web/main-CXESL347.js +0 -45
  430. package/dist/web/main-VLR7DVQ4.css +0 -1
  431. /package/dist/{cli/menu/settings → app/kernel}/schema-node.d.ts +0 -0
  432. /package/dist/{cli/menu/settings → app/kernel}/schema-node.js +0 -0
@@ -0,0 +1,211 @@
1
+ /** Programs that compile or link: they may be slowed down and, as the last resort, paused for a few seconds. */
2
+ const COMPILERS = new Set([
3
+ 'rustc',
4
+ 'clippy-driver',
5
+ 'rustdoc',
6
+ 'cc1',
7
+ 'cc1plus',
8
+ 'cc1obj',
9
+ 'collect2',
10
+ 'gcc',
11
+ 'g++',
12
+ 'c++',
13
+ 'cc',
14
+ 'clang',
15
+ 'clang++',
16
+ 'clang-cl',
17
+ 'cl',
18
+ 'link',
19
+ 'lld',
20
+ 'lld-link',
21
+ 'ld',
22
+ 'ld.lld',
23
+ 'as',
24
+ 'tsc',
25
+ 'javac',
26
+ ]);
27
+ /** Build tools and workers: slowed down but never paused (a node process may be a dev server or an agent). */
28
+ const BUILD_TOOLS = new Set([
29
+ 'node',
30
+ 'dotnet',
31
+ 'msbuild',
32
+ 'vbcscompiler',
33
+ 'ninja',
34
+ 'make',
35
+ 'mingw32-make',
36
+ 'cmake',
37
+ 'cargo',
38
+ 'go',
39
+ 'java',
40
+ 'gradle',
41
+ 'python',
42
+ ]);
43
+ /** Never touched: the agents themselves, shells, terminals, this tool's own programs, Windows. */
44
+ const NEVER = new Set([
45
+ 'claude',
46
+ 'codex',
47
+ 'gemini',
48
+ 'opencode',
49
+ 'aider',
50
+ 'cursor-agent',
51
+ 'cmd',
52
+ 'powershell',
53
+ 'pwsh',
54
+ 'bash',
55
+ 'sh',
56
+ 'zsh',
57
+ 'git',
58
+ 'conhost',
59
+ 'openconsole',
60
+ 'windowsterminal',
61
+ 'wt',
62
+ 'ptyhost',
63
+ 'memgov',
64
+ 'sandboxtools',
65
+ 'sbx-db',
66
+ 'explorer',
67
+ 'csrss',
68
+ 'wininit',
69
+ 'winlogon',
70
+ 'services',
71
+ 'svchost',
72
+ 'lsass',
73
+ 'system',
74
+ 'smss',
75
+ 'dwm',
76
+ ]);
77
+ const key = (name) => name.toLowerCase().replace(/\.exe$/, '');
78
+ export const isNeverTouched = (name) => NEVER.has(key(name));
79
+ export const canLower = (name) => !isNeverTouched(name) && (COMPILERS.has(key(name)) || BUILD_TOOLS.has(key(name)));
80
+ /** The heavy ones the concurrency cap counts (drivers like gcc and collect2 only wait for these). */
81
+ const HEAVY = new Set([
82
+ 'rustc',
83
+ 'clippy-driver',
84
+ 'rustdoc',
85
+ 'cc1',
86
+ 'cc1plus',
87
+ 'clang',
88
+ 'clang++',
89
+ 'clang-cl',
90
+ 'cl',
91
+ 'link',
92
+ 'lld',
93
+ 'lld-link',
94
+ 'ld',
95
+ 'ld.lld',
96
+ ]);
97
+ export const isHeavyCompiler = (name) => !isNeverTouched(name) && HEAVY.has(key(name));
98
+ export const canPause = (name) => !isNeverTouched(name) && COMPILERS.has(key(name));
99
+ export const INITIAL_STATE = {
100
+ pressure: false,
101
+ calm: 0,
102
+ samples: 0,
103
+ lowered: {},
104
+ pausedUntil: 0,
105
+ nextPauseAt: 0,
106
+ hostUntil: 0,
107
+ };
108
+ /** How long a held compiler waits before it gets a turn again (the governor repeats the hold while over the cap). */
109
+ export const HOLD_MS = 3000;
110
+ export const PAUSE_MS = 5000;
111
+ const PAUSE_COOLDOWN_MS = 10000;
112
+ /** Samples under pressure before programs go from below-normal to idle, and before one is paused. */
113
+ const IDLE_AFTER = 3;
114
+ const PAUSE_AFTER = 4;
115
+ /** Only a program this big is worth pausing. */
116
+ const PAUSE_MIN_MB = 300;
117
+ /**
118
+ * One step. `gentle` (vGPU on): compilers start below normal even without pressure. Programs go back to their normal
119
+ * priority only when pressure ends (several calm samples in a row).
120
+ */
121
+ export function decide(prev, sample, nowMs, thresholds, profile, maxCompilers = null) {
122
+ const ramFree = (sample.ramAvailMb / Math.max(1, sample.ramTotalMb)) * 100;
123
+ const commit = ((sample.commitLimitMb - sample.commitAvailMb) / Math.max(1, sample.commitLimitMb)) * 100;
124
+ const pcLow = nowMs < prev.hostUntil;
125
+ const low = ramFree < thresholds.enterAvailablePercent || commit > thresholds.enterCommitPercent || pcLow;
126
+ const recovered = ramFree > thresholds.exitAvailablePercent && commit < thresholds.exitCommitPercent && !pcLow;
127
+ let pressure = prev.pressure;
128
+ let calm = prev.calm;
129
+ let samples = prev.samples;
130
+ if (low) {
131
+ pressure = true;
132
+ calm = 0;
133
+ samples = prev.samples + 1;
134
+ }
135
+ else if (prev.pressure) {
136
+ calm = recovered ? prev.calm + 1 : 0;
137
+ if (calm >= thresholds.calmSamples) {
138
+ pressure = false;
139
+ calm = 0;
140
+ samples = 0;
141
+ }
142
+ }
143
+ const actions = [];
144
+ const present = new Set(sample.procs.map((p) => p.pid));
145
+ const lowered = {};
146
+ for (const [pid, to] of Object.entries(prev.lowered))
147
+ if (present.has(Number(pid)))
148
+ lowered[Number(pid)] = to;
149
+ if (pressure) {
150
+ const target = samples > IDLE_AFTER ? 'idle' : 'below';
151
+ for (const p of sample.procs) {
152
+ if (!canLower(p.name) || lowered[p.pid] === target)
153
+ continue;
154
+ // Already as low as asked (or lower): only remember it.
155
+ if (p.prio !== target && !(target === 'below' && p.prio === 'idle'))
156
+ actions.push({ kind: 'priority', pid: p.pid, name: p.name, to: target });
157
+ lowered[p.pid] = target;
158
+ }
159
+ }
160
+ else {
161
+ for (const p of sample.procs) {
162
+ if (!canLower(p.name))
163
+ continue;
164
+ // Where a program rests when nothing is wrong: compilers below normal in the gentle profile.
165
+ const base = profile === 'gentle' && canPause(p.name) ? 'below' : 'normal';
166
+ const was = lowered[p.pid];
167
+ if (prev.pressure && was !== undefined && was !== base) {
168
+ if (p.prio !== base)
169
+ actions.push({ kind: 'priority', pid: p.pid, name: p.name, to: base });
170
+ if (base === 'normal')
171
+ delete lowered[p.pid];
172
+ else
173
+ lowered[p.pid] = base;
174
+ }
175
+ else if (!prev.pressure && base === 'below' && was === undefined) {
176
+ if (p.prio === 'normal')
177
+ actions.push({ kind: 'priority', pid: p.pid, name: p.name, to: 'below' });
178
+ lowered[p.pid] = 'below';
179
+ }
180
+ }
181
+ }
182
+ let pausedUntil = prev.pausedUntil;
183
+ let nextPauseAt = prev.nextPauseAt;
184
+ if (pressure && samples >= PAUSE_AFTER && nowMs >= prev.nextPauseAt && nowMs >= prev.pausedUntil) {
185
+ const victim = [...sample.procs]
186
+ .filter((p) => canPause(p.name) && p.mb >= PAUSE_MIN_MB)
187
+ .sort((a, b) => b.mb - a.mb)[0];
188
+ if (victim) {
189
+ actions.push({ kind: 'pause', pid: victim.pid, name: victim.name, ms: PAUSE_MS });
190
+ pausedUntil = nowMs + PAUSE_MS;
191
+ nextPauseAt = pausedUntil + PAUSE_COOLDOWN_MS;
192
+ }
193
+ }
194
+ // Concurrency cap (vGPU profile): the oldest N heavy compilers run, the newer ones wait a few seconds at a time.
195
+ if (maxCompilers !== null) {
196
+ const heavy = sample.procs
197
+ .filter((p) => isHeavyCompiler(p.name) &&
198
+ !(nowMs < pausedUntil && actions.some((a) => a.kind === 'pause' && a.pid === p.pid)))
199
+ .sort((a, b) => a.pid - b.pid);
200
+ for (const p of heavy.slice(Math.max(1, maxCompilers)))
201
+ actions.push({ kind: 'hold', pid: p.pid, name: p.name, ms: HOLD_MS });
202
+ }
203
+ const level = nowMs < pausedUntil ? 'suspending' : pressure ? 'throttled' : 'ok';
204
+ return {
205
+ state: { pressure, calm, samples, lowered, pausedUntil, nextPauseAt, hostUntil: prev.hostUntil },
206
+ actions,
207
+ level,
208
+ ramFreePercent: Math.round(ramFree),
209
+ commitPercent: Math.round(commit),
210
+ };
211
+ }
@@ -0,0 +1,45 @@
1
+ import type { PressureStatus } from '../../shared/channel/schema.js';
2
+ import { type LoadProfile } from '../../shared/memory/index.js';
3
+ import { type GovernorState, type MemSample } from './decide.js';
4
+ /** What the governor needs from Windows (injectable: the tests use a fake). */
5
+ export interface GovernorPort {
6
+ setPriority(pid: number, to: 'idle' | 'below' | 'normal'): void;
7
+ pause(pid: number, ms: number): void;
8
+ }
9
+ /** Everything a step changes outside the decision, behind injectable functions. */
10
+ export interface GovernorDeps {
11
+ readonly port: GovernorPort;
12
+ readonly profile: LoadProfile;
13
+ /** At most this many heavy compilers run at once (null = no cap). */
14
+ readonly maxCompilers?: number | null;
15
+ readonly now: () => number;
16
+ /** A line in the memory log. */
17
+ readonly logLine: (line: string) => void;
18
+ /** run\pressure.json. */
19
+ readonly saveStatus: (status: PressureStatus) => void;
20
+ }
21
+ /** The governor's logic over a port: feed it samples; the host's "slow down" requests go to hostPressure. */
22
+ export declare class GovernorCore {
23
+ private readonly deps;
24
+ private state;
25
+ private lastAction;
26
+ private lastWrite;
27
+ private lastWriteAt;
28
+ private pausedName;
29
+ private pausedPid;
30
+ private held;
31
+ constructor(deps: GovernorDeps);
32
+ hostPressure(seconds: number, reason: string): void;
33
+ get current(): GovernorState;
34
+ onSample(sample: MemSample): void;
35
+ private apply;
36
+ }
37
+ /** The daemon's governor: on unless sandbox.pressureResponse is off. */
38
+ export declare class Governor {
39
+ private core;
40
+ describe(): string;
41
+ start(): void;
42
+ /** The host's watchdog: this PC is low for a while. */
43
+ hostPressure(seconds: number, reason: string): void;
44
+ }
45
+ export declare const governor: Governor;
@@ -0,0 +1,230 @@
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 os from 'node:os';
6
+ import path from 'node:path';
7
+ import { spawn } from 'node:child_process';
8
+ import { createInterface } from 'node:readline';
9
+ import { z } from 'zod';
10
+ import { now } from '../../shared/channel/run-dir.js';
11
+ import { writeJsonAtomic } from '../../shared/io/json.js';
12
+ import { GUEST_THRESHOLDS, maxCompilers } from '../../shared/memory/index.js';
13
+ import { ensureCompiled } from '../runtime/csc.js';
14
+ import { dataDir } from '../runtime/paths.js';
15
+ import { warn } from '../runtime/log.js';
16
+ import { run } from '../runtime/paths.js';
17
+ import { session } from '../runtime/session.js';
18
+ import { errMsg } from '../../core/util/errors.js';
19
+ import { decide, INITIAL_STATE } from './decide.js';
20
+ const SampleSchema = z.object({
21
+ ramTotalMb: z.number(),
22
+ ramAvailMb: z.number(),
23
+ commitLimitMb: z.number(),
24
+ commitAvailMb: z.number(),
25
+ procs: z
26
+ .array(z.object({
27
+ pid: z.number().int(),
28
+ name: z.string().max(128),
29
+ mb: z.number(),
30
+ prio: z.enum(['idle', 'below', 'normal']).catch('normal'),
31
+ }))
32
+ .max(1024),
33
+ });
34
+ /** The governor's logic over a port: feed it samples; the host's "slow down" requests go to hostPressure. */
35
+ export class GovernorCore {
36
+ deps;
37
+ state = INITIAL_STATE;
38
+ lastAction = '';
39
+ lastWrite = '';
40
+ lastWriteAt = 0;
41
+ pausedName = '';
42
+ pausedPid = 0;
43
+ held = new Set();
44
+ constructor(deps) {
45
+ this.deps = deps;
46
+ }
47
+ hostPressure(seconds, reason) {
48
+ const until = this.deps.now() + seconds * 1000;
49
+ if (until > this.state.hostUntil) {
50
+ if (this.state.hostUntil <= this.deps.now())
51
+ this.deps.logLine('governor: this PC is low (' + reason + '); slowing builds down');
52
+ this.state = { ...this.state, hostUntil: until };
53
+ }
54
+ }
55
+ get current() {
56
+ return this.state;
57
+ }
58
+ onSample(sample) {
59
+ const nowMs = this.deps.now();
60
+ const before = this.state.pressure;
61
+ const seen = new Set(sample.procs.map((p) => p.pid));
62
+ for (const pid of this.held)
63
+ if (!seen.has(pid))
64
+ this.held.delete(pid);
65
+ const d = decide(this.state, sample, nowMs, GUEST_THRESHOLDS[this.deps.profile], this.deps.profile, this.deps.maxCompilers ?? null);
66
+ this.state = d.state;
67
+ for (const action of d.actions)
68
+ this.apply(action);
69
+ if (d.state.pressure !== before)
70
+ this.deps.logLine(d.state.pressure
71
+ ? 'governor: memory is low (' +
72
+ d.ramFreePercent +
73
+ '% RAM free, commit ' +
74
+ d.commitPercent +
75
+ '% used): slowing builds down'
76
+ : 'governor: memory is fine again: builds back to normal');
77
+ const paused = nowMs < d.state.pausedUntil && this.pausedPid
78
+ ? [{ name: this.pausedName, pid: this.pausedPid, seconds: Math.ceil((d.state.pausedUntil - nowMs) / 1000) }]
79
+ : [];
80
+ const status = {
81
+ level: d.level,
82
+ profile: this.deps.profile,
83
+ ramFreePercent: Math.max(0, Math.min(100, d.ramFreePercent)),
84
+ commitPercent: Math.max(0, Math.min(100, d.commitPercent)),
85
+ lowered: Object.keys(d.state.lowered).length,
86
+ paused,
87
+ pcLow: nowMs < d.state.hostUntil,
88
+ lastAction: this.lastAction,
89
+ updatedAt: now(),
90
+ };
91
+ // Written when something changed, else once a minute (the host reads it, never polls it hard).
92
+ const shape = JSON.stringify({ ...status, updatedAt: '', paused: paused.map((p) => p.pid) });
93
+ if (shape !== this.lastWrite || nowMs - this.lastWriteAt > 60000) {
94
+ this.lastWrite = shape;
95
+ this.lastWriteAt = nowMs;
96
+ this.deps.saveStatus(status);
97
+ }
98
+ }
99
+ apply(action) {
100
+ try {
101
+ if (action.kind === 'hold') {
102
+ this.deps.port.pause(action.pid, action.ms);
103
+ if (!this.held.has(action.pid)) {
104
+ this.held.add(action.pid);
105
+ this.lastAction = 'holding ' + action.name + ' (' + action.pid + ') until another compiler ends';
106
+ this.deps.logLine('governor: ' + this.lastAction);
107
+ }
108
+ return;
109
+ }
110
+ if (action.kind === 'priority') {
111
+ this.deps.port.setPriority(action.pid, action.to);
112
+ this.lastAction = action.name + ' (' + action.pid + ') priority ' + action.to;
113
+ }
114
+ else {
115
+ this.deps.port.pause(action.pid, action.ms);
116
+ this.pausedName = action.name;
117
+ this.pausedPid = action.pid;
118
+ this.lastAction = 'paused ' + action.name + ' (' + action.pid + ') for ' + action.ms / 1000 + ' s';
119
+ this.deps.logLine('governor: ' + this.lastAction);
120
+ return;
121
+ }
122
+ this.deps.logLine('governor: ' + this.lastAction);
123
+ }
124
+ catch (e) {
125
+ warn('governor: ' + errMsg(e));
126
+ }
127
+ }
128
+ }
129
+ /** memgov.exe as a child process: samples come out of its stdout, commands go into its stdin. */
130
+ class MemGovProcess {
131
+ onSample;
132
+ child = null;
133
+ constructor(onSample) {
134
+ this.onSample = onSample;
135
+ }
136
+ start() {
137
+ try {
138
+ const child = spawn(ensureCompiled('memgov'), ['serve', '--interval', '2'], {
139
+ stdio: ['pipe', 'pipe', 'ignore'],
140
+ windowsHide: true,
141
+ });
142
+ this.child = child;
143
+ createInterface({ input: child.stdout }).on('line', (line) => {
144
+ try {
145
+ this.onSample(SampleSchema.parse(JSON.parse(line)));
146
+ }
147
+ catch (e) {
148
+ warn('governor: bad sample: ' + errMsg(e));
149
+ }
150
+ });
151
+ child.stdin.on('error', () => undefined);
152
+ child.once('exit', () => {
153
+ this.child = null;
154
+ // It ends only when something is wrong: try again in a while.
155
+ setTimeout(() => this.start(), 30000).unref();
156
+ });
157
+ }
158
+ catch (e) {
159
+ warn('governor: could not start memgov.exe (no memory governor): ' + errMsg(e));
160
+ }
161
+ }
162
+ setPriority(pid, to) {
163
+ this.child?.stdin?.write('priority ' + pid + ' ' + to + '\n');
164
+ }
165
+ pause(pid, ms) {
166
+ this.child?.stdin?.write('suspend ' + pid + ' ' + ms + '\n');
167
+ }
168
+ }
169
+ /** The newest memory log SandboxTools writes, to add the governor's lines to it. */
170
+ function appendToMemoryLog(line) {
171
+ try {
172
+ const logs = path.join(dataDir, 'logs');
173
+ const newest = fs
174
+ .readdirSync(logs)
175
+ .filter((f) => /^memory-\d{8}-\d{6}\.log$/.test(f))
176
+ .sort()
177
+ .pop();
178
+ if (!newest)
179
+ return;
180
+ const t = new Date();
181
+ const stamp = [t.getHours(), t.getMinutes(), t.getSeconds()].map((n) => String(n).padStart(2, '0')).join(':');
182
+ fs.appendFileSync(path.join(logs, newest), stamp + ' | ' + line + '\r\n');
183
+ }
184
+ catch {
185
+ // The log is for people; a missing or locked one never matters.
186
+ }
187
+ }
188
+ /** The daemon's governor: on unless sandbox.pressureResponse is off. */
189
+ export class Governor {
190
+ core = null;
191
+ describe() {
192
+ const profile = session.loadProfile === 'gentle' ? 'gentle' : 'normal';
193
+ const t = GUEST_THRESHOLDS[profile];
194
+ return session.pressureResponse === false
195
+ ? 'off (sandbox.pressureResponse)'
196
+ : profile +
197
+ ' profile: slows builds down below ' +
198
+ t.enterAvailablePercent +
199
+ '% free RAM or above ' +
200
+ t.enterCommitPercent +
201
+ '% commit';
202
+ }
203
+ start() {
204
+ if (session.pressureResponse === false)
205
+ return;
206
+ const profile = session.loadProfile === 'gentle' ? 'gentle' : 'normal';
207
+ const proc = new MemGovProcess((s) => this.core?.onSample(s));
208
+ this.core = new GovernorCore({
209
+ port: proc,
210
+ profile,
211
+ maxCompilers: maxCompilers(os.cpus().length, profile),
212
+ now: () => Date.now(),
213
+ logLine: appendToMemoryLog,
214
+ saveStatus: (status) => {
215
+ try {
216
+ writeJsonAtomic(run.pressureFile, status);
217
+ }
218
+ catch (e) {
219
+ warn('governor: could not write its status: ' + errMsg(e));
220
+ }
221
+ },
222
+ });
223
+ proc.start();
224
+ }
225
+ /** The host's watchdog: this PC is low for a while. */
226
+ hostPressure(seconds, reason) {
227
+ this.core?.hostPressure(seconds, reason);
228
+ }
229
+ }
230
+ 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';
@@ -1,5 +1,6 @@
1
1
  /** What the agent's manifest says about the LAN. */
2
2
  export type LanState = 'blocked' | 'open' | 'offline';
3
+ export declare function networkProblems(): readonly string[];
3
4
  export declare function run(commands: string[][]): void;
4
5
  /**
5
6
  * Applies the LAN block. Internet is checked first; if it works before the rules but not after, the rules (not the
@@ -4,14 +4,13 @@ import fs from 'node:fs';
4
4
  import path from 'node:path';
5
5
  import { spawnSync } from 'node:child_process';
6
6
  import { relayPort, withBlockedHosts } from '../../shared/network/policy.js';
7
- import { buildFirewallCommands, ipv4DnsServers, isIPv4, parseDefaultGateways, parseDnsServers, } from '../../shared/network/firewall-rules.js';
7
+ import { attachRuleCommands, buildFirewallCommands, hasShortName, ipv4DnsServers, isIPv4, parseDefaultGateways, parseDnsServers, } from '../../shared/network/firewall-rules.js';
8
8
  import { SYSTEM } from '../../shared/system.js';
9
9
  import { scriptArgs } from '../../shared/scripts.js';
10
10
  import { dryRun, isWin } from '../runtime/paths.js';
11
11
  import { log, warn } from '../runtime/log.js';
12
12
  import { session } from '../runtime/session.js';
13
13
  import { errMsg } from '../../core/util/errors.js';
14
- const ATTACH_RULE = 'AgentSandbox-Attach';
15
14
  const netsh = (args) => {
16
15
  const r = spawnSync(SYSTEM.netsh(), args, { encoding: 'utf8', windowsHide: true });
17
16
  return { status: r.status, out: (r.stdout ?? '') + (r.stderr ?? '') };
@@ -51,24 +50,49 @@ const waitForInternet = async (seconds) => {
51
50
  }
52
51
  return false;
53
52
  };
54
- /** Inbound rule for ptyhost only, and only from the sandbox's own subnet (where the host's Hyper-V adapter is). */
55
- const attachRule = (ptyHostExe) => [
56
- ['advfirewall', 'firewall', 'delete', 'rule', 'name=' + ATTACH_RULE],
57
- [
58
- 'advfirewall',
59
- 'firewall',
60
- 'add',
61
- 'rule',
62
- 'name=' + ATTACH_RULE,
63
- 'dir=in',
64
- 'action=allow',
65
- 'enable=yes',
66
- 'profile=any',
67
- 'protocol=tcp',
68
- 'remoteip=LocalSubnet',
69
- 'program=' + ptyHostExe,
70
- ],
71
- ];
53
+ /** Protections that could not be put in place this boot (shown in the boot summary and the log, never silent). */
54
+ const problems = [];
55
+ export function networkProblems() {
56
+ return problems;
57
+ }
58
+ /** netsh needs the long form of a path: the sandbox's TEMP is an 8.3 short path (WDAGUT~1). */
59
+ const longPath = (file) => {
60
+ if (!hasShortName(file))
61
+ return file;
62
+ try {
63
+ return fs.realpathSync.native(file);
64
+ }
65
+ catch {
66
+ return file;
67
+ }
68
+ };
69
+ /**
70
+ * The inbound rule for ptyhost (the attach channel). A rule that cannot be added is a missing protection, so it is
71
+ * tried again a few times and then reported loudly instead of being skipped.
72
+ */
73
+ async function applyAttachRule(ptyHostExe) {
74
+ if (!session.attach.enabled)
75
+ return;
76
+ if (!ptyHostExe) {
77
+ problems.push('attach: the session host was not built, so the firewall rule for it was not created');
78
+ warn(problems[problems.length - 1]);
79
+ return;
80
+ }
81
+ let last = '';
82
+ for (let attempt = 1; attempt <= 3; attempt++) {
83
+ try {
84
+ run(attachRuleCommands(longPath(ptyHostExe)));
85
+ return;
86
+ }
87
+ catch (e) {
88
+ last = errMsg(e);
89
+ if (attempt < 3)
90
+ await new Promise((r) => setTimeout(r, 1000));
91
+ }
92
+ }
93
+ problems.push('attach: the firewall rule for the session host could not be created (' + last + ')');
94
+ warn('PROTECTION MISSING: ' + problems[problems.length - 1]);
95
+ }
72
96
  export function run(commands) {
73
97
  for (const c of commands) {
74
98
  const r = netsh(c);
@@ -89,10 +113,11 @@ export async function applyNetworkPolicy(ptyHostExe) {
89
113
  const block = session.network.blockPrivateRanges;
90
114
  const exempt = block ? discoverExemptIps() : [];
91
115
  const lanRules = block ? buildFirewallCommands(exempt) : [];
116
+ const forwardRules = forwardRule();
92
117
  const commands = [
93
118
  ...lanRules,
94
- ...(ptyHostExe && session.attach.enabled ? attachRule(ptyHostExe) : []),
95
- ...forwardRule(),
119
+ ...(ptyHostExe && session.attach.enabled ? attachRuleCommands(ptyHostExe) : []),
120
+ ...forwardRules,
96
121
  ];
97
122
  if (isWin && !dryRun) {
98
123
  try {
@@ -122,7 +147,24 @@ export async function applyNetworkPolicy(ptyHostExe) {
122
147
  if (commands.length === 0)
123
148
  return 'open';
124
149
  const online = block ? await waitForInternet(30) : true;
125
- run(commands);
150
+ // Each group on its own: one failing must not skip the others (or the internet check below).
151
+ const failures = [];
152
+ try {
153
+ run(lanRules);
154
+ }
155
+ catch (e) {
156
+ failures.push(errMsg(e));
157
+ }
158
+ await applyAttachRule(ptyHostExe);
159
+ try {
160
+ run(forwardRules);
161
+ }
162
+ catch (e) {
163
+ problems.push('forwardPorts: the firewall rule for the relays could not be created (' + errMsg(e) + ')');
164
+ warn('PROTECTION MISSING: ' + problems[problems.length - 1]);
165
+ }
166
+ if (failures.length)
167
+ throw new Error(failures[0]);
126
168
  if (!block)
127
169
  return 'open';
128
170
  if (online && !(await waitForInternet(15))) {
@@ -7,6 +7,7 @@ declare const SOURCES: {
7
7
  readonly cargoshim: "CargoShim.cs";
8
8
  readonly linkgate: "LinkGate.cs";
9
9
  readonly pathsync: "PathSync.cs";
10
+ readonly memgov: "MemGov.cs";
10
11
  };
11
12
  export type Helper = keyof typeof SOURCES;
12
13
  /** %TEMP%\agent-sandbox\<name>-<hash>.exe, compiled from this launch's source the first time it is needed. */
@@ -20,6 +20,7 @@ const SOURCES = {
20
20
  cargoshim: 'CargoShim.cs',
21
21
  linkgate: 'LinkGate.cs',
22
22
  pathsync: 'PathSync.cs',
23
+ memgov: 'MemGov.cs',
23
24
  };
24
25
  function sourceOf(name) {
25
26
  return path.join(launchDir, 'sandbox', 'csharp', SOURCES[name]);