windows-development-sandbox 1.5.0 → 1.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -0
- package/config.example.json +27 -1
- package/dist/app/context.d.ts +8 -0
- package/dist/app/context.js +12 -0
- package/dist/app/features/defs.d.ts +322 -0
- package/dist/app/features/defs.js +28 -0
- package/dist/app/features/sandbox/index.d.ts +2 -0
- package/dist/app/features/sandbox/index.js +3 -0
- package/dist/app/features/sandbox/sandbox.def.d.ts +193 -0
- package/dist/app/features/sandbox/sandbox.def.js +245 -0
- package/dist/app/features/sandbox/sandbox.run.d.ts +72 -0
- package/dist/app/features/sandbox/sandbox.run.js +98 -0
- package/dist/app/features/sessions/index.d.ts +2 -0
- package/dist/app/features/sessions/index.js +3 -0
- package/dist/app/features/sessions/sessions.def.d.ts +141 -0
- package/dist/app/features/sessions/sessions.def.js +176 -0
- package/dist/app/features/sessions/sessions.run.d.ts +39 -0
- package/dist/app/features/sessions/sessions.run.js +58 -0
- package/dist/{cli/menu/settings/categories.d.ts → app/features/settings/categories.def.d.ts} +4 -0
- package/dist/{cli/menu/settings/categories.js → app/features/settings/categories.def.js} +40 -46
- package/dist/app/features/settings/index.d.ts +5 -0
- package/dist/app/features/settings/index.js +6 -0
- package/dist/{cli/menu/settings/config-file.d.ts → app/features/settings/settings-file.d.ts} +1 -1
- package/dist/{cli/menu/settings/config-file.js → app/features/settings/settings-file.js} +1 -1
- package/dist/app/features/settings/settings-rows.d.ts +35 -0
- package/dist/app/features/settings/settings-rows.js +94 -0
- package/dist/app/features/settings/settings.def.d.ts +157 -0
- package/dist/app/features/settings/settings.def.js +179 -0
- package/dist/app/features/settings/settings.run.d.ts +67 -0
- package/dist/app/features/settings/settings.run.js +84 -0
- package/dist/app/kernel/define.d.ts +143 -0
- package/dist/app/kernel/define.js +42 -0
- package/dist/app/kernel/errors.d.ts +34 -0
- package/dist/app/kernel/errors.js +45 -0
- package/dist/app/kernel/fields.d.ts +70 -0
- package/dist/app/kernel/fields.js +243 -0
- package/dist/app/kernel/index.d.ts +8 -0
- package/dist/app/kernel/index.js +10 -0
- package/dist/app/kernel/io.d.ts +193 -0
- package/dist/app/kernel/io.js +126 -0
- package/dist/app/kernel/rpc.d.ts +156 -0
- package/dist/app/kernel/rpc.js +47 -0
- package/dist/{cli/menu/settings → app/kernel}/schema-node.d.ts +9 -0
- package/dist/{cli/menu/settings → app/kernel}/schema-node.js +26 -0
- package/dist/app/kernel/text.d.ts +6 -0
- package/dist/app/kernel/text.js +57 -0
- package/dist/app/kernel/view.d.ts +146 -0
- package/dist/app/kernel/view.js +28 -0
- package/dist/app/registry.d.ts +10 -0
- package/dist/app/registry.js +50 -0
- package/dist/cli/args.d.ts +18 -2
- package/dist/cli/args.js +101 -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/engine.d.ts +2 -0
- package/dist/cli/commands/engine.js +60 -0
- package/dist/cli/commands/index.d.ts +2 -1
- package/dist/cli/commands/index.js +2 -1
- 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 +102 -9
- package/dist/cli/commands/launch/prepare.js +6 -4
- package/dist/cli/commands/launch/running.js +2 -1
- package/dist/cli/commands/launch/summary.d.ts +2 -0
- 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-share.d.ts +12 -0
- package/dist/cli/commands/maintenance/config-share.js +80 -0
- package/dist/cli/commands/maintenance/config.d.ts +1 -1
- package/dist/cli/commands/maintenance/config.js +38 -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/logs.js +14 -0
- 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 +10 -7
- 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/contained.d.ts +2 -0
- package/dist/cli/commands/repair/checks/contained.js +139 -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/hcs.d.ts +7 -0
- package/dist/cli/commands/repair/checks/hcs.js +28 -0
- package/dist/cli/commands/repair/checks/index.d.ts +2 -0
- package/dist/cli/commands/repair/checks/index.js +24 -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 +86 -0
- package/dist/cli/commands/repair/checks/sandbox.d.ts +2 -0
- package/dist/cli/commands/repair/checks/sandbox.js +282 -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 +78 -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 +50 -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/index.d.ts +0 -4
- package/dist/cli/commands/sessions/index.js +3 -7
- package/dist/cli/commands/setup/index.d.ts +5 -0
- package/dist/cli/commands/setup/index.js +25 -1
- package/dist/cli/commands/shared-use.d.ts +5 -2
- package/dist/cli/commands/shared-use.js +11 -8
- package/dist/cli/commands/storage/contained.d.ts +3 -0
- package/dist/cli/commands/storage/contained.js +179 -0
- package/dist/cli/commands/storage/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 +91 -0
- package/dist/cli/commands/storage/storage.d.ts +8 -0
- package/dist/cli/commands/storage/storage.js +179 -0
- package/dist/cli/commands/user-config.js +2 -2
- package/dist/cli/commands/vpn.d.ts +4 -0
- package/dist/cli/commands/vpn.js +91 -0
- package/dist/cli/commands/web.d.ts +4 -0
- package/dist/cli/commands/web.js +97 -0
- package/dist/cli/history.js +1 -1
- package/dist/cli/index.js +48 -4
- package/dist/cli/manifest.d.ts +339 -97
- package/dist/cli/manifest.js +222 -67
- 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 +38 -3
- package/dist/cli/menu/apps.js +80 -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/io-menu.d.ts +29 -0
- package/dist/cli/menu/io-menu.js +126 -0
- package/dist/cli/menu/live.d.ts +27 -0
- package/dist/cli/menu/live.js +69 -0
- package/dist/cli/menu/memory.d.ts +19 -0
- package/dist/cli/menu/memory.js +53 -0
- package/dist/cli/menu/menu.d.ts +11 -2
- package/dist/cli/menu/menu.js +36 -15
- package/dist/cli/menu/pages/accounts-page.js +55 -24
- package/dist/cli/menu/pages/agents-page.d.ts +68 -0
- package/dist/cli/menu/pages/agents-page.js +345 -0
- package/dist/cli/menu/pages/apps-page.d.ts +3 -1
- package/dist/cli/menu/pages/apps-page.js +20 -4
- package/dist/cli/menu/pages/list-page.d.ts +43 -3
- package/dist/cli/menu/pages/list-page.js +146 -12
- package/dist/cli/menu/pages/maintenance-page.d.ts +9 -5
- package/dist/cli/menu/pages/maintenance-page.js +172 -85
- package/dist/cli/menu/pages/sandbox-page.d.ts +7 -6
- package/dist/cli/menu/pages/sandbox-page.js +117 -120
- package/dist/cli/menu/pages/scopes.d.ts +1 -1
- package/dist/cli/menu/pages/sessions-page.d.ts +6 -8
- package/dist/cli/menu/pages/sessions-page.js +22 -75
- package/dist/cli/menu/pages/settings-page.d.ts +10 -14
- package/dist/cli/menu/pages/settings-page.js +95 -102
- package/dist/cli/menu/render-view.d.ts +28 -0
- package/dist/cli/menu/render-view.js +112 -0
- package/dist/cli/menu/settings/ask-path.d.ts +14 -0
- package/dist/cli/menu/settings/ask-path.js +14 -0
- package/dist/cli/menu/settings/collections/collection-editor.d.ts +8 -2
- 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 +10 -1
- package/dist/cli/menu/settings/collections/string-list-editor.js +23 -0
- package/dist/cli/menu/settings/draft.d.ts +1 -1
- package/dist/cli/menu/settings/format.d.ts +1 -3
- package/dist/cli/menu/settings/format.js +6 -36
- package/dist/cli/menu/settings/index.d.ts +1 -3
- package/dist/cli/menu/settings/index.js +3 -3
- package/dist/cli/menu/settings/object-editor.d.ts +6 -2
- package/dist/cli/menu/settings/object-editor.js +15 -4
- package/dist/cli/menu/settings/share.d.ts +36 -0
- package/dist/cli/menu/settings/share.js +131 -0
- package/dist/cli/menu/settings/value-editor.d.ts +10 -1
- package/dist/cli/menu/settings/value-editor.js +99 -63
- package/dist/cli/menu/several.js +7 -5
- package/dist/cli/menu/share-settings.d.ts +21 -0
- package/dist/cli/menu/share-settings.js +112 -0
- package/dist/cli/menu/shell.d.ts +53 -10
- package/dist/cli/menu/shell.js +115 -10
- package/dist/cli/menu/views.d.ts +7 -0
- package/dist/cli/menu/views.js +11 -0
- package/dist/cli/menu/vpn-login.d.ts +16 -0
- package/dist/cli/menu/vpn-login.js +74 -0
- package/dist/cli/operations/handler.d.ts +6 -0
- package/dist/cli/operations/handler.js +61 -0
- package/dist/cli/operations/index.d.ts +4 -0
- package/dist/cli/operations/index.js +5 -0
- package/dist/cli/operations/input.d.ts +6 -0
- package/dist/cli/operations/input.js +37 -0
- package/dist/cli/operations/io-cli.d.ts +7 -0
- package/dist/cli/operations/io-cli.js +62 -0
- package/dist/cli/operations/spec.d.ts +18 -0
- package/dist/cli/operations/spec.js +108 -0
- package/dist/cli/output/colors.d.ts +2 -2
- package/dist/cli/output/colors.js +2 -11
- package/dist/cli/output/index.d.ts +1 -0
- package/dist/cli/output/index.js +1 -0
- package/dist/cli/output/print.d.ts +5 -1
- package/dist/cli/output/print.js +15 -4
- package/dist/cli/output/progress.d.ts +15 -0
- package/dist/cli/output/progress.js +44 -0
- package/dist/cli/output/render-view.d.ts +4 -0
- package/dist/cli/output/render-view.js +63 -0
- package/dist/cli/services/accounts-service.d.ts +2 -0
- package/dist/cli/services/accounts-service.js +2 -2
- package/dist/cli/services/agent-commands-service.d.ts +2 -0
- package/dist/cli/services/agent-commands-service.js +11 -2
- package/dist/cli/services/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/logs-service.js +4 -3
- 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 +12 -4
- package/dist/cli/tui/app.js +38 -9
- 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 +28 -2
- package/dist/cli/tui/list/list-screen.js +130 -66
- package/dist/cli/tui/list/list-types.d.ts +10 -4
- package/dist/cli/tui/nav.d.ts +29 -0
- package/dist/cli/tui/nav.js +67 -0
- package/dist/cli/tui/terminal.d.ts +7 -0
- package/dist/cli/tui/terminal.js +30 -10
- 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 +13 -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 +36 -0
- package/dist/core/schema/config.js +26 -2
- package/dist/core/schema/harness.d.ts +2 -0
- package/dist/core/schema/harness.js +13 -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.d.ts +6 -0
- package/dist/core/schema/sandbox.js +21 -3
- package/dist/core/schema/vpn.d.ts +18 -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 +44 -0
- package/dist/core/util/fs.d.ts +2 -0
- package/dist/core/util/fs.js +9 -0
- package/dist/core/util/index.d.ts +1 -1
- package/dist/core/util/index.js +1 -1
- package/dist/guest/agents/agent-files.d.ts +54 -0
- package/dist/guest/agents/agent-files.js +67 -0
- package/dist/guest/agents/agent-installer.js +2 -9
- package/dist/guest/agents/local-state.d.ts +14 -0
- package/dist/guest/agents/local-state.js +218 -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 +51 -11
- package/dist/guest/daemon/daemon.js +8 -1
- package/dist/guest/daemon/exec.js +2 -1
- package/dist/guest/daemon/idle-shutdown.js +2 -0
- package/dist/guest/daemon/sessions.d.ts +5 -0
- package/dist/guest/daemon/sessions.js +20 -3
- package/dist/guest/entries/agent.d.ts +1 -0
- package/dist/guest/entries/agent.js +10 -0
- package/dist/guest/entries/daemon.js +5 -0
- package/dist/guest/governor/decide.d.ts +61 -0
- package/dist/guest/governor/decide.js +182 -0
- package/dist/guest/governor/governor.d.ts +42 -0
- package/dist/guest/governor/governor.js +214 -0
- package/dist/guest/governor/index.d.ts +2 -0
- package/dist/guest/governor/index.js +2 -0
- package/dist/guest/runtime/csc.d.ts +2 -0
- package/dist/guest/runtime/csc.js +2 -0
- package/dist/guest/runtime/secrets.d.ts +12 -0
- package/dist/guest/runtime/secrets.js +63 -0
- package/dist/guest/sessions/viewer.js +3 -1
- 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/native/rust-extras.js +4 -2
- 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 +174 -0
- package/dist/guest/vpn/wireguard.d.ts +32 -0
- package/dist/guest/vpn/wireguard.js +132 -0
- package/dist/host/agent-commands/commands.d.ts +4 -0
- package/dist/host/agent-commands/commands.js +31 -7
- package/dist/host/audit/log.d.ts +1 -1
- package/dist/host/channel/attach.d.ts +6 -2
- package/dist/host/channel/attach.js +6 -3
- package/dist/host/channel/channel.d.ts +9 -0
- package/dist/host/channel/channel.js +30 -2
- package/dist/host/engines/engine.d.ts +12 -0
- package/dist/host/engines/engine.js +1 -0
- package/dist/host/engines/hcs/check.d.ts +25 -0
- package/dist/host/engines/hcs/check.js +95 -0
- package/dist/host/engines/hcs/documents.d.ts +44 -0
- package/dist/host/engines/hcs/documents.js +155 -0
- package/dist/host/engines/hcs/engine.d.ts +39 -0
- package/dist/host/engines/hcs/engine.js +171 -0
- package/dist/host/engines/hcs/helper.d.ts +43 -0
- package/dist/host/engines/hcs/helper.js +173 -0
- package/dist/host/engines/hcs/images.d.ts +37 -0
- package/dist/host/engines/hcs/images.js +152 -0
- package/dist/host/engines/index.d.ts +7 -0
- package/dist/host/engines/index.js +5 -0
- package/dist/host/engines/registry.d.ts +16 -0
- package/dist/host/engines/registry.js +30 -0
- package/dist/host/engines/types.d.ts +58 -0
- package/dist/host/engines/types.js +1 -0
- package/dist/host/engines/windows-sandbox/engine.d.ts +16 -0
- package/dist/host/engines/windows-sandbox/engine.js +63 -0
- package/dist/host/engines/windows-sandbox/wsb-text.d.ts +2 -0
- package/dist/host/engines/windows-sandbox/wsb-text.js +29 -0
- package/dist/host/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.d.ts +5 -1
- package/dist/host/launch/generate.js +73 -7
- package/dist/host/launch/index.d.ts +3 -1
- package/dist/host/launch/index.js +3 -1
- package/dist/host/launch/launch-plan.d.ts +13 -0
- package/dist/host/launch/launch-plan.js +26 -0
- package/dist/host/launch/mappings.js +2 -1
- package/dist/host/launch/risk-notes.d.ts +10 -0
- package/dist/host/launch/risk-notes.js +18 -0
- package/dist/host/launch/session-file.d.ts +2 -0
- package/dist/host/launch/session-file.js +11 -2
- package/dist/host/launch/stage.js +1 -1
- package/dist/host/launch/wsb-file.d.ts +28 -4
- package/dist/host/launch/wsb-file.js +61 -42
- package/dist/host/life/crash-report.d.ts +27 -1
- package/dist/host/life/crash-report.js +173 -7
- package/dist/host/life/host-memory.d.ts +40 -0
- package/dist/host/life/host-memory.js +137 -0
- package/dist/host/life/index.d.ts +2 -0
- package/dist/host/life/index.js +2 -0
- package/dist/host/life/stop-events.d.ts +2 -0
- package/dist/host/life/stop-events.js +20 -3
- package/dist/host/life/stop-warning.js +1 -1
- package/dist/host/life/watchdog.d.ts +54 -0
- package/dist/host/life/watchdog.js +108 -0
- package/dist/host/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/native.d.ts +3 -2
- package/dist/host/native.js +22 -3
- 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/claude-login.js +3 -2
- 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/contained-deps.d.ts +2 -0
- package/dist/host/sandbox/contained-deps.js +17 -0
- package/dist/host/sandbox/index.d.ts +2 -0
- package/dist/host/sandbox/index.js +2 -0
- package/dist/host/sandbox/platform.d.ts +4 -0
- package/dist/host/sandbox/platform.js +23 -4
- package/dist/host/sandbox/tasklist.d.ts +13 -0
- package/dist/host/sandbox/tasklist.js +47 -0
- 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 +94 -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 +8 -3
- 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/contained/check.d.ts +9 -0
- package/dist/host/storage/contained/check.js +37 -0
- package/dist/host/storage/contained/contained-storage.d.ts +66 -0
- package/dist/host/storage/contained/contained-storage.js +168 -0
- package/dist/host/storage/contained/disk-port.d.ts +43 -0
- package/dist/host/storage/contained/disk-port.js +122 -0
- package/dist/host/storage/contained/index.d.ts +9 -0
- package/dist/host/storage/contained/index.js +8 -0
- package/dist/host/storage/contained/layout.d.ts +28 -0
- package/dist/host/storage/contained/layout.js +45 -0
- package/dist/host/storage/contained/resolve.d.ts +4 -0
- package/dist/host/storage/contained/resolve.js +30 -0
- package/dist/host/storage/contained/setting.d.ts +1 -0
- package/dist/host/storage/contained/setting.js +5 -0
- package/dist/host/storage/contained/state.d.ts +89 -0
- package/dist/host/storage/contained/state.js +166 -0
- package/dist/host/storage/contained/transfer.d.ts +24 -0
- package/dist/host/storage/contained/transfer.js +121 -0
- package/dist/host/storage/history.d.ts +21 -0
- package/dist/host/storage/history.js +49 -0
- package/dist/host/storage/index.d.ts +6 -0
- package/dist/host/storage/index.js +6 -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/providers/contained.d.ts +15 -0
- package/dist/host/storage/providers/contained.js +39 -0
- package/dist/host/storage/providers/folder.d.ts +12 -0
- package/dist/host/storage/providers/folder.js +20 -0
- package/dist/host/storage/providers/index.d.ts +4 -0
- package/dist/host/storage/providers/index.js +3 -0
- package/dist/host/storage/providers/registry.d.ts +9 -0
- package/dist/host/storage/providers/registry.js +14 -0
- package/dist/host/storage/providers/types.d.ts +33 -0
- package/dist/host/storage/providers/types.js +1 -0
- package/dist/host/storage/root.d.ts +18 -0
- package/dist/host/storage/root.js +77 -0
- package/dist/host/tools/conpty.js +3 -2
- package/dist/host/tools/windows-terminal.d.ts +2 -0
- package/dist/host/tools/windows-terminal.js +31 -12
- 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 +19 -0
- package/dist/host/vpn/prepare.js +138 -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 +3 -0
- package/dist/host/web/browser.js +23 -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 +10 -0
- package/dist/host/web/index.js +9 -0
- package/dist/host/web/rpc.d.ts +24 -0
- package/dist/host/web/rpc.js +149 -0
- package/dist/host/web/runner.d.ts +16 -0
- package/dist/host/web/runner.js +44 -0
- package/dist/host/web/server.d.ts +47 -0
- package/dist/host/web/server.js +238 -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 +27675 -0
- package/dist/runtime/daemon.js +1950 -1122
- package/dist/runtime/db.js +302 -111
- package/dist/runtime/main.js +1560 -275
- package/dist/runtime/netproxy.js +168 -8
- package/dist/runtime/view.js +186 -13
- 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 +125 -0
- package/dist/selftest/app.test.d.ts +2 -0
- package/dist/selftest/app.test.js +324 -0
- package/dist/selftest/channel.test.js +18 -0
- package/dist/selftest/cli.test.js +35 -4
- package/dist/selftest/config.test.js +59 -0
- package/dist/selftest/contained.test.d.ts +2 -0
- package/dist/selftest/contained.test.js +544 -0
- package/dist/selftest/credentials.test.d.ts +2 -0
- package/dist/selftest/credentials.test.js +198 -0
- package/dist/selftest/engine.test.d.ts +2 -0
- package/dist/selftest/engine.test.js +127 -0
- package/dist/selftest/generate.test.js +1 -1
- package/dist/selftest/hcs.test.d.ts +2 -0
- package/dist/selftest/hcs.test.js +482 -0
- package/dist/selftest/health.test.d.ts +2 -0
- package/dist/selftest/health.test.js +470 -0
- package/dist/selftest/heavy-load.test.d.ts +2 -0
- package/dist/selftest/heavy-load.test.js +329 -0
- package/dist/selftest/host-sim.test.js +2 -0
- package/dist/selftest/index.js +31 -0
- package/dist/selftest/layout.test.js +14 -0
- package/dist/selftest/menu-perf.test.d.ts +2 -0
- package/dist/selftest/menu-perf.test.js +248 -0
- package/dist/selftest/menu-screens.d.ts +7 -0
- package/dist/selftest/menu-screens.js +68 -17
- package/dist/selftest/menu.test.js +603 -22
- 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/engine-cases.d.ts +8 -0
- package/dist/selftest/support/engine-cases.js +65 -0
- package/dist/selftest/support/engine-golden.d.ts +3 -0
- package/dist/selftest/support/engine-golden.js +66 -0
- package/dist/selftest/support/fixtures.d.ts +20 -0
- package/dist/selftest/support/hcs-probes.d.ts +17 -0
- package/dist/selftest/support/hcs-probes.js +41 -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 +412 -0
- package/dist/selftest/web.test.d.ts +2 -0
- package/dist/selftest/web.test.js +402 -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 +9 -1
- package/dist/shared/channel/run-dir.js +18 -1
- package/dist/shared/channel/schema.d.ts +53 -0
- package/dist/shared/channel/schema.js +38 -0
- package/dist/shared/channel/secrets.d.ts +29 -0
- package/dist/shared/channel/secrets.js +50 -0
- package/dist/shared/memory/index.d.ts +1 -0
- package/dist/shared/memory/index.js +1 -0
- package/dist/shared/memory/policy.d.ts +33 -0
- package/dist/shared/memory/policy.js +55 -0
- package/dist/shared/pty/output-filter.d.ts +14 -1
- package/dist/shared/pty/output-filter.js +22 -4
- package/dist/shared/pty/terminal.d.ts +4 -1
- package/dist/shared/pty/terminal.js +4 -2
- package/dist/shared/system.d.ts +1 -0
- package/dist/shared/system.js +1 -0
- package/dist/shared/vpn/download.d.ts +29 -0
- package/dist/shared/vpn/download.js +30 -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/vpn/wireguard.d.ts +51 -0
- package/dist/shared/vpn/wireguard.js +227 -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 +9 -5
- package/dist/sync/sync-state.d.ts +1 -0
- package/dist/sync/sync-state.js +1 -0
- package/dist/sync/watcher.d.ts +13 -0
- package/dist/sync/watcher.js +102 -3
- package/dist/web/index.html +14 -0
- package/dist/web/main-NRRS5O6Z.js +157 -0
- package/dist/web/main-T5DMCHYV.css +1 -0
- package/native/csharp/FolderSecurity.cs +29 -0
- package/native/csharp/HcsHost/AssemblyInfo.cs +14 -0
- package/native/csharp/HcsHost/Guard.cs +100 -0
- package/native/csharp/HcsHost/Hcs.cs +256 -0
- package/native/csharp/HcsHost/Json.cs +78 -0
- package/native/csharp/HcsHost/Program.cs +185 -0
- package/native/csharp/HcsHost/VirtualDisk.cs +95 -0
- package/native/csharp/HostTools/AssemblyInfo.cs +14 -0
- package/native/csharp/HostTools/MemoryStatus.cs +107 -0
- package/native/csharp/HostTools/Program.cs +58 -17
- package/native/scripts/check-contained.ps1 +28 -0
- package/native/scripts/contained-common.ps1 +241 -0
- package/native/scripts/dismount-contained.ps1 +66 -0
- package/native/scripts/memory-status.ps1 +34 -0
- package/native/scripts/mount-contained.ps1 +139 -0
- package/native/scripts/protect-data.ps1 +29 -0
- package/native/scripts/read-folder-sddl.ps1 +10 -0
- package/native/scripts/run-elevated.ps1 +17 -4
- package/native/scripts/set-folder-access.ps1 +49 -7
- package/native/scripts/stop-events.ps1 +23 -8
- 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 +22 -5
- package/sandbox/csharp/EnvBroadcast.cs +33 -0
- package/sandbox/csharp/MemGov.cs +398 -0
- package/sandbox/csharp/PathSync.cs +90 -0
- package/sandbox/csharp/PtyHost.cs +111 -5
- package/sandbox/scripts/install-shell-path.ps1 +73 -0
- package/sandbox/scripts/set-machine-environment.ps1 +37 -4
- package/schemas/config.schema.json +136 -7
- package/schemas/sandbox-config.schema.json +17 -4
- package/dist/cli/commands/repair/checks.d.ts +0 -2
- package/dist/cli/commands/repair/checks.js +0 -246
- package/dist/cli/commands/sessions/control.d.ts +0 -4
- package/dist/cli/commands/sessions/control.js +0 -66
- package/dist/cli/commands/sessions/list.d.ts +0 -2
- package/dist/cli/commands/sessions/list.js +0 -45
- package/dist/cli/commands/sessions/status.d.ts +0 -2
- package/dist/cli/commands/sessions/status.js +0 -93
- package/dist/cli/commands/sessions/window.d.ts +0 -3
- package/dist/cli/commands/sessions/window.js +0 -18
- package/dist/cli/menu/pages/start-page.d.ts +0 -43
- package/dist/cli/menu/pages/start-page.js +0 -192
- package/dist/cli/tui/tab-bar.d.ts +0 -9
- package/dist/cli/tui/tab-bar.js +0 -33
|
@@ -1,18 +1,27 @@
|
|
|
1
1
|
import { Text } from '../text.js';
|
|
2
2
|
import { Theme } from '../theme.js';
|
|
3
|
+
/** Lists longer than this say how to search. */
|
|
4
|
+
const LONG_LIST = 12;
|
|
3
5
|
export class ListScreen {
|
|
4
6
|
o;
|
|
5
7
|
category = 0;
|
|
6
8
|
focus = 'list';
|
|
9
|
+
/** The list has the keyboard (false while the menu's navigation has it): the highlight is drawn softer. */
|
|
10
|
+
active = true;
|
|
7
11
|
cursor = 0;
|
|
8
12
|
offset = 0;
|
|
9
13
|
query = '';
|
|
10
14
|
searching = false;
|
|
11
15
|
notice;
|
|
12
16
|
checked;
|
|
17
|
+
/** The entries shown for the last query and category (the items never change, so only those two matter). */
|
|
18
|
+
shown;
|
|
19
|
+
/** What a search looks in, per entry, lowercased once. */
|
|
20
|
+
haystacks;
|
|
13
21
|
constructor(o) {
|
|
14
22
|
this.o = o;
|
|
15
23
|
this.notice = o.notice;
|
|
24
|
+
this.query = o.startQuery ?? '';
|
|
16
25
|
this.checked = new Set(o.items.flatMap((item, i) => (item.checked ? [i] : [])));
|
|
17
26
|
const start = o.startAt === undefined ? -1 : o.items.findIndex((item) => item.value === o.startAt);
|
|
18
27
|
const startCategory = start >= 0 ? o.items[start].category : o.startCategory;
|
|
@@ -23,21 +32,26 @@ export class ListScreen {
|
|
|
23
32
|
}
|
|
24
33
|
/** Indexes of the entries shown now: all matches of the search, else the current category's, else all. */
|
|
25
34
|
visible() {
|
|
35
|
+
const key = this.query + '\0' + this.category;
|
|
36
|
+
if (this.shown?.key !== key)
|
|
37
|
+
this.shown = { key, indexes: this.matching() };
|
|
38
|
+
return this.shown.indexes;
|
|
39
|
+
}
|
|
40
|
+
matching() {
|
|
26
41
|
const all = this.o.items.map((_, i) => i);
|
|
27
42
|
if (this.query.trim()) {
|
|
28
43
|
const words = this.query.toLowerCase().split(/\s+/).filter(Boolean);
|
|
29
|
-
const
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
.join(' ')
|
|
34
|
-
.toLowerCase();
|
|
35
|
-
return words.every((w) => hay.includes(w));
|
|
36
|
-
});
|
|
44
|
+
const hays = (this.haystacks ??= this.o.items.map((it) => [it.label, Text.strip(it.hint ?? ''), it.description, it.keywords, it.section, this.categoryLabel(it.category)]
|
|
45
|
+
.join(' ')
|
|
46
|
+
.toLowerCase()));
|
|
47
|
+
return all.filter((i) => words.every((w) => hays[i].includes(w)));
|
|
37
48
|
}
|
|
38
49
|
const cat = this.o.categories?.[this.category];
|
|
39
50
|
return cat ? all.filter((i) => this.o.items[i].category === cat.id) : all;
|
|
40
51
|
}
|
|
52
|
+
categoryLabel(id) {
|
|
53
|
+
return this.o.categories?.find((c) => c.id === id)?.label ?? '';
|
|
54
|
+
}
|
|
41
55
|
rows(visible) {
|
|
42
56
|
const rows = [];
|
|
43
57
|
let section;
|
|
@@ -45,7 +59,7 @@ export class ListScreen {
|
|
|
45
59
|
for (const index of visible) {
|
|
46
60
|
const it = this.o.items[index];
|
|
47
61
|
const heading = searchAll
|
|
48
|
-
? [this.
|
|
62
|
+
? [this.categoryLabel(it.category), it.section].filter(Boolean).join(' › ')
|
|
49
63
|
: it.section;
|
|
50
64
|
if (heading && heading !== section)
|
|
51
65
|
rows.push({ kind: 'section', text: heading });
|
|
@@ -57,40 +71,69 @@ export class ListScreen {
|
|
|
57
71
|
render(size) {
|
|
58
72
|
const visible = this.visible();
|
|
59
73
|
this.cursor = Math.min(this.cursor, Math.max(0, visible.length - 1));
|
|
60
|
-
const sideWidth = this.o.categories
|
|
74
|
+
const sideWidth = this.o.categories && !this.external
|
|
61
75
|
? Math.min(32, Math.max(...this.o.categories.map((c) => Text.width(c.label))) + 7)
|
|
62
76
|
: 0;
|
|
63
77
|
const rest = size.width - 1 - (sideWidth ? sideWidth + 3 : 0);
|
|
64
78
|
const detailsRight = rest >= 100;
|
|
65
79
|
const detailsWidth = detailsRight ? Math.min(52, Math.floor(rest * 0.38)) : rest;
|
|
66
80
|
const listWidth = detailsRight ? rest - detailsWidth - 3 : rest;
|
|
81
|
+
const top = this.topLines(size.width, visible.length);
|
|
82
|
+
const details = this.detailsLines(visible[this.cursor], detailsWidth);
|
|
83
|
+
const bottomDetails = !detailsRight && size.height - top.length >= 14 ? details.slice(0, 6) : [];
|
|
84
|
+
const rows = this.rows(visible);
|
|
85
|
+
const room = size.height - top.length - (bottomDetails.length ? bottomDetails.length + 1 : 0);
|
|
86
|
+
// A list longer than the room keeps one row for "▲ / ▼ more".
|
|
87
|
+
const listHeight = rows.length > room ? room - 1 : room;
|
|
88
|
+
const listLines = this.listLines(visible, rows, listHeight, listWidth);
|
|
89
|
+
const sideLines = sideWidth ? this.sideLines(sideWidth) : [];
|
|
90
|
+
const body = [...top];
|
|
91
|
+
const height = Math.max(listLines.length, detailsRight ? details.length : 0, sideLines.length);
|
|
92
|
+
for (let i = 0; i < Math.min(height, size.height - top.length); i++) {
|
|
93
|
+
const side = sideWidth ? Text.fit(sideLines[i] ?? '', sideWidth) + ' ' + Theme.dim(Theme.glyph.vline) + ' ' : '';
|
|
94
|
+
const main = Text.fit(listLines[i] ?? '', listWidth);
|
|
95
|
+
const right = detailsRight ? ' ' + Theme.dim(Theme.glyph.vline) + ' ' + (details[i] ?? '') : '';
|
|
96
|
+
body.push(side + main + right);
|
|
97
|
+
}
|
|
98
|
+
if (bottomDetails.length) {
|
|
99
|
+
// The details sit at the bottom, whatever the length of the list.
|
|
100
|
+
while (body.length < size.height - bottomDetails.length - 1)
|
|
101
|
+
body.push(sideWidth
|
|
102
|
+
? Text.fit(sideLines[body.length - top.length] ?? '', sideWidth) + ' ' + Theme.dim(Theme.glyph.vline)
|
|
103
|
+
: '');
|
|
104
|
+
body.push(Theme.dim(' ' + Theme.glyph.line.repeat(size.width - 3)), ...bottomDetails.map((l) => ' ' + l));
|
|
105
|
+
}
|
|
106
|
+
return { path: this.o.path, status: this.o.status, body, keys: this.keys(), notice: this.notice };
|
|
107
|
+
}
|
|
108
|
+
/** The rows above the list: the tabs, the intro, the search box (with a blank row after them). */
|
|
109
|
+
topLines(width, matches) {
|
|
67
110
|
const top = [];
|
|
68
|
-
if (this.o.tabs)
|
|
69
|
-
|
|
111
|
+
if (this.o.tabs) {
|
|
112
|
+
const row = ' ' +
|
|
70
113
|
this.o.tabs.items
|
|
71
114
|
.map((tab, i) => i === this.o.tabs.active
|
|
72
115
|
? tab.paint(' ' + tab.badge + ' ' + tab.label + ' ')
|
|
73
116
|
: Theme.muted(' ' + tab.label + ' '))
|
|
74
117
|
.join(' ') +
|
|
75
|
-
Theme.muted(' tab switches')
|
|
118
|
+
Theme.muted(' tab switches');
|
|
119
|
+
top.push(Text.truncate(row, width - 1), '');
|
|
120
|
+
}
|
|
76
121
|
const intro = typeof this.o.intro === 'string' ? [this.o.intro] : (this.o.intro ?? []);
|
|
77
122
|
for (const line of intro)
|
|
78
|
-
top.push(...Text.wrap(line,
|
|
123
|
+
top.push(...Text.wrap(line, width - 3).map((l) => ' ' + Theme.muted(l)));
|
|
79
124
|
if (this.searching || this.query)
|
|
80
125
|
top.push(' ' +
|
|
81
126
|
Theme.accent(Theme.glyph.search) +
|
|
82
127
|
' ' +
|
|
83
128
|
this.query +
|
|
84
129
|
(this.searching ? Theme.accent('▏') : '') +
|
|
85
|
-
Theme.muted(' ' +
|
|
130
|
+
Theme.muted(' ' + matches + ' match' + (matches === 1 ? '' : 'es')));
|
|
86
131
|
if (top.length)
|
|
87
132
|
top.push('');
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
// A list longer than the room keeps one row for "▲ / ▼ more".
|
|
93
|
-
const listHeight = rows.length > room ? room - 1 : room;
|
|
133
|
+
return top;
|
|
134
|
+
}
|
|
135
|
+
/** The rows of the list that fit: scrolled to keep the cursor in view, with "▲ above / ▼ more" under them. */
|
|
136
|
+
listLines(visible, rows, listHeight, listWidth) {
|
|
94
137
|
const cursorRow = rows.findIndex((r) => r.kind === 'item' && r.index === visible[this.cursor]);
|
|
95
138
|
if (cursorRow >= 0) {
|
|
96
139
|
// Keep the heading above the first entry in view, and the cursor inside the window.
|
|
@@ -113,26 +156,10 @@ export class ListScreen {
|
|
|
113
156
|
listLines.push(Theme.muted(' ' +
|
|
114
157
|
(above > 0 ? '▲ ' + above + ' above' : '') +
|
|
115
158
|
(above > 0 && below > 0 ? ' ' : '') +
|
|
116
|
-
(below > 0 ? '▼ ' + below + ' more' : '')
|
|
117
|
-
|
|
118
|
-
const sideLines = this.sideLines(sideWidth);
|
|
119
|
-
const body = [...top];
|
|
120
|
-
const height = Math.max(listLines.length, detailsRight ? details.length : 0, sideLines.length);
|
|
121
|
-
for (let i = 0; i < Math.min(height, size.height - top.length); i++) {
|
|
122
|
-
const side = sideWidth ? Text.fit(sideLines[i] ?? '', sideWidth) + ' ' + Theme.dim(Theme.glyph.vline) + ' ' : '';
|
|
123
|
-
const main = Text.fit(listLines[i] ?? '', listWidth);
|
|
124
|
-
const right = detailsRight ? ' ' + Theme.dim(Theme.glyph.vline) + ' ' + (details[i] ?? '') : '';
|
|
125
|
-
body.push(side + main + right);
|
|
126
|
-
}
|
|
127
|
-
if (bottomDetails.length) {
|
|
128
|
-
// The details sit at the bottom, whatever the length of the list.
|
|
129
|
-
while (body.length < size.height - bottomDetails.length - 1)
|
|
130
|
-
body.push(sideWidth
|
|
131
|
-
? Text.fit(sideLines[body.length - top.length] ?? '', sideWidth) + ' ' + Theme.dim(Theme.glyph.vline)
|
|
132
|
-
: '');
|
|
133
|
-
body.push(Theme.dim(' ' + Theme.glyph.line.repeat(size.width - 3)), ...bottomDetails.map((l) => ' ' + l));
|
|
159
|
+
(below > 0 ? '▼ ' + below + ' more' : '') +
|
|
160
|
+
(this.searching || this.query ? '' : ' / search')));
|
|
134
161
|
}
|
|
135
|
-
return
|
|
162
|
+
return listLines;
|
|
136
163
|
}
|
|
137
164
|
rowLine(row, visible, width) {
|
|
138
165
|
if (row.kind === 'section')
|
|
@@ -156,7 +183,9 @@ export class ListScreen {
|
|
|
156
183
|
' ';
|
|
157
184
|
if (!selected)
|
|
158
185
|
return ' ' + line;
|
|
159
|
-
return this.focus === 'list'
|
|
186
|
+
return this.focus === 'list' && this.active
|
|
187
|
+
? ' ' + Theme.selected(Text.strip(line))
|
|
188
|
+
: ' ' + Theme.accent(Text.strip(line));
|
|
160
189
|
}
|
|
161
190
|
sideLines(width) {
|
|
162
191
|
if (!this.o.categories)
|
|
@@ -199,12 +228,14 @@ export class ListScreen {
|
|
|
199
228
|
if (this.searching)
|
|
200
229
|
return [
|
|
201
230
|
['type', 'to search', 1],
|
|
202
|
-
['↵', this.o.multi ? 'done' : (this.
|
|
231
|
+
['↵', this.o.multi ? 'done' : this.enterLabel(this.valueAt(this.visible()[this.cursor])), 1],
|
|
203
232
|
['esc', 'clear search', 0],
|
|
204
233
|
['↑↓', 'move', 4],
|
|
205
234
|
];
|
|
206
235
|
const current = this.visible()[this.cursor];
|
|
236
|
+
const value = current === undefined ? undefined : this.o.items[current].value;
|
|
207
237
|
const flips = current !== undefined && this.o.items[current].flip;
|
|
238
|
+
const long = this.o.items.length > LONG_LIST;
|
|
208
239
|
return [
|
|
209
240
|
...(this.o.multi
|
|
210
241
|
? [
|
|
@@ -212,16 +243,19 @@ export class ListScreen {
|
|
|
212
243
|
...(this.o.enterTicks ? [] : [['↵', 'done', 1]]),
|
|
213
244
|
['a', 'tick all shown', 6],
|
|
214
245
|
]
|
|
215
|
-
: [
|
|
216
|
-
|
|
246
|
+
: [
|
|
247
|
+
...(this.enterLabel(value) ? [['↵', this.enterLabel(value), 1]] : []),
|
|
248
|
+
...(flips ? [['space', 'flip', 1]] : []),
|
|
249
|
+
]),
|
|
250
|
+
...this.actionsNow(value).map((a) => [
|
|
217
251
|
a.ctrl ? 'ctrl+' + a.key : a.key,
|
|
218
252
|
a.label,
|
|
219
253
|
a.ctrl ? 0 : (a.importance ?? 2),
|
|
220
254
|
]),
|
|
221
255
|
...(this.o.tabs ? [['tab', 'scope', 3]] : []),
|
|
222
|
-
...(this.o.categories ? [['←→', 'categories', 3]] : []),
|
|
256
|
+
...(this.o.categories && !this.external ? [['←→', 'categories', 3]] : []),
|
|
223
257
|
['↑↓', 'move', 5],
|
|
224
|
-
['/', 'search', 6],
|
|
258
|
+
['/', 'search', long ? 3 : 6],
|
|
225
259
|
['esc', this.o.escapeLabel ?? 'back', 0],
|
|
226
260
|
];
|
|
227
261
|
}
|
|
@@ -229,14 +263,53 @@ export class ListScreen {
|
|
|
229
263
|
setNotice(text) {
|
|
230
264
|
this.notice = text;
|
|
231
265
|
}
|
|
266
|
+
/** The categories are shown by the menu's navigation, which drives them (no sidebar of its own). */
|
|
267
|
+
get external() {
|
|
268
|
+
return this.o.categoryNav === 'external';
|
|
269
|
+
}
|
|
270
|
+
enterLabel(value) {
|
|
271
|
+
const label = this.o.enterLabel;
|
|
272
|
+
return (typeof label === 'function' ? label(this.currentCategory, value) : label) ?? 'open';
|
|
273
|
+
}
|
|
274
|
+
valueAt(index) {
|
|
275
|
+
return index === undefined ? undefined : this.o.items[index].value;
|
|
276
|
+
}
|
|
277
|
+
/** The categories of the list (empty without any). */
|
|
278
|
+
get categories() {
|
|
279
|
+
return this.o.categories ?? [];
|
|
280
|
+
}
|
|
281
|
+
/** Opens a category (the menu's navigation does this); a search in progress ends. */
|
|
282
|
+
setCategory(id) {
|
|
283
|
+
const index = this.categories.findIndex((c) => c.id === id);
|
|
284
|
+
if (index < 0 || index === this.category)
|
|
285
|
+
return;
|
|
286
|
+
this.category = index;
|
|
287
|
+
this.query = '';
|
|
288
|
+
this.searching = false;
|
|
289
|
+
this.cursor = 0;
|
|
290
|
+
this.offset = 0;
|
|
291
|
+
}
|
|
292
|
+
/** Whether the list has the keyboard (the highlight is drawn softer when it has not). */
|
|
293
|
+
setActive(on) {
|
|
294
|
+
this.active = on;
|
|
295
|
+
}
|
|
232
296
|
/** The id of the category open in the sidebar (undefined without a sidebar). */
|
|
233
297
|
get currentCategory() {
|
|
234
298
|
return this.o.categories?.[this.category]?.id;
|
|
235
299
|
}
|
|
236
|
-
/** The extra keys that work now (they may depend on the category). */
|
|
237
|
-
actionsNow() {
|
|
300
|
+
/** The extra keys that work now (they may depend on the category and on the highlighted entry). */
|
|
301
|
+
actionsNow(value) {
|
|
238
302
|
const actions = this.o.actions;
|
|
239
|
-
|
|
303
|
+
const all = typeof actions === 'function' ? actions(this.currentCategory) : (actions ?? []);
|
|
304
|
+
return all.filter((a) => !a.applies || (value !== undefined && a.applies(value)));
|
|
305
|
+
}
|
|
306
|
+
/** The value under the cursor (undefined: the list is empty). */
|
|
307
|
+
get current() {
|
|
308
|
+
return this.valueAt(this.visible()[this.cursor]);
|
|
309
|
+
}
|
|
310
|
+
/** The text of the search (empty: none). */
|
|
311
|
+
get searchText() {
|
|
312
|
+
return this.query;
|
|
240
313
|
}
|
|
241
314
|
/** Keys are going into the search box (digits and letters are text, not shortcuts). */
|
|
242
315
|
get isSearching() {
|
|
@@ -250,15 +323,10 @@ export class ListScreen {
|
|
|
250
323
|
const visible = this.visible();
|
|
251
324
|
const current = visible[this.cursor];
|
|
252
325
|
this.notice = undefined;
|
|
253
|
-
const
|
|
326
|
+
const value = this.valueAt(current);
|
|
327
|
+
const ctrlAction = key.ctrl ? this.actionsNow(value).find((a) => a.ctrl && a.key === key.name) : undefined;
|
|
254
328
|
if (ctrlAction)
|
|
255
|
-
return {
|
|
256
|
-
done: {
|
|
257
|
-
kind: 'action',
|
|
258
|
-
key: 'ctrl+' + ctrlAction.key,
|
|
259
|
-
value: current === undefined ? undefined : this.o.items[current].value,
|
|
260
|
-
},
|
|
261
|
-
};
|
|
329
|
+
return { done: { kind: 'action', key: 'ctrl+' + ctrlAction.key, value } };
|
|
262
330
|
const move = (by) => {
|
|
263
331
|
this.cursor = Math.max(0, Math.min(visible.length - 1, this.cursor + by));
|
|
264
332
|
};
|
|
@@ -318,7 +386,9 @@ export class ListScreen {
|
|
|
318
386
|
const n = this.o.tabs.items.length;
|
|
319
387
|
return { done: { kind: 'tab', index: (this.o.tabs.active + (key.shift ? n - 1 : 1)) % n } };
|
|
320
388
|
}
|
|
321
|
-
if (this.
|
|
389
|
+
if (this.external && !this.query && !this.searching && key.name === 'left')
|
|
390
|
+
return { done: { kind: 'back' } };
|
|
391
|
+
if (this.o.categories && !this.external && !this.query) {
|
|
322
392
|
if (key.name === 'left' && this.focus === 'list') {
|
|
323
393
|
this.focus = 'side';
|
|
324
394
|
return;
|
|
@@ -370,15 +440,9 @@ export class ListScreen {
|
|
|
370
440
|
}
|
|
371
441
|
return { done: { kind: 'pick', value: it.value } };
|
|
372
442
|
}
|
|
373
|
-
const action = !this.searching && key.text ? this.actionsNow().find((a) => !a.ctrl && a.key === key.text) : undefined;
|
|
443
|
+
const action = !this.searching && key.text ? this.actionsNow(value).find((a) => !a.ctrl && a.key === key.text) : undefined;
|
|
374
444
|
if (action)
|
|
375
|
-
return {
|
|
376
|
-
done: {
|
|
377
|
-
kind: 'action',
|
|
378
|
-
key: action.key,
|
|
379
|
-
value: current === undefined ? undefined : this.o.items[current].value,
|
|
380
|
-
},
|
|
381
|
-
};
|
|
445
|
+
return { done: { kind: 'action', key: action.key, value } };
|
|
382
446
|
return;
|
|
383
447
|
}
|
|
384
448
|
toggle(index) {
|
|
@@ -26,9 +26,11 @@ export interface Category {
|
|
|
26
26
|
label: string;
|
|
27
27
|
description?: string;
|
|
28
28
|
}
|
|
29
|
-
export interface ListAction {
|
|
29
|
+
export interface ListAction<T = unknown> {
|
|
30
30
|
key: string;
|
|
31
31
|
label: string;
|
|
32
|
+
/** Only while an entry this accepts is highlighted: the key bar and the key itself ignore it otherwise. */
|
|
33
|
+
applies?: (value: T) => boolean;
|
|
32
34
|
/** Pressed with Ctrl (ctrl+s ...); works while searching too. */
|
|
33
35
|
ctrl?: boolean;
|
|
34
36
|
/** How long it survives in a narrow footer: 0 never goes, bigger goes earlier (default 2). */
|
|
@@ -69,8 +71,10 @@ export interface ListOptions<T> {
|
|
|
69
71
|
/** Start on this entry (and its category). */
|
|
70
72
|
startAt?: T;
|
|
71
73
|
startCategory?: string;
|
|
74
|
+
/** Start with this search typed (it shows every match in all categories; Esc clears it). */
|
|
75
|
+
startQuery?: string;
|
|
72
76
|
/** Extra keys; a function picks them by the open category. */
|
|
73
|
-
actions?: ListAction[] | ((category: string | undefined) => ListAction[]);
|
|
77
|
+
actions?: ListAction<T>[] | ((category: string | undefined) => ListAction<T>[]);
|
|
74
78
|
notice?: string;
|
|
75
79
|
empty?: string;
|
|
76
80
|
tabs?: {
|
|
@@ -79,6 +83,8 @@ export interface ListOptions<T> {
|
|
|
79
83
|
};
|
|
80
84
|
/** What Esc does, for the footer ("back", "quit"). */
|
|
81
85
|
escapeLabel?: string;
|
|
82
|
-
/** What Enter does, for the footer ("open", "edit", "start"). */
|
|
83
|
-
enterLabel?: string;
|
|
86
|
+
/** What Enter does, for the footer ("open", "edit", "start"); a function picks it by entry ("": none). */
|
|
87
|
+
enterLabel?: string | ((category: string | undefined, value: T | undefined) => string);
|
|
88
|
+
/** Where the categories are listed: in a sidebar of the list itself (default) or in the menu's own navigation. */
|
|
89
|
+
categoryNav?: 'own' | 'external';
|
|
84
90
|
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
export interface NavCategory {
|
|
2
|
+
readonly label: string;
|
|
3
|
+
/** The category open in the list. */
|
|
4
|
+
readonly current: boolean;
|
|
5
|
+
}
|
|
6
|
+
export interface NavSection {
|
|
7
|
+
readonly label: string;
|
|
8
|
+
/** Something is waiting in this section (unsaved changes). */
|
|
9
|
+
readonly marked?: boolean;
|
|
10
|
+
/** The categories of the open section (other sections are drawn without theirs). */
|
|
11
|
+
readonly categories: readonly NavCategory[];
|
|
12
|
+
}
|
|
13
|
+
export interface NavState {
|
|
14
|
+
readonly sections: readonly NavSection[];
|
|
15
|
+
/** Index of the open section. */
|
|
16
|
+
readonly active: number;
|
|
17
|
+
/** The navigation has the keyboard (else the list has it). */
|
|
18
|
+
readonly focused: boolean;
|
|
19
|
+
/** A dialog or sub-screen is shown over the menu: everything is drawn grey. */
|
|
20
|
+
readonly dimmed?: boolean;
|
|
21
|
+
}
|
|
22
|
+
export declare class SideNav {
|
|
23
|
+
/** Columns the navigation takes on a terminal `termWidth` columns wide (without the divider). */
|
|
24
|
+
static width(termWidth: number): number;
|
|
25
|
+
/** Exactly `height` lines, each `SideNav.width(termWidth)` columns wide. */
|
|
26
|
+
static render(nav: NavState, termWidth: number, height: number): string[];
|
|
27
|
+
private static section;
|
|
28
|
+
private static category;
|
|
29
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
// The navigation on the left of every menu screen: the sections as a tree (the open one shows its categories), with
|
|
2
|
+
// the way you are standing marked. Narrow terminals get a slim column of numbers instead of names. Pure (tested).
|
|
3
|
+
import { Text } from './text.js';
|
|
4
|
+
import { Theme } from './theme.js';
|
|
5
|
+
/** Terminals narrower than this get the slim column. */
|
|
6
|
+
const SLIM_BELOW = 80;
|
|
7
|
+
const SLIM_WIDTH = 5;
|
|
8
|
+
export class SideNav {
|
|
9
|
+
/** Columns the navigation takes on a terminal `termWidth` columns wide (without the divider). */
|
|
10
|
+
static width(termWidth) {
|
|
11
|
+
if (termWidth < SLIM_BELOW)
|
|
12
|
+
return SLIM_WIDTH;
|
|
13
|
+
return termWidth >= 130 ? 28 : 24;
|
|
14
|
+
}
|
|
15
|
+
/** Exactly `height` lines, each `SideNav.width(termWidth)` columns wide. */
|
|
16
|
+
static render(nav, termWidth, height) {
|
|
17
|
+
const width = SideNav.width(termWidth);
|
|
18
|
+
const slim = width === SLIM_WIDTH;
|
|
19
|
+
const lines = [];
|
|
20
|
+
nav.sections.forEach((section, i) => {
|
|
21
|
+
const open = i === nav.active;
|
|
22
|
+
const hasCategories = open && section.categories.length > 0;
|
|
23
|
+
const standing = open && !hasCategories;
|
|
24
|
+
lines.push({ text: SideNav.section(nav, section, i, width, slim, standing), stop: standing });
|
|
25
|
+
if (!hasCategories)
|
|
26
|
+
return;
|
|
27
|
+
section.categories.forEach((cat, c) => {
|
|
28
|
+
const last = c === section.categories.length - 1;
|
|
29
|
+
lines.push({ text: SideNav.category(nav, cat, last, width, slim), stop: cat.current });
|
|
30
|
+
});
|
|
31
|
+
});
|
|
32
|
+
const at = Math.max(0, lines.findIndex((l) => l.stop));
|
|
33
|
+
const start = lines.length > height ? Math.min(Math.max(0, at - Math.floor(height / 2)), lines.length - height) : 0;
|
|
34
|
+
const shown = lines.slice(start, start + height).map((l) => l.text);
|
|
35
|
+
while (shown.length < height)
|
|
36
|
+
shown.push(' '.repeat(width));
|
|
37
|
+
return shown;
|
|
38
|
+
}
|
|
39
|
+
static section(nav, section, index, width, slim, standing) {
|
|
40
|
+
const open = index === nav.active;
|
|
41
|
+
const live = !nav.dimmed;
|
|
42
|
+
// The open section has a marker, so it shows without colour.
|
|
43
|
+
const lead = open ? (section.categories.length ? '▾' : Theme.glyph.pointer) : ' ';
|
|
44
|
+
const mark = section.marked ? Theme.changed(Theme.glyph.changed) : ' ';
|
|
45
|
+
const inner = slim
|
|
46
|
+
? lead + (index + 1) + mark + ' '
|
|
47
|
+
: Text.fit(lead + (index + 1) + ' ' + (open && live ? Theme.bold(section.label) : section.label), width - 3) +
|
|
48
|
+
' ' +
|
|
49
|
+
mark +
|
|
50
|
+
' ';
|
|
51
|
+
if (standing && live && nav.focused)
|
|
52
|
+
return Theme.selected(Text.fit(inner, width));
|
|
53
|
+
if (!live || !open)
|
|
54
|
+
return Theme.muted(Text.fit(inner, width));
|
|
55
|
+
return nav.focused ? Text.fit(inner, width) : Theme.accent(Text.fit(inner, width));
|
|
56
|
+
}
|
|
57
|
+
static category(nav, cat, last, width, slim) {
|
|
58
|
+
const live = !nav.dimmed;
|
|
59
|
+
const plain = slim
|
|
60
|
+
? ' ' + (cat.current ? Theme.glyph.on : Theme.glyph.dot) + ' '
|
|
61
|
+
: ' ' + (cat.current ? Theme.glyph.pointer : last ? '└' : '├') + ' ' + cat.label;
|
|
62
|
+
const line = Text.fit(plain, width);
|
|
63
|
+
if (!cat.current || !live)
|
|
64
|
+
return Theme.muted(line);
|
|
65
|
+
return nav.focused ? Theme.selected(line) : Theme.accentBold(line);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
@@ -10,6 +10,8 @@ export interface Key {
|
|
|
10
10
|
export declare class ExitRequested extends Error {
|
|
11
11
|
constructor();
|
|
12
12
|
}
|
|
13
|
+
/** Whether this terminal is known to take synchronized updates (AGENT_SANDBOX_SYNC_UPDATE=1 or 0 overrides). */
|
|
14
|
+
export declare function supportsSyncUpdate(env?: NodeJS.ProcessEnv): boolean;
|
|
13
15
|
export declare class Terminal {
|
|
14
16
|
private readonly stdin;
|
|
15
17
|
private readonly stdout;
|
|
@@ -18,17 +20,22 @@ export declare class Terminal {
|
|
|
18
20
|
private queue;
|
|
19
21
|
private waiting;
|
|
20
22
|
private resizeHandler;
|
|
23
|
+
private readonly sync;
|
|
21
24
|
private readonly onKeypress;
|
|
22
25
|
private readonly onResize;
|
|
23
26
|
constructor(stdin?: NodeJS.ReadStream, stdout?: NodeJS.WriteStream);
|
|
24
27
|
get width(): number;
|
|
25
28
|
get height(): number;
|
|
29
|
+
/** Keys can be read from a real terminal here (the menu refuses to open without one). */
|
|
30
|
+
get interactive(): boolean;
|
|
26
31
|
/** Called after the window was resized (the screen draws itself again). */
|
|
27
32
|
onResized(handler: (() => void) | null): void;
|
|
28
33
|
start(): void;
|
|
29
34
|
/** Gives the terminal back exactly as it was (also on errors: callers use try/finally). */
|
|
30
35
|
stop(): void;
|
|
31
36
|
get running(): boolean;
|
|
37
|
+
/** Key presses are waiting to be read (the screen may skip a draw and show the result of the last one). */
|
|
38
|
+
get hasKeys(): boolean;
|
|
32
39
|
/** Draws a whole screen: `lines` are cut to the width and padded to the height; unchanged rows are not rewritten. */
|
|
33
40
|
render(lines: string[]): void;
|
|
34
41
|
/** The next key press. Ctrl+C rejects with ExitRequested. */
|
package/dist/cli/tui/terminal.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// The terminal while the menu owns it: the alternate screen (your scrollback stays as it was), raw keys, a cursor that
|
|
2
|
-
// is hidden, and redraws that only rewrite the rows that changed
|
|
3
|
-
// a command's own output;
|
|
2
|
+
// is hidden, and redraws that only rewrite the rows that changed, in one write (inside a synchronized update where the
|
|
3
|
+
// terminal has one), so nothing flickers. stop() hands the terminal back for a command's own output; start() takes it
|
|
4
|
+
// again.
|
|
4
5
|
import readline from 'node:readline';
|
|
5
6
|
import { Text } from './text.js';
|
|
6
7
|
/** Ctrl+C: leave the menu at once (callers let it propagate to the top). */
|
|
@@ -10,6 +11,17 @@ export class ExitRequested extends Error {
|
|
|
10
11
|
this.name = 'ExitPromptError';
|
|
11
12
|
}
|
|
12
13
|
}
|
|
14
|
+
/** DEC 2026: the terminal shows a frame only when it is complete. Others ignore it, so only these are asked. */
|
|
15
|
+
const SYNC_BEGIN = '\x1b[?2026h';
|
|
16
|
+
const SYNC_END = '\x1b[?2026l';
|
|
17
|
+
/** Whether this terminal is known to take synchronized updates (AGENT_SANDBOX_SYNC_UPDATE=1 or 0 overrides). */
|
|
18
|
+
export function supportsSyncUpdate(env = process.env) {
|
|
19
|
+
const forced = env.AGENT_SANDBOX_SYNC_UPDATE;
|
|
20
|
+
if (forced === '1' || forced === '0')
|
|
21
|
+
return forced === '1';
|
|
22
|
+
const program = env.TERM_PROGRAM ?? '';
|
|
23
|
+
return Boolean(env.WT_SESSION) || ['vscode', 'WezTerm', 'iTerm.app', 'ghostty', 'contour'].includes(program);
|
|
24
|
+
}
|
|
13
25
|
export class Terminal {
|
|
14
26
|
stdin;
|
|
15
27
|
stdout;
|
|
@@ -18,6 +30,7 @@ export class Terminal {
|
|
|
18
30
|
queue = [];
|
|
19
31
|
waiting = null;
|
|
20
32
|
resizeHandler = null;
|
|
33
|
+
sync = supportsSyncUpdate();
|
|
21
34
|
onKeypress = (str, key) => this.push(str, key);
|
|
22
35
|
onResize = () => {
|
|
23
36
|
this.frame = [];
|
|
@@ -33,6 +46,10 @@ export class Terminal {
|
|
|
33
46
|
get height() {
|
|
34
47
|
return Math.max(12, this.stdout.rows ?? 30);
|
|
35
48
|
}
|
|
49
|
+
/** Keys can be read from a real terminal here (the menu refuses to open without one). */
|
|
50
|
+
get interactive() {
|
|
51
|
+
return Boolean(this.stdin.isTTY);
|
|
52
|
+
}
|
|
36
53
|
/** Called after the window was resized (the screen draws itself again). */
|
|
37
54
|
onResized(handler) {
|
|
38
55
|
this.resizeHandler = handler;
|
|
@@ -66,21 +83,24 @@ export class Terminal {
|
|
|
66
83
|
get running() {
|
|
67
84
|
return this.active;
|
|
68
85
|
}
|
|
86
|
+
/** Key presses are waiting to be read (the screen may skip a draw and show the result of the last one). */
|
|
87
|
+
get hasKeys() {
|
|
88
|
+
return this.queue.length > 0;
|
|
89
|
+
}
|
|
69
90
|
/** Draws a whole screen: `lines` are cut to the width and padded to the height; unchanged rows are not rewritten. */
|
|
70
91
|
render(lines) {
|
|
71
92
|
const { width, height } = this;
|
|
72
93
|
// One column is left free: writing the last column can scroll older consoles.
|
|
73
94
|
const rows = Array.from({ length: height }, (_, i) => Text.fit(lines[i] ?? '', width - 1));
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
out = '\x1b[H\x1b[2J' + rows.map((r, i) => '\x1b[' + (i + 1) + ';1H' + r + '\x1b[0m').join('');
|
|
95
|
+
// A different height (or nothing drawn yet: after a resize or a start) repaints everything.
|
|
96
|
+
const repaint = this.frame.length !== rows.length;
|
|
97
|
+
const out = (repaint ? '\x1b[H\x1b[2J' : '') +
|
|
98
|
+
rows
|
|
99
|
+
.map((row, i) => (repaint || this.frame[i] !== row ? '\x1b[' + (i + 1) + ';1H' + row + '\x1b[0m' : ''))
|
|
100
|
+
.join('');
|
|
81
101
|
this.frame = rows;
|
|
82
102
|
if (out)
|
|
83
|
-
this.stdout.write(out);
|
|
103
|
+
this.stdout.write(this.sync ? SYNC_BEGIN + out + SYNC_END : out);
|
|
84
104
|
}
|
|
85
105
|
/** The next key press. Ctrl+C rejects with ExitRequested. */
|
|
86
106
|
key() {
|
package/dist/cli/validate.d.ts
CHANGED
|
@@ -12,6 +12,6 @@ export declare function validPythonSpec(spec: string): boolean;
|
|
|
12
12
|
export declare function checkHarness(name: string | undefined, harnesses: string[]): void;
|
|
13
13
|
export declare const PROJECT_ACTIONS: readonly ["list", "choose", "add", "remove", "include", "exclude", "all", "roots"];
|
|
14
14
|
/** `sandbox projects <action> [value] [folder]`: the action, then what it needs. Pure (no file checks). */
|
|
15
|
-
export declare function validateProjectsArgs(args: string[]): void;
|
|
15
|
+
export declare function validateProjectsArgs(args: string[], canAsk?: boolean): void;
|
|
16
16
|
/** Fails with what is wrong and what is valid, before anything is started. */
|
|
17
17
|
export declare function validateOptions(ctx: Context): void;
|
package/dist/cli/validate.js
CHANGED
|
@@ -44,11 +44,11 @@ export function checkHarness(name, harnesses) {
|
|
|
44
44
|
const LAUNCHING = new Set(['launch', 'generate', 'host-claude']);
|
|
45
45
|
export const PROJECT_ACTIONS = ['list', 'choose', 'add', 'remove', 'include', 'exclude', 'all', 'roots'];
|
|
46
46
|
/** `sandbox projects <action> [value] [folder]`: the action, then what it needs. Pure (no file checks). */
|
|
47
|
-
export function validateProjectsArgs(args) {
|
|
47
|
+
export function validateProjectsArgs(args, canAsk = false) {
|
|
48
48
|
const [action = 'list', value, folder] = args;
|
|
49
49
|
if (!PROJECT_ACTIONS.includes(action))
|
|
50
50
|
unknownValue('projects action', action, PROJECT_ACTIONS, 'sandbox projects with no action lists your projects.');
|
|
51
|
-
if (['add', 'remove', 'include', 'exclude'].includes(action) && !value)
|
|
51
|
+
if (['add', 'remove', 'include', 'exclude'].includes(action) && !value && !canAsk)
|
|
52
52
|
fail('Which folder?', 'Usage: sandbox projects ' + action + ' <folder> (. = this folder)');
|
|
53
53
|
if (action === 'all' && value !== undefined && !['on', 'off'].includes(value))
|
|
54
54
|
unknownValue('value for projects all', value, ['on', 'off'], 'sandbox projects all on|off');
|
|
@@ -64,7 +64,7 @@ export function validateOptions(ctx) {
|
|
|
64
64
|
if (['launch', 'generate', 'restart', 'doctor'].includes(o.command))
|
|
65
65
|
checkHarness(o.harness, harnesses);
|
|
66
66
|
if (o.command === 'projects')
|
|
67
|
-
validateProjectsArgs(o.positionals);
|
|
67
|
+
validateProjectsArgs(o.positionals, Boolean(process.stdin.isTTY));
|
|
68
68
|
if (!LAUNCHING.has(o.command))
|
|
69
69
|
return;
|
|
70
70
|
if (o.node !== undefined && !validNodeSpec(o.node))
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
// `sandbox --version`: the version and where it runs from; `--version --short` is the plain number (the updater and the
|
|
2
|
+
// installer compare it to the version they just installed).
|
|
3
|
+
import { packageVersion } from '../core/package-info.js';
|
|
4
|
+
import { describeCopy } from '../host/install/index.js';
|
|
5
|
+
/** The text for a version-only command line (`--version`, `-v`, with or without `--short`), or null for any other. */
|
|
6
|
+
export function versionText(argv, packageRoot) {
|
|
7
|
+
const flags = argv.filter((a) => a !== '--short');
|
|
8
|
+
if (flags.length === 0 || flags.some((a) => a !== '--version' && a !== '-v'))
|
|
9
|
+
return null;
|
|
10
|
+
return argv.includes('--short') ? packageVersion() : packageVersion() + ' (' + describeCopy(packageRoot) + ')';
|
|
11
|
+
}
|