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
|
@@ -1,12 +1,18 @@
|
|
|
1
1
|
// Caps a process and everything it starts at a share of the PC's CPU (SandboxTools cpu-cap). Windows Sandbox has no
|
|
2
|
-
// CPU setting and gets every processor; a job object with a hard CPU-rate cap holds logon.cmd and all it starts
|
|
2
|
+
// CPU setting and gets every processor; a job object with a hard CPU-rate cap holds logon.cmd and all it starts, and
|
|
3
|
+
// limits them to as many processors as the cap allows, so programs that count processors (cargo, .NET, ninja, nproc)
|
|
4
|
+
// plan for what they may use, as on a PC of that size. C# 5.
|
|
3
5
|
using System;
|
|
4
6
|
using System.ComponentModel;
|
|
5
7
|
using System.Runtime.InteropServices;
|
|
6
8
|
|
|
7
9
|
public static class SandboxCpuCap
|
|
8
10
|
{
|
|
11
|
+
private const int JobObjectBasicLimitInformation = 2;
|
|
9
12
|
private const int JobObjectCpuRateControlInformation = 15;
|
|
13
|
+
private const uint LimitAffinity = 0x00000010;
|
|
14
|
+
/// <summary>Affinity masks hold 64 processors; with more, only the rate cap applies.</summary>
|
|
15
|
+
private const int MaxMaskProcessors = 64;
|
|
10
16
|
private const uint CpuRateEnable = 0x1;
|
|
11
17
|
private const uint CpuRateHardCap = 0x4;
|
|
12
18
|
// What AssignProcessToJobObject needs.
|
|
@@ -23,6 +29,21 @@ public static class SandboxCpuCap
|
|
|
23
29
|
public uint Rate;
|
|
24
30
|
}
|
|
25
31
|
|
|
32
|
+
// JOBOBJECT_BASIC_LIMIT_INFORMATION.
|
|
33
|
+
[StructLayout(LayoutKind.Sequential)]
|
|
34
|
+
private struct BasicLimit
|
|
35
|
+
{
|
|
36
|
+
public long PerProcessUserTimeLimit;
|
|
37
|
+
public long PerJobUserTimeLimit;
|
|
38
|
+
public uint LimitFlags;
|
|
39
|
+
public UIntPtr MinimumWorkingSetSize;
|
|
40
|
+
public UIntPtr MaximumWorkingSetSize;
|
|
41
|
+
public uint ActiveProcessLimit;
|
|
42
|
+
public UIntPtr Affinity;
|
|
43
|
+
public uint PriorityClass;
|
|
44
|
+
public uint SchedulingClass;
|
|
45
|
+
}
|
|
46
|
+
|
|
26
47
|
private const uint SnapshotProcesses = 0x2;
|
|
27
48
|
private static readonly IntPtr InvalidHandle = new IntPtr(-1);
|
|
28
49
|
|
|
@@ -60,6 +81,9 @@ public static class SandboxCpuCap
|
|
|
60
81
|
[DllImport("kernel32.dll", SetLastError = true)]
|
|
61
82
|
public static extern bool SetInformationJobObject(IntPtr job, int infoClass, ref CpuRate info, int length);
|
|
62
83
|
|
|
84
|
+
[DllImport("kernel32.dll", SetLastError = true, EntryPoint = "SetInformationJobObject")]
|
|
85
|
+
public static extern bool SetBasicLimit(IntPtr job, int infoClass, ref BasicLimit info, int length);
|
|
86
|
+
|
|
63
87
|
[DllImport("kernel32.dll", SetLastError = true)]
|
|
64
88
|
public static extern IntPtr OpenProcess(uint access, bool inherit, int pid);
|
|
65
89
|
|
|
@@ -98,6 +122,30 @@ public static class SandboxCpuCap
|
|
|
98
122
|
throw new InvalidOperationException("the parent process was not found.");
|
|
99
123
|
}
|
|
100
124
|
|
|
125
|
+
/// <summary>
|
|
126
|
+
/// How many processors a cap of percent % allows (at least 2), the same count the daemon gives NUMBER_OF_PROCESSORS.
|
|
127
|
+
/// </summary>
|
|
128
|
+
public static int UsableProcessors(int processors, int percent)
|
|
129
|
+
{
|
|
130
|
+
return Math.Max(2, Math.Min(processors, processors * percent / 100));
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/// <summary>The job's processes run on the first UsableProcessors processors; nothing changes when that is all.</summary>
|
|
134
|
+
private static void LimitProcessors(IntPtr job, int percent)
|
|
135
|
+
{
|
|
136
|
+
int processors = Environment.ProcessorCount;
|
|
137
|
+
int usable = UsableProcessors(processors, percent);
|
|
138
|
+
if (processors > MaxMaskProcessors || usable >= processors)
|
|
139
|
+
{
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
BasicLimit limit = new BasicLimit();
|
|
143
|
+
limit.LimitFlags = LimitAffinity;
|
|
144
|
+
limit.Affinity = new UIntPtr((1UL << usable) - 1);
|
|
145
|
+
// Best effort: without it the rate cap still holds, programs only count more processors than they get.
|
|
146
|
+
NativeMethods.SetBasicLimit(job, JobObjectBasicLimitInformation, ref limit, Marshal.SizeOf(typeof(BasicLimit)));
|
|
147
|
+
}
|
|
148
|
+
|
|
101
149
|
/// <summary>Puts process pid in a new job with a hard cap of percent % of all processors. Throws on failure.</summary>
|
|
102
150
|
public static void Apply(int pid, int percent)
|
|
103
151
|
{
|
|
@@ -113,6 +161,7 @@ public static class SandboxCpuCap
|
|
|
113
161
|
{
|
|
114
162
|
throw new Win32Exception(Marshal.GetLastWin32Error());
|
|
115
163
|
}
|
|
164
|
+
LimitProcessors(job, percent);
|
|
116
165
|
IntPtr process = NativeMethods.OpenProcess(ProcessSetQuota | ProcessTerminate, false, pid);
|
|
117
166
|
if (process == IntPtr.Zero)
|
|
118
167
|
{
|
|
@@ -61,7 +61,7 @@ static class Program
|
|
|
61
61
|
pid = SandboxCpuCap.ParentProcessId();
|
|
62
62
|
}
|
|
63
63
|
SandboxCpuCap.Apply(pid, percent);
|
|
64
|
-
Log("CPU capped at " + percent + "% of the PC (sandbox.cpuLimit).");
|
|
64
|
+
Log("CPU capped at " + percent + "% of the PC (sandbox.cpuLimit): programs see " + SandboxCpuCap.UsableProcessors(Environment.ProcessorCount, percent) + " of " + Environment.ProcessorCount + " processors.");
|
|
65
65
|
}
|
|
66
66
|
catch (Exception e)
|
|
67
67
|
{
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
#Requires -Version 5.1
|
|
2
|
+
# Windows Sandbox keeps the WMI class Win32_TerminalService but not the provider DLL behind it, so every query of
|
|
3
|
+
# Win32_Service (which includes its subclasses) fails with "Provider load failure". Installers that check a service
|
|
4
|
+
# that way (OpenVPN's MSI does) then fail with 1603. This removes that one class, and only when its provider is not
|
|
5
|
+
# registered: the sandbox is thrown away when it closes, and nothing else is changed. Prints what it did.
|
|
6
|
+
param()
|
|
7
|
+
$ErrorActionPreference = 'Stop'
|
|
8
|
+
|
|
9
|
+
$className = 'Win32_TerminalService'
|
|
10
|
+
$providerName = 'Win32_WIN32_TERMINALSERVICE_Prov'
|
|
11
|
+
|
|
12
|
+
$class = Get-WmiObject -Namespace 'root\cimv2' -List -Class $className -ErrorAction SilentlyContinue
|
|
13
|
+
if (-not $class) {
|
|
14
|
+
Write-Output 'absent'
|
|
15
|
+
exit 0
|
|
16
|
+
}
|
|
17
|
+
$provider = Get-WmiObject -Namespace 'root\cimv2' -Class '__Win32Provider' -Filter ("Name='" + $providerName + "'") -ErrorAction SilentlyContinue
|
|
18
|
+
if ($provider -and $provider.CLSID -match '^\{[0-9A-Fa-f-]{36}\}$') {
|
|
19
|
+
$registered = Test-Path -LiteralPath ('Registry::HKEY_CLASSES_ROOT\CLSID\' + $provider.CLSID + '\InprocServer32')
|
|
20
|
+
if ($registered) {
|
|
21
|
+
Write-Output 'kept'
|
|
22
|
+
exit 0
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
([wmiclass]('root\cimv2:' + $className)).Delete()
|
|
26
|
+
Write-Output 'removed'
|
|
@@ -140,7 +140,7 @@
|
|
|
140
140
|
"maximum": 9007199254740991
|
|
141
141
|
}
|
|
142
142
|
],
|
|
143
|
-
"description": "Sandbox RAM in MB (>= 2048), or \"auto\": free RAM minus reserveHostMb, capped at maxMemoryMb."
|
|
143
|
+
"description": "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."
|
|
144
144
|
},
|
|
145
145
|
"maxMemoryMb": {
|
|
146
146
|
"type": "integer",
|
|
@@ -196,11 +196,11 @@
|
|
|
196
196
|
"maximum": 9007199254740991
|
|
197
197
|
}
|
|
198
198
|
],
|
|
199
|
-
"description": "
|
|
199
|
+
"description": "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."
|
|
200
200
|
},
|
|
201
201
|
"pressureResponse": {
|
|
202
202
|
"type": "boolean",
|
|
203
|
-
"description": "When the sandbox (or this PC) runs low on memory, slow
|
|
203
|
+
"description": "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."
|
|
204
204
|
},
|
|
205
205
|
"vGpu": {
|
|
206
206
|
"type": "boolean",
|
|
@@ -397,6 +397,16 @@
|
|
|
397
397
|
},
|
|
398
398
|
"additionalProperties": false
|
|
399
399
|
},
|
|
400
|
+
"github": {
|
|
401
|
+
"type": "object",
|
|
402
|
+
"properties": {
|
|
403
|
+
"shareToken": {
|
|
404
|
+
"type": "boolean",
|
|
405
|
+
"description": "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."
|
|
406
|
+
}
|
|
407
|
+
},
|
|
408
|
+
"additionalProperties": false
|
|
409
|
+
},
|
|
400
410
|
"provisioning": {
|
|
401
411
|
"type": "object",
|
|
402
412
|
"properties": {
|
|
@@ -625,7 +635,7 @@
|
|
|
625
635
|
"maximum": 32
|
|
626
636
|
}
|
|
627
637
|
],
|
|
628
|
-
"description": "GNU host: how many programs may link at the same time in the whole sandbox (other links wait). \"auto\" = one per
|
|
638
|
+
"description": "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)."
|
|
629
639
|
}
|
|
630
640
|
},
|
|
631
641
|
"additionalProperties": false
|
|
@@ -901,7 +911,7 @@
|
|
|
901
911
|
"const": "auto"
|
|
902
912
|
}
|
|
903
913
|
],
|
|
904
|
-
"description": "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."
|
|
914
|
+
"description": "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."
|
|
905
915
|
},
|
|
906
916
|
"zstd": {
|
|
907
917
|
"anyOf": [
|
|
@@ -1227,6 +1237,10 @@
|
|
|
1227
1237
|
"autoHide": {
|
|
1228
1238
|
"type": "boolean",
|
|
1229
1239
|
"description": "Hide the Windows Sandbox window whenever this terminal attaches; it keeps running (sandbox show brings it back)."
|
|
1240
|
+
},
|
|
1241
|
+
"confirmCtrlC": {
|
|
1242
|
+
"type": "boolean",
|
|
1243
|
+
"description": "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."
|
|
1230
1244
|
}
|
|
1231
1245
|
},
|
|
1232
1246
|
"additionalProperties": false
|
|
@@ -105,7 +105,7 @@
|
|
|
105
105
|
"maximum": 9007199254740991
|
|
106
106
|
}
|
|
107
107
|
],
|
|
108
|
-
"description": "Sandbox RAM in MB (>= 2048), or \"auto\": free RAM minus reserveHostMb, capped at maxMemoryMb."
|
|
108
|
+
"description": "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."
|
|
109
109
|
},
|
|
110
110
|
"maxMemoryMb": {
|
|
111
111
|
"type": "integer",
|
|
@@ -411,7 +411,7 @@
|
|
|
411
411
|
"maximum": 32
|
|
412
412
|
}
|
|
413
413
|
],
|
|
414
|
-
"description": "GNU host: how many programs may link at the same time in the whole sandbox (other links wait). \"auto\" = one per
|
|
414
|
+
"description": "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)."
|
|
415
415
|
}
|
|
416
416
|
},
|
|
417
417
|
"additionalProperties": false
|
|
@@ -687,7 +687,7 @@
|
|
|
687
687
|
"const": "auto"
|
|
688
688
|
}
|
|
689
689
|
],
|
|
690
|
-
"description": "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."
|
|
690
|
+
"description": "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."
|
|
691
691
|
},
|
|
692
692
|
"zstd": {
|
|
693
693
|
"anyOf": [
|
|
@@ -1011,6 +1011,10 @@
|
|
|
1011
1011
|
"autoHide": {
|
|
1012
1012
|
"type": "boolean",
|
|
1013
1013
|
"description": "Hide the Windows Sandbox window whenever this terminal attaches; it keeps running (sandbox show brings it back)."
|
|
1014
|
+
},
|
|
1015
|
+
"confirmCtrlC": {
|
|
1016
|
+
"type": "boolean",
|
|
1017
|
+
"description": "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."
|
|
1014
1018
|
}
|
|
1015
1019
|
},
|
|
1016
1020
|
"additionalProperties": false
|
|
@@ -1,96 +0,0 @@
|
|
|
1
|
-
// `account list | save | use | default | rename | remove [--agent <name>]`
|
|
2
|
-
import { askChoice, askName, askRequired } from '../../core/prompt.js';
|
|
3
|
-
import { fail, safeText } from '../../core/util/index.js';
|
|
4
|
-
import { nextStep, printJson, table } from '../output/index.js';
|
|
5
|
-
import { AccountsService } from '../services/index.js';
|
|
6
|
-
function label(a) {
|
|
7
|
-
return '"' + a.name + '"' + (a.email ? ' (' + a.email + ')' : '');
|
|
8
|
-
}
|
|
9
|
-
function list(ctx, accounts, agent) {
|
|
10
|
-
const rows = accounts.list(agent);
|
|
11
|
-
if (printJson(ctx, rows))
|
|
12
|
-
return 0;
|
|
13
|
-
if (rows.length === 0) {
|
|
14
|
-
console.log(agent === 'claude'
|
|
15
|
-
? "No saved accounts. Sign in inside the sandbox, then: sandbox account save <name> (or --from-host to save this PC's login)"
|
|
16
|
-
: 'No saved ' +
|
|
17
|
-
agent +
|
|
18
|
-
' accounts. Sign in inside the sandbox, then: sandbox account save <name> --agent ' +
|
|
19
|
-
agent);
|
|
20
|
-
return 0;
|
|
21
|
-
}
|
|
22
|
-
table([
|
|
23
|
-
['', 'NAME', 'EMAIL', 'SAVED'],
|
|
24
|
-
...rows.map((a) => [
|
|
25
|
-
(a.isActive ? '*' : ' ') + (a.isDefault ? 'D' : ' '),
|
|
26
|
-
a.name,
|
|
27
|
-
a.email ?? '-',
|
|
28
|
-
a.savedAt.slice(0, 16).replace('T', ' '),
|
|
29
|
-
]),
|
|
30
|
-
]);
|
|
31
|
-
console.log('\n* = active in the sandbox D = default for new launches');
|
|
32
|
-
return 0;
|
|
33
|
-
}
|
|
34
|
-
async function use(ctx, accounts, name, agent) {
|
|
35
|
-
const used = accounts.activate(name, agent);
|
|
36
|
-
console.log('Sandbox now uses ' + label(used) + '.');
|
|
37
|
-
if (used.note)
|
|
38
|
-
console.log(safeText(used.note));
|
|
39
|
-
if (accounts.hasRunningSessions(agent) && !ctx.options.noRestart)
|
|
40
|
-
console.log(safeText(await accounts.restart(agent)) + ' with --continue; the conversation carries on under the new account.');
|
|
41
|
-
return 0;
|
|
42
|
-
}
|
|
43
|
-
/** The account the command is about: the one typed, or one picked from the saved accounts. */
|
|
44
|
-
async function accountName(accounts, action, agent, given) {
|
|
45
|
-
if (given)
|
|
46
|
-
return given;
|
|
47
|
-
const usage = 'Usage: sandbox account ' + action + ' <name>';
|
|
48
|
-
if (action === 'save')
|
|
49
|
-
return askName('Name for this login:', usage, (v) => v.length > 0 || 'Type a name.');
|
|
50
|
-
const rows = accounts.list(agent);
|
|
51
|
-
if (!rows.length)
|
|
52
|
-
fail('No saved accounts.', 'Sign in inside the sandbox, then run: sandbox account save <name>');
|
|
53
|
-
return askChoice('Which account?', rows.map((a) => ({ name: safeText(label(a)), value: a.name })), usage);
|
|
54
|
-
}
|
|
55
|
-
async function remove(ctx, accounts, name, agent) {
|
|
56
|
-
const sure = ctx.options.yes ||
|
|
57
|
-
(await askRequired('Remove the saved account "' + name + '"? Its login cannot be recovered; you would sign in again.', 'Add --yes to remove it without asking.'));
|
|
58
|
-
if (!sure) {
|
|
59
|
-
console.log('Nothing removed.');
|
|
60
|
-
return 1;
|
|
61
|
-
}
|
|
62
|
-
accounts.remove(name, agent);
|
|
63
|
-
console.log('Removed account ' + name + '.');
|
|
64
|
-
return 0;
|
|
65
|
-
}
|
|
66
|
-
export async function account(ctx) {
|
|
67
|
-
const [action = 'list', given] = ctx.options.positionals;
|
|
68
|
-
const agent = ctx.options.accountAgent ?? 'claude';
|
|
69
|
-
const accounts = new AccountsService(ctx);
|
|
70
|
-
if (action === 'list')
|
|
71
|
-
return list(ctx, accounts, agent);
|
|
72
|
-
const name = await accountName(accounts, action, agent, given);
|
|
73
|
-
switch (action) {
|
|
74
|
-
case 'save':
|
|
75
|
-
console.log('Saved account ' + label(accounts.save(name, Boolean(ctx.options.fromHost), agent)) + '.');
|
|
76
|
-
nextStep('sandbox account use ' + name + ' (the sandbox uses it)');
|
|
77
|
-
return 0;
|
|
78
|
-
case 'use':
|
|
79
|
-
return use(ctx, accounts, name, agent);
|
|
80
|
-
case 'default':
|
|
81
|
-
accounts.setDefault(name, agent);
|
|
82
|
-
console.log('Default account: ' + name);
|
|
83
|
-
return 0;
|
|
84
|
-
case 'rename': {
|
|
85
|
-
const to = ctx.options.accountTo ??
|
|
86
|
-
(await askName('New name for "' + name + '":', 'Usage: sandbox account rename <name> --to <new-name>', (v) => v.length > 0 || 'Type a name.'));
|
|
87
|
-
accounts.rename(name, to, agent);
|
|
88
|
-
console.log('Renamed account ' + name + ' to ' + to + '.');
|
|
89
|
-
return 0;
|
|
90
|
-
}
|
|
91
|
-
case 'remove':
|
|
92
|
-
return remove(ctx, accounts, name, agent);
|
|
93
|
-
default:
|
|
94
|
-
return fail('Unknown account action "' + action + '".', 'Use one of: sandbox account list | save <name> | use <name> | default <name> | rename <name> --to <new-name> | remove <name>');
|
|
95
|
-
}
|
|
96
|
-
}
|
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
// `sandbox data clean`: asks, then removes the folders the targets name (DataService does the work).
|
|
2
|
-
import { humanBytes } from '../../../core/disk.js';
|
|
3
|
-
import { askChoices, askRequired, askTyped } from '../../../core/prompt.js';
|
|
4
|
-
import { fail } from '../../../core/util/index.js';
|
|
5
|
-
import { nextStep, table, working } from '../../output/index.js';
|
|
6
|
-
import { DataService } from '../../services/index.js';
|
|
7
|
-
import { cleanTargetOf } from './collect.js';
|
|
8
|
-
export { resolveCleanTargets } from '../../services/index.js';
|
|
9
|
-
/** No target typed: a list of what can be cleaned, with sizes, to tick from (a terminal is needed). */
|
|
10
|
-
async function pickTargets(service) {
|
|
11
|
-
const fix = 'Name them: sandbox data clean logs tools/go (what exists: sandbox data)';
|
|
12
|
-
if (!process.stdin.isTTY)
|
|
13
|
-
fail('Which data should be cleaned?', fix);
|
|
14
|
-
const rows = await working('Measuring the saved data (big folders take a moment)', () => service.entries());
|
|
15
|
-
const choices = rows.flatMap((e) => {
|
|
16
|
-
const target = cleanTargetOf(e);
|
|
17
|
-
return target ? [{ name: target.padEnd(28) + humanBytes(e.bytes), value: target }] : [];
|
|
18
|
-
});
|
|
19
|
-
if (!choices.length)
|
|
20
|
-
return [];
|
|
21
|
-
return askChoices('What do you want to delete? (space ticks, enter confirms)', choices, fix);
|
|
22
|
-
}
|
|
23
|
-
export async function dataClean(ctx) {
|
|
24
|
-
const service = new DataService(ctx);
|
|
25
|
-
const typed = ctx.options.positionals.slice(1);
|
|
26
|
-
const inputs = typed.length ? typed : await pickTargets(service);
|
|
27
|
-
if (!inputs.length) {
|
|
28
|
-
console.log('Nothing chosen, nothing removed.');
|
|
29
|
-
return 0;
|
|
30
|
-
}
|
|
31
|
-
const { targets, present: sized, totalBytes: total } = service.plan(inputs);
|
|
32
|
-
if (!sized.length) {
|
|
33
|
-
console.log('Nothing to remove: ' + targets.map((t) => t.target).join(', ') + ' do(es) not exist.');
|
|
34
|
-
return 0;
|
|
35
|
-
}
|
|
36
|
-
table(sized.map((t) => [' ' + t.target, humanBytes(t.bytes), t.path]));
|
|
37
|
-
for (const t of sized)
|
|
38
|
-
if (t.warning)
|
|
39
|
-
console.log('Warning: ' + t.target + ' ' + t.warning + '.');
|
|
40
|
-
const yes = Boolean(ctx.options.yes);
|
|
41
|
-
if (!yes) {
|
|
42
|
-
const ok = sized.some((t) => t.target === 'all')
|
|
43
|
-
? await askTyped('This cannot be undone; the next sandbox starts from scratch and reinstalls everything.', 'all')
|
|
44
|
-
: await askRequired('Delete ' + sized.map((t) => t.target).join(', ') + ' (' + humanBytes(total) + ')? This cannot be undone.', 'Add --yes to delete without asking.');
|
|
45
|
-
if (!ok) {
|
|
46
|
-
console.log('Nothing removed.');
|
|
47
|
-
return 1;
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
const outcome = service.clean({ targets, present: sized, totalBytes: total });
|
|
51
|
-
if (outcome.failed.length)
|
|
52
|
-
fail('Could not remove everything: ' + outcome.failed.join('; '), 'Close programs using those folders and run the same command again.');
|
|
53
|
-
console.log('Removed ' +
|
|
54
|
-
sized.map((t) => t.target).join(', ') +
|
|
55
|
-
' and freed ' +
|
|
56
|
-
humanBytes(outcome.freedBytes) +
|
|
57
|
-
(outcome.touchedData ? '; the next sandbox reinstalls what it needs.' : '.'));
|
|
58
|
-
nextStep('sandbox data (see what is left)');
|
|
59
|
-
return 0;
|
|
60
|
-
}
|
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
// `sandbox data`: what persists between sandboxes (toolchains, databases, agent state, logs, host storage) and
|
|
2
|
-
// removing chosen parts of it. Everything under the data folder is sandbox-writable: sizes and deletes never follow
|
|
3
|
-
// links, and targets resolve strictly inside the data folder.
|
|
4
|
-
import _ from 'lodash';
|
|
5
|
-
import { humanBytes } from '../../../core/disk.js';
|
|
6
|
-
import { fail } from '../../../core/util/index.js';
|
|
7
|
-
import { printJson, table, working } from '../../output/index.js';
|
|
8
|
-
import { DataService } from '../../services/index.js';
|
|
9
|
-
import { dataClean } from './clean.js';
|
|
10
|
-
const AREA_LABEL = {
|
|
11
|
-
tools: 'Toolchains',
|
|
12
|
-
databases: 'Databases',
|
|
13
|
-
state: 'Agent state',
|
|
14
|
-
logs: 'Logs',
|
|
15
|
-
data: 'Other',
|
|
16
|
-
host: 'On this PC',
|
|
17
|
-
};
|
|
18
|
-
export async function dataInfo(ctx) {
|
|
19
|
-
const report = await working('Measuring the saved data (big folders take a moment)', () => new DataService(ctx).report(), !ctx.options.json);
|
|
20
|
-
const { entries, disks, totalBytes: total } = report;
|
|
21
|
-
if (printJson(ctx, { dataPath: ctx.dataPath, storageRoot: ctx.storageRoot, totalBytes: total, entries, disks }))
|
|
22
|
-
return 0;
|
|
23
|
-
console.log('Disks\n');
|
|
24
|
-
table([
|
|
25
|
-
['DRIVE', 'USED', 'FREE', 'SIZE', ''],
|
|
26
|
-
...disks.map((d) => [
|
|
27
|
-
d.drive,
|
|
28
|
-
humanBytes(d.usedBytes) + ' (' + Math.round((d.usedBytes / d.totalBytes) * 100) + '%)',
|
|
29
|
-
humanBytes(d.freeBytes),
|
|
30
|
-
humanBytes(d.totalBytes),
|
|
31
|
-
d.holdsStorage ? '<- sandbox storage (' + humanBytes(total) + ' of it)' : '',
|
|
32
|
-
]),
|
|
33
|
-
]);
|
|
34
|
-
console.log('');
|
|
35
|
-
console.log('Persistent data for the sandbox: ' + ctx.dataPath + ' (C:\\AgentData inside)\n');
|
|
36
|
-
if (!entries.length) {
|
|
37
|
-
console.log('Nothing stored yet. Toolchains, databases and agent logins appear here after the first start.');
|
|
38
|
-
return 0;
|
|
39
|
-
}
|
|
40
|
-
const rows = _.flatMap(_.groupBy(entries, 'area'), (group, area) => [
|
|
41
|
-
[AREA_LABEL[area], humanBytes(_.sumBy(group, 'bytes')), ''],
|
|
42
|
-
...group.map((e) => [' ' + e.name, humanBytes(e.bytes), e.path]),
|
|
43
|
-
]);
|
|
44
|
-
table([...rows, ['', '', ''], ['Total', humanBytes(total), '']]);
|
|
45
|
-
console.log('\nFree space with: sandbox data clean <target...> (e.g. tools/go, databases/postgres-18, logs, launches)');
|
|
46
|
-
return 0;
|
|
47
|
-
}
|
|
48
|
-
/** `sandbox data [info|clean] [targets...]`. */
|
|
49
|
-
export function data(ctx) {
|
|
50
|
-
const [action = 'info'] = ctx.options.positionals;
|
|
51
|
-
switch (action) {
|
|
52
|
-
case 'info':
|
|
53
|
-
case 'show':
|
|
54
|
-
case 'list':
|
|
55
|
-
return dataInfo(ctx);
|
|
56
|
-
case 'clean':
|
|
57
|
-
case 'remove':
|
|
58
|
-
return dataClean(ctx);
|
|
59
|
-
default:
|
|
60
|
-
return fail('Unknown data action "' + action + '".', 'Use: sandbox data (what is stored) or sandbox data clean <target...>');
|
|
61
|
-
}
|
|
62
|
-
}
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
// `sandbox clean`: old launch folders, logs and leftovers. Shows what and how much, then asks (--yes skips).
|
|
2
|
-
import _ from 'lodash';
|
|
3
|
-
import { askRequired } from '../../../core/prompt.js';
|
|
4
|
-
import { describePrune, pruneStorage } from '../../../host/storage/index.js';
|
|
5
|
-
import { isSandboxRunning } from '../../../host/sandbox/index.js';
|
|
6
|
-
import { RunDir } from '../../../shared/channel/index.js';
|
|
7
|
-
import { nextStep } from '../../output/index.js';
|
|
8
|
-
export async function clean(ctx) {
|
|
9
|
-
const running = isSandboxRunning() ? new RunDir(ctx.dataPath).readSandboxStatus()?.launchId : undefined;
|
|
10
|
-
const options = { launchDays: ctx.options.days, keep: _.compact([running]) };
|
|
11
|
-
const found = pruneStorage(ctx.storageRoot, { ...options, dryRun: true });
|
|
12
|
-
if (found.launches + found.logs + found.leftovers === 0) {
|
|
13
|
-
console.log('Nothing to clean.');
|
|
14
|
-
return 0;
|
|
15
|
-
}
|
|
16
|
-
console.log('Can be removed: ' + describePrune(found).replace(' removed', '') + '.');
|
|
17
|
-
if (!ctx.options.yes && !(await askRequired('Delete them?', 'Add --yes to delete without asking.'))) {
|
|
18
|
-
console.log('Nothing removed.');
|
|
19
|
-
return 1;
|
|
20
|
-
}
|
|
21
|
-
console.log('Removed ' + describePrune(pruneStorage(ctx.storageRoot, options)).replace(' removed', '') + '.');
|
|
22
|
-
nextStep('sandbox data (see what else is saved, and clean it)');
|
|
23
|
-
return 0;
|
|
24
|
-
}
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import { type ImportPlan } from '../../menu/settings/index.js';
|
|
2
|
-
import type { Context } from '../context.js';
|
|
3
|
-
/** The file `config export` writes when none is named. */
|
|
4
|
-
export declare const DEFAULT_EXPORT = "sandbox-settings.json";
|
|
5
|
-
/** Writes the settings that differ from the defaults (no secrets, no storage, no paths unless asked) to `file`. */
|
|
6
|
-
export declare function writeExport(ctx: Context, file: string, withPaths: boolean, overwrite: boolean): string[];
|
|
7
|
-
/** Reads a shared file and plans the import. Fails with the reason when it cannot be read. */
|
|
8
|
-
export declare function readImport(ctx: Context, file: string): ImportPlan;
|
|
9
|
-
/** Writes the planned changes to your settings file (comments stay); returns how many settings changed. */
|
|
10
|
-
export declare function applyImport(ctx: Context, plan: ImportPlan): number;
|
|
11
|
-
export declare function exportCommand(ctx: Context, file: string | undefined): number;
|
|
12
|
-
export declare function importCommand(ctx: Context, file: string | undefined): Promise<number>;
|
|
@@ -1,80 +0,0 @@
|
|
|
1
|
-
// `sandbox config export` and `import`: your settings as a shareable .json, and a shared file read back in.
|
|
2
|
-
import fs from 'node:fs';
|
|
3
|
-
import path from 'node:path';
|
|
4
|
-
import { askRequired } from '../../../core/prompt.js';
|
|
5
|
-
import { fail, safeText, writeJson } from '../../../core/util/index.js';
|
|
6
|
-
import { c } from '../../output/index.js';
|
|
7
|
-
import { ConfigFile } from '../../../app/features/settings/index.js';
|
|
8
|
-
import { diffText, exportSettings, planImport, skippedLine } from '../../menu/settings/index.js';
|
|
9
|
-
/** The file `config export` writes when none is named. */
|
|
10
|
-
export const DEFAULT_EXPORT = 'sandbox-settings.json';
|
|
11
|
-
/** A shared file is a few KB; anything bigger is not one. */
|
|
12
|
-
const MAX_BYTES = 1024 * 1024;
|
|
13
|
-
/** Writes the settings that differ from the defaults (no secrets, no storage, no paths unless asked) to `file`. */
|
|
14
|
-
export function writeExport(ctx, file, withPaths, overwrite) {
|
|
15
|
-
const target = path.resolve(file);
|
|
16
|
-
if (!overwrite && fs.existsSync(target))
|
|
17
|
-
fail(target + ' exists already.', 'Pick another name, or delete it first.');
|
|
18
|
-
const { data, skipped } = exportSettings(ctx.loaded.config, withPaths);
|
|
19
|
-
fs.mkdirSync(path.dirname(target), { recursive: true });
|
|
20
|
-
writeJson(target, data);
|
|
21
|
-
return skipped.map(skippedLine);
|
|
22
|
-
}
|
|
23
|
-
/** Reads a shared file and plans the import. Fails with the reason when it cannot be read. */
|
|
24
|
-
export function readImport(ctx, file) {
|
|
25
|
-
const source = path.resolve(file);
|
|
26
|
-
if (!fs.existsSync(source))
|
|
27
|
-
fail('There is no file ' + source + '.', 'Give the path of a file made by sandbox config export.');
|
|
28
|
-
if (fs.statSync(source).size > MAX_BYTES)
|
|
29
|
-
fail(source + ' is too big to be a settings file.');
|
|
30
|
-
const plan = planImport(fs.readFileSync(source, 'utf8'), ctx.loaded.config);
|
|
31
|
-
if (plan.problems.length)
|
|
32
|
-
fail(source + ' is not valid settings:\n ' + plan.problems.map(safeText).join('\n '), 'Nothing was changed. Fix the file, or export a new one with: sandbox config export');
|
|
33
|
-
return plan;
|
|
34
|
-
}
|
|
35
|
-
/** Writes the planned changes to your settings file (comments stay); returns how many settings changed. */
|
|
36
|
-
export function applyImport(ctx, plan) {
|
|
37
|
-
const outcome = ConfigFile.user(ctx.loaded.configPath).setMany(plan.changes);
|
|
38
|
-
if (typeof outcome === 'object')
|
|
39
|
-
fail('Could not import: ' + outcome.problems.join('; '), 'Nothing was written. Your settings are unchanged.');
|
|
40
|
-
return plan.changes.length;
|
|
41
|
-
}
|
|
42
|
-
export function exportCommand(ctx, file) {
|
|
43
|
-
const target = file ?? DEFAULT_EXPORT;
|
|
44
|
-
const skipped = writeExport(ctx, target, ctx.options.withPaths, false);
|
|
45
|
-
console.log('Wrote ' + path.resolve(target) + ' (only what differs from the defaults).');
|
|
46
|
-
if (skipped.length) {
|
|
47
|
-
console.log('Left out:');
|
|
48
|
-
for (const line of skipped)
|
|
49
|
-
console.log(' ' + line);
|
|
50
|
-
}
|
|
51
|
-
if (!ctx.options.withPaths && skipped.some((s) => s.includes('folder or file')))
|
|
52
|
-
console.log("Keep this PC's folders and files in the file with --with-paths.");
|
|
53
|
-
return 0;
|
|
54
|
-
}
|
|
55
|
-
export async function importCommand(ctx, file) {
|
|
56
|
-
if (!file)
|
|
57
|
-
fail('Which file?', 'Usage: sandbox config import <file>');
|
|
58
|
-
const plan = readImport(ctx, file);
|
|
59
|
-
if (plan.skipped.length) {
|
|
60
|
-
console.log('Not imported (never taken from a file):');
|
|
61
|
-
for (const s of plan.skipped)
|
|
62
|
-
console.log(' ' + safeText(skippedLine(s)));
|
|
63
|
-
}
|
|
64
|
-
if (!plan.changes.length) {
|
|
65
|
-
console.log('Nothing to change: your settings already match the file.');
|
|
66
|
-
return 0;
|
|
67
|
-
}
|
|
68
|
-
console.log('This would change ' + plan.changes.length + ' setting' + (plan.changes.length === 1 ? '' : 's') + ':');
|
|
69
|
-
for (const line of diffText(plan.lines))
|
|
70
|
-
console.log(' ' + safeText(line));
|
|
71
|
-
const yes = ctx.options.yes ||
|
|
72
|
-
(await askRequired('Change your settings like this?', 'Add --yes to change them without asking.'));
|
|
73
|
-
if (!yes) {
|
|
74
|
-
console.log('Nothing was changed.');
|
|
75
|
-
return 0;
|
|
76
|
-
}
|
|
77
|
-
const n = applyImport(ctx, plan);
|
|
78
|
-
console.log(c.green('Imported ' + n + ' setting' + (n === 1 ? '' : 's') + '.') + ' New sandboxes use them.');
|
|
79
|
-
return 0;
|
|
80
|
-
}
|