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
@@ -1,7 +1,100 @@
1
1
  // FXServer builds (the Cfx.re artifacts): which build "recommended", "optional", "latest" or a number means, from
2
- // changelogs-live.fivem.net/api/changelog/versions/win32/server. No checksums are published: the download is refused
3
- // under downloads.requireChecksum unless FXServer.exe is signed. Not available yet.
2
+ // changelogs-live.fivem.net/api/changelog/versions/win32/server (a pinned build that is no channel's is looked up on
3
+ // the artifacts page). No checksums are published: under downloads.requireChecksum a build is used only when its
4
+ // FXServer.exe carries a valid Authenticode signature from Rockstar Games (Cfx.re's owner); without that setting an
5
+ // unsigned one is used with a warning. No runtime imports: the self-test loads this file.
6
+ import { z } from 'zod';
7
+ import { fetchJson, fetchText } from '../../../shared/download/index.js';
8
+ export const VERSIONS_URL = 'https://changelogs-live.fivem.net/api/changelog/versions/win32/server';
9
+ export const ARTIFACTS_PAGE = 'https://runtime.fivem.net/artifacts/fivem/build_server_windows/master/';
10
+ /** The subject of the signature on FXServer.exe (checked on build 35245, 2026-11). */
11
+ export const FXSERVER_SIGNER = /^CN="?Rockstar Games, Inc\.?"?, O="?Rockstar Games, Inc\.?"?,/;
12
+ export const CHANNELS = ['recommended', 'optional', 'latest', 'critical'];
13
+ const BUILD = z.string().regex(/^\d{1,7}$/);
14
+ const DOWNLOAD = z
15
+ .string()
16
+ .max(512)
17
+ .regex(/^https:\/\/runtime\.fivem\.net\/artifacts\/fivem\/build_server_windows\/[A-Za-z0-9_./-]+\.(zip|7z)$/);
18
+ const TXADMIN = z.string().max(32).optional();
19
+ /** The versions API's answer (its other fields, such as support_policy, are not needed). */
20
+ export const VersionsSchema = z.object({
21
+ recommended: BUILD,
22
+ recommended_download: DOWNLOAD,
23
+ recommended_txadmin: TXADMIN,
24
+ optional: BUILD,
25
+ optional_download: DOWNLOAD,
26
+ optional_txadmin: TXADMIN,
27
+ latest: BUILD,
28
+ latest_download: DOWNLOAD,
29
+ latest_txadmin: TXADMIN,
30
+ critical: BUILD,
31
+ critical_download: DOWNLOAD,
32
+ critical_txadmin: TXADMIN,
33
+ });
34
+ /** Every channel's build, from the versions API's JSON (throws on any other shape). */
35
+ export function parseVersions(json) {
36
+ const v = VersionsSchema.parse(json);
37
+ const one = (channel, build, url, txAdmin) => ({
38
+ build: Number(build),
39
+ url,
40
+ channel,
41
+ ...(txAdmin ? { txAdmin } : {}),
42
+ });
43
+ return {
44
+ recommended: one('recommended', v.recommended, v.recommended_download, v.recommended_txadmin),
45
+ optional: one('optional', v.optional, v.optional_download, v.optional_txadmin),
46
+ latest: one('latest', v.latest, v.latest_download, v.latest_txadmin),
47
+ critical: one('critical', v.critical, v.critical_download, v.critical_txadmin),
48
+ };
49
+ }
50
+ const MAX_PAGE = 4 * 1024 * 1024;
51
+ /** The builds the artifacts page links to (newest first), as server.zip downloads. Reads at most 4 MB of it. */
52
+ export function parseArtifactsPage(html) {
53
+ const seen = new Map();
54
+ for (const m of html.slice(0, MAX_PAGE).matchAll(/\b(\d{3,7})-([0-9a-f]{40})\/server\.(?:zip|7z)\b/g)) {
55
+ const build = Number(m[1]);
56
+ if (!seen.has(build))
57
+ seen.set(build, { build, url: ARTIFACTS_PAGE + m[1] + '-' + m[2] + '/server.zip' });
58
+ }
59
+ return [...seen.values()].sort((a, b) => b.build - a.build);
60
+ }
61
+ /** What a setting names: a channel, or a build number. */
62
+ export function artifactSetting(setting) {
63
+ if (CHANNELS.includes(setting))
64
+ return setting;
65
+ return /^\d{1,7}$/.test(setting) ? Number(setting) : null;
66
+ }
67
+ /** The build a setting names among the channels and the page's builds, or null. */
68
+ export function chooseArtifact(setting, channels, page = []) {
69
+ const want = artifactSetting(setting);
70
+ if (want === null)
71
+ return null;
72
+ if (typeof want === 'string')
73
+ return channels[want];
74
+ return Object.values(channels).find((a) => a.build === want) ?? page.find((a) => a.build === want) ?? null;
75
+ }
76
+ /** The channels from the versions API. */
77
+ export async function fetchChannels(src = {}) {
78
+ return parseVersions(await (src.versions ?? (() => fetchJson(VERSIONS_URL)))());
79
+ }
4
80
  /** The build an artifact setting names, or null when it cannot be told. */
5
- export async function pickArtifact(_setting) {
6
- return null;
81
+ export async function pickArtifact(setting, src = {}) {
82
+ const want = artifactSetting(setting);
83
+ if (want === null)
84
+ return null;
85
+ const channels = await fetchChannels(src);
86
+ const found = chooseArtifact(setting, channels);
87
+ if (found || typeof want === 'string')
88
+ return found;
89
+ return chooseArtifact(setting, channels, parseArtifactsPage(await (src.page ?? (() => fetchText(ARTIFACTS_PAGE)))()));
90
+ }
91
+ /**
92
+ * Whether a downloaded build may be used. The artifacts have no checksums: the Authenticode signature on FXServer.exe
93
+ * stands in for one, so downloads.requireChecksum refuses a build whose FXServer.exe is not validly signed by Rockstar
94
+ * Games; without that setting an unsigned one is used (with a warning).
95
+ */
96
+ export function artifactTrust(requireChecksum, signerSubject) {
97
+ if (FXSERVER_SIGNER.test(signerSubject))
98
+ return 'signed';
99
+ return requireChecksum ? 'refused' : 'unsigned-allowed';
7
100
  }
@@ -1,4 +1,35 @@
1
1
  import type { Toolchains } from '../../../core/types.js';
2
+ import { type Installed } from '../persisted.js';
2
3
  import type { ToolCtx } from '../step.js';
3
4
  import type { ToolEnv } from '../tool-env.js';
4
- export declare function setupFivem(env: ToolEnv, _config: Toolchains['fivem'], _ctx: ToolCtx): Promise<void>;
5
+ import { type FivemArtifact } from './artifacts.js';
6
+ export declare const ARTIFACTS_NAME = "fivem/artifacts";
7
+ /** state\fivem: txData and the build chosen with sbx-fivem artifact use. */
8
+ export declare function fivemStateDir(): string;
9
+ export declare function txDataDir(): string;
10
+ export declare function artifactDir(build: number): string;
11
+ /** The secrets cfg FXServer +execs, when this boot handed a Cfx.re key over. */
12
+ export declare function secretsCfg(): string | null;
13
+ /** The build chosen with `sbx-fivem artifact use` (and the one it was then), or the setting. */
14
+ export declare function chosenArtifact(setting: string): {
15
+ setting: string;
16
+ chosen: boolean;
17
+ build: number | null;
18
+ };
19
+ /** Remembers a choice for sbx-fivem serve and the next boots (null: back to toolchains.fivem.artifact). */
20
+ export declare function rememberArtifact(choice: {
21
+ artifact: string;
22
+ build: number;
23
+ } | null): void;
24
+ /** The build sbx-fivem serve runs: the one chosen last, this boot's, or the newest installed. */
25
+ export declare function servingBuildDir(): string | null;
26
+ /** Builds installed in tools\fivem\artifacts (newest first). */
27
+ export declare function installedBuilds(): number[];
28
+ /**
29
+ * The build a setting names: looked up online at most once a day (offline: the one remembered, else the newest
30
+ * installed for a channel, the installed one for a number).
31
+ */
32
+ export declare function resolveArtifact(setting: string, live?: boolean): Promise<FivemArtifact>;
33
+ /** The build's folder, installed when it is not there yet. */
34
+ export declare function installArtifact(a: FivemArtifact, keepVersions: number): Promise<Installed>;
35
+ export declare function setupFivem(env: ToolEnv, config: Toolchains['fivem'], _ctx: ToolCtx): Promise<void>;
@@ -1,4 +1,169 @@
1
- import { notAvailableYet } from '../not-yet.js';
2
- export async function setupFivem(env, _config, _ctx) {
3
- notAvailableYet(env, 'FiveM server');
1
+ // FiveM / RedM (toolchains.fivem): FXServer (txAdmin is bundled) into tools\fivem\artifacts\<build>, kept between
2
+ // sandboxes (keepVersions of them), txData in state\fivem, and sbx-fivem to run it. Installs only once you accept the
3
+ // Cfx.re terms (acceptLicense). The build comes from toolchains.fivem.artifact, or from `sbx-fivem artifact use`
4
+ // (remembered in state\fivem\artifact.json). The artifacts have no checksums: see artifacts.ts for the signature rule.
5
+ import fs from 'node:fs';
6
+ import path from 'node:path';
7
+ import { z } from 'zod';
8
+ import { downloader, extractArchive } from '../../../shared/download/index.js';
9
+ import { readValid, writeJsonAtomic } from '../../../shared/io/json.js';
10
+ import { safeRemove } from '../../../shared/io/safe-remove.js';
11
+ import { dryRun, toolsDir } from '../../runtime/paths.js';
12
+ import { errMsg } from '../../../core/util/errors.js';
13
+ import { log, warn } from '../../runtime/log.js';
14
+ import { stateDir } from '../../runtime/session.js';
15
+ import { signatureOf } from '../signature.js';
16
+ import { ensurePersisted, installRecords } from '../persisted.js';
17
+ import { resolveCached } from '../version-cache.js';
18
+ import { cfxSecretsFile } from '../../accounts/kinds/cfx.js';
19
+ import { artifactSetting, artifactTrust, pickArtifact } from './artifacts.js';
20
+ export const ARTIFACTS_NAME = 'fivem/artifacts';
21
+ const MB = 1024 * 1024;
22
+ /** Room a build needs while installing: the zip (~65 MB) and its unpacked copy (~200 MB). */
23
+ const NEED_BYTES = 600 * MB;
24
+ const LICENCE = 'The FiveM server is installed only with toolchains.fivem.acceptLicense = true: FXServer comes under the Cfx.re platform terms (https://fivem.net/terms) and its licence';
25
+ const ArtifactSchema = z.strictObject({
26
+ build: z.number().int().positive(),
27
+ url: z.string().url().startsWith('https://runtime.fivem.net/'),
28
+ channel: z.enum(['recommended', 'optional', 'latest', 'critical']).optional(),
29
+ txAdmin: z.string().max(32).optional(),
30
+ });
31
+ const SelectionSchema = z.strictObject({
32
+ artifact: z.string().regex(/^(recommended|optional|latest|critical|\d{1,7})$/),
33
+ build: z.number().int().positive(),
34
+ });
35
+ /** state\fivem: txData and the build chosen with sbx-fivem artifact use. */
36
+ export function fivemStateDir() {
37
+ return path.join(stateDir, 'fivem');
38
+ }
39
+ export function txDataDir() {
40
+ return path.join(fivemStateDir(), 'txData');
41
+ }
42
+ const selectionFile = () => path.join(fivemStateDir(), 'artifact.json');
43
+ export function artifactDir(build) {
44
+ return path.join(toolsDir, ...ARTIFACTS_NAME.split('/'), String(build));
45
+ }
46
+ /** The secrets cfg FXServer +execs, when this boot handed a Cfx.re key over. */
47
+ export function secretsCfg() {
48
+ const file = cfxSecretsFile();
49
+ return fs.existsSync(file) ? file : null;
50
+ }
51
+ /** The build chosen with `sbx-fivem artifact use` (and the one it was then), or the setting. */
52
+ export function chosenArtifact(setting) {
53
+ const picked = readValid(SelectionSchema, selectionFile());
54
+ return picked
55
+ ? { setting: picked.artifact, chosen: true, build: picked.build }
56
+ : { setting, chosen: false, build: null };
57
+ }
58
+ /** Remembers a choice for sbx-fivem serve and the next boots (null: back to toolchains.fivem.artifact). */
59
+ export function rememberArtifact(choice) {
60
+ if (choice === null) {
61
+ fs.rmSync(selectionFile(), { force: true });
62
+ return;
63
+ }
64
+ fs.mkdirSync(fivemStateDir(), { recursive: true });
65
+ writeJsonAtomic(selectionFile(), SelectionSchema.parse(choice));
66
+ }
67
+ /** The build sbx-fivem serve runs: the one chosen last, this boot's, or the newest installed. */
68
+ export function servingBuildDir() {
69
+ const chosen = chosenArtifact('recommended').build;
70
+ const candidates = [
71
+ chosen === null ? null : artifactDir(chosen),
72
+ process.env.FXSERVER_DIR ?? null,
73
+ ...installedBuilds().map(artifactDir),
74
+ ];
75
+ return candidates.find((d) => d !== null && fs.existsSync(path.join(d, 'FXServer.exe'))) ?? null;
76
+ }
77
+ /** Builds installed in tools\fivem\artifacts (newest first). */
78
+ export function installedBuilds() {
79
+ return installRecords()
80
+ .filter((r) => r.name === ARTIFACTS_NAME && /^\d+$/.test(r.version))
81
+ .map((r) => Number(r.version))
82
+ .filter((b) => fs.existsSync(path.join(artifactDir(b), 'FXServer.exe')))
83
+ .sort((a, b) => b - a);
84
+ }
85
+ /**
86
+ * The build a setting names: looked up online at most once a day (offline: the one remembered, else the newest
87
+ * installed for a channel, the installed one for a number).
88
+ */
89
+ export async function resolveArtifact(setting, live = false) {
90
+ const want = artifactSetting(setting);
91
+ if (want === null)
92
+ throw new Error('"' + setting + '" is not a server build (recommended, optional, latest or a number)');
93
+ const lookup = async () => {
94
+ const found = await pickArtifact(setting);
95
+ if (!found)
96
+ throw new Error('there is no FXServer build ' + setting + ' for Windows');
97
+ return JSON.stringify(found);
98
+ };
99
+ try {
100
+ return ArtifactSchema.parse(JSON.parse(live ? await lookup() : await resolveCached('fivem:' + setting, lookup)));
101
+ }
102
+ catch (e) {
103
+ const installed = installedBuilds();
104
+ const fallback = typeof want === 'number' ? installed.find((b) => b === want) : installed[0];
105
+ if (fallback === undefined)
106
+ throw e;
107
+ warn('Could not look up FXServer ' + setting + ' (' + errMsg(e) + '); using installed build ' + fallback);
108
+ return { build: fallback, url: 'https://runtime.fivem.net/' };
109
+ }
110
+ }
111
+ /** Downloads and unpacks a build into `staging`; refuses it per artifactTrust. */
112
+ async function installBuild(a, staging, temp) {
113
+ const zip = path.join(temp, 'server.zip');
114
+ const check = path.join(temp, 'check');
115
+ // requireChecksum: the signature on FXServer.exe stands in for the checksum Cfx.re does not publish.
116
+ const verify = async (file) => {
117
+ await extractArchive(file, check, ['FXServer.exe']);
118
+ const exe = path.join(check, 'FXServer.exe');
119
+ if (artifactTrust(true, fs.existsSync(exe) ? (signatureOf(exe)?.subject ?? '') : '') !== 'signed')
120
+ throw new Error('FXServer build ' +
121
+ a.build +
122
+ ': FXServer.exe is not validly signed by Rockstar Games, and downloads.requireChecksum is on (Cfx.re publishes no checksums)');
123
+ safeRemove(check, temp);
124
+ };
125
+ log('Downloading FXServer build ' + a.build + ' (~65 MB once) ...');
126
+ await downloader.file(a.url, zip, downloader.requireChecksum ? { verify } : null);
127
+ await extractArchive(zip, staging);
128
+ fs.rmSync(zip, { force: true });
129
+ const exe = path.join(staging, 'FXServer.exe');
130
+ const trust = artifactTrust(downloader.requireChecksum, fs.existsSync(exe) ? (signatureOf(exe)?.subject ?? '') : '');
131
+ if (trust === 'refused')
132
+ throw new Error('FXServer build ' + a.build + ' is not validly signed; not using it');
133
+ if (trust === 'unsigned-allowed')
134
+ warn('FXServer build ' +
135
+ a.build +
136
+ ': FXServer.exe has no valid Rockstar Games signature (used anyway: downloads.requireChecksum is off)');
137
+ }
138
+ /** The build's folder, installed when it is not there yet. */
139
+ export async function installArtifact(a, keepVersions) {
140
+ return ensurePersisted({
141
+ name: ARTIFACTS_NAME,
142
+ version: String(a.build),
143
+ needBytes: NEED_BYTES,
144
+ marker: 'FXServer.exe',
145
+ what: 'FXServer build ' + a.build,
146
+ keepVersions,
147
+ }, (staging, temp) => installBuild(a, staging, temp), { log });
148
+ }
149
+ export async function setupFivem(env, config, _ctx) {
150
+ if (!config.acceptLicense)
151
+ throw new Error(LICENCE);
152
+ const { setting, chosen } = chosenArtifact(config.artifact);
153
+ if (dryRun) {
154
+ log('(dry run) would install FXServer ' + setting + ' into tools\\fivem\\artifacts');
155
+ return;
156
+ }
157
+ const artifact = await resolveArtifact(setting);
158
+ const installed = await installArtifact(artifact, config.keepVersions);
159
+ fs.mkdirSync(txDataDir(), { recursive: true });
160
+ env.vars.FXSERVER_DIR = installed.dir;
161
+ env.vars.FIVEM_GAME = config.game;
162
+ env.summary.push('fivem: FXServer build ' +
163
+ artifact.build +
164
+ ' (' +
165
+ (chosen ? setting + ', chosen with sbx-fivem artifact use' : setting) +
166
+ (config.game === 'rdr3' ? ', RedM' : '') +
167
+ '); start it with sbx-fivem serve' +
168
+ (secretsCfg() ? '' : ' (no Cfx.re key: sandbox account login cfx on your PC)'));
4
169
  }
@@ -0,0 +1,35 @@
1
+ export declare const RESOURCE_LANGS: readonly ["lua", "js", "ts", "cs"];
2
+ export type ResourceLang = (typeof RESOURCE_LANGS)[number];
3
+ export type FivemGame = 'gta5' | 'rdr3';
4
+ /** Resource names FXServer takes in `ensure`: letters, digits, - and _. */
5
+ export declare const RESOURCE_NAME: RegExp;
6
+ /** sandbox\templates\fivem in the launch folder. */
7
+ export declare function fivemTemplatesDir(): string;
8
+ /** The manifest's game lines (RedM also needs its prerelease acknowledgement). */
9
+ export declare function gameLines(game: FivemGame): string;
10
+ /** A resource name as a C# namespace: my-cool_res -> MyCoolRes (a leading digit gets an R). */
11
+ export declare function csNamespace(name: string): string;
12
+ /** Fills {{key}} placeholders; unknown ones stay as they are. */
13
+ export declare function renderTemplate(text: string, vars: Readonly<Record<string, string>>): string;
14
+ export declare function templateVars(name: string, game: FivemGame): Record<string, string>;
15
+ /** The template's files (relative paths), bounded; links are skipped. */
16
+ export declare function templateFiles(dir: string): string[];
17
+ export interface NewResource {
18
+ readonly templates: string;
19
+ readonly lang: ResourceLang;
20
+ readonly name: string;
21
+ /** The folder the resource folder goes in (resources\[local] of a server folder, or any folder). */
22
+ readonly into: string;
23
+ readonly game: FivemGame;
24
+ }
25
+ /** Makes <into>\<name> from the language's template; returns the folder and its files. */
26
+ export declare function scaffoldResource(o: NewResource): {
27
+ dir: string;
28
+ files: string[];
29
+ };
30
+ /** server.cfg with `ensure <name>` added at the end, or null when it already ensures it. */
31
+ export declare function withEnsure(cfg: string, name: string): string | null;
32
+ /** Where `sbx-fivem new` puts a resource: resources\[local] when the folder is a server folder, else the folder. */
33
+ export declare function resourceHome(folder: string): string;
34
+ /** Writes server.cfg (when there is none) and resources\[local] into `dir`; returns what it wrote. */
35
+ export declare function initServerFolder(templates: string, dir: string, name: string, game: FivemGame): string[];
@@ -0,0 +1,105 @@
1
+ // New FiveM / RedM resources and server folders from sandbox\templates\fivem (`sbx-fivem new`, `sbx-fivem init`):
2
+ // the template's files with {{name}}, {{namespace}}, {{game}} and {{gameLines}} filled in. Never overwrites anything.
3
+ // No runtime imports: the self-test loads this file.
4
+ import fs from 'node:fs';
5
+ import path from 'node:path';
6
+ import { sandboxScriptsDir } from '../../../shared/scripts.js';
7
+ export const RESOURCE_LANGS = ['lua', 'js', 'ts', 'cs'];
8
+ /** Resource names FXServer takes in `ensure`: letters, digits, - and _. */
9
+ export const RESOURCE_NAME = /^[A-Za-z0-9][A-Za-z0-9_-]{0,47}$/;
10
+ const MAX_TEMPLATE_FILES = 64;
11
+ const MAX_TEMPLATE_BYTES = 256 * 1024;
12
+ const RDR3_WARNING = "rdr3_warning 'I acknowledge that this is a prerelease build of RedM, and I am aware my resources *will* become incompatible once RedM ships.'";
13
+ /** sandbox\templates\fivem in the launch folder. */
14
+ export function fivemTemplatesDir() {
15
+ return path.join(sandboxScriptsDir(), 'templates', 'fivem');
16
+ }
17
+ /** The manifest's game lines (RedM also needs its prerelease acknowledgement). */
18
+ export function gameLines(game) {
19
+ return game === 'rdr3' ? "game 'rdr3'\n" + RDR3_WARNING : "game 'gta5'";
20
+ }
21
+ /** A resource name as a C# namespace: my-cool_res -> MyCoolRes (a leading digit gets an R). */
22
+ export function csNamespace(name) {
23
+ const pascal = name
24
+ .split(/[-_]+/)
25
+ .filter(Boolean)
26
+ .map((part) => part[0].toUpperCase() + part.slice(1))
27
+ .join('');
28
+ return /^[0-9]/.test(pascal) ? 'R' + pascal : pascal;
29
+ }
30
+ /** Fills {{key}} placeholders; unknown ones stay as they are. */
31
+ export function renderTemplate(text, vars) {
32
+ return text.replace(/\{\{([A-Za-z]{1,20})\}\}/g, (all, key) => vars[key] ?? all);
33
+ }
34
+ export function templateVars(name, game) {
35
+ return { name, namespace: csNamespace(name), game, gameLines: gameLines(game) };
36
+ }
37
+ /** The template's files (relative paths), bounded; links are skipped. */
38
+ export function templateFiles(dir) {
39
+ const out = [];
40
+ const walk = (current, depth) => {
41
+ for (const e of fs.readdirSync(current, { withFileTypes: true })) {
42
+ if (out.length >= MAX_TEMPLATE_FILES)
43
+ return;
44
+ const full = path.join(current, e.name);
45
+ if (e.isFile())
46
+ out.push(path.relative(dir, full));
47
+ else if (e.isDirectory() && depth < 4)
48
+ walk(full, depth + 1);
49
+ }
50
+ };
51
+ walk(dir, 0);
52
+ return out.sort();
53
+ }
54
+ function copyRendered(from, to, vars) {
55
+ const files = templateFiles(from);
56
+ for (const rel of files) {
57
+ const src = path.join(from, rel);
58
+ if (fs.statSync(src).size > MAX_TEMPLATE_BYTES)
59
+ throw new Error('template file too big: ' + rel);
60
+ const dest = path.join(to, rel);
61
+ fs.mkdirSync(path.dirname(dest), { recursive: true });
62
+ fs.writeFileSync(dest, renderTemplate(fs.readFileSync(src, 'utf8'), vars), { flag: 'wx' });
63
+ }
64
+ return files;
65
+ }
66
+ /** Makes <into>\<name> from the language's template; returns the folder and its files. */
67
+ export function scaffoldResource(o) {
68
+ if (!RESOURCE_NAME.test(o.name))
69
+ throw new Error('"' + o.name + '" is not a resource name: letters, digits, - and _ only (up to 48)');
70
+ const dir = path.join(o.into, o.name);
71
+ if (fs.existsSync(dir))
72
+ throw new Error(dir + ' already exists');
73
+ const files = copyRendered(path.join(o.templates, o.lang), dir, templateVars(o.name, o.game));
74
+ return { dir, files };
75
+ }
76
+ /** server.cfg with `ensure <name>` added at the end, or null when it already ensures it. */
77
+ export function withEnsure(cfg, name) {
78
+ const line = new RegExp('^\\s*(ensure|start)\\s+' + name.replace(/[-]/g, '\\-') + '\\s*$', 'm');
79
+ if (line.test(cfg))
80
+ return null;
81
+ return cfg.replace(/\s*$/, '') + '\nensure ' + name + '\n';
82
+ }
83
+ /** Where `sbx-fivem new` puts a resource: resources\[local] when the folder is a server folder, else the folder. */
84
+ export function resourceHome(folder) {
85
+ return fs.existsSync(path.join(folder, 'server.cfg')) || fs.existsSync(path.join(folder, 'resources'))
86
+ ? path.join(folder, 'resources', '[local]')
87
+ : folder;
88
+ }
89
+ /** Writes server.cfg (when there is none) and resources\[local] into `dir`; returns what it wrote. */
90
+ export function initServerFolder(templates, dir, name, game) {
91
+ const wrote = [];
92
+ const cfg = path.join(dir, 'server.cfg');
93
+ if (!fs.existsSync(cfg)) {
94
+ const text = renderTemplate(fs.readFileSync(path.join(templates, 'server.cfg'), 'utf8'), templateVars(name, game));
95
+ fs.mkdirSync(dir, { recursive: true });
96
+ fs.writeFileSync(cfg, text, { flag: 'wx' });
97
+ wrote.push('server.cfg');
98
+ }
99
+ const local = path.join(dir, 'resources', '[local]');
100
+ if (!fs.existsSync(local)) {
101
+ fs.mkdirSync(local, { recursive: true });
102
+ wrote.push('resources\\[local]');
103
+ }
104
+ return wrote;
105
+ }
@@ -0,0 +1,34 @@
1
+ import type { FivemGame } from './scaffold.js';
2
+ export declare const GAME_PORT = 30120;
3
+ export declare const TXADMIN_PORT = 40120;
4
+ export interface ServeInput {
5
+ /** The FXServer build's folder (FXServer.exe, citizen\). */
6
+ readonly artifactDir: string;
7
+ /** The server folder (server.cfg, resources\). */
8
+ readonly serverDir: string;
9
+ readonly game: FivemGame;
10
+ readonly txAdmin: boolean;
11
+ /** The Cfx.re key's cfg, or null when no key was handed over. */
12
+ readonly secretsCfg: string | null;
13
+ readonly txData: string;
14
+ /** The port of the sandbox's MariaDB (databases.mysql), or null when it has none. */
15
+ readonly mysqlPort: number | null;
16
+ }
17
+ export interface OpenPort {
18
+ readonly port: number;
19
+ readonly protocol: 'TCP' | 'UDP' | 'Both';
20
+ readonly name: string;
21
+ }
22
+ export interface ServePlan {
23
+ readonly exe: string;
24
+ readonly args: string[];
25
+ readonly cwd: string;
26
+ /** Added to sbx-fivem's own environment. */
27
+ readonly env: Record<string, string>;
28
+ readonly ports: OpenPort[];
29
+ }
30
+ /** FXServer's exec takes forward slashes. */
31
+ export declare function cfgPath(file: string): string;
32
+ /** oxmysql's connection string for the sandbox's MariaDB (user root, no password, database "fivem"). */
33
+ export declare function mysqlConnectionString(port: number): string;
34
+ export declare function servePlan(i: ServeInput): ServePlan;
@@ -0,0 +1,61 @@
1
+ // How `sbx-fivem serve` starts FXServer: the program, its arguments and environment, and the ports the PC needs.
2
+ // Plain: +exec the Cfx.re key's cfg (on the sandbox's own disk) and then the project's server.cfg, from the server
3
+ // folder. txAdmin: no +exec (FXServer then starts txAdmin), its data in state\fivem\txData through TXHOST_*.
4
+ // No runtime imports: the self-test loads this file.
5
+ import path from 'node:path';
6
+ export const GAME_PORT = 30120;
7
+ export const TXADMIN_PORT = 40120;
8
+ /** FXServer's exec takes forward slashes. */
9
+ export function cfgPath(file) {
10
+ return file.split('\\').join('/');
11
+ }
12
+ /** oxmysql's connection string for the sandbox's MariaDB (user root, no password, database "fivem"). */
13
+ export function mysqlConnectionString(port) {
14
+ return 'mysql://root@127.0.0.1:' + port + '/fivem?charset=utf8mb4';
15
+ }
16
+ export function servePlan(i) {
17
+ const exe = path.join(i.artifactDir, 'FXServer.exe');
18
+ const citizen = ['+set', 'citizen_dir', path.join(i.artifactDir, 'citizen')];
19
+ const game = i.game === 'rdr3' ? ['+set', 'gamename', 'rdr3'] : [];
20
+ if (i.txAdmin) {
21
+ const db = i.mysqlPort === null
22
+ ? {}
23
+ : {
24
+ TXHOST_DEFAULT_DBHOST: '127.0.0.1',
25
+ TXHOST_DEFAULT_DBPORT: String(i.mysqlPort),
26
+ TXHOST_DEFAULT_DBUSER: 'root',
27
+ TXHOST_DEFAULT_DBNAME: 'fivem',
28
+ };
29
+ return {
30
+ exe,
31
+ // RedM: txAdmin's recipes for it set gamename in the server.cfg they write.
32
+ args: citizen,
33
+ cwd: i.txData,
34
+ env: {
35
+ TXHOST_DATA_PATH: i.txData,
36
+ TXHOST_TXA_PORT: String(TXADMIN_PORT),
37
+ TXHOST_GAME_NAME: i.game === 'rdr3' ? 'redm' : 'fivem',
38
+ TXHOST_PROVIDER_NAME: 'Sandbox',
39
+ ...db,
40
+ },
41
+ ports: [
42
+ { port: GAME_PORT, protocol: 'Both', name: 'FiveM server' },
43
+ { port: TXADMIN_PORT, protocol: 'TCP', name: 'txAdmin' },
44
+ ],
45
+ };
46
+ }
47
+ return {
48
+ exe,
49
+ args: [
50
+ ...citizen,
51
+ ...game,
52
+ ...(i.mysqlPort === null ? [] : ['+set', 'mysql_connection_string', mysqlConnectionString(i.mysqlPort)]),
53
+ ...(i.secretsCfg ? ['+exec', cfgPath(i.secretsCfg)] : []),
54
+ '+exec',
55
+ 'server.cfg',
56
+ ],
57
+ cwd: i.serverDir,
58
+ env: {},
59
+ ports: [{ port: GAME_PORT, protocol: 'Both', name: 'FiveM server' }],
60
+ };
61
+ }
@@ -1,12 +1,8 @@
1
- /** Who signs the installers the toolchains run (the subject of the signature). */
2
- export declare const SIGNERS: {
3
- readonly microsoft: "CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US";
4
- readonly valve: RegExp;
5
- readonly unity: RegExp;
6
- };
7
- /** Whether a file's signature is the expected signer's. */
8
- export declare function signedBy(file: string, signer: string | RegExp): boolean;
1
+ import { SIGNERS, type AppSigner } from '../../shared/signer.js';
2
+ import { signedBy } from './signature.js';
3
+ export { SIGNERS };
4
+ export { signedBy };
9
5
  /** A downloader `verify` hook: refuses a file not signed by `signer` (it counts as integrity for requireChecksum). */
10
- export declare function signatureCheck(signer: string | RegExp, what: string): (file: string) => void;
6
+ export declare function signatureCheck(signer: AppSigner, what: string): (file: string) => void;
11
7
  /** The installer at `file` (downloaded once from `url`), checked against its signer and, when given, its SHA-256. */
12
- export declare function signedInstaller(url: string, file: string, what: string, signer: string | RegExp, sha256?: string | null): Promise<string>;
8
+ export declare function signedInstaller(url: string, file: string, what: string, signer: AppSigner, sha256?: string | null): Promise<string>;
@@ -5,18 +5,10 @@ import path from 'node:path';
5
5
  import { downloader } from '../../shared/download/index.js';
6
6
  import { exists, mkdirp } from '../runtime/fs.js';
7
7
  import { log } from '../runtime/log.js';
8
- import { MICROSOFT_SIGNER, signerOf } from './native/vcruntime.js';
9
- /** Who signs the installers the toolchains run (the subject of the signature). */
10
- export const SIGNERS = {
11
- microsoft: MICROSOFT_SIGNER,
12
- valve: /^CN="?Valve(,| Corp)/,
13
- unity: /^CN="?Unity Technologies/,
14
- };
15
- /** Whether a file's signature is the expected signer's. */
16
- export function signedBy(file, signer) {
17
- const subject = signerOf(file);
18
- return typeof signer === 'string' ? subject === signer : signer.test(subject);
19
- }
8
+ import { SIGNERS } from '../../shared/signer.js';
9
+ import { signedBy } from './signature.js';
10
+ export { SIGNERS };
11
+ export { signedBy };
20
12
  /** A downloader `verify` hook: refuses a file not signed by `signer` (it counts as integrity for requireChecksum). */
21
13
  export function signatureCheck(signer, what) {
22
14
  return (file) => {
@@ -4,7 +4,7 @@ import fs from 'node:fs';
4
4
  import path from 'node:path';
5
5
  import { downloader, fetchJson } from '../../../shared/download/index.js';
6
6
  import { dryRun } from '../../runtime/paths.js';
7
- import { execAsync } from '../../runtime/process.js';
7
+ import { execHeavy as execAsync } from '../../runtime/pools.js';
8
8
  import { exists } from '../../runtime/fs.js';
9
9
  import { log } from '../../runtime/log.js';
10
10
  import { arch, tool, versionOf } from '../tool-env.js';
@@ -5,7 +5,8 @@ import path from 'node:path';
5
5
  import { spawn } from 'node:child_process';
6
6
  import { downloader, fetchJson, githubAsset } from '../../../shared/download/index.js';
7
7
  import { safeRemove } from '../../../shared/io/safe-remove.js';
8
- import { copyNode, execAsync } from '../../runtime/process.js';
8
+ import { copyNode } from '../../runtime/process.js';
9
+ import { execHeavy as execAsync } from '../../runtime/pools.js';
9
10
  import { dryRun, hostToolsDir, localDir } from '../../runtime/paths.js';
10
11
  import { exists, mkdirp } from '../../runtime/fs.js';
11
12
  import { log, warn } from '../../runtime/log.js';
@@ -1,3 +1,5 @@
1
1
  import type { Toolchains } from '../../../core/types.js';
2
2
  import { type ToolEnv } from '../tool-env.js';
3
+ /** Downloads PHP's zip ahead of the install (which unpacks it); nothing when PHP is there already. */
4
+ export declare function fetchPhp(config: Toolchains['php']): Promise<void>;
3
5
  export declare function setupPhp(env: ToolEnv, config: Toolchains['php']): Promise<void>;