windows-development-sandbox 1.5.0 → 1.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (709) hide show
  1. package/README.md +1 -0
  2. package/config.example.json +27 -1
  3. package/dist/app/context.d.ts +8 -0
  4. package/dist/app/context.js +12 -0
  5. package/dist/app/features/defs.d.ts +322 -0
  6. package/dist/app/features/defs.js +28 -0
  7. package/dist/app/features/sandbox/index.d.ts +2 -0
  8. package/dist/app/features/sandbox/index.js +3 -0
  9. package/dist/app/features/sandbox/sandbox.def.d.ts +193 -0
  10. package/dist/app/features/sandbox/sandbox.def.js +245 -0
  11. package/dist/app/features/sandbox/sandbox.run.d.ts +72 -0
  12. package/dist/app/features/sandbox/sandbox.run.js +98 -0
  13. package/dist/app/features/sessions/index.d.ts +2 -0
  14. package/dist/app/features/sessions/index.js +3 -0
  15. package/dist/app/features/sessions/sessions.def.d.ts +141 -0
  16. package/dist/app/features/sessions/sessions.def.js +176 -0
  17. package/dist/app/features/sessions/sessions.run.d.ts +39 -0
  18. package/dist/app/features/sessions/sessions.run.js +58 -0
  19. package/dist/{cli/menu/settings/categories.d.ts → app/features/settings/categories.def.d.ts} +4 -0
  20. package/dist/{cli/menu/settings/categories.js → app/features/settings/categories.def.js} +40 -46
  21. package/dist/app/features/settings/index.d.ts +5 -0
  22. package/dist/app/features/settings/index.js +6 -0
  23. package/dist/{cli/menu/settings/config-file.d.ts → app/features/settings/settings-file.d.ts} +1 -1
  24. package/dist/{cli/menu/settings/config-file.js → app/features/settings/settings-file.js} +1 -1
  25. package/dist/app/features/settings/settings-rows.d.ts +35 -0
  26. package/dist/app/features/settings/settings-rows.js +94 -0
  27. package/dist/app/features/settings/settings.def.d.ts +157 -0
  28. package/dist/app/features/settings/settings.def.js +179 -0
  29. package/dist/app/features/settings/settings.run.d.ts +67 -0
  30. package/dist/app/features/settings/settings.run.js +84 -0
  31. package/dist/app/kernel/define.d.ts +143 -0
  32. package/dist/app/kernel/define.js +42 -0
  33. package/dist/app/kernel/errors.d.ts +34 -0
  34. package/dist/app/kernel/errors.js +45 -0
  35. package/dist/app/kernel/fields.d.ts +70 -0
  36. package/dist/app/kernel/fields.js +243 -0
  37. package/dist/app/kernel/index.d.ts +8 -0
  38. package/dist/app/kernel/index.js +10 -0
  39. package/dist/app/kernel/io.d.ts +193 -0
  40. package/dist/app/kernel/io.js +126 -0
  41. package/dist/app/kernel/rpc.d.ts +156 -0
  42. package/dist/app/kernel/rpc.js +47 -0
  43. package/dist/{cli/menu/settings → app/kernel}/schema-node.d.ts +9 -0
  44. package/dist/{cli/menu/settings → app/kernel}/schema-node.js +26 -0
  45. package/dist/app/kernel/text.d.ts +6 -0
  46. package/dist/app/kernel/text.js +57 -0
  47. package/dist/app/kernel/view.d.ts +146 -0
  48. package/dist/app/kernel/view.js +28 -0
  49. package/dist/app/registry.d.ts +10 -0
  50. package/dist/app/registry.js +50 -0
  51. package/dist/cli/args.d.ts +18 -2
  52. package/dist/cli/args.js +101 -24
  53. package/dist/cli/commands/accounts.js +45 -17
  54. package/dist/cli/commands/context.d.ts +2 -0
  55. package/dist/cli/commands/context.js +9 -2
  56. package/dist/cli/commands/data/clean.js +32 -9
  57. package/dist/cli/commands/engine.d.ts +2 -0
  58. package/dist/cli/commands/engine.js +60 -0
  59. package/dist/cli/commands/index.d.ts +2 -1
  60. package/dist/cli/commands/index.js +2 -1
  61. package/dist/cli/commands/launch/add-root.d.ts +3 -2
  62. package/dist/cli/commands/launch/add-root.js +11 -10
  63. package/dist/cli/commands/launch/launch.js +102 -9
  64. package/dist/cli/commands/launch/prepare.js +6 -4
  65. package/dist/cli/commands/launch/running.js +2 -1
  66. package/dist/cli/commands/launch/summary.d.ts +2 -0
  67. package/dist/cli/commands/maintenance/audit.js +1 -1
  68. package/dist/cli/commands/maintenance/clean.d.ts +1 -1
  69. package/dist/cli/commands/maintenance/clean.js +17 -3
  70. package/dist/cli/commands/maintenance/config-share.d.ts +12 -0
  71. package/dist/cli/commands/maintenance/config-share.js +80 -0
  72. package/dist/cli/commands/maintenance/config.d.ts +1 -1
  73. package/dist/cli/commands/maintenance/config.js +38 -10
  74. package/dist/cli/commands/maintenance/doctor.d.ts +1 -1
  75. package/dist/cli/commands/maintenance/doctor.js +2 -4
  76. package/dist/cli/commands/maintenance/logs.js +14 -0
  77. package/dist/cli/commands/maintenance/migrate.d.ts +2 -1
  78. package/dist/cli/commands/maintenance/migrate.js +19 -4
  79. package/dist/cli/commands/maintenance/sync.js +2 -0
  80. package/dist/cli/commands/maintenance/update.d.ts +2 -0
  81. package/dist/cli/commands/maintenance/update.js +27 -4
  82. package/dist/cli/commands/projects/here.js +12 -7
  83. package/dist/cli/commands/projects/projects.js +26 -17
  84. package/dist/cli/commands/registry.js +10 -7
  85. package/dist/cli/commands/repair/checks/agents.d.ts +2 -0
  86. package/dist/cli/commands/repair/checks/agents.js +70 -0
  87. package/dist/cli/commands/repair/checks/common.d.ts +8 -0
  88. package/dist/cli/commands/repair/checks/common.js +22 -0
  89. package/dist/cli/commands/repair/checks/contained.d.ts +2 -0
  90. package/dist/cli/commands/repair/checks/contained.js +139 -0
  91. package/dist/cli/commands/repair/checks/data.d.ts +2 -0
  92. package/dist/cli/commands/repair/checks/data.js +241 -0
  93. package/dist/cli/commands/repair/checks/hcs.d.ts +7 -0
  94. package/dist/cli/commands/repair/checks/hcs.js +28 -0
  95. package/dist/cli/commands/repair/checks/index.d.ts +2 -0
  96. package/dist/cli/commands/repair/checks/index.js +24 -0
  97. package/dist/cli/commands/repair/checks/install.d.ts +5 -0
  98. package/dist/cli/commands/repair/checks/install.js +318 -0
  99. package/dist/cli/commands/repair/checks/machine.d.ts +2 -0
  100. package/dist/cli/commands/repair/checks/machine.js +232 -0
  101. package/dist/cli/commands/repair/checks/network.d.ts +6 -0
  102. package/dist/cli/commands/repair/checks/network.js +60 -0
  103. package/dist/cli/commands/repair/checks/pc.d.ts +4 -0
  104. package/dist/cli/commands/repair/checks/pc.js +86 -0
  105. package/dist/cli/commands/repair/checks/sandbox.d.ts +2 -0
  106. package/dist/cli/commands/repair/checks/sandbox.js +282 -0
  107. package/dist/cli/commands/repair/checks/settings.d.ts +2 -0
  108. package/dist/cli/commands/repair/checks/settings.js +169 -0
  109. package/dist/cli/commands/repair/checks/vpn.d.ts +2 -0
  110. package/dist/cli/commands/repair/checks/vpn.js +78 -0
  111. package/dist/cli/commands/repair/engine.d.ts +32 -0
  112. package/dist/cli/commands/repair/engine.js +127 -0
  113. package/dist/cli/commands/repair/env.d.ts +7 -0
  114. package/dist/cli/commands/repair/env.js +50 -0
  115. package/dist/cli/commands/repair/index.d.ts +1 -9
  116. package/dist/cli/commands/repair/index.js +2 -54
  117. package/dist/cli/commands/repair/log.d.ts +17 -0
  118. package/dist/cli/commands/repair/log.js +82 -0
  119. package/dist/cli/commands/repair/printer.d.ts +32 -0
  120. package/dist/cli/commands/repair/printer.js +132 -0
  121. package/dist/cli/commands/repair/run.d.ts +33 -0
  122. package/dist/cli/commands/repair/run.js +133 -0
  123. package/dist/cli/commands/repair/types.d.ts +97 -9
  124. package/dist/cli/commands/repair/types.js +11 -7
  125. package/dist/cli/commands/resume.js +2 -2
  126. package/dist/cli/commands/sessions/index.d.ts +0 -4
  127. package/dist/cli/commands/sessions/index.js +3 -7
  128. package/dist/cli/commands/setup/index.d.ts +5 -0
  129. package/dist/cli/commands/setup/index.js +25 -1
  130. package/dist/cli/commands/shared-use.d.ts +5 -2
  131. package/dist/cli/commands/shared-use.js +11 -8
  132. package/dist/cli/commands/storage/contained.d.ts +3 -0
  133. package/dist/cli/commands/storage/contained.js +179 -0
  134. package/dist/cli/commands/storage/index.d.ts +2 -0
  135. package/dist/cli/commands/storage/index.js +2 -0
  136. package/dist/cli/commands/storage/offer.d.ts +3 -0
  137. package/dist/cli/commands/storage/offer.js +91 -0
  138. package/dist/cli/commands/storage/storage.d.ts +8 -0
  139. package/dist/cli/commands/storage/storage.js +179 -0
  140. package/dist/cli/commands/user-config.js +2 -2
  141. package/dist/cli/commands/vpn.d.ts +4 -0
  142. package/dist/cli/commands/vpn.js +91 -0
  143. package/dist/cli/commands/web.d.ts +4 -0
  144. package/dist/cli/commands/web.js +97 -0
  145. package/dist/cli/history.js +1 -1
  146. package/dist/cli/index.js +48 -4
  147. package/dist/cli/manifest.d.ts +339 -97
  148. package/dist/cli/manifest.js +222 -67
  149. package/dist/cli/menu/add-agent.d.ts +47 -0
  150. package/dist/cli/menu/add-agent.js +168 -0
  151. package/dist/cli/menu/apps.d.ts +38 -3
  152. package/dist/cli/menu/apps.js +80 -5
  153. package/dist/cli/menu/command-fields.d.ts +18 -0
  154. package/dist/cli/menu/command-fields.js +61 -0
  155. package/dist/cli/menu/command-form.d.ts +22 -0
  156. package/dist/cli/menu/command-form.js +169 -46
  157. package/dist/cli/menu/data-folder.d.ts +18 -0
  158. package/dist/cli/menu/data-folder.js +99 -0
  159. package/dist/cli/menu/io-menu.d.ts +29 -0
  160. package/dist/cli/menu/io-menu.js +126 -0
  161. package/dist/cli/menu/live.d.ts +27 -0
  162. package/dist/cli/menu/live.js +69 -0
  163. package/dist/cli/menu/memory.d.ts +19 -0
  164. package/dist/cli/menu/memory.js +53 -0
  165. package/dist/cli/menu/menu.d.ts +11 -2
  166. package/dist/cli/menu/menu.js +36 -15
  167. package/dist/cli/menu/pages/accounts-page.js +55 -24
  168. package/dist/cli/menu/pages/agents-page.d.ts +68 -0
  169. package/dist/cli/menu/pages/agents-page.js +345 -0
  170. package/dist/cli/menu/pages/apps-page.d.ts +3 -1
  171. package/dist/cli/menu/pages/apps-page.js +20 -4
  172. package/dist/cli/menu/pages/list-page.d.ts +43 -3
  173. package/dist/cli/menu/pages/list-page.js +146 -12
  174. package/dist/cli/menu/pages/maintenance-page.d.ts +9 -5
  175. package/dist/cli/menu/pages/maintenance-page.js +172 -85
  176. package/dist/cli/menu/pages/sandbox-page.d.ts +7 -6
  177. package/dist/cli/menu/pages/sandbox-page.js +117 -120
  178. package/dist/cli/menu/pages/scopes.d.ts +1 -1
  179. package/dist/cli/menu/pages/sessions-page.d.ts +6 -8
  180. package/dist/cli/menu/pages/sessions-page.js +22 -75
  181. package/dist/cli/menu/pages/settings-page.d.ts +10 -14
  182. package/dist/cli/menu/pages/settings-page.js +95 -102
  183. package/dist/cli/menu/render-view.d.ts +28 -0
  184. package/dist/cli/menu/render-view.js +112 -0
  185. package/dist/cli/menu/settings/ask-path.d.ts +14 -0
  186. package/dist/cli/menu/settings/ask-path.js +14 -0
  187. package/dist/cli/menu/settings/collections/collection-editor.d.ts +8 -2
  188. package/dist/cli/menu/settings/collections/collection-editor.js +12 -8
  189. package/dist/cli/menu/settings/collections/map-editor.js +5 -1
  190. package/dist/cli/menu/settings/collections/object-list-editor.js +2 -2
  191. package/dist/cli/menu/settings/collections/object-map-editor.js +2 -2
  192. package/dist/cli/menu/settings/collections/string-list-editor.d.ts +10 -1
  193. package/dist/cli/menu/settings/collections/string-list-editor.js +23 -0
  194. package/dist/cli/menu/settings/draft.d.ts +1 -1
  195. package/dist/cli/menu/settings/format.d.ts +1 -3
  196. package/dist/cli/menu/settings/format.js +6 -36
  197. package/dist/cli/menu/settings/index.d.ts +1 -3
  198. package/dist/cli/menu/settings/index.js +3 -3
  199. package/dist/cli/menu/settings/object-editor.d.ts +6 -2
  200. package/dist/cli/menu/settings/object-editor.js +15 -4
  201. package/dist/cli/menu/settings/share.d.ts +36 -0
  202. package/dist/cli/menu/settings/share.js +131 -0
  203. package/dist/cli/menu/settings/value-editor.d.ts +10 -1
  204. package/dist/cli/menu/settings/value-editor.js +99 -63
  205. package/dist/cli/menu/several.js +7 -5
  206. package/dist/cli/menu/share-settings.d.ts +21 -0
  207. package/dist/cli/menu/share-settings.js +112 -0
  208. package/dist/cli/menu/shell.d.ts +53 -10
  209. package/dist/cli/menu/shell.js +115 -10
  210. package/dist/cli/menu/views.d.ts +7 -0
  211. package/dist/cli/menu/views.js +11 -0
  212. package/dist/cli/menu/vpn-login.d.ts +16 -0
  213. package/dist/cli/menu/vpn-login.js +74 -0
  214. package/dist/cli/operations/handler.d.ts +6 -0
  215. package/dist/cli/operations/handler.js +61 -0
  216. package/dist/cli/operations/index.d.ts +4 -0
  217. package/dist/cli/operations/index.js +5 -0
  218. package/dist/cli/operations/input.d.ts +6 -0
  219. package/dist/cli/operations/input.js +37 -0
  220. package/dist/cli/operations/io-cli.d.ts +7 -0
  221. package/dist/cli/operations/io-cli.js +62 -0
  222. package/dist/cli/operations/spec.d.ts +18 -0
  223. package/dist/cli/operations/spec.js +108 -0
  224. package/dist/cli/output/colors.d.ts +2 -2
  225. package/dist/cli/output/colors.js +2 -11
  226. package/dist/cli/output/index.d.ts +1 -0
  227. package/dist/cli/output/index.js +1 -0
  228. package/dist/cli/output/print.d.ts +5 -1
  229. package/dist/cli/output/print.js +15 -4
  230. package/dist/cli/output/progress.d.ts +15 -0
  231. package/dist/cli/output/progress.js +44 -0
  232. package/dist/cli/output/render-view.d.ts +4 -0
  233. package/dist/cli/output/render-view.js +63 -0
  234. package/dist/cli/services/accounts-service.d.ts +2 -0
  235. package/dist/cli/services/accounts-service.js +2 -2
  236. package/dist/cli/services/agent-commands-service.d.ts +2 -0
  237. package/dist/cli/services/agent-commands-service.js +11 -2
  238. package/dist/cli/services/health-service.d.ts +0 -6
  239. package/dist/cli/services/health-service.js +5 -42
  240. package/dist/cli/services/index.d.ts +3 -1
  241. package/dist/cli/services/index.js +3 -1
  242. package/dist/cli/services/logs-service.js +4 -3
  243. package/dist/cli/services/migrate-service.js +1 -1
  244. package/dist/cli/services/update-service.d.ts +2 -0
  245. package/dist/cli/services/update-service.js +13 -6
  246. package/dist/cli/services/vpn-service.d.ts +28 -0
  247. package/dist/cli/services/vpn-service.js +46 -0
  248. package/dist/cli/services/web-service.d.ts +22 -0
  249. package/dist/cli/services/web-service.js +111 -0
  250. package/dist/cli/tui/app.d.ts +12 -4
  251. package/dist/cli/tui/app.js +38 -9
  252. package/dist/cli/tui/dialogs/path-listing.d.ts +43 -0
  253. package/dist/cli/tui/dialogs/path-listing.js +127 -0
  254. package/dist/cli/tui/dialogs/path-picker.d.ts +67 -0
  255. package/dist/cli/tui/dialogs/path-picker.js +423 -0
  256. package/dist/cli/tui/dialogs/text-screen.d.ts +6 -0
  257. package/dist/cli/tui/dialogs/text-screen.js +10 -3
  258. package/dist/cli/tui/frame.d.ts +7 -10
  259. package/dist/cli/tui/frame.js +19 -10
  260. package/dist/cli/tui/index.d.ts +4 -3
  261. package/dist/cli/tui/index.js +2 -1
  262. package/dist/cli/tui/list/list-screen.d.ts +28 -2
  263. package/dist/cli/tui/list/list-screen.js +130 -66
  264. package/dist/cli/tui/list/list-types.d.ts +10 -4
  265. package/dist/cli/tui/nav.d.ts +29 -0
  266. package/dist/cli/tui/nav.js +67 -0
  267. package/dist/cli/tui/terminal.d.ts +7 -0
  268. package/dist/cli/tui/terminal.js +30 -10
  269. package/dist/cli/validate.d.ts +1 -1
  270. package/dist/cli/validate.js +3 -3
  271. package/dist/cli/version.d.ts +2 -0
  272. package/dist/cli/version.js +11 -0
  273. package/dist/core/config/defaults.js +13 -1
  274. package/dist/core/config/loader.js +12 -2
  275. package/dist/core/local-config/overrides.js +1 -0
  276. package/dist/core/prompt.d.ts +19 -0
  277. package/dist/core/prompt.js +43 -3
  278. package/dist/core/schema/common.d.ts +6 -0
  279. package/dist/core/schema/common.js +8 -0
  280. package/dist/core/schema/config.d.ts +36 -0
  281. package/dist/core/schema/config.js +26 -2
  282. package/dist/core/schema/harness.d.ts +2 -0
  283. package/dist/core/schema/harness.js +13 -2
  284. package/dist/core/schema/index.d.ts +3 -1
  285. package/dist/core/schema/index.js +3 -1
  286. package/dist/core/schema/profile.d.ts +1 -0
  287. package/dist/core/schema/profile.js +3 -0
  288. package/dist/core/schema/redact.d.ts +13 -0
  289. package/dist/core/schema/redact.js +75 -0
  290. package/dist/core/schema/sandbox.d.ts +6 -0
  291. package/dist/core/schema/sandbox.js +21 -3
  292. package/dist/core/schema/vpn.d.ts +18 -0
  293. package/dist/core/schema/vpn.js +22 -0
  294. package/dist/core/schema/web.d.ts +6 -0
  295. package/dist/core/schema/web.js +14 -0
  296. package/dist/core/types.d.ts +44 -0
  297. package/dist/core/util/fs.d.ts +2 -0
  298. package/dist/core/util/fs.js +9 -0
  299. package/dist/core/util/index.d.ts +1 -1
  300. package/dist/core/util/index.js +1 -1
  301. package/dist/guest/agents/agent-files.d.ts +54 -0
  302. package/dist/guest/agents/agent-files.js +67 -0
  303. package/dist/guest/agents/agent-installer.js +2 -9
  304. package/dist/guest/agents/local-state.d.ts +14 -0
  305. package/dist/guest/agents/local-state.js +218 -0
  306. package/dist/guest/agents/sbx-agent.d.ts +2 -0
  307. package/dist/guest/agents/sbx-agent.js +35 -0
  308. package/dist/guest/boot/boot.d.ts +4 -0
  309. package/dist/guest/boot/boot.js +51 -11
  310. package/dist/guest/daemon/daemon.js +8 -1
  311. package/dist/guest/daemon/exec.js +2 -1
  312. package/dist/guest/daemon/idle-shutdown.js +2 -0
  313. package/dist/guest/daemon/sessions.d.ts +5 -0
  314. package/dist/guest/daemon/sessions.js +20 -3
  315. package/dist/guest/entries/agent.d.ts +1 -0
  316. package/dist/guest/entries/agent.js +10 -0
  317. package/dist/guest/entries/daemon.js +5 -0
  318. package/dist/guest/governor/decide.d.ts +61 -0
  319. package/dist/guest/governor/decide.js +182 -0
  320. package/dist/guest/governor/governor.d.ts +42 -0
  321. package/dist/guest/governor/governor.js +214 -0
  322. package/dist/guest/governor/index.d.ts +2 -0
  323. package/dist/guest/governor/index.js +2 -0
  324. package/dist/guest/runtime/csc.d.ts +2 -0
  325. package/dist/guest/runtime/csc.js +2 -0
  326. package/dist/guest/runtime/secrets.d.ts +12 -0
  327. package/dist/guest/runtime/secrets.js +63 -0
  328. package/dist/guest/sessions/viewer.js +3 -1
  329. package/dist/guest/setup/claude-profile.d.ts +2 -1
  330. package/dist/guest/setup/claude-profile.js +12 -1
  331. package/dist/guest/setup/environment.d.ts +6 -0
  332. package/dist/guest/setup/environment.js +56 -6
  333. package/dist/guest/setup/path-plan.d.ts +32 -0
  334. package/dist/guest/setup/path-plan.js +67 -0
  335. package/dist/guest/setup/shell-path.d.ts +1 -0
  336. package/dist/guest/setup/shell-path.js +22 -0
  337. package/dist/guest/toolchains/languages/python.js +1 -1
  338. package/dist/guest/toolchains/native/rust-extras.js +4 -2
  339. package/dist/guest/toolchains/runtimes.js +2 -2
  340. package/dist/guest/vpn/index.d.ts +1 -0
  341. package/dist/guest/vpn/index.js +1 -0
  342. package/dist/guest/vpn/openvpn.d.ts +9 -0
  343. package/dist/guest/vpn/openvpn.js +47 -0
  344. package/dist/guest/vpn/tunnel.d.ts +17 -0
  345. package/dist/guest/vpn/tunnel.js +78 -0
  346. package/dist/guest/vpn/vpn.d.ts +6 -0
  347. package/dist/guest/vpn/vpn.js +174 -0
  348. package/dist/guest/vpn/wireguard.d.ts +32 -0
  349. package/dist/guest/vpn/wireguard.js +132 -0
  350. package/dist/host/agent-commands/commands.d.ts +4 -0
  351. package/dist/host/agent-commands/commands.js +31 -7
  352. package/dist/host/audit/log.d.ts +1 -1
  353. package/dist/host/channel/attach.d.ts +6 -2
  354. package/dist/host/channel/attach.js +6 -3
  355. package/dist/host/channel/channel.d.ts +9 -0
  356. package/dist/host/channel/channel.js +30 -2
  357. package/dist/host/engines/engine.d.ts +12 -0
  358. package/dist/host/engines/engine.js +1 -0
  359. package/dist/host/engines/hcs/check.d.ts +25 -0
  360. package/dist/host/engines/hcs/check.js +95 -0
  361. package/dist/host/engines/hcs/documents.d.ts +44 -0
  362. package/dist/host/engines/hcs/documents.js +155 -0
  363. package/dist/host/engines/hcs/engine.d.ts +39 -0
  364. package/dist/host/engines/hcs/engine.js +171 -0
  365. package/dist/host/engines/hcs/helper.d.ts +43 -0
  366. package/dist/host/engines/hcs/helper.js +173 -0
  367. package/dist/host/engines/hcs/images.d.ts +37 -0
  368. package/dist/host/engines/hcs/images.js +152 -0
  369. package/dist/host/engines/index.d.ts +7 -0
  370. package/dist/host/engines/index.js +5 -0
  371. package/dist/host/engines/registry.d.ts +16 -0
  372. package/dist/host/engines/registry.js +30 -0
  373. package/dist/host/engines/types.d.ts +58 -0
  374. package/dist/host/engines/types.js +1 -0
  375. package/dist/host/engines/windows-sandbox/engine.d.ts +16 -0
  376. package/dist/host/engines/windows-sandbox/engine.js +63 -0
  377. package/dist/host/engines/windows-sandbox/wsb-text.d.ts +2 -0
  378. package/dist/host/engines/windows-sandbox/wsb-text.js +29 -0
  379. package/dist/host/health/acl-read.d.ts +17 -0
  380. package/dist/host/health/acl-read.js +45 -0
  381. package/dist/host/health/config-backup.d.ts +11 -0
  382. package/dist/host/health/config-backup.js +73 -0
  383. package/dist/host/health/index.d.ts +6 -0
  384. package/dist/host/health/index.js +7 -0
  385. package/dist/host/health/install-state.d.ts +33 -0
  386. package/dist/host/health/install-state.js +110 -0
  387. package/dist/host/health/path-copies.d.ts +32 -0
  388. package/dist/host/health/path-copies.js +82 -0
  389. package/dist/host/health/stale.d.ts +45 -0
  390. package/dist/host/health/stale.js +120 -0
  391. package/dist/host/health/system.d.ts +37 -0
  392. package/dist/host/health/system.js +87 -0
  393. package/dist/host/install/copies.d.ts +13 -0
  394. package/dist/host/install/copies.js +63 -0
  395. package/dist/host/install/index.d.ts +1 -0
  396. package/dist/host/install/index.js +1 -0
  397. package/dist/host/launch/generate.d.ts +5 -1
  398. package/dist/host/launch/generate.js +73 -7
  399. package/dist/host/launch/index.d.ts +3 -1
  400. package/dist/host/launch/index.js +3 -1
  401. package/dist/host/launch/launch-plan.d.ts +13 -0
  402. package/dist/host/launch/launch-plan.js +26 -0
  403. package/dist/host/launch/mappings.js +2 -1
  404. package/dist/host/launch/risk-notes.d.ts +10 -0
  405. package/dist/host/launch/risk-notes.js +18 -0
  406. package/dist/host/launch/session-file.d.ts +2 -0
  407. package/dist/host/launch/session-file.js +11 -2
  408. package/dist/host/launch/stage.js +1 -1
  409. package/dist/host/launch/wsb-file.d.ts +28 -4
  410. package/dist/host/launch/wsb-file.js +61 -42
  411. package/dist/host/life/crash-report.d.ts +27 -1
  412. package/dist/host/life/crash-report.js +173 -7
  413. package/dist/host/life/host-memory.d.ts +40 -0
  414. package/dist/host/life/host-memory.js +137 -0
  415. package/dist/host/life/index.d.ts +2 -0
  416. package/dist/host/life/index.js +2 -0
  417. package/dist/host/life/stop-events.d.ts +2 -0
  418. package/dist/host/life/stop-events.js +20 -3
  419. package/dist/host/life/stop-warning.js +1 -1
  420. package/dist/host/life/watchdog.d.ts +54 -0
  421. package/dist/host/life/watchdog.js +108 -0
  422. package/dist/host/migrate/backup.js +3 -0
  423. package/dist/host/migrate/migrations/config-file.d.ts +2 -0
  424. package/dist/host/migrate/migrations/config-file.js +7 -0
  425. package/dist/host/migrate/migrations/follow-machine-storage.js +9 -1
  426. package/dist/host/migrate/migrations/pin-storage-root.d.ts +4 -0
  427. package/dist/host/migrate/migrations/pin-storage-root.js +46 -0
  428. package/dist/host/migrate/migrations/unpin-config-defaults.js +4 -1
  429. package/dist/host/migrate/registry.js +2 -1
  430. package/dist/host/native.d.ts +3 -2
  431. package/dist/host/native.js +22 -3
  432. package/dist/host/profile/accounts.d.ts +25 -1
  433. package/dist/host/profile/accounts.js +96 -13
  434. package/dist/host/profile/agent-accounts.d.ts +5 -1
  435. package/dist/host/profile/agent-accounts.js +35 -5
  436. package/dist/host/profile/claude-login.js +3 -2
  437. package/dist/host/profile/index.d.ts +2 -1
  438. package/dist/host/profile/index.js +1 -0
  439. package/dist/host/profile/plugin-share.d.ts +26 -0
  440. package/dist/host/profile/plugin-share.js +146 -0
  441. package/dist/host/projects/join.d.ts +7 -1
  442. package/dist/host/projects/join.js +21 -4
  443. package/dist/host/projects/registry.d.ts +16 -10
  444. package/dist/host/projects/registry.js +74 -6
  445. package/dist/host/sandbox/contained-deps.d.ts +2 -0
  446. package/dist/host/sandbox/contained-deps.js +17 -0
  447. package/dist/host/sandbox/index.d.ts +2 -0
  448. package/dist/host/sandbox/index.js +2 -0
  449. package/dist/host/sandbox/platform.d.ts +4 -0
  450. package/dist/host/sandbox/platform.js +23 -4
  451. package/dist/host/sandbox/tasklist.d.ts +13 -0
  452. package/dist/host/sandbox/tasklist.js +47 -0
  453. package/dist/host/secrets/index.d.ts +2 -0
  454. package/dist/host/secrets/index.js +2 -0
  455. package/dist/host/secrets/launch-secrets.d.ts +17 -0
  456. package/dist/host/secrets/launch-secrets.js +94 -0
  457. package/dist/host/secrets/secret-store.d.ts +25 -0
  458. package/dist/host/secrets/secret-store.js +89 -0
  459. package/dist/host/sharing/acl.d.ts +16 -2
  460. package/dist/host/sharing/acl.js +35 -10
  461. package/dist/host/sharing/current.js +8 -3
  462. package/dist/host/sharing/doctor.d.ts +2 -0
  463. package/dist/host/sharing/doctor.js +44 -0
  464. package/dist/host/sharing/group-access.d.ts +6 -0
  465. package/dist/host/sharing/group-access.js +24 -0
  466. package/dist/host/sharing/index.d.ts +2 -1
  467. package/dist/host/sharing/index.js +2 -1
  468. package/dist/host/sharing/lifecycle.d.ts +8 -2
  469. package/dist/host/sharing/lifecycle.js +16 -7
  470. package/dist/host/storage/cleanup.d.ts +2 -0
  471. package/dist/host/storage/cleanup.js +2 -1
  472. package/dist/host/storage/contained/check.d.ts +9 -0
  473. package/dist/host/storage/contained/check.js +37 -0
  474. package/dist/host/storage/contained/contained-storage.d.ts +66 -0
  475. package/dist/host/storage/contained/contained-storage.js +168 -0
  476. package/dist/host/storage/contained/disk-port.d.ts +43 -0
  477. package/dist/host/storage/contained/disk-port.js +122 -0
  478. package/dist/host/storage/contained/index.d.ts +9 -0
  479. package/dist/host/storage/contained/index.js +8 -0
  480. package/dist/host/storage/contained/layout.d.ts +28 -0
  481. package/dist/host/storage/contained/layout.js +45 -0
  482. package/dist/host/storage/contained/resolve.d.ts +4 -0
  483. package/dist/host/storage/contained/resolve.js +30 -0
  484. package/dist/host/storage/contained/setting.d.ts +1 -0
  485. package/dist/host/storage/contained/setting.js +5 -0
  486. package/dist/host/storage/contained/state.d.ts +89 -0
  487. package/dist/host/storage/contained/state.js +166 -0
  488. package/dist/host/storage/contained/transfer.d.ts +24 -0
  489. package/dist/host/storage/contained/transfer.js +121 -0
  490. package/dist/host/storage/history.d.ts +21 -0
  491. package/dist/host/storage/history.js +49 -0
  492. package/dist/host/storage/index.d.ts +6 -0
  493. package/dist/host/storage/index.js +6 -0
  494. package/dist/host/storage/move.d.ts +95 -0
  495. package/dist/host/storage/move.js +384 -0
  496. package/dist/host/storage/offer.d.ts +11 -0
  497. package/dist/host/storage/offer.js +36 -0
  498. package/dist/host/storage/providers/contained.d.ts +15 -0
  499. package/dist/host/storage/providers/contained.js +39 -0
  500. package/dist/host/storage/providers/folder.d.ts +12 -0
  501. package/dist/host/storage/providers/folder.js +20 -0
  502. package/dist/host/storage/providers/index.d.ts +4 -0
  503. package/dist/host/storage/providers/index.js +3 -0
  504. package/dist/host/storage/providers/registry.d.ts +9 -0
  505. package/dist/host/storage/providers/registry.js +14 -0
  506. package/dist/host/storage/providers/types.d.ts +33 -0
  507. package/dist/host/storage/providers/types.js +1 -0
  508. package/dist/host/storage/root.d.ts +18 -0
  509. package/dist/host/storage/root.js +77 -0
  510. package/dist/host/tools/conpty.js +3 -2
  511. package/dist/host/tools/windows-terminal.d.ts +2 -0
  512. package/dist/host/tools/windows-terminal.js +31 -12
  513. package/dist/host/update/index.d.ts +1 -1
  514. package/dist/host/update/index.js +1 -1
  515. package/dist/host/update/notice.d.ts +2 -0
  516. package/dist/host/update/notice.js +13 -1
  517. package/dist/host/update/update-state.d.ts +6 -0
  518. package/dist/host/update/update-state.js +2 -0
  519. package/dist/host/update/updater.d.ts +19 -0
  520. package/dist/host/update/updater.js +88 -12
  521. package/dist/host/vpn/index.d.ts +4 -0
  522. package/dist/host/vpn/index.js +4 -0
  523. package/dist/host/vpn/login.d.ts +24 -0
  524. package/dist/host/vpn/login.js +79 -0
  525. package/dist/host/vpn/nordvpn.d.ts +21 -0
  526. package/dist/host/vpn/nordvpn.js +77 -0
  527. package/dist/host/vpn/prepare.d.ts +19 -0
  528. package/dist/host/vpn/prepare.js +138 -0
  529. package/dist/host/vpn/status.d.ts +12 -0
  530. package/dist/host/vpn/status.js +53 -0
  531. package/dist/host/web/auth.d.ts +38 -0
  532. package/dist/host/web/auth.js +96 -0
  533. package/dist/host/web/backend.d.ts +14 -0
  534. package/dist/host/web/backend.js +1 -0
  535. package/dist/host/web/bridge.d.ts +27 -0
  536. package/dist/host/web/bridge.js +144 -0
  537. package/dist/host/web/browser.d.ts +3 -0
  538. package/dist/host/web/browser.js +23 -0
  539. package/dist/host/web/control.d.ts +17 -0
  540. package/dist/host/web/control.js +67 -0
  541. package/dist/host/web/index.d.ts +10 -0
  542. package/dist/host/web/index.js +9 -0
  543. package/dist/host/web/rpc.d.ts +24 -0
  544. package/dist/host/web/rpc.js +149 -0
  545. package/dist/host/web/runner.d.ts +16 -0
  546. package/dist/host/web/runner.js +44 -0
  547. package/dist/host/web/server.d.ts +47 -0
  548. package/dist/host/web/server.js +238 -0
  549. package/dist/host/web/state.d.ts +20 -0
  550. package/dist/host/web/state.js +41 -0
  551. package/dist/host/web/static-files.d.ts +13 -0
  552. package/dist/host/web/static-files.js +57 -0
  553. package/dist/runtime/agent.js +27675 -0
  554. package/dist/runtime/daemon.js +1950 -1122
  555. package/dist/runtime/db.js +302 -111
  556. package/dist/runtime/main.js +1560 -275
  557. package/dist/runtime/netproxy.js +168 -8
  558. package/dist/runtime/view.js +186 -13
  559. package/dist/selftest/accounts.test.js +40 -0
  560. package/dist/selftest/agent-paths.test.d.ts +2 -0
  561. package/dist/selftest/agent-paths.test.js +125 -0
  562. package/dist/selftest/app.test.d.ts +2 -0
  563. package/dist/selftest/app.test.js +324 -0
  564. package/dist/selftest/channel.test.js +18 -0
  565. package/dist/selftest/cli.test.js +35 -4
  566. package/dist/selftest/config.test.js +59 -0
  567. package/dist/selftest/contained.test.d.ts +2 -0
  568. package/dist/selftest/contained.test.js +544 -0
  569. package/dist/selftest/credentials.test.d.ts +2 -0
  570. package/dist/selftest/credentials.test.js +198 -0
  571. package/dist/selftest/engine.test.d.ts +2 -0
  572. package/dist/selftest/engine.test.js +127 -0
  573. package/dist/selftest/generate.test.js +1 -1
  574. package/dist/selftest/hcs.test.d.ts +2 -0
  575. package/dist/selftest/hcs.test.js +482 -0
  576. package/dist/selftest/health.test.d.ts +2 -0
  577. package/dist/selftest/health.test.js +470 -0
  578. package/dist/selftest/heavy-load.test.d.ts +2 -0
  579. package/dist/selftest/heavy-load.test.js +329 -0
  580. package/dist/selftest/host-sim.test.js +2 -0
  581. package/dist/selftest/index.js +31 -0
  582. package/dist/selftest/layout.test.js +14 -0
  583. package/dist/selftest/menu-perf.test.d.ts +2 -0
  584. package/dist/selftest/menu-perf.test.js +248 -0
  585. package/dist/selftest/menu-screens.d.ts +7 -0
  586. package/dist/selftest/menu-screens.js +68 -17
  587. package/dist/selftest/menu.test.js +603 -22
  588. package/dist/selftest/migrate.test.js +1 -1
  589. package/dist/selftest/personalization.test.js +3 -1
  590. package/dist/selftest/projects.test.js +39 -1
  591. package/dist/selftest/shared-use.test.js +64 -2
  592. package/dist/selftest/sharing.test.js +50 -1
  593. package/dist/selftest/storage.test.d.ts +2 -0
  594. package/dist/selftest/storage.test.js +363 -0
  595. package/dist/selftest/support/engine-cases.d.ts +8 -0
  596. package/dist/selftest/support/engine-cases.js +65 -0
  597. package/dist/selftest/support/engine-golden.d.ts +3 -0
  598. package/dist/selftest/support/engine-golden.js +66 -0
  599. package/dist/selftest/support/fixtures.d.ts +20 -0
  600. package/dist/selftest/support/hcs-probes.d.ts +17 -0
  601. package/dist/selftest/support/hcs-probes.js +41 -0
  602. package/dist/selftest/support/releases.js +1 -1
  603. package/dist/selftest/toolchains.test.js +21 -0
  604. package/dist/selftest/update-service.test.js +87 -3
  605. package/dist/selftest/vpn.test.d.ts +2 -0
  606. package/dist/selftest/vpn.test.js +412 -0
  607. package/dist/selftest/web.test.d.ts +2 -0
  608. package/dist/selftest/web.test.js +402 -0
  609. package/dist/shared/apps/catalogue.js +31 -0
  610. package/dist/shared/channel/index.d.ts +1 -0
  611. package/dist/shared/channel/index.js +1 -0
  612. package/dist/shared/channel/run-dir.d.ts +9 -1
  613. package/dist/shared/channel/run-dir.js +18 -1
  614. package/dist/shared/channel/schema.d.ts +53 -0
  615. package/dist/shared/channel/schema.js +38 -0
  616. package/dist/shared/channel/secrets.d.ts +29 -0
  617. package/dist/shared/channel/secrets.js +50 -0
  618. package/dist/shared/memory/index.d.ts +1 -0
  619. package/dist/shared/memory/index.js +1 -0
  620. package/dist/shared/memory/policy.d.ts +33 -0
  621. package/dist/shared/memory/policy.js +55 -0
  622. package/dist/shared/pty/output-filter.d.ts +14 -1
  623. package/dist/shared/pty/output-filter.js +22 -4
  624. package/dist/shared/pty/terminal.d.ts +4 -1
  625. package/dist/shared/pty/terminal.js +4 -2
  626. package/dist/shared/system.d.ts +1 -0
  627. package/dist/shared/system.js +1 -0
  628. package/dist/shared/vpn/download.d.ts +29 -0
  629. package/dist/shared/vpn/download.js +30 -0
  630. package/dist/shared/vpn/kill-switch.d.ts +18 -0
  631. package/dist/shared/vpn/kill-switch.js +81 -0
  632. package/dist/shared/vpn/ovpn.d.ts +23 -0
  633. package/dist/shared/vpn/ovpn.js +244 -0
  634. package/dist/shared/vpn/wireguard.d.ts +51 -0
  635. package/dist/shared/vpn/wireguard.js +227 -0
  636. package/dist/shared/web/index.d.ts +1 -0
  637. package/dist/shared/web/index.js +1 -0
  638. package/dist/shared/web/protocol.d.ts +61 -0
  639. package/dist/shared/web/protocol.js +35 -0
  640. package/dist/sync/sync-cycle.js +9 -5
  641. package/dist/sync/sync-state.d.ts +1 -0
  642. package/dist/sync/sync-state.js +1 -0
  643. package/dist/sync/watcher.d.ts +13 -0
  644. package/dist/sync/watcher.js +102 -3
  645. package/dist/web/index.html +14 -0
  646. package/dist/web/main-NRRS5O6Z.js +157 -0
  647. package/dist/web/main-T5DMCHYV.css +1 -0
  648. package/native/csharp/FolderSecurity.cs +29 -0
  649. package/native/csharp/HcsHost/AssemblyInfo.cs +14 -0
  650. package/native/csharp/HcsHost/Guard.cs +100 -0
  651. package/native/csharp/HcsHost/Hcs.cs +256 -0
  652. package/native/csharp/HcsHost/Json.cs +78 -0
  653. package/native/csharp/HcsHost/Program.cs +185 -0
  654. package/native/csharp/HcsHost/VirtualDisk.cs +95 -0
  655. package/native/csharp/HostTools/AssemblyInfo.cs +14 -0
  656. package/native/csharp/HostTools/MemoryStatus.cs +107 -0
  657. package/native/csharp/HostTools/Program.cs +58 -17
  658. package/native/scripts/check-contained.ps1 +28 -0
  659. package/native/scripts/contained-common.ps1 +241 -0
  660. package/native/scripts/dismount-contained.ps1 +66 -0
  661. package/native/scripts/memory-status.ps1 +34 -0
  662. package/native/scripts/mount-contained.ps1 +139 -0
  663. package/native/scripts/protect-data.ps1 +29 -0
  664. package/native/scripts/read-folder-sddl.ps1 +10 -0
  665. package/native/scripts/run-elevated.ps1 +17 -4
  666. package/native/scripts/set-folder-access.ps1 +49 -7
  667. package/native/scripts/stop-events.ps1 +23 -8
  668. package/node_modules/ws/LICENSE +20 -0
  669. package/node_modules/ws/README.md +548 -0
  670. package/node_modules/ws/browser.js +8 -0
  671. package/node_modules/ws/index.js +22 -0
  672. package/node_modules/ws/lib/buffer-util.js +131 -0
  673. package/node_modules/ws/lib/constants.js +19 -0
  674. package/node_modules/ws/lib/event-target.js +292 -0
  675. package/node_modules/ws/lib/extension.js +203 -0
  676. package/node_modules/ws/lib/limiter.js +55 -0
  677. package/node_modules/ws/lib/permessage-deflate.js +530 -0
  678. package/node_modules/ws/lib/receiver.js +743 -0
  679. package/node_modules/ws/lib/sender.js +607 -0
  680. package/node_modules/ws/lib/stream.js +161 -0
  681. package/node_modules/ws/lib/subprotocol.js +62 -0
  682. package/node_modules/ws/lib/validation.js +152 -0
  683. package/node_modules/ws/lib/websocket-server.js +562 -0
  684. package/node_modules/ws/lib/websocket.js +1421 -0
  685. package/node_modules/ws/package.json +74 -0
  686. package/node_modules/ws/wrapper.mjs +21 -0
  687. package/package.json +22 -5
  688. package/sandbox/csharp/EnvBroadcast.cs +33 -0
  689. package/sandbox/csharp/MemGov.cs +398 -0
  690. package/sandbox/csharp/PathSync.cs +90 -0
  691. package/sandbox/csharp/PtyHost.cs +111 -5
  692. package/sandbox/scripts/install-shell-path.ps1 +73 -0
  693. package/sandbox/scripts/set-machine-environment.ps1 +37 -4
  694. package/schemas/config.schema.json +136 -7
  695. package/schemas/sandbox-config.schema.json +17 -4
  696. package/dist/cli/commands/repair/checks.d.ts +0 -2
  697. package/dist/cli/commands/repair/checks.js +0 -246
  698. package/dist/cli/commands/sessions/control.d.ts +0 -4
  699. package/dist/cli/commands/sessions/control.js +0 -66
  700. package/dist/cli/commands/sessions/list.d.ts +0 -2
  701. package/dist/cli/commands/sessions/list.js +0 -45
  702. package/dist/cli/commands/sessions/status.d.ts +0 -2
  703. package/dist/cli/commands/sessions/status.js +0 -93
  704. package/dist/cli/commands/sessions/window.d.ts +0 -3
  705. package/dist/cli/commands/sessions/window.js +0 -18
  706. package/dist/cli/menu/pages/start-page.d.ts +0 -43
  707. package/dist/cli/menu/pages/start-page.js +0 -192
  708. package/dist/cli/tui/tab-bar.d.ts +0 -9
  709. package/dist/cli/tui/tab-bar.js +0 -33
@@ -0,0 +1,91 @@
1
+ // At the start of an interactive command: makes sure the storage folder exists (private when it should be) and, once,
2
+ // offers to move saved data from another folder to where it belongs. Never asks without a terminal.
3
+ import { select } from '@inquirer/prompts';
4
+ import { userDir } from '../../../core/config/index.js';
5
+ import { errMsg } from '../../../core/util/index.js';
6
+ import { isSandboxRunning, insideSandbox } from '../../../host/sandbox/index.js';
7
+ import { protectPrivateFolder } from '../../../host/sharing/index.js';
8
+ import { describeDuration, describeSize, ensureStorageRoot, estimate, measureFolder, moveWarning, planOffer, staleMountNote, StorageHistory, } from '../../../host/storage/index.js';
9
+ import { c, working } from '../../output/index.js';
10
+ import { refreshStorage } from '../context.js';
11
+ import { performMove } from './storage.js';
12
+ /** Commands that do not touch the storage folder, or must work whatever state it is in. */
13
+ const NO_STORAGE = ['self-test', '_watch', '_web', 'update', 'storage', 'migrate', 'repair'];
14
+ /** Commands that start something the user is sitting in front of: the offer is shown before them. */
15
+ const OFFERS = ['menu', 'launch'];
16
+ async function ask(text) {
17
+ console.error('\n' + text + '\n');
18
+ return select({
19
+ message: 'Move it now?',
20
+ choices: [
21
+ { name: 'Move now', value: 'now' },
22
+ { name: 'Not now', value: 'later' },
23
+ { name: "Don't ask again", value: 'never' },
24
+ ],
25
+ default: 'now',
26
+ });
27
+ }
28
+ function offerText(offer, size, time, warning) {
29
+ const where = offer.toIsDefault
30
+ ? 'The default folder is now ' + offer.to + ', which works for both kinds of install.'
31
+ : 'Your folder is ' + offer.to + '.';
32
+ return ('Your saved data (' +
33
+ size +
34
+ ') is in ' +
35
+ offer.from +
36
+ '. ' +
37
+ where +
38
+ ' Move it there now? ' +
39
+ time +
40
+ '.' +
41
+ (warning ? '\n' + warning : ''));
42
+ }
43
+ async function offerMove(ctx, history) {
44
+ const offer = planOffer(ctx.storageRoot, history);
45
+ if (!offer || isSandboxRunning())
46
+ return;
47
+ const measured = await working('Looking at your saved data', () => measureFolder(offer.from));
48
+ const est = estimate(offer.from, offer.to, measured);
49
+ const spoken = est.sameVolume ? 'a few seconds' : describeDuration(est.seconds);
50
+ const time = spoken.charAt(0).toUpperCase() + spoken.slice(1);
51
+ if (!est.fits) {
52
+ console.error(c.dim(moveWarning(measured, est) ?? ''));
53
+ return;
54
+ }
55
+ const answer = await ask(offerText(offer, describeSize(measured), time, moveWarning(measured, est)));
56
+ if (answer === 'never')
57
+ history.setDontAsk();
58
+ else if (answer === 'later')
59
+ history.setNotNow();
60
+ if (answer !== 'now')
61
+ return;
62
+ const result = await performMove({ ...ctx, storageRoot: offer.from }, offer.to, false);
63
+ console.error('Moved. Your data is now in ' + result.to + '.');
64
+ for (const note of result.notes)
65
+ console.error(c.dim(note));
66
+ refreshStorage(ctx);
67
+ }
68
+ /** Before a command (after the saved settings are up to date). A failed move never stops the command. */
69
+ export async function storageBeforeCommand(ctx, command) {
70
+ if (insideSandbox() || NO_STORAGE.includes(command))
71
+ return;
72
+ if (OFFERS.includes(command) &&
73
+ process.stdin.isTTY &&
74
+ process.stdout.isTTY &&
75
+ !ctx.options.json &&
76
+ !ctx.options.unattended) {
77
+ try {
78
+ await offerMove(ctx, new StorageHistory(userDir()));
79
+ }
80
+ catch (e) {
81
+ console.error(c.red('Could not move your data: ') + errMsg(e));
82
+ }
83
+ }
84
+ ensureStorageRoot(ctx.storageRoot, protectPrivateFolder);
85
+ // Contained storage (beta): a mount an earlier sandbox left behind is only mentioned here; repair fixes it.
86
+ if (command !== 'launch' && !ctx.options.json) {
87
+ const stale = staleMountNote(ctx.storageRoot, ctx.loaded.config.storage.dataName, isSandboxRunning());
88
+ if (stale)
89
+ console.error(c.yellow(stale));
90
+ }
91
+ }
@@ -0,0 +1,8 @@
1
+ import { type MoveResult } from '../../../host/storage/index.js';
2
+ import { type Context } from '../context.js';
3
+ /** Why a move cannot start (a background sync is still on a data folder in the old storage), or null. */
4
+ export declare function storageBusy(root: string): string | null;
5
+ /** Moves the data with progress on the terminal; remembers both folders. Used by the command and the start offer. */
6
+ export declare function performMove(ctx: Context, to: string, keepOld: boolean): Promise<MoveResult>;
7
+ /** `sandbox storage [show|move <folder>|use <folder>]`. */
8
+ export declare function storage(ctx: Context): number | Promise<number>;
@@ -0,0 +1,179 @@
1
+ // `sandbox storage`: where everything kept between sandboxes lives, moving it to another folder (with the size, an
2
+ // estimate and a warning first) and switching to a folder without moving. The work is in host/storage.
3
+ import fs from 'node:fs';
4
+ import path from 'node:path';
5
+ import { userConfigPath, userDir } from '../../../core/config/index.js';
6
+ import { diskUsage, humanBytes } from '../../../core/disk.js';
7
+ import { askChoice, askName, askRequired } from '../../../core/prompt.js';
8
+ import { expandPath, fail } from '../../../core/util/index.js';
9
+ import { describeDuration, describeSize, estimate, holdsData, measureFolder, mountedSets, moveWarning, otherDataFolders, sharedDefaultRoot, StorageHistory, StorageMove, } from '../../../host/storage/index.js';
10
+ import { isSandboxRunning } from '../../../host/sandbox/index.js';
11
+ import { protectPrivateFolder } from '../../../host/sharing/index.js';
12
+ import { watcherRunning } from '../../../sync/index.js';
13
+ import { printJson, working } from '../../output/index.js';
14
+ import { requireOnPc } from '../context.js';
15
+ import { contained } from './contained.js';
16
+ /** Why a move cannot start (a background sync is still on a data folder in the old storage), or null. */
17
+ export function storageBusy(root) {
18
+ const mounted = mountedSets(root);
19
+ if (mounted.length > 0)
20
+ return ('The contained storage of "' +
21
+ mounted.join('", "') +
22
+ '" is mounted (a disk image; moving now would reach into it).');
23
+ const data = path.join(root, 'data');
24
+ try {
25
+ for (const name of fs.readdirSync(data))
26
+ if (watcherRunning(path.join(data, name)))
27
+ return 'The background sync of "' + name + '" is still finishing.';
28
+ }
29
+ catch {
30
+ // no data folder: nothing runs
31
+ }
32
+ return null;
33
+ }
34
+ function mover(ctx) {
35
+ return new StorageMove(ctx.loaded.configPath ?? userConfigPath(), () => storageBusy(ctx.storageRoot), isSandboxRunning, protectPrivateFolder);
36
+ }
37
+ /** The path as typed (variables and ~ expand, relative to the current folder). */
38
+ function typedPath(value) {
39
+ return expandPath(value, process.cwd());
40
+ }
41
+ /** The folder typed, or picked from the default folder, folders that hold data and the drives (or typed in). */
42
+ async function folderOf(ctx, value, what) {
43
+ if (value)
44
+ return typedPath(value);
45
+ const fix = 'Use: sandbox storage ' + what + ' <folder>';
46
+ const typed = 'type';
47
+ const known = [sharedDefaultRoot(), ...otherDataFolders(ctx.storageRoot, new StorageHistory(userDir()))];
48
+ const drives = diskUsage(ctx.storageRoot)
49
+ .filter((d) => !d.holdsStorage)
50
+ .map((d) => path.join(d.drive, 'AgentSandbox'));
51
+ const choices = [...new Set([...known, ...drives])]
52
+ .filter((f) => f.toLowerCase() !== ctx.storageRoot.toLowerCase())
53
+ .map((f) => ({ name: f, value: f }));
54
+ const picked = await askChoice('Which folder?', [...choices, { name: 'Type a path...', value: typed }], fix);
55
+ if (picked !== typed)
56
+ return picked;
57
+ const answer = await askName('Folder:', fix, (v) => v.length > 0 || 'Type a folder path.');
58
+ return typedPath(answer);
59
+ }
60
+ async function show(ctx) {
61
+ const history = new StorageHistory(userDir());
62
+ const measured = await working('Measuring your saved data (big folders take a moment)', () => measureFolder(ctx.storageRoot), !ctx.options.json);
63
+ const others = otherDataFolders(ctx.storageRoot, history);
64
+ const shared = sharedDefaultRoot();
65
+ if (printJson(ctx, {
66
+ root: ctx.storageRoot,
67
+ exists: fs.existsSync(ctx.storageRoot),
68
+ ...measured,
69
+ defaultRoot: shared,
70
+ otherFoldersWithData: others,
71
+ }))
72
+ return 0;
73
+ const inUse = shared.toLowerCase() === ctx.storageRoot.toLowerCase() ? ' (in use)' : '';
74
+ console.log('Your saved data is in: ' + ctx.storageRoot);
75
+ console.log(' ' + (holdsData(ctx.storageRoot) ? describeSize(measured) : 'nothing in it yet'));
76
+ console.log('The default folder is: ' + shared + inUse);
77
+ for (const other of others)
78
+ console.log('Another folder with data: ' + other);
79
+ console.log('\nMove it with: sandbox storage move <folder> (or switch without moving: sandbox storage use <folder>)');
80
+ console.log('What takes the space: sandbox data');
81
+ return 0;
82
+ }
83
+ function printPlan(from, to, measured, copyOnly) {
84
+ const est = estimate(from, to, measured, copyOnly);
85
+ const time = est.sameVolume
86
+ ? 'a few seconds (same drive, nothing is copied)'
87
+ : describeDuration(est.seconds) + ' (copied to another drive)';
88
+ console.log('Move from: ' + from);
89
+ console.log(' to: ' + to);
90
+ console.log(' size: ' + describeSize(measured));
91
+ console.log(' time: ' + time);
92
+ const warning = moveWarning(measured, est);
93
+ if (warning)
94
+ console.log('Warning: ' + warning);
95
+ if (!est.fits)
96
+ fail('Not enough free space on the target drive.', 'Free some space or pick another drive.');
97
+ }
98
+ /** Moves the data with progress on the terminal; remembers both folders. Used by the command and the start offer. */
99
+ export async function performMove(ctx, to, keepOld) {
100
+ const from = ctx.storageRoot;
101
+ const history = new StorageHistory(userDir());
102
+ let line = 'Moving your data';
103
+ const result = await working(() => line, () => mover(ctx).move(from, to, {
104
+ keepOld,
105
+ onProgress: (p) => {
106
+ line = 'Copying: ' + p.files.toLocaleString('en-US') + ' files, ' + humanBytes(p.bytes);
107
+ },
108
+ }));
109
+ history.remember(from);
110
+ history.remember(to);
111
+ return result;
112
+ }
113
+ async function move(ctx) {
114
+ const to = await folderOf(ctx, ctx.options.positionals[1], 'move');
115
+ const from = ctx.storageRoot;
116
+ if (!fs.existsSync(from))
117
+ fail('There is nothing to move: ' + from + ' does not exist.', 'Use sandbox storage use ' + to + ' to switch.');
118
+ mover(ctx).validate(from, to);
119
+ const measured = await working('Measuring your saved data', () => measureFolder(from), !ctx.options.json);
120
+ const keepOld = ctx.options.keepOld;
121
+ printPlan(from, to, measured, keepOld);
122
+ if (!ctx.options.yes) {
123
+ if (!(await askRequired('Move your data to ' + to + '?', 'Add --yes to move without asking.', true))) {
124
+ console.log('Nothing was moved.');
125
+ return 1;
126
+ }
127
+ }
128
+ const result = await performMove(ctx, to, keepOld);
129
+ if (printJson(ctx, result))
130
+ return 0;
131
+ const left = result.removedOld ? '' : '; the old folder is still at ' + result.from;
132
+ console.log('Moved ' + result.files.toLocaleString('en-US') + ' files. Your data is now in ' + result.to + left + '.');
133
+ for (const note of result.notes)
134
+ console.log(note);
135
+ console.log('Your settings now point to ' + result.pinned + ', so older versions find the data too.');
136
+ return 0;
137
+ }
138
+ async function use(ctx) {
139
+ const to = await folderOf(ctx, ctx.options.positionals[1], 'use');
140
+ if (to.toLowerCase() === ctx.storageRoot.toLowerCase()) {
141
+ console.log('That folder is in use already.');
142
+ return 0;
143
+ }
144
+ const busy = storageBusy(ctx.storageRoot);
145
+ if (busy)
146
+ fail(busy, 'Wait a minute, then try again.');
147
+ const state = holdsData(to)
148
+ ? to + ' is used as it is.'
149
+ : to + ' starts empty: tools, logins and history are set up again.';
150
+ console.log('Warning: your data stays in ' + ctx.storageRoot + '. ' + state);
151
+ if (!ctx.options.yes) {
152
+ if (!(await askRequired('Use ' + to + ' from now on, without moving your data?', 'Add --yes to switch without asking.'))) {
153
+ console.log('Nothing was changed.');
154
+ return 1;
155
+ }
156
+ }
157
+ new StorageHistory(userDir()).remember(ctx.storageRoot);
158
+ mover(ctx).pin(to);
159
+ console.log('Your data is now looked for in ' + to + '. Move it later with: sandbox storage move <folder>');
160
+ return 0;
161
+ }
162
+ /** `sandbox storage [show|move <folder>|use <folder>]`. */
163
+ export function storage(ctx) {
164
+ requireOnPc('storage');
165
+ const [action = 'show'] = ctx.options.positionals;
166
+ switch (action) {
167
+ case 'show':
168
+ case 'info':
169
+ return show(ctx);
170
+ case 'move':
171
+ return move(ctx);
172
+ case 'use':
173
+ return use(ctx);
174
+ case 'contained':
175
+ return contained(ctx);
176
+ default:
177
+ return fail('Unknown storage action "' + action + '".', 'Use: sandbox storage, sandbox storage move <folder>, sandbox storage use <folder> or sandbox storage contained on|off|status');
178
+ }
179
+ }
@@ -6,7 +6,7 @@ import { parse } from 'jsonc-parser';
6
6
  import _ from 'lodash';
7
7
  import { userConfigPath } from '../../core/config/index.js';
8
8
  import { fail } from '../../core/util/index.js';
9
- import { editConfigText } from '../menu/settings/index.js';
9
+ import { editConfigText } from '../../app/features/settings/index.js';
10
10
  export function configFile(ctx) {
11
11
  return ctx.loaded.configPath ?? userConfigPath();
12
12
  }
@@ -21,7 +21,7 @@ export function setSetting(ctx, key, value) {
21
21
  const text = fs.existsSync(file) ? fs.readFileSync(file, 'utf8') : '';
22
22
  const result = editConfigText(text, key, value);
23
23
  if ('problems' in result)
24
- fail('Could not change ' + key.join('.') + ':\n ' + result.problems.join('\n '));
24
+ fail('Could not change ' + key.join('.') + ':\n ' + result.problems.join('\n '), 'Nothing was written. Fix the value, or the settings file: ' + file);
25
25
  fs.mkdirSync(path.dirname(file), { recursive: true });
26
26
  fs.writeFileSync(file, result.text, 'utf8');
27
27
  }
@@ -0,0 +1,4 @@
1
+ import { type Context } from './context.js';
2
+ /** The warnings every VPN user must see. */
3
+ export declare const VPN_WARNINGS: readonly string[];
4
+ export declare function vpn(ctx: Context): Promise<number> | number;
@@ -0,0 +1,91 @@
1
+ // `sandbox vpn [status|login|logout]`: the VPN login (kept encrypted on this PC, never printed) and what the VPN is
2
+ // doing.
3
+ import { askSecret } from '../../core/prompt.js';
4
+ import { fail } from '../../core/util/index.js';
5
+ import { c, nextStep, printJson, table } from '../output/index.js';
6
+ import { NORD_STEPS, VpnService } from '../services/vpn-service.js';
7
+ import { requireOnPc } from './context.js';
8
+ const LOGIN_TEXT = {
9
+ none: c.yellow('not saved'),
10
+ saved: c.green('saved (encrypted)'),
11
+ unreadable: c.red('cannot be read'),
12
+ };
13
+ /** The warnings every VPN user must see. */
14
+ export const VPN_WARNINGS = [
15
+ 'The agent in the sandbox can read the VPN login (a service login you can revoke) and can turn the tunnel off, because it is the administrator there.',
16
+ 'Free VPNs see all your traffic: use one you trust.',
17
+ ];
18
+ async function status(ctx) {
19
+ const report = await new VpnService(ctx).report();
20
+ if (printJson(ctx, report))
21
+ return 0;
22
+ table([
23
+ ['VPN', report.enabled ? c.green('on') : 'off (turn on: sandbox config set vpn.enabled true)'],
24
+ [
25
+ 'Provider',
26
+ report.provider === 'nordvpn'
27
+ ? 'NordVPN'
28
+ : report.provider === 'wireguard-file'
29
+ ? 'your own WireGuard .conf'
30
+ : 'your own .ovpn file',
31
+ ],
32
+ ['Protocol', report.protocol],
33
+ ['Country', report.country || 'best available'],
34
+ ['Kill switch', report.killSwitch ? 'on (no internet if the tunnel fails)' : c.yellow('off')],
35
+ [
36
+ 'Login',
37
+ report.provider === 'wireguard-file'
38
+ ? c.dim('not needed (the keys are in your config)')
39
+ : LOGIN_TEXT[report.login] + (report.loginSavedAt ? c.dim(' ' + report.loginSavedAt.slice(0, 10)) : ''),
40
+ ],
41
+ ...(report.running ? [['Running now', report.running.text]] : []),
42
+ ]);
43
+ if (report.provider !== 'wireguard-file' && report.login === 'none')
44
+ nextStep('sandbox vpn login');
45
+ if (report.login === 'unreadable')
46
+ console.log(c.dim('Only the Windows user that saved it can read it. Save it again: sandbox vpn login'));
47
+ for (const w of VPN_WARNINGS)
48
+ console.log(c.dim(w));
49
+ return 0;
50
+ }
51
+ async function login(ctx) {
52
+ requireOnPc('vpn login');
53
+ const service = new VpnService(ctx);
54
+ if (service.provider === 'wireguard-file') {
55
+ console.log('A WireGuard config needs no login: the keys are in the file vpn.configFile points to.');
56
+ return 0;
57
+ }
58
+ const nord = service.provider === 'nordvpn';
59
+ console.log(nord
60
+ ? 'NordVPN needs its service credentials, not your usual login. To get them:'
61
+ : 'Type the user name and password your VPN profile asks for.');
62
+ if (nord)
63
+ NORD_STEPS.forEach((s, i) => console.log(' ' + (i + 1) + '. ' + s));
64
+ console.log(c.dim('What you type is not shown. It is kept encrypted for your Windows user and never printed.\n'));
65
+ const fix = 'Run sandbox vpn login in a terminal.';
66
+ const username = await askSecret(nord ? 'Service user name' : 'User name', fix);
67
+ const password = await askSecret(nord ? 'Service password' : 'Password', fix);
68
+ service.save({ username, password });
69
+ console.log(c.green('Saved.') + ' Turn the VPN on with: sandbox config set vpn.enabled true');
70
+ for (const w of VPN_WARNINGS)
71
+ console.log(c.dim(w));
72
+ return 0;
73
+ }
74
+ function logout(ctx) {
75
+ requireOnPc('vpn logout');
76
+ console.log(new VpnService(ctx).remove() ? 'The saved VPN login is deleted.' : 'No VPN login was saved.');
77
+ return 0;
78
+ }
79
+ export function vpn(ctx) {
80
+ const action = ctx.options.positionals[0] ?? 'status';
81
+ switch (action) {
82
+ case 'status':
83
+ return status(ctx);
84
+ case 'login':
85
+ return login(ctx);
86
+ case 'logout':
87
+ return logout(ctx);
88
+ default:
89
+ return fail('Unknown VPN action "' + action + '".', 'Use: sandbox vpn status | login | logout');
90
+ }
91
+ }
@@ -0,0 +1,4 @@
1
+ import { type Context } from './context.js';
2
+ export declare function web(ctx: Context): Promise<number>;
3
+ /** Body of the background process (`sandbox _web`): runs until stopped. */
4
+ export declare function webServer(ctx: Context): Promise<void>;
@@ -0,0 +1,97 @@
1
+ // `sandbox web start | stop | status | open`: the web UI's server runs in the background (as `_web`, like the sync
2
+ // watcher) and keeps running when no sandbox does. The work is in host/web.
3
+ import fs from 'node:fs';
4
+ import path from 'node:path';
5
+ import { fail, sleep } from '../../core/util/index.js';
6
+ import { spawnDetached } from '../../host/sandbox/index.js';
7
+ import { openBrowser, WebControl, WebRunner, WebStore } from '../../host/web/index.js';
8
+ import { printJson } from '../output/index.js';
9
+ import { createRpcHost } from '../../app/registry.js';
10
+ import { WebService } from '../services/index.js';
11
+ import { requireOnPc } from './context.js';
12
+ const START_WAIT_MS = 15000;
13
+ function controlOf(ctx) {
14
+ return new WebControl(new WebStore(ctx.storageRoot));
15
+ }
16
+ /** Starts the background server (when it is not running) and waits until it answers. */
17
+ async function startServer(ctx, control) {
18
+ const before = await control.status();
19
+ if (before.running && before.state) {
20
+ console.log('The web UI is already running on port ' + before.state.port + '.');
21
+ return before.state.port;
22
+ }
23
+ if (before.state)
24
+ control.clear();
25
+ const { config } = ctx.loaded;
26
+ if (!config.web.enabled)
27
+ console.log('web.enabled is off: this starts the web UI for now only. Set it to true in Settings to keep it allowed.');
28
+ const configFile = ctx.options.config;
29
+ spawnDetached(ctx.entry, ['_web', ...(configFile ? ['--config', path.resolve(configFile)] : [])]);
30
+ for (const started = Date.now(); Date.now() - started < START_WAIT_MS; await sleep(300)) {
31
+ const now = await control.status();
32
+ if (now.running && now.state) {
33
+ console.log('The web UI is running at http://127.0.0.1:' + now.state.port + '/ (this PC only).');
34
+ console.log('Open it already signed in with: sandbox web open');
35
+ return now.state.port;
36
+ }
37
+ }
38
+ return fail('The web UI did not start.', 'Run sandbox _web to see why (the port ' + config.web.port + ' may be taken: change web.port).');
39
+ }
40
+ export async function web(ctx) {
41
+ requireOnPc('web');
42
+ const action = ctx.options.positionals[0] ?? 'status';
43
+ const control = controlOf(ctx);
44
+ switch (action) {
45
+ case 'start':
46
+ await startServer(ctx, control);
47
+ return 0;
48
+ case 'open': {
49
+ await startServer(ctx, control);
50
+ const { state } = await control.status();
51
+ if (!state)
52
+ return fail('The web UI stopped right away.', 'Run sandbox web start again.');
53
+ openBrowser(control.url(state));
54
+ console.log('Opened in your browser.');
55
+ return 0;
56
+ }
57
+ case 'stop': {
58
+ const { running, state } = await control.status();
59
+ if (!state) {
60
+ console.log('The web UI is not running.');
61
+ return 0;
62
+ }
63
+ if (!running || (await control.stop(state)))
64
+ control.clear();
65
+ else
66
+ return fail('The web UI did not stop.', 'End the process ' + state.pid + ' in Task Manager.');
67
+ console.log('The web UI stopped.');
68
+ return 0;
69
+ }
70
+ case 'status': {
71
+ const { running, state } = await control.status();
72
+ const port = running && state ? state.port : null;
73
+ if (printJson(ctx, { running, port, address: port ? 'http://127.0.0.1:' + port + '/' : null }))
74
+ return 0;
75
+ console.log(running && port
76
+ ? 'The web UI is running at http://127.0.0.1:' + port + '/ (sandbox web open signs you in).'
77
+ : 'The web UI is not running (sandbox web start).');
78
+ return 0;
79
+ }
80
+ default:
81
+ return fail('Unknown action "' + action + '".', 'Use start, stop, status or open.');
82
+ }
83
+ }
84
+ /** Body of the background process (`sandbox _web`): runs until stopped. */
85
+ export async function webServer(ctx) {
86
+ const staticRoot = path.join(ctx.packageRoot, 'dist', 'web');
87
+ if (!fs.existsSync(path.join(staticRoot, 'index.html')))
88
+ fail('The web app is not built (' + staticRoot + ').', 'Run npm run build in the install folder.');
89
+ await new WebRunner({
90
+ storageRoot: ctx.storageRoot,
91
+ port: ctx.loaded.config.web.port,
92
+ backend: new WebService(ctx),
93
+ rpc: createRpcHost(ctx),
94
+ staticRoot,
95
+ }).run();
96
+ process.exit(0);
97
+ }
@@ -7,7 +7,7 @@ const HistorySchema = z.array(z.strictObject({ argv: z.array(z.string()).max(200
7
7
  function historyFile() {
8
8
  return new JsonFile(HistorySchema, path.join(userDir(), 'history.json'));
9
9
  }
10
- const HIDDEN = new Set(['menu', '_watch', 'self-test']);
10
+ const HIDDEN = new Set(['menu', '_watch', '_web', 'self-test']);
11
11
  export function readHistory() {
12
12
  return historyFile().read() ?? [];
13
13
  }
package/dist/cli/index.js CHANGED
@@ -1,18 +1,40 @@
1
1
  import path from 'node:path';
2
2
  import { buildProgram, parseCli } from './args.js';
3
- import { commandSpec } from './manifest.js';
3
+ import { COMMANDS, commandSpec } from './manifest.js';
4
4
  import { recordHistory } from './history.js';
5
5
  import { menu } from './menu/index.js';
6
- import { validateOptions } from './validate.js';
6
+ import { closest, validateOptions } from './validate.js';
7
7
  import { loadConfig } from '../core/config/index.js';
8
8
  import * as commands from './commands/index.js';
9
9
  import { fail } from '../core/util/index.js';
10
- import { PACKAGE_ROOT } from '../core/package-info.js';
10
+ import { PACKAGE_ROOT, packageVersion } from '../core/package-info.js';
11
+ import { takeHiddenInstallNotice } from '../host/install/index.js';
12
+ import { c } from './output/index.js';
11
13
  import { dropInheritedModulePath } from '../shared/system.js';
12
14
  import { withConfig, hoistConfig, withoutConfig } from './argv.js';
13
15
  import { report } from './report.js';
16
+ import { versionText } from './version.js';
14
17
  import { HANDLERS } from './commands/index.js';
18
+ import { operationHandler } from './operations/index.js';
15
19
  const entry = path.join(PACKAGE_ROOT, 'dist', 'bin', 'agent-sandbox.js');
20
+ /** A first word that is no command and no agent, but close to one: "Did you mean: sandbox status?". */
21
+ function failOnTypo(word, agents) {
22
+ const names = [...COMMANDS.filter((c) => !c.hidden).map((c) => c.name), ...agents];
23
+ const hint = closest(word, names);
24
+ if (hint)
25
+ fail('Unknown command "' + word + '". Did you mean: sandbox ' + hint + '?', 'Run sandbox --help for the list of commands, or sandbox for the menu.');
26
+ }
27
+ /** One yellow line, once per version, when this is not the managed install but one exists (it is hidden). */
28
+ function hiddenInstallNotice(storageRoot) {
29
+ try {
30
+ const line = takeHiddenInstallNotice(storageRoot, PACKAGE_ROOT, packageVersion());
31
+ if (line)
32
+ console.log(c.yellow(line));
33
+ }
34
+ catch {
35
+ // A note that cannot be saved is not worth stopping a start for.
36
+ }
37
+ }
16
38
  /** Runs an argv from the menu exactly as if it had been typed, reporting errors instead of throwing. */
17
39
  const runFromMenu = (config) => (argv) => main(withConfig(argv, config)).catch((e) => report(e));
18
40
  /**
@@ -33,10 +55,27 @@ export async function main(rawArgv, preset = {}) {
33
55
  }
34
56
  };
35
57
  if (!preset.command && !preset.harness) {
58
+ const version = versionText(withoutConfig(argv), PACKAGE_ROOT);
59
+ if (version !== null) {
60
+ console.log(version);
61
+ return 0;
62
+ }
36
63
  if (argv.length === 0)
37
64
  return process.stdin.isTTY ? main(['menu']) : (buildProgram(() => undefined).outputHelp(), 0);
38
65
  if (isAgent(argv[0]))
39
66
  return main(argv.slice(1), { harness: argv[0] });
67
+ const first = argv.slice(0, 1)[0];
68
+ if (first && !first.startsWith('-') && !commandSpec(first) && first !== 'help') {
69
+ const at = argv.indexOf('--config');
70
+ let agents = [];
71
+ try {
72
+ agents = Object.keys(loadConfig(at >= 0 ? argv[at + 1] : undefined).config.harnesses);
73
+ }
74
+ catch {
75
+ // A broken settings file: the commands alone are suggested.
76
+ }
77
+ failOnTypo(first, agents);
78
+ }
40
79
  }
41
80
  const options = parseCli(preset.command ? [preset.command, ...argv] : argv, Boolean(preset.harness));
42
81
  if (preset.harness)
@@ -48,8 +87,10 @@ export async function main(rawArgv, preset = {}) {
48
87
  : argv;
49
88
  if (options.command === 'menu') {
50
89
  const menuCtx = commands.createContext(PACKAGE_ROOT, entry, options);
90
+ hiddenInstallNotice(menuCtx.storageRoot);
51
91
  await commands.migrateBeforeCommand(menuCtx, options.command);
52
92
  commands.updatesBeforeCommand(entry, options.command);
93
+ await commands.storageBeforeCommand(menuCtx, options.command);
53
94
  return menu(menuCtx, runFromMenu(options.config));
54
95
  }
55
96
  // Loaded only when asked for: normal commands never load test code.
@@ -63,13 +104,16 @@ export async function main(rawArgv, preset = {}) {
63
104
  // update works on the install, not on a sandbox: it needs no settings (and a broken file must not stop it).
64
105
  if (options.command === 'update')
65
106
  return commands.update(options);
66
- const handler = HANDLERS[options.command];
107
+ const handler = operationHandler(options.command, options.positionals) ?? HANDLERS[options.command];
67
108
  if (!handler)
68
109
  return fail('Unknown command "' + options.command + '".', 'Run sandbox --help for the list of commands, or sandbox for the menu.');
69
110
  const ctx = commands.createContext(PACKAGE_ROOT, entry, options);
70
111
  validateOptions(ctx);
112
+ if (options.command === 'launch')
113
+ hiddenInstallNotice(ctx.storageRoot);
71
114
  await commands.migrateBeforeCommand(ctx, options.command);
72
115
  commands.updatesBeforeCommand(entry, options.command);
116
+ await commands.storageBeforeCommand(ctx, options.command);
73
117
  // Only what parsed and validated is offered again by the menu, without the --config (it is the same every time).
74
118
  recordHistory(withoutConfig(typed));
75
119
  return (await handler(ctx)) ?? 0;