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
@@ -1,9 +1,13 @@
1
1
  import { Text } from '../text.js';
2
2
  import { Theme } from '../theme.js';
3
+ /** Lists longer than this say how to search. */
4
+ const LONG_LIST = 12;
3
5
  export class ListScreen {
4
6
  o;
5
7
  category = 0;
6
8
  focus = 'list';
9
+ /** The list has the keyboard (false while the menu's navigation has it): the highlight is drawn softer. */
10
+ active = true;
7
11
  cursor = 0;
8
12
  offset = 0;
9
13
  query = '';
@@ -57,7 +61,7 @@ export class ListScreen {
57
61
  render(size) {
58
62
  const visible = this.visible();
59
63
  this.cursor = Math.min(this.cursor, Math.max(0, visible.length - 1));
60
- const sideWidth = this.o.categories
64
+ const sideWidth = this.o.categories && !this.external
61
65
  ? Math.min(32, Math.max(...this.o.categories.map((c) => Text.width(c.label))) + 7)
62
66
  : 0;
63
67
  const rest = size.width - 1 - (sideWidth ? sideWidth + 3 : 0);
@@ -65,14 +69,16 @@ export class ListScreen {
65
69
  const detailsWidth = detailsRight ? Math.min(52, Math.floor(rest * 0.38)) : rest;
66
70
  const listWidth = detailsRight ? rest - detailsWidth - 3 : rest;
67
71
  const top = [];
68
- if (this.o.tabs)
69
- top.push(' ' +
72
+ if (this.o.tabs) {
73
+ const row = ' ' +
70
74
  this.o.tabs.items
71
75
  .map((tab, i) => i === this.o.tabs.active
72
76
  ? tab.paint(' ' + tab.badge + ' ' + tab.label + ' ')
73
77
  : Theme.muted(' ' + tab.label + ' '))
74
78
  .join(' ') +
75
- Theme.muted(' tab switches'), '');
79
+ Theme.muted(' tab switches');
80
+ top.push(Text.truncate(row, size.width - 1), '');
81
+ }
76
82
  const intro = typeof this.o.intro === 'string' ? [this.o.intro] : (this.o.intro ?? []);
77
83
  for (const line of intro)
78
84
  top.push(...Text.wrap(line, size.width - 3).map((l) => ' ' + Theme.muted(l)));
@@ -113,9 +119,10 @@ export class ListScreen {
113
119
  listLines.push(Theme.muted(' ' +
114
120
  (above > 0 ? '▲ ' + above + ' above' : '') +
115
121
  (above > 0 && below > 0 ? ' ' : '') +
116
- (below > 0 ? '▼ ' + below + ' more' : '')));
122
+ (below > 0 ? '▼ ' + below + ' more' : '') +
123
+ (this.searching || this.query ? '' : ' / search')));
117
124
  }
118
- const sideLines = this.sideLines(sideWidth);
125
+ const sideLines = sideWidth ? this.sideLines(sideWidth) : [];
119
126
  const body = [...top];
120
127
  const height = Math.max(listLines.length, detailsRight ? details.length : 0, sideLines.length);
121
128
  for (let i = 0; i < Math.min(height, size.height - top.length); i++) {
@@ -156,7 +163,9 @@ export class ListScreen {
156
163
  ' ';
157
164
  if (!selected)
158
165
  return ' ' + line;
159
- return this.focus === 'list' ? ' ' + Theme.selected(Text.strip(line)) : ' ' + Theme.accent(Text.strip(line));
166
+ return this.focus === 'list' && this.active
167
+ ? ' ' + Theme.selected(Text.strip(line))
168
+ : ' ' + Theme.accent(Text.strip(line));
160
169
  }
161
170
  sideLines(width) {
162
171
  if (!this.o.categories)
@@ -199,12 +208,14 @@ export class ListScreen {
199
208
  if (this.searching)
200
209
  return [
201
210
  ['type', 'to search', 1],
202
- ['↵', this.o.multi ? 'done' : (this.o.enterLabel ?? 'open'), 1],
211
+ ['↵', this.o.multi ? 'done' : this.enterLabel(this.valueAt(this.visible()[this.cursor])), 1],
203
212
  ['esc', 'clear search', 0],
204
213
  ['↑↓', 'move', 4],
205
214
  ];
206
215
  const current = this.visible()[this.cursor];
216
+ const value = current === undefined ? undefined : this.o.items[current].value;
207
217
  const flips = current !== undefined && this.o.items[current].flip;
218
+ const long = this.o.items.length > LONG_LIST;
208
219
  return [
209
220
  ...(this.o.multi
210
221
  ? [
@@ -212,16 +223,19 @@ export class ListScreen {
212
223
  ...(this.o.enterTicks ? [] : [['↵', 'done', 1]]),
213
224
  ['a', 'tick all shown', 6],
214
225
  ]
215
- : [['↵', this.o.enterLabel ?? 'open', 1], ...(flips ? [['space', 'flip', 1]] : [])]),
216
- ...this.actionsNow().map((a) => [
226
+ : [
227
+ ...(this.enterLabel(value) ? [['↵', this.enterLabel(value), 1]] : []),
228
+ ...(flips ? [['space', 'flip', 1]] : []),
229
+ ]),
230
+ ...this.actionsNow(value).map((a) => [
217
231
  a.ctrl ? 'ctrl+' + a.key : a.key,
218
232
  a.label,
219
233
  a.ctrl ? 0 : (a.importance ?? 2),
220
234
  ]),
221
235
  ...(this.o.tabs ? [['tab', 'scope', 3]] : []),
222
- ...(this.o.categories ? [['←→', 'categories', 3]] : []),
236
+ ...(this.o.categories && !this.external ? [['←→', 'categories', 3]] : []),
223
237
  ['↑↓', 'move', 5],
224
- ['/', 'search', 6],
238
+ ['/', 'search', long ? 3 : 6],
225
239
  ['esc', this.o.escapeLabel ?? 'back', 0],
226
240
  ];
227
241
  }
@@ -229,14 +243,45 @@ export class ListScreen {
229
243
  setNotice(text) {
230
244
  this.notice = text;
231
245
  }
246
+ /** The categories are shown by the menu's navigation, which drives them (no sidebar of its own). */
247
+ get external() {
248
+ return this.o.categoryNav === 'external';
249
+ }
250
+ enterLabel(value) {
251
+ const label = this.o.enterLabel;
252
+ return (typeof label === 'function' ? label(this.currentCategory, value) : label) ?? 'open';
253
+ }
254
+ valueAt(index) {
255
+ return index === undefined ? undefined : this.o.items[index].value;
256
+ }
257
+ /** The categories of the list (empty without any). */
258
+ get categories() {
259
+ return this.o.categories ?? [];
260
+ }
261
+ /** Opens a category (the menu's navigation does this); a search in progress ends. */
262
+ setCategory(id) {
263
+ const index = this.categories.findIndex((c) => c.id === id);
264
+ if (index < 0 || index === this.category)
265
+ return;
266
+ this.category = index;
267
+ this.query = '';
268
+ this.searching = false;
269
+ this.cursor = 0;
270
+ this.offset = 0;
271
+ }
272
+ /** Whether the list has the keyboard (the highlight is drawn softer when it has not). */
273
+ setActive(on) {
274
+ this.active = on;
275
+ }
232
276
  /** The id of the category open in the sidebar (undefined without a sidebar). */
233
277
  get currentCategory() {
234
278
  return this.o.categories?.[this.category]?.id;
235
279
  }
236
- /** The extra keys that work now (they may depend on the category). */
237
- actionsNow() {
280
+ /** The extra keys that work now (they may depend on the category and on the highlighted entry). */
281
+ actionsNow(value) {
238
282
  const actions = this.o.actions;
239
- return typeof actions === 'function' ? actions(this.currentCategory) : (actions ?? []);
283
+ const all = typeof actions === 'function' ? actions(this.currentCategory) : (actions ?? []);
284
+ return all.filter((a) => !a.applies || (value !== undefined && a.applies(value)));
240
285
  }
241
286
  /** Keys are going into the search box (digits and letters are text, not shortcuts). */
242
287
  get isSearching() {
@@ -250,15 +295,10 @@ export class ListScreen {
250
295
  const visible = this.visible();
251
296
  const current = visible[this.cursor];
252
297
  this.notice = undefined;
253
- const ctrlAction = key.ctrl ? this.actionsNow().find((a) => a.ctrl && a.key === key.name) : undefined;
298
+ const value = this.valueAt(current);
299
+ const ctrlAction = key.ctrl ? this.actionsNow(value).find((a) => a.ctrl && a.key === key.name) : undefined;
254
300
  if (ctrlAction)
255
- return {
256
- done: {
257
- kind: 'action',
258
- key: 'ctrl+' + ctrlAction.key,
259
- value: current === undefined ? undefined : this.o.items[current].value,
260
- },
261
- };
301
+ return { done: { kind: 'action', key: 'ctrl+' + ctrlAction.key, value } };
262
302
  const move = (by) => {
263
303
  this.cursor = Math.max(0, Math.min(visible.length - 1, this.cursor + by));
264
304
  };
@@ -318,7 +358,9 @@ export class ListScreen {
318
358
  const n = this.o.tabs.items.length;
319
359
  return { done: { kind: 'tab', index: (this.o.tabs.active + (key.shift ? n - 1 : 1)) % n } };
320
360
  }
321
- if (this.o.categories && !this.query) {
361
+ if (this.external && !this.query && !this.searching && key.name === 'left')
362
+ return { done: { kind: 'back' } };
363
+ if (this.o.categories && !this.external && !this.query) {
322
364
  if (key.name === 'left' && this.focus === 'list') {
323
365
  this.focus = 'side';
324
366
  return;
@@ -370,15 +412,9 @@ export class ListScreen {
370
412
  }
371
413
  return { done: { kind: 'pick', value: it.value } };
372
414
  }
373
- const action = !this.searching && key.text ? this.actionsNow().find((a) => !a.ctrl && a.key === key.text) : undefined;
415
+ const action = !this.searching && key.text ? this.actionsNow(value).find((a) => !a.ctrl && a.key === key.text) : undefined;
374
416
  if (action)
375
- return {
376
- done: {
377
- kind: 'action',
378
- key: action.key,
379
- value: current === undefined ? undefined : this.o.items[current].value,
380
- },
381
- };
417
+ return { done: { kind: 'action', key: action.key, value } };
382
418
  return;
383
419
  }
384
420
  toggle(index) {
@@ -26,9 +26,11 @@ export interface Category {
26
26
  label: string;
27
27
  description?: string;
28
28
  }
29
- export interface ListAction {
29
+ export interface ListAction<T = unknown> {
30
30
  key: string;
31
31
  label: string;
32
+ /** Only while an entry this accepts is highlighted: the key bar and the key itself ignore it otherwise. */
33
+ applies?: (value: T) => boolean;
32
34
  /** Pressed with Ctrl (ctrl+s ...); works while searching too. */
33
35
  ctrl?: boolean;
34
36
  /** How long it survives in a narrow footer: 0 never goes, bigger goes earlier (default 2). */
@@ -70,7 +72,7 @@ export interface ListOptions<T> {
70
72
  startAt?: T;
71
73
  startCategory?: string;
72
74
  /** Extra keys; a function picks them by the open category. */
73
- actions?: ListAction[] | ((category: string | undefined) => ListAction[]);
75
+ actions?: ListAction<T>[] | ((category: string | undefined) => ListAction<T>[]);
74
76
  notice?: string;
75
77
  empty?: string;
76
78
  tabs?: {
@@ -79,6 +81,8 @@ export interface ListOptions<T> {
79
81
  };
80
82
  /** What Esc does, for the footer ("back", "quit"). */
81
83
  escapeLabel?: string;
82
- /** What Enter does, for the footer ("open", "edit", "start"). */
83
- enterLabel?: string;
84
+ /** What Enter does, for the footer ("open", "edit", "start"); a function picks it by entry ("": none). */
85
+ enterLabel?: string | ((category: string | undefined, value: T | undefined) => string);
86
+ /** Where the categories are listed: in a sidebar of the list itself (default) or in the menu's own navigation. */
87
+ categoryNav?: 'own' | 'external';
84
88
  }
@@ -0,0 +1,29 @@
1
+ export interface NavCategory {
2
+ readonly label: string;
3
+ /** The category open in the list. */
4
+ readonly current: boolean;
5
+ }
6
+ export interface NavSection {
7
+ readonly label: string;
8
+ /** Something is waiting in this section (unsaved changes). */
9
+ readonly marked?: boolean;
10
+ /** The categories of the open section (other sections are drawn without theirs). */
11
+ readonly categories: readonly NavCategory[];
12
+ }
13
+ export interface NavState {
14
+ readonly sections: readonly NavSection[];
15
+ /** Index of the open section. */
16
+ readonly active: number;
17
+ /** The navigation has the keyboard (else the list has it). */
18
+ readonly focused: boolean;
19
+ /** A dialog or sub-screen is shown over the menu: everything is drawn grey. */
20
+ readonly dimmed?: boolean;
21
+ }
22
+ export declare class SideNav {
23
+ /** Columns the navigation takes on a terminal `termWidth` columns wide (without the divider). */
24
+ static width(termWidth: number): number;
25
+ /** Exactly `height` lines, each `SideNav.width(termWidth)` columns wide. */
26
+ static render(nav: NavState, termWidth: number, height: number): string[];
27
+ private static section;
28
+ private static category;
29
+ }
@@ -0,0 +1,67 @@
1
+ // The navigation on the left of every menu screen: the sections as a tree (the open one shows its categories), with
2
+ // the way you are standing marked. Narrow terminals get a slim column of numbers instead of names. Pure (tested).
3
+ import { Text } from './text.js';
4
+ import { Theme } from './theme.js';
5
+ /** Terminals narrower than this get the slim column. */
6
+ const SLIM_BELOW = 80;
7
+ const SLIM_WIDTH = 5;
8
+ export class SideNav {
9
+ /** Columns the navigation takes on a terminal `termWidth` columns wide (without the divider). */
10
+ static width(termWidth) {
11
+ if (termWidth < SLIM_BELOW)
12
+ return SLIM_WIDTH;
13
+ return termWidth >= 130 ? 28 : 24;
14
+ }
15
+ /** Exactly `height` lines, each `SideNav.width(termWidth)` columns wide. */
16
+ static render(nav, termWidth, height) {
17
+ const width = SideNav.width(termWidth);
18
+ const slim = width === SLIM_WIDTH;
19
+ const lines = [];
20
+ nav.sections.forEach((section, i) => {
21
+ const open = i === nav.active;
22
+ const hasCategories = open && section.categories.length > 0;
23
+ const standing = open && !hasCategories;
24
+ lines.push({ text: SideNav.section(nav, section, i, width, slim, standing), stop: standing });
25
+ if (!hasCategories)
26
+ return;
27
+ section.categories.forEach((cat, c) => {
28
+ const last = c === section.categories.length - 1;
29
+ lines.push({ text: SideNav.category(nav, cat, last, width, slim), stop: cat.current });
30
+ });
31
+ });
32
+ const at = Math.max(0, lines.findIndex((l) => l.stop));
33
+ const start = lines.length > height ? Math.min(Math.max(0, at - Math.floor(height / 2)), lines.length - height) : 0;
34
+ const shown = lines.slice(start, start + height).map((l) => l.text);
35
+ while (shown.length < height)
36
+ shown.push(' '.repeat(width));
37
+ return shown;
38
+ }
39
+ static section(nav, section, index, width, slim, standing) {
40
+ const open = index === nav.active;
41
+ const live = !nav.dimmed;
42
+ // The open section has a marker, so it shows without colour.
43
+ const lead = open ? (section.categories.length ? '▾' : Theme.glyph.pointer) : ' ';
44
+ const mark = section.marked ? Theme.changed(Theme.glyph.changed) : ' ';
45
+ const inner = slim
46
+ ? lead + (index + 1) + mark + ' '
47
+ : Text.fit(lead + (index + 1) + ' ' + (open && live ? Theme.bold(section.label) : section.label), width - 3) +
48
+ ' ' +
49
+ mark +
50
+ ' ';
51
+ if (standing && live && nav.focused)
52
+ return Theme.selected(Text.fit(inner, width));
53
+ if (!live || !open)
54
+ return Theme.muted(Text.fit(inner, width));
55
+ return nav.focused ? Text.fit(inner, width) : Theme.accent(Text.fit(inner, width));
56
+ }
57
+ static category(nav, cat, last, width, slim) {
58
+ const live = !nav.dimmed;
59
+ const plain = slim
60
+ ? ' ' + (cat.current ? Theme.glyph.on : Theme.glyph.dot) + ' '
61
+ : ' ' + (cat.current ? Theme.glyph.pointer : last ? '└' : '├') + ' ' + cat.label;
62
+ const line = Text.fit(plain, width);
63
+ if (!cat.current || !live)
64
+ return Theme.muted(line);
65
+ return nav.focused ? Theme.selected(line) : Theme.accentBold(line);
66
+ }
67
+ }
@@ -12,6 +12,6 @@ export declare function validPythonSpec(spec: string): boolean;
12
12
  export declare function checkHarness(name: string | undefined, harnesses: string[]): void;
13
13
  export declare const PROJECT_ACTIONS: readonly ["list", "choose", "add", "remove", "include", "exclude", "all", "roots"];
14
14
  /** `sandbox projects <action> [value] [folder]`: the action, then what it needs. Pure (no file checks). */
15
- export declare function validateProjectsArgs(args: string[]): void;
15
+ export declare function validateProjectsArgs(args: string[], canAsk?: boolean): void;
16
16
  /** Fails with what is wrong and what is valid, before anything is started. */
17
17
  export declare function validateOptions(ctx: Context): void;
@@ -44,11 +44,11 @@ export function checkHarness(name, harnesses) {
44
44
  const LAUNCHING = new Set(['launch', 'generate', 'host-claude']);
45
45
  export const PROJECT_ACTIONS = ['list', 'choose', 'add', 'remove', 'include', 'exclude', 'all', 'roots'];
46
46
  /** `sandbox projects <action> [value] [folder]`: the action, then what it needs. Pure (no file checks). */
47
- export function validateProjectsArgs(args) {
47
+ export function validateProjectsArgs(args, canAsk = false) {
48
48
  const [action = 'list', value, folder] = args;
49
49
  if (!PROJECT_ACTIONS.includes(action))
50
50
  unknownValue('projects action', action, PROJECT_ACTIONS, 'sandbox projects with no action lists your projects.');
51
- if (['add', 'remove', 'include', 'exclude'].includes(action) && !value)
51
+ if (['add', 'remove', 'include', 'exclude'].includes(action) && !value && !canAsk)
52
52
  fail('Which folder?', 'Usage: sandbox projects ' + action + ' <folder> (. = this folder)');
53
53
  if (action === 'all' && value !== undefined && !['on', 'off'].includes(value))
54
54
  unknownValue('value for projects all', value, ['on', 'off'], 'sandbox projects all on|off');
@@ -64,7 +64,7 @@ export function validateOptions(ctx) {
64
64
  if (['launch', 'generate', 'restart', 'doctor'].includes(o.command))
65
65
  checkHarness(o.harness, harnesses);
66
66
  if (o.command === 'projects')
67
- validateProjectsArgs(o.positionals);
67
+ validateProjectsArgs(o.positionals, Boolean(process.stdin.isTTY));
68
68
  if (!LAUNCHING.has(o.command))
69
69
  return;
70
70
  if (o.node !== undefined && !validNodeSpec(o.node))
@@ -0,0 +1,2 @@
1
+ /** The text for a version-only command line (`--version`, `-v`, with or without `--short`), or null for any other. */
2
+ export declare function versionText(argv: readonly string[], packageRoot: string): string | null;
@@ -0,0 +1,11 @@
1
+ // `sandbox --version`: the version and where it runs from; `--version --short` is the plain number (the updater and the
2
+ // installer compare it to the version they just installed).
3
+ import { packageVersion } from '../core/package-info.js';
4
+ import { describeCopy } from '../host/install/index.js';
5
+ /** The text for a version-only command line (`--version`, `-v`, with or without `--short`), or null for any other. */
6
+ export function versionText(argv, packageRoot) {
7
+ const flags = argv.filter((a) => a !== '--short');
8
+ if (flags.length === 0 || flags.some((a) => a !== '--version' && a !== '-v'))
9
+ return null;
10
+ return argv.includes('--short') ? packageVersion() : packageVersion() + ' (' + describeCopy(packageRoot) + ')';
11
+ }
@@ -24,13 +24,14 @@ export const DEFAULTS = {
24
24
  },
25
25
  sharing: { otherUsers: false },
26
26
  storage: {
27
- root: '%LOCALAPPDATA%\\AgentSandbox',
27
+ root: '%ProgramData%\\AgentSandbox\\users\\%USERNAME%',
28
28
  persistAgentState: true,
29
29
  dataName: 'default',
30
30
  markSandboxFiles: true,
31
31
  warnDataGb: 50,
32
32
  },
33
33
  network: { blockPrivateRanges: true, allowOnly: [], blockHosts: [], forwardPorts: [], dns: [], proxy: '' },
34
+ vpn: { enabled: false, provider: 'nordvpn', protocol: 'udp', country: '', configFile: '', killSwitch: true },
34
35
  provisioning: {
35
36
  copyFromHost: true,
36
37
  fallbackToInstall: true,
@@ -88,6 +89,7 @@ export const DEFAULTS = {
88
89
  sqlserver: { enabled: 'auto' },
89
90
  },
90
91
  attach: { enabled: true, reuseSession: true, auto: false, autoHide: false },
92
+ web: { enabled: false, port: 47800 },
91
93
  agentCommands: { enabled: false, agents: 'auto' },
92
94
  secrets: { strip: true, allow: [], patterns: [], warnFiles: true },
93
95
  personalization: { enabled: true },
@@ -99,6 +101,7 @@ export const DEFAULTS = {
99
101
  globalStateFile: 'auto',
100
102
  copyCredentials: false,
101
103
  overwrite: true,
104
+ sharePluginsAcrossAccounts: false,
102
105
  syncHistory: true,
103
106
  historyScope: 'project',
104
107
  syncClaudeMem: true,
@@ -122,6 +125,7 @@ export const DEFAULTS = {
122
125
  arguments: [],
123
126
  environment: {},
124
127
  home: { env: { CODEX_HOME: 'codex' }, loginFiles: ['auth.json'], hostDir: '~/.codex' },
128
+ localState: { CODEX_SQLITE_HOME: 'sqlite' },
125
129
  resumeArguments: ['resume', '--last'],
126
130
  },
127
131
  gemini: {
@@ -23,8 +23,18 @@ export function machineConfigPath(env = process.env) {
23
23
  * folders in it must be full paths (after %VARIABLES% expand), never relative to someone's folder.
24
24
  */
25
25
  function readMachineConfig(file) {
26
- if (!fs.existsSync(file))
27
- return null;
26
+ // existsSync says false on "access denied": a user not yet in the group would silently get the defaults.
27
+ try {
28
+ fs.accessSync(file, fs.constants.R_OK);
29
+ }
30
+ catch (e) {
31
+ const code = e.code;
32
+ if (code === 'ENOENT' || code === 'ENOTDIR')
33
+ return null;
34
+ if (code === 'EACCES' || code === 'EPERM')
35
+ fail('Cannot read the settings for this PC in ' + file + '.', 'Sign out of Windows and in again after being added to the Agent Sandbox Users group.');
36
+ throw e;
37
+ }
28
38
  const raw = readJsonc(file);
29
39
  const config = validateConfig(mergeConfig(DEFAULTS, raw), file);
30
40
  const folders = config.mappings.map((m, i) => ['mappings[' + i + '].host', m.host]);
@@ -49,6 +49,7 @@ export const ON_IS_SAFER = [
49
49
  'network.blockPrivateRanges',
50
50
  'sandbox.protectedClient',
51
51
  'downloads.requireChecksum',
52
+ 'vpn.killSwitch',
52
53
  ];
53
54
  export const OFF_IS_SAFER = [
54
55
  'sandbox.networking',
@@ -1,4 +1,23 @@
1
+ /** One entry of a list question; `description` is shown under the highlighted entry. */
2
+ export interface PromptChoice<T> {
3
+ readonly name: string;
4
+ readonly value: T;
5
+ readonly description?: string;
6
+ }
1
7
  /** A yes/no question (default no). */
2
8
  export declare function askYesNo(question: string, defaultYes?: boolean): Promise<boolean>;
9
+ /** A yes/no question the command needs answered: no terminal fails (`--yes` answers yes on the command line). */
10
+ export declare function askRequired(question: string, fix?: string, defaultYes?: boolean): Promise<boolean>;
3
11
  /** Asks the user to type `expected` (a stronger confirmation than yes/no). */
4
12
  export declare function askTyped(question: string, expected: string): Promise<boolean>;
13
+ /** Pick one entry from a list (for an argument that was left out); `fix` says what to type instead. */
14
+ export declare function askChoice<T>(message: string, choices: readonly PromptChoice<T>[], fix: string): Promise<T>;
15
+ /** Tick any number of entries from a list; `fix` says what to type instead. */
16
+ export declare function askChoices<T>(message: string, choices: readonly PromptChoice<T>[], fix: string): Promise<T[]>;
17
+ /** Type a name or a path. `validate` returns true, or the problem to show. */
18
+ export declare function askName(message: string, fix: string, validate?: (value: string) => true | string): Promise<string>;
19
+ /**
20
+ * Type a secret (a password, an API key) with each character shown as *. Never echoed, never kept; `fix` says what to
21
+ * do without a terminal.
22
+ */
23
+ export declare function askSecret(message: string, fix: string): Promise<string>;
@@ -1,12 +1,24 @@
1
- // Questions asked on the terminal, all through @inquirer/prompts. Without an interactive terminal the answer is always
2
- // "no".
3
- import { confirm, input } from '@inquirer/prompts';
1
+ // Questions asked on the terminal, all through @inquirer/prompts. askYesNo is for optional offers: without an
2
+ // interactive terminal the answer is "no". askRequired, askChoice and askName are for questions a command cannot go on
3
+ // without: with no terminal they fail and say how to answer on the command line.
4
+ import { checkbox, confirm, input, password, select } from '@inquirer/prompts';
5
+ import { fail } from './util/errors.js';
6
+ /** The terminal check every required question starts with. */
7
+ function requireTerminal(fix) {
8
+ if (!process.stdin.isTTY)
9
+ fail('Cannot ask here (no terminal).', fix);
10
+ }
4
11
  /** A yes/no question (default no). */
5
12
  export async function askYesNo(question, defaultYes = false) {
6
13
  if (!process.stdin.isTTY)
7
14
  return false;
8
15
  return confirm({ message: question, default: defaultYes });
9
16
  }
17
+ /** A yes/no question the command needs answered: no terminal fails (`--yes` answers yes on the command line). */
18
+ export async function askRequired(question, fix = 'Add --yes to answer yes.', defaultYes = false) {
19
+ requireTerminal(fix);
20
+ return confirm({ message: question, default: defaultYes });
21
+ }
10
22
  /** Asks the user to type `expected` (a stronger confirmation than yes/no). */
11
23
  export async function askTyped(question, expected) {
12
24
  if (!process.stdin.isTTY)
@@ -14,3 +26,31 @@ export async function askTyped(question, expected) {
14
26
  const answer = await input({ message: question + ' Type "' + expected + '" to confirm:' });
15
27
  return answer.trim().toLowerCase() === expected;
16
28
  }
29
+ /** Pick one entry from a list (for an argument that was left out); `fix` says what to type instead. */
30
+ export async function askChoice(message, choices, fix) {
31
+ requireTerminal(fix);
32
+ return select({ message, choices: [...choices] });
33
+ }
34
+ /** Tick any number of entries from a list; `fix` says what to type instead. */
35
+ export async function askChoices(message, choices, fix) {
36
+ requireTerminal(fix);
37
+ return checkbox({ message, choices: [...choices] });
38
+ }
39
+ /** Type a name or a path. `validate` returns true, or the problem to show. */
40
+ export async function askName(message, fix, validate) {
41
+ requireTerminal(fix);
42
+ const answer = await input({ message, validate: validate ? (v) => validate(v.trim()) : undefined });
43
+ return answer.trim();
44
+ }
45
+ /**
46
+ * Type a secret (a password, an API key) with each character shown as *. Never echoed, never kept; `fix` says what to
47
+ * do without a terminal.
48
+ */
49
+ export async function askSecret(message, fix) {
50
+ requireTerminal(fix);
51
+ return password({
52
+ message,
53
+ mask: '*',
54
+ validate: (v) => (v.length > 0 ? true : 'Type it, or press Ctrl+C to cancel.'),
55
+ });
56
+ }
@@ -18,3 +18,9 @@ export declare const GitAccessSchema: z.ZodEnum<{
18
18
  export declare const EnabledSchema: z.ZodUnion<readonly [z.ZodBoolean, z.ZodLiteral<"auto">]>;
19
19
  export declare function enabled(what: string, markers: string): typeof EnabledSchema;
20
20
  export declare function Packages(what: string, example: string): typeof StringsSchema;
21
+ /**
22
+ * Marks a setting whose value is a secret (an API key in an agent's environment): config show / get, the menu, doctor
23
+ * and every --json print *** for it (core/schema/redact.ts), and it is never written to session.json or the launch
24
+ * folder (it travels in a one-shot file, see shared/channel/secrets.ts).
25
+ */
26
+ export declare function secret<T extends z.ZodType>(schema: T): T;
@@ -25,3 +25,11 @@ export function enabled(what, markers) {
25
25
  export function Packages(what, example) {
26
26
  return StringsSchema.describe(what + ', installed once and kept (e.g. ' + example + ').');
27
27
  }
28
+ /**
29
+ * Marks a setting whose value is a secret (an API key in an agent's environment): config show / get, the menu, doctor
30
+ * and every --json print *** for it (core/schema/redact.ts), and it is never written to session.json or the launch
31
+ * folder (it travels in a one-shot file, see shared/channel/secrets.ts).
32
+ */
33
+ export function secret(schema) {
34
+ return schema.meta({ secret: true });
35
+ }
@@ -60,6 +60,20 @@ export declare const ConfigSchema: z.ZodObject<{
60
60
  dns: z.ZodArray<z.ZodString>;
61
61
  proxy: z.ZodString;
62
62
  }, z.core.$strict>;
63
+ vpn: z.ZodObject<{
64
+ enabled: z.ZodBoolean;
65
+ provider: z.ZodEnum<{
66
+ nordvpn: "nordvpn";
67
+ "openvpn-file": "openvpn-file";
68
+ }>;
69
+ protocol: z.ZodEnum<{
70
+ udp: "udp";
71
+ tcp: "tcp";
72
+ }>;
73
+ country: z.ZodString;
74
+ configFile: z.ZodString;
75
+ killSwitch: z.ZodBoolean;
76
+ }, z.core.$strict>;
63
77
  provisioning: z.ZodObject<{
64
78
  copyFromHost: z.ZodBoolean;
65
79
  fallbackToInstall: z.ZodBoolean;
@@ -218,6 +232,10 @@ export declare const ConfigSchema: z.ZodObject<{
218
232
  auto: z.ZodBoolean;
219
233
  autoHide: z.ZodBoolean;
220
234
  }, z.core.$strict>;
235
+ web: z.ZodObject<{
236
+ enabled: z.ZodBoolean;
237
+ port: z.ZodNumber;
238
+ }, z.core.$strict>;
221
239
  agentCommands: z.ZodObject<{
222
240
  enabled: z.ZodBoolean;
223
241
  agents: z.ZodUnion<readonly [z.ZodLiteral<"auto">, z.ZodArray<z.ZodString>]>;
@@ -258,6 +276,7 @@ export declare const ConfigSchema: z.ZodObject<{
258
276
  globalStateFile: z.ZodString;
259
277
  copyCredentials: z.ZodBoolean;
260
278
  overwrite: z.ZodBoolean;
279
+ sharePluginsAcrossAccounts: z.ZodBoolean;
261
280
  syncHistory: z.ZodBoolean;
262
281
  historyScope: z.ZodEnum<{
263
282
  project: "project";
@@ -281,6 +300,7 @@ export declare const ConfigSchema: z.ZodObject<{
281
300
  loginFiles: z.ZodArray<z.ZodString>;
282
301
  hostDir: z.ZodOptional<z.ZodString>;
283
302
  }, z.core.$strict>>;
303
+ localState: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
284
304
  resumeArguments: z.ZodOptional<z.ZodArray<z.ZodString>>;
285
305
  resumeOneArguments: z.ZodOptional<z.ZodArray<z.ZodString>>;
286
306
  }, z.core.$strict>>;
@@ -345,6 +365,9 @@ export declare const LocalOverridesSchema: z.ZodObject<{
345
365
  blockPrivateRanges: z.ZodOptional<z.ZodBoolean>;
346
366
  blockHosts: z.ZodOptional<z.ZodArray<z.ZodString>>;
347
367
  }, z.core.$strict>>;
368
+ vpn: z.ZodOptional<z.ZodObject<{
369
+ killSwitch: z.ZodOptional<z.ZodBoolean>;
370
+ }, z.core.$strict>>;
348
371
  provisioning: z.ZodOptional<z.ZodObject<{
349
372
  copyFromHost: z.ZodOptional<z.ZodBoolean>;
350
373
  fallbackToInstall: z.ZodOptional<z.ZodBoolean>;