windows-development-sandbox 1.18.4 → 1.23.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 (438) hide show
  1. package/README.md +1 -1
  2. package/config.example.json +17 -1
  3. package/dist/app/features/access/access.def.js +5 -2
  4. package/dist/app/features/access/access.run.js +7 -3
  5. package/dist/app/features/accounts/accounts.def.d.ts +33 -1
  6. package/dist/app/features/accounts/accounts.def.js +10 -4
  7. package/dist/app/features/accounts/accounts.run.d.ts +2 -0
  8. package/dist/app/features/accounts/accounts.run.js +7 -2
  9. package/dist/app/features/accounts/services.def.d.ts +7 -1
  10. package/dist/app/features/accounts/services.def.js +19 -16
  11. package/dist/app/features/accounts/services.run.d.ts +2 -0
  12. package/dist/app/features/accounts/services.run.js +44 -16
  13. package/dist/app/features/agent-commands/agent-commands.def.d.ts +37 -0
  14. package/dist/app/features/agent-commands/agent-commands.def.js +91 -0
  15. package/dist/app/features/agent-commands/agent-commands.run.d.ts +28 -0
  16. package/dist/app/features/agent-commands/agent-commands.run.js +35 -0
  17. package/dist/app/features/agent-commands/index.d.ts +2 -0
  18. package/dist/app/features/agent-commands/index.js +3 -0
  19. package/dist/app/features/agents/agents.def.d.ts +14 -1
  20. package/dist/app/features/agents/agents.def.js +61 -6
  21. package/dist/app/features/agents/agents.run.d.ts +1 -0
  22. package/dist/app/features/agents/agents.run.js +8 -1
  23. package/dist/app/features/agents/claude-env.def.d.ts +36 -0
  24. package/dist/app/features/agents/claude-env.def.js +305 -0
  25. package/dist/app/features/agents/env.def.d.ts +163 -0
  26. package/dist/app/features/agents/env.def.js +184 -0
  27. package/dist/app/features/agents/env.run.d.ts +43 -0
  28. package/dist/app/features/agents/env.run.js +86 -0
  29. package/dist/app/features/agents/index.d.ts +2 -0
  30. package/dist/app/features/agents/index.js +2 -0
  31. package/dist/app/features/defs.d.ts +171 -3
  32. package/dist/app/features/defs.js +9 -0
  33. package/dist/app/features/engine/engine.run.js +1 -1
  34. package/dist/app/features/github/github.def.d.ts +44 -3
  35. package/dist/app/features/github/github.def.js +145 -63
  36. package/dist/app/features/github/github.run.d.ts +9 -2
  37. package/dist/app/features/github/github.run.js +43 -5
  38. package/dist/app/features/health/health.def.js +8 -2
  39. package/dist/app/features/logs/logs.def.js +0 -8
  40. package/dist/app/features/projects/projects.def.js +2 -2
  41. package/dist/app/features/projects/projects.run.js +5 -5
  42. package/dist/app/features/sandbox/sandbox.def.js +7 -3
  43. package/dist/app/features/sessions/sessions.def.d.ts +4 -4
  44. package/dist/app/features/sessions/sessions.def.js +0 -5
  45. package/dist/app/features/sessions/sessions.run.d.ts +1 -1
  46. package/dist/app/features/sessions/sessions.run.js +2 -2
  47. package/dist/app/features/settings/categories.def.js +7 -2
  48. package/dist/app/features/settings/settings-rows.js +6 -2
  49. package/dist/app/features/settings/settings.def.js +1 -1
  50. package/dist/app/features/settings/settings.run.d.ts +8 -0
  51. package/dist/app/features/settings/settings.run.js +12 -3
  52. package/dist/app/features/storage/storage.run.js +18 -9
  53. package/dist/app/features/updates/update-lines.js +2 -2
  54. package/dist/app/features/updates/updates.def.js +1 -1
  55. package/dist/app/features/updates/updates.run.js +13 -3
  56. package/dist/app/features/vpn/vpn.def.d.ts +33 -0
  57. package/dist/app/features/vpn/vpn.def.js +30 -6
  58. package/dist/app/features/vpn/vpn.run.d.ts +11 -0
  59. package/dist/app/features/vpn/vpn.run.js +4 -1
  60. package/dist/app/features/web/web.def.js +2 -2
  61. package/dist/app/features/web/web.run.js +12 -4
  62. package/dist/app/kernel/errors.d.ts +7 -0
  63. package/dist/app/kernel/errors.js +18 -3
  64. package/dist/app/kernel/rpc.d.ts +6 -1
  65. package/dist/app/kernel/view.d.ts +11 -1
  66. package/dist/app/registry.js +7 -1
  67. package/dist/bin/agent-sandbox.js +2 -2
  68. package/dist/bin/{chunk-N4GXYTLV.js → chunk-JETGP2C3.js} +239 -72
  69. package/dist/bin/{chunk-MY7NLQQY.js → chunk-XZKOPGNH.js} +1 -1
  70. package/dist/bin/{chunk-FRPLQLSY.js → chunk-ZTTOF5V3.js} +6566 -4964
  71. package/dist/bin/claude-host.js +2 -2
  72. package/dist/bin/claude-sbx.js +2 -2
  73. package/dist/bin/codex-sbx.js +2 -2
  74. package/dist/bin/gemini-sbx.js +2 -2
  75. package/dist/bin/sandbox.js +2 -2
  76. package/dist/bin/sbx-hide.js +2 -2
  77. package/dist/bin/sbx-show.js +2 -2
  78. package/dist/cli/commands/agent-commands.d.ts +0 -1
  79. package/dist/cli/commands/agent-commands.js +2 -32
  80. package/dist/cli/commands/index.d.ts +1 -1
  81. package/dist/cli/commands/index.js +1 -1
  82. package/dist/cli/commands/launch/launch.js +2 -2
  83. package/dist/cli/commands/registry.js +3 -2
  84. package/dist/cli/manifest.d.ts +3 -3
  85. package/dist/cli/manifest.js +3 -2
  86. package/dist/cli/menu/coverage-exempt.d.ts +17 -0
  87. package/dist/cli/menu/coverage-exempt.js +61 -0
  88. package/dist/cli/menu/io-menu.d.ts +2 -0
  89. package/dist/cli/menu/io-menu.js +50 -5
  90. package/dist/cli/menu/menu.d.ts +1 -1
  91. package/dist/cli/menu/menu.js +3 -3
  92. package/dist/cli/menu/pages/accounts-page.js +1 -1
  93. package/dist/cli/menu/pages/agents-page.d.ts +7 -2
  94. package/dist/cli/menu/pages/agents-page.js +75 -13
  95. package/dist/cli/menu/pages/maintenance-page.d.ts +6 -0
  96. package/dist/cli/menu/pages/maintenance-page.js +10 -4
  97. package/dist/cli/menu/pages/sessions-page.d.ts +2 -0
  98. package/dist/cli/menu/pages/sessions-page.js +12 -4
  99. package/dist/cli/menu/pages/settings-page.js +13 -1
  100. package/dist/cli/menu/remote-menu.js +1 -1
  101. package/dist/cli/menu/shell.d.ts +5 -0
  102. package/dist/cli/menu/shell.js +13 -0
  103. package/dist/cli/menu/views.js +2 -1
  104. package/dist/cli/report.js +2 -0
  105. package/dist/cli/services/agent-commands-service.d.ts +2 -0
  106. package/dist/cli/services/agent-commands-service.js +13 -7
  107. package/dist/cli/services/vpn-service.d.ts +5 -1
  108. package/dist/cli/services/vpn-service.js +6 -1
  109. package/dist/cli/tui/app.d.ts +5 -0
  110. package/dist/cli/tui/app.js +2 -0
  111. package/dist/cli/tui/dialogs/text-screen.js +2 -1
  112. package/dist/cli/tui/terminal.js +3 -1
  113. package/dist/core/config/defaults.js +12 -1
  114. package/dist/core/detect/toolchains.js +9 -0
  115. package/dist/core/disk.d.ts +1 -5
  116. package/dist/core/disk.js +1 -16
  117. package/dist/core/schema/accounts.d.ts +6 -0
  118. package/dist/core/schema/accounts.js +13 -11
  119. package/dist/core/schema/codex.d.ts +29 -0
  120. package/dist/core/schema/codex.js +24 -0
  121. package/dist/core/schema/config.d.ts +58 -14
  122. package/dist/core/schema/config.js +6 -4
  123. package/dist/core/schema/github.js +1 -1
  124. package/dist/core/schema/index.d.ts +1 -0
  125. package/dist/core/schema/index.js +1 -0
  126. package/dist/core/schema/profile.js +8 -4
  127. package/dist/core/schema/resume.js +1 -1
  128. package/dist/core/schema/sandbox.js +3 -3
  129. package/dist/core/schema/toolchains.d.ts +4 -0
  130. package/dist/core/schema/toolchains.js +3 -0
  131. package/dist/core/schema/vpn.js +1 -1
  132. package/dist/core/schema/web.js +3 -3
  133. package/dist/core/types.d.ts +8 -0
  134. package/dist/core/util/errors.d.ts +11 -1
  135. package/dist/core/util/errors.js +7 -1
  136. package/dist/core/util/index.d.ts +1 -1
  137. package/dist/core/util/index.js +1 -1
  138. package/dist/guest/accounts/adapter.d.ts +2 -0
  139. package/dist/guest/accounts/adapters.js +4 -0
  140. package/dist/guest/accounts/apply.d.ts +10 -6
  141. package/dist/guest/accounts/kinds/cfx.d.ts +7 -0
  142. package/dist/guest/accounts/kinds/cfx.js +33 -3
  143. package/dist/guest/accounts/kinds/comet.d.ts +7 -0
  144. package/dist/guest/accounts/kinds/comet.js +50 -0
  145. package/dist/guest/accounts/kinds/perplexity.d.ts +2 -0
  146. package/dist/guest/accounts/kinds/perplexity.js +12 -0
  147. package/dist/guest/accounts/watch.d.ts +2 -0
  148. package/dist/guest/accounts/watch.js +12 -2
  149. package/dist/guest/agents/agent-files.d.ts +26 -6
  150. package/dist/guest/agents/agent-files.js +84 -14
  151. package/dist/guest/agents/agent-installer.js +1 -1
  152. package/dist/guest/agents/local-state.d.ts +5 -2
  153. package/dist/guest/agents/local-state.js +24 -10
  154. package/dist/guest/agents/profile-links.d.ts +2 -0
  155. package/dist/guest/agents/profile-links.js +18 -4
  156. package/dist/guest/apps/after-install.js +19 -0
  157. package/dist/guest/apps/app-installer.d.ts +11 -0
  158. package/dist/guest/apps/app-installer.js +69 -6
  159. package/dist/guest/apps/comet-unpack.d.ts +20 -0
  160. package/dist/guest/apps/comet-unpack.js +127 -0
  161. package/dist/guest/apps/index.d.ts +1 -1
  162. package/dist/guest/apps/index.js +1 -1
  163. package/dist/guest/apps/resolvers-agents-web.d.ts +2 -0
  164. package/dist/guest/apps/resolvers-agents-web.js +7 -0
  165. package/dist/guest/apps/resolvers.js +2 -0
  166. package/dist/guest/apps/shortcuts.d.ts +2 -0
  167. package/dist/guest/apps/shortcuts.js +1 -0
  168. package/dist/guest/apps/unpack.js +14 -4
  169. package/dist/guest/boot/boot.d.ts +45 -16
  170. package/dist/guest/boot/boot.js +325 -149
  171. package/dist/guest/boot/graph.d.ts +252 -0
  172. package/dist/guest/boot/graph.js +257 -0
  173. package/dist/guest/boot/guide-lines.d.ts +25 -0
  174. package/dist/guest/boot/guide-lines.js +41 -0
  175. package/dist/guest/boot/guide.d.ts +1 -4
  176. package/dist/guest/boot/guide.js +6 -8
  177. package/dist/guest/boot/runner.d.ts +77 -0
  178. package/dist/guest/boot/runner.js +215 -0
  179. package/dist/guest/browser/cdp.d.ts +71 -0
  180. package/dist/guest/browser/cdp.js +306 -0
  181. package/dist/guest/browser/comet.d.ts +28 -0
  182. package/dist/guest/browser/comet.js +155 -0
  183. package/dist/guest/daemon/project-provisioner.js +6 -1
  184. package/dist/guest/daemon/sessions.js +2 -1
  185. package/dist/guest/devtools/fivem.d.ts +1 -1
  186. package/dist/guest/devtools/fivem.js +243 -3
  187. package/dist/guest/entries/daemon.js +2 -0
  188. package/dist/guest/runtime/log.d.ts +12 -0
  189. package/dist/guest/runtime/log.js +29 -5
  190. package/dist/guest/runtime/pools.d.ts +24 -0
  191. package/dist/guest/runtime/pools.js +60 -0
  192. package/dist/guest/runtime/process.d.ts +4 -0
  193. package/dist/guest/runtime/process.js +38 -1
  194. package/dist/guest/runtime/status.d.ts +5 -1
  195. package/dist/guest/runtime/status.js +19 -0
  196. package/dist/guest/setup/addon-mcp.d.ts +1 -1
  197. package/dist/guest/setup/addon-mcp.js +52 -12
  198. package/dist/guest/setup/agent-addons.d.ts +3 -2
  199. package/dist/guest/setup/agent-addons.js +12 -3
  200. package/dist/guest/setup/environment.d.ts +1 -1
  201. package/dist/guest/setup/environment.js +25 -12
  202. package/dist/guest/setup/headroom.d.ts +8 -3
  203. package/dist/guest/setup/headroom.js +44 -15
  204. package/dist/guest/setup/path-plan.d.ts +28 -0
  205. package/dist/guest/setup/path-plan.js +69 -2
  206. package/dist/guest/setup/shell-path.d.ts +1 -1
  207. package/dist/guest/setup/shell-path.js +3 -3
  208. package/dist/guest/toolchains/fivem/artifacts.d.ts +48 -1
  209. package/dist/guest/toolchains/fivem/artifacts.js +97 -4
  210. package/dist/guest/toolchains/fivem/fivem.d.ts +32 -1
  211. package/dist/guest/toolchains/fivem/fivem.js +168 -3
  212. package/dist/guest/toolchains/fivem/scaffold.d.ts +35 -0
  213. package/dist/guest/toolchains/fivem/scaffold.js +105 -0
  214. package/dist/guest/toolchains/fivem/serve-plan.d.ts +34 -0
  215. package/dist/guest/toolchains/fivem/serve-plan.js +61 -0
  216. package/dist/guest/toolchains/installers.d.ts +6 -10
  217. package/dist/guest/toolchains/installers.js +4 -12
  218. package/dist/guest/toolchains/languages/go.js +1 -1
  219. package/dist/guest/toolchains/languages/node.js +2 -1
  220. package/dist/guest/toolchains/languages/php.d.ts +2 -0
  221. package/dist/guest/toolchains/languages/php.js +13 -1
  222. package/dist/guest/toolchains/languages/python-tools.js +1 -1
  223. package/dist/guest/toolchains/languages/ruby.js +1 -1
  224. package/dist/guest/toolchains/native/autosdk.d.ts +3 -0
  225. package/dist/guest/toolchains/native/autosdk.js +50 -0
  226. package/dist/guest/toolchains/native/binstall.js +1 -1
  227. package/dist/guest/toolchains/native/msvc/packages.js +10 -4
  228. package/dist/guest/toolchains/native/rust.d.ts +2 -0
  229. package/dist/guest/toolchains/native/rust.js +11 -4
  230. package/dist/guest/toolchains/native/unreal.d.ts +2 -0
  231. package/dist/guest/toolchains/native/unreal.js +19 -6
  232. package/dist/guest/toolchains/native/vcruntime.d.ts +2 -3
  233. package/dist/guest/toolchains/native/vcruntime.js +12 -7
  234. package/dist/guest/toolchains/native/visual-studio.d.ts +5 -2
  235. package/dist/guest/toolchains/native/visual-studio.js +127 -25
  236. package/dist/guest/toolchains/native/vs-request.d.ts +23 -0
  237. package/dist/guest/toolchains/native/vs-request.js +62 -1
  238. package/dist/guest/toolchains/not-yet.d.ts +1 -1
  239. package/dist/guest/toolchains/not-yet.js +3 -3
  240. package/dist/guest/toolchains/persisted.js +2 -7
  241. package/dist/guest/toolchains/plan.js +27 -11
  242. package/dist/guest/toolchains/scheduler.d.ts +2 -21
  243. package/dist/guest/toolchains/scheduler.js +7 -121
  244. package/dist/guest/toolchains/setup.d.ts +15 -2
  245. package/dist/guest/toolchains/setup.js +39 -20
  246. package/dist/guest/toolchains/signature.d.ts +5 -0
  247. package/dist/guest/toolchains/signature.js +22 -0
  248. package/dist/guest/toolchains/split.d.ts +28 -0
  249. package/dist/guest/toolchains/split.js +60 -0
  250. package/dist/guest/toolchains/steam/client.js +2 -1
  251. package/dist/guest/toolchains/step-scheduler.d.ts +51 -0
  252. package/dist/guest/toolchains/step-scheduler.js +147 -0
  253. package/dist/guest/toolchains/step.d.ts +13 -0
  254. package/dist/guest/toolchains/tools/git.js +18 -0
  255. package/dist/guest/vpn/openvpn.js +3 -4
  256. package/dist/guest/vpn/tunnel.d.ts +3 -0
  257. package/dist/guest/vpn/tunnel.js +10 -12
  258. package/dist/guest/vpn/vpn.js +6 -1
  259. package/dist/guest/vpn/wireguard.js +11 -4
  260. package/dist/host/accounts/deliver.js +7 -0
  261. package/dist/host/accounts/handoff.js +2 -6
  262. package/dist/host/accounts/index.d.ts +1 -1
  263. package/dist/host/accounts/index.js +1 -1
  264. package/dist/host/accounts/kinds/cfx.d.ts +1 -1
  265. package/dist/host/accounts/kinds/cfx.js +47 -4
  266. package/dist/host/accounts/kinds/comet.d.ts +2 -0
  267. package/dist/host/accounts/kinds/comet.js +6 -0
  268. package/dist/host/accounts/kinds/perplexity.d.ts +2 -0
  269. package/dist/host/accounts/kinds/perplexity.js +30 -0
  270. package/dist/host/accounts/leases.d.ts +9 -3
  271. package/dist/host/accounts/leases.js +13 -2
  272. package/dist/host/accounts/source.d.ts +7 -1
  273. package/dist/host/accounts/source.js +28 -1
  274. package/dist/host/accounts/sources.js +4 -0
  275. package/dist/host/agent-commands/commands.js +1 -1
  276. package/dist/host/agent-commands/forwarders.d.ts +14 -2
  277. package/dist/host/agent-commands/forwarders.js +31 -13
  278. package/dist/host/agent-commands/reconcile.d.ts +2 -1
  279. package/dist/host/agent-commands/reconcile.js +7 -8
  280. package/dist/host/agent-commands/user-path.d.ts +5 -0
  281. package/dist/host/agent-commands/user-path.js +13 -0
  282. package/dist/host/github/deliver.d.ts +1 -1
  283. package/dist/host/github/deliver.js +20 -1
  284. package/dist/host/github/index.d.ts +2 -1
  285. package/dist/host/github/index.js +1 -0
  286. package/dist/host/github/token.d.ts +13 -1
  287. package/dist/host/github/token.js +19 -2
  288. package/dist/host/github/verify.d.ts +27 -0
  289. package/dist/host/github/verify.js +61 -0
  290. package/dist/host/launch/hints/fivem.d.ts +3 -1
  291. package/dist/host/launch/hints/fivem.js +68 -2
  292. package/dist/host/launch/session-file.js +5 -0
  293. package/dist/host/launch/toolchains.d.ts +2 -1
  294. package/dist/host/launch/toolchains.js +5 -3
  295. package/dist/host/profile/accounts.js +2 -4
  296. package/dist/host/profile/claude-login.d.ts +3 -2
  297. package/dist/host/profile/claude-login.js +3 -13
  298. package/dist/host/vpn/index.d.ts +2 -1
  299. package/dist/host/vpn/index.js +2 -1
  300. package/dist/host/vpn/last.d.ts +28 -0
  301. package/dist/host/vpn/last.js +43 -0
  302. package/dist/host/vpn/login.d.ts +3 -1
  303. package/dist/host/vpn/login.js +17 -3
  304. package/dist/host/vpn/nordvpn.d.ts +2 -4
  305. package/dist/host/vpn/nordvpn.js +2 -24
  306. package/dist/runtime/agent.js +433 -90
  307. package/dist/runtime/daemon.js +3378 -1546
  308. package/dist/runtime/db.js +363 -90
  309. package/dist/runtime/main.js +5134 -2096
  310. package/dist/runtime/netproxy.js +308 -69
  311. package/dist/runtime/tool.js +2867 -1765
  312. package/dist/runtime/view.js +308 -69
  313. package/dist/selftest/agent-commands.test.js +45 -7
  314. package/dist/selftest/agent-paths.test.js +40 -13
  315. package/dist/selftest/agent-settings.test.d.ts +2 -0
  316. package/dist/selftest/agent-settings.test.js +94 -0
  317. package/dist/selftest/agents-web.test.d.ts +2 -0
  318. package/dist/selftest/agents-web.test.js +647 -0
  319. package/dist/selftest/app.test.js +7 -3
  320. package/dist/selftest/boot-runner.test.d.ts +2 -0
  321. package/dist/selftest/boot-runner.test.js +456 -0
  322. package/dist/selftest/channel.test.js +15 -0
  323. package/dist/selftest/cli.test.js +4 -0
  324. package/dist/selftest/fivem.test.js +249 -3
  325. package/dist/selftest/github.test.js +94 -9
  326. package/dist/selftest/guest-boot.test.js +3 -0
  327. package/dist/selftest/health.test.js +1 -1
  328. package/dist/selftest/index.js +10 -0
  329. package/dist/selftest/layout.test.js +5 -0
  330. package/dist/selftest/menu-coverage.test.d.ts +2 -0
  331. package/dist/selftest/menu-coverage.test.js +46 -0
  332. package/dist/selftest/menu-screens.js +37 -1
  333. package/dist/selftest/menu.test.js +5 -3
  334. package/dist/selftest/pc-installs.test.js +5 -0
  335. package/dist/selftest/persisted-installs.test.js +72 -0
  336. package/dist/selftest/service-accounts.test.js +3 -2
  337. package/dist/selftest/support/engine-golden.js +28 -1
  338. package/dist/selftest/support/fixtures.d.ts +15 -0
  339. package/dist/selftest/support/web-preview.d.ts +34 -1
  340. package/dist/selftest/support/web-preview.js +21 -18
  341. package/dist/selftest/toolchains.test.js +23 -1
  342. package/dist/selftest/ui-text.test.d.ts +7 -0
  343. package/dist/selftest/ui-text.test.js +300 -0
  344. package/dist/selftest/vpn.test.js +51 -3
  345. package/dist/shared/accounts/anthropic.d.ts +5 -0
  346. package/dist/shared/accounts/anthropic.js +15 -0
  347. package/dist/shared/accounts/index.d.ts +3 -0
  348. package/dist/shared/accounts/index.js +3 -0
  349. package/dist/shared/accounts/kinds/comet.d.ts +12 -0
  350. package/dist/shared/accounts/kinds/comet.js +64 -0
  351. package/dist/shared/accounts/kinds/perplexity.d.ts +8 -0
  352. package/dist/shared/accounts/kinds/perplexity.js +37 -0
  353. package/dist/shared/accounts/kinds.d.ts +24 -5
  354. package/dist/shared/accounts/kinds.js +86 -4
  355. package/dist/shared/accounts/payloads.d.ts +81 -0
  356. package/dist/shared/accounts/payloads.js +39 -1
  357. package/dist/shared/apps/agent-addons.d.ts +33 -5
  358. package/dist/shared/apps/agent-addons.js +95 -3
  359. package/dist/shared/apps/catalogue-agents-web.d.ts +14 -0
  360. package/dist/shared/apps/catalogue-agents-web.js +112 -0
  361. package/dist/shared/apps/catalogue-modding.js +32 -1
  362. package/dist/shared/apps/catalogue.d.ts +27 -3
  363. package/dist/shared/apps/catalogue.js +2 -1
  364. package/dist/shared/apps/index.d.ts +3 -1
  365. package/dist/shared/apps/index.js +3 -1
  366. package/dist/shared/channel/schema.d.ts +40 -3
  367. package/dist/shared/channel/schema.js +9 -0
  368. package/dist/shared/channel/secrets.d.ts +19 -0
  369. package/dist/shared/concurrency/index.d.ts +3 -0
  370. package/dist/shared/concurrency/index.js +3 -0
  371. package/dist/shared/concurrency/installer-retry.d.ts +6 -0
  372. package/dist/shared/concurrency/installer-retry.js +10 -0
  373. package/dist/shared/concurrency/limiter.d.ts +19 -0
  374. package/dist/shared/concurrency/limiter.js +67 -0
  375. package/dist/shared/concurrency/pools.d.ts +7 -0
  376. package/dist/shared/concurrency/pools.js +9 -0
  377. package/dist/shared/download/archive.d.ts +2 -0
  378. package/dist/shared/download/archive.js +11 -1
  379. package/dist/shared/download/bounded-fetch.d.ts +13 -0
  380. package/dist/shared/download/bounded-fetch.js +40 -0
  381. package/dist/shared/download/downloader.d.ts +5 -0
  382. package/dist/shared/download/downloader.js +50 -38
  383. package/dist/shared/download/index.d.ts +2 -1
  384. package/dist/shared/download/index.js +2 -1
  385. package/dist/shared/io/disk.d.ts +9 -0
  386. package/dist/shared/io/disk.js +19 -0
  387. package/dist/shared/io/index.d.ts +1 -0
  388. package/dist/shared/io/index.js +1 -0
  389. package/dist/shared/readiness.d.ts +9 -0
  390. package/dist/shared/readiness.js +11 -0
  391. package/dist/shared/signer.d.ts +24 -0
  392. package/dist/shared/signer.js +15 -0
  393. package/dist/shared/vpn/failure.d.ts +10 -0
  394. package/dist/shared/vpn/failure.js +28 -0
  395. package/dist/sync/watcher.js +2 -0
  396. package/dist/web/index.html +1 -1
  397. package/dist/web/{main-GVZWWP4I.js → main-CCILLX2M.js} +75 -74
  398. package/native/csharp/HcsHost/AssemblyInfo.cs +3 -3
  399. package/native/csharp/HostTools/AssemblyInfo.cs +3 -3
  400. package/native/csharp/HostTools/Program.cs +14 -1
  401. package/native/csharp/HostTools/UserPath.cs +17 -0
  402. package/native/csharp/StorageHelper/AssemblyInfo.cs +3 -3
  403. package/native/scripts/edit-user-path.ps1 +6 -2
  404. package/package.json +1 -1
  405. package/sandbox/addons/browser-use-mcp/requirements.in +1 -0
  406. package/sandbox/addons/browser-use-mcp/requirements.txt +2350 -0
  407. package/sandbox/addons/chrome-devtools-mcp/package-lock.json +38 -0
  408. package/sandbox/addons/chrome-devtools-mcp/package.json +7 -0
  409. package/sandbox/addons/comet-mcp/package-lock.json +1277 -0
  410. package/sandbox/addons/comet-mcp/package.json +7 -0
  411. package/sandbox/addons/perplexity-mcp/package-lock.json +1655 -0
  412. package/sandbox/addons/perplexity-mcp/package.json +7 -0
  413. package/sandbox/scripts/add-firewall-port.ps1 +18 -4
  414. package/sandbox/scripts/get-signature.ps1 +13 -0
  415. package/sandbox/scripts/set-machine-environment.ps1 +30 -15
  416. package/sandbox/templates/fivem/README.txt +6 -2
  417. package/sandbox/templates/fivem/cs/Client/Client.csproj +15 -0
  418. package/sandbox/templates/fivem/cs/Client/ClientMain.cs +20 -0
  419. package/sandbox/templates/fivem/cs/Server/Server.csproj +14 -0
  420. package/sandbox/templates/fivem/cs/Server/ServerMain.cs +20 -0
  421. package/sandbox/templates/fivem/cs/fxmanifest.lua +11 -0
  422. package/sandbox/templates/fivem/js/client.js +12 -0
  423. package/sandbox/templates/fivem/js/fxmanifest.lua +9 -0
  424. package/sandbox/templates/fivem/js/server.js +6 -0
  425. package/sandbox/templates/fivem/lua/client.lua +8 -0
  426. package/sandbox/templates/fivem/lua/fxmanifest.lua +10 -0
  427. package/sandbox/templates/fivem/lua/server.lua +6 -0
  428. package/sandbox/templates/fivem/server.cfg +37 -0
  429. package/sandbox/templates/fivem/ts/build.js +17 -0
  430. package/sandbox/templates/fivem/ts/fxmanifest.lua +9 -0
  431. package/sandbox/templates/fivem/ts/package.json +16 -0
  432. package/sandbox/templates/fivem/ts/src/client/client.ts +12 -0
  433. package/sandbox/templates/fivem/ts/src/client/tsconfig.json +13 -0
  434. package/sandbox/templates/fivem/ts/src/server/server.ts +6 -0
  435. package/sandbox/templates/fivem/ts/src/server/tsconfig.json +13 -0
  436. package/schemas/config.schema.json +120 -27
  437. package/schemas/sandbox-config.schema.json +45 -14
  438. package/sandbox/scripts/get-signer.ps1 +0 -8
@@ -0,0 +1,28 @@
1
+ import { type CometPayload } from '../../shared/accounts/kinds/comet.js';
2
+ import { type DevToolsEndpoint } from './cdp.js';
3
+ /** The port comet-mcp looks for (it connects to a Comet already listening there). */
4
+ export declare const COMET_MCP_PORT = 9222;
5
+ /** The addresses whose cookies are read back (their cookies and the parent domain's). */
6
+ export declare const COMET_COOKIE_URLS: readonly string[];
7
+ /** Comet's profile: on the sandbox's own disk, wiped with it. */
8
+ export declare function cometProfileDir(): string;
9
+ /** Where `--install --silent` puts Comet (the fallback when the installer cannot be unpacked). */
10
+ export declare function installedCometExe(): string;
11
+ /** comet.exe: the portable copy in tools\apps\comet, else the installed one, else null. */
12
+ export declare function cometExe(): string | null;
13
+ /** How Comet is started here: this profile, DevTools on 127.0.0.1 (`port` 0: any free port, written to the profile). */
14
+ export declare function cometLaunchArgs(port: number, profile?: string): string[];
15
+ /** The same as one command line for a shortcut (quoted where it has spaces). */
16
+ export declare function cometShortcutArgs(port: number, profile?: string): string;
17
+ /** Where a Comet running with this profile listens, from its DevToolsActivePort file; null when there is none. */
18
+ export declare function devToolsEndpoint(profile?: string): DevToolsEndpoint | null;
19
+ /**
20
+ * The sign-in the running Comet holds now (perplexity.ai's own cookies, asked of one of its pages), or null when
21
+ * Comet is not running with this profile, has no page open, or holds no sign-in. Never asks for another site's cookies.
22
+ */
23
+ export declare function readCometSignIn(profile?: string): Promise<CometPayload | null>;
24
+ /**
25
+ * Writes the sign-in into Comet's profile: into the Comet running with it, or into one started without a window for
26
+ * this and closed again (Comet saves its cookies as it closes). Resolves with the number of cookies written.
27
+ */
28
+ export declare function restoreCometSignIn(exe: string, payload: CometPayload, profile?: string): Promise<number>;
@@ -0,0 +1,155 @@
1
+ // Comet (Perplexity's Chromium browser) in this sandbox: where it is, the profile it runs with, and its sign-in over
2
+ // the DevTools port. The profile is on the sandbox's own disk (%LOCALAPPDATA%\AgentSandbox\comet-profile): a profile
3
+ // on the data folder fails (rename-over is refused there, and its cookie key is sealed to this sandbox's Windows user).
4
+ // The sign-in travels instead as the allow-listed perplexity.ai cookies: read with Network.getCookies for those
5
+ // addresses only (other sites' cookies are never asked for), written back with Storage.setCookies. DevTools listen
6
+ // on 127.0.0.1 only. No runtime imports: the sign-in adapter and the self-test load this file.
7
+ import { spawn } from 'node:child_process';
8
+ import fs from 'node:fs';
9
+ import path from 'node:path';
10
+ import { cometPayloadFromCookies, cookiesToRestore } from '../../shared/accounts/kinds/comet.js';
11
+ import { readBoundedFile } from '../../shared/io/bounded.js';
12
+ import { localAppData } from '../accounts/adapter.js';
13
+ import { findExe } from '../apps/find-exe.js';
14
+ import { tool } from '../toolchains/tool-env.js';
15
+ import { CdpConnection, parseDevToolsActivePort } from './cdp.js';
16
+ /** The port comet-mcp looks for (it connects to a Comet already listening there). */
17
+ export const COMET_MCP_PORT = 9222;
18
+ /** The addresses whose cookies are read back (their cookies and the parent domain's). */
19
+ export const COMET_COOKIE_URLS = ['https://www.perplexity.ai/', 'https://perplexity.ai/'];
20
+ const START_MS = 30_000;
21
+ const STOP_MS = 15_000;
22
+ /** Comet's profile: on the sandbox's own disk, wiped with it. */
23
+ export function cometProfileDir() {
24
+ return path.join(localAppData(), 'AgentSandbox', 'comet-profile');
25
+ }
26
+ /** Where `--install --silent` puts Comet (the fallback when the installer cannot be unpacked). */
27
+ export function installedCometExe() {
28
+ return path.join(localAppData(), 'Perplexity', 'Comet', 'Application', 'comet.exe');
29
+ }
30
+ /** comet.exe: the portable copy in tools\apps\comet, else the installed one, else null. */
31
+ export function cometExe() {
32
+ const portable = findExe(tool('apps', 'comet'), 'comet.exe');
33
+ if (portable)
34
+ return portable;
35
+ return fs.existsSync(installedCometExe()) ? installedCometExe() : null;
36
+ }
37
+ /** How Comet is started here: this profile, DevTools on 127.0.0.1 (`port` 0: any free port, written to the profile). */
38
+ export function cometLaunchArgs(port, profile = cometProfileDir()) {
39
+ return [
40
+ '--user-data-dir=' + profile,
41
+ '--remote-debugging-port=' + port,
42
+ '--remote-debugging-address=127.0.0.1',
43
+ '--no-first-run',
44
+ '--no-default-browser-check',
45
+ ];
46
+ }
47
+ /** The same as one command line for a shortcut (quoted where it has spaces). */
48
+ export function cometShortcutArgs(port, profile = cometProfileDir()) {
49
+ return cometLaunchArgs(port, profile)
50
+ .map((a) => (/\s/.test(a) ? '"' + a + '"' : a))
51
+ .join(' ');
52
+ }
53
+ /** Where a Comet running with this profile listens, from its DevToolsActivePort file; null when there is none. */
54
+ export function devToolsEndpoint(profile = cometProfileDir()) {
55
+ const bytes = readBoundedFile(path.join(profile, 'DevToolsActivePort'), 512);
56
+ return bytes ? parseDevToolsActivePort(bytes.toString('utf8')) : null;
57
+ }
58
+ /** A connection to the Comet running with this profile, or null when none answers. */
59
+ async function connect(profile) {
60
+ const endpoint = devToolsEndpoint(profile);
61
+ if (!endpoint)
62
+ return null;
63
+ try {
64
+ return await CdpConnection.open(endpoint, 5000);
65
+ }
66
+ catch {
67
+ return null; // Not running (a file left by the last start), or not Comet.
68
+ }
69
+ }
70
+ /**
71
+ * The sign-in the running Comet holds now (perplexity.ai's own cookies, asked of one of its pages), or null when
72
+ * Comet is not running with this profile, has no page open, or holds no sign-in. Never asks for another site's cookies.
73
+ */
74
+ export async function readCometSignIn(profile = cometProfileDir()) {
75
+ const cdp = await connect(profile);
76
+ if (!cdp)
77
+ return null;
78
+ try {
79
+ const { targetInfos = [] } = await cdp.call('Target.getTargets');
80
+ const page = targetInfos.find((t) => t.type === 'page' && typeof t.targetId === 'string');
81
+ if (!page)
82
+ return null;
83
+ const { sessionId } = await cdp.call('Target.attachToTarget', {
84
+ targetId: page.targetId,
85
+ flatten: true,
86
+ });
87
+ try {
88
+ const { cookies = [] } = await cdp.call('Network.getCookies', { urls: [...COMET_COOKIE_URLS] }, { sessionId });
89
+ return cometPayloadFromCookies(Array.isArray(cookies) ? cookies : [], Math.floor(Date.now() / 1000));
90
+ }
91
+ finally {
92
+ await cdp.call('Target.detachFromTarget', { sessionId }).catch(() => undefined);
93
+ }
94
+ }
95
+ finally {
96
+ cdp.close();
97
+ }
98
+ }
99
+ /** Waits for a process to end (true), or gives up after `ms` (false). */
100
+ function exited(child, ms) {
101
+ if (child.exitCode !== null)
102
+ return Promise.resolve(true);
103
+ return new Promise((resolve) => {
104
+ const timer = setTimeout(() => resolve(false), ms);
105
+ child.once('exit', () => {
106
+ clearTimeout(timer);
107
+ resolve(true);
108
+ });
109
+ });
110
+ }
111
+ /** Comet started without a window on this profile, answering on its DevTools port; throws when it does not. */
112
+ async function startHidden(exe, profile) {
113
+ fs.mkdirSync(profile, { recursive: true });
114
+ fs.rmSync(path.join(profile, 'DevToolsActivePort'), { force: true });
115
+ const child = spawn(exe, [...cometLaunchArgs(0, profile), '--headless=new', 'about:blank'], {
116
+ stdio: 'ignore',
117
+ windowsHide: true,
118
+ });
119
+ child.on('error', () => undefined); // Reported below as "did not start".
120
+ const deadline = Date.now() + START_MS;
121
+ while (Date.now() < deadline && child.exitCode === null) {
122
+ const cdp = await connect(profile);
123
+ if (cdp)
124
+ return { cdp, child };
125
+ await new Promise((r) => setTimeout(r, 250));
126
+ }
127
+ child.kill();
128
+ throw new Error('Comet did not start (no DevTools answer within ' + START_MS / 1000 + ' s)');
129
+ }
130
+ /**
131
+ * Writes the sign-in into Comet's profile: into the Comet running with it, or into one started without a window for
132
+ * this and closed again (Comet saves its cookies as it closes). Resolves with the number of cookies written.
133
+ */
134
+ export async function restoreCometSignIn(exe, payload, profile = cometProfileDir()) {
135
+ const cookies = cookiesToRestore(payload, Math.floor(Date.now() / 1000));
136
+ if (!cookies.length)
137
+ return 0;
138
+ const running = await connect(profile);
139
+ const started = running ? null : await startHidden(exe, profile);
140
+ const cdp = running ?? started.cdp;
141
+ try {
142
+ await cdp.call('Storage.setCookies', { cookies });
143
+ if (started) {
144
+ await cdp.call('Browser.close').catch(() => undefined);
145
+ if (!(await exited(started.child, STOP_MS)))
146
+ started.child.kill();
147
+ }
148
+ return cookies.length;
149
+ }
150
+ finally {
151
+ cdp.close();
152
+ if (started && started.child.exitCode === null)
153
+ started.child.kill();
154
+ }
155
+ }
@@ -54,7 +54,12 @@ function refreshGuide(projects) {
54
54
  const boot = readBootEnv();
55
55
  if (!boot)
56
56
  return;
57
- const list = projects.map((p) => ({ guest: p.spec.workspace, host: p.spec.workspaceHost }));
57
+ const list = projects.map((p) => ({
58
+ guest: p.spec.workspace,
59
+ host: p.spec.workspaceHost,
60
+ name: p.spec.name,
61
+ tools: p.summary,
62
+ }));
58
63
  try {
59
64
  writeGuides(boot.summary, boot.lan, list);
60
65
  }
@@ -18,6 +18,7 @@ import { freePort } from '../runtime/ports.js';
18
18
  import { primaryProject } from '../boot/project-status.js';
19
19
  import { endLeftoverTree, ensurePtyHost, ptyHostLogTail, recordedTrees, startPtyHost, waitForPtyHost, } from '../sessions/pty-host.js';
20
20
  import { agents } from '../agents/agent-installer.js';
21
+ import { agentArguments } from '../agents/agent-files.js';
21
22
  import { saveClaudeMem } from '../setup/claude-mem.js';
22
23
  import { saveLocalState } from '../agents/local-state.js';
23
24
  import { projectHooks, runHooks, runHooksAsync } from '../setup/hooks.js';
@@ -108,7 +109,7 @@ const agentProgram = async (req, env, say) => {
108
109
  say('Preparing ' + req.harness);
109
110
  await agents.provision(req.harness, harness, env, false);
110
111
  const launch = agents.resolveLaunch(req.harness, harness);
111
- const base = [...launch.args, ...harness.arguments];
112
+ const base = [...launch.args, ...agentArguments(req.harness, harness, session.codex)];
112
113
  return {
113
114
  command: commandLine(launch.file, [...base, ...req.args]),
114
115
  restartCommand: commandLine(launch.file, [...base, ...(harness.resumeArguments ?? [])]),
@@ -1,2 +1,2 @@
1
- import { type DevTool } from './devtool.js';
1
+ import type { DevTool } from './devtool.js';
2
2
  export declare const fivemTool: DevTool;
@@ -1,7 +1,247 @@
1
- // sbx-fivem: start the FiveM / RedM server, pick a server build, make a new resource. Not available yet.
2
- import { notAvailableYet } from './devtool.js';
1
+ // sbx-fivem: start the FiveM / RedM server (plain or with txAdmin), make a server folder or a new resource, pick a
2
+ // server build, get the natives list. The Cfx.re key reaches FXServer only through +exec of its cfg on the sandbox's
3
+ // own disk; it is never written into the project.
4
+ import fs from 'node:fs';
5
+ import os from 'node:os';
6
+ import path from 'node:path';
7
+ import { spawnSync } from 'node:child_process';
8
+ import { downloader, spawnAsync } from '../../shared/download/index.js';
9
+ import { errMsg } from '../../core/util/errors.js';
10
+ import { toolsDir } from '../runtime/paths.js';
11
+ import { runScript } from '../runtime/process.js';
12
+ import { portOpen } from '../runtime/ports.js';
13
+ import { session } from '../runtime/session.js';
14
+ import { fetchChannels, CHANNELS } from '../toolchains/fivem/artifacts.js';
15
+ import { artifactDir, rememberArtifact, chosenArtifact, installArtifact, installedBuilds, resolveArtifact, secretsCfg, servingBuildDir, txDataDir, } from '../toolchains/fivem/fivem.js';
16
+ import { fivemTemplatesDir, initServerFolder, resourceHome, RESOURCE_LANGS, scaffoldResource, withEnsure, } from '../toolchains/fivem/scaffold.js';
17
+ import { GAME_PORT, servePlan, TXADMIN_PORT } from '../toolchains/fivem/serve-plan.js';
18
+ const USAGE = [
19
+ 'Usage:',
20
+ ' sbx-fivem serve [--txadmin | --no-txadmin] [--dir <server folder>] start the server (default: this folder)',
21
+ ' sbx-fivem init [--dir <folder>] a server.cfg (no keys in it) and resources\\[local]',
22
+ ' sbx-fivem new <name> --lua | --js | --ts | --cs [--dir <folder>] a new resource',
23
+ ' sbx-fivem artifact list server builds: recommended, latest ..., and the installed ones',
24
+ ' sbx-fivem artifact use <recommended|optional|latest|build> install a build and use it from now on',
25
+ ' sbx-fivem natives download the natives list (JSON) for the game',
26
+ ].join('\n');
27
+ const NATIVES = {
28
+ gta5: ['https://runtime.fivem.net/doc/natives.json', 'https://runtime.fivem.net/doc/natives_cfx.json'],
29
+ rdr3: [
30
+ 'https://raw.githubusercontent.com/alloc8or/rdr3-nativedb-data/master/natives.json',
31
+ 'https://runtime.fivem.net/doc/natives_cfx.json',
32
+ ],
33
+ };
34
+ const config = () => session.toolchains.fivem;
35
+ const game = () => config().game;
36
+ function parse(args) {
37
+ const positionals = [];
38
+ const flags = new Set();
39
+ let dir;
40
+ for (let i = 0; i < args.length; i++) {
41
+ const a = args[i];
42
+ if (a === '--dir') {
43
+ dir = args[++i];
44
+ if (!dir)
45
+ throw new Error('--dir needs a folder');
46
+ }
47
+ else if (a.startsWith('--'))
48
+ flags.add(a.slice(2));
49
+ else
50
+ positionals.push(a);
51
+ }
52
+ return { positionals, flags, dir: dir === undefined ? undefined : path.resolve(dir) };
53
+ }
54
+ /** The sandbox's IPv4 addresses the PC can use (its Hyper-V network). */
55
+ function addresses() {
56
+ return Object.values(os.networkInterfaces())
57
+ .flat()
58
+ .filter((a) => Boolean(a && a.family === 'IPv4' && !a.internal))
59
+ .map((a) => a.address);
60
+ }
61
+ /** The newest MariaDB client in tools\mariadb (databases.mysql installs it there). */
62
+ function mariadbClient() {
63
+ const root = path.join(toolsDir, 'mariadb');
64
+ let versions = [];
65
+ try {
66
+ versions = fs.readdirSync(root).sort().reverse();
67
+ }
68
+ catch {
69
+ return null;
70
+ }
71
+ for (const v of versions)
72
+ for (const exe of ['mariadb.exe', 'mysql.exe']) {
73
+ const file = path.join(root, v, 'bin', exe);
74
+ if (fs.existsSync(file))
75
+ return file;
76
+ }
77
+ return null;
78
+ }
79
+ /** The port of the sandbox's running MariaDB, with the "fivem" database made; null when it does not run. */
80
+ async function mysqlForServer() {
81
+ const own = (session.databases ?? []).find((p) => p.database === 'mysql');
82
+ const plan = own ?? (session.databaseCatalog ?? []).find((p) => p.database === 'mysql');
83
+ if (!plan)
84
+ return null;
85
+ if (!(await portOpen(plan.port))) {
86
+ if (own)
87
+ console.log('MySQL (MariaDB) is not running: sbx-db start mysql, then serve again for oxmysql.');
88
+ return null;
89
+ }
90
+ const client = mariadbClient();
91
+ if (client)
92
+ spawnSync(client, ['-h', '127.0.0.1', '-P', String(plan.port), '-u', 'root', '-e', 'CREATE DATABASE IF NOT EXISTS fivem'], { stdio: 'ignore', windowsHide: true });
93
+ return plan.port;
94
+ }
95
+ function openPorts(ports) {
96
+ for (const p of ports)
97
+ try {
98
+ runScript('add-firewall-port.ps1', ['-Port', String(p.port), '-Protocol', p.protocol, '-Name', p.name]);
99
+ }
100
+ catch (e) {
101
+ console.error('Could not open port ' + p.port + ' in the sandbox firewall (' + errMsg(e) + '): the PC may not reach it.');
102
+ }
103
+ }
104
+ async function serve(p) {
105
+ const build = servingBuildDir();
106
+ if (!build)
107
+ throw new Error('no FXServer build is installed: run sbx-fivem artifact use recommended');
108
+ const txAdmin = p.flags.has('txadmin') ? true : p.flags.has('no-txadmin') ? false : config().txAdmin;
109
+ const serverDir = p.dir ?? process.cwd();
110
+ if (!txAdmin && !fs.existsSync(path.join(serverDir, 'server.cfg')))
111
+ throw new Error('no server.cfg in ' + serverDir + ': run sbx-fivem init there (or serve --txadmin)');
112
+ const secrets = secretsCfg();
113
+ if (!secrets)
114
+ console.log('No Cfx.re key in this sandbox: on your PC run sandbox account login cfx and sandbox config set accounts.cfx.share true, then restart the sandbox.' +
115
+ (txAdmin ? '' : ' FXServer stops without one.'));
116
+ fs.mkdirSync(txDataDir(), { recursive: true });
117
+ const plan = servePlan({
118
+ artifactDir: build,
119
+ serverDir,
120
+ game: game(),
121
+ txAdmin,
122
+ secretsCfg: secrets,
123
+ txData: txDataDir(),
124
+ mysqlPort: await mysqlForServer(),
125
+ });
126
+ openPorts(plan.ports);
127
+ const ips = addresses();
128
+ const where = ips.length ? ips : ['<the sandbox address>'];
129
+ console.log('FXServer ' + path.basename(build) + (game() === 'rdr3' ? ' (RedM)' : '') + ' from ' + plan.cwd);
130
+ console.log('From your PC: in the ' +
131
+ (game() === 'rdr3' ? 'RedM' : 'FiveM') +
132
+ ' client press F8 and type: connect ' +
133
+ where[0] +
134
+ ':' +
135
+ GAME_PORT);
136
+ if (txAdmin) {
137
+ console.log('txAdmin: http://' + where[0] + ':' + TXADMIN_PORT + ' in a browser on your PC (its PIN is printed below).');
138
+ if (secrets)
139
+ console.log('Keep the key out of txData: in the server.cfg txAdmin makes, replace the sv_licenseKey line with: exec "' +
140
+ secrets.split('\\').join('/') +
141
+ '"');
142
+ }
143
+ return spawnAsync(plan.exe, plan.args, { cwd: plan.cwd, stdio: 'inherit', env: { ...process.env, ...plan.env } });
144
+ }
145
+ function init(p) {
146
+ const dir = p.dir ?? process.cwd();
147
+ const wrote = initServerFolder(fivemTemplatesDir(), dir, path.basename(dir), game());
148
+ console.log(wrote.length ? 'Wrote ' + wrote.join(', ') + ' in ' + dir : dir + ' already has a server.cfg.');
149
+ console.log('Next: sbx-fivem new <name> --lua (or --js, --ts, --cs), then sbx-fivem serve');
150
+ return 0;
151
+ }
152
+ const NEXT = {
153
+ lua: '',
154
+ js: '',
155
+ ts: 'npm install, then npm run build (npm run watch keeps building) in ',
156
+ cs: 'dotnet publish -c Release in Client and in Server of ',
157
+ };
158
+ function newResource(p) {
159
+ const [name] = p.positionals;
160
+ const langs = RESOURCE_LANGS.filter((l) => p.flags.has(l));
161
+ if (!name || langs.length !== 1)
162
+ throw new Error('give a name and one of --lua, --js, --ts, --cs\n' + USAGE);
163
+ const folder = p.dir ?? process.cwd();
164
+ const into = resourceHome(folder);
165
+ const made = scaffoldResource({ templates: fivemTemplatesDir(), lang: langs[0], name, into, game: game() });
166
+ console.log('Made ' + made.dir + ' (' + made.files.length + ' files)');
167
+ const cfg = path.join(folder, 'server.cfg');
168
+ if (fs.existsSync(cfg)) {
169
+ const next = withEnsure(fs.readFileSync(cfg, 'utf8'), name);
170
+ if (next !== null) {
171
+ fs.writeFileSync(cfg, next);
172
+ console.log('Added ensure ' + name + ' to ' + cfg);
173
+ }
174
+ }
175
+ else
176
+ console.log('Add ensure ' + name + ' to your server.cfg.');
177
+ if (NEXT[langs[0]])
178
+ console.log('Build it: ' + NEXT[langs[0]] + made.dir);
179
+ console.log('A running server picks it up with: refresh, then ensure ' + name + ' (in the server console).');
180
+ return 0;
181
+ }
182
+ async function artifact(p) {
183
+ const [, action, value] = p.positionals;
184
+ const installed = installedBuilds();
185
+ const chosen = chosenArtifact(config().artifact);
186
+ if (action === 'list' || action === undefined) {
187
+ try {
188
+ const channels = await fetchChannels();
189
+ for (const c of CHANNELS) {
190
+ const a = channels[c];
191
+ console.log(c.padEnd(12) +
192
+ String(a.build).padEnd(8) +
193
+ (a.txAdmin ? 'txAdmin ' + a.txAdmin : '').padEnd(16) +
194
+ (installed.includes(a.build) ? 'installed' : ''));
195
+ }
196
+ }
197
+ catch (e) {
198
+ console.log('Could not look up the builds online (' + errMsg(e) + ').');
199
+ }
200
+ console.log('Installed: ' + (installed.length ? installed.join(', ') : 'none') + ' (tools\\fivem\\artifacts)');
201
+ console.log('In use: ' +
202
+ (chosen.chosen
203
+ ? chosen.setting + ' (build ' + chosen.build + ', chosen with artifact use)'
204
+ : config().artifact + ' (toolchains.fivem.artifact)'));
205
+ return 0;
206
+ }
207
+ if (action !== 'use' || !value)
208
+ throw new Error(USAGE);
209
+ const a = await resolveArtifact(value, true);
210
+ const done = await installArtifact(a, config().keepVersions);
211
+ rememberArtifact(value === config().artifact ? null : { artifact: value, build: a.build });
212
+ console.log('FXServer build ' + a.build + (done.fresh ? ' installed' : ' was there') + ' in ' + artifactDir(a.build));
213
+ console.log('sbx-fivem serve uses it from now on' + (value === config().artifact ? '' : ', and so do the next sandboxes') + '.');
214
+ return 0;
215
+ }
216
+ async function natives() {
217
+ const dir = path.join(toolsDir, 'fivem', 'natives', game());
218
+ for (const url of NATIVES[game()]) {
219
+ const file = path.join(dir, path.basename(new URL(url).pathname));
220
+ await downloader.file(url, file);
221
+ console.log(file);
222
+ }
223
+ return 0;
224
+ }
3
225
  export const fivemTool = {
4
226
  name: 'fivem',
5
227
  summary: 'start the FiveM / RedM server, pick a server build, make a new resource',
6
- run: () => notAvailableYet('fivem'),
228
+ async run(args) {
229
+ const p = parse(args);
230
+ switch (p.positionals[0]) {
231
+ case 'serve':
232
+ return serve(p);
233
+ case 'init':
234
+ return init(p);
235
+ case 'new':
236
+ return newResource({ ...p, positionals: p.positionals.slice(1) });
237
+ case 'artifact':
238
+ case 'artifacts':
239
+ return artifact(p);
240
+ case 'natives':
241
+ return natives();
242
+ default:
243
+ console.log(USAGE);
244
+ return p.positionals[0] === undefined || p.positionals[0] === 'help' ? 0 : 2;
245
+ }
246
+ },
7
247
  };
@@ -7,6 +7,7 @@ import { startProcessCollector } from '../audit/process-audit.js';
7
7
  import { safely } from '../daemon/state.js';
8
8
  import { log, warn } from '../runtime/log.js';
9
9
  import { adoptBootSecrets } from '../runtime/secrets.js';
10
+ import { installPools } from '../runtime/pools.js';
10
11
  import { errMsg } from '../../core/util/errors.js';
11
12
  import { Daemon } from '../daemon/daemon.js';
12
13
  import { startLiveFolders } from '../daemon/live.js';
@@ -16,6 +17,7 @@ import { startAccountWatch } from '../daemon/accounts.js';
16
17
  import { startHeartbeat } from '../daemon/heartbeat.js';
17
18
  process.on('uncaughtException', (e) => warn('daemon: unexpected error (continuing): ' + (e.stack ?? errMsg(e))));
18
19
  process.on('unhandledRejection', (e) => warn('daemon: unexpected error (continuing): ' + errMsg(e)));
20
+ installPools();
19
21
  const liveKey = adoptBootSecrets();
20
22
  log('Session daemon started (pid ' + process.pid + ').');
21
23
  safely('live folders', () => startLiveFolders(liveKey));
@@ -1,3 +1,15 @@
1
+ /** Who is logging: the task title (a prefix while several tasks run) and whether the console stays silent. */
2
+ export interface LogContext {
3
+ readonly prefix?: () => string;
4
+ /** File only: nothing may print once the first session owns the console. */
5
+ readonly quiet?: boolean;
6
+ }
7
+ /** Runs `work` so that everything it logs (also after awaits) carries `ctx`. */
8
+ export declare function withLogContext<T>(ctx: LogContext, work: () => T): T;
9
+ /** Runs `work` logging to the file only. */
10
+ export declare function runQuiet<T>(work: () => T): T;
11
+ /** One line of the file: an ISO timestamp first (the console shows no times). */
12
+ export declare function fileLine(message: string, at?: Date): string;
1
13
  export declare function log(message: string): void;
2
14
  export declare function warn(message: string): void;
3
15
  export declare const logPath: string;
@@ -1,22 +1,46 @@
1
1
  import fs from 'node:fs';
2
2
  import path from 'node:path';
3
+ import { AsyncLocalStorage } from 'node:async_hooks';
3
4
  import { logsDir } from './paths.js';
4
5
  fs.mkdirSync(logsDir, { recursive: true });
5
6
  const logFile = path.join(logsDir, (process.env.AGENT_LOG_PREFIX ?? 'guest') + '-' + new Date().toISOString().replace(/[:.]/g, '-') + '.log');
7
+ const context = new AsyncLocalStorage();
8
+ /** Runs `work` so that everything it logs (also after awaits) carries `ctx`. */
9
+ export function withLogContext(ctx, work) {
10
+ return context.run(ctx, work);
11
+ }
12
+ /** Runs `work` logging to the file only. */
13
+ export function runQuiet(work) {
14
+ return context.run({ ...context.getStore(), quiet: true }, work);
15
+ }
16
+ /** One line of the file: an ISO timestamp first (the console shows no times). */
17
+ export function fileLine(message, at = new Date()) {
18
+ return at.toISOString() + ' ' + message;
19
+ }
6
20
  const append = (line) => {
7
21
  try {
8
- fs.appendFileSync(logFile, line + '\n');
22
+ fs.appendFileSync(logFile, fileLine(line) + '\n');
9
23
  }
10
24
  catch {
11
25
  /* logging must never break the run */
12
26
  }
13
27
  };
28
+ const tagged = (message, ctx) => {
29
+ const prefix = ctx?.prefix?.();
30
+ return prefix ? prefix + ' | ' + message : message;
31
+ };
14
32
  export function log(message) {
15
- console.log(message);
16
- append(message);
33
+ const ctx = context.getStore();
34
+ const line = tagged(message, ctx);
35
+ if (!ctx?.quiet)
36
+ console.log(line);
37
+ append(line);
17
38
  }
18
39
  export function warn(message) {
19
- console.warn('\x1b[33mWARNING: ' + message + '\x1b[0m');
20
- append('WARNING: ' + message);
40
+ const ctx = context.getStore();
41
+ const line = tagged(message, ctx);
42
+ if (!ctx?.quiet)
43
+ console.warn('\x1b[33mWARNING: ' + line + '\x1b[0m');
44
+ append('WARNING: ' + line);
21
45
  }
22
46
  export const logPath = logFile;
@@ -0,0 +1,24 @@
1
+ import { type SpawnOptions } from 'node:child_process';
2
+ import { heavy, installer, net } from '../../shared/concurrency/index.js';
3
+ export { net, heavy, installer };
4
+ /** Called at the start of the boot and of the daemon: the downloader and the extractor use the pools from then on. */
5
+ export declare function installPools(): void;
6
+ /** Lowers a process (and the children it starts from now on) to below-normal priority; best effort. */
7
+ export declare function belowNormal(pid: number | undefined): void;
8
+ export interface InstallerOptions {
9
+ /** Below-normal priority for the installer and what it starts (the background Visual Studio). */
10
+ readonly lowPriority?: boolean;
11
+ readonly cwd?: string;
12
+ readonly stdio?: 'ignore' | 'inherit';
13
+ /** Tests: how long to wait between tries. */
14
+ readonly waitMs?: number;
15
+ }
16
+ /**
17
+ * Runs an installer in the one installer slot and starts it again while another process holds the Windows Installer
18
+ * lock (exit 1618). Resolves with the exit code of the last try.
19
+ */
20
+ export declare function runInstaller(file: string, args: string[], o?: InstallerOptions): Promise<number>;
21
+ /** runInstaller that throws like execAsync when the installer fails. */
22
+ export declare function runInstallerChecked(file: string, args: string[], o?: InstallerOptions): Promise<void>;
23
+ /** execAsync for heavy local work (npm, uv, rustup ...): one of the two heavy slots. */
24
+ export declare function execHeavy(file: string, args: string[], options?: SpawnOptions): Promise<void>;
@@ -0,0 +1,60 @@
1
+ // The guest's work pools: network bodies, heavy local work and installers. A task takes one slot at the leaf (the
2
+ // call that downloads, unpacks or installs), never while it holds another: the limiter refuses nested pools.
3
+ import os from 'node:os';
4
+ import { spawn } from 'node:child_process';
5
+ import path from 'node:path';
6
+ import { heavy, installer, net, INSTALLER_WAIT_MS, installerRetry } from '../../shared/concurrency/index.js';
7
+ import { downloader, limitExtraction } from '../../shared/download/index.js';
8
+ import { log } from './log.js';
9
+ import { execAsync } from './process.js';
10
+ export { net, heavy, installer };
11
+ /** Called at the start of the boot and of the daemon: the downloader and the extractor use the pools from then on. */
12
+ export function installPools() {
13
+ downloader.limit = net;
14
+ limitExtraction(heavy);
15
+ }
16
+ const BELOW_NORMAL = os.constants.priority.PRIORITY_BELOW_NORMAL;
17
+ /** Lowers a process (and the children it starts from now on) to below-normal priority; best effort. */
18
+ export function belowNormal(pid) {
19
+ if (pid === undefined)
20
+ return;
21
+ try {
22
+ os.setPriority(pid, BELOW_NORMAL);
23
+ }
24
+ catch {
25
+ /* the process may have ended already; a normal priority only makes it a little slower to share the machine */
26
+ }
27
+ }
28
+ /**
29
+ * Runs an installer in the one installer slot and starts it again while another process holds the Windows Installer
30
+ * lock (exit 1618). Resolves with the exit code of the last try.
31
+ */
32
+ export async function runInstaller(file, args, o = {}) {
33
+ for (let attempt = 1;; attempt++) {
34
+ const code = await installer.run(() => new Promise((resolve, reject) => {
35
+ const child = spawn(file, args, {
36
+ stdio: o.stdio ?? 'ignore',
37
+ windowsHide: true,
38
+ ...(o.cwd ? { cwd: o.cwd } : {}),
39
+ });
40
+ if (o.lowPriority)
41
+ belowNormal(child.pid);
42
+ child.once('error', reject);
43
+ child.once('close', (c) => resolve(c ?? -1));
44
+ }));
45
+ if (!installerRetry(code, attempt))
46
+ return code;
47
+ log(path.basename(file) + ': another install is running; trying again in a moment (' + attempt + ')');
48
+ await new Promise((r) => setTimeout(r, o.waitMs ?? INSTALLER_WAIT_MS));
49
+ }
50
+ }
51
+ /** runInstaller that throws like execAsync when the installer fails. */
52
+ export async function runInstallerChecked(file, args, o = {}) {
53
+ const code = await runInstaller(file, args, o);
54
+ if (code !== 0)
55
+ throw new Error(path.basename(file) + ' ' + args.slice(0, 3).join(' ') + ' failed with exit code ' + code);
56
+ }
57
+ /** execAsync for heavy local work (npm, uv, rustup ...): one of the two heavy slots. */
58
+ export function execHeavy(file, args, options = {}) {
59
+ return heavy.run(() => execAsync(file, args, options));
60
+ }
@@ -6,10 +6,14 @@ export declare function execAsync(file: string, args: string[], options?: SpawnO
6
6
  export declare function execOutput(file: string, args: string[], options?: SpawnSyncOptions): string;
7
7
  /** Runs sandbox\scripts\<name> (a .ps1 in the launch folder) with `args`; throws when it fails. */
8
8
  export declare function runScript(name: string, args?: readonly string[]): void;
9
+ /** runScript without blocking the event loop (other boot tasks keep going while the script runs). */
10
+ export declare function runScriptAsync(name: string, args?: readonly string[]): Promise<void>;
9
11
  /** runScript for what it prints ('' when it fails). */
10
12
  export declare function scriptOutput(name: string, args?: readonly string[], options?: SpawnSyncOptions): string;
11
13
  /** Runs sandbox\scripts\<name> with a JSON file (-<param> path) holding `data`, removed afterwards. */
12
14
  export declare function runScriptWithJson(name: string, param: string, data: unknown, args?: readonly string[]): void;
15
+ /** runScriptWithJson without blocking the event loop. */
16
+ export declare function runScriptWithJsonAsync(name: string, param: string, data: unknown, args?: readonly string[]): Promise<void>;
13
17
  /**
14
18
  * Copies a folder with robocopy (fast, restartable), or just the named files in it; exit codes below 8 mean success.
15
19
  */