windows-development-sandbox 1.5.0 → 1.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (709) hide show
  1. package/README.md +1 -0
  2. package/config.example.json +27 -1
  3. package/dist/app/context.d.ts +8 -0
  4. package/dist/app/context.js +12 -0
  5. package/dist/app/features/defs.d.ts +322 -0
  6. package/dist/app/features/defs.js +28 -0
  7. package/dist/app/features/sandbox/index.d.ts +2 -0
  8. package/dist/app/features/sandbox/index.js +3 -0
  9. package/dist/app/features/sandbox/sandbox.def.d.ts +193 -0
  10. package/dist/app/features/sandbox/sandbox.def.js +245 -0
  11. package/dist/app/features/sandbox/sandbox.run.d.ts +72 -0
  12. package/dist/app/features/sandbox/sandbox.run.js +98 -0
  13. package/dist/app/features/sessions/index.d.ts +2 -0
  14. package/dist/app/features/sessions/index.js +3 -0
  15. package/dist/app/features/sessions/sessions.def.d.ts +141 -0
  16. package/dist/app/features/sessions/sessions.def.js +176 -0
  17. package/dist/app/features/sessions/sessions.run.d.ts +39 -0
  18. package/dist/app/features/sessions/sessions.run.js +58 -0
  19. package/dist/{cli/menu/settings/categories.d.ts → app/features/settings/categories.def.d.ts} +4 -0
  20. package/dist/{cli/menu/settings/categories.js → app/features/settings/categories.def.js} +40 -46
  21. package/dist/app/features/settings/index.d.ts +5 -0
  22. package/dist/app/features/settings/index.js +6 -0
  23. package/dist/{cli/menu/settings/config-file.d.ts → app/features/settings/settings-file.d.ts} +1 -1
  24. package/dist/{cli/menu/settings/config-file.js → app/features/settings/settings-file.js} +1 -1
  25. package/dist/app/features/settings/settings-rows.d.ts +35 -0
  26. package/dist/app/features/settings/settings-rows.js +94 -0
  27. package/dist/app/features/settings/settings.def.d.ts +157 -0
  28. package/dist/app/features/settings/settings.def.js +179 -0
  29. package/dist/app/features/settings/settings.run.d.ts +67 -0
  30. package/dist/app/features/settings/settings.run.js +84 -0
  31. package/dist/app/kernel/define.d.ts +143 -0
  32. package/dist/app/kernel/define.js +42 -0
  33. package/dist/app/kernel/errors.d.ts +34 -0
  34. package/dist/app/kernel/errors.js +45 -0
  35. package/dist/app/kernel/fields.d.ts +70 -0
  36. package/dist/app/kernel/fields.js +243 -0
  37. package/dist/app/kernel/index.d.ts +8 -0
  38. package/dist/app/kernel/index.js +10 -0
  39. package/dist/app/kernel/io.d.ts +193 -0
  40. package/dist/app/kernel/io.js +126 -0
  41. package/dist/app/kernel/rpc.d.ts +156 -0
  42. package/dist/app/kernel/rpc.js +47 -0
  43. package/dist/{cli/menu/settings → app/kernel}/schema-node.d.ts +9 -0
  44. package/dist/{cli/menu/settings → app/kernel}/schema-node.js +26 -0
  45. package/dist/app/kernel/text.d.ts +6 -0
  46. package/dist/app/kernel/text.js +57 -0
  47. package/dist/app/kernel/view.d.ts +146 -0
  48. package/dist/app/kernel/view.js +28 -0
  49. package/dist/app/registry.d.ts +10 -0
  50. package/dist/app/registry.js +50 -0
  51. package/dist/cli/args.d.ts +18 -2
  52. package/dist/cli/args.js +101 -24
  53. package/dist/cli/commands/accounts.js +45 -17
  54. package/dist/cli/commands/context.d.ts +2 -0
  55. package/dist/cli/commands/context.js +9 -2
  56. package/dist/cli/commands/data/clean.js +32 -9
  57. package/dist/cli/commands/engine.d.ts +2 -0
  58. package/dist/cli/commands/engine.js +60 -0
  59. package/dist/cli/commands/index.d.ts +2 -1
  60. package/dist/cli/commands/index.js +2 -1
  61. package/dist/cli/commands/launch/add-root.d.ts +3 -2
  62. package/dist/cli/commands/launch/add-root.js +11 -10
  63. package/dist/cli/commands/launch/launch.js +102 -9
  64. package/dist/cli/commands/launch/prepare.js +6 -4
  65. package/dist/cli/commands/launch/running.js +2 -1
  66. package/dist/cli/commands/launch/summary.d.ts +2 -0
  67. package/dist/cli/commands/maintenance/audit.js +1 -1
  68. package/dist/cli/commands/maintenance/clean.d.ts +1 -1
  69. package/dist/cli/commands/maintenance/clean.js +17 -3
  70. package/dist/cli/commands/maintenance/config-share.d.ts +12 -0
  71. package/dist/cli/commands/maintenance/config-share.js +80 -0
  72. package/dist/cli/commands/maintenance/config.d.ts +1 -1
  73. package/dist/cli/commands/maintenance/config.js +38 -10
  74. package/dist/cli/commands/maintenance/doctor.d.ts +1 -1
  75. package/dist/cli/commands/maintenance/doctor.js +2 -4
  76. package/dist/cli/commands/maintenance/logs.js +14 -0
  77. package/dist/cli/commands/maintenance/migrate.d.ts +2 -1
  78. package/dist/cli/commands/maintenance/migrate.js +19 -4
  79. package/dist/cli/commands/maintenance/sync.js +2 -0
  80. package/dist/cli/commands/maintenance/update.d.ts +2 -0
  81. package/dist/cli/commands/maintenance/update.js +27 -4
  82. package/dist/cli/commands/projects/here.js +12 -7
  83. package/dist/cli/commands/projects/projects.js +26 -17
  84. package/dist/cli/commands/registry.js +10 -7
  85. package/dist/cli/commands/repair/checks/agents.d.ts +2 -0
  86. package/dist/cli/commands/repair/checks/agents.js +70 -0
  87. package/dist/cli/commands/repair/checks/common.d.ts +8 -0
  88. package/dist/cli/commands/repair/checks/common.js +22 -0
  89. package/dist/cli/commands/repair/checks/contained.d.ts +2 -0
  90. package/dist/cli/commands/repair/checks/contained.js +139 -0
  91. package/dist/cli/commands/repair/checks/data.d.ts +2 -0
  92. package/dist/cli/commands/repair/checks/data.js +241 -0
  93. package/dist/cli/commands/repair/checks/hcs.d.ts +7 -0
  94. package/dist/cli/commands/repair/checks/hcs.js +28 -0
  95. package/dist/cli/commands/repair/checks/index.d.ts +2 -0
  96. package/dist/cli/commands/repair/checks/index.js +24 -0
  97. package/dist/cli/commands/repair/checks/install.d.ts +5 -0
  98. package/dist/cli/commands/repair/checks/install.js +318 -0
  99. package/dist/cli/commands/repair/checks/machine.d.ts +2 -0
  100. package/dist/cli/commands/repair/checks/machine.js +232 -0
  101. package/dist/cli/commands/repair/checks/network.d.ts +6 -0
  102. package/dist/cli/commands/repair/checks/network.js +60 -0
  103. package/dist/cli/commands/repair/checks/pc.d.ts +4 -0
  104. package/dist/cli/commands/repair/checks/pc.js +86 -0
  105. package/dist/cli/commands/repair/checks/sandbox.d.ts +2 -0
  106. package/dist/cli/commands/repair/checks/sandbox.js +282 -0
  107. package/dist/cli/commands/repair/checks/settings.d.ts +2 -0
  108. package/dist/cli/commands/repair/checks/settings.js +169 -0
  109. package/dist/cli/commands/repair/checks/vpn.d.ts +2 -0
  110. package/dist/cli/commands/repair/checks/vpn.js +78 -0
  111. package/dist/cli/commands/repair/engine.d.ts +32 -0
  112. package/dist/cli/commands/repair/engine.js +127 -0
  113. package/dist/cli/commands/repair/env.d.ts +7 -0
  114. package/dist/cli/commands/repair/env.js +50 -0
  115. package/dist/cli/commands/repair/index.d.ts +1 -9
  116. package/dist/cli/commands/repair/index.js +2 -54
  117. package/dist/cli/commands/repair/log.d.ts +17 -0
  118. package/dist/cli/commands/repair/log.js +82 -0
  119. package/dist/cli/commands/repair/printer.d.ts +32 -0
  120. package/dist/cli/commands/repair/printer.js +132 -0
  121. package/dist/cli/commands/repair/run.d.ts +33 -0
  122. package/dist/cli/commands/repair/run.js +133 -0
  123. package/dist/cli/commands/repair/types.d.ts +97 -9
  124. package/dist/cli/commands/repair/types.js +11 -7
  125. package/dist/cli/commands/resume.js +2 -2
  126. package/dist/cli/commands/sessions/index.d.ts +0 -4
  127. package/dist/cli/commands/sessions/index.js +3 -7
  128. package/dist/cli/commands/setup/index.d.ts +5 -0
  129. package/dist/cli/commands/setup/index.js +25 -1
  130. package/dist/cli/commands/shared-use.d.ts +5 -2
  131. package/dist/cli/commands/shared-use.js +11 -8
  132. package/dist/cli/commands/storage/contained.d.ts +3 -0
  133. package/dist/cli/commands/storage/contained.js +179 -0
  134. package/dist/cli/commands/storage/index.d.ts +2 -0
  135. package/dist/cli/commands/storage/index.js +2 -0
  136. package/dist/cli/commands/storage/offer.d.ts +3 -0
  137. package/dist/cli/commands/storage/offer.js +91 -0
  138. package/dist/cli/commands/storage/storage.d.ts +8 -0
  139. package/dist/cli/commands/storage/storage.js +179 -0
  140. package/dist/cli/commands/user-config.js +2 -2
  141. package/dist/cli/commands/vpn.d.ts +4 -0
  142. package/dist/cli/commands/vpn.js +91 -0
  143. package/dist/cli/commands/web.d.ts +4 -0
  144. package/dist/cli/commands/web.js +97 -0
  145. package/dist/cli/history.js +1 -1
  146. package/dist/cli/index.js +48 -4
  147. package/dist/cli/manifest.d.ts +339 -97
  148. package/dist/cli/manifest.js +222 -67
  149. package/dist/cli/menu/add-agent.d.ts +47 -0
  150. package/dist/cli/menu/add-agent.js +168 -0
  151. package/dist/cli/menu/apps.d.ts +38 -3
  152. package/dist/cli/menu/apps.js +80 -5
  153. package/dist/cli/menu/command-fields.d.ts +18 -0
  154. package/dist/cli/menu/command-fields.js +61 -0
  155. package/dist/cli/menu/command-form.d.ts +22 -0
  156. package/dist/cli/menu/command-form.js +169 -46
  157. package/dist/cli/menu/data-folder.d.ts +18 -0
  158. package/dist/cli/menu/data-folder.js +99 -0
  159. package/dist/cli/menu/io-menu.d.ts +29 -0
  160. package/dist/cli/menu/io-menu.js +126 -0
  161. package/dist/cli/menu/live.d.ts +27 -0
  162. package/dist/cli/menu/live.js +69 -0
  163. package/dist/cli/menu/memory.d.ts +19 -0
  164. package/dist/cli/menu/memory.js +53 -0
  165. package/dist/cli/menu/menu.d.ts +11 -2
  166. package/dist/cli/menu/menu.js +36 -15
  167. package/dist/cli/menu/pages/accounts-page.js +55 -24
  168. package/dist/cli/menu/pages/agents-page.d.ts +68 -0
  169. package/dist/cli/menu/pages/agents-page.js +345 -0
  170. package/dist/cli/menu/pages/apps-page.d.ts +3 -1
  171. package/dist/cli/menu/pages/apps-page.js +20 -4
  172. package/dist/cli/menu/pages/list-page.d.ts +43 -3
  173. package/dist/cli/menu/pages/list-page.js +146 -12
  174. package/dist/cli/menu/pages/maintenance-page.d.ts +9 -5
  175. package/dist/cli/menu/pages/maintenance-page.js +172 -85
  176. package/dist/cli/menu/pages/sandbox-page.d.ts +7 -6
  177. package/dist/cli/menu/pages/sandbox-page.js +117 -120
  178. package/dist/cli/menu/pages/scopes.d.ts +1 -1
  179. package/dist/cli/menu/pages/sessions-page.d.ts +6 -8
  180. package/dist/cli/menu/pages/sessions-page.js +22 -75
  181. package/dist/cli/menu/pages/settings-page.d.ts +10 -14
  182. package/dist/cli/menu/pages/settings-page.js +95 -102
  183. package/dist/cli/menu/render-view.d.ts +28 -0
  184. package/dist/cli/menu/render-view.js +112 -0
  185. package/dist/cli/menu/settings/ask-path.d.ts +14 -0
  186. package/dist/cli/menu/settings/ask-path.js +14 -0
  187. package/dist/cli/menu/settings/collections/collection-editor.d.ts +8 -2
  188. package/dist/cli/menu/settings/collections/collection-editor.js +12 -8
  189. package/dist/cli/menu/settings/collections/map-editor.js +5 -1
  190. package/dist/cli/menu/settings/collections/object-list-editor.js +2 -2
  191. package/dist/cli/menu/settings/collections/object-map-editor.js +2 -2
  192. package/dist/cli/menu/settings/collections/string-list-editor.d.ts +10 -1
  193. package/dist/cli/menu/settings/collections/string-list-editor.js +23 -0
  194. package/dist/cli/menu/settings/draft.d.ts +1 -1
  195. package/dist/cli/menu/settings/format.d.ts +1 -3
  196. package/dist/cli/menu/settings/format.js +6 -36
  197. package/dist/cli/menu/settings/index.d.ts +1 -3
  198. package/dist/cli/menu/settings/index.js +3 -3
  199. package/dist/cli/menu/settings/object-editor.d.ts +6 -2
  200. package/dist/cli/menu/settings/object-editor.js +15 -4
  201. package/dist/cli/menu/settings/share.d.ts +36 -0
  202. package/dist/cli/menu/settings/share.js +131 -0
  203. package/dist/cli/menu/settings/value-editor.d.ts +10 -1
  204. package/dist/cli/menu/settings/value-editor.js +99 -63
  205. package/dist/cli/menu/several.js +7 -5
  206. package/dist/cli/menu/share-settings.d.ts +21 -0
  207. package/dist/cli/menu/share-settings.js +112 -0
  208. package/dist/cli/menu/shell.d.ts +53 -10
  209. package/dist/cli/menu/shell.js +115 -10
  210. package/dist/cli/menu/views.d.ts +7 -0
  211. package/dist/cli/menu/views.js +11 -0
  212. package/dist/cli/menu/vpn-login.d.ts +16 -0
  213. package/dist/cli/menu/vpn-login.js +74 -0
  214. package/dist/cli/operations/handler.d.ts +6 -0
  215. package/dist/cli/operations/handler.js +61 -0
  216. package/dist/cli/operations/index.d.ts +4 -0
  217. package/dist/cli/operations/index.js +5 -0
  218. package/dist/cli/operations/input.d.ts +6 -0
  219. package/dist/cli/operations/input.js +37 -0
  220. package/dist/cli/operations/io-cli.d.ts +7 -0
  221. package/dist/cli/operations/io-cli.js +62 -0
  222. package/dist/cli/operations/spec.d.ts +18 -0
  223. package/dist/cli/operations/spec.js +108 -0
  224. package/dist/cli/output/colors.d.ts +2 -2
  225. package/dist/cli/output/colors.js +2 -11
  226. package/dist/cli/output/index.d.ts +1 -0
  227. package/dist/cli/output/index.js +1 -0
  228. package/dist/cli/output/print.d.ts +5 -1
  229. package/dist/cli/output/print.js +15 -4
  230. package/dist/cli/output/progress.d.ts +15 -0
  231. package/dist/cli/output/progress.js +44 -0
  232. package/dist/cli/output/render-view.d.ts +4 -0
  233. package/dist/cli/output/render-view.js +63 -0
  234. package/dist/cli/services/accounts-service.d.ts +2 -0
  235. package/dist/cli/services/accounts-service.js +2 -2
  236. package/dist/cli/services/agent-commands-service.d.ts +2 -0
  237. package/dist/cli/services/agent-commands-service.js +11 -2
  238. package/dist/cli/services/health-service.d.ts +0 -6
  239. package/dist/cli/services/health-service.js +5 -42
  240. package/dist/cli/services/index.d.ts +3 -1
  241. package/dist/cli/services/index.js +3 -1
  242. package/dist/cli/services/logs-service.js +4 -3
  243. package/dist/cli/services/migrate-service.js +1 -1
  244. package/dist/cli/services/update-service.d.ts +2 -0
  245. package/dist/cli/services/update-service.js +13 -6
  246. package/dist/cli/services/vpn-service.d.ts +28 -0
  247. package/dist/cli/services/vpn-service.js +46 -0
  248. package/dist/cli/services/web-service.d.ts +22 -0
  249. package/dist/cli/services/web-service.js +111 -0
  250. package/dist/cli/tui/app.d.ts +12 -4
  251. package/dist/cli/tui/app.js +38 -9
  252. package/dist/cli/tui/dialogs/path-listing.d.ts +43 -0
  253. package/dist/cli/tui/dialogs/path-listing.js +127 -0
  254. package/dist/cli/tui/dialogs/path-picker.d.ts +67 -0
  255. package/dist/cli/tui/dialogs/path-picker.js +423 -0
  256. package/dist/cli/tui/dialogs/text-screen.d.ts +6 -0
  257. package/dist/cli/tui/dialogs/text-screen.js +10 -3
  258. package/dist/cli/tui/frame.d.ts +7 -10
  259. package/dist/cli/tui/frame.js +19 -10
  260. package/dist/cli/tui/index.d.ts +4 -3
  261. package/dist/cli/tui/index.js +2 -1
  262. package/dist/cli/tui/list/list-screen.d.ts +28 -2
  263. package/dist/cli/tui/list/list-screen.js +130 -66
  264. package/dist/cli/tui/list/list-types.d.ts +10 -4
  265. package/dist/cli/tui/nav.d.ts +29 -0
  266. package/dist/cli/tui/nav.js +67 -0
  267. package/dist/cli/tui/terminal.d.ts +7 -0
  268. package/dist/cli/tui/terminal.js +30 -10
  269. package/dist/cli/validate.d.ts +1 -1
  270. package/dist/cli/validate.js +3 -3
  271. package/dist/cli/version.d.ts +2 -0
  272. package/dist/cli/version.js +11 -0
  273. package/dist/core/config/defaults.js +13 -1
  274. package/dist/core/config/loader.js +12 -2
  275. package/dist/core/local-config/overrides.js +1 -0
  276. package/dist/core/prompt.d.ts +19 -0
  277. package/dist/core/prompt.js +43 -3
  278. package/dist/core/schema/common.d.ts +6 -0
  279. package/dist/core/schema/common.js +8 -0
  280. package/dist/core/schema/config.d.ts +36 -0
  281. package/dist/core/schema/config.js +26 -2
  282. package/dist/core/schema/harness.d.ts +2 -0
  283. package/dist/core/schema/harness.js +13 -2
  284. package/dist/core/schema/index.d.ts +3 -1
  285. package/dist/core/schema/index.js +3 -1
  286. package/dist/core/schema/profile.d.ts +1 -0
  287. package/dist/core/schema/profile.js +3 -0
  288. package/dist/core/schema/redact.d.ts +13 -0
  289. package/dist/core/schema/redact.js +75 -0
  290. package/dist/core/schema/sandbox.d.ts +6 -0
  291. package/dist/core/schema/sandbox.js +21 -3
  292. package/dist/core/schema/vpn.d.ts +18 -0
  293. package/dist/core/schema/vpn.js +22 -0
  294. package/dist/core/schema/web.d.ts +6 -0
  295. package/dist/core/schema/web.js +14 -0
  296. package/dist/core/types.d.ts +44 -0
  297. package/dist/core/util/fs.d.ts +2 -0
  298. package/dist/core/util/fs.js +9 -0
  299. package/dist/core/util/index.d.ts +1 -1
  300. package/dist/core/util/index.js +1 -1
  301. package/dist/guest/agents/agent-files.d.ts +54 -0
  302. package/dist/guest/agents/agent-files.js +67 -0
  303. package/dist/guest/agents/agent-installer.js +2 -9
  304. package/dist/guest/agents/local-state.d.ts +14 -0
  305. package/dist/guest/agents/local-state.js +218 -0
  306. package/dist/guest/agents/sbx-agent.d.ts +2 -0
  307. package/dist/guest/agents/sbx-agent.js +35 -0
  308. package/dist/guest/boot/boot.d.ts +4 -0
  309. package/dist/guest/boot/boot.js +51 -11
  310. package/dist/guest/daemon/daemon.js +8 -1
  311. package/dist/guest/daemon/exec.js +2 -1
  312. package/dist/guest/daemon/idle-shutdown.js +2 -0
  313. package/dist/guest/daemon/sessions.d.ts +5 -0
  314. package/dist/guest/daemon/sessions.js +20 -3
  315. package/dist/guest/entries/agent.d.ts +1 -0
  316. package/dist/guest/entries/agent.js +10 -0
  317. package/dist/guest/entries/daemon.js +5 -0
  318. package/dist/guest/governor/decide.d.ts +61 -0
  319. package/dist/guest/governor/decide.js +182 -0
  320. package/dist/guest/governor/governor.d.ts +42 -0
  321. package/dist/guest/governor/governor.js +214 -0
  322. package/dist/guest/governor/index.d.ts +2 -0
  323. package/dist/guest/governor/index.js +2 -0
  324. package/dist/guest/runtime/csc.d.ts +2 -0
  325. package/dist/guest/runtime/csc.js +2 -0
  326. package/dist/guest/runtime/secrets.d.ts +12 -0
  327. package/dist/guest/runtime/secrets.js +63 -0
  328. package/dist/guest/sessions/viewer.js +3 -1
  329. package/dist/guest/setup/claude-profile.d.ts +2 -1
  330. package/dist/guest/setup/claude-profile.js +12 -1
  331. package/dist/guest/setup/environment.d.ts +6 -0
  332. package/dist/guest/setup/environment.js +56 -6
  333. package/dist/guest/setup/path-plan.d.ts +32 -0
  334. package/dist/guest/setup/path-plan.js +67 -0
  335. package/dist/guest/setup/shell-path.d.ts +1 -0
  336. package/dist/guest/setup/shell-path.js +22 -0
  337. package/dist/guest/toolchains/languages/python.js +1 -1
  338. package/dist/guest/toolchains/native/rust-extras.js +4 -2
  339. package/dist/guest/toolchains/runtimes.js +2 -2
  340. package/dist/guest/vpn/index.d.ts +1 -0
  341. package/dist/guest/vpn/index.js +1 -0
  342. package/dist/guest/vpn/openvpn.d.ts +9 -0
  343. package/dist/guest/vpn/openvpn.js +47 -0
  344. package/dist/guest/vpn/tunnel.d.ts +17 -0
  345. package/dist/guest/vpn/tunnel.js +78 -0
  346. package/dist/guest/vpn/vpn.d.ts +6 -0
  347. package/dist/guest/vpn/vpn.js +174 -0
  348. package/dist/guest/vpn/wireguard.d.ts +32 -0
  349. package/dist/guest/vpn/wireguard.js +132 -0
  350. package/dist/host/agent-commands/commands.d.ts +4 -0
  351. package/dist/host/agent-commands/commands.js +31 -7
  352. package/dist/host/audit/log.d.ts +1 -1
  353. package/dist/host/channel/attach.d.ts +6 -2
  354. package/dist/host/channel/attach.js +6 -3
  355. package/dist/host/channel/channel.d.ts +9 -0
  356. package/dist/host/channel/channel.js +30 -2
  357. package/dist/host/engines/engine.d.ts +12 -0
  358. package/dist/host/engines/engine.js +1 -0
  359. package/dist/host/engines/hcs/check.d.ts +25 -0
  360. package/dist/host/engines/hcs/check.js +95 -0
  361. package/dist/host/engines/hcs/documents.d.ts +44 -0
  362. package/dist/host/engines/hcs/documents.js +155 -0
  363. package/dist/host/engines/hcs/engine.d.ts +39 -0
  364. package/dist/host/engines/hcs/engine.js +171 -0
  365. package/dist/host/engines/hcs/helper.d.ts +43 -0
  366. package/dist/host/engines/hcs/helper.js +173 -0
  367. package/dist/host/engines/hcs/images.d.ts +37 -0
  368. package/dist/host/engines/hcs/images.js +152 -0
  369. package/dist/host/engines/index.d.ts +7 -0
  370. package/dist/host/engines/index.js +5 -0
  371. package/dist/host/engines/registry.d.ts +16 -0
  372. package/dist/host/engines/registry.js +30 -0
  373. package/dist/host/engines/types.d.ts +58 -0
  374. package/dist/host/engines/types.js +1 -0
  375. package/dist/host/engines/windows-sandbox/engine.d.ts +16 -0
  376. package/dist/host/engines/windows-sandbox/engine.js +63 -0
  377. package/dist/host/engines/windows-sandbox/wsb-text.d.ts +2 -0
  378. package/dist/host/engines/windows-sandbox/wsb-text.js +29 -0
  379. package/dist/host/health/acl-read.d.ts +17 -0
  380. package/dist/host/health/acl-read.js +45 -0
  381. package/dist/host/health/config-backup.d.ts +11 -0
  382. package/dist/host/health/config-backup.js +73 -0
  383. package/dist/host/health/index.d.ts +6 -0
  384. package/dist/host/health/index.js +7 -0
  385. package/dist/host/health/install-state.d.ts +33 -0
  386. package/dist/host/health/install-state.js +110 -0
  387. package/dist/host/health/path-copies.d.ts +32 -0
  388. package/dist/host/health/path-copies.js +82 -0
  389. package/dist/host/health/stale.d.ts +45 -0
  390. package/dist/host/health/stale.js +120 -0
  391. package/dist/host/health/system.d.ts +37 -0
  392. package/dist/host/health/system.js +87 -0
  393. package/dist/host/install/copies.d.ts +13 -0
  394. package/dist/host/install/copies.js +63 -0
  395. package/dist/host/install/index.d.ts +1 -0
  396. package/dist/host/install/index.js +1 -0
  397. package/dist/host/launch/generate.d.ts +5 -1
  398. package/dist/host/launch/generate.js +73 -7
  399. package/dist/host/launch/index.d.ts +3 -1
  400. package/dist/host/launch/index.js +3 -1
  401. package/dist/host/launch/launch-plan.d.ts +13 -0
  402. package/dist/host/launch/launch-plan.js +26 -0
  403. package/dist/host/launch/mappings.js +2 -1
  404. package/dist/host/launch/risk-notes.d.ts +10 -0
  405. package/dist/host/launch/risk-notes.js +18 -0
  406. package/dist/host/launch/session-file.d.ts +2 -0
  407. package/dist/host/launch/session-file.js +11 -2
  408. package/dist/host/launch/stage.js +1 -1
  409. package/dist/host/launch/wsb-file.d.ts +28 -4
  410. package/dist/host/launch/wsb-file.js +61 -42
  411. package/dist/host/life/crash-report.d.ts +27 -1
  412. package/dist/host/life/crash-report.js +173 -7
  413. package/dist/host/life/host-memory.d.ts +40 -0
  414. package/dist/host/life/host-memory.js +137 -0
  415. package/dist/host/life/index.d.ts +2 -0
  416. package/dist/host/life/index.js +2 -0
  417. package/dist/host/life/stop-events.d.ts +2 -0
  418. package/dist/host/life/stop-events.js +20 -3
  419. package/dist/host/life/stop-warning.js +1 -1
  420. package/dist/host/life/watchdog.d.ts +54 -0
  421. package/dist/host/life/watchdog.js +108 -0
  422. package/dist/host/migrate/backup.js +3 -0
  423. package/dist/host/migrate/migrations/config-file.d.ts +2 -0
  424. package/dist/host/migrate/migrations/config-file.js +7 -0
  425. package/dist/host/migrate/migrations/follow-machine-storage.js +9 -1
  426. package/dist/host/migrate/migrations/pin-storage-root.d.ts +4 -0
  427. package/dist/host/migrate/migrations/pin-storage-root.js +46 -0
  428. package/dist/host/migrate/migrations/unpin-config-defaults.js +4 -1
  429. package/dist/host/migrate/registry.js +2 -1
  430. package/dist/host/native.d.ts +3 -2
  431. package/dist/host/native.js +22 -3
  432. package/dist/host/profile/accounts.d.ts +25 -1
  433. package/dist/host/profile/accounts.js +96 -13
  434. package/dist/host/profile/agent-accounts.d.ts +5 -1
  435. package/dist/host/profile/agent-accounts.js +35 -5
  436. package/dist/host/profile/claude-login.js +3 -2
  437. package/dist/host/profile/index.d.ts +2 -1
  438. package/dist/host/profile/index.js +1 -0
  439. package/dist/host/profile/plugin-share.d.ts +26 -0
  440. package/dist/host/profile/plugin-share.js +146 -0
  441. package/dist/host/projects/join.d.ts +7 -1
  442. package/dist/host/projects/join.js +21 -4
  443. package/dist/host/projects/registry.d.ts +16 -10
  444. package/dist/host/projects/registry.js +74 -6
  445. package/dist/host/sandbox/contained-deps.d.ts +2 -0
  446. package/dist/host/sandbox/contained-deps.js +17 -0
  447. package/dist/host/sandbox/index.d.ts +2 -0
  448. package/dist/host/sandbox/index.js +2 -0
  449. package/dist/host/sandbox/platform.d.ts +4 -0
  450. package/dist/host/sandbox/platform.js +23 -4
  451. package/dist/host/sandbox/tasklist.d.ts +13 -0
  452. package/dist/host/sandbox/tasklist.js +47 -0
  453. package/dist/host/secrets/index.d.ts +2 -0
  454. package/dist/host/secrets/index.js +2 -0
  455. package/dist/host/secrets/launch-secrets.d.ts +17 -0
  456. package/dist/host/secrets/launch-secrets.js +94 -0
  457. package/dist/host/secrets/secret-store.d.ts +25 -0
  458. package/dist/host/secrets/secret-store.js +89 -0
  459. package/dist/host/sharing/acl.d.ts +16 -2
  460. package/dist/host/sharing/acl.js +35 -10
  461. package/dist/host/sharing/current.js +8 -3
  462. package/dist/host/sharing/doctor.d.ts +2 -0
  463. package/dist/host/sharing/doctor.js +44 -0
  464. package/dist/host/sharing/group-access.d.ts +6 -0
  465. package/dist/host/sharing/group-access.js +24 -0
  466. package/dist/host/sharing/index.d.ts +2 -1
  467. package/dist/host/sharing/index.js +2 -1
  468. package/dist/host/sharing/lifecycle.d.ts +8 -2
  469. package/dist/host/sharing/lifecycle.js +16 -7
  470. package/dist/host/storage/cleanup.d.ts +2 -0
  471. package/dist/host/storage/cleanup.js +2 -1
  472. package/dist/host/storage/contained/check.d.ts +9 -0
  473. package/dist/host/storage/contained/check.js +37 -0
  474. package/dist/host/storage/contained/contained-storage.d.ts +66 -0
  475. package/dist/host/storage/contained/contained-storage.js +168 -0
  476. package/dist/host/storage/contained/disk-port.d.ts +43 -0
  477. package/dist/host/storage/contained/disk-port.js +122 -0
  478. package/dist/host/storage/contained/index.d.ts +9 -0
  479. package/dist/host/storage/contained/index.js +8 -0
  480. package/dist/host/storage/contained/layout.d.ts +28 -0
  481. package/dist/host/storage/contained/layout.js +45 -0
  482. package/dist/host/storage/contained/resolve.d.ts +4 -0
  483. package/dist/host/storage/contained/resolve.js +30 -0
  484. package/dist/host/storage/contained/setting.d.ts +1 -0
  485. package/dist/host/storage/contained/setting.js +5 -0
  486. package/dist/host/storage/contained/state.d.ts +89 -0
  487. package/dist/host/storage/contained/state.js +166 -0
  488. package/dist/host/storage/contained/transfer.d.ts +24 -0
  489. package/dist/host/storage/contained/transfer.js +121 -0
  490. package/dist/host/storage/history.d.ts +21 -0
  491. package/dist/host/storage/history.js +49 -0
  492. package/dist/host/storage/index.d.ts +6 -0
  493. package/dist/host/storage/index.js +6 -0
  494. package/dist/host/storage/move.d.ts +95 -0
  495. package/dist/host/storage/move.js +384 -0
  496. package/dist/host/storage/offer.d.ts +11 -0
  497. package/dist/host/storage/offer.js +36 -0
  498. package/dist/host/storage/providers/contained.d.ts +15 -0
  499. package/dist/host/storage/providers/contained.js +39 -0
  500. package/dist/host/storage/providers/folder.d.ts +12 -0
  501. package/dist/host/storage/providers/folder.js +20 -0
  502. package/dist/host/storage/providers/index.d.ts +4 -0
  503. package/dist/host/storage/providers/index.js +3 -0
  504. package/dist/host/storage/providers/registry.d.ts +9 -0
  505. package/dist/host/storage/providers/registry.js +14 -0
  506. package/dist/host/storage/providers/types.d.ts +33 -0
  507. package/dist/host/storage/providers/types.js +1 -0
  508. package/dist/host/storage/root.d.ts +18 -0
  509. package/dist/host/storage/root.js +77 -0
  510. package/dist/host/tools/conpty.js +3 -2
  511. package/dist/host/tools/windows-terminal.d.ts +2 -0
  512. package/dist/host/tools/windows-terminal.js +31 -12
  513. package/dist/host/update/index.d.ts +1 -1
  514. package/dist/host/update/index.js +1 -1
  515. package/dist/host/update/notice.d.ts +2 -0
  516. package/dist/host/update/notice.js +13 -1
  517. package/dist/host/update/update-state.d.ts +6 -0
  518. package/dist/host/update/update-state.js +2 -0
  519. package/dist/host/update/updater.d.ts +19 -0
  520. package/dist/host/update/updater.js +88 -12
  521. package/dist/host/vpn/index.d.ts +4 -0
  522. package/dist/host/vpn/index.js +4 -0
  523. package/dist/host/vpn/login.d.ts +24 -0
  524. package/dist/host/vpn/login.js +79 -0
  525. package/dist/host/vpn/nordvpn.d.ts +21 -0
  526. package/dist/host/vpn/nordvpn.js +77 -0
  527. package/dist/host/vpn/prepare.d.ts +19 -0
  528. package/dist/host/vpn/prepare.js +138 -0
  529. package/dist/host/vpn/status.d.ts +12 -0
  530. package/dist/host/vpn/status.js +53 -0
  531. package/dist/host/web/auth.d.ts +38 -0
  532. package/dist/host/web/auth.js +96 -0
  533. package/dist/host/web/backend.d.ts +14 -0
  534. package/dist/host/web/backend.js +1 -0
  535. package/dist/host/web/bridge.d.ts +27 -0
  536. package/dist/host/web/bridge.js +144 -0
  537. package/dist/host/web/browser.d.ts +3 -0
  538. package/dist/host/web/browser.js +23 -0
  539. package/dist/host/web/control.d.ts +17 -0
  540. package/dist/host/web/control.js +67 -0
  541. package/dist/host/web/index.d.ts +10 -0
  542. package/dist/host/web/index.js +9 -0
  543. package/dist/host/web/rpc.d.ts +24 -0
  544. package/dist/host/web/rpc.js +149 -0
  545. package/dist/host/web/runner.d.ts +16 -0
  546. package/dist/host/web/runner.js +44 -0
  547. package/dist/host/web/server.d.ts +47 -0
  548. package/dist/host/web/server.js +238 -0
  549. package/dist/host/web/state.d.ts +20 -0
  550. package/dist/host/web/state.js +41 -0
  551. package/dist/host/web/static-files.d.ts +13 -0
  552. package/dist/host/web/static-files.js +57 -0
  553. package/dist/runtime/agent.js +27675 -0
  554. package/dist/runtime/daemon.js +1950 -1122
  555. package/dist/runtime/db.js +302 -111
  556. package/dist/runtime/main.js +1560 -275
  557. package/dist/runtime/netproxy.js +168 -8
  558. package/dist/runtime/view.js +186 -13
  559. package/dist/selftest/accounts.test.js +40 -0
  560. package/dist/selftest/agent-paths.test.d.ts +2 -0
  561. package/dist/selftest/agent-paths.test.js +125 -0
  562. package/dist/selftest/app.test.d.ts +2 -0
  563. package/dist/selftest/app.test.js +324 -0
  564. package/dist/selftest/channel.test.js +18 -0
  565. package/dist/selftest/cli.test.js +35 -4
  566. package/dist/selftest/config.test.js +59 -0
  567. package/dist/selftest/contained.test.d.ts +2 -0
  568. package/dist/selftest/contained.test.js +544 -0
  569. package/dist/selftest/credentials.test.d.ts +2 -0
  570. package/dist/selftest/credentials.test.js +198 -0
  571. package/dist/selftest/engine.test.d.ts +2 -0
  572. package/dist/selftest/engine.test.js +127 -0
  573. package/dist/selftest/generate.test.js +1 -1
  574. package/dist/selftest/hcs.test.d.ts +2 -0
  575. package/dist/selftest/hcs.test.js +482 -0
  576. package/dist/selftest/health.test.d.ts +2 -0
  577. package/dist/selftest/health.test.js +470 -0
  578. package/dist/selftest/heavy-load.test.d.ts +2 -0
  579. package/dist/selftest/heavy-load.test.js +329 -0
  580. package/dist/selftest/host-sim.test.js +2 -0
  581. package/dist/selftest/index.js +31 -0
  582. package/dist/selftest/layout.test.js +14 -0
  583. package/dist/selftest/menu-perf.test.d.ts +2 -0
  584. package/dist/selftest/menu-perf.test.js +248 -0
  585. package/dist/selftest/menu-screens.d.ts +7 -0
  586. package/dist/selftest/menu-screens.js +68 -17
  587. package/dist/selftest/menu.test.js +603 -22
  588. package/dist/selftest/migrate.test.js +1 -1
  589. package/dist/selftest/personalization.test.js +3 -1
  590. package/dist/selftest/projects.test.js +39 -1
  591. package/dist/selftest/shared-use.test.js +64 -2
  592. package/dist/selftest/sharing.test.js +50 -1
  593. package/dist/selftest/storage.test.d.ts +2 -0
  594. package/dist/selftest/storage.test.js +363 -0
  595. package/dist/selftest/support/engine-cases.d.ts +8 -0
  596. package/dist/selftest/support/engine-cases.js +65 -0
  597. package/dist/selftest/support/engine-golden.d.ts +3 -0
  598. package/dist/selftest/support/engine-golden.js +66 -0
  599. package/dist/selftest/support/fixtures.d.ts +20 -0
  600. package/dist/selftest/support/hcs-probes.d.ts +17 -0
  601. package/dist/selftest/support/hcs-probes.js +41 -0
  602. package/dist/selftest/support/releases.js +1 -1
  603. package/dist/selftest/toolchains.test.js +21 -0
  604. package/dist/selftest/update-service.test.js +87 -3
  605. package/dist/selftest/vpn.test.d.ts +2 -0
  606. package/dist/selftest/vpn.test.js +412 -0
  607. package/dist/selftest/web.test.d.ts +2 -0
  608. package/dist/selftest/web.test.js +402 -0
  609. package/dist/shared/apps/catalogue.js +31 -0
  610. package/dist/shared/channel/index.d.ts +1 -0
  611. package/dist/shared/channel/index.js +1 -0
  612. package/dist/shared/channel/run-dir.d.ts +9 -1
  613. package/dist/shared/channel/run-dir.js +18 -1
  614. package/dist/shared/channel/schema.d.ts +53 -0
  615. package/dist/shared/channel/schema.js +38 -0
  616. package/dist/shared/channel/secrets.d.ts +29 -0
  617. package/dist/shared/channel/secrets.js +50 -0
  618. package/dist/shared/memory/index.d.ts +1 -0
  619. package/dist/shared/memory/index.js +1 -0
  620. package/dist/shared/memory/policy.d.ts +33 -0
  621. package/dist/shared/memory/policy.js +55 -0
  622. package/dist/shared/pty/output-filter.d.ts +14 -1
  623. package/dist/shared/pty/output-filter.js +22 -4
  624. package/dist/shared/pty/terminal.d.ts +4 -1
  625. package/dist/shared/pty/terminal.js +4 -2
  626. package/dist/shared/system.d.ts +1 -0
  627. package/dist/shared/system.js +1 -0
  628. package/dist/shared/vpn/download.d.ts +29 -0
  629. package/dist/shared/vpn/download.js +30 -0
  630. package/dist/shared/vpn/kill-switch.d.ts +18 -0
  631. package/dist/shared/vpn/kill-switch.js +81 -0
  632. package/dist/shared/vpn/ovpn.d.ts +23 -0
  633. package/dist/shared/vpn/ovpn.js +244 -0
  634. package/dist/shared/vpn/wireguard.d.ts +51 -0
  635. package/dist/shared/vpn/wireguard.js +227 -0
  636. package/dist/shared/web/index.d.ts +1 -0
  637. package/dist/shared/web/index.js +1 -0
  638. package/dist/shared/web/protocol.d.ts +61 -0
  639. package/dist/shared/web/protocol.js +35 -0
  640. package/dist/sync/sync-cycle.js +9 -5
  641. package/dist/sync/sync-state.d.ts +1 -0
  642. package/dist/sync/sync-state.js +1 -0
  643. package/dist/sync/watcher.d.ts +13 -0
  644. package/dist/sync/watcher.js +102 -3
  645. package/dist/web/index.html +14 -0
  646. package/dist/web/main-NRRS5O6Z.js +157 -0
  647. package/dist/web/main-T5DMCHYV.css +1 -0
  648. package/native/csharp/FolderSecurity.cs +29 -0
  649. package/native/csharp/HcsHost/AssemblyInfo.cs +14 -0
  650. package/native/csharp/HcsHost/Guard.cs +100 -0
  651. package/native/csharp/HcsHost/Hcs.cs +256 -0
  652. package/native/csharp/HcsHost/Json.cs +78 -0
  653. package/native/csharp/HcsHost/Program.cs +185 -0
  654. package/native/csharp/HcsHost/VirtualDisk.cs +95 -0
  655. package/native/csharp/HostTools/AssemblyInfo.cs +14 -0
  656. package/native/csharp/HostTools/MemoryStatus.cs +107 -0
  657. package/native/csharp/HostTools/Program.cs +58 -17
  658. package/native/scripts/check-contained.ps1 +28 -0
  659. package/native/scripts/contained-common.ps1 +241 -0
  660. package/native/scripts/dismount-contained.ps1 +66 -0
  661. package/native/scripts/memory-status.ps1 +34 -0
  662. package/native/scripts/mount-contained.ps1 +139 -0
  663. package/native/scripts/protect-data.ps1 +29 -0
  664. package/native/scripts/read-folder-sddl.ps1 +10 -0
  665. package/native/scripts/run-elevated.ps1 +17 -4
  666. package/native/scripts/set-folder-access.ps1 +49 -7
  667. package/native/scripts/stop-events.ps1 +23 -8
  668. package/node_modules/ws/LICENSE +20 -0
  669. package/node_modules/ws/README.md +548 -0
  670. package/node_modules/ws/browser.js +8 -0
  671. package/node_modules/ws/index.js +22 -0
  672. package/node_modules/ws/lib/buffer-util.js +131 -0
  673. package/node_modules/ws/lib/constants.js +19 -0
  674. package/node_modules/ws/lib/event-target.js +292 -0
  675. package/node_modules/ws/lib/extension.js +203 -0
  676. package/node_modules/ws/lib/limiter.js +55 -0
  677. package/node_modules/ws/lib/permessage-deflate.js +530 -0
  678. package/node_modules/ws/lib/receiver.js +743 -0
  679. package/node_modules/ws/lib/sender.js +607 -0
  680. package/node_modules/ws/lib/stream.js +161 -0
  681. package/node_modules/ws/lib/subprotocol.js +62 -0
  682. package/node_modules/ws/lib/validation.js +152 -0
  683. package/node_modules/ws/lib/websocket-server.js +562 -0
  684. package/node_modules/ws/lib/websocket.js +1421 -0
  685. package/node_modules/ws/package.json +74 -0
  686. package/node_modules/ws/wrapper.mjs +21 -0
  687. package/package.json +22 -5
  688. package/sandbox/csharp/EnvBroadcast.cs +33 -0
  689. package/sandbox/csharp/MemGov.cs +398 -0
  690. package/sandbox/csharp/PathSync.cs +90 -0
  691. package/sandbox/csharp/PtyHost.cs +111 -5
  692. package/sandbox/scripts/install-shell-path.ps1 +73 -0
  693. package/sandbox/scripts/set-machine-environment.ps1 +37 -4
  694. package/schemas/config.schema.json +136 -7
  695. package/schemas/sandbox-config.schema.json +17 -4
  696. package/dist/cli/commands/repair/checks.d.ts +0 -2
  697. package/dist/cli/commands/repair/checks.js +0 -246
  698. package/dist/cli/commands/sessions/control.d.ts +0 -4
  699. package/dist/cli/commands/sessions/control.js +0 -66
  700. package/dist/cli/commands/sessions/list.d.ts +0 -2
  701. package/dist/cli/commands/sessions/list.js +0 -45
  702. package/dist/cli/commands/sessions/status.d.ts +0 -2
  703. package/dist/cli/commands/sessions/status.js +0 -93
  704. package/dist/cli/commands/sessions/window.d.ts +0 -3
  705. package/dist/cli/commands/sessions/window.js +0 -18
  706. package/dist/cli/menu/pages/start-page.d.ts +0 -43
  707. package/dist/cli/menu/pages/start-page.js +0 -192
  708. package/dist/cli/tui/tab-bar.d.ts +0 -9
  709. package/dist/cli/tui/tab-bar.js +0 -33
@@ -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
+ }
@@ -0,0 +1,46 @@
1
+ import { isSandboxRunning } from '../../host/sandbox/index.js';
2
+ import { hostPublicIp, readVpnLine, VpnLogin, } from '../../host/vpn/index.js';
3
+ /** The steps to get the NordVPN service credentials, in the words of Nord Account (shown before asking). */
4
+ export const NORD_STEPS = [
5
+ 'Sign in at https://my.nordaccount.com with your usual NordVPN e-mail and password.',
6
+ 'Open NordVPN, then "Set up NordVPN manually" (under Advanced settings).',
7
+ 'Verify your e-mail if it asks, then copy the "Service credentials": a user name and a password.',
8
+ 'These are NOT your account password. You can revoke them in the same place whenever you like.',
9
+ ];
10
+ export class VpnService {
11
+ ctx;
12
+ login;
13
+ constructor(ctx) {
14
+ this.ctx = ctx;
15
+ this.login = new VpnLogin(ctx.storageRoot);
16
+ }
17
+ get config() {
18
+ return this.ctx.loaded.config.vpn;
19
+ }
20
+ get provider() {
21
+ return this.config.provider;
22
+ }
23
+ async report() {
24
+ const c = this.config;
25
+ const running = isSandboxRunning();
26
+ return {
27
+ enabled: c.enabled,
28
+ provider: c.provider,
29
+ protocol: c.protocol,
30
+ country: c.country,
31
+ killSwitch: c.killSwitch,
32
+ login: this.login.state(c.provider),
33
+ loginSavedAt: this.login.savedAt(c.provider),
34
+ running: running ? readVpnLine(this.ctx.dataPath, await hostPublicIp()) : null,
35
+ };
36
+ }
37
+ loginState() {
38
+ return this.login.state(this.provider);
39
+ }
40
+ save(credentials) {
41
+ this.login.save(this.provider, credentials);
42
+ }
43
+ remove() {
44
+ return this.login.remove(this.provider);
45
+ }
46
+ }
@@ -0,0 +1,22 @@
1
+ import type { SessionStatus } from '../../core/types.js';
2
+ import type { WebBackend } from '../../host/web/index.js';
3
+ import type { Endpoint } from '../../shared/pty/index.js';
4
+ import type { NewSessionRequest, WebInfo, WebSession } from '../../shared/web/index.js';
5
+ import type { Context } from '../commands/context.js';
6
+ import { type ListedSession } from './sessions-service.js';
7
+ /** A session as the browser may see it: no attach address or token, text made safe. */
8
+ export declare function webSession(s: SessionStatus | ListedSession, viewers: number | null | undefined): WebSession;
9
+ export declare class WebService implements WebBackend {
10
+ private readonly ctx;
11
+ private cached;
12
+ constructor(ctx: Context);
13
+ /** The running sandbox as this user sees it, or null when none runs. */
14
+ private view;
15
+ /** The sandbox is this user's, or another user's and shared with them. */
16
+ private mayUse;
17
+ private projects;
18
+ info(): Promise<WebInfo>;
19
+ sessions(): Promise<WebSession[]>;
20
+ endpoint(sessionId: string): Endpoint | null;
21
+ create(request: NewSessionRequest): Promise<WebSession>;
22
+ }
@@ -0,0 +1,111 @@
1
+ // What the web UI's server may do with the running sandbox: the same sessions, projects and rules as the CLI (another
2
+ // user's sandbox is shown and used only as far as the sharing rules allow). Returns data, never prints.
3
+ import path from 'node:path';
4
+ import { fail, safeText } from '../../core/util/index.js';
5
+ import { hostEndpoint, SandboxChannel } from '../../host/channel/index.js';
6
+ import { insideSandbox, isSandboxRunning } from '../../host/sandbox/index.js';
7
+ import { ownerRule } from '../../host/sharing/index.js';
8
+ import { RunDir } from '../../shared/channel/index.js';
9
+ import { lookAtSandbox } from '../commands/shared-use.js';
10
+ import { registryOf } from '../commands/projects/here.js';
11
+ import { SessionsService } from './sessions-service.js';
12
+ /** The owner is asked (a process listing) at most this often: the browser polls. */
13
+ const VIEW_TTL_MS = 3000;
14
+ const SESSION_START_MS = 15 * 60 * 1000;
15
+ const MAX_SESSIONS = 50;
16
+ /** A session as the browser may see it: no attach address or token, text made safe. */
17
+ export function webSession(s, viewers) {
18
+ return {
19
+ id: s.id,
20
+ harness: safeText(s.harness),
21
+ project: safeText(('projectName' in s ? s.projectName : undefined) ?? s.project ?? path.win32.basename(s.cwd)),
22
+ cwd: safeText(s.cwd),
23
+ phase: s.phase,
24
+ message: safeText(s.message).slice(0, 300),
25
+ startedAt: s.startedAt,
26
+ viewers: viewers ?? null,
27
+ canOpen: s.phase === 'running' && hostEndpoint(s) !== null,
28
+ };
29
+ }
30
+ export class WebService {
31
+ ctx;
32
+ cached = null;
33
+ constructor(ctx) {
34
+ this.ctx = ctx;
35
+ }
36
+ /** The running sandbox as this user sees it, or null when none runs. */
37
+ view() {
38
+ const now = Date.now();
39
+ if (this.cached && now - this.cached.at < VIEW_TTL_MS)
40
+ return this.cached.view;
41
+ const view = !insideSandbox() && isSandboxRunning() ? lookAtSandbox(this.ctx) : null;
42
+ this.cached = { at: now, view };
43
+ return view;
44
+ }
45
+ /** The sandbox is this user's, or another user's and shared with them. */
46
+ mayUse(view) {
47
+ return !view.owner || ownerRule(view.owner, { kind: 'use' }).kind === 'allow';
48
+ }
49
+ projects(view) {
50
+ const known = registryOf(view.ctx).read()?.projects ?? [];
51
+ if (known.length)
52
+ return known.map((p) => ({ name: p.name, guest: safeText(p.guest) }));
53
+ // A sandbox from before projects existed has only its launch folder.
54
+ const status = new RunDir(view.ctx.dataPath).readSandboxStatus();
55
+ return status ? [{ name: 'workspace', guest: safeText(status.guestWorkspace) }] : [];
56
+ }
57
+ info() {
58
+ const config = this.ctx.loaded.config;
59
+ const view = this.view();
60
+ return Promise.resolve({
61
+ sandbox: view ? 'running' : 'stopped',
62
+ owner: view?.line ?? null,
63
+ canUse: view !== null && this.mayUse(view),
64
+ harnesses: Object.keys(config.harnesses),
65
+ defaultHarness: config.defaultHarness,
66
+ projects: view && this.mayUse(view) ? this.projects(view) : [],
67
+ });
68
+ }
69
+ async sessions() {
70
+ const view = this.view();
71
+ if (!view || !this.mayUse(view))
72
+ return [];
73
+ const launchId = new RunDir(view.ctx.dataPath).readSandboxStatus()?.launchId;
74
+ const listed = await new SessionsService(view.ctx).list();
75
+ return listed
76
+ .filter((s) => s.launchId === launchId && (s.phase === 'running' || s.phase === 'starting'))
77
+ .reverse()
78
+ .slice(0, MAX_SESSIONS)
79
+ .map((s) => webSession(s, s.viewers === undefined ? undefined : (s.viewers?.viewers ?? null)));
80
+ }
81
+ endpoint(sessionId) {
82
+ const view = this.view();
83
+ if (!view || !this.mayUse(view))
84
+ return null;
85
+ const run = new RunDir(view.ctx.dataPath);
86
+ const session = run.readSession(sessionId);
87
+ if (!session || session.phase !== 'running' || session.launchId !== run.readSandboxStatus()?.launchId)
88
+ return null;
89
+ return hostEndpoint(session);
90
+ }
91
+ async create(request) {
92
+ const view = this.view();
93
+ if (!view)
94
+ return fail('No Windows Sandbox is running.', 'Start one with sandbox claude, then try again.');
95
+ if (view.owner && view.owner.kind !== 'none' && view.owner.kind !== 'mine') {
96
+ const rule = ownerRule(view.owner, { kind: 'use' });
97
+ if (rule.kind === 'refuse')
98
+ return fail(rule.reason, rule.fix);
99
+ }
100
+ const project = this.projects(view).find((p) => p.name === request.project);
101
+ if (!project)
102
+ return fail('The running sandbox has no project "' + request.project + '".');
103
+ const harness = view.ctx.loaded.config.harnesses[request.harness];
104
+ if (!harness)
105
+ return fail('There is no agent called "' + request.harness + '".');
106
+ const channel = new SandboxChannel(view.ctx.dataPath);
107
+ const id = channel.requestSession(request.harness, [], project.guest, { harnessSpec: harness });
108
+ const session = await channel.waitForSession(id, SESSION_START_MS, () => undefined);
109
+ return webSession(session, null);
110
+ }
111
+ }
@@ -1,23 +1,29 @@
1
1
  import { type ConfirmOptions } from './dialogs/confirm-screen.js';
2
2
  import { MessageScreen } from './dialogs/message-screen.js';
3
3
  import { type TextOptions } from './dialogs/text-screen.js';
4
+ import { type PathPickerOptions } from './dialogs/path-picker.js';
4
5
  import { type OverlayOptions } from './dialogs/overlay.js';
5
- import { type TabsState } from './frame.js';
6
+ import type { NavState } from './nav.js';
6
7
  import { type ListOptions, type ListResult } from './list/list-types.js';
7
8
  import { Terminal } from './terminal.js';
8
9
  import type { Screen } from './screen.js';
9
10
  export declare class App {
10
11
  readonly terminal: Terminal;
11
- /** The status line for screens that do not set their own (refreshed on every draw). */
12
+ /** The status line for screens that do not set their own (read on every draw: it must not wait for anything). */
12
13
  status: () => string;
13
- /** The tabs shown across the top of every screen (none: no tab row). */
14
- tabs: () => TabsState | undefined;
14
+ /** Awaited after an action changed something, before the screen loads what it shows again. */
15
+ afterAction: () => Promise<void>;
16
+ /** The navigation on the left of every screen (none: no navigation column). */
17
+ nav: () => NavState | undefined;
15
18
  /** The screens being shown, innermost last: a dialog is drawn over the one below it. */
16
19
  private readonly shown;
17
20
  private redrawNow;
21
+ private redrawTimer;
18
22
  constructor(terminal?: Terminal);
19
23
  /** Draws the screen on top again now (before a slow piece of work, so its notice is visible). */
20
24
  redraw(): void;
25
+ /** Draws it again soon: what happens between two keys (a resize, fresh facts) is drawn once, not once each. */
26
+ requestRedraw(): void;
21
27
  /** Shows `screen` until its handler says it is done, and returns what it returned. */
22
28
  show<T>(screen: Screen<T>): Promise<T>;
23
29
  /** A dialog over the screen below (Save / Discard / Cancel, Yes / No ...). */
@@ -26,6 +32,8 @@ export declare class App {
26
32
  ask(title: string, lines: readonly string[], yes?: string, danger?: boolean): Promise<boolean>;
27
33
  list<T>(o: ListOptions<T>): Promise<ListResult<T>>;
28
34
  text(o: TextOptions): Promise<string | undefined>;
35
+ /** Choose a folder (or a file): the path on top, the folders to browse below. Undefined = cancelled. */
36
+ pickPath(o: PathPickerOptions): Promise<string | undefined>;
29
37
  confirm(o: ConfirmOptions): Promise<boolean>;
30
38
  message(o: ConstructorParameters<typeof MessageScreen>[0]): Promise<void>;
31
39
  /** One of a few values (undefined = back). */
@@ -3,27 +3,46 @@
3
3
  import { ConfirmScreen } from './dialogs/confirm-screen.js';
4
4
  import { MessageScreen } from './dialogs/message-screen.js';
5
5
  import { TextScreen } from './dialogs/text-screen.js';
6
+ import { PathPickerScreen } from './dialogs/path-picker.js';
6
7
  import { OverlayScreen } from './dialogs/overlay.js';
7
8
  import { Frame } from './frame.js';
8
9
  import { ListScreen } from './list/list-screen.js';
9
10
  import { Terminal } from './terminal.js';
10
11
  import { Theme } from './theme.js';
12
+ /** Changes that arrive together (a resize, fresh facts) are drawn once, this long after the first. */
13
+ const REDRAW_DELAY_MS = 16;
14
+ /** While keys are waiting, the screen is still drawn at least this often. */
15
+ const MAX_STALE_MS = 100;
11
16
  export class App {
12
17
  terminal;
13
- /** The status line for screens that do not set their own (refreshed on every draw). */
18
+ /** The status line for screens that do not set their own (read on every draw: it must not wait for anything). */
14
19
  status = () => '';
15
- /** The tabs shown across the top of every screen (none: no tab row). */
16
- tabs = () => undefined;
20
+ /** Awaited after an action changed something, before the screen loads what it shows again. */
21
+ afterAction = () => Promise.resolve();
22
+ /** The navigation on the left of every screen (none: no navigation column). */
23
+ nav = () => undefined;
17
24
  /** The screens being shown, innermost last: a dialog is drawn over the one below it. */
18
25
  shown = [];
19
26
  redrawNow = null;
27
+ redrawTimer;
20
28
  constructor(terminal = new Terminal()) {
21
29
  this.terminal = terminal;
30
+ terminal.onResized(() => this.requestRedraw());
22
31
  }
23
32
  /** Draws the screen on top again now (before a slow piece of work, so its notice is visible). */
24
33
  redraw() {
25
34
  this.redrawNow?.();
26
35
  }
36
+ /** Draws it again soon: what happens between two keys (a resize, fresh facts) is drawn once, not once each. */
37
+ requestRedraw() {
38
+ if (this.redrawTimer)
39
+ return;
40
+ this.redrawTimer = setTimeout(() => {
41
+ this.redrawTimer = undefined;
42
+ if (this.terminal.running)
43
+ this.redrawNow?.();
44
+ }, REDRAW_DELAY_MS);
45
+ }
27
46
  /** Shows `screen` until its handler says it is done, and returns what it returned. */
28
47
  async show(screen) {
29
48
  this.terminal.start();
@@ -31,15 +50,22 @@ export class App {
31
50
  const outer = this.redrawNow;
32
51
  const draw = () => {
33
52
  const { width, height } = this.terminal;
34
- const tabs = this.tabs();
35
- const parts = screen.render({ width, height: Frame.bodyHeight(height, Boolean(tabs)) });
36
- this.terminal.render(Frame.render({ ...parts, status: parts.status ?? this.status(), tabs: parts.tabs ?? tabs }, width, height));
53
+ const nav = this.nav();
54
+ // A screen over the menu (a dialog, an editor) leaves the navigation visible but grey.
55
+ const covered = this.shown.length > 1;
56
+ const parts = screen.render({ width: Frame.bodyWidth(width, nav), height: Frame.bodyHeight(height) });
57
+ this.terminal.render(Frame.render({ ...parts, status: parts.status ?? this.status(), nav: nav && { ...nav, dimmed: nav.dimmed || covered } }, width, height));
37
58
  };
38
59
  this.redrawNow = draw;
39
- this.terminal.onResized(draw);
60
+ let drawnAt = 0;
40
61
  try {
41
62
  for (;;) {
42
- draw();
63
+ // Keys that are already waiting (a held arrow, a paste) are handled first: the screen shows the result of the
64
+ // last one, but never stays stale for longer than MAX_STALE_MS.
65
+ if (!this.terminal.hasKeys || Date.now() - drawnAt >= MAX_STALE_MS) {
66
+ draw();
67
+ drawnAt = Date.now();
68
+ }
43
69
  const step = await screen.handle(await this.terminal.key());
44
70
  if (step)
45
71
  return step.done;
@@ -48,7 +74,6 @@ export class App {
48
74
  finally {
49
75
  this.shown.pop();
50
76
  this.redrawNow = outer;
51
- this.terminal.onResized(outer);
52
77
  }
53
78
  }
54
79
  /** A dialog over the screen below (Save / Discard / Cancel, Yes / No ...). */
@@ -75,6 +100,10 @@ export class App {
75
100
  text(o) {
76
101
  return this.show(new TextScreen(o));
77
102
  }
103
+ /** Choose a folder (or a file): the path on top, the folders to browse below. Undefined = cancelled. */
104
+ pickPath(o) {
105
+ return this.show(new PathPickerScreen(o));
106
+ }
78
107
  confirm(o) {
79
108
  return this.show(new ConfirmScreen(o));
80
109
  }
@@ -0,0 +1,43 @@
1
+ export type EntryKind = 'drive' | 'up' | 'dir' | 'file' | 'link';
2
+ export interface PickEntry {
3
+ readonly kind: EntryKind;
4
+ readonly name: string;
5
+ /** The full path it opens or picks ('' for the "This PC" level above a drive). */
6
+ readonly path: string;
7
+ /** Extra words: free space of a drive, "link". */
8
+ readonly detail?: string;
9
+ }
10
+ export interface Listing {
11
+ readonly entries: readonly PickEntry[];
12
+ /** Entries left out because of the cap. */
13
+ readonly more: number;
14
+ /** Why the folder could not be read. */
15
+ readonly error?: string;
16
+ }
17
+ /** Entries listed at most; the rest is counted ("... more"). */
18
+ export declare const LIST_CAP = 2000;
19
+ /** What was typed, split into the folder it names (or is in) and the start of a name in it. '' = This PC. */
20
+ export declare function splitInput(input: string): {
21
+ dir: string;
22
+ prefix: string;
23
+ };
24
+ /** The folder above, or '' (This PC) above a drive's root. */
25
+ export declare function parentOf(dir: string): string;
26
+ /** `dir` with exactly one trailing backslash (for the input line). */
27
+ export declare function withSeparator(dir: string): string;
28
+ /**
29
+ * The folders (and files when asked) in `dir`. Links and junctions are listed, marked, never opened; unreadable
30
+ * folders give an error text; at most `cap` entries come back.
31
+ */
32
+ export declare function listFolder(dir: string, files?: boolean, cap?: number): Listing;
33
+ /** The drives of this PC with their free space ("This PC"). */
34
+ export declare function listDrives(): PickEntry[];
35
+ /** Entries whose name starts with `prefix` (no case), or contains `text` when filtering. */
36
+ export declare function narrow(entries: readonly PickEntry[], prefix: string, text?: string): PickEntry[];
37
+ /**
38
+ * Completes the last name of `input` from the folders listed: the longest start they share, and a backslash when
39
+ * exactly one folder fits. The input is returned unchanged when nothing fits.
40
+ */
41
+ export declare function completeInput(input: string, folders: readonly PickEntry[]): string;
42
+ /** A name for a new folder: not empty, no path characters, not . or .., not reserved. */
43
+ export declare function folderNameProblem(name: string): string | null;
@@ -0,0 +1,127 @@
1
+ // What the path picker needs from the disk and from text, as plain functions (tested): splitting what was typed,
2
+ // listing a folder without ever following links, completing a name, filtering, and the drives of "This PC".
3
+ import fs from 'node:fs';
4
+ import path from 'node:path';
5
+ import { diskUsage } from '../../../core/disk.js';
6
+ const win = path.win32;
7
+ /** Entries listed at most; the rest is counted ("... more"). */
8
+ export const LIST_CAP = 2000;
9
+ const SEPARATOR = /[\\/]$/;
10
+ /** What was typed, split into the folder it names (or is in) and the start of a name in it. '' = This PC. */
11
+ export function splitInput(input) {
12
+ const text = input.trim();
13
+ if (text === '')
14
+ return { dir: '', prefix: '' };
15
+ if (/^[A-Za-z]:$/.test(text))
16
+ return { dir: text + '\\', prefix: '' };
17
+ if (SEPARATOR.test(text))
18
+ return { dir: text, prefix: '' };
19
+ const dir = win.dirname(text);
20
+ const base = win.basename(text);
21
+ // A bare name (no folder) has no folder to look in.
22
+ return dir === '.' ? { dir: '', prefix: base } : { dir, prefix: base };
23
+ }
24
+ /** The folder above, or '' (This PC) above a drive's root. */
25
+ export function parentOf(dir) {
26
+ if (dir === '')
27
+ return '';
28
+ const parent = win.dirname(win.resolve(dir));
29
+ return parent.toLowerCase() === win.resolve(dir).toLowerCase() ? '' : parent;
30
+ }
31
+ /** `dir` with exactly one trailing backslash (for the input line). */
32
+ export function withSeparator(dir) {
33
+ return dir === '' ? '' : dir.replace(/[\\/]+$/, '') + '\\';
34
+ }
35
+ /** Folders first, then files, each by name without regard to case. */
36
+ function byKindThenName(a, b) {
37
+ const rank = (e) => (e.kind === 'file' ? 1 : 0);
38
+ return rank(a) - rank(b) || a.name.localeCompare(b.name, undefined, { sensitivity: 'base' });
39
+ }
40
+ /**
41
+ * The folders (and files when asked) in `dir`. Links and junctions are listed, marked, never opened; unreadable
42
+ * folders give an error text; at most `cap` entries come back.
43
+ */
44
+ export function listFolder(dir, files = false, cap = LIST_CAP) {
45
+ let found;
46
+ try {
47
+ found = fs.readdirSync(dir, { withFileTypes: true });
48
+ }
49
+ catch (e) {
50
+ const code = e.code;
51
+ return {
52
+ entries: [],
53
+ more: 0,
54
+ error: code === 'ENOENT' || code === 'ENOTDIR' ? 'No such folder' : 'Cannot open it',
55
+ };
56
+ }
57
+ const entries = [];
58
+ for (const d of found) {
59
+ const full = win.join(dir, d.name);
60
+ if (d.isSymbolicLink())
61
+ entries.push({ kind: 'link', name: d.name, path: full, detail: 'link' });
62
+ else if (d.isDirectory())
63
+ entries.push({ kind: 'dir', name: d.name, path: full });
64
+ else if (files)
65
+ entries.push({ kind: 'file', name: d.name, path: full });
66
+ }
67
+ entries.sort(byKindThenName);
68
+ return { entries: entries.slice(0, cap), more: Math.max(0, entries.length - cap) };
69
+ }
70
+ /** The drives of this PC with their free space ("This PC"). */
71
+ export function listDrives() {
72
+ return diskUsage('C:\\').map((d) => ({
73
+ kind: 'drive',
74
+ name: d.drive,
75
+ path: d.drive,
76
+ detail: freeText(d.freeBytes, d.totalBytes),
77
+ }));
78
+ }
79
+ function freeText(free, total) {
80
+ const gb = (n) => (n / 1024 ** 3 >= 10 ? Math.round(n / 1024 ** 3) : (n / 1024 ** 3).toFixed(1)) + ' GB';
81
+ return gb(free) + ' free of ' + gb(total);
82
+ }
83
+ /** Entries whose name starts with `prefix` (no case), or contains `text` when filtering. */
84
+ export function narrow(entries, prefix, text = '') {
85
+ const start = prefix.toLowerCase();
86
+ const inside = text.toLowerCase();
87
+ return entries.filter((e) => {
88
+ const name = e.name.toLowerCase();
89
+ return name.startsWith(start) && name.includes(inside);
90
+ });
91
+ }
92
+ /**
93
+ * Completes the last name of `input` from the folders listed: the longest start they share, and a backslash when
94
+ * exactly one folder fits. The input is returned unchanged when nothing fits.
95
+ */
96
+ export function completeInput(input, folders) {
97
+ const { dir, prefix } = splitInput(input);
98
+ const names = folders
99
+ .filter((f) => f.kind === 'dir' && f.name.toLowerCase().startsWith(prefix.toLowerCase()))
100
+ .map((f) => f.name);
101
+ if (names.length === 0)
102
+ return input;
103
+ let common = names[0];
104
+ for (const name of names.slice(1)) {
105
+ let n = 0;
106
+ while (n < common.length && n < name.length && common[n].toLowerCase() === name[n].toLowerCase())
107
+ n++;
108
+ common = common.slice(0, n);
109
+ }
110
+ // Never shorten what was typed (the typed spelling wins when the listing only differs in case).
111
+ const completed = common.length >= prefix.length ? common : prefix;
112
+ const base = dir === '' ? '' : withSeparator(dir);
113
+ return base + completed + (names.length === 1 && completed.length === names[0].length ? '\\' : '');
114
+ }
115
+ /** A name for a new folder: not empty, no path characters, not . or .., not reserved. */
116
+ export function folderNameProblem(name) {
117
+ const trimmed = name.trim();
118
+ if (trimmed === '')
119
+ return 'Type a name.';
120
+ if (/[<>:"/\\|?*\x00-\x1f]/.test(trimmed))
121
+ return 'A folder name cannot contain < > : " / \\ | ? *';
122
+ if (/^\.+$/.test(trimmed) || /[. ]$/.test(trimmed))
123
+ return 'A folder name cannot end with a dot or a space.';
124
+ if (/^(con|prn|aux|nul|com[1-9]|lpt[1-9])(\..*)?$/i.test(trimmed))
125
+ return '"' + trimmed + '" is a reserved name in Windows.';
126
+ return null;
127
+ }
@@ -0,0 +1,67 @@
1
+ import type { FrameParts } from '../frame.js';
2
+ import type { Screen, Size, Step } from '../screen.js';
3
+ import type { Key } from '../terminal.js';
4
+ export interface PathPickerOptions {
5
+ path: string[];
6
+ title: string;
7
+ about?: string[];
8
+ /** The path in the input at first (also where the browser starts). */
9
+ initial?: string;
10
+ /** Show files (dim) and let them be picked; folders only by default. */
11
+ files?: boolean;
12
+ /** Label of the choose key, e.g. "use this folder". */
13
+ use?: string;
14
+ /** true = fine, a string = why this path cannot be chosen. */
15
+ validate?: (path: string) => true | string;
16
+ /** Typed words that are fine as they are (a setting that also takes "auto"). */
17
+ literals?: readonly string[];
18
+ /** A relative path may be typed too (it is kept as typed, not made absolute). */
19
+ relative?: boolean;
20
+ }
21
+ /** Resolves to the chosen path, or undefined when you press Esc. */
22
+ export declare class PathPickerScreen implements Screen<string | undefined> {
23
+ private readonly o;
24
+ private mode;
25
+ private input;
26
+ private cursor;
27
+ private dir;
28
+ private listing;
29
+ private loadedDir;
30
+ private selected;
31
+ private scroll;
32
+ private filter;
33
+ private newName;
34
+ private problem;
35
+ private notice;
36
+ private rows;
37
+ constructor(o: PathPickerOptions);
38
+ render(size: Size): FrameParts;
39
+ handle(key: Key): Promise<Step<string | undefined>>;
40
+ /** The entries on screen: the folder's, narrowed by what is typed after the last backslash and by the filter. */
41
+ private visible;
42
+ private dirIsTyped;
43
+ private row;
44
+ private where;
45
+ private verdict;
46
+ private verdictLine;
47
+ private keys;
48
+ /** What choosing now would pick. In the browser a highlighted folder (or file) wins over the folder being shown. */
49
+ private candidate;
50
+ private choose;
51
+ /** Is this typed text kept as typed: one of the allowed words, or a relative path where those are allowed? */
52
+ private kept;
53
+ /** Reads the folder the input names (only when it changed), keeping what was typed as a filter. */
54
+ private syncListing;
55
+ private openDir;
56
+ private go;
57
+ private keepSelectedInView;
58
+ private typing;
59
+ private edit;
60
+ /** A path ending in a backslash is opened to look inside; any other typed path is chosen. */
61
+ private enterInput;
62
+ private browsing;
63
+ private open;
64
+ private filtering;
65
+ private startName;
66
+ private naming;
67
+ }