windows-development-sandbox 1.10.0 → 1.11.4
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 +64 -17
- package/config.example.json +5 -1
- package/dist/app/features/accounts/accounts.def.d.ts +122 -0
- package/dist/app/features/accounts/accounts.def.js +243 -0
- package/dist/app/features/accounts/accounts.run.d.ts +51 -0
- package/dist/app/features/accounts/accounts.run.js +125 -0
- package/dist/app/features/accounts/index.d.ts +2 -0
- package/dist/app/features/accounts/index.js +3 -0
- package/dist/app/features/agents/agent-entry.d.ts +17 -0
- package/dist/app/features/agents/agent-entry.js +50 -0
- package/dist/app/features/agents/agents.def.d.ts +65 -0
- package/dist/app/features/agents/agents.def.js +142 -0
- package/dist/app/features/agents/agents.run.d.ts +31 -0
- package/dist/app/features/agents/agents.run.js +189 -0
- package/dist/app/features/agents/index.d.ts +3 -0
- package/dist/app/features/agents/index.js +4 -0
- package/dist/app/features/apps/apps-rows.d.ts +31 -0
- package/dist/app/features/apps/apps-rows.js +73 -0
- package/dist/app/features/apps/apps.def.d.ts +181 -0
- package/dist/app/features/apps/apps.def.js +264 -0
- package/dist/app/features/apps/apps.run.d.ts +58 -0
- package/dist/app/features/apps/apps.run.js +76 -0
- package/dist/app/features/apps/index.d.ts +3 -0
- package/dist/app/features/apps/index.js +4 -0
- package/dist/app/features/data/data.def.d.ts +154 -0
- package/dist/app/features/data/data.def.js +194 -0
- package/dist/app/features/data/data.run.d.ts +46 -0
- package/dist/app/features/data/data.run.js +141 -0
- package/dist/app/features/data/index.d.ts +2 -0
- package/dist/app/features/data/index.js +3 -0
- package/dist/app/features/defs.d.ts +959 -4
- package/dist/app/features/defs.js +151 -10
- package/dist/app/features/engine/engine.def.d.ts +228 -0
- package/dist/app/features/engine/engine.def.js +194 -0
- package/dist/app/features/engine/engine.run.d.ts +72 -0
- package/dist/app/features/engine/engine.run.js +77 -0
- package/dist/app/features/engine/index.d.ts +2 -0
- package/dist/app/features/engine/index.js +4 -0
- package/dist/app/features/files/files.def.d.ts +51 -0
- package/dist/app/features/files/files.def.js +38 -0
- package/dist/app/features/files/files.run.d.ts +20 -0
- package/dist/app/features/files/files.run.js +59 -0
- package/dist/app/features/files/index.d.ts +2 -0
- package/dist/app/features/files/index.js +3 -0
- package/dist/app/features/github/github.def.d.ts +80 -0
- package/dist/app/features/github/github.def.js +142 -0
- package/dist/app/features/github/github.run.d.ts +36 -0
- package/dist/app/features/github/github.run.js +59 -0
- package/dist/app/features/github/index.d.ts +2 -0
- package/dist/app/features/github/index.js +3 -0
- package/dist/app/features/health/health.def.d.ts +275 -0
- package/dist/app/features/health/health.def.js +297 -0
- package/dist/app/features/health/health.run.d.ts +125 -0
- package/dist/app/features/health/health.run.js +204 -0
- package/dist/app/features/health/index.d.ts +2 -0
- package/dist/app/features/health/index.js +3 -0
- package/dist/app/features/logs/index.d.ts +2 -0
- package/dist/app/features/logs/index.js +3 -0
- package/dist/app/features/logs/logs.def.d.ts +78 -0
- package/dist/app/features/logs/logs.def.js +115 -0
- package/dist/app/features/logs/logs.run.d.ts +20 -0
- package/dist/app/features/logs/logs.run.js +42 -0
- package/dist/app/features/projects/index.d.ts +2 -0
- package/dist/app/features/projects/index.js +3 -0
- package/dist/app/features/projects/projects.def.d.ts +101 -0
- package/dist/app/features/projects/projects.def.js +208 -0
- package/dist/app/features/projects/projects.run.d.ts +56 -0
- package/dist/app/features/projects/projects.run.js +155 -0
- package/dist/app/features/sandbox/sandbox.def.js +11 -5
- package/dist/app/features/sessions/sessions.def.js +3 -0
- package/dist/app/features/settings/categories.def.js +3 -2
- package/dist/{cli/menu/settings/share.d.ts → app/features/settings/settings-share.d.ts} +1 -1
- package/dist/{cli/menu/settings/share.js → app/features/settings/settings-share.js} +3 -2
- package/dist/app/features/settings/settings.def.d.ts +22 -5
- package/dist/app/features/settings/settings.def.js +81 -6
- package/dist/app/features/settings/settings.run.d.ts +17 -0
- package/dist/app/features/settings/settings.run.js +89 -4
- package/dist/app/features/storage/index.d.ts +2 -0
- package/dist/app/features/storage/index.js +3 -0
- package/dist/app/features/storage/storage.def.d.ts +133 -0
- package/dist/app/features/storage/storage.def.js +220 -0
- package/dist/app/features/storage/storage.run.d.ts +62 -0
- package/dist/app/features/storage/storage.run.js +370 -0
- package/dist/app/features/updates/index.d.ts +3 -0
- package/dist/app/features/updates/index.js +4 -0
- package/dist/app/features/updates/update-lines.d.ts +13 -0
- package/dist/app/features/updates/update-lines.js +61 -0
- package/dist/app/features/updates/updates.def.d.ts +89 -0
- package/dist/app/features/updates/updates.def.js +224 -0
- package/dist/app/features/updates/updates.run.d.ts +48 -0
- package/dist/app/features/updates/updates.run.js +154 -0
- package/dist/app/features/vpn/index.d.ts +2 -0
- package/dist/app/features/vpn/index.js +3 -0
- package/dist/app/features/vpn/vpn.def.d.ts +112 -0
- package/dist/app/features/vpn/vpn.def.js +174 -0
- package/dist/app/features/vpn/vpn.run.d.ts +37 -0
- package/dist/app/features/vpn/vpn.run.js +54 -0
- package/dist/app/features/web/index.d.ts +2 -0
- package/dist/app/features/web/index.js +3 -0
- package/dist/app/features/web/web.def.d.ts +33 -0
- package/dist/app/features/web/web.def.js +90 -0
- package/dist/app/features/web/web.run.d.ts +24 -0
- package/dist/app/features/web/web.run.js +93 -0
- package/dist/app/kernel/define.d.ts +10 -1
- package/dist/app/kernel/io.d.ts +34 -0
- package/dist/app/kernel/io.js +9 -0
- package/dist/app/kernel/rpc.d.ts +17 -0
- package/dist/app/kernel/text.d.ts +2 -0
- package/dist/app/kernel/text.js +7 -0
- package/dist/app/kernel/view.d.ts +24 -1
- package/dist/app/kernel/view.js +1 -1
- package/dist/app/registry.js +74 -1
- package/dist/cli/args.js +1 -1
- package/dist/cli/commands/context.d.ts +7 -0
- package/dist/cli/commands/context.js +29 -2
- package/dist/cli/commands/engine.js +5 -58
- package/dist/cli/commands/github.d.ts +2 -0
- package/dist/cli/commands/github.js +11 -0
- package/dist/cli/commands/index.d.ts +3 -5
- package/dist/cli/commands/index.js +3 -5
- package/dist/cli/commands/launch/launch.js +21 -4
- package/dist/cli/commands/launch/running.js +4 -1
- package/dist/cli/commands/maintenance/config.js +1 -6
- package/dist/cli/commands/maintenance/index.d.ts +0 -1
- package/dist/cli/commands/maintenance/index.js +1 -2
- package/dist/cli/commands/maintenance/logs.js +27 -32
- package/dist/cli/commands/maintenance/migrate.d.ts +0 -8
- package/dist/cli/commands/maintenance/migrate.js +2 -44
- package/dist/cli/commands/maintenance/update.d.ts +0 -19
- package/dist/cli/commands/maintenance/update.js +1 -99
- package/dist/cli/commands/projects/index.d.ts +0 -1
- package/dist/cli/commands/projects/index.js +0 -1
- package/dist/cli/commands/registry.d.ts +1 -1
- package/dist/cli/commands/registry.js +29 -11
- package/dist/cli/commands/repair/checks/data.js +1 -1
- package/dist/cli/commands/repair/checks/hcs.js +28 -1
- package/dist/cli/commands/repair/checks/sandbox.js +1 -1
- package/dist/cli/commands/repair/health-run.d.ts +30 -0
- package/dist/cli/commands/repair/health-run.js +32 -0
- package/dist/cli/commands/repair/printer.d.ts +2 -2
- package/dist/cli/commands/repair/printer.js +2 -11
- package/dist/cli/commands/repair/run.d.ts +1 -21
- package/dist/cli/commands/repair/run.js +13 -70
- package/dist/cli/commands/storage/index.d.ts +0 -1
- package/dist/cli/commands/storage/index.js +0 -1
- package/dist/cli/commands/storage/offer.js +6 -2
- package/dist/cli/commands/vpn.d.ts +1 -3
- package/dist/cli/commands/vpn.js +8 -89
- package/dist/cli/commands/web.d.ts +2 -1
- package/dist/cli/commands/web.js +14 -78
- package/dist/cli/index.js +3 -2
- package/dist/cli/manifest.d.ts +16 -153
- package/dist/cli/manifest.js +20 -50
- package/dist/cli/menu/command-form.js +1 -2
- package/dist/cli/menu/io-menu.d.ts +2 -2
- package/dist/cli/menu/io-menu.js +6 -4
- package/dist/cli/menu/menu.js +1 -1
- package/dist/cli/menu/pages/accounts-page.d.ts +5 -17
- package/dist/cli/menu/pages/accounts-page.js +28 -170
- package/dist/cli/menu/pages/agents-page.d.ts +17 -18
- package/dist/cli/menu/pages/agents-page.js +67 -124
- package/dist/cli/menu/pages/apps-page.d.ts +15 -8
- package/dist/cli/menu/pages/apps-page.js +121 -29
- package/dist/cli/menu/pages/list-page.js +10 -1
- package/dist/cli/menu/pages/maintenance-page.d.ts +51 -52
- package/dist/cli/menu/pages/maintenance-page.js +246 -427
- package/dist/cli/menu/pages/sandbox-page.d.ts +3 -5
- package/dist/cli/menu/pages/sandbox-page.js +34 -112
- package/dist/cli/menu/pages/settings-page.d.ts +21 -3
- package/dist/cli/menu/pages/settings-page.js +89 -17
- package/dist/cli/menu/render-view.js +2 -1
- package/dist/cli/menu/settings/index.d.ts +0 -1
- package/dist/cli/menu/settings/index.js +3 -3
- package/dist/cli/menu/views.js +28 -0
- package/dist/cli/operations/handler.js +7 -3
- package/dist/cli/operations/input.d.ts +1 -1
- package/dist/cli/operations/input.js +29 -5
- package/dist/cli/operations/io-cli.js +9 -1
- package/dist/cli/operations/spec.js +8 -2
- package/dist/cli/output/render-view.js +2 -0
- package/dist/cli/{commands/data/collect.js → services/data-collect.js} +2 -2
- package/dist/cli/{commands/data/remove.js → services/data-remove.js} +2 -2
- package/dist/cli/services/data-service.d.ts +1 -1
- package/dist/cli/services/data-service.js +2 -2
- package/dist/cli/services/databases-service.d.ts +5 -0
- package/dist/cli/services/databases-service.js +15 -0
- package/dist/cli/services/health-service.d.ts +8 -4
- package/dist/cli/services/health-service.js +10 -8
- package/dist/cli/services/index.d.ts +4 -1
- package/dist/cli/services/index.js +4 -1
- package/dist/cli/services/logs-service.d.ts +7 -0
- package/dist/cli/services/logs-service.js +13 -0
- package/dist/cli/services/storage-service.d.ts +19 -0
- package/dist/cli/services/storage-service.js +71 -0
- package/dist/cli/services/vpn-service.d.ts +6 -4
- package/dist/cli/services/vpn-service.js +5 -11
- package/dist/cli/services/web-service.d.ts +4 -3
- package/dist/cli/services/web-service.js +12 -32
- package/dist/core/config/defaults.js +2 -1
- package/dist/core/schema/config.d.ts +5 -0
- package/dist/core/schema/config.js +2 -0
- package/dist/core/schema/github.d.ts +4 -0
- package/dist/core/schema/github.js +7 -0
- package/dist/core/schema/index.d.ts +1 -0
- package/dist/core/schema/index.js +1 -0
- package/dist/core/schema/profile.d.ts +1 -0
- package/dist/core/schema/profile.js +3 -0
- package/dist/core/schema/sandbox.js +3 -3
- package/dist/core/schema/toolchains.js +2 -2
- package/dist/core/types.d.ts +6 -3
- package/dist/guest/boot/boot.js +8 -0
- package/dist/guest/daemon/daemon.js +1 -1
- package/dist/guest/daemon/sessions.d.ts +3 -2
- package/dist/guest/daemon/sessions.js +38 -7
- package/dist/guest/governor/core.d.ts +44 -0
- package/dist/guest/governor/core.js +124 -0
- package/dist/guest/governor/decide.d.ts +46 -18
- package/dist/guest/governor/decide.js +136 -82
- package/dist/guest/governor/governor.d.ts +2 -38
- package/dist/guest/governor/governor.js +33 -113
- package/dist/guest/governor/index.d.ts +1 -0
- package/dist/guest/governor/index.js +1 -0
- package/dist/guest/network/firewall.d.ts +2 -0
- package/dist/guest/network/firewall.js +3 -3
- package/dist/guest/sessions/viewer.js +5 -1
- package/dist/guest/setup/github-token.d.ts +7 -0
- package/dist/guest/setup/github-token.js +65 -0
- package/dist/guest/toolchains/languages/node.js +11 -1
- package/dist/guest/toolchains/native/rust-extras.js +2 -2
- package/dist/guest/toolchains/tools/cli.d.ts +8 -0
- package/dist/guest/toolchains/tools/cli.js +35 -2
- package/dist/guest/vpn/openvpn.d.ts +5 -0
- package/dist/guest/vpn/openvpn.js +14 -1
- package/dist/guest/vpn/vpn.js +55 -16
- package/dist/guest/vpn/wireguard.js +2 -0
- package/dist/host/channel/attach.d.ts +1 -0
- package/dist/host/channel/attach.js +1 -0
- package/dist/host/channel/channel.d.ts +1 -1
- package/dist/host/channel/channel.js +2 -2
- package/dist/host/engines/hcs/check.d.ts +1 -0
- package/dist/host/engines/hcs/check.js +1 -1
- package/dist/host/engines/hcs/engine.d.ts +1 -1
- package/dist/host/engines/hcs/engine.js +6 -4
- package/dist/host/engines/hcs/helper.d.ts +11 -0
- package/dist/host/engines/hcs/helper.js +31 -2
- package/dist/host/engines/hcs/leftovers.d.ts +42 -0
- package/dist/host/engines/hcs/leftovers.js +101 -0
- package/dist/host/engines/index.d.ts +1 -0
- package/dist/host/engines/index.js +1 -0
- package/dist/host/github/deliver.d.ts +13 -0
- package/dist/host/github/deliver.js +51 -0
- package/dist/host/github/index.d.ts +2 -0
- package/dist/host/github/index.js +3 -0
- package/dist/host/github/token.d.ts +21 -0
- package/dist/host/github/token.js +74 -0
- package/dist/host/launch/generate.js +11 -5
- package/dist/host/launch/index.d.ts +1 -1
- package/dist/host/launch/index.js +1 -1
- package/dist/host/launch/session-file.js +1 -2
- package/dist/host/launch/wsb-file.d.ts +11 -7
- package/dist/host/launch/wsb-file.js +30 -12
- package/dist/host/life/host-memory.d.ts +18 -0
- package/dist/host/life/host-memory.js +66 -0
- package/dist/host/life/watchdog.d.ts +9 -0
- package/dist/host/life/watchdog.js +17 -1
- package/dist/host/sandbox/tasklist.d.ts +6 -0
- package/dist/host/sandbox/tasklist.js +37 -0
- package/dist/host/secrets/launch-secrets.d.ts +2 -1
- package/dist/host/secrets/launch-secrets.js +4 -2
- package/dist/host/vpn/status.js +13 -3
- package/dist/host/web/backend.d.ts +1 -3
- package/dist/host/web/index.d.ts +2 -1
- package/dist/host/web/index.js +2 -1
- package/dist/host/web/live.d.ts +23 -0
- package/dist/host/web/live.js +107 -0
- package/dist/host/web/rpc.d.ts +6 -1
- package/dist/host/web/rpc.js +23 -31
- package/dist/host/web/runner.d.ts +4 -0
- package/dist/host/web/runner.js +12 -1
- package/dist/host/web/server.d.ts +30 -2
- package/dist/host/web/server.js +87 -29
- package/dist/host/web/state.d.ts +1 -0
- package/dist/host/web/state.js +2 -0
- package/dist/runtime/agent.js +30 -6
- package/dist/runtime/daemon.js +337 -177
- package/dist/runtime/db.js +30 -6
- package/dist/runtime/main.js +389 -77
- package/dist/runtime/netproxy.js +30 -6
- package/dist/runtime/view.js +495 -146
- package/dist/selftest/app.test.js +632 -12
- package/dist/selftest/channel.test.js +18 -1
- package/dist/selftest/cli.test.js +1 -1
- package/dist/selftest/config.test.js +1 -1
- package/dist/selftest/contained.test.js +1 -1
- package/dist/selftest/data.test.js +1 -2
- package/dist/selftest/engine.test.js +3 -1
- package/dist/selftest/github.test.d.ts +2 -0
- package/dist/selftest/github.test.js +243 -0
- package/dist/selftest/hcs.test.js +105 -8
- package/dist/selftest/health.test.js +71 -0
- package/dist/selftest/heavy-load.test.js +132 -72
- package/dist/selftest/index.js +4 -0
- package/dist/selftest/layout.test.js +8 -0
- package/dist/selftest/live-terminal.test.js +74 -0
- package/dist/selftest/menu-screens.js +171 -56
- package/dist/selftest/menu.test.js +54 -37
- package/dist/selftest/migrate.test.js +14 -12
- package/dist/selftest/powershell-variables.test.d.ts +2 -0
- package/dist/selftest/powershell-variables.test.js +61 -0
- package/dist/selftest/support/engine-golden.js +1 -0
- package/dist/selftest/support/fixtures.d.ts +4 -0
- package/dist/selftest/support/web-preview.d.ts +1 -0
- package/dist/selftest/support/web-preview.js +856 -0
- package/dist/selftest/update-service.test.js +15 -8
- package/dist/selftest/vpn.test.js +86 -2
- package/dist/selftest/web.test.js +58 -11
- package/dist/shared/channel/run-dir.d.ts +2 -0
- package/dist/shared/channel/run-dir.js +3 -0
- package/dist/shared/channel/schema.d.ts +7 -0
- package/dist/shared/channel/schema.js +9 -1
- package/dist/shared/channel/secrets.d.ts +1 -0
- package/dist/shared/channel/secrets.js +3 -0
- package/dist/shared/github/index.d.ts +1 -0
- package/dist/shared/github/index.js +2 -0
- package/dist/shared/github/token.d.ts +29 -0
- package/dist/shared/github/token.js +89 -0
- package/dist/shared/memory/policy.d.ts +33 -12
- package/dist/shared/memory/policy.js +50 -19
- package/dist/shared/pty/ctrl-c.d.ts +18 -0
- package/dist/shared/pty/ctrl-c.js +36 -0
- package/dist/shared/pty/index.d.ts +1 -0
- package/dist/shared/pty/index.js +1 -0
- package/dist/shared/pty/terminal.d.ts +2 -0
- package/dist/shared/pty/terminal.js +21 -2
- package/dist/shared/vpn/kill-switch.d.ts +13 -2
- package/dist/shared/vpn/kill-switch.js +88 -8
- package/dist/shared/web/protocol.d.ts +0 -4
- package/dist/sync/watcher.d.ts +2 -0
- package/dist/sync/watcher.js +8 -3
- package/dist/web/index.html +2 -2
- package/dist/web/{main-T5DMCHYV.css → main-MU5XWZMS.css} +1 -1
- package/dist/web/main-SLQNJRXD.js +219 -0
- package/native/csharp/HcsHost/AssemblyInfo.cs +3 -3
- package/native/csharp/HostTools/AssemblyInfo.cs +3 -3
- package/native/csharp/HostTools/MemoryStatus.cs +58 -2
- package/native/csharp/HostTools/Program.cs +7 -1
- package/package.json +10 -3
- package/sandbox/csharp/MemGov.cs +240 -38
- package/sandbox/csharp/PtyHost.cs +104 -15
- package/sandbox/csharp/SandboxTools/CpuCap.cs +50 -1
- package/sandbox/csharp/SandboxTools/Program.cs +1 -1
- package/sandbox/scripts/repair-wmi-services.ps1 +26 -0
- package/schemas/config.schema.json +19 -5
- package/schemas/sandbox-config.schema.json +7 -3
- package/dist/cli/commands/accounts.d.ts +0 -2
- package/dist/cli/commands/accounts.js +0 -96
- package/dist/cli/commands/data/clean.d.ts +0 -3
- package/dist/cli/commands/data/clean.js +0 -60
- package/dist/cli/commands/data/index.d.ts +0 -4
- package/dist/cli/commands/data/index.js +0 -62
- package/dist/cli/commands/maintenance/clean.d.ts +0 -2
- package/dist/cli/commands/maintenance/clean.js +0 -24
- package/dist/cli/commands/maintenance/config-share.d.ts +0 -12
- package/dist/cli/commands/maintenance/config-share.js +0 -80
- package/dist/cli/commands/projects/projects.d.ts +0 -2
- package/dist/cli/commands/projects/projects.js +0 -162
- package/dist/cli/commands/storage/contained.d.ts +0 -3
- package/dist/cli/commands/storage/contained.js +0 -179
- package/dist/cli/commands/storage/storage.d.ts +0 -8
- package/dist/cli/commands/storage/storage.js +0 -179
- package/dist/cli/menu/add-agent.d.ts +0 -47
- package/dist/cli/menu/add-agent.js +0 -168
- package/dist/cli/menu/apps.d.ts +0 -69
- package/dist/cli/menu/apps.js +0 -214
- package/dist/cli/menu/data-folder.d.ts +0 -18
- package/dist/cli/menu/data-folder.js +0 -99
- package/dist/cli/menu/share-settings.d.ts +0 -21
- package/dist/cli/menu/share-settings.js +0 -112
- package/dist/cli/menu/vpn-login.d.ts +0 -16
- package/dist/cli/menu/vpn-login.js +0 -74
- package/dist/web/main-NRRS5O6Z.js +0 -157
- /package/dist/cli/{commands/data/collect.d.ts → services/data-collect.d.ts} +0 -0
- /package/dist/cli/{commands/data/remove.d.ts → services/data-remove.d.ts} +0 -0
package/dist/runtime/main.js
CHANGED
|
@@ -5532,7 +5532,7 @@ var require_lodash = __commonJS({
|
|
|
5532
5532
|
});
|
|
5533
5533
|
|
|
5534
5534
|
// src/guest/entries/main.ts
|
|
5535
|
-
import
|
|
5535
|
+
import fs61 from "node:fs";
|
|
5536
5536
|
import path74 from "node:path";
|
|
5537
5537
|
|
|
5538
5538
|
// src/guest/runtime/paths.ts
|
|
@@ -25411,6 +25411,9 @@ var AttachSchema = external_exports.strictObject({
|
|
|
25411
25411
|
),
|
|
25412
25412
|
autoHide: external_exports.boolean().describe(
|
|
25413
25413
|
"Hide the Windows Sandbox window whenever this terminal attaches; it keeps running (sandbox show brings it back)."
|
|
25414
|
+
),
|
|
25415
|
+
confirmCtrlC: external_exports.boolean().describe(
|
|
25416
|
+
'In an attached terminal and the sandbox window, a single Ctrl+C is held back (the title says so) and only a second one within 1.5 seconds reaches the agent: a Ctrl+C meant as "copy" no longer stops it. Esc still stops an agent.'
|
|
25414
25417
|
)
|
|
25415
25418
|
});
|
|
25416
25419
|
var AgentCommandsSchema = external_exports.strictObject({
|
|
@@ -25455,7 +25458,9 @@ var SandboxSchema = external_exports.strictObject({
|
|
|
25455
25458
|
engine: external_exports.enum(["windows-sandbox", "hcs"]).describe(
|
|
25456
25459
|
'(alpha) What runs the sandbox. "windows-sandbox" = Windows Sandbox (the default: desktop, Windows Terminal, GPU, clipboard, audio, printers). "hcs" = a headless Hyper-V isolated Server Core container for agents (no desktop, GPU or clipboard); it needs Windows features and an image on this PC (sandbox engine check hcs lists what is missing), and starting it is not enabled yet in this alpha. sandbox engine shows what each engine can do. Yours only: a project file (.sandbox-config.json) cannot set it.'
|
|
25457
25460
|
),
|
|
25458
|
-
memoryMb: external_exports.union([external_exports.literal("auto"), external_exports.number().int().min(2048)]).describe(
|
|
25461
|
+
memoryMb: external_exports.union([external_exports.literal("auto"), external_exports.number().int().min(2048)]).describe(
|
|
25462
|
+
'Sandbox RAM in MB (>= 2048), or "auto": free RAM minus reserveHostMb, capped at maxMemoryMb. Never more than this PC can keep in RAM for it (its RAM minus the larger of reserveHostMb and 25 %, 2 GB more with vGPU): a bigger value is lowered.'
|
|
25463
|
+
),
|
|
25459
25464
|
maxMemoryMb: external_exports.number().int().positive().describe('Upper limit for memoryMb "auto".'),
|
|
25460
25465
|
maxMemoryPercent: external_exports.number().int().min(10).max(100).describe(`memoryMb "auto" never takes more than this share of this PC's total RAM (percent).`),
|
|
25461
25466
|
cpuLimit: external_exports.union([external_exports.literal("none"), external_exports.number().int().min(5).max(100)]).describe(
|
|
@@ -25468,10 +25473,10 @@ var SandboxSchema = external_exports.strictObject({
|
|
|
25468
25473
|
'Memory always left for this PC when memoryMb is "auto": the sandbox gets at most (free RAM, and RAM plus paging file still unused) minus this.'
|
|
25469
25474
|
),
|
|
25470
25475
|
agentMemoryHeadroomMb: external_exports.union([external_exports.literal("auto"), external_exports.literal("none"), external_exports.number().int().min(0)]).describe(
|
|
25471
|
-
'
|
|
25476
|
+
'The last resort that keeps the sandbox up, in MB below its commit limit (RAM plus paging file): builds are slowed down long before (sandbox.pressureResponse); only if everything the agents start together would take the sandbox to the very edge of its memory, where Windows inside it would start failing, is a build refused memory instead of Windows. "auto" = the larger of 1536 MB and 3 % of the commit limit; "none" = no backstop. Yours only: a project file cannot change it.'
|
|
25472
25477
|
),
|
|
25473
25478
|
pressureResponse: external_exports.boolean().describe(
|
|
25474
|
-
"When the sandbox (or this PC) runs low on memory, slow
|
|
25479
|
+
"When the sandbox (or this PC) runs low on memory, slow builds down in steps, like a PC that gets slower instead of failing: build programs get lower CPU and memory priority, then less CPU, then compilers take turns (the waiting ones briefly suspended and trimmed to the paging file). Nothing is stopped or killed, and the agents themselves are never touched. Yours only: a project file cannot change it."
|
|
25475
25480
|
),
|
|
25476
25481
|
vGpu: external_exports.boolean().describe(
|
|
25477
25482
|
"Virtual GPU. Off by default: Microsoft notes it widens the sandbox attack surface. The sandbox then uses this PC's graphics card, and with some graphics drivers heavy use can freeze the whole PC: turn it on only when a program in the sandbox needs the GPU (the mesa toolchain gives software OpenGL without it)."
|
|
@@ -25617,7 +25622,7 @@ var ToolchainsSchema = external_exports.strictObject({
|
|
|
25617
25622
|
`GNU host: "lld" links with Rust's own lld through MinGW's gcc (much less memory than GNU ld), "gnu" with GNU ld.`
|
|
25618
25623
|
),
|
|
25619
25624
|
linkSlots: external_exports.union([external_exports.literal("auto"), external_exports.number().int().min(1).max(32)]).describe(
|
|
25620
|
-
'GNU host: how many programs may link at the same time in the whole sandbox (other links wait). "auto" = one per
|
|
25625
|
+
'GNU host: how many programs may link at the same time in the whole sandbox (other links wait). "auto" = one per 3 GB of sandbox memory after 6 GB, 2 to 8 (the memory governor slows links down too when memory runs short).'
|
|
25621
25626
|
)
|
|
25622
25627
|
}),
|
|
25623
25628
|
msvc: external_exports.strictObject({
|
|
@@ -25692,7 +25697,7 @@ var ToolchainsSchema = external_exports.strictObject({
|
|
|
25692
25697
|
}),
|
|
25693
25698
|
cli: external_exports.strictObject({
|
|
25694
25699
|
gh: EnabledSchema.describe(
|
|
25695
|
-
'GitHub CLI (gh). Only with provisioning.git.access "full": gh can push and merge through the GitHub API, past a read-only git. Your PC\'s gh login is never copied; `gh auth login` inside persists (GH_CONFIG_DIR). "auto" = when the project has a .github folder.'
|
|
25700
|
+
'GitHub CLI (gh). Only with provisioning.git.access "full": gh can push and merge through the GitHub API, past a read-only git. Your PC\'s gh login is never copied; `gh auth login` inside persists (GH_CONFIG_DIR), unless a token you saved for sandboxes is handed over (github.shareToken). "auto" = when the project has a .github folder.'
|
|
25696
25701
|
),
|
|
25697
25702
|
zstd: EnabledSchema.describe('Zstandard (zstd). "auto" = off; set true to get it.'),
|
|
25698
25703
|
openssl: EnabledSchema.describe(
|
|
@@ -26620,6 +26625,13 @@ var VpnSchema = external_exports.strictObject({
|
|
|
26620
26625
|
)
|
|
26621
26626
|
});
|
|
26622
26627
|
|
|
26628
|
+
// src/core/schema/github.ts
|
|
26629
|
+
var GithubSchema = external_exports.strictObject({
|
|
26630
|
+
shareToken: external_exports.boolean().describe(
|
|
26631
|
+
'Give each sandbox the GitHub token you saved with `sandbox github login` (best a fine-grained token limited to some repositories and permissions), so gh and https git work there without logging in. Only with provisioning.git.access "full". The agent in the sandbox can read the token and use it for whatever it allows. A project file (.sandbox-config.json) cannot turn this on.'
|
|
26632
|
+
)
|
|
26633
|
+
});
|
|
26634
|
+
|
|
26623
26635
|
// src/core/schema/config.ts
|
|
26624
26636
|
var ConfigSchema = external_exports.strictObject({
|
|
26625
26637
|
$schema: SchemaRefSchema.optional(),
|
|
@@ -26650,6 +26662,7 @@ var ConfigSchema = external_exports.strictObject({
|
|
|
26650
26662
|
}),
|
|
26651
26663
|
network: NetworkSchema,
|
|
26652
26664
|
vpn: VpnSchema,
|
|
26665
|
+
github: GithubSchema,
|
|
26653
26666
|
provisioning: ProvisioningSchema,
|
|
26654
26667
|
downloads: DownloadsSchema,
|
|
26655
26668
|
toolchains: ToolchainsSchema,
|
|
@@ -26812,19 +26825,25 @@ var GuestRequestSchema = external_exports.discriminatedUnion("kind", [
|
|
|
26812
26825
|
id: IdSchema,
|
|
26813
26826
|
reason: Text(300),
|
|
26814
26827
|
seconds: external_exports.number().int().min(10).max(300),
|
|
26828
|
+
/** "severe": the PC is nearly out of memory; builds go to the governor's last step at once. */
|
|
26829
|
+
level: external_exports.enum(["slow", "severe"]).optional(),
|
|
26815
26830
|
createdAt: TimeSchema
|
|
26816
26831
|
})
|
|
26817
26832
|
]);
|
|
26818
26833
|
var PressureStatusSchema = external_exports.object({
|
|
26819
26834
|
level: external_exports.enum(["ok", "throttled", "suspending"]),
|
|
26835
|
+
/** The governor's dial, 0 (nothing wrong) to 4 (one compiler at a time). */
|
|
26836
|
+
step: external_exports.number().int().min(0).max(4).optional(),
|
|
26820
26837
|
profile: external_exports.enum(["normal", "gentle"]),
|
|
26821
26838
|
/** Share of the sandbox's RAM still free and of its commit limit in use (percent). */
|
|
26822
26839
|
ramFreePercent: external_exports.number().int().min(0).max(100),
|
|
26823
26840
|
commitPercent: external_exports.number().int().min(0).max(100),
|
|
26824
26841
|
/** Programs running at lower priority because of it. */
|
|
26825
26842
|
lowered: external_exports.number().int().min(0).max(1024),
|
|
26826
|
-
/**
|
|
26843
|
+
/** Compilers waiting their turn right now (name, process id, seconds until they may go on). */
|
|
26827
26844
|
paused: external_exports.array(external_exports.object({ name: Text(64), pid: external_exports.number().int(), seconds: external_exports.number().int().min(0).max(60) })).max(8),
|
|
26845
|
+
/** The CPU share the compilers get together (percent; 100 = no cap). */
|
|
26846
|
+
cpuPercent: external_exports.number().int().min(0).max(100).optional(),
|
|
26828
26847
|
/** The PC itself asked for slowing down (its memory or CPU is low). */
|
|
26829
26848
|
pcLow: external_exports.boolean(),
|
|
26830
26849
|
lastAction: Text(300),
|
|
@@ -26868,6 +26887,8 @@ var VpnStatusSchema = external_exports.object({
|
|
|
26868
26887
|
state: external_exports.enum(["off", "starting", "up", "failed"]),
|
|
26869
26888
|
message: Text(2e3),
|
|
26870
26889
|
killSwitch: external_exports.boolean(),
|
|
26890
|
+
/** A direct connection was tried after the kill switch was applied: false = it still got out. */
|
|
26891
|
+
killSwitchHeld: external_exports.boolean().optional(),
|
|
26871
26892
|
/** The server's name, e.g. uk2201.nordvpn.com. */
|
|
26872
26893
|
server: Text(128).optional(),
|
|
26873
26894
|
/** What the sandbox's traffic looks like from outside, once the tunnel is up. */
|
|
@@ -27055,6 +27076,8 @@ var RunDir = class {
|
|
|
27055
27076
|
vpnFile;
|
|
27056
27077
|
/** What the memory governor in the sandbox is doing (pressure.json). */
|
|
27057
27078
|
pressureFile;
|
|
27079
|
+
/** What the sandbox's programs may really use (budget.json): processors, memory, build jobs, link slots. */
|
|
27080
|
+
budgetFile;
|
|
27058
27081
|
requestsDir;
|
|
27059
27082
|
responsesDir;
|
|
27060
27083
|
sessionsDir;
|
|
@@ -27068,6 +27091,7 @@ var RunDir = class {
|
|
|
27068
27091
|
this.sandboxFile = path6.join(this.root, "sandbox.json");
|
|
27069
27092
|
this.vpnFile = path6.join(this.root, "vpn.json");
|
|
27070
27093
|
this.pressureFile = path6.join(this.root, "pressure.json");
|
|
27094
|
+
this.budgetFile = path6.join(this.root, "budget.json");
|
|
27071
27095
|
this.requestsDir = path6.join(this.root, "requests");
|
|
27072
27096
|
this.responsesDir = path6.join(this.root, "responses");
|
|
27073
27097
|
this.sessionsDir = path6.join(this.root, "sessions");
|
|
@@ -27507,7 +27531,7 @@ function writeStatus(phase, message) {
|
|
|
27507
27531
|
}
|
|
27508
27532
|
|
|
27509
27533
|
// src/guest/boot/boot.ts
|
|
27510
|
-
import
|
|
27534
|
+
import fs60 from "node:fs";
|
|
27511
27535
|
import path73 from "node:path";
|
|
27512
27536
|
import { spawn as spawn9 } from "node:child_process";
|
|
27513
27537
|
|
|
@@ -29234,9 +29258,28 @@ async function setupUv(env) {
|
|
|
29234
29258
|
function ghConfigDir() {
|
|
29235
29259
|
return path34.join(stateDir, "gh");
|
|
29236
29260
|
}
|
|
29261
|
+
function deliveredGhConfigDir() {
|
|
29262
|
+
return path34.join(localDir, "gh-token");
|
|
29263
|
+
}
|
|
29264
|
+
function ghExePath() {
|
|
29265
|
+
const entry = CLI_TOOLS.find((t) => t.name === "gh");
|
|
29266
|
+
const dir = tool("cli", "gh");
|
|
29267
|
+
return path34.join(entry?.subdir ? path34.join(dir, entry.subdir) : dir, entry?.exe ?? "gh.exe");
|
|
29268
|
+
}
|
|
29269
|
+
var GH_NOTE = " (log in once with: gh auth login --web --insecure-storage; it is kept between sandboxes)";
|
|
29270
|
+
function warnKeyringLogin() {
|
|
29271
|
+
try {
|
|
29272
|
+
const hosts = fs28.readFileSync(path34.join(ghConfigDir(), "hosts.yml"), "utf8");
|
|
29273
|
+
if (/^\s*user:/m.test(hosts) && !/oauth_token:/.test(hosts))
|
|
29274
|
+
warn(
|
|
29275
|
+
"gh: the GitHub login from an earlier sandbox was kept in Windows Credential Manager, which is wiped with each sandbox. Log in again with: gh auth login --web --insecure-storage (then it lasts)."
|
|
29276
|
+
);
|
|
29277
|
+
} catch {
|
|
29278
|
+
}
|
|
29279
|
+
}
|
|
29237
29280
|
var toolVars = {
|
|
29238
29281
|
gh: () => ({
|
|
29239
|
-
GH_CONFIG_DIR: mkdirp(ghConfigDir()),
|
|
29282
|
+
GH_CONFIG_DIR: exists(deliveredGhConfigDir()) ? deliveredGhConfigDir() : mkdirp(ghConfigDir()),
|
|
29240
29283
|
GH_NO_UPDATE_NOTIFIER: "1",
|
|
29241
29284
|
GH_NO_EXTENSION_UPDATE_NOTIFIER: "1"
|
|
29242
29285
|
})
|
|
@@ -29274,9 +29317,11 @@ async function setupCli(env, settings, gitAccess, refresh = false) {
|
|
|
29274
29317
|
await setupSingleExe(env, name, entry.repo, entry.asset(arch), entry.exe, tool("cli", name), {
|
|
29275
29318
|
refresh,
|
|
29276
29319
|
subdir: entry.subdir,
|
|
29277
|
-
size: entry.size
|
|
29320
|
+
size: entry.size,
|
|
29321
|
+
...name === "gh" ? { note: GH_NOTE } : {}
|
|
29278
29322
|
});
|
|
29279
29323
|
Object.assign(env.vars, toolVars[name]?.() ?? {});
|
|
29324
|
+
if (name === "gh") warnKeyringLogin();
|
|
29280
29325
|
} catch (e) {
|
|
29281
29326
|
warn(name + " could not be set up and is skipped; the other tools are not affected. Reason: " + errMsg(e));
|
|
29282
29327
|
env.summary.push(entry.name + ": FAILED");
|
|
@@ -30082,6 +30127,10 @@ var activate = async (version2) => {
|
|
|
30082
30127
|
fs36.rmSync(NVM_SYMLINK, { recursive: true, force: true });
|
|
30083
30128
|
fs36.symlinkSync(path45.join(NVM_HOME, "v" + version2), NVM_SYMLINK, "junction");
|
|
30084
30129
|
};
|
|
30130
|
+
var PLAYWRIGHT_VARS = () => ({
|
|
30131
|
+
PLAYWRIGHT_BROWSERS_PATH: tool("ms-playwright"),
|
|
30132
|
+
PLAYWRIGHT_MCP_BROWSER: "msedge"
|
|
30133
|
+
});
|
|
30085
30134
|
async function setupNode(env, versions, config2) {
|
|
30086
30135
|
if (dryRun) {
|
|
30087
30136
|
log("(dry run) would provision nvm and Node " + versions.node.spec + " (from " + versions.node.source + ")");
|
|
@@ -30115,13 +30164,14 @@ async function setupNode(env, versions, config2) {
|
|
|
30115
30164
|
warn("Node " + version2 + " from this PC: " + errMsg(e));
|
|
30116
30165
|
}
|
|
30117
30166
|
}
|
|
30118
|
-
Object.assign(env.vars, { NVM_HOME, NVM_SYMLINK });
|
|
30167
|
+
Object.assign(env.vars, { NVM_HOME, NVM_SYMLINK, ...PLAYWRIGHT_VARS() });
|
|
30119
30168
|
if (duringSession()) env.prepend.push(path45.join(NVM_HOME, "v" + main), NVM_HOME, NVM_SYMLINK);
|
|
30120
30169
|
else {
|
|
30121
30170
|
await activate(main);
|
|
30122
30171
|
env.prepend.push(NVM_HOME, NVM_SYMLINK);
|
|
30123
30172
|
}
|
|
30124
30173
|
env.summary.push("node: " + main + " (from " + versions.node.source + ", switch with nvm use)");
|
|
30174
|
+
env.summary.push("playwright: ready (Edge; browsers it downloads are kept; in tests use channel: 'msedge')");
|
|
30125
30175
|
await packageManagers(env, config2, main);
|
|
30126
30176
|
}
|
|
30127
30177
|
var packageManagers = async (env, config2, version2) => {
|
|
@@ -32032,11 +32082,17 @@ import os8 from "node:os";
|
|
|
32032
32082
|
import path51 from "node:path";
|
|
32033
32083
|
|
|
32034
32084
|
// src/shared/memory/policy.ts
|
|
32085
|
+
function buildJobs(cpus, memoryGb) {
|
|
32086
|
+
return Math.max(2, Math.min(cpus, Math.floor((memoryGb - 6) / 3)));
|
|
32087
|
+
}
|
|
32088
|
+
function linkSlotsFor(memoryGb) {
|
|
32089
|
+
return Math.max(2, Math.min(8, Math.floor((memoryGb - 6) / 3)));
|
|
32090
|
+
}
|
|
32035
32091
|
function cargoJobs(cpus, memoryGb, sessions) {
|
|
32036
|
-
const byCpu = Math.max(2, Math.min(
|
|
32092
|
+
const byCpu = Math.max(2, Math.min(8, Math.floor(cpus / 4)));
|
|
32037
32093
|
const byMemory = Math.max(1, Math.floor(memoryGb / 4));
|
|
32038
32094
|
const jobs = Math.min(byCpu, byMemory);
|
|
32039
|
-
return Math.max(1, Math.min(jobs, Math.floor(
|
|
32095
|
+
return Math.max(1, Math.min(jobs, Math.floor(buildJobs(cpus, memoryGb) / Math.max(1, sessions))));
|
|
32040
32096
|
}
|
|
32041
32097
|
|
|
32042
32098
|
// src/guest/toolchains/native/rust-extras.ts
|
|
@@ -32059,7 +32115,7 @@ function linkGate(env, rust, host) {
|
|
|
32059
32115
|
const gate = path51.join(mkdirp(tool("shims")), "linkgate.exe");
|
|
32060
32116
|
fs41.copyFileSync(ensureCompiled("linkgate"), gate);
|
|
32061
32117
|
const memoryGb = os8.totalmem() / 1024 ** 3;
|
|
32062
|
-
const slots = rust.linkSlots === "auto" ?
|
|
32118
|
+
const slots = rust.linkSlots === "auto" ? linkSlotsFor(memoryGb) : rust.linkSlots;
|
|
32063
32119
|
env.vars.AGENT_LINK_SLOTS = String(slots);
|
|
32064
32120
|
env.vars.AGENT_REAL_LINKER = gcc;
|
|
32065
32121
|
env.vars.CARGO_TARGET_X86_64_PC_WINDOWS_GNU_LINKER = gate;
|
|
@@ -33170,14 +33226,14 @@ var problems = [];
|
|
|
33170
33226
|
function networkProblems() {
|
|
33171
33227
|
return problems;
|
|
33172
33228
|
}
|
|
33173
|
-
|
|
33229
|
+
function longPath(file3) {
|
|
33174
33230
|
if (!hasShortName(file3)) return file3;
|
|
33175
33231
|
try {
|
|
33176
33232
|
return fs48.realpathSync.native(file3);
|
|
33177
33233
|
} catch {
|
|
33178
33234
|
return file3;
|
|
33179
33235
|
}
|
|
33180
|
-
}
|
|
33236
|
+
}
|
|
33181
33237
|
async function applyAttachRule(ptyHostExe) {
|
|
33182
33238
|
if (!session.attach.enabled) return;
|
|
33183
33239
|
if (!ptyHostExe) {
|
|
@@ -33210,9 +33266,9 @@ async function applyNetworkPolicy(ptyHostExe) {
|
|
|
33210
33266
|
log("Networking is disabled for this sandbox.");
|
|
33211
33267
|
return "offline";
|
|
33212
33268
|
}
|
|
33213
|
-
const
|
|
33214
|
-
const exempt =
|
|
33215
|
-
const lanRules =
|
|
33269
|
+
const block2 = session.network.blockPrivateRanges;
|
|
33270
|
+
const exempt = block2 ? discoverExemptIps() : [];
|
|
33271
|
+
const lanRules = block2 ? buildFirewallCommands(exempt) : [];
|
|
33216
33272
|
const forwardRules = forwardRule();
|
|
33217
33273
|
const commands = [
|
|
33218
33274
|
...lanRules,
|
|
@@ -33231,18 +33287,18 @@ async function applyNetworkPolicy(ptyHostExe) {
|
|
|
33231
33287
|
warn("network.dns could not be applied: " + errMsg(e));
|
|
33232
33288
|
}
|
|
33233
33289
|
}
|
|
33234
|
-
if (!
|
|
33235
|
-
if (
|
|
33290
|
+
if (!block2) log("Private-range blocking disabled by config.");
|
|
33291
|
+
if (block2)
|
|
33236
33292
|
log(
|
|
33237
33293
|
"Gateway/DNS addresses kept reachable for DNS only: " + (exempt.length ? [...new Set(exempt)].join(", ") : "(none found)")
|
|
33238
33294
|
);
|
|
33239
33295
|
if (!isWin || dryRun) {
|
|
33240
33296
|
log("(dry run) firewall plan:");
|
|
33241
33297
|
for (const c of commands) log(" netsh " + c.join(" "));
|
|
33242
|
-
return
|
|
33298
|
+
return block2 ? "blocked" : "open";
|
|
33243
33299
|
}
|
|
33244
33300
|
if (commands.length === 0) return "open";
|
|
33245
|
-
const online =
|
|
33301
|
+
const online = block2 ? await waitForInternet(30) : true;
|
|
33246
33302
|
const failures = [];
|
|
33247
33303
|
try {
|
|
33248
33304
|
run2(lanRules);
|
|
@@ -33257,7 +33313,7 @@ async function applyNetworkPolicy(ptyHostExe) {
|
|
|
33257
33313
|
warn("PROTECTION MISSING: " + problems[problems.length - 1]);
|
|
33258
33314
|
}
|
|
33259
33315
|
if (failures.length) throw new Error(failures[0]);
|
|
33260
|
-
if (!
|
|
33316
|
+
if (!block2) return "open";
|
|
33261
33317
|
if (online && !await waitForInternet(15)) {
|
|
33262
33318
|
run2(lanRules.filter((c) => c[2] === "delete"));
|
|
33263
33319
|
warn(
|
|
@@ -33487,18 +33543,109 @@ function setupGitConfig(env) {
|
|
|
33487
33543
|
spawnSync7(git, ["config", "--global", "core.autocrlf", "input"], { env: rest, windowsHide: true, stdio: "ignore" });
|
|
33488
33544
|
}
|
|
33489
33545
|
|
|
33546
|
+
// src/guest/setup/github-token.ts
|
|
33547
|
+
import fs53 from "node:fs";
|
|
33548
|
+
import { spawnSync as spawnSync8 } from "node:child_process";
|
|
33549
|
+
|
|
33550
|
+
// src/shared/github/token.ts
|
|
33551
|
+
var MIN_LENGTH = 20;
|
|
33552
|
+
var MAX_LENGTH = 255;
|
|
33553
|
+
var PRINTABLE = /^[\x21-\x7e]+$/;
|
|
33554
|
+
var GithubTokenSchema = external_exports.string().min(MIN_LENGTH).max(MAX_LENGTH).regex(PRINTABLE);
|
|
33555
|
+
var TOKEN_VARIABLES = /^(GH_TOKEN|GITHUB_TOKEN|GH_ENTERPRISE_TOKEN|GITHUB_ENTERPRISE_TOKEN)$/i;
|
|
33556
|
+
var ghEnv = (base, configDir) => ({
|
|
33557
|
+
...Object.fromEntries(
|
|
33558
|
+
Object.entries(base).filter((e) => e[1] !== void 0 && !TOKEN_VARIABLES.test(e[0]))
|
|
33559
|
+
),
|
|
33560
|
+
GH_CONFIG_DIR: configDir,
|
|
33561
|
+
GH_PROMPT_DISABLED: "1",
|
|
33562
|
+
GH_NO_UPDATE_NOTIFIER: "1"
|
|
33563
|
+
});
|
|
33564
|
+
function ghLoginCommand(ghExe, configDir, token, base) {
|
|
33565
|
+
return {
|
|
33566
|
+
file: ghExe,
|
|
33567
|
+
args: [
|
|
33568
|
+
"auth",
|
|
33569
|
+
"login",
|
|
33570
|
+
"--hostname",
|
|
33571
|
+
"github.com",
|
|
33572
|
+
"--git-protocol",
|
|
33573
|
+
"https",
|
|
33574
|
+
"--insecure-storage",
|
|
33575
|
+
"--with-token"
|
|
33576
|
+
],
|
|
33577
|
+
input: token + "\n",
|
|
33578
|
+
env: ghEnv(base, configDir)
|
|
33579
|
+
};
|
|
33580
|
+
}
|
|
33581
|
+
function ghSetupGitCommand(ghExe, configDir, base) {
|
|
33582
|
+
return { file: ghExe, args: ["auth", "setup-git", "--hostname", "github.com"], env: ghEnv(base, configDir) };
|
|
33583
|
+
}
|
|
33584
|
+
function ghOutputText(text, token) {
|
|
33585
|
+
const clean = token ? text.split(token).join("***") : text;
|
|
33586
|
+
return clean.replace(/\s+/g, " ").trim().slice(0, 300);
|
|
33587
|
+
}
|
|
33588
|
+
|
|
33589
|
+
// src/guest/setup/github-token.ts
|
|
33590
|
+
var GH_TIMEOUT_MS = 6e4;
|
|
33591
|
+
function prepareGithubFolder(token) {
|
|
33592
|
+
const dir = deliveredGhConfigDir();
|
|
33593
|
+
fs53.rmSync(dir, { recursive: true, force: true });
|
|
33594
|
+
if (!token) return false;
|
|
33595
|
+
mkdirp(dir);
|
|
33596
|
+
return true;
|
|
33597
|
+
}
|
|
33598
|
+
function runGh(command, token, what) {
|
|
33599
|
+
const result = spawnSync8(command.file, [...command.args], {
|
|
33600
|
+
env: command.env,
|
|
33601
|
+
encoding: "utf8",
|
|
33602
|
+
windowsHide: true,
|
|
33603
|
+
timeout: GH_TIMEOUT_MS,
|
|
33604
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
33605
|
+
...command.input !== void 0 ? { input: command.input } : {}
|
|
33606
|
+
});
|
|
33607
|
+
if (result.error) throw new Error(what + " could not run: " + ghOutputText(result.error.message, token));
|
|
33608
|
+
if (result.status !== 0)
|
|
33609
|
+
throw new Error(
|
|
33610
|
+
what + " failed: " + ghOutputText(String(result.stderr ?? "") || String(result.stdout ?? ""), token)
|
|
33611
|
+
);
|
|
33612
|
+
}
|
|
33613
|
+
function loginGithub(token, env) {
|
|
33614
|
+
if (dryRun) {
|
|
33615
|
+
log("(dry run) would log gh in with the GitHub token from your PC");
|
|
33616
|
+
return;
|
|
33617
|
+
}
|
|
33618
|
+
const gh2 = ghExePath();
|
|
33619
|
+
const dir = deliveredGhConfigDir();
|
|
33620
|
+
if (!exists(gh2) || env.GH_CONFIG_DIR !== dir) {
|
|
33621
|
+
fs53.rmSync(dir, { recursive: true, force: true });
|
|
33622
|
+
log("A GitHub token arrived, but gh is not set up in this sandbox (toolchains.cli.gh), so it is not used.");
|
|
33623
|
+
return;
|
|
33624
|
+
}
|
|
33625
|
+
try {
|
|
33626
|
+
runGh(ghLoginCommand(gh2, dir, token, env), token, "gh auth login");
|
|
33627
|
+
runGh(ghSetupGitCommand(gh2, dir, env), token, "gh auth setup-git");
|
|
33628
|
+
} catch (e) {
|
|
33629
|
+
fs53.rmSync(dir, { recursive: true, force: true });
|
|
33630
|
+
env.GH_CONFIG_DIR = mkdirp(ghConfigDir());
|
|
33631
|
+
addMachineEnvironment({ GH_CONFIG_DIR: env.GH_CONFIG_DIR }, []);
|
|
33632
|
+
throw e;
|
|
33633
|
+
}
|
|
33634
|
+
log("gh and https git to github.com use the GitHub token from your PC (github.shareToken); the agent can read it.");
|
|
33635
|
+
}
|
|
33636
|
+
|
|
33490
33637
|
// src/guest/sessions/pty-host.ts
|
|
33491
33638
|
function ensurePtyHost() {
|
|
33492
33639
|
return ensureCompiled("ptyhost");
|
|
33493
33640
|
}
|
|
33494
33641
|
|
|
33495
33642
|
// src/guest/toolchains/leftovers.ts
|
|
33496
|
-
import
|
|
33643
|
+
import fs54 from "node:fs";
|
|
33497
33644
|
import path66 from "node:path";
|
|
33498
33645
|
var STAGING = /\.staging-[0-9a-f]+$/i;
|
|
33499
33646
|
var entries2 = (dir) => {
|
|
33500
33647
|
try {
|
|
33501
|
-
return
|
|
33648
|
+
return fs54.readdirSync(dir, { withFileTypes: true });
|
|
33502
33649
|
} catch {
|
|
33503
33650
|
return [];
|
|
33504
33651
|
}
|
|
@@ -33515,17 +33662,17 @@ function pruneToolLeftovers() {
|
|
|
33515
33662
|
|
|
33516
33663
|
// src/guest/audit/process-audit.ts
|
|
33517
33664
|
import path67 from "node:path";
|
|
33518
|
-
import { spawnSync as
|
|
33665
|
+
import { spawnSync as spawnSync9 } from "node:child_process";
|
|
33519
33666
|
var PROCESS_CREATION = "{0CCE922B-69AE-11D9-BED3-505054503030}";
|
|
33520
33667
|
var auditOn = () => Boolean(session.auditProcesses) && isWin && !dryRun;
|
|
33521
33668
|
function enableProcessAudit() {
|
|
33522
33669
|
if (!auditOn()) return;
|
|
33523
|
-
|
|
33670
|
+
spawnSync9(
|
|
33524
33671
|
path67.join(process.env.WINDIR ?? "C:\\Windows", "System32", "auditpol.exe"),
|
|
33525
33672
|
["/set", "/subcategory:" + PROCESS_CREATION, "/success:enable"],
|
|
33526
33673
|
{ windowsHide: true, stdio: "ignore" }
|
|
33527
33674
|
);
|
|
33528
|
-
|
|
33675
|
+
spawnSync9(
|
|
33529
33676
|
SYSTEM.reg(),
|
|
33530
33677
|
[
|
|
33531
33678
|
"add",
|
|
@@ -33545,7 +33692,8 @@ function enableProcessAudit() {
|
|
|
33545
33692
|
|
|
33546
33693
|
// src/guest/vpn/vpn.ts
|
|
33547
33694
|
import dns2 from "node:dns";
|
|
33548
|
-
import
|
|
33695
|
+
import fs58 from "node:fs";
|
|
33696
|
+
import net3 from "node:net";
|
|
33549
33697
|
import os14 from "node:os";
|
|
33550
33698
|
import path71 from "node:path";
|
|
33551
33699
|
|
|
@@ -33710,13 +33858,13 @@ function inspectOvpn(text) {
|
|
|
33710
33858
|
if (text.includes("\0")) return { ok: false, problems: ["the file is not text"] };
|
|
33711
33859
|
const lines = text.split(/\r?\n/);
|
|
33712
33860
|
if (lines.length > MAX_LINES) return { ok: false, problems: ["the file has too many lines"] };
|
|
33713
|
-
let
|
|
33861
|
+
let block2 = null;
|
|
33714
33862
|
let defaultProto = "udp";
|
|
33715
33863
|
lines.forEach((line, i) => {
|
|
33716
33864
|
const at = "line " + (i + 1) + ": ";
|
|
33717
33865
|
const trimmed = line.trim();
|
|
33718
|
-
if (
|
|
33719
|
-
if (trimmed.toLowerCase() === "</" +
|
|
33866
|
+
if (block2) {
|
|
33867
|
+
if (trimmed.toLowerCase() === "</" + block2 + ">") block2 = null;
|
|
33720
33868
|
else if (/^<\/?[A-Za-z-]+>$/.test(trimmed)) refuse(at + "a section inside a section");
|
|
33721
33869
|
return;
|
|
33722
33870
|
}
|
|
@@ -33724,7 +33872,7 @@ function inspectOvpn(text) {
|
|
|
33724
33872
|
if (open2) {
|
|
33725
33873
|
const tag = open2[1].toLowerCase();
|
|
33726
33874
|
if (!BLOCKS.has(tag)) refuse(at + "<" + tag + "> is not allowed");
|
|
33727
|
-
|
|
33875
|
+
block2 = tag;
|
|
33728
33876
|
return;
|
|
33729
33877
|
}
|
|
33730
33878
|
const d = directiveOf(line);
|
|
@@ -33749,7 +33897,7 @@ function inspectOvpn(text) {
|
|
|
33749
33897
|
}
|
|
33750
33898
|
});
|
|
33751
33899
|
const remotes = found.map((r) => ({ host: r.host, port: r.port, proto: r.proto ?? defaultProto }));
|
|
33752
|
-
if (
|
|
33900
|
+
if (block2) refuse("a <" + block2 + "> section is never closed");
|
|
33753
33901
|
if (remotes.length === 0) refuse("it names no remote server");
|
|
33754
33902
|
if (remotes.length > 64) refuse("it names too many servers");
|
|
33755
33903
|
return problems2.length ? { ok: false, problems: problems2 } : { ok: true, remotes };
|
|
@@ -33958,8 +34106,22 @@ var drop = (name) => [
|
|
|
33958
34106
|
"rule",
|
|
33959
34107
|
"name=" + VPN_RULE_PREFIX + name
|
|
33960
34108
|
];
|
|
34109
|
+
var block = (name, extra) => [
|
|
34110
|
+
"advfirewall",
|
|
34111
|
+
"firewall",
|
|
34112
|
+
"add",
|
|
34113
|
+
"rule",
|
|
34114
|
+
"name=" + VPN_RULE_PREFIX + name,
|
|
34115
|
+
"dir=out",
|
|
34116
|
+
"action=block",
|
|
34117
|
+
"enable=yes",
|
|
34118
|
+
"profile=any",
|
|
34119
|
+
...extra
|
|
34120
|
+
];
|
|
34121
|
+
var BLOCK_RULES = ["Block-Internet", "Block-IPv6", "Block-DNS-UDP", "Block-DNS-TCP"];
|
|
33961
34122
|
function ruleNames(serverCount) {
|
|
33962
34123
|
return [
|
|
34124
|
+
...BLOCK_RULES,
|
|
33963
34125
|
"Loopback",
|
|
33964
34126
|
"DHCP",
|
|
33965
34127
|
"Host",
|
|
@@ -33967,6 +34129,39 @@ function ruleNames(serverCount) {
|
|
|
33967
34129
|
...Array.from({ length: Math.max(serverCount, 0) }, (_v, i) => "Server-" + (i + 1))
|
|
33968
34130
|
];
|
|
33969
34131
|
}
|
|
34132
|
+
var NOT_INTERNET = [
|
|
34133
|
+
["0.0.0.0", "0.255.255.255"],
|
|
34134
|
+
["10.0.0.0", "10.255.255.255"],
|
|
34135
|
+
["100.64.0.0", "100.127.255.255"],
|
|
34136
|
+
["127.0.0.0", "127.255.255.255"],
|
|
34137
|
+
["169.254.0.0", "169.254.255.255"],
|
|
34138
|
+
["172.16.0.0", "172.31.255.255"],
|
|
34139
|
+
["192.168.0.0", "192.168.255.255"],
|
|
34140
|
+
["224.0.0.0", "255.255.255.255"]
|
|
34141
|
+
];
|
|
34142
|
+
var LAST_IPV4 = 4294967295;
|
|
34143
|
+
function ipNumber(ip) {
|
|
34144
|
+
return ip.split(".").reduce((n, part) => n * 256 + Number(part), 0);
|
|
34145
|
+
}
|
|
34146
|
+
function ipText(n) {
|
|
34147
|
+
return [24, 16, 8, 0].map((shift) => Math.floor(n / 2 ** shift) % 256).join(".");
|
|
34148
|
+
}
|
|
34149
|
+
function ipv4Except(excluded) {
|
|
34150
|
+
const sorted = [...excluded].sort((a, b) => a[0] - b[0]);
|
|
34151
|
+
const out = [];
|
|
34152
|
+
let next = 0;
|
|
34153
|
+
for (const [from, to] of sorted) {
|
|
34154
|
+
if (from > next) out.push(ipText(next) + "-" + ipText(from - 1));
|
|
34155
|
+
next = Math.max(next, to + 1);
|
|
34156
|
+
}
|
|
34157
|
+
if (next <= LAST_IPV4) out.push(ipText(next) + "-" + ipText(LAST_IPV4));
|
|
34158
|
+
return out.join(",");
|
|
34159
|
+
}
|
|
34160
|
+
function internetExcept(servers) {
|
|
34161
|
+
const ranges = NOT_INTERNET.map(([a, b]) => [ipNumber(a), ipNumber(b)]);
|
|
34162
|
+
for (const s of cleanServers(servers)) ranges.push([ipNumber(s.ip), ipNumber(s.ip)]);
|
|
34163
|
+
return ipv4Except(ranges);
|
|
34164
|
+
}
|
|
33970
34165
|
function cleanServers(servers) {
|
|
33971
34166
|
const seen = /* @__PURE__ */ new Set();
|
|
33972
34167
|
return servers.filter((s) => {
|
|
@@ -33981,6 +34176,10 @@ function killSwitchCommands(servers, ptyHostExe) {
|
|
|
33981
34176
|
return [
|
|
33982
34177
|
...ruleNames(Math.max(list.length, 8)).map(drop),
|
|
33983
34178
|
["advfirewall", "set", "allprofiles", "state", "on"],
|
|
34179
|
+
block("Block-Internet", ["protocol=any", "remoteip=" + internetExcept(list)]),
|
|
34180
|
+
block("Block-IPv6", ["protocol=any", "remoteip=2000::/3"]),
|
|
34181
|
+
block("Block-DNS-UDP", ["protocol=udp", "remoteport=53"]),
|
|
34182
|
+
block("Block-DNS-TCP", ["protocol=tcp", "remoteport=53"]),
|
|
33984
34183
|
["advfirewall", "set", "allprofiles", "firewallpolicy", "blockinbound,blockoutbound"],
|
|
33985
34184
|
rule("Loopback", ["protocol=any", "remoteip=127.0.0.0/8"]),
|
|
33986
34185
|
rule("DHCP", ["protocol=udp", "localport=68", "remoteport=67"]),
|
|
@@ -33992,7 +34191,21 @@ function killSwitchCommands(servers, ptyHostExe) {
|
|
|
33992
34191
|
}
|
|
33993
34192
|
function tunnelCommands(tunnelIp) {
|
|
33994
34193
|
if (!isIPv4(tunnelIp)) throw new Error("Not an IPv4 address: " + tunnelIp);
|
|
33995
|
-
|
|
34194
|
+
const n = ipNumber(tunnelIp);
|
|
34195
|
+
const notTunnel = ipv4Except([[n, n]]);
|
|
34196
|
+
return [
|
|
34197
|
+
...["Block-Internet", "Block-DNS-UDP", "Block-DNS-TCP"].map((name) => [
|
|
34198
|
+
"advfirewall",
|
|
34199
|
+
"firewall",
|
|
34200
|
+
"set",
|
|
34201
|
+
"rule",
|
|
34202
|
+
"name=" + VPN_RULE_PREFIX + name,
|
|
34203
|
+
"new",
|
|
34204
|
+
"localip=" + notTunnel
|
|
34205
|
+
]),
|
|
34206
|
+
drop("Tunnel"),
|
|
34207
|
+
rule("Tunnel", ["protocol=any", "localip=" + tunnelIp])
|
|
34208
|
+
];
|
|
33996
34209
|
}
|
|
33997
34210
|
function tunnelAddressFromLog(log2) {
|
|
33998
34211
|
const add = /net_addr_v4_add:\s*(\d{1,3}(?:\.\d{1,3}){3})\/\d+/.exec(log2);
|
|
@@ -34005,7 +34218,7 @@ function tunnelAddressFromLog(log2) {
|
|
|
34005
34218
|
|
|
34006
34219
|
// src/guest/vpn/openvpn.ts
|
|
34007
34220
|
import crypto4 from "node:crypto";
|
|
34008
|
-
import
|
|
34221
|
+
import fs55 from "node:fs";
|
|
34009
34222
|
import path68 from "node:path";
|
|
34010
34223
|
|
|
34011
34224
|
// src/shared/vpn/download.ts
|
|
@@ -34042,7 +34255,12 @@ function openvpnDownload(arch2 = process.arch) {
|
|
|
34042
34255
|
const entry = arch2 === "arm64" ? OPENVPN_MSI.arm64 : OPENVPN_MSI.x64;
|
|
34043
34256
|
return { ...entry, url: OPENVPN_MSI.base + entry.file };
|
|
34044
34257
|
}
|
|
34045
|
-
|
|
34258
|
+
function repairServiceQueries() {
|
|
34259
|
+
const did = scriptOutput("repair-wmi-services.ps1");
|
|
34260
|
+
if (did === "removed") log("VPN: repaired the Windows service queries installers use (a Windows Sandbox gap).");
|
|
34261
|
+
else if (did !== "absent" && did !== "kept") warn("VPN: could not check the Windows service queries installers use.");
|
|
34262
|
+
}
|
|
34263
|
+
var hasHash = (file3, sha256) => crypto4.createHash("sha256").update(fs55.readFileSync(file3)).digest("hex") === sha256;
|
|
34046
34264
|
async function ensureOpenVpn() {
|
|
34047
34265
|
const exe = openvpnExe();
|
|
34048
34266
|
if (!isWin || dryRun) return exe;
|
|
@@ -34053,6 +34271,7 @@ async function ensureOpenVpn() {
|
|
|
34053
34271
|
log("VPN: downloading OpenVPN " + OPENVPN_MSI.version + " (about 6 MB)");
|
|
34054
34272
|
await downloader.file(dl.url, msi, dl.sha256);
|
|
34055
34273
|
}
|
|
34274
|
+
repairServiceQueries();
|
|
34056
34275
|
log("VPN: installing OpenVPN");
|
|
34057
34276
|
const logFile2 = path68.join(toolsDir, "downloads", "openvpn-install.log");
|
|
34058
34277
|
const code = await spawnAsync(SYSTEM.msiexec(), ["/i", msi, "/qn", "/norestart", "/l*v", logFile2], {
|
|
@@ -34066,7 +34285,7 @@ async function ensureOpenVpn() {
|
|
|
34066
34285
|
|
|
34067
34286
|
// src/guest/vpn/tunnel.ts
|
|
34068
34287
|
import { spawn as spawn7 } from "node:child_process";
|
|
34069
|
-
import
|
|
34288
|
+
import fs56 from "node:fs";
|
|
34070
34289
|
import os12 from "node:os";
|
|
34071
34290
|
import path69 from "node:path";
|
|
34072
34291
|
var DONE = "Initialization Sequence Completed";
|
|
@@ -34084,17 +34303,17 @@ function failureReason(text) {
|
|
|
34084
34303
|
}
|
|
34085
34304
|
var tail = (text, lines = 12) => text.trim().split(/\r?\n/).slice(-lines).join("\n");
|
|
34086
34305
|
async function startTunnel(o) {
|
|
34087
|
-
const dir =
|
|
34306
|
+
const dir = fs56.mkdtempSync(path69.join(os12.tmpdir(), "sbx-vpn-"));
|
|
34088
34307
|
const auth = path69.join(dir, "login.txt");
|
|
34089
34308
|
const logFile2 = path69.join(dir, "openvpn.log");
|
|
34090
34309
|
const keepLog = () => {
|
|
34091
34310
|
try {
|
|
34092
|
-
|
|
34093
|
-
|
|
34311
|
+
fs56.mkdirSync(logsDir, { recursive: true });
|
|
34312
|
+
fs56.copyFileSync(logFile2, path69.join(logsDir, "openvpn.log"));
|
|
34094
34313
|
} catch {
|
|
34095
34314
|
}
|
|
34096
34315
|
};
|
|
34097
|
-
|
|
34316
|
+
fs56.writeFileSync(auth, o.username + "\r\n" + o.password + "\r\n", "utf8");
|
|
34098
34317
|
try {
|
|
34099
34318
|
const child = spawn7(
|
|
34100
34319
|
o.exe,
|
|
@@ -34112,7 +34331,7 @@ async function startTunnel(o) {
|
|
|
34112
34331
|
child.unref();
|
|
34113
34332
|
const deadline = Date.now() + (o.timeoutMs ?? 9e4);
|
|
34114
34333
|
for (; ; ) {
|
|
34115
|
-
const text =
|
|
34334
|
+
const text = fs56.existsSync(logFile2) ? fs56.readFileSync(logFile2, "utf8") : "";
|
|
34116
34335
|
if (text.includes(DONE)) {
|
|
34117
34336
|
keepLog();
|
|
34118
34337
|
const tunnelIp = tunnelAddressFromLog(text) ?? void 0;
|
|
@@ -34132,14 +34351,14 @@ async function startTunnel(o) {
|
|
|
34132
34351
|
await new Promise((r) => setTimeout(r, 500));
|
|
34133
34352
|
}
|
|
34134
34353
|
} finally {
|
|
34135
|
-
|
|
34354
|
+
fs56.rmSync(auth, { force: true });
|
|
34136
34355
|
}
|
|
34137
34356
|
}
|
|
34138
34357
|
|
|
34139
34358
|
// src/guest/vpn/wireguard.ts
|
|
34140
34359
|
import { execFile } from "node:child_process";
|
|
34141
34360
|
import crypto5 from "node:crypto";
|
|
34142
|
-
import
|
|
34361
|
+
import fs57 from "node:fs";
|
|
34143
34362
|
import os13 from "node:os";
|
|
34144
34363
|
import path70 from "node:path";
|
|
34145
34364
|
var WIREGUARD_TUNNEL = "sandbox";
|
|
@@ -34153,7 +34372,7 @@ function wireguardDownload(arch2 = process.arch) {
|
|
|
34153
34372
|
const entry = arch2 === "arm64" ? WIREGUARD_MSI.arm64 : WIREGUARD_MSI.x64;
|
|
34154
34373
|
return { ...entry, url: WIREGUARD_MSI.base + entry.file };
|
|
34155
34374
|
}
|
|
34156
|
-
var hasHash2 = (file3, sha256) => crypto5.createHash("sha256").update(
|
|
34375
|
+
var hasHash2 = (file3, sha256) => crypto5.createHash("sha256").update(fs57.readFileSync(file3)).digest("hex") === sha256;
|
|
34157
34376
|
async function ensureWireguard() {
|
|
34158
34377
|
const exe = wireguardExe();
|
|
34159
34378
|
if (!isWin || dryRun) return exe;
|
|
@@ -34164,6 +34383,7 @@ async function ensureWireguard() {
|
|
|
34164
34383
|
log("VPN: downloading WireGuard " + WIREGUARD_MSI.version + " (about 3 MB)");
|
|
34165
34384
|
await downloader.file(dl.url, msi, dl.sha256);
|
|
34166
34385
|
}
|
|
34386
|
+
repairServiceQueries();
|
|
34167
34387
|
log("VPN: installing WireGuard");
|
|
34168
34388
|
const logFile2 = path70.join(toolsDir, "downloads", "wireguard-install.log");
|
|
34169
34389
|
const code = await spawnAsync(
|
|
@@ -34198,9 +34418,9 @@ async function removeWireguardTunnel(exe) {
|
|
|
34198
34418
|
}
|
|
34199
34419
|
async function startWireguardTunnel(o) {
|
|
34200
34420
|
const root = path70.join(process.env.SystemRoot ?? "C:\\Windows", "Temp");
|
|
34201
|
-
const dir =
|
|
34421
|
+
const dir = fs57.mkdtempSync(path70.join(fs57.existsSync(root) ? root : os13.tmpdir(), "sbx-wg-"));
|
|
34202
34422
|
const file3 = path70.join(dir, WIREGUARD_TUNNEL + ".conf");
|
|
34203
|
-
|
|
34423
|
+
fs57.writeFileSync(file3, o.config, "utf8");
|
|
34204
34424
|
const fail = async (message) => {
|
|
34205
34425
|
await removeWireguardTunnel(o.exe);
|
|
34206
34426
|
return { ok: false, message };
|
|
@@ -34221,7 +34441,7 @@ async function startWireguardTunnel(o) {
|
|
|
34221
34441
|
await sleep(500);
|
|
34222
34442
|
}
|
|
34223
34443
|
} finally {
|
|
34224
|
-
|
|
34444
|
+
fs57.rmSync(dir, { recursive: true, force: true });
|
|
34225
34445
|
}
|
|
34226
34446
|
}
|
|
34227
34447
|
async function waitForHandshake(exe, poke, timeoutMs = 3e4) {
|
|
@@ -34290,15 +34510,47 @@ async function publicAddress() {
|
|
|
34290
34510
|
}
|
|
34291
34511
|
}
|
|
34292
34512
|
var hasAdapter2 = (ip) => Object.values(os14.networkInterfaces()).some((list) => (list ?? []).some((i) => i.address === ip));
|
|
34513
|
+
var PROBE_TARGETS = ["1.1.1.1", "8.8.8.8", "9.9.9.9"];
|
|
34514
|
+
var PROBE_TIMEOUT_MS = 3e3;
|
|
34515
|
+
function connects(ip, port) {
|
|
34516
|
+
return new Promise((resolve2) => {
|
|
34517
|
+
const socket = net3.connect({ host: ip, port });
|
|
34518
|
+
const done = (ok) => {
|
|
34519
|
+
socket.destroy();
|
|
34520
|
+
resolve2(ok);
|
|
34521
|
+
};
|
|
34522
|
+
socket.setTimeout(PROBE_TIMEOUT_MS, () => done(false));
|
|
34523
|
+
socket.once("connect", () => done(true));
|
|
34524
|
+
socket.once("error", () => done(false));
|
|
34525
|
+
});
|
|
34526
|
+
}
|
|
34527
|
+
async function directConnectionBlocked(servers) {
|
|
34528
|
+
const targets = PROBE_TARGETS.filter((ip) => !servers.some((s) => s.ip === ip));
|
|
34529
|
+
const results = await Promise.all(targets.map((ip) => connects(ip, 443)));
|
|
34530
|
+
return !results.some(Boolean);
|
|
34531
|
+
}
|
|
34293
34532
|
async function setupVpn(secrets, ptyHostExe) {
|
|
34294
34533
|
const vpn = session.vpn;
|
|
34295
34534
|
if (!vpn) return true;
|
|
34296
34535
|
const killSwitch = vpn.killSwitch;
|
|
34297
34536
|
let blocked = false;
|
|
34298
|
-
|
|
34299
|
-
|
|
34300
|
-
|
|
34301
|
-
|
|
34537
|
+
let held = false;
|
|
34538
|
+
const block2 = async (servers) => {
|
|
34539
|
+
if (!isWin || dryRun) {
|
|
34540
|
+
blocked = held = true;
|
|
34541
|
+
return;
|
|
34542
|
+
}
|
|
34543
|
+
try {
|
|
34544
|
+
run2(killSwitchCommands(servers, ptyHostExe ? longPath(ptyHostExe) : null));
|
|
34545
|
+
} finally {
|
|
34546
|
+
blocked = true;
|
|
34547
|
+
held = await directConnectionBlocked(servers);
|
|
34548
|
+
}
|
|
34549
|
+
if (held) log("VPN: kill switch on: nothing leaves the sandbox except through the tunnel (checked).");
|
|
34550
|
+
else
|
|
34551
|
+
warn(
|
|
34552
|
+
"VPN: the kill switch did not hold: a direct connection still got out. If the tunnel drops, traffic leaves through your normal connection."
|
|
34553
|
+
);
|
|
34302
34554
|
};
|
|
34303
34555
|
setVpnStatus("starting", "Starting the VPN");
|
|
34304
34556
|
try {
|
|
@@ -34314,7 +34566,7 @@ async function setupVpn(secrets, ptyHostExe) {
|
|
|
34314
34566
|
warn(
|
|
34315
34567
|
"VPN: AllowedIPs does not include 0.0.0.0/0: with the kill switch on, only the tunnel traffic can leave the sandbox."
|
|
34316
34568
|
);
|
|
34317
|
-
if (killSwitch)
|
|
34569
|
+
if (killSwitch) await block2(servers);
|
|
34318
34570
|
if (dryRun || !isWin) {
|
|
34319
34571
|
log("(dry run) would start the WireGuard tunnel " + vpn.server);
|
|
34320
34572
|
setVpnStatus("off", "dry run");
|
|
@@ -34329,11 +34581,11 @@ async function setupVpn(secrets, ptyHostExe) {
|
|
|
34329
34581
|
const credentials = secrets.vpn;
|
|
34330
34582
|
if (!credentials) throw new Error("the VPN login did not arrive (start the sandbox again)");
|
|
34331
34583
|
const profile = path71.join(launchDir, "vpn", "server.ovpn");
|
|
34332
|
-
const remotes = assertSafeOvpn(
|
|
34584
|
+
const remotes = assertSafeOvpn(fs58.readFileSync(profile, "utf8"), vpn.server);
|
|
34333
34585
|
const exe = await ensureOpenVpn();
|
|
34334
34586
|
const servers = await serverAddresses(remotes);
|
|
34335
34587
|
if (servers.length === 0) throw new Error("the VPN server addresses could not be found");
|
|
34336
|
-
if (killSwitch)
|
|
34588
|
+
if (killSwitch) await block2(servers);
|
|
34337
34589
|
if (dryRun || !isWin) {
|
|
34338
34590
|
log("(dry run) would start the VPN tunnel to " + vpn.server);
|
|
34339
34591
|
setVpnStatus("off", "dry run");
|
|
@@ -34352,18 +34604,21 @@ async function setupVpn(secrets, ptyHostExe) {
|
|
|
34352
34604
|
throw new Error("the tunnel reported it was up, but no network adapter with its address appeared");
|
|
34353
34605
|
const publicIp = await publicAddress();
|
|
34354
34606
|
log("VPN: up" + (publicIp ? " (the sandbox appears as " + publicIp + ")" : "") + ".");
|
|
34355
|
-
setVpnStatus("up", "The tunnel is up",
|
|
34607
|
+
setVpnStatus("up", "The tunnel is up", {
|
|
34608
|
+
...publicIp ? { publicIp } : {},
|
|
34609
|
+
...killSwitch ? { killSwitchHeld: held } : {}
|
|
34610
|
+
});
|
|
34356
34611
|
return true;
|
|
34357
34612
|
} catch (e) {
|
|
34358
34613
|
const reason = errMsg(e);
|
|
34359
34614
|
try {
|
|
34360
|
-
if (killSwitch && !blocked)
|
|
34615
|
+
if (killSwitch && !blocked) await block2([]);
|
|
34361
34616
|
} catch (blockError) {
|
|
34362
34617
|
warn("VPN: could not close the network after the failure: " + errMsg(blockError));
|
|
34363
34618
|
}
|
|
34364
|
-
const
|
|
34365
|
-
warn(
|
|
34366
|
-
setVpnStatus("failed", reason);
|
|
34619
|
+
const after = !killSwitch ? " The kill switch is off, so this sandbox is using your normal connection." : held ? " The kill switch is on, so this sandbox has NO internet access." : " The kill switch could NOT close the network, so this sandbox is ONLINE through your normal connection, without the VPN.";
|
|
34620
|
+
warn("VPN failed: " + reason + after);
|
|
34621
|
+
setVpnStatus("failed", reason, killSwitch ? { killSwitchHeld: held } : {});
|
|
34367
34622
|
return false;
|
|
34368
34623
|
}
|
|
34369
34624
|
}
|
|
@@ -34420,10 +34675,10 @@ var FrameReader = class {
|
|
|
34420
34675
|
};
|
|
34421
34676
|
|
|
34422
34677
|
// src/shared/pty/client.ts
|
|
34423
|
-
import
|
|
34678
|
+
import net4 from "node:net";
|
|
34424
34679
|
var connectOnce = (host, port, timeoutMs) => {
|
|
34425
34680
|
return new Promise((resolve2, reject) => {
|
|
34426
|
-
const socket =
|
|
34681
|
+
const socket = net4.connect({ host, port });
|
|
34427
34682
|
const timer = setTimeout(() => {
|
|
34428
34683
|
socket.destroy();
|
|
34429
34684
|
reject(new Error("timed out connecting to " + host + ":" + port));
|
|
@@ -34644,6 +34899,36 @@ function unfinishedSequence(data) {
|
|
|
34644
34899
|
return data.length;
|
|
34645
34900
|
}
|
|
34646
34901
|
|
|
34902
|
+
// src/shared/pty/ctrl-c.ts
|
|
34903
|
+
var CTRL_C_CONFIRM_MS = 1500;
|
|
34904
|
+
var CTRL_C_HINT = "Ctrl+C again to send it to the program (Esc stops an agent)";
|
|
34905
|
+
var OSC_TITLE = /\x1b\][02];([^\x07\x1b]{0,256})(?:\x07|\x1b\\)/g;
|
|
34906
|
+
var CtrlCGuard = class {
|
|
34907
|
+
armedAt = Number.NEGATIVE_INFINITY;
|
|
34908
|
+
lastTitle = "";
|
|
34909
|
+
/** What to send for one read from the keyboard: a lone Ctrl+C only when another came just before. */
|
|
34910
|
+
push(chunk, nowMs) {
|
|
34911
|
+
if (chunk.length !== 1 || chunk[0] !== 3) return { send: chunk, held: false };
|
|
34912
|
+
if (nowMs - this.armedAt <= CTRL_C_CONFIRM_MS) {
|
|
34913
|
+
this.armedAt = Number.NEGATIVE_INFINITY;
|
|
34914
|
+
return { send: chunk, held: false };
|
|
34915
|
+
}
|
|
34916
|
+
this.armedAt = nowMs;
|
|
34917
|
+
return { send: Buffer.alloc(0), held: true };
|
|
34918
|
+
}
|
|
34919
|
+
/** Remembers the title the program last set (from its output), to put it back after the hint. */
|
|
34920
|
+
watchOutput(text) {
|
|
34921
|
+
for (const m of text.matchAll(OSC_TITLE)) this.lastTitle = m[1];
|
|
34922
|
+
}
|
|
34923
|
+
/** The escape sequence that shows the hint, and the one that puts the program's title back. */
|
|
34924
|
+
hintTitle() {
|
|
34925
|
+
return "\x1B]0;" + CTRL_C_HINT + "\x07";
|
|
34926
|
+
}
|
|
34927
|
+
restoreTitle() {
|
|
34928
|
+
return "\x1B]0;" + this.lastTitle.replace(/[\x00-\x1f\x7f]/g, "") + "\x07";
|
|
34929
|
+
}
|
|
34930
|
+
};
|
|
34931
|
+
|
|
34647
34932
|
// src/shared/pty/terminal.ts
|
|
34648
34933
|
var MOUSE_OFF = "\x1B[?1000l\x1B[?1002l\x1B[?1003l\x1B[?1005l\x1B[?1006l\x1B[?1015l";
|
|
34649
34934
|
function fixWindowsKeys(chunk) {
|
|
@@ -34674,6 +34959,7 @@ function runTerminalClient(socket, token, options = {}) {
|
|
|
34674
34959
|
clearInterval(heartbeat);
|
|
34675
34960
|
clearInterval(sizeWatch);
|
|
34676
34961
|
clearTimeout(joinTimer);
|
|
34962
|
+
clearTimeout(hintTimer);
|
|
34677
34963
|
socket.destroy();
|
|
34678
34964
|
stdout.write("\x1B[0m\x1B[?25h" + MOUSE_OFF + "\r\n");
|
|
34679
34965
|
void (vtInput?.stop() ?? Promise.resolve()).then(() => {
|
|
@@ -34687,11 +34973,23 @@ function runTerminalClient(socket, token, options = {}) {
|
|
|
34687
34973
|
const sendInput = (data) => {
|
|
34688
34974
|
if (data.length && !done) socket.write(encodeFrame(FrameType.Input, swapKeys ? fixWindowsKeys(data) : data));
|
|
34689
34975
|
};
|
|
34976
|
+
const guard = options.confirmCtrlC ? new CtrlCGuard() : null;
|
|
34977
|
+
let hintTimer;
|
|
34690
34978
|
const onInput = (chunk) => {
|
|
34691
34979
|
if (options.detachKey !== void 0 && chunk.includes(options.detachKey)) {
|
|
34692
34980
|
finish({ reason: "detach" });
|
|
34693
34981
|
return;
|
|
34694
34982
|
}
|
|
34983
|
+
if (guard) {
|
|
34984
|
+
const decided = guard.push(chunk, Date.now());
|
|
34985
|
+
clearTimeout(hintTimer);
|
|
34986
|
+
if (decided.held) {
|
|
34987
|
+
stdout.write(guard.hintTitle());
|
|
34988
|
+
hintTimer = setTimeout(() => stdout.write(guard.restoreTitle()), CTRL_C_CONFIRM_MS);
|
|
34989
|
+
return;
|
|
34990
|
+
}
|
|
34991
|
+
if (decided.send.length === 1 && decided.send[0] === 3) stdout.write(guard.restoreTitle());
|
|
34992
|
+
}
|
|
34695
34993
|
clearTimeout(joinTimer);
|
|
34696
34994
|
sendInput(joiner.push(chunk));
|
|
34697
34995
|
if (joiner.holding()) joinTimer = setTimeout(() => sendInput(joiner.flush()), JOIN_MS);
|
|
@@ -34724,8 +35022,11 @@ function runTerminalClient(socket, token, options = {}) {
|
|
|
34724
35022
|
return;
|
|
34725
35023
|
}
|
|
34726
35024
|
for (const frame of frames) {
|
|
34727
|
-
if (frame.type === FrameType.Output)
|
|
34728
|
-
|
|
35025
|
+
if (frame.type === FrameType.Output) {
|
|
35026
|
+
const out = filter.push(frame.payload);
|
|
35027
|
+
guard?.watchOutput(out.toString("latin1"));
|
|
35028
|
+
stdout.write(out);
|
|
35029
|
+
} else if (frame.type === FrameType.Console) passthrough = frame.payload.toString("latin1") === "conpty.dll";
|
|
34729
35030
|
else if (frame.type === FrameType.Restarting) stdout.write(MOUSE_OFF + "\x1B[2J\x1B[3J\x1B[H");
|
|
34730
35031
|
else if (frame.type === FrameType.Exit)
|
|
34731
35032
|
finish({ reason: "exit", exitCode: frame.payload.length >= 4 ? frame.payload.readInt32LE(0) : 1 });
|
|
@@ -34778,7 +35079,10 @@ async function viewSession(id) {
|
|
|
34778
35079
|
return 1;
|
|
34779
35080
|
}
|
|
34780
35081
|
const socket = await connect({ ...session2.attach, addresses: ["127.0.0.1"] });
|
|
34781
|
-
const result = await runTerminalClient(socket, session2.attach.token, {
|
|
35082
|
+
const result = await runTerminalClient(socket, session2.attach.token, {
|
|
35083
|
+
clipboardWrites: true,
|
|
35084
|
+
confirmCtrlC: session.attach.confirmCtrlC !== false
|
|
35085
|
+
});
|
|
34782
35086
|
if (result.reason === "exit") console.log(session2.harness + " exited with code " + result.exitCode + ".");
|
|
34783
35087
|
else if (result.reason === "error") console.log("Session error: " + result.message);
|
|
34784
35088
|
return result.reason === "exit" ? result.exitCode : 1;
|
|
@@ -34833,7 +35137,7 @@ function saveProjectStatus(name, workspace2, phase, message, databases, summary)
|
|
|
34833
35137
|
}
|
|
34834
35138
|
|
|
34835
35139
|
// src/guest/runtime/secrets.ts
|
|
34836
|
-
import
|
|
35140
|
+
import fs59 from "node:fs";
|
|
34837
35141
|
|
|
34838
35142
|
// src/shared/channel/secrets.ts
|
|
34839
35143
|
var Environment = external_exports.record(external_exports.string().max(256), external_exports.string().max(65536));
|
|
@@ -34849,7 +35153,9 @@ var SecretsFileSchema = external_exports.strictObject({
|
|
|
34849
35153
|
/** VPN service credentials (vpn.provider's login), only for the launch's own sandbox. */
|
|
34850
35154
|
vpn: external_exports.strictObject({ username: external_exports.string().min(1).max(256), password: external_exports.string().min(1).max(1024) }).optional(),
|
|
34851
35155
|
/** The checked WireGuard config of vpn.provider wireguard-file (holds the private key). */
|
|
34852
|
-
wireguardConfig: external_exports.string().min(1).max(32 * 1024).optional()
|
|
35156
|
+
wireguardConfig: external_exports.string().min(1).max(32 * 1024).optional(),
|
|
35157
|
+
/** The GitHub token you saved for sandboxes (github.shareToken), only with git access "full". */
|
|
35158
|
+
githubToken: GithubTokenSchema.optional()
|
|
34853
35159
|
});
|
|
34854
35160
|
|
|
34855
35161
|
// src/guest/runtime/secrets.ts
|
|
@@ -34859,12 +35165,12 @@ function takeSecrets(id) {
|
|
|
34859
35165
|
const file3 = run.secretFile(id);
|
|
34860
35166
|
let text;
|
|
34861
35167
|
try {
|
|
34862
|
-
if (
|
|
34863
|
-
text =
|
|
35168
|
+
if (fs59.statSync(file3).size > MAX_BYTES) throw new Error("too big");
|
|
35169
|
+
text = fs59.readFileSync(file3, "utf8").replace(/^\uFEFF/, "");
|
|
34864
35170
|
} catch {
|
|
34865
35171
|
return {};
|
|
34866
35172
|
} finally {
|
|
34867
|
-
|
|
35173
|
+
fs59.rmSync(file3, { force: true });
|
|
34868
35174
|
}
|
|
34869
35175
|
try {
|
|
34870
35176
|
const parsed = SecretsFileSchema.safeParse(JSON.parse(text));
|
|
@@ -34917,7 +35223,7 @@ function startDaemon(env, secrets) {
|
|
|
34917
35223
|
function writeDbCommand() {
|
|
34918
35224
|
const dir = mkdirp(path73.join(localDir, "bin"));
|
|
34919
35225
|
const db = path73.join(path73.dirname(process.argv[1]), "db.js");
|
|
34920
|
-
|
|
35226
|
+
fs60.writeFileSync(
|
|
34921
35227
|
path73.join(dir, "sbx-db.cmd"),
|
|
34922
35228
|
'@setlocal\r\n@set AGENT_LOG_PREFIX=db\r\n@"' + process.execPath + '" "' + db + '" %*\r\n'
|
|
34923
35229
|
);
|
|
@@ -34927,8 +35233,8 @@ function writeDbCommand() {
|
|
|
34927
35233
|
function writeAgentCommands(dir) {
|
|
34928
35234
|
const install = { node: process.execPath, script: path73.join(path73.dirname(process.argv[1]), "agent.js") };
|
|
34929
35235
|
for (const shim3 of agentShims(toolsDir, session.agents ?? {}))
|
|
34930
|
-
|
|
34931
|
-
|
|
35236
|
+
fs60.writeFileSync(path73.join(dir, shim3.command + ".cmd"), shimText(shim3, install));
|
|
35237
|
+
fs60.writeFileSync(path73.join(dir, "sbx-agent.cmd"), sbxAgentText(install));
|
|
34932
35238
|
}
|
|
34933
35239
|
async function waitForPrimary() {
|
|
34934
35240
|
for (let i = 0; i < PRIMARY_POLLS; i++) {
|
|
@@ -34956,12 +35262,13 @@ var Boot = class {
|
|
|
34956
35262
|
log(
|
|
34957
35263
|
"Agent sandbox: " + session.project + " | workspace " + workspace + " | agent " + session.harnessName + " | log " + logPath
|
|
34958
35264
|
);
|
|
34959
|
-
if (!
|
|
35265
|
+
if (!fs60.statSync(workspace, { throwIfNoEntry: false })?.isDirectory())
|
|
34960
35266
|
throw new Error("Workspace folder is missing in the sandbox: " + workspace);
|
|
34961
35267
|
mkdirp(toolsDir);
|
|
34962
35268
|
mkdirp(run.root);
|
|
34963
35269
|
this.secrets = takeSecrets(session.launchId);
|
|
34964
35270
|
applyBootEnvironment(this.secrets.harnessEnvironment);
|
|
35271
|
+
prepareGithubFolder(this.secrets.githubToken);
|
|
34965
35272
|
await this.networkAndSessionHost();
|
|
34966
35273
|
await this.hooksAndDesktop();
|
|
34967
35274
|
const { tools, env } = await this.developerTools();
|
|
@@ -35044,6 +35351,11 @@ var Boot = class {
|
|
|
35044
35351
|
async gitIdentity(env) {
|
|
35045
35352
|
step(5, "Git identity");
|
|
35046
35353
|
await soft("Git config", () => setupGitConfig(env));
|
|
35354
|
+
const token = this.secrets.githubToken;
|
|
35355
|
+
if (token) {
|
|
35356
|
+
this.secrets = { ...this.secrets, githubToken: void 0 };
|
|
35357
|
+
await soft("GitHub token", () => loginGithub(token, env));
|
|
35358
|
+
}
|
|
35047
35359
|
}
|
|
35048
35360
|
async claude(tools) {
|
|
35049
35361
|
step(6, "Claude settings, history and claude-mem");
|
|
@@ -35105,7 +35417,7 @@ runBoot().catch((e) => {
|
|
|
35105
35417
|
const message = errMsg(e) + (e instanceof Error && e.stack ? "\n" + e.stack : "");
|
|
35106
35418
|
try {
|
|
35107
35419
|
setSandboxStatus("failed", errMsg(e));
|
|
35108
|
-
|
|
35420
|
+
fs61.writeFileSync(path74.join(logsDir, "guest-error.txt"), message);
|
|
35109
35421
|
} catch {
|
|
35110
35422
|
}
|
|
35111
35423
|
console.error(
|