windows-development-sandbox 1.10.0 → 1.11.3

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 (378) hide show
  1. package/README.md +64 -17
  2. package/config.example.json +5 -1
  3. package/dist/app/features/accounts/accounts.def.d.ts +122 -0
  4. package/dist/app/features/accounts/accounts.def.js +243 -0
  5. package/dist/app/features/accounts/accounts.run.d.ts +51 -0
  6. package/dist/app/features/accounts/accounts.run.js +125 -0
  7. package/dist/app/features/accounts/index.d.ts +2 -0
  8. package/dist/app/features/accounts/index.js +3 -0
  9. package/dist/app/features/agents/agent-entry.d.ts +17 -0
  10. package/dist/app/features/agents/agent-entry.js +50 -0
  11. package/dist/app/features/agents/agents.def.d.ts +65 -0
  12. package/dist/app/features/agents/agents.def.js +142 -0
  13. package/dist/app/features/agents/agents.run.d.ts +31 -0
  14. package/dist/app/features/agents/agents.run.js +189 -0
  15. package/dist/app/features/agents/index.d.ts +3 -0
  16. package/dist/app/features/agents/index.js +4 -0
  17. package/dist/app/features/apps/apps-rows.d.ts +31 -0
  18. package/dist/app/features/apps/apps-rows.js +73 -0
  19. package/dist/app/features/apps/apps.def.d.ts +181 -0
  20. package/dist/app/features/apps/apps.def.js +264 -0
  21. package/dist/app/features/apps/apps.run.d.ts +58 -0
  22. package/dist/app/features/apps/apps.run.js +76 -0
  23. package/dist/app/features/apps/index.d.ts +3 -0
  24. package/dist/app/features/apps/index.js +4 -0
  25. package/dist/app/features/data/data.def.d.ts +154 -0
  26. package/dist/app/features/data/data.def.js +201 -0
  27. package/dist/app/features/data/data.run.d.ts +46 -0
  28. package/dist/app/features/data/data.run.js +141 -0
  29. package/dist/app/features/data/index.d.ts +2 -0
  30. package/dist/app/features/data/index.js +3 -0
  31. package/dist/app/features/defs.d.ts +952 -4
  32. package/dist/app/features/defs.js +147 -10
  33. package/dist/app/features/engine/engine.def.d.ts +228 -0
  34. package/dist/app/features/engine/engine.def.js +194 -0
  35. package/dist/app/features/engine/engine.run.d.ts +72 -0
  36. package/dist/app/features/engine/engine.run.js +77 -0
  37. package/dist/app/features/engine/index.d.ts +2 -0
  38. package/dist/app/features/engine/index.js +4 -0
  39. package/dist/app/features/files/files.def.d.ts +51 -0
  40. package/dist/app/features/files/files.def.js +38 -0
  41. package/dist/app/features/files/files.run.d.ts +20 -0
  42. package/dist/app/features/files/files.run.js +59 -0
  43. package/dist/app/features/files/index.d.ts +2 -0
  44. package/dist/app/features/files/index.js +3 -0
  45. package/dist/app/features/github/github.def.d.ts +80 -0
  46. package/dist/app/features/github/github.def.js +142 -0
  47. package/dist/app/features/github/github.run.d.ts +36 -0
  48. package/dist/app/features/github/github.run.js +59 -0
  49. package/dist/app/features/github/index.d.ts +2 -0
  50. package/dist/app/features/github/index.js +3 -0
  51. package/dist/app/features/health/health.def.d.ts +275 -0
  52. package/dist/app/features/health/health.def.js +281 -0
  53. package/dist/app/features/health/health.run.d.ts +125 -0
  54. package/dist/app/features/health/health.run.js +204 -0
  55. package/dist/app/features/health/index.d.ts +2 -0
  56. package/dist/app/features/health/index.js +3 -0
  57. package/dist/app/features/logs/index.d.ts +2 -0
  58. package/dist/app/features/logs/index.js +3 -0
  59. package/dist/app/features/logs/logs.def.d.ts +78 -0
  60. package/dist/app/features/logs/logs.def.js +115 -0
  61. package/dist/app/features/logs/logs.run.d.ts +20 -0
  62. package/dist/app/features/logs/logs.run.js +42 -0
  63. package/dist/app/features/projects/index.d.ts +2 -0
  64. package/dist/app/features/projects/index.js +3 -0
  65. package/dist/app/features/projects/projects.def.d.ts +101 -0
  66. package/dist/app/features/projects/projects.def.js +208 -0
  67. package/dist/app/features/projects/projects.run.d.ts +56 -0
  68. package/dist/app/features/projects/projects.run.js +155 -0
  69. package/dist/app/features/sandbox/sandbox.def.js +11 -5
  70. package/dist/app/features/sessions/sessions.def.js +3 -0
  71. package/dist/app/features/settings/categories.def.js +3 -2
  72. package/dist/{cli/menu/settings/share.d.ts → app/features/settings/settings-share.d.ts} +1 -1
  73. package/dist/{cli/menu/settings/share.js → app/features/settings/settings-share.js} +3 -2
  74. package/dist/app/features/settings/settings.def.d.ts +22 -5
  75. package/dist/app/features/settings/settings.def.js +81 -6
  76. package/dist/app/features/settings/settings.run.d.ts +17 -0
  77. package/dist/app/features/settings/settings.run.js +89 -4
  78. package/dist/app/features/storage/index.d.ts +2 -0
  79. package/dist/app/features/storage/index.js +3 -0
  80. package/dist/app/features/storage/storage.def.d.ts +133 -0
  81. package/dist/app/features/storage/storage.def.js +225 -0
  82. package/dist/app/features/storage/storage.run.d.ts +62 -0
  83. package/dist/app/features/storage/storage.run.js +370 -0
  84. package/dist/app/features/updates/index.d.ts +3 -0
  85. package/dist/app/features/updates/index.js +4 -0
  86. package/dist/app/features/updates/update-lines.d.ts +13 -0
  87. package/dist/app/features/updates/update-lines.js +61 -0
  88. package/dist/app/features/updates/updates.def.d.ts +89 -0
  89. package/dist/app/features/updates/updates.def.js +225 -0
  90. package/dist/app/features/updates/updates.run.d.ts +48 -0
  91. package/dist/app/features/updates/updates.run.js +154 -0
  92. package/dist/app/features/vpn/index.d.ts +2 -0
  93. package/dist/app/features/vpn/index.js +3 -0
  94. package/dist/app/features/vpn/vpn.def.d.ts +112 -0
  95. package/dist/app/features/vpn/vpn.def.js +174 -0
  96. package/dist/app/features/vpn/vpn.run.d.ts +37 -0
  97. package/dist/app/features/vpn/vpn.run.js +54 -0
  98. package/dist/app/features/web/index.d.ts +2 -0
  99. package/dist/app/features/web/index.js +3 -0
  100. package/dist/app/features/web/web.def.d.ts +33 -0
  101. package/dist/app/features/web/web.def.js +90 -0
  102. package/dist/app/features/web/web.run.d.ts +24 -0
  103. package/dist/app/features/web/web.run.js +93 -0
  104. package/dist/app/kernel/define.d.ts +10 -1
  105. package/dist/app/kernel/io.d.ts +34 -0
  106. package/dist/app/kernel/io.js +9 -0
  107. package/dist/app/kernel/rpc.d.ts +17 -0
  108. package/dist/app/kernel/text.d.ts +2 -0
  109. package/dist/app/kernel/text.js +7 -0
  110. package/dist/app/kernel/view.d.ts +24 -1
  111. package/dist/app/kernel/view.js +1 -1
  112. package/dist/app/registry.js +74 -1
  113. package/dist/cli/args.js +1 -1
  114. package/dist/cli/commands/context.d.ts +7 -0
  115. package/dist/cli/commands/context.js +29 -2
  116. package/dist/cli/commands/engine.js +5 -58
  117. package/dist/cli/commands/github.d.ts +2 -0
  118. package/dist/cli/commands/github.js +11 -0
  119. package/dist/cli/commands/index.d.ts +3 -5
  120. package/dist/cli/commands/index.js +3 -5
  121. package/dist/cli/commands/launch/launch.js +21 -4
  122. package/dist/cli/commands/launch/running.js +4 -1
  123. package/dist/cli/commands/maintenance/config.js +1 -6
  124. package/dist/cli/commands/maintenance/index.d.ts +0 -1
  125. package/dist/cli/commands/maintenance/index.js +1 -2
  126. package/dist/cli/commands/maintenance/logs.js +27 -32
  127. package/dist/cli/commands/maintenance/migrate.d.ts +0 -8
  128. package/dist/cli/commands/maintenance/migrate.js +2 -44
  129. package/dist/cli/commands/maintenance/update.d.ts +0 -19
  130. package/dist/cli/commands/maintenance/update.js +1 -99
  131. package/dist/cli/commands/projects/index.d.ts +0 -1
  132. package/dist/cli/commands/projects/index.js +0 -1
  133. package/dist/cli/commands/registry.d.ts +1 -1
  134. package/dist/cli/commands/registry.js +29 -11
  135. package/dist/cli/commands/repair/checks/data.js +1 -1
  136. package/dist/cli/commands/repair/checks/hcs.js +28 -1
  137. package/dist/cli/commands/repair/checks/sandbox.js +1 -1
  138. package/dist/cli/commands/repair/health-run.d.ts +30 -0
  139. package/dist/cli/commands/repair/health-run.js +32 -0
  140. package/dist/cli/commands/repair/printer.d.ts +2 -2
  141. package/dist/cli/commands/repair/printer.js +2 -11
  142. package/dist/cli/commands/repair/run.d.ts +1 -21
  143. package/dist/cli/commands/repair/run.js +13 -70
  144. package/dist/cli/commands/storage/index.d.ts +0 -1
  145. package/dist/cli/commands/storage/index.js +0 -1
  146. package/dist/cli/commands/storage/offer.js +6 -2
  147. package/dist/cli/commands/vpn.d.ts +1 -3
  148. package/dist/cli/commands/vpn.js +8 -89
  149. package/dist/cli/commands/web.d.ts +2 -1
  150. package/dist/cli/commands/web.js +14 -78
  151. package/dist/cli/index.js +3 -2
  152. package/dist/cli/manifest.d.ts +16 -153
  153. package/dist/cli/manifest.js +20 -50
  154. package/dist/cli/menu/command-form.js +1 -2
  155. package/dist/cli/menu/io-menu.d.ts +2 -2
  156. package/dist/cli/menu/io-menu.js +6 -4
  157. package/dist/cli/menu/menu.js +1 -1
  158. package/dist/cli/menu/pages/accounts-page.d.ts +5 -17
  159. package/dist/cli/menu/pages/accounts-page.js +28 -170
  160. package/dist/cli/menu/pages/agents-page.d.ts +17 -18
  161. package/dist/cli/menu/pages/agents-page.js +67 -124
  162. package/dist/cli/menu/pages/apps-page.d.ts +15 -8
  163. package/dist/cli/menu/pages/apps-page.js +121 -29
  164. package/dist/cli/menu/pages/list-page.js +10 -1
  165. package/dist/cli/menu/pages/maintenance-page.d.ts +51 -52
  166. package/dist/cli/menu/pages/maintenance-page.js +246 -427
  167. package/dist/cli/menu/pages/sandbox-page.d.ts +3 -5
  168. package/dist/cli/menu/pages/sandbox-page.js +34 -112
  169. package/dist/cli/menu/pages/settings-page.d.ts +21 -3
  170. package/dist/cli/menu/pages/settings-page.js +89 -17
  171. package/dist/cli/menu/render-view.js +2 -1
  172. package/dist/cli/menu/settings/index.d.ts +0 -1
  173. package/dist/cli/menu/settings/index.js +3 -3
  174. package/dist/cli/menu/views.js +28 -0
  175. package/dist/cli/operations/handler.js +7 -3
  176. package/dist/cli/operations/input.d.ts +1 -1
  177. package/dist/cli/operations/input.js +29 -5
  178. package/dist/cli/operations/io-cli.js +9 -1
  179. package/dist/cli/operations/spec.js +8 -2
  180. package/dist/cli/output/render-view.js +2 -0
  181. package/dist/cli/{commands/data/collect.js → services/data-collect.js} +2 -2
  182. package/dist/cli/{commands/data/remove.js → services/data-remove.js} +2 -2
  183. package/dist/cli/services/data-service.d.ts +1 -1
  184. package/dist/cli/services/data-service.js +2 -2
  185. package/dist/cli/services/databases-service.d.ts +5 -0
  186. package/dist/cli/services/databases-service.js +15 -0
  187. package/dist/cli/services/health-service.d.ts +8 -4
  188. package/dist/cli/services/health-service.js +10 -8
  189. package/dist/cli/services/index.d.ts +4 -1
  190. package/dist/cli/services/index.js +4 -1
  191. package/dist/cli/services/logs-service.d.ts +7 -0
  192. package/dist/cli/services/logs-service.js +13 -0
  193. package/dist/cli/services/storage-service.d.ts +19 -0
  194. package/dist/cli/services/storage-service.js +71 -0
  195. package/dist/cli/services/vpn-service.d.ts +6 -4
  196. package/dist/cli/services/vpn-service.js +5 -11
  197. package/dist/cli/services/web-service.d.ts +4 -3
  198. package/dist/cli/services/web-service.js +12 -32
  199. package/dist/core/config/defaults.js +2 -1
  200. package/dist/core/schema/config.d.ts +5 -0
  201. package/dist/core/schema/config.js +2 -0
  202. package/dist/core/schema/github.d.ts +4 -0
  203. package/dist/core/schema/github.js +7 -0
  204. package/dist/core/schema/index.d.ts +1 -0
  205. package/dist/core/schema/index.js +1 -0
  206. package/dist/core/schema/profile.d.ts +1 -0
  207. package/dist/core/schema/profile.js +3 -0
  208. package/dist/core/schema/sandbox.js +3 -3
  209. package/dist/core/schema/toolchains.js +2 -2
  210. package/dist/core/types.d.ts +6 -3
  211. package/dist/guest/boot/boot.js +8 -0
  212. package/dist/guest/daemon/daemon.js +1 -1
  213. package/dist/guest/daemon/sessions.d.ts +3 -2
  214. package/dist/guest/daemon/sessions.js +38 -7
  215. package/dist/guest/governor/core.d.ts +44 -0
  216. package/dist/guest/governor/core.js +124 -0
  217. package/dist/guest/governor/decide.d.ts +46 -18
  218. package/dist/guest/governor/decide.js +136 -82
  219. package/dist/guest/governor/governor.d.ts +2 -38
  220. package/dist/guest/governor/governor.js +33 -113
  221. package/dist/guest/governor/index.d.ts +1 -0
  222. package/dist/guest/governor/index.js +1 -0
  223. package/dist/guest/network/firewall.d.ts +2 -0
  224. package/dist/guest/network/firewall.js +3 -3
  225. package/dist/guest/sessions/viewer.js +5 -1
  226. package/dist/guest/setup/github-token.d.ts +7 -0
  227. package/dist/guest/setup/github-token.js +65 -0
  228. package/dist/guest/toolchains/languages/node.js +11 -1
  229. package/dist/guest/toolchains/native/rust-extras.js +2 -2
  230. package/dist/guest/toolchains/tools/cli.d.ts +8 -0
  231. package/dist/guest/toolchains/tools/cli.js +16 -2
  232. package/dist/guest/vpn/openvpn.d.ts +5 -0
  233. package/dist/guest/vpn/openvpn.js +14 -1
  234. package/dist/guest/vpn/vpn.js +55 -16
  235. package/dist/guest/vpn/wireguard.js +2 -0
  236. package/dist/host/channel/attach.d.ts +1 -0
  237. package/dist/host/channel/attach.js +1 -0
  238. package/dist/host/channel/channel.d.ts +1 -1
  239. package/dist/host/channel/channel.js +2 -2
  240. package/dist/host/engines/hcs/check.d.ts +1 -0
  241. package/dist/host/engines/hcs/check.js +1 -1
  242. package/dist/host/engines/hcs/engine.d.ts +1 -1
  243. package/dist/host/engines/hcs/engine.js +6 -4
  244. package/dist/host/engines/hcs/helper.d.ts +11 -0
  245. package/dist/host/engines/hcs/helper.js +31 -2
  246. package/dist/host/engines/hcs/leftovers.d.ts +42 -0
  247. package/dist/host/engines/hcs/leftovers.js +101 -0
  248. package/dist/host/engines/index.d.ts +1 -0
  249. package/dist/host/engines/index.js +1 -0
  250. package/dist/host/github/deliver.d.ts +13 -0
  251. package/dist/host/github/deliver.js +51 -0
  252. package/dist/host/github/index.d.ts +2 -0
  253. package/dist/host/github/index.js +3 -0
  254. package/dist/host/github/token.d.ts +21 -0
  255. package/dist/host/github/token.js +74 -0
  256. package/dist/host/launch/generate.js +11 -5
  257. package/dist/host/launch/index.d.ts +1 -1
  258. package/dist/host/launch/index.js +1 -1
  259. package/dist/host/launch/session-file.js +1 -2
  260. package/dist/host/launch/wsb-file.d.ts +11 -7
  261. package/dist/host/launch/wsb-file.js +30 -12
  262. package/dist/host/life/watchdog.d.ts +9 -0
  263. package/dist/host/life/watchdog.js +17 -1
  264. package/dist/host/sandbox/tasklist.d.ts +6 -0
  265. package/dist/host/sandbox/tasklist.js +37 -0
  266. package/dist/host/secrets/launch-secrets.d.ts +2 -1
  267. package/dist/host/secrets/launch-secrets.js +4 -2
  268. package/dist/host/vpn/status.js +13 -3
  269. package/dist/host/web/backend.d.ts +1 -3
  270. package/dist/host/web/index.d.ts +2 -1
  271. package/dist/host/web/index.js +2 -1
  272. package/dist/host/web/live.d.ts +23 -0
  273. package/dist/host/web/live.js +107 -0
  274. package/dist/host/web/rpc.d.ts +6 -1
  275. package/dist/host/web/rpc.js +23 -31
  276. package/dist/host/web/runner.d.ts +4 -0
  277. package/dist/host/web/runner.js +12 -1
  278. package/dist/host/web/server.d.ts +30 -2
  279. package/dist/host/web/server.js +87 -29
  280. package/dist/host/web/state.d.ts +1 -0
  281. package/dist/host/web/state.js +2 -0
  282. package/dist/runtime/agent.js +30 -6
  283. package/dist/runtime/daemon.js +323 -176
  284. package/dist/runtime/db.js +30 -6
  285. package/dist/runtime/main.js +375 -76
  286. package/dist/runtime/netproxy.js +30 -6
  287. package/dist/runtime/view.js +495 -146
  288. package/dist/selftest/app.test.js +620 -12
  289. package/dist/selftest/channel.test.js +18 -1
  290. package/dist/selftest/cli.test.js +1 -1
  291. package/dist/selftest/config.test.js +1 -1
  292. package/dist/selftest/contained.test.js +1 -1
  293. package/dist/selftest/data.test.js +1 -2
  294. package/dist/selftest/engine.test.js +3 -1
  295. package/dist/selftest/github.test.d.ts +2 -0
  296. package/dist/selftest/github.test.js +243 -0
  297. package/dist/selftest/hcs.test.js +105 -8
  298. package/dist/selftest/health.test.js +71 -0
  299. package/dist/selftest/heavy-load.test.js +132 -72
  300. package/dist/selftest/index.js +4 -0
  301. package/dist/selftest/layout.test.js +8 -0
  302. package/dist/selftest/live-terminal.test.js +74 -0
  303. package/dist/selftest/menu-screens.js +171 -56
  304. package/dist/selftest/menu.test.js +54 -37
  305. package/dist/selftest/migrate.test.js +14 -12
  306. package/dist/selftest/powershell-variables.test.d.ts +2 -0
  307. package/dist/selftest/powershell-variables.test.js +61 -0
  308. package/dist/selftest/support/engine-golden.js +1 -0
  309. package/dist/selftest/support/fixtures.d.ts +4 -0
  310. package/dist/selftest/support/web-preview.d.ts +1 -0
  311. package/dist/selftest/support/web-preview.js +856 -0
  312. package/dist/selftest/update-service.test.js +15 -8
  313. package/dist/selftest/vpn.test.js +86 -2
  314. package/dist/selftest/web.test.js +58 -11
  315. package/dist/shared/channel/run-dir.d.ts +2 -0
  316. package/dist/shared/channel/run-dir.js +3 -0
  317. package/dist/shared/channel/schema.d.ts +7 -0
  318. package/dist/shared/channel/schema.js +9 -1
  319. package/dist/shared/channel/secrets.d.ts +1 -0
  320. package/dist/shared/channel/secrets.js +3 -0
  321. package/dist/shared/github/index.d.ts +1 -0
  322. package/dist/shared/github/index.js +2 -0
  323. package/dist/shared/github/token.d.ts +29 -0
  324. package/dist/shared/github/token.js +89 -0
  325. package/dist/shared/memory/policy.d.ts +33 -12
  326. package/dist/shared/memory/policy.js +50 -19
  327. package/dist/shared/pty/ctrl-c.d.ts +18 -0
  328. package/dist/shared/pty/ctrl-c.js +36 -0
  329. package/dist/shared/pty/index.d.ts +1 -0
  330. package/dist/shared/pty/index.js +1 -0
  331. package/dist/shared/pty/terminal.d.ts +2 -0
  332. package/dist/shared/pty/terminal.js +21 -2
  333. package/dist/shared/vpn/kill-switch.d.ts +13 -2
  334. package/dist/shared/vpn/kill-switch.js +88 -8
  335. package/dist/shared/web/protocol.d.ts +0 -4
  336. package/dist/sync/watcher.js +1 -1
  337. package/dist/web/index.html +2 -2
  338. package/dist/web/{main-T5DMCHYV.css → main-6JF3ASB5.css} +1 -1
  339. package/dist/web/main-Z645W45E.js +219 -0
  340. package/native/csharp/HcsHost/AssemblyInfo.cs +3 -3
  341. package/native/csharp/HostTools/AssemblyInfo.cs +3 -3
  342. package/package.json +10 -3
  343. package/sandbox/csharp/MemGov.cs +240 -38
  344. package/sandbox/csharp/PtyHost.cs +104 -15
  345. package/sandbox/csharp/SandboxTools/CpuCap.cs +50 -1
  346. package/sandbox/csharp/SandboxTools/Program.cs +1 -1
  347. package/sandbox/scripts/repair-wmi-services.ps1 +26 -0
  348. package/schemas/config.schema.json +19 -5
  349. package/schemas/sandbox-config.schema.json +7 -3
  350. package/dist/cli/commands/accounts.d.ts +0 -2
  351. package/dist/cli/commands/accounts.js +0 -96
  352. package/dist/cli/commands/data/clean.d.ts +0 -3
  353. package/dist/cli/commands/data/clean.js +0 -60
  354. package/dist/cli/commands/data/index.d.ts +0 -4
  355. package/dist/cli/commands/data/index.js +0 -62
  356. package/dist/cli/commands/maintenance/clean.d.ts +0 -2
  357. package/dist/cli/commands/maintenance/clean.js +0 -24
  358. package/dist/cli/commands/maintenance/config-share.d.ts +0 -12
  359. package/dist/cli/commands/maintenance/config-share.js +0 -80
  360. package/dist/cli/commands/projects/projects.d.ts +0 -2
  361. package/dist/cli/commands/projects/projects.js +0 -162
  362. package/dist/cli/commands/storage/contained.d.ts +0 -3
  363. package/dist/cli/commands/storage/contained.js +0 -179
  364. package/dist/cli/commands/storage/storage.d.ts +0 -8
  365. package/dist/cli/commands/storage/storage.js +0 -179
  366. package/dist/cli/menu/add-agent.d.ts +0 -47
  367. package/dist/cli/menu/add-agent.js +0 -168
  368. package/dist/cli/menu/apps.d.ts +0 -69
  369. package/dist/cli/menu/apps.js +0 -214
  370. package/dist/cli/menu/data-folder.d.ts +0 -18
  371. package/dist/cli/menu/data-folder.js +0 -99
  372. package/dist/cli/menu/share-settings.d.ts +0 -21
  373. package/dist/cli/menu/share-settings.js +0 -112
  374. package/dist/cli/menu/vpn-login.d.ts +0 -16
  375. package/dist/cli/menu/vpn-login.js +0 -74
  376. package/dist/web/main-NRRS5O6Z.js +0 -157
  377. /package/dist/cli/{commands/data/collect.d.ts → services/data-collect.d.ts} +0 -0
  378. /package/dist/cli/{commands/data/remove.d.ts → services/data-remove.d.ts} +0 -0
@@ -0,0 +1,208 @@
1
+ // The projects a sandbox can open without a restart: the list, roots, include/exclude, the all-projects setting, and
2
+ // choosing the ticked ones. Pure: schemas, labels and the view; projects.run.ts does the work.
3
+ import { z } from 'zod';
4
+ import { action, defineOperation, defineQuery, defineView, fieldsOf, } from '../../kernel/index.js';
5
+ export const ProjectRowSchema = z.object({
6
+ folder: z.string().describe('The project folder on this PC'),
7
+ here: z.boolean().describe('The folder you are in is inside it'),
8
+ known: z.boolean().describe('Started with this tool before'),
9
+ root: z.string().nullable().describe('The project root it is in, if any'),
10
+ excluded: z.boolean().describe('Excluded from the projects mapped at every start'),
11
+ mappedAtStart: z.boolean().describe('Mapped at every start'),
12
+ running: z.string().nullable().describe('Its name and how it got into the running sandbox, if it is there'),
13
+ });
14
+ export const ProjectsListSchema = z.object({
15
+ all: z.boolean().describe('Every project is mapped at every start (except excluded ones)'),
16
+ roots: z.array(z.string()).describe('Folders of projects, each opened without a restart'),
17
+ exclude: z.array(z.string()).describe('Folders left out of the projects mapped at every start'),
18
+ projects: z.array(ProjectRowSchema).describe('Every project worth listing'),
19
+ });
20
+ const Message = z.object({ message: z.string().describe('What happened') });
21
+ const FolderText = (what) => z
22
+ .string()
23
+ .optional()
24
+ .describe(what + ' (. = this folder; asked when left out)');
25
+ export const listProjects = defineQuery({
26
+ id: 'projects.list',
27
+ title: 'Projects',
28
+ summary: 'list your projects, roots and the all-projects setting',
29
+ input: z.object({}),
30
+ output: ProjectsListSchema,
31
+ cli: { name: 'projects', action: 'list', json: true },
32
+ });
33
+ export const chooseProjects = defineOperation({
34
+ id: 'projects.choose',
35
+ title: 'Choose the projects mapped at every start…',
36
+ summary: 'tick the projects mapped at every start; the rest are excluded',
37
+ input: z.object({}),
38
+ output: Message,
39
+ text: (o) => o.message,
40
+ cli: { name: 'projects', action: 'choose' },
41
+ });
42
+ export const addProject = defineOperation({
43
+ id: 'projects.add',
44
+ title: 'Add a project…',
45
+ summary: 'remember a project folder',
46
+ input: z.object({ projectFolder: FolderText('The project folder') }),
47
+ output: z.object({
48
+ message: z.string().describe('What happened'),
49
+ next: z.string().optional().describe('What to do next, when mapping all projects is off'),
50
+ }),
51
+ text: (o) => (o.next ? o.message + '\n' + o.next : o.message),
52
+ cli: { name: 'projects', action: 'add', positional: ['projectFolder'] },
53
+ });
54
+ export const removeProject = defineOperation({
55
+ id: 'projects.remove',
56
+ title: 'Forget project',
57
+ summary: 'forget a project (nothing in the folder is touched)',
58
+ input: z.object({ projectFolder: FolderText('The project folder') }),
59
+ output: Message,
60
+ danger: true,
61
+ text: (o) => o.message,
62
+ cli: { name: 'projects', action: 'remove', positional: ['projectFolder'] },
63
+ });
64
+ export const includeProject = defineOperation({
65
+ id: 'projects.include',
66
+ title: 'Include',
67
+ summary: 'map a project at every start again',
68
+ input: z.object({ projectFolder: FolderText('The project folder') }),
69
+ output: Message,
70
+ text: (o) => o.message,
71
+ cli: { name: 'projects', action: 'include', positional: ['projectFolder'] },
72
+ });
73
+ export const excludeProject = defineOperation({
74
+ id: 'projects.exclude',
75
+ title: 'Exclude',
76
+ summary: 'leave a project out of the projects mapped at every start',
77
+ input: z.object({ projectFolder: FolderText('The project folder') }),
78
+ output: Message,
79
+ text: (o) => o.message,
80
+ cli: { name: 'projects', action: 'exclude', positional: ['projectFolder'] },
81
+ });
82
+ export const allProjects = defineOperation({
83
+ id: 'projects.all',
84
+ title: 'Map all projects at every start',
85
+ summary: 'map every project at every start, or not',
86
+ input: z.object({ state: z.enum(['on', 'off']).optional().describe('on or off (left out: say which it is)') }),
87
+ output: Message,
88
+ text: (o) => o.message,
89
+ cli: { name: 'projects', action: 'all', positional: ['state'] },
90
+ });
91
+ export const projectRoots = defineOperation({
92
+ id: 'projects.roots',
93
+ title: 'Project roots',
94
+ summary: 'list, add or remove project roots',
95
+ input: z.object({
96
+ change: z.enum(['list', 'add', 'remove']).default('list').describe('list, add or remove'),
97
+ rootFolder: z.string().optional().describe('(add, remove) the folder that holds your projects'),
98
+ }),
99
+ output: Message,
100
+ text: (o) => o.message,
101
+ cli: { name: 'projects', action: 'roots', positional: ['change', 'rootFolder'] },
102
+ });
103
+ /** The folder fields: their names end in Folder, so the menu and the web give them the folder picker. */
104
+ const rootField = fieldsOf(projectRoots.input).find((f) => f.name === 'rootFolder');
105
+ const projectField = fieldsOf(addProject.input).find((f) => f.name === 'projectFolder');
106
+ const ROOT_DESCRIPTION = 'Every project in this folder (also new ones) opens without a restart.';
107
+ function atStart(p) {
108
+ return p.root ? 'root' : p.excluded ? 'excluded' : p.mappedAtStart ? 'mapped' : '-';
109
+ }
110
+ function projectItem(p) {
111
+ return {
112
+ id: 'project:' + p.folder,
113
+ label: p.folder,
114
+ marked: p.here,
115
+ icon: 'project',
116
+ hint: p.running ?? (p.root ? 'in a root' : p.excluded ? 'excluded' : p.mappedAtStart ? 'mapped' : '-'),
117
+ description: p.here ? 'This is the folder you started the menu in.' : undefined,
118
+ details: ['At start ' + atStart(p), 'In sandbox ' + (p.running ?? '-')],
119
+ cells: { here: p.here ? '*' : '', folder: p.folder, atStart: atStart(p), running: p.running ?? '-' },
120
+ actions: [
121
+ action(removeProject, { projectFolder: p.folder }, { key: 'f', verb: 'forget project', importance: 1 }),
122
+ p.excluded
123
+ ? action(includeProject, { projectFolder: p.folder })
124
+ : action(excludeProject, { projectFolder: p.folder }),
125
+ ],
126
+ };
127
+ }
128
+ function rootItem(r) {
129
+ return {
130
+ id: 'root:' + r,
131
+ label: r,
132
+ hint: 'root',
133
+ icon: 'folder',
134
+ description: ROOT_DESCRIPTION,
135
+ keys: 'f removes the root.',
136
+ actions: [
137
+ action(projectRoots, { change: 'remove', rootFolder: r }, { label: 'Remove the root', key: 'f', verb: 'remove root', importance: 1 }),
138
+ ],
139
+ };
140
+ }
141
+ /** The projects page: the settings, the project roots, and the projects (the same rows as the menu's Projects). */
142
+ export function projectsPage(o) {
143
+ const settings = {
144
+ id: 'settings',
145
+ facts: [
146
+ {
147
+ id: 'all',
148
+ label: 'All projects',
149
+ value: o.all ? 'on (every project below is mapped at every start, except excluded ones)' : 'off',
150
+ },
151
+ {
152
+ id: 'roots',
153
+ label: 'Roots',
154
+ value: o.roots.length ? o.roots.join(', ') : 'none (sandbox projects roots add <folder>)',
155
+ },
156
+ ],
157
+ actions: [
158
+ action(allProjects, { state: o.all ? 'off' : 'on' }, { label: o.all ? 'Stop mapping all projects' : 'Map all projects at every start' }),
159
+ ],
160
+ notes: [{ text: 'sandbox projects all on|off', tone: 'muted', only: 'cli' }],
161
+ };
162
+ const roots = {
163
+ id: 'roots',
164
+ title: 'Project roots',
165
+ items: [
166
+ {
167
+ id: '@add-root',
168
+ label: '+ Add a project root…',
169
+ description: 'Pick a folder that holds your projects: every project in it (also new ones) opens without a restart.',
170
+ primary: action(projectRoots, { change: 'add' }, { label: 'Choose the folder…', verb: 'choose folder', fields: [rootField] }),
171
+ },
172
+ ...o.roots.map(rootItem),
173
+ ],
174
+ };
175
+ const projects = {
176
+ id: 'projects',
177
+ title: 'Projects',
178
+ columns: [
179
+ { key: 'here', label: '' },
180
+ { key: 'folder', label: 'FOLDER' },
181
+ { key: 'atStart', label: 'AT START' },
182
+ { key: 'running', label: 'RUNNING SANDBOX' },
183
+ ],
184
+ // The web lists the rows in full (its table cannot carry the row actions: forget, include, exclude).
185
+ columnsOn: 'cli',
186
+ items: o.projects.map(projectItem),
187
+ notes: o.projects.length === 0
188
+ ? [{ text: 'No projects yet: start one with sandbox claude in its folder.', tone: 'muted' }]
189
+ : [{ text: '* = this folder. Choose with: sandbox projects choose', tone: 'muted', only: 'cli' }],
190
+ };
191
+ return {
192
+ title: 'Projects',
193
+ sections: [settings, roots, projects],
194
+ actions: [
195
+ action(chooseProjects, {}, { label: 'Choose…' }),
196
+ action(addProject, {}, { fields: [projectField] }),
197
+ action(projectRoots, { change: 'add' }, { label: 'Add a project root…', key: 'a', verb: 'add root', importance: 1, fields: [rootField] }),
198
+ ],
199
+ };
200
+ }
201
+ export const projectsView = defineView({
202
+ id: 'projects',
203
+ title: 'Projects',
204
+ summary: 'The projects a sandbox opens without a restart: roots, your projects, all or chosen.',
205
+ queries: { projects: listProjects },
206
+ operations: [chooseProjects, addProject, removeProject, includeProject, excludeProject, allProjects, projectRoots],
207
+ build: ({ projects }) => projectsPage(projects),
208
+ });
@@ -0,0 +1,56 @@
1
+ export declare const listProjectsRun: import("../../kernel/define.js").Implementation<import("../../kernel/define.js").QueryDef<import("zod").ZodObject<{}, import("zod/v4/core").$strip>, import("zod").ZodObject<{
2
+ all: import("zod").ZodBoolean;
3
+ roots: import("zod").ZodArray<import("zod").ZodString>;
4
+ exclude: import("zod").ZodArray<import("zod").ZodString>;
5
+ projects: import("zod").ZodArray<import("zod").ZodObject<{
6
+ folder: import("zod").ZodString;
7
+ here: import("zod").ZodBoolean;
8
+ known: import("zod").ZodBoolean;
9
+ root: import("zod").ZodNullable<import("zod").ZodString>;
10
+ excluded: import("zod").ZodBoolean;
11
+ mappedAtStart: import("zod").ZodBoolean;
12
+ running: import("zod").ZodNullable<import("zod").ZodString>;
13
+ }, import("zod/v4/core").$strip>>;
14
+ }, import("zod/v4/core").$strip>, "projects.list">, import("../../../cli/commands/context.js").Context>;
15
+ export declare const chooseProjectsRun: import("../../kernel/define.js").Implementation<import("../../kernel/define.js").OperationDef<import("zod").ZodObject<{}, import("zod/v4/core").$strip>, import("zod").ZodObject<{
16
+ message: import("zod").ZodString;
17
+ }, import("zod/v4/core").$strip>, "projects.choose">, import("../../../cli/commands/context.js").Context>;
18
+ export declare const addProjectRun: import("../../kernel/define.js").Implementation<import("../../kernel/define.js").OperationDef<import("zod").ZodObject<{
19
+ projectFolder: import("zod").ZodOptional<import("zod").ZodString>;
20
+ }, import("zod/v4/core").$strip>, import("zod").ZodObject<{
21
+ message: import("zod").ZodString;
22
+ next: import("zod").ZodOptional<import("zod").ZodString>;
23
+ }, import("zod/v4/core").$strip>, "projects.add">, import("../../../cli/commands/context.js").Context>;
24
+ export declare const removeProjectRun: import("../../kernel/define.js").Implementation<import("../../kernel/define.js").OperationDef<import("zod").ZodObject<{
25
+ projectFolder: import("zod").ZodOptional<import("zod").ZodString>;
26
+ }, import("zod/v4/core").$strip>, import("zod").ZodObject<{
27
+ message: import("zod").ZodString;
28
+ }, import("zod/v4/core").$strip>, "projects.remove">, import("../../../cli/commands/context.js").Context>;
29
+ export declare const includeProjectRun: import("../../kernel/define.js").Implementation<import("../../kernel/define.js").OperationDef<import("zod").ZodObject<{
30
+ projectFolder: import("zod").ZodOptional<import("zod").ZodString>;
31
+ }, import("zod/v4/core").$strip>, import("zod").ZodObject<{
32
+ message: import("zod").ZodString;
33
+ }, import("zod/v4/core").$strip>, "projects.include">, import("../../../cli/commands/context.js").Context>;
34
+ export declare const excludeProjectRun: import("../../kernel/define.js").Implementation<import("../../kernel/define.js").OperationDef<import("zod").ZodObject<{
35
+ projectFolder: import("zod").ZodOptional<import("zod").ZodString>;
36
+ }, import("zod/v4/core").$strip>, import("zod").ZodObject<{
37
+ message: import("zod").ZodString;
38
+ }, import("zod/v4/core").$strip>, "projects.exclude">, import("../../../cli/commands/context.js").Context>;
39
+ export declare const allProjectsRun: import("../../kernel/define.js").Implementation<import("../../kernel/define.js").OperationDef<import("zod").ZodObject<{
40
+ state: import("zod").ZodOptional<import("zod").ZodEnum<{
41
+ off: "off";
42
+ on: "on";
43
+ }>>;
44
+ }, import("zod/v4/core").$strip>, import("zod").ZodObject<{
45
+ message: import("zod").ZodString;
46
+ }, import("zod/v4/core").$strip>, "projects.all">, import("../../../cli/commands/context.js").Context>;
47
+ export declare const projectRootsRun: import("../../kernel/define.js").Implementation<import("../../kernel/define.js").OperationDef<import("zod").ZodObject<{
48
+ change: import("zod").ZodDefault<import("zod").ZodEnum<{
49
+ list: "list";
50
+ add: "add";
51
+ remove: "remove";
52
+ }>>;
53
+ rootFolder: import("zod").ZodOptional<import("zod").ZodString>;
54
+ }, import("zod/v4/core").$strip>, import("zod").ZodObject<{
55
+ message: import("zod").ZodString;
56
+ }, import("zod/v4/core").$strip>, "projects.roots">, import("../../../cli/commands/context.js").Context>;
@@ -0,0 +1,155 @@
1
+ // The projects feature's work: your project list, roots and the all-projects setting, through ProjectsService. Talks
2
+ // only through io. Changes what is mapped from the next start; a running sandbox keeps what it has.
3
+ import path from 'node:path';
4
+ import { isSandboxRunning } from '../../../host/sandbox/index.js';
5
+ import { fail } from '../../../core/util/index.js';
6
+ import { hereDir } from '../../../cli/commands/projects/here.js';
7
+ import { ProjectsService } from '../../../cli/services/index.js';
8
+ import { implement } from '../../context.js';
9
+ import { cancelled } from '../../kernel/index.js';
10
+ import { addProject, allProjects, chooseProjects, excludeProject, includeProject, listProjects, projectRoots, removeProject, } from './projects.def.js';
11
+ const NEXT_START = 'This changes what is mapped from the next start.';
12
+ function runningNote() {
13
+ return isSandboxRunning()
14
+ ? ' The running sandbox keeps what it has; start a project in it (sandbox claude there) and it joins without a restart when it can, or you are offered one.'
15
+ : '';
16
+ }
17
+ /** The folder given, or one picked from the known projects (or this folder) when it was left out. */
18
+ async function pickFolder(ctx, io, given) {
19
+ if (given)
20
+ return path.resolve(given);
21
+ const here = hereDir(ctx);
22
+ const chosen = await io.choose({
23
+ title: 'Which folder?',
24
+ choices: [
25
+ { value: here, label: 'This folder (' + here + ')' },
26
+ ...new ProjectsService(ctx)
27
+ .rows()
28
+ .filter((r) => !r.here)
29
+ .map((r) => ({ value: r.folder, label: r.folder })),
30
+ ],
31
+ });
32
+ if (chosen === undefined)
33
+ cancelled();
34
+ return chosen;
35
+ }
36
+ export const listProjectsRun = implement(listProjects, async (ctx) => new ProjectsService(ctx).list());
37
+ export const chooseProjectsRun = implement(chooseProjects, async (ctx, _input, io) => {
38
+ const service = new ProjectsService(ctx);
39
+ const rows = service.rows().filter((r) => !r.root);
40
+ if (!rows.length)
41
+ return {
42
+ message: 'No projects to choose from yet (projects in a root are always mapped with it). Start one with sandbox claude in its folder.',
43
+ };
44
+ const all = service.settings().all;
45
+ const picked = await io.checklist({
46
+ title: 'Projects mapped at every start, so they open without a restart (every agent in the sandbox can see them):',
47
+ choices: rows.map((r) => ({ value: r.folder, label: r.folder + (r.here ? ' (this folder)' : '') })),
48
+ checked: rows.filter((r) => all && !r.excluded).map((r) => r.folder),
49
+ });
50
+ if (picked === undefined)
51
+ cancelled();
52
+ const { mapped, excluded } = service.choose(rows, picked);
53
+ return {
54
+ message: mapped + ' project(s) mapped at every start, ' + excluded + ' excluded. ' + NEXT_START + runningNote(),
55
+ };
56
+ });
57
+ export const addProjectRun = implement(addProject, async (ctx, input, io) => {
58
+ const folder = await pickFolder(ctx, io, input.projectFolder);
59
+ const service = new ProjectsService(ctx);
60
+ const dir = service.add(folder);
61
+ const all = service.settings().all;
62
+ return {
63
+ message: 'Added ' + dir + ' to your projects.' + (all ? ' ' + NEXT_START : ''),
64
+ ...(all ? {} : { next: 'Next: sandbox projects all on (map every project at every start)' }),
65
+ };
66
+ });
67
+ export const removeProjectRun = implement(removeProject, async (ctx, input, io) => {
68
+ const dir = await pickFolder(ctx, io, input.projectFolder);
69
+ const yes = await io.confirm({
70
+ title: 'Forget ' + path.basename(dir) + '?',
71
+ lines: ['The project is dropped from your list of projects.', 'Nothing in ' + dir + ' is touched.'],
72
+ yes: 'Forget',
73
+ danger: true,
74
+ implied: true,
75
+ });
76
+ if (!yes)
77
+ cancelled();
78
+ const { dir: forgotten, removed } = new ProjectsService(ctx).forget(dir);
79
+ return {
80
+ message: removed
81
+ ? 'Removed ' + forgotten + ' from your projects (nothing in the folder was touched).'
82
+ : forgotten + ' was not in your projects.',
83
+ };
84
+ });
85
+ export const includeProjectRun = implement(includeProject, async (ctx, input, io) => {
86
+ const dir = await pickFolder(ctx, io, input.projectFolder);
87
+ const service = new ProjectsService(ctx);
88
+ const changed = service.include(dir);
89
+ return { message: includeOrExcludeText(service, 'include', dir, changed) };
90
+ });
91
+ export const excludeProjectRun = implement(excludeProject, async (ctx, input, io) => {
92
+ const dir = await pickFolder(ctx, io, input.projectFolder);
93
+ const service = new ProjectsService(ctx);
94
+ const changed = service.exclude(dir);
95
+ return { message: includeOrExcludeText(service, 'exclude', dir, changed) };
96
+ });
97
+ /** The sentence include and exclude print. */
98
+ function includeOrExcludeText(service, action, dir, changed) {
99
+ return ((changed
100
+ ? (action === 'exclude' ? 'Excluded ' : 'Included ') + path.resolve(dir) + '. ' + NEXT_START
101
+ : 'Nothing changed.') +
102
+ (action === 'include' && !service.settings().all
103
+ ? ' Mapping all projects is off: sandbox projects all on maps your projects at every start.'
104
+ : '') +
105
+ (changed ? runningNote() : ''));
106
+ }
107
+ export const allProjectsRun = implement(allProjects, async (ctx, input) => {
108
+ const service = new ProjectsService(ctx);
109
+ if (input.state === undefined)
110
+ return { message: 'Mapping all projects at every start is ' + (service.settings().all ? 'on' : 'off') + '.' };
111
+ service.setAll(input.state === 'on');
112
+ return {
113
+ message: 'Mapping all projects at every start is ' +
114
+ input.state +
115
+ '. ' +
116
+ NEXT_START +
117
+ (input.state === 'on' ? ' Every agent in the sandbox can then see all of those projects.' : '') +
118
+ runningNote(),
119
+ };
120
+ });
121
+ export const projectRootsRun = implement(projectRoots, async (ctx, input, io) => {
122
+ const service = new ProjectsService(ctx);
123
+ if (input.change === 'list') {
124
+ const list = service.settings().roots;
125
+ return {
126
+ message: list.length ? list.join('\n') : 'No project roots. Add one: sandbox projects roots add <folder>',
127
+ };
128
+ }
129
+ if (!input.rootFolder)
130
+ fail('Which folder?', 'Usage: sandbox projects roots ' + input.change + ' <folder>');
131
+ if (input.change === 'add') {
132
+ const { dir, added } = service.addRoot(input.rootFolder);
133
+ return {
134
+ message: added
135
+ ? 'Added the project root ' +
136
+ dir +
137
+ ': every project in it (also new ones) opens without a restart. Every agent in the sandbox can see all of them. ' +
138
+ NEXT_START +
139
+ runningNote()
140
+ : dir + ' is a root already.',
141
+ };
142
+ }
143
+ const dir = path.resolve(input.rootFolder);
144
+ const yes = await io.confirm({
145
+ title: 'Remove the root ' + path.basename(dir) + '?',
146
+ lines: ['Its projects are no longer opened without a restart.', 'Nothing in ' + dir + ' is touched.'],
147
+ yes: 'Remove',
148
+ danger: true,
149
+ implied: true,
150
+ });
151
+ if (!yes)
152
+ cancelled();
153
+ const { removed } = service.removeRoot(dir);
154
+ return { message: removed ? 'Removed the project root ' + dir + '. ' + NEXT_START : dir + ' was not a root.' };
155
+ });
@@ -126,6 +126,7 @@ function projectItem(p) {
126
126
  return {
127
127
  id: 'project:' + p.name,
128
128
  label: p.name,
129
+ icon: 'project',
129
130
  hint: p.host + ' -> ' + p.guest + ' (' + (MECHANISM_TEXT[p.mechanism] ?? 'wsb share') + ')',
130
131
  marked: p.here,
131
132
  details: [
@@ -149,11 +150,12 @@ function facts(o) {
149
150
  });
150
151
  return [
151
152
  ...(o.shared?.startedBy ? [fact('owner', 'Started by', o.shared.startedBy)] : []),
152
- fact('running', 'Running', s.running ? 'yes' : 'no', { tone: s.running ? 'ok' : 'muted' }),
153
+ // One line for what it is doing: "Ready", "Installing Rust ...", or "not running".
154
+ fact('state', 'State', s.running ? s.message || s.phase : 'not running', {
155
+ tone: !s.running ? 'muted' : s.phase === 'ready' ? 'ok' : 'warn',
156
+ }),
153
157
  ...(s.running
154
158
  ? [
155
- fact('phase', 'Phase', s.phase, { tone: s.phase === 'ready' ? 'ok' : 'warn' }),
156
- fact('message', 'Message', s.message || '-'),
157
159
  fact('window', 'Window', s.headless ? 'hidden (sandbox show opens it)' : 'shown'),
158
160
  fact('uptime', 'Uptime', uptime(s) ?? '-'),
159
161
  fact('helper', 'Helper', s.daemon === '-' ? '-' : helperText(s.daemon)),
@@ -168,6 +170,7 @@ function projectsSection(o) {
168
170
  const roots = o.roots.map((r) => ({
169
171
  id: 'root:' + r.host,
170
172
  label: 'root',
173
+ icon: 'folder',
171
174
  hint: r.host + ' -> ' + r.guest + ' (every project in it opens without a restart)',
172
175
  }));
173
176
  const here = o.projects.some((p) => p.here);
@@ -206,11 +209,14 @@ export function sandboxPage(o) {
206
209
  const running = o.sandbox.running;
207
210
  const status = {
208
211
  id: 'status',
212
+ title: 'Status',
209
213
  facts: facts(o),
214
+ // Only the window action that changes something: show a hidden window, hide a shown one.
210
215
  actions: running
211
216
  ? [
212
- action(showWindow, {}, { key: 'w', verb: 'show', importance: 3 }),
213
- action(hideWindow, {}, { key: 'h', verb: 'hide', importance: 3 }),
217
+ o.sandbox.headless
218
+ ? action(showWindow, {}, { key: 'w', verb: 'show', importance: 3 })
219
+ : action(hideWindow, {}, { key: 'h', verb: 'hide', importance: 3 }),
214
220
  action(stopSandbox, {}, { key: 'x', verb: 'stop', importance: 1 }),
215
221
  ]
216
222
  : [],
@@ -92,6 +92,7 @@ function sessionItem(s, wide) {
92
92
  badges: [{ text: s.phase, tone: running ? 'ok' : s.phase === 'failed' ? 'danger' : 'muted' }],
93
93
  group: s.here ? "This folder's project" : 'Other sessions',
94
94
  marked: s.here,
95
+ icon: s.harness,
95
96
  description: running
96
97
  ? "Opens this session's terminal (in a terminal, Ctrl+] detaches; the session keeps running)."
97
98
  : undefined,
@@ -126,6 +127,7 @@ export function sessionsPage(o) {
126
127
  sections: [
127
128
  {
128
129
  id: 'sessions',
130
+ cards: true,
129
131
  columns: [
130
132
  { key: 'here', label: '' },
131
133
  { key: 'id', label: 'ID' },
@@ -147,6 +149,7 @@ export function sessionsPage(o) {
147
149
  ...startSection,
148
150
  ],
149
151
  actions: [
152
+ ...(o.sandboxRunning ? [{ ...start, label: 'New session', key: 'n', verb: 'new session', importance: 1 }] : []),
150
153
  ...(sessions.length
151
154
  ? [action(restartSessions, { all: false }, { key: 'r', verb: 'restart agents', importance: 1 })]
152
155
  : []),
@@ -42,8 +42,8 @@ export const CATEGORIES = [
42
42
  {
43
43
  id: 'security',
44
44
  label: 'Security & privacy',
45
- description: 'Git-ignored files kept out, secrets kept out of the sandbox, download checks, what is kept on this PC, and sharing your sandbox with other Windows users.',
46
- keys: ['workspaceFilter', 'audit', 'secrets', 'downloads', 'storage', 'sharing'],
45
+ description: 'Git-ignored files kept out, secrets kept out of the sandbox, a GitHub token for sandboxes (with its login set here), download checks, what is kept on this PC, and sharing your sandbox with other Windows users.',
46
+ keys: ['workspaceFilter', 'audit', 'secrets', 'github', 'downloads', 'storage', 'sharing'],
47
47
  },
48
48
  {
49
49
  id: 'projects',
@@ -67,6 +67,7 @@ const NAMES = {
67
67
  storage: 'Storage on this PC',
68
68
  network: 'Network',
69
69
  vpn: 'VPN',
70
+ github: 'GitHub',
70
71
  hooks: 'Hooks',
71
72
  personalization: 'Desktop look',
72
73
  projects: 'Projects',
@@ -1,5 +1,5 @@
1
1
  import type { Config } from '../../../core/types.js';
2
- import type { SettingChange } from '../../../app/features/settings/index.js';
2
+ import type { SettingChange } from './settings-file.js';
3
3
  /** Why something was left out. */
4
4
  export interface Skipped {
5
5
  readonly key: string;
@@ -1,11 +1,12 @@
1
1
  // Sharing your settings: the part of them that differs from the defaults, as a .json a team can pass around, and the
2
2
  // reverse (read a file, show what it would change, apply the rest). Secrets (anything the schema marks), the data
3
- // folder and folders or files of this PC never go into a file and are never taken from one.
3
+ // folder and folders or files of this PC never go into a file and are never taken from one. Node side (lodash,
4
+ // core/schema): the settings run functions use these; the menu and the web only see the operations.
4
5
  import { parse } from 'jsonc-parser';
5
6
  import _ from 'lodash';
6
7
  import { DEFAULTS, mergeConfig } from '../../../core/config/index.js';
7
8
  import { ConfigSchema, describeIssues, secretPaths } from '../../../core/schema/index.js';
8
- import { pathKindOf } from '../../../app/kernel/index.js';
9
+ import { pathKindOf } from '../../kernel/index.js';
9
10
  /** Settings that are about this PC and never travel (the data folder). */
10
11
  const MACHINE_ONLY = ['storage.root'];
11
12
  /** A folder or file of this PC: a drive path, a network path, a rooted path or a %VARIABLE% path. */
@@ -1,5 +1,5 @@
1
1
  import { z } from 'zod';
2
- import { type Page } from '../../kernel/index.js';
2
+ import { type Field, type Page } from '../../kernel/index.js';
3
3
  export declare const ScopeSchema: z.ZodEnum<{
4
4
  project: "project";
5
5
  user: "user";
@@ -12,7 +12,7 @@ export declare const SettingRowSchema: z.ZodObject<{
12
12
  label: z.ZodString;
13
13
  category: z.ZodString;
14
14
  section: z.ZodOptional<z.ZodString>;
15
- field: z.ZodType<import("../../kernel/fields.js").Field, unknown, z.core.$ZodTypeInternals<import("../../kernel/fields.js").Field, unknown>>;
15
+ field: z.ZodType<Field, unknown, z.core.$ZodTypeInternals<Field, unknown>>;
16
16
  value: z.ZodUnknown;
17
17
  set: z.ZodBoolean;
18
18
  yours: z.ZodUnknown;
@@ -30,6 +30,7 @@ export declare const SettingsListSchema: z.ZodObject<{
30
30
  file: z.ZodString;
31
31
  exists: z.ZodBoolean;
32
32
  dataFolder: z.ZodOptional<z.ZodString>;
33
+ exportFile: z.ZodOptional<z.ZodString>;
33
34
  categories: z.ZodArray<z.ZodObject<{
34
35
  id: z.ZodString;
35
36
  label: z.ZodString;
@@ -41,7 +42,7 @@ export declare const SettingsListSchema: z.ZodObject<{
41
42
  label: z.ZodString;
42
43
  category: z.ZodString;
43
44
  section: z.ZodOptional<z.ZodString>;
44
- field: z.ZodType<import("../../kernel/fields.js").Field, unknown, z.core.$ZodTypeInternals<import("../../kernel/fields.js").Field, unknown>>;
45
+ field: z.ZodType<Field, unknown, z.core.$ZodTypeInternals<Field, unknown>>;
45
46
  value: z.ZodUnknown;
46
47
  set: z.ZodBoolean;
47
48
  yours: z.ZodUnknown;
@@ -65,6 +66,7 @@ export declare const listSettings: import("../../kernel/define.js").QueryDef<z.Z
65
66
  file: z.ZodString;
66
67
  exists: z.ZodBoolean;
67
68
  dataFolder: z.ZodOptional<z.ZodString>;
69
+ exportFile: z.ZodOptional<z.ZodString>;
68
70
  categories: z.ZodArray<z.ZodObject<{
69
71
  id: z.ZodString;
70
72
  label: z.ZodString;
@@ -76,7 +78,7 @@ export declare const listSettings: import("../../kernel/define.js").QueryDef<z.Z
76
78
  label: z.ZodString;
77
79
  category: z.ZodString;
78
80
  section: z.ZodOptional<z.ZodString>;
79
- field: z.ZodType<import("../../kernel/fields.js").Field, unknown, z.core.$ZodTypeInternals<import("../../kernel/fields.js").Field, unknown>>;
81
+ field: z.ZodType<Field, unknown, z.core.$ZodTypeInternals<Field, unknown>>;
80
82
  value: z.ZodUnknown;
81
83
  set: z.ZodBoolean;
82
84
  yours: z.ZodUnknown;
@@ -115,6 +117,20 @@ export declare const resetSetting: import("../../kernel/define.js").OperationDef
115
117
  changed: z.ZodBoolean;
116
118
  message: z.ZodString;
117
119
  }, z.core.$strip>, "settings.reset">;
120
+ export declare const exportConfig: import("../../kernel/define.js").OperationDef<z.ZodObject<{
121
+ settingsFile: z.ZodOptional<z.ZodString>;
122
+ withPaths: z.ZodDefault<z.ZodBoolean>;
123
+ }, z.core.$strip>, z.ZodObject<{
124
+ file: z.ZodString;
125
+ leftOut: z.ZodArray<z.ZodString>;
126
+ pathsLeftOut: z.ZodBoolean;
127
+ }, z.core.$strip>, "settings.export">;
128
+ export declare const importConfig: import("../../kernel/define.js").OperationDef<z.ZodObject<{
129
+ settingsFile: z.ZodOptional<z.ZodString>;
130
+ }, z.core.$strip>, z.ZodObject<{
131
+ changed: z.ZodNumber;
132
+ message: z.ZodString;
133
+ }, z.core.$strip>, "settings.import">;
118
134
  /** The settings page of one scope: a section per category, each setting with its value and an edit action. */
119
135
  export declare function settingsPage(o: SettingsList): Page;
120
136
  export declare const settingsView: import("../../kernel/define.js").ViewDef<{
@@ -131,6 +147,7 @@ export declare const settingsView: import("../../kernel/define.js").ViewDef<{
131
147
  file: z.ZodString;
132
148
  exists: z.ZodBoolean;
133
149
  dataFolder: z.ZodOptional<z.ZodString>;
150
+ exportFile: z.ZodOptional<z.ZodString>;
134
151
  categories: z.ZodArray<z.ZodObject<{
135
152
  id: z.ZodString;
136
153
  label: z.ZodString;
@@ -142,7 +159,7 @@ export declare const settingsView: import("../../kernel/define.js").ViewDef<{
142
159
  label: z.ZodString;
143
160
  category: z.ZodString;
144
161
  section: z.ZodOptional<z.ZodString>;
145
- field: z.ZodType<import("../../kernel/fields.js").Field, unknown, z.core.$ZodTypeInternals<import("../../kernel/fields.js").Field, unknown>>;
162
+ field: z.ZodType<Field, unknown, z.core.$ZodTypeInternals<Field, unknown>>;
146
163
  value: z.ZodUnknown;
147
164
  set: z.ZodBoolean;
148
165
  yours: z.ZodUnknown;