windows-development-sandbox 1.7.0 → 1.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/config.example.json +10 -0
- package/dist/app/context.d.ts +8 -0
- package/dist/app/context.js +12 -0
- package/dist/app/features/defs.d.ts +322 -0
- package/dist/app/features/defs.js +28 -0
- package/dist/app/features/sandbox/index.d.ts +2 -0
- package/dist/app/features/sandbox/index.js +3 -0
- package/dist/app/features/sandbox/sandbox.def.d.ts +193 -0
- package/dist/app/features/sandbox/sandbox.def.js +245 -0
- package/dist/app/features/sandbox/sandbox.run.d.ts +72 -0
- package/dist/app/features/sandbox/sandbox.run.js +98 -0
- package/dist/app/features/sessions/index.d.ts +2 -0
- package/dist/app/features/sessions/index.js +3 -0
- package/dist/app/features/sessions/sessions.def.d.ts +141 -0
- package/dist/app/features/sessions/sessions.def.js +176 -0
- package/dist/app/features/sessions/sessions.run.d.ts +39 -0
- package/dist/app/features/sessions/sessions.run.js +58 -0
- package/dist/{cli/menu/settings/categories.d.ts → app/features/settings/categories.def.d.ts} +2 -0
- package/dist/{cli/menu/settings/categories.js → app/features/settings/categories.def.js} +24 -5
- package/dist/app/features/settings/index.d.ts +5 -0
- package/dist/app/features/settings/index.js +6 -0
- package/dist/{cli/menu/settings/config-file.d.ts → app/features/settings/settings-file.d.ts} +1 -1
- package/dist/{cli/menu/settings/config-file.js → app/features/settings/settings-file.js} +1 -1
- package/dist/app/features/settings/settings-rows.d.ts +35 -0
- package/dist/app/features/settings/settings-rows.js +94 -0
- package/dist/app/features/settings/settings.def.d.ts +157 -0
- package/dist/app/features/settings/settings.def.js +179 -0
- package/dist/app/features/settings/settings.run.d.ts +67 -0
- package/dist/app/features/settings/settings.run.js +84 -0
- package/dist/app/kernel/define.d.ts +143 -0
- package/dist/app/kernel/define.js +42 -0
- package/dist/app/kernel/errors.d.ts +34 -0
- package/dist/app/kernel/errors.js +45 -0
- package/dist/app/kernel/fields.d.ts +70 -0
- package/dist/app/kernel/fields.js +243 -0
- package/dist/app/kernel/index.d.ts +8 -0
- package/dist/app/kernel/index.js +10 -0
- package/dist/app/kernel/io.d.ts +193 -0
- package/dist/app/kernel/io.js +126 -0
- package/dist/app/kernel/rpc.d.ts +156 -0
- package/dist/app/kernel/rpc.js +47 -0
- package/dist/app/kernel/text.d.ts +6 -0
- package/dist/app/kernel/text.js +57 -0
- package/dist/app/kernel/view.d.ts +146 -0
- package/dist/app/kernel/view.js +28 -0
- package/dist/app/registry.d.ts +10 -0
- package/dist/app/registry.js +50 -0
- package/dist/cli/args.d.ts +5 -0
- package/dist/cli/args.js +6 -0
- package/dist/cli/commands/engine.d.ts +2 -0
- package/dist/cli/commands/engine.js +60 -0
- package/dist/cli/commands/index.d.ts +1 -1
- package/dist/cli/commands/index.js +1 -1
- package/dist/cli/commands/launch/launch.js +47 -7
- package/dist/cli/commands/launch/prepare.js +3 -3
- package/dist/cli/commands/launch/running.js +2 -1
- package/dist/cli/commands/launch/summary.d.ts +2 -0
- package/dist/cli/commands/maintenance/config-share.d.ts +12 -0
- package/dist/cli/commands/maintenance/config-share.js +80 -0
- package/dist/cli/commands/maintenance/config.js +8 -82
- package/dist/cli/commands/maintenance/logs.js +14 -0
- package/dist/cli/commands/registry.js +3 -7
- package/dist/cli/commands/repair/checks/contained.d.ts +2 -0
- package/dist/cli/commands/repair/checks/contained.js +139 -0
- package/dist/cli/commands/repair/checks/hcs.d.ts +7 -0
- package/dist/cli/commands/repair/checks/hcs.js +28 -0
- package/dist/cli/commands/repair/checks/index.js +4 -0
- package/dist/cli/commands/repair/checks/pc.js +32 -1
- package/dist/cli/commands/repair/checks/sandbox.js +16 -1
- package/dist/cli/commands/repair/checks/vpn.js +34 -9
- package/dist/cli/commands/repair/env.js +2 -1
- package/dist/cli/commands/sessions/index.d.ts +0 -4
- package/dist/cli/commands/sessions/index.js +3 -7
- package/dist/cli/commands/shared-use.d.ts +5 -2
- package/dist/cli/commands/shared-use.js +11 -8
- package/dist/cli/commands/storage/contained.d.ts +3 -0
- package/dist/cli/commands/storage/contained.js +179 -0
- package/dist/cli/commands/storage/offer.js +7 -1
- package/dist/cli/commands/storage/storage.js +10 -2
- package/dist/cli/commands/user-config.js +1 -1
- package/dist/cli/commands/vpn.js +19 -3
- package/dist/cli/commands/web.js +2 -0
- package/dist/cli/index.js +2 -1
- package/dist/cli/manifest.d.ts +72 -104
- package/dist/cli/manifest.js +64 -39
- package/dist/cli/menu/add-agent.d.ts +1 -1
- package/dist/cli/menu/add-agent.js +1 -1
- package/dist/cli/menu/apps.d.ts +7 -1
- package/dist/cli/menu/apps.js +36 -0
- package/dist/cli/menu/command-fields.d.ts +1 -1
- package/dist/cli/menu/command-form.js +2 -2
- package/dist/cli/menu/io-menu.d.ts +29 -0
- package/dist/cli/menu/io-menu.js +126 -0
- package/dist/cli/menu/live.d.ts +27 -0
- package/dist/cli/menu/live.js +69 -0
- package/dist/cli/menu/memory.d.ts +19 -0
- package/dist/cli/menu/memory.js +53 -0
- package/dist/cli/menu/menu.d.ts +10 -1
- package/dist/cli/menu/menu.js +27 -9
- package/dist/cli/menu/pages/agents-page.d.ts +3 -1
- package/dist/cli/menu/pages/agents-page.js +12 -5
- package/dist/cli/menu/pages/apps-page.d.ts +3 -1
- package/dist/cli/menu/pages/apps-page.js +19 -2
- package/dist/cli/menu/pages/list-page.d.ts +27 -0
- package/dist/cli/menu/pages/list-page.js +109 -7
- package/dist/cli/menu/pages/maintenance-page.d.ts +0 -5
- package/dist/cli/menu/pages/maintenance-page.js +17 -19
- package/dist/cli/menu/pages/sandbox-page.d.ts +4 -6
- package/dist/cli/menu/pages/sandbox-page.js +26 -118
- package/dist/cli/menu/pages/scopes.d.ts +1 -1
- package/dist/cli/menu/pages/sessions-page.d.ts +5 -11
- package/dist/cli/menu/pages/sessions-page.js +19 -88
- package/dist/cli/menu/pages/settings-page.d.ts +2 -10
- package/dist/cli/menu/pages/settings-page.js +64 -94
- package/dist/cli/menu/render-view.d.ts +28 -0
- package/dist/cli/menu/render-view.js +112 -0
- package/dist/cli/menu/settings/{path-kind.d.ts → ask-path.d.ts} +1 -7
- package/dist/cli/menu/settings/ask-path.js +14 -0
- package/dist/cli/menu/settings/collections/collection-editor.d.ts +1 -1
- package/dist/cli/menu/settings/collections/string-list-editor.d.ts +1 -2
- package/dist/cli/menu/settings/collections/string-list-editor.js +1 -1
- package/dist/cli/menu/settings/draft.d.ts +1 -1
- package/dist/cli/menu/settings/format.d.ts +1 -3
- package/dist/cli/menu/settings/format.js +6 -36
- package/dist/cli/menu/settings/index.d.ts +1 -3
- package/dist/cli/menu/settings/index.js +3 -3
- package/dist/cli/menu/settings/object-editor.d.ts +1 -1
- package/dist/cli/menu/settings/share.d.ts +36 -0
- package/dist/cli/menu/settings/share.js +131 -0
- package/dist/cli/menu/settings/value-editor.d.ts +5 -1
- package/dist/cli/menu/settings/value-editor.js +57 -54
- package/dist/cli/menu/several.js +1 -1
- package/dist/cli/menu/share-settings.d.ts +21 -0
- package/dist/cli/menu/share-settings.js +112 -0
- package/dist/cli/menu/shell.d.ts +21 -5
- package/dist/cli/menu/shell.js +31 -6
- package/dist/cli/menu/views.d.ts +7 -0
- package/dist/cli/menu/views.js +11 -0
- package/dist/cli/menu/vpn-login.js +8 -0
- package/dist/cli/operations/handler.d.ts +6 -0
- package/dist/cli/operations/handler.js +61 -0
- package/dist/cli/operations/index.d.ts +4 -0
- package/dist/cli/operations/index.js +5 -0
- package/dist/cli/operations/input.d.ts +6 -0
- package/dist/cli/operations/input.js +37 -0
- package/dist/cli/operations/io-cli.d.ts +7 -0
- package/dist/cli/operations/io-cli.js +62 -0
- package/dist/cli/operations/spec.d.ts +18 -0
- package/dist/cli/operations/spec.js +108 -0
- package/dist/cli/output/colors.d.ts +2 -2
- package/dist/cli/output/colors.js +2 -11
- package/dist/cli/output/index.d.ts +1 -0
- package/dist/cli/output/index.js +1 -0
- package/dist/cli/output/print.d.ts +3 -1
- package/dist/cli/output/print.js +7 -3
- package/dist/cli/output/progress.d.ts +15 -0
- package/dist/cli/output/progress.js +44 -0
- package/dist/cli/output/render-view.d.ts +4 -0
- package/dist/cli/output/render-view.js +63 -0
- package/dist/cli/services/agent-commands-service.d.ts +2 -0
- package/dist/cli/services/agent-commands-service.js +11 -2
- package/dist/cli/services/logs-service.js +4 -3
- package/dist/cli/tui/app.d.ts +6 -1
- package/dist/cli/tui/app.js +26 -4
- package/dist/cli/tui/list/list-screen.d.ts +14 -0
- package/dist/cli/tui/list/list-screen.js +64 -36
- package/dist/cli/tui/list/list-types.d.ts +2 -0
- package/dist/cli/tui/terminal.d.ts +7 -0
- package/dist/cli/tui/terminal.js +30 -10
- package/dist/core/config/defaults.js +8 -0
- package/dist/core/schema/config.d.ts +13 -0
- package/dist/core/schema/config.js +16 -1
- package/dist/core/schema/harness.d.ts +1 -0
- package/dist/core/schema/harness.js +5 -0
- package/dist/core/schema/sandbox.d.ts +6 -0
- package/dist/core/schema/sandbox.js +20 -3
- package/dist/core/schema/vpn.d.ts +2 -1
- package/dist/core/schema/vpn.js +3 -3
- package/dist/core/types.d.ts +23 -5
- package/dist/core/util/fs.d.ts +2 -0
- package/dist/core/util/fs.js +9 -0
- package/dist/core/util/index.d.ts +1 -1
- package/dist/core/util/index.js +1 -1
- package/dist/guest/agents/agent-files.d.ts +5 -0
- package/dist/guest/agents/agent-files.js +4 -0
- package/dist/guest/agents/local-state.d.ts +2 -0
- package/dist/guest/agents/local-state.js +21 -1
- package/dist/guest/boot/boot.js +2 -1
- package/dist/guest/daemon/daemon.js +4 -0
- package/dist/guest/daemon/sessions.d.ts +5 -0
- package/dist/guest/daemon/sessions.js +17 -3
- package/dist/guest/entries/daemon.js +3 -0
- package/dist/guest/governor/decide.d.ts +61 -0
- package/dist/guest/governor/decide.js +182 -0
- package/dist/guest/governor/governor.d.ts +42 -0
- package/dist/guest/governor/governor.js +214 -0
- package/dist/guest/governor/index.d.ts +2 -0
- package/dist/guest/governor/index.js +2 -0
- package/dist/guest/runtime/csc.d.ts +1 -0
- package/dist/guest/runtime/csc.js +1 -0
- package/dist/guest/sessions/viewer.js +3 -1
- package/dist/guest/toolchains/native/rust-extras.js +4 -2
- package/dist/guest/vpn/vpn.js +69 -21
- package/dist/guest/vpn/wireguard.d.ts +32 -0
- package/dist/guest/vpn/wireguard.js +132 -0
- package/dist/host/agent-commands/commands.d.ts +4 -0
- package/dist/host/agent-commands/commands.js +31 -7
- package/dist/host/audit/log.d.ts +1 -1
- package/dist/host/channel/attach.d.ts +3 -1
- package/dist/host/channel/attach.js +5 -2
- package/dist/host/channel/channel.d.ts +2 -0
- package/dist/host/channel/channel.js +4 -0
- package/dist/host/engines/engine.d.ts +12 -0
- package/dist/host/engines/engine.js +1 -0
- package/dist/host/engines/hcs/check.d.ts +25 -0
- package/dist/host/engines/hcs/check.js +95 -0
- package/dist/host/engines/hcs/documents.d.ts +44 -0
- package/dist/host/engines/hcs/documents.js +155 -0
- package/dist/host/engines/hcs/engine.d.ts +39 -0
- package/dist/host/engines/hcs/engine.js +171 -0
- package/dist/host/engines/hcs/helper.d.ts +43 -0
- package/dist/host/engines/hcs/helper.js +173 -0
- package/dist/host/engines/hcs/images.d.ts +37 -0
- package/dist/host/engines/hcs/images.js +152 -0
- package/dist/host/engines/index.d.ts +7 -0
- package/dist/host/engines/index.js +5 -0
- package/dist/host/engines/registry.d.ts +16 -0
- package/dist/host/engines/registry.js +30 -0
- package/dist/host/engines/types.d.ts +58 -0
- package/dist/host/engines/types.js +1 -0
- package/dist/host/engines/windows-sandbox/engine.d.ts +16 -0
- package/dist/host/engines/windows-sandbox/engine.js +63 -0
- package/dist/host/engines/windows-sandbox/wsb-text.d.ts +2 -0
- package/dist/host/engines/windows-sandbox/wsb-text.js +29 -0
- package/dist/host/launch/generate.d.ts +5 -1
- package/dist/host/launch/generate.js +50 -8
- package/dist/host/launch/index.d.ts +3 -1
- package/dist/host/launch/index.js +3 -1
- package/dist/host/launch/launch-plan.d.ts +13 -0
- package/dist/host/launch/launch-plan.js +26 -0
- package/dist/host/launch/mappings.js +2 -1
- package/dist/host/launch/risk-notes.d.ts +10 -0
- package/dist/host/launch/risk-notes.js +18 -0
- package/dist/host/launch/session-file.d.ts +2 -0
- package/dist/host/launch/session-file.js +7 -1
- package/dist/host/launch/wsb-file.d.ts +28 -4
- package/dist/host/launch/wsb-file.js +61 -42
- package/dist/host/life/crash-report.d.ts +27 -1
- package/dist/host/life/crash-report.js +173 -7
- package/dist/host/life/host-memory.d.ts +40 -0
- package/dist/host/life/host-memory.js +137 -0
- package/dist/host/life/index.d.ts +2 -0
- package/dist/host/life/index.js +2 -0
- package/dist/host/life/stop-events.d.ts +2 -0
- package/dist/host/life/stop-events.js +20 -3
- package/dist/host/life/stop-warning.js +1 -1
- package/dist/host/life/watchdog.d.ts +54 -0
- package/dist/host/life/watchdog.js +108 -0
- package/dist/host/native.d.ts +3 -2
- package/dist/host/native.js +22 -3
- package/dist/host/profile/claude-login.js +3 -2
- package/dist/host/sandbox/contained-deps.d.ts +2 -0
- package/dist/host/sandbox/contained-deps.js +17 -0
- package/dist/host/sandbox/index.d.ts +2 -0
- package/dist/host/sandbox/index.js +2 -0
- package/dist/host/sandbox/platform.d.ts +2 -0
- package/dist/host/sandbox/platform.js +7 -7
- package/dist/host/sandbox/tasklist.d.ts +13 -0
- package/dist/host/sandbox/tasklist.js +47 -0
- package/dist/host/secrets/launch-secrets.js +2 -1
- package/dist/host/sharing/current.js +2 -6
- package/dist/host/storage/contained/check.d.ts +9 -0
- package/dist/host/storage/contained/check.js +37 -0
- package/dist/host/storage/contained/contained-storage.d.ts +66 -0
- package/dist/host/storage/contained/contained-storage.js +168 -0
- package/dist/host/storage/contained/disk-port.d.ts +43 -0
- package/dist/host/storage/contained/disk-port.js +122 -0
- package/dist/host/storage/contained/index.d.ts +9 -0
- package/dist/host/storage/contained/index.js +8 -0
- package/dist/host/storage/contained/layout.d.ts +28 -0
- package/dist/host/storage/contained/layout.js +45 -0
- package/dist/host/storage/contained/resolve.d.ts +4 -0
- package/dist/host/storage/contained/resolve.js +30 -0
- package/dist/host/storage/contained/setting.d.ts +1 -0
- package/dist/host/storage/contained/setting.js +5 -0
- package/dist/host/storage/contained/state.d.ts +89 -0
- package/dist/host/storage/contained/state.js +166 -0
- package/dist/host/storage/contained/transfer.d.ts +24 -0
- package/dist/host/storage/contained/transfer.js +121 -0
- package/dist/host/storage/index.d.ts +2 -0
- package/dist/host/storage/index.js +2 -0
- package/dist/host/storage/providers/contained.d.ts +15 -0
- package/dist/host/storage/providers/contained.js +39 -0
- package/dist/host/storage/providers/folder.d.ts +12 -0
- package/dist/host/storage/providers/folder.js +20 -0
- package/dist/host/storage/providers/index.d.ts +4 -0
- package/dist/host/storage/providers/index.js +3 -0
- package/dist/host/storage/providers/registry.d.ts +9 -0
- package/dist/host/storage/providers/registry.js +14 -0
- package/dist/host/storage/providers/types.d.ts +33 -0
- package/dist/host/storage/providers/types.js +1 -0
- package/dist/host/tools/conpty.js +3 -2
- package/dist/host/tools/windows-terminal.js +8 -7
- package/dist/host/vpn/index.d.ts +1 -1
- package/dist/host/vpn/index.js +1 -1
- package/dist/host/vpn/prepare.d.ts +2 -0
- package/dist/host/vpn/prepare.js +63 -2
- package/dist/host/web/browser.d.ts +2 -0
- package/dist/host/web/browser.js +14 -1
- package/dist/host/web/index.d.ts +3 -2
- package/dist/host/web/index.js +3 -2
- package/dist/host/web/rpc.d.ts +24 -0
- package/dist/host/web/rpc.js +149 -0
- package/dist/host/web/runner.d.ts +2 -0
- package/dist/host/web/runner.js +1 -2
- package/dist/host/web/server.d.ts +7 -0
- package/dist/host/web/server.js +23 -3
- package/dist/runtime/agent.js +69 -8
- package/dist/runtime/daemon.js +1058 -624
- package/dist/runtime/db.js +69 -8
- package/dist/runtime/main.js +624 -182
- package/dist/runtime/netproxy.js +69 -8
- package/dist/runtime/view.js +87 -13
- package/dist/selftest/agent-paths.test.js +11 -1
- package/dist/selftest/app.test.d.ts +2 -0
- package/dist/selftest/app.test.js +324 -0
- package/dist/selftest/channel.test.js +13 -0
- package/dist/selftest/cli.test.js +2 -1
- package/dist/selftest/config.test.js +59 -0
- package/dist/selftest/contained.test.d.ts +2 -0
- package/dist/selftest/contained.test.js +544 -0
- package/dist/selftest/credentials.test.js +1 -1
- package/dist/selftest/engine.test.d.ts +2 -0
- package/dist/selftest/engine.test.js +127 -0
- package/dist/selftest/hcs.test.d.ts +2 -0
- package/dist/selftest/hcs.test.js +482 -0
- package/dist/selftest/heavy-load.test.d.ts +2 -0
- package/dist/selftest/heavy-load.test.js +329 -0
- package/dist/selftest/index.js +12 -0
- package/dist/selftest/layout.test.js +12 -0
- package/dist/selftest/menu-perf.test.d.ts +2 -0
- package/dist/selftest/menu-perf.test.js +248 -0
- package/dist/selftest/menu-screens.js +4 -2
- package/dist/selftest/menu.test.js +36 -8
- package/dist/selftest/support/engine-cases.d.ts +8 -0
- package/dist/selftest/support/engine-cases.js +65 -0
- package/dist/selftest/support/engine-golden.d.ts +3 -0
- package/dist/selftest/support/engine-golden.js +66 -0
- package/dist/selftest/support/fixtures.d.ts +7 -1
- package/dist/selftest/support/hcs-probes.d.ts +17 -0
- package/dist/selftest/support/hcs-probes.js +41 -0
- package/dist/selftest/vpn.test.js +136 -3
- package/dist/selftest/web.test.js +101 -3
- package/dist/shared/channel/run-dir.d.ts +4 -1
- package/dist/shared/channel/run-dir.js +7 -1
- package/dist/shared/channel/schema.d.ts +35 -1
- package/dist/shared/channel/schema.js +27 -0
- package/dist/shared/channel/secrets.d.ts +1 -0
- package/dist/shared/channel/secrets.js +6 -0
- package/dist/shared/memory/index.d.ts +1 -0
- package/dist/shared/memory/index.js +1 -0
- package/dist/shared/memory/policy.d.ts +33 -0
- package/dist/shared/memory/policy.js +55 -0
- package/dist/shared/pty/output-filter.d.ts +14 -1
- package/dist/shared/pty/output-filter.js +22 -4
- package/dist/shared/pty/terminal.d.ts +4 -1
- package/dist/shared/pty/terminal.js +4 -2
- package/dist/shared/system.d.ts +1 -0
- package/dist/shared/system.js +1 -0
- package/dist/shared/vpn/download.d.ts +16 -0
- package/dist/shared/vpn/download.js +16 -0
- package/dist/shared/vpn/wireguard.d.ts +51 -0
- package/dist/shared/vpn/wireguard.js +227 -0
- package/dist/sync/sync-cycle.js +5 -5
- package/dist/sync/watcher.d.ts +13 -0
- package/dist/sync/watcher.js +92 -3
- package/dist/web/index.html +4 -3
- package/dist/web/main-NRRS5O6Z.js +157 -0
- package/dist/web/main-T5DMCHYV.css +1 -0
- package/native/csharp/HcsHost/AssemblyInfo.cs +14 -0
- package/native/csharp/HcsHost/Guard.cs +100 -0
- package/native/csharp/HcsHost/Hcs.cs +256 -0
- package/native/csharp/HcsHost/Json.cs +78 -0
- package/native/csharp/HcsHost/Program.cs +185 -0
- package/native/csharp/HcsHost/VirtualDisk.cs +95 -0
- package/native/csharp/HostTools/AssemblyInfo.cs +14 -0
- package/native/csharp/HostTools/MemoryStatus.cs +107 -0
- package/native/csharp/HostTools/Program.cs +58 -17
- package/native/scripts/check-contained.ps1 +28 -0
- package/native/scripts/contained-common.ps1 +241 -0
- package/native/scripts/dismount-contained.ps1 +66 -0
- package/native/scripts/memory-status.ps1 +34 -0
- package/native/scripts/mount-contained.ps1 +139 -0
- package/native/scripts/run-elevated.ps1 +17 -4
- package/native/scripts/stop-events.ps1 +23 -8
- package/package.json +9 -2
- package/sandbox/csharp/MemGov.cs +398 -0
- package/sandbox/csharp/PtyHost.cs +111 -5
- package/schemas/config.schema.json +60 -6
- package/schemas/sandbox-config.schema.json +3 -3
- package/dist/cli/commands/sessions/control.d.ts +0 -4
- package/dist/cli/commands/sessions/control.js +0 -66
- package/dist/cli/commands/sessions/list.d.ts +0 -2
- package/dist/cli/commands/sessions/list.js +0 -48
- package/dist/cli/commands/sessions/status.d.ts +0 -4
- package/dist/cli/commands/sessions/status.js +0 -114
- package/dist/cli/commands/sessions/window.d.ts +0 -3
- package/dist/cli/commands/sessions/window.js +0 -18
- package/dist/cli/menu/settings/path-kind.js +0 -44
- package/dist/web/main-CXESL347.js +0 -45
- package/dist/web/main-VLR7DVQ4.css +0 -1
- /package/dist/{cli/menu/settings → app/kernel}/schema-node.d.ts +0 -0
- /package/dist/{cli/menu/settings → app/kernel}/schema-node.js +0 -0
package/dist/core/schema/vpn.js
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
// The VPN setting (inside the sandbox only; the login is not a setting: it is kept encrypted by `sandbox vpn login`).
|
|
2
2
|
import { z } from 'zod';
|
|
3
|
-
export const VPN_PROVIDERS = ['nordvpn', 'openvpn-file'];
|
|
3
|
+
export const VPN_PROVIDERS = ['nordvpn', 'openvpn-file', 'wireguard-file'];
|
|
4
4
|
export const VpnSchema = z.strictObject({
|
|
5
5
|
enabled: z
|
|
6
6
|
.boolean()
|
|
7
7
|
.describe("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)."),
|
|
8
8
|
provider: z
|
|
9
9
|
.enum(VPN_PROVIDERS)
|
|
10
|
-
.describe('nordvpn: a recommended NordVPN server is picked at every launch. openvpn-file: your own .ovpn file (configFile).'),
|
|
10
|
+
.describe('nordvpn: a recommended NordVPN server is picked at every launch. openvpn-file: your own .ovpn file (configFile). wireguard-file: your own WireGuard .conf (configFile), e.g. from your company.'),
|
|
11
11
|
protocol: z.enum(['udp', 'tcp']).describe('udp is faster; tcp gets through networks that block udp.'),
|
|
12
12
|
country: z
|
|
13
13
|
.string()
|
|
@@ -15,7 +15,7 @@ export const VpnSchema = z.strictObject({
|
|
|
15
15
|
.describe('nordvpn: the country of the server, e.g. uk, us or Germany. Empty = the best server anywhere.'),
|
|
16
16
|
configFile: z
|
|
17
17
|
.string()
|
|
18
|
-
.describe("openvpn-file: the .ovpn file on this PC (its certificates inside it). Files that run programs (script-security, up, down, plugin ...) are refused. A project's file can never set this."),
|
|
18
|
+
.describe("openvpn-file / wireguard-file: the .ovpn or .conf file on this PC (an .ovpn has its certificates inside it). Files that run programs (script-security, up, down, plugin, PostUp ...) are refused. A WireGuard file holds your private key: it is read when a sandbox starts and handed over in a one-shot file. A project's file can never set this."),
|
|
19
19
|
killSwitch: z
|
|
20
20
|
.boolean()
|
|
21
21
|
.describe('Block all traffic that does not go through the tunnel: when the tunnel cannot start, the sandbox stays offline instead of using your normal connection. A project can only turn this on, never off.'),
|
package/dist/core/types.d.ts
CHANGED
|
@@ -105,12 +105,15 @@ export interface DatabasePlan {
|
|
|
105
105
|
/** The VPN decided at launch (host/vpn/prepare.ts): its checked profile, and the login for the one-shot file. */
|
|
106
106
|
export interface PreparedVpn {
|
|
107
107
|
session: GuestVpn;
|
|
108
|
-
/**
|
|
109
|
-
profile
|
|
110
|
-
|
|
108
|
+
/** openvpn: the profile text, already checked (goes in the launch folder). */
|
|
109
|
+
profile?: string;
|
|
110
|
+
/** openvpn: the login (one-shot file). */
|
|
111
|
+
credentials?: {
|
|
111
112
|
username: string;
|
|
112
113
|
password: string;
|
|
113
114
|
};
|
|
115
|
+
/** wireguard-file: the checked config; holds the private key (one-shot file only). */
|
|
116
|
+
wireguardConfig?: string;
|
|
114
117
|
}
|
|
115
118
|
/** databases / pcLanguages: use these instead of scanning (tests). */
|
|
116
119
|
export interface GenerateOptions {
|
|
@@ -119,6 +122,8 @@ export interface GenerateOptions {
|
|
|
119
122
|
harnessArgs: string[];
|
|
120
123
|
probe: HostProbe;
|
|
121
124
|
freeMemoryBytes?: number;
|
|
125
|
+
/** This PC's unused commit (RAM plus paging file) in MB from HostTools memory-status; omitted = not checked. */
|
|
126
|
+
commitAvailableMb?: number | null;
|
|
122
127
|
databases?: DatabasePlan[];
|
|
123
128
|
pcLanguages?: AutoToolchain[];
|
|
124
129
|
/**
|
|
@@ -136,6 +141,8 @@ export interface GenerateOptions {
|
|
|
136
141
|
};
|
|
137
142
|
/** The VPN for this launch (vpn.enabled); its profile goes in the launch folder, its login in the one-shot file. */
|
|
138
143
|
vpn?: PreparedVpn;
|
|
144
|
+
/** The data set's mappings from a storage provider (contained storage); else the data folder is one mapping. */
|
|
145
|
+
dataMappings?: ResolvedMapping[];
|
|
139
146
|
}
|
|
140
147
|
export interface Generated {
|
|
141
148
|
wsbPath: string;
|
|
@@ -143,6 +150,8 @@ export interface Generated {
|
|
|
143
150
|
launchId: string;
|
|
144
151
|
sessionPath: string;
|
|
145
152
|
memoryMb: number;
|
|
153
|
+
/** Plain words when the PC's commit made the memory much smaller than free RAM allowed. */
|
|
154
|
+
memoryNote: string | null;
|
|
146
155
|
/** The config the sandbox boots with: the launch folder's plus what the other projects mapped at boot want. */
|
|
147
156
|
bootConfig: Config;
|
|
148
157
|
/** Boot settings turned on for another project (setting -> project). */
|
|
@@ -181,8 +190,8 @@ export interface GuestVpn {
|
|
|
181
190
|
killSwitch: boolean;
|
|
182
191
|
/** The server's name, for messages. */
|
|
183
192
|
server: string;
|
|
184
|
-
/**
|
|
185
|
-
profile
|
|
193
|
+
/** openvpn: the checked profile, relative to the launch folder (none for wireguard-file: its config is a secret). */
|
|
194
|
+
profile?: string;
|
|
186
195
|
}
|
|
187
196
|
/** Written by the host to C:\AgentLaunch\session.json (read-only for the guest): everything the guest needs to know. */
|
|
188
197
|
export interface GuestSession {
|
|
@@ -253,6 +262,15 @@ export interface GuestSession {
|
|
|
253
262
|
cpuLimitPercent?: number | null;
|
|
254
263
|
/** sandbox.pageFileMb (0 = Windows' own); sandbox\scripts\set-page-file.ps1 applies it at logon. */
|
|
255
264
|
pageFileMb?: number;
|
|
265
|
+
/**
|
|
266
|
+
* sandbox.agentMemoryHeadroomMb as a limit: the most memory (MB) everything the agents start may use together
|
|
267
|
+
* (the sandbox's memory minus the headroom); null = no limit. ptyhost puts each agent in a job object with it.
|
|
268
|
+
*/
|
|
269
|
+
agentMemoryLimitMb?: number | null;
|
|
270
|
+
/** "gentle" when vGPU is on: the governor and the watchdog act earlier, compilers run below normal. */
|
|
271
|
+
loadProfile?: 'normal' | 'gentle';
|
|
272
|
+
/** sandbox.pressureResponse: the daemon slows builds down when memory runs low. */
|
|
273
|
+
pressureResponse?: boolean;
|
|
256
274
|
/** Apps to install (catalogue ids and your own programs); missing in launch folders of older versions. */
|
|
257
275
|
apps?: Config['apps'];
|
|
258
276
|
/** audit.enabled and audit.processes: the sandbox reports the programs it starts (host keeps the log). */
|
package/dist/core/util/fs.d.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
export declare function ensureDir(p: string): void;
|
|
2
2
|
export declare function dirExists(p: string): boolean;
|
|
3
3
|
export declare function fileExists(p: string): boolean;
|
|
4
|
+
/** fileExists without blocking the program (the menu looks for programs while it stays responsive). */
|
|
5
|
+
export declare function fileExistsAsync(p: string): Promise<boolean>;
|
|
4
6
|
export declare function readJson<T>(p: string): T;
|
|
5
7
|
export declare function tryReadJson<T>(p: string): T | null;
|
|
6
8
|
/** Atomic (a crash or a second command never leaves half a file); refused outside temp during the self-test. */
|
package/dist/core/util/fs.js
CHANGED
|
@@ -19,6 +19,15 @@ export function fileExists(p) {
|
|
|
19
19
|
return false;
|
|
20
20
|
}
|
|
21
21
|
}
|
|
22
|
+
/** fileExists without blocking the program (the menu looks for programs while it stays responsive). */
|
|
23
|
+
export async function fileExistsAsync(p) {
|
|
24
|
+
try {
|
|
25
|
+
return (await fs.promises.stat(p)).isFile();
|
|
26
|
+
}
|
|
27
|
+
catch {
|
|
28
|
+
return false;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
22
31
|
export function readJson(p) {
|
|
23
32
|
return JSON.parse(fs.readFileSync(p, 'utf8').replace(/^\uFEFF/, ''));
|
|
24
33
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export { isWin, sleep, captureOutput } from './process.js';
|
|
2
2
|
export { UserError, fail, errMsg } from './errors.js';
|
|
3
3
|
export { parseJsonc, readJsonc } from './jsonc.js';
|
|
4
|
-
export { ensureDir, dirExists, fileExists, readJson, tryReadJson, writeJson, realPath } from './fs.js';
|
|
4
|
+
export { ensureDir, dirExists, fileExists, fileExistsAsync, readJson, tryReadJson, writeJson, realPath } from './fs.js';
|
|
5
5
|
export { xmlEscape, safeText, plainText } from './text.js';
|
|
6
6
|
export { homeDir, expandPath, expandVariables, isRootPath, isUserProfile, isInsideOrEqual, findOnPath, } from './paths.js';
|
|
7
7
|
export { isLink, removeLink, assertNoLinks } from './links.js';
|
package/dist/core/util/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export { isWin, sleep, captureOutput } from './process.js';
|
|
2
2
|
export { UserError, fail, errMsg } from './errors.js';
|
|
3
3
|
export { parseJsonc, readJsonc } from './jsonc.js';
|
|
4
|
-
export { ensureDir, dirExists, fileExists, readJson, tryReadJson, writeJson, realPath } from './fs.js';
|
|
4
|
+
export { ensureDir, dirExists, fileExists, fileExistsAsync, readJson, tryReadJson, writeJson, realPath } from './fs.js';
|
|
5
5
|
export { xmlEscape, safeText, plainText } from './text.js';
|
|
6
6
|
export { homeDir, expandPath, expandVariables, isRootPath, isUserProfile, isInsideOrEqual, findOnPath, } from './paths.js';
|
|
7
7
|
export { isLink, removeLink, assertNoLinks } from './links.js';
|
|
@@ -43,6 +43,11 @@ export interface LocalState {
|
|
|
43
43
|
readonly legacy: string;
|
|
44
44
|
}
|
|
45
45
|
export declare function localStateEntries(agents: Readonly<Record<string, Harness>>, stateDir: string, localRoot: string): LocalState[];
|
|
46
|
+
/** Every agent's bootReset paths, absolute below its state folder (the schema allows only plain relative paths). */
|
|
47
|
+
export declare function bootResetPaths(agents: Readonly<Record<string, Harness>>, stateDir: string): {
|
|
48
|
+
agent: string;
|
|
49
|
+
path: string;
|
|
50
|
+
}[];
|
|
46
51
|
/** A SQLite database file or one of its -wal / -shm siblings. */
|
|
47
52
|
export declare const isDatabaseFile: (name: string) => boolean;
|
|
48
53
|
/** Files that make a consistent copy: the databases and their -wal (the -shm is rebuilt by SQLite). */
|
|
@@ -57,6 +57,10 @@ export function localStateEntries(agents, stateDir, localRoot) {
|
|
|
57
57
|
legacy: path.join(stateDir, agent),
|
|
58
58
|
})));
|
|
59
59
|
}
|
|
60
|
+
/** Every agent's bootReset paths, absolute below its state folder (the schema allows only plain relative paths). */
|
|
61
|
+
export function bootResetPaths(agents, stateDir) {
|
|
62
|
+
return Object.entries(agents).flatMap(([agent, harness]) => (harness.bootReset ?? []).map((rel) => ({ agent, path: path.join(stateDir, agent, rel) })));
|
|
63
|
+
}
|
|
60
64
|
/** A SQLite database file or one of its -wal / -shm siblings. */
|
|
61
65
|
export const isDatabaseFile = (name) => /\.(sqlite3?|db)(-wal|-shm)?$/i.test(name);
|
|
62
66
|
/** Files that make a consistent copy: the databases and their -wal (the -shm is rebuilt by SQLite). */
|
|
@@ -3,6 +3,8 @@ import { type LocalState } from './agent-files.js';
|
|
|
3
3
|
export declare function agentLocalStates(): LocalState[];
|
|
4
4
|
/** Variable -> working folder, for the agent environment (and the machine environment of new terminal tabs). */
|
|
5
5
|
export declare function localStateVars(): Record<string, string>;
|
|
6
|
+
/** Boot: what an agent sealed to the last sandbox (bootReset) is deleted, so it sets it up again. Links are left. */
|
|
7
|
+
export declare function resetMachineBound(): void;
|
|
6
8
|
/** Boot: the saved databases of every configured agent are copied to the sandbox's disk, where the agent runs them. */
|
|
7
9
|
export declare function restoreLocalState(): void;
|
|
8
10
|
/**
|
|
@@ -10,7 +10,7 @@ import { execOutput } from '../runtime/process.js';
|
|
|
10
10
|
import { log, warn } from '../runtime/log.js';
|
|
11
11
|
import { session, stateDir } from '../runtime/session.js';
|
|
12
12
|
import { errMsg } from '../../core/util/errors.js';
|
|
13
|
-
import { isCopyableDatabaseFile, isDatabaseFile, localStateEntries } from './agent-files.js';
|
|
13
|
+
import { bootResetPaths, isCopyableDatabaseFile, isDatabaseFile, localStateEntries, } from './agent-files.js';
|
|
14
14
|
const SQLITE_HEADER = 'SQLite format 3\0';
|
|
15
15
|
/** The sandbox-disk folder that holds the working copies. */
|
|
16
16
|
const localRoot = () => path.join(localDir, 'agent-state');
|
|
@@ -82,6 +82,26 @@ function adoptLegacy(s) {
|
|
|
82
82
|
fs.rmSync(path.join(s.legacy, n), { force: true });
|
|
83
83
|
log(s.agent + ': moved ' + copyable.length + ' database file(s) to ' + s.store + '.');
|
|
84
84
|
}
|
|
85
|
+
/** Boot: what an agent sealed to the last sandbox (bootReset) is deleted, so it sets it up again. Links are left. */
|
|
86
|
+
export function resetMachineBound() {
|
|
87
|
+
if (dryRun)
|
|
88
|
+
return;
|
|
89
|
+
for (const { agent, path: target } of bootResetPaths(session.agents ?? {}, stateDir)) {
|
|
90
|
+
try {
|
|
91
|
+
const stat = fs.lstatSync(target, { throwIfNoEntry: false });
|
|
92
|
+
if (!stat || stat.isSymbolicLink())
|
|
93
|
+
continue;
|
|
94
|
+
fs.rmSync(target, { recursive: true, force: true });
|
|
95
|
+
log(agent +
|
|
96
|
+
': removed ' +
|
|
97
|
+
path.relative(path.join(stateDir, agent), target) +
|
|
98
|
+
' (it only worked in the last sandbox).');
|
|
99
|
+
}
|
|
100
|
+
catch (e) {
|
|
101
|
+
warn(agent + ': could not remove ' + target + ' (' + errMsg(e) + ').');
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
85
105
|
/** Boot: the saved databases of every configured agent are copied to the sandbox's disk, where the agent runs them. */
|
|
86
106
|
export function restoreLocalState() {
|
|
87
107
|
if (dryRun)
|
package/dist/guest/boot/boot.js
CHANGED
|
@@ -6,7 +6,7 @@ import { writeGuides } from './guide.js';
|
|
|
6
6
|
import { setupToolchains } from '../toolchains/index.js';
|
|
7
7
|
import { agents } from '../agents/agent-installer.js';
|
|
8
8
|
import { agentShims, sbxAgentText, shimText } from '../agents/agent-files.js';
|
|
9
|
-
import { restoreLocalState } from '../agents/local-state.js';
|
|
9
|
+
import { resetMachineBound, restoreLocalState } from '../agents/local-state.js';
|
|
10
10
|
import { installShellPath } from '../setup/shell-path.js';
|
|
11
11
|
import { linkProfileDirs } from '../agents/profile-links.js';
|
|
12
12
|
import { restoreClaudeMem } from '../setup/claude-mem.js';
|
|
@@ -225,6 +225,7 @@ export class Boot {
|
|
|
225
225
|
if (session.harnessName === 'claude')
|
|
226
226
|
await soft('Claude settings', () => syncClaudeProfile(this.secrets.claudeCredentials));
|
|
227
227
|
await soft('claude-mem restore', restoreClaudeMem);
|
|
228
|
+
await soft('Agent files of the last sandbox', resetMachineBound);
|
|
228
229
|
await soft('Agent databases restore', restoreLocalState);
|
|
229
230
|
await soft('Sandbox guide for the agent', () => writeGuides(tools.summary, this.lan));
|
|
230
231
|
await soft('Claude managed settings', () => writeManagedSettings(this.gitAccess));
|
|
@@ -4,6 +4,7 @@ import { saveClaudeMem } from '../setup/claude-mem.js';
|
|
|
4
4
|
import { saveLocalState } from '../agents/local-state.js';
|
|
5
5
|
import { execCommand } from './exec.js';
|
|
6
6
|
import { sessions } from './sessions.js';
|
|
7
|
+
import { governor } from '../governor/index.js';
|
|
7
8
|
import { respond, safely } from './state.js';
|
|
8
9
|
import { run } from '../runtime/paths.js';
|
|
9
10
|
import { withRequestSecrets } from '../runtime/secrets.js';
|
|
@@ -53,6 +54,9 @@ export class Daemon {
|
|
|
53
54
|
return execCommand(req);
|
|
54
55
|
case 'restart':
|
|
55
56
|
return sessions.restart(req);
|
|
57
|
+
case 'pressure':
|
|
58
|
+
// No response: the host repeats it every few seconds while its memory stays low.
|
|
59
|
+
return governor.hostPressure(req.seconds, req.reason);
|
|
56
60
|
case 'ping':
|
|
57
61
|
return respond(req.id, { ok: true, message: 'pong (' + sessions.count + ' session(s) running)' });
|
|
58
62
|
}
|
|
@@ -2,6 +2,11 @@ import type { GuestRequest } from '../../core/types.js';
|
|
|
2
2
|
type SessionRequest = Extract<GuestRequest, {
|
|
3
3
|
kind: 'session';
|
|
4
4
|
}>;
|
|
5
|
+
/**
|
|
6
|
+
* What keeps heavy load from taking the sandbox down: the job object's memory limit for everything the agents start
|
|
7
|
+
* (ptyhost reads PTYHOST_JOB_MB) and cargo's parallel jobs sized to the sandbox's memory and the sessions building.
|
|
8
|
+
*/
|
|
9
|
+
export declare function memoryEnv(env: NodeJS.ProcessEnv, sessions: number): NodeJS.ProcessEnv;
|
|
5
10
|
/** The agent sessions of this sandbox: the running ones, the ones starting, and what happens when one ends. */
|
|
6
11
|
export declare class SessionManager {
|
|
7
12
|
private readonly live;
|
|
@@ -3,11 +3,13 @@
|
|
|
3
3
|
// (daemon/project).
|
|
4
4
|
import path from 'node:path';
|
|
5
5
|
import crypto from 'node:crypto';
|
|
6
|
+
import os from 'node:os';
|
|
6
7
|
import { spawn } from 'node:child_process';
|
|
7
8
|
import { FrameType, sendControl } from '../../shared/pty/index.js';
|
|
8
9
|
import { isWithin } from '../../shared/paths/projects.js';
|
|
9
10
|
import { now } from '../../shared/channel/run-dir.js';
|
|
10
11
|
import { SYSTEM } from '../../shared/system.js';
|
|
12
|
+
import { cargoJobs } from '../../shared/memory/index.js';
|
|
11
13
|
import { commandLine } from '../sessions/cmdline.js';
|
|
12
14
|
import { freePort } from '../runtime/ports.js';
|
|
13
15
|
import { primaryProject } from '../boot/project-status.js';
|
|
@@ -48,8 +50,20 @@ const harnessFor = (req) => {
|
|
|
48
50
|
return sent;
|
|
49
51
|
throw new Error('Agent "' + req.harness + '" is not configured for this sandbox (it runs ' + session.harnessName + ').');
|
|
50
52
|
};
|
|
53
|
+
/**
|
|
54
|
+
* What keeps heavy load from taking the sandbox down: the job object's memory limit for everything the agents start
|
|
55
|
+
* (ptyhost reads PTYHOST_JOB_MB) and cargo's parallel jobs sized to the sandbox's memory and the sessions building.
|
|
56
|
+
*/
|
|
57
|
+
export function memoryEnv(env, sessions) {
|
|
58
|
+
const out = {};
|
|
59
|
+
if (session.agentMemoryLimitMb)
|
|
60
|
+
out.PTYHOST_JOB_MB = String(session.agentMemoryLimitMb);
|
|
61
|
+
if (!env.CARGO_BUILD_JOBS)
|
|
62
|
+
out.CARGO_BUILD_JOBS = String(cargoJobs(os.cpus().length, os.totalmem() / 1024 ** 3, sessions));
|
|
63
|
+
return out;
|
|
64
|
+
}
|
|
51
65
|
/** Starts ptyhost for the agent and waits until it listens; a failure carries the tail of ptyhost's own log. */
|
|
52
|
-
const launchPtyHost = async (req, remote, env, say) => {
|
|
66
|
+
const launchPtyHost = async (req, remote, env, say, sessions) => {
|
|
53
67
|
const harness = harnessFor(req);
|
|
54
68
|
// Never refresh here: main already did, and replacing a running agent's executable would fail.
|
|
55
69
|
say('Preparing ' + req.harness);
|
|
@@ -66,7 +80,7 @@ const launchPtyHost = async (req, remote, env, say) => {
|
|
|
66
80
|
rows: 32,
|
|
67
81
|
id: req.id,
|
|
68
82
|
cwd: req.cwd,
|
|
69
|
-
env: { ...withRegistryPath(env), ...harness.environment },
|
|
83
|
+
env: { ...withRegistryPath(env), ...harness.environment, ...memoryEnv(env, sessions) },
|
|
70
84
|
remote,
|
|
71
85
|
command: commandLine(launch.file, [...base, ...req.args]),
|
|
72
86
|
restartCommand: commandLine(launch.file, [...base, ...(harness.resumeArguments ?? [])]),
|
|
@@ -145,7 +159,7 @@ export class SessionManager {
|
|
|
145
159
|
try {
|
|
146
160
|
const place = await placeFor(req, say);
|
|
147
161
|
const remote = session.networking && session.attach.enabled;
|
|
148
|
-
const { child, port, token } = await launchPtyHost(req, remote, place.env, say);
|
|
162
|
+
const { child, port, token } = await launchPtyHost(req, remote, place.env, say, this.live.size + 1);
|
|
149
163
|
const resumed = req.harness === 'claude' ? resumedConversation(req.args) : undefined;
|
|
150
164
|
const running = {
|
|
151
165
|
...status,
|
|
@@ -9,10 +9,13 @@ import { log, warn } from '../runtime/log.js';
|
|
|
9
9
|
import { adoptBootSecrets } from '../runtime/secrets.js';
|
|
10
10
|
import { errMsg } from '../../core/util/errors.js';
|
|
11
11
|
import { Daemon } from '../daemon/daemon.js';
|
|
12
|
+
import { governor } from '../governor/index.js';
|
|
12
13
|
process.on('uncaughtException', (e) => warn('daemon: unexpected error (continuing): ' + (e.stack ?? errMsg(e))));
|
|
13
14
|
process.on('unhandledRejection', (e) => warn('daemon: unexpected error (continuing): ' + errMsg(e)));
|
|
14
15
|
adoptBootSecrets();
|
|
15
16
|
log('Session daemon started (pid ' + process.pid + ').');
|
|
16
17
|
safely('port forwards', startRelays);
|
|
17
18
|
safely('audit', startProcessCollector);
|
|
19
|
+
safely('memory governor', () => governor.start());
|
|
20
|
+
log('Memory governor: ' + governor.describe());
|
|
18
21
|
new Daemon().start();
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import type { GuestThresholds, LoadProfile } from '../../shared/memory/index.js';
|
|
2
|
+
export type Priority = 'idle' | 'below' | 'normal';
|
|
3
|
+
export interface ProcSample {
|
|
4
|
+
readonly pid: number;
|
|
5
|
+
readonly name: string;
|
|
6
|
+
/** Private memory in MB. */
|
|
7
|
+
readonly mb: number;
|
|
8
|
+
readonly prio: Priority;
|
|
9
|
+
}
|
|
10
|
+
export interface MemSample {
|
|
11
|
+
readonly ramTotalMb: number;
|
|
12
|
+
readonly ramAvailMb: number;
|
|
13
|
+
readonly commitLimitMb: number;
|
|
14
|
+
readonly commitAvailMb: number;
|
|
15
|
+
/** Only the processes in the agents' job. */
|
|
16
|
+
readonly procs: readonly ProcSample[];
|
|
17
|
+
}
|
|
18
|
+
export declare const isNeverTouched: (name: string) => boolean;
|
|
19
|
+
export declare const canLower: (name: string) => boolean;
|
|
20
|
+
export declare const canPause: (name: string) => boolean;
|
|
21
|
+
export type Level = 'ok' | 'throttled' | 'suspending';
|
|
22
|
+
export interface GovernorState {
|
|
23
|
+
/** Under pressure now (with hysteresis). */
|
|
24
|
+
readonly pressure: boolean;
|
|
25
|
+
/** Samples in a row that looked calm while under pressure. */
|
|
26
|
+
readonly calm: number;
|
|
27
|
+
/** Samples under pressure so far (resets when it ends). */
|
|
28
|
+
readonly samples: number;
|
|
29
|
+
/** What was lowered and to what, by pid. */
|
|
30
|
+
readonly lowered: Readonly<Record<number, Priority>>;
|
|
31
|
+
/** Until when (ms) the last pause lasts, and when another may start. */
|
|
32
|
+
readonly pausedUntil: number;
|
|
33
|
+
readonly nextPauseAt: number;
|
|
34
|
+
/** The PC asked for slowing down until this time (ms). */
|
|
35
|
+
readonly hostUntil: number;
|
|
36
|
+
}
|
|
37
|
+
export declare const INITIAL_STATE: GovernorState;
|
|
38
|
+
export type Action = {
|
|
39
|
+
readonly kind: 'priority';
|
|
40
|
+
readonly pid: number;
|
|
41
|
+
readonly name: string;
|
|
42
|
+
readonly to: Priority;
|
|
43
|
+
} | {
|
|
44
|
+
readonly kind: 'pause';
|
|
45
|
+
readonly pid: number;
|
|
46
|
+
readonly name: string;
|
|
47
|
+
readonly ms: number;
|
|
48
|
+
};
|
|
49
|
+
export interface Decision {
|
|
50
|
+
readonly state: GovernorState;
|
|
51
|
+
readonly actions: readonly Action[];
|
|
52
|
+
readonly level: Level;
|
|
53
|
+
readonly ramFreePercent: number;
|
|
54
|
+
readonly commitPercent: number;
|
|
55
|
+
}
|
|
56
|
+
export declare const PAUSE_MS = 5000;
|
|
57
|
+
/**
|
|
58
|
+
* One step. `gentle` (vGPU on): compilers start below normal even without pressure. Programs go back to their normal
|
|
59
|
+
* priority only when pressure ends (several calm samples in a row).
|
|
60
|
+
*/
|
|
61
|
+
export declare function decide(prev: GovernorState, sample: MemSample, nowMs: number, thresholds: GuestThresholds, profile: LoadProfile): Decision;
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
/** Programs that compile or link: they may be slowed down and, as the last resort, paused for a few seconds. */
|
|
2
|
+
const COMPILERS = new Set([
|
|
3
|
+
'rustc',
|
|
4
|
+
'clippy-driver',
|
|
5
|
+
'rustdoc',
|
|
6
|
+
'cc1',
|
|
7
|
+
'cc1plus',
|
|
8
|
+
'cc1obj',
|
|
9
|
+
'collect2',
|
|
10
|
+
'gcc',
|
|
11
|
+
'g++',
|
|
12
|
+
'c++',
|
|
13
|
+
'cc',
|
|
14
|
+
'clang',
|
|
15
|
+
'clang++',
|
|
16
|
+
'clang-cl',
|
|
17
|
+
'cl',
|
|
18
|
+
'link',
|
|
19
|
+
'lld',
|
|
20
|
+
'lld-link',
|
|
21
|
+
'ld',
|
|
22
|
+
'ld.lld',
|
|
23
|
+
'as',
|
|
24
|
+
'tsc',
|
|
25
|
+
'javac',
|
|
26
|
+
]);
|
|
27
|
+
/** Build tools and workers: slowed down but never paused (a node process may be a dev server or an agent). */
|
|
28
|
+
const BUILD_TOOLS = new Set([
|
|
29
|
+
'node',
|
|
30
|
+
'dotnet',
|
|
31
|
+
'msbuild',
|
|
32
|
+
'vbcscompiler',
|
|
33
|
+
'ninja',
|
|
34
|
+
'make',
|
|
35
|
+
'mingw32-make',
|
|
36
|
+
'cmake',
|
|
37
|
+
'cargo',
|
|
38
|
+
'go',
|
|
39
|
+
'java',
|
|
40
|
+
'gradle',
|
|
41
|
+
'python',
|
|
42
|
+
]);
|
|
43
|
+
/** Never touched: the agents themselves, shells, terminals, this tool's own programs, Windows. */
|
|
44
|
+
const NEVER = new Set([
|
|
45
|
+
'claude',
|
|
46
|
+
'codex',
|
|
47
|
+
'gemini',
|
|
48
|
+
'opencode',
|
|
49
|
+
'aider',
|
|
50
|
+
'cursor-agent',
|
|
51
|
+
'cmd',
|
|
52
|
+
'powershell',
|
|
53
|
+
'pwsh',
|
|
54
|
+
'bash',
|
|
55
|
+
'sh',
|
|
56
|
+
'zsh',
|
|
57
|
+
'git',
|
|
58
|
+
'conhost',
|
|
59
|
+
'openconsole',
|
|
60
|
+
'windowsterminal',
|
|
61
|
+
'wt',
|
|
62
|
+
'ptyhost',
|
|
63
|
+
'memgov',
|
|
64
|
+
'sandboxtools',
|
|
65
|
+
'sbx-db',
|
|
66
|
+
'explorer',
|
|
67
|
+
'csrss',
|
|
68
|
+
'wininit',
|
|
69
|
+
'winlogon',
|
|
70
|
+
'services',
|
|
71
|
+
'svchost',
|
|
72
|
+
'lsass',
|
|
73
|
+
'system',
|
|
74
|
+
'smss',
|
|
75
|
+
'dwm',
|
|
76
|
+
]);
|
|
77
|
+
const key = (name) => name.toLowerCase().replace(/\.exe$/, '');
|
|
78
|
+
export const isNeverTouched = (name) => NEVER.has(key(name));
|
|
79
|
+
export const canLower = (name) => !isNeverTouched(name) && (COMPILERS.has(key(name)) || BUILD_TOOLS.has(key(name)));
|
|
80
|
+
export const canPause = (name) => !isNeverTouched(name) && COMPILERS.has(key(name));
|
|
81
|
+
export const INITIAL_STATE = {
|
|
82
|
+
pressure: false,
|
|
83
|
+
calm: 0,
|
|
84
|
+
samples: 0,
|
|
85
|
+
lowered: {},
|
|
86
|
+
pausedUntil: 0,
|
|
87
|
+
nextPauseAt: 0,
|
|
88
|
+
hostUntil: 0,
|
|
89
|
+
};
|
|
90
|
+
export const PAUSE_MS = 5000;
|
|
91
|
+
const PAUSE_COOLDOWN_MS = 10000;
|
|
92
|
+
/** Samples under pressure before programs go from below-normal to idle, and before one is paused. */
|
|
93
|
+
const IDLE_AFTER = 3;
|
|
94
|
+
const PAUSE_AFTER = 4;
|
|
95
|
+
/** Only a program this big is worth pausing. */
|
|
96
|
+
const PAUSE_MIN_MB = 300;
|
|
97
|
+
/**
|
|
98
|
+
* One step. `gentle` (vGPU on): compilers start below normal even without pressure. Programs go back to their normal
|
|
99
|
+
* priority only when pressure ends (several calm samples in a row).
|
|
100
|
+
*/
|
|
101
|
+
export function decide(prev, sample, nowMs, thresholds, profile) {
|
|
102
|
+
const ramFree = (sample.ramAvailMb / Math.max(1, sample.ramTotalMb)) * 100;
|
|
103
|
+
const commit = ((sample.commitLimitMb - sample.commitAvailMb) / Math.max(1, sample.commitLimitMb)) * 100;
|
|
104
|
+
const pcLow = nowMs < prev.hostUntil;
|
|
105
|
+
const low = ramFree < thresholds.enterAvailablePercent || commit > thresholds.enterCommitPercent || pcLow;
|
|
106
|
+
const recovered = ramFree > thresholds.exitAvailablePercent && commit < thresholds.exitCommitPercent && !pcLow;
|
|
107
|
+
let pressure = prev.pressure;
|
|
108
|
+
let calm = prev.calm;
|
|
109
|
+
let samples = prev.samples;
|
|
110
|
+
if (low) {
|
|
111
|
+
pressure = true;
|
|
112
|
+
calm = 0;
|
|
113
|
+
samples = prev.samples + 1;
|
|
114
|
+
}
|
|
115
|
+
else if (prev.pressure) {
|
|
116
|
+
calm = recovered ? prev.calm + 1 : 0;
|
|
117
|
+
if (calm >= thresholds.calmSamples) {
|
|
118
|
+
pressure = false;
|
|
119
|
+
calm = 0;
|
|
120
|
+
samples = 0;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
const actions = [];
|
|
124
|
+
const present = new Set(sample.procs.map((p) => p.pid));
|
|
125
|
+
const lowered = {};
|
|
126
|
+
for (const [pid, to] of Object.entries(prev.lowered))
|
|
127
|
+
if (present.has(Number(pid)))
|
|
128
|
+
lowered[Number(pid)] = to;
|
|
129
|
+
if (pressure) {
|
|
130
|
+
const target = samples > IDLE_AFTER ? 'idle' : 'below';
|
|
131
|
+
for (const p of sample.procs) {
|
|
132
|
+
if (!canLower(p.name) || lowered[p.pid] === target)
|
|
133
|
+
continue;
|
|
134
|
+
// Already as low as asked (or lower): only remember it.
|
|
135
|
+
if (p.prio !== target && !(target === 'below' && p.prio === 'idle'))
|
|
136
|
+
actions.push({ kind: 'priority', pid: p.pid, name: p.name, to: target });
|
|
137
|
+
lowered[p.pid] = target;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
else {
|
|
141
|
+
for (const p of sample.procs) {
|
|
142
|
+
if (!canLower(p.name))
|
|
143
|
+
continue;
|
|
144
|
+
// Where a program rests when nothing is wrong: compilers below normal in the gentle profile.
|
|
145
|
+
const base = profile === 'gentle' && canPause(p.name) ? 'below' : 'normal';
|
|
146
|
+
const was = lowered[p.pid];
|
|
147
|
+
if (prev.pressure && was !== undefined && was !== base) {
|
|
148
|
+
if (p.prio !== base)
|
|
149
|
+
actions.push({ kind: 'priority', pid: p.pid, name: p.name, to: base });
|
|
150
|
+
if (base === 'normal')
|
|
151
|
+
delete lowered[p.pid];
|
|
152
|
+
else
|
|
153
|
+
lowered[p.pid] = base;
|
|
154
|
+
}
|
|
155
|
+
else if (!prev.pressure && base === 'below' && was === undefined) {
|
|
156
|
+
if (p.prio === 'normal')
|
|
157
|
+
actions.push({ kind: 'priority', pid: p.pid, name: p.name, to: 'below' });
|
|
158
|
+
lowered[p.pid] = 'below';
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
let pausedUntil = prev.pausedUntil;
|
|
163
|
+
let nextPauseAt = prev.nextPauseAt;
|
|
164
|
+
if (pressure && samples >= PAUSE_AFTER && nowMs >= prev.nextPauseAt && nowMs >= prev.pausedUntil) {
|
|
165
|
+
const victim = [...sample.procs]
|
|
166
|
+
.filter((p) => canPause(p.name) && p.mb >= PAUSE_MIN_MB)
|
|
167
|
+
.sort((a, b) => b.mb - a.mb)[0];
|
|
168
|
+
if (victim) {
|
|
169
|
+
actions.push({ kind: 'pause', pid: victim.pid, name: victim.name, ms: PAUSE_MS });
|
|
170
|
+
pausedUntil = nowMs + PAUSE_MS;
|
|
171
|
+
nextPauseAt = pausedUntil + PAUSE_COOLDOWN_MS;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
const level = nowMs < pausedUntil ? 'suspending' : pressure ? 'throttled' : 'ok';
|
|
175
|
+
return {
|
|
176
|
+
state: { pressure, calm, samples, lowered, pausedUntil, nextPauseAt, hostUntil: prev.hostUntil },
|
|
177
|
+
actions,
|
|
178
|
+
level,
|
|
179
|
+
ramFreePercent: Math.round(ramFree),
|
|
180
|
+
commitPercent: Math.round(commit),
|
|
181
|
+
};
|
|
182
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import type { PressureStatus } from '../../shared/channel/schema.js';
|
|
2
|
+
import { type LoadProfile } from '../../shared/memory/index.js';
|
|
3
|
+
import { type GovernorState, type MemSample } from './decide.js';
|
|
4
|
+
/** What the governor needs from Windows (injectable: the tests use a fake). */
|
|
5
|
+
export interface GovernorPort {
|
|
6
|
+
setPriority(pid: number, to: 'idle' | 'below' | 'normal'): void;
|
|
7
|
+
pause(pid: number, ms: number): void;
|
|
8
|
+
}
|
|
9
|
+
/** Everything a step changes outside the decision, behind injectable functions. */
|
|
10
|
+
export interface GovernorDeps {
|
|
11
|
+
readonly port: GovernorPort;
|
|
12
|
+
readonly profile: LoadProfile;
|
|
13
|
+
readonly now: () => number;
|
|
14
|
+
/** A line in the memory log. */
|
|
15
|
+
readonly logLine: (line: string) => void;
|
|
16
|
+
/** run\pressure.json. */
|
|
17
|
+
readonly saveStatus: (status: PressureStatus) => void;
|
|
18
|
+
}
|
|
19
|
+
/** The governor's logic over a port: feed it samples; the host's "slow down" requests go to hostPressure. */
|
|
20
|
+
export declare class GovernorCore {
|
|
21
|
+
private readonly deps;
|
|
22
|
+
private state;
|
|
23
|
+
private lastAction;
|
|
24
|
+
private lastWrite;
|
|
25
|
+
private lastWriteAt;
|
|
26
|
+
private pausedName;
|
|
27
|
+
private pausedPid;
|
|
28
|
+
constructor(deps: GovernorDeps);
|
|
29
|
+
hostPressure(seconds: number, reason: string): void;
|
|
30
|
+
get current(): GovernorState;
|
|
31
|
+
onSample(sample: MemSample): void;
|
|
32
|
+
private apply;
|
|
33
|
+
}
|
|
34
|
+
/** The daemon's governor: on unless sandbox.pressureResponse is off. */
|
|
35
|
+
export declare class Governor {
|
|
36
|
+
private core;
|
|
37
|
+
describe(): string;
|
|
38
|
+
start(): void;
|
|
39
|
+
/** The host's watchdog: this PC is low for a while. */
|
|
40
|
+
hostPressure(seconds: number, reason: string): void;
|
|
41
|
+
}
|
|
42
|
+
export declare const governor: Governor;
|