windows-development-sandbox 1.5.0 → 1.7.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/README.md +1 -0
- package/config.example.json +17 -1
- package/dist/cli/args.d.ts +13 -2
- package/dist/cli/args.js +95 -24
- package/dist/cli/commands/accounts.js +45 -17
- package/dist/cli/commands/context.d.ts +2 -0
- package/dist/cli/commands/context.js +9 -2
- package/dist/cli/commands/data/clean.js +32 -9
- package/dist/cli/commands/index.d.ts +1 -0
- package/dist/cli/commands/index.js +1 -0
- package/dist/cli/commands/launch/add-root.d.ts +3 -2
- package/dist/cli/commands/launch/add-root.js +11 -10
- package/dist/cli/commands/launch/launch.js +57 -4
- package/dist/cli/commands/launch/prepare.js +3 -1
- package/dist/cli/commands/maintenance/audit.js +1 -1
- package/dist/cli/commands/maintenance/clean.d.ts +1 -1
- package/dist/cli/commands/maintenance/clean.js +17 -3
- package/dist/cli/commands/maintenance/config.d.ts +1 -1
- package/dist/cli/commands/maintenance/config.js +112 -10
- package/dist/cli/commands/maintenance/doctor.d.ts +1 -1
- package/dist/cli/commands/maintenance/doctor.js +2 -4
- package/dist/cli/commands/maintenance/migrate.d.ts +2 -1
- package/dist/cli/commands/maintenance/migrate.js +19 -4
- package/dist/cli/commands/maintenance/sync.js +2 -0
- package/dist/cli/commands/maintenance/update.d.ts +2 -0
- package/dist/cli/commands/maintenance/update.js +27 -4
- package/dist/cli/commands/projects/here.js +12 -7
- package/dist/cli/commands/projects/projects.js +26 -17
- package/dist/cli/commands/registry.js +7 -0
- package/dist/cli/commands/repair/checks/agents.d.ts +2 -0
- package/dist/cli/commands/repair/checks/agents.js +70 -0
- package/dist/cli/commands/repair/checks/common.d.ts +8 -0
- package/dist/cli/commands/repair/checks/common.js +22 -0
- package/dist/cli/commands/repair/checks/data.d.ts +2 -0
- package/dist/cli/commands/repair/checks/data.js +241 -0
- package/dist/cli/commands/repair/checks/index.d.ts +2 -0
- package/dist/cli/commands/repair/checks/index.js +20 -0
- package/dist/cli/commands/repair/checks/install.d.ts +5 -0
- package/dist/cli/commands/repair/checks/install.js +318 -0
- package/dist/cli/commands/repair/checks/machine.d.ts +2 -0
- package/dist/cli/commands/repair/checks/machine.js +232 -0
- package/dist/cli/commands/repair/checks/network.d.ts +6 -0
- package/dist/cli/commands/repair/checks/network.js +60 -0
- package/dist/cli/commands/repair/checks/pc.d.ts +4 -0
- package/dist/cli/commands/repair/checks/pc.js +55 -0
- package/dist/cli/commands/repair/checks/sandbox.d.ts +2 -0
- package/dist/cli/commands/repair/checks/sandbox.js +267 -0
- package/dist/cli/commands/repair/checks/settings.d.ts +2 -0
- package/dist/cli/commands/repair/checks/settings.js +169 -0
- package/dist/cli/commands/repair/checks/vpn.d.ts +2 -0
- package/dist/cli/commands/repair/checks/vpn.js +53 -0
- package/dist/cli/commands/repair/engine.d.ts +32 -0
- package/dist/cli/commands/repair/engine.js +127 -0
- package/dist/cli/commands/repair/env.d.ts +7 -0
- package/dist/cli/commands/repair/env.js +49 -0
- package/dist/cli/commands/repair/index.d.ts +1 -9
- package/dist/cli/commands/repair/index.js +2 -54
- package/dist/cli/commands/repair/log.d.ts +17 -0
- package/dist/cli/commands/repair/log.js +82 -0
- package/dist/cli/commands/repair/printer.d.ts +32 -0
- package/dist/cli/commands/repair/printer.js +132 -0
- package/dist/cli/commands/repair/run.d.ts +33 -0
- package/dist/cli/commands/repair/run.js +133 -0
- package/dist/cli/commands/repair/types.d.ts +97 -9
- package/dist/cli/commands/repair/types.js +11 -7
- package/dist/cli/commands/resume.js +2 -2
- package/dist/cli/commands/sessions/list.js +5 -2
- package/dist/cli/commands/sessions/status.d.ts +2 -0
- package/dist/cli/commands/sessions/status.js +27 -6
- package/dist/cli/commands/setup/index.d.ts +5 -0
- package/dist/cli/commands/setup/index.js +25 -1
- package/dist/cli/commands/storage/index.d.ts +2 -0
- package/dist/cli/commands/storage/index.js +2 -0
- package/dist/cli/commands/storage/offer.d.ts +3 -0
- package/dist/cli/commands/storage/offer.js +85 -0
- package/dist/cli/commands/storage/storage.d.ts +8 -0
- package/dist/cli/commands/storage/storage.js +171 -0
- package/dist/cli/commands/user-config.js +1 -1
- package/dist/cli/commands/vpn.d.ts +4 -0
- package/dist/cli/commands/vpn.js +75 -0
- package/dist/cli/commands/web.d.ts +4 -0
- package/dist/cli/commands/web.js +95 -0
- package/dist/cli/history.js +1 -1
- package/dist/cli/index.js +46 -3
- package/dist/cli/manifest.d.ts +303 -29
- package/dist/cli/manifest.js +173 -43
- package/dist/cli/menu/add-agent.d.ts +47 -0
- package/dist/cli/menu/add-agent.js +168 -0
- package/dist/cli/menu/apps.d.ts +31 -2
- package/dist/cli/menu/apps.js +44 -5
- package/dist/cli/menu/command-fields.d.ts +18 -0
- package/dist/cli/menu/command-fields.js +61 -0
- package/dist/cli/menu/command-form.d.ts +22 -0
- package/dist/cli/menu/command-form.js +169 -46
- package/dist/cli/menu/data-folder.d.ts +18 -0
- package/dist/cli/menu/data-folder.js +99 -0
- package/dist/cli/menu/menu.d.ts +1 -1
- package/dist/cli/menu/menu.js +11 -8
- package/dist/cli/menu/pages/accounts-page.js +55 -24
- package/dist/cli/menu/pages/agents-page.d.ts +66 -0
- package/dist/cli/menu/pages/agents-page.js +338 -0
- package/dist/cli/menu/pages/apps-page.js +1 -2
- package/dist/cli/menu/pages/list-page.d.ts +16 -3
- package/dist/cli/menu/pages/list-page.js +40 -8
- package/dist/cli/menu/pages/maintenance-page.d.ts +9 -0
- package/dist/cli/menu/pages/maintenance-page.js +161 -72
- package/dist/cli/menu/pages/sandbox-page.d.ts +3 -0
- package/dist/cli/menu/pages/sandbox-page.js +132 -43
- package/dist/cli/menu/pages/sessions-page.d.ts +4 -0
- package/dist/cli/menu/pages/sessions-page.js +41 -25
- package/dist/cli/menu/pages/settings-page.d.ts +8 -4
- package/dist/cli/menu/pages/settings-page.js +36 -13
- package/dist/cli/menu/settings/categories.d.ts +2 -0
- package/dist/cli/menu/settings/categories.js +19 -44
- package/dist/cli/menu/settings/collections/collection-editor.d.ts +7 -1
- package/dist/cli/menu/settings/collections/collection-editor.js +12 -8
- package/dist/cli/menu/settings/collections/map-editor.js +5 -1
- package/dist/cli/menu/settings/collections/object-list-editor.js +2 -2
- package/dist/cli/menu/settings/collections/object-map-editor.js +2 -2
- package/dist/cli/menu/settings/collections/string-list-editor.d.ts +11 -1
- package/dist/cli/menu/settings/collections/string-list-editor.js +23 -0
- package/dist/cli/menu/settings/index.d.ts +1 -1
- package/dist/cli/menu/settings/index.js +1 -1
- package/dist/cli/menu/settings/object-editor.d.ts +5 -1
- package/dist/cli/menu/settings/object-editor.js +15 -4
- package/dist/cli/menu/settings/path-kind.d.ts +20 -0
- package/dist/cli/menu/settings/path-kind.js +44 -0
- package/dist/cli/menu/settings/schema-node.d.ts +9 -0
- package/dist/cli/menu/settings/schema-node.js +26 -0
- package/dist/cli/menu/settings/value-editor.d.ts +5 -0
- package/dist/cli/menu/settings/value-editor.js +51 -18
- package/dist/cli/menu/several.js +7 -5
- package/dist/cli/menu/shell.d.ts +37 -10
- package/dist/cli/menu/shell.js +90 -10
- package/dist/cli/menu/vpn-login.d.ts +16 -0
- package/dist/cli/menu/vpn-login.js +66 -0
- package/dist/cli/output/print.d.ts +2 -0
- package/dist/cli/output/print.js +8 -1
- package/dist/cli/services/accounts-service.d.ts +2 -0
- package/dist/cli/services/accounts-service.js +2 -2
- package/dist/cli/services/health-service.d.ts +0 -6
- package/dist/cli/services/health-service.js +5 -42
- package/dist/cli/services/index.d.ts +3 -1
- package/dist/cli/services/index.js +3 -1
- package/dist/cli/services/migrate-service.js +1 -1
- package/dist/cli/services/update-service.d.ts +2 -0
- package/dist/cli/services/update-service.js +13 -6
- package/dist/cli/services/vpn-service.d.ts +28 -0
- package/dist/cli/services/vpn-service.js +46 -0
- package/dist/cli/services/web-service.d.ts +22 -0
- package/dist/cli/services/web-service.js +111 -0
- package/dist/cli/tui/app.d.ts +6 -3
- package/dist/cli/tui/app.js +12 -5
- package/dist/cli/tui/dialogs/path-listing.d.ts +43 -0
- package/dist/cli/tui/dialogs/path-listing.js +127 -0
- package/dist/cli/tui/dialogs/path-picker.d.ts +67 -0
- package/dist/cli/tui/dialogs/path-picker.js +423 -0
- package/dist/cli/tui/dialogs/text-screen.d.ts +6 -0
- package/dist/cli/tui/dialogs/text-screen.js +10 -3
- package/dist/cli/tui/frame.d.ts +7 -10
- package/dist/cli/tui/frame.js +19 -10
- package/dist/cli/tui/index.d.ts +4 -3
- package/dist/cli/tui/index.js +2 -1
- package/dist/cli/tui/list/list-screen.d.ts +14 -2
- package/dist/cli/tui/list/list-screen.js +68 -32
- package/dist/cli/tui/list/list-types.d.ts +8 -4
- package/dist/cli/tui/nav.d.ts +29 -0
- package/dist/cli/tui/nav.js +67 -0
- package/dist/cli/validate.d.ts +1 -1
- package/dist/cli/validate.js +3 -3
- package/dist/cli/version.d.ts +2 -0
- package/dist/cli/version.js +11 -0
- package/dist/core/config/defaults.js +5 -1
- package/dist/core/config/loader.js +12 -2
- package/dist/core/local-config/overrides.js +1 -0
- package/dist/core/prompt.d.ts +19 -0
- package/dist/core/prompt.js +43 -3
- package/dist/core/schema/common.d.ts +6 -0
- package/dist/core/schema/common.js +8 -0
- package/dist/core/schema/config.d.ts +23 -0
- package/dist/core/schema/config.js +10 -1
- package/dist/core/schema/harness.d.ts +1 -0
- package/dist/core/schema/harness.js +8 -2
- package/dist/core/schema/index.d.ts +3 -1
- package/dist/core/schema/index.js +3 -1
- package/dist/core/schema/profile.d.ts +1 -0
- package/dist/core/schema/profile.js +3 -0
- package/dist/core/schema/redact.d.ts +13 -0
- package/dist/core/schema/redact.js +75 -0
- package/dist/core/schema/sandbox.js +1 -0
- package/dist/core/schema/vpn.d.ts +17 -0
- package/dist/core/schema/vpn.js +22 -0
- package/dist/core/schema/web.d.ts +6 -0
- package/dist/core/schema/web.js +14 -0
- package/dist/core/types.d.ts +26 -0
- package/dist/guest/agents/agent-files.d.ts +49 -0
- package/dist/guest/agents/agent-files.js +63 -0
- package/dist/guest/agents/agent-installer.js +2 -9
- package/dist/guest/agents/local-state.d.ts +12 -0
- package/dist/guest/agents/local-state.js +198 -0
- package/dist/guest/agents/sbx-agent.d.ts +2 -0
- package/dist/guest/agents/sbx-agent.js +35 -0
- package/dist/guest/boot/boot.d.ts +4 -0
- package/dist/guest/boot/boot.js +50 -11
- package/dist/guest/daemon/daemon.js +4 -1
- package/dist/guest/daemon/exec.js +2 -1
- package/dist/guest/daemon/idle-shutdown.js +2 -0
- package/dist/guest/daemon/sessions.js +4 -1
- package/dist/guest/entries/agent.d.ts +1 -0
- package/dist/guest/entries/agent.js +10 -0
- package/dist/guest/entries/daemon.js +2 -0
- package/dist/guest/runtime/csc.d.ts +1 -0
- package/dist/guest/runtime/csc.js +1 -0
- package/dist/guest/runtime/secrets.d.ts +12 -0
- package/dist/guest/runtime/secrets.js +63 -0
- package/dist/guest/setup/claude-profile.d.ts +2 -1
- package/dist/guest/setup/claude-profile.js +12 -1
- package/dist/guest/setup/environment.d.ts +6 -0
- package/dist/guest/setup/environment.js +56 -6
- package/dist/guest/setup/path-plan.d.ts +32 -0
- package/dist/guest/setup/path-plan.js +67 -0
- package/dist/guest/setup/shell-path.d.ts +1 -0
- package/dist/guest/setup/shell-path.js +22 -0
- package/dist/guest/toolchains/languages/python.js +1 -1
- package/dist/guest/toolchains/runtimes.js +2 -2
- package/dist/guest/vpn/index.d.ts +1 -0
- package/dist/guest/vpn/index.js +1 -0
- package/dist/guest/vpn/openvpn.d.ts +9 -0
- package/dist/guest/vpn/openvpn.js +47 -0
- package/dist/guest/vpn/tunnel.d.ts +17 -0
- package/dist/guest/vpn/tunnel.js +78 -0
- package/dist/guest/vpn/vpn.d.ts +6 -0
- package/dist/guest/vpn/vpn.js +126 -0
- package/dist/host/channel/attach.d.ts +3 -1
- package/dist/host/channel/attach.js +1 -1
- package/dist/host/channel/channel.d.ts +7 -0
- package/dist/host/channel/channel.js +26 -2
- package/dist/host/health/acl-read.d.ts +17 -0
- package/dist/host/health/acl-read.js +45 -0
- package/dist/host/health/config-backup.d.ts +11 -0
- package/dist/host/health/config-backup.js +73 -0
- package/dist/host/health/index.d.ts +6 -0
- package/dist/host/health/index.js +7 -0
- package/dist/host/health/install-state.d.ts +33 -0
- package/dist/host/health/install-state.js +110 -0
- package/dist/host/health/path-copies.d.ts +32 -0
- package/dist/host/health/path-copies.js +82 -0
- package/dist/host/health/stale.d.ts +45 -0
- package/dist/host/health/stale.js +120 -0
- package/dist/host/health/system.d.ts +37 -0
- package/dist/host/health/system.js +87 -0
- package/dist/host/install/copies.d.ts +13 -0
- package/dist/host/install/copies.js +63 -0
- package/dist/host/install/index.d.ts +1 -0
- package/dist/host/install/index.js +1 -0
- package/dist/host/launch/generate.js +25 -1
- package/dist/host/launch/session-file.js +4 -1
- package/dist/host/launch/stage.js +1 -1
- package/dist/host/migrate/backup.js +3 -0
- package/dist/host/migrate/migrations/config-file.d.ts +2 -0
- package/dist/host/migrate/migrations/config-file.js +7 -0
- package/dist/host/migrate/migrations/follow-machine-storage.js +9 -1
- package/dist/host/migrate/migrations/pin-storage-root.d.ts +4 -0
- package/dist/host/migrate/migrations/pin-storage-root.js +46 -0
- package/dist/host/migrate/migrations/unpin-config-defaults.js +4 -1
- package/dist/host/migrate/registry.js +2 -1
- package/dist/host/profile/accounts.d.ts +25 -1
- package/dist/host/profile/accounts.js +96 -13
- package/dist/host/profile/agent-accounts.d.ts +5 -1
- package/dist/host/profile/agent-accounts.js +35 -5
- package/dist/host/profile/index.d.ts +2 -1
- package/dist/host/profile/index.js +1 -0
- package/dist/host/profile/plugin-share.d.ts +26 -0
- package/dist/host/profile/plugin-share.js +146 -0
- package/dist/host/projects/join.d.ts +7 -1
- package/dist/host/projects/join.js +21 -4
- package/dist/host/projects/registry.d.ts +16 -10
- package/dist/host/projects/registry.js +74 -6
- package/dist/host/sandbox/platform.d.ts +2 -0
- package/dist/host/sandbox/platform.js +21 -2
- package/dist/host/secrets/index.d.ts +2 -0
- package/dist/host/secrets/index.js +2 -0
- package/dist/host/secrets/launch-secrets.d.ts +17 -0
- package/dist/host/secrets/launch-secrets.js +93 -0
- package/dist/host/secrets/secret-store.d.ts +25 -0
- package/dist/host/secrets/secret-store.js +89 -0
- package/dist/host/sharing/acl.d.ts +16 -2
- package/dist/host/sharing/acl.js +35 -10
- package/dist/host/sharing/current.js +11 -2
- package/dist/host/sharing/doctor.d.ts +2 -0
- package/dist/host/sharing/doctor.js +44 -0
- package/dist/host/sharing/group-access.d.ts +6 -0
- package/dist/host/sharing/group-access.js +24 -0
- package/dist/host/sharing/index.d.ts +2 -1
- package/dist/host/sharing/index.js +2 -1
- package/dist/host/sharing/lifecycle.d.ts +8 -2
- package/dist/host/sharing/lifecycle.js +16 -7
- package/dist/host/storage/cleanup.d.ts +2 -0
- package/dist/host/storage/cleanup.js +2 -1
- package/dist/host/storage/history.d.ts +21 -0
- package/dist/host/storage/history.js +49 -0
- package/dist/host/storage/index.d.ts +4 -0
- package/dist/host/storage/index.js +4 -0
- package/dist/host/storage/move.d.ts +95 -0
- package/dist/host/storage/move.js +384 -0
- package/dist/host/storage/offer.d.ts +11 -0
- package/dist/host/storage/offer.js +36 -0
- package/dist/host/storage/root.d.ts +18 -0
- package/dist/host/storage/root.js +77 -0
- package/dist/host/tools/windows-terminal.d.ts +2 -0
- package/dist/host/tools/windows-terminal.js +23 -5
- package/dist/host/update/index.d.ts +1 -1
- package/dist/host/update/index.js +1 -1
- package/dist/host/update/notice.d.ts +2 -0
- package/dist/host/update/notice.js +13 -1
- package/dist/host/update/update-state.d.ts +6 -0
- package/dist/host/update/update-state.js +2 -0
- package/dist/host/update/updater.d.ts +19 -0
- package/dist/host/update/updater.js +88 -12
- package/dist/host/vpn/index.d.ts +4 -0
- package/dist/host/vpn/index.js +4 -0
- package/dist/host/vpn/login.d.ts +24 -0
- package/dist/host/vpn/login.js +79 -0
- package/dist/host/vpn/nordvpn.d.ts +21 -0
- package/dist/host/vpn/nordvpn.js +77 -0
- package/dist/host/vpn/prepare.d.ts +17 -0
- package/dist/host/vpn/prepare.js +77 -0
- package/dist/host/vpn/status.d.ts +12 -0
- package/dist/host/vpn/status.js +53 -0
- package/dist/host/web/auth.d.ts +38 -0
- package/dist/host/web/auth.js +96 -0
- package/dist/host/web/backend.d.ts +14 -0
- package/dist/host/web/backend.js +1 -0
- package/dist/host/web/bridge.d.ts +27 -0
- package/dist/host/web/bridge.js +144 -0
- package/dist/host/web/browser.d.ts +1 -0
- package/dist/host/web/browser.js +10 -0
- package/dist/host/web/control.d.ts +17 -0
- package/dist/host/web/control.js +67 -0
- package/dist/host/web/index.d.ts +9 -0
- package/dist/host/web/index.js +8 -0
- package/dist/host/web/runner.d.ts +14 -0
- package/dist/host/web/runner.js +45 -0
- package/dist/host/web/server.d.ts +40 -0
- package/dist/host/web/server.js +218 -0
- package/dist/host/web/state.d.ts +20 -0
- package/dist/host/web/state.js +41 -0
- package/dist/host/web/static-files.d.ts +13 -0
- package/dist/host/web/static-files.js +57 -0
- package/dist/runtime/agent.js +27614 -0
- package/dist/runtime/daemon.js +1012 -618
- package/dist/runtime/db.js +236 -106
- package/dist/runtime/main.js +1093 -250
- package/dist/runtime/netproxy.js +102 -3
- package/dist/runtime/view.js +102 -3
- package/dist/selftest/accounts.test.js +40 -0
- package/dist/selftest/agent-paths.test.d.ts +2 -0
- package/dist/selftest/agent-paths.test.js +115 -0
- package/dist/selftest/channel.test.js +5 -0
- package/dist/selftest/cli.test.js +34 -4
- package/dist/selftest/credentials.test.d.ts +2 -0
- package/dist/selftest/credentials.test.js +198 -0
- package/dist/selftest/generate.test.js +1 -1
- package/dist/selftest/health.test.d.ts +2 -0
- package/dist/selftest/health.test.js +470 -0
- package/dist/selftest/host-sim.test.js +2 -0
- package/dist/selftest/index.js +19 -0
- package/dist/selftest/layout.test.js +2 -0
- package/dist/selftest/menu-screens.d.ts +7 -0
- package/dist/selftest/menu-screens.js +65 -16
- package/dist/selftest/menu.test.js +574 -21
- package/dist/selftest/migrate.test.js +1 -1
- package/dist/selftest/personalization.test.js +3 -1
- package/dist/selftest/projects.test.js +39 -1
- package/dist/selftest/shared-use.test.js +64 -2
- package/dist/selftest/sharing.test.js +50 -1
- package/dist/selftest/storage.test.d.ts +2 -0
- package/dist/selftest/storage.test.js +363 -0
- package/dist/selftest/support/fixtures.d.ts +14 -0
- package/dist/selftest/support/releases.js +1 -1
- package/dist/selftest/toolchains.test.js +21 -0
- package/dist/selftest/update-service.test.js +87 -3
- package/dist/selftest/vpn.test.d.ts +2 -0
- package/dist/selftest/vpn.test.js +279 -0
- package/dist/selftest/web.test.d.ts +2 -0
- package/dist/selftest/web.test.js +304 -0
- package/dist/shared/apps/catalogue.js +31 -0
- package/dist/shared/channel/index.d.ts +1 -0
- package/dist/shared/channel/index.js +1 -0
- package/dist/shared/channel/run-dir.d.ts +6 -1
- package/dist/shared/channel/run-dir.js +12 -1
- package/dist/shared/channel/schema.d.ts +19 -0
- package/dist/shared/channel/schema.js +11 -0
- package/dist/shared/channel/secrets.d.ts +28 -0
- package/dist/shared/channel/secrets.js +44 -0
- package/dist/shared/vpn/download.d.ts +13 -0
- package/dist/shared/vpn/download.js +14 -0
- package/dist/shared/vpn/kill-switch.d.ts +18 -0
- package/dist/shared/vpn/kill-switch.js +81 -0
- package/dist/shared/vpn/ovpn.d.ts +23 -0
- package/dist/shared/vpn/ovpn.js +244 -0
- package/dist/shared/web/index.d.ts +1 -0
- package/dist/shared/web/index.js +1 -0
- package/dist/shared/web/protocol.d.ts +61 -0
- package/dist/shared/web/protocol.js +35 -0
- package/dist/sync/sync-cycle.js +5 -1
- package/dist/sync/sync-state.d.ts +1 -0
- package/dist/sync/sync-state.js +1 -0
- package/dist/sync/watcher.js +10 -0
- package/dist/web/index.html +13 -0
- package/dist/web/main-CXESL347.js +45 -0
- package/dist/web/main-VLR7DVQ4.css +1 -0
- package/native/csharp/FolderSecurity.cs +29 -0
- package/native/scripts/protect-data.ps1 +29 -0
- package/native/scripts/read-folder-sddl.ps1 +10 -0
- package/native/scripts/set-folder-access.ps1 +49 -7
- package/node_modules/ws/LICENSE +20 -0
- package/node_modules/ws/README.md +548 -0
- package/node_modules/ws/browser.js +8 -0
- package/node_modules/ws/index.js +22 -0
- package/node_modules/ws/lib/buffer-util.js +131 -0
- package/node_modules/ws/lib/constants.js +19 -0
- package/node_modules/ws/lib/event-target.js +292 -0
- package/node_modules/ws/lib/extension.js +203 -0
- package/node_modules/ws/lib/limiter.js +55 -0
- package/node_modules/ws/lib/permessage-deflate.js +530 -0
- package/node_modules/ws/lib/receiver.js +743 -0
- package/node_modules/ws/lib/sender.js +607 -0
- package/node_modules/ws/lib/stream.js +161 -0
- package/node_modules/ws/lib/subprotocol.js +62 -0
- package/node_modules/ws/lib/validation.js +152 -0
- package/node_modules/ws/lib/websocket-server.js +562 -0
- package/node_modules/ws/lib/websocket.js +1421 -0
- package/node_modules/ws/package.json +74 -0
- package/node_modules/ws/wrapper.mjs +21 -0
- package/package.json +15 -5
- package/sandbox/csharp/EnvBroadcast.cs +33 -0
- package/sandbox/csharp/PathSync.cs +90 -0
- package/sandbox/scripts/install-shell-path.ps1 +73 -0
- package/sandbox/scripts/set-machine-environment.ps1 +37 -4
- package/schemas/config.schema.json +79 -4
- package/schemas/sandbox-config.schema.json +14 -1
- package/dist/cli/commands/repair/checks.d.ts +0 -2
- package/dist/cli/commands/repair/checks.js +0 -246
- package/dist/cli/menu/pages/start-page.d.ts +0 -43
- package/dist/cli/menu/pages/start-page.js +0 -192
- package/dist/cli/tui/tab-bar.d.ts +0 -9
- package/dist/cli/tui/tab-bar.js +0 -33
|
@@ -1,18 +1,26 @@
|
|
|
1
|
-
// One command as a form: its arguments and options listed with their current values, each changed in place
|
|
2
|
-
//
|
|
3
|
-
// command
|
|
1
|
+
// One command as a form: its arguments and options listed with their current values, each changed in place with the
|
|
2
|
+
// input that fits it (a switch flips, a choice is picked, a number is typed within its limits, a folder or file is
|
|
3
|
+
// picked in the path picker, a list is edited item by item), and the exact command line it will run shown live (the
|
|
4
|
+
// same line you could type yourself). Built from manifest.ts, so a new command or option appears here on its own.
|
|
5
|
+
import { z } from 'zod';
|
|
4
6
|
import { humanBytes } from '../../core/disk.js';
|
|
5
|
-
import {
|
|
7
|
+
import { plainText } from '../../core/util/index.js';
|
|
6
8
|
import { SandboxChannel } from '../../host/channel/index.js';
|
|
7
9
|
import { isSandboxRunning } from '../../host/sandbox/index.js';
|
|
10
|
+
import { moveProblem } from '../../host/storage/index.js';
|
|
8
11
|
import { splitArgs } from '../args.js';
|
|
9
12
|
import { cleanTargetOf } from '../commands/data/collect.js';
|
|
10
|
-
import { AccountsService, DataService } from '../services/index.js';
|
|
13
|
+
import { AccountsService, DataService, ProjectsService } from '../services/index.js';
|
|
11
14
|
import { commandLine } from '../history.js';
|
|
12
15
|
import { askedWhen } from '../manifest.js';
|
|
13
16
|
import { Text, Theme } from '../tui/index.js';
|
|
14
|
-
import { optionProblem } from './command-fields.js';
|
|
17
|
+
import { actionOf, argLabel, argPathKind, optionLabel, optionPathKind, optionProblem, plainDescription, plainSummary, } from './command-fields.js';
|
|
18
|
+
import { StringListEditor } from './settings/collections/string-list-editor.js';
|
|
19
|
+
import { askPath } from './settings/path-kind.js';
|
|
20
|
+
import { SchemaNode } from './settings/schema-node.js';
|
|
21
|
+
import { ValueEditor } from './settings/value-editor.js';
|
|
15
22
|
const MORE = '@more';
|
|
23
|
+
const OTHER = '@other';
|
|
16
24
|
export class CommandForm {
|
|
17
25
|
app;
|
|
18
26
|
ctx;
|
|
@@ -36,6 +44,11 @@ export class CommandForm {
|
|
|
36
44
|
]);
|
|
37
45
|
}
|
|
38
46
|
}
|
|
47
|
+
/** The actions the command's first argument offers (account: save, use, rename ...). */
|
|
48
|
+
actions() {
|
|
49
|
+
const choices = this.spec.args[0]?.choices;
|
|
50
|
+
return Array.isArray(choices) ? choices : [];
|
|
51
|
+
}
|
|
39
52
|
/** Values a choices list names, filled in from config and the running sandbox. */
|
|
40
53
|
choices(choices) {
|
|
41
54
|
if (Array.isArray(choices))
|
|
@@ -53,10 +66,21 @@ export class CommandForm {
|
|
|
53
66
|
first() {
|
|
54
67
|
return this.values.get('arg:' + this.spec.args[0]?.name)?.[0] ?? '';
|
|
55
68
|
}
|
|
69
|
+
valueOf(name) {
|
|
70
|
+
return this.values.get('arg:' + name)?.[0] ?? '';
|
|
71
|
+
}
|
|
56
72
|
/** Options the form may ask for at all (advanced ones included). */
|
|
57
73
|
askable() {
|
|
58
74
|
const first = this.first();
|
|
59
|
-
return this.spec.options.filter((o) =>
|
|
75
|
+
return this.spec.options.filter((o) => {
|
|
76
|
+
if (o.noMenu || !askedWhen(o.when, first))
|
|
77
|
+
return false;
|
|
78
|
+
if (typeof o.choices === 'string' && !this.choices(o.choices).length)
|
|
79
|
+
return false;
|
|
80
|
+
// "(check) the folder": asked only for that action.
|
|
81
|
+
const action = actionOf(o.description, this.actions());
|
|
82
|
+
return !action || action === first;
|
|
83
|
+
});
|
|
60
84
|
}
|
|
61
85
|
hiddenCount() {
|
|
62
86
|
return this.showAdvanced ? 0 : this.askable().filter((o) => o.advanced && !this.values.has('opt:' + o.flag)).length;
|
|
@@ -102,7 +126,7 @@ export class CommandForm {
|
|
|
102
126
|
/** The name of a required argument that has no value yet. */
|
|
103
127
|
missing() {
|
|
104
128
|
const field = this.fields().find((f) => f.kind === 'arg' && f.spec.required && !this.values.get(this.id(f))?.length);
|
|
105
|
-
return field?.kind === 'arg' ?
|
|
129
|
+
return field?.kind === 'arg' ? argLabel(field.spec) : undefined;
|
|
106
130
|
}
|
|
107
131
|
item(f) {
|
|
108
132
|
const v = this.values.get(this.id(f));
|
|
@@ -119,12 +143,13 @@ export class CommandForm {
|
|
|
119
143
|
: Array.isArray(v) && v.length
|
|
120
144
|
? v.join(' ')
|
|
121
145
|
: Theme.muted('not set');
|
|
146
|
+
const actions = this.actions();
|
|
122
147
|
if (f.kind === 'arg')
|
|
123
148
|
return {
|
|
124
149
|
value: this.id(f),
|
|
125
|
-
label:
|
|
150
|
+
label: argLabel(f.spec),
|
|
126
151
|
hint: shown,
|
|
127
|
-
description: f.spec.description,
|
|
152
|
+
description: plainDescription(f.spec.description, actions),
|
|
128
153
|
section: 'What',
|
|
129
154
|
keywords: f.spec.name,
|
|
130
155
|
};
|
|
@@ -133,8 +158,9 @@ export class CommandForm {
|
|
|
133
158
|
value: 'json',
|
|
134
159
|
label: 'Machine-readable output',
|
|
135
160
|
hint: shown,
|
|
136
|
-
description: 'Print JSON instead of a table
|
|
161
|
+
description: 'Print JSON instead of a table.',
|
|
137
162
|
section: 'Output',
|
|
163
|
+
flip: true,
|
|
138
164
|
};
|
|
139
165
|
if (f.kind === 'extra')
|
|
140
166
|
return {
|
|
@@ -148,15 +174,12 @@ export class CommandForm {
|
|
|
148
174
|
};
|
|
149
175
|
return {
|
|
150
176
|
value: this.id(f),
|
|
151
|
-
label: f.spec
|
|
152
|
-
f.spec.flag
|
|
153
|
-
.replace(/^--/, '')
|
|
154
|
-
.replace(/-/g, ' ')
|
|
155
|
-
.replace(/^./, (c) => c.toUpperCase()),
|
|
177
|
+
label: optionLabel(f.spec),
|
|
156
178
|
hint: shown,
|
|
157
|
-
description: f.spec.description,
|
|
179
|
+
description: plainDescription(f.spec.description, actions),
|
|
158
180
|
section: f.spec.advanced ? 'Advanced' : 'Options',
|
|
159
181
|
keywords: f.spec.flag,
|
|
182
|
+
flip: f.spec.type === 'boolean',
|
|
160
183
|
};
|
|
161
184
|
}
|
|
162
185
|
/** Shows the form until you run the command (its argv) or go back (null). */
|
|
@@ -170,7 +193,7 @@ export class CommandForm {
|
|
|
170
193
|
const line = commandLine(this.argv());
|
|
171
194
|
const picked = await this.app.list({
|
|
172
195
|
path,
|
|
173
|
-
intro: this.spec.summary
|
|
196
|
+
intro: plainSummary(this.spec.summary),
|
|
174
197
|
status: Theme.muted('$ ') + Theme.accent(line),
|
|
175
198
|
items: [
|
|
176
199
|
...fields.map((f) => this.item(f)),
|
|
@@ -181,8 +204,9 @@ export class CommandForm {
|
|
|
181
204
|
startAt: focus,
|
|
182
205
|
actions: [
|
|
183
206
|
{ key: 'r', label: 'start', ctrl: true },
|
|
184
|
-
{ key: 'r', label: 'clear' },
|
|
207
|
+
{ key: 'r', label: 'clear', applies: (id) => this.values.has(id) },
|
|
185
208
|
],
|
|
209
|
+
enterLabel: (_category, id) => (id === MORE ? 'show' : this.isSwitch(id) ? 'flip' : 'change'),
|
|
186
210
|
notice,
|
|
187
211
|
});
|
|
188
212
|
notice = undefined;
|
|
@@ -210,64 +234,124 @@ export class CommandForm {
|
|
|
210
234
|
this.values.delete(this.id(field));
|
|
211
235
|
continue;
|
|
212
236
|
}
|
|
213
|
-
await this.edit(field, path);
|
|
237
|
+
notice = await this.edit(field, path);
|
|
214
238
|
// Enter on the last field starts it (a switch only flips).
|
|
215
239
|
const isSwitch = field.kind === 'json' || (field.kind === 'option' && field.spec.type === 'boolean');
|
|
216
240
|
if (field === fields[fields.length - 1] && !isSwitch && !hidden && !this.missing())
|
|
217
241
|
return this.argv();
|
|
218
242
|
}
|
|
219
243
|
}
|
|
244
|
+
isSwitch(id) {
|
|
245
|
+
const f = this.fields().find((x) => this.id(x) === id);
|
|
246
|
+
return f?.kind === 'json' || (f?.kind === 'option' && f.spec.type === 'boolean');
|
|
247
|
+
}
|
|
248
|
+
/** Sets (or, with no value, clears) a field's answer. */
|
|
249
|
+
set(id, value) {
|
|
250
|
+
if (value.length)
|
|
251
|
+
this.values.set(id, value);
|
|
252
|
+
else
|
|
253
|
+
this.values.delete(id);
|
|
254
|
+
}
|
|
255
|
+
/** The kind of path a field takes (a folder or a file), if it is one. */
|
|
256
|
+
pathKind(f) {
|
|
257
|
+
if (f.kind === 'option')
|
|
258
|
+
return optionPathKind(f.spec);
|
|
259
|
+
return f.kind === 'arg' ? argPathKind(f.spec, this.spec.name, this.first()) : undefined;
|
|
260
|
+
}
|
|
261
|
+
/** A name that does not exist yet (the new login's name): typed, not picked. */
|
|
262
|
+
freeText(f) {
|
|
263
|
+
return f.kind === 'arg' && this.spec.name === 'account' && f.spec.name === 'name' && this.first() === 'save';
|
|
264
|
+
}
|
|
265
|
+
/** The values to pick from for a field with a fixed or looked-up set of answers. */
|
|
266
|
+
options(f) {
|
|
267
|
+
if (f.kind === 'extra' || f.kind === 'json' || this.freeText(f))
|
|
268
|
+
return [];
|
|
269
|
+
const fixed = this.choices(f.spec.choices);
|
|
270
|
+
if (fixed.length || f.kind !== 'arg' || this.spec.name !== 'projects')
|
|
271
|
+
return fixed;
|
|
272
|
+
const first = this.first();
|
|
273
|
+
if (f.spec.name === 'value' && first === 'all')
|
|
274
|
+
return ['on', 'off'];
|
|
275
|
+
if (f.spec.name === 'value' && first === 'roots')
|
|
276
|
+
return ['list', 'add', 'remove'];
|
|
277
|
+
if (f.spec.name === 'folder' && this.valueOf('value') === 'remove')
|
|
278
|
+
return new ProjectsService(this.ctx).list().roots;
|
|
279
|
+
return [];
|
|
280
|
+
}
|
|
281
|
+
/** Changes one field with the input that fits it. Returns a notice to show (when there is something to say). */
|
|
220
282
|
async edit(f, path) {
|
|
221
283
|
const id = this.id(f);
|
|
222
284
|
const current = this.values.get(id);
|
|
223
285
|
if (f.kind === 'json' || (f.kind === 'option' && f.spec.type === 'boolean')) {
|
|
224
286
|
this.values.set(id, current !== true);
|
|
225
|
-
return;
|
|
287
|
+
return undefined;
|
|
226
288
|
}
|
|
227
|
-
const label = f.kind === 'extra' ? 'Arguments' : f.kind === 'arg' ?
|
|
228
|
-
const about = f.kind === 'extra' ? [] : [f.spec.description];
|
|
289
|
+
const label = f.kind === 'extra' ? 'Arguments' : f.kind === 'arg' ? argLabel(f.spec) : optionLabel(f.spec);
|
|
290
|
+
const about = f.kind === 'extra' ? [] : [plainDescription(f.spec.description, this.actions())];
|
|
291
|
+
const here = [...path, label];
|
|
229
292
|
if (f.kind === 'arg' && this.spec.name === 'data' && f.spec.name === 'targets') {
|
|
230
293
|
const picked = await this.dataTargets(path);
|
|
231
294
|
if (picked)
|
|
232
295
|
this.values.set(id, picked);
|
|
233
|
-
return;
|
|
296
|
+
return undefined;
|
|
234
297
|
}
|
|
235
|
-
const list = f.kind === 'extra' ? [] : this.choices(f.spec.choices);
|
|
236
298
|
const many = (f.kind === 'option' && f.spec.type === 'list') || (f.kind === 'arg' && f.spec.variadic);
|
|
299
|
+
const list = this.options(f);
|
|
237
300
|
if (list.length && many) {
|
|
238
301
|
const picked = await this.app.list({
|
|
239
|
-
path:
|
|
302
|
+
path: here,
|
|
240
303
|
intro: about,
|
|
241
304
|
multi: true,
|
|
242
305
|
items: list.map((v) => ({ value: v, label: v, checked: Array.isArray(current) && current.includes(v) })),
|
|
243
306
|
});
|
|
244
307
|
if (picked.kind === 'multi')
|
|
245
|
-
this.
|
|
246
|
-
return;
|
|
308
|
+
this.set(id, picked.values);
|
|
309
|
+
return undefined;
|
|
310
|
+
}
|
|
311
|
+
if (f.kind === 'arg' && this.spec.name === 'projects' && f.spec.name === 'value' && this.projectAction()) {
|
|
312
|
+
await this.projectFolder(id, here, about);
|
|
313
|
+
return undefined;
|
|
247
314
|
}
|
|
248
315
|
if (list.length) {
|
|
249
316
|
const optional = !(f.kind === 'arg' && f.spec.required);
|
|
250
|
-
const picked = await this.app.choose(
|
|
317
|
+
const picked = await this.app.choose(here, about.join(' '), [
|
|
251
318
|
...list.map((v) => ({ value: v, label: v })),
|
|
252
319
|
...(optional ? [{ value: '', label: Theme.muted('(not set)') }] : []),
|
|
253
320
|
], Array.isArray(current) ? current[0] : undefined);
|
|
254
|
-
if (picked !== undefined)
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
else
|
|
258
|
-
this.values.set(id, [picked]);
|
|
259
|
-
}
|
|
260
|
-
return;
|
|
321
|
+
if (picked !== undefined)
|
|
322
|
+
this.set(id, picked === '' ? [] : [picked]);
|
|
323
|
+
return undefined;
|
|
261
324
|
}
|
|
262
|
-
if (f.kind
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
325
|
+
if (f.kind !== 'extra' && typeof f.spec.choices === 'string' && !this.freeText(f))
|
|
326
|
+
return this.nothingToChoose(f.spec.choices);
|
|
327
|
+
const kind = this.pathKind(f);
|
|
328
|
+
if (kind && f.kind !== 'extra') {
|
|
329
|
+
if (many)
|
|
330
|
+
return this.pathList(id, here, about, kind);
|
|
331
|
+
const picked = await askPath(this.app, {
|
|
332
|
+
path: here,
|
|
333
|
+
title: kind === 'file' ? 'Choose the file' : 'Choose the folder',
|
|
334
|
+
about,
|
|
335
|
+
kind,
|
|
336
|
+
initial: Array.isArray(current) ? current[0] : '',
|
|
337
|
+
validate: (v) => this.pathProblem(f, v),
|
|
338
|
+
});
|
|
339
|
+
if (picked !== undefined)
|
|
340
|
+
this.set(id, [picked]);
|
|
341
|
+
return undefined;
|
|
342
|
+
}
|
|
343
|
+
if (f.kind === 'option' && f.spec.type === 'list')
|
|
344
|
+
return this.pathList(id, here, about, undefined);
|
|
345
|
+
const number = f.kind === 'option' && f.spec.type === 'number' ? f.spec : undefined;
|
|
266
346
|
const typed = await this.app.text({
|
|
267
|
-
path:
|
|
347
|
+
path: here,
|
|
268
348
|
label,
|
|
269
349
|
about,
|
|
270
350
|
allowEmpty: true,
|
|
351
|
+
accept: number ? /[0-9]/ : undefined,
|
|
352
|
+
hint: number
|
|
353
|
+
? 'A whole number greater than 0' + (number.default !== undefined ? '. Default: ' + number.default : '') + '.'
|
|
354
|
+
: undefined,
|
|
271
355
|
initial: Array.isArray(current)
|
|
272
356
|
? many || f.kind === 'extra'
|
|
273
357
|
? current.map((x) => (/\s/.test(x) ? '"' + x + '"' : x)).join(' ')
|
|
@@ -276,12 +360,51 @@ export class CommandForm {
|
|
|
276
360
|
validate: (v) => (f.kind === 'option' ? (optionProblem(f.spec, v) ?? true) : true),
|
|
277
361
|
});
|
|
278
362
|
if (typed === undefined)
|
|
363
|
+
return undefined;
|
|
364
|
+
this.set(id, many || f.kind === 'extra' ? splitArgs(typed) : typed.trim() ? [typed.trim()] : []);
|
|
365
|
+
return undefined;
|
|
366
|
+
}
|
|
367
|
+
/** Is the problem with a picked path (true = fine)? Moving or switching the data folder has its own rules. */
|
|
368
|
+
pathProblem(f, picked) {
|
|
369
|
+
if (this.spec.name === 'storage' && f.kind === 'arg') {
|
|
370
|
+
const problem = moveProblem(this.ctx.storageRoot, picked, true);
|
|
371
|
+
return problem ? problem.message : true;
|
|
372
|
+
}
|
|
373
|
+
return f.kind === 'option' ? (optionProblem(f.spec, picked) ?? true) : true;
|
|
374
|
+
}
|
|
375
|
+
/** Several folders or files (--script ...): a list to add to, change and remove from. */
|
|
376
|
+
async pathList(id, path, about, kind) {
|
|
377
|
+
const node = new SchemaNode(z.array(z.string()).describe(about.join(' ')));
|
|
378
|
+
const edited = await new StringListEditor(this.app, path, node, new ValueEditor(this.app), [], kind, 'Esc keeps it for the command').run(Array.isArray(this.values.get(id)) ? [...this.values.get(id)] : []);
|
|
379
|
+
if (edited)
|
|
380
|
+
this.set(id, edited.value);
|
|
381
|
+
return undefined;
|
|
382
|
+
}
|
|
383
|
+
/** projects remove / include / exclude pick from the known projects (or any folder); add takes a folder. */
|
|
384
|
+
projectAction() {
|
|
385
|
+
return ['remove', 'include', 'exclude'].includes(this.first());
|
|
386
|
+
}
|
|
387
|
+
async projectFolder(id, path, about) {
|
|
388
|
+
const known = new ProjectsService(this.ctx).list().projects.map((p) => p.folder);
|
|
389
|
+
const current = this.values.get(id);
|
|
390
|
+
const picked = await this.app.choose(path, about.join(' '), [...known.map((v) => ({ value: v, label: v })), { value: OTHER, label: 'Another folder…' }], Array.isArray(current) ? current[0] : undefined);
|
|
391
|
+
if (picked === undefined)
|
|
279
392
|
return;
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
393
|
+
if (picked !== OTHER) {
|
|
394
|
+
this.set(id, [picked]);
|
|
395
|
+
return;
|
|
396
|
+
}
|
|
397
|
+
const folder = await askPath(this.app, { path, title: 'Choose the folder', about, kind: 'dir' });
|
|
398
|
+
if (folder !== undefined)
|
|
399
|
+
this.set(id, [folder]);
|
|
400
|
+
}
|
|
401
|
+
/** Nothing to pick from (no saved logins, no running session): say what to do, in the form, without an error. */
|
|
402
|
+
nothingToChoose(what) {
|
|
403
|
+
return Theme.warn(what === 'accounts'
|
|
404
|
+
? 'No saved logins yet: sign in inside the sandbox, then save it in Accounts.'
|
|
405
|
+
: what === 'sessions'
|
|
406
|
+
? 'No session is running: start an agent first.'
|
|
407
|
+
: 'There is nothing to choose from yet.');
|
|
285
408
|
}
|
|
286
409
|
/** `data clean` targets, ticked from a list with their sizes (never "all": that is typed on purpose). */
|
|
287
410
|
async dataTargets(path) {
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { Context } from '../commands/context.js';
|
|
2
|
+
import type { App } from '../tui/index.js';
|
|
3
|
+
import type { ShellExit } from './shell.js';
|
|
4
|
+
/** The row in Settings and Maintenance. */
|
|
5
|
+
export declare function dataFolderRow(ctx: Context): {
|
|
6
|
+
label: string;
|
|
7
|
+
hint: string;
|
|
8
|
+
description: string;
|
|
9
|
+
};
|
|
10
|
+
export declare class DataFolderFlow {
|
|
11
|
+
private readonly app;
|
|
12
|
+
private readonly ctx;
|
|
13
|
+
constructor(app: App, ctx: Context);
|
|
14
|
+
/** The command to run (move or use), or undefined when nothing was chosen. */
|
|
15
|
+
run(): Promise<ShellExit | undefined>;
|
|
16
|
+
private measure;
|
|
17
|
+
private decide;
|
|
18
|
+
}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
// The "Data folder" row and its flow: shows where the saved data is, lets you pick another folder in the path picker,
|
|
2
|
+
// asks whether to move the data or only switch, and hands the command to run on the normal screen (the move prints its
|
|
3
|
+
// progress there).
|
|
4
|
+
import fs from 'node:fs';
|
|
5
|
+
import { humanBytes } from '../../core/disk.js';
|
|
6
|
+
import { describeDuration, describeSize, estimate, holdsData, measureFolder, moveProblem, moveWarning, } from '../../host/storage/index.js';
|
|
7
|
+
/** Measuring for the dialog stops after this long (the size then reads "at least"). */
|
|
8
|
+
const MEASURE_MS = 8000;
|
|
9
|
+
/** The row in Settings and Maintenance. */
|
|
10
|
+
export function dataFolderRow(ctx) {
|
|
11
|
+
return {
|
|
12
|
+
label: 'Data folder',
|
|
13
|
+
hint: ctx.storageRoot,
|
|
14
|
+
description: 'Where your tools, logins, history and logs are kept between sandboxes. Press Enter to move them to another folder or drive, or to use a different folder.',
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
export class DataFolderFlow {
|
|
18
|
+
app;
|
|
19
|
+
ctx;
|
|
20
|
+
constructor(app, ctx) {
|
|
21
|
+
this.app = app;
|
|
22
|
+
this.ctx = ctx;
|
|
23
|
+
}
|
|
24
|
+
/** The command to run (move or use), or undefined when nothing was chosen. */
|
|
25
|
+
async run() {
|
|
26
|
+
const from = this.ctx.storageRoot;
|
|
27
|
+
const exists = fs.existsSync(from);
|
|
28
|
+
const measured = exists ? this.measure(from) : { bytes: 0, files: 0, partial: false };
|
|
29
|
+
const size = exists && holdsData(from) ? describeSize(measured) : 'nothing in it yet';
|
|
30
|
+
const to = await this.app.pickPath({
|
|
31
|
+
path: ['Data folder'],
|
|
32
|
+
title: 'Choose the folder for your saved data',
|
|
33
|
+
about: [
|
|
34
|
+
'Now: ' + from + ' (' + size + ').',
|
|
35
|
+
'Pick a new or empty folder to move your data there, or a folder that already holds data to use it.',
|
|
36
|
+
],
|
|
37
|
+
initial: from.replace(/[\\/][^\\/]*$/, '\\'),
|
|
38
|
+
use: 'use this folder',
|
|
39
|
+
validate: (picked) => {
|
|
40
|
+
const problem = moveProblem(from, picked, true);
|
|
41
|
+
return problem ? problem.message : true;
|
|
42
|
+
},
|
|
43
|
+
});
|
|
44
|
+
if (!to)
|
|
45
|
+
return undefined;
|
|
46
|
+
return this.decide(from, to, measured, exists);
|
|
47
|
+
}
|
|
48
|
+
measure(from) {
|
|
49
|
+
const before = this.app.status;
|
|
50
|
+
this.app.status = () => 'Measuring your saved data…';
|
|
51
|
+
this.app.redraw();
|
|
52
|
+
try {
|
|
53
|
+
return measureFolder(from, MEASURE_MS);
|
|
54
|
+
}
|
|
55
|
+
finally {
|
|
56
|
+
this.app.status = before;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
async decide(from, to, measured, exists) {
|
|
60
|
+
if (to.toLowerCase() === from.toLowerCase())
|
|
61
|
+
return undefined;
|
|
62
|
+
const target = holdsData(to);
|
|
63
|
+
const lines = [];
|
|
64
|
+
let canMove = exists && holdsData(from) && !target;
|
|
65
|
+
if (canMove) {
|
|
66
|
+
const est = estimate(from, to, measured);
|
|
67
|
+
lines.push('From: ' + from, 'To: ' + to, 'Size: ' + describeSize(measured));
|
|
68
|
+
lines.push(est.sameVolume
|
|
69
|
+
? 'Time: a few seconds (same drive, nothing is copied)'
|
|
70
|
+
: 'Time: ' + describeDuration(est.seconds) + ' (copied to another drive)');
|
|
71
|
+
if (est.freeBytes !== null)
|
|
72
|
+
lines.push('Free space on the target drive: ' + humanBytes(est.freeBytes));
|
|
73
|
+
const warning = moveWarning(measured, est);
|
|
74
|
+
if (warning)
|
|
75
|
+
lines.push('', warning);
|
|
76
|
+
if (!est.fits)
|
|
77
|
+
canMove = false;
|
|
78
|
+
}
|
|
79
|
+
else {
|
|
80
|
+
lines.push(target ? to + ' already holds data, so it is used as it is.' : 'There is nothing in ' + from + ' to move.', 'Your data stays where it is.');
|
|
81
|
+
}
|
|
82
|
+
const choice = await this.app.dialog({
|
|
83
|
+
title: canMove ? 'Move your data to ' + to + '?' : 'Use ' + to + '?',
|
|
84
|
+
lines: [...lines, '', 'Use without moving: the new folder is used from now on and your old data is left behind.'],
|
|
85
|
+
choices: [
|
|
86
|
+
...(canMove ? [{ value: 'move', label: 'Move data', key: 'm' }] : []),
|
|
87
|
+
{ value: 'use', label: 'Switch without moving', key: 's' },
|
|
88
|
+
{ value: 'cancel', label: 'Cancel', key: 'c' },
|
|
89
|
+
],
|
|
90
|
+
initial: 0,
|
|
91
|
+
escape: 'cancel',
|
|
92
|
+
});
|
|
93
|
+
if (choice === 'move')
|
|
94
|
+
return { kind: 'run', argv: ['storage', 'move', to, '--yes'] };
|
|
95
|
+
if (choice === 'use')
|
|
96
|
+
return { kind: 'run', argv: ['storage', 'use', to, '--yes'] };
|
|
97
|
+
return undefined;
|
|
98
|
+
}
|
|
99
|
+
}
|
package/dist/cli/menu/menu.d.ts
CHANGED
|
@@ -5,7 +5,7 @@ export declare class Menu {
|
|
|
5
5
|
private readonly app;
|
|
6
6
|
constructor(ctx: Context, runArgv: (argv: string[]) => Promise<number>);
|
|
7
7
|
private status;
|
|
8
|
-
/** The
|
|
8
|
+
/** The sections, in order. */
|
|
9
9
|
private shell;
|
|
10
10
|
/** Runs the menu until you leave it, or until a command that takes over the terminal (attach) has run. */
|
|
11
11
|
start(): Promise<number>;
|
package/dist/cli/menu/menu.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
// The interactive menu (`sandbox` with no arguments): a full-screen app with seven
|
|
2
|
-
// Apps, Settings, Accounts, Maintenance). The
|
|
3
|
-
// (attach, a start, a log) leaves the menu for a moment, one keypress from its screen.
|
|
1
|
+
// The interactive menu (`sandbox` with no arguments): a full-screen app with seven sections down the left (Agents,
|
|
2
|
+
// Sessions, Sandbox, Apps, Settings, Accounts, Maintenance). The sections are real screens fed by the services; only
|
|
3
|
+
// what needs the terminal (attach, a start, a log) leaves the menu for a moment, one keypress from its screen.
|
|
4
4
|
import fs from 'node:fs';
|
|
5
5
|
import path from 'node:path';
|
|
6
6
|
import { loadConfig } from '../../core/config/index.js';
|
|
@@ -13,15 +13,17 @@ import { commandSpec } from '../manifest.js';
|
|
|
13
13
|
import { AgentCommandsService, LogsService } from '../services/index.js';
|
|
14
14
|
import { App, ExitRequested, Frame, Text, Theme } from '../tui/index.js';
|
|
15
15
|
import { AccountsPage } from './pages/accounts-page.js';
|
|
16
|
+
import { AgentsPage } from './pages/agents-page.js';
|
|
16
17
|
import { AppsPage } from './pages/apps-page.js';
|
|
17
18
|
import { MaintenancePage } from './pages/maintenance-page.js';
|
|
18
19
|
import { SandboxPage } from './pages/sandbox-page.js';
|
|
19
20
|
import { SessionsPage } from './pages/sessions-page.js';
|
|
20
21
|
import { SettingsPage } from './pages/settings-page.js';
|
|
21
|
-
import { StartPage } from './pages/start-page.js';
|
|
22
22
|
import { ConfigFile } from './settings/config-file.js';
|
|
23
23
|
import { Draft } from './settings/draft.js';
|
|
24
24
|
import { Shell } from './shell.js';
|
|
25
|
+
/** Where the menu was last left in this run: it opens there again (a new run opens on Agents). */
|
|
26
|
+
let lastView;
|
|
25
27
|
export class Menu {
|
|
26
28
|
ctx;
|
|
27
29
|
runArgv;
|
|
@@ -55,7 +57,7 @@ export class Menu {
|
|
|
55
57
|
' ' +
|
|
56
58
|
folder);
|
|
57
59
|
}
|
|
58
|
-
/** The
|
|
60
|
+
/** The sections, in order. */
|
|
59
61
|
shell() {
|
|
60
62
|
const files = {
|
|
61
63
|
user: ConfigFile.user(this.ctx.loaded.configPath),
|
|
@@ -64,11 +66,11 @@ export class Menu {
|
|
|
64
66
|
const draft = new Draft();
|
|
65
67
|
const { app, ctx } = this;
|
|
66
68
|
return new Shell(app, [
|
|
67
|
-
new
|
|
69
|
+
new AgentsPage(app, ctx, files.user, draft),
|
|
68
70
|
new SessionsPage(app, ctx),
|
|
69
71
|
new SandboxPage(app, ctx),
|
|
70
72
|
new AppsPage(app, files, draft, ctx.dataPath),
|
|
71
|
-
new SettingsPage(app, files, draft),
|
|
73
|
+
new SettingsPage(app, files, draft, ctx),
|
|
72
74
|
new AccountsPage(app, ctx),
|
|
73
75
|
new MaintenancePage(app, ctx),
|
|
74
76
|
], draft, (saved) => this.applyAgentCommands(saved));
|
|
@@ -81,9 +83,10 @@ export class Menu {
|
|
|
81
83
|
}
|
|
82
84
|
try {
|
|
83
85
|
const shell = this.shell();
|
|
84
|
-
await shell.
|
|
86
|
+
await shell.restore(lastView ?? { section: 0, category: undefined });
|
|
85
87
|
for (;;) {
|
|
86
88
|
const exit = await this.app.show(shell);
|
|
89
|
+
lastView = shell.view();
|
|
87
90
|
if (exit.kind === 'quit')
|
|
88
91
|
return 0;
|
|
89
92
|
if (exit.kind === 'view')
|