windows-development-sandbox 1.10.0 → 1.11.3
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 +201 -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 +952 -4
- package/dist/app/features/defs.js +147 -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 +281 -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 +225 -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 +225 -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 +16 -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/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 +323 -176
- package/dist/runtime/db.js +30 -6
- package/dist/runtime/main.js +375 -76
- package/dist/runtime/netproxy.js +30 -6
- package/dist/runtime/view.js +495 -146
- package/dist/selftest/app.test.js +620 -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.js +1 -1
- package/dist/web/index.html +2 -2
- package/dist/web/{main-T5DMCHYV.css → main-6JF3ASB5.css} +1 -1
- package/dist/web/main-Z645W45E.js +219 -0
- package/native/csharp/HcsHost/AssemblyInfo.cs +3 -3
- package/native/csharp/HostTools/AssemblyInfo.cs +3 -3
- 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,17 @@ 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
|
+
}
|
|
29237
29269
|
var toolVars = {
|
|
29238
29270
|
gh: () => ({
|
|
29239
|
-
GH_CONFIG_DIR: mkdirp(ghConfigDir()),
|
|
29271
|
+
GH_CONFIG_DIR: exists(deliveredGhConfigDir()) ? deliveredGhConfigDir() : mkdirp(ghConfigDir()),
|
|
29240
29272
|
GH_NO_UPDATE_NOTIFIER: "1",
|
|
29241
29273
|
GH_NO_EXTENSION_UPDATE_NOTIFIER: "1"
|
|
29242
29274
|
})
|
|
@@ -30082,6 +30114,10 @@ var activate = async (version2) => {
|
|
|
30082
30114
|
fs36.rmSync(NVM_SYMLINK, { recursive: true, force: true });
|
|
30083
30115
|
fs36.symlinkSync(path45.join(NVM_HOME, "v" + version2), NVM_SYMLINK, "junction");
|
|
30084
30116
|
};
|
|
30117
|
+
var PLAYWRIGHT_VARS = () => ({
|
|
30118
|
+
PLAYWRIGHT_BROWSERS_PATH: tool("ms-playwright"),
|
|
30119
|
+
PLAYWRIGHT_MCP_BROWSER: "msedge"
|
|
30120
|
+
});
|
|
30085
30121
|
async function setupNode(env, versions, config2) {
|
|
30086
30122
|
if (dryRun) {
|
|
30087
30123
|
log("(dry run) would provision nvm and Node " + versions.node.spec + " (from " + versions.node.source + ")");
|
|
@@ -30115,13 +30151,14 @@ async function setupNode(env, versions, config2) {
|
|
|
30115
30151
|
warn("Node " + version2 + " from this PC: " + errMsg(e));
|
|
30116
30152
|
}
|
|
30117
30153
|
}
|
|
30118
|
-
Object.assign(env.vars, { NVM_HOME, NVM_SYMLINK });
|
|
30154
|
+
Object.assign(env.vars, { NVM_HOME, NVM_SYMLINK, ...PLAYWRIGHT_VARS() });
|
|
30119
30155
|
if (duringSession()) env.prepend.push(path45.join(NVM_HOME, "v" + main), NVM_HOME, NVM_SYMLINK);
|
|
30120
30156
|
else {
|
|
30121
30157
|
await activate(main);
|
|
30122
30158
|
env.prepend.push(NVM_HOME, NVM_SYMLINK);
|
|
30123
30159
|
}
|
|
30124
30160
|
env.summary.push("node: " + main + " (from " + versions.node.source + ", switch with nvm use)");
|
|
30161
|
+
env.summary.push("playwright: ready (Edge; browsers it downloads are kept; in tests use channel: 'msedge')");
|
|
30125
30162
|
await packageManagers(env, config2, main);
|
|
30126
30163
|
}
|
|
30127
30164
|
var packageManagers = async (env, config2, version2) => {
|
|
@@ -32032,11 +32069,17 @@ import os8 from "node:os";
|
|
|
32032
32069
|
import path51 from "node:path";
|
|
32033
32070
|
|
|
32034
32071
|
// src/shared/memory/policy.ts
|
|
32072
|
+
function buildJobs(cpus, memoryGb) {
|
|
32073
|
+
return Math.max(2, Math.min(cpus, Math.floor((memoryGb - 6) / 3)));
|
|
32074
|
+
}
|
|
32075
|
+
function linkSlotsFor(memoryGb) {
|
|
32076
|
+
return Math.max(2, Math.min(8, Math.floor((memoryGb - 6) / 3)));
|
|
32077
|
+
}
|
|
32035
32078
|
function cargoJobs(cpus, memoryGb, sessions) {
|
|
32036
|
-
const byCpu = Math.max(2, Math.min(
|
|
32079
|
+
const byCpu = Math.max(2, Math.min(8, Math.floor(cpus / 4)));
|
|
32037
32080
|
const byMemory = Math.max(1, Math.floor(memoryGb / 4));
|
|
32038
32081
|
const jobs = Math.min(byCpu, byMemory);
|
|
32039
|
-
return Math.max(1, Math.min(jobs, Math.floor(
|
|
32082
|
+
return Math.max(1, Math.min(jobs, Math.floor(buildJobs(cpus, memoryGb) / Math.max(1, sessions))));
|
|
32040
32083
|
}
|
|
32041
32084
|
|
|
32042
32085
|
// src/guest/toolchains/native/rust-extras.ts
|
|
@@ -32059,7 +32102,7 @@ function linkGate(env, rust, host) {
|
|
|
32059
32102
|
const gate = path51.join(mkdirp(tool("shims")), "linkgate.exe");
|
|
32060
32103
|
fs41.copyFileSync(ensureCompiled("linkgate"), gate);
|
|
32061
32104
|
const memoryGb = os8.totalmem() / 1024 ** 3;
|
|
32062
|
-
const slots = rust.linkSlots === "auto" ?
|
|
32105
|
+
const slots = rust.linkSlots === "auto" ? linkSlotsFor(memoryGb) : rust.linkSlots;
|
|
32063
32106
|
env.vars.AGENT_LINK_SLOTS = String(slots);
|
|
32064
32107
|
env.vars.AGENT_REAL_LINKER = gcc;
|
|
32065
32108
|
env.vars.CARGO_TARGET_X86_64_PC_WINDOWS_GNU_LINKER = gate;
|
|
@@ -33170,14 +33213,14 @@ var problems = [];
|
|
|
33170
33213
|
function networkProblems() {
|
|
33171
33214
|
return problems;
|
|
33172
33215
|
}
|
|
33173
|
-
|
|
33216
|
+
function longPath(file3) {
|
|
33174
33217
|
if (!hasShortName(file3)) return file3;
|
|
33175
33218
|
try {
|
|
33176
33219
|
return fs48.realpathSync.native(file3);
|
|
33177
33220
|
} catch {
|
|
33178
33221
|
return file3;
|
|
33179
33222
|
}
|
|
33180
|
-
}
|
|
33223
|
+
}
|
|
33181
33224
|
async function applyAttachRule(ptyHostExe) {
|
|
33182
33225
|
if (!session.attach.enabled) return;
|
|
33183
33226
|
if (!ptyHostExe) {
|
|
@@ -33210,9 +33253,9 @@ async function applyNetworkPolicy(ptyHostExe) {
|
|
|
33210
33253
|
log("Networking is disabled for this sandbox.");
|
|
33211
33254
|
return "offline";
|
|
33212
33255
|
}
|
|
33213
|
-
const
|
|
33214
|
-
const exempt =
|
|
33215
|
-
const lanRules =
|
|
33256
|
+
const block2 = session.network.blockPrivateRanges;
|
|
33257
|
+
const exempt = block2 ? discoverExemptIps() : [];
|
|
33258
|
+
const lanRules = block2 ? buildFirewallCommands(exempt) : [];
|
|
33216
33259
|
const forwardRules = forwardRule();
|
|
33217
33260
|
const commands = [
|
|
33218
33261
|
...lanRules,
|
|
@@ -33231,18 +33274,18 @@ async function applyNetworkPolicy(ptyHostExe) {
|
|
|
33231
33274
|
warn("network.dns could not be applied: " + errMsg(e));
|
|
33232
33275
|
}
|
|
33233
33276
|
}
|
|
33234
|
-
if (!
|
|
33235
|
-
if (
|
|
33277
|
+
if (!block2) log("Private-range blocking disabled by config.");
|
|
33278
|
+
if (block2)
|
|
33236
33279
|
log(
|
|
33237
33280
|
"Gateway/DNS addresses kept reachable for DNS only: " + (exempt.length ? [...new Set(exempt)].join(", ") : "(none found)")
|
|
33238
33281
|
);
|
|
33239
33282
|
if (!isWin || dryRun) {
|
|
33240
33283
|
log("(dry run) firewall plan:");
|
|
33241
33284
|
for (const c of commands) log(" netsh " + c.join(" "));
|
|
33242
|
-
return
|
|
33285
|
+
return block2 ? "blocked" : "open";
|
|
33243
33286
|
}
|
|
33244
33287
|
if (commands.length === 0) return "open";
|
|
33245
|
-
const online =
|
|
33288
|
+
const online = block2 ? await waitForInternet(30) : true;
|
|
33246
33289
|
const failures = [];
|
|
33247
33290
|
try {
|
|
33248
33291
|
run2(lanRules);
|
|
@@ -33257,7 +33300,7 @@ async function applyNetworkPolicy(ptyHostExe) {
|
|
|
33257
33300
|
warn("PROTECTION MISSING: " + problems[problems.length - 1]);
|
|
33258
33301
|
}
|
|
33259
33302
|
if (failures.length) throw new Error(failures[0]);
|
|
33260
|
-
if (!
|
|
33303
|
+
if (!block2) return "open";
|
|
33261
33304
|
if (online && !await waitForInternet(15)) {
|
|
33262
33305
|
run2(lanRules.filter((c) => c[2] === "delete"));
|
|
33263
33306
|
warn(
|
|
@@ -33487,18 +33530,109 @@ function setupGitConfig(env) {
|
|
|
33487
33530
|
spawnSync7(git, ["config", "--global", "core.autocrlf", "input"], { env: rest, windowsHide: true, stdio: "ignore" });
|
|
33488
33531
|
}
|
|
33489
33532
|
|
|
33533
|
+
// src/guest/setup/github-token.ts
|
|
33534
|
+
import fs53 from "node:fs";
|
|
33535
|
+
import { spawnSync as spawnSync8 } from "node:child_process";
|
|
33536
|
+
|
|
33537
|
+
// src/shared/github/token.ts
|
|
33538
|
+
var MIN_LENGTH = 20;
|
|
33539
|
+
var MAX_LENGTH = 255;
|
|
33540
|
+
var PRINTABLE = /^[\x21-\x7e]+$/;
|
|
33541
|
+
var GithubTokenSchema = external_exports.string().min(MIN_LENGTH).max(MAX_LENGTH).regex(PRINTABLE);
|
|
33542
|
+
var TOKEN_VARIABLES = /^(GH_TOKEN|GITHUB_TOKEN|GH_ENTERPRISE_TOKEN|GITHUB_ENTERPRISE_TOKEN)$/i;
|
|
33543
|
+
var ghEnv = (base, configDir) => ({
|
|
33544
|
+
...Object.fromEntries(
|
|
33545
|
+
Object.entries(base).filter((e) => e[1] !== void 0 && !TOKEN_VARIABLES.test(e[0]))
|
|
33546
|
+
),
|
|
33547
|
+
GH_CONFIG_DIR: configDir,
|
|
33548
|
+
GH_PROMPT_DISABLED: "1",
|
|
33549
|
+
GH_NO_UPDATE_NOTIFIER: "1"
|
|
33550
|
+
});
|
|
33551
|
+
function ghLoginCommand(ghExe, configDir, token, base) {
|
|
33552
|
+
return {
|
|
33553
|
+
file: ghExe,
|
|
33554
|
+
args: [
|
|
33555
|
+
"auth",
|
|
33556
|
+
"login",
|
|
33557
|
+
"--hostname",
|
|
33558
|
+
"github.com",
|
|
33559
|
+
"--git-protocol",
|
|
33560
|
+
"https",
|
|
33561
|
+
"--insecure-storage",
|
|
33562
|
+
"--with-token"
|
|
33563
|
+
],
|
|
33564
|
+
input: token + "\n",
|
|
33565
|
+
env: ghEnv(base, configDir)
|
|
33566
|
+
};
|
|
33567
|
+
}
|
|
33568
|
+
function ghSetupGitCommand(ghExe, configDir, base) {
|
|
33569
|
+
return { file: ghExe, args: ["auth", "setup-git", "--hostname", "github.com"], env: ghEnv(base, configDir) };
|
|
33570
|
+
}
|
|
33571
|
+
function ghOutputText(text, token) {
|
|
33572
|
+
const clean = token ? text.split(token).join("***") : text;
|
|
33573
|
+
return clean.replace(/\s+/g, " ").trim().slice(0, 300);
|
|
33574
|
+
}
|
|
33575
|
+
|
|
33576
|
+
// src/guest/setup/github-token.ts
|
|
33577
|
+
var GH_TIMEOUT_MS = 6e4;
|
|
33578
|
+
function prepareGithubFolder(token) {
|
|
33579
|
+
const dir = deliveredGhConfigDir();
|
|
33580
|
+
fs53.rmSync(dir, { recursive: true, force: true });
|
|
33581
|
+
if (!token) return false;
|
|
33582
|
+
mkdirp(dir);
|
|
33583
|
+
return true;
|
|
33584
|
+
}
|
|
33585
|
+
function runGh(command, token, what) {
|
|
33586
|
+
const result = spawnSync8(command.file, [...command.args], {
|
|
33587
|
+
env: command.env,
|
|
33588
|
+
encoding: "utf8",
|
|
33589
|
+
windowsHide: true,
|
|
33590
|
+
timeout: GH_TIMEOUT_MS,
|
|
33591
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
33592
|
+
...command.input !== void 0 ? { input: command.input } : {}
|
|
33593
|
+
});
|
|
33594
|
+
if (result.error) throw new Error(what + " could not run: " + ghOutputText(result.error.message, token));
|
|
33595
|
+
if (result.status !== 0)
|
|
33596
|
+
throw new Error(
|
|
33597
|
+
what + " failed: " + ghOutputText(String(result.stderr ?? "") || String(result.stdout ?? ""), token)
|
|
33598
|
+
);
|
|
33599
|
+
}
|
|
33600
|
+
function loginGithub(token, env) {
|
|
33601
|
+
if (dryRun) {
|
|
33602
|
+
log("(dry run) would log gh in with the GitHub token from your PC");
|
|
33603
|
+
return;
|
|
33604
|
+
}
|
|
33605
|
+
const gh2 = ghExePath();
|
|
33606
|
+
const dir = deliveredGhConfigDir();
|
|
33607
|
+
if (!exists(gh2) || env.GH_CONFIG_DIR !== dir) {
|
|
33608
|
+
fs53.rmSync(dir, { recursive: true, force: true });
|
|
33609
|
+
log("A GitHub token arrived, but gh is not set up in this sandbox (toolchains.cli.gh), so it is not used.");
|
|
33610
|
+
return;
|
|
33611
|
+
}
|
|
33612
|
+
try {
|
|
33613
|
+
runGh(ghLoginCommand(gh2, dir, token, env), token, "gh auth login");
|
|
33614
|
+
runGh(ghSetupGitCommand(gh2, dir, env), token, "gh auth setup-git");
|
|
33615
|
+
} catch (e) {
|
|
33616
|
+
fs53.rmSync(dir, { recursive: true, force: true });
|
|
33617
|
+
env.GH_CONFIG_DIR = mkdirp(ghConfigDir());
|
|
33618
|
+
addMachineEnvironment({ GH_CONFIG_DIR: env.GH_CONFIG_DIR }, []);
|
|
33619
|
+
throw e;
|
|
33620
|
+
}
|
|
33621
|
+
log("gh and https git to github.com use the GitHub token from your PC (github.shareToken); the agent can read it.");
|
|
33622
|
+
}
|
|
33623
|
+
|
|
33490
33624
|
// src/guest/sessions/pty-host.ts
|
|
33491
33625
|
function ensurePtyHost() {
|
|
33492
33626
|
return ensureCompiled("ptyhost");
|
|
33493
33627
|
}
|
|
33494
33628
|
|
|
33495
33629
|
// src/guest/toolchains/leftovers.ts
|
|
33496
|
-
import
|
|
33630
|
+
import fs54 from "node:fs";
|
|
33497
33631
|
import path66 from "node:path";
|
|
33498
33632
|
var STAGING = /\.staging-[0-9a-f]+$/i;
|
|
33499
33633
|
var entries2 = (dir) => {
|
|
33500
33634
|
try {
|
|
33501
|
-
return
|
|
33635
|
+
return fs54.readdirSync(dir, { withFileTypes: true });
|
|
33502
33636
|
} catch {
|
|
33503
33637
|
return [];
|
|
33504
33638
|
}
|
|
@@ -33515,17 +33649,17 @@ function pruneToolLeftovers() {
|
|
|
33515
33649
|
|
|
33516
33650
|
// src/guest/audit/process-audit.ts
|
|
33517
33651
|
import path67 from "node:path";
|
|
33518
|
-
import { spawnSync as
|
|
33652
|
+
import { spawnSync as spawnSync9 } from "node:child_process";
|
|
33519
33653
|
var PROCESS_CREATION = "{0CCE922B-69AE-11D9-BED3-505054503030}";
|
|
33520
33654
|
var auditOn = () => Boolean(session.auditProcesses) && isWin && !dryRun;
|
|
33521
33655
|
function enableProcessAudit() {
|
|
33522
33656
|
if (!auditOn()) return;
|
|
33523
|
-
|
|
33657
|
+
spawnSync9(
|
|
33524
33658
|
path67.join(process.env.WINDIR ?? "C:\\Windows", "System32", "auditpol.exe"),
|
|
33525
33659
|
["/set", "/subcategory:" + PROCESS_CREATION, "/success:enable"],
|
|
33526
33660
|
{ windowsHide: true, stdio: "ignore" }
|
|
33527
33661
|
);
|
|
33528
|
-
|
|
33662
|
+
spawnSync9(
|
|
33529
33663
|
SYSTEM.reg(),
|
|
33530
33664
|
[
|
|
33531
33665
|
"add",
|
|
@@ -33545,7 +33679,8 @@ function enableProcessAudit() {
|
|
|
33545
33679
|
|
|
33546
33680
|
// src/guest/vpn/vpn.ts
|
|
33547
33681
|
import dns2 from "node:dns";
|
|
33548
|
-
import
|
|
33682
|
+
import fs58 from "node:fs";
|
|
33683
|
+
import net3 from "node:net";
|
|
33549
33684
|
import os14 from "node:os";
|
|
33550
33685
|
import path71 from "node:path";
|
|
33551
33686
|
|
|
@@ -33710,13 +33845,13 @@ function inspectOvpn(text) {
|
|
|
33710
33845
|
if (text.includes("\0")) return { ok: false, problems: ["the file is not text"] };
|
|
33711
33846
|
const lines = text.split(/\r?\n/);
|
|
33712
33847
|
if (lines.length > MAX_LINES) return { ok: false, problems: ["the file has too many lines"] };
|
|
33713
|
-
let
|
|
33848
|
+
let block2 = null;
|
|
33714
33849
|
let defaultProto = "udp";
|
|
33715
33850
|
lines.forEach((line, i) => {
|
|
33716
33851
|
const at = "line " + (i + 1) + ": ";
|
|
33717
33852
|
const trimmed = line.trim();
|
|
33718
|
-
if (
|
|
33719
|
-
if (trimmed.toLowerCase() === "</" +
|
|
33853
|
+
if (block2) {
|
|
33854
|
+
if (trimmed.toLowerCase() === "</" + block2 + ">") block2 = null;
|
|
33720
33855
|
else if (/^<\/?[A-Za-z-]+>$/.test(trimmed)) refuse(at + "a section inside a section");
|
|
33721
33856
|
return;
|
|
33722
33857
|
}
|
|
@@ -33724,7 +33859,7 @@ function inspectOvpn(text) {
|
|
|
33724
33859
|
if (open2) {
|
|
33725
33860
|
const tag = open2[1].toLowerCase();
|
|
33726
33861
|
if (!BLOCKS.has(tag)) refuse(at + "<" + tag + "> is not allowed");
|
|
33727
|
-
|
|
33862
|
+
block2 = tag;
|
|
33728
33863
|
return;
|
|
33729
33864
|
}
|
|
33730
33865
|
const d = directiveOf(line);
|
|
@@ -33749,7 +33884,7 @@ function inspectOvpn(text) {
|
|
|
33749
33884
|
}
|
|
33750
33885
|
});
|
|
33751
33886
|
const remotes = found.map((r) => ({ host: r.host, port: r.port, proto: r.proto ?? defaultProto }));
|
|
33752
|
-
if (
|
|
33887
|
+
if (block2) refuse("a <" + block2 + "> section is never closed");
|
|
33753
33888
|
if (remotes.length === 0) refuse("it names no remote server");
|
|
33754
33889
|
if (remotes.length > 64) refuse("it names too many servers");
|
|
33755
33890
|
return problems2.length ? { ok: false, problems: problems2 } : { ok: true, remotes };
|
|
@@ -33958,8 +34093,22 @@ var drop = (name) => [
|
|
|
33958
34093
|
"rule",
|
|
33959
34094
|
"name=" + VPN_RULE_PREFIX + name
|
|
33960
34095
|
];
|
|
34096
|
+
var block = (name, extra) => [
|
|
34097
|
+
"advfirewall",
|
|
34098
|
+
"firewall",
|
|
34099
|
+
"add",
|
|
34100
|
+
"rule",
|
|
34101
|
+
"name=" + VPN_RULE_PREFIX + name,
|
|
34102
|
+
"dir=out",
|
|
34103
|
+
"action=block",
|
|
34104
|
+
"enable=yes",
|
|
34105
|
+
"profile=any",
|
|
34106
|
+
...extra
|
|
34107
|
+
];
|
|
34108
|
+
var BLOCK_RULES = ["Block-Internet", "Block-IPv6", "Block-DNS-UDP", "Block-DNS-TCP"];
|
|
33961
34109
|
function ruleNames(serverCount) {
|
|
33962
34110
|
return [
|
|
34111
|
+
...BLOCK_RULES,
|
|
33963
34112
|
"Loopback",
|
|
33964
34113
|
"DHCP",
|
|
33965
34114
|
"Host",
|
|
@@ -33967,6 +34116,39 @@ function ruleNames(serverCount) {
|
|
|
33967
34116
|
...Array.from({ length: Math.max(serverCount, 0) }, (_v, i) => "Server-" + (i + 1))
|
|
33968
34117
|
];
|
|
33969
34118
|
}
|
|
34119
|
+
var NOT_INTERNET = [
|
|
34120
|
+
["0.0.0.0", "0.255.255.255"],
|
|
34121
|
+
["10.0.0.0", "10.255.255.255"],
|
|
34122
|
+
["100.64.0.0", "100.127.255.255"],
|
|
34123
|
+
["127.0.0.0", "127.255.255.255"],
|
|
34124
|
+
["169.254.0.0", "169.254.255.255"],
|
|
34125
|
+
["172.16.0.0", "172.31.255.255"],
|
|
34126
|
+
["192.168.0.0", "192.168.255.255"],
|
|
34127
|
+
["224.0.0.0", "255.255.255.255"]
|
|
34128
|
+
];
|
|
34129
|
+
var LAST_IPV4 = 4294967295;
|
|
34130
|
+
function ipNumber(ip) {
|
|
34131
|
+
return ip.split(".").reduce((n, part) => n * 256 + Number(part), 0);
|
|
34132
|
+
}
|
|
34133
|
+
function ipText(n) {
|
|
34134
|
+
return [24, 16, 8, 0].map((shift) => Math.floor(n / 2 ** shift) % 256).join(".");
|
|
34135
|
+
}
|
|
34136
|
+
function ipv4Except(excluded) {
|
|
34137
|
+
const sorted = [...excluded].sort((a, b) => a[0] - b[0]);
|
|
34138
|
+
const out = [];
|
|
34139
|
+
let next = 0;
|
|
34140
|
+
for (const [from, to] of sorted) {
|
|
34141
|
+
if (from > next) out.push(ipText(next) + "-" + ipText(from - 1));
|
|
34142
|
+
next = Math.max(next, to + 1);
|
|
34143
|
+
}
|
|
34144
|
+
if (next <= LAST_IPV4) out.push(ipText(next) + "-" + ipText(LAST_IPV4));
|
|
34145
|
+
return out.join(",");
|
|
34146
|
+
}
|
|
34147
|
+
function internetExcept(servers) {
|
|
34148
|
+
const ranges = NOT_INTERNET.map(([a, b]) => [ipNumber(a), ipNumber(b)]);
|
|
34149
|
+
for (const s of cleanServers(servers)) ranges.push([ipNumber(s.ip), ipNumber(s.ip)]);
|
|
34150
|
+
return ipv4Except(ranges);
|
|
34151
|
+
}
|
|
33970
34152
|
function cleanServers(servers) {
|
|
33971
34153
|
const seen = /* @__PURE__ */ new Set();
|
|
33972
34154
|
return servers.filter((s) => {
|
|
@@ -33981,6 +34163,10 @@ function killSwitchCommands(servers, ptyHostExe) {
|
|
|
33981
34163
|
return [
|
|
33982
34164
|
...ruleNames(Math.max(list.length, 8)).map(drop),
|
|
33983
34165
|
["advfirewall", "set", "allprofiles", "state", "on"],
|
|
34166
|
+
block("Block-Internet", ["protocol=any", "remoteip=" + internetExcept(list)]),
|
|
34167
|
+
block("Block-IPv6", ["protocol=any", "remoteip=2000::/3"]),
|
|
34168
|
+
block("Block-DNS-UDP", ["protocol=udp", "remoteport=53"]),
|
|
34169
|
+
block("Block-DNS-TCP", ["protocol=tcp", "remoteport=53"]),
|
|
33984
34170
|
["advfirewall", "set", "allprofiles", "firewallpolicy", "blockinbound,blockoutbound"],
|
|
33985
34171
|
rule("Loopback", ["protocol=any", "remoteip=127.0.0.0/8"]),
|
|
33986
34172
|
rule("DHCP", ["protocol=udp", "localport=68", "remoteport=67"]),
|
|
@@ -33992,7 +34178,21 @@ function killSwitchCommands(servers, ptyHostExe) {
|
|
|
33992
34178
|
}
|
|
33993
34179
|
function tunnelCommands(tunnelIp) {
|
|
33994
34180
|
if (!isIPv4(tunnelIp)) throw new Error("Not an IPv4 address: " + tunnelIp);
|
|
33995
|
-
|
|
34181
|
+
const n = ipNumber(tunnelIp);
|
|
34182
|
+
const notTunnel = ipv4Except([[n, n]]);
|
|
34183
|
+
return [
|
|
34184
|
+
...["Block-Internet", "Block-DNS-UDP", "Block-DNS-TCP"].map((name) => [
|
|
34185
|
+
"advfirewall",
|
|
34186
|
+
"firewall",
|
|
34187
|
+
"set",
|
|
34188
|
+
"rule",
|
|
34189
|
+
"name=" + VPN_RULE_PREFIX + name,
|
|
34190
|
+
"new",
|
|
34191
|
+
"localip=" + notTunnel
|
|
34192
|
+
]),
|
|
34193
|
+
drop("Tunnel"),
|
|
34194
|
+
rule("Tunnel", ["protocol=any", "localip=" + tunnelIp])
|
|
34195
|
+
];
|
|
33996
34196
|
}
|
|
33997
34197
|
function tunnelAddressFromLog(log2) {
|
|
33998
34198
|
const add = /net_addr_v4_add:\s*(\d{1,3}(?:\.\d{1,3}){3})\/\d+/.exec(log2);
|
|
@@ -34005,7 +34205,7 @@ function tunnelAddressFromLog(log2) {
|
|
|
34005
34205
|
|
|
34006
34206
|
// src/guest/vpn/openvpn.ts
|
|
34007
34207
|
import crypto4 from "node:crypto";
|
|
34008
|
-
import
|
|
34208
|
+
import fs55 from "node:fs";
|
|
34009
34209
|
import path68 from "node:path";
|
|
34010
34210
|
|
|
34011
34211
|
// src/shared/vpn/download.ts
|
|
@@ -34042,7 +34242,12 @@ function openvpnDownload(arch2 = process.arch) {
|
|
|
34042
34242
|
const entry = arch2 === "arm64" ? OPENVPN_MSI.arm64 : OPENVPN_MSI.x64;
|
|
34043
34243
|
return { ...entry, url: OPENVPN_MSI.base + entry.file };
|
|
34044
34244
|
}
|
|
34045
|
-
|
|
34245
|
+
function repairServiceQueries() {
|
|
34246
|
+
const did = scriptOutput("repair-wmi-services.ps1");
|
|
34247
|
+
if (did === "removed") log("VPN: repaired the Windows service queries installers use (a Windows Sandbox gap).");
|
|
34248
|
+
else if (did !== "absent" && did !== "kept") warn("VPN: could not check the Windows service queries installers use.");
|
|
34249
|
+
}
|
|
34250
|
+
var hasHash = (file3, sha256) => crypto4.createHash("sha256").update(fs55.readFileSync(file3)).digest("hex") === sha256;
|
|
34046
34251
|
async function ensureOpenVpn() {
|
|
34047
34252
|
const exe = openvpnExe();
|
|
34048
34253
|
if (!isWin || dryRun) return exe;
|
|
@@ -34053,6 +34258,7 @@ async function ensureOpenVpn() {
|
|
|
34053
34258
|
log("VPN: downloading OpenVPN " + OPENVPN_MSI.version + " (about 6 MB)");
|
|
34054
34259
|
await downloader.file(dl.url, msi, dl.sha256);
|
|
34055
34260
|
}
|
|
34261
|
+
repairServiceQueries();
|
|
34056
34262
|
log("VPN: installing OpenVPN");
|
|
34057
34263
|
const logFile2 = path68.join(toolsDir, "downloads", "openvpn-install.log");
|
|
34058
34264
|
const code = await spawnAsync(SYSTEM.msiexec(), ["/i", msi, "/qn", "/norestart", "/l*v", logFile2], {
|
|
@@ -34066,7 +34272,7 @@ async function ensureOpenVpn() {
|
|
|
34066
34272
|
|
|
34067
34273
|
// src/guest/vpn/tunnel.ts
|
|
34068
34274
|
import { spawn as spawn7 } from "node:child_process";
|
|
34069
|
-
import
|
|
34275
|
+
import fs56 from "node:fs";
|
|
34070
34276
|
import os12 from "node:os";
|
|
34071
34277
|
import path69 from "node:path";
|
|
34072
34278
|
var DONE = "Initialization Sequence Completed";
|
|
@@ -34084,17 +34290,17 @@ function failureReason(text) {
|
|
|
34084
34290
|
}
|
|
34085
34291
|
var tail = (text, lines = 12) => text.trim().split(/\r?\n/).slice(-lines).join("\n");
|
|
34086
34292
|
async function startTunnel(o) {
|
|
34087
|
-
const dir =
|
|
34293
|
+
const dir = fs56.mkdtempSync(path69.join(os12.tmpdir(), "sbx-vpn-"));
|
|
34088
34294
|
const auth = path69.join(dir, "login.txt");
|
|
34089
34295
|
const logFile2 = path69.join(dir, "openvpn.log");
|
|
34090
34296
|
const keepLog = () => {
|
|
34091
34297
|
try {
|
|
34092
|
-
|
|
34093
|
-
|
|
34298
|
+
fs56.mkdirSync(logsDir, { recursive: true });
|
|
34299
|
+
fs56.copyFileSync(logFile2, path69.join(logsDir, "openvpn.log"));
|
|
34094
34300
|
} catch {
|
|
34095
34301
|
}
|
|
34096
34302
|
};
|
|
34097
|
-
|
|
34303
|
+
fs56.writeFileSync(auth, o.username + "\r\n" + o.password + "\r\n", "utf8");
|
|
34098
34304
|
try {
|
|
34099
34305
|
const child = spawn7(
|
|
34100
34306
|
o.exe,
|
|
@@ -34112,7 +34318,7 @@ async function startTunnel(o) {
|
|
|
34112
34318
|
child.unref();
|
|
34113
34319
|
const deadline = Date.now() + (o.timeoutMs ?? 9e4);
|
|
34114
34320
|
for (; ; ) {
|
|
34115
|
-
const text =
|
|
34321
|
+
const text = fs56.existsSync(logFile2) ? fs56.readFileSync(logFile2, "utf8") : "";
|
|
34116
34322
|
if (text.includes(DONE)) {
|
|
34117
34323
|
keepLog();
|
|
34118
34324
|
const tunnelIp = tunnelAddressFromLog(text) ?? void 0;
|
|
@@ -34132,14 +34338,14 @@ async function startTunnel(o) {
|
|
|
34132
34338
|
await new Promise((r) => setTimeout(r, 500));
|
|
34133
34339
|
}
|
|
34134
34340
|
} finally {
|
|
34135
|
-
|
|
34341
|
+
fs56.rmSync(auth, { force: true });
|
|
34136
34342
|
}
|
|
34137
34343
|
}
|
|
34138
34344
|
|
|
34139
34345
|
// src/guest/vpn/wireguard.ts
|
|
34140
34346
|
import { execFile } from "node:child_process";
|
|
34141
34347
|
import crypto5 from "node:crypto";
|
|
34142
|
-
import
|
|
34348
|
+
import fs57 from "node:fs";
|
|
34143
34349
|
import os13 from "node:os";
|
|
34144
34350
|
import path70 from "node:path";
|
|
34145
34351
|
var WIREGUARD_TUNNEL = "sandbox";
|
|
@@ -34153,7 +34359,7 @@ function wireguardDownload(arch2 = process.arch) {
|
|
|
34153
34359
|
const entry = arch2 === "arm64" ? WIREGUARD_MSI.arm64 : WIREGUARD_MSI.x64;
|
|
34154
34360
|
return { ...entry, url: WIREGUARD_MSI.base + entry.file };
|
|
34155
34361
|
}
|
|
34156
|
-
var hasHash2 = (file3, sha256) => crypto5.createHash("sha256").update(
|
|
34362
|
+
var hasHash2 = (file3, sha256) => crypto5.createHash("sha256").update(fs57.readFileSync(file3)).digest("hex") === sha256;
|
|
34157
34363
|
async function ensureWireguard() {
|
|
34158
34364
|
const exe = wireguardExe();
|
|
34159
34365
|
if (!isWin || dryRun) return exe;
|
|
@@ -34164,6 +34370,7 @@ async function ensureWireguard() {
|
|
|
34164
34370
|
log("VPN: downloading WireGuard " + WIREGUARD_MSI.version + " (about 3 MB)");
|
|
34165
34371
|
await downloader.file(dl.url, msi, dl.sha256);
|
|
34166
34372
|
}
|
|
34373
|
+
repairServiceQueries();
|
|
34167
34374
|
log("VPN: installing WireGuard");
|
|
34168
34375
|
const logFile2 = path70.join(toolsDir, "downloads", "wireguard-install.log");
|
|
34169
34376
|
const code = await spawnAsync(
|
|
@@ -34198,9 +34405,9 @@ async function removeWireguardTunnel(exe) {
|
|
|
34198
34405
|
}
|
|
34199
34406
|
async function startWireguardTunnel(o) {
|
|
34200
34407
|
const root = path70.join(process.env.SystemRoot ?? "C:\\Windows", "Temp");
|
|
34201
|
-
const dir =
|
|
34408
|
+
const dir = fs57.mkdtempSync(path70.join(fs57.existsSync(root) ? root : os13.tmpdir(), "sbx-wg-"));
|
|
34202
34409
|
const file3 = path70.join(dir, WIREGUARD_TUNNEL + ".conf");
|
|
34203
|
-
|
|
34410
|
+
fs57.writeFileSync(file3, o.config, "utf8");
|
|
34204
34411
|
const fail = async (message) => {
|
|
34205
34412
|
await removeWireguardTunnel(o.exe);
|
|
34206
34413
|
return { ok: false, message };
|
|
@@ -34221,7 +34428,7 @@ async function startWireguardTunnel(o) {
|
|
|
34221
34428
|
await sleep(500);
|
|
34222
34429
|
}
|
|
34223
34430
|
} finally {
|
|
34224
|
-
|
|
34431
|
+
fs57.rmSync(dir, { recursive: true, force: true });
|
|
34225
34432
|
}
|
|
34226
34433
|
}
|
|
34227
34434
|
async function waitForHandshake(exe, poke, timeoutMs = 3e4) {
|
|
@@ -34290,15 +34497,47 @@ async function publicAddress() {
|
|
|
34290
34497
|
}
|
|
34291
34498
|
}
|
|
34292
34499
|
var hasAdapter2 = (ip) => Object.values(os14.networkInterfaces()).some((list) => (list ?? []).some((i) => i.address === ip));
|
|
34500
|
+
var PROBE_TARGETS = ["1.1.1.1", "8.8.8.8", "9.9.9.9"];
|
|
34501
|
+
var PROBE_TIMEOUT_MS = 3e3;
|
|
34502
|
+
function connects(ip, port) {
|
|
34503
|
+
return new Promise((resolve2) => {
|
|
34504
|
+
const socket = net3.connect({ host: ip, port });
|
|
34505
|
+
const done = (ok) => {
|
|
34506
|
+
socket.destroy();
|
|
34507
|
+
resolve2(ok);
|
|
34508
|
+
};
|
|
34509
|
+
socket.setTimeout(PROBE_TIMEOUT_MS, () => done(false));
|
|
34510
|
+
socket.once("connect", () => done(true));
|
|
34511
|
+
socket.once("error", () => done(false));
|
|
34512
|
+
});
|
|
34513
|
+
}
|
|
34514
|
+
async function directConnectionBlocked(servers) {
|
|
34515
|
+
const targets = PROBE_TARGETS.filter((ip) => !servers.some((s) => s.ip === ip));
|
|
34516
|
+
const results = await Promise.all(targets.map((ip) => connects(ip, 443)));
|
|
34517
|
+
return !results.some(Boolean);
|
|
34518
|
+
}
|
|
34293
34519
|
async function setupVpn(secrets, ptyHostExe) {
|
|
34294
34520
|
const vpn = session.vpn;
|
|
34295
34521
|
if (!vpn) return true;
|
|
34296
34522
|
const killSwitch = vpn.killSwitch;
|
|
34297
34523
|
let blocked = false;
|
|
34298
|
-
|
|
34299
|
-
|
|
34300
|
-
|
|
34301
|
-
|
|
34524
|
+
let held = false;
|
|
34525
|
+
const block2 = async (servers) => {
|
|
34526
|
+
if (!isWin || dryRun) {
|
|
34527
|
+
blocked = held = true;
|
|
34528
|
+
return;
|
|
34529
|
+
}
|
|
34530
|
+
try {
|
|
34531
|
+
run2(killSwitchCommands(servers, ptyHostExe ? longPath(ptyHostExe) : null));
|
|
34532
|
+
} finally {
|
|
34533
|
+
blocked = true;
|
|
34534
|
+
held = await directConnectionBlocked(servers);
|
|
34535
|
+
}
|
|
34536
|
+
if (held) log("VPN: kill switch on: nothing leaves the sandbox except through the tunnel (checked).");
|
|
34537
|
+
else
|
|
34538
|
+
warn(
|
|
34539
|
+
"VPN: the kill switch did not hold: a direct connection still got out. If the tunnel drops, traffic leaves through your normal connection."
|
|
34540
|
+
);
|
|
34302
34541
|
};
|
|
34303
34542
|
setVpnStatus("starting", "Starting the VPN");
|
|
34304
34543
|
try {
|
|
@@ -34314,7 +34553,7 @@ async function setupVpn(secrets, ptyHostExe) {
|
|
|
34314
34553
|
warn(
|
|
34315
34554
|
"VPN: AllowedIPs does not include 0.0.0.0/0: with the kill switch on, only the tunnel traffic can leave the sandbox."
|
|
34316
34555
|
);
|
|
34317
|
-
if (killSwitch)
|
|
34556
|
+
if (killSwitch) await block2(servers);
|
|
34318
34557
|
if (dryRun || !isWin) {
|
|
34319
34558
|
log("(dry run) would start the WireGuard tunnel " + vpn.server);
|
|
34320
34559
|
setVpnStatus("off", "dry run");
|
|
@@ -34329,11 +34568,11 @@ async function setupVpn(secrets, ptyHostExe) {
|
|
|
34329
34568
|
const credentials = secrets.vpn;
|
|
34330
34569
|
if (!credentials) throw new Error("the VPN login did not arrive (start the sandbox again)");
|
|
34331
34570
|
const profile = path71.join(launchDir, "vpn", "server.ovpn");
|
|
34332
|
-
const remotes = assertSafeOvpn(
|
|
34571
|
+
const remotes = assertSafeOvpn(fs58.readFileSync(profile, "utf8"), vpn.server);
|
|
34333
34572
|
const exe = await ensureOpenVpn();
|
|
34334
34573
|
const servers = await serverAddresses(remotes);
|
|
34335
34574
|
if (servers.length === 0) throw new Error("the VPN server addresses could not be found");
|
|
34336
|
-
if (killSwitch)
|
|
34575
|
+
if (killSwitch) await block2(servers);
|
|
34337
34576
|
if (dryRun || !isWin) {
|
|
34338
34577
|
log("(dry run) would start the VPN tunnel to " + vpn.server);
|
|
34339
34578
|
setVpnStatus("off", "dry run");
|
|
@@ -34352,18 +34591,21 @@ async function setupVpn(secrets, ptyHostExe) {
|
|
|
34352
34591
|
throw new Error("the tunnel reported it was up, but no network adapter with its address appeared");
|
|
34353
34592
|
const publicIp = await publicAddress();
|
|
34354
34593
|
log("VPN: up" + (publicIp ? " (the sandbox appears as " + publicIp + ")" : "") + ".");
|
|
34355
|
-
setVpnStatus("up", "The tunnel is up",
|
|
34594
|
+
setVpnStatus("up", "The tunnel is up", {
|
|
34595
|
+
...publicIp ? { publicIp } : {},
|
|
34596
|
+
...killSwitch ? { killSwitchHeld: held } : {}
|
|
34597
|
+
});
|
|
34356
34598
|
return true;
|
|
34357
34599
|
} catch (e) {
|
|
34358
34600
|
const reason = errMsg(e);
|
|
34359
34601
|
try {
|
|
34360
|
-
if (killSwitch && !blocked)
|
|
34602
|
+
if (killSwitch && !blocked) await block2([]);
|
|
34361
34603
|
} catch (blockError) {
|
|
34362
34604
|
warn("VPN: could not close the network after the failure: " + errMsg(blockError));
|
|
34363
34605
|
}
|
|
34364
|
-
const
|
|
34365
|
-
warn(
|
|
34366
|
-
setVpnStatus("failed", reason);
|
|
34606
|
+
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.";
|
|
34607
|
+
warn("VPN failed: " + reason + after);
|
|
34608
|
+
setVpnStatus("failed", reason, killSwitch ? { killSwitchHeld: held } : {});
|
|
34367
34609
|
return false;
|
|
34368
34610
|
}
|
|
34369
34611
|
}
|
|
@@ -34420,10 +34662,10 @@ var FrameReader = class {
|
|
|
34420
34662
|
};
|
|
34421
34663
|
|
|
34422
34664
|
// src/shared/pty/client.ts
|
|
34423
|
-
import
|
|
34665
|
+
import net4 from "node:net";
|
|
34424
34666
|
var connectOnce = (host, port, timeoutMs) => {
|
|
34425
34667
|
return new Promise((resolve2, reject) => {
|
|
34426
|
-
const socket =
|
|
34668
|
+
const socket = net4.connect({ host, port });
|
|
34427
34669
|
const timer = setTimeout(() => {
|
|
34428
34670
|
socket.destroy();
|
|
34429
34671
|
reject(new Error("timed out connecting to " + host + ":" + port));
|
|
@@ -34644,6 +34886,36 @@ function unfinishedSequence(data) {
|
|
|
34644
34886
|
return data.length;
|
|
34645
34887
|
}
|
|
34646
34888
|
|
|
34889
|
+
// src/shared/pty/ctrl-c.ts
|
|
34890
|
+
var CTRL_C_CONFIRM_MS = 1500;
|
|
34891
|
+
var CTRL_C_HINT = "Ctrl+C again to send it to the program (Esc stops an agent)";
|
|
34892
|
+
var OSC_TITLE = /\x1b\][02];([^\x07\x1b]{0,256})(?:\x07|\x1b\\)/g;
|
|
34893
|
+
var CtrlCGuard = class {
|
|
34894
|
+
armedAt = Number.NEGATIVE_INFINITY;
|
|
34895
|
+
lastTitle = "";
|
|
34896
|
+
/** What to send for one read from the keyboard: a lone Ctrl+C only when another came just before. */
|
|
34897
|
+
push(chunk, nowMs) {
|
|
34898
|
+
if (chunk.length !== 1 || chunk[0] !== 3) return { send: chunk, held: false };
|
|
34899
|
+
if (nowMs - this.armedAt <= CTRL_C_CONFIRM_MS) {
|
|
34900
|
+
this.armedAt = Number.NEGATIVE_INFINITY;
|
|
34901
|
+
return { send: chunk, held: false };
|
|
34902
|
+
}
|
|
34903
|
+
this.armedAt = nowMs;
|
|
34904
|
+
return { send: Buffer.alloc(0), held: true };
|
|
34905
|
+
}
|
|
34906
|
+
/** Remembers the title the program last set (from its output), to put it back after the hint. */
|
|
34907
|
+
watchOutput(text) {
|
|
34908
|
+
for (const m of text.matchAll(OSC_TITLE)) this.lastTitle = m[1];
|
|
34909
|
+
}
|
|
34910
|
+
/** The escape sequence that shows the hint, and the one that puts the program's title back. */
|
|
34911
|
+
hintTitle() {
|
|
34912
|
+
return "\x1B]0;" + CTRL_C_HINT + "\x07";
|
|
34913
|
+
}
|
|
34914
|
+
restoreTitle() {
|
|
34915
|
+
return "\x1B]0;" + this.lastTitle.replace(/[\x00-\x1f\x7f]/g, "") + "\x07";
|
|
34916
|
+
}
|
|
34917
|
+
};
|
|
34918
|
+
|
|
34647
34919
|
// src/shared/pty/terminal.ts
|
|
34648
34920
|
var MOUSE_OFF = "\x1B[?1000l\x1B[?1002l\x1B[?1003l\x1B[?1005l\x1B[?1006l\x1B[?1015l";
|
|
34649
34921
|
function fixWindowsKeys(chunk) {
|
|
@@ -34674,6 +34946,7 @@ function runTerminalClient(socket, token, options = {}) {
|
|
|
34674
34946
|
clearInterval(heartbeat);
|
|
34675
34947
|
clearInterval(sizeWatch);
|
|
34676
34948
|
clearTimeout(joinTimer);
|
|
34949
|
+
clearTimeout(hintTimer);
|
|
34677
34950
|
socket.destroy();
|
|
34678
34951
|
stdout.write("\x1B[0m\x1B[?25h" + MOUSE_OFF + "\r\n");
|
|
34679
34952
|
void (vtInput?.stop() ?? Promise.resolve()).then(() => {
|
|
@@ -34687,11 +34960,23 @@ function runTerminalClient(socket, token, options = {}) {
|
|
|
34687
34960
|
const sendInput = (data) => {
|
|
34688
34961
|
if (data.length && !done) socket.write(encodeFrame(FrameType.Input, swapKeys ? fixWindowsKeys(data) : data));
|
|
34689
34962
|
};
|
|
34963
|
+
const guard = options.confirmCtrlC ? new CtrlCGuard() : null;
|
|
34964
|
+
let hintTimer;
|
|
34690
34965
|
const onInput = (chunk) => {
|
|
34691
34966
|
if (options.detachKey !== void 0 && chunk.includes(options.detachKey)) {
|
|
34692
34967
|
finish({ reason: "detach" });
|
|
34693
34968
|
return;
|
|
34694
34969
|
}
|
|
34970
|
+
if (guard) {
|
|
34971
|
+
const decided = guard.push(chunk, Date.now());
|
|
34972
|
+
clearTimeout(hintTimer);
|
|
34973
|
+
if (decided.held) {
|
|
34974
|
+
stdout.write(guard.hintTitle());
|
|
34975
|
+
hintTimer = setTimeout(() => stdout.write(guard.restoreTitle()), CTRL_C_CONFIRM_MS);
|
|
34976
|
+
return;
|
|
34977
|
+
}
|
|
34978
|
+
if (decided.send.length === 1 && decided.send[0] === 3) stdout.write(guard.restoreTitle());
|
|
34979
|
+
}
|
|
34695
34980
|
clearTimeout(joinTimer);
|
|
34696
34981
|
sendInput(joiner.push(chunk));
|
|
34697
34982
|
if (joiner.holding()) joinTimer = setTimeout(() => sendInput(joiner.flush()), JOIN_MS);
|
|
@@ -34724,8 +35009,11 @@ function runTerminalClient(socket, token, options = {}) {
|
|
|
34724
35009
|
return;
|
|
34725
35010
|
}
|
|
34726
35011
|
for (const frame of frames) {
|
|
34727
|
-
if (frame.type === FrameType.Output)
|
|
34728
|
-
|
|
35012
|
+
if (frame.type === FrameType.Output) {
|
|
35013
|
+
const out = filter.push(frame.payload);
|
|
35014
|
+
guard?.watchOutput(out.toString("latin1"));
|
|
35015
|
+
stdout.write(out);
|
|
35016
|
+
} else if (frame.type === FrameType.Console) passthrough = frame.payload.toString("latin1") === "conpty.dll";
|
|
34729
35017
|
else if (frame.type === FrameType.Restarting) stdout.write(MOUSE_OFF + "\x1B[2J\x1B[3J\x1B[H");
|
|
34730
35018
|
else if (frame.type === FrameType.Exit)
|
|
34731
35019
|
finish({ reason: "exit", exitCode: frame.payload.length >= 4 ? frame.payload.readInt32LE(0) : 1 });
|
|
@@ -34778,7 +35066,10 @@ async function viewSession(id) {
|
|
|
34778
35066
|
return 1;
|
|
34779
35067
|
}
|
|
34780
35068
|
const socket = await connect({ ...session2.attach, addresses: ["127.0.0.1"] });
|
|
34781
|
-
const result = await runTerminalClient(socket, session2.attach.token, {
|
|
35069
|
+
const result = await runTerminalClient(socket, session2.attach.token, {
|
|
35070
|
+
clipboardWrites: true,
|
|
35071
|
+
confirmCtrlC: session.attach.confirmCtrlC !== false
|
|
35072
|
+
});
|
|
34782
35073
|
if (result.reason === "exit") console.log(session2.harness + " exited with code " + result.exitCode + ".");
|
|
34783
35074
|
else if (result.reason === "error") console.log("Session error: " + result.message);
|
|
34784
35075
|
return result.reason === "exit" ? result.exitCode : 1;
|
|
@@ -34833,7 +35124,7 @@ function saveProjectStatus(name, workspace2, phase, message, databases, summary)
|
|
|
34833
35124
|
}
|
|
34834
35125
|
|
|
34835
35126
|
// src/guest/runtime/secrets.ts
|
|
34836
|
-
import
|
|
35127
|
+
import fs59 from "node:fs";
|
|
34837
35128
|
|
|
34838
35129
|
// src/shared/channel/secrets.ts
|
|
34839
35130
|
var Environment = external_exports.record(external_exports.string().max(256), external_exports.string().max(65536));
|
|
@@ -34849,7 +35140,9 @@ var SecretsFileSchema = external_exports.strictObject({
|
|
|
34849
35140
|
/** VPN service credentials (vpn.provider's login), only for the launch's own sandbox. */
|
|
34850
35141
|
vpn: external_exports.strictObject({ username: external_exports.string().min(1).max(256), password: external_exports.string().min(1).max(1024) }).optional(),
|
|
34851
35142
|
/** The checked WireGuard config of vpn.provider wireguard-file (holds the private key). */
|
|
34852
|
-
wireguardConfig: external_exports.string().min(1).max(32 * 1024).optional()
|
|
35143
|
+
wireguardConfig: external_exports.string().min(1).max(32 * 1024).optional(),
|
|
35144
|
+
/** The GitHub token you saved for sandboxes (github.shareToken), only with git access "full". */
|
|
35145
|
+
githubToken: GithubTokenSchema.optional()
|
|
34853
35146
|
});
|
|
34854
35147
|
|
|
34855
35148
|
// src/guest/runtime/secrets.ts
|
|
@@ -34859,12 +35152,12 @@ function takeSecrets(id) {
|
|
|
34859
35152
|
const file3 = run.secretFile(id);
|
|
34860
35153
|
let text;
|
|
34861
35154
|
try {
|
|
34862
|
-
if (
|
|
34863
|
-
text =
|
|
35155
|
+
if (fs59.statSync(file3).size > MAX_BYTES) throw new Error("too big");
|
|
35156
|
+
text = fs59.readFileSync(file3, "utf8").replace(/^\uFEFF/, "");
|
|
34864
35157
|
} catch {
|
|
34865
35158
|
return {};
|
|
34866
35159
|
} finally {
|
|
34867
|
-
|
|
35160
|
+
fs59.rmSync(file3, { force: true });
|
|
34868
35161
|
}
|
|
34869
35162
|
try {
|
|
34870
35163
|
const parsed = SecretsFileSchema.safeParse(JSON.parse(text));
|
|
@@ -34917,7 +35210,7 @@ function startDaemon(env, secrets) {
|
|
|
34917
35210
|
function writeDbCommand() {
|
|
34918
35211
|
const dir = mkdirp(path73.join(localDir, "bin"));
|
|
34919
35212
|
const db = path73.join(path73.dirname(process.argv[1]), "db.js");
|
|
34920
|
-
|
|
35213
|
+
fs60.writeFileSync(
|
|
34921
35214
|
path73.join(dir, "sbx-db.cmd"),
|
|
34922
35215
|
'@setlocal\r\n@set AGENT_LOG_PREFIX=db\r\n@"' + process.execPath + '" "' + db + '" %*\r\n'
|
|
34923
35216
|
);
|
|
@@ -34927,8 +35220,8 @@ function writeDbCommand() {
|
|
|
34927
35220
|
function writeAgentCommands(dir) {
|
|
34928
35221
|
const install = { node: process.execPath, script: path73.join(path73.dirname(process.argv[1]), "agent.js") };
|
|
34929
35222
|
for (const shim3 of agentShims(toolsDir, session.agents ?? {}))
|
|
34930
|
-
|
|
34931
|
-
|
|
35223
|
+
fs60.writeFileSync(path73.join(dir, shim3.command + ".cmd"), shimText(shim3, install));
|
|
35224
|
+
fs60.writeFileSync(path73.join(dir, "sbx-agent.cmd"), sbxAgentText(install));
|
|
34932
35225
|
}
|
|
34933
35226
|
async function waitForPrimary() {
|
|
34934
35227
|
for (let i = 0; i < PRIMARY_POLLS; i++) {
|
|
@@ -34956,12 +35249,13 @@ var Boot = class {
|
|
|
34956
35249
|
log(
|
|
34957
35250
|
"Agent sandbox: " + session.project + " | workspace " + workspace + " | agent " + session.harnessName + " | log " + logPath
|
|
34958
35251
|
);
|
|
34959
|
-
if (!
|
|
35252
|
+
if (!fs60.statSync(workspace, { throwIfNoEntry: false })?.isDirectory())
|
|
34960
35253
|
throw new Error("Workspace folder is missing in the sandbox: " + workspace);
|
|
34961
35254
|
mkdirp(toolsDir);
|
|
34962
35255
|
mkdirp(run.root);
|
|
34963
35256
|
this.secrets = takeSecrets(session.launchId);
|
|
34964
35257
|
applyBootEnvironment(this.secrets.harnessEnvironment);
|
|
35258
|
+
prepareGithubFolder(this.secrets.githubToken);
|
|
34965
35259
|
await this.networkAndSessionHost();
|
|
34966
35260
|
await this.hooksAndDesktop();
|
|
34967
35261
|
const { tools, env } = await this.developerTools();
|
|
@@ -35044,6 +35338,11 @@ var Boot = class {
|
|
|
35044
35338
|
async gitIdentity(env) {
|
|
35045
35339
|
step(5, "Git identity");
|
|
35046
35340
|
await soft("Git config", () => setupGitConfig(env));
|
|
35341
|
+
const token = this.secrets.githubToken;
|
|
35342
|
+
if (token) {
|
|
35343
|
+
this.secrets = { ...this.secrets, githubToken: void 0 };
|
|
35344
|
+
await soft("GitHub token", () => loginGithub(token, env));
|
|
35345
|
+
}
|
|
35047
35346
|
}
|
|
35048
35347
|
async claude(tools) {
|
|
35049
35348
|
step(6, "Claude settings, history and claude-mem");
|
|
@@ -35105,7 +35404,7 @@ runBoot().catch((e) => {
|
|
|
35105
35404
|
const message = errMsg(e) + (e instanceof Error && e.stack ? "\n" + e.stack : "");
|
|
35106
35405
|
try {
|
|
35107
35406
|
setSandboxStatus("failed", errMsg(e));
|
|
35108
|
-
|
|
35407
|
+
fs61.writeFileSync(path74.join(logsDir, "guest-error.txt"), message);
|
|
35109
35408
|
} catch {
|
|
35110
35409
|
}
|
|
35111
35410
|
console.error(
|