windows-development-sandbox 1.20.0 → 1.23.1

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 (337) hide show
  1. package/config.example.json +8 -1
  2. package/dist/app/features/access/access.def.js +5 -2
  3. package/dist/app/features/access/access.run.js +7 -3
  4. package/dist/app/features/accounts/accounts.def.d.ts +29 -1
  5. package/dist/app/features/accounts/accounts.def.js +10 -4
  6. package/dist/app/features/accounts/accounts.run.d.ts +1 -0
  7. package/dist/app/features/accounts/accounts.run.js +7 -2
  8. package/dist/app/features/accounts/services.def.d.ts +4 -1
  9. package/dist/app/features/accounts/services.def.js +15 -14
  10. package/dist/app/features/accounts/services.run.d.ts +1 -0
  11. package/dist/app/features/accounts/services.run.js +41 -15
  12. package/dist/app/features/defs.d.ts +39 -2
  13. package/dist/app/features/engine/engine.run.js +1 -1
  14. package/dist/app/features/github/github.def.d.ts +44 -3
  15. package/dist/app/features/github/github.def.js +145 -63
  16. package/dist/app/features/github/github.run.d.ts +9 -2
  17. package/dist/app/features/github/github.run.js +43 -5
  18. package/dist/app/features/health/health.def.js +8 -2
  19. package/dist/app/features/logs/logs.def.js +0 -8
  20. package/dist/app/features/projects/projects.def.js +2 -2
  21. package/dist/app/features/projects/projects.run.js +5 -5
  22. package/dist/app/features/sandbox/sandbox.def.js +7 -3
  23. package/dist/app/features/sessions/sessions.def.d.ts +4 -4
  24. package/dist/app/features/sessions/sessions.def.js +0 -5
  25. package/dist/app/features/sessions/sessions.run.d.ts +1 -1
  26. package/dist/app/features/sessions/sessions.run.js +2 -2
  27. package/dist/app/features/settings/categories.def.js +2 -0
  28. package/dist/app/features/settings/settings-rows.js +1 -1
  29. package/dist/app/features/settings/settings.def.js +1 -1
  30. package/dist/app/features/settings/settings.run.js +3 -3
  31. package/dist/app/features/storage/storage.run.js +18 -9
  32. package/dist/app/features/updates/update-lines.js +2 -2
  33. package/dist/app/features/updates/updates.def.js +1 -1
  34. package/dist/app/features/updates/updates.run.js +1 -1
  35. package/dist/app/features/web/web.def.js +2 -2
  36. package/dist/app/features/web/web.run.js +12 -4
  37. package/dist/app/kernel/errors.d.ts +7 -0
  38. package/dist/app/kernel/errors.js +18 -3
  39. package/dist/app/kernel/rpc.d.ts +5 -0
  40. package/dist/app/kernel/view.d.ts +11 -1
  41. package/dist/bin/agent-sandbox.js +2 -2
  42. package/dist/bin/{chunk-DK4NTBUF.js → chunk-7YPEDAJD.js} +172 -48
  43. package/dist/bin/{chunk-2IMT7ZCT.js → chunk-QFSJX2KW.js} +1 -1
  44. package/dist/bin/{chunk-Z2P5OGKL.js → chunk-USTRSHIE.js} +2436 -1693
  45. package/dist/bin/claude-host.js +2 -2
  46. package/dist/bin/claude-sbx.js +2 -2
  47. package/dist/bin/codex-sbx.js +2 -2
  48. package/dist/bin/gemini-sbx.js +2 -2
  49. package/dist/bin/sandbox.js +2 -2
  50. package/dist/bin/sbx-hide.js +2 -2
  51. package/dist/bin/sbx-show.js +2 -2
  52. package/dist/cli/manifest.d.ts +2 -2
  53. package/dist/cli/manifest.js +2 -1
  54. package/dist/cli/menu/coverage-exempt.d.ts +17 -0
  55. package/dist/cli/menu/coverage-exempt.js +61 -0
  56. package/dist/cli/menu/io-menu.d.ts +2 -0
  57. package/dist/cli/menu/io-menu.js +50 -5
  58. package/dist/cli/menu/pages/accounts-page.js +1 -1
  59. package/dist/cli/menu/pages/agents-page.js +8 -2
  60. package/dist/cli/menu/pages/maintenance-page.d.ts +6 -0
  61. package/dist/cli/menu/pages/maintenance-page.js +9 -2
  62. package/dist/cli/menu/pages/sessions-page.d.ts +2 -0
  63. package/dist/cli/menu/pages/sessions-page.js +12 -4
  64. package/dist/cli/menu/pages/settings-page.js +12 -1
  65. package/dist/cli/menu/remote-menu.js +1 -1
  66. package/dist/cli/menu/shell.d.ts +5 -0
  67. package/dist/cli/menu/shell.js +13 -0
  68. package/dist/cli/report.js +2 -0
  69. package/dist/cli/tui/app.d.ts +5 -0
  70. package/dist/cli/tui/app.js +2 -0
  71. package/dist/core/config/defaults.js +3 -1
  72. package/dist/core/schema/accounts.d.ts +6 -0
  73. package/dist/core/schema/accounts.js +13 -11
  74. package/dist/core/schema/config.d.ts +20 -8
  75. package/dist/core/schema/config.js +4 -4
  76. package/dist/core/schema/github.js +1 -1
  77. package/dist/core/schema/profile.js +8 -4
  78. package/dist/core/schema/resume.js +1 -1
  79. package/dist/core/schema/sandbox.js +3 -3
  80. package/dist/core/schema/vpn.js +1 -1
  81. package/dist/core/schema/web.js +3 -3
  82. package/dist/core/types.d.ts +6 -0
  83. package/dist/core/util/errors.d.ts +11 -1
  84. package/dist/core/util/errors.js +7 -1
  85. package/dist/core/util/index.d.ts +1 -1
  86. package/dist/core/util/index.js +1 -1
  87. package/dist/guest/accounts/adapter.d.ts +2 -0
  88. package/dist/guest/accounts/adapters.js +4 -0
  89. package/dist/guest/accounts/apply.d.ts +6 -2
  90. package/dist/guest/accounts/kinds/cfx.d.ts +7 -0
  91. package/dist/guest/accounts/kinds/cfx.js +33 -3
  92. package/dist/guest/accounts/kinds/comet.d.ts +7 -0
  93. package/dist/guest/accounts/kinds/comet.js +50 -0
  94. package/dist/guest/accounts/kinds/perplexity.d.ts +2 -0
  95. package/dist/guest/accounts/kinds/perplexity.js +12 -0
  96. package/dist/guest/accounts/watch.d.ts +2 -0
  97. package/dist/guest/accounts/watch.js +12 -2
  98. package/dist/guest/agents/agent-installer.js +1 -1
  99. package/dist/guest/agents/profile-links.d.ts +2 -0
  100. package/dist/guest/agents/profile-links.js +18 -4
  101. package/dist/guest/apps/after-install.js +19 -0
  102. package/dist/guest/apps/app-installer.d.ts +11 -0
  103. package/dist/guest/apps/app-installer.js +69 -6
  104. package/dist/guest/apps/comet-unpack.d.ts +20 -0
  105. package/dist/guest/apps/comet-unpack.js +127 -0
  106. package/dist/guest/apps/index.d.ts +1 -1
  107. package/dist/guest/apps/index.js +1 -1
  108. package/dist/guest/apps/resolvers-agents-web.d.ts +2 -0
  109. package/dist/guest/apps/resolvers-agents-web.js +7 -0
  110. package/dist/guest/apps/resolvers.js +2 -0
  111. package/dist/guest/apps/shortcuts.d.ts +2 -0
  112. package/dist/guest/apps/shortcuts.js +1 -0
  113. package/dist/guest/apps/unpack.js +14 -4
  114. package/dist/guest/boot/boot.d.ts +45 -16
  115. package/dist/guest/boot/boot.js +316 -145
  116. package/dist/guest/boot/graph.d.ts +252 -0
  117. package/dist/guest/boot/graph.js +257 -0
  118. package/dist/guest/boot/guide-lines.d.ts +25 -0
  119. package/dist/guest/boot/guide-lines.js +41 -0
  120. package/dist/guest/boot/guide.d.ts +1 -4
  121. package/dist/guest/boot/guide.js +6 -8
  122. package/dist/guest/boot/runner.d.ts +77 -0
  123. package/dist/guest/boot/runner.js +215 -0
  124. package/dist/guest/browser/cdp.d.ts +71 -0
  125. package/dist/guest/browser/cdp.js +306 -0
  126. package/dist/guest/browser/comet.d.ts +28 -0
  127. package/dist/guest/browser/comet.js +155 -0
  128. package/dist/guest/daemon/project-provisioner.js +6 -1
  129. package/dist/guest/devtools/fivem.d.ts +1 -1
  130. package/dist/guest/devtools/fivem.js +243 -3
  131. package/dist/guest/entries/daemon.js +2 -0
  132. package/dist/guest/runtime/log.d.ts +12 -0
  133. package/dist/guest/runtime/log.js +29 -5
  134. package/dist/guest/runtime/pools.d.ts +24 -0
  135. package/dist/guest/runtime/pools.js +60 -0
  136. package/dist/guest/runtime/process.d.ts +4 -0
  137. package/dist/guest/runtime/process.js +38 -1
  138. package/dist/guest/runtime/status.d.ts +5 -1
  139. package/dist/guest/runtime/status.js +19 -0
  140. package/dist/guest/setup/addon-mcp.d.ts +1 -1
  141. package/dist/guest/setup/addon-mcp.js +52 -12
  142. package/dist/guest/setup/agent-addons.d.ts +3 -2
  143. package/dist/guest/setup/agent-addons.js +12 -3
  144. package/dist/guest/setup/environment.d.ts +1 -1
  145. package/dist/guest/setup/environment.js +25 -12
  146. package/dist/guest/setup/headroom.d.ts +8 -3
  147. package/dist/guest/setup/headroom.js +44 -15
  148. package/dist/guest/setup/path-plan.d.ts +28 -0
  149. package/dist/guest/setup/path-plan.js +69 -2
  150. package/dist/guest/setup/shell-path.d.ts +1 -1
  151. package/dist/guest/setup/shell-path.js +3 -3
  152. package/dist/guest/toolchains/fivem/artifacts.d.ts +48 -1
  153. package/dist/guest/toolchains/fivem/artifacts.js +97 -4
  154. package/dist/guest/toolchains/fivem/fivem.d.ts +32 -1
  155. package/dist/guest/toolchains/fivem/fivem.js +168 -3
  156. package/dist/guest/toolchains/fivem/scaffold.d.ts +35 -0
  157. package/dist/guest/toolchains/fivem/scaffold.js +105 -0
  158. package/dist/guest/toolchains/fivem/serve-plan.d.ts +34 -0
  159. package/dist/guest/toolchains/fivem/serve-plan.js +61 -0
  160. package/dist/guest/toolchains/languages/go.js +1 -1
  161. package/dist/guest/toolchains/languages/node.js +2 -1
  162. package/dist/guest/toolchains/languages/php.d.ts +2 -0
  163. package/dist/guest/toolchains/languages/php.js +13 -1
  164. package/dist/guest/toolchains/languages/python-tools.js +1 -1
  165. package/dist/guest/toolchains/languages/ruby.js +1 -1
  166. package/dist/guest/toolchains/native/binstall.js +1 -1
  167. package/dist/guest/toolchains/native/msvc/packages.js +10 -4
  168. package/dist/guest/toolchains/native/rust.d.ts +2 -0
  169. package/dist/guest/toolchains/native/rust.js +11 -4
  170. package/dist/guest/toolchains/native/unreal.d.ts +2 -0
  171. package/dist/guest/toolchains/native/unreal.js +16 -6
  172. package/dist/guest/toolchains/native/vcruntime.d.ts +2 -0
  173. package/dist/guest/toolchains/native/vcruntime.js +10 -2
  174. package/dist/guest/toolchains/native/visual-studio.d.ts +3 -0
  175. package/dist/guest/toolchains/native/visual-studio.js +44 -26
  176. package/dist/guest/toolchains/native/vs-request.d.ts +2 -0
  177. package/dist/guest/toolchains/native/vs-request.js +2 -0
  178. package/dist/guest/toolchains/plan.js +19 -8
  179. package/dist/guest/toolchains/scheduler.d.ts +2 -21
  180. package/dist/guest/toolchains/scheduler.js +7 -121
  181. package/dist/guest/toolchains/setup.d.ts +15 -2
  182. package/dist/guest/toolchains/setup.js +39 -20
  183. package/dist/guest/toolchains/split.d.ts +28 -0
  184. package/dist/guest/toolchains/split.js +60 -0
  185. package/dist/guest/toolchains/steam/client.js +2 -1
  186. package/dist/guest/toolchains/step-scheduler.d.ts +51 -0
  187. package/dist/guest/toolchains/step-scheduler.js +147 -0
  188. package/dist/guest/toolchains/step.d.ts +13 -0
  189. package/dist/guest/toolchains/tools/git.js +18 -0
  190. package/dist/guest/vpn/openvpn.js +3 -4
  191. package/dist/guest/vpn/wireguard.js +11 -4
  192. package/dist/host/accounts/deliver.js +7 -0
  193. package/dist/host/accounts/handoff.js +2 -6
  194. package/dist/host/accounts/index.d.ts +1 -1
  195. package/dist/host/accounts/index.js +1 -1
  196. package/dist/host/accounts/kinds/cfx.d.ts +1 -1
  197. package/dist/host/accounts/kinds/cfx.js +47 -4
  198. package/dist/host/accounts/kinds/comet.d.ts +2 -0
  199. package/dist/host/accounts/kinds/comet.js +6 -0
  200. package/dist/host/accounts/kinds/perplexity.d.ts +2 -0
  201. package/dist/host/accounts/kinds/perplexity.js +30 -0
  202. package/dist/host/accounts/leases.d.ts +7 -1
  203. package/dist/host/accounts/leases.js +13 -2
  204. package/dist/host/accounts/source.d.ts +7 -1
  205. package/dist/host/accounts/source.js +27 -0
  206. package/dist/host/accounts/sources.js +4 -0
  207. package/dist/host/github/deliver.d.ts +1 -1
  208. package/dist/host/github/deliver.js +20 -1
  209. package/dist/host/github/index.d.ts +2 -1
  210. package/dist/host/github/index.js +1 -0
  211. package/dist/host/github/token.d.ts +13 -1
  212. package/dist/host/github/token.js +19 -2
  213. package/dist/host/github/verify.d.ts +27 -0
  214. package/dist/host/github/verify.js +61 -0
  215. package/dist/host/launch/hints/fivem.d.ts +3 -1
  216. package/dist/host/launch/hints/fivem.js +68 -2
  217. package/dist/host/launch/session-file.js +4 -0
  218. package/dist/host/launch/toolchains.d.ts +2 -1
  219. package/dist/host/launch/toolchains.js +5 -3
  220. package/dist/host/profile/claude-login.d.ts +2 -2
  221. package/dist/host/profile/claude-login.js +4 -3
  222. package/dist/host/vpn/nordvpn.d.ts +2 -4
  223. package/dist/host/vpn/nordvpn.js +2 -24
  224. package/dist/runtime/agent.js +405 -90
  225. package/dist/runtime/daemon.js +3010 -1383
  226. package/dist/runtime/db.js +333 -90
  227. package/dist/runtime/main.js +4720 -1954
  228. package/dist/runtime/netproxy.js +286 -69
  229. package/dist/runtime/tool.js +2852 -1780
  230. package/dist/runtime/view.js +286 -69
  231. package/dist/selftest/accounts.test.js +1 -1
  232. package/dist/selftest/agent-paths.test.js +39 -1
  233. package/dist/selftest/agent-settings.test.js +6 -0
  234. package/dist/selftest/agents-web.test.d.ts +2 -0
  235. package/dist/selftest/agents-web.test.js +647 -0
  236. package/dist/selftest/app.test.js +5 -2
  237. package/dist/selftest/boot-runner.test.d.ts +2 -0
  238. package/dist/selftest/boot-runner.test.js +456 -0
  239. package/dist/selftest/channel.test.js +15 -0
  240. package/dist/selftest/fivem.test.js +249 -3
  241. package/dist/selftest/github.test.js +94 -9
  242. package/dist/selftest/guest-boot.test.js +3 -0
  243. package/dist/selftest/health.test.js +1 -1
  244. package/dist/selftest/index.js +8 -0
  245. package/dist/selftest/layout.test.js +5 -0
  246. package/dist/selftest/menu-coverage.test.d.ts +2 -0
  247. package/dist/selftest/menu-coverage.test.js +46 -0
  248. package/dist/selftest/menu-screens.js +37 -1
  249. package/dist/selftest/persisted-installs.test.js +6 -3
  250. package/dist/selftest/service-accounts.test.js +3 -2
  251. package/dist/selftest/support/engine-golden.js +27 -0
  252. package/dist/selftest/support/fixtures.d.ts +6 -0
  253. package/dist/selftest/support/web-preview.d.ts +34 -1
  254. package/dist/selftest/support/web-preview.js +21 -18
  255. package/dist/selftest/toolchains.test.js +23 -1
  256. package/dist/selftest/ui-text.test.d.ts +7 -0
  257. package/dist/selftest/ui-text.test.js +300 -0
  258. package/dist/shared/accounts/anthropic.d.ts +1 -1
  259. package/dist/shared/accounts/anthropic.js +9 -8
  260. package/dist/shared/accounts/index.d.ts +2 -0
  261. package/dist/shared/accounts/index.js +2 -0
  262. package/dist/shared/accounts/kinds/comet.d.ts +12 -0
  263. package/dist/shared/accounts/kinds/comet.js +64 -0
  264. package/dist/shared/accounts/kinds/perplexity.d.ts +8 -0
  265. package/dist/shared/accounts/kinds/perplexity.js +37 -0
  266. package/dist/shared/accounts/kinds.d.ts +24 -5
  267. package/dist/shared/accounts/kinds.js +86 -4
  268. package/dist/shared/accounts/payloads.d.ts +81 -0
  269. package/dist/shared/accounts/payloads.js +39 -1
  270. package/dist/shared/apps/agent-addons.d.ts +33 -5
  271. package/dist/shared/apps/agent-addons.js +95 -3
  272. package/dist/shared/apps/catalogue-agents-web.d.ts +14 -0
  273. package/dist/shared/apps/catalogue-agents-web.js +112 -0
  274. package/dist/shared/apps/catalogue-modding.js +32 -1
  275. package/dist/shared/apps/catalogue.d.ts +27 -3
  276. package/dist/shared/apps/catalogue.js +2 -1
  277. package/dist/shared/apps/index.d.ts +3 -1
  278. package/dist/shared/apps/index.js +3 -1
  279. package/dist/shared/channel/schema.d.ts +21 -3
  280. package/dist/shared/channel/schema.js +7 -0
  281. package/dist/shared/channel/secrets.d.ts +19 -0
  282. package/dist/shared/concurrency/index.d.ts +3 -0
  283. package/dist/shared/concurrency/index.js +3 -0
  284. package/dist/shared/concurrency/installer-retry.d.ts +6 -0
  285. package/dist/shared/concurrency/installer-retry.js +10 -0
  286. package/dist/shared/concurrency/limiter.d.ts +19 -0
  287. package/dist/shared/concurrency/limiter.js +67 -0
  288. package/dist/shared/concurrency/pools.d.ts +7 -0
  289. package/dist/shared/concurrency/pools.js +9 -0
  290. package/dist/shared/download/archive.d.ts +2 -0
  291. package/dist/shared/download/archive.js +11 -1
  292. package/dist/shared/download/bounded-fetch.d.ts +13 -0
  293. package/dist/shared/download/bounded-fetch.js +40 -0
  294. package/dist/shared/download/downloader.d.ts +5 -0
  295. package/dist/shared/download/downloader.js +50 -38
  296. package/dist/shared/download/index.d.ts +2 -1
  297. package/dist/shared/download/index.js +2 -1
  298. package/dist/shared/readiness.d.ts +2 -2
  299. package/dist/shared/readiness.js +2 -2
  300. package/dist/web/index.html +1 -1
  301. package/dist/web/{main-OUUQYNK4.js → main-CCILLX2M.js} +67 -67
  302. package/native/csharp/HcsHost/AssemblyInfo.cs +3 -3
  303. package/native/csharp/HostTools/AssemblyInfo.cs +3 -3
  304. package/native/csharp/StorageHelper/AssemblyInfo.cs +3 -3
  305. package/package.json +1 -1
  306. package/sandbox/addons/browser-use-mcp/requirements.in +1 -0
  307. package/sandbox/addons/browser-use-mcp/requirements.txt +2350 -0
  308. package/sandbox/addons/chrome-devtools-mcp/package-lock.json +38 -0
  309. package/sandbox/addons/chrome-devtools-mcp/package.json +7 -0
  310. package/sandbox/addons/comet-mcp/package-lock.json +1277 -0
  311. package/sandbox/addons/comet-mcp/package.json +7 -0
  312. package/sandbox/addons/perplexity-mcp/package-lock.json +1655 -0
  313. package/sandbox/addons/perplexity-mcp/package.json +7 -0
  314. package/sandbox/scripts/add-firewall-port.ps1 +18 -4
  315. package/sandbox/scripts/set-machine-environment.ps1 +30 -15
  316. package/sandbox/templates/fivem/README.txt +6 -2
  317. package/sandbox/templates/fivem/cs/Client/Client.csproj +15 -0
  318. package/sandbox/templates/fivem/cs/Client/ClientMain.cs +20 -0
  319. package/sandbox/templates/fivem/cs/Server/Server.csproj +14 -0
  320. package/sandbox/templates/fivem/cs/Server/ServerMain.cs +20 -0
  321. package/sandbox/templates/fivem/cs/fxmanifest.lua +11 -0
  322. package/sandbox/templates/fivem/js/client.js +12 -0
  323. package/sandbox/templates/fivem/js/fxmanifest.lua +9 -0
  324. package/sandbox/templates/fivem/js/server.js +6 -0
  325. package/sandbox/templates/fivem/lua/client.lua +8 -0
  326. package/sandbox/templates/fivem/lua/fxmanifest.lua +10 -0
  327. package/sandbox/templates/fivem/lua/server.lua +6 -0
  328. package/sandbox/templates/fivem/server.cfg +37 -0
  329. package/sandbox/templates/fivem/ts/build.js +17 -0
  330. package/sandbox/templates/fivem/ts/fxmanifest.lua +9 -0
  331. package/sandbox/templates/fivem/ts/package.json +16 -0
  332. package/sandbox/templates/fivem/ts/src/client/client.ts +12 -0
  333. package/sandbox/templates/fivem/ts/src/client/tsconfig.json +13 -0
  334. package/sandbox/templates/fivem/ts/src/server/server.ts +6 -0
  335. package/sandbox/templates/fivem/ts/src/server/tsconfig.json +13 -0
  336. package/schemas/config.schema.json +56 -27
  337. package/schemas/sandbox-config.schema.json +37 -14
@@ -4,11 +4,14 @@ import path from 'node:path';
4
4
  import { spawn } from 'node:child_process';
5
5
  import { writeGuides } from './guide.js';
6
6
  import { setupToolchains } from '../toolchains/index.js';
7
+ import { mergeToolchains } from '../toolchains/setup.js';
8
+ import { tool } from '../toolchains/tool-env.js';
9
+ import { installedAddon } from '../setup/agent-addons.js';
7
10
  import { agents } from '../agents/agent-installer.js';
8
11
  import { agentArguments, agentShims, codexArguments, sbxAgentText, shimText } from '../agents/agent-files.js';
9
12
  import { codexBootConfig, resetMachineBound, restoreLocalState } from '../agents/local-state.js';
10
13
  import { installShellPath } from '../setup/shell-path.js';
11
- import { linkProfileDirs } from '../agents/profile-links.js';
14
+ import { linkProfileDirsAsync } from '../agents/profile-links.js';
12
15
  import { restoreClaudeMem } from '../setup/claude-mem.js';
13
16
  import { syncClaudeProfile } from '../setup/claude-profile.js';
14
17
  import { agentEnv, persistEnvironment } from '../setup/environment.js';
@@ -17,7 +20,7 @@ import { applyAllowOnly, proxyEnv } from '../network/allow-only.js';
17
20
  import { applyNetworkPolicy, networkProblems } from '../network/firewall.js';
18
21
  import { writeManagedSettings } from '../setup/managed-policy.js';
19
22
  import { writeAddonMcpServers } from '../setup/addon-mcp.js';
20
- import { startHeadroom } from '../setup/headroom.js';
23
+ import { awaitHeadroom, spawnHeadroom } from '../setup/headroom.js';
21
24
  import { applyPersonalization } from '../setup/desktop.js';
22
25
  import { keepBrowsersOffGpu } from '../setup/browser-gpu.js';
23
26
  import { setupGitConfig } from '../setup/git-identity.js';
@@ -34,39 +37,20 @@ import { now } from '../../shared/channel/run-dir.js';
34
37
  import { writeJsonAtomic } from '../../shared/io/json.js';
35
38
  import { viewSession } from '../sessions/viewer.js';
36
39
  import { saveBootEnv } from './boot-env.js';
40
+ import { BOOT_DEFS, STAGES, stageTitle } from './graph.js';
41
+ import { BootRunner, bootSummary, seconds } from './runner.js';
42
+ import { installPools } from '../runtime/pools.js';
37
43
  import { primaryProject, saveProjectStatus } from './project-status.js';
38
44
  import { dryRun, isWin, localDir, logsDir, run, toolsDir } from '../runtime/paths.js';
39
- import { log, logPath, warn } from '../runtime/log.js';
45
+ import { log, logPath, runQuiet, warn, withLogContext } from '../runtime/log.js';
40
46
  import { mkdirp } from '../runtime/fs.js';
41
47
  import { session, workspace } from '../runtime/session.js';
42
48
  import { applyBootEnvironment, BOOT_SECRETS_VARIABLE, takeSecrets } from '../runtime/secrets.js';
43
- import { setSandboxStatus } from '../runtime/status.js';
49
+ import { setBackgroundWork, setSandboxStatus } from '../runtime/status.js';
44
50
  import { errMsg } from '../../core/util/errors.js';
45
- const STEPS = 9;
46
51
  const PRIMARY_POLLS = 600;
47
52
  const POLL_MS = 500;
48
53
  const VSCODE_LANGUAGES = ['python', 'java', 'go', 'rust', 'cpp', 'msvc', 'dotnet', 'ruby', 'php', 'deno', 'pwsh'];
49
- /** Step n of STEPS: a line in the window and the host's progress (the short title, with what is set up in it). */
50
- function step(n, title) {
51
- log('\n\x1b[36m[' + n + '/' + STEPS + '] ' + title + '\x1b[0m');
52
- setSandboxStatus(n === 1 ? 'booting' : 'provisioning', '[' + n + '/' + STEPS + '] ' + title, {
53
- step: n,
54
- steps: STEPS,
55
- title: title.replace(/ \(.*\)$/, ''),
56
- active: [],
57
- done: 0,
58
- total: 0,
59
- });
60
- }
61
- /** Runs work that may fail without stopping the boot (a warning says what failed). */
62
- async function soft(what, work) {
63
- try {
64
- await work();
65
- }
66
- catch (e) {
67
- warn(what + ' failed (continuing): ' + errMsg(e));
68
- }
69
- }
70
54
  function startDaemon(env, secrets) {
71
55
  spawn(process.execPath, [path.join(path.dirname(process.argv[1]), 'daemon.js')], {
72
56
  detached: true,
@@ -142,13 +126,49 @@ function vscodeLanguages() {
142
126
  const toolchains = session.toolchains;
143
127
  return VSCODE_LANGUAGES.filter((t) => wanted(toolchains[t]?.enabled ?? false, t));
144
128
  }
145
- /** One boot of the sandbox, step by step: each step is a method, in the order they run. */
129
+ /** Headroom's own marker: the app was installed in an earlier boot (so the Apps step will not replace its folder). */
130
+ function headroomInstalledBefore() {
131
+ return (!session.provisioning.refresh &&
132
+ installedAddon('headroom') !== null &&
133
+ fs.existsSync(path.join(tool('apps', 'headroom'), '.agent-sandbox-app')));
134
+ }
135
+ /** Warns and goes on (a step inside a task that must not stop the rest of that task). */
136
+ async function soft(what, work) {
137
+ try {
138
+ await work();
139
+ }
140
+ catch (e) {
141
+ warn(what + ' failed (continuing): ' + errMsg(e));
142
+ }
143
+ }
144
+ /** One boot of the sandbox: a graph of tasks (graph.ts) run by the BootRunner, each task a method below. */
146
145
  export class Boot {
146
+ // The shared boot state: each field is written by one task (graph.ts says which); readers come after that task.
147
147
  ptyHost = null;
148
148
  lan = session.networking ? 'open' : 'offline';
149
+ tools = null;
150
+ dbBin = null;
151
+ allowSummary = [];
152
+ vscodeSummary = [];
153
+ env = {};
154
+ toolVars = [];
155
+ summary = [];
156
+ headroom = null;
149
157
  gitAccess = session.provisioning.git.access ?? 'full';
150
- /** What the host handed over in its one-shot file (read and deleted at the start of run()). */
151
- secrets = {};
158
+ /** What the host handed over in its one-shot file (read and deleted in the prelude; never changed afterwards). */
159
+ secrets = Object.freeze({});
160
+ basePath = '';
161
+ startedAt = Date.now();
162
+ openGate = () => undefined;
163
+ gate = new Promise((resolve) => {
164
+ this.openGate = resolve;
165
+ });
166
+ /** The boot is ready: the runner no longer writes the status (the session owns it). */
167
+ ready = false;
168
+ lastStatus = null;
169
+ activeSteps = [];
170
+ stepsDone = 0;
171
+ stepsTotal = 0;
152
172
  async run() {
153
173
  log('Agent sandbox: ' +
154
174
  session.project +
@@ -160,151 +180,305 @@ export class Boot {
160
180
  logPath);
161
181
  if (!fs.statSync(workspace, { throwIfNoEntry: false })?.isDirectory())
162
182
  throw new Error('Workspace folder is missing in the sandbox: ' + workspace);
183
+ this.basePath = process.env.PATH ?? '';
163
184
  mkdirp(toolsDir);
164
185
  mkdirp(run.root);
165
- this.secrets = takeSecrets(session.launchId);
166
- await this.serviceAccounts();
186
+ // The prelude is sequential: it changes process.env, so it ends before any task starts a program.
187
+ this.secrets = await this.takeSecretsAndAccounts();
167
188
  applyBootEnvironment(this.secrets.harnessEnvironment);
168
189
  prepareGithubFolder(this.secrets.githubToken);
169
- await this.networkAndSessionHost();
170
- await this.hooksAndDesktop();
171
- const { tools, env } = await this.developerTools();
172
- await this.vpn();
173
- await this.gitIdentity(env);
174
- await this.claude(tools, env);
175
- await this.agent(env);
176
- this.preAgentHooks(env);
177
- await this.start(env);
190
+ installPools();
191
+ const runner = new BootRunner(BOOT_DEFS, this.tasks(), {
192
+ say: (line, quiet) => (quiet ? runQuiet(() => log(line)) : log(line)),
193
+ warn: (line, quiet) => (quiet ? runQuiet(() => warn(line)) : warn(line)),
194
+ now: () => Date.now(),
195
+ dryRun,
196
+ stages: STAGES,
197
+ stageTitle: (n) => this.stageTitle(n),
198
+ status: (s) => {
199
+ this.lastStatus = s;
200
+ this.publish();
201
+ },
202
+ inContext: (ctx, work) => withLogContext({ prefix: ctx.prefix, quiet: ctx.quiet }, work),
203
+ });
204
+ await runner.run('foreground');
205
+ const background = this.backgroundNames();
206
+ log(bootSummary(Date.now() - this.startedAt, runner.results(), background, logPath));
207
+ if (dryRun) {
208
+ // Same graph, one task at a time: the background tasks run in place, right after the session.
209
+ this.openGate();
210
+ await runner.run('background');
211
+ return;
212
+ }
213
+ this.openGate();
214
+ const later = runner.run('background');
215
+ // The viewer owns the console now: the background tasks write to the log file only.
216
+ if (session.harness && session.autoSession !== false && process.stdin.isTTY) {
217
+ await viewSession(session.launchId);
218
+ log('\nThis window stays open in ' + workspace + '. Other sessions keep running in their own tabs.');
219
+ }
220
+ await later.catch((e) => warn('Background work failed: ' + errMsg(e)));
221
+ }
222
+ stageTitle(n) {
223
+ return stageTitle(n, { ...(session.vpn ? { vpnServer: session.vpn.server } : {}), agent: session.harnessName });
224
+ }
225
+ /** The names shown for work that goes on after the boot is ready. */
226
+ backgroundNames() {
227
+ const t = this.tools;
228
+ if (!t?.later)
229
+ return [];
230
+ const later = t.names.filter((n) => !(n in t.steps));
231
+ return later.length ? [later.slice(0, 3).join(', ') + (later.length > 3 ? ' ...' : '')] : [];
178
232
  }
179
233
  /**
180
- * Your saved service sign-ins (accounts.<kind>.share) go to their tools before anything opens them, and leave memory
181
- * at once; what they give the agent (EXPO_TOKEN ...) joins its environment (in memory only).
234
+ * The host's one-shot file, read once. Your saved service sign-ins (accounts.<kind>.share) go to their tools before
235
+ * anything opens them, and leave memory at once; what they give the agent (EXPO_TOKEN ...) joins its environment
236
+ * (in memory only).
182
237
  */
183
- async serviceAccounts() {
184
- const given = this.secrets.serviceAccounts;
185
- this.secrets = { ...this.secrets, serviceAccounts: undefined };
186
- if (dryRun || (!given && !session.accountLeases?.length))
238
+ async takeSecretsAndAccounts() {
239
+ const taken = takeSecrets(session.launchId);
240
+ const given = taken.serviceAccounts;
241
+ let secrets = { ...taken, serviceAccounts: undefined };
242
+ if (!dryRun && (given || session.accountLeases?.length)) {
243
+ try {
244
+ const env = await applyServiceAccounts(given, {
245
+ leased: session.accountLeases ?? [],
246
+ say: (line) => log(line),
247
+ });
248
+ if (Object.keys(env).length)
249
+ secrets = { ...secrets, harnessEnvironment: { ...env, ...secrets.harnessEnvironment } };
250
+ }
251
+ catch (e) {
252
+ warn('Service sign-ins failed (continuing): ' + errMsg(e));
253
+ }
254
+ }
255
+ return Object.freeze(secrets);
256
+ }
257
+ /** The host's progress line: the runner's stage, the tasks that run now, and what the toolchain scheduler runs. */
258
+ publish() {
259
+ const s = this.lastStatus;
260
+ if (!s || this.ready)
187
261
  return;
188
- await soft('Service sign-ins', async () => {
189
- const env = await applyServiceAccounts(given, { leased: session.accountLeases ?? [], say: (line) => log(line) });
190
- if (Object.keys(env).length)
191
- this.secrets = { ...this.secrets, harnessEnvironment: { ...env, ...this.secrets.harnessEnvironment } };
262
+ setSandboxStatus(s.phase, s.message, {
263
+ step: s.step,
264
+ steps: STAGES,
265
+ title: this.stageTitle(s.step).replace(/ \(.*\)$/, ''),
266
+ active: [...s.running.map((name) => ({ name })), ...this.activeSteps],
267
+ done: this.stepsDone,
268
+ total: this.stepsTotal,
192
269
  });
193
270
  }
194
- async networkAndSessionHost() {
195
- step(1, 'Network and session host');
196
- if (isWin && !dryRun && session.attach.enabled)
197
- await soft('Building the session host', () => {
198
- this.ptyHost = ensurePtyHost();
199
- });
200
- await soft('Private-network blocking', async () => {
201
- this.lan = await applyNetworkPolicy(this.ptyHost);
202
- });
203
- await soft('Audit', enableProcessAudit);
271
+ /** Every task of the graph. */
272
+ tasks() {
273
+ return {
274
+ // 1 - network and session host
275
+ ptyhost: () => {
276
+ if (isWin && !dryRun && session.attach.enabled)
277
+ this.ptyHost = ensurePtyHost();
278
+ },
279
+ network: async () => {
280
+ this.lan = await applyNetworkPolicy(this.ptyHost);
281
+ },
282
+ audit: () => enableProcessAudit(),
283
+ // 2 - pre-provision hooks and desktop
284
+ hooksPreProvision: () => runHooks('pre-provision', process.env),
285
+ desktop: () => applyPersonalization(),
286
+ browserGpu: () => keepBrowsersOffGpu(),
287
+ // 3 - developer tools
288
+ toolchains: () => this.toolchains(),
289
+ dbCommands: () => {
290
+ if (!dryRun)
291
+ this.dbBin = writeDbCommand();
292
+ },
293
+ allowOnly: async () => {
294
+ if (await applyAllowOnly())
295
+ this.allowSummary = ['network: only network.allowOnly hosts (refused: logs\\netproxy.log)'];
296
+ },
297
+ vscode: () => this.vscode(),
298
+ env: () => this.environment(),
299
+ bootEnv: () => this.bootEnv(),
300
+ // 4 - VPN
301
+ vpn: async () => {
302
+ if (session.vpn)
303
+ await setupVpn(this.secrets, this.ptyHost);
304
+ },
305
+ // 5 - git
306
+ gitConfig: () => setupGitConfig(this.env),
307
+ githubLogin: async () => {
308
+ const token = this.secrets.githubToken;
309
+ if (token)
310
+ await loginGithub(token, this.env);
311
+ },
312
+ // 6 - Claude settings
313
+ claudeProfile: async () => {
314
+ if (session.harnessName === 'claude')
315
+ await syncClaudeProfile(this.secrets.claudeCredentials);
316
+ },
317
+ claudeMem: () => restoreClaudeMem(),
318
+ agentState: async () => {
319
+ // All three touch the agents' state folders: one task, in this order, each failing on its own.
320
+ await soft('Agent files of the last sandbox', resetMachineBound);
321
+ await soft('Codex settings', codexBootConfig);
322
+ await soft('Agent databases restore', restoreLocalState);
323
+ },
324
+ headroomSpawn: async () => {
325
+ // Early only when the proxy is installed already (the Apps step must not replace a running one).
326
+ if (headroomInstalledBefore())
327
+ await spawnHeadroom(this.headroomAgentEnv());
328
+ },
329
+ mcpServers: () => {
330
+ writeAddonMcpServers();
331
+ },
332
+ headroomReady: async () => {
333
+ this.headroom = await awaitHeadroom(this.headroomAgentEnv());
334
+ },
335
+ managedSettings: () => writeManagedSettings(this.gitAccess, this.headroom),
336
+ guide: () => {
337
+ writeGuides(this.summary, this.lan);
338
+ },
339
+ // 7 - agent
340
+ profileLinks: () => linkProfileDirsAsync(session.agentProfileDirs ?? {}),
341
+ agentProvision: async () => {
342
+ if (session.harness)
343
+ await agents.provision(session.harnessName, session.harness, this.env);
344
+ },
345
+ // 8 - pre-agent hooks
346
+ hooksPreAgent: () => runHooks('pre-agent', this.env),
347
+ // 9 - start
348
+ session: () => this.start(),
349
+ // After the first session runs
350
+ toolchainsLater: () => this.toolchainsLater(),
351
+ prune: () => {
352
+ pruneToolLeftovers();
353
+ },
354
+ };
204
355
  }
205
- async hooksAndDesktop() {
206
- step(2, 'Pre-provision hooks and desktop');
207
- runHooks('pre-provision', process.env);
208
- await soft('Personalisation', applyPersonalization);
209
- await soft('Browsers without the GPU', keepBrowsersOffGpu);
356
+ /** The agent environment before the toolchains are known (the proxy needs no PATH of theirs). */
357
+ headroomAgentEnv() {
358
+ return agentEnv({ vars: { ...session.toolchains.environment, ...proxyEnv() }, prepend: [], append: [] });
210
359
  }
211
- /** Toolchains, databases, apps, the network proxy and VS Code; then the agent environment, saved machine-wide. */
212
- async developerTools() {
213
- step(3, 'Developer tools (the first start downloads them once; later starts are quick)');
214
- const basePath = process.env.PATH ?? '';
215
- const tools = await setupToolchains(session.toolchains, session.versions, {
360
+ /** Foreground toolchain steps and databases and apps; Visual Studio and what needs it wait for the background. */
361
+ async toolchains() {
362
+ const deferHeavy = !dryRun && !session.vpn && !(session.network.allowOnly ?? []).length;
363
+ this.tools = await setupToolchains(session.toolchains, session.versions, {
216
364
  gitEnabled: session.provisioning.git.enabled,
217
365
  gitAccess: this.gitAccess,
218
366
  hostGit: session.hostTools.git,
219
367
  refresh: session.provisioning.refresh,
220
368
  databases: session.databases ?? [],
221
369
  apps: session.apps,
370
+ deferHeavy,
222
371
  ...(session.pcInstalls ? { pcInstalls: session.pcInstalls } : {}),
372
+ }, {
373
+ progress: (p) => {
374
+ this.activeSteps = p.active;
375
+ this.stepsDone = p.done;
376
+ this.stepsTotal = p.total;
377
+ this.publish();
378
+ },
379
+ // Headroom is installed by the Apps step on a first boot: start it as soon as that step is done.
380
+ onDone: (name) => {
381
+ if (name === 'Apps')
382
+ void spawnHeadroom(this.headroomAgentEnv()).catch((e) => warn('Headroom proxy failed (continuing): ' + errMsg(e)));
383
+ },
384
+ }, { gate: this.gate });
385
+ }
386
+ vscode() {
387
+ const vscode = session.toolchains.vscode;
388
+ const tools = this.tools;
389
+ if (!vscode.enabled || vscode.setup === false)
390
+ return;
391
+ // configureVscode only adds lines to `summary`: they are collected here and merged by the bootEnv task.
392
+ const lines = [];
393
+ configureVscode({ vars: tools.vars, prepend: tools.prepend, append: tools.append, summary: lines }, {
394
+ toolchains: ['node', ...vscodeLanguages()],
395
+ databases: (session.databases ?? []).map((d) => d.database),
396
+ config: vscode,
397
+ workspace,
223
398
  });
224
- for (const p of networkProblems())
225
- tools.summary.push('PROTECTION MISSING: ' + p);
226
- if (!dryRun)
227
- tools.prepend.push(writeDbCommand());
399
+ this.vscodeSummary = lines;
400
+ }
401
+ /** The agent environment, saved machine-wide, and the PATH of new shells. */
402
+ async environment() {
403
+ const tools = this.tools;
228
404
  // network.allowOnly / network.proxy: everything started from now on uses the proxy.
229
- Object.assign(tools.vars, proxyEnv());
230
- await soft('Network: allow only some hosts', async () => {
231
- if (await applyAllowOnly())
232
- tools.summary.push('network: only network.allowOnly hosts (refused: logs\\netproxy.log)');
405
+ const vars = { ...tools.vars, ...proxyEnv() };
406
+ this.toolVars = Object.keys(vars);
407
+ this.env = agentEnv({
408
+ vars,
409
+ prepend: [...tools.prepend, ...(this.dbBin ? [this.dbBin] : [])],
410
+ append: tools.append,
233
411
  });
234
- const vscode = session.toolchains.vscode;
235
- if (vscode.enabled && vscode.setup !== false)
236
- await soft('VS Code setup', () => configureVscode(tools, {
237
- toolchains: ['node', ...vscodeLanguages()],
238
- databases: (session.databases ?? []).map((d) => d.database),
239
- config: vscode,
240
- workspace,
241
- }));
242
- const env = agentEnv(tools);
243
- persistEnvironment(env, Object.keys(tools.vars));
412
+ await persistEnvironment(this.env, this.toolVars);
244
413
  await soft('Shell start-up PATH', installShellPath);
414
+ }
415
+ /** What the tools left: lines for the guide and status, and what later projects start from. */
416
+ bootEnv() {
417
+ const tools = this.tools;
418
+ this.summary = this.summaryLines(tools.summary);
245
419
  saveBootEnv({
246
- basePath,
247
- toolVars: Object.keys(tools.vars),
420
+ basePath: this.basePath,
421
+ toolVars: this.toolVars,
248
422
  steps: tools.steps,
249
- summary: tools.summary,
423
+ summary: this.summary,
250
424
  lan: this.lan,
251
425
  });
252
- saveProjectStatus(primaryProject(), workspace, 'ready', 'Ready', session.databases ?? [], tools.summary);
253
- for (const line of tools.summary)
426
+ saveProjectStatus(primaryProject(), workspace, 'ready', 'Ready', session.databases ?? [], this.summary);
427
+ for (const line of this.summary)
254
428
  log(' ' + line);
255
- await soft('Cleaning old tool builds', () => pruneToolLeftovers());
256
- return { tools, env };
257
429
  }
258
- /** vpn.enabled: the tunnel and its kill switch, before anything else uses the network (git, the agent). */
259
- async vpn() {
260
- step(4, session.vpn ? 'VPN (' + session.vpn.server + ')' : 'VPN (off)');
261
- if (!session.vpn)
262
- return;
263
- await soft('VPN', async () => {
264
- await setupVpn(this.secrets, this.ptyHost);
265
- });
430
+ /** The toolchains' lines, then the missing protections, allowOnly and VS Code (in this order). */
431
+ summaryLines(toolchainLines) {
432
+ return [
433
+ ...toolchainLines,
434
+ ...networkProblems().map((p) => 'PROTECTION MISSING: ' + p),
435
+ ...this.allowSummary,
436
+ ...this.vscodeSummary,
437
+ ];
266
438
  }
267
- async gitIdentity(env) {
268
- step(5, 'Git identity');
269
- await soft('Git config', () => setupGitConfig(env));
270
- // After the VPN (gh checks the token with GitHub) and the git config (setup-git adds to it).
271
- const token = this.secrets.githubToken;
272
- if (token) {
273
- this.secrets = { ...this.secrets, githubToken: undefined };
274
- await soft('GitHub token', () => loginGithub(token, env));
439
+ /** Visual Studio and what depends on it (after the session has started): merged into the environment again. */
440
+ async toolchainsLater() {
441
+ const tools = this.tools;
442
+ if (!tools?.later)
443
+ return;
444
+ const name = this.backgroundNames()[0] ?? 'Visual Studio';
445
+ const began = Date.now();
446
+ setBackgroundWork([{ name, state: 'running' }]);
447
+ log('Background: ' + name + ' (installing)');
448
+ try {
449
+ const part = await tools.later;
450
+ const steps = { ...tools.steps, ...part.steps };
451
+ const all = mergeToolchains(session.toolchains, tools.names, steps);
452
+ const vars = { ...all.vars, ...proxyEnv() };
453
+ const env = agentEnv({
454
+ vars,
455
+ prepend: [...all.prepend, ...(this.dbBin ? [this.dbBin] : [])],
456
+ append: all.append,
457
+ });
458
+ // Additive: nothing the boot or a project added since is taken away.
459
+ await persistEnvironment(env, Object.keys(vars), true);
460
+ this.summary = this.summaryLines(all.summary);
461
+ saveBootEnv({
462
+ basePath: this.basePath,
463
+ toolVars: Object.keys(vars),
464
+ steps,
465
+ summary: this.summary,
466
+ lan: this.lan,
467
+ });
468
+ saveProjectStatus(primaryProject(), workspace, 'ready', 'Ready', session.databases ?? [], this.summary);
469
+ await soft('Sandbox guide for the agent', () => writeGuides(this.summary, this.lan));
470
+ setBackgroundWork([{ name, state: 'done' }]);
471
+ log('Background done in ' + seconds(Date.now() - began) + ': ' + name);
472
+ }
473
+ catch (e) {
474
+ setBackgroundWork([{ name, state: 'failed' }]);
475
+ throw e;
275
476
  }
276
477
  }
277
- async claude(tools, env) {
278
- step(6, 'Claude settings, history and claude-mem');
279
- if (session.harnessName === 'claude')
280
- await soft('Claude settings', () => syncClaudeProfile(this.secrets.claudeCredentials));
281
- await soft('claude-mem restore', restoreClaudeMem);
282
- await soft('Agent files of the last sandbox', resetMachineBound);
283
- await soft('Codex settings', codexBootConfig);
284
- await soft('Agent databases restore', restoreLocalState);
285
- // Agent add-ons: MCP servers in the sandbox's Claude Code, and the Headroom proxy before the managed settings point
286
- // Claude Code at it (the guide reads them back, so it comes last).
287
- let headroom = null;
288
- await soft('MCP servers from Apps', writeAddonMcpServers);
289
- await soft('Headroom proxy', async () => {
290
- headroom = await startHeadroom(env);
291
- });
292
- await soft('Claude managed settings', () => writeManagedSettings(this.gitAccess, headroom));
293
- await soft('Sandbox guide for the agent', () => writeGuides(tools.summary, this.lan));
294
- }
295
- async agent(env) {
296
- step(7, 'Agent: ' + session.harnessName);
297
- linkProfileDirs(session.agentProfileDirs ?? {});
298
- if (session.harness)
299
- await agents.provision(session.harnessName, session.harness, env);
300
- }
301
- preAgentHooks(env) {
302
- step(8, 'Pre-agent hooks');
303
- runHooks('pre-agent', env);
304
- }
305
- /** Ready: starts the session daemon and, with an agent, its first session, shown in this window. */
306
- async start(env) {
307
- step(9, 'Starting ' + session.harnessName);
478
+ /** Ready: starts the session daemon and, with an agent, its first session (shown in this window by run()). */
479
+ async start() {
480
+ const env = this.env;
481
+ this.ready = true;
308
482
  setSandboxStatus('ready', 'Ready');
309
483
  // No agent, or a restart that adds a project (the host opens its sessions itself once the sandbox is ready).
310
484
  if (!session.harness || session.autoSession === false) {
@@ -339,9 +513,6 @@ export class Boot {
339
513
  if (!(await waitForPrimary()))
340
514
  throw new Error('The agent session did not start. Logs: ' + logsDir);
341
515
  log('If Claude asks you to sign in, do it once; the login is saved in persistent storage.');
342
- if (process.stdin.isTTY)
343
- await viewSession(session.launchId);
344
- log('\nThis window stays open in ' + workspace + '. Other sessions keep running in their own tabs.');
345
516
  }
346
517
  }
347
518
  export function runBoot() {