windows-development-sandbox 1.5.0 → 1.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (709) hide show
  1. package/README.md +1 -0
  2. package/config.example.json +27 -1
  3. package/dist/app/context.d.ts +8 -0
  4. package/dist/app/context.js +12 -0
  5. package/dist/app/features/defs.d.ts +322 -0
  6. package/dist/app/features/defs.js +28 -0
  7. package/dist/app/features/sandbox/index.d.ts +2 -0
  8. package/dist/app/features/sandbox/index.js +3 -0
  9. package/dist/app/features/sandbox/sandbox.def.d.ts +193 -0
  10. package/dist/app/features/sandbox/sandbox.def.js +245 -0
  11. package/dist/app/features/sandbox/sandbox.run.d.ts +72 -0
  12. package/dist/app/features/sandbox/sandbox.run.js +98 -0
  13. package/dist/app/features/sessions/index.d.ts +2 -0
  14. package/dist/app/features/sessions/index.js +3 -0
  15. package/dist/app/features/sessions/sessions.def.d.ts +141 -0
  16. package/dist/app/features/sessions/sessions.def.js +176 -0
  17. package/dist/app/features/sessions/sessions.run.d.ts +39 -0
  18. package/dist/app/features/sessions/sessions.run.js +58 -0
  19. package/dist/{cli/menu/settings/categories.d.ts → app/features/settings/categories.def.d.ts} +4 -0
  20. package/dist/{cli/menu/settings/categories.js → app/features/settings/categories.def.js} +40 -46
  21. package/dist/app/features/settings/index.d.ts +5 -0
  22. package/dist/app/features/settings/index.js +6 -0
  23. package/dist/{cli/menu/settings/config-file.d.ts → app/features/settings/settings-file.d.ts} +1 -1
  24. package/dist/{cli/menu/settings/config-file.js → app/features/settings/settings-file.js} +1 -1
  25. package/dist/app/features/settings/settings-rows.d.ts +35 -0
  26. package/dist/app/features/settings/settings-rows.js +94 -0
  27. package/dist/app/features/settings/settings.def.d.ts +157 -0
  28. package/dist/app/features/settings/settings.def.js +179 -0
  29. package/dist/app/features/settings/settings.run.d.ts +67 -0
  30. package/dist/app/features/settings/settings.run.js +84 -0
  31. package/dist/app/kernel/define.d.ts +143 -0
  32. package/dist/app/kernel/define.js +42 -0
  33. package/dist/app/kernel/errors.d.ts +34 -0
  34. package/dist/app/kernel/errors.js +45 -0
  35. package/dist/app/kernel/fields.d.ts +70 -0
  36. package/dist/app/kernel/fields.js +243 -0
  37. package/dist/app/kernel/index.d.ts +8 -0
  38. package/dist/app/kernel/index.js +10 -0
  39. package/dist/app/kernel/io.d.ts +193 -0
  40. package/dist/app/kernel/io.js +126 -0
  41. package/dist/app/kernel/rpc.d.ts +156 -0
  42. package/dist/app/kernel/rpc.js +47 -0
  43. package/dist/{cli/menu/settings → app/kernel}/schema-node.d.ts +9 -0
  44. package/dist/{cli/menu/settings → app/kernel}/schema-node.js +26 -0
  45. package/dist/app/kernel/text.d.ts +6 -0
  46. package/dist/app/kernel/text.js +57 -0
  47. package/dist/app/kernel/view.d.ts +146 -0
  48. package/dist/app/kernel/view.js +28 -0
  49. package/dist/app/registry.d.ts +10 -0
  50. package/dist/app/registry.js +50 -0
  51. package/dist/cli/args.d.ts +18 -2
  52. package/dist/cli/args.js +101 -24
  53. package/dist/cli/commands/accounts.js +45 -17
  54. package/dist/cli/commands/context.d.ts +2 -0
  55. package/dist/cli/commands/context.js +9 -2
  56. package/dist/cli/commands/data/clean.js +32 -9
  57. package/dist/cli/commands/engine.d.ts +2 -0
  58. package/dist/cli/commands/engine.js +60 -0
  59. package/dist/cli/commands/index.d.ts +2 -1
  60. package/dist/cli/commands/index.js +2 -1
  61. package/dist/cli/commands/launch/add-root.d.ts +3 -2
  62. package/dist/cli/commands/launch/add-root.js +11 -10
  63. package/dist/cli/commands/launch/launch.js +102 -9
  64. package/dist/cli/commands/launch/prepare.js +6 -4
  65. package/dist/cli/commands/launch/running.js +2 -1
  66. package/dist/cli/commands/launch/summary.d.ts +2 -0
  67. package/dist/cli/commands/maintenance/audit.js +1 -1
  68. package/dist/cli/commands/maintenance/clean.d.ts +1 -1
  69. package/dist/cli/commands/maintenance/clean.js +17 -3
  70. package/dist/cli/commands/maintenance/config-share.d.ts +12 -0
  71. package/dist/cli/commands/maintenance/config-share.js +80 -0
  72. package/dist/cli/commands/maintenance/config.d.ts +1 -1
  73. package/dist/cli/commands/maintenance/config.js +38 -10
  74. package/dist/cli/commands/maintenance/doctor.d.ts +1 -1
  75. package/dist/cli/commands/maintenance/doctor.js +2 -4
  76. package/dist/cli/commands/maintenance/logs.js +14 -0
  77. package/dist/cli/commands/maintenance/migrate.d.ts +2 -1
  78. package/dist/cli/commands/maintenance/migrate.js +19 -4
  79. package/dist/cli/commands/maintenance/sync.js +2 -0
  80. package/dist/cli/commands/maintenance/update.d.ts +2 -0
  81. package/dist/cli/commands/maintenance/update.js +27 -4
  82. package/dist/cli/commands/projects/here.js +12 -7
  83. package/dist/cli/commands/projects/projects.js +26 -17
  84. package/dist/cli/commands/registry.js +10 -7
  85. package/dist/cli/commands/repair/checks/agents.d.ts +2 -0
  86. package/dist/cli/commands/repair/checks/agents.js +70 -0
  87. package/dist/cli/commands/repair/checks/common.d.ts +8 -0
  88. package/dist/cli/commands/repair/checks/common.js +22 -0
  89. package/dist/cli/commands/repair/checks/contained.d.ts +2 -0
  90. package/dist/cli/commands/repair/checks/contained.js +139 -0
  91. package/dist/cli/commands/repair/checks/data.d.ts +2 -0
  92. package/dist/cli/commands/repair/checks/data.js +241 -0
  93. package/dist/cli/commands/repair/checks/hcs.d.ts +7 -0
  94. package/dist/cli/commands/repair/checks/hcs.js +28 -0
  95. package/dist/cli/commands/repair/checks/index.d.ts +2 -0
  96. package/dist/cli/commands/repair/checks/index.js +24 -0
  97. package/dist/cli/commands/repair/checks/install.d.ts +5 -0
  98. package/dist/cli/commands/repair/checks/install.js +318 -0
  99. package/dist/cli/commands/repair/checks/machine.d.ts +2 -0
  100. package/dist/cli/commands/repair/checks/machine.js +232 -0
  101. package/dist/cli/commands/repair/checks/network.d.ts +6 -0
  102. package/dist/cli/commands/repair/checks/network.js +60 -0
  103. package/dist/cli/commands/repair/checks/pc.d.ts +4 -0
  104. package/dist/cli/commands/repair/checks/pc.js +86 -0
  105. package/dist/cli/commands/repair/checks/sandbox.d.ts +2 -0
  106. package/dist/cli/commands/repair/checks/sandbox.js +282 -0
  107. package/dist/cli/commands/repair/checks/settings.d.ts +2 -0
  108. package/dist/cli/commands/repair/checks/settings.js +169 -0
  109. package/dist/cli/commands/repair/checks/vpn.d.ts +2 -0
  110. package/dist/cli/commands/repair/checks/vpn.js +78 -0
  111. package/dist/cli/commands/repair/engine.d.ts +32 -0
  112. package/dist/cli/commands/repair/engine.js +127 -0
  113. package/dist/cli/commands/repair/env.d.ts +7 -0
  114. package/dist/cli/commands/repair/env.js +50 -0
  115. package/dist/cli/commands/repair/index.d.ts +1 -9
  116. package/dist/cli/commands/repair/index.js +2 -54
  117. package/dist/cli/commands/repair/log.d.ts +17 -0
  118. package/dist/cli/commands/repair/log.js +82 -0
  119. package/dist/cli/commands/repair/printer.d.ts +32 -0
  120. package/dist/cli/commands/repair/printer.js +132 -0
  121. package/dist/cli/commands/repair/run.d.ts +33 -0
  122. package/dist/cli/commands/repair/run.js +133 -0
  123. package/dist/cli/commands/repair/types.d.ts +97 -9
  124. package/dist/cli/commands/repair/types.js +11 -7
  125. package/dist/cli/commands/resume.js +2 -2
  126. package/dist/cli/commands/sessions/index.d.ts +0 -4
  127. package/dist/cli/commands/sessions/index.js +3 -7
  128. package/dist/cli/commands/setup/index.d.ts +5 -0
  129. package/dist/cli/commands/setup/index.js +25 -1
  130. package/dist/cli/commands/shared-use.d.ts +5 -2
  131. package/dist/cli/commands/shared-use.js +11 -8
  132. package/dist/cli/commands/storage/contained.d.ts +3 -0
  133. package/dist/cli/commands/storage/contained.js +179 -0
  134. package/dist/cli/commands/storage/index.d.ts +2 -0
  135. package/dist/cli/commands/storage/index.js +2 -0
  136. package/dist/cli/commands/storage/offer.d.ts +3 -0
  137. package/dist/cli/commands/storage/offer.js +91 -0
  138. package/dist/cli/commands/storage/storage.d.ts +8 -0
  139. package/dist/cli/commands/storage/storage.js +179 -0
  140. package/dist/cli/commands/user-config.js +2 -2
  141. package/dist/cli/commands/vpn.d.ts +4 -0
  142. package/dist/cli/commands/vpn.js +91 -0
  143. package/dist/cli/commands/web.d.ts +4 -0
  144. package/dist/cli/commands/web.js +97 -0
  145. package/dist/cli/history.js +1 -1
  146. package/dist/cli/index.js +48 -4
  147. package/dist/cli/manifest.d.ts +339 -97
  148. package/dist/cli/manifest.js +222 -67
  149. package/dist/cli/menu/add-agent.d.ts +47 -0
  150. package/dist/cli/menu/add-agent.js +168 -0
  151. package/dist/cli/menu/apps.d.ts +38 -3
  152. package/dist/cli/menu/apps.js +80 -5
  153. package/dist/cli/menu/command-fields.d.ts +18 -0
  154. package/dist/cli/menu/command-fields.js +61 -0
  155. package/dist/cli/menu/command-form.d.ts +22 -0
  156. package/dist/cli/menu/command-form.js +169 -46
  157. package/dist/cli/menu/data-folder.d.ts +18 -0
  158. package/dist/cli/menu/data-folder.js +99 -0
  159. package/dist/cli/menu/io-menu.d.ts +29 -0
  160. package/dist/cli/menu/io-menu.js +126 -0
  161. package/dist/cli/menu/live.d.ts +27 -0
  162. package/dist/cli/menu/live.js +69 -0
  163. package/dist/cli/menu/memory.d.ts +19 -0
  164. package/dist/cli/menu/memory.js +53 -0
  165. package/dist/cli/menu/menu.d.ts +11 -2
  166. package/dist/cli/menu/menu.js +36 -15
  167. package/dist/cli/menu/pages/accounts-page.js +55 -24
  168. package/dist/cli/menu/pages/agents-page.d.ts +68 -0
  169. package/dist/cli/menu/pages/agents-page.js +345 -0
  170. package/dist/cli/menu/pages/apps-page.d.ts +3 -1
  171. package/dist/cli/menu/pages/apps-page.js +20 -4
  172. package/dist/cli/menu/pages/list-page.d.ts +43 -3
  173. package/dist/cli/menu/pages/list-page.js +146 -12
  174. package/dist/cli/menu/pages/maintenance-page.d.ts +9 -5
  175. package/dist/cli/menu/pages/maintenance-page.js +172 -85
  176. package/dist/cli/menu/pages/sandbox-page.d.ts +7 -6
  177. package/dist/cli/menu/pages/sandbox-page.js +117 -120
  178. package/dist/cli/menu/pages/scopes.d.ts +1 -1
  179. package/dist/cli/menu/pages/sessions-page.d.ts +6 -8
  180. package/dist/cli/menu/pages/sessions-page.js +22 -75
  181. package/dist/cli/menu/pages/settings-page.d.ts +10 -14
  182. package/dist/cli/menu/pages/settings-page.js +95 -102
  183. package/dist/cli/menu/render-view.d.ts +28 -0
  184. package/dist/cli/menu/render-view.js +112 -0
  185. package/dist/cli/menu/settings/ask-path.d.ts +14 -0
  186. package/dist/cli/menu/settings/ask-path.js +14 -0
  187. package/dist/cli/menu/settings/collections/collection-editor.d.ts +8 -2
  188. package/dist/cli/menu/settings/collections/collection-editor.js +12 -8
  189. package/dist/cli/menu/settings/collections/map-editor.js +5 -1
  190. package/dist/cli/menu/settings/collections/object-list-editor.js +2 -2
  191. package/dist/cli/menu/settings/collections/object-map-editor.js +2 -2
  192. package/dist/cli/menu/settings/collections/string-list-editor.d.ts +10 -1
  193. package/dist/cli/menu/settings/collections/string-list-editor.js +23 -0
  194. package/dist/cli/menu/settings/draft.d.ts +1 -1
  195. package/dist/cli/menu/settings/format.d.ts +1 -3
  196. package/dist/cli/menu/settings/format.js +6 -36
  197. package/dist/cli/menu/settings/index.d.ts +1 -3
  198. package/dist/cli/menu/settings/index.js +3 -3
  199. package/dist/cli/menu/settings/object-editor.d.ts +6 -2
  200. package/dist/cli/menu/settings/object-editor.js +15 -4
  201. package/dist/cli/menu/settings/share.d.ts +36 -0
  202. package/dist/cli/menu/settings/share.js +131 -0
  203. package/dist/cli/menu/settings/value-editor.d.ts +10 -1
  204. package/dist/cli/menu/settings/value-editor.js +99 -63
  205. package/dist/cli/menu/several.js +7 -5
  206. package/dist/cli/menu/share-settings.d.ts +21 -0
  207. package/dist/cli/menu/share-settings.js +112 -0
  208. package/dist/cli/menu/shell.d.ts +53 -10
  209. package/dist/cli/menu/shell.js +115 -10
  210. package/dist/cli/menu/views.d.ts +7 -0
  211. package/dist/cli/menu/views.js +11 -0
  212. package/dist/cli/menu/vpn-login.d.ts +16 -0
  213. package/dist/cli/menu/vpn-login.js +74 -0
  214. package/dist/cli/operations/handler.d.ts +6 -0
  215. package/dist/cli/operations/handler.js +61 -0
  216. package/dist/cli/operations/index.d.ts +4 -0
  217. package/dist/cli/operations/index.js +5 -0
  218. package/dist/cli/operations/input.d.ts +6 -0
  219. package/dist/cli/operations/input.js +37 -0
  220. package/dist/cli/operations/io-cli.d.ts +7 -0
  221. package/dist/cli/operations/io-cli.js +62 -0
  222. package/dist/cli/operations/spec.d.ts +18 -0
  223. package/dist/cli/operations/spec.js +108 -0
  224. package/dist/cli/output/colors.d.ts +2 -2
  225. package/dist/cli/output/colors.js +2 -11
  226. package/dist/cli/output/index.d.ts +1 -0
  227. package/dist/cli/output/index.js +1 -0
  228. package/dist/cli/output/print.d.ts +5 -1
  229. package/dist/cli/output/print.js +15 -4
  230. package/dist/cli/output/progress.d.ts +15 -0
  231. package/dist/cli/output/progress.js +44 -0
  232. package/dist/cli/output/render-view.d.ts +4 -0
  233. package/dist/cli/output/render-view.js +63 -0
  234. package/dist/cli/services/accounts-service.d.ts +2 -0
  235. package/dist/cli/services/accounts-service.js +2 -2
  236. package/dist/cli/services/agent-commands-service.d.ts +2 -0
  237. package/dist/cli/services/agent-commands-service.js +11 -2
  238. package/dist/cli/services/health-service.d.ts +0 -6
  239. package/dist/cli/services/health-service.js +5 -42
  240. package/dist/cli/services/index.d.ts +3 -1
  241. package/dist/cli/services/index.js +3 -1
  242. package/dist/cli/services/logs-service.js +4 -3
  243. package/dist/cli/services/migrate-service.js +1 -1
  244. package/dist/cli/services/update-service.d.ts +2 -0
  245. package/dist/cli/services/update-service.js +13 -6
  246. package/dist/cli/services/vpn-service.d.ts +28 -0
  247. package/dist/cli/services/vpn-service.js +46 -0
  248. package/dist/cli/services/web-service.d.ts +22 -0
  249. package/dist/cli/services/web-service.js +111 -0
  250. package/dist/cli/tui/app.d.ts +12 -4
  251. package/dist/cli/tui/app.js +38 -9
  252. package/dist/cli/tui/dialogs/path-listing.d.ts +43 -0
  253. package/dist/cli/tui/dialogs/path-listing.js +127 -0
  254. package/dist/cli/tui/dialogs/path-picker.d.ts +67 -0
  255. package/dist/cli/tui/dialogs/path-picker.js +423 -0
  256. package/dist/cli/tui/dialogs/text-screen.d.ts +6 -0
  257. package/dist/cli/tui/dialogs/text-screen.js +10 -3
  258. package/dist/cli/tui/frame.d.ts +7 -10
  259. package/dist/cli/tui/frame.js +19 -10
  260. package/dist/cli/tui/index.d.ts +4 -3
  261. package/dist/cli/tui/index.js +2 -1
  262. package/dist/cli/tui/list/list-screen.d.ts +28 -2
  263. package/dist/cli/tui/list/list-screen.js +130 -66
  264. package/dist/cli/tui/list/list-types.d.ts +10 -4
  265. package/dist/cli/tui/nav.d.ts +29 -0
  266. package/dist/cli/tui/nav.js +67 -0
  267. package/dist/cli/tui/terminal.d.ts +7 -0
  268. package/dist/cli/tui/terminal.js +30 -10
  269. package/dist/cli/validate.d.ts +1 -1
  270. package/dist/cli/validate.js +3 -3
  271. package/dist/cli/version.d.ts +2 -0
  272. package/dist/cli/version.js +11 -0
  273. package/dist/core/config/defaults.js +13 -1
  274. package/dist/core/config/loader.js +12 -2
  275. package/dist/core/local-config/overrides.js +1 -0
  276. package/dist/core/prompt.d.ts +19 -0
  277. package/dist/core/prompt.js +43 -3
  278. package/dist/core/schema/common.d.ts +6 -0
  279. package/dist/core/schema/common.js +8 -0
  280. package/dist/core/schema/config.d.ts +36 -0
  281. package/dist/core/schema/config.js +26 -2
  282. package/dist/core/schema/harness.d.ts +2 -0
  283. package/dist/core/schema/harness.js +13 -2
  284. package/dist/core/schema/index.d.ts +3 -1
  285. package/dist/core/schema/index.js +3 -1
  286. package/dist/core/schema/profile.d.ts +1 -0
  287. package/dist/core/schema/profile.js +3 -0
  288. package/dist/core/schema/redact.d.ts +13 -0
  289. package/dist/core/schema/redact.js +75 -0
  290. package/dist/core/schema/sandbox.d.ts +6 -0
  291. package/dist/core/schema/sandbox.js +21 -3
  292. package/dist/core/schema/vpn.d.ts +18 -0
  293. package/dist/core/schema/vpn.js +22 -0
  294. package/dist/core/schema/web.d.ts +6 -0
  295. package/dist/core/schema/web.js +14 -0
  296. package/dist/core/types.d.ts +44 -0
  297. package/dist/core/util/fs.d.ts +2 -0
  298. package/dist/core/util/fs.js +9 -0
  299. package/dist/core/util/index.d.ts +1 -1
  300. package/dist/core/util/index.js +1 -1
  301. package/dist/guest/agents/agent-files.d.ts +54 -0
  302. package/dist/guest/agents/agent-files.js +67 -0
  303. package/dist/guest/agents/agent-installer.js +2 -9
  304. package/dist/guest/agents/local-state.d.ts +14 -0
  305. package/dist/guest/agents/local-state.js +218 -0
  306. package/dist/guest/agents/sbx-agent.d.ts +2 -0
  307. package/dist/guest/agents/sbx-agent.js +35 -0
  308. package/dist/guest/boot/boot.d.ts +4 -0
  309. package/dist/guest/boot/boot.js +51 -11
  310. package/dist/guest/daemon/daemon.js +8 -1
  311. package/dist/guest/daemon/exec.js +2 -1
  312. package/dist/guest/daemon/idle-shutdown.js +2 -0
  313. package/dist/guest/daemon/sessions.d.ts +5 -0
  314. package/dist/guest/daemon/sessions.js +20 -3
  315. package/dist/guest/entries/agent.d.ts +1 -0
  316. package/dist/guest/entries/agent.js +10 -0
  317. package/dist/guest/entries/daemon.js +5 -0
  318. package/dist/guest/governor/decide.d.ts +61 -0
  319. package/dist/guest/governor/decide.js +182 -0
  320. package/dist/guest/governor/governor.d.ts +42 -0
  321. package/dist/guest/governor/governor.js +214 -0
  322. package/dist/guest/governor/index.d.ts +2 -0
  323. package/dist/guest/governor/index.js +2 -0
  324. package/dist/guest/runtime/csc.d.ts +2 -0
  325. package/dist/guest/runtime/csc.js +2 -0
  326. package/dist/guest/runtime/secrets.d.ts +12 -0
  327. package/dist/guest/runtime/secrets.js +63 -0
  328. package/dist/guest/sessions/viewer.js +3 -1
  329. package/dist/guest/setup/claude-profile.d.ts +2 -1
  330. package/dist/guest/setup/claude-profile.js +12 -1
  331. package/dist/guest/setup/environment.d.ts +6 -0
  332. package/dist/guest/setup/environment.js +56 -6
  333. package/dist/guest/setup/path-plan.d.ts +32 -0
  334. package/dist/guest/setup/path-plan.js +67 -0
  335. package/dist/guest/setup/shell-path.d.ts +1 -0
  336. package/dist/guest/setup/shell-path.js +22 -0
  337. package/dist/guest/toolchains/languages/python.js +1 -1
  338. package/dist/guest/toolchains/native/rust-extras.js +4 -2
  339. package/dist/guest/toolchains/runtimes.js +2 -2
  340. package/dist/guest/vpn/index.d.ts +1 -0
  341. package/dist/guest/vpn/index.js +1 -0
  342. package/dist/guest/vpn/openvpn.d.ts +9 -0
  343. package/dist/guest/vpn/openvpn.js +47 -0
  344. package/dist/guest/vpn/tunnel.d.ts +17 -0
  345. package/dist/guest/vpn/tunnel.js +78 -0
  346. package/dist/guest/vpn/vpn.d.ts +6 -0
  347. package/dist/guest/vpn/vpn.js +174 -0
  348. package/dist/guest/vpn/wireguard.d.ts +32 -0
  349. package/dist/guest/vpn/wireguard.js +132 -0
  350. package/dist/host/agent-commands/commands.d.ts +4 -0
  351. package/dist/host/agent-commands/commands.js +31 -7
  352. package/dist/host/audit/log.d.ts +1 -1
  353. package/dist/host/channel/attach.d.ts +6 -2
  354. package/dist/host/channel/attach.js +6 -3
  355. package/dist/host/channel/channel.d.ts +9 -0
  356. package/dist/host/channel/channel.js +30 -2
  357. package/dist/host/engines/engine.d.ts +12 -0
  358. package/dist/host/engines/engine.js +1 -0
  359. package/dist/host/engines/hcs/check.d.ts +25 -0
  360. package/dist/host/engines/hcs/check.js +95 -0
  361. package/dist/host/engines/hcs/documents.d.ts +44 -0
  362. package/dist/host/engines/hcs/documents.js +155 -0
  363. package/dist/host/engines/hcs/engine.d.ts +39 -0
  364. package/dist/host/engines/hcs/engine.js +171 -0
  365. package/dist/host/engines/hcs/helper.d.ts +43 -0
  366. package/dist/host/engines/hcs/helper.js +173 -0
  367. package/dist/host/engines/hcs/images.d.ts +37 -0
  368. package/dist/host/engines/hcs/images.js +152 -0
  369. package/dist/host/engines/index.d.ts +7 -0
  370. package/dist/host/engines/index.js +5 -0
  371. package/dist/host/engines/registry.d.ts +16 -0
  372. package/dist/host/engines/registry.js +30 -0
  373. package/dist/host/engines/types.d.ts +58 -0
  374. package/dist/host/engines/types.js +1 -0
  375. package/dist/host/engines/windows-sandbox/engine.d.ts +16 -0
  376. package/dist/host/engines/windows-sandbox/engine.js +63 -0
  377. package/dist/host/engines/windows-sandbox/wsb-text.d.ts +2 -0
  378. package/dist/host/engines/windows-sandbox/wsb-text.js +29 -0
  379. package/dist/host/health/acl-read.d.ts +17 -0
  380. package/dist/host/health/acl-read.js +45 -0
  381. package/dist/host/health/config-backup.d.ts +11 -0
  382. package/dist/host/health/config-backup.js +73 -0
  383. package/dist/host/health/index.d.ts +6 -0
  384. package/dist/host/health/index.js +7 -0
  385. package/dist/host/health/install-state.d.ts +33 -0
  386. package/dist/host/health/install-state.js +110 -0
  387. package/dist/host/health/path-copies.d.ts +32 -0
  388. package/dist/host/health/path-copies.js +82 -0
  389. package/dist/host/health/stale.d.ts +45 -0
  390. package/dist/host/health/stale.js +120 -0
  391. package/dist/host/health/system.d.ts +37 -0
  392. package/dist/host/health/system.js +87 -0
  393. package/dist/host/install/copies.d.ts +13 -0
  394. package/dist/host/install/copies.js +63 -0
  395. package/dist/host/install/index.d.ts +1 -0
  396. package/dist/host/install/index.js +1 -0
  397. package/dist/host/launch/generate.d.ts +5 -1
  398. package/dist/host/launch/generate.js +73 -7
  399. package/dist/host/launch/index.d.ts +3 -1
  400. package/dist/host/launch/index.js +3 -1
  401. package/dist/host/launch/launch-plan.d.ts +13 -0
  402. package/dist/host/launch/launch-plan.js +26 -0
  403. package/dist/host/launch/mappings.js +2 -1
  404. package/dist/host/launch/risk-notes.d.ts +10 -0
  405. package/dist/host/launch/risk-notes.js +18 -0
  406. package/dist/host/launch/session-file.d.ts +2 -0
  407. package/dist/host/launch/session-file.js +11 -2
  408. package/dist/host/launch/stage.js +1 -1
  409. package/dist/host/launch/wsb-file.d.ts +28 -4
  410. package/dist/host/launch/wsb-file.js +61 -42
  411. package/dist/host/life/crash-report.d.ts +27 -1
  412. package/dist/host/life/crash-report.js +173 -7
  413. package/dist/host/life/host-memory.d.ts +40 -0
  414. package/dist/host/life/host-memory.js +137 -0
  415. package/dist/host/life/index.d.ts +2 -0
  416. package/dist/host/life/index.js +2 -0
  417. package/dist/host/life/stop-events.d.ts +2 -0
  418. package/dist/host/life/stop-events.js +20 -3
  419. package/dist/host/life/stop-warning.js +1 -1
  420. package/dist/host/life/watchdog.d.ts +54 -0
  421. package/dist/host/life/watchdog.js +108 -0
  422. package/dist/host/migrate/backup.js +3 -0
  423. package/dist/host/migrate/migrations/config-file.d.ts +2 -0
  424. package/dist/host/migrate/migrations/config-file.js +7 -0
  425. package/dist/host/migrate/migrations/follow-machine-storage.js +9 -1
  426. package/dist/host/migrate/migrations/pin-storage-root.d.ts +4 -0
  427. package/dist/host/migrate/migrations/pin-storage-root.js +46 -0
  428. package/dist/host/migrate/migrations/unpin-config-defaults.js +4 -1
  429. package/dist/host/migrate/registry.js +2 -1
  430. package/dist/host/native.d.ts +3 -2
  431. package/dist/host/native.js +22 -3
  432. package/dist/host/profile/accounts.d.ts +25 -1
  433. package/dist/host/profile/accounts.js +96 -13
  434. package/dist/host/profile/agent-accounts.d.ts +5 -1
  435. package/dist/host/profile/agent-accounts.js +35 -5
  436. package/dist/host/profile/claude-login.js +3 -2
  437. package/dist/host/profile/index.d.ts +2 -1
  438. package/dist/host/profile/index.js +1 -0
  439. package/dist/host/profile/plugin-share.d.ts +26 -0
  440. package/dist/host/profile/plugin-share.js +146 -0
  441. package/dist/host/projects/join.d.ts +7 -1
  442. package/dist/host/projects/join.js +21 -4
  443. package/dist/host/projects/registry.d.ts +16 -10
  444. package/dist/host/projects/registry.js +74 -6
  445. package/dist/host/sandbox/contained-deps.d.ts +2 -0
  446. package/dist/host/sandbox/contained-deps.js +17 -0
  447. package/dist/host/sandbox/index.d.ts +2 -0
  448. package/dist/host/sandbox/index.js +2 -0
  449. package/dist/host/sandbox/platform.d.ts +4 -0
  450. package/dist/host/sandbox/platform.js +23 -4
  451. package/dist/host/sandbox/tasklist.d.ts +13 -0
  452. package/dist/host/sandbox/tasklist.js +47 -0
  453. package/dist/host/secrets/index.d.ts +2 -0
  454. package/dist/host/secrets/index.js +2 -0
  455. package/dist/host/secrets/launch-secrets.d.ts +17 -0
  456. package/dist/host/secrets/launch-secrets.js +94 -0
  457. package/dist/host/secrets/secret-store.d.ts +25 -0
  458. package/dist/host/secrets/secret-store.js +89 -0
  459. package/dist/host/sharing/acl.d.ts +16 -2
  460. package/dist/host/sharing/acl.js +35 -10
  461. package/dist/host/sharing/current.js +8 -3
  462. package/dist/host/sharing/doctor.d.ts +2 -0
  463. package/dist/host/sharing/doctor.js +44 -0
  464. package/dist/host/sharing/group-access.d.ts +6 -0
  465. package/dist/host/sharing/group-access.js +24 -0
  466. package/dist/host/sharing/index.d.ts +2 -1
  467. package/dist/host/sharing/index.js +2 -1
  468. package/dist/host/sharing/lifecycle.d.ts +8 -2
  469. package/dist/host/sharing/lifecycle.js +16 -7
  470. package/dist/host/storage/cleanup.d.ts +2 -0
  471. package/dist/host/storage/cleanup.js +2 -1
  472. package/dist/host/storage/contained/check.d.ts +9 -0
  473. package/dist/host/storage/contained/check.js +37 -0
  474. package/dist/host/storage/contained/contained-storage.d.ts +66 -0
  475. package/dist/host/storage/contained/contained-storage.js +168 -0
  476. package/dist/host/storage/contained/disk-port.d.ts +43 -0
  477. package/dist/host/storage/contained/disk-port.js +122 -0
  478. package/dist/host/storage/contained/index.d.ts +9 -0
  479. package/dist/host/storage/contained/index.js +8 -0
  480. package/dist/host/storage/contained/layout.d.ts +28 -0
  481. package/dist/host/storage/contained/layout.js +45 -0
  482. package/dist/host/storage/contained/resolve.d.ts +4 -0
  483. package/dist/host/storage/contained/resolve.js +30 -0
  484. package/dist/host/storage/contained/setting.d.ts +1 -0
  485. package/dist/host/storage/contained/setting.js +5 -0
  486. package/dist/host/storage/contained/state.d.ts +89 -0
  487. package/dist/host/storage/contained/state.js +166 -0
  488. package/dist/host/storage/contained/transfer.d.ts +24 -0
  489. package/dist/host/storage/contained/transfer.js +121 -0
  490. package/dist/host/storage/history.d.ts +21 -0
  491. package/dist/host/storage/history.js +49 -0
  492. package/dist/host/storage/index.d.ts +6 -0
  493. package/dist/host/storage/index.js +6 -0
  494. package/dist/host/storage/move.d.ts +95 -0
  495. package/dist/host/storage/move.js +384 -0
  496. package/dist/host/storage/offer.d.ts +11 -0
  497. package/dist/host/storage/offer.js +36 -0
  498. package/dist/host/storage/providers/contained.d.ts +15 -0
  499. package/dist/host/storage/providers/contained.js +39 -0
  500. package/dist/host/storage/providers/folder.d.ts +12 -0
  501. package/dist/host/storage/providers/folder.js +20 -0
  502. package/dist/host/storage/providers/index.d.ts +4 -0
  503. package/dist/host/storage/providers/index.js +3 -0
  504. package/dist/host/storage/providers/registry.d.ts +9 -0
  505. package/dist/host/storage/providers/registry.js +14 -0
  506. package/dist/host/storage/providers/types.d.ts +33 -0
  507. package/dist/host/storage/providers/types.js +1 -0
  508. package/dist/host/storage/root.d.ts +18 -0
  509. package/dist/host/storage/root.js +77 -0
  510. package/dist/host/tools/conpty.js +3 -2
  511. package/dist/host/tools/windows-terminal.d.ts +2 -0
  512. package/dist/host/tools/windows-terminal.js +31 -12
  513. package/dist/host/update/index.d.ts +1 -1
  514. package/dist/host/update/index.js +1 -1
  515. package/dist/host/update/notice.d.ts +2 -0
  516. package/dist/host/update/notice.js +13 -1
  517. package/dist/host/update/update-state.d.ts +6 -0
  518. package/dist/host/update/update-state.js +2 -0
  519. package/dist/host/update/updater.d.ts +19 -0
  520. package/dist/host/update/updater.js +88 -12
  521. package/dist/host/vpn/index.d.ts +4 -0
  522. package/dist/host/vpn/index.js +4 -0
  523. package/dist/host/vpn/login.d.ts +24 -0
  524. package/dist/host/vpn/login.js +79 -0
  525. package/dist/host/vpn/nordvpn.d.ts +21 -0
  526. package/dist/host/vpn/nordvpn.js +77 -0
  527. package/dist/host/vpn/prepare.d.ts +19 -0
  528. package/dist/host/vpn/prepare.js +138 -0
  529. package/dist/host/vpn/status.d.ts +12 -0
  530. package/dist/host/vpn/status.js +53 -0
  531. package/dist/host/web/auth.d.ts +38 -0
  532. package/dist/host/web/auth.js +96 -0
  533. package/dist/host/web/backend.d.ts +14 -0
  534. package/dist/host/web/backend.js +1 -0
  535. package/dist/host/web/bridge.d.ts +27 -0
  536. package/dist/host/web/bridge.js +144 -0
  537. package/dist/host/web/browser.d.ts +3 -0
  538. package/dist/host/web/browser.js +23 -0
  539. package/dist/host/web/control.d.ts +17 -0
  540. package/dist/host/web/control.js +67 -0
  541. package/dist/host/web/index.d.ts +10 -0
  542. package/dist/host/web/index.js +9 -0
  543. package/dist/host/web/rpc.d.ts +24 -0
  544. package/dist/host/web/rpc.js +149 -0
  545. package/dist/host/web/runner.d.ts +16 -0
  546. package/dist/host/web/runner.js +44 -0
  547. package/dist/host/web/server.d.ts +47 -0
  548. package/dist/host/web/server.js +238 -0
  549. package/dist/host/web/state.d.ts +20 -0
  550. package/dist/host/web/state.js +41 -0
  551. package/dist/host/web/static-files.d.ts +13 -0
  552. package/dist/host/web/static-files.js +57 -0
  553. package/dist/runtime/agent.js +27675 -0
  554. package/dist/runtime/daemon.js +1950 -1122
  555. package/dist/runtime/db.js +302 -111
  556. package/dist/runtime/main.js +1560 -275
  557. package/dist/runtime/netproxy.js +168 -8
  558. package/dist/runtime/view.js +186 -13
  559. package/dist/selftest/accounts.test.js +40 -0
  560. package/dist/selftest/agent-paths.test.d.ts +2 -0
  561. package/dist/selftest/agent-paths.test.js +125 -0
  562. package/dist/selftest/app.test.d.ts +2 -0
  563. package/dist/selftest/app.test.js +324 -0
  564. package/dist/selftest/channel.test.js +18 -0
  565. package/dist/selftest/cli.test.js +35 -4
  566. package/dist/selftest/config.test.js +59 -0
  567. package/dist/selftest/contained.test.d.ts +2 -0
  568. package/dist/selftest/contained.test.js +544 -0
  569. package/dist/selftest/credentials.test.d.ts +2 -0
  570. package/dist/selftest/credentials.test.js +198 -0
  571. package/dist/selftest/engine.test.d.ts +2 -0
  572. package/dist/selftest/engine.test.js +127 -0
  573. package/dist/selftest/generate.test.js +1 -1
  574. package/dist/selftest/hcs.test.d.ts +2 -0
  575. package/dist/selftest/hcs.test.js +482 -0
  576. package/dist/selftest/health.test.d.ts +2 -0
  577. package/dist/selftest/health.test.js +470 -0
  578. package/dist/selftest/heavy-load.test.d.ts +2 -0
  579. package/dist/selftest/heavy-load.test.js +329 -0
  580. package/dist/selftest/host-sim.test.js +2 -0
  581. package/dist/selftest/index.js +31 -0
  582. package/dist/selftest/layout.test.js +14 -0
  583. package/dist/selftest/menu-perf.test.d.ts +2 -0
  584. package/dist/selftest/menu-perf.test.js +248 -0
  585. package/dist/selftest/menu-screens.d.ts +7 -0
  586. package/dist/selftest/menu-screens.js +68 -17
  587. package/dist/selftest/menu.test.js +603 -22
  588. package/dist/selftest/migrate.test.js +1 -1
  589. package/dist/selftest/personalization.test.js +3 -1
  590. package/dist/selftest/projects.test.js +39 -1
  591. package/dist/selftest/shared-use.test.js +64 -2
  592. package/dist/selftest/sharing.test.js +50 -1
  593. package/dist/selftest/storage.test.d.ts +2 -0
  594. package/dist/selftest/storage.test.js +363 -0
  595. package/dist/selftest/support/engine-cases.d.ts +8 -0
  596. package/dist/selftest/support/engine-cases.js +65 -0
  597. package/dist/selftest/support/engine-golden.d.ts +3 -0
  598. package/dist/selftest/support/engine-golden.js +66 -0
  599. package/dist/selftest/support/fixtures.d.ts +20 -0
  600. package/dist/selftest/support/hcs-probes.d.ts +17 -0
  601. package/dist/selftest/support/hcs-probes.js +41 -0
  602. package/dist/selftest/support/releases.js +1 -1
  603. package/dist/selftest/toolchains.test.js +21 -0
  604. package/dist/selftest/update-service.test.js +87 -3
  605. package/dist/selftest/vpn.test.d.ts +2 -0
  606. package/dist/selftest/vpn.test.js +412 -0
  607. package/dist/selftest/web.test.d.ts +2 -0
  608. package/dist/selftest/web.test.js +402 -0
  609. package/dist/shared/apps/catalogue.js +31 -0
  610. package/dist/shared/channel/index.d.ts +1 -0
  611. package/dist/shared/channel/index.js +1 -0
  612. package/dist/shared/channel/run-dir.d.ts +9 -1
  613. package/dist/shared/channel/run-dir.js +18 -1
  614. package/dist/shared/channel/schema.d.ts +53 -0
  615. package/dist/shared/channel/schema.js +38 -0
  616. package/dist/shared/channel/secrets.d.ts +29 -0
  617. package/dist/shared/channel/secrets.js +50 -0
  618. package/dist/shared/memory/index.d.ts +1 -0
  619. package/dist/shared/memory/index.js +1 -0
  620. package/dist/shared/memory/policy.d.ts +33 -0
  621. package/dist/shared/memory/policy.js +55 -0
  622. package/dist/shared/pty/output-filter.d.ts +14 -1
  623. package/dist/shared/pty/output-filter.js +22 -4
  624. package/dist/shared/pty/terminal.d.ts +4 -1
  625. package/dist/shared/pty/terminal.js +4 -2
  626. package/dist/shared/system.d.ts +1 -0
  627. package/dist/shared/system.js +1 -0
  628. package/dist/shared/vpn/download.d.ts +29 -0
  629. package/dist/shared/vpn/download.js +30 -0
  630. package/dist/shared/vpn/kill-switch.d.ts +18 -0
  631. package/dist/shared/vpn/kill-switch.js +81 -0
  632. package/dist/shared/vpn/ovpn.d.ts +23 -0
  633. package/dist/shared/vpn/ovpn.js +244 -0
  634. package/dist/shared/vpn/wireguard.d.ts +51 -0
  635. package/dist/shared/vpn/wireguard.js +227 -0
  636. package/dist/shared/web/index.d.ts +1 -0
  637. package/dist/shared/web/index.js +1 -0
  638. package/dist/shared/web/protocol.d.ts +61 -0
  639. package/dist/shared/web/protocol.js +35 -0
  640. package/dist/sync/sync-cycle.js +9 -5
  641. package/dist/sync/sync-state.d.ts +1 -0
  642. package/dist/sync/sync-state.js +1 -0
  643. package/dist/sync/watcher.d.ts +13 -0
  644. package/dist/sync/watcher.js +102 -3
  645. package/dist/web/index.html +14 -0
  646. package/dist/web/main-NRRS5O6Z.js +157 -0
  647. package/dist/web/main-T5DMCHYV.css +1 -0
  648. package/native/csharp/FolderSecurity.cs +29 -0
  649. package/native/csharp/HcsHost/AssemblyInfo.cs +14 -0
  650. package/native/csharp/HcsHost/Guard.cs +100 -0
  651. package/native/csharp/HcsHost/Hcs.cs +256 -0
  652. package/native/csharp/HcsHost/Json.cs +78 -0
  653. package/native/csharp/HcsHost/Program.cs +185 -0
  654. package/native/csharp/HcsHost/VirtualDisk.cs +95 -0
  655. package/native/csharp/HostTools/AssemblyInfo.cs +14 -0
  656. package/native/csharp/HostTools/MemoryStatus.cs +107 -0
  657. package/native/csharp/HostTools/Program.cs +58 -17
  658. package/native/scripts/check-contained.ps1 +28 -0
  659. package/native/scripts/contained-common.ps1 +241 -0
  660. package/native/scripts/dismount-contained.ps1 +66 -0
  661. package/native/scripts/memory-status.ps1 +34 -0
  662. package/native/scripts/mount-contained.ps1 +139 -0
  663. package/native/scripts/protect-data.ps1 +29 -0
  664. package/native/scripts/read-folder-sddl.ps1 +10 -0
  665. package/native/scripts/run-elevated.ps1 +17 -4
  666. package/native/scripts/set-folder-access.ps1 +49 -7
  667. package/native/scripts/stop-events.ps1 +23 -8
  668. package/node_modules/ws/LICENSE +20 -0
  669. package/node_modules/ws/README.md +548 -0
  670. package/node_modules/ws/browser.js +8 -0
  671. package/node_modules/ws/index.js +22 -0
  672. package/node_modules/ws/lib/buffer-util.js +131 -0
  673. package/node_modules/ws/lib/constants.js +19 -0
  674. package/node_modules/ws/lib/event-target.js +292 -0
  675. package/node_modules/ws/lib/extension.js +203 -0
  676. package/node_modules/ws/lib/limiter.js +55 -0
  677. package/node_modules/ws/lib/permessage-deflate.js +530 -0
  678. package/node_modules/ws/lib/receiver.js +743 -0
  679. package/node_modules/ws/lib/sender.js +607 -0
  680. package/node_modules/ws/lib/stream.js +161 -0
  681. package/node_modules/ws/lib/subprotocol.js +62 -0
  682. package/node_modules/ws/lib/validation.js +152 -0
  683. package/node_modules/ws/lib/websocket-server.js +562 -0
  684. package/node_modules/ws/lib/websocket.js +1421 -0
  685. package/node_modules/ws/package.json +74 -0
  686. package/node_modules/ws/wrapper.mjs +21 -0
  687. package/package.json +22 -5
  688. package/sandbox/csharp/EnvBroadcast.cs +33 -0
  689. package/sandbox/csharp/MemGov.cs +398 -0
  690. package/sandbox/csharp/PathSync.cs +90 -0
  691. package/sandbox/csharp/PtyHost.cs +111 -5
  692. package/sandbox/scripts/install-shell-path.ps1 +73 -0
  693. package/sandbox/scripts/set-machine-environment.ps1 +37 -4
  694. package/schemas/config.schema.json +136 -7
  695. package/schemas/sandbox-config.schema.json +17 -4
  696. package/dist/cli/commands/repair/checks.d.ts +0 -2
  697. package/dist/cli/commands/repair/checks.js +0 -246
  698. package/dist/cli/commands/sessions/control.d.ts +0 -4
  699. package/dist/cli/commands/sessions/control.js +0 -66
  700. package/dist/cli/commands/sessions/list.d.ts +0 -2
  701. package/dist/cli/commands/sessions/list.js +0 -45
  702. package/dist/cli/commands/sessions/status.d.ts +0 -2
  703. package/dist/cli/commands/sessions/status.js +0 -93
  704. package/dist/cli/commands/sessions/window.d.ts +0 -3
  705. package/dist/cli/commands/sessions/window.js +0 -18
  706. package/dist/cli/menu/pages/start-page.d.ts +0 -43
  707. package/dist/cli/menu/pages/start-page.js +0 -192
  708. package/dist/cli/tui/tab-bar.d.ts +0 -9
  709. package/dist/cli/tui/tab-bar.js +0 -33
@@ -1,7 +1,7 @@
1
1
  // Bun, uv and Deno: single-binary tools from GitHub releases (claude-mem needs Bun and uv).
2
2
  import path from 'node:path';
3
3
  import { dryRun, localDir } from '../runtime/paths.js';
4
- import { exists } from '../runtime/fs.js';
4
+ import { exists, mkdirp } from '../runtime/fs.js';
5
5
  import { log } from '../runtime/log.js';
6
6
  import { arch, tool, versionOf } from './tool-env.js';
7
7
  import { installFromGithub } from './install.js';
@@ -52,5 +52,5 @@ export function uvVars() {
52
52
  export async function setupUv(env) {
53
53
  await setupSingleExe(env, 'uv', 'astral-sh/uv', arch === 'arm64' ? /^uv-aarch64-pc-windows-msvc\.zip$/ : /^uv-x86_64-pc-windows-msvc\.zip$/, 'uv.exe', tool('uv'), { size: '20 MB' });
54
54
  Object.assign(env.vars, uvVars());
55
- env.prepend.push(tool('uv-bin'));
55
+ env.prepend.push(mkdirp(tool('uv-bin')));
56
56
  }
@@ -0,0 +1 @@
1
+ export { setupVpn, setVpnStatus } from './vpn.js';
@@ -0,0 +1 @@
1
+ export { setupVpn, setVpnStatus } from './vpn.js';
@@ -0,0 +1,9 @@
1
+ /** Where the MSI puts the program. */
2
+ export declare function openvpnExe(env?: NodeJS.ProcessEnv): string;
3
+ export declare function openvpnDownload(arch?: string): {
4
+ file: string;
5
+ sha256: string;
6
+ url: string;
7
+ };
8
+ /** Installs OpenVPN unless it is there; returns the path of openvpn.exe. Throws with the reason when it cannot. */
9
+ export declare function ensureOpenVpn(): Promise<string>;
@@ -0,0 +1,47 @@
1
+ // OpenVPN Community for the sandbox: one checksummed MSI from the publisher, installed silently (it brings the driver).
2
+ // The sandbox is new at every boot, so the install runs each time; the MSI itself is cached in the persistent tools
3
+ // folder. downloads.requireChecksum is honoured by the downloader (this entry has a checksum, so it always passes).
4
+ import crypto from 'node:crypto';
5
+ import fs from 'node:fs';
6
+ import path from 'node:path';
7
+ import { downloader, spawnAsync } from '../../shared/download/index.js';
8
+ import { SYSTEM } from '../../shared/system.js';
9
+ import { dryRun, isWin, toolsDir } from '../runtime/paths.js';
10
+ import { exists, mkdirp } from '../runtime/fs.js';
11
+ import { log } from '../runtime/log.js';
12
+ import { OPENVPN_MSI } from '../../shared/vpn/download.js';
13
+ /** Where the MSI puts the program. */
14
+ export function openvpnExe(env = process.env) {
15
+ return path.join(env.ProgramFiles ?? 'C:\\Program Files', 'OpenVPN', 'bin', 'openvpn.exe');
16
+ }
17
+ export function openvpnDownload(arch = process.arch) {
18
+ const entry = arch === 'arm64' ? OPENVPN_MSI.arm64 : OPENVPN_MSI.x64;
19
+ return { ...entry, url: OPENVPN_MSI.base + entry.file };
20
+ }
21
+ const hasHash = (file, sha256) => crypto.createHash('sha256').update(fs.readFileSync(file)).digest('hex') === sha256;
22
+ /** Installs OpenVPN unless it is there; returns the path of openvpn.exe. Throws with the reason when it cannot. */
23
+ export async function ensureOpenVpn() {
24
+ const exe = openvpnExe();
25
+ if (!isWin || dryRun)
26
+ return exe;
27
+ if (exists(exe))
28
+ return exe;
29
+ const dl = openvpnDownload();
30
+ const msi = path.join(mkdirp(path.join(toolsDir, 'downloads')), dl.file);
31
+ // The tools folder lasts between sandboxes and the agent can write it: a cached file is trusted only by its hash.
32
+ if (!exists(msi) || !hasHash(msi, dl.sha256)) {
33
+ log('VPN: downloading OpenVPN ' + OPENVPN_MSI.version + ' (about 6 MB)');
34
+ await downloader.file(dl.url, msi, dl.sha256);
35
+ }
36
+ log('VPN: installing OpenVPN');
37
+ const logFile = path.join(toolsDir, 'downloads', 'openvpn-install.log');
38
+ const code = await spawnAsync(SYSTEM.msiexec(), ['/i', msi, '/qn', '/norestart', '/l*v', logFile], {
39
+ stdio: 'ignore',
40
+ });
41
+ // 3010: installed, a restart is wanted (nothing here needs one).
42
+ if (code !== 0 && code !== 3010)
43
+ throw new Error('The OpenVPN installer failed (exit ' + code + '). Its log: ' + logFile);
44
+ if (!exists(exe))
45
+ throw new Error('OpenVPN was installed but ' + exe + ' is missing. The installer log: ' + logFile);
46
+ return exe;
47
+ }
@@ -0,0 +1,17 @@
1
+ export interface TunnelOutcome {
2
+ readonly ok: boolean;
3
+ readonly message: string;
4
+ /** The tunnel's own address (what the kill switch lets through). */
5
+ readonly tunnelIp?: string;
6
+ }
7
+ export interface TunnelOptions {
8
+ readonly exe: string;
9
+ readonly profile: string;
10
+ readonly username: string;
11
+ readonly password: string;
12
+ readonly timeoutMs?: number;
13
+ }
14
+ /** Why the log says OpenVPN stopped, in a short plain sentence (or null when it does not say). */
15
+ export declare function failureReason(text: string): string | null;
16
+ /** Connects. Never leaves the login on disk; kills OpenVPN when the tunnel does not come up in time. */
17
+ export declare function startTunnel(o: TunnelOptions): Promise<TunnelOutcome>;
@@ -0,0 +1,78 @@
1
+ // Starts OpenVPN with the login in a file that exists only while it connects, waits for the tunnel, and reports. The
2
+ // file is deleted as soon as the tunnel is up (or has failed). OpenVPN reads it again when it must log in again, so a
3
+ // tunnel that drops does not come back on its own (the kill switch then keeps the sandbox offline): the sandbox's
4
+ // login is not left on disk for that.
5
+ import { spawn } from 'node:child_process';
6
+ import fs from 'node:fs';
7
+ import os from 'node:os';
8
+ import path from 'node:path';
9
+ import { tunnelAddressFromLog } from '../../shared/vpn/kill-switch.js';
10
+ import { logsDir } from '../runtime/paths.js';
11
+ import { log } from '../runtime/log.js';
12
+ const DONE = 'Initialization Sequence Completed';
13
+ /** Why the log says OpenVPN stopped, in a short plain sentence (or null when it does not say). */
14
+ export function failureReason(text) {
15
+ if (/AUTH_FAILED/i.test(text))
16
+ return 'the VPN refused the login (for NordVPN use the service credentials, not your account password)';
17
+ if (/TLS Error: TLS key negotiation failed|TLS handshake failed/i.test(text))
18
+ return 'it could not reach the VPN server (the network blocks it, or the server is down)';
19
+ if (/All wintun adapters on this system are in use|Cannot open TUN\/TAP|Could not create Wintun|ovpn-dco.*(error|failed)/i.test(text))
20
+ return 'the network driver for the tunnel could not be used';
21
+ if (/Exiting due to fatal error/i.test(text))
22
+ return 'OpenVPN stopped with an error';
23
+ return null;
24
+ }
25
+ const tail = (text, lines = 12) => text.trim().split(/\r?\n/).slice(-lines).join('\n');
26
+ /** Connects. Never leaves the login on disk; kills OpenVPN when the tunnel does not come up in time. */
27
+ export async function startTunnel(o) {
28
+ const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'sbx-vpn-'));
29
+ const auth = path.join(dir, 'login.txt');
30
+ const logFile = path.join(dir, 'openvpn.log');
31
+ const keepLog = () => {
32
+ try {
33
+ fs.mkdirSync(logsDir, { recursive: true });
34
+ fs.copyFileSync(logFile, path.join(logsDir, 'openvpn.log'));
35
+ }
36
+ catch {
37
+ // The log is only for finding out what went wrong.
38
+ }
39
+ };
40
+ fs.writeFileSync(auth, o.username + '\r\n' + o.password + '\r\n', 'utf8');
41
+ try {
42
+ const child = spawn(o.exe, ['--config', o.profile, '--auth-user-pass', auth, '--auth-nocache', '--verb', '3', '--log', logFile], { detached: true, stdio: 'ignore', windowsHide: true });
43
+ let exited = null;
44
+ child.once('exit', (code) => {
45
+ exited = code ?? -1;
46
+ });
47
+ child.once('error', (e) => {
48
+ exited = -1;
49
+ log('VPN: could not start OpenVPN: ' + e.message);
50
+ });
51
+ child.unref();
52
+ const deadline = Date.now() + (o.timeoutMs ?? 90000);
53
+ for (;;) {
54
+ const text = fs.existsSync(logFile) ? fs.readFileSync(logFile, 'utf8') : '';
55
+ if (text.includes(DONE)) {
56
+ keepLog();
57
+ const tunnelIp = tunnelAddressFromLog(text) ?? undefined;
58
+ return { ok: true, message: 'the tunnel is up', ...(tunnelIp ? { tunnelIp } : {}) };
59
+ }
60
+ const reason = failureReason(text);
61
+ if (exited !== null || reason) {
62
+ if (exited === null)
63
+ child.kill();
64
+ keepLog();
65
+ return { ok: false, message: (reason ?? 'OpenVPN stopped') + '. ' + tail(text, 4) };
66
+ }
67
+ if (Date.now() > deadline) {
68
+ child.kill();
69
+ keepLog();
70
+ return { ok: false, message: 'the tunnel did not come up in time. ' + tail(text, 4) };
71
+ }
72
+ await new Promise((r) => setTimeout(r, 500));
73
+ }
74
+ }
75
+ finally {
76
+ fs.rmSync(auth, { force: true });
77
+ }
78
+ }
@@ -0,0 +1,6 @@
1
+ import type { VpnStatus } from '../../shared/channel/schema.js';
2
+ import type { SecretsFile } from '../../shared/channel/secrets.js';
3
+ /** Writes run\vpn.json (what `sandbox vpn status` and the launch show). Never throws. */
4
+ export declare function setVpnStatus(state: VpnStatus['state'], message: string, extra?: Partial<VpnStatus>): void;
5
+ /** The whole step. Returns true when the tunnel is up. */
6
+ export declare function setupVpn(secrets: SecretsFile, ptyHostExe: string | null): Promise<boolean>;
@@ -0,0 +1,174 @@
1
+ // The VPN boot step (after the toolchains, before the agent): install OpenVPN, block everything that does not go
2
+ // through the tunnel (the kill switch, applied BEFORE the tunnel starts), connect, check, delete the login, report. A
3
+ // tunnel that fails never stops the boot: with the kill switch the sandbox stays offline and says so; without it, it
4
+ // warns.
5
+ import dns from 'node:dns';
6
+ import fs from 'node:fs';
7
+ import os from 'node:os';
8
+ import path from 'node:path';
9
+ import { now } from '../../shared/channel/run-dir.js';
10
+ import { writeJsonAtomic } from '../../shared/io/json.js';
11
+ import { assertSafeOvpn } from '../../shared/vpn/ovpn.js';
12
+ import { assertSafeWireguard, renderWireguard, routesEverything, wireguardEndpoints, wireguardTunnelAddress, } from '../../shared/vpn/wireguard.js';
13
+ import { isIPv4 } from '../../shared/network/firewall-rules.js';
14
+ import { killSwitchCommands, tunnelCommands } from '../../shared/vpn/kill-switch.js';
15
+ import { errMsg } from '../../core/util/errors.js';
16
+ import { run as netsh } from '../network/firewall.js';
17
+ import { dryRun, isWin, launchDir, run } from '../runtime/paths.js';
18
+ import { log, warn } from '../runtime/log.js';
19
+ import { session } from '../runtime/session.js';
20
+ import { ensureOpenVpn } from './openvpn.js';
21
+ import { startTunnel } from './tunnel.js';
22
+ import { ensureWireguard, removeWireguardTunnel, startWireguardTunnel, waitForHandshake } from './wireguard.js';
23
+ /** Writes run\vpn.json (what `sandbox vpn status` and the launch show). Never throws. */
24
+ export function setVpnStatus(state, message, extra = {}) {
25
+ try {
26
+ writeJsonAtomic(run.vpnFile, {
27
+ state,
28
+ message: message.slice(0, 1900),
29
+ killSwitch: session.vpn?.killSwitch ?? false,
30
+ updatedAt: now(),
31
+ ...(session.vpn ? { server: session.vpn.server.slice(0, 120) } : {}),
32
+ ...extra,
33
+ });
34
+ }
35
+ catch (e) {
36
+ warn('Could not write the VPN status: ' + errMsg(e));
37
+ }
38
+ }
39
+ /** IPv4 addresses of the servers the profile names: names are looked up now, before the kill switch closes DNS. */
40
+ async function serverAddresses(remotes) {
41
+ const out = [];
42
+ for (const r of remotes) {
43
+ const ips = isIPv4(r.host)
44
+ ? [r.host]
45
+ : await dns.promises.lookup(r.host, { all: true, family: 4 }).then((all) => all.map((a) => a.address), () => []);
46
+ for (const ip of ips)
47
+ out.push({ ip, port: r.port, proto: r.proto });
48
+ }
49
+ return out;
50
+ }
51
+ /** The WireGuard peers' endpoints as IPv4 servers (udp), and the config with those addresses in place of host names. */
52
+ async function wireguardServers(config) {
53
+ const endpointIps = {};
54
+ const servers = [];
55
+ const found = wireguardEndpoints(config);
56
+ for (let i = 0; i < found.length; i++) {
57
+ const [ip] = await serverAddresses([{ host: found[i].host, port: found[i].port, proto: 'udp' }]).then((all) => all.map((s) => s.ip));
58
+ if (!ip)
59
+ throw new Error('the VPN server address could not be found');
60
+ // WireGuard looks the name up itself at start, after the kill switch has closed DNS: give it the address.
61
+ endpointIps[i] = ip;
62
+ servers.push({ ip, port: found[i].port, proto: 'udp' });
63
+ }
64
+ return { servers, text: renderWireguard(config, endpointIps) };
65
+ }
66
+ /** What the sandbox looks like from outside, through the tunnel (null when it cannot be told quickly). */
67
+ async function publicAddress() {
68
+ try {
69
+ const text = (await (await fetch('https://api.ipify.org', { signal: AbortSignal.timeout(10000) })).text()).trim();
70
+ return /^[0-9a-fA-F.:]{3,45}$/.test(text) ? text : null;
71
+ }
72
+ catch {
73
+ return null;
74
+ }
75
+ }
76
+ const hasAdapter = (ip) => Object.values(os.networkInterfaces()).some((list) => (list ?? []).some((i) => i.address === ip));
77
+ /** The whole step. Returns true when the tunnel is up. */
78
+ export async function setupVpn(secrets, ptyHostExe) {
79
+ const vpn = session.vpn;
80
+ if (!vpn)
81
+ return true;
82
+ const killSwitch = vpn.killSwitch;
83
+ let blocked = false;
84
+ const block = (servers) => {
85
+ if (isWin && !dryRun)
86
+ netsh(killSwitchCommands(servers, ptyHostExe));
87
+ blocked = true;
88
+ log('VPN: kill switch on: nothing leaves the sandbox except through the tunnel.');
89
+ };
90
+ setVpnStatus('starting', 'Starting the VPN');
91
+ try {
92
+ if (!session.networking)
93
+ throw new Error('networking is off for this sandbox');
94
+ let result;
95
+ let wireguardExe = null;
96
+ if (vpn.provider === 'wireguard-file') {
97
+ // The config came from the host (through the one-shot file), but it is data like any other: checked again here.
98
+ if (!secrets.wireguardConfig)
99
+ throw new Error('the WireGuard config did not arrive (start the sandbox again)');
100
+ const config = assertSafeWireguard(secrets.wireguardConfig, vpn.server);
101
+ const exe = await ensureWireguard();
102
+ const { servers, text } = await wireguardServers(config);
103
+ if (killSwitch && !routesEverything(config))
104
+ warn('VPN: AllowedIPs does not include 0.0.0.0/0: with the kill switch on, only the tunnel traffic can leave the sandbox.');
105
+ if (killSwitch)
106
+ block(servers);
107
+ if (dryRun || !isWin) {
108
+ log('(dry run) would start the WireGuard tunnel ' + vpn.server);
109
+ setVpnStatus('off', 'dry run');
110
+ return true;
111
+ }
112
+ log('VPN: connecting with ' + vpn.server);
113
+ wireguardExe = exe;
114
+ result = await startWireguardTunnel({ exe, config: text, tunnelIp: wireguardTunnelAddress(config) });
115
+ if (result.ok && result.tunnelIp && killSwitch)
116
+ netsh(tunnelCommands(result.tunnelIp));
117
+ if (result.ok)
118
+ result = await waitForHandshake(exe, publicAddress);
119
+ }
120
+ else {
121
+ const credentials = secrets.vpn;
122
+ if (!credentials)
123
+ throw new Error('the VPN login did not arrive (start the sandbox again)');
124
+ // The profile came from the host, but it is data like any other: checked again here before OpenVPN reads it.
125
+ const profile = path.join(launchDir, 'vpn', 'server.ovpn');
126
+ const remotes = assertSafeOvpn(fs.readFileSync(profile, 'utf8'), vpn.server);
127
+ const exe = await ensureOpenVpn();
128
+ const servers = await serverAddresses(remotes);
129
+ if (servers.length === 0)
130
+ throw new Error('the VPN server addresses could not be found');
131
+ if (killSwitch)
132
+ block(servers);
133
+ if (dryRun || !isWin) {
134
+ log('(dry run) would start the VPN tunnel to ' + vpn.server);
135
+ setVpnStatus('off', 'dry run');
136
+ return true;
137
+ }
138
+ log('VPN: connecting to ' + vpn.server);
139
+ result = await startTunnel({ exe, profile, username: credentials.username, password: credentials.password });
140
+ if (result.ok && result.tunnelIp && hasAdapter(result.tunnelIp) && killSwitch)
141
+ netsh(tunnelCommands(result.tunnelIp));
142
+ }
143
+ if (!result.ok) {
144
+ if (wireguardExe)
145
+ await removeWireguardTunnel(wireguardExe);
146
+ throw new Error(result.message);
147
+ }
148
+ if (!result.tunnelIp || !hasAdapter(result.tunnelIp))
149
+ throw new Error('the tunnel reported it was up, but no network adapter with its address appeared');
150
+ const publicIp = await publicAddress();
151
+ log('VPN: up' + (publicIp ? ' (the sandbox appears as ' + publicIp + ')' : '') + '.');
152
+ setVpnStatus('up', 'The tunnel is up', publicIp ? { publicIp } : {});
153
+ return true;
154
+ }
155
+ catch (e) {
156
+ const reason = errMsg(e);
157
+ // Without the kill switch the sandbox keeps its normal connection: the rest of the boot goes on, with a warning.
158
+ try {
159
+ if (killSwitch && !blocked)
160
+ block([]);
161
+ }
162
+ catch (blockError) {
163
+ warn('VPN: could not close the network after the failure: ' + errMsg(blockError));
164
+ }
165
+ const text = 'VPN failed: ' +
166
+ reason +
167
+ (killSwitch
168
+ ? ' The kill switch is on, so this sandbox has NO internet access.'
169
+ : ' The kill switch is off, so this sandbox is using your normal connection.');
170
+ warn(text);
171
+ setVpnStatus('failed', reason);
172
+ return false;
173
+ }
174
+ }
@@ -0,0 +1,32 @@
1
+ import type { TunnelOutcome } from './tunnel.js';
2
+ /** The tunnel's name: the config file is sandbox.conf and the Windows service WireGuardTunnel$sandbox. */
3
+ export declare const WIREGUARD_TUNNEL = "sandbox";
4
+ export declare function wireguardDir(env?: NodeJS.ProcessEnv): string;
5
+ export declare function wireguardExe(env?: NodeJS.ProcessEnv): string;
6
+ export declare function wireguardDownload(arch?: string): {
7
+ file: string;
8
+ sha256: string;
9
+ url: string;
10
+ };
11
+ /** Installs WireGuard unless it is there; returns the path of wireguard.exe. Throws with the reason when it cannot. */
12
+ export declare function ensureWireguard(): Promise<string>;
13
+ /** Takes the tunnel away again (a failed tunnel must not leave a route into nothing). Never throws. */
14
+ export declare function removeWireguardTunnel(exe: string): Promise<void>;
15
+ export interface WireguardOptions {
16
+ readonly exe: string;
17
+ /** The checked config text (private key inside). */
18
+ readonly config: string;
19
+ /** The tunnel's own IPv4 address from the config's Address. */
20
+ readonly tunnelIp: string;
21
+ readonly timeoutMs?: number;
22
+ }
23
+ /**
24
+ * Installs the tunnel service from a config file that is deleted when the service has it, and waits until the service
25
+ * runs and its adapter has the tunnel address. Removes the service again when that fails.
26
+ */
27
+ export declare function startWireguardTunnel(o: WireguardOptions): Promise<TunnelOutcome>;
28
+ /**
29
+ * Waits for the server to answer: the first handshake. `poke` sends some traffic through the tunnel (a handshake only
30
+ * starts when there is something to send, unless PersistentKeepalive is set). Without wg.exe the check is skipped.
31
+ */
32
+ export declare function waitForHandshake(exe: string, poke: () => Promise<unknown>, timeoutMs?: number): Promise<TunnelOutcome>;
@@ -0,0 +1,132 @@
1
+ // WireGuard for the sandbox: one checksummed MSI from the publisher (installed silently, it brings wireguard.exe and
2
+ // wg.exe), the checked config in a file that exists only while the tunnel service starts, and a wait for the
3
+ // tunnel. The config holds the private key: it is written from the one-shot secrets file and deleted as soon as the
4
+ // service has it (or has failed). The kill switch is applied by the caller BEFORE this runs.
5
+ import { execFile } from 'node:child_process';
6
+ import crypto from 'node:crypto';
7
+ import fs from 'node:fs';
8
+ import os from 'node:os';
9
+ import path from 'node:path';
10
+ import { downloader, spawnAsync } from '../../shared/download/index.js';
11
+ import { SYSTEM } from '../../shared/system.js';
12
+ import { WIREGUARD_MSI } from '../../shared/vpn/download.js';
13
+ import { handshakeDone, serviceRunning } from '../../shared/vpn/wireguard.js';
14
+ import { dryRun, isWin, toolsDir } from '../runtime/paths.js';
15
+ import { exists, mkdirp } from '../runtime/fs.js';
16
+ import { log } from '../runtime/log.js';
17
+ /** The tunnel's name: the config file is sandbox.conf and the Windows service WireGuardTunnel$sandbox. */
18
+ export const WIREGUARD_TUNNEL = 'sandbox';
19
+ export function wireguardDir(env = process.env) {
20
+ return path.join(env.ProgramFiles ?? 'C:\\Program Files', 'WireGuard');
21
+ }
22
+ export function wireguardExe(env = process.env) {
23
+ return path.join(wireguardDir(env), 'wireguard.exe');
24
+ }
25
+ export function wireguardDownload(arch = process.arch) {
26
+ const entry = arch === 'arm64' ? WIREGUARD_MSI.arm64 : WIREGUARD_MSI.x64;
27
+ return { ...entry, url: WIREGUARD_MSI.base + entry.file };
28
+ }
29
+ const hasHash = (file, sha256) => crypto.createHash('sha256').update(fs.readFileSync(file)).digest('hex') === sha256;
30
+ /** Installs WireGuard unless it is there; returns the path of wireguard.exe. Throws with the reason when it cannot. */
31
+ export async function ensureWireguard() {
32
+ const exe = wireguardExe();
33
+ if (!isWin || dryRun)
34
+ return exe;
35
+ if (exists(exe))
36
+ return exe;
37
+ const dl = wireguardDownload();
38
+ const msi = path.join(mkdirp(path.join(toolsDir, 'downloads')), dl.file);
39
+ // The tools folder lasts between sandboxes and the agent can write it: a cached file is trusted only by its hash.
40
+ if (!exists(msi) || !hasHash(msi, dl.sha256)) {
41
+ log('VPN: downloading WireGuard ' + WIREGUARD_MSI.version + ' (about 3 MB)');
42
+ await downloader.file(dl.url, msi, dl.sha256);
43
+ }
44
+ log('VPN: installing WireGuard');
45
+ const logFile = path.join(toolsDir, 'downloads', 'wireguard-install.log');
46
+ // DO_NOT_LAUNCH: the installer would otherwise start the manager window.
47
+ const code = await spawnAsync(SYSTEM.msiexec(), ['/i', msi, '/qn', '/norestart', 'DO_NOT_LAUNCH=1', '/l*v', logFile], {
48
+ stdio: 'ignore',
49
+ });
50
+ if (code !== 0 && code !== 3010)
51
+ throw new Error('The WireGuard installer failed (exit ' + code + '). Its log: ' + logFile);
52
+ if (!exists(exe))
53
+ throw new Error('WireGuard was installed but ' + exe + ' is missing. The installer log: ' + logFile);
54
+ return exe;
55
+ }
56
+ const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
57
+ function output(file, args) {
58
+ return new Promise((resolve) => {
59
+ execFile(file, args, { windowsHide: true, timeout: 15000, maxBuffer: 1024 * 1024 }, (error, stdout, stderr) => {
60
+ const code = error ? (typeof error.code === 'number' ? error.code : -1) : 0;
61
+ resolve({ code, text: String(stdout) + String(stderr) });
62
+ });
63
+ });
64
+ }
65
+ const serviceName = () => 'WireGuardTunnel$' + WIREGUARD_TUNNEL;
66
+ const hasAdapter = (ip) => Object.values(os.networkInterfaces()).some((list) => (list ?? []).some((i) => i.address === ip));
67
+ /** Takes the tunnel away again (a failed tunnel must not leave a route into nothing). Never throws. */
68
+ export async function removeWireguardTunnel(exe) {
69
+ try {
70
+ await output(exe, ['/uninstalltunnelservice', WIREGUARD_TUNNEL]);
71
+ }
72
+ catch {
73
+ // Nothing installed, nothing to remove.
74
+ }
75
+ }
76
+ /**
77
+ * Installs the tunnel service from a config file that is deleted when the service has it, and waits until the service
78
+ * runs and its adapter has the tunnel address. Removes the service again when that fails.
79
+ */
80
+ export async function startWireguardTunnel(o) {
81
+ const root = path.join(process.env.SystemRoot ?? 'C:\\Windows', 'Temp');
82
+ const dir = fs.mkdtempSync(path.join(fs.existsSync(root) ? root : os.tmpdir(), 'sbx-wg-'));
83
+ const file = path.join(dir, WIREGUARD_TUNNEL + '.conf');
84
+ fs.writeFileSync(file, o.config, 'utf8');
85
+ const fail = async (message) => {
86
+ await removeWireguardTunnel(o.exe);
87
+ return { ok: false, message };
88
+ };
89
+ try {
90
+ const install = await output(o.exe, ['/installtunnelservice', file]);
91
+ if (install.code !== 0)
92
+ return await fail('WireGuard could not install the tunnel (exit ' + install.code + ')');
93
+ const deadline = Date.now() + (o.timeoutMs ?? 60000);
94
+ for (;;) {
95
+ const state = await output(SYSTEM.sc(), ['query', serviceName()]);
96
+ if (serviceRunning(state.text) && hasAdapter(o.tunnelIp)) {
97
+ return { ok: true, message: 'the tunnel service is running', tunnelIp: o.tunnelIp };
98
+ }
99
+ if (/STOPPED/i.test(state.text) || /1060/.test(state.text))
100
+ return await fail('the WireGuard tunnel service stopped (check the config: keys, address, endpoint)');
101
+ if (Date.now() > deadline)
102
+ return await fail('the WireGuard tunnel did not start in time (the network driver may not work here)');
103
+ await sleep(500);
104
+ }
105
+ }
106
+ finally {
107
+ // The service has read the file by now (or never will): the private key is not left on disk.
108
+ fs.rmSync(dir, { recursive: true, force: true });
109
+ }
110
+ }
111
+ /**
112
+ * Waits for the server to answer: the first handshake. `poke` sends some traffic through the tunnel (a handshake only
113
+ * starts when there is something to send, unless PersistentKeepalive is set). Without wg.exe the check is skipped.
114
+ */
115
+ export async function waitForHandshake(exe, poke, timeoutMs = 30000) {
116
+ const wg = path.join(path.dirname(exe), 'wg.exe');
117
+ if (!exists(wg))
118
+ return { ok: true, message: 'the tunnel service is running (no wg.exe to check the handshake)' };
119
+ const deadline = Date.now() + timeoutMs;
120
+ for (;;) {
121
+ await poke().catch(() => undefined);
122
+ const shown = await output(wg, ['show', WIREGUARD_TUNNEL, 'latest-handshakes']);
123
+ if (shown.code === 0 && handshakeDone(shown.text))
124
+ return { ok: true, message: 'the server answered' };
125
+ if (Date.now() > deadline)
126
+ return {
127
+ ok: false,
128
+ message: 'the VPN server did not answer (check the endpoint, the keys and that its UDP port is reachable)',
129
+ };
130
+ await sleep(1000);
131
+ }
132
+ }
@@ -9,5 +9,9 @@ export interface AgentCommand {
9
9
  export declare function cmdSafe(p: string): boolean;
10
10
  /** The agent's own executable on this PC, skipping this tool's forwarding files. */
11
11
  export declare function realAgent(command: string, skipDir: string, pathValue?: string): string | null;
12
+ /** realAgent without blocking the program: every candidate is looked up at once, the first in PATH order wins. */
13
+ export declare function realAgentAsync(command: string, skipDir: string, pathValue?: string): Promise<string | null>;
12
14
  /** The agents that get a forwarding command: installed on this PC, and listed (or "auto" = all of them). */
13
15
  export declare function agentCommands(config: Config, storageRoot: string, pathValue?: string): AgentCommand[];
16
+ /** agentCommands without blocking the program. */
17
+ export declare function agentCommandsAsync(config: Config, storageRoot: string, pathValue?: string): Promise<AgentCommand[]>;
@@ -3,7 +3,7 @@
3
3
  // <storage>\agent-commands go first on YOUR PATH (so they win over npm's and the installers' copies); turning it off
4
4
  // removes the files and that one PATH entry. SANDBOX_AGENT_DIRECT=1 runs the real agent on this PC instead.
5
5
  import path from 'node:path';
6
- import { fileExists } from '../../core/util/index.js';
6
+ import { fileExists, fileExistsAsync } from '../../core/util/index.js';
7
7
  export function commandsDir(storageRoot) {
8
8
  return path.join(storageRoot, 'agent-commands');
9
9
  }
@@ -12,11 +12,14 @@ const EXTENSIONS = ['.exe', '.cmd', '.bat'];
12
12
  export function cmdSafe(p) {
13
13
  return !/[%"^\r\n]/.test(p);
14
14
  }
15
+ /** The folders of PATH to look in, without this tool's forwarding folder. */
16
+ function searchDirs(skipDir, pathValue) {
17
+ const skip = path.resolve(skipDir).toLowerCase();
18
+ return pathValue.split(path.delimiter).filter((d) => d && path.resolve(d).toLowerCase() !== skip);
19
+ }
15
20
  /** The agent's own executable on this PC, skipping this tool's forwarding files. */
16
21
  export function realAgent(command, skipDir, pathValue = process.env.PATH ?? process.env.Path ?? '') {
17
- const skip = path.resolve(skipDir).toLowerCase();
18
- const dirs = pathValue.split(path.delimiter).filter((d) => d && path.resolve(d).toLowerCase() !== skip);
19
- for (const dir of dirs)
22
+ for (const dir of searchDirs(skipDir, pathValue))
20
23
  for (const ext of EXTENSIONS) {
21
24
  const candidate = path.join(dir, command + ext);
22
25
  if (fileExists(candidate))
@@ -24,14 +27,35 @@ export function realAgent(command, skipDir, pathValue = process.env.PATH ?? proc
24
27
  }
25
28
  return null;
26
29
  }
27
- /** The agents that get a forwarding command: installed on this PC, and listed (or "auto" = all of them). */
28
- export function agentCommands(config, storageRoot, pathValue) {
30
+ /** realAgent without blocking the program: every candidate is looked up at once, the first in PATH order wins. */
31
+ export async function realAgentAsync(command, skipDir, pathValue = process.env.PATH ?? process.env.Path ?? '') {
32
+ const candidates = searchDirs(skipDir, pathValue).flatMap((dir) => EXTENSIONS.map((ext) => path.join(dir, command + ext)));
33
+ const found = await Promise.all(candidates.map(fileExistsAsync));
34
+ const at = found.indexOf(true);
35
+ return at < 0 ? null : candidates[at];
36
+ }
37
+ /** The agents that may get a forwarding command (listed, or "auto" = all) and the command each is typed as. */
38
+ function wantedCommands(config) {
29
39
  const wanted = config.agentCommands.agents;
30
40
  return Object.entries(config.harnesses).flatMap(([harness, h]) => {
31
41
  if (wanted !== 'auto' && !wanted.includes(harness))
32
42
  return [];
33
43
  const command = h.npmBin ?? (h.hostExecutable ? path.parse(h.hostExecutable).name : harness);
34
- const real = /^[A-Za-z0-9._-]+$/.test(command) ? realAgent(command, commandsDir(storageRoot), pathValue) : null;
44
+ return /^[A-Za-z0-9._-]+$/.test(command) ? [{ harness, command }] : [];
45
+ });
46
+ }
47
+ /** The agents that get a forwarding command: installed on this PC, and listed (or "auto" = all of them). */
48
+ export function agentCommands(config, storageRoot, pathValue) {
49
+ return wantedCommands(config).flatMap(({ harness, command }) => {
50
+ const real = realAgent(command, commandsDir(storageRoot), pathValue);
35
51
  return real && cmdSafe(real) ? [{ harness, command, real }] : [];
36
52
  });
37
53
  }
54
+ /** agentCommands without blocking the program. */
55
+ export async function agentCommandsAsync(config, storageRoot, pathValue) {
56
+ const found = await Promise.all(wantedCommands(config).map(async ({ harness, command }) => {
57
+ const real = await realAgentAsync(command, commandsDir(storageRoot), pathValue);
58
+ return real && cmdSafe(real) ? [{ harness, command, real }] : [];
59
+ }));
60
+ return found.flat();
61
+ }
@@ -5,9 +5,9 @@ export declare const AuditEventSchema: z.ZodObject<{
5
5
  k: z.ZodEnum<{
6
6
  file: "file";
7
7
  session: "session";
8
+ note: "note";
8
9
  proc: "proc";
9
10
  guard: "guard";
10
- note: "note";
11
11
  }>;
12
12
  p: z.ZodOptional<z.ZodString>;
13
13
  c: z.ZodOptional<z.ZodString>;
@@ -1,11 +1,13 @@
1
1
  import os from 'node:os';
2
2
  import type { SessionStatus } from '../../core/types.js';
3
- import { type Viewers } from '../../shared/pty/index.js';
3
+ import { type Endpoint, type Viewers } from '../../shared/pty/index.js';
4
4
  /**
5
5
  * True only for IPv4 addresses inside the subnet of one of this PC's Hyper-V adapters ("vEthernet ..."), which is
6
6
  * where Windows Sandbox lives. Stops a compromised sandbox from pointing the host (and your keystrokes) anywhere else.
7
7
  */
8
8
  export declare function isSandboxAddress(ip: string, interfaces?: NodeJS.Dict<os.NetworkInterfaceInfo[]>): boolean;
9
+ /** Where this PC may connect for a session: only addresses on its own Hyper-V network (null if there are none). */
10
+ export declare const hostEndpoint: (session: SessionStatus) => Endpoint | null;
9
11
  /** Who is watching a session right now (closed terminals do not count); null when it cannot be asked. */
10
12
  export declare function sessionViewers(session: SessionStatus): Promise<Viewers | null>;
11
13
  /**
@@ -14,4 +16,6 @@ export declare function sessionViewers(session: SessionStatus): Promise<Viewers
14
16
  */
15
17
  export declare function findUnwatchedSession(dataPath: string, harness: string, cwd: string): Promise<SessionStatus | null>;
16
18
  /** Bridges this terminal to a session. Returns the agent's exit code, or 0 when the user detaches. */
17
- export declare function attachTerminal(session: SessionStatus): Promise<number>;
19
+ export declare function attachTerminal(session: SessionStatus, o?: {
20
+ clipboardWrites?: boolean;
21
+ }): Promise<number>;