windows-development-sandbox 1.5.0 → 1.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (448) hide show
  1. package/README.md +1 -0
  2. package/config.example.json +17 -1
  3. package/dist/cli/args.d.ts +13 -2
  4. package/dist/cli/args.js +95 -24
  5. package/dist/cli/commands/accounts.js +45 -17
  6. package/dist/cli/commands/context.d.ts +2 -0
  7. package/dist/cli/commands/context.js +9 -2
  8. package/dist/cli/commands/data/clean.js +32 -9
  9. package/dist/cli/commands/index.d.ts +1 -0
  10. package/dist/cli/commands/index.js +1 -0
  11. package/dist/cli/commands/launch/add-root.d.ts +3 -2
  12. package/dist/cli/commands/launch/add-root.js +11 -10
  13. package/dist/cli/commands/launch/launch.js +57 -4
  14. package/dist/cli/commands/launch/prepare.js +3 -1
  15. package/dist/cli/commands/maintenance/audit.js +1 -1
  16. package/dist/cli/commands/maintenance/clean.d.ts +1 -1
  17. package/dist/cli/commands/maintenance/clean.js +17 -3
  18. package/dist/cli/commands/maintenance/config.d.ts +1 -1
  19. package/dist/cli/commands/maintenance/config.js +112 -10
  20. package/dist/cli/commands/maintenance/doctor.d.ts +1 -1
  21. package/dist/cli/commands/maintenance/doctor.js +2 -4
  22. package/dist/cli/commands/maintenance/migrate.d.ts +2 -1
  23. package/dist/cli/commands/maintenance/migrate.js +19 -4
  24. package/dist/cli/commands/maintenance/sync.js +2 -0
  25. package/dist/cli/commands/maintenance/update.d.ts +2 -0
  26. package/dist/cli/commands/maintenance/update.js +27 -4
  27. package/dist/cli/commands/projects/here.js +12 -7
  28. package/dist/cli/commands/projects/projects.js +26 -17
  29. package/dist/cli/commands/registry.js +7 -0
  30. package/dist/cli/commands/repair/checks/agents.d.ts +2 -0
  31. package/dist/cli/commands/repair/checks/agents.js +70 -0
  32. package/dist/cli/commands/repair/checks/common.d.ts +8 -0
  33. package/dist/cli/commands/repair/checks/common.js +22 -0
  34. package/dist/cli/commands/repair/checks/data.d.ts +2 -0
  35. package/dist/cli/commands/repair/checks/data.js +241 -0
  36. package/dist/cli/commands/repair/checks/index.d.ts +2 -0
  37. package/dist/cli/commands/repair/checks/index.js +20 -0
  38. package/dist/cli/commands/repair/checks/install.d.ts +5 -0
  39. package/dist/cli/commands/repair/checks/install.js +318 -0
  40. package/dist/cli/commands/repair/checks/machine.d.ts +2 -0
  41. package/dist/cli/commands/repair/checks/machine.js +232 -0
  42. package/dist/cli/commands/repair/checks/network.d.ts +6 -0
  43. package/dist/cli/commands/repair/checks/network.js +60 -0
  44. package/dist/cli/commands/repair/checks/pc.d.ts +4 -0
  45. package/dist/cli/commands/repair/checks/pc.js +55 -0
  46. package/dist/cli/commands/repair/checks/sandbox.d.ts +2 -0
  47. package/dist/cli/commands/repair/checks/sandbox.js +267 -0
  48. package/dist/cli/commands/repair/checks/settings.d.ts +2 -0
  49. package/dist/cli/commands/repair/checks/settings.js +169 -0
  50. package/dist/cli/commands/repair/checks/vpn.d.ts +2 -0
  51. package/dist/cli/commands/repair/checks/vpn.js +53 -0
  52. package/dist/cli/commands/repair/engine.d.ts +32 -0
  53. package/dist/cli/commands/repair/engine.js +127 -0
  54. package/dist/cli/commands/repair/env.d.ts +7 -0
  55. package/dist/cli/commands/repair/env.js +49 -0
  56. package/dist/cli/commands/repair/index.d.ts +1 -9
  57. package/dist/cli/commands/repair/index.js +2 -54
  58. package/dist/cli/commands/repair/log.d.ts +17 -0
  59. package/dist/cli/commands/repair/log.js +82 -0
  60. package/dist/cli/commands/repair/printer.d.ts +32 -0
  61. package/dist/cli/commands/repair/printer.js +132 -0
  62. package/dist/cli/commands/repair/run.d.ts +33 -0
  63. package/dist/cli/commands/repair/run.js +133 -0
  64. package/dist/cli/commands/repair/types.d.ts +97 -9
  65. package/dist/cli/commands/repair/types.js +11 -7
  66. package/dist/cli/commands/resume.js +2 -2
  67. package/dist/cli/commands/sessions/list.js +5 -2
  68. package/dist/cli/commands/sessions/status.d.ts +2 -0
  69. package/dist/cli/commands/sessions/status.js +27 -6
  70. package/dist/cli/commands/setup/index.d.ts +5 -0
  71. package/dist/cli/commands/setup/index.js +25 -1
  72. package/dist/cli/commands/storage/index.d.ts +2 -0
  73. package/dist/cli/commands/storage/index.js +2 -0
  74. package/dist/cli/commands/storage/offer.d.ts +3 -0
  75. package/dist/cli/commands/storage/offer.js +85 -0
  76. package/dist/cli/commands/storage/storage.d.ts +8 -0
  77. package/dist/cli/commands/storage/storage.js +171 -0
  78. package/dist/cli/commands/user-config.js +1 -1
  79. package/dist/cli/commands/vpn.d.ts +4 -0
  80. package/dist/cli/commands/vpn.js +75 -0
  81. package/dist/cli/commands/web.d.ts +4 -0
  82. package/dist/cli/commands/web.js +95 -0
  83. package/dist/cli/history.js +1 -1
  84. package/dist/cli/index.js +46 -3
  85. package/dist/cli/manifest.d.ts +303 -29
  86. package/dist/cli/manifest.js +173 -43
  87. package/dist/cli/menu/add-agent.d.ts +47 -0
  88. package/dist/cli/menu/add-agent.js +168 -0
  89. package/dist/cli/menu/apps.d.ts +31 -2
  90. package/dist/cli/menu/apps.js +44 -5
  91. package/dist/cli/menu/command-fields.d.ts +18 -0
  92. package/dist/cli/menu/command-fields.js +61 -0
  93. package/dist/cli/menu/command-form.d.ts +22 -0
  94. package/dist/cli/menu/command-form.js +169 -46
  95. package/dist/cli/menu/data-folder.d.ts +18 -0
  96. package/dist/cli/menu/data-folder.js +99 -0
  97. package/dist/cli/menu/menu.d.ts +1 -1
  98. package/dist/cli/menu/menu.js +11 -8
  99. package/dist/cli/menu/pages/accounts-page.js +55 -24
  100. package/dist/cli/menu/pages/agents-page.d.ts +66 -0
  101. package/dist/cli/menu/pages/agents-page.js +338 -0
  102. package/dist/cli/menu/pages/apps-page.js +1 -2
  103. package/dist/cli/menu/pages/list-page.d.ts +16 -3
  104. package/dist/cli/menu/pages/list-page.js +40 -8
  105. package/dist/cli/menu/pages/maintenance-page.d.ts +9 -0
  106. package/dist/cli/menu/pages/maintenance-page.js +161 -72
  107. package/dist/cli/menu/pages/sandbox-page.d.ts +3 -0
  108. package/dist/cli/menu/pages/sandbox-page.js +132 -43
  109. package/dist/cli/menu/pages/sessions-page.d.ts +4 -0
  110. package/dist/cli/menu/pages/sessions-page.js +41 -25
  111. package/dist/cli/menu/pages/settings-page.d.ts +8 -4
  112. package/dist/cli/menu/pages/settings-page.js +36 -13
  113. package/dist/cli/menu/settings/categories.d.ts +2 -0
  114. package/dist/cli/menu/settings/categories.js +19 -44
  115. package/dist/cli/menu/settings/collections/collection-editor.d.ts +7 -1
  116. package/dist/cli/menu/settings/collections/collection-editor.js +12 -8
  117. package/dist/cli/menu/settings/collections/map-editor.js +5 -1
  118. package/dist/cli/menu/settings/collections/object-list-editor.js +2 -2
  119. package/dist/cli/menu/settings/collections/object-map-editor.js +2 -2
  120. package/dist/cli/menu/settings/collections/string-list-editor.d.ts +11 -1
  121. package/dist/cli/menu/settings/collections/string-list-editor.js +23 -0
  122. package/dist/cli/menu/settings/index.d.ts +1 -1
  123. package/dist/cli/menu/settings/index.js +1 -1
  124. package/dist/cli/menu/settings/object-editor.d.ts +5 -1
  125. package/dist/cli/menu/settings/object-editor.js +15 -4
  126. package/dist/cli/menu/settings/path-kind.d.ts +20 -0
  127. package/dist/cli/menu/settings/path-kind.js +44 -0
  128. package/dist/cli/menu/settings/schema-node.d.ts +9 -0
  129. package/dist/cli/menu/settings/schema-node.js +26 -0
  130. package/dist/cli/menu/settings/value-editor.d.ts +5 -0
  131. package/dist/cli/menu/settings/value-editor.js +51 -18
  132. package/dist/cli/menu/several.js +7 -5
  133. package/dist/cli/menu/shell.d.ts +37 -10
  134. package/dist/cli/menu/shell.js +90 -10
  135. package/dist/cli/menu/vpn-login.d.ts +16 -0
  136. package/dist/cli/menu/vpn-login.js +66 -0
  137. package/dist/cli/output/print.d.ts +2 -0
  138. package/dist/cli/output/print.js +8 -1
  139. package/dist/cli/services/accounts-service.d.ts +2 -0
  140. package/dist/cli/services/accounts-service.js +2 -2
  141. package/dist/cli/services/health-service.d.ts +0 -6
  142. package/dist/cli/services/health-service.js +5 -42
  143. package/dist/cli/services/index.d.ts +3 -1
  144. package/dist/cli/services/index.js +3 -1
  145. package/dist/cli/services/migrate-service.js +1 -1
  146. package/dist/cli/services/update-service.d.ts +2 -0
  147. package/dist/cli/services/update-service.js +13 -6
  148. package/dist/cli/services/vpn-service.d.ts +28 -0
  149. package/dist/cli/services/vpn-service.js +46 -0
  150. package/dist/cli/services/web-service.d.ts +22 -0
  151. package/dist/cli/services/web-service.js +111 -0
  152. package/dist/cli/tui/app.d.ts +6 -3
  153. package/dist/cli/tui/app.js +12 -5
  154. package/dist/cli/tui/dialogs/path-listing.d.ts +43 -0
  155. package/dist/cli/tui/dialogs/path-listing.js +127 -0
  156. package/dist/cli/tui/dialogs/path-picker.d.ts +67 -0
  157. package/dist/cli/tui/dialogs/path-picker.js +423 -0
  158. package/dist/cli/tui/dialogs/text-screen.d.ts +6 -0
  159. package/dist/cli/tui/dialogs/text-screen.js +10 -3
  160. package/dist/cli/tui/frame.d.ts +7 -10
  161. package/dist/cli/tui/frame.js +19 -10
  162. package/dist/cli/tui/index.d.ts +4 -3
  163. package/dist/cli/tui/index.js +2 -1
  164. package/dist/cli/tui/list/list-screen.d.ts +14 -2
  165. package/dist/cli/tui/list/list-screen.js +68 -32
  166. package/dist/cli/tui/list/list-types.d.ts +8 -4
  167. package/dist/cli/tui/nav.d.ts +29 -0
  168. package/dist/cli/tui/nav.js +67 -0
  169. package/dist/cli/validate.d.ts +1 -1
  170. package/dist/cli/validate.js +3 -3
  171. package/dist/cli/version.d.ts +2 -0
  172. package/dist/cli/version.js +11 -0
  173. package/dist/core/config/defaults.js +5 -1
  174. package/dist/core/config/loader.js +12 -2
  175. package/dist/core/local-config/overrides.js +1 -0
  176. package/dist/core/prompt.d.ts +19 -0
  177. package/dist/core/prompt.js +43 -3
  178. package/dist/core/schema/common.d.ts +6 -0
  179. package/dist/core/schema/common.js +8 -0
  180. package/dist/core/schema/config.d.ts +23 -0
  181. package/dist/core/schema/config.js +10 -1
  182. package/dist/core/schema/harness.d.ts +1 -0
  183. package/dist/core/schema/harness.js +8 -2
  184. package/dist/core/schema/index.d.ts +3 -1
  185. package/dist/core/schema/index.js +3 -1
  186. package/dist/core/schema/profile.d.ts +1 -0
  187. package/dist/core/schema/profile.js +3 -0
  188. package/dist/core/schema/redact.d.ts +13 -0
  189. package/dist/core/schema/redact.js +75 -0
  190. package/dist/core/schema/sandbox.js +1 -0
  191. package/dist/core/schema/vpn.d.ts +17 -0
  192. package/dist/core/schema/vpn.js +22 -0
  193. package/dist/core/schema/web.d.ts +6 -0
  194. package/dist/core/schema/web.js +14 -0
  195. package/dist/core/types.d.ts +26 -0
  196. package/dist/guest/agents/agent-files.d.ts +49 -0
  197. package/dist/guest/agents/agent-files.js +63 -0
  198. package/dist/guest/agents/agent-installer.js +2 -9
  199. package/dist/guest/agents/local-state.d.ts +12 -0
  200. package/dist/guest/agents/local-state.js +198 -0
  201. package/dist/guest/agents/sbx-agent.d.ts +2 -0
  202. package/dist/guest/agents/sbx-agent.js +35 -0
  203. package/dist/guest/boot/boot.d.ts +4 -0
  204. package/dist/guest/boot/boot.js +50 -11
  205. package/dist/guest/daemon/daemon.js +4 -1
  206. package/dist/guest/daemon/exec.js +2 -1
  207. package/dist/guest/daemon/idle-shutdown.js +2 -0
  208. package/dist/guest/daemon/sessions.js +4 -1
  209. package/dist/guest/entries/agent.d.ts +1 -0
  210. package/dist/guest/entries/agent.js +10 -0
  211. package/dist/guest/entries/daemon.js +2 -0
  212. package/dist/guest/runtime/csc.d.ts +1 -0
  213. package/dist/guest/runtime/csc.js +1 -0
  214. package/dist/guest/runtime/secrets.d.ts +12 -0
  215. package/dist/guest/runtime/secrets.js +63 -0
  216. package/dist/guest/setup/claude-profile.d.ts +2 -1
  217. package/dist/guest/setup/claude-profile.js +12 -1
  218. package/dist/guest/setup/environment.d.ts +6 -0
  219. package/dist/guest/setup/environment.js +56 -6
  220. package/dist/guest/setup/path-plan.d.ts +32 -0
  221. package/dist/guest/setup/path-plan.js +67 -0
  222. package/dist/guest/setup/shell-path.d.ts +1 -0
  223. package/dist/guest/setup/shell-path.js +22 -0
  224. package/dist/guest/toolchains/languages/python.js +1 -1
  225. package/dist/guest/toolchains/runtimes.js +2 -2
  226. package/dist/guest/vpn/index.d.ts +1 -0
  227. package/dist/guest/vpn/index.js +1 -0
  228. package/dist/guest/vpn/openvpn.d.ts +9 -0
  229. package/dist/guest/vpn/openvpn.js +47 -0
  230. package/dist/guest/vpn/tunnel.d.ts +17 -0
  231. package/dist/guest/vpn/tunnel.js +78 -0
  232. package/dist/guest/vpn/vpn.d.ts +6 -0
  233. package/dist/guest/vpn/vpn.js +126 -0
  234. package/dist/host/channel/attach.d.ts +3 -1
  235. package/dist/host/channel/attach.js +1 -1
  236. package/dist/host/channel/channel.d.ts +7 -0
  237. package/dist/host/channel/channel.js +26 -2
  238. package/dist/host/health/acl-read.d.ts +17 -0
  239. package/dist/host/health/acl-read.js +45 -0
  240. package/dist/host/health/config-backup.d.ts +11 -0
  241. package/dist/host/health/config-backup.js +73 -0
  242. package/dist/host/health/index.d.ts +6 -0
  243. package/dist/host/health/index.js +7 -0
  244. package/dist/host/health/install-state.d.ts +33 -0
  245. package/dist/host/health/install-state.js +110 -0
  246. package/dist/host/health/path-copies.d.ts +32 -0
  247. package/dist/host/health/path-copies.js +82 -0
  248. package/dist/host/health/stale.d.ts +45 -0
  249. package/dist/host/health/stale.js +120 -0
  250. package/dist/host/health/system.d.ts +37 -0
  251. package/dist/host/health/system.js +87 -0
  252. package/dist/host/install/copies.d.ts +13 -0
  253. package/dist/host/install/copies.js +63 -0
  254. package/dist/host/install/index.d.ts +1 -0
  255. package/dist/host/install/index.js +1 -0
  256. package/dist/host/launch/generate.js +25 -1
  257. package/dist/host/launch/session-file.js +4 -1
  258. package/dist/host/launch/stage.js +1 -1
  259. package/dist/host/migrate/backup.js +3 -0
  260. package/dist/host/migrate/migrations/config-file.d.ts +2 -0
  261. package/dist/host/migrate/migrations/config-file.js +7 -0
  262. package/dist/host/migrate/migrations/follow-machine-storage.js +9 -1
  263. package/dist/host/migrate/migrations/pin-storage-root.d.ts +4 -0
  264. package/dist/host/migrate/migrations/pin-storage-root.js +46 -0
  265. package/dist/host/migrate/migrations/unpin-config-defaults.js +4 -1
  266. package/dist/host/migrate/registry.js +2 -1
  267. package/dist/host/profile/accounts.d.ts +25 -1
  268. package/dist/host/profile/accounts.js +96 -13
  269. package/dist/host/profile/agent-accounts.d.ts +5 -1
  270. package/dist/host/profile/agent-accounts.js +35 -5
  271. package/dist/host/profile/index.d.ts +2 -1
  272. package/dist/host/profile/index.js +1 -0
  273. package/dist/host/profile/plugin-share.d.ts +26 -0
  274. package/dist/host/profile/plugin-share.js +146 -0
  275. package/dist/host/projects/join.d.ts +7 -1
  276. package/dist/host/projects/join.js +21 -4
  277. package/dist/host/projects/registry.d.ts +16 -10
  278. package/dist/host/projects/registry.js +74 -6
  279. package/dist/host/sandbox/platform.d.ts +2 -0
  280. package/dist/host/sandbox/platform.js +21 -2
  281. package/dist/host/secrets/index.d.ts +2 -0
  282. package/dist/host/secrets/index.js +2 -0
  283. package/dist/host/secrets/launch-secrets.d.ts +17 -0
  284. package/dist/host/secrets/launch-secrets.js +93 -0
  285. package/dist/host/secrets/secret-store.d.ts +25 -0
  286. package/dist/host/secrets/secret-store.js +89 -0
  287. package/dist/host/sharing/acl.d.ts +16 -2
  288. package/dist/host/sharing/acl.js +35 -10
  289. package/dist/host/sharing/current.js +11 -2
  290. package/dist/host/sharing/doctor.d.ts +2 -0
  291. package/dist/host/sharing/doctor.js +44 -0
  292. package/dist/host/sharing/group-access.d.ts +6 -0
  293. package/dist/host/sharing/group-access.js +24 -0
  294. package/dist/host/sharing/index.d.ts +2 -1
  295. package/dist/host/sharing/index.js +2 -1
  296. package/dist/host/sharing/lifecycle.d.ts +8 -2
  297. package/dist/host/sharing/lifecycle.js +16 -7
  298. package/dist/host/storage/cleanup.d.ts +2 -0
  299. package/dist/host/storage/cleanup.js +2 -1
  300. package/dist/host/storage/history.d.ts +21 -0
  301. package/dist/host/storage/history.js +49 -0
  302. package/dist/host/storage/index.d.ts +4 -0
  303. package/dist/host/storage/index.js +4 -0
  304. package/dist/host/storage/move.d.ts +95 -0
  305. package/dist/host/storage/move.js +384 -0
  306. package/dist/host/storage/offer.d.ts +11 -0
  307. package/dist/host/storage/offer.js +36 -0
  308. package/dist/host/storage/root.d.ts +18 -0
  309. package/dist/host/storage/root.js +77 -0
  310. package/dist/host/tools/windows-terminal.d.ts +2 -0
  311. package/dist/host/tools/windows-terminal.js +23 -5
  312. package/dist/host/update/index.d.ts +1 -1
  313. package/dist/host/update/index.js +1 -1
  314. package/dist/host/update/notice.d.ts +2 -0
  315. package/dist/host/update/notice.js +13 -1
  316. package/dist/host/update/update-state.d.ts +6 -0
  317. package/dist/host/update/update-state.js +2 -0
  318. package/dist/host/update/updater.d.ts +19 -0
  319. package/dist/host/update/updater.js +88 -12
  320. package/dist/host/vpn/index.d.ts +4 -0
  321. package/dist/host/vpn/index.js +4 -0
  322. package/dist/host/vpn/login.d.ts +24 -0
  323. package/dist/host/vpn/login.js +79 -0
  324. package/dist/host/vpn/nordvpn.d.ts +21 -0
  325. package/dist/host/vpn/nordvpn.js +77 -0
  326. package/dist/host/vpn/prepare.d.ts +17 -0
  327. package/dist/host/vpn/prepare.js +77 -0
  328. package/dist/host/vpn/status.d.ts +12 -0
  329. package/dist/host/vpn/status.js +53 -0
  330. package/dist/host/web/auth.d.ts +38 -0
  331. package/dist/host/web/auth.js +96 -0
  332. package/dist/host/web/backend.d.ts +14 -0
  333. package/dist/host/web/backend.js +1 -0
  334. package/dist/host/web/bridge.d.ts +27 -0
  335. package/dist/host/web/bridge.js +144 -0
  336. package/dist/host/web/browser.d.ts +1 -0
  337. package/dist/host/web/browser.js +10 -0
  338. package/dist/host/web/control.d.ts +17 -0
  339. package/dist/host/web/control.js +67 -0
  340. package/dist/host/web/index.d.ts +9 -0
  341. package/dist/host/web/index.js +8 -0
  342. package/dist/host/web/runner.d.ts +14 -0
  343. package/dist/host/web/runner.js +45 -0
  344. package/dist/host/web/server.d.ts +40 -0
  345. package/dist/host/web/server.js +218 -0
  346. package/dist/host/web/state.d.ts +20 -0
  347. package/dist/host/web/state.js +41 -0
  348. package/dist/host/web/static-files.d.ts +13 -0
  349. package/dist/host/web/static-files.js +57 -0
  350. package/dist/runtime/agent.js +27614 -0
  351. package/dist/runtime/daemon.js +1012 -618
  352. package/dist/runtime/db.js +236 -106
  353. package/dist/runtime/main.js +1093 -250
  354. package/dist/runtime/netproxy.js +102 -3
  355. package/dist/runtime/view.js +102 -3
  356. package/dist/selftest/accounts.test.js +40 -0
  357. package/dist/selftest/agent-paths.test.d.ts +2 -0
  358. package/dist/selftest/agent-paths.test.js +115 -0
  359. package/dist/selftest/channel.test.js +5 -0
  360. package/dist/selftest/cli.test.js +34 -4
  361. package/dist/selftest/credentials.test.d.ts +2 -0
  362. package/dist/selftest/credentials.test.js +198 -0
  363. package/dist/selftest/generate.test.js +1 -1
  364. package/dist/selftest/health.test.d.ts +2 -0
  365. package/dist/selftest/health.test.js +470 -0
  366. package/dist/selftest/host-sim.test.js +2 -0
  367. package/dist/selftest/index.js +19 -0
  368. package/dist/selftest/layout.test.js +2 -0
  369. package/dist/selftest/menu-screens.d.ts +7 -0
  370. package/dist/selftest/menu-screens.js +65 -16
  371. package/dist/selftest/menu.test.js +574 -21
  372. package/dist/selftest/migrate.test.js +1 -1
  373. package/dist/selftest/personalization.test.js +3 -1
  374. package/dist/selftest/projects.test.js +39 -1
  375. package/dist/selftest/shared-use.test.js +64 -2
  376. package/dist/selftest/sharing.test.js +50 -1
  377. package/dist/selftest/storage.test.d.ts +2 -0
  378. package/dist/selftest/storage.test.js +363 -0
  379. package/dist/selftest/support/fixtures.d.ts +14 -0
  380. package/dist/selftest/support/releases.js +1 -1
  381. package/dist/selftest/toolchains.test.js +21 -0
  382. package/dist/selftest/update-service.test.js +87 -3
  383. package/dist/selftest/vpn.test.d.ts +2 -0
  384. package/dist/selftest/vpn.test.js +279 -0
  385. package/dist/selftest/web.test.d.ts +2 -0
  386. package/dist/selftest/web.test.js +304 -0
  387. package/dist/shared/apps/catalogue.js +31 -0
  388. package/dist/shared/channel/index.d.ts +1 -0
  389. package/dist/shared/channel/index.js +1 -0
  390. package/dist/shared/channel/run-dir.d.ts +6 -1
  391. package/dist/shared/channel/run-dir.js +12 -1
  392. package/dist/shared/channel/schema.d.ts +19 -0
  393. package/dist/shared/channel/schema.js +11 -0
  394. package/dist/shared/channel/secrets.d.ts +28 -0
  395. package/dist/shared/channel/secrets.js +44 -0
  396. package/dist/shared/vpn/download.d.ts +13 -0
  397. package/dist/shared/vpn/download.js +14 -0
  398. package/dist/shared/vpn/kill-switch.d.ts +18 -0
  399. package/dist/shared/vpn/kill-switch.js +81 -0
  400. package/dist/shared/vpn/ovpn.d.ts +23 -0
  401. package/dist/shared/vpn/ovpn.js +244 -0
  402. package/dist/shared/web/index.d.ts +1 -0
  403. package/dist/shared/web/index.js +1 -0
  404. package/dist/shared/web/protocol.d.ts +61 -0
  405. package/dist/shared/web/protocol.js +35 -0
  406. package/dist/sync/sync-cycle.js +5 -1
  407. package/dist/sync/sync-state.d.ts +1 -0
  408. package/dist/sync/sync-state.js +1 -0
  409. package/dist/sync/watcher.js +10 -0
  410. package/dist/web/index.html +13 -0
  411. package/dist/web/main-CXESL347.js +45 -0
  412. package/dist/web/main-VLR7DVQ4.css +1 -0
  413. package/native/csharp/FolderSecurity.cs +29 -0
  414. package/native/scripts/protect-data.ps1 +29 -0
  415. package/native/scripts/read-folder-sddl.ps1 +10 -0
  416. package/native/scripts/set-folder-access.ps1 +49 -7
  417. package/node_modules/ws/LICENSE +20 -0
  418. package/node_modules/ws/README.md +548 -0
  419. package/node_modules/ws/browser.js +8 -0
  420. package/node_modules/ws/index.js +22 -0
  421. package/node_modules/ws/lib/buffer-util.js +131 -0
  422. package/node_modules/ws/lib/constants.js +19 -0
  423. package/node_modules/ws/lib/event-target.js +292 -0
  424. package/node_modules/ws/lib/extension.js +203 -0
  425. package/node_modules/ws/lib/limiter.js +55 -0
  426. package/node_modules/ws/lib/permessage-deflate.js +530 -0
  427. package/node_modules/ws/lib/receiver.js +743 -0
  428. package/node_modules/ws/lib/sender.js +607 -0
  429. package/node_modules/ws/lib/stream.js +161 -0
  430. package/node_modules/ws/lib/subprotocol.js +62 -0
  431. package/node_modules/ws/lib/validation.js +152 -0
  432. package/node_modules/ws/lib/websocket-server.js +562 -0
  433. package/node_modules/ws/lib/websocket.js +1421 -0
  434. package/node_modules/ws/package.json +74 -0
  435. package/node_modules/ws/wrapper.mjs +21 -0
  436. package/package.json +15 -5
  437. package/sandbox/csharp/EnvBroadcast.cs +33 -0
  438. package/sandbox/csharp/PathSync.cs +90 -0
  439. package/sandbox/scripts/install-shell-path.ps1 +73 -0
  440. package/sandbox/scripts/set-machine-environment.ps1 +37 -4
  441. package/schemas/config.schema.json +79 -4
  442. package/schemas/sandbox-config.schema.json +14 -1
  443. package/dist/cli/commands/repair/checks.d.ts +0 -2
  444. package/dist/cli/commands/repair/checks.js +0 -246
  445. package/dist/cli/menu/pages/start-page.d.ts +0 -43
  446. package/dist/cli/menu/pages/start-page.js +0 -192
  447. package/dist/cli/tui/tab-bar.d.ts +0 -9
  448. package/dist/cli/tui/tab-bar.js +0 -33
@@ -11,6 +11,8 @@ import { ToolchainsSchema } from './toolchains.js';
11
11
  import { AppsSchema } from './apps.js';
12
12
  import { ProjectsSchema } from './projects.js';
13
13
  import { ResumeSchema } from './resume.js';
14
+ import { WebSchema } from './web.js';
15
+ import { VpnSchema } from './vpn.js';
14
16
  export const ConfigSchema = z
15
17
  .strictObject({
16
18
  $schema: SchemaRefSchema.optional(),
@@ -23,7 +25,10 @@ export const ConfigSchema = z
23
25
  sandbox: SandboxSchema,
24
26
  sharing: SharingSchema,
25
27
  storage: z.strictObject({
26
- root: z.string().min(1).describe('Where everything is kept on this PC (tools, databases, logins, launches).'),
28
+ root: z
29
+ .string()
30
+ .min(1)
31
+ .describe('Where everything is kept on this PC (tools, databases, logins, launches). The default is a private folder for you under %ProgramData%\\AgentSandbox\\users, which works for installs for one user and for everyone. sandbox storage move <folder> moves it.'),
27
32
  persistAgentState: z.boolean().describe('Keep agent logins and history between sandboxes.'),
28
33
  dataName: NameSchema.describe('Name of the persistent data set (C:\\AgentData) shared by all workspaces.'),
29
34
  markSandboxFiles: z
@@ -35,11 +40,13 @@ export const ConfigSchema = z
35
40
  .describe('Say at launch when the persisted data (tools, databases, logins) is bigger than this many GB; 0 = never. sandbox data shows what takes the space.'),
36
41
  }),
37
42
  network: NetworkSchema,
43
+ vpn: VpnSchema,
38
44
  provisioning: ProvisioningSchema,
39
45
  downloads: DownloadsSchema,
40
46
  toolchains: ToolchainsSchema,
41
47
  databases: DatabasesSchema.describe('Databases running inside the sandbox. Data persists in C:\\AgentData\\databases; each one starts at boot.'),
42
48
  attach: AttachSchema,
49
+ web: WebSchema,
43
50
  agentCommands: AgentCommandsSchema,
44
51
  secrets: SecretsSchema,
45
52
  personalization: toggle('Copy your desktop look (theme, accent, taskbar, wallpaper, ...) into the sandbox.'),
@@ -74,6 +81,8 @@ export const LocalOverridesSchema = z
74
81
  sandbox: SandboxSchema.omit({ cpuLimit: true, pageFileMb: true }).partial(),
75
82
  // A project may block more (the LAN, hosts); it never opens hosts, ports, DNS or a proxy.
76
83
  network: NetworkSchema.pick({ blockPrivateRanges: true, blockHosts: true }).partial(),
84
+ // A project may turn the kill switch on, never off, and never choose a VPN, a server, a file or a login.
85
+ vpn: VpnSchema.pick({ killSwitch: true }).partial(),
77
86
  provisioning: ProvisioningSchema.pick({ copyFromHost: true, fallbackToInstall: true, refresh: true })
78
87
  .extend({ git: GitSchema.partial(), terminal: toggle('Windows Terminal as the sandbox window.').partial() })
79
88
  .partial(),
@@ -21,6 +21,7 @@ export declare const HarnessSchema: z.ZodObject<{
21
21
  loginFiles: z.ZodArray<z.ZodString>;
22
22
  hostDir: z.ZodOptional<z.ZodString>;
23
23
  }, z.core.$strict>>;
24
+ localState: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
24
25
  resumeArguments: z.ZodOptional<z.ZodArray<z.ZodString>>;
25
26
  resumeOneArguments: z.ZodOptional<z.ZodArray<z.ZodString>>;
26
27
  }, z.core.$strict>;
@@ -1,6 +1,6 @@
1
1
  // An agent (claude, codex, ...) the sandbox can run.
2
2
  import { z } from 'zod';
3
- import { StringsSchema } from './common.js';
3
+ import { secret, StringsSchema } from './common.js';
4
4
  /** A folder below the agent's state folder: plain names only, no drive, no "..". */
5
5
  const SubfolderSchema = z
6
6
  .string()
@@ -41,8 +41,14 @@ export const HarnessSchema = z
41
41
  .describe('Python package installed with `uv tool install` inside the sandbox (e.g. aider-chat).'),
42
42
  uvBin: z.string().optional().describe('Command the uv package provides.'),
43
43
  arguments: StringsSchema.describe('Arguments always passed to the agent.'),
44
- environment: z.record(z.string(), z.string()).describe('Environment variables for the agent.'),
44
+ environment: z
45
+ .record(z.string(), secret(z.string()))
46
+ .describe('Environment variables for the agent (API keys go here). Their values are shown as *** and are handed to the sandbox in a one-shot file, never kept in the launch folder. The agent can read its own environment.'),
45
47
  home: HarnessHomeSchema.optional().describe('Where its login lives inside the sandbox; leave out when the agent cannot be pointed at a folder (then its login is not kept between sandboxes).'),
48
+ localState: z
49
+ .record(z.string().regex(/^[A-Za-z_][A-Za-z0-9_]*$/), SubfolderSchema)
50
+ .optional()
51
+ .describe("Environment variable -> folder below the agent's own state folder (state\\<agent>) for SQLite databases. SQLite cannot run in a mapped folder, so the agent runs from a copy on the sandbox's disk (the variable points to it) that is copied from and back to that folder."),
46
52
  resumeArguments: StringsSchema.optional().describe('Arguments used when the agent is restarted in place (e.g. after an account switch) so it resumes the conversation.'),
47
53
  resumeOneArguments: StringsSchema.optional().describe('Arguments that reopen one conversation, with {id} where its id goes (claude: --resume {id}). Used instead of resumeArguments when the conversation of a session is known.'),
48
54
  })
@@ -1,6 +1,8 @@
1
- export { GitAccessSchema } from './common.js';
1
+ export { GitAccessSchema, NameSchema, secret } from './common.js';
2
+ export { REDACTED, redactSecrets, scrubSecrets, secretPaths, secretValues } from './redact.js';
2
3
  export { ConfigSchema, LocalOverridesSchema } from './config.js';
3
4
  export { HarnessSchema } from './harness.js';
4
5
  export { describeIssues, jsonSchemas } from './json-schema.js';
5
6
  export { MappingSchema } from './sandbox.js';
6
7
  export { ToolchainsSchema } from './toolchains.js';
8
+ export { VpnSchema, VPN_PROVIDERS, type VpnProvider } from './vpn.js';
@@ -1,8 +1,10 @@
1
1
  // Every setting, defined once with zod, split by area in schema/. This file is the one place the rest of the code (and
2
2
  // scripts/schemas.mjs, which generates the JSON Schema files) imports them from.
3
- export { GitAccessSchema } from './common.js';
3
+ export { GitAccessSchema, NameSchema, secret } from './common.js';
4
+ export { REDACTED, redactSecrets, scrubSecrets, secretPaths, secretValues } from './redact.js';
4
5
  export { ConfigSchema, LocalOverridesSchema } from './config.js';
5
6
  export { HarnessSchema } from './harness.js';
6
7
  export { describeIssues, jsonSchemas } from './json-schema.js';
7
8
  export { MappingSchema } from './sandbox.js';
8
9
  export { ToolchainsSchema } from './toolchains.js';
10
+ export { VpnSchema, VPN_PROVIDERS } from './vpn.js';
@@ -22,6 +22,7 @@ export declare const ClaudeProfileSchema: z.ZodObject<{
22
22
  globalStateFile: z.ZodString;
23
23
  copyCredentials: z.ZodBoolean;
24
24
  overwrite: z.ZodBoolean;
25
+ sharePluginsAcrossAccounts: z.ZodBoolean;
25
26
  syncHistory: z.ZodBoolean;
26
27
  historyScope: z.ZodEnum<{
27
28
  project: "project";
@@ -38,6 +38,9 @@ export const ClaudeProfileSchema = z.strictObject({
38
38
  globalStateFile: z.string().describe('Your .claude.json, or "auto". Empty string = do not copy.'),
39
39
  copyCredentials: z.boolean().describe('Copy your Claude LOGIN into the sandbox. Prefer sandbox account instead.'),
40
40
  overwrite: z.boolean().describe('Refresh these settings from this PC on every launch.'),
41
+ sharePluginsAcrossAccounts: z
42
+ .boolean()
43
+ .describe('When you switch Claude accounts, copy your Claude plugins (and which ones are enabled) into a data set that has none yet. Off by default: plugins are code that runs in your sessions.'),
41
44
  syncHistory: z.boolean().describe('Bring conversation history in, and sync new history back (path-translated).'),
42
45
  historyScope: z
43
46
  .enum(['project', 'all'])
@@ -0,0 +1,13 @@
1
+ /** What is printed instead of a secret. */
2
+ export declare const REDACTED = "***";
3
+ /** A path through a config; "*" stands for any key of a map or any item of a list. */
4
+ type SecretPath = readonly string[];
5
+ /** Every setting marked secret, found from the schema itself (so a new secret setting needs no list). */
6
+ export declare function secretPaths(): readonly SecretPath[];
7
+ /** A copy of `config` with every secret value replaced by ***. */
8
+ export declare function redactSecrets<T>(config: T): T;
9
+ /** The secret values in `config` (for scrubbing text that was built from it). */
10
+ export declare function secretValues(config: unknown): string[];
11
+ /** `text` with every secret value of `config` replaced by *** (a last safety net for output built from a config). */
12
+ export declare function scrubSecrets(text: string, config: unknown): string;
13
+ export {};
@@ -0,0 +1,75 @@
1
+ // Secrets in settings: which values are marked `secret` in the schemas, and printing a config without them.
2
+ import { z } from 'zod';
3
+ import { ConfigSchema } from './config.js';
4
+ /** What is printed instead of a secret. */
5
+ export const REDACTED = '***';
6
+ let cached = null;
7
+ const walk = (node, at, out) => {
8
+ if (typeof node !== 'object' || node === null)
9
+ return;
10
+ const n = node;
11
+ if (n.secret === true)
12
+ out.push(at);
13
+ for (const [k, v] of Object.entries(n.properties ?? {}))
14
+ walk(v, [...at, k], out);
15
+ if (typeof n.additionalProperties === 'object')
16
+ walk(n.additionalProperties, [...at, '*'], out);
17
+ if (n.items)
18
+ walk(n.items, [...at, '*'], out);
19
+ for (const key of ['anyOf', 'oneOf', 'allOf'])
20
+ if (Array.isArray(n[key]))
21
+ for (const v of n[key])
22
+ walk(v, at, out);
23
+ };
24
+ /** Every setting marked secret, found from the schema itself (so a new secret setting needs no list). */
25
+ export function secretPaths() {
26
+ if (!cached) {
27
+ const out = [];
28
+ walk(z.toJSONSchema(ConfigSchema, { io: 'input', unrepresentable: 'any' }), [], out);
29
+ cached = out;
30
+ }
31
+ return cached;
32
+ }
33
+ const blank = (value, path) => {
34
+ if (path.length === 0)
35
+ return typeof value === 'string' && value !== '' ? REDACTED : value;
36
+ if (typeof value !== 'object' || value === null)
37
+ return value;
38
+ const [head, ...rest] = path;
39
+ if (Array.isArray(value))
40
+ return value.map((v) => (head === '*' ? blank(v, rest) : v));
41
+ const o = value;
42
+ return Object.fromEntries(Object.entries(o).map(([k, v]) => [k, head === '*' || head === k ? blank(v, rest) : v]));
43
+ };
44
+ /** A copy of `config` with every secret value replaced by ***. */
45
+ export function redactSecrets(config) {
46
+ return secretPaths().reduce((value, path) => blank(value, path), config);
47
+ }
48
+ const collect = (value, path, out) => {
49
+ if (path.length === 0) {
50
+ if (typeof value === 'string' && value !== '')
51
+ out.push(value);
52
+ return;
53
+ }
54
+ if (typeof value !== 'object' || value === null)
55
+ return;
56
+ const [head, ...rest] = path;
57
+ const o = value;
58
+ for (const [k, v] of Object.entries(o))
59
+ if (head === '*' || head === k)
60
+ collect(v, rest, out);
61
+ };
62
+ /** The secret values in `config` (for scrubbing text that was built from it). */
63
+ export function secretValues(config) {
64
+ const out = [];
65
+ for (const path of secretPaths())
66
+ collect(config, path, out);
67
+ return [...new Set(out)];
68
+ }
69
+ /** `text` with every secret value of `config` replaced by *** (a last safety net for output built from a config). */
70
+ export function scrubSecrets(text, config) {
71
+ return secretValues(config)
72
+ .filter((v) => v.length >= 4)
73
+ .sort((a, b) => b.length - a.length)
74
+ .reduce((t, v) => t.split(v).join(REDACTED).split(JSON.stringify(v).slice(1, -1)).join(REDACTED), text);
75
+ }
@@ -85,6 +85,7 @@ export const NetworkSchema = z.strictObject({
85
85
  proxy: z
86
86
  .string()
87
87
  .regex(/^(https?:\/\/[^\s]+)?$/, 'http://host:port')
88
+ .refine((v) => !/^https?:\/\/[^/?#]*@/i.test(v), 'no user name or password in the address (it would be stored in plain text and visible to the agent): use a proxy that needs no login')
88
89
  .describe('An HTTP proxy the sandbox uses to reach the internet (HTTP_PROXY / HTTPS_PROXY for everything in it), e.g. http://proxy.corp:8080. Empty = none.'),
89
90
  });
90
91
  export const AuditSchema = z.strictObject({
@@ -0,0 +1,17 @@
1
+ import { z } from 'zod';
2
+ export declare const VPN_PROVIDERS: readonly ["nordvpn", "openvpn-file"];
3
+ export declare const VpnSchema: z.ZodObject<{
4
+ enabled: z.ZodBoolean;
5
+ provider: z.ZodEnum<{
6
+ nordvpn: "nordvpn";
7
+ "openvpn-file": "openvpn-file";
8
+ }>;
9
+ protocol: z.ZodEnum<{
10
+ udp: "udp";
11
+ tcp: "tcp";
12
+ }>;
13
+ country: z.ZodString;
14
+ configFile: z.ZodString;
15
+ killSwitch: z.ZodBoolean;
16
+ }, z.core.$strict>;
17
+ export type VpnProvider = (typeof VPN_PROVIDERS)[number];
@@ -0,0 +1,22 @@
1
+ // The VPN setting (inside the sandbox only; the login is not a setting: it is kept encrypted by `sandbox vpn login`).
2
+ import { z } from 'zod';
3
+ export const VPN_PROVIDERS = ['nordvpn', 'openvpn-file'];
4
+ export const VpnSchema = z.strictObject({
5
+ enabled: z
6
+ .boolean()
7
+ .describe("Send the sandbox's traffic through a VPN. Only the sandbox: your PC's own connection is untouched. Needs a saved login first (sandbox vpn login). The agent in the sandbox can read that login and can turn the tunnel off (it is the administrator there)."),
8
+ provider: z
9
+ .enum(VPN_PROVIDERS)
10
+ .describe('nordvpn: a recommended NordVPN server is picked at every launch. openvpn-file: your own .ovpn file (configFile).'),
11
+ protocol: z.enum(['udp', 'tcp']).describe('udp is faster; tcp gets through networks that block udp.'),
12
+ country: z
13
+ .string()
14
+ .regex(/^([A-Za-z][A-Za-z .'-]{0,39})?$/, 'a country name or code like uk or Germany')
15
+ .describe('nordvpn: the country of the server, e.g. uk, us or Germany. Empty = the best server anywhere.'),
16
+ configFile: z
17
+ .string()
18
+ .describe("openvpn-file: the .ovpn file on this PC (its certificates inside it). Files that run programs (script-security, up, down, plugin ...) are refused. A project's file can never set this."),
19
+ killSwitch: z
20
+ .boolean()
21
+ .describe('Block all traffic that does not go through the tunnel: when the tunnel cannot start, the sandbox stays offline instead of using your normal connection. A project can only turn this on, never off.'),
22
+ });
@@ -0,0 +1,6 @@
1
+ import { z } from 'zod';
2
+ export declare const WEB_DEFAULT_PORT = 47800;
3
+ export declare const WebSchema: z.ZodObject<{
4
+ enabled: z.ZodBoolean;
5
+ port: z.ZodNumber;
6
+ }, z.core.$strict>;
@@ -0,0 +1,14 @@
1
+ // The web UI settings (sandbox web): not part of LocalOverrides, a repo never turns a way into your agents on.
2
+ import { z } from 'zod';
3
+ export const WEB_DEFAULT_PORT = 47800;
4
+ export const WebSchema = z.strictObject({
5
+ enabled: z
6
+ .boolean()
7
+ .describe('(Beta) Allow the web UI: your sandbox sessions in a browser on this PC. Off by default, and nothing starts it by itself yet: sandbox web start works either way and runs it until sandbox web stop (or a restart of the PC).'),
8
+ port: z
9
+ .number()
10
+ .int()
11
+ .min(1024)
12
+ .max(65535)
13
+ .describe('Port of the web UI on 127.0.0.1 (this PC only). Pick another when it is taken.'),
14
+ });
@@ -102,6 +102,16 @@ export interface DatabasePlan {
102
102
  port: number;
103
103
  adminPort?: number;
104
104
  }
105
+ /** The VPN decided at launch (host/vpn/prepare.ts): its checked profile, and the login for the one-shot file. */
106
+ export interface PreparedVpn {
107
+ session: GuestVpn;
108
+ /** The profile text, already checked. */
109
+ profile: string;
110
+ credentials: {
111
+ username: string;
112
+ password: string;
113
+ };
114
+ }
105
115
  /** databases / pcLanguages: use these instead of scanning (tests). */
106
116
  export interface GenerateOptions {
107
117
  packageRoot: string;
@@ -124,6 +134,8 @@ export interface GenerateOptions {
124
134
  projects: BootWant[];
125
135
  keepOff: string[];
126
136
  };
137
+ /** The VPN for this launch (vpn.enabled); its profile goes in the launch folder, its login in the one-shot file. */
138
+ vpn?: PreparedVpn;
127
139
  }
128
140
  export interface Generated {
129
141
  wsbPath: string;
@@ -162,6 +174,16 @@ export interface ProfileResult {
162
174
  credentials: boolean;
163
175
  secretsRemoved: string[];
164
176
  }
177
+ /** The VPN of one launch: what the guest needs besides the login (which comes in the one-shot secrets file). */
178
+ export interface GuestVpn {
179
+ provider: Config['vpn']['provider'];
180
+ protocol: Config['vpn']['protocol'];
181
+ killSwitch: boolean;
182
+ /** The server's name, for messages. */
183
+ server: string;
184
+ /** The checked profile, relative to the launch folder. */
185
+ profile: string;
186
+ }
165
187
  /** Written by the host to C:\AgentLaunch\session.json (read-only for the guest): everything the guest needs to know. */
166
188
  export interface GuestSession {
167
189
  launchId: string;
@@ -196,6 +218,8 @@ export interface GuestSession {
196
218
  attach: Config['attach'];
197
219
  hooks: Config['hooks'];
198
220
  downloads: Config['downloads'];
221
+ /** Set when the VPN is on for this launch (older launch folders lack it). */
222
+ vpn?: GuestVpn;
199
223
  /** nodeVersion: this PC's Node (e.g. 22.11.0), found under nvm\v<version> when nvm is mapped, else under node. */
200
224
  /** volta / pyenv: this PC uses them (their "auto" settings turn them on in the sandbox too). */
201
225
  hostTools: {
@@ -237,4 +261,6 @@ export interface GuestSession {
237
261
  agentHomes?: Record<string, string>;
238
262
  /** Per agent: folders of the user profile (.qwen ...) linked into the persistent state at boot. */
239
263
  agentProfileDirs?: Record<string, string[]>;
264
+ /** Every configured agent (without its environment): a terminal command each; older launch folders lack it. */
265
+ agents?: Record<string, Harness>;
240
266
  }
@@ -0,0 +1,49 @@
1
+ import type { Harness } from '../../core/types.js';
2
+ /** Where an agent lives in persistent storage: its folder, and the program (an .exe, or an npm .cmd) in it. */
3
+ export interface AgentPaths {
4
+ readonly dir: string;
5
+ readonly exe: string | null;
6
+ readonly cmd: string | null;
7
+ }
8
+ export declare function agentPaths(toolsDir: string, name: string, harness: Harness): AgentPaths;
9
+ /** The word a user types for this agent (`claude`, `codex` ...). */
10
+ export declare function agentCommand(name: string, harness: Harness): string;
11
+ /** What a terminal needs to run the agent by name: the command, and the program it runs once installed. */
12
+ export interface AgentShim {
13
+ readonly name: string;
14
+ readonly command: string;
15
+ readonly target: string;
16
+ }
17
+ /** One shim per configured agent that can be installed here (a name that is not a plain command word is skipped). */
18
+ export declare function agentShims(toolsDir: string, agents: Readonly<Record<string, Harness>>): AgentShim[];
19
+ /**
20
+ * The text of `<command>.cmd`: runs the installed agent, or installs it first (`install` = node + installer script).
21
+ * The agent's own arguments pass through %* untouched.
22
+ */
23
+ export declare function shimText(shim: AgentShim, install: {
24
+ node: string;
25
+ script: string;
26
+ }): string;
27
+ /** The `sbx-agent` command: `sbx-agent install <agent>` / `sbx-agent list`. */
28
+ export declare function sbxAgentText(install: {
29
+ node: string;
30
+ script: string;
31
+ }): string;
32
+ /** A SQLite folder an agent runs from the sandbox's disk: the variable that points to `local`, and its saved copy. */
33
+ export interface LocalState {
34
+ readonly agent: string;
35
+ readonly env: string;
36
+ /** The saved copy in persistent storage (state\<agent>\<folder>). */
37
+ readonly store: string;
38
+ /** The working copy on the sandbox's own disk. */
39
+ readonly local: string;
40
+ /** Image names of the programs that hold the databases open while they run. */
41
+ readonly processes: readonly string[];
42
+ /** Where the agent kept the databases before this existed (its state folder itself). */
43
+ readonly legacy: string;
44
+ }
45
+ export declare function localStateEntries(agents: Readonly<Record<string, Harness>>, stateDir: string, localRoot: string): LocalState[];
46
+ /** A SQLite database file or one of its -wal / -shm siblings. */
47
+ export declare const isDatabaseFile: (name: string) => boolean;
48
+ /** Files that make a consistent copy: the databases and their -wal (the -shm is rebuilt by SQLite). */
49
+ export declare const isCopyableDatabaseFile: (name: string) => boolean;
@@ -0,0 +1,63 @@
1
+ // Pure parts of the agents' files: where an agent is installed, the command that starts it in a terminal tab, and the
2
+ // SQLite folders it runs from the sandbox's own disk. No side effects: the self-test imports this file.
3
+ import path from 'node:path';
4
+ export function agentPaths(toolsDir, name, harness) {
5
+ const dir = path.join(toolsDir, 'agents', name);
6
+ const exe = harness.hostExecutable ?? (harness.uvBin ? harness.uvBin + '.exe' : null);
7
+ return {
8
+ dir,
9
+ exe: exe ? path.join(dir, exe) : null,
10
+ cmd: harness.npmBin ? path.join(dir, harness.npmBin + '.cmd') : null,
11
+ };
12
+ }
13
+ /** The word a user types for this agent (`claude`, `codex` ...). */
14
+ export function agentCommand(name, harness) {
15
+ return harness.npmBin ?? harness.uvBin ?? (harness.hostExecutable ?? name).replace(/\.exe$/i, '');
16
+ }
17
+ /** One shim per configured agent that can be installed here (a name that is not a plain command word is skipped). */
18
+ export function agentShims(toolsDir, agents) {
19
+ return Object.entries(agents).flatMap(([name, harness]) => {
20
+ const p = agentPaths(toolsDir, name, harness);
21
+ const target = p.exe ?? p.cmd;
22
+ const command = agentCommand(name, harness);
23
+ return target && /^[A-Za-z0-9_-]+$/.test(command) && /^[A-Za-z0-9_-]+$/.test(name)
24
+ ? [{ name, command, target }]
25
+ : [];
26
+ });
27
+ }
28
+ /**
29
+ * The text of `<command>.cmd`: runs the installed agent, or installs it first (`install` = node + installer script).
30
+ * The agent's own arguments pass through %* untouched.
31
+ */
32
+ export function shimText(shim, install) {
33
+ return [
34
+ '@echo off',
35
+ 'setlocal',
36
+ 'set "SBX_REAL=' + shim.target + '"',
37
+ 'if exist "%SBX_REAL%" goto run',
38
+ 'echo ' + shim.command + ' is not installed in this sandbox yet. Installing it now (one time)...',
39
+ '"' + install.node + '" "' + install.script + '" install ' + shim.name,
40
+ 'if errorlevel 1 exit /b 1',
41
+ ':run',
42
+ 'endlocal & "%SBX_REAL%" %*',
43
+ '',
44
+ ].join('\r\n');
45
+ }
46
+ /** The `sbx-agent` command: `sbx-agent install <agent>` / `sbx-agent list`. */
47
+ export function sbxAgentText(install) {
48
+ return '@"' + install.node + '" "' + install.script + '" %*\r\n';
49
+ }
50
+ export function localStateEntries(agents, stateDir, localRoot) {
51
+ return Object.entries(agents).flatMap(([agent, harness]) => Object.entries(harness.localState ?? {}).map(([env, folder]) => ({
52
+ agent,
53
+ env,
54
+ store: path.join(stateDir, agent, folder),
55
+ local: path.join(localRoot, agent, folder),
56
+ processes: [agentCommand(agent, harness) + '.exe'],
57
+ legacy: path.join(stateDir, agent),
58
+ })));
59
+ }
60
+ /** A SQLite database file or one of its -wal / -shm siblings. */
61
+ export const isDatabaseFile = (name) => /\.(sqlite3?|db)(-wal|-shm)?$/i.test(name);
62
+ /** Files that make a consistent copy: the databases and their -wal (the -shm is rebuilt by SQLite). */
63
+ export const isCopyableDatabaseFile = (name) => isDatabaseFile(name) && !/-shm$/i.test(name);
@@ -11,16 +11,9 @@ import { exists, mkdirp } from '../runtime/fs.js';
11
11
  import { log, warn } from '../runtime/log.js';
12
12
  import { session } from '../runtime/session.js';
13
13
  import { addMachineEnvironment } from '../setup/environment.js';
14
+ import { agentPaths as paths } from './agent-files.js';
14
15
  import { linkHarnessProfile } from './profile-links.js';
15
- function agentPaths(name, harness) {
16
- const dir = path.join(toolsDir, 'agents', name);
17
- const exe = harness.hostExecutable ?? (harness.uvBin ? harness.uvBin + '.exe' : null);
18
- return {
19
- dir,
20
- exe: exe ? path.join(dir, exe) : null,
21
- cmd: harness.npmBin ? path.join(dir, harness.npmBin + '.cmd') : null,
22
- };
23
- }
16
+ const agentPaths = (name, harness) => paths(toolsDir, name, harness);
24
17
  /** npm install with the runner's own npm into tools\agents\<name> (no global state outside persistent storage). */
25
18
  async function installViaNpm(name, harness, dir, env) {
26
19
  if (!harness.npmPackage)
@@ -0,0 +1,12 @@
1
+ import { type LocalState } from './agent-files.js';
2
+ /** Every SQLite folder of every configured agent (none in launch folders that predate the agents list). */
3
+ export declare function agentLocalStates(): LocalState[];
4
+ /** Variable -> working folder, for the agent environment (and the machine environment of new terminal tabs). */
5
+ export declare function localStateVars(): Record<string, string>;
6
+ /** Boot: the saved databases of every configured agent are copied to the sandbox's disk, where the agent runs them. */
7
+ export declare function restoreLocalState(): void;
8
+ /**
9
+ * Copies the working databases back to persistent storage (staging folder + swap). While the agent runs they are
10
+ * snapshotted with SQLite's online backup instead (see snapshotWhileRunning); nothing is done when nothing changed.
11
+ */
12
+ export declare function saveLocalState(): void;