windows-development-sandbox 1.18.4 → 1.23.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/config.example.json +17 -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 +33 -1
- package/dist/app/features/accounts/accounts.def.js +10 -4
- package/dist/app/features/accounts/accounts.run.d.ts +2 -0
- package/dist/app/features/accounts/accounts.run.js +7 -2
- package/dist/app/features/accounts/services.def.d.ts +7 -1
- package/dist/app/features/accounts/services.def.js +19 -16
- package/dist/app/features/accounts/services.run.d.ts +2 -0
- package/dist/app/features/accounts/services.run.js +44 -16
- package/dist/app/features/agent-commands/agent-commands.def.d.ts +37 -0
- package/dist/app/features/agent-commands/agent-commands.def.js +91 -0
- package/dist/app/features/agent-commands/agent-commands.run.d.ts +28 -0
- package/dist/app/features/agent-commands/agent-commands.run.js +35 -0
- package/dist/app/features/agent-commands/index.d.ts +2 -0
- package/dist/app/features/agent-commands/index.js +3 -0
- package/dist/app/features/agents/agents.def.d.ts +14 -1
- package/dist/app/features/agents/agents.def.js +61 -6
- package/dist/app/features/agents/agents.run.d.ts +1 -0
- package/dist/app/features/agents/agents.run.js +8 -1
- package/dist/app/features/agents/claude-env.def.d.ts +36 -0
- package/dist/app/features/agents/claude-env.def.js +305 -0
- package/dist/app/features/agents/env.def.d.ts +163 -0
- package/dist/app/features/agents/env.def.js +184 -0
- package/dist/app/features/agents/env.run.d.ts +43 -0
- package/dist/app/features/agents/env.run.js +86 -0
- package/dist/app/features/agents/index.d.ts +2 -0
- package/dist/app/features/agents/index.js +2 -0
- package/dist/app/features/defs.d.ts +171 -3
- package/dist/app/features/defs.js +9 -0
- 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 +7 -2
- package/dist/app/features/settings/settings-rows.js +6 -2
- package/dist/app/features/settings/settings.def.js +1 -1
- package/dist/app/features/settings/settings.run.d.ts +8 -0
- package/dist/app/features/settings/settings.run.js +12 -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 +13 -3
- package/dist/app/features/vpn/vpn.def.d.ts +33 -0
- package/dist/app/features/vpn/vpn.def.js +30 -6
- package/dist/app/features/vpn/vpn.run.d.ts +11 -0
- package/dist/app/features/vpn/vpn.run.js +4 -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 +6 -1
- package/dist/app/kernel/view.d.ts +11 -1
- package/dist/app/registry.js +7 -1
- package/dist/bin/agent-sandbox.js +2 -2
- package/dist/bin/{chunk-N4GXYTLV.js → chunk-JETGP2C3.js} +239 -72
- package/dist/bin/{chunk-MY7NLQQY.js → chunk-XZKOPGNH.js} +1 -1
- package/dist/bin/{chunk-FRPLQLSY.js → chunk-ZTTOF5V3.js} +6566 -4964
- 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/commands/agent-commands.d.ts +0 -1
- package/dist/cli/commands/agent-commands.js +2 -32
- package/dist/cli/commands/index.d.ts +1 -1
- package/dist/cli/commands/index.js +1 -1
- package/dist/cli/commands/launch/launch.js +2 -2
- package/dist/cli/commands/registry.js +3 -2
- package/dist/cli/manifest.d.ts +3 -3
- package/dist/cli/manifest.js +3 -2
- 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/menu.d.ts +1 -1
- package/dist/cli/menu/menu.js +3 -3
- package/dist/cli/menu/pages/accounts-page.js +1 -1
- package/dist/cli/menu/pages/agents-page.d.ts +7 -2
- package/dist/cli/menu/pages/agents-page.js +75 -13
- package/dist/cli/menu/pages/maintenance-page.d.ts +6 -0
- package/dist/cli/menu/pages/maintenance-page.js +10 -4
- 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 +13 -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/menu/views.js +2 -1
- package/dist/cli/report.js +2 -0
- package/dist/cli/services/agent-commands-service.d.ts +2 -0
- package/dist/cli/services/agent-commands-service.js +13 -7
- package/dist/cli/services/vpn-service.d.ts +5 -1
- package/dist/cli/services/vpn-service.js +6 -1
- package/dist/cli/tui/app.d.ts +5 -0
- package/dist/cli/tui/app.js +2 -0
- package/dist/cli/tui/dialogs/text-screen.js +2 -1
- package/dist/cli/tui/terminal.js +3 -1
- package/dist/core/config/defaults.js +12 -1
- package/dist/core/detect/toolchains.js +9 -0
- package/dist/core/disk.d.ts +1 -5
- package/dist/core/disk.js +1 -16
- package/dist/core/schema/accounts.d.ts +6 -0
- package/dist/core/schema/accounts.js +13 -11
- package/dist/core/schema/codex.d.ts +29 -0
- package/dist/core/schema/codex.js +24 -0
- package/dist/core/schema/config.d.ts +58 -14
- package/dist/core/schema/config.js +6 -4
- package/dist/core/schema/github.js +1 -1
- package/dist/core/schema/index.d.ts +1 -0
- package/dist/core/schema/index.js +1 -0
- 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/toolchains.d.ts +4 -0
- package/dist/core/schema/toolchains.js +3 -0
- package/dist/core/schema/vpn.js +1 -1
- package/dist/core/schema/web.js +3 -3
- package/dist/core/types.d.ts +8 -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 +10 -6
- 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-files.d.ts +26 -6
- package/dist/guest/agents/agent-files.js +84 -14
- package/dist/guest/agents/agent-installer.js +1 -1
- package/dist/guest/agents/local-state.d.ts +5 -2
- package/dist/guest/agents/local-state.js +24 -10
- 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 +325 -149
- 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/daemon/sessions.js +2 -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/installers.d.ts +6 -10
- package/dist/guest/toolchains/installers.js +4 -12
- 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/autosdk.d.ts +3 -0
- package/dist/guest/toolchains/native/autosdk.js +50 -0
- 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 +19 -6
- package/dist/guest/toolchains/native/vcruntime.d.ts +2 -3
- package/dist/guest/toolchains/native/vcruntime.js +12 -7
- package/dist/guest/toolchains/native/visual-studio.d.ts +5 -2
- package/dist/guest/toolchains/native/visual-studio.js +127 -25
- package/dist/guest/toolchains/native/vs-request.d.ts +23 -0
- package/dist/guest/toolchains/native/vs-request.js +62 -1
- package/dist/guest/toolchains/not-yet.d.ts +1 -1
- package/dist/guest/toolchains/not-yet.js +3 -3
- package/dist/guest/toolchains/persisted.js +2 -7
- package/dist/guest/toolchains/plan.js +27 -11
- 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/signature.d.ts +5 -0
- package/dist/guest/toolchains/signature.js +22 -0
- 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/tunnel.d.ts +3 -0
- package/dist/guest/vpn/tunnel.js +10 -12
- package/dist/guest/vpn/vpn.js +6 -1
- 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 +9 -3
- package/dist/host/accounts/leases.js +13 -2
- package/dist/host/accounts/source.d.ts +7 -1
- package/dist/host/accounts/source.js +28 -1
- package/dist/host/accounts/sources.js +4 -0
- package/dist/host/agent-commands/commands.js +1 -1
- package/dist/host/agent-commands/forwarders.d.ts +14 -2
- package/dist/host/agent-commands/forwarders.js +31 -13
- package/dist/host/agent-commands/reconcile.d.ts +2 -1
- package/dist/host/agent-commands/reconcile.js +7 -8
- package/dist/host/agent-commands/user-path.d.ts +5 -0
- package/dist/host/agent-commands/user-path.js +13 -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 +5 -0
- package/dist/host/launch/toolchains.d.ts +2 -1
- package/dist/host/launch/toolchains.js +5 -3
- package/dist/host/profile/accounts.js +2 -4
- package/dist/host/profile/claude-login.d.ts +3 -2
- package/dist/host/profile/claude-login.js +3 -13
- package/dist/host/vpn/index.d.ts +2 -1
- package/dist/host/vpn/index.js +2 -1
- package/dist/host/vpn/last.d.ts +28 -0
- package/dist/host/vpn/last.js +43 -0
- package/dist/host/vpn/login.d.ts +3 -1
- package/dist/host/vpn/login.js +17 -3
- package/dist/host/vpn/nordvpn.d.ts +2 -4
- package/dist/host/vpn/nordvpn.js +2 -24
- package/dist/runtime/agent.js +433 -90
- package/dist/runtime/daemon.js +3378 -1546
- package/dist/runtime/db.js +363 -90
- package/dist/runtime/main.js +5134 -2096
- package/dist/runtime/netproxy.js +308 -69
- package/dist/runtime/tool.js +2867 -1765
- package/dist/runtime/view.js +308 -69
- package/dist/selftest/agent-commands.test.js +45 -7
- package/dist/selftest/agent-paths.test.js +40 -13
- package/dist/selftest/agent-settings.test.d.ts +2 -0
- package/dist/selftest/agent-settings.test.js +94 -0
- 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 +7 -3
- 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/cli.test.js +4 -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 +10 -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/menu.test.js +5 -3
- package/dist/selftest/pc-installs.test.js +5 -0
- package/dist/selftest/persisted-installs.test.js +72 -0
- package/dist/selftest/service-accounts.test.js +3 -2
- package/dist/selftest/support/engine-golden.js +28 -1
- package/dist/selftest/support/fixtures.d.ts +15 -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/selftest/vpn.test.js +51 -3
- package/dist/shared/accounts/anthropic.d.ts +5 -0
- package/dist/shared/accounts/anthropic.js +15 -0
- package/dist/shared/accounts/index.d.ts +3 -0
- package/dist/shared/accounts/index.js +3 -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 +40 -3
- package/dist/shared/channel/schema.js +9 -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/io/disk.d.ts +9 -0
- package/dist/shared/io/disk.js +19 -0
- package/dist/shared/io/index.d.ts +1 -0
- package/dist/shared/io/index.js +1 -0
- package/dist/shared/readiness.d.ts +9 -0
- package/dist/shared/readiness.js +11 -0
- package/dist/shared/signer.d.ts +24 -0
- package/dist/shared/signer.js +15 -0
- package/dist/shared/vpn/failure.d.ts +10 -0
- package/dist/shared/vpn/failure.js +28 -0
- package/dist/sync/watcher.js +2 -0
- package/dist/web/index.html +1 -1
- package/dist/web/{main-GVZWWP4I.js → main-CCILLX2M.js} +75 -74
- package/native/csharp/HcsHost/AssemblyInfo.cs +3 -3
- package/native/csharp/HostTools/AssemblyInfo.cs +3 -3
- package/native/csharp/HostTools/Program.cs +14 -1
- package/native/csharp/HostTools/UserPath.cs +17 -0
- package/native/csharp/StorageHelper/AssemblyInfo.cs +3 -3
- package/native/scripts/edit-user-path.ps1 +6 -2
- 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/get-signature.ps1 +13 -0
- 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 +120 -27
- package/schemas/sandbox-config.schema.json +45 -14
- package/sandbox/scripts/get-signer.ps1 +0 -8
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { AppSigner } from '../signer.js';
|
|
1
2
|
export type AppCategory = 'agents' | 'editors' | 'databases' | 'api' | 'git' | 'utilities' | 'browsers' | 'gamedev' | 'cloud' | 'diagrams' | 'network' | 'reversing' | 'cli';
|
|
2
3
|
export declare const APP_CATEGORIES: {
|
|
3
4
|
id: AppCategory;
|
|
@@ -23,13 +24,31 @@ export type AppSource = {
|
|
|
23
24
|
locked: 'npm' | 'uv';
|
|
24
25
|
package: string;
|
|
25
26
|
version: string;
|
|
27
|
+
}
|
|
28
|
+
/** Nothing to download: a remote MCP server (AddonMcp.url). */
|
|
29
|
+
| {
|
|
30
|
+
remote: true;
|
|
26
31
|
};
|
|
27
|
-
/**
|
|
32
|
+
/**
|
|
33
|
+
* An MCP server an add-on adds to the sandbox's Claude Code (and Codex, with `codex`): `node <its folder>\<script>
|
|
34
|
+
* <args>`, the add-on's own program (`program`), or a remote server (`url`).
|
|
35
|
+
*/
|
|
28
36
|
export interface AddonMcp {
|
|
29
37
|
/** The server's name in Claude Code (sbx-...: the sandbox removes its own names again when the add-on is off). */
|
|
30
38
|
readonly name: string;
|
|
31
|
-
|
|
39
|
+
/** The script node runs, below the add-on's folder. */
|
|
40
|
+
readonly script?: string;
|
|
41
|
+
/** Instead: the add-on's own program (its exe) runs the server. */
|
|
42
|
+
readonly program?: boolean;
|
|
43
|
+
/** Instead: a remote server over HTTP; nothing runs in the sandbox, and it signs in with OAuth on first use. */
|
|
44
|
+
readonly url?: string;
|
|
32
45
|
readonly args?: readonly string[];
|
|
46
|
+
/** Variables of the agent's environment the server reads (Codex passes on only those it is told about). */
|
|
47
|
+
readonly envVars?: readonly string[];
|
|
48
|
+
/** Fixed variables for the server (switches such as telemetry off; never a secret). */
|
|
49
|
+
readonly env?: Readonly<Record<string, string>>;
|
|
50
|
+
/** Also in the sandbox's Codex (its config.toml), not only Claude Code. */
|
|
51
|
+
readonly codex?: boolean;
|
|
33
52
|
}
|
|
34
53
|
export interface AppEntry {
|
|
35
54
|
id: string;
|
|
@@ -41,7 +60,7 @@ export interface AppEntry {
|
|
|
41
60
|
/**
|
|
42
61
|
* How the download is unpacked: an archive (zip/7z/tar, the default), the file itself, an NSIS installer or an MSI.
|
|
43
62
|
*/
|
|
44
|
-
unpack?: 'archive' | 'file' | 'nsis' | 'msi';
|
|
63
|
+
unpack?: 'archive' | 'file' | 'nsis' | 'msi' | 'chromium';
|
|
45
64
|
/** The program to start (or the tool on PATH): a file name, or a regex (/.../) for names with a version in them. */
|
|
46
65
|
exe: string;
|
|
47
66
|
/** A command-line tool: its folder goes on PATH (no desktop shortcut). */
|
|
@@ -63,6 +82,11 @@ export interface AppEntry {
|
|
|
63
82
|
service?: boolean;
|
|
64
83
|
/** The MCP server it adds to the sandbox's Claude Code while it is on. */
|
|
65
84
|
mcp?: AddonMcp;
|
|
85
|
+
/**
|
|
86
|
+
* Who must sign the download (Authenticode), for a vendor that publishes no checksum: a download signed by anyone
|
|
87
|
+
* else is refused, and it counts as integrity for downloads.requireChecksum.
|
|
88
|
+
*/
|
|
89
|
+
signer?: AppSigner;
|
|
66
90
|
}
|
|
67
91
|
/** rtk (rtk-ai/rtk), pinned: the Apache-2.0 edition's Windows build. The checksum is the release's checksums.txt. */
|
|
68
92
|
export declare const RTK_VERSION = "1.0.1";
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
// shared by the menu on the PC (to list them) and the sandbox (to install them, guest/apps). VS Code and Windows
|
|
4
4
|
// Terminal have settings of their own (toolchains.vscode, provisioning.terminal) and are listed here too, like
|
|
5
5
|
// claude-mem (claudeProfile.syncClaudeMem) among the agent add-ons.
|
|
6
|
+
import { AGENTS_WEB_APPS } from './catalogue-agents-web.js';
|
|
6
7
|
import { GAMEDEV_APPS } from './catalogue-gamedev.js';
|
|
7
8
|
import { MOBILE_APPS } from './catalogue-mobile.js';
|
|
8
9
|
import { MODDING_APPS } from './catalogue-modding.js';
|
|
@@ -891,7 +892,7 @@ const CORE_APPS = [
|
|
|
891
892
|
},
|
|
892
893
|
];
|
|
893
894
|
/** Every app: the ones above, then the game-development, modding and mobile ones (each list in its own file). */
|
|
894
|
-
export const APPS = [...CORE_APPS, ...GAMEDEV_APPS, ...MODDING_APPS, ...MOBILE_APPS];
|
|
895
|
+
export const APPS = [...CORE_APPS, ...GAMEDEV_APPS, ...MODDING_APPS, ...MOBILE_APPS, ...AGENTS_WEB_APPS];
|
|
895
896
|
export function appById(id) {
|
|
896
897
|
return APPS.find((a) => a.id === id);
|
|
897
898
|
}
|
|
@@ -1,3 +1,5 @@
|
|
|
1
1
|
export { type AddonMcp, type AppCategory, APP_CATEGORIES, type AppSource, type AppEntry, APPS, appById, CCUSAGE_VERSION, CONTEXT7_MCP_VERSION, HEADROOM_VERSION, PLAYWRIGHT_MCP_VERSION, RTK_VERSION, } from './catalogue.js';
|
|
2
2
|
export { exeMatcher, appsToInstall, appsNeedMesa, appsNeedUv } from './selection.js';
|
|
3
|
-
export {
|
|
3
|
+
export { signerMatches, type AppSigner, type Signature } from '../signer.js';
|
|
4
|
+
export { AGENTS_WEB_APPS, BROWSER_USE_VERSION, CHROME_DEVTOOLS_MCP_VERSION, COMET_DOWNLOAD_URL, COMET_MCP_VERSION, COMET_SIGNER, PERPLEXITY_COMPUTER_MCP_URL, PERPLEXITY_MCP_VERSION, } from './catalogue-agents-web.js';
|
|
5
|
+
export { ADDON_MCP_PREFIX, addonGuideLine, addonMcpServer, type AddonPlace, claudeManagedSettings, codexWithAddonMcpServers, type CodexMcpServer, HEADROOM_ENV, HEADROOM_PORT, HEADROOM_UPSTREAM, headroomArgs, headroomEnv, headroomGuideLine, headroomUrl, type ManagedSettings, type McpServerConfig, rtkHookCommand, RTK_GUIDE_LINE, withAddonMcpServers, } from './agent-addons.js';
|
|
@@ -1,3 +1,5 @@
|
|
|
1
1
|
export { APP_CATEGORIES, APPS, appById, CCUSAGE_VERSION, CONTEXT7_MCP_VERSION, HEADROOM_VERSION, PLAYWRIGHT_MCP_VERSION, RTK_VERSION, } from './catalogue.js';
|
|
2
2
|
export { exeMatcher, appsToInstall, appsNeedMesa, appsNeedUv } from './selection.js';
|
|
3
|
-
export {
|
|
3
|
+
export { signerMatches } from '../signer.js';
|
|
4
|
+
export { AGENTS_WEB_APPS, BROWSER_USE_VERSION, CHROME_DEVTOOLS_MCP_VERSION, COMET_DOWNLOAD_URL, COMET_MCP_VERSION, COMET_SIGNER, PERPLEXITY_COMPUTER_MCP_URL, PERPLEXITY_MCP_VERSION, } from './catalogue-agents-web.js';
|
|
5
|
+
export { ADDON_MCP_PREFIX, addonGuideLine, addonMcpServer, claudeManagedSettings, codexWithAddonMcpServers, HEADROOM_ENV, HEADROOM_PORT, HEADROOM_UPSTREAM, headroomArgs, headroomEnv, headroomGuideLine, headroomUrl, rtkHookCommand, RTK_GUIDE_LINE, withAddonMcpServers, } from './agent-addons.js';
|
|
@@ -17,14 +17,23 @@ export declare const BootProgressSchema: z.ZodObject<{
|
|
|
17
17
|
done: z.ZodNumber;
|
|
18
18
|
total: z.ZodNumber;
|
|
19
19
|
}, z.core.$strict>;
|
|
20
|
+
/** Work that goes on after the agent has started (Visual Studio installing): its name and how it is going. */
|
|
21
|
+
export declare const BackgroundWorkSchema: z.ZodObject<{
|
|
22
|
+
name: z.ZodString;
|
|
23
|
+
state: z.ZodEnum<{
|
|
24
|
+
done: "done";
|
|
25
|
+
running: "running";
|
|
26
|
+
failed: "failed";
|
|
27
|
+
}>;
|
|
28
|
+
}, z.core.$strict>;
|
|
20
29
|
/** C:\AgentData\run\sandbox.json: boot progress of the sandbox as a whole. */
|
|
21
30
|
export declare const SandboxStatusSchema: z.ZodObject<{
|
|
22
31
|
launchId: z.ZodString;
|
|
23
32
|
phase: z.ZodEnum<{
|
|
24
33
|
provisioning: "provisioning";
|
|
34
|
+
failed: "failed";
|
|
25
35
|
booting: "booting";
|
|
26
36
|
ready: "ready";
|
|
27
|
-
failed: "failed";
|
|
28
37
|
}>;
|
|
29
38
|
message: z.ZodString;
|
|
30
39
|
updatedAt: z.ZodString;
|
|
@@ -43,6 +52,14 @@ export declare const SandboxStatusSchema: z.ZodObject<{
|
|
|
43
52
|
done: z.ZodNumber;
|
|
44
53
|
total: z.ZodNumber;
|
|
45
54
|
}, z.core.$strict>>>;
|
|
55
|
+
background: z.ZodCatch<z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
56
|
+
name: z.ZodString;
|
|
57
|
+
state: z.ZodEnum<{
|
|
58
|
+
done: "done";
|
|
59
|
+
running: "running";
|
|
60
|
+
failed: "failed";
|
|
61
|
+
}>;
|
|
62
|
+
}, z.core.$strict>>>>;
|
|
46
63
|
}, z.core.$strip>;
|
|
47
64
|
/**
|
|
48
65
|
* A project the host registered after boot (sandbox claude from another folder): everything the guest needs to
|
|
@@ -93,6 +110,10 @@ export declare const ProjectSpecSchema: z.ZodObject<{
|
|
|
93
110
|
acceptLicense: z.ZodBoolean;
|
|
94
111
|
components: z.ZodArray<z.ZodString>;
|
|
95
112
|
keepInstallFiles: z.ZodBoolean;
|
|
113
|
+
visualStudio: z.ZodEnum<{
|
|
114
|
+
full: "full";
|
|
115
|
+
autosdk: "autosdk";
|
|
116
|
+
}>;
|
|
96
117
|
persistEngines: z.ZodBoolean;
|
|
97
118
|
derivedDataCache: z.ZodEnum<{
|
|
98
119
|
persisted: "persisted";
|
|
@@ -326,6 +347,10 @@ export declare const GuestRequestSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
|
326
347
|
acceptLicense: z.ZodBoolean;
|
|
327
348
|
components: z.ZodArray<z.ZodString>;
|
|
328
349
|
keepInstallFiles: z.ZodBoolean;
|
|
350
|
+
visualStudio: z.ZodEnum<{
|
|
351
|
+
full: "full";
|
|
352
|
+
autosdk: "autosdk";
|
|
353
|
+
}>;
|
|
329
354
|
persistEngines: z.ZodBoolean;
|
|
330
355
|
derivedDataCache: z.ZodEnum<{
|
|
331
356
|
persisted: "persisted";
|
|
@@ -579,6 +604,10 @@ export declare const GuestRequestSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
|
579
604
|
acceptLicense: z.ZodBoolean;
|
|
580
605
|
components: z.ZodArray<z.ZodString>;
|
|
581
606
|
keepInstallFiles: z.ZodBoolean;
|
|
607
|
+
visualStudio: z.ZodEnum<{
|
|
608
|
+
full: "full";
|
|
609
|
+
autosdk: "autosdk";
|
|
610
|
+
}>;
|
|
582
611
|
persistEngines: z.ZodBoolean;
|
|
583
612
|
derivedDataCache: z.ZodEnum<{
|
|
584
613
|
persisted: "persisted";
|
|
@@ -854,9 +883,9 @@ export declare const SessionStatusSchema: z.ZodObject<{
|
|
|
854
883
|
cwd: z.ZodString;
|
|
855
884
|
project: z.ZodOptional<z.ZodString>;
|
|
856
885
|
phase: z.ZodEnum<{
|
|
886
|
+
running: "running";
|
|
857
887
|
failed: "failed";
|
|
858
888
|
starting: "starting";
|
|
859
|
-
running: "running";
|
|
860
889
|
exited: "exited";
|
|
861
890
|
}>;
|
|
862
891
|
message: z.ZodString;
|
|
@@ -878,8 +907,8 @@ export declare const ProjectStatusSchema: z.ZodObject<{
|
|
|
878
907
|
workspace: z.ZodString;
|
|
879
908
|
phase: z.ZodEnum<{
|
|
880
909
|
provisioning: "provisioning";
|
|
881
|
-
ready: "ready";
|
|
882
910
|
failed: "failed";
|
|
911
|
+
ready: "ready";
|
|
883
912
|
}>;
|
|
884
913
|
message: z.ZodString;
|
|
885
914
|
updatedAt: z.ZodString;
|
|
@@ -898,6 +927,13 @@ export declare const VpnStatusSchema: z.ZodObject<{
|
|
|
898
927
|
up: "up";
|
|
899
928
|
}>;
|
|
900
929
|
message: z.ZodString;
|
|
930
|
+
code: z.ZodOptional<z.ZodEnum<{
|
|
931
|
+
auth: "auth";
|
|
932
|
+
unreachable: "unreachable";
|
|
933
|
+
driver: "driver";
|
|
934
|
+
timeout: "timeout";
|
|
935
|
+
other: "other";
|
|
936
|
+
}>>;
|
|
901
937
|
killSwitch: z.ZodBoolean;
|
|
902
938
|
killSwitchHeld: z.ZodOptional<z.ZodBoolean>;
|
|
903
939
|
server: z.ZodOptional<z.ZodString>;
|
|
@@ -910,6 +946,7 @@ export type ProjectStatus = z.output<typeof ProjectStatusSchema>;
|
|
|
910
946
|
export type AttachEndpoint = z.output<typeof AttachEndpointSchema>;
|
|
911
947
|
export type SandboxStatus = z.output<typeof SandboxStatusSchema>;
|
|
912
948
|
export type BootProgress = z.output<typeof BootProgressSchema>;
|
|
949
|
+
export type BackgroundWork = z.output<typeof BackgroundWorkSchema>;
|
|
913
950
|
export type GuestRequest = z.output<typeof GuestRequestSchema>;
|
|
914
951
|
export type GuestResponse = z.output<typeof GuestResponseSchema>;
|
|
915
952
|
export type SessionStatus = z.output<typeof SessionStatusSchema>;
|
|
@@ -20,6 +20,11 @@ export const BootProgressSchema = z.strictObject({
|
|
|
20
20
|
done: z.number().int().min(0).max(1000),
|
|
21
21
|
total: z.number().int().min(0).max(1000),
|
|
22
22
|
});
|
|
23
|
+
/** Work that goes on after the agent has started (Visual Studio installing): its name and how it is going. */
|
|
24
|
+
export const BackgroundWorkSchema = z.strictObject({
|
|
25
|
+
name: Text(64),
|
|
26
|
+
state: z.enum(['running', 'done', 'failed']),
|
|
27
|
+
});
|
|
23
28
|
/** C:\AgentData\run\sandbox.json: boot progress of the sandbox as a whole. */
|
|
24
29
|
export const SandboxStatusSchema = z.object({
|
|
25
30
|
launchId: Text(64),
|
|
@@ -33,6 +38,8 @@ export const SandboxStatusSchema = z.object({
|
|
|
33
38
|
addresses: z.array(z.string().max(45)).max(8).optional(),
|
|
34
39
|
/** A malformed progress is dropped, never the status (the phase still counts). */
|
|
35
40
|
progress: BootProgressSchema.optional().catch(undefined),
|
|
41
|
+
/** Installs that continue after the boot is ready; a malformed list is dropped, never the status. */
|
|
42
|
+
background: z.array(BackgroundWorkSchema).max(16).optional().catch(undefined),
|
|
36
43
|
});
|
|
37
44
|
const VersionSchema = z.strictObject({ spec: Text(128), source: Text(256) });
|
|
38
45
|
const DatabasePlanSchema = z.strictObject({
|
|
@@ -198,6 +205,8 @@ export const ProjectStatusSchema = z.object({
|
|
|
198
205
|
export const VpnStatusSchema = z.object({
|
|
199
206
|
state: z.enum(['off', 'starting', 'up', 'failed']),
|
|
200
207
|
message: Text(2000),
|
|
208
|
+
/** Why it failed, when it did: `auth` (login refused), `unreachable`, `driver`, `timeout` or `other`. */
|
|
209
|
+
code: z.enum(['auth', 'unreachable', 'driver', 'timeout', 'other']).optional(),
|
|
201
210
|
killSwitch: z.boolean(),
|
|
202
211
|
/** A direct connection was tried after the kill switch was applied: false = it still got out. */
|
|
203
212
|
killSwitchHeld: z.boolean().optional(),
|
|
@@ -51,6 +51,25 @@ export declare const SecretsFileSchema: z.ZodObject<{
|
|
|
51
51
|
keyId: z.ZodString;
|
|
52
52
|
p8: z.ZodString;
|
|
53
53
|
}, z.core.$strict>>;
|
|
54
|
+
perplexity: z.ZodOptional<z.ZodObject<{
|
|
55
|
+
apiKey: z.ZodString;
|
|
56
|
+
}, z.core.$strict>>;
|
|
57
|
+
comet: z.ZodOptional<z.ZodObject<{
|
|
58
|
+
cookies: z.ZodArray<z.ZodObject<{
|
|
59
|
+
name: z.ZodString;
|
|
60
|
+
value: z.ZodString;
|
|
61
|
+
domain: z.ZodString;
|
|
62
|
+
path: z.ZodString;
|
|
63
|
+
expires: z.ZodOptional<z.ZodNumber>;
|
|
64
|
+
secure: z.ZodBoolean;
|
|
65
|
+
httpOnly: z.ZodBoolean;
|
|
66
|
+
sameSite: z.ZodOptional<z.ZodEnum<{
|
|
67
|
+
Strict: "Strict";
|
|
68
|
+
Lax: "Lax";
|
|
69
|
+
None: "None";
|
|
70
|
+
}>>;
|
|
71
|
+
}, z.core.$strict>>;
|
|
72
|
+
}, z.core.$strict>>;
|
|
54
73
|
}, z.core.$strict>>;
|
|
55
74
|
liveFoldersKey: z.ZodOptional<z.ZodString>;
|
|
56
75
|
}, z.core.$strict>;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/** msiexec: "another installation is already in progress". */
|
|
2
|
+
export declare const ERROR_INSTALL_ALREADY_RUNNING = 1618;
|
|
3
|
+
export declare const INSTALLER_RETRIES = 20;
|
|
4
|
+
export declare const INSTALLER_WAIT_MS = 15000;
|
|
5
|
+
/** Whether an installer that exited with `code` after `attempt` tries (1 = the first) should be started again. */
|
|
6
|
+
export declare function installerRetry(code: number | null, attempt: number): boolean;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
// Windows Installer lets one install run at a time machine-wide: another process holding Global\_MSIExecute makes
|
|
2
|
+
// msiexec exit with 1618. Pure.
|
|
3
|
+
/** msiexec: "another installation is already in progress". */
|
|
4
|
+
export const ERROR_INSTALL_ALREADY_RUNNING = 1618;
|
|
5
|
+
export const INSTALLER_RETRIES = 20;
|
|
6
|
+
export const INSTALLER_WAIT_MS = 15_000;
|
|
7
|
+
/** Whether an installer that exited with `code` after `attempt` tries (1 = the first) should be started again. */
|
|
8
|
+
export function installerRetry(code, attempt) {
|
|
9
|
+
return code === ERROR_INSTALL_ALREADY_RUNNING && attempt <= INSTALLER_RETRIES;
|
|
10
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export type Priority = 'foreground' | 'background';
|
|
2
|
+
/** Runs `work` so that every pool slot it asks for queues behind foreground work. */
|
|
3
|
+
export declare function asBackground<T>(work: () => T): T;
|
|
4
|
+
export declare class Limiter {
|
|
5
|
+
private readonly size;
|
|
6
|
+
readonly name: string;
|
|
7
|
+
private active;
|
|
8
|
+
private peakActive;
|
|
9
|
+
private readonly queues;
|
|
10
|
+
constructor(size: number, name?: string);
|
|
11
|
+
/** The most slots that were ever busy at once (tests). */
|
|
12
|
+
get peak(): number;
|
|
13
|
+
get running(): number;
|
|
14
|
+
/** Runs `work` in a free slot (waiting its turn), and frees the slot afterwards. */
|
|
15
|
+
run<T>(work: () => Promise<T> | T, priority?: Priority): Promise<T>;
|
|
16
|
+
private acquire;
|
|
17
|
+
private take;
|
|
18
|
+
private release;
|
|
19
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
// A counting limiter for heavy work (downloads, unpacking, installers). FIFO, foreground before background. A task
|
|
2
|
+
// that holds a slot may not take a slot of another limiter: nested pools throw, so a deadlock cannot happen. Pure.
|
|
3
|
+
import { AsyncLocalStorage } from 'node:async_hooks';
|
|
4
|
+
/** The pool whose slot the current async context holds (at most one). */
|
|
5
|
+
const held = new AsyncLocalStorage();
|
|
6
|
+
/** The priority of work started in this async context (set by `asBackground`). */
|
|
7
|
+
const priorityOf = new AsyncLocalStorage();
|
|
8
|
+
/** Runs `work` so that every pool slot it asks for queues behind foreground work. */
|
|
9
|
+
export function asBackground(work) {
|
|
10
|
+
return priorityOf.run('background', work);
|
|
11
|
+
}
|
|
12
|
+
export class Limiter {
|
|
13
|
+
size;
|
|
14
|
+
name;
|
|
15
|
+
active = 0;
|
|
16
|
+
peakActive = 0;
|
|
17
|
+
queues = { foreground: [], background: [] };
|
|
18
|
+
constructor(size, name = 'pool') {
|
|
19
|
+
this.size = size;
|
|
20
|
+
this.name = name;
|
|
21
|
+
if (!Number.isInteger(size) || size < 1)
|
|
22
|
+
throw new Error('A pool needs a size of at least 1');
|
|
23
|
+
}
|
|
24
|
+
/** The most slots that were ever busy at once (tests). */
|
|
25
|
+
get peak() {
|
|
26
|
+
return this.peakActive;
|
|
27
|
+
}
|
|
28
|
+
get running() {
|
|
29
|
+
return this.active;
|
|
30
|
+
}
|
|
31
|
+
/** Runs `work` in a free slot (waiting its turn), and frees the slot afterwards. */
|
|
32
|
+
async run(work, priority = priorityOf.getStore() ?? 'foreground') {
|
|
33
|
+
const holding = held.getStore();
|
|
34
|
+
if (holding)
|
|
35
|
+
throw new Error('nested pool: ' + this.name + ' requested while holding ' + holding.name);
|
|
36
|
+
await this.acquire(priority);
|
|
37
|
+
try {
|
|
38
|
+
return await held.run(this, async () => work());
|
|
39
|
+
}
|
|
40
|
+
finally {
|
|
41
|
+
this.release();
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
acquire(priority) {
|
|
45
|
+
if (this.active < this.size) {
|
|
46
|
+
this.take();
|
|
47
|
+
return Promise.resolve();
|
|
48
|
+
}
|
|
49
|
+
return new Promise((resolve) => {
|
|
50
|
+
this.queues[priority].push({
|
|
51
|
+
start: () => {
|
|
52
|
+
this.take();
|
|
53
|
+
resolve();
|
|
54
|
+
},
|
|
55
|
+
});
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
take() {
|
|
59
|
+
this.active++;
|
|
60
|
+
this.peakActive = Math.max(this.peakActive, this.active);
|
|
61
|
+
}
|
|
62
|
+
release() {
|
|
63
|
+
this.active--;
|
|
64
|
+
const next = this.queues.foreground.shift() ?? this.queues.background.shift();
|
|
65
|
+
next?.start();
|
|
66
|
+
}
|
|
67
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { Limiter } from './limiter.js';
|
|
2
|
+
/** HTTP bodies. */
|
|
3
|
+
export declare const net: Limiter;
|
|
4
|
+
/** extractArchive, 7-Zip/NSIS unpack, npm ci/install, uv/pip, Steam, robocopy of big layouts, rustup/cargo. */
|
|
5
|
+
export declare const heavy: Limiter;
|
|
6
|
+
/** Every msiexec, vcredist, DXSETUP and the Visual Studio bootstrapper: Windows runs one install at a time. */
|
|
7
|
+
export declare const installer: Limiter;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
// The three pools (one set per process): the limiter instances only, so pure code can take a slot. The guest wires
|
|
2
|
+
// them to the downloader and extractor (guest/runtime/pools.ts installPools).
|
|
3
|
+
import { Limiter } from './limiter.js';
|
|
4
|
+
/** HTTP bodies. */
|
|
5
|
+
export const net = new Limiter(4, 'net');
|
|
6
|
+
/** extractArchive, 7-Zip/NSIS unpack, npm ci/install, uv/pip, Steam, robocopy of big layouts, rustup/cargo. */
|
|
7
|
+
export const heavy = new Limiter(2, 'heavy');
|
|
8
|
+
/** Every msiexec, vcredist, DXSETUP and the Visual Studio bootstrapper: Windows runs one install at a time. */
|
|
9
|
+
export const installer = new Limiter(1, 'installer');
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { Limiter } from '../concurrency/index.js';
|
|
1
2
|
/**
|
|
2
3
|
* A fresh `<destination>.staging-<hex>` folder next to `destination`: fill it, then moveIntoPlace. An interrupted copy
|
|
3
4
|
* or extraction leaves only the staging folder (cleanup/repair remove those), never a half-filled destination.
|
|
@@ -5,6 +6,7 @@
|
|
|
5
6
|
export declare function stagingFolder(destination: string): string;
|
|
6
7
|
/** Replaces `destination` with the finished `work` folder (a folder rename: the destination is never half there). */
|
|
7
8
|
export declare function moveIntoPlace(work: string, destination: string): void;
|
|
9
|
+
export declare function limitExtraction(limiter: Limiter | null): void;
|
|
8
10
|
/**
|
|
9
11
|
* Extracts .zip / .nupkg / .7z / .tar.gz with the tar.exe that ships with Windows, falling back to Expand-Archive.
|
|
10
12
|
* `members` limits it to those paths inside the archive (e.g. skip pgAdmin in the PostgreSQL zip).
|
|
@@ -18,11 +18,21 @@ export function moveIntoPlace(work, destination) {
|
|
|
18
18
|
fs.mkdirSync(path.dirname(destination), { recursive: true });
|
|
19
19
|
fs.renameSync(work, destination);
|
|
20
20
|
}
|
|
21
|
+
/** The guest's heavy pool (set by the guest at start-up; host code leaves it unset). */
|
|
22
|
+
let extractLimit = null;
|
|
23
|
+
export function limitExtraction(limiter) {
|
|
24
|
+
extractLimit = limiter;
|
|
25
|
+
}
|
|
21
26
|
/**
|
|
22
27
|
* Extracts .zip / .nupkg / .7z / .tar.gz with the tar.exe that ships with Windows, falling back to Expand-Archive.
|
|
23
28
|
* `members` limits it to those paths inside the archive (e.g. skip pgAdmin in the PostgreSQL zip).
|
|
24
29
|
*/
|
|
25
|
-
export
|
|
30
|
+
export function extractArchive(archive, destination, members = []) {
|
|
31
|
+
return extractLimit
|
|
32
|
+
? extractLimit.run(() => extract(archive, destination, members))
|
|
33
|
+
: extract(archive, destination, members);
|
|
34
|
+
}
|
|
35
|
+
async function extract(archive, destination, members) {
|
|
26
36
|
fs.mkdirSync(destination, { recursive: true });
|
|
27
37
|
let status = await spawnAsync(SYSTEM.tar(), ['-xf', archive, '-C', destination, ...members]);
|
|
28
38
|
if (status !== 0 && /\.(zip|nupkg)$/i.test(archive)) {
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/** Reads a URL as text, refusing more than `max` bytes. */
|
|
2
|
+
export type Fetcher = (url: string, max: number) => Promise<string>;
|
|
3
|
+
/** An answer whatever its status: the status, the header values asked for, and the body (at most `max` bytes). */
|
|
4
|
+
export interface BoundedResponse {
|
|
5
|
+
readonly status: number;
|
|
6
|
+
readonly header: (name: string) => string | null;
|
|
7
|
+
readonly text: string;
|
|
8
|
+
}
|
|
9
|
+
/** Reads a request with headers (or any other init) once; a status that is not 200 is an answer, not an error. */
|
|
10
|
+
export type RequestFetcher = (url: string, max: number, init?: RequestInit) => Promise<BoundedResponse>;
|
|
11
|
+
export declare function fetchBounded(url: string, max: number): Promise<string>;
|
|
12
|
+
/** One request with a timeout (10 s by default), no retries: for a check that should answer quickly. */
|
|
13
|
+
export declare function fetchBoundedResponse(url: string, max: number, init?: RequestInit, timeoutMs?: number): Promise<BoundedResponse>;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
// Reading an answer from the internet with a size limit: a server cannot make this PC download without end. Node
|
|
2
|
+
// built-ins only (it is part of the shared download helpers).
|
|
3
|
+
import { fetchRetry } from './http.js';
|
|
4
|
+
/** The body of a response, refusing more than `max` bytes. */
|
|
5
|
+
async function readBounded(response, url, max) {
|
|
6
|
+
const host = new URL(url).host;
|
|
7
|
+
const length = Number(response.headers.get('content-length')) || 0;
|
|
8
|
+
if (length > max)
|
|
9
|
+
throw new Error('The answer from ' + host + ' is too big.');
|
|
10
|
+
const reader = response.body?.getReader();
|
|
11
|
+
if (!reader)
|
|
12
|
+
throw new Error('Empty answer from ' + host + '.');
|
|
13
|
+
const chunks = [];
|
|
14
|
+
let size = 0;
|
|
15
|
+
for (;;) {
|
|
16
|
+
const { done, value } = await reader.read();
|
|
17
|
+
if (done)
|
|
18
|
+
break;
|
|
19
|
+
size += value.length;
|
|
20
|
+
if (size > max) {
|
|
21
|
+
await reader.cancel();
|
|
22
|
+
throw new Error('The answer from ' + host + ' is too big.');
|
|
23
|
+
}
|
|
24
|
+
chunks.push(value);
|
|
25
|
+
}
|
|
26
|
+
return Buffer.concat(chunks).toString('utf8');
|
|
27
|
+
}
|
|
28
|
+
export async function fetchBounded(url, max) {
|
|
29
|
+
return readBounded(await fetchRetry(url, {}, 2, 30000), url, max);
|
|
30
|
+
}
|
|
31
|
+
/** One request with a timeout (10 s by default), no retries: for a check that should answer quickly. */
|
|
32
|
+
export async function fetchBoundedResponse(url, max, init = {}, timeoutMs = 10000) {
|
|
33
|
+
const response = await fetch(url, {
|
|
34
|
+
...init,
|
|
35
|
+
signal: AbortSignal.timeout(timeoutMs),
|
|
36
|
+
headers: { 'User-Agent': 'windows-development-sandbox', ...(init.headers ?? {}) },
|
|
37
|
+
});
|
|
38
|
+
const text = await readBounded(response, url, max);
|
|
39
|
+
return { status: response.status, header: (name) => response.headers.get(name), text };
|
|
40
|
+
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { Limiter } from '../concurrency/index.js';
|
|
1
2
|
/** Expected checksums of a download; any that are given must match. */
|
|
2
3
|
export interface Checksums {
|
|
3
4
|
sha256?: string | null;
|
|
@@ -16,6 +17,8 @@ export interface ArchiveOptions extends Checksums {
|
|
|
16
17
|
/** Folders above `locate`'s to keep. */
|
|
17
18
|
up?: number;
|
|
18
19
|
fileName?: string;
|
|
20
|
+
/** A copy of the archive that `file()` already downloaded (checked then): used and removed instead of downloading. */
|
|
21
|
+
cached?: string;
|
|
19
22
|
members?: string[];
|
|
20
23
|
}
|
|
21
24
|
/**
|
|
@@ -26,6 +29,8 @@ export type DownloadWatcher = () => ((fraction: number) => void) | null;
|
|
|
26
29
|
export declare class Downloader {
|
|
27
30
|
/** downloads.requireChecksum: refuse anything without an expected hash. The guest sets it from session.json. */
|
|
28
31
|
requireChecksum: boolean;
|
|
32
|
+
/** The guest's net pool: how many HTTP bodies stream at once. Host code leaves it null. */
|
|
33
|
+
limit: Limiter | null;
|
|
29
34
|
private watcher;
|
|
30
35
|
/** Reports coarse progress of the downloads that start from now on to `watcher` (null: stop). */
|
|
31
36
|
watch(watcher: DownloadWatcher | null): void;
|
|
@@ -9,6 +9,8 @@ import { extractArchive, findFile, moveIntoPlace, stagingFolder } from './archiv
|
|
|
9
9
|
export class Downloader {
|
|
10
10
|
/** downloads.requireChecksum: refuse anything without an expected hash. The guest sets it from session.json. */
|
|
11
11
|
requireChecksum = false;
|
|
12
|
+
/** The guest's net pool: how many HTTP bodies stream at once. Host code leaves it null. */
|
|
13
|
+
limit = null;
|
|
12
14
|
watcher = null;
|
|
13
15
|
/** Reports coarse progress of the downloads that start from now on to `watcher` (null: stop). */
|
|
14
16
|
watch(watcher) {
|
|
@@ -28,48 +30,52 @@ export class Downloader {
|
|
|
28
30
|
url +
|
|
29
31
|
'): no checksum is published for it, and downloads.requireChecksum is on. Turn that setting off to allow downloads that cannot be verified.');
|
|
30
32
|
}
|
|
31
|
-
const response = await fetchRetry(url, {}, 3, 20 * 60 * 1000);
|
|
32
|
-
if (!response.body)
|
|
33
|
-
throw new Error('Empty response for ' + url);
|
|
34
33
|
fs.mkdirSync(path.dirname(destination), { recursive: true });
|
|
35
34
|
// Only the hashes that will be checked (sha512 of a 330 MB archive is not free).
|
|
36
35
|
const checks = ['sha256', 'sha512', 'sha1'].flatMap((kind) => {
|
|
37
36
|
const want = sums[kind]?.trim().toLowerCase();
|
|
38
37
|
return want ? [{ want, hash: crypto.createHash(kind) }] : [];
|
|
39
38
|
});
|
|
40
|
-
// Progress for the boot screen: every 10% or 5 s at most, never per chunk; called here so it knows who is
|
|
41
|
-
// downloading.
|
|
42
|
-
const size = Number(response.headers.get('content-length')) || 0;
|
|
43
|
-
const report = size > 0 ? (this.watcher?.() ?? null) : null;
|
|
44
|
-
let received = 0;
|
|
45
|
-
let tenth = 0;
|
|
46
|
-
let reportedAt = Date.now();
|
|
47
|
-
const tap = new Transform({
|
|
48
|
-
transform(chunk, _encoding, done) {
|
|
49
|
-
for (const c of checks)
|
|
50
|
-
c.hash.update(chunk);
|
|
51
|
-
if (report) {
|
|
52
|
-
received += chunk.length;
|
|
53
|
-
const now = Math.floor((received * 10) / size);
|
|
54
|
-
if (now !== tenth || Date.now() - reportedAt > 5000) {
|
|
55
|
-
tenth = now;
|
|
56
|
-
reportedAt = Date.now();
|
|
57
|
-
try {
|
|
58
|
-
report(Math.min(1, received / size));
|
|
59
|
-
}
|
|
60
|
-
catch {
|
|
61
|
-
/* progress never breaks a download */
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
done(null, chunk);
|
|
66
|
-
},
|
|
67
|
-
});
|
|
68
39
|
// Written to <destination>.part and moved into place only once complete and verified, so an interrupted download
|
|
69
40
|
// never leaves a partial file under the real name.
|
|
70
41
|
const partial = destination + '.part';
|
|
71
|
-
|
|
42
|
+
// Only the transfer holds a net slot; the signature check and the rename below stay outside it.
|
|
43
|
+
const transfer = async () => {
|
|
44
|
+
const response = await fetchRetry(url, {}, 3, 20 * 60 * 1000);
|
|
45
|
+
if (!response.body)
|
|
46
|
+
throw new Error('Empty response for ' + url);
|
|
47
|
+
// Progress for the boot screen: every 10% or 5 s at most, never per chunk; called here so it knows who is
|
|
48
|
+
// downloading.
|
|
49
|
+
const size = Number(response.headers.get('content-length')) || 0;
|
|
50
|
+
const report = size > 0 ? (this.watcher?.() ?? null) : null;
|
|
51
|
+
let received = 0;
|
|
52
|
+
let tenth = 0;
|
|
53
|
+
let reportedAt = Date.now();
|
|
54
|
+
const tap = new Transform({
|
|
55
|
+
transform(chunk, _encoding, done) {
|
|
56
|
+
for (const c of checks)
|
|
57
|
+
c.hash.update(chunk);
|
|
58
|
+
if (report) {
|
|
59
|
+
received += chunk.length;
|
|
60
|
+
const now = Math.floor((received * 10) / size);
|
|
61
|
+
if (now !== tenth || Date.now() - reportedAt > 5000) {
|
|
62
|
+
tenth = now;
|
|
63
|
+
reportedAt = Date.now();
|
|
64
|
+
try {
|
|
65
|
+
report(Math.min(1, received / size));
|
|
66
|
+
}
|
|
67
|
+
catch {
|
|
68
|
+
/* progress never breaks a download */
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
done(null, chunk);
|
|
73
|
+
},
|
|
74
|
+
});
|
|
72
75
|
await pipeline(Readable.fromWeb(response.body), tap, fs.createWriteStream(partial));
|
|
76
|
+
};
|
|
77
|
+
try {
|
|
78
|
+
await (this.limit ? this.limit.run(transfer) : transfer());
|
|
73
79
|
if (checks.some((c) => c.hash.digest('hex') !== c.want))
|
|
74
80
|
throw new Error('Checksum mismatch for ' + url);
|
|
75
81
|
if (sums.verify)
|
|
@@ -90,12 +96,18 @@ export class Downloader {
|
|
|
90
96
|
const work = stagingFolder(destination);
|
|
91
97
|
try {
|
|
92
98
|
const archive = path.join(work, options.fileName ?? path.basename(new URL(url).pathname));
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
+
if (options.cached && fs.existsSync(options.cached)) {
|
|
100
|
+
fs.mkdirSync(work, { recursive: true });
|
|
101
|
+
fs.copyFileSync(options.cached, archive);
|
|
102
|
+
fs.rmSync(options.cached, { force: true });
|
|
103
|
+
}
|
|
104
|
+
else
|
|
105
|
+
await this.file(url, archive, {
|
|
106
|
+
sha256: options.sha256,
|
|
107
|
+
sha512: options.sha512,
|
|
108
|
+
sha1: options.sha1,
|
|
109
|
+
...(options.verify ? { verify: options.verify } : {}),
|
|
110
|
+
});
|
|
99
111
|
const extracted = path.join(work, 'x');
|
|
100
112
|
await extractArchive(archive, extracted, options.members);
|
|
101
113
|
let root = extracted;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export { fetchRetry, fetchJson, fetchText } from './http.js';
|
|
2
|
-
export {
|
|
2
|
+
export { fetchBounded, fetchBoundedResponse, type BoundedResponse, type Fetcher, type RequestFetcher, } from './bounded-fetch.js';
|
|
3
|
+
export { stagingFolder, moveIntoPlace, extractArchive, findFile, limitExtraction } from './archive.js';
|
|
3
4
|
export { type ArchiveOptions, type Checksums, type DownloadWatcher, Downloader, downloader } from './downloader.js';
|
|
4
5
|
export { spawnAsync } from './spawn.js';
|
|
5
6
|
export { type ReleaseAsset, githubAsset, parseReleasePage, latestGithubTag, parseReleaseTags } from './github.js';
|