windows-development-sandbox 1.5.0 → 1.7.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 (448) hide show
  1. package/README.md +1 -0
  2. package/config.example.json +17 -1
  3. package/dist/cli/args.d.ts +13 -2
  4. package/dist/cli/args.js +95 -24
  5. package/dist/cli/commands/accounts.js +45 -17
  6. package/dist/cli/commands/context.d.ts +2 -0
  7. package/dist/cli/commands/context.js +9 -2
  8. package/dist/cli/commands/data/clean.js +32 -9
  9. package/dist/cli/commands/index.d.ts +1 -0
  10. package/dist/cli/commands/index.js +1 -0
  11. package/dist/cli/commands/launch/add-root.d.ts +3 -2
  12. package/dist/cli/commands/launch/add-root.js +11 -10
  13. package/dist/cli/commands/launch/launch.js +57 -4
  14. package/dist/cli/commands/launch/prepare.js +3 -1
  15. package/dist/cli/commands/maintenance/audit.js +1 -1
  16. package/dist/cli/commands/maintenance/clean.d.ts +1 -1
  17. package/dist/cli/commands/maintenance/clean.js +17 -3
  18. package/dist/cli/commands/maintenance/config.d.ts +1 -1
  19. package/dist/cli/commands/maintenance/config.js +112 -10
  20. package/dist/cli/commands/maintenance/doctor.d.ts +1 -1
  21. package/dist/cli/commands/maintenance/doctor.js +2 -4
  22. package/dist/cli/commands/maintenance/migrate.d.ts +2 -1
  23. package/dist/cli/commands/maintenance/migrate.js +19 -4
  24. package/dist/cli/commands/maintenance/sync.js +2 -0
  25. package/dist/cli/commands/maintenance/update.d.ts +2 -0
  26. package/dist/cli/commands/maintenance/update.js +27 -4
  27. package/dist/cli/commands/projects/here.js +12 -7
  28. package/dist/cli/commands/projects/projects.js +26 -17
  29. package/dist/cli/commands/registry.js +7 -0
  30. package/dist/cli/commands/repair/checks/agents.d.ts +2 -0
  31. package/dist/cli/commands/repair/checks/agents.js +70 -0
  32. package/dist/cli/commands/repair/checks/common.d.ts +8 -0
  33. package/dist/cli/commands/repair/checks/common.js +22 -0
  34. package/dist/cli/commands/repair/checks/data.d.ts +2 -0
  35. package/dist/cli/commands/repair/checks/data.js +241 -0
  36. package/dist/cli/commands/repair/checks/index.d.ts +2 -0
  37. package/dist/cli/commands/repair/checks/index.js +20 -0
  38. package/dist/cli/commands/repair/checks/install.d.ts +5 -0
  39. package/dist/cli/commands/repair/checks/install.js +318 -0
  40. package/dist/cli/commands/repair/checks/machine.d.ts +2 -0
  41. package/dist/cli/commands/repair/checks/machine.js +232 -0
  42. package/dist/cli/commands/repair/checks/network.d.ts +6 -0
  43. package/dist/cli/commands/repair/checks/network.js +60 -0
  44. package/dist/cli/commands/repair/checks/pc.d.ts +4 -0
  45. package/dist/cli/commands/repair/checks/pc.js +55 -0
  46. package/dist/cli/commands/repair/checks/sandbox.d.ts +2 -0
  47. package/dist/cli/commands/repair/checks/sandbox.js +267 -0
  48. package/dist/cli/commands/repair/checks/settings.d.ts +2 -0
  49. package/dist/cli/commands/repair/checks/settings.js +169 -0
  50. package/dist/cli/commands/repair/checks/vpn.d.ts +2 -0
  51. package/dist/cli/commands/repair/checks/vpn.js +53 -0
  52. package/dist/cli/commands/repair/engine.d.ts +32 -0
  53. package/dist/cli/commands/repair/engine.js +127 -0
  54. package/dist/cli/commands/repair/env.d.ts +7 -0
  55. package/dist/cli/commands/repair/env.js +49 -0
  56. package/dist/cli/commands/repair/index.d.ts +1 -9
  57. package/dist/cli/commands/repair/index.js +2 -54
  58. package/dist/cli/commands/repair/log.d.ts +17 -0
  59. package/dist/cli/commands/repair/log.js +82 -0
  60. package/dist/cli/commands/repair/printer.d.ts +32 -0
  61. package/dist/cli/commands/repair/printer.js +132 -0
  62. package/dist/cli/commands/repair/run.d.ts +33 -0
  63. package/dist/cli/commands/repair/run.js +133 -0
  64. package/dist/cli/commands/repair/types.d.ts +97 -9
  65. package/dist/cli/commands/repair/types.js +11 -7
  66. package/dist/cli/commands/resume.js +2 -2
  67. package/dist/cli/commands/sessions/list.js +5 -2
  68. package/dist/cli/commands/sessions/status.d.ts +2 -0
  69. package/dist/cli/commands/sessions/status.js +27 -6
  70. package/dist/cli/commands/setup/index.d.ts +5 -0
  71. package/dist/cli/commands/setup/index.js +25 -1
  72. package/dist/cli/commands/storage/index.d.ts +2 -0
  73. package/dist/cli/commands/storage/index.js +2 -0
  74. package/dist/cli/commands/storage/offer.d.ts +3 -0
  75. package/dist/cli/commands/storage/offer.js +85 -0
  76. package/dist/cli/commands/storage/storage.d.ts +8 -0
  77. package/dist/cli/commands/storage/storage.js +171 -0
  78. package/dist/cli/commands/user-config.js +1 -1
  79. package/dist/cli/commands/vpn.d.ts +4 -0
  80. package/dist/cli/commands/vpn.js +75 -0
  81. package/dist/cli/commands/web.d.ts +4 -0
  82. package/dist/cli/commands/web.js +95 -0
  83. package/dist/cli/history.js +1 -1
  84. package/dist/cli/index.js +46 -3
  85. package/dist/cli/manifest.d.ts +303 -29
  86. package/dist/cli/manifest.js +173 -43
  87. package/dist/cli/menu/add-agent.d.ts +47 -0
  88. package/dist/cli/menu/add-agent.js +168 -0
  89. package/dist/cli/menu/apps.d.ts +31 -2
  90. package/dist/cli/menu/apps.js +44 -5
  91. package/dist/cli/menu/command-fields.d.ts +18 -0
  92. package/dist/cli/menu/command-fields.js +61 -0
  93. package/dist/cli/menu/command-form.d.ts +22 -0
  94. package/dist/cli/menu/command-form.js +169 -46
  95. package/dist/cli/menu/data-folder.d.ts +18 -0
  96. package/dist/cli/menu/data-folder.js +99 -0
  97. package/dist/cli/menu/menu.d.ts +1 -1
  98. package/dist/cli/menu/menu.js +11 -8
  99. package/dist/cli/menu/pages/accounts-page.js +55 -24
  100. package/dist/cli/menu/pages/agents-page.d.ts +66 -0
  101. package/dist/cli/menu/pages/agents-page.js +338 -0
  102. package/dist/cli/menu/pages/apps-page.js +1 -2
  103. package/dist/cli/menu/pages/list-page.d.ts +16 -3
  104. package/dist/cli/menu/pages/list-page.js +40 -8
  105. package/dist/cli/menu/pages/maintenance-page.d.ts +9 -0
  106. package/dist/cli/menu/pages/maintenance-page.js +161 -72
  107. package/dist/cli/menu/pages/sandbox-page.d.ts +3 -0
  108. package/dist/cli/menu/pages/sandbox-page.js +132 -43
  109. package/dist/cli/menu/pages/sessions-page.d.ts +4 -0
  110. package/dist/cli/menu/pages/sessions-page.js +41 -25
  111. package/dist/cli/menu/pages/settings-page.d.ts +8 -4
  112. package/dist/cli/menu/pages/settings-page.js +36 -13
  113. package/dist/cli/menu/settings/categories.d.ts +2 -0
  114. package/dist/cli/menu/settings/categories.js +19 -44
  115. package/dist/cli/menu/settings/collections/collection-editor.d.ts +7 -1
  116. package/dist/cli/menu/settings/collections/collection-editor.js +12 -8
  117. package/dist/cli/menu/settings/collections/map-editor.js +5 -1
  118. package/dist/cli/menu/settings/collections/object-list-editor.js +2 -2
  119. package/dist/cli/menu/settings/collections/object-map-editor.js +2 -2
  120. package/dist/cli/menu/settings/collections/string-list-editor.d.ts +11 -1
  121. package/dist/cli/menu/settings/collections/string-list-editor.js +23 -0
  122. package/dist/cli/menu/settings/index.d.ts +1 -1
  123. package/dist/cli/menu/settings/index.js +1 -1
  124. package/dist/cli/menu/settings/object-editor.d.ts +5 -1
  125. package/dist/cli/menu/settings/object-editor.js +15 -4
  126. package/dist/cli/menu/settings/path-kind.d.ts +20 -0
  127. package/dist/cli/menu/settings/path-kind.js +44 -0
  128. package/dist/cli/menu/settings/schema-node.d.ts +9 -0
  129. package/dist/cli/menu/settings/schema-node.js +26 -0
  130. package/dist/cli/menu/settings/value-editor.d.ts +5 -0
  131. package/dist/cli/menu/settings/value-editor.js +51 -18
  132. package/dist/cli/menu/several.js +7 -5
  133. package/dist/cli/menu/shell.d.ts +37 -10
  134. package/dist/cli/menu/shell.js +90 -10
  135. package/dist/cli/menu/vpn-login.d.ts +16 -0
  136. package/dist/cli/menu/vpn-login.js +66 -0
  137. package/dist/cli/output/print.d.ts +2 -0
  138. package/dist/cli/output/print.js +8 -1
  139. package/dist/cli/services/accounts-service.d.ts +2 -0
  140. package/dist/cli/services/accounts-service.js +2 -2
  141. package/dist/cli/services/health-service.d.ts +0 -6
  142. package/dist/cli/services/health-service.js +5 -42
  143. package/dist/cli/services/index.d.ts +3 -1
  144. package/dist/cli/services/index.js +3 -1
  145. package/dist/cli/services/migrate-service.js +1 -1
  146. package/dist/cli/services/update-service.d.ts +2 -0
  147. package/dist/cli/services/update-service.js +13 -6
  148. package/dist/cli/services/vpn-service.d.ts +28 -0
  149. package/dist/cli/services/vpn-service.js +46 -0
  150. package/dist/cli/services/web-service.d.ts +22 -0
  151. package/dist/cli/services/web-service.js +111 -0
  152. package/dist/cli/tui/app.d.ts +6 -3
  153. package/dist/cli/tui/app.js +12 -5
  154. package/dist/cli/tui/dialogs/path-listing.d.ts +43 -0
  155. package/dist/cli/tui/dialogs/path-listing.js +127 -0
  156. package/dist/cli/tui/dialogs/path-picker.d.ts +67 -0
  157. package/dist/cli/tui/dialogs/path-picker.js +423 -0
  158. package/dist/cli/tui/dialogs/text-screen.d.ts +6 -0
  159. package/dist/cli/tui/dialogs/text-screen.js +10 -3
  160. package/dist/cli/tui/frame.d.ts +7 -10
  161. package/dist/cli/tui/frame.js +19 -10
  162. package/dist/cli/tui/index.d.ts +4 -3
  163. package/dist/cli/tui/index.js +2 -1
  164. package/dist/cli/tui/list/list-screen.d.ts +14 -2
  165. package/dist/cli/tui/list/list-screen.js +68 -32
  166. package/dist/cli/tui/list/list-types.d.ts +8 -4
  167. package/dist/cli/tui/nav.d.ts +29 -0
  168. package/dist/cli/tui/nav.js +67 -0
  169. package/dist/cli/validate.d.ts +1 -1
  170. package/dist/cli/validate.js +3 -3
  171. package/dist/cli/version.d.ts +2 -0
  172. package/dist/cli/version.js +11 -0
  173. package/dist/core/config/defaults.js +5 -1
  174. package/dist/core/config/loader.js +12 -2
  175. package/dist/core/local-config/overrides.js +1 -0
  176. package/dist/core/prompt.d.ts +19 -0
  177. package/dist/core/prompt.js +43 -3
  178. package/dist/core/schema/common.d.ts +6 -0
  179. package/dist/core/schema/common.js +8 -0
  180. package/dist/core/schema/config.d.ts +23 -0
  181. package/dist/core/schema/config.js +10 -1
  182. package/dist/core/schema/harness.d.ts +1 -0
  183. package/dist/core/schema/harness.js +8 -2
  184. package/dist/core/schema/index.d.ts +3 -1
  185. package/dist/core/schema/index.js +3 -1
  186. package/dist/core/schema/profile.d.ts +1 -0
  187. package/dist/core/schema/profile.js +3 -0
  188. package/dist/core/schema/redact.d.ts +13 -0
  189. package/dist/core/schema/redact.js +75 -0
  190. package/dist/core/schema/sandbox.js +1 -0
  191. package/dist/core/schema/vpn.d.ts +17 -0
  192. package/dist/core/schema/vpn.js +22 -0
  193. package/dist/core/schema/web.d.ts +6 -0
  194. package/dist/core/schema/web.js +14 -0
  195. package/dist/core/types.d.ts +26 -0
  196. package/dist/guest/agents/agent-files.d.ts +49 -0
  197. package/dist/guest/agents/agent-files.js +63 -0
  198. package/dist/guest/agents/agent-installer.js +2 -9
  199. package/dist/guest/agents/local-state.d.ts +12 -0
  200. package/dist/guest/agents/local-state.js +198 -0
  201. package/dist/guest/agents/sbx-agent.d.ts +2 -0
  202. package/dist/guest/agents/sbx-agent.js +35 -0
  203. package/dist/guest/boot/boot.d.ts +4 -0
  204. package/dist/guest/boot/boot.js +50 -11
  205. package/dist/guest/daemon/daemon.js +4 -1
  206. package/dist/guest/daemon/exec.js +2 -1
  207. package/dist/guest/daemon/idle-shutdown.js +2 -0
  208. package/dist/guest/daemon/sessions.js +4 -1
  209. package/dist/guest/entries/agent.d.ts +1 -0
  210. package/dist/guest/entries/agent.js +10 -0
  211. package/dist/guest/entries/daemon.js +2 -0
  212. package/dist/guest/runtime/csc.d.ts +1 -0
  213. package/dist/guest/runtime/csc.js +1 -0
  214. package/dist/guest/runtime/secrets.d.ts +12 -0
  215. package/dist/guest/runtime/secrets.js +63 -0
  216. package/dist/guest/setup/claude-profile.d.ts +2 -1
  217. package/dist/guest/setup/claude-profile.js +12 -1
  218. package/dist/guest/setup/environment.d.ts +6 -0
  219. package/dist/guest/setup/environment.js +56 -6
  220. package/dist/guest/setup/path-plan.d.ts +32 -0
  221. package/dist/guest/setup/path-plan.js +67 -0
  222. package/dist/guest/setup/shell-path.d.ts +1 -0
  223. package/dist/guest/setup/shell-path.js +22 -0
  224. package/dist/guest/toolchains/languages/python.js +1 -1
  225. package/dist/guest/toolchains/runtimes.js +2 -2
  226. package/dist/guest/vpn/index.d.ts +1 -0
  227. package/dist/guest/vpn/index.js +1 -0
  228. package/dist/guest/vpn/openvpn.d.ts +9 -0
  229. package/dist/guest/vpn/openvpn.js +47 -0
  230. package/dist/guest/vpn/tunnel.d.ts +17 -0
  231. package/dist/guest/vpn/tunnel.js +78 -0
  232. package/dist/guest/vpn/vpn.d.ts +6 -0
  233. package/dist/guest/vpn/vpn.js +126 -0
  234. package/dist/host/channel/attach.d.ts +3 -1
  235. package/dist/host/channel/attach.js +1 -1
  236. package/dist/host/channel/channel.d.ts +7 -0
  237. package/dist/host/channel/channel.js +26 -2
  238. package/dist/host/health/acl-read.d.ts +17 -0
  239. package/dist/host/health/acl-read.js +45 -0
  240. package/dist/host/health/config-backup.d.ts +11 -0
  241. package/dist/host/health/config-backup.js +73 -0
  242. package/dist/host/health/index.d.ts +6 -0
  243. package/dist/host/health/index.js +7 -0
  244. package/dist/host/health/install-state.d.ts +33 -0
  245. package/dist/host/health/install-state.js +110 -0
  246. package/dist/host/health/path-copies.d.ts +32 -0
  247. package/dist/host/health/path-copies.js +82 -0
  248. package/dist/host/health/stale.d.ts +45 -0
  249. package/dist/host/health/stale.js +120 -0
  250. package/dist/host/health/system.d.ts +37 -0
  251. package/dist/host/health/system.js +87 -0
  252. package/dist/host/install/copies.d.ts +13 -0
  253. package/dist/host/install/copies.js +63 -0
  254. package/dist/host/install/index.d.ts +1 -0
  255. package/dist/host/install/index.js +1 -0
  256. package/dist/host/launch/generate.js +25 -1
  257. package/dist/host/launch/session-file.js +4 -1
  258. package/dist/host/launch/stage.js +1 -1
  259. package/dist/host/migrate/backup.js +3 -0
  260. package/dist/host/migrate/migrations/config-file.d.ts +2 -0
  261. package/dist/host/migrate/migrations/config-file.js +7 -0
  262. package/dist/host/migrate/migrations/follow-machine-storage.js +9 -1
  263. package/dist/host/migrate/migrations/pin-storage-root.d.ts +4 -0
  264. package/dist/host/migrate/migrations/pin-storage-root.js +46 -0
  265. package/dist/host/migrate/migrations/unpin-config-defaults.js +4 -1
  266. package/dist/host/migrate/registry.js +2 -1
  267. package/dist/host/profile/accounts.d.ts +25 -1
  268. package/dist/host/profile/accounts.js +96 -13
  269. package/dist/host/profile/agent-accounts.d.ts +5 -1
  270. package/dist/host/profile/agent-accounts.js +35 -5
  271. package/dist/host/profile/index.d.ts +2 -1
  272. package/dist/host/profile/index.js +1 -0
  273. package/dist/host/profile/plugin-share.d.ts +26 -0
  274. package/dist/host/profile/plugin-share.js +146 -0
  275. package/dist/host/projects/join.d.ts +7 -1
  276. package/dist/host/projects/join.js +21 -4
  277. package/dist/host/projects/registry.d.ts +16 -10
  278. package/dist/host/projects/registry.js +74 -6
  279. package/dist/host/sandbox/platform.d.ts +2 -0
  280. package/dist/host/sandbox/platform.js +21 -2
  281. package/dist/host/secrets/index.d.ts +2 -0
  282. package/dist/host/secrets/index.js +2 -0
  283. package/dist/host/secrets/launch-secrets.d.ts +17 -0
  284. package/dist/host/secrets/launch-secrets.js +93 -0
  285. package/dist/host/secrets/secret-store.d.ts +25 -0
  286. package/dist/host/secrets/secret-store.js +89 -0
  287. package/dist/host/sharing/acl.d.ts +16 -2
  288. package/dist/host/sharing/acl.js +35 -10
  289. package/dist/host/sharing/current.js +11 -2
  290. package/dist/host/sharing/doctor.d.ts +2 -0
  291. package/dist/host/sharing/doctor.js +44 -0
  292. package/dist/host/sharing/group-access.d.ts +6 -0
  293. package/dist/host/sharing/group-access.js +24 -0
  294. package/dist/host/sharing/index.d.ts +2 -1
  295. package/dist/host/sharing/index.js +2 -1
  296. package/dist/host/sharing/lifecycle.d.ts +8 -2
  297. package/dist/host/sharing/lifecycle.js +16 -7
  298. package/dist/host/storage/cleanup.d.ts +2 -0
  299. package/dist/host/storage/cleanup.js +2 -1
  300. package/dist/host/storage/history.d.ts +21 -0
  301. package/dist/host/storage/history.js +49 -0
  302. package/dist/host/storage/index.d.ts +4 -0
  303. package/dist/host/storage/index.js +4 -0
  304. package/dist/host/storage/move.d.ts +95 -0
  305. package/dist/host/storage/move.js +384 -0
  306. package/dist/host/storage/offer.d.ts +11 -0
  307. package/dist/host/storage/offer.js +36 -0
  308. package/dist/host/storage/root.d.ts +18 -0
  309. package/dist/host/storage/root.js +77 -0
  310. package/dist/host/tools/windows-terminal.d.ts +2 -0
  311. package/dist/host/tools/windows-terminal.js +23 -5
  312. package/dist/host/update/index.d.ts +1 -1
  313. package/dist/host/update/index.js +1 -1
  314. package/dist/host/update/notice.d.ts +2 -0
  315. package/dist/host/update/notice.js +13 -1
  316. package/dist/host/update/update-state.d.ts +6 -0
  317. package/dist/host/update/update-state.js +2 -0
  318. package/dist/host/update/updater.d.ts +19 -0
  319. package/dist/host/update/updater.js +88 -12
  320. package/dist/host/vpn/index.d.ts +4 -0
  321. package/dist/host/vpn/index.js +4 -0
  322. package/dist/host/vpn/login.d.ts +24 -0
  323. package/dist/host/vpn/login.js +79 -0
  324. package/dist/host/vpn/nordvpn.d.ts +21 -0
  325. package/dist/host/vpn/nordvpn.js +77 -0
  326. package/dist/host/vpn/prepare.d.ts +17 -0
  327. package/dist/host/vpn/prepare.js +77 -0
  328. package/dist/host/vpn/status.d.ts +12 -0
  329. package/dist/host/vpn/status.js +53 -0
  330. package/dist/host/web/auth.d.ts +38 -0
  331. package/dist/host/web/auth.js +96 -0
  332. package/dist/host/web/backend.d.ts +14 -0
  333. package/dist/host/web/backend.js +1 -0
  334. package/dist/host/web/bridge.d.ts +27 -0
  335. package/dist/host/web/bridge.js +144 -0
  336. package/dist/host/web/browser.d.ts +1 -0
  337. package/dist/host/web/browser.js +10 -0
  338. package/dist/host/web/control.d.ts +17 -0
  339. package/dist/host/web/control.js +67 -0
  340. package/dist/host/web/index.d.ts +9 -0
  341. package/dist/host/web/index.js +8 -0
  342. package/dist/host/web/runner.d.ts +14 -0
  343. package/dist/host/web/runner.js +45 -0
  344. package/dist/host/web/server.d.ts +40 -0
  345. package/dist/host/web/server.js +218 -0
  346. package/dist/host/web/state.d.ts +20 -0
  347. package/dist/host/web/state.js +41 -0
  348. package/dist/host/web/static-files.d.ts +13 -0
  349. package/dist/host/web/static-files.js +57 -0
  350. package/dist/runtime/agent.js +27614 -0
  351. package/dist/runtime/daemon.js +1012 -618
  352. package/dist/runtime/db.js +236 -106
  353. package/dist/runtime/main.js +1093 -250
  354. package/dist/runtime/netproxy.js +102 -3
  355. package/dist/runtime/view.js +102 -3
  356. package/dist/selftest/accounts.test.js +40 -0
  357. package/dist/selftest/agent-paths.test.d.ts +2 -0
  358. package/dist/selftest/agent-paths.test.js +115 -0
  359. package/dist/selftest/channel.test.js +5 -0
  360. package/dist/selftest/cli.test.js +34 -4
  361. package/dist/selftest/credentials.test.d.ts +2 -0
  362. package/dist/selftest/credentials.test.js +198 -0
  363. package/dist/selftest/generate.test.js +1 -1
  364. package/dist/selftest/health.test.d.ts +2 -0
  365. package/dist/selftest/health.test.js +470 -0
  366. package/dist/selftest/host-sim.test.js +2 -0
  367. package/dist/selftest/index.js +19 -0
  368. package/dist/selftest/layout.test.js +2 -0
  369. package/dist/selftest/menu-screens.d.ts +7 -0
  370. package/dist/selftest/menu-screens.js +65 -16
  371. package/dist/selftest/menu.test.js +574 -21
  372. package/dist/selftest/migrate.test.js +1 -1
  373. package/dist/selftest/personalization.test.js +3 -1
  374. package/dist/selftest/projects.test.js +39 -1
  375. package/dist/selftest/shared-use.test.js +64 -2
  376. package/dist/selftest/sharing.test.js +50 -1
  377. package/dist/selftest/storage.test.d.ts +2 -0
  378. package/dist/selftest/storage.test.js +363 -0
  379. package/dist/selftest/support/fixtures.d.ts +14 -0
  380. package/dist/selftest/support/releases.js +1 -1
  381. package/dist/selftest/toolchains.test.js +21 -0
  382. package/dist/selftest/update-service.test.js +87 -3
  383. package/dist/selftest/vpn.test.d.ts +2 -0
  384. package/dist/selftest/vpn.test.js +279 -0
  385. package/dist/selftest/web.test.d.ts +2 -0
  386. package/dist/selftest/web.test.js +304 -0
  387. package/dist/shared/apps/catalogue.js +31 -0
  388. package/dist/shared/channel/index.d.ts +1 -0
  389. package/dist/shared/channel/index.js +1 -0
  390. package/dist/shared/channel/run-dir.d.ts +6 -1
  391. package/dist/shared/channel/run-dir.js +12 -1
  392. package/dist/shared/channel/schema.d.ts +19 -0
  393. package/dist/shared/channel/schema.js +11 -0
  394. package/dist/shared/channel/secrets.d.ts +28 -0
  395. package/dist/shared/channel/secrets.js +44 -0
  396. package/dist/shared/vpn/download.d.ts +13 -0
  397. package/dist/shared/vpn/download.js +14 -0
  398. package/dist/shared/vpn/kill-switch.d.ts +18 -0
  399. package/dist/shared/vpn/kill-switch.js +81 -0
  400. package/dist/shared/vpn/ovpn.d.ts +23 -0
  401. package/dist/shared/vpn/ovpn.js +244 -0
  402. package/dist/shared/web/index.d.ts +1 -0
  403. package/dist/shared/web/index.js +1 -0
  404. package/dist/shared/web/protocol.d.ts +61 -0
  405. package/dist/shared/web/protocol.js +35 -0
  406. package/dist/sync/sync-cycle.js +5 -1
  407. package/dist/sync/sync-state.d.ts +1 -0
  408. package/dist/sync/sync-state.js +1 -0
  409. package/dist/sync/watcher.js +10 -0
  410. package/dist/web/index.html +13 -0
  411. package/dist/web/main-CXESL347.js +45 -0
  412. package/dist/web/main-VLR7DVQ4.css +1 -0
  413. package/native/csharp/FolderSecurity.cs +29 -0
  414. package/native/scripts/protect-data.ps1 +29 -0
  415. package/native/scripts/read-folder-sddl.ps1 +10 -0
  416. package/native/scripts/set-folder-access.ps1 +49 -7
  417. package/node_modules/ws/LICENSE +20 -0
  418. package/node_modules/ws/README.md +548 -0
  419. package/node_modules/ws/browser.js +8 -0
  420. package/node_modules/ws/index.js +22 -0
  421. package/node_modules/ws/lib/buffer-util.js +131 -0
  422. package/node_modules/ws/lib/constants.js +19 -0
  423. package/node_modules/ws/lib/event-target.js +292 -0
  424. package/node_modules/ws/lib/extension.js +203 -0
  425. package/node_modules/ws/lib/limiter.js +55 -0
  426. package/node_modules/ws/lib/permessage-deflate.js +530 -0
  427. package/node_modules/ws/lib/receiver.js +743 -0
  428. package/node_modules/ws/lib/sender.js +607 -0
  429. package/node_modules/ws/lib/stream.js +161 -0
  430. package/node_modules/ws/lib/subprotocol.js +62 -0
  431. package/node_modules/ws/lib/validation.js +152 -0
  432. package/node_modules/ws/lib/websocket-server.js +562 -0
  433. package/node_modules/ws/lib/websocket.js +1421 -0
  434. package/node_modules/ws/package.json +74 -0
  435. package/node_modules/ws/wrapper.mjs +21 -0
  436. package/package.json +15 -5
  437. package/sandbox/csharp/EnvBroadcast.cs +33 -0
  438. package/sandbox/csharp/PathSync.cs +90 -0
  439. package/sandbox/scripts/install-shell-path.ps1 +73 -0
  440. package/sandbox/scripts/set-machine-environment.ps1 +37 -4
  441. package/schemas/config.schema.json +79 -4
  442. package/schemas/sandbox-config.schema.json +14 -1
  443. package/dist/cli/commands/repair/checks.d.ts +0 -2
  444. package/dist/cli/commands/repair/checks.js +0 -246
  445. package/dist/cli/menu/pages/start-page.d.ts +0 -43
  446. package/dist/cli/menu/pages/start-page.js +0 -192
  447. package/dist/cli/tui/tab-bar.d.ts +0 -9
  448. package/dist/cli/tui/tab-bar.js +0 -33
@@ -8,6 +8,7 @@ import { KnownProjects } from '../../host/projects/index.js';
8
8
  import { isWithin } from '../../shared/paths/index.js';
9
9
  import { commandLine } from '../history.js';
10
10
  import { Text, Theme } from '../tui/index.js';
11
+ import { askPath } from './settings/path-kind.js';
11
12
  /** Folders worth offering: this one, the projects started before, and the folders inside your roots. */
12
13
  export function candidateFolders(ctx, cwd = process.cwd()) {
13
14
  const roots = ctx.loaded.config.projects.roots.map((r) => expandPath(r, ctx.loaded.base));
@@ -66,10 +67,10 @@ export class SeveralAgents {
66
67
  const headless = await this.app.confirm({
67
68
  path: this.path,
68
69
  question: 'Hide the sandbox window (headless)?',
69
- about: ['sandbox show brings it back.'],
70
+ about: ['Sandbox > Show the window brings it back.'],
70
71
  initial: this.ctx.loaded.config.sandbox.headless,
71
72
  });
72
- const attach = await this.app.choose(this.path, 'Attach this terminal to one of them? Each session also has a tab inside the sandbox; sandbox attach shows any of them later.', [
73
+ const attach = await this.app.choose(this.path, 'Attach this terminal to one of them? Each session also has a tab inside the sandbox; Sessions shows any of them later.', [
73
74
  { value: -1, label: 'None' },
74
75
  ...sessions.map((s, i) => ({ value: i, label: s.harness + ' in ' + Text.middle(s.folder, 60) })),
75
76
  ], 0);
@@ -119,9 +120,10 @@ export class SeveralAgents {
119
120
  return null;
120
121
  const folders = picked.values.filter((f) => f !== ADD);
121
122
  if (picked.values.includes(ADD)) {
122
- const extra = await this.app.text({
123
+ const extra = await askPath(this.app, {
123
124
  path: this.path,
124
- label: 'Folder to add',
125
+ title: 'Choose the folder to add',
126
+ kind: 'dir',
125
127
  validate: (v) => {
126
128
  const dir = path.resolve(v.trim());
127
129
  if (!v.trim() || !fs.existsSync(dir) || !fs.statSync(dir).isDirectory())
@@ -136,7 +138,7 @@ export class SeveralAgents {
136
138
  },
137
139
  });
138
140
  if (extra)
139
- folders.push(path.resolve(extra.trim()));
141
+ folders.push(path.resolve(extra));
140
142
  }
141
143
  return folders;
142
144
  }
@@ -1,4 +1,4 @@
1
- import type { App, FrameParts, Key, Screen, Size, Step, TabsState } from '../tui/index.js';
1
+ import type { App, Category, FrameParts, Key, NavState, Screen, Size, Step } from '../tui/index.js';
2
2
  import type { Draft, DraftResult } from './settings/draft.js';
3
3
  /** Why the shell closed. */
4
4
  export type ShellExit = {
@@ -14,20 +14,34 @@ export type ShellExit = {
14
14
  kind: 'view';
15
15
  file: string;
16
16
  };
17
- /** One tab. */
17
+ /** Which section and category the menu shows. */
18
+ export interface MenuView {
19
+ readonly section: number;
20
+ readonly category: string | undefined;
21
+ }
22
+ /** One section of the menu. */
18
23
  export interface Page {
19
24
  readonly label: string;
20
- /** This page stages changes in the Draft (its tab is marked while something is unsaved). */
25
+ /** This page stages changes in the Draft (its section is marked while something is unsaved). */
21
26
  readonly stages: boolean;
22
- /** Typing goes into a search box: digits are text, not tab numbers. */
27
+ /** Typing goes into a search box: digits are text, not section numbers. */
23
28
  readonly capturing: boolean;
24
- /** The tab was opened (or the shell came back from a command): load what it shows again. */
29
+ /** The categories listed under the section while it is open (none: the section is one list). */
30
+ categories(): readonly Category[];
31
+ /** The id of the open category. */
32
+ readonly category: string | undefined;
33
+ /** Opens a category (the navigation moved onto it). */
34
+ selectCategory(id: string): Promise<void>;
35
+ /** Whether the list has the keyboard (its highlight is softer while the navigation has it). */
36
+ setFocus(list: boolean): void;
37
+ /** The section was opened (or the shell came back from a command): load what it shows again. */
25
38
  open(): Promise<void>;
26
39
  render(size: Size): FrameParts;
40
+ /** A `quit` from the page means "Esc with nothing left to close": the shell moves to the navigation. */
27
41
  handle(key: Key): Promise<Step<ShellExit>> | Step<ShellExit>;
28
42
  }
29
- /** The tab names, in order. Number keys 1-7 open them. */
30
- export declare const TAB_LABELS: readonly ["Start", "Sessions", "Sandbox", "Apps", "Settings", "Accounts", "Maintenance"];
43
+ /** The section names, in order. Number keys 1-7 open them. */
44
+ export declare const SECTION_LABELS: readonly ["Agents", "Sessions", "Sandbox", "Apps", "Settings", "Accounts", "Maintenance"];
31
45
  export declare class Shell implements Screen<ShellExit> {
32
46
  private readonly app;
33
47
  readonly pages: readonly Page[];
@@ -35,20 +49,33 @@ export declare class Shell implements Screen<ShellExit> {
35
49
  /** Told after a save (the menu applies settings that act on this PC) and returns a note to add. */
36
50
  private readonly afterSave;
37
51
  private active;
52
+ private focus;
38
53
  private notice;
39
54
  constructor(app: App, pages: readonly Page[], draft: Draft,
40
55
  /** Told after a save (the menu applies settings that act on this PC) and returns a note to add. */
41
56
  afterSave?: (result: DraftResult) => string | undefined);
42
57
  get page(): Page;
43
- tabs(): TabsState;
44
- /** Opens a tab by index (loads its data). */
58
+ /** Which pane has the keyboard. */
59
+ get focused(): 'nav' | 'list';
60
+ nav(): NavState;
61
+ /** The section and category that are open (the menu opens on them again later in the same run). */
62
+ view(): MenuView;
63
+ /** Opens the section and category a view names (a category that is gone is ignored). */
64
+ restore(view: MenuView): Promise<void>;
65
+ /** Opens a section by index (loads its data). */
45
66
  openTab(index: number): Promise<void>;
46
- /** Loads the open tab again (after a command ran). */
67
+ /** Puts the keyboard in the navigation or in the list. */
68
+ setFocus(focus: 'nav' | 'list'): void;
69
+ /** Loads the open section again (after a command ran). */
47
70
  reload(): Promise<void>;
48
71
  render(size: Size): FrameParts;
49
72
  /** Writes the staged changes; the notice says what happened. */
50
73
  save(): string;
51
74
  handle(key: Key): Promise<Step<ShellExit>>;
75
+ /** A key while the navigation has the keyboard. */
76
+ private navKey;
77
+ /** One stop up or down the tree: the categories of the open section, then the next section. */
78
+ private move;
52
79
  /** Leaving with unsaved changes asks what to do with them. */
53
80
  private leave;
54
81
  }
@@ -1,12 +1,20 @@
1
1
  import { Theme } from '../tui/index.js';
2
- /** The tab names, in order. Number keys 1-7 open them. */
3
- export const TAB_LABELS = ['Start', 'Sessions', 'Sandbox', 'Apps', 'Settings', 'Accounts', 'Maintenance'];
2
+ /** The section names, in order. Number keys 1-7 open them. */
3
+ export const SECTION_LABELS = ['Agents', 'Sessions', 'Sandbox', 'Apps', 'Settings', 'Accounts', 'Maintenance'];
4
+ const NAV_KEYS = [
5
+ ['↑↓', 'move', 1],
6
+ ['→', 'open', 1],
7
+ ['1-7', 'jump', 4],
8
+ ['/', 'search', 6],
9
+ ['esc', 'quit', 0],
10
+ ];
4
11
  export class Shell {
5
12
  app;
6
13
  pages;
7
14
  draft;
8
15
  afterSave;
9
16
  active = 0;
17
+ focus = 'list';
10
18
  notice;
11
19
  constructor(app, pages, draft,
12
20
  /** Told after a save (the menu applies settings that act on this PC) and returns a note to add. */
@@ -15,24 +23,50 @@ export class Shell {
15
23
  this.pages = pages;
16
24
  this.draft = draft;
17
25
  this.afterSave = afterSave;
18
- app.tabs = () => this.tabs();
26
+ app.nav = () => this.nav();
19
27
  }
20
28
  get page() {
21
29
  return this.pages[this.active];
22
30
  }
23
- tabs() {
31
+ /** Which pane has the keyboard. */
32
+ get focused() {
33
+ return this.focus;
34
+ }
35
+ nav() {
24
36
  const unsaved = this.draft.count() > 0;
37
+ const current = this.page.category;
25
38
  return {
26
- tabs: this.pages.map((p) => ({ label: p.label, marked: p.stages && unsaved })),
39
+ sections: this.pages.map((p, i) => ({
40
+ label: p.label,
41
+ marked: p.stages && unsaved,
42
+ categories: i === this.active ? p.categories().map((c) => ({ label: c.label, current: c.id === current })) : [],
43
+ })),
27
44
  active: this.active,
45
+ focused: this.focus === 'nav',
28
46
  };
29
47
  }
30
- /** Opens a tab by index (loads its data). */
48
+ /** The section and category that are open (the menu opens on them again later in the same run). */
49
+ view() {
50
+ return { section: this.active, category: this.page.category };
51
+ }
52
+ /** Opens the section and category a view names (a category that is gone is ignored). */
53
+ async restore(view) {
54
+ await this.openTab(view.section);
55
+ if (view.category && this.page.categories().some((c) => c.id === view.category))
56
+ await this.page.selectCategory(view.category);
57
+ }
58
+ /** Opens a section by index (loads its data). */
31
59
  async openTab(index) {
32
60
  this.active = Math.max(0, Math.min(this.pages.length - 1, index));
61
+ this.page.setFocus(this.focus === 'list');
33
62
  await this.page.open();
34
63
  }
35
- /** Loads the open tab again (after a command ran). */
64
+ /** Puts the keyboard in the navigation or in the list. */
65
+ setFocus(focus) {
66
+ this.focus = focus;
67
+ this.page.setFocus(focus === 'list');
68
+ }
69
+ /** Loads the open section again (after a command ran). */
36
70
  reload() {
37
71
  return this.page.open();
38
72
  }
@@ -40,11 +74,14 @@ export class Shell {
40
74
  const parts = this.page.render(size);
41
75
  const unsaved = this.draft.count();
42
76
  const status = parts.status ?? this.app.status();
77
+ const category = this.page.categories().find((c) => c.id === this.page.category);
78
+ const keys = this.focus === 'nav' ? NAV_KEYS : parts.keys;
43
79
  return {
44
80
  ...parts,
81
+ path: parts.path.length ? parts.path : [this.page.label, ...(category ? [category.label] : [])],
45
82
  status: unsaved ? Theme.changed('unsaved: ' + unsaved) + ' ' + status : status,
46
83
  notice: this.notice ?? parts.notice,
47
- keys: unsaved ? [['ctrl+s', 'save (' + unsaved + ')', 0], ...parts.keys] : parts.keys,
84
+ keys: unsaved ? [['ctrl+s', 'save (' + unsaved + ')', 0], ...keys] : keys,
48
85
  };
49
86
  }
50
87
  /** Writes the staged changes; the notice says what happened. */
@@ -75,11 +112,54 @@ export class Shell {
75
112
  await this.openTab(index);
76
113
  return;
77
114
  }
115
+ if (this.focus === 'nav')
116
+ return this.navKey(key);
78
117
  const step = await this.page.handle(key);
79
- if (step && step.done.kind === 'quit')
80
- return this.leave();
118
+ if (step && step.done.kind === 'quit') {
119
+ // Esc (or Left) in the list: nothing left to close there, so go to the navigation.
120
+ this.setFocus('nav');
121
+ return;
122
+ }
81
123
  return step;
82
124
  }
125
+ /** A key while the navigation has the keyboard. */
126
+ async navKey(key) {
127
+ if (key.name === 'up' || key.name === 'down') {
128
+ await this.move(key.name === 'up' ? -1 : 1);
129
+ return;
130
+ }
131
+ if (key.name === 'right' || key.name === 'return') {
132
+ this.setFocus('list');
133
+ return;
134
+ }
135
+ if (key.name === 'escape')
136
+ return this.leave();
137
+ // The scopes of Settings and Apps switch from anywhere; "/" starts a search in the list.
138
+ if (key.name === 'tab')
139
+ return this.page.handle(key);
140
+ if (key.text === '/') {
141
+ this.setFocus('list');
142
+ return this.page.handle(key);
143
+ }
144
+ return;
145
+ }
146
+ /** One stop up or down the tree: the categories of the open section, then the next section. */
147
+ async move(by) {
148
+ const categories = this.page.categories();
149
+ const at = categories.findIndex((c) => c.id === this.page.category);
150
+ const next = at + by;
151
+ if (categories.length && next >= 0 && next < categories.length) {
152
+ await this.page.selectCategory(categories[next].id);
153
+ return;
154
+ }
155
+ const section = this.active + by;
156
+ if (section < 0 || section >= this.pages.length)
157
+ return;
158
+ await this.openTab(section);
159
+ const entered = this.page.categories();
160
+ if (entered.length)
161
+ await this.page.selectCategory(entered[by === 1 ? 0 : entered.length - 1].id);
162
+ }
83
163
  /** Leaving with unsaved changes asks what to do with them. */
84
164
  async leave() {
85
165
  const count = this.draft.count();
@@ -0,0 +1,16 @@
1
+ import type { Context } from '../commands/context.js';
2
+ import { type App } from '../tui/index.js';
3
+ /** The row's id in the settings list. */
4
+ export declare const VPN_LOGIN = "@vpn-login";
5
+ export declare function vpnLoginRow(ctx: Context): {
6
+ label: string;
7
+ hint: string;
8
+ description: string;
9
+ };
10
+ export declare class VpnLoginFlow {
11
+ private readonly app;
12
+ private readonly ctx;
13
+ constructor(app: App, ctx: Context);
14
+ /** Returns the notice to show (undefined when cancelled). */
15
+ run(): Promise<string | undefined>;
16
+ }
@@ -0,0 +1,66 @@
1
+ import { VPN_WARNINGS } from '../commands/vpn.js';
2
+ import { NORD_STEPS, VpnService } from '../services/index.js';
3
+ import { Theme } from '../tui/index.js';
4
+ /** The row's id in the settings list. */
5
+ export const VPN_LOGIN = '@vpn-login';
6
+ export function vpnLoginRow(ctx) {
7
+ const service = new VpnService(ctx);
8
+ const nord = service.provider === 'nordvpn';
9
+ const state = service.loginState();
10
+ return {
11
+ label: nord ? 'Set NordVPN login…' : 'Set VPN login…',
12
+ hint: state === 'saved' ? 'saved' : state === 'unreadable' ? 'cannot be read' : 'not saved',
13
+ description: 'The login the VPN uses (for NordVPN the service credentials from Nord Account > NordVPN > Set up NordVPN manually, not your account password). Typed hidden, kept encrypted for your Windows user, never shown. ' +
14
+ VPN_WARNINGS.join(' '),
15
+ };
16
+ }
17
+ export class VpnLoginFlow {
18
+ app;
19
+ ctx;
20
+ constructor(app, ctx) {
21
+ this.app = app;
22
+ this.ctx = ctx;
23
+ }
24
+ /** Returns the notice to show (undefined when cancelled). */
25
+ async run() {
26
+ const service = new VpnService(this.ctx);
27
+ const nord = service.provider === 'nordvpn';
28
+ const path = ['Settings', 'Network', 'VPN login'];
29
+ await this.app.message({
30
+ path,
31
+ title: nord ? 'NordVPN service credentials' : 'VPN login',
32
+ lines: [
33
+ ...(nord
34
+ ? ['To find them:', ...NORD_STEPS.map((s, i) => i + 1 + '. ' + s)]
35
+ : ['The user name and password your VPN profile asks for.']),
36
+ '',
37
+ 'What you type next is hidden, kept encrypted for your Windows user and never shown again.',
38
+ '',
39
+ ...VPN_WARNINGS,
40
+ ],
41
+ });
42
+ const username = await this.app.text({
43
+ path,
44
+ label: nord ? 'Service user name' : 'User name',
45
+ masked: true,
46
+ validate: (v) => (v.trim() ? true : 'Type the user name.'),
47
+ });
48
+ if (username === undefined)
49
+ return undefined;
50
+ const password = await this.app.text({
51
+ path,
52
+ label: nord ? 'Service password' : 'Password',
53
+ masked: true,
54
+ validate: (v) => (v ? true : 'Type the password.'),
55
+ });
56
+ if (password === undefined)
57
+ return undefined;
58
+ try {
59
+ service.save({ username, password });
60
+ }
61
+ catch (e) {
62
+ return Theme.error(Theme.glyph.cross + ' ' + (e instanceof Error ? e.message : String(e)));
63
+ }
64
+ return Theme.ok(Theme.glyph.ok + ' The VPN login is saved (encrypted). Turn the VPN on under Settings > Network.');
65
+ }
66
+ }
@@ -3,3 +3,5 @@ import type { Context } from '../commands/context.js';
3
3
  export declare function table(rows: string[][]): void;
4
4
  /** Prints `value` as JSON when --json was given; returns whether it did. */
5
5
  export declare function printJson(ctx: Context, value: unknown): boolean;
6
+ /** A dim "Next: ..." line after a command: the usual thing to do now. */
7
+ export declare function nextStep(text: string): void;
@@ -1,4 +1,6 @@
1
1
  import _ from 'lodash';
2
+ import { scrubSecrets } from '../../core/schema/index.js';
3
+ import { c } from './colors.js';
2
4
  /** Prints rows as aligned columns (the last column is not padded). */
3
5
  export function table(rows) {
4
6
  const widths = _.range(_.max(rows.map((r) => r.length)) ?? 0).map((i) => _.max(rows.map((r) => (r[i] ?? '').length)) ?? 0);
@@ -8,7 +10,12 @@ export function table(rows) {
8
10
  /** Prints `value` as JSON when --json was given; returns whether it did. */
9
11
  export function printJson(ctx, value) {
10
12
  // JSON.stringify leaves C1 controls (U+0080-U+009F) as they are; text from the sandbox must not reach a terminal raw.
13
+ // Secret values of your settings (agent API keys) never appear, whatever built the value.
11
14
  if (ctx.options.json)
12
- console.log(JSON.stringify(value, null, 2).replace(/[\u0080-\u009f]/g, (ch) => '\\u' + ch.charCodeAt(0).toString(16).padStart(4, '0')));
15
+ console.log(scrubSecrets(JSON.stringify(value, null, 2), ctx.loaded.config).replace(/[\u0080-\u009f]/g, (ch) => '\\u' + ch.charCodeAt(0).toString(16).padStart(4, '0')));
13
16
  return ctx.options.json;
14
17
  }
18
+ /** A dim "Next: ..." line after a command: the usual thing to do now. */
19
+ export function nextStep(text) {
20
+ console.log(c.dim('Next: ' + text));
21
+ }
@@ -13,6 +13,8 @@ export interface AgentAccounts {
13
13
  export interface AccountRef {
14
14
  readonly name: string;
15
15
  readonly email: string | null;
16
+ /** Something worth telling after a switch (e.g. plugins were copied, or could not be). */
17
+ readonly note?: string;
16
18
  }
17
19
  export declare class AccountsService {
18
20
  private readonly ctx;
@@ -12,7 +12,7 @@ export class AccountsService {
12
12
  claude;
13
13
  constructor(ctx) {
14
14
  this.ctx = ctx;
15
- this.claude = new AccountStore(ctx.storageRoot);
15
+ this.claude = new AccountStore(ctx.storageRoot, ctx.loaded.config.claudeProfile.sharePluginsAcrossAccounts);
16
16
  }
17
17
  /** Claude first, then the other agents that keep a login, then the ones that cannot. */
18
18
  agents() {
@@ -68,7 +68,7 @@ export class AccountsService {
68
68
  activate(name, agent = CLAUDE) {
69
69
  if (agent === CLAUDE) {
70
70
  const a = this.claude.activate(this.ctx.dataPath, name);
71
- return { name: a.name, email: a.email };
71
+ return { name: a.name, email: a.email, note: this.claude.pluginNote ?? undefined };
72
72
  }
73
73
  const { store, stateDir } = this.other(agent);
74
74
  store.activate(this.ctx.dataPath, name, stateDir);
@@ -1,10 +1,6 @@
1
- import { UserError } from '../../core/util/index.js';
2
1
  import type { Context } from '../commands/context.js';
3
- import type { RepairCheck, RepairEnv, RepairResult } from '../commands/repair/types.js';
4
2
  import { type Check } from '../commands/setup/checks.js';
5
3
  import { type MachineFacts } from '../commands/setup/facts.js';
6
- /** Runs every check in order; a check that throws is reported, never stops the rest. */
7
- export declare function runChecks(env: RepairEnv, checks?: RepairCheck[]): RepairResult[];
8
4
  /** What `sandbox setup` found out about this PC. */
9
5
  export interface SetupReport {
10
6
  readonly facts: MachineFacts;
@@ -17,8 +13,6 @@ export declare class HealthService {
17
13
  constructor(ctx: Context);
18
14
  /** The table `doctor` shows: [name, detail] rows. */
19
15
  doctor(): string[][];
20
- /** Runs the repair checks (and the fixes they make). A config file that does not load is the first problem. */
21
- repair(configError?: UserError | null): RepairResult[];
22
16
  /** Fails unless this is Windows: Windows Sandbox runs nowhere else. */
23
17
  assertWindows(): void;
24
18
  /** The setup checklist for this PC. */
@@ -1,28 +1,15 @@
1
- // Is this PC (and the sandbox) in good shape: doctor rows, repair checks, the setup checklist. Never prints.
2
- import path from 'node:path';
1
+ // Is this PC (and the sandbox) in good shape: the doctor details, the setup checklist. The checks themselves are in
2
+ // commands/repair (one engine for doctor and repair). Never prints.
3
3
  import { spawnSync } from 'node:child_process';
4
- import { loadConfig } from '../../core/config/index.js';
5
- import { errMsg, expandPath, fail, isWin, UserError } from '../../core/util/index.js';
4
+ import { expandPath, fail, isWin } from '../../core/util/index.js';
6
5
  import { detectWsb, doctorRows, insideSandbox, isSandboxRunning } from '../../host/sandbox/index.js';
6
+ import { machineDoctorRows } from '../../host/sharing/index.js';
7
7
  import { KnownProjects, ProjectRegistry } from '../../host/projects/index.js';
8
8
  import { nativeScript } from '../../host/native.js';
9
9
  import { refuseInSelfTest } from '../../host/test-guard.js';
10
10
  import { SYSTEM } from '../../shared/system.js';
11
- import { CHECKS } from '../commands/repair/checks.js';
12
11
  import { buildChecks, canEnableFeature } from '../commands/setup/checks.js';
13
12
  import { ENABLE_COMMAND, gatherFacts } from '../commands/setup/facts.js';
14
- /** Runs every check in order; a check that throws is reported, never stops the rest. */
15
- export function runChecks(env, checks = CHECKS) {
16
- return checks.map((check) => {
17
- try {
18
- return { name: check.name, ...check.run(env) };
19
- }
20
- catch (e) {
21
- const fix = e instanceof UserError && e.fix ? ' ' + e.fix : '';
22
- return { name: check.name, status: 'needs-you', detail: 'check failed: ' + errMsg(e) + fix };
23
- }
24
- });
25
- }
26
13
  export class HealthService {
27
14
  ctx;
28
15
  constructor(ctx) {
@@ -45,6 +32,7 @@ export class HealthService {
45
32
  const wsb = p.wsbShare ? detectWsb() : null;
46
33
  return [
47
34
  ...rows,
35
+ ...machineDoctorRows(ctx.packageRoot, ctx.dataPath),
48
36
  [
49
37
  'Project roots',
50
38
  p.roots.length
@@ -75,31 +63,6 @@ export class HealthService {
75
63
  ],
76
64
  ];
77
65
  }
78
- /** Runs the repair checks (and the fixes they make). A config file that does not load is the first problem. */
79
- repair(configError = null) {
80
- const { ctx } = this;
81
- const env = {
82
- ctx,
83
- running: isSandboxRunning(),
84
- dataPath: ctx.dataPath,
85
- storageRoot: ctx.storageRoot,
86
- toolsDir: path.join(ctx.dataPath, 'tools'),
87
- configError,
88
- };
89
- // Re-check the config file even when the context loaded (it may have been edited since, or come from --config).
90
- if (!env.configError) {
91
- try {
92
- loadConfig(ctx.options.config);
93
- }
94
- catch (e) {
95
- if (e instanceof UserError)
96
- env.configError = e;
97
- else
98
- throw e;
99
- }
100
- }
101
- return runChecks(env);
102
- }
103
66
  /** Fails unless this is Windows: Windows Sandbox runs nowhere else. */
104
67
  assertWindows() {
105
68
  if (!isWin)
@@ -5,8 +5,10 @@ export { resolveCleanTargets, type CleanTarget } from './data-targets.js';
5
5
  export { DatabasesService, parseDatabaseList, type DatabaseAction, type DatabaseRow } from './databases-service.js';
6
6
  export { autoMigrates, continuesAfterFailedMigration, MigrateService, type MigrateContext, type MigrateResult, } from './migrate-service.js';
7
7
  export { NPM_UPDATE_COMMAND, UpdateService, runsAsSystem, type CheckResult, type UpdateServiceOptions, type UpdateStatus, type UpdateTaskPort, } from './update-service.js';
8
+ export { NORD_STEPS, VpnService, type VpnReport } from './vpn-service.js';
8
9
  export { LogsService, type LogFile } from './logs-service.js';
9
- export { HealthService, runChecks, type SetupReport } from './health-service.js';
10
+ export { WebService, webSession } from './web-service.js';
11
+ export { HealthService, type SetupReport } from './health-service.js';
10
12
  export { ProjectsService, type ProjectRow, type ProjectSettings, type ProjectsListing } from './projects-service.js';
11
13
  export { SandboxService, type OtherSession, type ProjectInfo, type SandboxReport, type SandboxState, type StopPlan, } from './sandbox-service.js';
12
14
  export { SessionsService, projectOf, viewerText, type ListedSession, type RestartScope } from './sessions-service.js';
@@ -5,8 +5,10 @@ export { resolveCleanTargets } from './data-targets.js';
5
5
  export { DatabasesService, parseDatabaseList } from './databases-service.js';
6
6
  export { autoMigrates, continuesAfterFailedMigration, MigrateService, } from './migrate-service.js';
7
7
  export { NPM_UPDATE_COMMAND, UpdateService, runsAsSystem, } from './update-service.js';
8
+ export { NORD_STEPS, VpnService } from './vpn-service.js';
8
9
  export { LogsService } from './logs-service.js';
9
- export { HealthService, runChecks } from './health-service.js';
10
+ export { WebService, webSession } from './web-service.js';
11
+ export { HealthService } from './health-service.js';
10
12
  export { ProjectsService } from './projects-service.js';
11
13
  export { SandboxService, } from './sandbox-service.js';
12
14
  export { SessionsService, projectOf, viewerText } from './sessions-service.js';
@@ -32,7 +32,7 @@ export class MigrateService {
32
32
  }
33
33
  }
34
34
  /** Commands that never update the settings first: they must work whatever state the settings are in. */
35
- const NO_AUTO_MIGRATION = ['self-test', 'migrate', 'update', '_watch'];
35
+ const NO_AUTO_MIGRATION = ['self-test', 'migrate', 'update', '_watch', '_web'];
36
36
  /** Does this command update the saved settings before it runs (when the version changed)? Never inside a sandbox. */
37
37
  export function autoMigrates(command, inSandbox) {
38
38
  return !inSandbox && !NO_AUTO_MIGRATION.includes(command);
@@ -9,6 +9,8 @@ export interface UpdateStatus {
9
9
  readonly scope: 'user' | 'machine' | null;
10
10
  readonly autoUpdate: boolean;
11
11
  readonly state: UpdateState;
12
+ /** Set when a failed update was undone and switched automatic updates off: the sentence to show (menu, CLI). */
13
+ readonly autoOffText?: string | null;
12
14
  }
13
15
  export interface CheckResult {
14
16
  readonly current: string;
@@ -9,7 +9,7 @@ import { errMsg, fail } from '../../core/util/index.js';
9
9
  import { packageVersion } from '../../core/package-info.js';
10
10
  import { InstallLayout, InstallRecordFile, UpdateTask, compareVersions } from '../../host/install/index.js';
11
11
  import { isSandboxRunning } from '../../host/sandbox/index.js';
12
- import { FolderFeed, GithubReleases, UpdateLock, Updater, UpdateStateFile, decideUpdate, isTooSoon, updateNotice, } from '../../host/update/index.js';
12
+ import { FolderFeed, GithubReleases, UpdateLock, Updater, UpdateStateFile, autoOffText, decideUpdate, isTooSoon, updateNotice, } from '../../host/update/index.js';
13
13
  import { JsonFile } from '../../shared/io/index.js';
14
14
  /** The command for an install that is not managed (npm). */
15
15
  export const NPM_UPDATE_COMMAND = 'npm install -g windows-development-sandbox';
@@ -53,13 +53,17 @@ export class UpdateService {
53
53
  status() {
54
54
  const layout = this.layout;
55
55
  if (!layout)
56
- return { managed: false, version: this.version, scope: null, autoUpdate: false, state: {} };
56
+ return { managed: false, version: this.version, scope: null, autoUpdate: false, state: {}, autoOffText: null };
57
+ const version = layout.activeVersion() ?? this.version;
58
+ const autoUpdate = new InstallRecordFile(layout.root).read()?.autoUpdate ?? false;
59
+ const state = new UpdateStateFile(layout.root).read();
57
60
  return {
58
61
  managed: true,
59
- version: layout.activeVersion() ?? this.version,
62
+ version,
60
63
  scope: layout.scope,
61
- autoUpdate: new InstallRecordFile(layout.root).read()?.autoUpdate ?? false,
62
- state: new UpdateStateFile(layout.root).read(),
64
+ autoUpdate,
65
+ state,
66
+ autoOffText: !autoUpdate && state.autoOff ? autoOffText(state.autoOff.version, version) : null,
63
67
  };
64
68
  }
65
69
  /** Asks the source what is newest. Changes nothing (the time of the look is not recorded). */
@@ -92,7 +96,7 @@ export class UpdateService {
92
96
  if (!release)
93
97
  return null;
94
98
  try {
95
- const updater = new Updater(layout, this.source, { now: this.now });
99
+ const updater = new Updater(layout, this.source, { now: this.now, task: this.task });
96
100
  return await updater.run({ sandboxRunning: this.sandboxRunning(), force: true });
97
101
  }
98
102
  finally {
@@ -129,6 +133,9 @@ export class UpdateService {
129
133
  const record = new InstallRecordFile(layout.root);
130
134
  if (!record.setAutoUpdate(on))
131
135
  fail('This install has no install.json.', 'Run the installer again: it writes the file.');
136
+ // Turned back on by the user: the "turned off by a failed update" remark is history.
137
+ if (on)
138
+ new UpdateStateFile(layout.root).update(({ autoOff: _gone, ...rest }) => rest);
132
139
  }
133
140
  /**
134
141
  * Should this CLI start update by itself? Only current-user installs (an all-users install has its scheduled task),
@@ -0,0 +1,28 @@
1
+ import type { Config } from '../../core/types.js';
2
+ import type { VpnProvider } from '../../core/schema/index.js';
3
+ import { type LoginState, type VpnCredentials, type VpnLine } from '../../host/vpn/index.js';
4
+ import type { Context } from '../commands/context.js';
5
+ export interface VpnReport {
6
+ readonly enabled: boolean;
7
+ readonly provider: VpnProvider;
8
+ readonly protocol: Config['vpn']['protocol'];
9
+ readonly country: string;
10
+ readonly killSwitch: boolean;
11
+ readonly login: LoginState;
12
+ readonly loginSavedAt: string | null;
13
+ /** The running sandbox's tunnel, when one runs with the VPN on. */
14
+ readonly running: VpnLine | null;
15
+ }
16
+ /** The steps to get the NordVPN service credentials, in the words of Nord Account (shown before asking). */
17
+ export declare const NORD_STEPS: readonly string[];
18
+ export declare class VpnService {
19
+ private readonly ctx;
20
+ private readonly login;
21
+ constructor(ctx: Context);
22
+ private get config();
23
+ get provider(): VpnProvider;
24
+ report(): Promise<VpnReport>;
25
+ loginState(): LoginState;
26
+ save(credentials: VpnCredentials): void;
27
+ remove(): boolean;
28
+ }