windows-development-sandbox 1.9.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 +7 -2
- 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 +23 -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 -88
- package/dist/cli/commands/web.d.ts +7 -1
- package/dist/cli/commands/web.js +45 -71
- 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 +3 -2
- package/dist/core/schema/config.d.ts +6 -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/schema/vpn.js +1 -1
- package/dist/core/schema/web.d.ts +1 -0
- package/dist/core/schema/web.js +4 -1
- package/dist/core/types.d.ts +6 -3
- package/dist/guest/boot/boot.js +11 -1
- 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 +53 -15
- package/dist/guest/governor/decide.js +155 -72
- package/dist/guest/governor/governor.d.ts +2 -35
- package/dist/guest/governor/governor.js +35 -99
- package/dist/guest/governor/index.d.ts +1 -0
- package/dist/guest/governor/index.js +1 -0
- package/dist/guest/network/firewall.d.ts +3 -0
- package/dist/guest/network/firewall.js +65 -23
- package/dist/guest/runtime/process.js +53 -5
- package/dist/guest/sessions/viewer.js +5 -1
- package/dist/guest/setup/claude-mem.js +12 -4
- 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 +40 -4
- 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/host-memory.d.ts +1 -0
- package/dist/host/life/host-memory.js +4 -1
- package/dist/host/life/watchdog.d.ts +11 -0
- package/dist/host/life/watchdog.js +36 -4
- 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 +44 -16
- package/dist/runtime/daemon.js +1154 -857
- package/dist/runtime/db.js +44 -16
- package/dist/runtime/main.js +532 -115
- package/dist/runtime/netproxy.js +34 -9
- package/dist/runtime/view.js +499 -149
- 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/guest-boot.test.js +47 -1
- package/dist/selftest/hcs.test.js +105 -8
- package/dist/selftest/health.test.js +71 -0
- package/dist/selftest/heavy-load.test.js +152 -66
- 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/network.test.js +20 -1
- 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 +5 -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/io/copy-tree.d.ts +7 -0
- package/dist/shared/io/copy-tree.js +45 -0
- package/dist/shared/io/index.d.ts +2 -0
- package/dist/shared/io/index.js +2 -0
- package/dist/shared/io/robocopy-result.d.ts +6 -0
- package/dist/shared/io/robocopy-result.js +23 -0
- package/dist/shared/memory/policy.d.ts +38 -12
- package/dist/shared/memory/policy.js +58 -19
- package/dist/shared/network/firewall-rules.d.ts +8 -0
- package/dist/shared/network/firewall-rules.js +28 -0
- 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/native/csharp/HostTools/MemoryStatus.cs +128 -107
- package/native/scripts/memory-status.ps1 +10 -2
- package/package.json +10 -3
- package/sandbox/csharp/MemGov.cs +668 -398
- 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/new-shortcuts.ps1 +3 -1
- package/sandbox/scripts/repair-wmi-services.ps1 +26 -0
- package/schemas/config.schema.json +25 -7
- 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
|
@@ -432,7 +432,17 @@ sealed class ClientHub
|
|
|
432
432
|
clients.Add(client);
|
|
433
433
|
}
|
|
434
434
|
}
|
|
435
|
-
|
|
435
|
+
// Passed through, a size change makes the program redraw for everyone (a second copy of the screen in some),
|
|
436
|
+
// so a viewer that only looks leaves the size to the one in use; it takes over when it types or is resized.
|
|
437
|
+
bool owned;
|
|
438
|
+
lock (gate)
|
|
439
|
+
{
|
|
440
|
+
owned = sizeOwner != null;
|
|
441
|
+
}
|
|
442
|
+
if (!passthrough || !owned)
|
|
443
|
+
{
|
|
444
|
+
TakeOwnership(client);
|
|
445
|
+
}
|
|
436
446
|
return true;
|
|
437
447
|
}
|
|
438
448
|
|
|
@@ -781,9 +791,11 @@ sealed class ClientHub
|
|
|
781
791
|
return;
|
|
782
792
|
}
|
|
783
793
|
PseudoConsole current;
|
|
794
|
+
bool same;
|
|
784
795
|
lock (gate)
|
|
785
796
|
{
|
|
786
797
|
current = console;
|
|
798
|
+
same = cols == width && rows == height;
|
|
787
799
|
cols = width;
|
|
788
800
|
rows = height;
|
|
789
801
|
}
|
|
@@ -791,7 +803,18 @@ sealed class ClientHub
|
|
|
791
803
|
{
|
|
792
804
|
return;
|
|
793
805
|
}
|
|
794
|
-
|
|
806
|
+
if (Native.ConsoleKind.StartsWith("conpty"))
|
|
807
|
+
{
|
|
808
|
+
// Passed through: nothing repaints, the program redraws itself on every resize. Programs like Claude Code
|
|
809
|
+
// leave a second copy of their screen behind when they do, so resize only when the size really changes.
|
|
810
|
+
if (!same)
|
|
811
|
+
{
|
|
812
|
+
current.Resize(width, height);
|
|
813
|
+
}
|
|
814
|
+
return;
|
|
815
|
+
}
|
|
816
|
+
// Windows' own ConPTY repaints everything on a size change; resizing by one row first forces that even for the
|
|
817
|
+
// same size.
|
|
795
818
|
current.Resize(width, (short)(height - 1));
|
|
796
819
|
current.Resize(width, height);
|
|
797
820
|
}
|
|
@@ -1090,6 +1113,10 @@ static class Native
|
|
|
1090
1113
|
private const string AgentJobName = "Local\\AgentSandboxAgentsJob";
|
|
1091
1114
|
private const int JobObjectExtendedLimitInformation = 9;
|
|
1092
1115
|
private const uint JobObjectLimitJobMemory = 0x00000200;
|
|
1116
|
+
private const int ErrorAlreadyExists = 183;
|
|
1117
|
+
/// <summary>The backstop's headroom for "auto": this much of the commit limit, at least MinHeadroomMb.</summary>
|
|
1118
|
+
private const int HeadroomPercent = 3;
|
|
1119
|
+
private const long MinHeadroomMb = 1536;
|
|
1093
1120
|
private const long BytesPerMb = 1024L * 1024L;
|
|
1094
1121
|
private const int UseStdHandles = 0x00000100;
|
|
1095
1122
|
private static readonly IntPtr PseudoConsoleAttribute = (IntPtr)0x00020016;
|
|
@@ -1157,6 +1184,21 @@ static class Native
|
|
|
1157
1184
|
public ulong OtherTransferCount;
|
|
1158
1185
|
}
|
|
1159
1186
|
|
|
1187
|
+
// MEMORYSTATUSEX: ullTotalPageFile is the commit limit (RAM plus paging files).
|
|
1188
|
+
[StructLayout(LayoutKind.Sequential)]
|
|
1189
|
+
private struct MemoryStatus
|
|
1190
|
+
{
|
|
1191
|
+
public uint Length;
|
|
1192
|
+
public uint MemoryLoad;
|
|
1193
|
+
public ulong TotalPhys;
|
|
1194
|
+
public ulong AvailPhys;
|
|
1195
|
+
public ulong TotalPageFile;
|
|
1196
|
+
public ulong AvailPageFile;
|
|
1197
|
+
public ulong TotalVirtual;
|
|
1198
|
+
public ulong AvailVirtual;
|
|
1199
|
+
public ulong AvailExtendedVirtual;
|
|
1200
|
+
}
|
|
1201
|
+
|
|
1160
1202
|
[StructLayout(LayoutKind.Sequential)]
|
|
1161
1203
|
private struct JobExtendedLimit
|
|
1162
1204
|
{
|
|
@@ -1228,6 +1270,9 @@ static class Native
|
|
|
1228
1270
|
[DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
|
|
1229
1271
|
public static extern IntPtr CreateJobObjectW(IntPtr attributes, string name);
|
|
1230
1272
|
|
|
1273
|
+
[DllImport("kernel32.dll", SetLastError = true)]
|
|
1274
|
+
public static extern bool GlobalMemoryStatusEx(ref MemoryStatus status);
|
|
1275
|
+
|
|
1231
1276
|
[DllImport("kernel32.dll", SetLastError = true)]
|
|
1232
1277
|
public static extern bool SetInformationJobObject(IntPtr job, int infoClass, ref JobExtendedLimit info, int length);
|
|
1233
1278
|
|
|
@@ -1300,10 +1345,12 @@ static class Native
|
|
|
1300
1345
|
private static bool agentJobTried;
|
|
1301
1346
|
|
|
1302
1347
|
/// <summary>
|
|
1303
|
-
/// The shared job of everything the agents start
|
|
1304
|
-
///
|
|
1305
|
-
///
|
|
1306
|
-
///
|
|
1348
|
+
/// The shared job of everything the agents start (the governor reads it to slow builds down). Its only limit is a
|
|
1349
|
+
/// last-resort backstop: the sandbox's commit limit minus a small headroom (PTYHOST_BACKSTOP_MB: "auto", a number
|
|
1350
|
+
/// of MB, or "none"). The job's committed memory is part of the whole sandbox's, so it can reach the backstop only
|
|
1351
|
+
/// when Windows inside the sandbox is about to refuse memory to everyone; then a build is refused instead of
|
|
1352
|
+
/// Windows' own processes. Only the ptyhost that creates the job sets it: one that joins it never changes it.
|
|
1353
|
+
/// ptyhost itself is never in it; the handle stays open for ptyhost's whole life.
|
|
1307
1354
|
/// </summary>
|
|
1308
1355
|
private static IntPtr AgentJob(Log log)
|
|
1309
1356
|
{
|
|
@@ -1312,31 +1359,73 @@ static class Native
|
|
|
1312
1359
|
return agentJob;
|
|
1313
1360
|
}
|
|
1314
1361
|
agentJobTried = true;
|
|
1315
|
-
|
|
1316
|
-
if (
|
|
1362
|
+
string setting = Environment.GetEnvironmentVariable("PTYHOST_BACKSTOP_MB");
|
|
1363
|
+
if (string.IsNullOrEmpty(setting))
|
|
1317
1364
|
{
|
|
1318
1365
|
return IntPtr.Zero;
|
|
1319
1366
|
}
|
|
1320
|
-
|
|
1367
|
+
// The self-test uses a job of its own (a name in the same family), never the agents' real one.
|
|
1368
|
+
string name = Environment.GetEnvironmentVariable("PTYHOST_JOB_NAME");
|
|
1369
|
+
if (string.IsNullOrEmpty(name) || !name.StartsWith(AgentJobName + "Test", StringComparison.Ordinal))
|
|
1370
|
+
{
|
|
1371
|
+
name = AgentJobName;
|
|
1372
|
+
}
|
|
1373
|
+
IntPtr job = NativeMethods.CreateJobObjectW(IntPtr.Zero, name);
|
|
1374
|
+
int error = Marshal.GetLastWin32Error();
|
|
1321
1375
|
if (job == IntPtr.Zero)
|
|
1322
1376
|
{
|
|
1323
|
-
log.Write("agent job: CreateJobObject failed (" +
|
|
1377
|
+
log.Write("agent job: CreateJobObject failed (" + error + "); agents run outside it");
|
|
1324
1378
|
return IntPtr.Zero;
|
|
1325
1379
|
}
|
|
1380
|
+
agentJob = job;
|
|
1381
|
+
if (error == ErrorAlreadyExists)
|
|
1382
|
+
{
|
|
1383
|
+
log.Write("agent job: joined the existing one (its backstop stays as it was set)");
|
|
1384
|
+
return job;
|
|
1385
|
+
}
|
|
1386
|
+
if (setting == "none")
|
|
1387
|
+
{
|
|
1388
|
+
log.Write("agent job: no backstop (sandbox.agentMemoryHeadroomMb is none)");
|
|
1389
|
+
return job;
|
|
1390
|
+
}
|
|
1391
|
+
long commitMb;
|
|
1392
|
+
long limitMb = BackstopMb(setting, out commitMb);
|
|
1393
|
+
if (limitMb <= 0)
|
|
1394
|
+
{
|
|
1395
|
+
log.Write("agent job: the commit limit cannot be read; no backstop");
|
|
1396
|
+
return job;
|
|
1397
|
+
}
|
|
1326
1398
|
JobExtendedLimit info = new JobExtendedLimit();
|
|
1327
1399
|
info.BasicLimitInformation.LimitFlags = JobObjectLimitJobMemory;
|
|
1328
1400
|
info.JobMemoryLimit = new UIntPtr((ulong)(limitMb * BytesPerMb));
|
|
1329
1401
|
if (!NativeMethods.SetInformationJobObject(job, JobObjectExtendedLimitInformation, ref info, Marshal.SizeOf(typeof(JobExtendedLimit))))
|
|
1330
1402
|
{
|
|
1331
|
-
log.Write("agent job: setting the
|
|
1332
|
-
|
|
1333
|
-
return IntPtr.Zero;
|
|
1403
|
+
log.Write("agent job: setting the backstop failed (" + Marshal.GetLastWin32Error() + "); no backstop");
|
|
1404
|
+
return job;
|
|
1334
1405
|
}
|
|
1335
|
-
log.Write("agent job:
|
|
1336
|
-
agentJob = job;
|
|
1406
|
+
log.Write("agent job: last-resort backstop at " + limitMb + " MB committed (the sandbox's commit limit is " + commitMb + " MB)");
|
|
1337
1407
|
return job;
|
|
1338
1408
|
}
|
|
1339
1409
|
|
|
1410
|
+
/// <summary>The commit limit minus the headroom ("auto" or MB), at least half of it; 0 when it cannot be read.</summary>
|
|
1411
|
+
private static long BackstopMb(string setting, out long commitMb)
|
|
1412
|
+
{
|
|
1413
|
+
commitMb = 0;
|
|
1414
|
+
MemoryStatus status = new MemoryStatus();
|
|
1415
|
+
status.Length = (uint)Marshal.SizeOf(typeof(MemoryStatus));
|
|
1416
|
+
if (!NativeMethods.GlobalMemoryStatusEx(ref status))
|
|
1417
|
+
{
|
|
1418
|
+
return 0;
|
|
1419
|
+
}
|
|
1420
|
+
commitMb = (long)(status.TotalPageFile / (ulong)BytesPerMb);
|
|
1421
|
+
long headroom;
|
|
1422
|
+
if (setting == "auto" || !long.TryParse(setting, out headroom) || headroom < 0)
|
|
1423
|
+
{
|
|
1424
|
+
headroom = Math.Max(MinHeadroomMb, commitMb * HeadroomPercent / 100);
|
|
1425
|
+
}
|
|
1426
|
+
return Math.Max(commitMb / 2, commitMb - headroom);
|
|
1427
|
+
}
|
|
1428
|
+
|
|
1340
1429
|
/// <summary>Starts `commandLine` attached to the pseudo console. Null std handles: never leak our own stdio into the child.</summary>
|
|
1341
1430
|
public static IntPtr Spawn(string commandLine, IntPtr pseudoConsole, Log log)
|
|
1342
1431
|
{
|
|
@@ -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
|
{
|
|
@@ -5,7 +5,9 @@ param([Parameter(Mandatory = $true)][string]$ListFile)
|
|
|
5
5
|
$ErrorActionPreference = 'Stop'
|
|
6
6
|
|
|
7
7
|
$shell = New-Object -ComObject WScript.Shell
|
|
8
|
-
|
|
8
|
+
# Windows PowerShell 5.1 hands a JSON array over as ONE object: pipe it through ForEach-Object to get its elements.
|
|
9
|
+
$entries = @(ConvertFrom-Json -InputObject (Get-Content -LiteralPath $ListFile -Raw -Encoding UTF8) | ForEach-Object { $_ })
|
|
10
|
+
foreach ($entry in $entries) {
|
|
9
11
|
New-Item -ItemType Directory -Force -Path (Split-Path -Parent $entry.link) | Out-Null
|
|
10
12
|
$shortcut = $shell.CreateShortcut($entry.link)
|
|
11
13
|
$shortcut.TargetPath = $entry.target
|
|
@@ -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",
|
|
@@ -362,7 +362,7 @@
|
|
|
362
362
|
"properties": {
|
|
363
363
|
"enabled": {
|
|
364
364
|
"type": "boolean",
|
|
365
|
-
"description": "Send the sandbox's traffic through a VPN. Only the sandbox: your PC's own connection is untouched. Needs a saved login first (sandbox vpn login). The agent in the sandbox can read that login and can turn the tunnel off (it is the administrator there)."
|
|
365
|
+
"description": "(Alpha: not yet tried on a real PC) Send the sandbox's traffic through a VPN. Only the sandbox: your PC's own connection is untouched. Needs a saved login first (sandbox vpn login). The agent in the sandbox can read that login and can turn the tunnel off (it is the administrator there)."
|
|
366
366
|
},
|
|
367
367
|
"provider": {
|
|
368
368
|
"type": "string",
|
|
@@ -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
|
|
@@ -1236,13 +1250,17 @@
|
|
|
1236
1250
|
"properties": {
|
|
1237
1251
|
"enabled": {
|
|
1238
1252
|
"type": "boolean",
|
|
1239
|
-
"description": "(Beta)
|
|
1253
|
+
"description": "(Beta) The web UI: your sandbox sessions in a browser on this PC (http://127.0.0.1:<port>, this PC only). On: every sandbox start also starts it in the background (it keeps running until sandbox web stop or a restart of the PC). Off: only sandbox web start runs it. Open it signed in with sandbox web open."
|
|
1240
1254
|
},
|
|
1241
1255
|
"port": {
|
|
1242
1256
|
"type": "integer",
|
|
1243
1257
|
"minimum": 1024,
|
|
1244
1258
|
"maximum": 65535,
|
|
1245
1259
|
"description": "Port of the web UI on 127.0.0.1 (this PC only). Pick another when it is taken."
|
|
1260
|
+
},
|
|
1261
|
+
"openOnLaunch": {
|
|
1262
|
+
"type": "boolean",
|
|
1263
|
+
"description": "(Beta) With the web UI on: open it in your browser, already signed in, every time a sandbox starts."
|
|
1246
1264
|
}
|
|
1247
1265
|
},
|
|
1248
1266
|
"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
|
-
}
|