windows-development-sandbox 1.0.5 → 1.4.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/LICENSE +21 -0
- package/README.md +25 -8
- package/config.example.json +55 -5
- package/dist/api.js +2 -1
- package/dist/cli/args.d.ts +23 -0
- package/dist/cli/args.js +38 -4
- package/dist/cli/colors.d.ts +24 -0
- package/dist/cli/colors.js +42 -0
- package/dist/cli/commands/accounts.js +2 -2
- package/dist/cli/commands/agent-commands.d.ts +6 -0
- package/dist/cli/commands/agent-commands.js +61 -0
- package/dist/cli/commands/context.d.ts +2 -0
- package/dist/cli/commands/context.js +5 -1
- package/dist/cli/commands/data/clean.d.ts +15 -0
- package/dist/cli/commands/data/clean.js +106 -0
- package/dist/cli/commands/data/collect.d.ts +11 -0
- package/dist/cli/commands/data/collect.js +54 -0
- package/dist/cli/commands/data/index.d.ts +4 -0
- package/dist/cli/commands/data/index.js +45 -0
- package/dist/cli/commands/data/remove.d.ts +2 -0
- package/dist/cli/commands/data/remove.js +30 -0
- package/dist/cli/commands/index.d.ts +6 -4
- package/dist/cli/commands/index.js +6 -4
- package/dist/cli/commands/launch.d.ts +26 -2
- package/dist/cli/commands/launch.js +256 -42
- package/dist/cli/commands/maintenance.d.ts +2 -0
- package/dist/cli/commands/maintenance.js +67 -5
- package/dist/cli/commands/project.d.ts +29 -0
- package/dist/cli/commands/project.js +63 -0
- package/dist/cli/commands/projects.d.ts +14 -0
- package/dist/cli/commands/projects.js +146 -0
- package/dist/cli/commands/repair/checks.d.ts +2 -0
- package/dist/cli/commands/{repair.js → repair/checks.js} +19 -181
- package/dist/cli/commands/{repair.d.ts → repair/finders.d.ts} +0 -29
- package/dist/cli/commands/repair/finders.js +108 -0
- package/dist/cli/commands/repair/index.d.ts +12 -0
- package/dist/cli/commands/repair/index.js +61 -0
- package/dist/cli/commands/repair/types.d.ts +26 -0
- package/dist/cli/commands/repair/types.js +3 -0
- package/dist/cli/commands/restart.d.ts +6 -0
- package/dist/cli/commands/restart.js +85 -0
- package/dist/cli/commands/sessions.d.ts +2 -1
- package/dist/cli/commands/sessions.js +189 -45
- package/dist/cli/commands/setup/checks.d.ts +13 -0
- package/dist/cli/commands/setup/checks.js +71 -0
- package/dist/cli/commands/{setup.d.ts → setup/facts.d.ts} +1 -15
- package/dist/cli/commands/setup/facts.js +60 -0
- package/dist/cli/commands/setup/index.d.ts +2 -0
- package/dist/cli/commands/setup/index.js +43 -0
- package/dist/cli/commands/user-config.d.ts +8 -0
- package/dist/cli/commands/user-config.js +41 -0
- package/dist/cli/history.d.ts +11 -0
- package/dist/cli/history.js +21 -0
- package/dist/cli/index.d.ts +7 -1
- package/dist/cli/index.js +42 -15
- package/dist/cli/manifest.d.ts +8 -0
- package/dist/cli/manifest.js +40 -15
- package/dist/cli/menu/apps.d.ts +21 -0
- package/dist/cli/menu/apps.js +122 -0
- package/dist/cli/menu/command-form.d.ts +28 -0
- package/dist/cli/menu/command-form.js +219 -0
- package/dist/cli/menu/index.d.ts +26 -0
- package/dist/cli/menu/index.js +180 -0
- package/dist/cli/menu/settings/categories.d.ts +9 -0
- package/dist/cli/menu/settings/categories.js +28 -0
- package/dist/cli/menu/settings/config-file.d.ts +40 -0
- package/dist/cli/menu/settings/config-file.js +71 -0
- package/dist/cli/menu/settings/editors.d.ts +30 -0
- package/dist/cli/menu/settings/editors.js +305 -0
- package/dist/cli/menu/settings/index.d.ts +32 -0
- package/dist/cli/menu/settings/index.js +136 -0
- package/dist/cli/menu/settings/schema-node.d.ts +62 -0
- package/dist/cli/menu/settings/schema-node.js +104 -0
- package/dist/cli/menu/several.d.ts +20 -0
- package/dist/cli/menu/several.js +102 -0
- package/dist/cli/progress.d.ts +9 -0
- package/dist/cli/progress.js +49 -0
- package/dist/cli/tui/app.d.ts +39 -0
- package/dist/cli/tui/app.js +52 -0
- package/dist/cli/tui/dialogs.d.ts +57 -0
- package/dist/cli/tui/dialogs.js +162 -0
- package/dist/cli/tui/frame.d.ts +18 -0
- package/dist/cli/tui/frame.js +27 -0
- package/dist/cli/tui/index.d.ts +7 -0
- package/dist/cli/tui/index.js +8 -0
- package/dist/cli/tui/list-screen.d.ts +101 -0
- package/dist/cli/tui/list-screen.js +299 -0
- package/dist/cli/tui/terminal.d.ts +37 -0
- package/dist/cli/tui/terminal.js +89 -0
- package/dist/cli/tui/text.d.ts +20 -0
- package/dist/cli/tui/text.js +105 -0
- package/dist/cli/tui/theme.d.ts +45 -0
- package/dist/cli/tui/theme.js +30 -0
- package/dist/cli/validate.d.ts +17 -0
- package/dist/cli/validate.js +89 -0
- package/dist/core/config.js +12 -6
- package/dist/core/disk.d.ts +16 -0
- package/dist/core/disk.js +55 -0
- package/dist/core/local-config.d.ts +23 -0
- package/dist/core/local-config.js +79 -7
- package/dist/core/project-policy.d.ts +15 -0
- package/dist/core/project-policy.js +35 -0
- package/dist/core/prompt.d.ts +4 -0
- package/dist/core/prompt.js +15 -0
- package/dist/core/safe-paths.d.ts +4 -0
- package/dist/core/safe-paths.js +37 -0
- package/dist/core/schema/apps.d.ts +40 -0
- package/dist/core/schema/apps.js +27 -0
- package/dist/core/schema/common.d.ts +17 -0
- package/dist/core/schema/common.js +15 -0
- package/dist/core/schema/config.d.ts +659 -0
- package/dist/core/schema/config.js +75 -0
- package/dist/core/schema/databases.d.ts +33 -0
- package/dist/core/schema/databases.js +35 -0
- package/dist/core/schema/harness.d.ts +12 -0
- package/dist/core/schema/harness.js +17 -0
- package/dist/core/schema/json-schema.d.ts +5 -0
- package/dist/core/schema/json-schema.js +25 -0
- package/dist/core/schema/profile.d.ts +32 -0
- package/dist/core/schema/profile.js +31 -0
- package/dist/core/schema/projects.d.ts +9 -0
- package/dist/core/schema/projects.js +11 -0
- package/dist/core/schema/sandbox.d.ts +78 -0
- package/dist/core/schema/sandbox.js +64 -0
- package/dist/core/schema/toolchains.d.ts +96 -0
- package/dist/core/schema/toolchains.js +88 -0
- package/dist/core/schema.d.ts +6 -604
- package/dist/core/schema.js +8 -264
- package/dist/core/types.d.ts +35 -1
- package/dist/core/util.d.ts +9 -0
- package/dist/core/util.js +14 -3
- package/dist/core/workspace.d.ts +0 -5
- package/dist/core/workspace.js +33 -50
- package/dist/guest/apps/index.d.ts +10 -0
- package/dist/guest/apps/index.js +206 -0
- package/dist/guest/apps/resolvers.d.ts +8 -0
- package/dist/guest/apps/resolvers.js +90 -0
- package/dist/guest/audit-parse.d.ts +7 -0
- package/dist/guest/audit-parse.js +24 -0
- package/dist/guest/audit.d.ts +4 -0
- package/dist/guest/audit.js +47 -0
- package/dist/guest/boot-env.d.ts +4 -0
- package/dist/guest/boot-env.js +25 -0
- package/dist/guest/cmdline.d.ts +12 -0
- package/dist/guest/cmdline.js +23 -0
- package/dist/guest/daemon/exec.d.ts +5 -0
- package/dist/guest/daemon/exec.js +32 -0
- package/dist/guest/daemon/project.d.ts +14 -0
- package/dist/guest/daemon/project.js +132 -0
- package/dist/guest/daemon/relays.d.ts +1 -0
- package/dist/guest/daemon/relays.js +18 -0
- package/dist/guest/daemon/session.d.ts +13 -0
- package/dist/guest/daemon/session.js +139 -0
- package/dist/guest/daemon/shutdown.d.ts +1 -0
- package/dist/guest/daemon/shutdown.js +21 -0
- package/dist/guest/daemon/state.d.ts +17 -0
- package/dist/guest/daemon/state.js +31 -0
- package/dist/guest/daemon.js +12 -141
- package/dist/guest/db.js +18 -3
- package/dist/guest/env.d.ts +3 -0
- package/dist/guest/env.js +7 -3
- package/dist/guest/guide.d.ts +6 -2
- package/dist/guest/guide.js +5 -4
- package/dist/guest/helpers.d.ts +3 -0
- package/dist/guest/helpers.js +26 -0
- package/dist/guest/main.js +31 -8
- package/dist/guest/netproxy.d.ts +1 -0
- package/dist/guest/netproxy.js +100 -0
- package/dist/guest/ports.d.ts +6 -0
- package/dist/guest/ports.js +22 -0
- package/dist/guest/project-context.d.ts +7 -0
- package/dist/guest/project-context.js +10 -0
- package/dist/guest/project-env.d.ts +20 -0
- package/dist/guest/project-env.js +20 -0
- package/dist/guest/project-status.d.ts +5 -0
- package/dist/guest/project-status.js +17 -0
- package/dist/guest/ptyhost.d.ts +0 -18
- package/dist/guest/ptyhost.js +17 -65
- package/dist/guest/setup/agents.d.ts +5 -2
- package/dist/guest/setup/agents.js +22 -8
- package/dist/guest/setup/claude.d.ts +0 -4
- package/dist/guest/setup/claude.js +59 -5
- package/dist/guest/setup/environment.d.ts +13 -3
- package/dist/guest/setup/environment.js +14 -10
- package/dist/guest/setup/hooks.d.ts +9 -1
- package/dist/guest/setup/hooks.js +28 -14
- package/dist/guest/setup/network.d.ts +9 -0
- package/dist/guest/setup/network.js +97 -4
- package/dist/guest/setup/user.js +4 -0
- package/dist/guest/toolchains/catalogue.d.ts +4 -0
- package/dist/guest/toolchains/catalogue.js +2 -2
- package/dist/guest/toolchains/cli.js +25 -17
- package/dist/guest/toolchains/common.d.ts +18 -1
- package/dist/guest/toolchains/common.js +34 -11
- package/dist/guest/toolchains/databases/dynamodb.d.ts +8 -0
- package/dist/guest/toolchains/databases/dynamodb.js +52 -0
- package/dist/guest/toolchains/{databases.d.ts → databases/index.d.ts} +2 -3
- package/dist/guest/toolchains/databases/index.js +62 -0
- package/dist/guest/toolchains/databases/mongodb.d.ts +3 -0
- package/dist/guest/toolchains/databases/mongodb.js +31 -0
- package/dist/guest/toolchains/databases/mysql.d.ts +3 -0
- package/dist/guest/toolchains/databases/mysql.js +38 -0
- package/dist/guest/toolchains/databases/postgres.d.ts +5 -0
- package/dist/guest/toolchains/databases/postgres.js +38 -0
- package/dist/guest/toolchains/databases/redis.d.ts +3 -0
- package/dist/guest/toolchains/databases/redis.js +16 -0
- package/dist/guest/toolchains/databases/server.d.ts +14 -0
- package/dist/guest/toolchains/databases/server.js +52 -0
- package/dist/guest/toolchains/git.js +25 -16
- package/dist/guest/toolchains/go.js +1 -1
- package/dist/guest/toolchains/index.d.ts +13 -9
- package/dist/guest/toolchains/index.js +40 -82
- package/dist/guest/toolchains/java.js +5 -5
- package/dist/guest/toolchains/leftovers.d.ts +2 -0
- package/dist/guest/toolchains/leftovers.js +26 -0
- package/dist/guest/toolchains/managers.js +12 -10
- package/dist/guest/toolchains/{binstall.js → native/binstall.js} +6 -9
- package/dist/guest/toolchains/native/cpp.d.ts +4 -0
- package/dist/guest/toolchains/native/cpp.js +38 -0
- package/dist/guest/toolchains/native/dotnet.d.ts +4 -0
- package/dist/guest/toolchains/native/dotnet.js +103 -0
- package/dist/guest/toolchains/native/mesa.d.ts +7 -0
- package/dist/guest/toolchains/native/mesa.js +56 -0
- package/dist/guest/toolchains/native/msvc/environment.d.ts +16 -0
- package/dist/guest/toolchains/native/msvc/environment.js +57 -0
- package/dist/guest/toolchains/native/msvc/index.d.ts +6 -0
- package/dist/guest/toolchains/native/msvc/index.js +48 -0
- package/dist/guest/toolchains/native/msvc/packages.d.ts +6 -0
- package/dist/guest/toolchains/native/msvc/packages.js +156 -0
- package/dist/guest/toolchains/native/msvc/tree.d.ts +15 -0
- package/dist/guest/toolchains/native/msvc/tree.js +21 -0
- package/dist/guest/toolchains/native/rust.d.ts +3 -0
- package/dist/guest/toolchains/native/rust.js +45 -0
- package/dist/guest/toolchains/node.js +26 -6
- package/dist/guest/toolchains/plan.d.ts +24 -0
- package/dist/guest/toolchains/plan.js +140 -0
- package/dist/guest/toolchains/pwsh.js +1 -1
- package/dist/guest/toolchains/python.js +43 -12
- package/dist/guest/toolchains/runtimes.d.ts +2 -0
- package/dist/guest/toolchains/runtimes.js +6 -8
- package/dist/guest/toolchains/scripting/php.d.ts +3 -0
- package/dist/guest/toolchains/scripting/php.js +71 -0
- package/dist/guest/toolchains/scripting/ruby.d.ts +3 -0
- package/dist/guest/toolchains/scripting/ruby.js +47 -0
- package/dist/guest/toolchains/scripting/vcruntime.d.ts +7 -0
- package/dist/guest/toolchains/scripting/vcruntime.js +45 -0
- package/dist/guest/toolchains/vscode-profile.d.ts +30 -0
- package/dist/guest/toolchains/vscode-profile.js +69 -0
- package/dist/guest/toolchains/vscode.d.ts +17 -0
- package/dist/guest/toolchains/vscode.js +87 -1
- package/dist/guest/view.js +21 -1
- package/dist/host/accounts.js +14 -5
- package/dist/host/agent-commands.d.ts +25 -0
- package/dist/host/agent-commands.js +145 -0
- package/dist/host/attach.d.ts +17 -0
- package/dist/host/attach.js +70 -0
- package/dist/host/audit/collect.d.ts +34 -0
- package/dist/host/audit/collect.js +126 -0
- package/dist/host/audit/log.d.ts +46 -0
- package/dist/host/audit/log.js +143 -0
- package/dist/host/channel.d.ts +23 -22
- package/dist/host/channel.js +66 -84
- package/dist/host/claude-profile.js +7 -3
- package/dist/host/cleanup.js +2 -11
- package/dist/host/database-plan.d.ts +12 -0
- package/dist/host/database-plan.js +52 -0
- package/dist/host/generate.d.ts +10 -12
- package/dist/host/generate.js +58 -135
- package/dist/host/join.d.ts +28 -0
- package/dist/host/join.js +76 -0
- package/dist/host/launch/mappings.d.ts +3 -0
- package/dist/host/launch/mappings.js +54 -0
- package/dist/host/launch/projects.d.ts +15 -0
- package/dist/host/launch/projects.js +56 -0
- package/dist/host/launch/stage.d.ts +11 -0
- package/dist/host/launch/stage.js +66 -0
- package/dist/host/launch/wsb.d.ts +10 -0
- package/dist/host/launch/wsb.js +34 -0
- package/dist/host/motw.d.ts +17 -0
- package/dist/host/motw.js +74 -0
- package/dist/host/pc-scan.d.ts +6 -0
- package/dist/host/pc-scan.js +37 -0
- package/dist/host/platform.d.ts +2 -0
- package/dist/host/platform.js +16 -1
- package/dist/host/port-forward.d.ts +8 -0
- package/dist/host/port-forward.js +37 -0
- package/dist/host/project-scan.d.ts +1 -17
- package/dist/host/project-scan.js +2 -86
- package/dist/host/projects.d.ts +100 -0
- package/dist/host/projects.js +147 -0
- package/dist/host/repo-guard.d.ts +25 -5
- package/dist/host/repo-guard.js +242 -23
- package/dist/host/stops.d.ts +67 -0
- package/dist/host/stops.js +126 -0
- package/dist/host/terminal.d.ts +8 -0
- package/dist/host/terminal.js +48 -1
- package/dist/host/test-guard.d.ts +6 -0
- package/dist/host/test-guard.js +15 -0
- package/dist/host/window.js +7 -3
- package/dist/host/workspace-view/index.d.ts +20 -0
- package/dist/host/workspace-view/index.js +53 -0
- package/dist/host/workspace-view/rules.d.ts +26 -0
- package/dist/host/workspace-view/rules.js +93 -0
- package/dist/host/workspace-view/view.d.ts +50 -0
- package/dist/host/workspace-view/view.js +281 -0
- package/dist/host/wsb.d.ts +37 -0
- package/dist/host/wsb.js +101 -0
- package/dist/runtime/daemon.js +11791 -2821
- package/dist/runtime/db.js +6585 -466
- package/dist/runtime/main.js +10238 -1724
- package/dist/runtime/netproxy.js +25936 -0
- package/dist/runtime/view.js +6183 -59
- package/dist/selftest/accounts.test.d.ts +2 -0
- package/dist/selftest/accounts.test.js +44 -0
- package/dist/selftest/agent-commands.test.d.ts +2 -0
- package/dist/selftest/agent-commands.test.js +47 -0
- package/dist/selftest/audit.test.d.ts +2 -0
- package/dist/selftest/audit.test.js +57 -0
- package/dist/selftest/channel.test.d.ts +2 -0
- package/dist/selftest/channel.test.js +44 -0
- package/dist/selftest/cli.test.d.ts +2 -2
- package/dist/selftest/cli.test.js +145 -27
- package/dist/selftest/cmdline.test.d.ts +2 -0
- package/dist/selftest/cmdline.test.js +45 -0
- package/dist/selftest/config.test.d.ts +2 -3
- package/dist/selftest/config.test.js +36 -72
- package/dist/selftest/data.test.d.ts +2 -2
- package/dist/selftest/data.test.js +77 -70
- package/dist/selftest/detect.test.d.ts +2 -2
- package/dist/selftest/detect.test.js +54 -38
- package/dist/selftest/fixtures.d.ts +89 -4
- package/dist/selftest/fixtures.js +43 -24
- package/dist/selftest/generate.test.d.ts +2 -0
- package/dist/selftest/generate.test.js +68 -0
- package/dist/selftest/git-access.test.d.ts +2 -0
- package/dist/selftest/git-access.test.js +26 -0
- package/dist/selftest/guest-boot.test.d.ts +2 -0
- package/dist/selftest/guest-boot.test.js +76 -0
- package/dist/selftest/harness.d.ts +44 -7
- package/dist/selftest/harness.js +62 -21
- package/dist/selftest/host-sim.test.d.ts +2 -0
- package/dist/selftest/host-sim.test.js +93 -0
- package/dist/selftest/hostile-input.test.d.ts +2 -0
- package/dist/selftest/hostile-input.test.js +54 -0
- package/dist/selftest/index.d.ts +8 -1
- package/dist/selftest/index.js +137 -35
- package/dist/selftest/links.test.d.ts +2 -0
- package/dist/selftest/links.test.js +50 -0
- package/dist/selftest/live-daemon.test.d.ts +2 -0
- package/dist/selftest/live-daemon.test.js +91 -0
- package/dist/selftest/live-git.test.d.ts +2 -0
- package/dist/selftest/live-git.test.js +60 -0
- package/dist/selftest/live-network.test.d.ts +2 -0
- package/dist/selftest/live-network.test.js +63 -0
- package/dist/selftest/live-projects.test.d.ts +2 -0
- package/dist/selftest/live-projects.test.js +127 -0
- package/dist/selftest/live.d.ts +65 -0
- package/dist/selftest/live.js +109 -0
- package/dist/selftest/local-config.test.d.ts +2 -0
- package/dist/selftest/local-config.test.js +120 -0
- package/dist/selftest/mirror.test.d.ts +2 -3
- package/dist/selftest/mirror.test.js +92 -65
- package/dist/selftest/network.test.d.ts +2 -0
- package/dist/selftest/network.test.js +40 -0
- package/dist/selftest/personalization.test.d.ts +2 -0
- package/dist/selftest/personalization.test.js +53 -0
- package/dist/selftest/projects.test.d.ts +2 -0
- package/dist/selftest/projects.test.js +254 -0
- package/dist/selftest/repair.test.d.ts +2 -0
- package/dist/selftest/repair.test.js +42 -0
- package/dist/selftest/repo-guard.test.d.ts +2 -0
- package/dist/selftest/repo-guard.test.js +121 -0
- package/dist/selftest/secrets.test.d.ts +2 -0
- package/dist/selftest/secrets.test.js +71 -0
- package/dist/selftest/setup.test.d.ts +2 -2
- package/dist/selftest/setup.test.js +45 -22
- package/dist/selftest/suite.d.ts +13 -0
- package/dist/selftest/suite.js +1 -0
- package/dist/selftest/sync.test.d.ts +2 -3
- package/dist/selftest/sync.test.js +130 -78
- package/dist/selftest/test-guard.test.d.ts +2 -0
- package/dist/selftest/test-guard.test.js +49 -0
- package/dist/selftest/toolchains.test.d.ts +2 -0
- package/dist/selftest/toolchains.test.js +133 -0
- package/dist/selftest/workspace-view.test.d.ts +2 -0
- package/dist/selftest/workspace-view.test.js +89 -0
- package/dist/selftest/workspace.test.d.ts +2 -0
- package/dist/selftest/workspace.test.js +53 -0
- package/dist/shared/apps.d.ts +49 -0
- package/dist/shared/apps.js +114 -0
- package/dist/shared/download.d.ts +3 -1
- package/dist/shared/download.js +19 -4
- package/dist/shared/netpolicy.d.ts +27 -0
- package/dist/shared/netpolicy.js +51 -0
- package/dist/shared/paths.d.ts +5 -0
- package/dist/shared/paths.js +6 -0
- package/dist/shared/projects.d.ts +53 -0
- package/dist/shared/projects.js +67 -0
- package/dist/shared/pty-client.d.ts +9 -4
- package/dist/shared/pty-client.js +139 -17
- package/dist/shared/rundir.d.ts +12 -1
- package/dist/shared/rundir.js +14 -4
- package/dist/shared/safe-remove.js +11 -0
- package/dist/shared/schema.d.ts +453 -0
- package/dist/shared/schema.js +43 -2
- package/dist/shared/system.d.ts +1 -0
- package/dist/shared/system.js +1 -0
- package/dist/shared/test-guard.d.ts +4 -0
- package/dist/shared/test-guard.js +37 -0
- package/dist/sync/claude-mem.js +6 -3
- package/dist/sync/history.d.ts +29 -12
- package/dist/sync/history.js +72 -25
- package/dist/sync/watcher.d.ts +8 -0
- package/dist/sync/watcher.js +99 -8
- package/package.json +7 -6
- package/sandbox/bootstrap.ps1 +258 -258
- package/sandbox/cargoshim.cs +56 -0
- package/sandbox/cpucap.cs +33 -0
- package/sandbox/cpucap.ps1 +20 -0
- package/sandbox/logon.cmd +24 -16
- package/sandbox/memlog.ps1 +34 -0
- package/sandbox/openssl.cs +42 -0
- package/sandbox/pagefile.cs +31 -0
- package/sandbox/pagefile.ps1 +21 -0
- package/sandbox/ptyhost.cs +120 -11
- package/sandbox/trust.cmd +35 -35
- package/schemas/config.schema.json +403 -3
- package/schemas/sandbox-config.schema.json +143 -13
- package/dist/cli/commands/data.d.ts +0 -46
- package/dist/cli/commands/data.js +0 -249
- package/dist/cli/commands/setup.js +0 -152
- package/dist/cli/menu.d.ts +0 -22
- package/dist/cli/menu.js +0 -187
- package/dist/cli/settings.d.ts +0 -11
- package/dist/cli/settings.js +0 -156
- package/dist/guest/toolchains/databases.js +0 -226
- package/dist/guest/toolchains/msvc.d.ts +0 -10
- package/dist/guest/toolchains/msvc.js +0 -216
- package/dist/guest/toolchains/native.d.ts +0 -12
- package/dist/guest/toolchains/native.js +0 -220
- package/dist/guest/toolchains/scripting.d.ts +0 -10
- package/dist/guest/toolchains/scripting.js +0 -137
- package/dist/selftest/guest.test.d.ts +0 -3
- package/dist/selftest/guest.test.js +0 -61
- package/dist/selftest/helpers.test.d.ts +0 -2
- package/dist/selftest/helpers.test.js +0 -125
- package/dist/selftest/host.test.d.ts +0 -2
- package/dist/selftest/host.test.js +0 -71
- package/dist/selftest/live.test.d.ts +0 -7
- package/dist/selftest/live.test.js +0 -127
- package/dist/selftest/security.test.d.ts +0 -3
- package/dist/selftest/security.test.js +0 -143
- /package/dist/guest/toolchains/{binstall.d.ts → native/binstall.d.ts} +0 -0
|
@@ -1,102 +1,54 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import { DATABASE_NAMES, setupDatabase } from './databases.js';
|
|
5
|
-
import { setupGit } from './git.js';
|
|
6
|
-
import { setupGo } from './go.js';
|
|
7
|
-
import { setupJava } from './java.js';
|
|
8
|
-
import { setupMsvc } from './msvc.js';
|
|
9
|
-
import { setupPwsh } from './pwsh.js';
|
|
10
|
-
import { setupCli } from './cli.js';
|
|
11
|
-
import { setupPyenv, setupVolta, wantsPyenv, wantsVolta } from './managers.js';
|
|
12
|
-
import { setupNode } from './node.js';
|
|
13
|
-
import { setupPython } from './python.js';
|
|
14
|
-
import { setupCpp, setupDotnet, setupMesa, setupRust } from './native.js';
|
|
15
|
-
import { setupBun, setupDeno, setupUv, uvVars } from './runtimes.js';
|
|
16
|
-
import { setupPhp, setupRuby, setupVcRuntime } from './scripting.js';
|
|
17
|
-
import { setupVscode } from './vscode.js';
|
|
18
|
-
export { pickNodeVersion, pickPackageVersion } from './versions.js';
|
|
1
|
+
import { log, mkdirp, setSandboxStatus } from '../env.js';
|
|
2
|
+
import { emptyEnv, step, tool } from './common.js';
|
|
3
|
+
import { plan } from './plan.js';
|
|
19
4
|
/** How many installers run at once: enough to overlap downloads with installs, few enough not to thrash the disk. */
|
|
20
5
|
const PARALLEL = 4;
|
|
21
|
-
/**
|
|
22
|
-
const
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
}
|
|
40
|
-
/** "auto": the msvc host when the MSVC step runs (as on most PCs), else GNU with MinGW. */
|
|
41
|
-
const rustHost = (config) => {
|
|
42
|
-
if (config.rust.host !== 'auto')
|
|
43
|
-
return config.rust.host;
|
|
44
|
-
return (arch === 'arm64' ? 'aarch64' : 'x86_64') + (wanted(config.msvc.enabled, 'msvc') ? '-pc-windows-msvc' : '-pc-windows-gnu');
|
|
45
|
-
};
|
|
46
|
-
/** The toolchains and databases for this sandbox, in the order their PATH entries are listed. */
|
|
47
|
-
const plan = (config, versions, o) => {
|
|
48
|
-
const java = wanted(config.java.enabled, 'java');
|
|
49
|
-
return [
|
|
50
|
-
{ name: 'Git', on: o.gitEnabled, run: (env) => setupGit(env, o.hostGit, o.refresh, o.gitAccess) },
|
|
51
|
-
// Before Node: with package.json pins, Volta's node/npm/pnpm/yarn come first on PATH.
|
|
52
|
-
{ name: 'Volta', on: wantsVolta(config.node.volta), run: (env) => setupVolta(env) },
|
|
53
|
-
{ name: 'Node ' + versions.node.spec, on: true, run: (env) => setupNode(env, versions, config.node) },
|
|
54
|
-
{ name: 'Python', on: wanted(config.python.enabled, 'python'), run: (env) => setupPython(env, config.python, versions) },
|
|
55
|
-
{ name: 'pyenv-win', on: wanted(config.python.enabled, 'python') && wantsPyenv(config.python.pyenv), run: (env) => setupPyenv(env) },
|
|
56
|
-
{ name: 'C/C++', on: wanted(config.cpp.enabled, 'cpp') || wanted(config.rust.enabled, 'rust'), run: (env) => setupCpp(env, config.cpp) },
|
|
57
|
-
{ name: 'MSVC', on: wanted(config.msvc.enabled, 'msvc'), run: (env) => setupMsvc(env, config.msvc) },
|
|
58
|
-
// Rust links with MSVC (msvc host) or MinGW's gcc (GNU host): whichever it uses goes first.
|
|
59
|
-
{ name: 'Rust', on: wanted(config.rust.enabled, 'rust'), after: ['C/C++', 'MSVC'], run: async (env) => { await setupRust(env, { ...config.rust, host: rustHost(config) }, o.refresh); Object.assign(env.vars, rustCaches(config.rust)); } },
|
|
60
|
-
{ name: '.NET', on: wanted(config.dotnet.enabled, 'dotnet'), run: (env) => setupDotnet(env, config.dotnet, o.refresh) },
|
|
61
|
-
{ name: 'Go', on: wanted(config.go.enabled, 'go'), run: (env) => setupGo(env, config.go) },
|
|
62
|
-
{ name: 'Java', on: java, run: (env) => setupJava(env, config.java) },
|
|
63
|
-
{ name: 'Ruby', on: wanted(config.ruby.enabled, 'ruby'), run: (env) => setupRuby(env, config.ruby) },
|
|
64
|
-
// PHP installs the Visual C++ runtime itself: one installer at a time.
|
|
65
|
-
{ name: 'Visual C++ runtime', on: config.vcRuntime.enabled, run: async (env) => { await setupVcRuntime(env); } },
|
|
66
|
-
{ name: 'PHP', on: wanted(config.php.enabled, 'php'), after: ['Visual C++ runtime'], run: (env) => setupPhp(env, config.php) },
|
|
67
|
-
{ name: 'Deno', on: wanted(config.deno.enabled, 'deno'), run: (env) => setupDeno(env) },
|
|
68
|
-
{ name: 'Bun', on: config.bun.enabled, run: (env) => setupBun(env) },
|
|
69
|
-
{ name: 'uv', on: config.uv.enabled, run: (env) => setupUv(env) },
|
|
70
|
-
{ name: 'PowerShell 7', on: wanted(config.pwsh.enabled, 'pwsh'), run: (env) => setupPwsh(env, o.refresh) },
|
|
71
|
-
// The openssl tool comes from Git's install: after Git.
|
|
72
|
-
{ name: 'CLI tools', on: Object.values(config.cli).some((v) => v !== false), after: ['Git'], run: (env) => setupCli(env, config.cli, o.gitAccess, o.refresh) },
|
|
73
|
-
{ name: 'Mesa 3D', on: config.mesa.enabled, run: (env) => setupMesa(env, config.mesa) },
|
|
74
|
-
{ name: 'VS Code', on: config.vscode.enabled, run: (env) => setupVscode(env, o.refresh) },
|
|
75
|
-
{ name: 'Python tools', on: wanted(config.python.enabled, 'python') && config.python.tools.length > 0, after: ['Python', 'uv'], run: (env) => setupPythonTools(env, config.python.tools) },
|
|
76
|
-
// DynamoDB Local runs on Java: the Java step installs the JDK first instead of racing it.
|
|
77
|
-
...o.databases.map((db) => ({ name: DATABASE_NAMES[db.database], on: true, after: db.database === 'dynamodb' && java ? ['Java'] : [], run: (env) => setupDatabase(env, db) })),
|
|
78
|
-
];
|
|
6
|
+
/** One lock per kind of step ("Node 20" and "Node 22" share nvm's folders): held while that step runs, in any run. */
|
|
7
|
+
const locks = new Map();
|
|
8
|
+
const lockKey = (name) => name.split(' ')[0].toLowerCase();
|
|
9
|
+
const exclusive = async (name, work) => {
|
|
10
|
+
const key = lockKey(name);
|
|
11
|
+
const previous = locks.get(key) ?? Promise.resolve();
|
|
12
|
+
let release = () => undefined;
|
|
13
|
+
const mine = new Promise((r) => { release = r; });
|
|
14
|
+
const chained = previous.then(() => mine);
|
|
15
|
+
locks.set(key, chained);
|
|
16
|
+
await previous;
|
|
17
|
+
try {
|
|
18
|
+
return await work();
|
|
19
|
+
}
|
|
20
|
+
finally {
|
|
21
|
+
release();
|
|
22
|
+
if (locks.get(key) === chained)
|
|
23
|
+
locks.delete(key);
|
|
24
|
+
}
|
|
79
25
|
};
|
|
80
|
-
/**
|
|
81
|
-
|
|
82
|
-
const steps = plan(config, versions, options).filter((s) => s.on);
|
|
26
|
+
/** Runs the steps (each with its own environment) at most PARALLEL at a time, after the steps they depend on. */
|
|
27
|
+
const runSteps = async (steps, o) => {
|
|
83
28
|
const envs = new Map(steps.map((s) => [s.name, emptyEnv()]));
|
|
84
29
|
const finished = new Map();
|
|
85
30
|
const running = new Set();
|
|
86
31
|
const waiting = [];
|
|
87
32
|
let done = 0;
|
|
33
|
+
const say = o.report ?? ((message) => setSandboxStatus('provisioning', message));
|
|
88
34
|
const report = () => { if (running.size)
|
|
89
|
-
|
|
35
|
+
say('Installing ' + [...running].join(', ') + ' (' + done + ' of ' + steps.length + ' done)'); };
|
|
90
36
|
for (const s of steps) {
|
|
91
37
|
// Dependencies first (they are earlier in the plan, so their promises exist), then a free slot.
|
|
92
38
|
finished.set(s.name, (async () => {
|
|
93
39
|
await Promise.all((s.after ?? []).map((name) => finished.get(name)));
|
|
40
|
+
const reused = s.shared ? o.reuse?.[s.name] : undefined;
|
|
41
|
+
if (reused) {
|
|
42
|
+
envs.set(s.name, structuredClone(reused));
|
|
43
|
+
done++;
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
94
46
|
while (running.size >= PARALLEL)
|
|
95
47
|
await new Promise((r) => waiting.push(r));
|
|
96
48
|
running.add(s.name);
|
|
97
49
|
report();
|
|
98
50
|
try {
|
|
99
|
-
await step(s.name, envs.get(s.name), async () => s.run(envs.get(s.name)));
|
|
51
|
+
await exclusive(s.name, () => step(s.name, envs.get(s.name), async () => s.run(envs.get(s.name))));
|
|
100
52
|
}
|
|
101
53
|
finally {
|
|
102
54
|
running.delete(s.name);
|
|
@@ -107,8 +59,14 @@ export const setupToolchains = async (config, versions, options) => {
|
|
|
107
59
|
})());
|
|
108
60
|
}
|
|
109
61
|
await Promise.all(finished.values());
|
|
62
|
+
return envs;
|
|
63
|
+
};
|
|
64
|
+
/** Provisions every enabled toolchain and database, and returns the combined environment for the agent. */
|
|
65
|
+
export const setupToolchains = async (config, versions, options, run = {}) => {
|
|
66
|
+
const steps = plan(config, versions, options).filter((s) => s.on);
|
|
67
|
+
const envs = await runSteps(steps, run);
|
|
110
68
|
// Merged in plan order, so PATH order never depends on which download finished first.
|
|
111
|
-
const env = emptyEnv();
|
|
69
|
+
const env = { ...emptyEnv(), steps: Object.fromEntries(envs) };
|
|
112
70
|
env.prepend.push(mkdirp(tool('bin')));
|
|
113
71
|
for (const part of envs.values()) {
|
|
114
72
|
Object.assign(env.vars, part.vars);
|
|
@@ -4,7 +4,7 @@ import fs from 'node:fs';
|
|
|
4
4
|
import path from 'node:path';
|
|
5
5
|
import { fetchJson, fetchText, installArchive } from '../../shared/download.js';
|
|
6
6
|
import { dryRun, errMsg, exists, log, warn } from '../env.js';
|
|
7
|
-
import { arch, resolveCached, tool, versionFromFiles } from './common.js';
|
|
7
|
+
import { arch, emptyEnv, resolveCached, tool, versionFromFiles } from './common.js';
|
|
8
8
|
import { javaMajorFrom, pickPackageVersion } from './versions.js';
|
|
9
9
|
const ADOPTIUM = 'https://api.adoptium.net/v3';
|
|
10
10
|
const MAVEN = 'https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/';
|
|
@@ -29,7 +29,7 @@ const setupJdk = async (env, config) => {
|
|
|
29
29
|
const home = tool('java', release.replace(/[^A-Za-z0-9.-]/g, '_'));
|
|
30
30
|
if (!exists(path.join(home, 'bin', 'java.exe'))) {
|
|
31
31
|
const asset = await temurin(major);
|
|
32
|
-
log('Downloading ' +
|
|
32
|
+
log('Downloading Java ' + release + ' (JDK, ~200 MB once) ...');
|
|
33
33
|
await installArchive(asset.binary.package.link, home, { sha256: asset.binary.package.checksum, locate: 'release', fileName: asset.binary.package.name });
|
|
34
34
|
}
|
|
35
35
|
env.vars.JAVA_HOME = home;
|
|
@@ -45,7 +45,7 @@ export const ensureJdk = async () => {
|
|
|
45
45
|
const installed = exists(root) ? fs.readdirSync(root).filter((d) => exists(path.join(root, d, 'bin', 'java.exe'))).sort((a, b) => b.localeCompare(a, undefined, { numeric: true })) : [];
|
|
46
46
|
if (installed.length)
|
|
47
47
|
return path.join(root, installed[0]);
|
|
48
|
-
const scratch =
|
|
48
|
+
const scratch = emptyEnv();
|
|
49
49
|
await setupJdk(scratch, { enabled: true, version: 'lts', maven: false, gradle: false });
|
|
50
50
|
return scratch.vars.JAVA_HOME;
|
|
51
51
|
};
|
|
@@ -57,7 +57,7 @@ const setupMaven = async (env) => {
|
|
|
57
57
|
const home = tool('maven', version);
|
|
58
58
|
if (!exists(path.join(home, 'bin', 'mvn.cmd'))) {
|
|
59
59
|
const url = MAVEN + version + '/apache-maven-' + version + '-bin.zip';
|
|
60
|
-
log('Downloading Maven ' + version + ' ...');
|
|
60
|
+
log('Downloading Maven ' + version + ' (~10 MB once) ...');
|
|
61
61
|
await installArchive(url, home, { sha512: (await fetchText(url + '.sha512')).trim().split(/\s+/)[0], locate: 'LICENSE' });
|
|
62
62
|
}
|
|
63
63
|
const repo = tool('maven-repository');
|
|
@@ -72,7 +72,7 @@ const setupGradle = async (env) => {
|
|
|
72
72
|
if (!exists(path.join(home, 'bin', 'gradle.bat'))) {
|
|
73
73
|
if (!current || current.version !== version)
|
|
74
74
|
throw new Error('Gradle ' + version + ' is not installed and cannot be downloaded right now');
|
|
75
|
-
log('Downloading Gradle ' + version + ' ...');
|
|
75
|
+
log('Downloading Gradle ' + version + ' (~130 MB once) ...');
|
|
76
76
|
await installArchive(current.downloadUrl, home, { sha256: (await fetchText(current.checksumUrl)).trim(), locate: 'LICENSE', fileName: 'gradle-' + version + '.zip' });
|
|
77
77
|
}
|
|
78
78
|
const userHome = tool('gradle-home');
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
// Clean-up of what interrupted or older installs left in the tools folder.
|
|
2
|
+
import fs from 'node:fs';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import { safeRemove } from '../../shared/safe-remove.js';
|
|
5
|
+
import { toolsDir } from '../env.js';
|
|
6
|
+
const STAGING = /\.staging-[0-9a-f]+$/i;
|
|
7
|
+
const entries = (dir) => { try {
|
|
8
|
+
return fs.readdirSync(dir, { withFileTypes: true });
|
|
9
|
+
}
|
|
10
|
+
catch {
|
|
11
|
+
return [];
|
|
12
|
+
} };
|
|
13
|
+
/** Removes helper builds older versions left in persistent storage, and interrupted installs' staging folders. */
|
|
14
|
+
export const pruneToolLeftovers = () => {
|
|
15
|
+
for (const legacy of ['ptyhost', 'gitshim'])
|
|
16
|
+
safeRemove(path.join(toolsDir, legacy), toolsDir);
|
|
17
|
+
// Staging folders sit next to their destination: tools\x.staging-ab12 and one level down (tools\nvm\v22.staging-ab12).
|
|
18
|
+
for (const top of entries(toolsDir)) {
|
|
19
|
+
const dir = path.join(toolsDir, top.name);
|
|
20
|
+
if (STAGING.test(top.name))
|
|
21
|
+
safeRemove(dir, toolsDir);
|
|
22
|
+
else if (top.isDirectory())
|
|
23
|
+
for (const sub of entries(dir).filter((e) => STAGING.test(e.name)))
|
|
24
|
+
safeRemove(path.join(dir, sub.name), dir);
|
|
25
|
+
}
|
|
26
|
+
};
|
|
@@ -2,13 +2,14 @@
|
|
|
2
2
|
// the Python step still provide the default versions; these come along when the project or this PC uses them.
|
|
3
3
|
import fs from 'node:fs';
|
|
4
4
|
import path from 'node:path';
|
|
5
|
-
import {
|
|
6
|
-
import { dryRun, errMsg, execAsync, exists, log, mkdirp, session, warn
|
|
7
|
-
import {
|
|
5
|
+
import { installArchive, latestGithubTag } from '../../shared/download.js';
|
|
6
|
+
import { dryRun, errMsg, execAsync, exists, log, mkdirp, session, warn } from '../env.js';
|
|
7
|
+
import { projectWorkspace } from '../project-context.js';
|
|
8
|
+
import { arch, installFromGithub, resolveCached, tool, versionOf } from './common.js';
|
|
8
9
|
/** The "volta" block of the workspace's package.json ({ node, npm, yarn, pnpm }), if any. */
|
|
9
10
|
export const voltaPins = () => {
|
|
10
11
|
try {
|
|
11
|
-
const pkg = JSON.parse(fs.readFileSync(path.join(
|
|
12
|
+
const pkg = JSON.parse(fs.readFileSync(path.join(projectWorkspace(), 'package.json'), 'utf8').replace(/^/, ''));
|
|
12
13
|
return Object.fromEntries(Object.entries(pkg.volta ?? {}).filter((e) => ['node', 'npm', 'yarn', 'pnpm'].includes(e[0]) && typeof e[1] === 'string'));
|
|
13
14
|
}
|
|
14
15
|
catch {
|
|
@@ -28,9 +29,8 @@ export const setupVolta = async (env) => {
|
|
|
28
29
|
}
|
|
29
30
|
const dir = tool('volta');
|
|
30
31
|
if (!exists(path.join(dir, 'volta.exe'))) {
|
|
31
|
-
const
|
|
32
|
-
|
|
33
|
-
await installArchive(asset.url, dir, { sha256: asset.sha256, locate: 'volta.exe', fileName: asset.name });
|
|
32
|
+
const pattern = arch === 'arm64' ? /^volta-[\d.]+-windows-arm64\.zip$/ : /^volta-[\d.]+-windows\.zip$/;
|
|
33
|
+
await installFromGithub('volta-cli/volta', pattern, { dest: dir, what: 'Volta (~15 MB once)', locate: 'volta.exe' });
|
|
34
34
|
}
|
|
35
35
|
// The MSI puts these shims (copies of volta-shim.exe) next to volta.exe; the portable zip leaves that to us.
|
|
36
36
|
for (const shim of ['node', 'npm', 'npx', 'pnpm', 'pnpx', 'yarn', 'yarnpkg']) {
|
|
@@ -51,13 +51,15 @@ export const setupVolta = async (env) => {
|
|
|
51
51
|
// `volta install` fetches the pinned versions now (not on the agent's first `node`) and makes them the defaults.
|
|
52
52
|
for (const [toolName, version] of Object.entries(pins)) {
|
|
53
53
|
try {
|
|
54
|
-
await execAsync(volta, ['install', toolName + '@' + version], { env: { ...process.env, ...vars }, cwd:
|
|
54
|
+
await execAsync(volta, ['install', toolName + '@' + version], { env: { ...process.env, ...vars }, cwd: projectWorkspace(), stdio: 'ignore' });
|
|
55
55
|
}
|
|
56
56
|
catch (e) {
|
|
57
57
|
warn('Volta could not install ' + toolName + '@' + version + ': ' + errMsg(e));
|
|
58
58
|
}
|
|
59
59
|
}
|
|
60
|
-
|
|
60
|
+
const pinned = Object.entries(pins).map(([k, v]) => k + '@' + v);
|
|
61
|
+
const note = pinned.length ? ' (pins from package.json: ' + pinned.join(', ') + ')' : ' (no pins in this project; nvm\'s node is the default)';
|
|
62
|
+
env.summary.push('volta: ' + versionOf(volta) + note);
|
|
61
63
|
};
|
|
62
64
|
/**
|
|
63
65
|
* pyenv-win from its source archive (it ships no release assets). Its versions persist in tools\pyenv. It comes after
|
|
@@ -71,7 +73,7 @@ export const setupPyenv = async (env) => {
|
|
|
71
73
|
const root = tool('pyenv', 'pyenv-win');
|
|
72
74
|
if (!exists(path.join(root, 'bin', 'pyenv.bat'))) {
|
|
73
75
|
const tag = await resolveCached('pyenv-win', () => latestGithubTag('pyenv-win/pyenv-win'));
|
|
74
|
-
log('Downloading pyenv-win ' + tag + ' ...');
|
|
76
|
+
log('Downloading pyenv-win ' + tag + ' (~5 MB once) ...');
|
|
75
77
|
// GitHub's tag archive: no published checksum, but HTTPS from github.com for the project's own tag.
|
|
76
78
|
await installArchive('https://github.com/pyenv-win/pyenv-win/archive/refs/tags/' + encodeURIComponent(tag) + '.zip', root, { locate: 'pyenv.bat', up: 1, fileName: 'pyenv-win.zip' });
|
|
77
79
|
}
|
|
@@ -2,10 +2,9 @@
|
|
|
2
2
|
// published Windows build in seconds; only crates without one are compiled with `cargo install --locked`.
|
|
3
3
|
import fs from 'node:fs';
|
|
4
4
|
import path from 'node:path';
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import { arch, tool } from './common.js';
|
|
5
|
+
import { errMsg, execAsync, exists, log, warn } from '../../env.js';
|
|
6
|
+
import { binstallAsset } from '../catalogue.js';
|
|
7
|
+
import { arch, installFromGithub, tool } from '../common.js';
|
|
9
8
|
/**
|
|
10
9
|
* cargo-binstall.exe into CARGO_HOME\bin (so `cargo binstall` works for the agent too). Downloaded into its own
|
|
11
10
|
* tools\cargo-binstall folder first: installArchive replaces its destination, which must never be cargo's bin.
|
|
@@ -17,9 +16,7 @@ const ensureBinstall = async (cargoBin) => {
|
|
|
17
16
|
try {
|
|
18
17
|
const dir = tool('cargo-binstall');
|
|
19
18
|
if (!exists(path.join(dir, 'cargo-binstall.exe'))) {
|
|
20
|
-
|
|
21
|
-
log('Downloading ' + asset.name + ' (prebuilt Rust tools) ...');
|
|
22
|
-
await installArchive(asset.url, dir, { sha256: asset.sha256, locate: 'cargo-binstall.exe', fileName: asset.name });
|
|
19
|
+
await installFromGithub('cargo-bins/cargo-binstall', binstallAsset(arch), { dest: dir, what: 'cargo-binstall for prebuilt Rust tools (~10 MB once)', locate: 'cargo-binstall.exe' });
|
|
23
20
|
}
|
|
24
21
|
fs.copyFileSync(path.join(dir, 'cargo-binstall.exe'), target);
|
|
25
22
|
return true;
|
|
@@ -46,8 +43,8 @@ export const crateInstaller = (cargoHome, cargoEnv) => {
|
|
|
46
43
|
await execAsync(cargo, ['binstall', '--no-confirm', '--locked', '--disable-strategies', 'compile', crate], binstallEnv);
|
|
47
44
|
return;
|
|
48
45
|
}
|
|
49
|
-
catch
|
|
50
|
-
log('No prebuilt ' + crate + ' for Windows
|
|
46
|
+
catch {
|
|
47
|
+
log('No prebuilt ' + crate + ' for Windows; compiling it with cargo (takes a few minutes) ...');
|
|
51
48
|
}
|
|
52
49
|
}
|
|
53
50
|
await execAsync(cargo, ['install', '--locked', crate], cargoEnv);
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { Toolchains } from '../../../core/types.js';
|
|
2
|
+
import { type ToolEnv } from '../common.js';
|
|
3
|
+
/** MinGW-w64 GCC from WinLibs: gcc/g++/mingw32-make for the agent, and the linker for Rust's GNU host. */
|
|
4
|
+
export declare const setupCpp: (env: ToolEnv, config: Toolchains["cpp"]) => Promise<void>;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
// C/C++: MinGW-w64 GCC (with CMake, Ninja, make) and the flex/bison parser generators.
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { dryRun, exists, log, warn } from '../../env.js';
|
|
4
|
+
import { arch, installFromGithub, tool, versionOf } from '../common.js';
|
|
5
|
+
import { CMAKE_FLOOR, cmakeTooOld } from '../versions.js';
|
|
6
|
+
/** MinGW-w64 GCC from WinLibs: gcc/g++/mingw32-make for the agent, and the linker for Rust's GNU host. */
|
|
7
|
+
export const setupCpp = async (env, config) => {
|
|
8
|
+
const bin = tool('mingw', 'mingw64', 'bin');
|
|
9
|
+
const gcc = path.join(bin, 'gcc.exe');
|
|
10
|
+
if (dryRun) {
|
|
11
|
+
log('(dry run) would provision MinGW-w64 GCC');
|
|
12
|
+
return;
|
|
13
|
+
}
|
|
14
|
+
if (!exists(gcc)) {
|
|
15
|
+
const pattern = arch === 'arm64' ? /^winlibs-aarch64-.*\.zip$/ : /^winlibs-x86_64-posix-seh-gcc-.*\.zip$/;
|
|
16
|
+
await installFromGithub('brechtsanders/winlibs_mingw', pattern, { dest: tool('mingw'), what: 'the C/C++ compiler, MinGW-w64 GCC with CMake and Ninja (~270 MB once)', searchOlder: true });
|
|
17
|
+
}
|
|
18
|
+
if (!exists(gcc))
|
|
19
|
+
throw new Error('gcc.exe missing after installing MinGW');
|
|
20
|
+
// Appended (not prepended) so MinGW's tools never shadow Windows or toolchain commands of the same name.
|
|
21
|
+
env.append.unshift(bin);
|
|
22
|
+
env.vars.CARGO_TARGET_X86_64_PC_WINDOWS_GNU_LINKER = gcc;
|
|
23
|
+
const cmake = versionOf(path.join(bin, 'cmake.exe'));
|
|
24
|
+
if (cmakeTooOld(cmake))
|
|
25
|
+
warn('The bundled CMake ' + cmake + ' is older than ' + CMAKE_FLOOR + ', which many projects need; set toolchains.cpp.enabled to refresh it, or install a newer CMake into C:\\AgentData\\tools\\bin.');
|
|
26
|
+
env.summary.push('gcc: ' + versionOf(gcc) + ' (MinGW-w64, with cmake ' + cmake + ', ninja, premake5)');
|
|
27
|
+
if (config.flexBison)
|
|
28
|
+
await setupFlexBison(env);
|
|
29
|
+
};
|
|
30
|
+
/** win_flex / win_bison (CMake's FindFLEX/FindBISON look for these names). Kept with the C/C++ tools on PATH. */
|
|
31
|
+
const setupFlexBison = async (env) => {
|
|
32
|
+
const dir = tool('winflexbison');
|
|
33
|
+
if (!exists(path.join(dir, 'win_bison.exe'))) {
|
|
34
|
+
await installFromGithub('lexxmark/winflexbison', /^win_flex_bison-[\d.]+\.zip$/, { dest: dir, what: 'win_flex / win_bison (~1 MB once)', locate: 'win_bison.exe' });
|
|
35
|
+
}
|
|
36
|
+
env.append.push(dir);
|
|
37
|
+
env.summary.push('win_flex/win_bison: ' + versionOf(path.join(dir, 'win_bison.exe')));
|
|
38
|
+
};
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { Toolchains } from '../../../core/types.js';
|
|
2
|
+
import { type ToolEnv } from '../common.js';
|
|
3
|
+
/** .NET SDK channels from config plus whatever the workspace's global.json pins. Installs are remembered in a marker. */
|
|
4
|
+
export declare const setupDotnet: (env: ToolEnv, config: Toolchains["dotnet"], refresh: boolean) => Promise<void>;
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
// .NET: the SDK (dotnet-install.ps1), .NET Framework reference assemblies for old-style projects, and .NET Framework 3.5.
|
|
2
|
+
import fs from 'node:fs';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import { z } from 'zod';
|
|
5
|
+
import { fetchJson, installArchive } from '../../../shared/download.js';
|
|
6
|
+
import { readJsonFile, writeJsonAtomic } from '../../../shared/rundir.js';
|
|
7
|
+
import { safeRemove } from '../../../shared/safe-remove.js';
|
|
8
|
+
import { SYSTEM } from '../../../shared/system.js';
|
|
9
|
+
import { dataDir, dryRun, errMsg, execAsync, execOutput, exists, log, mkdirp, warn } from '../../env.js';
|
|
10
|
+
import { projectWorkspace } from '../../project-context.js';
|
|
11
|
+
import { downloadFile, installOnce, tool } from '../common.js';
|
|
12
|
+
/** tools\dotnet\.agent-sandbox-installed.json: which install keys (channel:8.0, global.json:...) already ran. */
|
|
13
|
+
const DotnetMarker = z.record(z.string(), z.boolean());
|
|
14
|
+
/** .NET SDK channels from config plus whatever the workspace's global.json pins. Installs are remembered in a marker. */
|
|
15
|
+
export const setupDotnet = async (env, config, refresh) => {
|
|
16
|
+
const root = tool('dotnet');
|
|
17
|
+
const marker = path.join(root, '.agent-sandbox-installed.json');
|
|
18
|
+
const script = tool('dotnet-install.ps1');
|
|
19
|
+
if (dryRun) {
|
|
20
|
+
log('(dry run) would provision .NET SDK channels ' + config.channels.join(', '));
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
// A corrupt or hand-edited marker just means "nothing recorded yet" (the installs are idempotent).
|
|
24
|
+
const recorded = DotnetMarker.safeParse(exists(marker) && !refresh ? readJsonFile(marker) : {});
|
|
25
|
+
const done = recorded.success ? recorded.data : {};
|
|
26
|
+
const globalJson = path.join(projectWorkspace(), 'global.json');
|
|
27
|
+
const installs = [
|
|
28
|
+
...config.channels.map((c) => ['channel:' + c, ['-Channel', c]]),
|
|
29
|
+
...(exists(globalJson) ? [['global.json:' + fs.readFileSync(globalJson, 'utf8').replace(/\s+/g, ''), ['-JSonFile', globalJson]]] : []),
|
|
30
|
+
];
|
|
31
|
+
for (const [key, args] of installs.filter(([k]) => !done[k])) {
|
|
32
|
+
// Fetched every time something is installed (it is small): an interrupted earlier download must not be run.
|
|
33
|
+
await downloadFile('https://dot.net/v1/dotnet-install.ps1', script);
|
|
34
|
+
log('Installing the .NET SDK ' + (key.startsWith('channel:') ? key.slice(8) : 'pinned in global.json') + ' (~250 MB once) ...');
|
|
35
|
+
await execAsync(SYSTEM.powershell(), ['-NoLogo', '-NoProfile', '-ExecutionPolicy', 'Bypass', '-File', script, ...args, '-InstallDir', root, '-NoPath']);
|
|
36
|
+
done[key] = true;
|
|
37
|
+
writeJsonAtomic(marker, done);
|
|
38
|
+
}
|
|
39
|
+
const home = mkdirp(tool('dotnet-home'));
|
|
40
|
+
Object.assign(env.vars, { DOTNET_ROOT: root, DOTNET_CLI_HOME: home, DOTNET_CLI_TELEMETRY_OPTOUT: '1', DOTNET_NOLOGO: '1', DOTNET_SKIP_FIRST_TIME_EXPERIENCE: '1', NUGET_PACKAGES: tool('nuget', 'packages') });
|
|
41
|
+
env.prepend.push(root, path.join(home, '.dotnet', 'tools'));
|
|
42
|
+
env.summary.push('dotnet: ' + execOutput(path.join(root, 'dotnet.exe'), ['--list-sdks']).split(/\r?\n/).map((l) => l.split(' ')[0]).filter(Boolean).join(', '));
|
|
43
|
+
const dotnet = path.join(root, 'dotnet.exe');
|
|
44
|
+
const dotnetEnv = { env: { ...process.env, ...env.vars, PATH: root + path.delimiter + (process.env.PATH ?? '') } };
|
|
45
|
+
await installOnce(env, 'dotnet workload', config.workloads, (w) => execAsync(dotnet, ['workload', 'install', w, '--skip-manifest-update'], dotnetEnv));
|
|
46
|
+
await installOnce(env, 'dotnet tool', config.tools, (t) => execAsync(dotnet, ['tool', 'install', '--global', t], dotnetEnv));
|
|
47
|
+
await setupFrameworkReferences(env, config.frameworkTargets);
|
|
48
|
+
if (config.netfx35)
|
|
49
|
+
await setupNetFx35(env);
|
|
50
|
+
};
|
|
51
|
+
/**
|
|
52
|
+
* .NET Framework reference assemblies (the "targeting packs" Visual Studio would install) from NuGet, so net4x projects,
|
|
53
|
+
* old-style .csproj included, build with the SDK's MSBuild. MSBuild reads TargetFrameworkRootPath from the environment.
|
|
54
|
+
* Running .NET Framework 4.8 apps needs nothing: Windows ships it.
|
|
55
|
+
*/
|
|
56
|
+
const setupFrameworkReferences = async (env, targets) => {
|
|
57
|
+
if (!targets.length)
|
|
58
|
+
return;
|
|
59
|
+
const root = tool('netfx-references');
|
|
60
|
+
for (const target of targets) {
|
|
61
|
+
const id = 'microsoft.netframework.referenceassemblies.' + target.toLowerCase();
|
|
62
|
+
const marker = path.join(root, '.installed-' + target.toLowerCase());
|
|
63
|
+
if (exists(marker))
|
|
64
|
+
continue;
|
|
65
|
+
const staging = tool('netfx-references-' + target.toLowerCase());
|
|
66
|
+
try {
|
|
67
|
+
const { versions } = await fetchJson('https://api.nuget.org/v3-flatcontainer/' + id + '/index.json');
|
|
68
|
+
const version = versions.filter((v) => /^\d+(\.\d+)*$/.test(v)).pop();
|
|
69
|
+
if (!version)
|
|
70
|
+
throw new Error('no stable version of ' + id);
|
|
71
|
+
log('Downloading the .NET Framework ' + target + ' reference assemblies (~30 MB once) ...');
|
|
72
|
+
await installArchive('https://api.nuget.org/v3-flatcontainer/' + id + '/' + version + '/' + id + '.' + version + '.nupkg', staging, { fileName: id + '.zip' });
|
|
73
|
+
fs.cpSync(path.join(staging, 'build', '.NETFramework'), path.join(root, '.NETFramework'), { recursive: true });
|
|
74
|
+
fs.writeFileSync(marker, version);
|
|
75
|
+
}
|
|
76
|
+
catch (e) {
|
|
77
|
+
warn('.NET Framework ' + target + ' reference assemblies could not be installed (projects targeting it will not build): ' + errMsg(e));
|
|
78
|
+
}
|
|
79
|
+
finally {
|
|
80
|
+
safeRemove(staging, dataDir);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
if (!exists(path.join(root, '.NETFramework')))
|
|
84
|
+
return;
|
|
85
|
+
env.vars.TargetFrameworkRootPath = root + path.sep;
|
|
86
|
+
env.summary.push('.NET Framework targeting: ' + fs.readdirSync(path.join(root, '.NETFramework')).join(', '));
|
|
87
|
+
};
|
|
88
|
+
/** .NET Framework 3.5 is a Windows feature the sandbox image lacks; DISM fetches it from Windows Update on every boot. */
|
|
89
|
+
const setupNetFx35 = async (env) => {
|
|
90
|
+
if (execOutput(SYSTEM.reg(), ['query', 'HKLM\\SOFTWARE\\Microsoft\\NET Framework Setup\\NDP\\v3.5', '/v', 'Install']).includes('0x1')) {
|
|
91
|
+
env.summary.push('.NET Framework 3.5: on');
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
log('Enabling .NET Framework 3.5 (downloads from Windows Update, a few minutes) ...');
|
|
95
|
+
try {
|
|
96
|
+
await execAsync(SYSTEM.dism(), ['/Online', '/Enable-Feature', '/FeatureName:NetFx3', '/All', '/NoRestart', '/Quiet'], { stdio: 'ignore' });
|
|
97
|
+
env.summary.push('.NET Framework 3.5: on');
|
|
98
|
+
}
|
|
99
|
+
catch (e) {
|
|
100
|
+
warn('.NET Framework 3.5 could not be enabled: ' + errMsg(e));
|
|
101
|
+
env.summary.push('.NET Framework 3.5: FAILED');
|
|
102
|
+
}
|
|
103
|
+
};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { Toolchains } from '../../../core/types.js';
|
|
2
|
+
import { type ToolEnv } from '../common.js';
|
|
3
|
+
/**
|
|
4
|
+
* Mesa 3D for Windows (llvmpipe): OpenGL 4.5 on the CPU when the sandbox has no GPU. Windows only offers OpenGL 1.1 in
|
|
5
|
+
* software, and opengl32.dll cannot be replaced system-wide, so programs pick Mesa up from their own folder.
|
|
6
|
+
*/
|
|
7
|
+
export declare const setupMesa: (env: ToolEnv, config: Toolchains["mesa"]) => Promise<void>;
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
// Mesa for running OpenGL and Vulkan programs without a GPU (llvmpipe, lavapipe).
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { installArchive } from '../../../shared/download.js';
|
|
4
|
+
import { SYSTEM } from '../../../shared/system.js';
|
|
5
|
+
import { dryRun, execAsync, execOutput, exists, log } from '../../env.js';
|
|
6
|
+
import { arch, installFromGithub, tool } from '../common.js';
|
|
7
|
+
/**
|
|
8
|
+
* Mesa 3D for Windows (llvmpipe): OpenGL 4.5 on the CPU when the sandbox has no GPU. Windows only offers OpenGL 1.1 in
|
|
9
|
+
* software, and opengl32.dll cannot be replaced system-wide, so programs pick Mesa up from their own folder.
|
|
10
|
+
*/
|
|
11
|
+
export const setupMesa = async (env, config) => {
|
|
12
|
+
if (dryRun) {
|
|
13
|
+
log('(dry run) would provision Mesa 3D');
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
const root = tool('mesa');
|
|
17
|
+
const dir = path.join(root, arch === 'arm64' ? 'arm64' : 'x64');
|
|
18
|
+
if (!exists(path.join(dir, 'opengl32.dll'))) {
|
|
19
|
+
await installFromGithub('pal1000/mesa-dist-win', /^mesa3d-[\d.]+-release-msvc\.7z$/, { dest: root, what: 'Mesa 3D for software OpenGL (~100 MB once)', locate: 'opengl32.dll', up: 1 });
|
|
20
|
+
}
|
|
21
|
+
Object.assign(env.vars, { MESA_DIR: dir, GALLIUM_DRIVER: 'llvmpipe' });
|
|
22
|
+
env.summary.push('mesa (software OpenGL 4.5): copy opengl32.dll + libgallium_wgl.dll from %MESA_DIR% next to a game\'s .exe');
|
|
23
|
+
if (config.vulkan)
|
|
24
|
+
await setupLavapipe(env, dir);
|
|
25
|
+
};
|
|
26
|
+
const VULKAN_RUNTIME = 'https://sdk.lunarg.com/sdk/download/latest/windows/vulkan-runtime-components.zip';
|
|
27
|
+
/**
|
|
28
|
+
* Software Vulkan: Mesa's lavapipe plus the Khronos loader (vulkan-1.dll, from LunarG's runtime components; Windows
|
|
29
|
+
* Sandbox has no Vulkan loader). The loader ignores VK_DRIVER_FILES in elevated processes, and everything in the
|
|
30
|
+
* sandbox runs elevated, so lavapipe is registered where the loader looks (HKLM; the registry is new every boot).
|
|
31
|
+
*/
|
|
32
|
+
const setupLavapipe = async (env, mesaDir) => {
|
|
33
|
+
const icd = path.join(mesaDir, arch === 'arm64' ? 'lvp_icd.aarch64.json' : 'lvp_icd.x86_64.json');
|
|
34
|
+
if (!exists(icd))
|
|
35
|
+
throw new Error('this Mesa build has no lavapipe (' + path.basename(icd) + ')');
|
|
36
|
+
const dir = tool('vulkan');
|
|
37
|
+
if (!exists(path.join(dir, 'vulkan-1.dll'))) {
|
|
38
|
+
log('Downloading the Vulkan loader (~10 MB once) ...');
|
|
39
|
+
// LunarG publishes no checksum for this zip; it comes over HTTPS from LunarG, the Khronos SDK's maintainer.
|
|
40
|
+
// The zip has x86 and x64 folders: only the 64-bit loader (and vulkaninfo) is extracted.
|
|
41
|
+
await installArchive(VULKAN_RUNTIME, dir, { locate: 'vulkan-1.dll', fileName: 'vulkan-runtime.zip', members: ['*/x64/*'] });
|
|
42
|
+
}
|
|
43
|
+
const register = (file) => execAsync(SYSTEM.reg(), ['add', 'HKLM\\SOFTWARE\\Khronos\\Vulkan\\Drivers', '/v', file, '/t', 'REG_DWORD', '/d', '0', '/f'], { stdio: 'ignore' });
|
|
44
|
+
await register(icd);
|
|
45
|
+
// sandbox.vGpu: the sandbox sees this PC's GPU through Direct3D 12, and Dozen runs Vulkan on it. Programs prefer it
|
|
46
|
+
// over lavapipe (a GPU before a CPU device); lavapipe stays for the ones that need it.
|
|
47
|
+
const dozen = path.join(mesaDir, arch === 'arm64' ? 'dzn_icd.aarch64.json' : 'dzn_icd.x86_64.json');
|
|
48
|
+
const gpu = hasGpu();
|
|
49
|
+
if (gpu && exists(dozen))
|
|
50
|
+
await register(dozen);
|
|
51
|
+
env.prepend.push(dir);
|
|
52
|
+
env.summary.push('vulkan: ' + (gpu && exists(dozen) ? 'Dozen (Vulkan on the GPU via Direct3D 12) and ' : '') + 'lavapipe (software Vulkan 1.4 on the CPU), vulkaninfo on PATH; WGPU_BACKEND=vulkan for wgpu');
|
|
53
|
+
};
|
|
54
|
+
/** A real display adapter (sandbox.vGpu on), not only the remote display or basic render driver. */
|
|
55
|
+
const hasGpu = () => execOutput(SYSTEM.powershell(), ['-NoProfile', '-NonInteractive', '-Command', '(Get-CimInstance Win32_VideoController).Name'], { timeout: 30000 })
|
|
56
|
+
.split(/\r?\n/).map((n) => n.trim()).some((n) => n && !/^Microsoft (Remote Display|Basic (Render|Display))/i.test(n));
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export interface VcEnv {
|
|
2
|
+
vars: Record<string, string>;
|
|
3
|
+
path: string[];
|
|
4
|
+
}
|
|
5
|
+
/** Variables vcvars64.bat would set for this tree (host x64, target x64). */
|
|
6
|
+
export declare const vcvars: (root: string, msvc: string, sdk: string) => VcEnv;
|
|
7
|
+
/** vcvars64.bat / vcvarsall.bat in the usual place, for scripts that `call` them. */
|
|
8
|
+
export declare const writeVcvars: (env: VcEnv) => void;
|
|
9
|
+
/** vswhere.exe where Visual Studio's installer would put it, answering with this tree. */
|
|
10
|
+
export declare const installVswhere: (msvc: string) => void;
|
|
11
|
+
/**
|
|
12
|
+
* cl.exe and link.exe start vctip.exe (Visual Studio's telemetry uploader), which lingers after the build and keeps the
|
|
13
|
+
* folder locked, so `sandbox repair` / `data clean` could not delete tools\msvc. Neither VSCMD_SKIP_SENDTELEMETRY nor
|
|
14
|
+
* the TurnOffSwitch registry value stops it; without the file the compiler simply skips it. Nothing else needs it.
|
|
15
|
+
*/
|
|
16
|
+
export declare const removeTelemetry: (msvc: string) => void;
|