windows-development-sandbox 1.7.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 (413) hide show
  1. package/config.example.json +10 -0
  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 +47 -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 +19 -3
  82. package/dist/cli/commands/web.js +2 -0
  83. package/dist/cli/index.js +2 -1
  84. package/dist/cli/manifest.d.ts +72 -104
  85. package/dist/cli/manifest.js +64 -39
  86. package/dist/cli/menu/add-agent.d.ts +1 -1
  87. package/dist/cli/menu/add-agent.js +1 -1
  88. package/dist/cli/menu/apps.d.ts +7 -1
  89. package/dist/cli/menu/apps.js +36 -0
  90. package/dist/cli/menu/command-fields.d.ts +1 -1
  91. package/dist/cli/menu/command-form.js +2 -2
  92. package/dist/cli/menu/io-menu.d.ts +29 -0
  93. package/dist/cli/menu/io-menu.js +126 -0
  94. package/dist/cli/menu/live.d.ts +27 -0
  95. package/dist/cli/menu/live.js +69 -0
  96. package/dist/cli/menu/memory.d.ts +19 -0
  97. package/dist/cli/menu/memory.js +53 -0
  98. package/dist/cli/menu/menu.d.ts +10 -1
  99. package/dist/cli/menu/menu.js +27 -9
  100. package/dist/cli/menu/pages/agents-page.d.ts +3 -1
  101. package/dist/cli/menu/pages/agents-page.js +12 -5
  102. package/dist/cli/menu/pages/apps-page.d.ts +3 -1
  103. package/dist/cli/menu/pages/apps-page.js +19 -2
  104. package/dist/cli/menu/pages/list-page.d.ts +27 -0
  105. package/dist/cli/menu/pages/list-page.js +109 -7
  106. package/dist/cli/menu/pages/maintenance-page.d.ts +0 -5
  107. package/dist/cli/menu/pages/maintenance-page.js +17 -19
  108. package/dist/cli/menu/pages/sandbox-page.d.ts +4 -6
  109. package/dist/cli/menu/pages/sandbox-page.js +26 -118
  110. package/dist/cli/menu/pages/scopes.d.ts +1 -1
  111. package/dist/cli/menu/pages/sessions-page.d.ts +5 -11
  112. package/dist/cli/menu/pages/sessions-page.js +19 -88
  113. package/dist/cli/menu/pages/settings-page.d.ts +2 -10
  114. package/dist/cli/menu/pages/settings-page.js +64 -94
  115. package/dist/cli/menu/render-view.d.ts +28 -0
  116. package/dist/cli/menu/render-view.js +112 -0
  117. package/dist/cli/menu/settings/{path-kind.d.ts → ask-path.d.ts} +1 -7
  118. package/dist/cli/menu/settings/ask-path.js +14 -0
  119. package/dist/cli/menu/settings/collections/collection-editor.d.ts +1 -1
  120. package/dist/cli/menu/settings/collections/string-list-editor.d.ts +1 -2
  121. package/dist/cli/menu/settings/collections/string-list-editor.js +1 -1
  122. package/dist/cli/menu/settings/draft.d.ts +1 -1
  123. package/dist/cli/menu/settings/format.d.ts +1 -3
  124. package/dist/cli/menu/settings/format.js +6 -36
  125. package/dist/cli/menu/settings/index.d.ts +1 -3
  126. package/dist/cli/menu/settings/index.js +3 -3
  127. package/dist/cli/menu/settings/object-editor.d.ts +1 -1
  128. package/dist/cli/menu/settings/share.d.ts +36 -0
  129. package/dist/cli/menu/settings/share.js +131 -0
  130. package/dist/cli/menu/settings/value-editor.d.ts +5 -1
  131. package/dist/cli/menu/settings/value-editor.js +57 -54
  132. package/dist/cli/menu/several.js +1 -1
  133. package/dist/cli/menu/share-settings.d.ts +21 -0
  134. package/dist/cli/menu/share-settings.js +112 -0
  135. package/dist/cli/menu/shell.d.ts +21 -5
  136. package/dist/cli/menu/shell.js +31 -6
  137. package/dist/cli/menu/views.d.ts +7 -0
  138. package/dist/cli/menu/views.js +11 -0
  139. package/dist/cli/menu/vpn-login.js +8 -0
  140. package/dist/cli/operations/handler.d.ts +6 -0
  141. package/dist/cli/operations/handler.js +61 -0
  142. package/dist/cli/operations/index.d.ts +4 -0
  143. package/dist/cli/operations/index.js +5 -0
  144. package/dist/cli/operations/input.d.ts +6 -0
  145. package/dist/cli/operations/input.js +37 -0
  146. package/dist/cli/operations/io-cli.d.ts +7 -0
  147. package/dist/cli/operations/io-cli.js +62 -0
  148. package/dist/cli/operations/spec.d.ts +18 -0
  149. package/dist/cli/operations/spec.js +108 -0
  150. package/dist/cli/output/colors.d.ts +2 -2
  151. package/dist/cli/output/colors.js +2 -11
  152. package/dist/cli/output/index.d.ts +1 -0
  153. package/dist/cli/output/index.js +1 -0
  154. package/dist/cli/output/print.d.ts +3 -1
  155. package/dist/cli/output/print.js +7 -3
  156. package/dist/cli/output/progress.d.ts +15 -0
  157. package/dist/cli/output/progress.js +44 -0
  158. package/dist/cli/output/render-view.d.ts +4 -0
  159. package/dist/cli/output/render-view.js +63 -0
  160. package/dist/cli/services/agent-commands-service.d.ts +2 -0
  161. package/dist/cli/services/agent-commands-service.js +11 -2
  162. package/dist/cli/services/logs-service.js +4 -3
  163. package/dist/cli/tui/app.d.ts +6 -1
  164. package/dist/cli/tui/app.js +26 -4
  165. package/dist/cli/tui/list/list-screen.d.ts +14 -0
  166. package/dist/cli/tui/list/list-screen.js +64 -36
  167. package/dist/cli/tui/list/list-types.d.ts +2 -0
  168. package/dist/cli/tui/terminal.d.ts +7 -0
  169. package/dist/cli/tui/terminal.js +30 -10
  170. package/dist/core/config/defaults.js +8 -0
  171. package/dist/core/schema/config.d.ts +13 -0
  172. package/dist/core/schema/config.js +16 -1
  173. package/dist/core/schema/harness.d.ts +1 -0
  174. package/dist/core/schema/harness.js +5 -0
  175. package/dist/core/schema/sandbox.d.ts +6 -0
  176. package/dist/core/schema/sandbox.js +20 -3
  177. package/dist/core/schema/vpn.d.ts +2 -1
  178. package/dist/core/schema/vpn.js +3 -3
  179. package/dist/core/types.d.ts +23 -5
  180. package/dist/core/util/fs.d.ts +2 -0
  181. package/dist/core/util/fs.js +9 -0
  182. package/dist/core/util/index.d.ts +1 -1
  183. package/dist/core/util/index.js +1 -1
  184. package/dist/guest/agents/agent-files.d.ts +5 -0
  185. package/dist/guest/agents/agent-files.js +4 -0
  186. package/dist/guest/agents/local-state.d.ts +2 -0
  187. package/dist/guest/agents/local-state.js +21 -1
  188. package/dist/guest/boot/boot.js +2 -1
  189. package/dist/guest/daemon/daemon.js +4 -0
  190. package/dist/guest/daemon/sessions.d.ts +5 -0
  191. package/dist/guest/daemon/sessions.js +17 -3
  192. package/dist/guest/entries/daemon.js +3 -0
  193. package/dist/guest/governor/decide.d.ts +61 -0
  194. package/dist/guest/governor/decide.js +182 -0
  195. package/dist/guest/governor/governor.d.ts +42 -0
  196. package/dist/guest/governor/governor.js +214 -0
  197. package/dist/guest/governor/index.d.ts +2 -0
  198. package/dist/guest/governor/index.js +2 -0
  199. package/dist/guest/runtime/csc.d.ts +1 -0
  200. package/dist/guest/runtime/csc.js +1 -0
  201. package/dist/guest/sessions/viewer.js +3 -1
  202. package/dist/guest/toolchains/native/rust-extras.js +4 -2
  203. package/dist/guest/vpn/vpn.js +69 -21
  204. package/dist/guest/vpn/wireguard.d.ts +32 -0
  205. package/dist/guest/vpn/wireguard.js +132 -0
  206. package/dist/host/agent-commands/commands.d.ts +4 -0
  207. package/dist/host/agent-commands/commands.js +31 -7
  208. package/dist/host/audit/log.d.ts +1 -1
  209. package/dist/host/channel/attach.d.ts +3 -1
  210. package/dist/host/channel/attach.js +5 -2
  211. package/dist/host/channel/channel.d.ts +2 -0
  212. package/dist/host/channel/channel.js +4 -0
  213. package/dist/host/engines/engine.d.ts +12 -0
  214. package/dist/host/engines/engine.js +1 -0
  215. package/dist/host/engines/hcs/check.d.ts +25 -0
  216. package/dist/host/engines/hcs/check.js +95 -0
  217. package/dist/host/engines/hcs/documents.d.ts +44 -0
  218. package/dist/host/engines/hcs/documents.js +155 -0
  219. package/dist/host/engines/hcs/engine.d.ts +39 -0
  220. package/dist/host/engines/hcs/engine.js +171 -0
  221. package/dist/host/engines/hcs/helper.d.ts +43 -0
  222. package/dist/host/engines/hcs/helper.js +173 -0
  223. package/dist/host/engines/hcs/images.d.ts +37 -0
  224. package/dist/host/engines/hcs/images.js +152 -0
  225. package/dist/host/engines/index.d.ts +7 -0
  226. package/dist/host/engines/index.js +5 -0
  227. package/dist/host/engines/registry.d.ts +16 -0
  228. package/dist/host/engines/registry.js +30 -0
  229. package/dist/host/engines/types.d.ts +58 -0
  230. package/dist/host/engines/types.js +1 -0
  231. package/dist/host/engines/windows-sandbox/engine.d.ts +16 -0
  232. package/dist/host/engines/windows-sandbox/engine.js +63 -0
  233. package/dist/host/engines/windows-sandbox/wsb-text.d.ts +2 -0
  234. package/dist/host/engines/windows-sandbox/wsb-text.js +29 -0
  235. package/dist/host/launch/generate.d.ts +5 -1
  236. package/dist/host/launch/generate.js +50 -8
  237. package/dist/host/launch/index.d.ts +3 -1
  238. package/dist/host/launch/index.js +3 -1
  239. package/dist/host/launch/launch-plan.d.ts +13 -0
  240. package/dist/host/launch/launch-plan.js +26 -0
  241. package/dist/host/launch/mappings.js +2 -1
  242. package/dist/host/launch/risk-notes.d.ts +10 -0
  243. package/dist/host/launch/risk-notes.js +18 -0
  244. package/dist/host/launch/session-file.d.ts +2 -0
  245. package/dist/host/launch/session-file.js +7 -1
  246. package/dist/host/launch/wsb-file.d.ts +28 -4
  247. package/dist/host/launch/wsb-file.js +61 -42
  248. package/dist/host/life/crash-report.d.ts +27 -1
  249. package/dist/host/life/crash-report.js +173 -7
  250. package/dist/host/life/host-memory.d.ts +40 -0
  251. package/dist/host/life/host-memory.js +137 -0
  252. package/dist/host/life/index.d.ts +2 -0
  253. package/dist/host/life/index.js +2 -0
  254. package/dist/host/life/stop-events.d.ts +2 -0
  255. package/dist/host/life/stop-events.js +20 -3
  256. package/dist/host/life/stop-warning.js +1 -1
  257. package/dist/host/life/watchdog.d.ts +54 -0
  258. package/dist/host/life/watchdog.js +108 -0
  259. package/dist/host/native.d.ts +3 -2
  260. package/dist/host/native.js +22 -3
  261. package/dist/host/profile/claude-login.js +3 -2
  262. package/dist/host/sandbox/contained-deps.d.ts +2 -0
  263. package/dist/host/sandbox/contained-deps.js +17 -0
  264. package/dist/host/sandbox/index.d.ts +2 -0
  265. package/dist/host/sandbox/index.js +2 -0
  266. package/dist/host/sandbox/platform.d.ts +2 -0
  267. package/dist/host/sandbox/platform.js +7 -7
  268. package/dist/host/sandbox/tasklist.d.ts +13 -0
  269. package/dist/host/sandbox/tasklist.js +47 -0
  270. package/dist/host/secrets/launch-secrets.js +2 -1
  271. package/dist/host/sharing/current.js +2 -6
  272. package/dist/host/storage/contained/check.d.ts +9 -0
  273. package/dist/host/storage/contained/check.js +37 -0
  274. package/dist/host/storage/contained/contained-storage.d.ts +66 -0
  275. package/dist/host/storage/contained/contained-storage.js +168 -0
  276. package/dist/host/storage/contained/disk-port.d.ts +43 -0
  277. package/dist/host/storage/contained/disk-port.js +122 -0
  278. package/dist/host/storage/contained/index.d.ts +9 -0
  279. package/dist/host/storage/contained/index.js +8 -0
  280. package/dist/host/storage/contained/layout.d.ts +28 -0
  281. package/dist/host/storage/contained/layout.js +45 -0
  282. package/dist/host/storage/contained/resolve.d.ts +4 -0
  283. package/dist/host/storage/contained/resolve.js +30 -0
  284. package/dist/host/storage/contained/setting.d.ts +1 -0
  285. package/dist/host/storage/contained/setting.js +5 -0
  286. package/dist/host/storage/contained/state.d.ts +89 -0
  287. package/dist/host/storage/contained/state.js +166 -0
  288. package/dist/host/storage/contained/transfer.d.ts +24 -0
  289. package/dist/host/storage/contained/transfer.js +121 -0
  290. package/dist/host/storage/index.d.ts +2 -0
  291. package/dist/host/storage/index.js +2 -0
  292. package/dist/host/storage/providers/contained.d.ts +15 -0
  293. package/dist/host/storage/providers/contained.js +39 -0
  294. package/dist/host/storage/providers/folder.d.ts +12 -0
  295. package/dist/host/storage/providers/folder.js +20 -0
  296. package/dist/host/storage/providers/index.d.ts +4 -0
  297. package/dist/host/storage/providers/index.js +3 -0
  298. package/dist/host/storage/providers/registry.d.ts +9 -0
  299. package/dist/host/storage/providers/registry.js +14 -0
  300. package/dist/host/storage/providers/types.d.ts +33 -0
  301. package/dist/host/storage/providers/types.js +1 -0
  302. package/dist/host/tools/conpty.js +3 -2
  303. package/dist/host/tools/windows-terminal.js +8 -7
  304. package/dist/host/vpn/index.d.ts +1 -1
  305. package/dist/host/vpn/index.js +1 -1
  306. package/dist/host/vpn/prepare.d.ts +2 -0
  307. package/dist/host/vpn/prepare.js +63 -2
  308. package/dist/host/web/browser.d.ts +2 -0
  309. package/dist/host/web/browser.js +14 -1
  310. package/dist/host/web/index.d.ts +3 -2
  311. package/dist/host/web/index.js +3 -2
  312. package/dist/host/web/rpc.d.ts +24 -0
  313. package/dist/host/web/rpc.js +149 -0
  314. package/dist/host/web/runner.d.ts +2 -0
  315. package/dist/host/web/runner.js +1 -2
  316. package/dist/host/web/server.d.ts +7 -0
  317. package/dist/host/web/server.js +23 -3
  318. package/dist/runtime/agent.js +69 -8
  319. package/dist/runtime/daemon.js +1058 -624
  320. package/dist/runtime/db.js +69 -8
  321. package/dist/runtime/main.js +624 -182
  322. package/dist/runtime/netproxy.js +69 -8
  323. package/dist/runtime/view.js +87 -13
  324. package/dist/selftest/agent-paths.test.js +11 -1
  325. package/dist/selftest/app.test.d.ts +2 -0
  326. package/dist/selftest/app.test.js +324 -0
  327. package/dist/selftest/channel.test.js +13 -0
  328. package/dist/selftest/cli.test.js +2 -1
  329. package/dist/selftest/config.test.js +59 -0
  330. package/dist/selftest/contained.test.d.ts +2 -0
  331. package/dist/selftest/contained.test.js +544 -0
  332. package/dist/selftest/credentials.test.js +1 -1
  333. package/dist/selftest/engine.test.d.ts +2 -0
  334. package/dist/selftest/engine.test.js +127 -0
  335. package/dist/selftest/hcs.test.d.ts +2 -0
  336. package/dist/selftest/hcs.test.js +482 -0
  337. package/dist/selftest/heavy-load.test.d.ts +2 -0
  338. package/dist/selftest/heavy-load.test.js +329 -0
  339. package/dist/selftest/index.js +12 -0
  340. package/dist/selftest/layout.test.js +12 -0
  341. package/dist/selftest/menu-perf.test.d.ts +2 -0
  342. package/dist/selftest/menu-perf.test.js +248 -0
  343. package/dist/selftest/menu-screens.js +4 -2
  344. package/dist/selftest/menu.test.js +36 -8
  345. package/dist/selftest/support/engine-cases.d.ts +8 -0
  346. package/dist/selftest/support/engine-cases.js +65 -0
  347. package/dist/selftest/support/engine-golden.d.ts +3 -0
  348. package/dist/selftest/support/engine-golden.js +66 -0
  349. package/dist/selftest/support/fixtures.d.ts +7 -1
  350. package/dist/selftest/support/hcs-probes.d.ts +17 -0
  351. package/dist/selftest/support/hcs-probes.js +41 -0
  352. package/dist/selftest/vpn.test.js +136 -3
  353. package/dist/selftest/web.test.js +101 -3
  354. package/dist/shared/channel/run-dir.d.ts +4 -1
  355. package/dist/shared/channel/run-dir.js +7 -1
  356. package/dist/shared/channel/schema.d.ts +35 -1
  357. package/dist/shared/channel/schema.js +27 -0
  358. package/dist/shared/channel/secrets.d.ts +1 -0
  359. package/dist/shared/channel/secrets.js +6 -0
  360. package/dist/shared/memory/index.d.ts +1 -0
  361. package/dist/shared/memory/index.js +1 -0
  362. package/dist/shared/memory/policy.d.ts +33 -0
  363. package/dist/shared/memory/policy.js +55 -0
  364. package/dist/shared/pty/output-filter.d.ts +14 -1
  365. package/dist/shared/pty/output-filter.js +22 -4
  366. package/dist/shared/pty/terminal.d.ts +4 -1
  367. package/dist/shared/pty/terminal.js +4 -2
  368. package/dist/shared/system.d.ts +1 -0
  369. package/dist/shared/system.js +1 -0
  370. package/dist/shared/vpn/download.d.ts +16 -0
  371. package/dist/shared/vpn/download.js +16 -0
  372. package/dist/shared/vpn/wireguard.d.ts +51 -0
  373. package/dist/shared/vpn/wireguard.js +227 -0
  374. package/dist/sync/sync-cycle.js +5 -5
  375. package/dist/sync/watcher.d.ts +13 -0
  376. package/dist/sync/watcher.js +92 -3
  377. package/dist/web/index.html +4 -3
  378. package/dist/web/main-NRRS5O6Z.js +157 -0
  379. package/dist/web/main-T5DMCHYV.css +1 -0
  380. package/native/csharp/HcsHost/AssemblyInfo.cs +14 -0
  381. package/native/csharp/HcsHost/Guard.cs +100 -0
  382. package/native/csharp/HcsHost/Hcs.cs +256 -0
  383. package/native/csharp/HcsHost/Json.cs +78 -0
  384. package/native/csharp/HcsHost/Program.cs +185 -0
  385. package/native/csharp/HcsHost/VirtualDisk.cs +95 -0
  386. package/native/csharp/HostTools/AssemblyInfo.cs +14 -0
  387. package/native/csharp/HostTools/MemoryStatus.cs +107 -0
  388. package/native/csharp/HostTools/Program.cs +58 -17
  389. package/native/scripts/check-contained.ps1 +28 -0
  390. package/native/scripts/contained-common.ps1 +241 -0
  391. package/native/scripts/dismount-contained.ps1 +66 -0
  392. package/native/scripts/memory-status.ps1 +34 -0
  393. package/native/scripts/mount-contained.ps1 +139 -0
  394. package/native/scripts/run-elevated.ps1 +17 -4
  395. package/native/scripts/stop-events.ps1 +23 -8
  396. package/package.json +9 -2
  397. package/sandbox/csharp/MemGov.cs +398 -0
  398. package/sandbox/csharp/PtyHost.cs +111 -5
  399. package/schemas/config.schema.json +60 -6
  400. package/schemas/sandbox-config.schema.json +3 -3
  401. package/dist/cli/commands/sessions/control.d.ts +0 -4
  402. package/dist/cli/commands/sessions/control.js +0 -66
  403. package/dist/cli/commands/sessions/list.d.ts +0 -2
  404. package/dist/cli/commands/sessions/list.js +0 -48
  405. package/dist/cli/commands/sessions/status.d.ts +0 -4
  406. package/dist/cli/commands/sessions/status.js +0 -114
  407. package/dist/cli/commands/sessions/window.d.ts +0 -3
  408. package/dist/cli/commands/sessions/window.js +0 -18
  409. package/dist/cli/menu/settings/path-kind.js +0 -44
  410. package/dist/web/main-CXESL347.js +0 -45
  411. package/dist/web/main-VLR7DVQ4.css +0 -1
  412. /package/dist/{cli/menu/settings → app/kernel}/schema-node.d.ts +0 -0
  413. /package/dist/{cli/menu/settings → app/kernel}/schema-node.js +0 -0
@@ -0,0 +1,248 @@
1
+ // The menu stays quick: no key or draw waits for a child process (tasklist is faked and counted), a slow tab load shows
2
+ // "Loading…" instead of holding up the keys, a held key is drawn once, and the terminal writes only the rows that
3
+ // changed (the screen after the diffs is the same as a full draw, also after a resize).
4
+ import { EventEmitter } from 'node:events';
5
+ import { PassThrough } from 'node:stream';
6
+ import { DEFAULTS } from '../core/config/index.js';
7
+ import { sleep } from '../core/util/index.js';
8
+ import { Menu } from '../cli/menu/menu.js';
9
+ import { LiveStatus } from '../cli/menu/live.js';
10
+ import { ListPage } from '../cli/menu/pages/list-page.js';
11
+ import { App, Text, Terminal } from '../cli/tui/index.js';
12
+ import { supportsSyncUpdate } from '../cli/tui/terminal.js';
13
+ import { isSandboxRunning, useTasklistCache, useTasklistRunners } from '../host/sandbox/index.js';
14
+ const TASKLIST = [
15
+ '"System Idle Process","0","Services","0","8 K"',
16
+ '"WindowsSandboxClient.exe","4242","Console","1","9,000 K"',
17
+ ].join('\r\n');
18
+ const KEYS = { down: '\x1b[B', up: '\x1b[A', left: '\x1b[D', right: '\x1b[C', tab: '\t', ctrlC: '\x03' };
19
+ /** A terminal the test can type into and read: the keys go in as bytes, everything written is kept. */
20
+ class FakeTty {
21
+ stdin = Object.assign(new PassThrough(), { isTTY: true, setRawMode: () => undefined });
22
+ stdout = Object.assign(new EventEmitter(), {
23
+ columns: 100,
24
+ rows: 30,
25
+ write: (chunk) => {
26
+ this.writes.push(String(chunk));
27
+ return true;
28
+ },
29
+ });
30
+ writes = [];
31
+ terminal() {
32
+ return new Terminal(this.stdin, this.stdout);
33
+ }
34
+ type(bytes) {
35
+ this.stdin.write(bytes);
36
+ }
37
+ }
38
+ /** What the screen shows after a stream of writes: rows set by "ESC[r;1H", wiped by "ESC[H ESC[2J". */
39
+ function replay(writes, height) {
40
+ const rows = Array.from({ length: height }, () => '');
41
+ for (const write of writes) {
42
+ const body = write.replace(/\x1b\[\?2026[hl]/g, '');
43
+ if (body.startsWith('\x1b[?1049h'))
44
+ continue;
45
+ for (const part of body.split(/(?=\x1b\[(?:\d+;1H|H))/)) {
46
+ const clear = /^\x1b\[H\x1b\[2J/.exec(part);
47
+ if (clear)
48
+ rows.fill('');
49
+ const at = /^\x1b\[(\d+);1H([\s\S]*?)\x1b\[0m/.exec(part.slice(clear ? clear[0].length : 0));
50
+ if (at)
51
+ rows[Number(at[1]) - 1] = at[2];
52
+ }
53
+ }
54
+ return rows;
55
+ }
56
+ function context(t) {
57
+ const root = t.dir('menu-perf');
58
+ return {
59
+ packageRoot: t.packageRoot,
60
+ entry: 'sandbox.js',
61
+ options: {},
62
+ loaded: {
63
+ config: structuredClone(DEFAULTS),
64
+ configPath: null,
65
+ base: root,
66
+ layers: { machine: null, user: null },
67
+ },
68
+ storageRoot: root,
69
+ dataPath: t.dir('menu-perf', 'data'),
70
+ };
71
+ }
72
+ export const menuPerfSuite = {
73
+ name: 'menu-perf',
74
+ title: 'menu speed: no child process on a key or a draw, diff rendering, slow loads',
75
+ run: async (t) => {
76
+ t.section('the terminal writes only what changed');
77
+ {
78
+ const tty = new FakeTty();
79
+ const term = tty.terminal();
80
+ const height = term.height;
81
+ const frame = (mark) => Array.from({ length: height }, (_, i) => 'row ' + i + (i === 7 ? mark : ''));
82
+ term.start();
83
+ tty.writes.length = 0;
84
+ term.render(frame('a'));
85
+ const first = tty.writes.join('');
86
+ term.render(frame('a'));
87
+ const unchanged = tty.writes.length;
88
+ term.render(frame('b'));
89
+ const diff = tty.writes.slice(1).join('');
90
+ t.check(unchanged === 1 && diff.includes('row 7b') && !diff.includes('row 6') && diff.length < first.length / 5, 'an identical frame writes nothing and a change writes only its rows, in one write', diff);
91
+ t.equal(replay(tty.writes, height).map((r) => r.trimEnd()), frame('b').map((r) => Text.fit(r, term.width - 1).trimEnd()), 'the screen after the diffs equals a full draw');
92
+ tty.stdout.rows = height + 5;
93
+ tty.stdout.emit('resize');
94
+ tty.writes.length = 0;
95
+ const bigger = Array.from({ length: height + 5 }, (_, i) => 'big ' + i);
96
+ term.render(bigger);
97
+ t.check(tty.writes.length === 1 && tty.writes[0].includes('\x1b[2J'), 'a resize repaints everything in one write');
98
+ t.equal(replay(tty.writes, height + 5).map((r) => r.trimEnd()), bigger.map((r) => Text.fit(r, term.width - 1).trimEnd()), 'the screen after a resize equals a full draw');
99
+ term.stop();
100
+ t.check(supportsSyncUpdate({ WT_SESSION: 'x' }) &&
101
+ !supportsSyncUpdate({}) &&
102
+ !supportsSyncUpdate({ WT_SESSION: 'x', AGENT_SANDBOX_SYNC_UPDATE: '0' }) &&
103
+ supportsSyncUpdate({ AGENT_SANDBOX_SYNC_UPDATE: '1' }), 'synchronized updates are used where the terminal is known to take them, and can be forced on or off');
104
+ }
105
+ t.section('a held key is drawn once');
106
+ {
107
+ const tty = new FakeTty();
108
+ const app = new App(tty.terminal());
109
+ let renders = 0;
110
+ let handled = 0;
111
+ const screen = {
112
+ render: (_size) => {
113
+ renders++;
114
+ return { path: [], body: ['x'], keys: [] };
115
+ },
116
+ handle: (key) => {
117
+ handled++;
118
+ return key.text === 'q' ? { done: 'bye' } : undefined;
119
+ },
120
+ };
121
+ // Thirty keys arrive together (a held arrow, a paste).
122
+ tty.type(KEYS.down.repeat(30) + 'q');
123
+ const result = await app.show(screen);
124
+ app.close();
125
+ t.check(result === 'bye' && handled === 31 && renders < 10, 'keys that are already waiting are handled first and drawn once, not once each', 'handled ' + handled + ', drawn ' + renders);
126
+ }
127
+ t.section('a slow load does not hold up the keys');
128
+ {
129
+ const tty = new FakeTty();
130
+ const app = new App(tty.terminal());
131
+ class Slow extends ListPage {
132
+ label = 'Slow';
133
+ rows = [];
134
+ async load() {
135
+ await sleep(500);
136
+ this.rows = ['alpha', 'beta'];
137
+ }
138
+ options() {
139
+ return { path: [], items: this.rows.map((r) => ({ value: r, label: r })) };
140
+ }
141
+ act() {
142
+ return Promise.resolve({});
143
+ }
144
+ }
145
+ const page = new Slow(app);
146
+ const started = Date.now();
147
+ await page.open();
148
+ const waited = Date.now() - started;
149
+ const text = () => Text.strip(page.render({ width: 80, height: 14 }).body.join('\n'));
150
+ t.check(waited < 400 && page.loading && text().includes('Loading'), 'the tab opens at once and says Loading… while the data comes', 'waited ' + waited + ' ms');
151
+ const arrived = await t.waitFor(() => (text().includes('beta') ? true : null), 5000, 20);
152
+ t.check(arrived === true && !page.loading, 'the list is built when the data arrives');
153
+ }
154
+ t.section('no child process on a key or a draw');
155
+ const saved = { hostOnly: process.env.AGENT_SANDBOX_HOST_ONLY };
156
+ process.env.AGENT_SANDBOX_HOST_ONLY = '1';
157
+ const calls = { sync: 0, async: 0 };
158
+ useTasklistRunners({
159
+ sync: () => {
160
+ calls.sync++;
161
+ return TASKLIST;
162
+ },
163
+ async: async () => {
164
+ calls.async++;
165
+ // A busy PC: every look at the process list takes a second and a half.
166
+ await sleep(1500);
167
+ return TASKLIST;
168
+ },
169
+ });
170
+ try {
171
+ const tty = new FakeTty();
172
+ const menu = new Menu(context(t), () => Promise.resolve(0), {
173
+ terminal: tty.terminal(),
174
+ fetchTasklist: async () => {
175
+ calls.async++;
176
+ await sleep(1500);
177
+ return TASKLIST;
178
+ },
179
+ refreshMs: 100,
180
+ });
181
+ const done = menu.start();
182
+ const shown = await t.waitFor(() => tty.writes.length > 0, 20000, 20);
183
+ t.check(shown === true, 'the menu draws its first screen');
184
+ const slowest = { ms: 0, key: '' };
185
+ const press = async (name, bytes) => {
186
+ const before = tty.writes.length;
187
+ const at = Date.now();
188
+ tty.type(bytes);
189
+ // Not every key changes the screen: give the ones that do a chance, and measure those.
190
+ await t.waitFor(() => tty.writes.length > before, 400, 5);
191
+ const took = Date.now() - at;
192
+ if (tty.writes.length > before && took > slowest.ms) {
193
+ slowest.ms = took;
194
+ slowest.key = name;
195
+ }
196
+ await sleep(15);
197
+ };
198
+ const syncBefore = calls.sync;
199
+ for (const section of ['2', '3', '4', '5', '6', '7', '1'])
200
+ await press('section ' + section, section);
201
+ for (const k of ['down', 'down', 'up', 'left', 'down', 'down', 'right', 'down', 'down', 'tab'])
202
+ await press(k, KEYS[k]);
203
+ for (const section of ['5', '4', '2', '1'])
204
+ await press('section ' + section, section);
205
+ t.check(calls.sync === syncBefore, 'no key or draw ran tasklist (' + (calls.sync - syncBefore) + ' calls in 21 keys and every draw)', String(calls.sync - syncBefore));
206
+ t.check(calls.async >= 2, 'the process list is refreshed in the background (' + calls.async + ' times)');
207
+ t.check(slowest.ms < 1000, 'with a 1.5 second tasklist, no key took a second to show its result (slowest: ' +
208
+ slowest.key +
209
+ ' ' +
210
+ slowest.ms +
211
+ ' ms)');
212
+ tty.type(KEYS.ctrlC);
213
+ const code = await Promise.race([done, sleep(5000).then(() => -1)]);
214
+ t.check(code === 130, 'Ctrl+C leaves the menu');
215
+ const after = calls.sync;
216
+ isSandboxRunning();
217
+ t.check(calls.sync === after + 1, 'after the menu, "is the sandbox running?" runs tasklist again');
218
+ }
219
+ finally {
220
+ useTasklistRunners();
221
+ useTasklistCache(null);
222
+ if (saved.hostOnly === undefined)
223
+ delete process.env.AGENT_SANDBOX_HOST_ONLY;
224
+ else
225
+ process.env.AGENT_SANDBOX_HOST_ONLY = saved.hostOnly;
226
+ }
227
+ t.section('the status line');
228
+ {
229
+ let facts = 'a';
230
+ let changes = 0;
231
+ const live = new LiveStatus({
232
+ fetch: () => Promise.resolve(facts),
233
+ derive: () => 'status ' + facts,
234
+ onChange: () => changes++,
235
+ intervalMs: 20,
236
+ });
237
+ await live.start();
238
+ t.equal([live.line(), changes], ['status a', 1], 'the first look sets the line');
239
+ facts = 'b';
240
+ const changed = await t.waitFor(() => live.line() === 'status b', 3000, 10);
241
+ t.check(changed === true && changes === 2, 'a change is picked up in the background and announced');
242
+ live.stop();
243
+ facts = 'c';
244
+ await sleep(80);
245
+ t.check(live.line() === 'status b' && changes === 2, 'a stopped status looks at nothing');
246
+ }
247
+ },
248
+ };
@@ -3,7 +3,7 @@
3
3
  import fs from 'node:fs';
4
4
  import path from 'node:path';
5
5
  import { Draft } from '../cli/menu/settings/draft.js';
6
- import { ConfigFile } from '../cli/menu/settings/config-file.js';
6
+ import { ConfigFile } from '../app/features/settings/index.js';
7
7
  import { AppsModel } from '../cli/menu/apps.js';
8
8
  import { accountsOptions } from '../cli/menu/pages/accounts-page.js';
9
9
  import { appsOptions } from '../cli/menu/pages/apps-page.js';
@@ -11,7 +11,7 @@ import { maintenanceOptions } from '../cli/menu/pages/maintenance-page.js';
11
11
  import { sandboxOptions } from '../cli/menu/pages/sandbox-page.js';
12
12
  import { sessionsOptions } from '../cli/menu/pages/sessions-page.js';
13
13
  import { settingsOf, settingsOptions } from '../cli/menu/pages/settings-page.js';
14
- import { CATEGORIES } from '../cli/menu/settings/categories.js';
14
+ import { CATEGORIES } from '../app/features/settings/index.js';
15
15
  import { agentsOptions } from '../cli/menu/pages/agents-page.js';
16
16
  import { SECTION_LABELS } from '../cli/menu/shell.js';
17
17
  import { Frame, ListScreen, OverlayScreen, Text } from '../cli/tui/index.js';
@@ -57,6 +57,7 @@ const SESSIONS = [
57
57
  projectName: 'api',
58
58
  here: true,
59
59
  viewers: { remote: 1, viewers: 1 },
60
+ canOpen: true,
60
61
  },
61
62
  {
62
63
  id: '1791927991436-cc22dd',
@@ -67,6 +68,7 @@ const SESSIONS = [
67
68
  projectName: 'web',
68
69
  here: false,
69
70
  viewers: { remote: 0, viewers: 0 },
71
+ canOpen: true,
70
72
  },
71
73
  ];
72
74
  /** The navigation the shell would show: every section, the open one with the categories of `options`. */
@@ -2,11 +2,13 @@
2
2
  // box, the Draft of unsaved changes, and the sections' lists. With MENU_SCREENS_OUT set it also writes every screen as
3
3
  // text there, for review.
4
4
  import fs from 'node:fs';
5
- import { ConfigFile } from '../cli/menu/settings/config-file.js';
5
+ import { CATEGORIES, ConfigFile, SETTINGS_ELSEWHERE } from '../app/features/settings/index.js';
6
6
  import { Draft } from '../cli/menu/settings/draft.js';
7
7
  import { z } from 'zod';
8
8
  import { AddAgent, agentNameProblem, commandFromPackage, makeDefaultAgent, newAgent, removeAgent, } from '../cli/menu/add-agent.js';
9
- import { APP_GROUPS, AppsModel } from '../cli/menu/apps.js';
9
+ import { APP_GROUPS, AppsModel, REQUEST_APP, requestAppUrl } from '../cli/menu/apps.js';
10
+ import { readMenuView, saveMenuView } from '../cli/menu/memory.js';
11
+ import path from 'node:path';
10
12
  import { argPathKind, optionLabel, optionPathKind, plainDescription } from '../cli/menu/command-fields.js';
11
13
  import { CommandForm } from '../cli/menu/command-form.js';
12
14
  import { COMMANDS, commandSpec } from '../cli/manifest.js';
@@ -15,12 +17,10 @@ import { addedAgents, agentActions, agentCategories, agentsOptions, hostAgentsTo
15
17
  import { ListPage } from '../cli/menu/pages/list-page.js';
16
18
  import { sandboxOptions } from '../cli/menu/pages/sandbox-page.js';
17
19
  import { sessionsOptions } from '../cli/menu/pages/sessions-page.js';
18
- import { pathKindOf } from '../cli/menu/settings/path-kind.js';
19
- import { SchemaNode } from '../cli/menu/settings/schema-node.js';
20
+ import { pathKindOf, SchemaNode } from '../app/kernel/index.js';
20
21
  import { numberProblem, ValueEditor } from '../cli/menu/settings/value-editor.js';
21
22
  import { APP_CATEGORIES } from '../shared/apps/index.js';
22
23
  import { settingsOf, settingsOptions } from '../cli/menu/pages/settings-page.js';
23
- import { CATEGORIES, SETTINGS_ELSEWHERE } from '../cli/menu/settings/index.js';
24
24
  import { SECTION_LABELS, Shell } from '../cli/menu/shell.js';
25
25
  import { DEFAULTS } from '../core/config/index.js';
26
26
  import { HarnessSchema } from '../core/schema/index.js';
@@ -103,6 +103,7 @@ export const menuSuite = {
103
103
  stages = false;
104
104
  capturing = false;
105
105
  category;
106
+ search = '';
106
107
  focusList = true;
107
108
  constructor(label, ids) {
108
109
  this.label = label;
@@ -116,6 +117,9 @@ export const menuSuite = {
116
117
  this.category = id;
117
118
  return Promise.resolve();
118
119
  }
120
+ restoreSearch(text) {
121
+ this.search = text;
122
+ }
119
123
  setFocus(list) {
120
124
  this.focusList = list;
121
125
  }
@@ -153,8 +157,32 @@ export const menuSuite = {
153
157
  t.check(keys.includes('→ open') && keys.includes('1-7 jump'), 'the key bar shows the navigation keys while it has the keyboard', keys.join(', '));
154
158
  const leave = await shell.handle(press('escape'));
155
159
  t.check(leave !== undefined && leave.done.kind === 'quit', 'Esc in the navigation quits');
156
- await shell.restore({ section: 2, category: 'd' });
157
- t.equal([shell.page.label, pages[2].category, shell.view()], ['Three', 'd', { section: 2, category: 'd' }], 'the menu can be put back on the section and category it was left on');
160
+ await shell.restore({ section: 2, screens: { Three: { category: 'd', search: 'abc' }, One: { category: 'b' } } });
161
+ t.equal([shell.page.label, pages[2].category, pages[2].search, shell.view()], [
162
+ 'Three',
163
+ 'd',
164
+ 'abc',
165
+ { section: 2, screens: { Three: { category: 'd', search: 'abc' }, One: { category: 'b' } } },
166
+ ], 'the menu can be put back on the section, category and search it was left on (other sections keep theirs)');
167
+ await shell.openTab(0);
168
+ t.equal([pages[0].category, pages[0].search], ['b', ''], 'a section opened later goes back to its own category');
169
+ t.section('menu memory file');
170
+ const labels = ['Agents', 'Sessions', 'Sandbox'];
171
+ const memDir = t.dir('menu-memory');
172
+ const view = { section: 2, screens: { Sessions: { category: 'x', search: 'foo' }, Gone: { category: 'y' } } };
173
+ saveMenuView(view, labels, memDir);
174
+ t.equal(readMenuView(labels, memDir), { section: 2, screens: { Sessions: { category: 'x', search: 'foo' } } }, 'the last section, category and search are saved and read back (a section that is gone is dropped)');
175
+ t.equal(readMenuView(['Agents', 'Sessions'], memDir)?.section, 0, 'a remembered section that no longer exists falls back to the first (Agents)');
176
+ fs.writeFileSync(path.join(memDir, 'menu-state.json'), '{"section": 5, "screens": "no"}');
177
+ t.equal(readMenuView(labels, memDir), undefined, 'an invalid state file is ignored');
178
+ fs.writeFileSync(path.join(memDir, 'menu-state.json'), 'not json');
179
+ t.equal(readMenuView(labels, memDir), undefined, 'a file that is not JSON is ignored');
180
+ t.section('request an app');
181
+ const issue = new URL(requestAppUrl());
182
+ t.check(issue.origin === 'https://github.com' &&
183
+ issue.pathname.endsWith('/issues/new') &&
184
+ (issue.searchParams.get('title') ?? '').startsWith('App request') &&
185
+ (issue.searchParams.get('body') ?? '').includes('App name'), 'the request-an-app address is a GitHub new-issue page with a title and a body template', requestAppUrl());
158
186
  t.section('list categories driven from outside');
159
187
  const catItems = (id, n) => Array.from({ length: n }, (_, i) => ({ value: id + i, label: id + ' item ' + i, category: id }));
160
188
  const catList = {
@@ -577,7 +605,7 @@ export const menuSuite = {
577
605
  t.section('apps in a few groups');
578
606
  const appsUser = new AppsModel(user2, t.dir('apps-groups'));
579
607
  const groupIds = appsUser.categories().map((c) => c.id);
580
- const appItems = appsUser.items(new Draft());
608
+ const appItems = appsUser.items(new Draft()).filter((i) => i.value !== REQUEST_APP);
581
609
  t.check(groupIds.length <= 6 &&
582
610
  new AppsModel(ConfigFile.project(t.dir('apps-groups', 'project')), t.dir('apps-groups')).categories().length <=
583
611
  5 &&
@@ -0,0 +1,8 @@
1
+ import type { Config, ResolvedMapping } from '../../core/types.js';
2
+ export interface EngineCase {
3
+ readonly name: string;
4
+ readonly config: Config;
5
+ readonly memoryMb: number;
6
+ readonly mappings: readonly ResolvedMapping[];
7
+ }
8
+ export declare const ENGINE_CASES: readonly EngineCase[];
@@ -0,0 +1,65 @@
1
+ import { DEFAULTS } from '../../core/config/index.js';
2
+ const BASE = [
3
+ { host: 'C:\\L\\launches\\1', guest: 'C:\\AgentLaunch', readOnly: true },
4
+ { host: 'C:\\S\\data\\default', guest: 'C:\\AgentData', readOnly: false },
5
+ { host: 'C:\\Work\\app', guest: 'C:\\Workspace\\app', readOnly: false },
6
+ ];
7
+ function withSandbox(change) {
8
+ const config = structuredClone(DEFAULTS);
9
+ Object.assign(config.sandbox, change);
10
+ return config;
11
+ }
12
+ export const ENGINE_CASES = [
13
+ { name: 'default', config: withSandbox({}), memoryMb: 8192, mappings: BASE },
14
+ { name: 'vGpu on', config: withSandbox({ vGpu: true }), memoryMb: 8192, mappings: BASE },
15
+ { name: 'networking off', config: withSandbox({ networking: false }), memoryMb: 4096, mappings: BASE },
16
+ {
17
+ name: 'several projects and roots',
18
+ config: withSandbox({}),
19
+ memoryMb: 16384,
20
+ mappings: [
21
+ ...BASE,
22
+ { host: 'C:\\Work\\one', guest: 'C:\\Projects\\Work\\one', readOnly: false },
23
+ { host: 'C:\\Work\\two', guest: 'C:\\Projects\\Work\\two', readOnly: false },
24
+ { host: 'D:\\Roots\\r', guest: 'C:\\Projects\\r', readOnly: false },
25
+ ],
26
+ },
27
+ {
28
+ name: 'read-only workspace and extra folders',
29
+ config: withSandbox({}),
30
+ memoryMb: 8192,
31
+ mappings: [
32
+ BASE[0],
33
+ BASE[1],
34
+ { host: 'C:\\Work\\app', guest: 'C:\\Workspace\\app', readOnly: true },
35
+ { host: 'C:\\Data', guest: 'C:\\Assets', readOnly: true, label: 'outside the project, allowed' },
36
+ ],
37
+ },
38
+ {
39
+ name: 'mirror paths on another drive and escaped characters',
40
+ config: withSandbox({}),
41
+ memoryMb: 6144,
42
+ mappings: [
43
+ ...BASE,
44
+ { host: 'F:\\Games\\a&b <x>', guest: 'F:\\SteamLibrary\\steamapps\\common\\Game', readOnly: true },
45
+ ],
46
+ },
47
+ {
48
+ name: 'memory 2048 and protectedClient off',
49
+ config: withSandbox({ protectedClient: false }),
50
+ memoryMb: 2048,
51
+ mappings: BASE,
52
+ },
53
+ {
54
+ name: 'every device on',
55
+ config: withSandbox({ vGpu: true, clipboard: true, audioInput: true, videoInput: true, printerRedirection: true }),
56
+ memoryMb: 12288,
57
+ mappings: BASE,
58
+ },
59
+ {
60
+ name: 'every device off',
61
+ config: withSandbox({ clipboard: false, networking: false, protectedClient: false }),
62
+ memoryMb: 8192,
63
+ mappings: [BASE[0], BASE[1]],
64
+ },
65
+ ];
@@ -0,0 +1,3 @@
1
+ export declare const ENGINE_GOLDEN: Readonly<Record<string, string>>;
2
+ /** The files of a default launch folder (the fixtures' default launch) before the engine layer existed. */
3
+ export declare const LAUNCH_FILES_GOLDEN: readonly string[];
@@ -0,0 +1,66 @@
1
+ // The .wsb text written before the engine layer existed (captured from the old buildWsb); never regenerate it.
2
+ export const ENGINE_GOLDEN = {
3
+ default: '<Configuration><MemoryInMB>8192</MemoryInMB><vGPU>Disable</vGPU><Networking>Enable</Networking><ClipboardRedirection>Enable</ClipboardRedirection><AudioInput>Disable</AudioInput><VideoInput>Disable</VideoInput><PrinterRedirection>Disable</PrinterRedirection><ProtectedClient>Enable</ProtectedClient><MappedFolders><MappedFolder><HostFolder>C:\\L\\launches\\1</HostFolder><SandboxFolder>C:\\AgentLaunch</SandboxFolder><ReadOnly>true</ReadOnly></MappedFolder><MappedFolder><HostFolder>C:\\S\\data\\default</HostFolder><SandboxFolder>C:\\AgentData</SandboxFolder><ReadOnly>false</ReadOnly></MappedFolder><MappedFolder><HostFolder>C:\\Work\\app</HostFolder><SandboxFolder>C:\\Workspace\\app</SandboxFolder><ReadOnly>false</ReadOnly></MappedFolder></MappedFolders><LogonCommand><Command>C:\\AgentLaunch\\sandbox\\boot\\logon.cmd</Command></LogonCommand></Configuration>',
4
+ 'vGpu on': '<Configuration><MemoryInMB>8192</MemoryInMB><vGPU>Enable</vGPU><Networking>Enable</Networking><ClipboardRedirection>Enable</ClipboardRedirection><AudioInput>Disable</AudioInput><VideoInput>Disable</VideoInput><PrinterRedirection>Disable</PrinterRedirection><ProtectedClient>Enable</ProtectedClient><MappedFolders><MappedFolder><HostFolder>C:\\L\\launches\\1</HostFolder><SandboxFolder>C:\\AgentLaunch</SandboxFolder><ReadOnly>true</ReadOnly></MappedFolder><MappedFolder><HostFolder>C:\\S\\data\\default</HostFolder><SandboxFolder>C:\\AgentData</SandboxFolder><ReadOnly>false</ReadOnly></MappedFolder><MappedFolder><HostFolder>C:\\Work\\app</HostFolder><SandboxFolder>C:\\Workspace\\app</SandboxFolder><ReadOnly>false</ReadOnly></MappedFolder></MappedFolders><LogonCommand><Command>C:\\AgentLaunch\\sandbox\\boot\\logon.cmd</Command></LogonCommand></Configuration>',
5
+ 'networking off': '<Configuration><MemoryInMB>4096</MemoryInMB><vGPU>Disable</vGPU><Networking>Disable</Networking><ClipboardRedirection>Enable</ClipboardRedirection><AudioInput>Disable</AudioInput><VideoInput>Disable</VideoInput><PrinterRedirection>Disable</PrinterRedirection><ProtectedClient>Enable</ProtectedClient><MappedFolders><MappedFolder><HostFolder>C:\\L\\launches\\1</HostFolder><SandboxFolder>C:\\AgentLaunch</SandboxFolder><ReadOnly>true</ReadOnly></MappedFolder><MappedFolder><HostFolder>C:\\S\\data\\default</HostFolder><SandboxFolder>C:\\AgentData</SandboxFolder><ReadOnly>false</ReadOnly></MappedFolder><MappedFolder><HostFolder>C:\\Work\\app</HostFolder><SandboxFolder>C:\\Workspace\\app</SandboxFolder><ReadOnly>false</ReadOnly></MappedFolder></MappedFolders><LogonCommand><Command>C:\\AgentLaunch\\sandbox\\boot\\logon.cmd</Command></LogonCommand></Configuration>',
6
+ 'several projects and roots': '<Configuration><MemoryInMB>16384</MemoryInMB><vGPU>Disable</vGPU><Networking>Enable</Networking><ClipboardRedirection>Enable</ClipboardRedirection><AudioInput>Disable</AudioInput><VideoInput>Disable</VideoInput><PrinterRedirection>Disable</PrinterRedirection><ProtectedClient>Enable</ProtectedClient><MappedFolders><MappedFolder><HostFolder>C:\\L\\launches\\1</HostFolder><SandboxFolder>C:\\AgentLaunch</SandboxFolder><ReadOnly>true</ReadOnly></MappedFolder><MappedFolder><HostFolder>C:\\S\\data\\default</HostFolder><SandboxFolder>C:\\AgentData</SandboxFolder><ReadOnly>false</ReadOnly></MappedFolder><MappedFolder><HostFolder>C:\\Work\\app</HostFolder><SandboxFolder>C:\\Workspace\\app</SandboxFolder><ReadOnly>false</ReadOnly></MappedFolder><MappedFolder><HostFolder>C:\\Work\\one</HostFolder><SandboxFolder>C:\\Projects\\Work\\one</SandboxFolder><ReadOnly>false</ReadOnly></MappedFolder><MappedFolder><HostFolder>C:\\Work\\two</HostFolder><SandboxFolder>C:\\Projects\\Work\\two</SandboxFolder><ReadOnly>false</ReadOnly></MappedFolder><MappedFolder><HostFolder>D:\\Roots\\r</HostFolder><SandboxFolder>C:\\Projects\\r</SandboxFolder><ReadOnly>false</ReadOnly></MappedFolder></MappedFolders><LogonCommand><Command>C:\\AgentLaunch\\sandbox\\boot\\logon.cmd</Command></LogonCommand></Configuration>',
7
+ 'read-only workspace and extra folders': '<Configuration><MemoryInMB>8192</MemoryInMB><vGPU>Disable</vGPU><Networking>Enable</Networking><ClipboardRedirection>Enable</ClipboardRedirection><AudioInput>Disable</AudioInput><VideoInput>Disable</VideoInput><PrinterRedirection>Disable</PrinterRedirection><ProtectedClient>Enable</ProtectedClient><MappedFolders><MappedFolder><HostFolder>C:\\L\\launches\\1</HostFolder><SandboxFolder>C:\\AgentLaunch</SandboxFolder><ReadOnly>true</ReadOnly></MappedFolder><MappedFolder><HostFolder>C:\\S\\data\\default</HostFolder><SandboxFolder>C:\\AgentData</SandboxFolder><ReadOnly>false</ReadOnly></MappedFolder><MappedFolder><HostFolder>C:\\Work\\app</HostFolder><SandboxFolder>C:\\Workspace\\app</SandboxFolder><ReadOnly>true</ReadOnly></MappedFolder><MappedFolder><HostFolder>C:\\Data</HostFolder><SandboxFolder>C:\\Assets</SandboxFolder><ReadOnly>true</ReadOnly></MappedFolder></MappedFolders><LogonCommand><Command>C:\\AgentLaunch\\sandbox\\boot\\logon.cmd</Command></LogonCommand></Configuration>',
8
+ 'mirror paths on another drive and escaped characters': '<Configuration><MemoryInMB>6144</MemoryInMB><vGPU>Disable</vGPU><Networking>Enable</Networking><ClipboardRedirection>Enable</ClipboardRedirection><AudioInput>Disable</AudioInput><VideoInput>Disable</VideoInput><PrinterRedirection>Disable</PrinterRedirection><ProtectedClient>Enable</ProtectedClient><MappedFolders><MappedFolder><HostFolder>C:\\L\\launches\\1</HostFolder><SandboxFolder>C:\\AgentLaunch</SandboxFolder><ReadOnly>true</ReadOnly></MappedFolder><MappedFolder><HostFolder>C:\\S\\data\\default</HostFolder><SandboxFolder>C:\\AgentData</SandboxFolder><ReadOnly>false</ReadOnly></MappedFolder><MappedFolder><HostFolder>C:\\Work\\app</HostFolder><SandboxFolder>C:\\Workspace\\app</SandboxFolder><ReadOnly>false</ReadOnly></MappedFolder><MappedFolder><HostFolder>F:\\Games\\a&amp;b &lt;x&gt;</HostFolder><SandboxFolder>C:\\Mirror\\F\\SteamLibrary\\steamapps\\common\\Game</SandboxFolder><ReadOnly>true</ReadOnly></MappedFolder></MappedFolders><LogonCommand><Command>C:\\AgentLaunch\\sandbox\\boot\\logon.cmd</Command></LogonCommand></Configuration>',
9
+ 'memory 2048 and protectedClient off': '<Configuration><MemoryInMB>2048</MemoryInMB><vGPU>Disable</vGPU><Networking>Enable</Networking><ClipboardRedirection>Enable</ClipboardRedirection><AudioInput>Disable</AudioInput><VideoInput>Disable</VideoInput><PrinterRedirection>Disable</PrinterRedirection><ProtectedClient>Disable</ProtectedClient><MappedFolders><MappedFolder><HostFolder>C:\\L\\launches\\1</HostFolder><SandboxFolder>C:\\AgentLaunch</SandboxFolder><ReadOnly>true</ReadOnly></MappedFolder><MappedFolder><HostFolder>C:\\S\\data\\default</HostFolder><SandboxFolder>C:\\AgentData</SandboxFolder><ReadOnly>false</ReadOnly></MappedFolder><MappedFolder><HostFolder>C:\\Work\\app</HostFolder><SandboxFolder>C:\\Workspace\\app</SandboxFolder><ReadOnly>false</ReadOnly></MappedFolder></MappedFolders><LogonCommand><Command>C:\\AgentLaunch\\sandbox\\boot\\logon.cmd</Command></LogonCommand></Configuration>',
10
+ 'every device on': '<Configuration><MemoryInMB>12288</MemoryInMB><vGPU>Enable</vGPU><Networking>Enable</Networking><ClipboardRedirection>Enable</ClipboardRedirection><AudioInput>Enable</AudioInput><VideoInput>Enable</VideoInput><PrinterRedirection>Enable</PrinterRedirection><ProtectedClient>Enable</ProtectedClient><MappedFolders><MappedFolder><HostFolder>C:\\L\\launches\\1</HostFolder><SandboxFolder>C:\\AgentLaunch</SandboxFolder><ReadOnly>true</ReadOnly></MappedFolder><MappedFolder><HostFolder>C:\\S\\data\\default</HostFolder><SandboxFolder>C:\\AgentData</SandboxFolder><ReadOnly>false</ReadOnly></MappedFolder><MappedFolder><HostFolder>C:\\Work\\app</HostFolder><SandboxFolder>C:\\Workspace\\app</SandboxFolder><ReadOnly>false</ReadOnly></MappedFolder></MappedFolders><LogonCommand><Command>C:\\AgentLaunch\\sandbox\\boot\\logon.cmd</Command></LogonCommand></Configuration>',
11
+ 'every device off': '<Configuration><MemoryInMB>8192</MemoryInMB><vGPU>Disable</vGPU><Networking>Disable</Networking><ClipboardRedirection>Disable</ClipboardRedirection><AudioInput>Disable</AudioInput><VideoInput>Disable</VideoInput><PrinterRedirection>Disable</PrinterRedirection><ProtectedClient>Disable</ProtectedClient><MappedFolders><MappedFolder><HostFolder>C:\\L\\launches\\1</HostFolder><SandboxFolder>C:\\AgentLaunch</SandboxFolder><ReadOnly>true</ReadOnly></MappedFolder><MappedFolder><HostFolder>C:\\S\\data\\default</HostFolder><SandboxFolder>C:\\AgentData</SandboxFolder><ReadOnly>false</ReadOnly></MappedFolder></MappedFolders><LogonCommand><Command>C:\\AgentLaunch\\sandbox\\boot\\logon.cmd</Command></LogonCommand></Configuration>',
12
+ };
13
+ /** The files of a default launch folder (the fixtures' default launch) before the engine layer existed. */
14
+ export const LAUNCH_FILES_GOLDEN = [
15
+ 'agent.wsb',
16
+ 'claude-profile/.claude.json',
17
+ 'claude-profile/CLAUDE.md',
18
+ 'claude-profile/commands/review.md',
19
+ 'claude-profile/plugins/installed_plugins.json',
20
+ 'claude-profile/settings.json',
21
+ 'env.cmd',
22
+ 'home/.gitconfig',
23
+ 'hooks/post-agent/README.txt',
24
+ 'hooks/pre-provision/README.txt',
25
+ 'package.json',
26
+ 'runtime/agent.js',
27
+ 'runtime/daemon.js',
28
+ 'runtime/db.js',
29
+ 'runtime/gitguard.js',
30
+ 'runtime/main.js',
31
+ 'runtime/netproxy.js',
32
+ 'runtime/view.js',
33
+ 'sandbox/boot/bootstrap.ps1',
34
+ 'sandbox/boot/bootstrap/drives.ps1',
35
+ 'sandbox/boot/bootstrap/files.ps1',
36
+ 'sandbox/boot/bootstrap/runner.ps1',
37
+ 'sandbox/boot/bootstrap/status.ps1',
38
+ 'sandbox/boot/logon.cmd',
39
+ 'sandbox/boot/trust.cmd',
40
+ 'sandbox/csharp/CargoShim.cs',
41
+ 'sandbox/csharp/Desktop.cs',
42
+ 'sandbox/csharp/EnvBroadcast.cs',
43
+ 'sandbox/csharp/GitShim.cs',
44
+ 'sandbox/csharp/LinkGate.cs',
45
+ 'sandbox/csharp/MemGov.cs',
46
+ 'sandbox/csharp/OpenSsl.cs',
47
+ 'sandbox/csharp/PathSync.cs',
48
+ 'sandbox/csharp/PtyHost.cs',
49
+ 'sandbox/csharp/SandboxTools/CpuCap.cs',
50
+ 'sandbox/csharp/SandboxTools/MemoryLog.cs',
51
+ 'sandbox/csharp/SandboxTools/PageFile.cs',
52
+ 'sandbox/csharp/SandboxTools/Program.cs',
53
+ 'sandbox/csharp/VsWhere.cs',
54
+ 'sandbox/csharp/VtInput.cs',
55
+ 'sandbox/scripts/enable-vt-input.ps1',
56
+ 'sandbox/scripts/expand-archive.ps1',
57
+ 'sandbox/scripts/get-gpu-names.ps1',
58
+ 'sandbox/scripts/get-signer.ps1',
59
+ 'sandbox/scripts/install-shell-path.ps1',
60
+ 'sandbox/scripts/link-profile-dirs.ps1',
61
+ 'sandbox/scripts/new-shortcuts.ps1',
62
+ 'sandbox/scripts/set-desktop.ps1',
63
+ 'sandbox/scripts/set-dns-servers.ps1',
64
+ 'sandbox/scripts/set-machine-environment.ps1',
65
+ 'session.json',
66
+ ];
@@ -53,12 +53,15 @@ export declare function createFixtures(t: Harness): {
53
53
  optional?: boolean | undefined;
54
54
  }[];
55
55
  sandbox: {
56
+ engine: "windows-sandbox" | "hcs";
56
57
  memoryMb: number | "auto";
57
58
  maxMemoryMb: number;
58
59
  maxMemoryPercent: number;
59
60
  cpuLimit: number | "none";
60
61
  pageFileMb: number;
61
62
  reserveHostMb: number;
63
+ agentMemoryHeadroomMb: number | "auto" | "none";
64
+ pressureResponse: boolean;
62
65
  vGpu: boolean;
63
66
  networking: boolean;
64
67
  clipboard: boolean;
@@ -77,6 +80,8 @@ export declare function createFixtures(t: Harness): {
77
80
  persistAgentState: boolean;
78
81
  dataName: string;
79
82
  markSandboxFiles: boolean;
83
+ contained: "off" | "vhdx";
84
+ containedMaxGb: number;
80
85
  warnDataGb: number;
81
86
  };
82
87
  network: {
@@ -92,7 +97,7 @@ export declare function createFixtures(t: Harness): {
92
97
  };
93
98
  vpn: {
94
99
  enabled: boolean;
95
- provider: "nordvpn" | "openvpn-file";
100
+ provider: "nordvpn" | "openvpn-file" | "wireguard-file";
96
101
  protocol: "udp" | "tcp";
97
102
  country: string;
98
103
  configFile: string;
@@ -308,6 +313,7 @@ export declare function createFixtures(t: Harness): {
308
313
  hostDir?: string | undefined;
309
314
  } | undefined;
310
315
  localState?: Record<string, string> | undefined;
316
+ bootReset?: string[] | undefined;
311
317
  resumeArguments?: string[] | undefined;
312
318
  resumeOneArguments?: string[] | undefined;
313
319
  }>;
@@ -0,0 +1,17 @@
1
+ import type { HcsProbes, TokenGroups } from '../../host/engines/hcs/check.js';
2
+ import type { HcsImage } from '../../host/engines/hcs/documents.js';
3
+ export declare const FAKE_IMAGE: HcsImage;
4
+ export interface FakePc {
5
+ windows: boolean;
6
+ build: number | null;
7
+ computecore: boolean;
8
+ services: Record<string, boolean | null>;
9
+ token: TokenGroups | null;
10
+ image: HcsImage | null;
11
+ }
12
+ export declare const GOOD_PC: FakePc;
13
+ export declare function fakeProbes(pc?: Partial<FakePc>): HcsProbes & {
14
+ readonly calls: string[];
15
+ };
16
+ /** A PC without the HCS pieces, for the tests that must not depend on the PC they run on. */
17
+ export declare const NO_HCS_PC: HcsProbes;
@@ -0,0 +1,41 @@
1
+ export const FAKE_IMAGE = {
2
+ id: 'sha256:' + 'a'.repeat(64),
3
+ layers: ['C:\\img\\base', 'C:\\img\\l2'],
4
+ utilityVmFiles: 'C:\\img\\base\\UtilityVM\\Files',
5
+ };
6
+ export const GOOD_PC = {
7
+ windows: true,
8
+ build: 22621,
9
+ computecore: true,
10
+ services: { vmcompute: true, cexecsvc: true },
11
+ token: { elevatedAdministrator: true, hyperVAdministrators: false },
12
+ image: FAKE_IMAGE,
13
+ };
14
+ export function fakeProbes(pc = {}) {
15
+ const p = { ...GOOD_PC, ...pc };
16
+ const calls = [];
17
+ const store = {
18
+ name: 'fake store',
19
+ find: () => {
20
+ calls.push('imageStore.find');
21
+ return { image: p.image, reason: p.image ? '' : 'The fake store has no image.' };
22
+ },
23
+ };
24
+ return {
25
+ calls,
26
+ isWindows: () => p.windows,
27
+ windowsBuild: () => p.build,
28
+ serviceInstalled: (name) => {
29
+ calls.push('serviceInstalled:' + name);
30
+ return name in p.services ? p.services[name] : null;
31
+ },
32
+ fileExists: (file) => {
33
+ calls.push('fileExists:' + file);
34
+ return file.toLowerCase().endsWith('computecore.dll') ? p.computecore : false;
35
+ },
36
+ tokenGroups: () => p.token,
37
+ imageStores: () => [store],
38
+ };
39
+ }
40
+ /** A PC without the HCS pieces, for the tests that must not depend on the PC they run on. */
41
+ export const NO_HCS_PC = fakeProbes({ computecore: false, services: { vmcompute: false, cexecsvc: false } });