windows-development-sandbox 1.10.0 → 1.11.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +64 -17
- package/config.example.json +5 -1
- package/dist/app/features/accounts/accounts.def.d.ts +122 -0
- package/dist/app/features/accounts/accounts.def.js +243 -0
- package/dist/app/features/accounts/accounts.run.d.ts +51 -0
- package/dist/app/features/accounts/accounts.run.js +125 -0
- package/dist/app/features/accounts/index.d.ts +2 -0
- package/dist/app/features/accounts/index.js +3 -0
- package/dist/app/features/agents/agent-entry.d.ts +17 -0
- package/dist/app/features/agents/agent-entry.js +50 -0
- package/dist/app/features/agents/agents.def.d.ts +65 -0
- package/dist/app/features/agents/agents.def.js +142 -0
- package/dist/app/features/agents/agents.run.d.ts +31 -0
- package/dist/app/features/agents/agents.run.js +189 -0
- package/dist/app/features/agents/index.d.ts +3 -0
- package/dist/app/features/agents/index.js +4 -0
- package/dist/app/features/apps/apps-rows.d.ts +31 -0
- package/dist/app/features/apps/apps-rows.js +73 -0
- package/dist/app/features/apps/apps.def.d.ts +181 -0
- package/dist/app/features/apps/apps.def.js +264 -0
- package/dist/app/features/apps/apps.run.d.ts +58 -0
- package/dist/app/features/apps/apps.run.js +76 -0
- package/dist/app/features/apps/index.d.ts +3 -0
- package/dist/app/features/apps/index.js +4 -0
- package/dist/app/features/data/data.def.d.ts +154 -0
- package/dist/app/features/data/data.def.js +194 -0
- package/dist/app/features/data/data.run.d.ts +46 -0
- package/dist/app/features/data/data.run.js +141 -0
- package/dist/app/features/data/index.d.ts +2 -0
- package/dist/app/features/data/index.js +3 -0
- package/dist/app/features/defs.d.ts +959 -4
- package/dist/app/features/defs.js +151 -10
- package/dist/app/features/engine/engine.def.d.ts +228 -0
- package/dist/app/features/engine/engine.def.js +194 -0
- package/dist/app/features/engine/engine.run.d.ts +72 -0
- package/dist/app/features/engine/engine.run.js +77 -0
- package/dist/app/features/engine/index.d.ts +2 -0
- package/dist/app/features/engine/index.js +4 -0
- package/dist/app/features/files/files.def.d.ts +51 -0
- package/dist/app/features/files/files.def.js +38 -0
- package/dist/app/features/files/files.run.d.ts +20 -0
- package/dist/app/features/files/files.run.js +59 -0
- package/dist/app/features/files/index.d.ts +2 -0
- package/dist/app/features/files/index.js +3 -0
- package/dist/app/features/github/github.def.d.ts +80 -0
- package/dist/app/features/github/github.def.js +142 -0
- package/dist/app/features/github/github.run.d.ts +36 -0
- package/dist/app/features/github/github.run.js +59 -0
- package/dist/app/features/github/index.d.ts +2 -0
- package/dist/app/features/github/index.js +3 -0
- package/dist/app/features/health/health.def.d.ts +275 -0
- package/dist/app/features/health/health.def.js +297 -0
- package/dist/app/features/health/health.run.d.ts +125 -0
- package/dist/app/features/health/health.run.js +204 -0
- package/dist/app/features/health/index.d.ts +2 -0
- package/dist/app/features/health/index.js +3 -0
- package/dist/app/features/logs/index.d.ts +2 -0
- package/dist/app/features/logs/index.js +3 -0
- package/dist/app/features/logs/logs.def.d.ts +78 -0
- package/dist/app/features/logs/logs.def.js +115 -0
- package/dist/app/features/logs/logs.run.d.ts +20 -0
- package/dist/app/features/logs/logs.run.js +42 -0
- package/dist/app/features/projects/index.d.ts +2 -0
- package/dist/app/features/projects/index.js +3 -0
- package/dist/app/features/projects/projects.def.d.ts +101 -0
- package/dist/app/features/projects/projects.def.js +208 -0
- package/dist/app/features/projects/projects.run.d.ts +56 -0
- package/dist/app/features/projects/projects.run.js +155 -0
- package/dist/app/features/sandbox/sandbox.def.js +11 -5
- package/dist/app/features/sessions/sessions.def.js +3 -0
- package/dist/app/features/settings/categories.def.js +3 -2
- package/dist/{cli/menu/settings/share.d.ts → app/features/settings/settings-share.d.ts} +1 -1
- package/dist/{cli/menu/settings/share.js → app/features/settings/settings-share.js} +3 -2
- package/dist/app/features/settings/settings.def.d.ts +22 -5
- package/dist/app/features/settings/settings.def.js +81 -6
- package/dist/app/features/settings/settings.run.d.ts +17 -0
- package/dist/app/features/settings/settings.run.js +89 -4
- package/dist/app/features/storage/index.d.ts +2 -0
- package/dist/app/features/storage/index.js +3 -0
- package/dist/app/features/storage/storage.def.d.ts +133 -0
- package/dist/app/features/storage/storage.def.js +220 -0
- package/dist/app/features/storage/storage.run.d.ts +62 -0
- package/dist/app/features/storage/storage.run.js +370 -0
- package/dist/app/features/updates/index.d.ts +3 -0
- package/dist/app/features/updates/index.js +4 -0
- package/dist/app/features/updates/update-lines.d.ts +13 -0
- package/dist/app/features/updates/update-lines.js +61 -0
- package/dist/app/features/updates/updates.def.d.ts +89 -0
- package/dist/app/features/updates/updates.def.js +224 -0
- package/dist/app/features/updates/updates.run.d.ts +48 -0
- package/dist/app/features/updates/updates.run.js +154 -0
- package/dist/app/features/vpn/index.d.ts +2 -0
- package/dist/app/features/vpn/index.js +3 -0
- package/dist/app/features/vpn/vpn.def.d.ts +112 -0
- package/dist/app/features/vpn/vpn.def.js +174 -0
- package/dist/app/features/vpn/vpn.run.d.ts +37 -0
- package/dist/app/features/vpn/vpn.run.js +54 -0
- package/dist/app/features/web/index.d.ts +2 -0
- package/dist/app/features/web/index.js +3 -0
- package/dist/app/features/web/web.def.d.ts +33 -0
- package/dist/app/features/web/web.def.js +90 -0
- package/dist/app/features/web/web.run.d.ts +24 -0
- package/dist/app/features/web/web.run.js +93 -0
- package/dist/app/kernel/define.d.ts +10 -1
- package/dist/app/kernel/io.d.ts +34 -0
- package/dist/app/kernel/io.js +9 -0
- package/dist/app/kernel/rpc.d.ts +17 -0
- package/dist/app/kernel/text.d.ts +2 -0
- package/dist/app/kernel/text.js +7 -0
- package/dist/app/kernel/view.d.ts +24 -1
- package/dist/app/kernel/view.js +1 -1
- package/dist/app/registry.js +74 -1
- package/dist/cli/args.js +1 -1
- package/dist/cli/commands/context.d.ts +7 -0
- package/dist/cli/commands/context.js +29 -2
- package/dist/cli/commands/engine.js +5 -58
- package/dist/cli/commands/github.d.ts +2 -0
- package/dist/cli/commands/github.js +11 -0
- package/dist/cli/commands/index.d.ts +3 -5
- package/dist/cli/commands/index.js +3 -5
- package/dist/cli/commands/launch/launch.js +21 -4
- package/dist/cli/commands/launch/running.js +4 -1
- package/dist/cli/commands/maintenance/config.js +1 -6
- package/dist/cli/commands/maintenance/index.d.ts +0 -1
- package/dist/cli/commands/maintenance/index.js +1 -2
- package/dist/cli/commands/maintenance/logs.js +27 -32
- package/dist/cli/commands/maintenance/migrate.d.ts +0 -8
- package/dist/cli/commands/maintenance/migrate.js +2 -44
- package/dist/cli/commands/maintenance/update.d.ts +0 -19
- package/dist/cli/commands/maintenance/update.js +1 -99
- package/dist/cli/commands/projects/index.d.ts +0 -1
- package/dist/cli/commands/projects/index.js +0 -1
- package/dist/cli/commands/registry.d.ts +1 -1
- package/dist/cli/commands/registry.js +29 -11
- package/dist/cli/commands/repair/checks/data.js +1 -1
- package/dist/cli/commands/repair/checks/hcs.js +28 -1
- package/dist/cli/commands/repair/checks/sandbox.js +1 -1
- package/dist/cli/commands/repair/health-run.d.ts +30 -0
- package/dist/cli/commands/repair/health-run.js +32 -0
- package/dist/cli/commands/repair/printer.d.ts +2 -2
- package/dist/cli/commands/repair/printer.js +2 -11
- package/dist/cli/commands/repair/run.d.ts +1 -21
- package/dist/cli/commands/repair/run.js +13 -70
- package/dist/cli/commands/storage/index.d.ts +0 -1
- package/dist/cli/commands/storage/index.js +0 -1
- package/dist/cli/commands/storage/offer.js +6 -2
- package/dist/cli/commands/vpn.d.ts +1 -3
- package/dist/cli/commands/vpn.js +8 -89
- package/dist/cli/commands/web.d.ts +2 -1
- package/dist/cli/commands/web.js +14 -78
- package/dist/cli/index.js +3 -2
- package/dist/cli/manifest.d.ts +16 -153
- package/dist/cli/manifest.js +20 -50
- package/dist/cli/menu/command-form.js +1 -2
- package/dist/cli/menu/io-menu.d.ts +2 -2
- package/dist/cli/menu/io-menu.js +6 -4
- package/dist/cli/menu/menu.js +1 -1
- package/dist/cli/menu/pages/accounts-page.d.ts +5 -17
- package/dist/cli/menu/pages/accounts-page.js +28 -170
- package/dist/cli/menu/pages/agents-page.d.ts +17 -18
- package/dist/cli/menu/pages/agents-page.js +67 -124
- package/dist/cli/menu/pages/apps-page.d.ts +15 -8
- package/dist/cli/menu/pages/apps-page.js +121 -29
- package/dist/cli/menu/pages/list-page.js +10 -1
- package/dist/cli/menu/pages/maintenance-page.d.ts +51 -52
- package/dist/cli/menu/pages/maintenance-page.js +246 -427
- package/dist/cli/menu/pages/sandbox-page.d.ts +3 -5
- package/dist/cli/menu/pages/sandbox-page.js +34 -112
- package/dist/cli/menu/pages/settings-page.d.ts +21 -3
- package/dist/cli/menu/pages/settings-page.js +89 -17
- package/dist/cli/menu/render-view.js +2 -1
- package/dist/cli/menu/settings/index.d.ts +0 -1
- package/dist/cli/menu/settings/index.js +3 -3
- package/dist/cli/menu/views.js +28 -0
- package/dist/cli/operations/handler.js +7 -3
- package/dist/cli/operations/input.d.ts +1 -1
- package/dist/cli/operations/input.js +29 -5
- package/dist/cli/operations/io-cli.js +9 -1
- package/dist/cli/operations/spec.js +8 -2
- package/dist/cli/output/render-view.js +2 -0
- package/dist/cli/{commands/data/collect.js → services/data-collect.js} +2 -2
- package/dist/cli/{commands/data/remove.js → services/data-remove.js} +2 -2
- package/dist/cli/services/data-service.d.ts +1 -1
- package/dist/cli/services/data-service.js +2 -2
- package/dist/cli/services/databases-service.d.ts +5 -0
- package/dist/cli/services/databases-service.js +15 -0
- package/dist/cli/services/health-service.d.ts +8 -4
- package/dist/cli/services/health-service.js +10 -8
- package/dist/cli/services/index.d.ts +4 -1
- package/dist/cli/services/index.js +4 -1
- package/dist/cli/services/logs-service.d.ts +7 -0
- package/dist/cli/services/logs-service.js +13 -0
- package/dist/cli/services/storage-service.d.ts +19 -0
- package/dist/cli/services/storage-service.js +71 -0
- package/dist/cli/services/vpn-service.d.ts +6 -4
- package/dist/cli/services/vpn-service.js +5 -11
- package/dist/cli/services/web-service.d.ts +4 -3
- package/dist/cli/services/web-service.js +12 -32
- package/dist/core/config/defaults.js +2 -1
- package/dist/core/schema/config.d.ts +5 -0
- package/dist/core/schema/config.js +2 -0
- package/dist/core/schema/github.d.ts +4 -0
- package/dist/core/schema/github.js +7 -0
- package/dist/core/schema/index.d.ts +1 -0
- package/dist/core/schema/index.js +1 -0
- package/dist/core/schema/profile.d.ts +1 -0
- package/dist/core/schema/profile.js +3 -0
- package/dist/core/schema/sandbox.js +3 -3
- package/dist/core/schema/toolchains.js +2 -2
- package/dist/core/types.d.ts +6 -3
- package/dist/guest/boot/boot.js +8 -0
- package/dist/guest/daemon/daemon.js +1 -1
- package/dist/guest/daemon/sessions.d.ts +3 -2
- package/dist/guest/daemon/sessions.js +38 -7
- package/dist/guest/governor/core.d.ts +44 -0
- package/dist/guest/governor/core.js +124 -0
- package/dist/guest/governor/decide.d.ts +46 -18
- package/dist/guest/governor/decide.js +136 -82
- package/dist/guest/governor/governor.d.ts +2 -38
- package/dist/guest/governor/governor.js +33 -113
- package/dist/guest/governor/index.d.ts +1 -0
- package/dist/guest/governor/index.js +1 -0
- package/dist/guest/network/firewall.d.ts +2 -0
- package/dist/guest/network/firewall.js +3 -3
- package/dist/guest/sessions/viewer.js +5 -1
- package/dist/guest/setup/github-token.d.ts +7 -0
- package/dist/guest/setup/github-token.js +65 -0
- package/dist/guest/toolchains/languages/node.js +11 -1
- package/dist/guest/toolchains/native/rust-extras.js +2 -2
- package/dist/guest/toolchains/tools/cli.d.ts +8 -0
- package/dist/guest/toolchains/tools/cli.js +35 -2
- package/dist/guest/vpn/openvpn.d.ts +5 -0
- package/dist/guest/vpn/openvpn.js +14 -1
- package/dist/guest/vpn/vpn.js +55 -16
- package/dist/guest/vpn/wireguard.js +2 -0
- package/dist/host/channel/attach.d.ts +1 -0
- package/dist/host/channel/attach.js +1 -0
- package/dist/host/channel/channel.d.ts +1 -1
- package/dist/host/channel/channel.js +2 -2
- package/dist/host/engines/hcs/check.d.ts +1 -0
- package/dist/host/engines/hcs/check.js +1 -1
- package/dist/host/engines/hcs/engine.d.ts +1 -1
- package/dist/host/engines/hcs/engine.js +6 -4
- package/dist/host/engines/hcs/helper.d.ts +11 -0
- package/dist/host/engines/hcs/helper.js +31 -2
- package/dist/host/engines/hcs/leftovers.d.ts +42 -0
- package/dist/host/engines/hcs/leftovers.js +101 -0
- package/dist/host/engines/index.d.ts +1 -0
- package/dist/host/engines/index.js +1 -0
- package/dist/host/github/deliver.d.ts +13 -0
- package/dist/host/github/deliver.js +51 -0
- package/dist/host/github/index.d.ts +2 -0
- package/dist/host/github/index.js +3 -0
- package/dist/host/github/token.d.ts +21 -0
- package/dist/host/github/token.js +74 -0
- package/dist/host/launch/generate.js +11 -5
- package/dist/host/launch/index.d.ts +1 -1
- package/dist/host/launch/index.js +1 -1
- package/dist/host/launch/session-file.js +1 -2
- package/dist/host/launch/wsb-file.d.ts +11 -7
- package/dist/host/launch/wsb-file.js +30 -12
- package/dist/host/life/host-memory.d.ts +18 -0
- package/dist/host/life/host-memory.js +66 -0
- package/dist/host/life/watchdog.d.ts +9 -0
- package/dist/host/life/watchdog.js +17 -1
- package/dist/host/sandbox/tasklist.d.ts +6 -0
- package/dist/host/sandbox/tasklist.js +37 -0
- package/dist/host/secrets/launch-secrets.d.ts +2 -1
- package/dist/host/secrets/launch-secrets.js +4 -2
- package/dist/host/vpn/status.js +13 -3
- package/dist/host/web/backend.d.ts +1 -3
- package/dist/host/web/index.d.ts +2 -1
- package/dist/host/web/index.js +2 -1
- package/dist/host/web/live.d.ts +23 -0
- package/dist/host/web/live.js +107 -0
- package/dist/host/web/rpc.d.ts +6 -1
- package/dist/host/web/rpc.js +23 -31
- package/dist/host/web/runner.d.ts +4 -0
- package/dist/host/web/runner.js +12 -1
- package/dist/host/web/server.d.ts +30 -2
- package/dist/host/web/server.js +87 -29
- package/dist/host/web/state.d.ts +1 -0
- package/dist/host/web/state.js +2 -0
- package/dist/runtime/agent.js +30 -6
- package/dist/runtime/daemon.js +337 -177
- package/dist/runtime/db.js +30 -6
- package/dist/runtime/main.js +389 -77
- package/dist/runtime/netproxy.js +30 -6
- package/dist/runtime/view.js +495 -146
- package/dist/selftest/app.test.js +632 -12
- package/dist/selftest/channel.test.js +18 -1
- package/dist/selftest/cli.test.js +1 -1
- package/dist/selftest/config.test.js +1 -1
- package/dist/selftest/contained.test.js +1 -1
- package/dist/selftest/data.test.js +1 -2
- package/dist/selftest/engine.test.js +3 -1
- package/dist/selftest/github.test.d.ts +2 -0
- package/dist/selftest/github.test.js +243 -0
- package/dist/selftest/hcs.test.js +105 -8
- package/dist/selftest/health.test.js +71 -0
- package/dist/selftest/heavy-load.test.js +132 -72
- package/dist/selftest/index.js +4 -0
- package/dist/selftest/layout.test.js +8 -0
- package/dist/selftest/live-terminal.test.js +74 -0
- package/dist/selftest/menu-screens.js +171 -56
- package/dist/selftest/menu.test.js +54 -37
- package/dist/selftest/migrate.test.js +14 -12
- package/dist/selftest/powershell-variables.test.d.ts +2 -0
- package/dist/selftest/powershell-variables.test.js +61 -0
- package/dist/selftest/support/engine-golden.js +1 -0
- package/dist/selftest/support/fixtures.d.ts +4 -0
- package/dist/selftest/support/web-preview.d.ts +1 -0
- package/dist/selftest/support/web-preview.js +856 -0
- package/dist/selftest/update-service.test.js +15 -8
- package/dist/selftest/vpn.test.js +86 -2
- package/dist/selftest/web.test.js +58 -11
- package/dist/shared/channel/run-dir.d.ts +2 -0
- package/dist/shared/channel/run-dir.js +3 -0
- package/dist/shared/channel/schema.d.ts +7 -0
- package/dist/shared/channel/schema.js +9 -1
- package/dist/shared/channel/secrets.d.ts +1 -0
- package/dist/shared/channel/secrets.js +3 -0
- package/dist/shared/github/index.d.ts +1 -0
- package/dist/shared/github/index.js +2 -0
- package/dist/shared/github/token.d.ts +29 -0
- package/dist/shared/github/token.js +89 -0
- package/dist/shared/memory/policy.d.ts +33 -12
- package/dist/shared/memory/policy.js +50 -19
- package/dist/shared/pty/ctrl-c.d.ts +18 -0
- package/dist/shared/pty/ctrl-c.js +36 -0
- package/dist/shared/pty/index.d.ts +1 -0
- package/dist/shared/pty/index.js +1 -0
- package/dist/shared/pty/terminal.d.ts +2 -0
- package/dist/shared/pty/terminal.js +21 -2
- package/dist/shared/vpn/kill-switch.d.ts +13 -2
- package/dist/shared/vpn/kill-switch.js +88 -8
- package/dist/shared/web/protocol.d.ts +0 -4
- package/dist/sync/watcher.d.ts +2 -0
- package/dist/sync/watcher.js +8 -3
- package/dist/web/index.html +2 -2
- package/dist/web/{main-T5DMCHYV.css → main-MU5XWZMS.css} +1 -1
- package/dist/web/main-SLQNJRXD.js +219 -0
- package/native/csharp/HcsHost/AssemblyInfo.cs +3 -3
- package/native/csharp/HostTools/AssemblyInfo.cs +3 -3
- package/native/csharp/HostTools/MemoryStatus.cs +58 -2
- package/native/csharp/HostTools/Program.cs +7 -1
- package/package.json +10 -3
- package/sandbox/csharp/MemGov.cs +240 -38
- package/sandbox/csharp/PtyHost.cs +104 -15
- package/sandbox/csharp/SandboxTools/CpuCap.cs +50 -1
- package/sandbox/csharp/SandboxTools/Program.cs +1 -1
- package/sandbox/scripts/repair-wmi-services.ps1 +26 -0
- package/schemas/config.schema.json +19 -5
- package/schemas/sandbox-config.schema.json +7 -3
- package/dist/cli/commands/accounts.d.ts +0 -2
- package/dist/cli/commands/accounts.js +0 -96
- package/dist/cli/commands/data/clean.d.ts +0 -3
- package/dist/cli/commands/data/clean.js +0 -60
- package/dist/cli/commands/data/index.d.ts +0 -4
- package/dist/cli/commands/data/index.js +0 -62
- package/dist/cli/commands/maintenance/clean.d.ts +0 -2
- package/dist/cli/commands/maintenance/clean.js +0 -24
- package/dist/cli/commands/maintenance/config-share.d.ts +0 -12
- package/dist/cli/commands/maintenance/config-share.js +0 -80
- package/dist/cli/commands/projects/projects.d.ts +0 -2
- package/dist/cli/commands/projects/projects.js +0 -162
- package/dist/cli/commands/storage/contained.d.ts +0 -3
- package/dist/cli/commands/storage/contained.js +0 -179
- package/dist/cli/commands/storage/storage.d.ts +0 -8
- package/dist/cli/commands/storage/storage.js +0 -179
- package/dist/cli/menu/add-agent.d.ts +0 -47
- package/dist/cli/menu/add-agent.js +0 -168
- package/dist/cli/menu/apps.d.ts +0 -69
- package/dist/cli/menu/apps.js +0 -214
- package/dist/cli/menu/data-folder.d.ts +0 -18
- package/dist/cli/menu/data-folder.js +0 -99
- package/dist/cli/menu/share-settings.d.ts +0 -21
- package/dist/cli/menu/share-settings.js +0 -112
- package/dist/cli/menu/vpn-login.d.ts +0 -16
- package/dist/cli/menu/vpn-login.js +0 -74
- package/dist/web/main-NRRS5O6Z.js +0 -157
- /package/dist/cli/{commands/data/collect.d.ts → services/data-collect.d.ts} +0 -0
- /package/dist/cli/{commands/data/remove.d.ts → services/data-remove.d.ts} +0 -0
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
// The apps feature's work: the rows of a scope, an app switched on or off, your own programs saved, and the request
|
|
2
|
+
// page opened in this PC's browser. Writes go through ConfigFile like the settings do (comments kept, nothing written
|
|
3
|
+
// unless the file stays valid).
|
|
4
|
+
import { APPS } from '../../../shared/apps/index.js';
|
|
5
|
+
import { errMsg, fail } from '../../../core/util/index.js';
|
|
6
|
+
import { openIssuePage } from '../../../host/web/index.js';
|
|
7
|
+
import { implement } from '../../context.js';
|
|
8
|
+
import { allowedText, fieldOf, valueFromText } from '../../kernel/index.js';
|
|
9
|
+
import { settingsFiles } from '../settings/settings.run.js';
|
|
10
|
+
import { appRows, customRows, CUSTOM_KEY, INSTALL, SAVED } from './apps-rows.js';
|
|
11
|
+
import { listApps, requestApp, requestAppUrl, setCustomApps, toggleApp } from './apps.def.js';
|
|
12
|
+
export const listAppsRun = implement(listApps, (ctx, input) => {
|
|
13
|
+
const file = settingsFiles(ctx)[input.scope];
|
|
14
|
+
const own = input.scope === 'user';
|
|
15
|
+
const node = own ? file.schema.child('apps')?.child('custom') : undefined;
|
|
16
|
+
return {
|
|
17
|
+
scope: input.scope,
|
|
18
|
+
file: file.file,
|
|
19
|
+
exists: file.exists,
|
|
20
|
+
apps: appRows(file, ctx.dataPath),
|
|
21
|
+
custom: own ? customRows(file) : [],
|
|
22
|
+
...(own ? { customValue: SAVED.custom(file) } : {}),
|
|
23
|
+
...(node ? { customField: fieldOf(node, CUSTOM_KEY, 'Your own programs') } : {}),
|
|
24
|
+
};
|
|
25
|
+
});
|
|
26
|
+
export const toggleAppRun = implement(toggleApp, (ctx, input) => {
|
|
27
|
+
const file = settingsFiles(ctx)[input.scope];
|
|
28
|
+
const entry = APPS.find((a) => a.id === input.id);
|
|
29
|
+
if (!entry || (file.isProject && entry.setting))
|
|
30
|
+
fail('"' + input.id + '" is not an app this scope can change.', 'Pick one of the apps the Apps page lists.');
|
|
31
|
+
const name = entry.name;
|
|
32
|
+
// A setting-backed app (VS Code, Windows Terminal) is its setting; a catalogue app is one id in apps.install.
|
|
33
|
+
const key = entry.setting ? entry.setting.split('.') : INSTALL;
|
|
34
|
+
let value = input.on;
|
|
35
|
+
if (!entry.setting) {
|
|
36
|
+
const current = SAVED.install(file) ?? [];
|
|
37
|
+
const next = input.on
|
|
38
|
+
? current.includes(entry.id)
|
|
39
|
+
? current
|
|
40
|
+
: [...current, entry.id]
|
|
41
|
+
: current.filter((id) => id !== entry.id);
|
|
42
|
+
// Your own file keeps no empty list (back to the default); a project file always says what it chooses.
|
|
43
|
+
value = next.length || file.isProject ? next : undefined;
|
|
44
|
+
}
|
|
45
|
+
const outcome = file.set(key, value);
|
|
46
|
+
if (typeof outcome === 'object')
|
|
47
|
+
fail('Could not change ' + key.join('.') + ': ' + outcome.problems.join('; '), 'Nothing was written.');
|
|
48
|
+
const said = input.on ? name + ' is installed in every sandbox.' : name + ' is no longer installed.';
|
|
49
|
+
return { message: said + (outcome === 'unchanged' ? ' (it was already)' : '') };
|
|
50
|
+
});
|
|
51
|
+
export const setCustomAppsRun = implement(setCustomApps, (ctx, input) => {
|
|
52
|
+
if (input.scope === 'project')
|
|
53
|
+
fail('Your own programs are set in your own settings only.', 'Switch to All projects.');
|
|
54
|
+
const file = settingsFiles(ctx).user;
|
|
55
|
+
const node = file.schema.child('apps')?.child('custom');
|
|
56
|
+
if (!node)
|
|
57
|
+
fail('Your own programs are not a setting of this version.', 'Update sandbox, then try again.');
|
|
58
|
+
const value = typeof input.value === 'string' ? valueFromText(node, input.value) : input.value;
|
|
59
|
+
const problem = node.check(value);
|
|
60
|
+
if (problem !== true)
|
|
61
|
+
fail('That does not work for apps.custom: ' + problem, allowedText(node));
|
|
62
|
+
const outcome = file.set(CUSTOM_KEY, value);
|
|
63
|
+
if (typeof outcome === 'object')
|
|
64
|
+
fail('Could not change apps.custom: ' + outcome.problems.join('; '), 'Nothing was written.');
|
|
65
|
+
return { message: 'Your own programs are saved.' };
|
|
66
|
+
});
|
|
67
|
+
export const requestAppRun = implement(requestApp, () => {
|
|
68
|
+
const url = requestAppUrl();
|
|
69
|
+
try {
|
|
70
|
+
openIssuePage(url);
|
|
71
|
+
}
|
|
72
|
+
catch (e) {
|
|
73
|
+
fail(errMsg(e), 'Open it yourself: ' + url);
|
|
74
|
+
}
|
|
75
|
+
return { url };
|
|
76
|
+
});
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { type Page } from '../../kernel/index.js';
|
|
3
|
+
export declare const DATA_AREAS: readonly ["tools", "databases", "state", "logs", "data", "host"];
|
|
4
|
+
export type DataAreaName = (typeof DATA_AREAS)[number];
|
|
5
|
+
/** The heading of each area's section (the CLI's group labels). */
|
|
6
|
+
export declare const AREA_LABEL: Readonly<Record<DataAreaName, string>>;
|
|
7
|
+
declare const DataEntrySchema: z.ZodObject<{
|
|
8
|
+
area: z.ZodEnum<{
|
|
9
|
+
host: "host";
|
|
10
|
+
tools: "tools";
|
|
11
|
+
databases: "databases";
|
|
12
|
+
state: "state";
|
|
13
|
+
data: "data";
|
|
14
|
+
logs: "logs";
|
|
15
|
+
}>;
|
|
16
|
+
name: z.ZodString;
|
|
17
|
+
path: z.ZodString;
|
|
18
|
+
bytes: z.ZodNumber;
|
|
19
|
+
size: z.ZodString;
|
|
20
|
+
target: z.ZodNullable<z.ZodString>;
|
|
21
|
+
}, z.core.$strip>;
|
|
22
|
+
declare const DiskSchema: z.ZodObject<{
|
|
23
|
+
drive: z.ZodString;
|
|
24
|
+
totalBytes: z.ZodNumber;
|
|
25
|
+
freeBytes: z.ZodNumber;
|
|
26
|
+
usedBytes: z.ZodNumber;
|
|
27
|
+
holdsStorage: z.ZodBoolean;
|
|
28
|
+
used: z.ZodString;
|
|
29
|
+
usedPercent: z.ZodNumber;
|
|
30
|
+
free: z.ZodString;
|
|
31
|
+
total: z.ZodString;
|
|
32
|
+
}, z.core.$strip>;
|
|
33
|
+
export declare const DataShowSchema: z.ZodObject<{
|
|
34
|
+
dataPath: z.ZodString;
|
|
35
|
+
storageRoot: z.ZodString;
|
|
36
|
+
totalBytes: z.ZodNumber;
|
|
37
|
+
total: z.ZodString;
|
|
38
|
+
storageShare: z.ZodString;
|
|
39
|
+
areaTotals: z.ZodRecord<z.ZodString, z.ZodString>;
|
|
40
|
+
entries: z.ZodArray<z.ZodObject<{
|
|
41
|
+
area: z.ZodEnum<{
|
|
42
|
+
host: "host";
|
|
43
|
+
tools: "tools";
|
|
44
|
+
databases: "databases";
|
|
45
|
+
state: "state";
|
|
46
|
+
data: "data";
|
|
47
|
+
logs: "logs";
|
|
48
|
+
}>;
|
|
49
|
+
name: z.ZodString;
|
|
50
|
+
path: z.ZodString;
|
|
51
|
+
bytes: z.ZodNumber;
|
|
52
|
+
size: z.ZodString;
|
|
53
|
+
target: z.ZodNullable<z.ZodString>;
|
|
54
|
+
}, z.core.$strip>>;
|
|
55
|
+
disks: z.ZodArray<z.ZodObject<{
|
|
56
|
+
drive: z.ZodString;
|
|
57
|
+
totalBytes: z.ZodNumber;
|
|
58
|
+
freeBytes: z.ZodNumber;
|
|
59
|
+
usedBytes: z.ZodNumber;
|
|
60
|
+
holdsStorage: z.ZodBoolean;
|
|
61
|
+
used: z.ZodString;
|
|
62
|
+
usedPercent: z.ZodNumber;
|
|
63
|
+
free: z.ZodString;
|
|
64
|
+
total: z.ZodString;
|
|
65
|
+
}, z.core.$strip>>;
|
|
66
|
+
}, z.core.$strip>;
|
|
67
|
+
export type DataShow = z.output<typeof DataShowSchema>;
|
|
68
|
+
export type DataEntryRow = z.output<typeof DataEntrySchema>;
|
|
69
|
+
export type DataDisk = z.output<typeof DiskSchema>;
|
|
70
|
+
export declare const showData: import("../../kernel/define.js").QueryDef<z.ZodObject<{}, z.core.$strip>, z.ZodObject<{
|
|
71
|
+
dataPath: z.ZodString;
|
|
72
|
+
storageRoot: z.ZodString;
|
|
73
|
+
totalBytes: z.ZodNumber;
|
|
74
|
+
total: z.ZodString;
|
|
75
|
+
storageShare: z.ZodString;
|
|
76
|
+
areaTotals: z.ZodRecord<z.ZodString, z.ZodString>;
|
|
77
|
+
entries: z.ZodArray<z.ZodObject<{
|
|
78
|
+
area: z.ZodEnum<{
|
|
79
|
+
host: "host";
|
|
80
|
+
tools: "tools";
|
|
81
|
+
databases: "databases";
|
|
82
|
+
state: "state";
|
|
83
|
+
data: "data";
|
|
84
|
+
logs: "logs";
|
|
85
|
+
}>;
|
|
86
|
+
name: z.ZodString;
|
|
87
|
+
path: z.ZodString;
|
|
88
|
+
bytes: z.ZodNumber;
|
|
89
|
+
size: z.ZodString;
|
|
90
|
+
target: z.ZodNullable<z.ZodString>;
|
|
91
|
+
}, z.core.$strip>>;
|
|
92
|
+
disks: z.ZodArray<z.ZodObject<{
|
|
93
|
+
drive: z.ZodString;
|
|
94
|
+
totalBytes: z.ZodNumber;
|
|
95
|
+
freeBytes: z.ZodNumber;
|
|
96
|
+
usedBytes: z.ZodNumber;
|
|
97
|
+
holdsStorage: z.ZodBoolean;
|
|
98
|
+
used: z.ZodString;
|
|
99
|
+
usedPercent: z.ZodNumber;
|
|
100
|
+
free: z.ZodString;
|
|
101
|
+
total: z.ZodString;
|
|
102
|
+
}, z.core.$strip>>;
|
|
103
|
+
}, z.core.$strip>, "data.show">;
|
|
104
|
+
export declare const cleanData: import("../../kernel/define.js").OperationDef<z.ZodObject<{
|
|
105
|
+
targets: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
106
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
107
|
+
message: z.ZodString;
|
|
108
|
+
freedBytes: z.ZodNumber;
|
|
109
|
+
}, z.core.$strip>, "data.clean">;
|
|
110
|
+
export declare const pruneStorage: import("../../kernel/define.js").OperationDef<z.ZodObject<{
|
|
111
|
+
days: z.ZodDefault<z.ZodNumber>;
|
|
112
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
113
|
+
message: z.ZodString;
|
|
114
|
+
removed: z.ZodBoolean;
|
|
115
|
+
}, z.core.$strip>, "data.prune">;
|
|
116
|
+
/** The data page: the disks, then every kept folder in one table (its total as the summary, clean-up as its action). */
|
|
117
|
+
export declare function dataPage(o: DataShow): Page;
|
|
118
|
+
export declare const dataView: import("../../kernel/define.js").ViewDef<{
|
|
119
|
+
data: import("../../kernel/define.js").QueryDef<z.ZodObject<{}, z.core.$strip>, z.ZodObject<{
|
|
120
|
+
dataPath: z.ZodString;
|
|
121
|
+
storageRoot: z.ZodString;
|
|
122
|
+
totalBytes: z.ZodNumber;
|
|
123
|
+
total: z.ZodString;
|
|
124
|
+
storageShare: z.ZodString;
|
|
125
|
+
areaTotals: z.ZodRecord<z.ZodString, z.ZodString>;
|
|
126
|
+
entries: z.ZodArray<z.ZodObject<{
|
|
127
|
+
area: z.ZodEnum<{
|
|
128
|
+
host: "host";
|
|
129
|
+
tools: "tools";
|
|
130
|
+
databases: "databases";
|
|
131
|
+
state: "state";
|
|
132
|
+
data: "data";
|
|
133
|
+
logs: "logs";
|
|
134
|
+
}>;
|
|
135
|
+
name: z.ZodString;
|
|
136
|
+
path: z.ZodString;
|
|
137
|
+
bytes: z.ZodNumber;
|
|
138
|
+
size: z.ZodString;
|
|
139
|
+
target: z.ZodNullable<z.ZodString>;
|
|
140
|
+
}, z.core.$strip>>;
|
|
141
|
+
disks: z.ZodArray<z.ZodObject<{
|
|
142
|
+
drive: z.ZodString;
|
|
143
|
+
totalBytes: z.ZodNumber;
|
|
144
|
+
freeBytes: z.ZodNumber;
|
|
145
|
+
usedBytes: z.ZodNumber;
|
|
146
|
+
holdsStorage: z.ZodBoolean;
|
|
147
|
+
used: z.ZodString;
|
|
148
|
+
usedPercent: z.ZodNumber;
|
|
149
|
+
free: z.ZodString;
|
|
150
|
+
total: z.ZodString;
|
|
151
|
+
}, z.core.$strip>>;
|
|
152
|
+
}, z.core.$strip>, "data.show">;
|
|
153
|
+
}, Record<string, never>, "data">;
|
|
154
|
+
export {};
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
// The data area: what the sandbox keeps between runs (toolchains, databases, agent state, logs, what this PC keeps for
|
|
2
|
+
// it), deleting chosen parts of it, and the clean-up of old launch folders. Pure: the page builder is here, the work is
|
|
3
|
+
// in data.run.ts. Sizes come as bytes and as words (the run formats them: this file cannot import core/disk).
|
|
4
|
+
import { z } from 'zod';
|
|
5
|
+
import { action, defineOperation, defineQuery, defineView, fieldOf, SchemaNode, } from '../../kernel/index.js';
|
|
6
|
+
export const DATA_AREAS = ['tools', 'databases', 'state', 'logs', 'data', 'host'];
|
|
7
|
+
/** The heading of each area's section (the CLI's group labels). */
|
|
8
|
+
export const AREA_LABEL = {
|
|
9
|
+
tools: 'Toolchains',
|
|
10
|
+
databases: 'Databases',
|
|
11
|
+
state: 'Agent state',
|
|
12
|
+
logs: 'Logs',
|
|
13
|
+
data: 'Other',
|
|
14
|
+
host: 'On this PC',
|
|
15
|
+
};
|
|
16
|
+
const DataEntrySchema = z.object({
|
|
17
|
+
area: z.enum(DATA_AREAS).describe('Which kind of data it is'),
|
|
18
|
+
name: z.string().describe('The folder as listed (tools: its name; others: area/name)'),
|
|
19
|
+
path: z.string().describe('Its full path on this PC'),
|
|
20
|
+
bytes: z.number().describe('Its size in bytes (links count 0)'),
|
|
21
|
+
size: z.string().describe('Its size in words, e.g. 1.5 KB'),
|
|
22
|
+
target: z.string().nullable().describe('What sandbox data clean calls it; null when it is kept on purpose'),
|
|
23
|
+
});
|
|
24
|
+
const DiskSchema = z.object({
|
|
25
|
+
drive: z.string().describe('The drive, e.g. C:\\'),
|
|
26
|
+
totalBytes: z.number().describe('Its size in bytes'),
|
|
27
|
+
freeBytes: z.number().describe('Free bytes'),
|
|
28
|
+
usedBytes: z.number().describe('Used bytes'),
|
|
29
|
+
holdsStorage: z.boolean().describe('The sandbox keeps its files on this drive'),
|
|
30
|
+
used: z.string().describe('Used, in words'),
|
|
31
|
+
usedPercent: z.number().describe('Used, in percent of the size (rounded)'),
|
|
32
|
+
free: z.string().describe('Free, in words'),
|
|
33
|
+
total: z.string().describe('Size, in words'),
|
|
34
|
+
});
|
|
35
|
+
export const DataShowSchema = z.object({
|
|
36
|
+
dataPath: z.string().describe('The data folder (C:\\AgentData inside the sandbox)'),
|
|
37
|
+
storageRoot: z.string().describe('The storage folder that holds it'),
|
|
38
|
+
totalBytes: z.number().describe('Everything listed, in bytes'),
|
|
39
|
+
total: z.string().describe('Everything listed, in words'),
|
|
40
|
+
storageShare: z.string().describe('"<- sandbox storage (<total> of it)": the note on the storage drive'),
|
|
41
|
+
areaTotals: z.record(z.string(), z.string()).describe("Each area's total in words"),
|
|
42
|
+
entries: z.array(DataEntrySchema).describe('What is stored, by area, biggest first'),
|
|
43
|
+
disks: z.array(DiskSchema).describe("This PC's drives"),
|
|
44
|
+
});
|
|
45
|
+
export const showData = defineQuery({
|
|
46
|
+
id: 'data.show',
|
|
47
|
+
title: 'Stored data',
|
|
48
|
+
summary: 'show what is kept between sandboxes (tools, databases, logins, logs), or delete some of it',
|
|
49
|
+
input: z.object({}),
|
|
50
|
+
output: DataShowSchema,
|
|
51
|
+
cli: {
|
|
52
|
+
name: 'data',
|
|
53
|
+
action: 'show',
|
|
54
|
+
json: true,
|
|
55
|
+
// The --json shape `sandbox data` has always printed.
|
|
56
|
+
shapeJson: (o) => ({
|
|
57
|
+
dataPath: o.dataPath,
|
|
58
|
+
storageRoot: o.storageRoot,
|
|
59
|
+
totalBytes: o.totalBytes,
|
|
60
|
+
entries: o.entries.map(({ area, name, path, bytes }) => ({ area, name, path, bytes })),
|
|
61
|
+
disks: o.disks.map(({ drive, totalBytes, freeBytes, usedBytes, holdsStorage }) => ({
|
|
62
|
+
drive,
|
|
63
|
+
totalBytes,
|
|
64
|
+
freeBytes,
|
|
65
|
+
usedBytes,
|
|
66
|
+
holdsStorage,
|
|
67
|
+
})),
|
|
68
|
+
}),
|
|
69
|
+
},
|
|
70
|
+
});
|
|
71
|
+
const MessageSchema = z.object({ message: z.string().describe('What happened') });
|
|
72
|
+
export const cleanData = defineOperation({
|
|
73
|
+
id: 'data.clean',
|
|
74
|
+
title: 'Delete stored data…',
|
|
75
|
+
summary: 'delete chosen parts of what is kept between sandboxes',
|
|
76
|
+
input: z.object({
|
|
77
|
+
targets: z.array(z.string()).default([]).describe('what to clean, e.g. tools/go databases logs'),
|
|
78
|
+
}),
|
|
79
|
+
output: MessageSchema.extend({
|
|
80
|
+
freedBytes: z.number().describe('Bytes freed (0 when nothing was removed)'),
|
|
81
|
+
}),
|
|
82
|
+
danger: true,
|
|
83
|
+
text: (o) => o.message,
|
|
84
|
+
next: (o) => (o.freedBytes > 0 ? 'sandbox data (see what is left)' : undefined),
|
|
85
|
+
cli: { name: 'data', action: 'clean', positional: ['targets'] },
|
|
86
|
+
});
|
|
87
|
+
const PruneInputSchema = z.object({
|
|
88
|
+
days: z.number().int().min(1).default(7).describe('launch folders older than this many days'),
|
|
89
|
+
});
|
|
90
|
+
export const pruneStorage = defineOperation({
|
|
91
|
+
id: 'data.prune',
|
|
92
|
+
title: 'Clean up…',
|
|
93
|
+
summary: 'delete old launch folders, logs and leftovers',
|
|
94
|
+
input: PruneInputSchema,
|
|
95
|
+
output: MessageSchema.extend({ removed: z.boolean().describe('Something was deleted') }),
|
|
96
|
+
text: (o) => o.message,
|
|
97
|
+
next: (o) => (o.removed ? 'sandbox data (see what else is saved, and clean it)' : undefined),
|
|
98
|
+
cli: {
|
|
99
|
+
name: 'clean',
|
|
100
|
+
group: 'Data',
|
|
101
|
+
flags: { days: { flag: '--days', value: 'n' } },
|
|
102
|
+
yes: 'do not ask before deleting',
|
|
103
|
+
},
|
|
104
|
+
});
|
|
105
|
+
const DAYS_FIELD = fieldOf(new SchemaNode(PruneInputSchema).child('days'), ['days']);
|
|
106
|
+
/** The data page: the disks, then every kept folder in one table (its total as the summary, clean-up as its action). */
|
|
107
|
+
export function dataPage(o) {
|
|
108
|
+
const disks = {
|
|
109
|
+
id: 'disks',
|
|
110
|
+
title: 'Disks',
|
|
111
|
+
columns: [
|
|
112
|
+
{ key: 'drive', label: 'DRIVE' },
|
|
113
|
+
{ key: 'used', label: 'USED' },
|
|
114
|
+
{ key: 'free', label: 'FREE' },
|
|
115
|
+
{ key: 'size', label: 'SIZE' },
|
|
116
|
+
{ key: 'note', label: '' },
|
|
117
|
+
],
|
|
118
|
+
// The web shows each drive as a row (a table with the storage note does not fit a phone); the CLI keeps the table.
|
|
119
|
+
columnsOn: 'cli',
|
|
120
|
+
items: o.disks.map((d) => ({
|
|
121
|
+
id: 'disk:' + d.drive,
|
|
122
|
+
label: d.drive,
|
|
123
|
+
hint: d.used + ' used · ' + d.free + ' free of ' + d.total, // the menu's wording
|
|
124
|
+
...(d.holdsStorage ? { description: 'The sandbox keeps its files on this drive.' } : {}),
|
|
125
|
+
cells: {
|
|
126
|
+
drive: d.drive,
|
|
127
|
+
used: d.used + ' (' + d.usedPercent + '%)',
|
|
128
|
+
free: d.free,
|
|
129
|
+
size: d.total,
|
|
130
|
+
note: d.holdsStorage ? o.storageShare : '',
|
|
131
|
+
},
|
|
132
|
+
})),
|
|
133
|
+
notes: [{ text: 'Persistent data for the sandbox: ' + o.dataPath + ' (C:\\AgentData inside)' }],
|
|
134
|
+
};
|
|
135
|
+
// Every folder in one table, grouped by kind (the order of DATA_AREAS), biggest first within a kind.
|
|
136
|
+
const kindRank = (area) => DATA_AREAS.indexOf(area);
|
|
137
|
+
const rows = [...o.entries].sort((a, b) => kindRank(a.area) - kindRank(b.area) || b.bytes - a.bytes);
|
|
138
|
+
const kept = {
|
|
139
|
+
id: 'kept',
|
|
140
|
+
title: 'What the sandbox keeps',
|
|
141
|
+
summary: o.total + ' in all',
|
|
142
|
+
columns: [
|
|
143
|
+
{ key: 'kind', label: 'KIND' },
|
|
144
|
+
{ key: 'name', label: 'NAME' },
|
|
145
|
+
{ key: 'size', label: 'SIZE' },
|
|
146
|
+
{ key: 'folder', label: 'FOLDER' },
|
|
147
|
+
],
|
|
148
|
+
items: rows.map((e) => {
|
|
149
|
+
const del = e.target
|
|
150
|
+
? action(cleanData, { targets: [e.target] }, { label: 'Delete', key: 'x', verb: 'delete' })
|
|
151
|
+
: undefined;
|
|
152
|
+
return {
|
|
153
|
+
id: 'entry:' + e.name,
|
|
154
|
+
label: e.name,
|
|
155
|
+
hint: e.size,
|
|
156
|
+
cells: { kind: AREA_LABEL[e.area], name: e.name, size: e.size, folder: e.path },
|
|
157
|
+
...(del ? { primary: del } : {}),
|
|
158
|
+
};
|
|
159
|
+
}),
|
|
160
|
+
actions: [
|
|
161
|
+
action(pruneStorage, {}, {
|
|
162
|
+
label: 'Clean up…',
|
|
163
|
+
verb: 'choose what',
|
|
164
|
+
description: 'Delete caches, old sandboxes and other leftovers (the clean command, with its options).',
|
|
165
|
+
fields: [DAYS_FIELD],
|
|
166
|
+
}),
|
|
167
|
+
],
|
|
168
|
+
notes: [
|
|
169
|
+
...(o.entries.length
|
|
170
|
+
? []
|
|
171
|
+
: [{ text: 'Nothing stored yet. Toolchains, databases and agent logins appear here after the first start.' }]),
|
|
172
|
+
...keptNote(o),
|
|
173
|
+
{
|
|
174
|
+
text: 'Free space with: sandbox data clean <target...> (e.g. tools/go, databases/postgres-18, logs, launches)',
|
|
175
|
+
tone: 'muted',
|
|
176
|
+
only: 'cli',
|
|
177
|
+
},
|
|
178
|
+
],
|
|
179
|
+
};
|
|
180
|
+
return { title: 'Data', sections: [disks, kept] };
|
|
181
|
+
}
|
|
182
|
+
/** The folders kept on purpose (not deleted here), named in one note. */
|
|
183
|
+
function keptNote(o) {
|
|
184
|
+
const names = o.entries.filter((e) => !e.target).map((e) => e.name);
|
|
185
|
+
return names.length ? [{ text: 'Kept on this PC on purpose, not deleted here: ' + names.join(', ') + '.' }] : [];
|
|
186
|
+
}
|
|
187
|
+
export const dataView = defineView({
|
|
188
|
+
id: 'data',
|
|
189
|
+
title: 'Data',
|
|
190
|
+
summary: 'What the sandbox keeps between runs, and deleting parts of it.',
|
|
191
|
+
queries: { data: showData },
|
|
192
|
+
operations: [cleanData, pruneStorage],
|
|
193
|
+
build: ({ data }) => dataPage(data),
|
|
194
|
+
});
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
export declare const showDataRun: import("../../kernel/define.js").Implementation<import("../../kernel/define.js").QueryDef<import("zod").ZodObject<{}, import("zod/v4/core").$strip>, import("zod").ZodObject<{
|
|
2
|
+
dataPath: import("zod").ZodString;
|
|
3
|
+
storageRoot: import("zod").ZodString;
|
|
4
|
+
totalBytes: import("zod").ZodNumber;
|
|
5
|
+
total: import("zod").ZodString;
|
|
6
|
+
storageShare: import("zod").ZodString;
|
|
7
|
+
areaTotals: import("zod").ZodRecord<import("zod").ZodString, import("zod").ZodString>;
|
|
8
|
+
entries: import("zod").ZodArray<import("zod").ZodObject<{
|
|
9
|
+
area: import("zod").ZodEnum<{
|
|
10
|
+
host: "host";
|
|
11
|
+
tools: "tools";
|
|
12
|
+
databases: "databases";
|
|
13
|
+
state: "state";
|
|
14
|
+
data: "data";
|
|
15
|
+
logs: "logs";
|
|
16
|
+
}>;
|
|
17
|
+
name: import("zod").ZodString;
|
|
18
|
+
path: import("zod").ZodString;
|
|
19
|
+
bytes: import("zod").ZodNumber;
|
|
20
|
+
size: import("zod").ZodString;
|
|
21
|
+
target: import("zod").ZodNullable<import("zod").ZodString>;
|
|
22
|
+
}, import("zod/v4/core").$strip>>;
|
|
23
|
+
disks: import("zod").ZodArray<import("zod").ZodObject<{
|
|
24
|
+
drive: import("zod").ZodString;
|
|
25
|
+
totalBytes: import("zod").ZodNumber;
|
|
26
|
+
freeBytes: import("zod").ZodNumber;
|
|
27
|
+
usedBytes: import("zod").ZodNumber;
|
|
28
|
+
holdsStorage: import("zod").ZodBoolean;
|
|
29
|
+
used: import("zod").ZodString;
|
|
30
|
+
usedPercent: import("zod").ZodNumber;
|
|
31
|
+
free: import("zod").ZodString;
|
|
32
|
+
total: import("zod").ZodString;
|
|
33
|
+
}, import("zod/v4/core").$strip>>;
|
|
34
|
+
}, import("zod/v4/core").$strip>, "data.show">, import("../../../cli/commands/context.js").Context>;
|
|
35
|
+
export declare const cleanDataRun: import("../../kernel/define.js").Implementation<import("../../kernel/define.js").OperationDef<import("zod").ZodObject<{
|
|
36
|
+
targets: import("zod").ZodDefault<import("zod").ZodArray<import("zod").ZodString>>;
|
|
37
|
+
}, import("zod/v4/core").$strip>, import("zod").ZodObject<{
|
|
38
|
+
message: import("zod").ZodString;
|
|
39
|
+
freedBytes: import("zod").ZodNumber;
|
|
40
|
+
}, import("zod/v4/core").$strip>, "data.clean">, import("../../../cli/commands/context.js").Context>;
|
|
41
|
+
export declare const pruneStorageRun: import("../../kernel/define.js").Implementation<import("../../kernel/define.js").OperationDef<import("zod").ZodObject<{
|
|
42
|
+
days: import("zod").ZodDefault<import("zod").ZodNumber>;
|
|
43
|
+
}, import("zod/v4/core").$strip>, import("zod").ZodObject<{
|
|
44
|
+
message: import("zod").ZodString;
|
|
45
|
+
removed: import("zod").ZodBoolean;
|
|
46
|
+
}, import("zod/v4/core").$strip>, "data.prune">, import("../../../cli/commands/context.js").Context>;
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
// The data area's work: measuring what is kept, deleting chosen parts of it (DataService: never follows links, refuses
|
|
2
|
+
// while a sandbox runs) and the clean-up of old launch folders, logs and leftovers. Talks only through io.
|
|
3
|
+
import { humanBytes } from '../../../core/disk.js';
|
|
4
|
+
import { fail } from '../../../core/util/index.js';
|
|
5
|
+
import { cleanTargetOf, DataService } from '../../../cli/services/index.js';
|
|
6
|
+
import { describePrune, pruneStorage as prune } from '../../../host/storage/index.js';
|
|
7
|
+
import { isSandboxRunning } from '../../../host/sandbox/index.js';
|
|
8
|
+
import { RunDir } from '../../../shared/channel/index.js';
|
|
9
|
+
import { implement } from '../../context.js';
|
|
10
|
+
import { cancelled } from '../../kernel/index.js';
|
|
11
|
+
import { cleanData, DATA_AREAS, pruneStorage, showData } from './data.def.js';
|
|
12
|
+
const MEASURING = 'Measuring the saved data (big folders take a moment)';
|
|
13
|
+
const NOTHING_CHOSEN = 'Nothing chosen, nothing removed.';
|
|
14
|
+
/** The page's numbers, in bytes and in words (the definition cannot format them). */
|
|
15
|
+
function showOf(report) {
|
|
16
|
+
const total = report.totalBytes;
|
|
17
|
+
const areaTotals = {};
|
|
18
|
+
for (const area of DATA_AREAS) {
|
|
19
|
+
const sum = report.entries.filter((e) => e.area === area).reduce((n, e) => n + e.bytes, 0);
|
|
20
|
+
areaTotals[area] = humanBytes(sum);
|
|
21
|
+
}
|
|
22
|
+
return {
|
|
23
|
+
dataPath: report.dataPath,
|
|
24
|
+
storageRoot: report.storageRoot,
|
|
25
|
+
totalBytes: total,
|
|
26
|
+
total: humanBytes(total),
|
|
27
|
+
storageShare: '<- sandbox storage (' + humanBytes(total) + ' of it)',
|
|
28
|
+
areaTotals,
|
|
29
|
+
entries: report.entries.map((e) => ({
|
|
30
|
+
area: e.area,
|
|
31
|
+
name: e.name,
|
|
32
|
+
path: e.path,
|
|
33
|
+
bytes: e.bytes,
|
|
34
|
+
size: humanBytes(e.bytes),
|
|
35
|
+
target: cleanTargetOf(e),
|
|
36
|
+
})),
|
|
37
|
+
disks: report.disks.map((d) => ({
|
|
38
|
+
drive: d.drive,
|
|
39
|
+
totalBytes: d.totalBytes,
|
|
40
|
+
freeBytes: d.freeBytes,
|
|
41
|
+
usedBytes: d.usedBytes,
|
|
42
|
+
holdsStorage: d.holdsStorage,
|
|
43
|
+
used: humanBytes(d.usedBytes),
|
|
44
|
+
usedPercent: Math.round((d.usedBytes / d.totalBytes) * 100),
|
|
45
|
+
free: humanBytes(d.freeBytes),
|
|
46
|
+
total: humanBytes(d.totalBytes),
|
|
47
|
+
})),
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
/** Rows as aligned columns, as the command line's tables print them (the last column is not padded). */
|
|
51
|
+
function alignedLines(rows) {
|
|
52
|
+
const width = (i) => Math.max(0, ...rows.map((r) => (r[i] ?? '').length));
|
|
53
|
+
return rows.map((row) => row.map((cell, i) => (i === row.length - 1 ? cell : cell.padEnd(width(i) + 2))).join(''));
|
|
54
|
+
}
|
|
55
|
+
/** No target named: what can be cleaned, with sizes, to tick from. Undefined when nothing can be. */
|
|
56
|
+
async function pickTargets(service, io) {
|
|
57
|
+
io.progress(MEASURING);
|
|
58
|
+
const choices = service.entries().flatMap((e) => {
|
|
59
|
+
const target = cleanTargetOf(e);
|
|
60
|
+
return target ? [{ value: target, label: target.padEnd(28) + humanBytes(e.bytes) }] : [];
|
|
61
|
+
});
|
|
62
|
+
if (!choices.length)
|
|
63
|
+
return undefined;
|
|
64
|
+
return io.checklist({
|
|
65
|
+
title: 'What do you want to delete? (space ticks, enter confirms)',
|
|
66
|
+
choices,
|
|
67
|
+
noTerminal: {
|
|
68
|
+
message: 'Which data should be cleaned?',
|
|
69
|
+
fix: 'Name them: sandbox data clean logs tools/go (what exists: sandbox data)',
|
|
70
|
+
},
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
export const showDataRun = implement(showData, (ctx) => {
|
|
74
|
+
return showOf(new DataService(ctx).report());
|
|
75
|
+
});
|
|
76
|
+
export const cleanDataRun = implement(cleanData, async (ctx, input, io) => {
|
|
77
|
+
const service = new DataService(ctx);
|
|
78
|
+
let inputs = input.targets;
|
|
79
|
+
if (!inputs.length) {
|
|
80
|
+
const chosen = await pickTargets(service, io);
|
|
81
|
+
if (!chosen?.length)
|
|
82
|
+
return { message: NOTHING_CHOSEN, freedBytes: 0 };
|
|
83
|
+
inputs = chosen;
|
|
84
|
+
}
|
|
85
|
+
const plan = service.plan(inputs);
|
|
86
|
+
if (!plan.present.length)
|
|
87
|
+
return {
|
|
88
|
+
message: 'Nothing to remove: ' + plan.targets.map((t) => t.target).join(', ') + ' do(es) not exist.',
|
|
89
|
+
freedBytes: 0,
|
|
90
|
+
};
|
|
91
|
+
for (const line of alignedLines(plan.present.map((t) => [' ' + t.target, humanBytes(t.bytes), t.path])))
|
|
92
|
+
io.log(line);
|
|
93
|
+
for (const t of plan.present)
|
|
94
|
+
if (t.warning)
|
|
95
|
+
io.log('Warning: ' + t.target + ' ' + t.warning + '.', 'warn');
|
|
96
|
+
const names = plan.present.map((t) => t.target).join(', ');
|
|
97
|
+
const confirmed = plan.present.some((t) => t.target === 'all')
|
|
98
|
+
? await io.confirm({
|
|
99
|
+
title: 'This cannot be undone; the next sandbox starts from scratch and reinstalls everything.',
|
|
100
|
+
typed: 'all',
|
|
101
|
+
danger: true,
|
|
102
|
+
noTerminal: { message: 'Nothing removed.', fix: 'Add --yes to delete without asking.' },
|
|
103
|
+
})
|
|
104
|
+
: await io.confirm({
|
|
105
|
+
title: 'Delete ' + names + ' (' + humanBytes(plan.totalBytes) + ')? This cannot be undone.',
|
|
106
|
+
yes: 'Delete',
|
|
107
|
+
danger: true,
|
|
108
|
+
noTerminal: { message: 'Cannot ask here (no terminal).', fix: 'Add --yes to delete without asking.' },
|
|
109
|
+
});
|
|
110
|
+
if (!confirmed)
|
|
111
|
+
cancelled('Nothing removed.');
|
|
112
|
+
const outcome = service.clean(plan);
|
|
113
|
+
if (outcome.failed.length)
|
|
114
|
+
fail('Could not remove everything: ' + outcome.failed.join('; '), 'Close programs using those folders and run the same command again.');
|
|
115
|
+
return {
|
|
116
|
+
message: 'Removed ' +
|
|
117
|
+
names +
|
|
118
|
+
' and freed ' +
|
|
119
|
+
humanBytes(outcome.freedBytes) +
|
|
120
|
+
(outcome.touchedData ? '; the next sandbox reinstalls what it needs.' : '.'),
|
|
121
|
+
freedBytes: outcome.freedBytes,
|
|
122
|
+
};
|
|
123
|
+
});
|
|
124
|
+
export const pruneStorageRun = implement(pruneStorage, async (ctx, input, io) => {
|
|
125
|
+
const running = isSandboxRunning() ? new RunDir(ctx.dataPath).readSandboxStatus()?.launchId : undefined;
|
|
126
|
+
const options = { launchDays: input.days, keep: running ? [running] : [] };
|
|
127
|
+
const found = prune(ctx.storageRoot, { ...options, dryRun: true });
|
|
128
|
+
if (found.launches + found.logs + found.leftovers === 0)
|
|
129
|
+
return { message: 'Nothing to clean.', removed: false };
|
|
130
|
+
io.log('Can be removed: ' + describePrune(found).replace(' removed', '') + '.');
|
|
131
|
+
const confirmed = await io.confirm({
|
|
132
|
+
title: 'Delete them?',
|
|
133
|
+
yes: 'Delete',
|
|
134
|
+
danger: true,
|
|
135
|
+
noTerminal: { message: 'Cannot ask here (no terminal).', fix: 'Add --yes to delete without asking.' },
|
|
136
|
+
});
|
|
137
|
+
if (!confirmed)
|
|
138
|
+
cancelled('Nothing removed.');
|
|
139
|
+
const removed = describePrune(prune(ctx.storageRoot, options)).replace(' removed', '');
|
|
140
|
+
return { message: 'Removed ' + removed + '.', removed: true };
|
|
141
|
+
});
|