windows-development-sandbox 1.0.5 → 1.4.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 (453) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +25 -8
  3. package/config.example.json +55 -5
  4. package/dist/api.js +2 -1
  5. package/dist/cli/args.d.ts +23 -0
  6. package/dist/cli/args.js +38 -4
  7. package/dist/cli/colors.d.ts +24 -0
  8. package/dist/cli/colors.js +42 -0
  9. package/dist/cli/commands/accounts.js +2 -2
  10. package/dist/cli/commands/agent-commands.d.ts +6 -0
  11. package/dist/cli/commands/agent-commands.js +61 -0
  12. package/dist/cli/commands/context.d.ts +2 -0
  13. package/dist/cli/commands/context.js +5 -1
  14. package/dist/cli/commands/data/clean.d.ts +15 -0
  15. package/dist/cli/commands/data/clean.js +106 -0
  16. package/dist/cli/commands/data/collect.d.ts +11 -0
  17. package/dist/cli/commands/data/collect.js +54 -0
  18. package/dist/cli/commands/data/index.d.ts +4 -0
  19. package/dist/cli/commands/data/index.js +45 -0
  20. package/dist/cli/commands/data/remove.d.ts +2 -0
  21. package/dist/cli/commands/data/remove.js +30 -0
  22. package/dist/cli/commands/index.d.ts +6 -4
  23. package/dist/cli/commands/index.js +6 -4
  24. package/dist/cli/commands/launch.d.ts +26 -2
  25. package/dist/cli/commands/launch.js +256 -42
  26. package/dist/cli/commands/maintenance.d.ts +2 -0
  27. package/dist/cli/commands/maintenance.js +67 -5
  28. package/dist/cli/commands/project.d.ts +29 -0
  29. package/dist/cli/commands/project.js +63 -0
  30. package/dist/cli/commands/projects.d.ts +14 -0
  31. package/dist/cli/commands/projects.js +146 -0
  32. package/dist/cli/commands/repair/checks.d.ts +2 -0
  33. package/dist/cli/commands/{repair.js → repair/checks.js} +19 -181
  34. package/dist/cli/commands/{repair.d.ts → repair/finders.d.ts} +0 -29
  35. package/dist/cli/commands/repair/finders.js +108 -0
  36. package/dist/cli/commands/repair/index.d.ts +12 -0
  37. package/dist/cli/commands/repair/index.js +61 -0
  38. package/dist/cli/commands/repair/types.d.ts +26 -0
  39. package/dist/cli/commands/repair/types.js +3 -0
  40. package/dist/cli/commands/restart.d.ts +6 -0
  41. package/dist/cli/commands/restart.js +85 -0
  42. package/dist/cli/commands/sessions.d.ts +2 -1
  43. package/dist/cli/commands/sessions.js +189 -45
  44. package/dist/cli/commands/setup/checks.d.ts +13 -0
  45. package/dist/cli/commands/setup/checks.js +71 -0
  46. package/dist/cli/commands/{setup.d.ts → setup/facts.d.ts} +1 -15
  47. package/dist/cli/commands/setup/facts.js +60 -0
  48. package/dist/cli/commands/setup/index.d.ts +2 -0
  49. package/dist/cli/commands/setup/index.js +43 -0
  50. package/dist/cli/commands/user-config.d.ts +8 -0
  51. package/dist/cli/commands/user-config.js +41 -0
  52. package/dist/cli/history.d.ts +11 -0
  53. package/dist/cli/history.js +21 -0
  54. package/dist/cli/index.d.ts +7 -1
  55. package/dist/cli/index.js +42 -15
  56. package/dist/cli/manifest.d.ts +8 -0
  57. package/dist/cli/manifest.js +40 -15
  58. package/dist/cli/menu/apps.d.ts +21 -0
  59. package/dist/cli/menu/apps.js +122 -0
  60. package/dist/cli/menu/command-form.d.ts +28 -0
  61. package/dist/cli/menu/command-form.js +219 -0
  62. package/dist/cli/menu/index.d.ts +26 -0
  63. package/dist/cli/menu/index.js +180 -0
  64. package/dist/cli/menu/settings/categories.d.ts +9 -0
  65. package/dist/cli/menu/settings/categories.js +28 -0
  66. package/dist/cli/menu/settings/config-file.d.ts +40 -0
  67. package/dist/cli/menu/settings/config-file.js +71 -0
  68. package/dist/cli/menu/settings/editors.d.ts +30 -0
  69. package/dist/cli/menu/settings/editors.js +305 -0
  70. package/dist/cli/menu/settings/index.d.ts +32 -0
  71. package/dist/cli/menu/settings/index.js +136 -0
  72. package/dist/cli/menu/settings/schema-node.d.ts +62 -0
  73. package/dist/cli/menu/settings/schema-node.js +104 -0
  74. package/dist/cli/menu/several.d.ts +20 -0
  75. package/dist/cli/menu/several.js +102 -0
  76. package/dist/cli/progress.d.ts +9 -0
  77. package/dist/cli/progress.js +49 -0
  78. package/dist/cli/tui/app.d.ts +39 -0
  79. package/dist/cli/tui/app.js +52 -0
  80. package/dist/cli/tui/dialogs.d.ts +57 -0
  81. package/dist/cli/tui/dialogs.js +162 -0
  82. package/dist/cli/tui/frame.d.ts +18 -0
  83. package/dist/cli/tui/frame.js +27 -0
  84. package/dist/cli/tui/index.d.ts +7 -0
  85. package/dist/cli/tui/index.js +8 -0
  86. package/dist/cli/tui/list-screen.d.ts +101 -0
  87. package/dist/cli/tui/list-screen.js +299 -0
  88. package/dist/cli/tui/terminal.d.ts +37 -0
  89. package/dist/cli/tui/terminal.js +89 -0
  90. package/dist/cli/tui/text.d.ts +20 -0
  91. package/dist/cli/tui/text.js +105 -0
  92. package/dist/cli/tui/theme.d.ts +45 -0
  93. package/dist/cli/tui/theme.js +30 -0
  94. package/dist/cli/validate.d.ts +17 -0
  95. package/dist/cli/validate.js +89 -0
  96. package/dist/core/config.js +12 -6
  97. package/dist/core/disk.d.ts +16 -0
  98. package/dist/core/disk.js +55 -0
  99. package/dist/core/local-config.d.ts +23 -0
  100. package/dist/core/local-config.js +79 -7
  101. package/dist/core/project-policy.d.ts +15 -0
  102. package/dist/core/project-policy.js +35 -0
  103. package/dist/core/prompt.d.ts +4 -0
  104. package/dist/core/prompt.js +15 -0
  105. package/dist/core/safe-paths.d.ts +4 -0
  106. package/dist/core/safe-paths.js +37 -0
  107. package/dist/core/schema/apps.d.ts +40 -0
  108. package/dist/core/schema/apps.js +27 -0
  109. package/dist/core/schema/common.d.ts +17 -0
  110. package/dist/core/schema/common.js +15 -0
  111. package/dist/core/schema/config.d.ts +659 -0
  112. package/dist/core/schema/config.js +75 -0
  113. package/dist/core/schema/databases.d.ts +33 -0
  114. package/dist/core/schema/databases.js +35 -0
  115. package/dist/core/schema/harness.d.ts +12 -0
  116. package/dist/core/schema/harness.js +17 -0
  117. package/dist/core/schema/json-schema.d.ts +5 -0
  118. package/dist/core/schema/json-schema.js +25 -0
  119. package/dist/core/schema/profile.d.ts +32 -0
  120. package/dist/core/schema/profile.js +31 -0
  121. package/dist/core/schema/projects.d.ts +9 -0
  122. package/dist/core/schema/projects.js +11 -0
  123. package/dist/core/schema/sandbox.d.ts +78 -0
  124. package/dist/core/schema/sandbox.js +64 -0
  125. package/dist/core/schema/toolchains.d.ts +96 -0
  126. package/dist/core/schema/toolchains.js +88 -0
  127. package/dist/core/schema.d.ts +6 -604
  128. package/dist/core/schema.js +8 -264
  129. package/dist/core/types.d.ts +35 -1
  130. package/dist/core/util.d.ts +9 -0
  131. package/dist/core/util.js +14 -3
  132. package/dist/core/workspace.d.ts +0 -5
  133. package/dist/core/workspace.js +33 -50
  134. package/dist/guest/apps/index.d.ts +10 -0
  135. package/dist/guest/apps/index.js +206 -0
  136. package/dist/guest/apps/resolvers.d.ts +8 -0
  137. package/dist/guest/apps/resolvers.js +90 -0
  138. package/dist/guest/audit-parse.d.ts +7 -0
  139. package/dist/guest/audit-parse.js +24 -0
  140. package/dist/guest/audit.d.ts +4 -0
  141. package/dist/guest/audit.js +47 -0
  142. package/dist/guest/boot-env.d.ts +4 -0
  143. package/dist/guest/boot-env.js +25 -0
  144. package/dist/guest/cmdline.d.ts +12 -0
  145. package/dist/guest/cmdline.js +23 -0
  146. package/dist/guest/daemon/exec.d.ts +5 -0
  147. package/dist/guest/daemon/exec.js +32 -0
  148. package/dist/guest/daemon/project.d.ts +14 -0
  149. package/dist/guest/daemon/project.js +132 -0
  150. package/dist/guest/daemon/relays.d.ts +1 -0
  151. package/dist/guest/daemon/relays.js +18 -0
  152. package/dist/guest/daemon/session.d.ts +13 -0
  153. package/dist/guest/daemon/session.js +139 -0
  154. package/dist/guest/daemon/shutdown.d.ts +1 -0
  155. package/dist/guest/daemon/shutdown.js +21 -0
  156. package/dist/guest/daemon/state.d.ts +17 -0
  157. package/dist/guest/daemon/state.js +31 -0
  158. package/dist/guest/daemon.js +12 -141
  159. package/dist/guest/db.js +18 -3
  160. package/dist/guest/env.d.ts +3 -0
  161. package/dist/guest/env.js +7 -3
  162. package/dist/guest/guide.d.ts +6 -2
  163. package/dist/guest/guide.js +5 -4
  164. package/dist/guest/helpers.d.ts +3 -0
  165. package/dist/guest/helpers.js +26 -0
  166. package/dist/guest/main.js +31 -8
  167. package/dist/guest/netproxy.d.ts +1 -0
  168. package/dist/guest/netproxy.js +100 -0
  169. package/dist/guest/ports.d.ts +6 -0
  170. package/dist/guest/ports.js +22 -0
  171. package/dist/guest/project-context.d.ts +7 -0
  172. package/dist/guest/project-context.js +10 -0
  173. package/dist/guest/project-env.d.ts +20 -0
  174. package/dist/guest/project-env.js +20 -0
  175. package/dist/guest/project-status.d.ts +5 -0
  176. package/dist/guest/project-status.js +17 -0
  177. package/dist/guest/ptyhost.d.ts +0 -18
  178. package/dist/guest/ptyhost.js +17 -65
  179. package/dist/guest/setup/agents.d.ts +5 -2
  180. package/dist/guest/setup/agents.js +22 -8
  181. package/dist/guest/setup/claude.d.ts +0 -4
  182. package/dist/guest/setup/claude.js +59 -5
  183. package/dist/guest/setup/environment.d.ts +13 -3
  184. package/dist/guest/setup/environment.js +14 -10
  185. package/dist/guest/setup/hooks.d.ts +9 -1
  186. package/dist/guest/setup/hooks.js +28 -14
  187. package/dist/guest/setup/network.d.ts +9 -0
  188. package/dist/guest/setup/network.js +97 -4
  189. package/dist/guest/setup/user.js +4 -0
  190. package/dist/guest/toolchains/catalogue.d.ts +4 -0
  191. package/dist/guest/toolchains/catalogue.js +2 -2
  192. package/dist/guest/toolchains/cli.js +25 -17
  193. package/dist/guest/toolchains/common.d.ts +18 -1
  194. package/dist/guest/toolchains/common.js +34 -11
  195. package/dist/guest/toolchains/databases/dynamodb.d.ts +8 -0
  196. package/dist/guest/toolchains/databases/dynamodb.js +52 -0
  197. package/dist/guest/toolchains/{databases.d.ts → databases/index.d.ts} +2 -3
  198. package/dist/guest/toolchains/databases/index.js +62 -0
  199. package/dist/guest/toolchains/databases/mongodb.d.ts +3 -0
  200. package/dist/guest/toolchains/databases/mongodb.js +31 -0
  201. package/dist/guest/toolchains/databases/mysql.d.ts +3 -0
  202. package/dist/guest/toolchains/databases/mysql.js +38 -0
  203. package/dist/guest/toolchains/databases/postgres.d.ts +5 -0
  204. package/dist/guest/toolchains/databases/postgres.js +38 -0
  205. package/dist/guest/toolchains/databases/redis.d.ts +3 -0
  206. package/dist/guest/toolchains/databases/redis.js +16 -0
  207. package/dist/guest/toolchains/databases/server.d.ts +14 -0
  208. package/dist/guest/toolchains/databases/server.js +52 -0
  209. package/dist/guest/toolchains/git.js +25 -16
  210. package/dist/guest/toolchains/go.js +1 -1
  211. package/dist/guest/toolchains/index.d.ts +13 -9
  212. package/dist/guest/toolchains/index.js +40 -82
  213. package/dist/guest/toolchains/java.js +5 -5
  214. package/dist/guest/toolchains/leftovers.d.ts +2 -0
  215. package/dist/guest/toolchains/leftovers.js +26 -0
  216. package/dist/guest/toolchains/managers.js +12 -10
  217. package/dist/guest/toolchains/{binstall.js → native/binstall.js} +6 -9
  218. package/dist/guest/toolchains/native/cpp.d.ts +4 -0
  219. package/dist/guest/toolchains/native/cpp.js +38 -0
  220. package/dist/guest/toolchains/native/dotnet.d.ts +4 -0
  221. package/dist/guest/toolchains/native/dotnet.js +103 -0
  222. package/dist/guest/toolchains/native/mesa.d.ts +7 -0
  223. package/dist/guest/toolchains/native/mesa.js +56 -0
  224. package/dist/guest/toolchains/native/msvc/environment.d.ts +16 -0
  225. package/dist/guest/toolchains/native/msvc/environment.js +57 -0
  226. package/dist/guest/toolchains/native/msvc/index.d.ts +6 -0
  227. package/dist/guest/toolchains/native/msvc/index.js +48 -0
  228. package/dist/guest/toolchains/native/msvc/packages.d.ts +6 -0
  229. package/dist/guest/toolchains/native/msvc/packages.js +156 -0
  230. package/dist/guest/toolchains/native/msvc/tree.d.ts +15 -0
  231. package/dist/guest/toolchains/native/msvc/tree.js +21 -0
  232. package/dist/guest/toolchains/native/rust.d.ts +3 -0
  233. package/dist/guest/toolchains/native/rust.js +45 -0
  234. package/dist/guest/toolchains/node.js +26 -6
  235. package/dist/guest/toolchains/plan.d.ts +24 -0
  236. package/dist/guest/toolchains/plan.js +140 -0
  237. package/dist/guest/toolchains/pwsh.js +1 -1
  238. package/dist/guest/toolchains/python.js +43 -12
  239. package/dist/guest/toolchains/runtimes.d.ts +2 -0
  240. package/dist/guest/toolchains/runtimes.js +6 -8
  241. package/dist/guest/toolchains/scripting/php.d.ts +3 -0
  242. package/dist/guest/toolchains/scripting/php.js +71 -0
  243. package/dist/guest/toolchains/scripting/ruby.d.ts +3 -0
  244. package/dist/guest/toolchains/scripting/ruby.js +47 -0
  245. package/dist/guest/toolchains/scripting/vcruntime.d.ts +7 -0
  246. package/dist/guest/toolchains/scripting/vcruntime.js +45 -0
  247. package/dist/guest/toolchains/vscode-profile.d.ts +30 -0
  248. package/dist/guest/toolchains/vscode-profile.js +69 -0
  249. package/dist/guest/toolchains/vscode.d.ts +17 -0
  250. package/dist/guest/toolchains/vscode.js +87 -1
  251. package/dist/guest/view.js +21 -1
  252. package/dist/host/accounts.js +14 -5
  253. package/dist/host/agent-commands.d.ts +25 -0
  254. package/dist/host/agent-commands.js +145 -0
  255. package/dist/host/attach.d.ts +17 -0
  256. package/dist/host/attach.js +70 -0
  257. package/dist/host/audit/collect.d.ts +34 -0
  258. package/dist/host/audit/collect.js +126 -0
  259. package/dist/host/audit/log.d.ts +46 -0
  260. package/dist/host/audit/log.js +143 -0
  261. package/dist/host/channel.d.ts +23 -22
  262. package/dist/host/channel.js +66 -84
  263. package/dist/host/claude-profile.js +7 -3
  264. package/dist/host/cleanup.js +2 -11
  265. package/dist/host/database-plan.d.ts +12 -0
  266. package/dist/host/database-plan.js +52 -0
  267. package/dist/host/generate.d.ts +10 -12
  268. package/dist/host/generate.js +58 -135
  269. package/dist/host/join.d.ts +28 -0
  270. package/dist/host/join.js +76 -0
  271. package/dist/host/launch/mappings.d.ts +3 -0
  272. package/dist/host/launch/mappings.js +54 -0
  273. package/dist/host/launch/projects.d.ts +15 -0
  274. package/dist/host/launch/projects.js +56 -0
  275. package/dist/host/launch/stage.d.ts +11 -0
  276. package/dist/host/launch/stage.js +66 -0
  277. package/dist/host/launch/wsb.d.ts +10 -0
  278. package/dist/host/launch/wsb.js +34 -0
  279. package/dist/host/motw.d.ts +17 -0
  280. package/dist/host/motw.js +74 -0
  281. package/dist/host/pc-scan.d.ts +6 -0
  282. package/dist/host/pc-scan.js +37 -0
  283. package/dist/host/platform.d.ts +2 -0
  284. package/dist/host/platform.js +16 -1
  285. package/dist/host/port-forward.d.ts +8 -0
  286. package/dist/host/port-forward.js +37 -0
  287. package/dist/host/project-scan.d.ts +1 -17
  288. package/dist/host/project-scan.js +2 -86
  289. package/dist/host/projects.d.ts +100 -0
  290. package/dist/host/projects.js +147 -0
  291. package/dist/host/repo-guard.d.ts +25 -5
  292. package/dist/host/repo-guard.js +242 -23
  293. package/dist/host/stops.d.ts +67 -0
  294. package/dist/host/stops.js +126 -0
  295. package/dist/host/terminal.d.ts +8 -0
  296. package/dist/host/terminal.js +48 -1
  297. package/dist/host/test-guard.d.ts +6 -0
  298. package/dist/host/test-guard.js +15 -0
  299. package/dist/host/window.js +7 -3
  300. package/dist/host/workspace-view/index.d.ts +20 -0
  301. package/dist/host/workspace-view/index.js +53 -0
  302. package/dist/host/workspace-view/rules.d.ts +26 -0
  303. package/dist/host/workspace-view/rules.js +93 -0
  304. package/dist/host/workspace-view/view.d.ts +50 -0
  305. package/dist/host/workspace-view/view.js +281 -0
  306. package/dist/host/wsb.d.ts +37 -0
  307. package/dist/host/wsb.js +101 -0
  308. package/dist/runtime/daemon.js +11791 -2821
  309. package/dist/runtime/db.js +6585 -466
  310. package/dist/runtime/main.js +10238 -1724
  311. package/dist/runtime/netproxy.js +25936 -0
  312. package/dist/runtime/view.js +6183 -59
  313. package/dist/selftest/accounts.test.d.ts +2 -0
  314. package/dist/selftest/accounts.test.js +44 -0
  315. package/dist/selftest/agent-commands.test.d.ts +2 -0
  316. package/dist/selftest/agent-commands.test.js +47 -0
  317. package/dist/selftest/audit.test.d.ts +2 -0
  318. package/dist/selftest/audit.test.js +57 -0
  319. package/dist/selftest/channel.test.d.ts +2 -0
  320. package/dist/selftest/channel.test.js +44 -0
  321. package/dist/selftest/cli.test.d.ts +2 -2
  322. package/dist/selftest/cli.test.js +145 -27
  323. package/dist/selftest/cmdline.test.d.ts +2 -0
  324. package/dist/selftest/cmdline.test.js +45 -0
  325. package/dist/selftest/config.test.d.ts +2 -3
  326. package/dist/selftest/config.test.js +36 -72
  327. package/dist/selftest/data.test.d.ts +2 -2
  328. package/dist/selftest/data.test.js +77 -70
  329. package/dist/selftest/detect.test.d.ts +2 -2
  330. package/dist/selftest/detect.test.js +54 -38
  331. package/dist/selftest/fixtures.d.ts +89 -4
  332. package/dist/selftest/fixtures.js +43 -24
  333. package/dist/selftest/generate.test.d.ts +2 -0
  334. package/dist/selftest/generate.test.js +68 -0
  335. package/dist/selftest/git-access.test.d.ts +2 -0
  336. package/dist/selftest/git-access.test.js +26 -0
  337. package/dist/selftest/guest-boot.test.d.ts +2 -0
  338. package/dist/selftest/guest-boot.test.js +76 -0
  339. package/dist/selftest/harness.d.ts +44 -7
  340. package/dist/selftest/harness.js +62 -21
  341. package/dist/selftest/host-sim.test.d.ts +2 -0
  342. package/dist/selftest/host-sim.test.js +93 -0
  343. package/dist/selftest/hostile-input.test.d.ts +2 -0
  344. package/dist/selftest/hostile-input.test.js +54 -0
  345. package/dist/selftest/index.d.ts +8 -1
  346. package/dist/selftest/index.js +137 -35
  347. package/dist/selftest/links.test.d.ts +2 -0
  348. package/dist/selftest/links.test.js +50 -0
  349. package/dist/selftest/live-daemon.test.d.ts +2 -0
  350. package/dist/selftest/live-daemon.test.js +91 -0
  351. package/dist/selftest/live-git.test.d.ts +2 -0
  352. package/dist/selftest/live-git.test.js +60 -0
  353. package/dist/selftest/live-network.test.d.ts +2 -0
  354. package/dist/selftest/live-network.test.js +63 -0
  355. package/dist/selftest/live-projects.test.d.ts +2 -0
  356. package/dist/selftest/live-projects.test.js +127 -0
  357. package/dist/selftest/live.d.ts +65 -0
  358. package/dist/selftest/live.js +109 -0
  359. package/dist/selftest/local-config.test.d.ts +2 -0
  360. package/dist/selftest/local-config.test.js +120 -0
  361. package/dist/selftest/mirror.test.d.ts +2 -3
  362. package/dist/selftest/mirror.test.js +92 -65
  363. package/dist/selftest/network.test.d.ts +2 -0
  364. package/dist/selftest/network.test.js +40 -0
  365. package/dist/selftest/personalization.test.d.ts +2 -0
  366. package/dist/selftest/personalization.test.js +53 -0
  367. package/dist/selftest/projects.test.d.ts +2 -0
  368. package/dist/selftest/projects.test.js +254 -0
  369. package/dist/selftest/repair.test.d.ts +2 -0
  370. package/dist/selftest/repair.test.js +42 -0
  371. package/dist/selftest/repo-guard.test.d.ts +2 -0
  372. package/dist/selftest/repo-guard.test.js +121 -0
  373. package/dist/selftest/secrets.test.d.ts +2 -0
  374. package/dist/selftest/secrets.test.js +71 -0
  375. package/dist/selftest/setup.test.d.ts +2 -2
  376. package/dist/selftest/setup.test.js +45 -22
  377. package/dist/selftest/suite.d.ts +13 -0
  378. package/dist/selftest/suite.js +1 -0
  379. package/dist/selftest/sync.test.d.ts +2 -3
  380. package/dist/selftest/sync.test.js +130 -78
  381. package/dist/selftest/test-guard.test.d.ts +2 -0
  382. package/dist/selftest/test-guard.test.js +49 -0
  383. package/dist/selftest/toolchains.test.d.ts +2 -0
  384. package/dist/selftest/toolchains.test.js +133 -0
  385. package/dist/selftest/workspace-view.test.d.ts +2 -0
  386. package/dist/selftest/workspace-view.test.js +89 -0
  387. package/dist/selftest/workspace.test.d.ts +2 -0
  388. package/dist/selftest/workspace.test.js +53 -0
  389. package/dist/shared/apps.d.ts +49 -0
  390. package/dist/shared/apps.js +114 -0
  391. package/dist/shared/download.d.ts +3 -1
  392. package/dist/shared/download.js +19 -4
  393. package/dist/shared/netpolicy.d.ts +27 -0
  394. package/dist/shared/netpolicy.js +51 -0
  395. package/dist/shared/paths.d.ts +5 -0
  396. package/dist/shared/paths.js +6 -0
  397. package/dist/shared/projects.d.ts +53 -0
  398. package/dist/shared/projects.js +67 -0
  399. package/dist/shared/pty-client.d.ts +9 -4
  400. package/dist/shared/pty-client.js +139 -17
  401. package/dist/shared/rundir.d.ts +12 -1
  402. package/dist/shared/rundir.js +14 -4
  403. package/dist/shared/safe-remove.js +11 -0
  404. package/dist/shared/schema.d.ts +453 -0
  405. package/dist/shared/schema.js +43 -2
  406. package/dist/shared/system.d.ts +1 -0
  407. package/dist/shared/system.js +1 -0
  408. package/dist/shared/test-guard.d.ts +4 -0
  409. package/dist/shared/test-guard.js +37 -0
  410. package/dist/sync/claude-mem.js +6 -3
  411. package/dist/sync/history.d.ts +29 -12
  412. package/dist/sync/history.js +72 -25
  413. package/dist/sync/watcher.d.ts +8 -0
  414. package/dist/sync/watcher.js +99 -8
  415. package/package.json +7 -6
  416. package/sandbox/bootstrap.ps1 +258 -258
  417. package/sandbox/cargoshim.cs +56 -0
  418. package/sandbox/cpucap.cs +33 -0
  419. package/sandbox/cpucap.ps1 +20 -0
  420. package/sandbox/logon.cmd +24 -16
  421. package/sandbox/memlog.ps1 +34 -0
  422. package/sandbox/openssl.cs +42 -0
  423. package/sandbox/pagefile.cs +31 -0
  424. package/sandbox/pagefile.ps1 +21 -0
  425. package/sandbox/ptyhost.cs +120 -11
  426. package/sandbox/trust.cmd +35 -35
  427. package/schemas/config.schema.json +403 -3
  428. package/schemas/sandbox-config.schema.json +143 -13
  429. package/dist/cli/commands/data.d.ts +0 -46
  430. package/dist/cli/commands/data.js +0 -249
  431. package/dist/cli/commands/setup.js +0 -152
  432. package/dist/cli/menu.d.ts +0 -22
  433. package/dist/cli/menu.js +0 -187
  434. package/dist/cli/settings.d.ts +0 -11
  435. package/dist/cli/settings.js +0 -156
  436. package/dist/guest/toolchains/databases.js +0 -226
  437. package/dist/guest/toolchains/msvc.d.ts +0 -10
  438. package/dist/guest/toolchains/msvc.js +0 -216
  439. package/dist/guest/toolchains/native.d.ts +0 -12
  440. package/dist/guest/toolchains/native.js +0 -220
  441. package/dist/guest/toolchains/scripting.d.ts +0 -10
  442. package/dist/guest/toolchains/scripting.js +0 -137
  443. package/dist/selftest/guest.test.d.ts +0 -3
  444. package/dist/selftest/guest.test.js +0 -61
  445. package/dist/selftest/helpers.test.d.ts +0 -2
  446. package/dist/selftest/helpers.test.js +0 -125
  447. package/dist/selftest/host.test.d.ts +0 -2
  448. package/dist/selftest/host.test.js +0 -71
  449. package/dist/selftest/live.test.d.ts +0 -7
  450. package/dist/selftest/live.test.js +0 -127
  451. package/dist/selftest/security.test.d.ts +0 -3
  452. package/dist/selftest/security.test.js +0 -143
  453. /package/dist/guest/toolchains/{binstall.d.ts → native/binstall.d.ts} +0 -0
package/sandbox/logon.cmd CHANGED
@@ -1,16 +1,24 @@
1
- @echo off
2
- rem Windows Sandbox runs LogonCommand in a hidden window, so this opens the VISIBLE sandbox window: Windows Terminal
3
- rem (downloaded once by the host into persistent storage), or a plain PowerShell window if it is missing or fails.
4
- if not exist C:\AgentData\logs mkdir C:\AgentData\logs
5
- echo logon.cmd ran at %date% %time% > C:\AgentData\logs\logon-hit.txt
6
- call C:\AgentLaunch\sandbox\trust.cmd
7
- set "PS=%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe"
8
- set "BOOT=%PS% -NoLogo -NoProfile -ExecutionPolicy Bypass -NoExit -File C:\AgentLaunch\sandbox\bootstrap.ps1"
9
- if not exist C:\AgentData\tools\terminal\wt.exe goto plain
10
- start "" C:\AgentData\tools\terminal\wt.exe --maximized new-tab --title "Agent Sandbox" -d C:\AgentLaunch %BOOT%
11
- rem If Windows Terminal could not start, fall back to PowerShell so there is always a window.
12
- %SystemRoot%\System32\timeout.exe /t 10 /nobreak >nul
13
- %SystemRoot%\System32\tasklist.exe /fi "imagename eq WindowsTerminal.exe" | %SystemRoot%\System32\find.exe /i "WindowsTerminal" >nul && exit /b 0
14
- echo Windows Terminal did not start; using PowerShell. >> C:\AgentData\logs\logon-hit.txt
15
- :plain
16
- start "Agent Sandbox" %BOOT%
1
+ @echo off
2
+ rem Windows Sandbox runs LogonCommand in a hidden window, so this opens the VISIBLE sandbox window: Windows Terminal
3
+ rem (downloaded once by the host into persistent storage), or a plain PowerShell window if it is missing or fails.
4
+ if not exist C:\AgentData\logs mkdir C:\AgentData\logs
5
+ echo logon.cmd ran at %date% %time% > C:\AgentData\logs\logon-hit.txt
6
+ call C:\AgentLaunch\sandbox\trust.cmd
7
+ rem New Terminal tabs start in %AGENT_WORKSPACE%: Terminal must have it before the runtime sets it machine-wide.
8
+ if exist C:\AgentLaunch\env.cmd call C:\AgentLaunch\env.cmd
9
+ set "PS=%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe"
10
+ rem sandbox.cpuLimit: this window joins a CPU-capped job first, so everything started below inherits the cap.
11
+ "%PS%" -NoLogo -NoProfile -ExecutionPolicy Bypass -File C:\AgentLaunch\sandbox\cpucap.ps1
12
+ rem sandbox.pageFileMb: room for many parallel builds (the sandbox starts with about 1 GB of paging file).
13
+ "%PS%" -NoLogo -NoProfile -ExecutionPolicy Bypass -File C:\AgentLaunch\sandbox\pagefile.ps1
14
+ rem The memory state every 30 s into the persistent logs, so a crash leaves evidence.
15
+ start "" /min "%PS%" -NoLogo -NoProfile -WindowStyle Hidden -ExecutionPolicy Bypass -File C:\AgentLaunch\sandbox\memlog.ps1
16
+ set "BOOT=%PS% -NoLogo -NoProfile -ExecutionPolicy Bypass -NoExit -File C:\AgentLaunch\sandbox\bootstrap.ps1"
17
+ if not exist C:\AgentData\tools\terminal\wt.exe goto plain
18
+ start "" C:\AgentData\tools\terminal\wt.exe --maximized new-tab --title "Agent Sandbox" -d C:\AgentLaunch %BOOT%
19
+ rem If Windows Terminal could not start, fall back to PowerShell so there is always a window.
20
+ %SystemRoot%\System32\timeout.exe /t 10 /nobreak >nul
21
+ %SystemRoot%\System32\tasklist.exe /fi "imagename eq WindowsTerminal.exe" | %SystemRoot%\System32\find.exe /i "WindowsTerminal" >nul && exit /b 0
22
+ echo Windows Terminal did not start; using PowerShell. >> C:\AgentData\logs\logon-hit.txt
23
+ :plain
24
+ start "Agent Sandbox" %BOOT%
@@ -0,0 +1,34 @@
1
+ #Requires -Version 5.1
2
+ # Writes the sandbox's memory state to C:\AgentData\logs\memory-<time>.log every 30 seconds, while it runs. That folder
3
+ # outlives the sandbox, so if Windows inside it ever crashes again, the last lines show what was using memory just
4
+ # before. Bounded: a file is closed at 1 MB (about two days) and a new one started; only the newest 10 are kept, so
5
+ # the logs never take more than about 10 MB. Started hidden by logon.cmd. Never stops the boot.
6
+ $ErrorActionPreference = 'SilentlyContinue'
7
+ $logFolder = 'C:\AgentData\logs'
8
+ $maxFileBytes = 1MB
9
+ $keepFiles = 10
10
+
11
+ # A new log file, and the oldest ones beyond $keepFiles removed. Returns its path.
12
+ function New-MemoryLog {
13
+ $path = Join-Path $logFolder ('memory-{0:yyyyMMdd-HHmmss}.log' -f (Get-Date))
14
+ 'time | RAM used/total MB | commit used/limit MB | biggest processes (private MB)' | Set-Content -LiteralPath $path
15
+ Get-ChildItem -LiteralPath $logFolder -Filter 'memory-*.log' | Sort-Object LastWriteTime -Descending |
16
+ Select-Object -Skip $keepFiles | Remove-Item -Force
17
+ return $path
18
+ }
19
+
20
+ $logPath = New-MemoryLog
21
+ while ($true) {
22
+ $os = Get-CimInstance Win32_OperatingSystem
23
+ $ramTotalMb = [math]::Round($os.TotalVisibleMemorySize / 1KB)
24
+ $ramUsedMb = $ramTotalMb - [math]::Round($os.FreePhysicalMemory / 1KB)
25
+ $commitLimitMb = [math]::Round($os.TotalVirtualMemorySize / 1KB)
26
+ $commitUsedMb = $commitLimitMb - [math]::Round($os.FreeVirtualMemory / 1KB)
27
+ $processes = @(Get-Process)
28
+ $biggest = $processes | Sort-Object PrivateMemorySize64 -Descending | Select-Object -First 5 |
29
+ ForEach-Object { '{0} {1}' -f $_.ProcessName, [math]::Round($_.PrivateMemorySize64 / 1MB) }
30
+ '{0:HH:mm:ss} | {1}/{2} | {3}/{4} | {5} processes; {6}' -f (Get-Date), $ramUsedMb, $ramTotalMb, $commitUsedMb, $commitLimitMb, $processes.Count, ($biggest -join ', ') |
31
+ Add-Content -LiteralPath $logPath
32
+ if ((Get-Item -LiteralPath $logPath).Length -ge $maxFileBytes) { $logPath = New-MemoryLog }
33
+ Start-Sleep -Seconds 30
34
+ }
@@ -0,0 +1,42 @@
1
+ // openssl.exe stand-in on the sandbox's PATH (tools\shims), running the copy Git for Windows ships in
2
+ // <tools>\git\mingw64\bin. A real .exe, so CreateProcess callers (Rust's Command::new("openssl"), Node's spawn) find it,
3
+ // which a .cmd would not be; and mingw64\bin itself stays off PATH, where it would shadow the MinGW gcc.
4
+ // It finds Git relative to itself (<tools>\shims\openssl.exe -> <tools>\git\...) and sets OPENSSL_CONF for the child
5
+ // only when the caller has none. C# 5 (compiled in the sandbox by the .NET Framework csc).
6
+ using System;
7
+ using System.Diagnostics;
8
+ using System.IO;
9
+
10
+ static class OpensslShim
11
+ {
12
+ static int Main()
13
+ {
14
+ string here = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
15
+ string mingw = Path.GetFullPath(Path.Combine(here, "..\\git\\mingw64"));
16
+ string exe = Path.Combine(mingw, "bin\\openssl.exe");
17
+ if (!File.Exists(exe))
18
+ {
19
+ Console.Error.WriteLine("openssl is not available: Git for Windows is not installed in this sandbox.");
20
+ return 127;
21
+ }
22
+ var start = new ProcessStartInfo(exe, ArgumentsOf(Environment.CommandLine)) { UseShellExecute = false };
23
+ string conf = Path.Combine(mingw, "etc\\ssl\\openssl.cnf");
24
+ if (string.IsNullOrEmpty(Environment.GetEnvironmentVariable("OPENSSL_CONF")) && File.Exists(conf))
25
+ start.EnvironmentVariables["OPENSSL_CONF"] = conf;
26
+ using (Process p = Process.Start(start))
27
+ {
28
+ p.WaitForExit();
29
+ return p.ExitCode;
30
+ }
31
+ }
32
+
33
+ // Everything after the program name, untouched, so quoting survives exactly as the caller wrote it.
34
+ static string ArgumentsOf(string commandLine)
35
+ {
36
+ string s = commandLine.TrimStart();
37
+ int end;
38
+ if (s.StartsWith("\"")) { end = s.IndexOf('"', 1); end = end < 0 ? s.Length : end + 1; }
39
+ else { end = s.IndexOf(' '); if (end < 0) end = s.Length; }
40
+ return s.Substring(end).TrimStart();
41
+ }
42
+ }
@@ -0,0 +1,31 @@
1
+ // Sets the size of the sandbox's paging file at once, with no restart. Loaded by pagefile.ps1 (Add-Type). C# 5.
2
+ using System;
3
+ using System.ComponentModel;
4
+ using System.Runtime.InteropServices;
5
+
6
+ public static class SandboxPageFile {
7
+ // UNICODE_STRING. The marshaller copies Buffer to native memory for the length of the call.
8
+ [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
9
+ private struct NtString { public ushort Length; public ushort MaximumLength; public string Buffer; }
10
+
11
+ [DllImport("ntdll.dll")] private static extern int RtlAdjustPrivilege(int privilege, bool enable, bool currentThread, out bool wasEnabled);
12
+ [DllImport("ntdll.dll")] private static extern int NtCreatePagingFile(ref NtString path, ref long minimumBytes, ref long maximumBytes, uint priority);
13
+ [DllImport("ntdll.dll")] private static extern int RtlNtStatusToDosError(int status);
14
+
15
+ private const int SeCreatePagefilePrivilege = 15;
16
+
17
+ /// <summary>Makes C:\pagefile.sys sizeMb, fixed (it never grows). Throws with Windows' reason on failure.</summary>
18
+ public static void Set(int sizeMb) {
19
+ bool wasEnabled;
20
+ Check(RtlAdjustPrivilege(SeCreatePagefilePrivilege, true, false, out wasEnabled));
21
+ // The same call Windows makes at startup; for the existing file it changes the size in place.
22
+ const string path = @"\??\C:\pagefile.sys";
23
+ NtString name = new NtString { Length = (ushort)(path.Length * 2), MaximumLength = (ushort)(path.Length * 2 + 2), Buffer = path };
24
+ long minimum = sizeMb * 1048576L, maximum = minimum;
25
+ Check(NtCreatePagingFile(ref name, ref minimum, ref maximum, 0));
26
+ }
27
+
28
+ private static void Check(int status) {
29
+ if (status != 0) throw new Win32Exception(RtlNtStatusToDosError(status));
30
+ }
31
+ }
@@ -0,0 +1,21 @@
1
+ #Requires -Version 5.1
2
+ # Gives the sandbox a paging file of sandbox.pageFileMb, created at full size now, before anything runs. Windows Sandbox
3
+ # starts with about 1 GB, so parallel builds run out of memory ("The paging file is too small", os error 1455), and
4
+ # then Windows grows the file while they run: both crashes of Windows inside the sandbox (13 Oct 2026, stop code 0x1A
5
+ # MEMORY_MANAGEMENT) happened under that load. A fixed size never grows. Never stops the boot: it logs one line.
6
+ param([int]$SizeMb = 0) # 0 = read sandbox.pageFileMb from session.json
7
+ $ErrorActionPreference = 'Stop'
8
+ $log = 'C:\AgentData\logs\logon-hit.txt'
9
+ try {
10
+ if ($SizeMb -eq 0) { $SizeMb = [int](Get-Content -LiteralPath 'C:\AgentLaunch\session.json' -Raw -Encoding UTF8 | ConvertFrom-Json).pageFileMb }
11
+ if ($SizeMb -le 0) { exit 0 }
12
+ # Keep 8 GB of the sandbox's disk free for everything else.
13
+ $SizeMb = [math]::Min($SizeMb, [math]::Floor((Get-PSDrive -Name C).Free / 1MB) - 8192)
14
+ if ($SizeMb -lt 1024) { throw 'too little free disk.' }
15
+ Add-Type -Path (Join-Path $PSScriptRoot 'pagefile.cs')
16
+ [SandboxPageFile]::Set($SizeMb)
17
+ "Paging file set to $SizeMb MB, fixed (sandbox.pageFileMb)." | Add-Content -LiteralPath $log
18
+ } catch {
19
+ "Paging file left as it is: $($_.Exception.Message)" | Add-Content -LiteralPath $log
20
+ }
21
+ exit 0
@@ -16,6 +16,9 @@
16
16
  // 18 ERROR utf8 message
17
17
  // 19 RESTARTING
18
18
  // 20 STATUS [viewers:2][remoteViewers:2] viewers heard from recently (remote = not loopback, i.e. the PC)
19
+ // 21 CONSOLE utf8 "conpty.dll" or "windows", sent after HELLO. With conpty.dll the output is passed
20
+ // through (real scrollback, no repaint on resize): a viewer that joins later is sent the
21
+ // output since the last screen clear instead, and must not clear its screen on a resize.
19
22
  using System;
20
23
  using System.Collections.Concurrent;
21
24
  using System.Collections.Generic;
@@ -75,6 +78,7 @@ sealed class SessionHost
75
78
  using (var console = PseudoConsole.Start(command, hub.Cols, hub.Rows, hub.Broadcast))
76
79
  {
77
80
  hub.Attach(console);
81
+ log.Write("pseudo console: " + Native.ConsoleKind);
78
82
  int exitCode = console.WaitForExit();
79
83
  if (!restartRequested)
80
84
  {
@@ -92,6 +96,7 @@ sealed class SessionHost
92
96
  public void Restart()
93
97
  {
94
98
  restartRequested = true;
99
+ hub.ResetReplay();
95
100
  hub.Notify(Frame.Restarting);
96
101
  hub.KillProgram();
97
102
  }
@@ -181,6 +186,8 @@ sealed class Client
181
186
  public readonly NetworkStream Stream;
182
187
  public readonly BlockingCollection<byte[]> Outbox = new BlockingCollection<byte[]>(4096);
183
188
  public readonly bool Remote;
189
+ /** Set by the writer thread once everything queued has been written and the connection is closed. */
190
+ public readonly ManualResetEvent Finished = new ManualResetEvent(false);
184
191
  public bool ControlOnly, Query;
185
192
  public short Cols, Rows;
186
193
  long lastSeen = DateTime.UtcNow.Ticks;
@@ -203,7 +210,11 @@ sealed class Client
203
210
  {
204
211
  try { foreach (byte[] frame in Outbox.GetConsumingEnumerable()) Stream.Write(frame, 0, frame.Length); }
205
212
  catch (Exception) { }
206
- finally { try { Tcp.Close(); } catch (Exception) { } }
213
+ finally
214
+ {
215
+ try { Tcp.Close(); } catch (Exception) { }
216
+ Finished.Set();
217
+ }
207
218
  }
208
219
  }
209
220
 
@@ -219,6 +230,9 @@ sealed class ClientHub
219
230
  readonly byte[] token;
220
231
  readonly byte[] tail = new byte[8192];
221
232
  int tailLength;
233
+ readonly object replayGate = new object();
234
+ readonly MemoryStream replay = new MemoryStream();
235
+ const int MaxReplay = 4 << 20;
222
236
  PseudoConsole console;
223
237
  Client sizeOwner;
224
238
  short cols, rows;
@@ -245,8 +259,18 @@ sealed class ClientHub
245
259
  client.ControlOnly = (hello[4] & 3) != 0;
246
260
  client.Query = (hello[4] & 2) != 0;
247
261
  if (client.Query) return true;
248
- lock (gate) clients.Add(client);
249
- if (!client.ControlOnly) TakeOwnership(client);
262
+ if (!client.ControlOnly)
263
+ {
264
+ Send(client, Frame.Console, Encoding.UTF8.GetBytes(Native.ConsoleKind.StartsWith("conpty") ? "conpty.dll" : "windows"));
265
+ // Taken and queued under the replay lock, so no output falls between the replay and the live stream.
266
+ lock (replayGate)
267
+ {
268
+ if (Native.ConsoleKind.StartsWith("conpty") && replay.Length > 0) Send(client, Frame.Output, replay.ToArray());
269
+ lock (gate) clients.Add(client);
270
+ }
271
+ TakeOwnership(client);
272
+ }
273
+ else lock (gate) clients.Add(client);
250
274
  return true;
251
275
  }
252
276
 
@@ -281,7 +305,41 @@ sealed class ClientHub
281
305
  public void Broadcast(byte[] output)
282
306
  {
283
307
  Remember(output);
284
- foreach (Client c in Snapshot()) if (!c.ControlOnly) Send(c, Frame.Output, output);
308
+ lock (replayGate)
309
+ {
310
+ Record(output);
311
+ foreach (Client c in Snapshot()) if (!c.ControlOnly) Send(c, Frame.Output, output);
312
+ }
313
+ }
314
+
315
+ /**
316
+ * The output a viewer joining now needs to see the screen (conpty.dll does not repaint for it): everything since the
317
+ * last "clear screen", capped. Cut at a line start when capped, so the replay never begins inside an escape sequence.
318
+ */
319
+ void Record(byte[] output)
320
+ {
321
+ if (!Native.ConsoleKind.StartsWith("conpty")) return;
322
+ int clear = LastClear(output);
323
+ if (clear >= 0) { replay.SetLength(0); replay.Write(output, clear, output.Length - clear); }
324
+ else replay.Write(output, 0, output.Length);
325
+ if (replay.Length <= MaxReplay) return;
326
+ byte[] all = replay.ToArray();
327
+ int from = all.Length - MaxReplay / 2;
328
+ while (from < all.Length && all[from] != (byte)'\n') from++;
329
+ replay.SetLength(0);
330
+ if (from + 1 < all.Length) replay.Write(all, from + 1, all.Length - from - 1);
331
+ }
332
+
333
+ /** Where the last ESC[2J (clear screen) or ESC c (reset) starts in `data`, or -1. */
334
+ static int LastClear(byte[] data)
335
+ {
336
+ for (int i = data.Length - 2; i >= 0; i--)
337
+ {
338
+ if (data[i] != 0x1b) continue;
339
+ if (data[i + 1] == (byte)'c') return i;
340
+ if (i + 3 < data.Length && data[i + 1] == (byte)'[' && data[i + 2] == (byte)'2' && data[i + 3] == (byte)'J') return i;
341
+ }
342
+ return -1;
285
343
  }
286
344
 
287
345
  /** The program's last output as plain text (escape sequences removed), for the log when it exits. */
@@ -305,6 +363,9 @@ sealed class ClientHub
305
363
  }
306
364
  }
307
365
 
366
+ /** A restarted program starts on a clean screen (viewers clear theirs on RESTARTING). */
367
+ public void ResetReplay() { lock (replayGate) replay.SetLength(0); }
368
+
308
369
  public void Notify(byte type)
309
370
  {
310
371
  foreach (Client c in Snapshot()) if (!c.ControlOnly) Send(c, type, new byte[0]);
@@ -323,7 +384,7 @@ sealed class ClientHub
323
384
  var everyone = Snapshot();
324
385
  foreach (Client c in everyone) { Send(c, Frame.Exit, code); Retire(c); }
325
386
  // Give the writer threads a moment to deliver the EXIT frame before the process ends.
326
- foreach (Client c in everyone) for (int i = 0; i < 20 && c.Outbox.Count > 0; i++) Thread.Sleep(50);
387
+ foreach (Client c in everyone) c.Finished.WaitOne(1000);
327
388
  }
328
389
 
329
390
  /** Stops sending to a client after what is already queued (its writer closes the connection when done). */
@@ -343,11 +404,16 @@ sealed class ClientHub
343
404
  if (next != null) TakeOwnership(next);
344
405
  }
345
406
 
346
- /** Disconnects a client (after at most half a second for frames already queued, e.g. "access denied"). */
407
+ /**
408
+ * Disconnects a client. Frames already queued (e.g. "access denied", STATUS) are written first: the client's writer
409
+ * thread closes the connection when it is done, so wait for that rather than for an empty queue (the writer takes a
410
+ * frame off the queue before it has written it, so an empty queue does not mean "sent"), and only force the close
411
+ * if the peer is not reading.
412
+ */
347
413
  public void Kill(Client client)
348
414
  {
349
415
  Retire(client);
350
- for (int i = 0; i < 20 && client.Outbox.Count > 0; i++) Thread.Sleep(25);
416
+ client.Finished.WaitOne(3000);
351
417
  try { client.Tcp.Close(); } catch (Exception) { }
352
418
  }
353
419
 
@@ -492,7 +558,7 @@ sealed class PseudoConsole : IDisposable
492
558
  static class Frame
493
559
  {
494
560
  public const byte Hello = 1, Input = 2, Resize = 3, Restart = 4, Ping = 5;
495
- public const byte Output = 16, Exit = 17, Error = 18, Restarting = 19, Status = 20;
561
+ public const byte Output = 16, Exit = 17, Error = 18, Restarting = 19, Status = 20, Console = 21;
496
562
  const int MaxPayload = 1 << 20;
497
563
 
498
564
  public static bool Read(Stream stream, out byte type, out byte[] payload)
@@ -587,9 +653,52 @@ static class Native
587
653
  }
588
654
  }
589
655
 
590
- [DllImport("kernel32.dll")] public static extern int CreatePseudoConsole(Coord size, SafeFileHandle hInput, SafeFileHandle hOutput, uint dwFlags, out IntPtr phPC);
591
- [DllImport("kernel32.dll")] public static extern int ResizePseudoConsole(IntPtr hPC, Coord size);
592
- [DllImport("kernel32.dll")] public static extern void ClosePseudoConsole(IntPtr hPC);
656
+ // The pseudo console: the newer conpty.dll (+ OpenConsole.exe next to it) when PTYHOST_CONPTY names one, else the one
657
+ // built into Windows. Windows 10/11 before 24H2 ship a ConPTY that re-renders the screen instead of passing the
658
+ // program's output through, which garbles wide characters after a resize and loses mouse input and scrollback.
659
+ [UnmanagedFunctionPointer(CallingConvention.Winapi)] delegate int CreateFn(Coord size, SafeFileHandle hInput, SafeFileHandle hOutput, uint dwFlags, out IntPtr phPC);
660
+ [UnmanagedFunctionPointer(CallingConvention.Winapi)] delegate int ResizeFn(IntPtr hPC, Coord size);
661
+ [UnmanagedFunctionPointer(CallingConvention.Winapi)] delegate void CloseFn(IntPtr hPC);
662
+ static CreateFn create;
663
+ static ResizeFn resize;
664
+ static CloseFn close;
665
+ /** "conpty.dll" or "windows": which pseudo console is in use (logged, and told to viewers). */
666
+ public static string ConsoleKind = "windows";
667
+
668
+ static Native()
669
+ {
670
+ string dll = Environment.GetEnvironmentVariable("PTYHOST_CONPTY");
671
+ if (string.IsNullOrEmpty(dll) || !File.Exists(dll) || !File.Exists(Path.Combine(Path.GetDirectoryName(dll), "OpenConsole.exe"))) return;
672
+ IntPtr module = LoadLibraryW(dll);
673
+ if (module == IntPtr.Zero) return;
674
+ IntPtr c = GetProcAddress(module, "ConptyCreatePseudoConsole"), r = GetProcAddress(module, "ConptyResizePseudoConsole"), x = GetProcAddress(module, "ConptyClosePseudoConsole");
675
+ if (c == IntPtr.Zero || r == IntPtr.Zero || x == IntPtr.Zero) return;
676
+ create = (CreateFn)Marshal.GetDelegateForFunctionPointer(c, typeof(CreateFn));
677
+ resize = (ResizeFn)Marshal.GetDelegateForFunctionPointer(r, typeof(ResizeFn));
678
+ close = (CloseFn)Marshal.GetDelegateForFunctionPointer(x, typeof(CloseFn));
679
+ ConsoleKind = "conpty.dll";
680
+ }
681
+
682
+ /** conpty.dll first; if it cannot start one (OpenConsole.exe blocked or broken), the built-in one for good. */
683
+ public static int CreatePseudoConsole(Coord size, SafeFileHandle hInput, SafeFileHandle hOutput, uint dwFlags, out IntPtr phPC)
684
+ {
685
+ if (create != null)
686
+ {
687
+ int hr = create(size, hInput, hOutput, dwFlags, out phPC);
688
+ if (hr == 0) return 0;
689
+ create = null; resize = null; close = null;
690
+ ConsoleKind = "windows (conpty.dll failed: 0x" + hr.ToString("X8") + ")";
691
+ }
692
+ return KernelCreatePseudoConsole(size, hInput, hOutput, dwFlags, out phPC);
693
+ }
694
+ public static int ResizePseudoConsole(IntPtr hPC, Coord size) { return resize != null ? resize(hPC, size) : KernelResizePseudoConsole(hPC, size); }
695
+ public static void ClosePseudoConsole(IntPtr hPC) { if (close != null) close(hPC); else KernelClosePseudoConsole(hPC); }
696
+
697
+ [DllImport("kernel32.dll", EntryPoint = "CreatePseudoConsole")] static extern int KernelCreatePseudoConsole(Coord size, SafeFileHandle hInput, SafeFileHandle hOutput, uint dwFlags, out IntPtr phPC);
698
+ [DllImport("kernel32.dll", EntryPoint = "ResizePseudoConsole")] static extern int KernelResizePseudoConsole(IntPtr hPC, Coord size);
699
+ [DllImport("kernel32.dll", EntryPoint = "ClosePseudoConsole")] static extern void KernelClosePseudoConsole(IntPtr hPC);
700
+ [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)] static extern IntPtr LoadLibraryW(string path);
701
+ [DllImport("kernel32.dll", CharSet = CharSet.Ansi, BestFitMapping = false)] static extern IntPtr GetProcAddress(IntPtr module, string name);
593
702
  [DllImport("kernel32.dll", SetLastError = true)] public static extern bool CreatePipe(out SafeFileHandle hReadPipe, out SafeFileHandle hWritePipe, IntPtr lpPipeAttributes, int nSize);
594
703
  [DllImport("kernel32.dll", SetLastError = true)] static extern bool InitializeProcThreadAttributeList(IntPtr lpAttributeList, int dwAttributeCount, int dwFlags, ref IntPtr lpSize);
595
704
  [DllImport("kernel32.dll", SetLastError = true)] static extern bool UpdateProcThreadAttribute(IntPtr lpAttributeList, uint dwFlags, IntPtr attribute, IntPtr lpValue, IntPtr cbSize, IntPtr lpPreviousValue, IntPtr lpReturnSize);
package/sandbox/trust.cmd CHANGED
@@ -1,35 +1,35 @@
1
- @echo off
2
- rem Runs first at logon, INSIDE the disposable sandbox only (the host PC is never touched).
3
- rem Lets the sandbox's own tools run without "Open File - Security Warning", SmartScreen, script-policy or UAC prompts.
4
- rem The security boundary is Windows Sandbox itself plus workspace-only write access and the LAN block; these prompts add
5
- rem nothing inside a throwaway VM except interruptions.
6
- set "POL=HKCU\Software\Microsoft\Windows\CurrentVersion\Policies"
7
- reg add "%POL%\Associations" /v LowRiskFileTypes /t REG_SZ /d ".exe;.com;.cmd;.bat;.ps1;.psm1;.msi;.vbs;.js;.zip;.7z" /f >nul
8
- reg add "%POL%\Attachments" /v SaveZoneInformation /t REG_DWORD /d 1 /f >nul
9
- rem Mapped folders and UNC paths count as Local Intranet, where launching programs is allowed without asking.
10
- reg add "HKCU\Software\Microsoft\Windows\CurrentVersion\Internet Settings\ZoneMap" /v UNCAsIntranet /t REG_DWORD /d 1 /f >nul
11
- reg add "HKCU\Software\Microsoft\Windows\CurrentVersion\Internet Settings\ZoneMap" /v IntranetName /t REG_DWORD /d 1 /f >nul
12
- rem Files copied from this PC keep their "downloaded from the internet" mark, so launching is allowed in every zone
13
- rem (1806 = 0), for this user and machine-wide, and ShellExecute skips the zone check altogether.
14
- for %%Z in (0 1 2 3 4) do (
15
- reg add "HKCU\Software\Microsoft\Windows\CurrentVersion\Internet Settings\Zones\%%Z" /v 1806 /t REG_DWORD /d 0 /f >nul
16
- reg add "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Internet Settings\Zones\%%Z" /v 1806 /t REG_DWORD /d 0 /f >nul 2>&1
17
- )
18
- reg add "HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment" /v SEE_MASK_NOZONECHECKS /t REG_SZ /d 1 /f >nul 2>&1
19
- set "SEE_MASK_NOZONECHECKS=1"
20
- rem Paths over 260 characters (deep node_modules, Gradle and NuGet caches) work for every program.
21
- reg add "HKLM\SYSTEM\CurrentControlSet\Control\FileSystem" /v LongPathsEnabled /t REG_DWORD /d 1 /f >nul 2>&1
22
- rem "Windows Defender Firewall has blocked some features of this app" pops up whenever a program (node, a dev server,
23
- rem the session host) listens on the network. Inbound stays blocked, just silently; the attach rule lets this PC in.
24
- netsh advfirewall set allprofiles settings inboundusernotification disable >nul 2>&1
25
- for %%P in (DomainProfile PrivateProfile PublicProfile) do reg add "HKLM\SOFTWARE\Policies\Microsoft\WindowsFirewall\%%P" /v DisableNotifications /t REG_DWORD /d 1 /f >nul 2>&1
26
- rem SmartScreen ("Windows protected your PC") for downloaded, unsigned tools.
27
- reg add "HKLM\SOFTWARE\Policies\Microsoft\Windows\System" /v EnableSmartScreen /t REG_DWORD /d 0 /f >nul 2>&1
28
- reg add "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer" /v SmartScreenEnabled /t REG_SZ /d Off /f >nul 2>&1
29
- rem PowerShell scripts (hooks, installers) run without the "Do you want to run ..." question.
30
- reg add "HKLM\SOFTWARE\Microsoft\PowerShell\1\ShellIds\Microsoft.PowerShell" /v ExecutionPolicy /t REG_SZ /d Bypass /f >nul 2>&1
31
- reg add "HKCU\SOFTWARE\Microsoft\PowerShell\1\ShellIds\Microsoft.PowerShell" /v ExecutionPolicy /t REG_SZ /d Bypass /f >nul
32
- rem Elevation requests from the (already admin) sandbox user are granted without a dialog.
33
- reg add "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System" /v ConsentPromptBehaviorAdmin /t REG_DWORD /d 0 /f >nul 2>&1
34
- reg add "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System" /v PromptOnSecureDesktop /t REG_DWORD /d 0 /f >nul 2>&1
35
- exit /b 0
1
+ @echo off
2
+ rem Runs first at logon, INSIDE the disposable sandbox only (the host PC is never touched).
3
+ rem Lets the sandbox's own tools run without "Open File - Security Warning", SmartScreen, script-policy or UAC prompts.
4
+ rem The security boundary is Windows Sandbox itself plus workspace-only write access and the LAN block; these prompts add
5
+ rem nothing inside a throwaway VM except interruptions.
6
+ set "POL=HKCU\Software\Microsoft\Windows\CurrentVersion\Policies"
7
+ reg add "%POL%\Associations" /v LowRiskFileTypes /t REG_SZ /d ".exe;.com;.cmd;.bat;.ps1;.psm1;.msi;.vbs;.js;.zip;.7z" /f >nul
8
+ reg add "%POL%\Attachments" /v SaveZoneInformation /t REG_DWORD /d 1 /f >nul
9
+ rem Mapped folders and UNC paths count as Local Intranet, where launching programs is allowed without asking.
10
+ reg add "HKCU\Software\Microsoft\Windows\CurrentVersion\Internet Settings\ZoneMap" /v UNCAsIntranet /t REG_DWORD /d 1 /f >nul
11
+ reg add "HKCU\Software\Microsoft\Windows\CurrentVersion\Internet Settings\ZoneMap" /v IntranetName /t REG_DWORD /d 1 /f >nul
12
+ rem Files copied from this PC keep their "downloaded from the internet" mark, so launching is allowed in every zone
13
+ rem (1806 = 0), for this user and machine-wide, and ShellExecute skips the zone check altogether.
14
+ for %%Z in (0 1 2 3 4) do (
15
+ reg add "HKCU\Software\Microsoft\Windows\CurrentVersion\Internet Settings\Zones\%%Z" /v 1806 /t REG_DWORD /d 0 /f >nul
16
+ reg add "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Internet Settings\Zones\%%Z" /v 1806 /t REG_DWORD /d 0 /f >nul 2>&1
17
+ )
18
+ reg add "HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment" /v SEE_MASK_NOZONECHECKS /t REG_SZ /d 1 /f >nul 2>&1
19
+ set "SEE_MASK_NOZONECHECKS=1"
20
+ rem Paths over 260 characters (deep node_modules, Gradle and NuGet caches) work for every program.
21
+ reg add "HKLM\SYSTEM\CurrentControlSet\Control\FileSystem" /v LongPathsEnabled /t REG_DWORD /d 1 /f >nul 2>&1
22
+ rem "Windows Defender Firewall has blocked some features of this app" pops up whenever a program (node, a dev server,
23
+ rem the session host) listens on the network. Inbound stays blocked, just silently; the attach rule lets this PC in.
24
+ netsh advfirewall set allprofiles settings inboundusernotification disable >nul 2>&1
25
+ for %%P in (DomainProfile PrivateProfile PublicProfile) do reg add "HKLM\SOFTWARE\Policies\Microsoft\WindowsFirewall\%%P" /v DisableNotifications /t REG_DWORD /d 1 /f >nul 2>&1
26
+ rem SmartScreen ("Windows protected your PC") for downloaded, unsigned tools.
27
+ reg add "HKLM\SOFTWARE\Policies\Microsoft\Windows\System" /v EnableSmartScreen /t REG_DWORD /d 0 /f >nul 2>&1
28
+ reg add "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer" /v SmartScreenEnabled /t REG_SZ /d Off /f >nul 2>&1
29
+ rem PowerShell scripts (hooks, installers) run without the "Do you want to run ..." question.
30
+ reg add "HKLM\SOFTWARE\Microsoft\PowerShell\1\ShellIds\Microsoft.PowerShell" /v ExecutionPolicy /t REG_SZ /d Bypass /f >nul 2>&1
31
+ reg add "HKCU\SOFTWARE\Microsoft\PowerShell\1\ShellIds\Microsoft.PowerShell" /v ExecutionPolicy /t REG_SZ /d Bypass /f >nul
32
+ rem Elevation requests from the (already admin) sandbox user are granted without a dialog.
33
+ reg add "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System" /v ConsentPromptBehaviorAdmin /t REG_DWORD /d 0 /f >nul 2>&1
34
+ reg add "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System" /v PromptOnSecureDesktop /t REG_DWORD /d 0 /f >nul 2>&1
35
+ exit /b 0