windows-development-sandbox 1.20.0 → 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.
- package/config.example.json +8 -1
- package/dist/app/features/access/access.def.js +5 -2
- package/dist/app/features/access/access.run.js +7 -3
- package/dist/app/features/accounts/accounts.def.d.ts +29 -1
- package/dist/app/features/accounts/accounts.def.js +10 -4
- package/dist/app/features/accounts/accounts.run.d.ts +1 -0
- package/dist/app/features/accounts/accounts.run.js +7 -2
- package/dist/app/features/accounts/services.def.d.ts +4 -1
- package/dist/app/features/accounts/services.def.js +15 -14
- package/dist/app/features/accounts/services.run.d.ts +1 -0
- package/dist/app/features/accounts/services.run.js +41 -15
- package/dist/app/features/defs.d.ts +39 -2
- package/dist/app/features/engine/engine.run.js +1 -1
- package/dist/app/features/github/github.def.d.ts +44 -3
- package/dist/app/features/github/github.def.js +145 -63
- package/dist/app/features/github/github.run.d.ts +9 -2
- package/dist/app/features/github/github.run.js +43 -5
- package/dist/app/features/health/health.def.js +8 -2
- package/dist/app/features/logs/logs.def.js +0 -8
- package/dist/app/features/projects/projects.def.js +2 -2
- package/dist/app/features/projects/projects.run.js +5 -5
- package/dist/app/features/sandbox/sandbox.def.js +7 -3
- package/dist/app/features/sessions/sessions.def.d.ts +4 -4
- package/dist/app/features/sessions/sessions.def.js +0 -5
- package/dist/app/features/sessions/sessions.run.d.ts +1 -1
- package/dist/app/features/sessions/sessions.run.js +2 -2
- package/dist/app/features/settings/categories.def.js +2 -0
- package/dist/app/features/settings/settings-rows.js +1 -1
- package/dist/app/features/settings/settings.def.js +1 -1
- package/dist/app/features/settings/settings.run.js +3 -3
- package/dist/app/features/storage/storage.run.js +18 -9
- package/dist/app/features/updates/update-lines.js +2 -2
- package/dist/app/features/updates/updates.def.js +1 -1
- package/dist/app/features/updates/updates.run.js +1 -1
- package/dist/app/features/web/web.def.js +2 -2
- package/dist/app/features/web/web.run.js +12 -4
- package/dist/app/kernel/errors.d.ts +7 -0
- package/dist/app/kernel/errors.js +18 -3
- package/dist/app/kernel/rpc.d.ts +5 -0
- package/dist/app/kernel/view.d.ts +11 -1
- package/dist/bin/agent-sandbox.js +2 -2
- package/dist/bin/{chunk-DK4NTBUF.js → chunk-JETGP2C3.js} +172 -48
- package/dist/bin/{chunk-2IMT7ZCT.js → chunk-XZKOPGNH.js} +1 -1
- package/dist/bin/{chunk-Z2P5OGKL.js → chunk-ZTTOF5V3.js} +2430 -1688
- package/dist/bin/claude-host.js +2 -2
- package/dist/bin/claude-sbx.js +2 -2
- package/dist/bin/codex-sbx.js +2 -2
- package/dist/bin/gemini-sbx.js +2 -2
- package/dist/bin/sandbox.js +2 -2
- package/dist/bin/sbx-hide.js +2 -2
- package/dist/bin/sbx-show.js +2 -2
- package/dist/cli/manifest.d.ts +2 -2
- package/dist/cli/manifest.js +2 -1
- package/dist/cli/menu/coverage-exempt.d.ts +17 -0
- package/dist/cli/menu/coverage-exempt.js +61 -0
- package/dist/cli/menu/io-menu.d.ts +2 -0
- package/dist/cli/menu/io-menu.js +50 -5
- package/dist/cli/menu/pages/accounts-page.js +1 -1
- package/dist/cli/menu/pages/agents-page.js +8 -2
- package/dist/cli/menu/pages/maintenance-page.d.ts +6 -0
- package/dist/cli/menu/pages/maintenance-page.js +9 -2
- package/dist/cli/menu/pages/sessions-page.d.ts +2 -0
- package/dist/cli/menu/pages/sessions-page.js +12 -4
- package/dist/cli/menu/pages/settings-page.js +12 -1
- package/dist/cli/menu/remote-menu.js +1 -1
- package/dist/cli/menu/shell.d.ts +5 -0
- package/dist/cli/menu/shell.js +13 -0
- package/dist/cli/report.js +2 -0
- package/dist/cli/tui/app.d.ts +5 -0
- package/dist/cli/tui/app.js +2 -0
- package/dist/core/config/defaults.js +3 -1
- package/dist/core/schema/accounts.d.ts +6 -0
- package/dist/core/schema/accounts.js +13 -11
- package/dist/core/schema/config.d.ts +20 -8
- package/dist/core/schema/config.js +4 -4
- package/dist/core/schema/github.js +1 -1
- package/dist/core/schema/profile.js +8 -4
- package/dist/core/schema/resume.js +1 -1
- package/dist/core/schema/sandbox.js +3 -3
- package/dist/core/schema/vpn.js +1 -1
- package/dist/core/schema/web.js +3 -3
- package/dist/core/types.d.ts +6 -0
- package/dist/core/util/errors.d.ts +11 -1
- package/dist/core/util/errors.js +7 -1
- package/dist/core/util/index.d.ts +1 -1
- package/dist/core/util/index.js +1 -1
- package/dist/guest/accounts/adapter.d.ts +2 -0
- package/dist/guest/accounts/adapters.js +4 -0
- package/dist/guest/accounts/apply.d.ts +6 -2
- package/dist/guest/accounts/kinds/cfx.d.ts +7 -0
- package/dist/guest/accounts/kinds/cfx.js +33 -3
- package/dist/guest/accounts/kinds/comet.d.ts +7 -0
- package/dist/guest/accounts/kinds/comet.js +50 -0
- package/dist/guest/accounts/kinds/perplexity.d.ts +2 -0
- package/dist/guest/accounts/kinds/perplexity.js +12 -0
- package/dist/guest/accounts/watch.d.ts +2 -0
- package/dist/guest/accounts/watch.js +12 -2
- package/dist/guest/agents/agent-installer.js +1 -1
- package/dist/guest/agents/profile-links.d.ts +2 -0
- package/dist/guest/agents/profile-links.js +18 -4
- package/dist/guest/apps/after-install.js +19 -0
- package/dist/guest/apps/app-installer.d.ts +11 -0
- package/dist/guest/apps/app-installer.js +69 -6
- package/dist/guest/apps/comet-unpack.d.ts +20 -0
- package/dist/guest/apps/comet-unpack.js +127 -0
- package/dist/guest/apps/index.d.ts +1 -1
- package/dist/guest/apps/index.js +1 -1
- package/dist/guest/apps/resolvers-agents-web.d.ts +2 -0
- package/dist/guest/apps/resolvers-agents-web.js +7 -0
- package/dist/guest/apps/resolvers.js +2 -0
- package/dist/guest/apps/shortcuts.d.ts +2 -0
- package/dist/guest/apps/shortcuts.js +1 -0
- package/dist/guest/apps/unpack.js +14 -4
- package/dist/guest/boot/boot.d.ts +45 -16
- package/dist/guest/boot/boot.js +316 -145
- package/dist/guest/boot/graph.d.ts +252 -0
- package/dist/guest/boot/graph.js +257 -0
- package/dist/guest/boot/guide-lines.d.ts +25 -0
- package/dist/guest/boot/guide-lines.js +41 -0
- package/dist/guest/boot/guide.d.ts +1 -4
- package/dist/guest/boot/guide.js +6 -8
- package/dist/guest/boot/runner.d.ts +77 -0
- package/dist/guest/boot/runner.js +215 -0
- package/dist/guest/browser/cdp.d.ts +71 -0
- package/dist/guest/browser/cdp.js +306 -0
- package/dist/guest/browser/comet.d.ts +28 -0
- package/dist/guest/browser/comet.js +155 -0
- package/dist/guest/daemon/project-provisioner.js +6 -1
- package/dist/guest/devtools/fivem.d.ts +1 -1
- package/dist/guest/devtools/fivem.js +243 -3
- package/dist/guest/entries/daemon.js +2 -0
- package/dist/guest/runtime/log.d.ts +12 -0
- package/dist/guest/runtime/log.js +29 -5
- package/dist/guest/runtime/pools.d.ts +24 -0
- package/dist/guest/runtime/pools.js +60 -0
- package/dist/guest/runtime/process.d.ts +4 -0
- package/dist/guest/runtime/process.js +38 -1
- package/dist/guest/runtime/status.d.ts +5 -1
- package/dist/guest/runtime/status.js +19 -0
- package/dist/guest/setup/addon-mcp.d.ts +1 -1
- package/dist/guest/setup/addon-mcp.js +52 -12
- package/dist/guest/setup/agent-addons.d.ts +3 -2
- package/dist/guest/setup/agent-addons.js +12 -3
- package/dist/guest/setup/environment.d.ts +1 -1
- package/dist/guest/setup/environment.js +25 -12
- package/dist/guest/setup/headroom.d.ts +8 -3
- package/dist/guest/setup/headroom.js +44 -15
- package/dist/guest/setup/path-plan.d.ts +28 -0
- package/dist/guest/setup/path-plan.js +69 -2
- package/dist/guest/setup/shell-path.d.ts +1 -1
- package/dist/guest/setup/shell-path.js +3 -3
- package/dist/guest/toolchains/fivem/artifacts.d.ts +48 -1
- package/dist/guest/toolchains/fivem/artifacts.js +97 -4
- package/dist/guest/toolchains/fivem/fivem.d.ts +32 -1
- package/dist/guest/toolchains/fivem/fivem.js +168 -3
- package/dist/guest/toolchains/fivem/scaffold.d.ts +35 -0
- package/dist/guest/toolchains/fivem/scaffold.js +105 -0
- package/dist/guest/toolchains/fivem/serve-plan.d.ts +34 -0
- package/dist/guest/toolchains/fivem/serve-plan.js +61 -0
- package/dist/guest/toolchains/languages/go.js +1 -1
- package/dist/guest/toolchains/languages/node.js +2 -1
- package/dist/guest/toolchains/languages/php.d.ts +2 -0
- package/dist/guest/toolchains/languages/php.js +13 -1
- package/dist/guest/toolchains/languages/python-tools.js +1 -1
- package/dist/guest/toolchains/languages/ruby.js +1 -1
- package/dist/guest/toolchains/native/binstall.js +1 -1
- package/dist/guest/toolchains/native/msvc/packages.js +10 -4
- package/dist/guest/toolchains/native/rust.d.ts +2 -0
- package/dist/guest/toolchains/native/rust.js +11 -4
- package/dist/guest/toolchains/native/unreal.d.ts +2 -0
- package/dist/guest/toolchains/native/unreal.js +16 -6
- package/dist/guest/toolchains/native/vcruntime.d.ts +2 -0
- package/dist/guest/toolchains/native/vcruntime.js +10 -2
- package/dist/guest/toolchains/native/visual-studio.d.ts +3 -0
- package/dist/guest/toolchains/native/visual-studio.js +44 -26
- package/dist/guest/toolchains/native/vs-request.d.ts +2 -0
- package/dist/guest/toolchains/native/vs-request.js +2 -0
- package/dist/guest/toolchains/plan.js +19 -8
- package/dist/guest/toolchains/scheduler.d.ts +2 -21
- package/dist/guest/toolchains/scheduler.js +7 -121
- package/dist/guest/toolchains/setup.d.ts +15 -2
- package/dist/guest/toolchains/setup.js +39 -20
- package/dist/guest/toolchains/split.d.ts +28 -0
- package/dist/guest/toolchains/split.js +60 -0
- package/dist/guest/toolchains/steam/client.js +2 -1
- package/dist/guest/toolchains/step-scheduler.d.ts +51 -0
- package/dist/guest/toolchains/step-scheduler.js +147 -0
- package/dist/guest/toolchains/step.d.ts +13 -0
- package/dist/guest/toolchains/tools/git.js +18 -0
- package/dist/guest/vpn/openvpn.js +3 -4
- package/dist/guest/vpn/wireguard.js +11 -4
- package/dist/host/accounts/deliver.js +7 -0
- package/dist/host/accounts/handoff.js +2 -6
- package/dist/host/accounts/index.d.ts +1 -1
- package/dist/host/accounts/index.js +1 -1
- package/dist/host/accounts/kinds/cfx.d.ts +1 -1
- package/dist/host/accounts/kinds/cfx.js +47 -4
- package/dist/host/accounts/kinds/comet.d.ts +2 -0
- package/dist/host/accounts/kinds/comet.js +6 -0
- package/dist/host/accounts/kinds/perplexity.d.ts +2 -0
- package/dist/host/accounts/kinds/perplexity.js +30 -0
- package/dist/host/accounts/leases.d.ts +7 -1
- package/dist/host/accounts/leases.js +13 -2
- package/dist/host/accounts/source.d.ts +7 -1
- package/dist/host/accounts/source.js +27 -0
- package/dist/host/accounts/sources.js +4 -0
- package/dist/host/github/deliver.d.ts +1 -1
- package/dist/host/github/deliver.js +20 -1
- package/dist/host/github/index.d.ts +2 -1
- package/dist/host/github/index.js +1 -0
- package/dist/host/github/token.d.ts +13 -1
- package/dist/host/github/token.js +19 -2
- package/dist/host/github/verify.d.ts +27 -0
- package/dist/host/github/verify.js +61 -0
- package/dist/host/launch/hints/fivem.d.ts +3 -1
- package/dist/host/launch/hints/fivem.js +68 -2
- package/dist/host/launch/session-file.js +4 -0
- package/dist/host/launch/toolchains.d.ts +2 -1
- package/dist/host/launch/toolchains.js +5 -3
- package/dist/host/vpn/nordvpn.d.ts +2 -4
- package/dist/host/vpn/nordvpn.js +2 -24
- package/dist/runtime/agent.js +405 -90
- package/dist/runtime/daemon.js +3010 -1383
- package/dist/runtime/db.js +333 -90
- package/dist/runtime/main.js +4720 -1954
- package/dist/runtime/netproxy.js +286 -69
- package/dist/runtime/tool.js +2852 -1780
- package/dist/runtime/view.js +286 -69
- package/dist/selftest/agent-paths.test.js +39 -1
- package/dist/selftest/agents-web.test.d.ts +2 -0
- package/dist/selftest/agents-web.test.js +647 -0
- package/dist/selftest/app.test.js +5 -2
- package/dist/selftest/boot-runner.test.d.ts +2 -0
- package/dist/selftest/boot-runner.test.js +456 -0
- package/dist/selftest/channel.test.js +15 -0
- package/dist/selftest/fivem.test.js +249 -3
- package/dist/selftest/github.test.js +94 -9
- package/dist/selftest/guest-boot.test.js +3 -0
- package/dist/selftest/health.test.js +1 -1
- package/dist/selftest/index.js +8 -0
- package/dist/selftest/layout.test.js +5 -0
- package/dist/selftest/menu-coverage.test.d.ts +2 -0
- package/dist/selftest/menu-coverage.test.js +46 -0
- package/dist/selftest/menu-screens.js +37 -1
- package/dist/selftest/persisted-installs.test.js +6 -3
- package/dist/selftest/service-accounts.test.js +3 -2
- package/dist/selftest/support/engine-golden.js +27 -0
- package/dist/selftest/support/fixtures.d.ts +6 -0
- package/dist/selftest/support/web-preview.d.ts +34 -1
- package/dist/selftest/support/web-preview.js +21 -18
- package/dist/selftest/toolchains.test.js +23 -1
- package/dist/selftest/ui-text.test.d.ts +7 -0
- package/dist/selftest/ui-text.test.js +300 -0
- package/dist/shared/accounts/index.d.ts +2 -0
- package/dist/shared/accounts/index.js +2 -0
- package/dist/shared/accounts/kinds/comet.d.ts +12 -0
- package/dist/shared/accounts/kinds/comet.js +64 -0
- package/dist/shared/accounts/kinds/perplexity.d.ts +8 -0
- package/dist/shared/accounts/kinds/perplexity.js +37 -0
- package/dist/shared/accounts/kinds.d.ts +24 -5
- package/dist/shared/accounts/kinds.js +86 -4
- package/dist/shared/accounts/payloads.d.ts +81 -0
- package/dist/shared/accounts/payloads.js +39 -1
- package/dist/shared/apps/agent-addons.d.ts +33 -5
- package/dist/shared/apps/agent-addons.js +95 -3
- package/dist/shared/apps/catalogue-agents-web.d.ts +14 -0
- package/dist/shared/apps/catalogue-agents-web.js +112 -0
- package/dist/shared/apps/catalogue-modding.js +32 -1
- package/dist/shared/apps/catalogue.d.ts +27 -3
- package/dist/shared/apps/catalogue.js +2 -1
- package/dist/shared/apps/index.d.ts +3 -1
- package/dist/shared/apps/index.js +3 -1
- package/dist/shared/channel/schema.d.ts +21 -3
- package/dist/shared/channel/schema.js +7 -0
- package/dist/shared/channel/secrets.d.ts +19 -0
- package/dist/shared/concurrency/index.d.ts +3 -0
- package/dist/shared/concurrency/index.js +3 -0
- package/dist/shared/concurrency/installer-retry.d.ts +6 -0
- package/dist/shared/concurrency/installer-retry.js +10 -0
- package/dist/shared/concurrency/limiter.d.ts +19 -0
- package/dist/shared/concurrency/limiter.js +67 -0
- package/dist/shared/concurrency/pools.d.ts +7 -0
- package/dist/shared/concurrency/pools.js +9 -0
- package/dist/shared/download/archive.d.ts +2 -0
- package/dist/shared/download/archive.js +11 -1
- package/dist/shared/download/bounded-fetch.d.ts +13 -0
- package/dist/shared/download/bounded-fetch.js +40 -0
- package/dist/shared/download/downloader.d.ts +5 -0
- package/dist/shared/download/downloader.js +50 -38
- package/dist/shared/download/index.d.ts +2 -1
- package/dist/shared/download/index.js +2 -1
- package/dist/shared/readiness.d.ts +2 -2
- package/dist/shared/readiness.js +2 -2
- package/dist/web/index.html +1 -1
- package/dist/web/{main-OUUQYNK4.js → main-CCILLX2M.js} +67 -67
- package/native/csharp/HcsHost/AssemblyInfo.cs +3 -3
- package/native/csharp/HostTools/AssemblyInfo.cs +3 -3
- package/native/csharp/StorageHelper/AssemblyInfo.cs +3 -3
- package/package.json +1 -1
- package/sandbox/addons/browser-use-mcp/requirements.in +1 -0
- package/sandbox/addons/browser-use-mcp/requirements.txt +2350 -0
- package/sandbox/addons/chrome-devtools-mcp/package-lock.json +38 -0
- package/sandbox/addons/chrome-devtools-mcp/package.json +7 -0
- package/sandbox/addons/comet-mcp/package-lock.json +1277 -0
- package/sandbox/addons/comet-mcp/package.json +7 -0
- package/sandbox/addons/perplexity-mcp/package-lock.json +1655 -0
- package/sandbox/addons/perplexity-mcp/package.json +7 -0
- package/sandbox/scripts/add-firewall-port.ps1 +18 -4
- package/sandbox/scripts/set-machine-environment.ps1 +30 -15
- package/sandbox/templates/fivem/README.txt +6 -2
- package/sandbox/templates/fivem/cs/Client/Client.csproj +15 -0
- package/sandbox/templates/fivem/cs/Client/ClientMain.cs +20 -0
- package/sandbox/templates/fivem/cs/Server/Server.csproj +14 -0
- package/sandbox/templates/fivem/cs/Server/ServerMain.cs +20 -0
- package/sandbox/templates/fivem/cs/fxmanifest.lua +11 -0
- package/sandbox/templates/fivem/js/client.js +12 -0
- package/sandbox/templates/fivem/js/fxmanifest.lua +9 -0
- package/sandbox/templates/fivem/js/server.js +6 -0
- package/sandbox/templates/fivem/lua/client.lua +8 -0
- package/sandbox/templates/fivem/lua/fxmanifest.lua +10 -0
- package/sandbox/templates/fivem/lua/server.lua +6 -0
- package/sandbox/templates/fivem/server.cfg +37 -0
- package/sandbox/templates/fivem/ts/build.js +17 -0
- package/sandbox/templates/fivem/ts/fxmanifest.lua +9 -0
- package/sandbox/templates/fivem/ts/package.json +16 -0
- package/sandbox/templates/fivem/ts/src/client/client.ts +12 -0
- package/sandbox/templates/fivem/ts/src/client/tsconfig.json +13 -0
- package/sandbox/templates/fivem/ts/src/server/server.ts +6 -0
- package/sandbox/templates/fivem/ts/src/server/tsconfig.json +13 -0
- package/schemas/config.schema.json +56 -27
- package/schemas/sandbox-config.schema.json +37 -14
|
@@ -6,7 +6,7 @@ import path from 'node:path';
|
|
|
6
6
|
import { downloader, extractArchive, fetchJson } from '../../../../shared/download/index.js';
|
|
7
7
|
import { safeRemove } from '../../../../shared/io/safe-remove.js';
|
|
8
8
|
import { system32 } from '../../../../shared/system.js';
|
|
9
|
-
import {
|
|
9
|
+
import { runInstallerChecked } from '../../../runtime/pools.js';
|
|
10
10
|
import { exists, mkdirp } from '../../../runtime/fs.js';
|
|
11
11
|
import { log } from '../../../runtime/log.js';
|
|
12
12
|
import { msiCabs, pickMsvcVersion, pickWindowsSdk } from '../../../../core/detect/versions.js';
|
|
@@ -93,9 +93,15 @@ const unpackVsix = async (vsix, work) => {
|
|
|
93
93
|
const unpackMsi = async (msi) => {
|
|
94
94
|
const logFile = msi + '.log';
|
|
95
95
|
try {
|
|
96
|
-
await
|
|
97
|
-
|
|
98
|
-
|
|
96
|
+
await runInstallerChecked(system32('msiexec.exe'), [
|
|
97
|
+
'/a',
|
|
98
|
+
msi,
|
|
99
|
+
'/quiet',
|
|
100
|
+
'/qn',
|
|
101
|
+
'TARGETDIR=' + ROOT,
|
|
102
|
+
'/l*v',
|
|
103
|
+
logFile,
|
|
104
|
+
]);
|
|
99
105
|
}
|
|
100
106
|
catch (e) {
|
|
101
107
|
const lines = exists(logFile)
|
|
@@ -1,3 +1,5 @@
|
|
|
1
1
|
import type { Toolchains } from '../../../core/types.js';
|
|
2
2
|
import { type ToolEnv } from '../tool-env.js';
|
|
3
|
+
/** rustup-init.exe (the small installer; the toolchain itself downloads when it runs), kept with Rust's tools. */
|
|
4
|
+
export declare function fetchRustupInit(): Promise<void>;
|
|
3
5
|
export declare function setupRust(env: ToolEnv, config: Toolchains['rust'], refresh: boolean): Promise<void>;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// Rust: rustup + cargo, with crates installed prebuilt where possible (binstall.ts).
|
|
2
2
|
import path from 'node:path';
|
|
3
3
|
import { dryRun } from '../../runtime/paths.js';
|
|
4
|
-
import { execAsync } from '../../runtime/
|
|
4
|
+
import { execHeavy as execAsync } from '../../runtime/pools.js';
|
|
5
5
|
import { exists } from '../../runtime/fs.js';
|
|
6
6
|
import { log } from '../../runtime/log.js';
|
|
7
7
|
import { arch, tool, versionOf } from '../tool-env.js';
|
|
@@ -9,6 +9,15 @@ import { downloadFile } from '../install.js';
|
|
|
9
9
|
import { installOnce } from '../package-ledger.js';
|
|
10
10
|
import { crateInstaller } from './binstall.js';
|
|
11
11
|
import { installedMsvcEnv } from './msvc/index.js';
|
|
12
|
+
/** rustup-init.exe (the small installer; the toolchain itself downloads when it runs), kept with Rust's tools. */
|
|
13
|
+
export async function fetchRustupInit() {
|
|
14
|
+
const init = tool('rust', 'rustup-init.exe');
|
|
15
|
+
if (exists(init) || exists(path.join(tool('rust', 'cargo'), 'bin', 'rustup.exe')))
|
|
16
|
+
return;
|
|
17
|
+
await downloadFile('https://static.rust-lang.org/rustup/dist/' +
|
|
18
|
+
(arch === 'arm64' ? 'aarch64' : 'x86_64') +
|
|
19
|
+
'-pc-windows-msvc/rustup-init.exe', init);
|
|
20
|
+
}
|
|
12
21
|
export async function setupRust(env, config, refresh) {
|
|
13
22
|
const RUSTUP_HOME = tool('rust', 'rustup');
|
|
14
23
|
const CARGO_HOME = tool('rust', 'cargo');
|
|
@@ -21,9 +30,7 @@ export async function setupRust(env, config, refresh) {
|
|
|
21
30
|
if (!exists(rustup)) {
|
|
22
31
|
const init = tool('rust', 'rustup-init.exe');
|
|
23
32
|
log('Installing Rust with rustup (~300 MB once; the toolchain downloads after rustup itself) ...');
|
|
24
|
-
await
|
|
25
|
-
(arch === 'arm64' ? 'aarch64' : 'x86_64') +
|
|
26
|
-
'-pc-windows-msvc/rustup-init.exe', init);
|
|
33
|
+
await fetchRustupInit();
|
|
27
34
|
await execAsync(init, [
|
|
28
35
|
'-y',
|
|
29
36
|
'--no-modify-path',
|
|
@@ -2,4 +2,6 @@ import type { Toolchains } from '../../../core/types.js';
|
|
|
2
2
|
import type { ToolCtx } from '../step.js';
|
|
3
3
|
import { type ToolEnv } from '../tool-env.js';
|
|
4
4
|
export { UNREAL_COMPONENTS } from './vs-request.js';
|
|
5
|
+
/** Downloads the DirectX redistributable ahead of the install (only once the licence is accepted). */
|
|
6
|
+
export declare function fetchDirectX(config: Toolchains['unreal']): Promise<void>;
|
|
5
7
|
export declare function setupUnreal(env: ToolEnv, config: Toolchains['unreal'], ctx: ToolCtx): Promise<void>;
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
// (visual-studio.ts), which the plan runs first. The engine itself comes from the Epic Games Launcher or its source.
|
|
5
5
|
import os from 'node:os';
|
|
6
6
|
import path from 'node:path';
|
|
7
|
-
import {
|
|
7
|
+
import { runInstaller } from '../../runtime/pools.js';
|
|
8
8
|
import { safeRemove } from '../../../shared/io/safe-remove.js';
|
|
9
9
|
import { dryRun } from '../../runtime/paths.js';
|
|
10
10
|
import { exists, mkdirp } from '../../runtime/fs.js';
|
|
@@ -17,17 +17,27 @@ import { installedVs } from './visual-studio.js';
|
|
|
17
17
|
export { UNREAL_COMPONENTS } from './vs-request.js';
|
|
18
18
|
const DIRECTX_URL = 'https://download.microsoft.com/download/8/4/A/84A35BF1-DAFE-4AE8-82AF-AD2AE20B6B14/directx_Jun2010_redist.exe';
|
|
19
19
|
/** The June 2010 DirectX End-User Runtime (D3DX, XAudio 2.7, XInput 1.3), which Epic lists for the engine. */
|
|
20
|
-
|
|
20
|
+
const directXInstalled = () => {
|
|
21
21
|
const system32 = path.join(process.env.WINDIR ?? 'C:\\Windows', 'System32');
|
|
22
|
-
|
|
22
|
+
return exists(path.join(system32, 'd3dx9_43.dll')) && exists(path.join(system32, 'XAudio2_7.dll'));
|
|
23
|
+
};
|
|
24
|
+
/** The redistributable (downloaded once, signature checked). */
|
|
25
|
+
const directXRedist = () => signedInstaller(DIRECTX_URL, path.join(tool('visualstudio'), 'directx_Jun2010_redist.exe'), 'the DirectX End-User Runtime (~95 MB once)', SIGNERS.microsoft);
|
|
26
|
+
/** Downloads the DirectX redistributable ahead of the install (only once the licence is accepted). */
|
|
27
|
+
export async function fetchDirectX(config) {
|
|
28
|
+
if (config.acceptLicense && !directXInstalled())
|
|
29
|
+
await directXRedist();
|
|
30
|
+
}
|
|
31
|
+
async function installDirectX() {
|
|
32
|
+
if (directXInstalled())
|
|
23
33
|
return;
|
|
24
|
-
const redist = await
|
|
34
|
+
const redist = await directXRedist();
|
|
25
35
|
const unpacked = path.join(os.tmpdir(), 'directx-redist');
|
|
26
36
|
safeRemove(unpacked, os.tmpdir());
|
|
27
37
|
mkdirp(unpacked);
|
|
28
|
-
if ((await
|
|
38
|
+
if ((await runInstaller(redist, ['/Q', '/T:' + unpacked])) !== 0 || !exists(path.join(unpacked, 'DXSETUP.exe')))
|
|
29
39
|
throw new Error('could not unpack the DirectX End-User Runtime');
|
|
30
|
-
const code = await
|
|
40
|
+
const code = await runInstaller(path.join(unpacked, 'DXSETUP.exe'), ['/silent']);
|
|
31
41
|
safeRemove(unpacked, os.tmpdir());
|
|
32
42
|
if (code !== 0)
|
|
33
43
|
throw new Error('the DirectX End-User Runtime installer failed (exit ' + code + ')');
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { type ToolEnv } from '../tool-env.js';
|
|
2
|
+
/** Downloads the installer ahead of `setupVcRuntime` (nothing when the runtime or the installer is there). */
|
|
3
|
+
export declare function fetchVcRuntime(): Promise<void>;
|
|
2
4
|
/**
|
|
3
5
|
* A real installer (it writes to System32), so it runs on every boot; the installer itself is kept in persistent
|
|
4
6
|
* storage and only run when Microsoft's signature on it checks out. Resolves true when this call ran the installer.
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// The Visual C++ runtime (vcruntime140.dll & co.) that PHP and other native tools need.
|
|
2
2
|
import fs from 'node:fs';
|
|
3
3
|
import path from 'node:path';
|
|
4
|
-
import {
|
|
4
|
+
import { runInstaller } from '../../runtime/pools.js';
|
|
5
5
|
import { dryRun } from '../../runtime/paths.js';
|
|
6
6
|
import { exists } from '../../runtime/fs.js';
|
|
7
7
|
import { log } from '../../runtime/log.js';
|
|
@@ -11,6 +11,14 @@ import { tool } from '../tool-env.js';
|
|
|
11
11
|
const VC_REDIST = 'https://aka.ms/vs/17/release/vc_redist.x64.exe';
|
|
12
12
|
/** 1638: a newer version is already installed; 3010: installed, a restart would finish it (not needed for the DLLs). */
|
|
13
13
|
const OK_EXIT_CODES = [0, 1638, 3010];
|
|
14
|
+
/** Downloads the installer ahead of `setupVcRuntime` (nothing when the runtime or the installer is there). */
|
|
15
|
+
export async function fetchVcRuntime() {
|
|
16
|
+
const system32 = path.join(process.env.WINDIR ?? 'C:\\Windows', 'System32');
|
|
17
|
+
const installer = tool('vcredist', 'vc_redist.x64.exe');
|
|
18
|
+
if (exists(installer) || exists(path.join(system32, 'vcruntime140.dll')))
|
|
19
|
+
return;
|
|
20
|
+
await downloadFile(VC_REDIST, installer);
|
|
21
|
+
}
|
|
14
22
|
/**
|
|
15
23
|
* A real installer (it writes to System32), so it runs on every boot; the installer itself is kept in persistent
|
|
16
24
|
* storage and only run when Microsoft's signature on it checks out. Resolves true when this call ran the installer.
|
|
@@ -34,7 +42,7 @@ export async function setupVcRuntime(env, summary = true) {
|
|
|
34
42
|
throw new Error('vc_redist.x64.exe is not signed by Microsoft; deleted it (it is downloaded again next boot)');
|
|
35
43
|
}
|
|
36
44
|
log('Installing the Visual C++ runtime ...');
|
|
37
|
-
const code = await
|
|
45
|
+
const code = await runInstaller(installer, ['/install', '/quiet', '/norestart']);
|
|
38
46
|
if (!OK_EXIT_CODES.includes(code ?? -1) || !exists(path.join(system32, 'vcruntime140.dll')))
|
|
39
47
|
throw new Error('the Visual C++ runtime installer failed (exit ' + code + ')');
|
|
40
48
|
}
|
|
@@ -6,9 +6,12 @@ export declare function installedVs(): {
|
|
|
6
6
|
path: string;
|
|
7
7
|
version: string;
|
|
8
8
|
} | null;
|
|
9
|
+
/** Downloads the bootstrapper now, so the install later starts without waiting for it. */
|
|
10
|
+
export declare function prefetchVisualStudio(req: VsRequest): Promise<void>;
|
|
9
11
|
/** Visual Studio as asked for: installed at boot when it is not there yet; its folder and version. */
|
|
10
12
|
export declare function ensureVisualStudio(env: ToolEnv, req: VsRequest, o: {
|
|
11
13
|
keepInstallFiles: boolean;
|
|
14
|
+
lowPriority?: boolean;
|
|
12
15
|
}): Promise<{
|
|
13
16
|
path: string;
|
|
14
17
|
version: string;
|
|
@@ -9,6 +9,7 @@ import os from 'node:os';
|
|
|
9
9
|
import path from 'node:path';
|
|
10
10
|
import { z } from 'zod';
|
|
11
11
|
import { spawnAsync } from '../../../shared/download/index.js';
|
|
12
|
+
import { heavy, runInstaller } from '../../runtime/pools.js';
|
|
12
13
|
import { writeJsonAtomic } from '../../../shared/io/json.js';
|
|
13
14
|
import { robocopyFailed } from '../../../shared/io/robocopy-result.js';
|
|
14
15
|
import { safeRemove } from '../../../shared/io/safe-remove.js';
|
|
@@ -18,11 +19,12 @@ import { exists, mkdirp } from '../../runtime/fs.js';
|
|
|
18
19
|
import { log, warn } from '../../runtime/log.js';
|
|
19
20
|
import { logsDir } from '../../runtime/paths.js';
|
|
20
21
|
import { duringSession } from '../../runtime/project-context.js';
|
|
22
|
+
import { backgroundRunning } from '../../runtime/status.js';
|
|
21
23
|
import { errMsg } from '../../../core/util/errors.js';
|
|
22
24
|
import { SIGNERS, signedInstaller } from '../installers.js';
|
|
23
|
-
import { assertLocalRoom, freeBytes
|
|
25
|
+
import { assertLocalRoom, freeBytes } from '../persisted.js';
|
|
24
26
|
import { tool } from '../tool-env.js';
|
|
25
|
-
import { layoutNextStep, vsExitText } from './vs-request.js';
|
|
27
|
+
import { LAYOUT_STAGING_BYTES, layoutNextStep, STAGING_RESERVE_BYTES, vsExitText, } from './vs-request.js';
|
|
26
28
|
export { BUILD_TOOLS_COMPONENTS, UNREAL_COMPONENTS, unrealUsesAutosdk, visualStudioWanted, } from './vs-request.js';
|
|
27
29
|
const BOOTSTRAPPERS = {
|
|
28
30
|
community: {
|
|
@@ -120,11 +122,11 @@ function reportLayoutFailure(code, temps) {
|
|
|
120
122
|
/** Copies a finished layout onto the data disk (never /MOV: mapped folders refuse rename-over). */
|
|
121
123
|
async function copyLayout(from, to) {
|
|
122
124
|
mkdirp(to);
|
|
123
|
-
const code = await spawnAsync(SYSTEM.robocopy(), [from, to, '/E', '/COPY:DAT', '/R:1', '/W:1', '/MT:8', '/NP']);
|
|
125
|
+
const code = await heavy.run(() => spawnAsync(SYSTEM.robocopy(), [from, to, '/E', '/COPY:DAT', '/R:1', '/W:1', '/MT:8', '/NP']));
|
|
124
126
|
return !robocopyFailed(code);
|
|
125
127
|
}
|
|
126
128
|
/** The offline copy's installer when it holds every component; made or completed when there is room. */
|
|
127
|
-
async function layoutInstaller(req, bootstrapper) {
|
|
129
|
+
async function layoutInstaller(req, bootstrapper, lowPriority) {
|
|
128
130
|
const layout = layoutDir(req.product);
|
|
129
131
|
const marker = path.join(layout, '.complete.json');
|
|
130
132
|
const installer = path.join(layout, BOOTSTRAPPERS[req.product].file);
|
|
@@ -151,24 +153,21 @@ async function layoutInstaller(req, bootstrapper) {
|
|
|
151
153
|
}
|
|
152
154
|
log('Saving the Visual Studio install files for later boots (~10 GB, once) ...');
|
|
153
155
|
fs.rmSync(marker, { force: true });
|
|
154
|
-
//
|
|
155
|
-
//
|
|
156
|
-
|
|
157
|
-
const code = await spawnAsync(bootstrapper, layoutArgs(req, layout), {
|
|
158
|
-
env: { ...process.env, TEMP: scratch, TMP: scratch },
|
|
159
|
-
});
|
|
160
|
-
if (OK_EXIT_CODES.includes(code) && exists(installer))
|
|
161
|
-
return finish();
|
|
162
|
-
reportLayoutFailure(code, [scratch, os.tmpdir()]);
|
|
163
|
-
// (b) Build it on the sandbox's own disk instead, then copy it over.
|
|
156
|
+
// The installer crashes (0xE0434352) when it builds the layout in a mapped folder, so it is built on the sandbox's
|
|
157
|
+
// own disk and copied over. That runs before Visual Studio is installed and the copy on C: is deleted first, so it
|
|
158
|
+
// needs room for the layout only (STAGING_RESERVE_BYTES spare), not for the layout and the install together.
|
|
164
159
|
const drive = (process.env.SystemDrive ?? 'C:') + '\\';
|
|
165
|
-
if (layoutNextStep(
|
|
166
|
-
warn('Visual Studio:
|
|
160
|
+
if (layoutNextStep(null, freeBytes(drive), STAGING_RESERVE_BYTES) !== 'stage') {
|
|
161
|
+
warn('Visual Studio: less than ' +
|
|
162
|
+
Math.round((LAYOUT_STAGING_BYTES + STAGING_RESERVE_BYTES) / 1024 ** 3) +
|
|
163
|
+
' GB free on ' +
|
|
164
|
+
drive +
|
|
165
|
+
' to build the install files; downloading this boot');
|
|
167
166
|
return null;
|
|
168
167
|
}
|
|
169
168
|
const staging = path.join(drive, 'vs-layout-staging');
|
|
170
169
|
log('Building the install files on ' + drive + ' and copying them to ' + layout + ' ...');
|
|
171
|
-
const stagedCode = await
|
|
170
|
+
const stagedCode = await runInstaller(bootstrapper, layoutArgs(req, staging), { lowPriority });
|
|
172
171
|
const staged = path.join(staging, BOOTSTRAPPERS[req.product].file);
|
|
173
172
|
let kept = false;
|
|
174
173
|
if (OK_EXIT_CODES.includes(stagedCode) && exists(staged)) {
|
|
@@ -182,27 +181,44 @@ async function layoutInstaller(req, bootstrapper) {
|
|
|
182
181
|
safeRemove(staging, drive);
|
|
183
182
|
return kept && exists(installer) ? finish() : null;
|
|
184
183
|
}
|
|
185
|
-
|
|
184
|
+
/** The bootstrapper, downloaded (net pool) and checked; kept in tools\ for later boots. */
|
|
185
|
+
function bootstrapperFor(req) {
|
|
186
|
+
const boot = BOOTSTRAPPERS[req.product];
|
|
187
|
+
return signedInstaller(boot.url, path.join(VS_DIR, boot.file), 'the ' + boot.name + ' installer', SIGNERS.microsoft);
|
|
188
|
+
}
|
|
189
|
+
/** Downloads the bootstrapper now, so the install later starts without waiting for it. */
|
|
190
|
+
export async function prefetchVisualStudio(req) {
|
|
191
|
+
if (!req.accepted || installedVs())
|
|
192
|
+
return;
|
|
193
|
+
await bootstrapperFor(req);
|
|
194
|
+
}
|
|
195
|
+
async function install(req, keepInstallFiles, lowPriority) {
|
|
186
196
|
const boot = BOOTSTRAPPERS[req.product];
|
|
187
|
-
const bootstrapper = await
|
|
197
|
+
const bootstrapper = await bootstrapperFor(req);
|
|
188
198
|
let installer = null;
|
|
189
199
|
if (keepInstallFiles) {
|
|
190
200
|
try {
|
|
191
|
-
installer = await layoutInstaller(req, bootstrapper);
|
|
201
|
+
installer = await layoutInstaller(req, bootstrapper, lowPriority);
|
|
192
202
|
}
|
|
193
203
|
catch (e) {
|
|
194
204
|
warn('Visual Studio: the offline copy failed (' + errMsg(e) + '); downloading this boot');
|
|
195
205
|
}
|
|
196
206
|
}
|
|
197
|
-
|
|
198
|
-
const code = await spawnAsync(installer ?? bootstrapper, [
|
|
207
|
+
const run = (from, offline) => runInstaller(from, [
|
|
199
208
|
'--quiet',
|
|
200
209
|
'--wait',
|
|
201
210
|
'--norestart',
|
|
202
211
|
'--nocache',
|
|
203
|
-
...(
|
|
212
|
+
...(offline ? ['--noWeb'] : []),
|
|
204
213
|
...req.components.flatMap((id) => ['--add', id]),
|
|
205
|
-
]);
|
|
214
|
+
], { lowPriority });
|
|
215
|
+
log('Installing ' + boot.name + (installer ? ' from the saved install files' : ' (downloads ~5-8 GB)') + ' ...');
|
|
216
|
+
let code = await run(installer ?? bootstrapper, installer !== null);
|
|
217
|
+
if (installer && (!OK_EXIT_CODES.includes(code) || !installedVs())) {
|
|
218
|
+
// The saved copy is on the shared data disk: if installing from it fails, this boot downloads instead.
|
|
219
|
+
warn('Visual Studio: installing from the saved install files failed (' + vsExitText(code) + '); downloading');
|
|
220
|
+
code = await run(bootstrapper, false);
|
|
221
|
+
}
|
|
206
222
|
if (!OK_EXIT_CODES.includes(code) || !installedVs())
|
|
207
223
|
throw new Error('the Visual Studio installer failed (exit ' +
|
|
208
224
|
code +
|
|
@@ -226,9 +242,11 @@ export async function ensureVisualStudio(env, req, o) {
|
|
|
226
242
|
if (have)
|
|
227
243
|
return have;
|
|
228
244
|
if (duringSession())
|
|
229
|
-
throw new Error('Visual Studio
|
|
245
|
+
throw new Error(backgroundRunning('Visual Studio')
|
|
246
|
+
? 'Visual Studio is still installing in the background; it is ready in a few minutes'
|
|
247
|
+
: 'Visual Studio is installed when the sandbox starts: restart it (sandbox restart) to get it');
|
|
230
248
|
assertLocalRoom(INSTALL_BYTES[req.product], BOOTSTRAPPERS[req.product].name);
|
|
231
|
-
await install(req, o.keepInstallFiles);
|
|
249
|
+
await install(req, o.keepInstallFiles, o.lowPriority === true);
|
|
232
250
|
const vs = installedVs();
|
|
233
251
|
env.summary.push('visual studio: ' +
|
|
234
252
|
BOOTSTRAPPERS[req.product].name +
|
|
@@ -23,6 +23,8 @@ export declare function unrealUsesAutosdk(t: Toolchains, on?: (setting: boolean
|
|
|
23
23
|
export declare function vsExitText(code: number): string;
|
|
24
24
|
/** Room the staging copy of the layout needs on the sandbox's own disk, on top of the reserve. */
|
|
25
25
|
export declare const LAYOUT_STAGING_BYTES: number;
|
|
26
|
+
/** Spare room on the sandbox's disk while the layout is built there (before Visual Studio is installed). */
|
|
27
|
+
export declare const STAGING_RESERVE_BYTES: number;
|
|
26
28
|
/**
|
|
27
29
|
* What to do after the layout attempt in the data disk: 'done' when it worked, 'stage' (build it on the sandbox's
|
|
28
30
|
* own disk and copy it over) when it failed and that disk has room, 'skip' (download this boot) otherwise.
|
|
@@ -76,6 +76,8 @@ export function vsExitText(code) {
|
|
|
76
76
|
}
|
|
77
77
|
/** Room the staging copy of the layout needs on the sandbox's own disk, on top of the reserve. */
|
|
78
78
|
export const LAYOUT_STAGING_BYTES = 12 * 1024 ** 3;
|
|
79
|
+
/** Spare room on the sandbox's disk while the layout is built there (before Visual Studio is installed). */
|
|
80
|
+
export const STAGING_RESERVE_BYTES = 3 * 1024 ** 3;
|
|
79
81
|
/**
|
|
80
82
|
* What to do after the layout attempt in the data disk: 'done' when it worked, 'stage' (build it on the sandbox's
|
|
81
83
|
* own disk and copy it over) when it failed and that disk has room, 'skip' (download this boot) otherwise.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { appsNeedMesa, appsNeedUv, setupApps } from '../apps/index.js';
|
|
1
|
+
import { appsNeedMesa, appsNeedUv, prefetchApps, setupApps } from '../apps/index.js';
|
|
2
2
|
import { dryRun } from '../runtime/paths.js';
|
|
3
3
|
import { wanted } from './detect.js';
|
|
4
4
|
import { DATABASE_NAMES, setupDatabase } from '../databases/index.js';
|
|
@@ -11,17 +11,17 @@ import { setupCpp } from './native/cpp.js';
|
|
|
11
11
|
import { setupDotnet } from './native/dotnet.js';
|
|
12
12
|
import { setupMesa } from './native/mesa.js';
|
|
13
13
|
import { setupMsvc } from './native/msvc/index.js';
|
|
14
|
-
import { setupUnreal } from './native/unreal.js';
|
|
15
|
-
import { setupRust } from './native/rust.js';
|
|
14
|
+
import { fetchDirectX, setupUnreal } from './native/unreal.js';
|
|
15
|
+
import { fetchRustupInit, setupRust } from './native/rust.js';
|
|
16
16
|
import { setupNode } from './languages/node.js';
|
|
17
17
|
import { setupPwsh } from './tools/pwsh.js';
|
|
18
18
|
import { setupPython } from './languages/python.js';
|
|
19
19
|
import { setupBun, setupDeno, setupUv } from './runtimes.js';
|
|
20
|
-
import { setupPhp } from './languages/php.js';
|
|
20
|
+
import { fetchPhp, setupPhp } from './languages/php.js';
|
|
21
21
|
import { setupRuby } from './languages/ruby.js';
|
|
22
|
-
import { setupVcRuntime } from './native/vcruntime.js';
|
|
22
|
+
import { fetchVcRuntime, setupVcRuntime } from './native/vcruntime.js';
|
|
23
23
|
import { setupVscode } from './tools/vscode.js';
|
|
24
|
-
import { ensureVisualStudio, unrealUsesAutosdk, visualStudioWanted } from './native/visual-studio.js';
|
|
24
|
+
import { ensureVisualStudio, prefetchVisualStudio, unrealUsesAutosdk, visualStudioWanted, } from './native/visual-studio.js';
|
|
25
25
|
import { duringSession } from '../runtime/project-context.js';
|
|
26
26
|
import { setupSteam } from './steam/steam.js';
|
|
27
27
|
import { setupGodot } from './engines/godot.js';
|
|
@@ -49,6 +49,9 @@ export function plan(config, versions, o) {
|
|
|
49
49
|
pcInstalls: o.pcInstalls ?? { items: [] },
|
|
50
50
|
duringSession: duringSession(),
|
|
51
51
|
};
|
|
52
|
+
// Downloads that run ahead of their steps (the scheduler starts them at once); a dry run downloads nothing.
|
|
53
|
+
const ahead = (work) => (dryRun ? {} : { fetch: work });
|
|
54
|
+
const deferred = o.deferHeavy === true && !dryRun;
|
|
52
55
|
return [
|
|
53
56
|
{
|
|
54
57
|
name: 'Git',
|
|
@@ -71,8 +74,10 @@ export function plan(config, versions, o) {
|
|
|
71
74
|
name: 'Visual Studio',
|
|
72
75
|
enabled: vs !== null,
|
|
73
76
|
shared: true,
|
|
77
|
+
background: deferred,
|
|
78
|
+
...ahead(() => prefetchVisualStudio(vs)),
|
|
74
79
|
install: async (env) => {
|
|
75
|
-
await ensureVisualStudio(env, vs, { keepInstallFiles: config.unreal.keepInstallFiles });
|
|
80
|
+
await ensureVisualStudio(env, vs, { keepInstallFiles: config.unreal.keepInstallFiles, lowPriority: deferred });
|
|
76
81
|
},
|
|
77
82
|
},
|
|
78
83
|
{
|
|
@@ -80,6 +85,7 @@ export function plan(config, versions, o) {
|
|
|
80
85
|
enabled: unreal,
|
|
81
86
|
shared: true,
|
|
82
87
|
after: ['Visual Studio', 'MSVC'],
|
|
88
|
+
...ahead(() => fetchDirectX(config.unreal)),
|
|
83
89
|
install: (env) => setupUnreal(env, config.unreal, ctx),
|
|
84
90
|
},
|
|
85
91
|
{
|
|
@@ -94,7 +100,9 @@ export function plan(config, versions, o) {
|
|
|
94
100
|
{
|
|
95
101
|
name: 'Rust',
|
|
96
102
|
enabled: wanted(config.rust.enabled, 'rust'),
|
|
97
|
-
|
|
103
|
+
// Only the msvc host links with Visual Studio (and Unreal's tools): the GNU host does not wait for them.
|
|
104
|
+
after: rustHost(config).endsWith('-msvc') ? ['C/C++', 'MSVC', 'Visual Studio', 'Unreal'] : ['C/C++'],
|
|
105
|
+
...ahead(fetchRustupInit),
|
|
98
106
|
install: async (env) => {
|
|
99
107
|
await setupRust(env, { ...config.rust, host: rustHost(config) }, o.refresh);
|
|
100
108
|
const rust = resolveTargetDir(config.rust);
|
|
@@ -164,6 +172,7 @@ export function plan(config, versions, o) {
|
|
|
164
172
|
name: 'Visual C++ runtime',
|
|
165
173
|
enabled: config.vcRuntime.enabled || apps,
|
|
166
174
|
shared: true,
|
|
175
|
+
...ahead(fetchVcRuntime),
|
|
167
176
|
install: async (env) => {
|
|
168
177
|
await setupVcRuntime(env);
|
|
169
178
|
},
|
|
@@ -172,6 +181,7 @@ export function plan(config, versions, o) {
|
|
|
172
181
|
name: 'PHP',
|
|
173
182
|
enabled: wanted(config.php.enabled, 'php'),
|
|
174
183
|
after: ['Visual C++ runtime'],
|
|
184
|
+
...ahead(() => fetchPhp(config.php)),
|
|
175
185
|
install: (env) => setupPhp(env, config.php),
|
|
176
186
|
},
|
|
177
187
|
{ name: 'Deno', enabled: wanted(config.deno.enabled, 'deno'), install: (env) => setupDeno(env) },
|
|
@@ -208,6 +218,7 @@ export function plan(config, versions, o) {
|
|
|
208
218
|
enabled: apps,
|
|
209
219
|
shared: true,
|
|
210
220
|
after: ['Mesa 3D', 'Visual C++ runtime', 'uv'],
|
|
221
|
+
...ahead(() => prefetchApps(o.apps, { gitAccess: o.gitAccess, refresh: o.refresh })),
|
|
211
222
|
install: (env) => setupApps(env, o.apps, { gitAccess: o.gitAccess, refresh: o.refresh }),
|
|
212
223
|
},
|
|
213
224
|
{
|
|
@@ -1,22 +1,3 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
export interface RunOptions {
|
|
4
|
-
/** Progress lines ("Installing Go, Rust (3 of 9 done)"); default: the sandbox's boot status. */
|
|
5
|
-
report?: (message: string) => void;
|
|
6
|
-
/** What machine-wide (shared) steps contributed at boot: reused instead of run again. */
|
|
7
|
-
reuse?: Record<string, ToolEnv>;
|
|
8
|
-
}
|
|
9
|
-
export declare class StepScheduler {
|
|
10
|
-
private readonly parallel;
|
|
11
|
-
/** One lock per kind of step ("Node 20" and "Node 22" share nvm's folders): held while that step runs, in any run. */
|
|
12
|
-
private readonly locks;
|
|
13
|
-
/** The step a download belongs to (several run at once), for its progress. */
|
|
14
|
-
private readonly currentStep;
|
|
15
|
-
constructor(parallel?: number);
|
|
16
|
-
/** Runs the steps (each with its own environment) and returns each step's environment, in plan order. */
|
|
17
|
-
run(steps: readonly ToolchainStep[], o: RunOptions): Promise<Map<string, ToolEnv>>;
|
|
18
|
-
/** Runs `work` once no other step of the same kind (first word of the name) is running. */
|
|
19
|
-
private exclusive;
|
|
20
|
-
}
|
|
21
|
-
/** The one scheduler: its locks span the boot's run and every project's run. */
|
|
1
|
+
import { StepScheduler } from './step-scheduler.js';
|
|
2
|
+
export { StepScheduler, type RunOptions, type SchedulerSink } from './step-scheduler.js';
|
|
22
3
|
export declare const scheduler: StepScheduler;
|
|
@@ -1,123 +1,9 @@
|
|
|
1
|
-
//
|
|
2
|
-
// held across runs: the boot and projects that join later never install two Nodes (or two Gos) at once.
|
|
3
|
-
import { AsyncLocalStorage } from 'node:async_hooks';
|
|
4
|
-
import { downloader } from '../../shared/download/index.js';
|
|
1
|
+
// The one scheduler: its locks span the boot's run and every project's run.
|
|
5
2
|
import { warn } from '../runtime/log.js';
|
|
6
3
|
import { setSandboxStatus } from '../runtime/status.js';
|
|
7
|
-
import {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
try {
|
|
14
|
-
await work();
|
|
15
|
-
}
|
|
16
|
-
catch (e) {
|
|
17
|
-
warn(name +
|
|
18
|
-
' could not be set up and is skipped; everything else still works, and the next start tries again. Reason: ' +
|
|
19
|
-
errMsg(e));
|
|
20
|
-
env.summary.push(name + ': FAILED');
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
export class StepScheduler {
|
|
24
|
-
parallel;
|
|
25
|
-
/** One lock per kind of step ("Node 20" and "Node 22" share nvm's folders): held while that step runs, in any run. */
|
|
26
|
-
locks = new Map();
|
|
27
|
-
/** The step a download belongs to (several run at once), for its progress. */
|
|
28
|
-
currentStep = new AsyncLocalStorage();
|
|
29
|
-
constructor(parallel = PARALLEL) {
|
|
30
|
-
this.parallel = parallel;
|
|
31
|
-
}
|
|
32
|
-
/** Runs the steps (each with its own environment) and returns each step's environment, in plan order. */
|
|
33
|
-
async run(steps, o) {
|
|
34
|
-
const envs = new Map(steps.map((s) => [s.name, emptyEnv()]));
|
|
35
|
-
const finished = new Map();
|
|
36
|
-
const running = new Set();
|
|
37
|
-
const waiting = [];
|
|
38
|
-
let done = 0;
|
|
39
|
-
// The boot (no `report`) also publishes structured progress: what runs now, how far its download is, how many are
|
|
40
|
-
// done.
|
|
41
|
-
const percent = new Map();
|
|
42
|
-
const active = () => [...running].map((name) => ({ name, ...(percent.has(name) ? { percent: percent.get(name) } : {}) }));
|
|
43
|
-
const say = o.report ??
|
|
44
|
-
((message) => setSandboxStatus('provisioning', message, { active: active(), done, total: steps.length }));
|
|
45
|
-
const report = () => {
|
|
46
|
-
if (running.size)
|
|
47
|
-
say('Installing ' + [...running].join(', ') + ' (' + done + ' of ' + steps.length + ' done)');
|
|
48
|
-
};
|
|
49
|
-
if (!o.report)
|
|
50
|
-
downloader.watch(() => {
|
|
51
|
-
const name = this.currentStep.getStore();
|
|
52
|
-
return name
|
|
53
|
-
? (fraction) => {
|
|
54
|
-
percent.set(name, Math.round(fraction * 100));
|
|
55
|
-
report();
|
|
56
|
-
}
|
|
57
|
-
: null;
|
|
58
|
-
});
|
|
59
|
-
for (const s of steps) {
|
|
60
|
-
// Dependencies first (they are earlier in the plan, so their promises exist), then a free slot.
|
|
61
|
-
finished.set(s.name, (async () => {
|
|
62
|
-
await Promise.all((s.after ?? []).map((name) => finished.get(name)));
|
|
63
|
-
const env = envs.get(s.name);
|
|
64
|
-
const reused = s.shared ? o.reuse?.[s.name] : undefined;
|
|
65
|
-
if (reused) {
|
|
66
|
-
envs.set(s.name, structuredClone(reused));
|
|
67
|
-
done++;
|
|
68
|
-
return;
|
|
69
|
-
}
|
|
70
|
-
while (running.size >= this.parallel)
|
|
71
|
-
await new Promise((r) => waiting.push(r));
|
|
72
|
-
running.add(s.name);
|
|
73
|
-
report();
|
|
74
|
-
try {
|
|
75
|
-
await this.currentStep.run(s.name, () => this.exclusive(s.name, () => runReported(s.name, env, async () => s.install(env))));
|
|
76
|
-
}
|
|
77
|
-
finally {
|
|
78
|
-
running.delete(s.name);
|
|
79
|
-
percent.delete(s.name);
|
|
80
|
-
done++;
|
|
81
|
-
report();
|
|
82
|
-
waiting.shift()?.();
|
|
83
|
-
}
|
|
84
|
-
})());
|
|
85
|
-
}
|
|
86
|
-
try {
|
|
87
|
-
await Promise.all(finished.values());
|
|
88
|
-
}
|
|
89
|
-
finally {
|
|
90
|
-
if (!o.report)
|
|
91
|
-
downloader.watch(null);
|
|
92
|
-
}
|
|
93
|
-
if (!o.report)
|
|
94
|
-
setSandboxStatus('provisioning', 'Set up ' + steps.length + ' toolchains and databases', {
|
|
95
|
-
active: [],
|
|
96
|
-
done,
|
|
97
|
-
total: steps.length,
|
|
98
|
-
});
|
|
99
|
-
return envs;
|
|
100
|
-
}
|
|
101
|
-
/** Runs `work` once no other step of the same kind (first word of the name) is running. */
|
|
102
|
-
async exclusive(name, work) {
|
|
103
|
-
const key = name.split(' ')[0].toLowerCase();
|
|
104
|
-
const previous = this.locks.get(key) ?? Promise.resolve();
|
|
105
|
-
let release = () => undefined;
|
|
106
|
-
const mine = new Promise((r) => {
|
|
107
|
-
release = r;
|
|
108
|
-
});
|
|
109
|
-
const chained = previous.then(() => mine);
|
|
110
|
-
this.locks.set(key, chained);
|
|
111
|
-
await previous;
|
|
112
|
-
try {
|
|
113
|
-
return await work();
|
|
114
|
-
}
|
|
115
|
-
finally {
|
|
116
|
-
release();
|
|
117
|
-
if (this.locks.get(key) === chained)
|
|
118
|
-
this.locks.delete(key);
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
/** The one scheduler: its locks span the boot's run and every project's run. */
|
|
123
|
-
export const scheduler = new StepScheduler();
|
|
4
|
+
import { StepScheduler } from './step-scheduler.js';
|
|
5
|
+
export { StepScheduler } from './step-scheduler.js';
|
|
6
|
+
export const scheduler = new StepScheduler({
|
|
7
|
+
warn,
|
|
8
|
+
status: (message, progress) => setSandboxStatus('provisioning', message, progress),
|
|
9
|
+
});
|
|
@@ -5,6 +5,19 @@ import { type RunOptions } from './scheduler.js';
|
|
|
5
5
|
/** The combined environment, plus what each step contributed (kept so later projects reuse the shared steps). */
|
|
6
6
|
export interface ToolchainResult extends ToolEnv {
|
|
7
7
|
steps: Record<string, ToolEnv>;
|
|
8
|
+
/** Every enabled step of the plan (foreground and background), in plan order: the order the parts are merged in. */
|
|
9
|
+
names: string[];
|
|
8
10
|
}
|
|
9
|
-
|
|
10
|
-
|
|
11
|
+
export interface SetupExtras {
|
|
12
|
+
/** The background steps start once this resolves (the boot: the agent's first session is running). */
|
|
13
|
+
gate?: Promise<void>;
|
|
14
|
+
}
|
|
15
|
+
/** The parts of these steps merged in the order of `names` (and the config's own variables on top). */
|
|
16
|
+
export declare function mergeToolchains(config: Toolchains, names: readonly string[], parts: ReadonlyMap<string, ToolEnv> | Readonly<Record<string, ToolEnv>>, planNames?: readonly string[]): ToolchainResult;
|
|
17
|
+
/**
|
|
18
|
+
* Provisions every enabled toolchain and database, and returns the combined environment for the agent. `later` is
|
|
19
|
+
* set when steps were left for the background: it resolves with the result of those steps alone.
|
|
20
|
+
*/
|
|
21
|
+
export declare function setupToolchains(config: Toolchains, versions: ToolVersions, options: ToolchainOptions, run?: RunOptions, extras?: SetupExtras): Promise<ToolchainResult & {
|
|
22
|
+
later: Promise<ToolchainResult> | null;
|
|
23
|
+
}>;
|