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,31 +1,26 @@
|
|
|
1
|
-
// How the settings are grouped on screen: categories in the
|
|
2
|
-
// top-level setting of both files must belong to a category (a self-test checks
|
|
1
|
+
// How the settings are grouped on screen: categories in the navigation, readable names for sections and toolchains.
|
|
2
|
+
// Every top-level setting of both files must belong to a category or be covered by another section (a self-test checks
|
|
3
|
+
// it), so nothing is ever hidden.
|
|
3
4
|
import { Text } from '../../tui/index.js';
|
|
4
5
|
export const CATEGORIES = [
|
|
5
6
|
{
|
|
6
7
|
id: 'general',
|
|
7
8
|
label: 'General',
|
|
8
|
-
description: 'Which agent starts, where the project appears in the sandbox,
|
|
9
|
+
description: 'Which agent starts, where the project appears in the sandbox, extra folders from this PC, and where the sandbox keeps its data.',
|
|
9
10
|
keys: ['defaultHarness', 'harness', 'guestWorkspace', 'readOnly', 'mappings', 'scripts'],
|
|
10
11
|
},
|
|
11
12
|
{
|
|
12
13
|
id: 'machine',
|
|
13
14
|
label: 'Sandbox machine',
|
|
14
|
-
description: 'Memory, CPU, window, GPU, clipboard, audio and
|
|
15
|
-
keys: ['sandbox'],
|
|
15
|
+
description: 'Memory, CPU, window, GPU, clipboard, audio and networking of the sandbox itself, and its desktop look (theme, accent colour, taskbar, wallpaper).',
|
|
16
|
+
keys: ['sandbox', 'personalization'],
|
|
16
17
|
},
|
|
17
18
|
{
|
|
18
19
|
id: 'languages',
|
|
19
20
|
label: 'Languages & tools',
|
|
20
|
-
description: 'Toolchains installed in the sandbox. "auto" follows your project
|
|
21
|
+
description: 'Toolchains installed in the sandbox. "auto" follows the files of your project and what this PC has.',
|
|
21
22
|
keys: ['toolchains'],
|
|
22
23
|
},
|
|
23
|
-
{
|
|
24
|
-
id: 'apps',
|
|
25
|
-
label: 'Apps',
|
|
26
|
-
description: 'Desktop apps installed in the sandbox: editors, database clients, API clients, game engines ... (also: Apps catalogue on the home screen).',
|
|
27
|
-
keys: ['apps'],
|
|
28
|
-
},
|
|
29
24
|
{
|
|
30
25
|
id: 'databases',
|
|
31
26
|
label: 'Databases',
|
|
@@ -34,21 +29,15 @@ export const CATEGORIES = [
|
|
|
34
29
|
},
|
|
35
30
|
{
|
|
36
31
|
id: 'agents',
|
|
37
|
-
label: 'Agents &
|
|
38
|
-
description: 'The agents you can start, attaching your terminal to them,
|
|
39
|
-
keys: ['harnesses', 'attach', 'agentCommands'],
|
|
40
|
-
},
|
|
41
|
-
{
|
|
42
|
-
id: 'claude',
|
|
43
|
-
label: 'Claude profile',
|
|
44
|
-
description: 'Which of your Claude settings, history and memory are copied in and synced back.',
|
|
45
|
-
keys: ['claudeProfile'],
|
|
32
|
+
label: 'Agents & sessions',
|
|
33
|
+
description: 'The agents you can start (also: Agents section), attaching your terminal to them, the (Beta) web UI and agent commands, which of your Claude settings are copied in, and reopening sessions.',
|
|
34
|
+
keys: ['harnesses', 'attach', 'web', 'agentCommands', 'claudeProfile', 'resume'],
|
|
46
35
|
},
|
|
47
36
|
{
|
|
48
37
|
id: 'network',
|
|
49
38
|
label: 'Network',
|
|
50
|
-
description: 'What the sandbox can reach: your LAN, only some hosts, blocked hosts, DNS, a proxy,
|
|
51
|
-
keys: ['network'],
|
|
39
|
+
description: 'What the sandbox can reach: your LAN, only some hosts, blocked hosts, DNS, a proxy, ports forwarded from this PC to servers inside, and a VPN (with a login set here). (No network at all: Sandbox machine > Networking.)',
|
|
40
|
+
keys: ['network', 'vpn'],
|
|
52
41
|
},
|
|
53
42
|
{
|
|
54
43
|
id: 'security',
|
|
@@ -56,42 +45,28 @@ export const CATEGORIES = [
|
|
|
56
45
|
description: 'Git-ignored files kept out, secrets kept out of the sandbox, download checks, what is kept on this PC, and sharing your sandbox with other Windows users.',
|
|
57
46
|
keys: ['workspaceFilter', 'audit', 'secrets', 'downloads', 'storage', 'sharing'],
|
|
58
47
|
},
|
|
59
|
-
{
|
|
60
|
-
id: 'setup',
|
|
61
|
-
label: 'Setup & hooks',
|
|
62
|
-
description: 'How tools get into the sandbox (copied from this PC or downloaded), Git, the terminal, and hook scripts.',
|
|
63
|
-
keys: ['provisioning', 'hooks'],
|
|
64
|
-
},
|
|
65
48
|
{
|
|
66
49
|
id: 'projects',
|
|
67
|
-
label: 'Projects',
|
|
68
|
-
description: 'Several projects in one sandbox
|
|
69
|
-
keys: ['projects'],
|
|
70
|
-
},
|
|
71
|
-
{
|
|
72
|
-
id: 'resume',
|
|
73
|
-
label: 'Reopening sessions',
|
|
74
|
-
description: 'Open the sessions of the last sandbox again when a new one starts, or after a crash.',
|
|
75
|
-
keys: ['resume'],
|
|
76
|
-
},
|
|
77
|
-
{
|
|
78
|
-
id: 'desktop',
|
|
79
|
-
label: 'Desktop look',
|
|
80
|
-
description: 'Copy your theme, accent colour, taskbar and wallpaper into the sandbox.',
|
|
81
|
-
keys: ['personalization'],
|
|
50
|
+
label: 'Projects & setup',
|
|
51
|
+
description: 'Several projects in one sandbox (roots mapped at every start, adding folders while it runs), how tools get into the sandbox (copied from this PC or downloaded), Git, the terminal, and hook scripts.',
|
|
52
|
+
keys: ['projects', 'provisioning', 'hooks'],
|
|
82
53
|
},
|
|
83
54
|
];
|
|
55
|
+
/** Settings not listed here because their own section covers them (Apps: the catalogue and your own programs). */
|
|
56
|
+
export const SETTINGS_ELSEWHERE = ['apps'];
|
|
84
57
|
/** Readable names for sections and toolchains (anything missing gets a name made from its key). */
|
|
85
58
|
const NAMES = {
|
|
86
59
|
sandbox: 'Sandbox machine',
|
|
87
60
|
attach: 'Attaching your terminal',
|
|
88
61
|
agentCommands: 'Agent commands (Beta)',
|
|
62
|
+
web: 'Web UI (Beta)',
|
|
89
63
|
provisioning: 'Provisioning',
|
|
90
64
|
downloads: 'Downloads',
|
|
91
65
|
secrets: 'Secrets',
|
|
92
66
|
claudeProfile: 'Claude profile',
|
|
93
67
|
storage: 'Storage on this PC',
|
|
94
68
|
network: 'Network',
|
|
69
|
+
vpn: 'VPN',
|
|
95
70
|
hooks: 'Hooks',
|
|
96
71
|
personalization: 'Desktop look',
|
|
97
72
|
projects: 'Projects',
|
|
@@ -10,14 +10,20 @@ export declare abstract class CollectionEditor<C> {
|
|
|
10
10
|
protected readonly path: string[];
|
|
11
11
|
protected readonly node: SchemaNode;
|
|
12
12
|
protected readonly editor: ValueEditor;
|
|
13
|
+
/** The setting's key (a list's own, without positions): what the entries are is read from it. */
|
|
14
|
+
protected readonly key: string[];
|
|
13
15
|
protected value: C;
|
|
14
16
|
private original;
|
|
15
|
-
constructor(app: App, path: string[], node: SchemaNode, editor: ValueEditor
|
|
17
|
+
constructor(app: App, path: string[], node: SchemaNode, editor: ValueEditor,
|
|
18
|
+
/** The setting's key (a list's own, without positions): what the entries are is read from it. */
|
|
19
|
+
key?: string[]);
|
|
16
20
|
protected abstract entries(): ListItem<string>[];
|
|
17
21
|
protected abstract add(): Promise<void>;
|
|
18
22
|
protected abstract open(id: string): Promise<void>;
|
|
19
23
|
protected abstract remove(id: string): void;
|
|
20
24
|
protected move?(id: string, by: number): string | undefined;
|
|
21
25
|
protected noun: string;
|
|
26
|
+
/** What leaving with changes does, shown under the list (settings: they wait for Ctrl+S). */
|
|
27
|
+
protected keepNote: string;
|
|
22
28
|
run(start: C): Promise<Edited>;
|
|
23
29
|
}
|
|
@@ -10,15 +10,21 @@ export class CollectionEditor {
|
|
|
10
10
|
path;
|
|
11
11
|
node;
|
|
12
12
|
editor;
|
|
13
|
+
key;
|
|
13
14
|
value;
|
|
14
15
|
original;
|
|
15
|
-
constructor(app, path, node, editor
|
|
16
|
+
constructor(app, path, node, editor,
|
|
17
|
+
/** The setting's key (a list's own, without positions): what the entries are is read from it. */
|
|
18
|
+
key = []) {
|
|
16
19
|
this.app = app;
|
|
17
20
|
this.path = path;
|
|
18
21
|
this.node = node;
|
|
19
22
|
this.editor = editor;
|
|
23
|
+
this.key = key;
|
|
20
24
|
}
|
|
21
25
|
noun = 'entry';
|
|
26
|
+
/** What leaving with changes does, shown under the list (settings: they wait for Ctrl+S). */
|
|
27
|
+
keepNote = 'Esc keeps it for saving with Ctrl+S';
|
|
22
28
|
async run(start) {
|
|
23
29
|
this.original = structuredClone(start);
|
|
24
30
|
this.value = structuredClone(start);
|
|
@@ -29,9 +35,7 @@ export class CollectionEditor {
|
|
|
29
35
|
const picked = await this.app.list({
|
|
30
36
|
path: this.path,
|
|
31
37
|
intro: this.node.description,
|
|
32
|
-
status: dirty
|
|
33
|
-
? Theme.changed(Theme.glyph.changed + ' changed: Esc keeps it for saving with Ctrl+S')
|
|
34
|
-
: undefined,
|
|
38
|
+
status: dirty ? Theme.changed(Theme.glyph.changed + ' changed: ' + this.keepNote) : undefined,
|
|
35
39
|
items: [
|
|
36
40
|
{ value: ADD, label: '+ Add ' + this.noun, section: 'Actions' },
|
|
37
41
|
...entries.map((e) => ({
|
|
@@ -41,11 +45,11 @@ export class CollectionEditor {
|
|
|
41
45
|
],
|
|
42
46
|
startAt: focus,
|
|
43
47
|
actions: [
|
|
44
|
-
{ key: 'd', label: '
|
|
45
|
-
...(this.move
|
|
48
|
+
{ key: 'd', label: 'remove', applies: (id) => id !== ADD },
|
|
49
|
+
...(this.move && entries.length > 1
|
|
46
50
|
? [
|
|
47
|
-
{ key: 'u', label: 'move up' },
|
|
48
|
-
{ key: 'j', label: 'move down' },
|
|
51
|
+
{ key: 'u', label: 'move up', applies: (id) => id !== ADD },
|
|
52
|
+
{ key: 'j', label: 'move down', applies: (id) => id !== ADD },
|
|
49
53
|
]
|
|
50
54
|
: []),
|
|
51
55
|
],
|
|
@@ -4,7 +4,11 @@ import { formatValue } from '../format.js';
|
|
|
4
4
|
export class MapEditor extends CollectionEditor {
|
|
5
5
|
noun = 'variable';
|
|
6
6
|
entries() {
|
|
7
|
-
return Object.entries(this.value).map(([k, v]) => ({
|
|
7
|
+
return Object.entries(this.value).map(([k, v]) => ({
|
|
8
|
+
value: k,
|
|
9
|
+
label: k,
|
|
10
|
+
hint: this.node.element?.secret ? '***' : formatValue(v),
|
|
11
|
+
}));
|
|
8
12
|
}
|
|
9
13
|
async add() {
|
|
10
14
|
const name = await this.app.text({
|
|
@@ -8,12 +8,12 @@ export class ObjectListEditor extends CollectionEditor {
|
|
|
8
8
|
return this.value.map((v, i) => ({ value: String(i), label: summary(v) }));
|
|
9
9
|
}
|
|
10
10
|
async add() {
|
|
11
|
-
const edited = await new ObjectEditor(this.app, [...this.path, 'New'], this.node.element, this.editor).run(this.node.element.initial(), true);
|
|
11
|
+
const edited = await new ObjectEditor(this.app, [...this.path, 'New'], this.node.element, this.editor, this.key).run(this.node.element.initial(), true);
|
|
12
12
|
if (edited)
|
|
13
13
|
this.value.push(edited.value);
|
|
14
14
|
}
|
|
15
15
|
async open(id) {
|
|
16
|
-
const edited = await new ObjectEditor(this.app, [...this.path, summary(this.value[Number(id)])], this.node.element, this.editor).run(this.value[Number(id)]);
|
|
16
|
+
const edited = await new ObjectEditor(this.app, [...this.path, summary(this.value[Number(id)])], this.node.element, this.editor, this.key).run(this.value[Number(id)]);
|
|
17
17
|
if (edited)
|
|
18
18
|
this.value[Number(id)] = edited.value;
|
|
19
19
|
}
|
|
@@ -20,12 +20,12 @@ export class ObjectMapEditor extends CollectionEditor {
|
|
|
20
20
|
});
|
|
21
21
|
if (name === undefined)
|
|
22
22
|
return;
|
|
23
|
-
const edited = await new ObjectEditor(this.app, [...this.path, name], this.node.element, this.editor).run(this.node.element.initial(), true);
|
|
23
|
+
const edited = await new ObjectEditor(this.app, [...this.path, name], this.node.element, this.editor, this.key).run(this.node.element.initial(), true);
|
|
24
24
|
if (edited)
|
|
25
25
|
this.value[name] = edited.value;
|
|
26
26
|
}
|
|
27
27
|
async open(id) {
|
|
28
|
-
const edited = await new ObjectEditor(this.app, [...this.path, id], this.node.element, this.editor).run(this.value[id]);
|
|
28
|
+
const edited = await new ObjectEditor(this.app, [...this.path, id], this.node.element, this.editor, this.key).run(this.value[id]);
|
|
29
29
|
if (edited)
|
|
30
30
|
this.value[id] = edited.value;
|
|
31
31
|
}
|
|
@@ -1,8 +1,18 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { App, ListItem } from '../../../tui/index.js';
|
|
2
2
|
import { CollectionEditor } from './collection-editor.js';
|
|
3
|
+
import { type PathKind } from '../path-kind.js';
|
|
4
|
+
import type { SchemaNode } from '../schema-node.js';
|
|
5
|
+
import type { ValueEditor } from '../value-editor.js';
|
|
3
6
|
/** A list of strings (project roots, scripts, extra packages ...). */
|
|
4
7
|
export declare class StringListEditor extends CollectionEditor<string[]> {
|
|
8
|
+
/** The items are folders or files on this PC: they are picked in the path picker. */
|
|
9
|
+
private readonly pathKind?;
|
|
5
10
|
protected noun: string;
|
|
11
|
+
constructor(app: App, path: string[], node: SchemaNode, editor: ValueEditor, key: string[],
|
|
12
|
+
/** The items are folders or files on this PC: they are picked in the path picker. */
|
|
13
|
+
pathKind?: PathKind | undefined,
|
|
14
|
+
/** What leaving with changes does, when it is not "wait for Ctrl+S". */
|
|
15
|
+
keepNote?: string);
|
|
6
16
|
protected entries(): ListItem<string>[];
|
|
7
17
|
private ask;
|
|
8
18
|
protected add(): Promise<void>;
|
|
@@ -1,13 +1,36 @@
|
|
|
1
1
|
import { Theme } from '../../../tui/index.js';
|
|
2
2
|
import { CollectionEditor } from './collection-editor.js';
|
|
3
|
+
import { askPath } from '../path-kind.js';
|
|
3
4
|
/** A list of strings (project roots, scripts, extra packages ...). */
|
|
4
5
|
export class StringListEditor extends CollectionEditor {
|
|
6
|
+
pathKind;
|
|
5
7
|
noun = 'item';
|
|
8
|
+
constructor(app, path, node, editor, key,
|
|
9
|
+
/** The items are folders or files on this PC: they are picked in the path picker. */
|
|
10
|
+
pathKind,
|
|
11
|
+
/** What leaving with changes does, when it is not "wait for Ctrl+S". */
|
|
12
|
+
keepNote) {
|
|
13
|
+
super(app, path, node, editor, key);
|
|
14
|
+
this.pathKind = pathKind;
|
|
15
|
+
if (pathKind)
|
|
16
|
+
this.noun = pathKind === 'file' ? 'file' : 'folder';
|
|
17
|
+
if (keepNote)
|
|
18
|
+
this.keepNote = keepNote;
|
|
19
|
+
}
|
|
6
20
|
entries() {
|
|
7
21
|
return this.value.map((v, i) => ({ value: String(i), label: v || Theme.muted('(empty)') }));
|
|
8
22
|
}
|
|
9
23
|
async ask(initial) {
|
|
10
24
|
const element = this.node.element;
|
|
25
|
+
if (this.pathKind)
|
|
26
|
+
return askPath(this.app, {
|
|
27
|
+
path: this.path,
|
|
28
|
+
title: this.pathKind === 'file' ? 'Choose a file' : 'Choose a folder',
|
|
29
|
+
about: this.node.description ? [this.node.description] : [],
|
|
30
|
+
kind: this.pathKind,
|
|
31
|
+
initial,
|
|
32
|
+
validate: (v) => element.check(v),
|
|
33
|
+
});
|
|
11
34
|
return this.app.text({
|
|
12
35
|
path: this.path,
|
|
13
36
|
label: 'Value',
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { CATEGORIES, nameOf } from './categories.js';
|
|
1
|
+
export { CATEGORIES, categoryOf, nameOf, SETTINGS_ELSEWHERE } from './categories.js';
|
|
2
2
|
export { ConfigFile, editConfigText, fileValue, type SettingChange, type SettingsTarget } from './config-file.js';
|
|
3
3
|
export { Draft, type DraftResult } from './draft.js';
|
|
4
4
|
export { SchemaNode } from './schema-node.js';
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { CATEGORIES, nameOf } from './categories.js';
|
|
1
|
+
export { CATEGORIES, categoryOf, nameOf, SETTINGS_ELSEWHERE } from './categories.js';
|
|
2
2
|
export { ConfigFile, editConfigText, fileValue } from './config-file.js';
|
|
3
3
|
export { Draft } from './draft.js';
|
|
4
4
|
export { SchemaNode } from './schema-node.js';
|
|
@@ -7,6 +7,10 @@ export declare class ObjectEditor {
|
|
|
7
7
|
private readonly path;
|
|
8
8
|
private readonly node;
|
|
9
9
|
private readonly editor;
|
|
10
|
-
|
|
10
|
+
/** The setting's key (the object's own, without list positions), so a field knows what it is. */
|
|
11
|
+
private readonly key;
|
|
12
|
+
constructor(app: App, path: string[], node: SchemaNode, editor: ValueEditor,
|
|
13
|
+
/** The setting's key (the object's own, without list positions), so a field knows what it is. */
|
|
14
|
+
key?: string[]);
|
|
11
15
|
run(start: Record<string, unknown>, isNew?: boolean): Promise<Edited>;
|
|
12
16
|
}
|
|
@@ -7,11 +7,15 @@ export class ObjectEditor {
|
|
|
7
7
|
path;
|
|
8
8
|
node;
|
|
9
9
|
editor;
|
|
10
|
-
|
|
10
|
+
key;
|
|
11
|
+
constructor(app, path, node, editor,
|
|
12
|
+
/** The setting's key (the object's own, without list positions), so a field knows what it is. */
|
|
13
|
+
key = []) {
|
|
11
14
|
this.app = app;
|
|
12
15
|
this.path = path;
|
|
13
16
|
this.node = node;
|
|
14
17
|
this.editor = editor;
|
|
18
|
+
this.key = key;
|
|
15
19
|
}
|
|
16
20
|
async run(start, isNew = false) {
|
|
17
21
|
const value = structuredClone(start);
|
|
@@ -30,13 +34,20 @@ export class ObjectEditor {
|
|
|
30
34
|
...fields.map(([name, field]) => ({
|
|
31
35
|
value: name,
|
|
32
36
|
label: Text.humanize(name),
|
|
33
|
-
hint: formatValue(value[name]),
|
|
37
|
+
hint: field.secret && value[name] ? '***' : formatValue(value[name]),
|
|
34
38
|
description: field.description,
|
|
35
39
|
section: 'Fields',
|
|
40
|
+
flip: field.editor === 'boolean',
|
|
36
41
|
})),
|
|
37
42
|
],
|
|
38
43
|
startAt: focus,
|
|
39
|
-
actions: [
|
|
44
|
+
actions: [
|
|
45
|
+
{
|
|
46
|
+
key: 'r',
|
|
47
|
+
label: 'clear',
|
|
48
|
+
applies: (name) => Boolean(this.node.child(name)?.optional) && value[name] !== undefined,
|
|
49
|
+
},
|
|
50
|
+
],
|
|
40
51
|
});
|
|
41
52
|
notice = undefined;
|
|
42
53
|
if (picked.kind === 'back') {
|
|
@@ -58,7 +69,7 @@ export class ObjectEditor {
|
|
|
58
69
|
delete value[name];
|
|
59
70
|
continue;
|
|
60
71
|
}
|
|
61
|
-
const edited = await this.editor.edit([...this.path, Text.humanize(name)], [name], field, value[name]);
|
|
72
|
+
const edited = await this.editor.edit([...this.path, Text.humanize(name)], [...this.key, name], field, value[name]);
|
|
62
73
|
if (edited)
|
|
63
74
|
value[name] = edited.value;
|
|
64
75
|
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { App } from '../../tui/index.js';
|
|
2
|
+
import type { SchemaNode } from './schema-node.js';
|
|
3
|
+
/** A folder or a file. */
|
|
4
|
+
export type PathKind = 'dir' | 'file';
|
|
5
|
+
/** The kind of path a setting holds (its key without list positions), or undefined when it is not a path. */
|
|
6
|
+
export declare function pathKindOf(key: readonly string[]): PathKind | undefined;
|
|
7
|
+
/** Words that are fine instead of a path ("auto"), read from the setting's description. */
|
|
8
|
+
export declare function pathLiterals(node: SchemaNode): string[];
|
|
9
|
+
export interface AskPathOptions {
|
|
10
|
+
readonly path: string[];
|
|
11
|
+
readonly title: string;
|
|
12
|
+
readonly about?: string[];
|
|
13
|
+
readonly kind: PathKind;
|
|
14
|
+
readonly initial?: string;
|
|
15
|
+
readonly literals?: readonly string[];
|
|
16
|
+
/** true = fine, a string = what is wrong (shown under the path). */
|
|
17
|
+
readonly validate?: (path: string) => true | string;
|
|
18
|
+
}
|
|
19
|
+
/** Picks a folder or file in the path picker; typing a path (or an allowed word) still works. */
|
|
20
|
+
export declare function askPath(app: App, o: AskPathOptions): Promise<string | undefined>;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/** Top-level settings whose list entries are folders or files, and the single settings that are one. */
|
|
2
|
+
const KINDS = {
|
|
3
|
+
'storage.root': 'dir',
|
|
4
|
+
'projects.roots': 'dir',
|
|
5
|
+
'projects.exclude': 'dir',
|
|
6
|
+
'projects.declinedRoots': 'dir',
|
|
7
|
+
'claudeProfile.hostDir': 'dir',
|
|
8
|
+
'claudeProfile.globalStateFile': 'file',
|
|
9
|
+
scripts: 'file',
|
|
10
|
+
};
|
|
11
|
+
/** The kind of path a setting holds (its key without list positions), or undefined when it is not a path. */
|
|
12
|
+
export function pathKindOf(key) {
|
|
13
|
+
const id = key.join('.');
|
|
14
|
+
const last = key[key.length - 1] ?? '';
|
|
15
|
+
if (KINDS[id])
|
|
16
|
+
return KINDS[id];
|
|
17
|
+
if (key[0] === 'mappings' && last === 'host')
|
|
18
|
+
return 'dir';
|
|
19
|
+
if (last === 'hostDir')
|
|
20
|
+
return 'dir';
|
|
21
|
+
if (/(Dir|Folder)$/.test(last))
|
|
22
|
+
return 'dir';
|
|
23
|
+
if (/File$/.test(last))
|
|
24
|
+
return 'file';
|
|
25
|
+
return undefined;
|
|
26
|
+
}
|
|
27
|
+
/** Words that are fine instead of a path ("auto"), read from the setting's description. */
|
|
28
|
+
export function pathLiterals(node) {
|
|
29
|
+
return /"auto"/.test(node.description ?? '') ? ['auto'] : [];
|
|
30
|
+
}
|
|
31
|
+
/** Picks a folder or file in the path picker; typing a path (or an allowed word) still works. */
|
|
32
|
+
export function askPath(app, o) {
|
|
33
|
+
return app.pickPath({
|
|
34
|
+
path: o.path,
|
|
35
|
+
title: o.title,
|
|
36
|
+
about: o.about,
|
|
37
|
+
initial: o.initial,
|
|
38
|
+
files: o.kind === 'file',
|
|
39
|
+
use: o.kind === 'file' ? 'use this file' : 'use this folder',
|
|
40
|
+
literals: o.literals,
|
|
41
|
+
relative: true,
|
|
42
|
+
validate: o.validate,
|
|
43
|
+
});
|
|
44
|
+
}
|
|
@@ -20,6 +20,7 @@ type ZodLike = z.ZodType & {
|
|
|
20
20
|
description?: string;
|
|
21
21
|
minValue?: number | null;
|
|
22
22
|
maxValue?: number | null;
|
|
23
|
+
isInt?: boolean;
|
|
23
24
|
};
|
|
24
25
|
/** The editor a setting gets. */
|
|
25
26
|
export type EditorKind = 'boolean' | 'choice' | 'union' | 'number' | 'string' | 'string-list' | 'choice-list' | 'object-list' | 'string-map' | 'object-map' | 'object' | 'json';
|
|
@@ -35,6 +36,14 @@ export declare class SchemaNode {
|
|
|
35
36
|
get description(): string | undefined;
|
|
36
37
|
get min(): number | undefined;
|
|
37
38
|
get max(): number | undefined;
|
|
39
|
+
/** A number that must be whole. */
|
|
40
|
+
get integer(): boolean;
|
|
41
|
+
/** A secret (an API key): shown as ***, typed with each character hidden. */
|
|
42
|
+
get secret(): boolean;
|
|
43
|
+
/** May the setting be left out (optional or with a default)? */
|
|
44
|
+
get optional(): boolean;
|
|
45
|
+
/** The numbers allowed, in words: "1 to 65535", "at least 2048", "more than 0", "" without limits. */
|
|
46
|
+
rangeText(): string;
|
|
38
47
|
/** The fields of an object, in schema order. */
|
|
39
48
|
children(): [string, SchemaNode][];
|
|
40
49
|
child(name: string): SchemaNode | undefined;
|
|
@@ -35,6 +35,32 @@ export class SchemaNode {
|
|
|
35
35
|
get max() {
|
|
36
36
|
return this.inner.maxValue ?? undefined;
|
|
37
37
|
}
|
|
38
|
+
/** A number that must be whole. */
|
|
39
|
+
get integer() {
|
|
40
|
+
return Boolean(this.inner.isInt);
|
|
41
|
+
}
|
|
42
|
+
/** A secret (an API key): shown as ***, typed with each character hidden. */
|
|
43
|
+
get secret() {
|
|
44
|
+
const meta = (z) => z.meta?.();
|
|
45
|
+
return meta(this.schema)?.secret === true || meta(this.inner)?.secret === true;
|
|
46
|
+
}
|
|
47
|
+
/** May the setting be left out (optional or with a default)? */
|
|
48
|
+
get optional() {
|
|
49
|
+
return ['optional', 'default'].includes(this.schema._zod.def.type);
|
|
50
|
+
}
|
|
51
|
+
/** The numbers allowed, in words: "1 to 65535", "at least 2048", "more than 0", "" without limits. */
|
|
52
|
+
rangeText() {
|
|
53
|
+
const checks = (this.inner._zod.def.checks ?? []).map((c) => c._zod.def);
|
|
54
|
+
const lower = checks.find((c) => c.check === 'greater_than');
|
|
55
|
+
const upper = checks.find((c) => c.check === 'less_than');
|
|
56
|
+
const lo = lower?.value;
|
|
57
|
+
const hi = upper?.value;
|
|
58
|
+
if (lo !== undefined && hi !== undefined && lower?.inclusive !== false && upper?.inclusive !== false)
|
|
59
|
+
return lo + ' to ' + hi;
|
|
60
|
+
const low = lo === undefined ? '' : (lower?.inclusive === false ? 'more than ' : 'at least ') + lo;
|
|
61
|
+
const high = hi === undefined ? '' : (upper?.inclusive === false ? 'less than ' : 'at most ') + hi;
|
|
62
|
+
return [low, high].filter(Boolean).join(' and ');
|
|
63
|
+
}
|
|
38
64
|
/** The fields of an object, in schema order. */
|
|
39
65
|
children() {
|
|
40
66
|
return Object.entries(this.inner.shape ?? {})
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { type App } from '../../tui/index.js';
|
|
2
2
|
import { type SchemaNode } from './schema-node.js';
|
|
3
|
+
/** What is wrong with the text typed for a number setting (true = fine), in words that name the allowed range. */
|
|
4
|
+
export declare function numberProblem(node: SchemaNode, text: string): true | string;
|
|
3
5
|
/** The new value, or undefined when you backed out without changing anything. */
|
|
4
6
|
export type Edited = {
|
|
5
7
|
value: unknown;
|
|
@@ -13,6 +15,9 @@ export declare class ValueEditor {
|
|
|
13
15
|
private readonly hints;
|
|
14
16
|
constructor(app: App, hints?: EditorHints);
|
|
15
17
|
edit(path: string[], key: string[], node: SchemaNode, current: unknown): Promise<Edited>;
|
|
18
|
+
private number;
|
|
19
|
+
/** A folder or file on this PC: the path picker (typing a path still works). */
|
|
20
|
+
private folderOrFile;
|
|
16
21
|
private pick;
|
|
17
22
|
private suggest;
|
|
18
23
|
private json;
|
|
@@ -9,6 +9,20 @@ import { MapEditor } from './collections/map-editor.js';
|
|
|
9
9
|
import { ObjectListEditor } from './collections/object-list-editor.js';
|
|
10
10
|
import { ObjectMapEditor } from './collections/object-map-editor.js';
|
|
11
11
|
import { ObjectEditor } from './object-editor.js';
|
|
12
|
+
import { askPath, pathKindOf, pathLiterals } from './path-kind.js';
|
|
13
|
+
/** What is wrong with the text typed for a number setting (true = fine), in words that name the allowed range. */
|
|
14
|
+
export function numberProblem(node, text) {
|
|
15
|
+
const n = Number(text);
|
|
16
|
+
if (text.trim() === '' || !Number.isFinite(n))
|
|
17
|
+
return 'Enter a number.';
|
|
18
|
+
if (node.integer && !Number.isInteger(n))
|
|
19
|
+
return 'Enter a whole number.';
|
|
20
|
+
const verdict = node.check(n);
|
|
21
|
+
if (verdict === true)
|
|
22
|
+
return true;
|
|
23
|
+
const range = node.rangeText();
|
|
24
|
+
return range ? 'Use ' + range + '.' : verdict;
|
|
25
|
+
}
|
|
12
26
|
export class ValueEditor {
|
|
13
27
|
app;
|
|
14
28
|
hints;
|
|
@@ -47,26 +61,19 @@ export class ValueEditor {
|
|
|
47
61
|
? this.edit(path, key, open, node.choiceValues.includes(current) ? undefined : current)
|
|
48
62
|
: { value: picked };
|
|
49
63
|
}
|
|
50
|
-
case 'number':
|
|
51
|
-
|
|
52
|
-
? ' (' + (node.min ?? '…') + ' to ' + (node.max ?? '…') + ')'
|
|
53
|
-
: '';
|
|
54
|
-
const typed = await this.app.text({
|
|
55
|
-
path,
|
|
56
|
-
label: Text.humanize(key[key.length - 1]) + range,
|
|
57
|
-
about,
|
|
58
|
-
initial: current === undefined ? '' : String(current),
|
|
59
|
-
validate: (v) => (v.trim() === '' || !Number.isFinite(Number(v)) ? 'Enter a number.' : node.check(Number(v))),
|
|
60
|
-
});
|
|
61
|
-
return typed === undefined ? undefined : { value: Number(typed) };
|
|
62
|
-
}
|
|
64
|
+
case 'number':
|
|
65
|
+
return this.number(path, key, node, current);
|
|
63
66
|
case 'string': {
|
|
67
|
+
const kind = pathKindOf(key);
|
|
68
|
+
if (kind)
|
|
69
|
+
return this.folderOrFile(path, key, node, current, kind);
|
|
64
70
|
const typed = await this.app.text({
|
|
65
71
|
path,
|
|
66
72
|
label: Text.humanize(key[key.length - 1]),
|
|
67
73
|
about,
|
|
68
74
|
initial: typeof current === 'string' ? current : '',
|
|
69
75
|
allowEmpty: node.check('') === true,
|
|
76
|
+
masked: node.secret,
|
|
70
77
|
validate: (v) => node.check(v),
|
|
71
78
|
});
|
|
72
79
|
return typed === undefined ? undefined : { value: typed };
|
|
@@ -82,19 +89,45 @@ export class ValueEditor {
|
|
|
82
89
|
return picked.kind === 'multi' ? { value: picked.values } : undefined;
|
|
83
90
|
}
|
|
84
91
|
case 'string-list':
|
|
85
|
-
return new StringListEditor(this.app, path, node, this).run(Array.isArray(current) ? current : []);
|
|
92
|
+
return new StringListEditor(this.app, path, node, this, key, pathKindOf(key)).run(Array.isArray(current) ? current : []);
|
|
86
93
|
case 'string-map':
|
|
87
|
-
return new MapEditor(this.app, path, node, this).run(_.isPlainObject(current) ? current : {});
|
|
94
|
+
return new MapEditor(this.app, path, node, this, key).run(_.isPlainObject(current) ? current : {});
|
|
88
95
|
case 'object-list':
|
|
89
|
-
return new ObjectListEditor(this.app, path, node, this).run(Array.isArray(current) ? current : []);
|
|
96
|
+
return new ObjectListEditor(this.app, path, node, this, key).run(Array.isArray(current) ? current : []);
|
|
90
97
|
case 'object-map':
|
|
91
|
-
return new ObjectMapEditor(this.app, path, node, this).run(_.isPlainObject(current) ? current : {});
|
|
98
|
+
return new ObjectMapEditor(this.app, path, node, this, key).run(_.isPlainObject(current) ? current : {});
|
|
92
99
|
case 'object':
|
|
93
|
-
return new ObjectEditor(this.app, path, node, this).run(_.isPlainObject(current) ? current : node.initial());
|
|
100
|
+
return new ObjectEditor(this.app, path, node, this, key).run(_.isPlainObject(current) ? current : node.initial());
|
|
94
101
|
default:
|
|
95
102
|
return this.json(path, key, node, current);
|
|
96
103
|
}
|
|
97
104
|
}
|
|
105
|
+
async number(path, key, node, current) {
|
|
106
|
+
const range = node.rangeText();
|
|
107
|
+
const typed = await this.app.text({
|
|
108
|
+
path,
|
|
109
|
+
label: Text.humanize(key[key.length - 1]),
|
|
110
|
+
about: node.description ? [node.description] : [],
|
|
111
|
+
hint: 'A ' + (node.integer ? 'whole number' : 'number') + (range ? ': ' + range : '') + '.',
|
|
112
|
+
accept: node.integer ? (node.min !== undefined && node.min >= 0 ? /[0-9]/ : /[-0-9]/) : /[-0-9.]/,
|
|
113
|
+
initial: current === undefined ? '' : String(current),
|
|
114
|
+
validate: (v) => numberProblem(node, v),
|
|
115
|
+
});
|
|
116
|
+
return typed === undefined ? undefined : { value: Number(typed) };
|
|
117
|
+
}
|
|
118
|
+
/** A folder or file on this PC: the path picker (typing a path still works). */
|
|
119
|
+
async folderOrFile(path, key, node, current, kind) {
|
|
120
|
+
const picked = await askPath(this.app, {
|
|
121
|
+
path,
|
|
122
|
+
title: 'Choose ' + (kind === 'file' ? 'the file' : 'the folder') + ': ' + Text.humanize(key[key.length - 1]),
|
|
123
|
+
about: node.description ? [node.description] : [],
|
|
124
|
+
kind,
|
|
125
|
+
initial: typeof current === 'string' && current !== 'auto' ? current : '',
|
|
126
|
+
literals: pathLiterals(node),
|
|
127
|
+
validate: (v) => node.check(v),
|
|
128
|
+
});
|
|
129
|
+
return picked === undefined ? undefined : { value: picked };
|
|
130
|
+
}
|
|
98
131
|
async pick(path, node, current, values) {
|
|
99
132
|
const picked = await this.app.choose(path, node.description ?? '', values.map((v) => ({ value: v, label: choiceLabel(v) })), current);
|
|
100
133
|
return picked === undefined ? undefined : { value: picked };
|