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
|
@@ -6,7 +6,8 @@ import _ from 'lodash';
|
|
|
6
6
|
import { generateSandbox } from '../../../host/launch/index.js';
|
|
7
7
|
import { findSecretFiles } from '../../../host/profile/index.js';
|
|
8
8
|
import { RepoGuardStore } from '../../../host/guard/index.js';
|
|
9
|
-
import {
|
|
9
|
+
import { hostPublicIp, prepareVpn, readVpnLine, vpnNotes } from '../../../host/vpn/index.js';
|
|
10
|
+
import { assertCanLaunch, isSandboxRunning, spawnDetached, startSandbox, confirmSandboxStarted, probeHost, hideSandboxWindow, } from '../../../host/sandbox/index.js';
|
|
10
11
|
import { KnownProjects, ProjectRegistry } from '../../../host/projects/index.js';
|
|
11
12
|
import { LifeRecord, SessionLedger } from '../../../host/life/index.js';
|
|
12
13
|
import { isWithin } from '../../../shared/paths/index.js';
|
|
@@ -19,6 +20,7 @@ import { c, table } from '../../output/index.js';
|
|
|
19
20
|
import { syncAgentCommands } from '../agent-commands.js';
|
|
20
21
|
import { requireOnPc } from '../context.js';
|
|
21
22
|
import { joinHere } from '../projects/index.js';
|
|
23
|
+
import { offerSetupWhenOff } from '../setup/index.js';
|
|
22
24
|
import { useSharedSandbox } from '../shared-use.js';
|
|
23
25
|
import { beginSharing, currentUserName, currentUserSid, listProcesses, runningOwner, sessionOf, sharingDeps, takeSharingNotice, } from '../../../host/sharing/index.js';
|
|
24
26
|
import { packageVersion } from '../../../core/package-info.js';
|
|
@@ -50,6 +52,11 @@ class Launcher {
|
|
|
50
52
|
requireOnPc('launch');
|
|
51
53
|
if (!generateOnly)
|
|
52
54
|
this.syncAgentCommands();
|
|
55
|
+
if (!generateOnly) {
|
|
56
|
+
const setUp = await offerSetupWhenOff(this.ctx);
|
|
57
|
+
if (setUp !== undefined)
|
|
58
|
+
return setUp;
|
|
59
|
+
}
|
|
53
60
|
if (!generateOnly && isSandboxRunning()) {
|
|
54
61
|
// Another user's sandbox: an agent session in a project it has, when it is shared; nothing else.
|
|
55
62
|
const ctx = await useSharedSandbox(this.ctx, options.noAgent ? { kind: 'owner-only', what: 'start a sandbox' } : { kind: 'use' });
|
|
@@ -120,6 +127,15 @@ class Launcher {
|
|
|
120
127
|
await maybeAddRoot(ctx, run);
|
|
121
128
|
const prepared = generateOnly ? null : await prepare(ctx, run);
|
|
122
129
|
const bootWants = await bootWantsFor(ctx, run, extras.extraProjects);
|
|
130
|
+
// The VPN (vpn.enabled): its server and profile are fetched and checked here, before anything is written.
|
|
131
|
+
const vpn = generateOnly
|
|
132
|
+
? null
|
|
133
|
+
: await prepareVpn({
|
|
134
|
+
config,
|
|
135
|
+
storageRoot: ctx.storageRoot,
|
|
136
|
+
sandboxRunning: isSandboxRunning(),
|
|
137
|
+
base: run.workspaceHost,
|
|
138
|
+
});
|
|
123
139
|
const generated = generateSandbox({
|
|
124
140
|
packageRoot: ctx.packageRoot,
|
|
125
141
|
run,
|
|
@@ -128,11 +144,14 @@ class Launcher {
|
|
|
128
144
|
extraProjects: extras.extraProjects,
|
|
129
145
|
autoSession: extras.autoSession,
|
|
130
146
|
bootWants: bootWants.wants,
|
|
147
|
+
...(vpn ? { vpn } : {}),
|
|
131
148
|
});
|
|
132
149
|
const notes = [...run.notes, ...bootWants.notes, ...generated.projects.notes, ...generated.mappingNotes];
|
|
133
150
|
for (const note of notes)
|
|
134
151
|
console.log(note);
|
|
135
152
|
this.warnSecretFiles(run);
|
|
153
|
+
for (const line of vpnNotes(config.vpn))
|
|
154
|
+
console.log(c.yellow(line));
|
|
136
155
|
table(launchSummary(run, generated, prepared));
|
|
137
156
|
if (generateOnly)
|
|
138
157
|
return 0;
|
|
@@ -141,6 +160,7 @@ class Launcher {
|
|
|
141
160
|
this.record(run, generated);
|
|
142
161
|
this.share(generated);
|
|
143
162
|
startSandbox(generated.wsbPath);
|
|
163
|
+
await confirmSandboxStarted(generated.wsbPath);
|
|
144
164
|
this.startWatcher();
|
|
145
165
|
if (reopen.length)
|
|
146
166
|
await this.reopenAfterBoot(generated.launchId, reopen);
|
|
@@ -188,8 +208,12 @@ class Launcher {
|
|
|
188
208
|
*/
|
|
189
209
|
share(generated) {
|
|
190
210
|
const deps = sharingDeps(this.ctx.packageRoot);
|
|
191
|
-
if (!deps)
|
|
211
|
+
if (!deps) {
|
|
212
|
+
if (this.ctx.loaded.config.sharing.otherUsers)
|
|
213
|
+
console.log(c.yellow('This sandbox is not shared: sharing.otherUsers is on, but no all-users install was found on this PC. ' +
|
|
214
|
+
'Install for everyone (install.ps1 -Scope AllUsers) to share sandboxes.'));
|
|
192
215
|
return;
|
|
216
|
+
}
|
|
193
217
|
// Only the shared tree may be opened to the group: never a storage folder of your own (your profile, say).
|
|
194
218
|
const inSharedTree = isWithin(deps.usersDir, this.ctx.dataPath);
|
|
195
219
|
if (this.ctx.loaded.config.sharing.otherUsers && !inSharedTree)
|
|
@@ -199,6 +223,9 @@ class Launcher {
|
|
|
199
223
|
deps.usersDir +
|
|
200
224
|
'. Remove storage.root from your config to use the shared folder.'));
|
|
201
225
|
const shared = this.ctx.loaded.config.sharing.otherUsers && inSharedTree;
|
|
226
|
+
// Only an opened folder has permissions to write; a closed one is checked in a moment and usually needs nothing.
|
|
227
|
+
if (shared)
|
|
228
|
+
console.log('Setting folder permissions...');
|
|
202
229
|
const rows = listProcesses();
|
|
203
230
|
beginSharing(deps, {
|
|
204
231
|
user: currentUserName(),
|
|
@@ -230,6 +257,26 @@ class Launcher {
|
|
|
230
257
|
if (!watcherRunning(this.ctx.dataPath))
|
|
231
258
|
spawnDetached(this.ctx.entry, ['_watch', ...(config ? ['--config', path.resolve(config)] : [])]);
|
|
232
259
|
}
|
|
260
|
+
/** Waits for the boot; the VPN's outcome is said whether the boot worked or not (a failed tunnel can be why). */
|
|
261
|
+
async bootThenReportVpn(run, launchId, timed) {
|
|
262
|
+
try {
|
|
263
|
+
await waitForBoot(this.ctx.dataPath, launchId, timed);
|
|
264
|
+
}
|
|
265
|
+
catch (e) {
|
|
266
|
+
await this.reportVpn(run);
|
|
267
|
+
throw e;
|
|
268
|
+
}
|
|
269
|
+
await this.reportVpn(run);
|
|
270
|
+
}
|
|
271
|
+
/** Says whether the VPN came up (the sandbox reports it; its address is compared with this PC's). */
|
|
272
|
+
async reportVpn(run) {
|
|
273
|
+
if (!run.config.vpn.enabled)
|
|
274
|
+
return;
|
|
275
|
+
const line = readVpnLine(this.ctx.dataPath, await hostPublicIp());
|
|
276
|
+
if (!line)
|
|
277
|
+
return;
|
|
278
|
+
console.log(line.level === 'ok' ? c.green(line.text) : line.level === 'warn' ? c.yellow(line.text) : c.red(line.text));
|
|
279
|
+
}
|
|
233
280
|
/** Waits for the boot and attaches when asked to; otherwise says where the agent opens. */
|
|
234
281
|
async afterStart(run, generated) {
|
|
235
282
|
const { ctx, options, extras } = this;
|
|
@@ -241,7 +288,7 @@ class Launcher {
|
|
|
241
288
|
if (options.terminal || options.noAgent || extras.waitUntilReady) {
|
|
242
289
|
if (headsUp)
|
|
243
290
|
console.log(headsUp);
|
|
244
|
-
await
|
|
291
|
+
await this.bootThenReportVpn(run, generated.launchId, Boolean(headsUp));
|
|
245
292
|
if (extras.waitUntilReady)
|
|
246
293
|
return 0;
|
|
247
294
|
// Without an agent there is no session to attach to: the sandbox itself is the result.
|
|
@@ -253,7 +300,13 @@ class Launcher {
|
|
|
253
300
|
}
|
|
254
301
|
return attachHere(ctx, await waitForStart(ctx, generated.launchId, 'Starting ' + run.harnessName));
|
|
255
302
|
}
|
|
256
|
-
|
|
303
|
+
// The VPN's outcome is worth waiting for: a failed tunnel with the kill switch on means no internet.
|
|
304
|
+
if (config.vpn.enabled) {
|
|
305
|
+
if (headsUp)
|
|
306
|
+
console.log(headsUp);
|
|
307
|
+
await this.bootThenReportVpn(run, generated.launchId, Boolean(headsUp));
|
|
308
|
+
}
|
|
309
|
+
else if (headsUp)
|
|
257
310
|
console.log(headsUp + '\nFollow along: sandbox logs -f');
|
|
258
311
|
if (hidden)
|
|
259
312
|
console.log((await hidden)
|
|
@@ -77,10 +77,12 @@ async function prepareWorkspaceView(ctx, run) {
|
|
|
77
77
|
export async function prepare(ctx, run) {
|
|
78
78
|
const { options, dataPath, storageRoot } = ctx;
|
|
79
79
|
const { config } = run;
|
|
80
|
-
const accounts = new AccountStore(storageRoot);
|
|
80
|
+
const accounts = new AccountStore(storageRoot, config.claudeProfile.sharePluginsAcrossAccounts);
|
|
81
81
|
const account = options.account ?? accounts.defaultName();
|
|
82
82
|
if (account && run.harnessName === 'claude' && account !== accounts.activeFor(dataPath))
|
|
83
83
|
accounts.activate(dataPath, account);
|
|
84
|
+
else if (run.harnessName === 'claude')
|
|
85
|
+
accounts.syncPlugins(dataPath);
|
|
84
86
|
const terminal = config.provisioning.terminal.enabled
|
|
85
87
|
? await ensureTerminal(dataPath, config.provisioning.refresh, { pwsh: config.toolchains.pwsh.enabled !== false })
|
|
86
88
|
: { exe: null, message: 'disabled' };
|
|
@@ -28,7 +28,7 @@ export async function audit(ctx) {
|
|
|
28
28
|
if (!events.length) {
|
|
29
29
|
console.log(settings.enabled
|
|
30
30
|
? 'Nothing in the audit log for the last ' + ctx.options.days + ' day(s).'
|
|
31
|
-
: 'The audit log is off. Turn it on in the menu (Settings > Security & privacy > Audit log) or with audit.enabled
|
|
31
|
+
: 'The audit log is off. Turn it on in the menu (Settings > Security & privacy > Audit log) or with: sandbox config set audit.enabled true');
|
|
32
32
|
return 0;
|
|
33
33
|
}
|
|
34
34
|
for (const e of events) {
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import { type Context } from '../context.js';
|
|
2
|
-
export declare function clean(ctx: Context): number
|
|
2
|
+
export declare function clean(ctx: Context): Promise<number>;
|
|
@@ -1,10 +1,24 @@
|
|
|
1
|
+
// `sandbox clean`: old launch folders, logs and leftovers. Shows what and how much, then asks (--yes skips).
|
|
1
2
|
import _ from 'lodash';
|
|
3
|
+
import { askRequired } from '../../../core/prompt.js';
|
|
2
4
|
import { describePrune, pruneStorage } from '../../../host/storage/index.js';
|
|
3
5
|
import { isSandboxRunning } from '../../../host/sandbox/index.js';
|
|
4
6
|
import { RunDir } from '../../../shared/channel/index.js';
|
|
5
|
-
|
|
7
|
+
import { nextStep } from '../../output/index.js';
|
|
8
|
+
export async function clean(ctx) {
|
|
6
9
|
const running = isSandboxRunning() ? new RunDir(ctx.dataPath).readSandboxStatus()?.launchId : undefined;
|
|
7
|
-
|
|
8
|
-
|
|
10
|
+
const options = { launchDays: ctx.options.days, keep: _.compact([running]) };
|
|
11
|
+
const found = pruneStorage(ctx.storageRoot, { ...options, dryRun: true });
|
|
12
|
+
if (found.launches + found.logs + found.leftovers === 0) {
|
|
13
|
+
console.log('Nothing to clean.');
|
|
14
|
+
return 0;
|
|
15
|
+
}
|
|
16
|
+
console.log('Can be removed: ' + describePrune(found).replace(' removed', '') + '.');
|
|
17
|
+
if (!ctx.options.yes && !(await askRequired('Delete them?', 'Add --yes to delete without asking.'))) {
|
|
18
|
+
console.log('Nothing removed.');
|
|
19
|
+
return 1;
|
|
20
|
+
}
|
|
21
|
+
console.log('Removed ' + describePrune(pruneStorage(ctx.storageRoot, options)).replace(' removed', '') + '.');
|
|
22
|
+
nextStep('sandbox data (see what else is saved, and clean it)');
|
|
9
23
|
return 0;
|
|
10
24
|
}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import { type Context } from '../context.js';
|
|
2
|
-
export declare function config(ctx: Context): number
|
|
2
|
+
export declare function config(ctx: Context): number | Promise<number>;
|
|
@@ -1,21 +1,119 @@
|
|
|
1
|
+
import { spawn } from 'node:child_process';
|
|
1
2
|
import fs from 'node:fs';
|
|
2
3
|
import path from 'node:path';
|
|
3
4
|
import { pathToFileURL } from 'node:url';
|
|
5
|
+
import _ from 'lodash';
|
|
4
6
|
import { DEFAULTS, userConfigPath, userDir } from '../../../core/config/index.js';
|
|
7
|
+
import { redactSecrets } from '../../../core/schema/index.js';
|
|
5
8
|
import { allowedAnswer, allowStorePath, applyOverrides, describeOverrides, isTrusted, LOCAL_CONFIG_NAME, loosenedRequests, normalizeOverrides, OUTSIDE_FOLDER, outsideKey, outsideMappings, readLocalConfig, trustStorePath, } from '../../../core/local-config/index.js';
|
|
6
9
|
import { guestWorkspaceOf, previewGuest } from '../../../core/run/index.js';
|
|
10
|
+
import { askChoice } from '../../../core/prompt.js';
|
|
7
11
|
import { dirExists, fail, safeText, writeJson } from '../../../core/util/index.js';
|
|
8
|
-
import {
|
|
9
|
-
|
|
12
|
+
import { system32 } from '../../../shared/system.js';
|
|
13
|
+
import { refuseInSelfTest } from '../../../host/test-guard.js';
|
|
14
|
+
import { closest } from '../../validate.js';
|
|
15
|
+
import { c, nextStep, table } from '../../output/index.js';
|
|
16
|
+
import { ConfigFile } from '../../menu/settings/index.js';
|
|
17
|
+
/** The settings file exists already: open it, start over, or leave it (no terminal: say how). */
|
|
18
|
+
async function existingFile(file) {
|
|
19
|
+
return askChoice(file + ' exists already.', [
|
|
20
|
+
{ name: 'Open it', value: 'open' },
|
|
21
|
+
{ name: 'Overwrite it with the defaults (your changes are lost)', value: 'overwrite' },
|
|
22
|
+
{ name: 'Cancel', value: 'cancel' },
|
|
23
|
+
], 'Open it with: sandbox config path. To start over, delete it first.');
|
|
24
|
+
}
|
|
25
|
+
async function initConfig() {
|
|
10
26
|
const file = userConfigPath();
|
|
11
|
-
if (fs.existsSync(file))
|
|
12
|
-
|
|
27
|
+
if (fs.existsSync(file)) {
|
|
28
|
+
const answer = await existingFile(file);
|
|
29
|
+
if (answer === 'cancel')
|
|
30
|
+
return 0;
|
|
31
|
+
if (answer === 'open') {
|
|
32
|
+
refuseInSelfTest('open files');
|
|
33
|
+
spawn(system32('notepad.exe'), [file], { detached: true, stdio: 'ignore' }).unref();
|
|
34
|
+
console.log('Opened ' + file + '.');
|
|
35
|
+
return 0;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
13
38
|
fs.mkdirSync(path.join(userDir(), 'hooks', 'pre-agent'), { recursive: true });
|
|
14
39
|
// The schema sits next to the file (a local path), so editors trust it and show docs and autocomplete.
|
|
15
40
|
writeJson(file, { $schema: './config.schema.json', ...DEFAULTS });
|
|
16
41
|
console.log('Created ' + file + '. It lists every setting with its default; delete the ones you do not change.');
|
|
17
42
|
console.log('Your own hook scripts go in ' + path.join(userDir(), 'hooks') + '\\{pre-provision,pre-agent,post-agent}.');
|
|
18
|
-
|
|
43
|
+
nextStep("sandbox config schema (editor help in every project's .sandbox-config.json)");
|
|
44
|
+
return 0;
|
|
45
|
+
}
|
|
46
|
+
/** The setting a key names, as the schema knows it; an unknown key says what is close. */
|
|
47
|
+
function settingNode(key) {
|
|
48
|
+
const root = ConfigFile.user(null).schema;
|
|
49
|
+
const keyPath = key.split('.');
|
|
50
|
+
let node = root;
|
|
51
|
+
for (const part of keyPath)
|
|
52
|
+
node = node?.child(part);
|
|
53
|
+
if (node)
|
|
54
|
+
return { path: keyPath, node };
|
|
55
|
+
const known = root.leaves().map((l) => l.key.join('.'));
|
|
56
|
+
const hint = closest(key, known);
|
|
57
|
+
return fail('There is no setting "' + key + '".' + (hint ? ' Did you mean ' + hint + '?' : ''), 'Settings are named like sandbox.memoryMb. See them all with: sandbox config show');
|
|
58
|
+
}
|
|
59
|
+
/** What was typed for a setting as the value it stands for: true/false/on/off, a number, JSON, or plain text. */
|
|
60
|
+
function settingValue(node, text) {
|
|
61
|
+
const word = text.trim().toLowerCase();
|
|
62
|
+
if (node.type === 'string')
|
|
63
|
+
return text;
|
|
64
|
+
if (node.type === 'boolean' || node.options.some((o) => o.type === 'boolean')) {
|
|
65
|
+
if (['true', 'on', 'yes'].includes(word))
|
|
66
|
+
return true;
|
|
67
|
+
if (['false', 'off', 'no'].includes(word))
|
|
68
|
+
return false;
|
|
69
|
+
}
|
|
70
|
+
try {
|
|
71
|
+
return JSON.parse(text);
|
|
72
|
+
}
|
|
73
|
+
catch {
|
|
74
|
+
// Not JSON: a bare word such as auto or a path is the text itself.
|
|
75
|
+
return node.type === 'array' ? text.split(',').map((t) => t.trim()) : text;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
/** What a setting accepts, in words: its fixed values, a number and its range, true or false. */
|
|
79
|
+
function allowedText(node) {
|
|
80
|
+
const values = node.choiceValues.map((v) => String(v));
|
|
81
|
+
const open = node.openOption ?? (node.type === 'number' ? node : undefined);
|
|
82
|
+
const range = (n) => (n.rangeText() ? ' (' + n.rangeText() + ')' : '');
|
|
83
|
+
const more = open ? (open.type === 'number' ? 'a number' + range(open) : 'text') : '';
|
|
84
|
+
if (node.type === 'boolean')
|
|
85
|
+
return 'Use true or false.';
|
|
86
|
+
const parts = [...values, ...(more ? [more] : [])];
|
|
87
|
+
return parts.length ? 'Allowed: ' + parts.join(', or ') + '.' : 'Check the value.';
|
|
88
|
+
}
|
|
89
|
+
function setSettingCommand(ctx, key, text) {
|
|
90
|
+
if (!key || text === undefined)
|
|
91
|
+
fail('Which setting and value?', 'Usage: sandbox config set <setting> <value>');
|
|
92
|
+
const { path: keyPath, node } = settingNode(key);
|
|
93
|
+
if (node.isSection)
|
|
94
|
+
fail('"' + key + '" is a group of settings.', 'Set one of them, e.g. ' + node.leaves(keyPath)[0]?.key.join('.'));
|
|
95
|
+
const value = settingValue(node, text);
|
|
96
|
+
const problem = node.check(value);
|
|
97
|
+
if (problem !== true) {
|
|
98
|
+
fail('"' + text + '" does not work for ' + key + ': ' + problem, allowedText(node));
|
|
99
|
+
}
|
|
100
|
+
const outcome = ConfigFile.user(ctx.loaded.configPath).set(keyPath, value);
|
|
101
|
+
if (typeof outcome === 'object')
|
|
102
|
+
fail('Could not change ' + key + ': ' + outcome.problems.join('; '), 'Nothing was written.');
|
|
103
|
+
console.log(key +
|
|
104
|
+
' is ' +
|
|
105
|
+
JSON.stringify(_.get(redactSecrets(_.set({}, keyPath, value)), keyPath)) +
|
|
106
|
+
(outcome === 'unchanged' ? ' (it was already)' : '') +
|
|
107
|
+
'.');
|
|
108
|
+
return 0;
|
|
109
|
+
}
|
|
110
|
+
function getSettingCommand(ctx, key) {
|
|
111
|
+
if (!key)
|
|
112
|
+
fail('Which setting?', 'Usage: sandbox config get <setting> (all of them: sandbox config show)');
|
|
113
|
+
const { path: keyPath } = settingNode(key);
|
|
114
|
+
// Secret values (an agent's API keys) are never printed.
|
|
115
|
+
const value = _.get(redactSecrets(ctx.loaded.config), keyPath);
|
|
116
|
+
console.log(typeof value === 'string' ? value : JSON.stringify(value, null, 2));
|
|
19
117
|
return 0;
|
|
20
118
|
}
|
|
21
119
|
/**
|
|
@@ -72,9 +170,9 @@ function previewFolders(ctx, dir, filePath, overrides) {
|
|
|
72
170
|
if (!outside.includes(m))
|
|
73
171
|
return m.guest ? 'inside the project' : 'inside the project (already in the sandbox there)';
|
|
74
172
|
if (policy === true)
|
|
75
|
-
return 'outside the project, allowed (
|
|
173
|
+
return 'outside the project, allowed (your settings allow it)';
|
|
76
174
|
if (policy === false)
|
|
77
|
-
return c.red('outside the project: refused (
|
|
175
|
+
return c.red('outside the project: refused (your settings do not allow it)');
|
|
78
176
|
return allowedAnswer(store, filePath, OUTSIDE_FOLDER, outsideKey(m)) === true
|
|
79
177
|
? 'outside the project, allowed (you said yes)'
|
|
80
178
|
: c.yellow('outside the project: the next interactive launch asks you');
|
|
@@ -110,7 +208,7 @@ function previewFolders(ctx, dir, filePath, overrides) {
|
|
|
110
208
|
}
|
|
111
209
|
}
|
|
112
210
|
export function config(ctx) {
|
|
113
|
-
const [action = 'summary'] = ctx.options.positionals;
|
|
211
|
+
const [action = 'summary', key, value] = ctx.options.positionals;
|
|
114
212
|
switch (action) {
|
|
115
213
|
case 'summary':
|
|
116
214
|
table([
|
|
@@ -133,13 +231,17 @@ export function config(ctx) {
|
|
|
133
231
|
case 'init':
|
|
134
232
|
return initConfig();
|
|
135
233
|
case 'show':
|
|
136
|
-
console.log(JSON.stringify(ctx.loaded.config, null, 2));
|
|
234
|
+
console.log(JSON.stringify(redactSecrets(ctx.loaded.config), null, 2));
|
|
137
235
|
return 0;
|
|
236
|
+
case 'get':
|
|
237
|
+
return getSettingCommand(ctx, key);
|
|
238
|
+
case 'set':
|
|
239
|
+
return setSettingCommand(ctx, key, value);
|
|
138
240
|
case 'schema':
|
|
139
241
|
return printSchemaSettings();
|
|
140
242
|
case 'check':
|
|
141
243
|
return checkLocalConfig(ctx);
|
|
142
244
|
default:
|
|
143
|
-
fail('Unknown config action "' + action + '".', 'Use one of: sandbox config show | path | init | schema | check');
|
|
245
|
+
fail('Unknown config action "' + action + '".', 'Use one of: sandbox config show | get | set | path | init | schema | check');
|
|
144
246
|
}
|
|
145
247
|
}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import { type Context } from '../context.js';
|
|
2
|
-
export declare function doctor(ctx: Context): number
|
|
2
|
+
export declare function doctor(ctx: Context): Promise<number>;
|
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { HealthService } from '../../services/index.js';
|
|
1
|
+
import { runDoctor } from '../repair/index.js';
|
|
3
2
|
export function doctor(ctx) {
|
|
4
|
-
|
|
5
|
-
return 0;
|
|
3
|
+
return runDoctor(ctx);
|
|
6
4
|
}
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { MigrateService } from '../../services/index.js';
|
|
2
|
-
import type
|
|
2
|
+
import { type Context } from '../context.js';
|
|
3
3
|
/** `sandbox migrate`: the work, with the service and the output given so a test can drive it. */
|
|
4
4
|
export declare function runMigrate(service: MigrateService, options: {
|
|
5
5
|
readonly dryRun: boolean;
|
|
6
6
|
readonly restore?: string;
|
|
7
|
+
readonly yes?: boolean;
|
|
7
8
|
}, print: (line: string) => void): Promise<number>;
|
|
8
9
|
export declare function migrate(ctx: Context): Promise<number>;
|
|
9
10
|
/**
|
|
@@ -1,15 +1,28 @@
|
|
|
1
1
|
import { userDir } from '../../../core/config/index.js';
|
|
2
2
|
import { autoMigrates, continuesAfterFailedMigration, MigrateService, } from '../../services/index.js';
|
|
3
|
+
import { askRequired } from '../../../core/prompt.js';
|
|
3
4
|
import { c } from '../../output/index.js';
|
|
4
5
|
import { errMsg, UserError } from '../../../core/util/index.js';
|
|
5
6
|
import { insideSandbox } from '../../../host/sandbox/index.js';
|
|
6
|
-
|
|
7
|
+
import { holdsData, oldDefaultRoot } from '../../../host/storage/index.js';
|
|
8
|
+
import { refreshStorage } from '../context.js';
|
|
9
|
+
/**
|
|
10
|
+
* Where this context keeps the saved settings. Backups go where the data is: an upgrade that has not pinned the old
|
|
11
|
+
* folder yet would otherwise fill the new, empty default folder with them.
|
|
12
|
+
*/
|
|
7
13
|
function whereOf(ctx) {
|
|
8
|
-
|
|
14
|
+
const old = oldDefaultRoot();
|
|
15
|
+
const unpinned = old !== null && !holdsData(ctx.storageRoot) && holdsData(old) && !ctx.loaded.layers?.machine;
|
|
16
|
+
return { storageRoot: unpinned ? old : ctx.storageRoot, userDir: userDir(), configPath: ctx.loaded.configPath };
|
|
9
17
|
}
|
|
10
18
|
/** `sandbox migrate`: the work, with the service and the output given so a test can drive it. */
|
|
11
19
|
export async function runMigrate(service, options, print) {
|
|
12
20
|
if (options.restore) {
|
|
21
|
+
if (!options.yes &&
|
|
22
|
+
!(await askRequired('Put back the files saved in ' + options.restore + '? Your current settings files are replaced.', 'Add --yes to put them back without asking.'))) {
|
|
23
|
+
print('Nothing was changed.');
|
|
24
|
+
return 1;
|
|
25
|
+
}
|
|
13
26
|
service.restore(options.restore);
|
|
14
27
|
print('Put back the files saved in ' + options.restore + '.');
|
|
15
28
|
return 0;
|
|
@@ -31,7 +44,7 @@ export async function runMigrate(service, options, print) {
|
|
|
31
44
|
return 0;
|
|
32
45
|
}
|
|
33
46
|
export function migrate(ctx) {
|
|
34
|
-
return runMigrate(new MigrateService(whereOf(ctx)), { dryRun: ctx.options.dryRun, restore: ctx.options.restore }, (line) => console.log(line));
|
|
47
|
+
return runMigrate(new MigrateService(whereOf(ctx)), { dryRun: ctx.options.dryRun, restore: ctx.options.restore, yes: ctx.options.yes }, (line) => console.log(line));
|
|
35
48
|
}
|
|
36
49
|
/**
|
|
37
50
|
* Before a command: brings the settings up to date when the version changed (one small file is read otherwise).
|
|
@@ -44,7 +57,9 @@ export async function migrateBeforeCommand(ctx, command) {
|
|
|
44
57
|
try {
|
|
45
58
|
if (!service.versionChanged())
|
|
46
59
|
return;
|
|
47
|
-
await service.run((line) => console.error(c.dim(line)));
|
|
60
|
+
const result = await service.run((line) => console.error(c.dim(line)));
|
|
61
|
+
if (result.applied.length)
|
|
62
|
+
refreshStorage(ctx);
|
|
48
63
|
}
|
|
49
64
|
catch (e) {
|
|
50
65
|
if (!continuesAfterFailedMigration(command))
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { isSandboxRunning } from '../../../host/sandbox/index.js';
|
|
2
2
|
import { syncBack } from '../../../sync/index.js';
|
|
3
|
+
import { nextStep } from '../../output/index.js';
|
|
3
4
|
export function sync(ctx) {
|
|
4
5
|
const running = isSandboxRunning();
|
|
5
6
|
const result = syncBack(ctx.dataPath, !running);
|
|
@@ -8,5 +9,6 @@ export function sync(ctx) {
|
|
|
8
9
|
' item(s) synced back. claude-mem: ' +
|
|
9
10
|
result.claudeMem +
|
|
10
11
|
(running ? ' (claude-mem syncs when the sandbox closes)' : ''));
|
|
12
|
+
nextStep('sandbox claude (carry on where you left off)');
|
|
11
13
|
return 0;
|
|
12
14
|
}
|
|
@@ -6,6 +6,8 @@ export interface UpdateRequest {
|
|
|
6
6
|
readonly rollback: boolean;
|
|
7
7
|
readonly auto?: 'on' | 'off';
|
|
8
8
|
readonly unattended: boolean;
|
|
9
|
+
/** Do not ask before going back. */
|
|
10
|
+
readonly yes?: boolean;
|
|
9
11
|
}
|
|
10
12
|
/** One sentence for what an update run did, and whether it counts as done. */
|
|
11
13
|
export declare function describeResult(result: UpdateResult | null, unattended: boolean): {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { userDir } from '../../../core/config/index.js';
|
|
2
|
+
import { askRequired } from '../../../core/prompt.js';
|
|
2
3
|
import { errMsg } from '../../../core/util/index.js';
|
|
3
4
|
import { PACKAGE_ROOT } from '../../../core/package-info.js';
|
|
4
5
|
import { insideSandbox, spawnDetached } from '../../../host/sandbox/index.js';
|
|
@@ -23,8 +24,14 @@ export function describeResult(result, unattended) {
|
|
|
23
24
|
result.version +
|
|
24
25
|
' failed: ' +
|
|
25
26
|
result.reason.replace(/\.?\s*$/, '.') +
|
|
26
|
-
|
|
27
|
-
|
|
27
|
+
(result.rolledBack
|
|
28
|
+
? ' The change was undone: you are on the version you had.'
|
|
29
|
+
: ' Going back to your previous version did not fully work: run sandbox update --rollback or the installer.') +
|
|
30
|
+
(result.autoUpdateOff
|
|
31
|
+
? ' Automatic updates are off; turn them back on in Maintenance > Updates or with sandbox update --auto on.'
|
|
32
|
+
: result.blocked
|
|
33
|
+
? ' It is not tried again; the next release is.'
|
|
34
|
+
: ' It is tried again later.'),
|
|
28
35
|
code: 1,
|
|
29
36
|
};
|
|
30
37
|
switch (result.reason) {
|
|
@@ -52,12 +59,22 @@ export async function runUpdate(service, request, print) {
|
|
|
52
59
|
print('This copy was installed with npm. Update it with: ' + NPM_UPDATE_COMMAND);
|
|
53
60
|
return 0;
|
|
54
61
|
}
|
|
62
|
+
// The scheduled task (it may outlive a removal that needed admin) and background starts only run when updates are on.
|
|
63
|
+
if (request.unattended && !request.auto && !service.status().autoUpdate)
|
|
64
|
+
return 0;
|
|
55
65
|
if (request.auto) {
|
|
56
66
|
service.setAuto(request.auto === 'on');
|
|
57
67
|
print('Automatic updates are ' + request.auto + '.');
|
|
58
68
|
return 0;
|
|
59
69
|
}
|
|
60
70
|
if (request.rollback) {
|
|
71
|
+
const { version, state } = service.status();
|
|
72
|
+
const target = state.previous ? 'version ' + state.previous : 'the version before the last update';
|
|
73
|
+
if (!request.yes &&
|
|
74
|
+
!(await askRequired('Go back from version ' + version + ' to ' + target + '?', 'Add --yes to go back without asking.'))) {
|
|
75
|
+
print('Nothing was changed.');
|
|
76
|
+
return 1;
|
|
77
|
+
}
|
|
61
78
|
print('Went back to version ' + service.rollback() + '.');
|
|
62
79
|
return 0;
|
|
63
80
|
}
|
|
@@ -77,10 +94,16 @@ export async function runUpdate(service, request, print) {
|
|
|
77
94
|
}
|
|
78
95
|
export function update(options) {
|
|
79
96
|
const service = UpdateService.forPackage(PACKAGE_ROOT, options.feed, { userDir: userDir() });
|
|
80
|
-
return runUpdate(service, {
|
|
97
|
+
return runUpdate(service, {
|
|
98
|
+
check: options.check,
|
|
99
|
+
rollback: options.rollback,
|
|
100
|
+
auto: options.autoUpdate,
|
|
101
|
+
unattended: options.unattended,
|
|
102
|
+
yes: options.yes,
|
|
103
|
+
}, (line) => console.log(line));
|
|
81
104
|
}
|
|
82
105
|
/** Commands that never look for updates first: they are how updates run, or they must stay quiet. */
|
|
83
|
-
const NO_STARTUP_UPDATE = ['self-test', 'update', '_watch'];
|
|
106
|
+
const NO_STARTUP_UPDATE = ['self-test', 'update', '_watch', '_web'];
|
|
84
107
|
/**
|
|
85
108
|
* At the start of a command: tells this user once about an update that ran without them, and (current-user installs
|
|
86
109
|
* with automatic updates on) starts the daily check in the background. Never stops the command.
|
|
@@ -3,13 +3,13 @@
|
|
|
3
3
|
// folder a project of the running sandbox when it can without a restart (launch, start, exec, db).
|
|
4
4
|
import path from 'node:path';
|
|
5
5
|
import { select } from '@inquirer/prompts';
|
|
6
|
-
import { describeMissing, missingTip } from '../../../core/local-config/index.js';
|
|
6
|
+
import { describeMissing, missingTip, protectionsOf } from '../../../core/local-config/index.js';
|
|
7
7
|
import { askYesNo } from '../../../core/prompt.js';
|
|
8
8
|
import { fail, isInsideOrEqual } from '../../../core/util/index.js';
|
|
9
9
|
import { ownerName } from '../../../host/sharing/index.js';
|
|
10
10
|
import { resolveRun } from '../../../core/run/index.js';
|
|
11
11
|
import { SandboxChannel } from '../../../host/channel/index.js';
|
|
12
|
-
import { BorrowedRegistry, ProjectRegistry, joinRunning, } from '../../../host/projects/index.js';
|
|
12
|
+
import { BorrowedRegistry, ProjectRegistry, joinRunning, runningRegistry, } from '../../../host/projects/index.js';
|
|
13
13
|
import { c, working } from '../../output/index.js';
|
|
14
14
|
import { describeSessions } from './describe-sessions.js';
|
|
15
15
|
import { guestPathFor } from '../context.js';
|
|
@@ -21,17 +21,22 @@ export function registryOf(ctx) {
|
|
|
21
21
|
export function hereDir(ctx) {
|
|
22
22
|
return path.resolve(ctx.options.workspace ?? process.cwd());
|
|
23
23
|
}
|
|
24
|
+
/**
|
|
25
|
+
* Your running sandbox's registry, rebuilt from its launch folder when the file is missing, unreadable or an earlier
|
|
26
|
+
* sandbox's (another copy or version of this tool started it). null only for a sandbox without one at all.
|
|
27
|
+
*/
|
|
28
|
+
function ownRegistry(ctx) {
|
|
29
|
+
return runningRegistry(ctx.storageRoot, ctx.dataPath, protectionsOf(ctx.loaded.config));
|
|
30
|
+
}
|
|
24
31
|
/** Where this folder is in the running sandbox, if it is in it at all (nothing is registered). */
|
|
25
32
|
export function locateHere(ctx, status) {
|
|
26
33
|
const dir = hereDir(ctx);
|
|
34
|
+
const own = ctx.borrowed ? null : ownRegistry(ctx);
|
|
27
35
|
const here = registryOf(ctx).here(dir);
|
|
28
36
|
if (here)
|
|
29
37
|
return here;
|
|
30
38
|
// A sandbox started before projects existed: only its launch folder.
|
|
31
|
-
if (!ctx.borrowed &&
|
|
32
|
-
!new ProjectRegistry(ctx.storageRoot).read() &&
|
|
33
|
-
status &&
|
|
34
|
-
isInsideOrEqual(status.workspaceHost, dir))
|
|
39
|
+
if (!ctx.borrowed && !own && status && isInsideOrEqual(status.workspaceHost, dir))
|
|
35
40
|
return { project: null, guestDir: guestPathFor(dir, status.workspaceHost, status.guestWorkspace) };
|
|
36
41
|
return { project: null, guestDir: null };
|
|
37
42
|
}
|
|
@@ -57,7 +62,7 @@ export async function joinHere(ctx, status, o = {}) {
|
|
|
57
62
|
return { project: known.project, guestDir: known.guestDir, spec: null, harness: null, notes: [] };
|
|
58
63
|
}
|
|
59
64
|
// A sandbox started before projects existed: only its launch folder (guestPathFor explains why otherwise).
|
|
60
|
-
if (!
|
|
65
|
+
if (!ownRegistry(ctx))
|
|
61
66
|
return {
|
|
62
67
|
project: null,
|
|
63
68
|
guestDir: guestPathFor(dir, status.workspaceHost, status.guestWorkspace),
|