windows-development-sandbox 1.7.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/config.example.json +10 -0
- 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} +2 -0
- package/dist/{cli/menu/settings/categories.js → app/features/settings/categories.def.js} +24 -5
- 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/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 +5 -0
- package/dist/cli/args.js +6 -0
- package/dist/cli/commands/engine.d.ts +2 -0
- package/dist/cli/commands/engine.js +60 -0
- package/dist/cli/commands/index.d.ts +1 -1
- package/dist/cli/commands/index.js +1 -1
- package/dist/cli/commands/launch/launch.js +47 -7
- package/dist/cli/commands/launch/prepare.js +3 -3
- package/dist/cli/commands/launch/running.js +2 -1
- package/dist/cli/commands/launch/summary.d.ts +2 -0
- 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.js +8 -82
- package/dist/cli/commands/maintenance/logs.js +14 -0
- package/dist/cli/commands/registry.js +3 -7
- 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/hcs.d.ts +7 -0
- package/dist/cli/commands/repair/checks/hcs.js +28 -0
- package/dist/cli/commands/repair/checks/index.js +4 -0
- package/dist/cli/commands/repair/checks/pc.js +32 -1
- package/dist/cli/commands/repair/checks/sandbox.js +16 -1
- package/dist/cli/commands/repair/checks/vpn.js +34 -9
- package/dist/cli/commands/repair/env.js +2 -1
- package/dist/cli/commands/sessions/index.d.ts +0 -4
- package/dist/cli/commands/sessions/index.js +3 -7
- 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/offer.js +7 -1
- package/dist/cli/commands/storage/storage.js +10 -2
- package/dist/cli/commands/user-config.js +1 -1
- package/dist/cli/commands/vpn.js +19 -3
- package/dist/cli/commands/web.js +2 -0
- package/dist/cli/index.js +2 -1
- package/dist/cli/manifest.d.ts +72 -104
- package/dist/cli/manifest.js +64 -39
- package/dist/cli/menu/add-agent.d.ts +1 -1
- package/dist/cli/menu/add-agent.js +1 -1
- package/dist/cli/menu/apps.d.ts +7 -1
- package/dist/cli/menu/apps.js +36 -0
- package/dist/cli/menu/command-fields.d.ts +1 -1
- package/dist/cli/menu/command-form.js +2 -2
- 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 +10 -1
- package/dist/cli/menu/menu.js +27 -9
- package/dist/cli/menu/pages/agents-page.d.ts +3 -1
- package/dist/cli/menu/pages/agents-page.js +12 -5
- package/dist/cli/menu/pages/apps-page.d.ts +3 -1
- package/dist/cli/menu/pages/apps-page.js +19 -2
- package/dist/cli/menu/pages/list-page.d.ts +27 -0
- package/dist/cli/menu/pages/list-page.js +109 -7
- package/dist/cli/menu/pages/maintenance-page.d.ts +0 -5
- package/dist/cli/menu/pages/maintenance-page.js +17 -19
- package/dist/cli/menu/pages/sandbox-page.d.ts +4 -6
- package/dist/cli/menu/pages/sandbox-page.js +26 -118
- package/dist/cli/menu/pages/scopes.d.ts +1 -1
- package/dist/cli/menu/pages/sessions-page.d.ts +5 -11
- package/dist/cli/menu/pages/sessions-page.js +19 -88
- package/dist/cli/menu/pages/settings-page.d.ts +2 -10
- package/dist/cli/menu/pages/settings-page.js +64 -94
- package/dist/cli/menu/render-view.d.ts +28 -0
- package/dist/cli/menu/render-view.js +112 -0
- package/dist/cli/menu/settings/{path-kind.d.ts → ask-path.d.ts} +1 -7
- package/dist/cli/menu/settings/ask-path.js +14 -0
- package/dist/cli/menu/settings/collections/collection-editor.d.ts +1 -1
- package/dist/cli/menu/settings/collections/string-list-editor.d.ts +1 -2
- package/dist/cli/menu/settings/collections/string-list-editor.js +1 -1
- 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 +1 -1
- 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 +5 -1
- package/dist/cli/menu/settings/value-editor.js +57 -54
- package/dist/cli/menu/several.js +1 -1
- 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 +21 -5
- package/dist/cli/menu/shell.js +31 -6
- package/dist/cli/menu/views.d.ts +7 -0
- package/dist/cli/menu/views.js +11 -0
- package/dist/cli/menu/vpn-login.js +8 -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 +3 -1
- package/dist/cli/output/print.js +7 -3
- 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/agent-commands-service.d.ts +2 -0
- package/dist/cli/services/agent-commands-service.js +11 -2
- package/dist/cli/services/logs-service.js +4 -3
- package/dist/cli/tui/app.d.ts +6 -1
- package/dist/cli/tui/app.js +26 -4
- package/dist/cli/tui/list/list-screen.d.ts +14 -0
- package/dist/cli/tui/list/list-screen.js +64 -36
- package/dist/cli/tui/list/list-types.d.ts +2 -0
- package/dist/cli/tui/terminal.d.ts +7 -0
- package/dist/cli/tui/terminal.js +30 -10
- package/dist/core/config/defaults.js +8 -0
- package/dist/core/schema/config.d.ts +13 -0
- package/dist/core/schema/config.js +16 -1
- package/dist/core/schema/harness.d.ts +1 -0
- package/dist/core/schema/harness.js +5 -0
- package/dist/core/schema/sandbox.d.ts +6 -0
- package/dist/core/schema/sandbox.js +20 -3
- package/dist/core/schema/vpn.d.ts +2 -1
- package/dist/core/schema/vpn.js +3 -3
- package/dist/core/types.d.ts +23 -5
- 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 +5 -0
- package/dist/guest/agents/agent-files.js +4 -0
- package/dist/guest/agents/local-state.d.ts +2 -0
- package/dist/guest/agents/local-state.js +21 -1
- package/dist/guest/boot/boot.js +2 -1
- package/dist/guest/daemon/daemon.js +4 -0
- package/dist/guest/daemon/sessions.d.ts +5 -0
- package/dist/guest/daemon/sessions.js +17 -3
- package/dist/guest/entries/daemon.js +3 -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 +1 -0
- package/dist/guest/runtime/csc.js +1 -0
- package/dist/guest/sessions/viewer.js +3 -1
- package/dist/guest/toolchains/native/rust-extras.js +4 -2
- package/dist/guest/vpn/vpn.js +69 -21
- 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 +3 -1
- package/dist/host/channel/attach.js +5 -2
- package/dist/host/channel/channel.d.ts +2 -0
- package/dist/host/channel/channel.js +4 -0
- 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/launch/generate.d.ts +5 -1
- package/dist/host/launch/generate.js +50 -8
- 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 +7 -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/native.d.ts +3 -2
- package/dist/host/native.js +22 -3
- package/dist/host/profile/claude-login.js +3 -2
- 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 +2 -0
- package/dist/host/sandbox/platform.js +7 -7
- package/dist/host/sandbox/tasklist.d.ts +13 -0
- package/dist/host/sandbox/tasklist.js +47 -0
- package/dist/host/secrets/launch-secrets.js +2 -1
- package/dist/host/sharing/current.js +2 -6
- 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/index.d.ts +2 -0
- package/dist/host/storage/index.js +2 -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/tools/conpty.js +3 -2
- package/dist/host/tools/windows-terminal.js +8 -7
- package/dist/host/vpn/index.d.ts +1 -1
- package/dist/host/vpn/index.js +1 -1
- package/dist/host/vpn/prepare.d.ts +2 -0
- package/dist/host/vpn/prepare.js +63 -2
- package/dist/host/web/browser.d.ts +2 -0
- package/dist/host/web/browser.js +14 -1
- package/dist/host/web/index.d.ts +3 -2
- package/dist/host/web/index.js +3 -2
- package/dist/host/web/rpc.d.ts +24 -0
- package/dist/host/web/rpc.js +149 -0
- package/dist/host/web/runner.d.ts +2 -0
- package/dist/host/web/runner.js +1 -2
- package/dist/host/web/server.d.ts +7 -0
- package/dist/host/web/server.js +23 -3
- package/dist/runtime/agent.js +69 -8
- package/dist/runtime/daemon.js +1058 -624
- package/dist/runtime/db.js +69 -8
- package/dist/runtime/main.js +624 -182
- package/dist/runtime/netproxy.js +69 -8
- package/dist/runtime/view.js +87 -13
- package/dist/selftest/agent-paths.test.js +11 -1
- package/dist/selftest/app.test.d.ts +2 -0
- package/dist/selftest/app.test.js +324 -0
- package/dist/selftest/channel.test.js +13 -0
- package/dist/selftest/cli.test.js +2 -1
- 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.js +1 -1
- package/dist/selftest/engine.test.d.ts +2 -0
- package/dist/selftest/engine.test.js +127 -0
- package/dist/selftest/hcs.test.d.ts +2 -0
- package/dist/selftest/hcs.test.js +482 -0
- package/dist/selftest/heavy-load.test.d.ts +2 -0
- package/dist/selftest/heavy-load.test.js +329 -0
- package/dist/selftest/index.js +12 -0
- package/dist/selftest/layout.test.js +12 -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.js +4 -2
- package/dist/selftest/menu.test.js +36 -8
- 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 +7 -1
- package/dist/selftest/support/hcs-probes.d.ts +17 -0
- package/dist/selftest/support/hcs-probes.js +41 -0
- package/dist/selftest/vpn.test.js +136 -3
- package/dist/selftest/web.test.js +101 -3
- package/dist/shared/channel/run-dir.d.ts +4 -1
- package/dist/shared/channel/run-dir.js +7 -1
- package/dist/shared/channel/schema.d.ts +35 -1
- package/dist/shared/channel/schema.js +27 -0
- package/dist/shared/channel/secrets.d.ts +1 -0
- package/dist/shared/channel/secrets.js +6 -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 +16 -0
- package/dist/shared/vpn/download.js +16 -0
- package/dist/shared/vpn/wireguard.d.ts +51 -0
- package/dist/shared/vpn/wireguard.js +227 -0
- package/dist/sync/sync-cycle.js +5 -5
- package/dist/sync/watcher.d.ts +13 -0
- package/dist/sync/watcher.js +92 -3
- package/dist/web/index.html +4 -3
- package/dist/web/main-NRRS5O6Z.js +157 -0
- package/dist/web/main-T5DMCHYV.css +1 -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/run-elevated.ps1 +17 -4
- package/native/scripts/stop-events.ps1 +23 -8
- package/package.json +9 -2
- package/sandbox/csharp/MemGov.cs +398 -0
- package/sandbox/csharp/PtyHost.cs +111 -5
- package/schemas/config.schema.json +60 -6
- package/schemas/sandbox-config.schema.json +3 -3
- 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 -48
- package/dist/cli/commands/sessions/status.d.ts +0 -4
- package/dist/cli/commands/sessions/status.js +0 -114
- package/dist/cli/commands/sessions/window.d.ts +0 -3
- package/dist/cli/commands/sessions/window.js +0 -18
- package/dist/cli/menu/settings/path-kind.js +0 -44
- package/dist/web/main-CXESL347.js +0 -45
- package/dist/web/main-VLR7DVQ4.css +0 -1
- /package/dist/{cli/menu/settings → app/kernel}/schema-node.d.ts +0 -0
- /package/dist/{cli/menu/settings → app/kernel}/schema-node.js +0 -0
|
@@ -1,110 +1,41 @@
|
|
|
1
|
-
// Section 2: the agent sessions of the running sandbox
|
|
2
|
-
// menu), r restarts the agents.
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import { Theme } from '../../tui/index.js';
|
|
1
|
+
// Section 2: the agent sessions of the running sandbox, as the sessions view shows them (src/app/features/sessions).
|
|
2
|
+
// Enter shows one in this terminal (the one thing that leaves the menu), r restarts the agents.
|
|
3
|
+
import { listSessions, sessionsPage } from '../../../app/features/sessions/index.js';
|
|
4
|
+
import { readQuery } from '../../../app/registry.js';
|
|
5
|
+
import { MenuOperations } from '../io-menu.js';
|
|
6
|
+
import { menuView } from '../render-view.js';
|
|
8
7
|
import { ListPage } from './list-page.js';
|
|
9
|
-
|
|
8
|
+
function view(m) {
|
|
9
|
+
return menuView(sessionsPage({ ...m, wide: false }));
|
|
10
|
+
}
|
|
10
11
|
/** The list for the sessions tab. Pure. */
|
|
11
12
|
export function sessionsOptions(m) {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
items: m.sessions.length
|
|
15
|
-
? m.sessions.map((s) => ({
|
|
16
|
-
value: s.id,
|
|
17
|
-
label: safeText(s.harness) + ' ' + safeText(s.projectName ?? '-'),
|
|
18
|
-
hint: s.phase + (s.exitCode !== undefined ? ' (' + s.exitCode + ')' : '') + ' ' + ago(s.startedAt),
|
|
19
|
-
section: s.here ? "This folder's project" : 'Other sessions',
|
|
20
|
-
description: s.phase === 'running'
|
|
21
|
-
? 'Enter shows this session in this terminal (Ctrl+] detaches; the session keeps running).'
|
|
22
|
-
: undefined,
|
|
23
|
-
details: [
|
|
24
|
-
Theme.muted('Session ') + s.id,
|
|
25
|
-
Theme.muted('Folder ') + safeText(s.cwd),
|
|
26
|
-
Theme.muted('Attached ') + viewerText(s.viewers),
|
|
27
|
-
],
|
|
28
|
-
...(s.phase === 'running' ? {} : { disabled: 'This session has ended.' }),
|
|
29
|
-
}))
|
|
30
|
-
: [
|
|
31
|
-
{
|
|
32
|
-
value: START,
|
|
33
|
-
label: 'Start ' + m.defaultAgent,
|
|
34
|
-
hint: Theme.muted('default agent'),
|
|
35
|
-
section: m.sandboxRunning ? 'No sessions' : 'No sandbox is running',
|
|
36
|
-
description: m.sandboxRunning
|
|
37
|
-
? 'No agent is running. Enter starts ' + m.defaultAgent + ' in this folder.'
|
|
38
|
-
: 'Enter starts the sandbox and ' + m.defaultAgent + ' in this folder; its session is listed here.',
|
|
39
|
-
},
|
|
40
|
-
],
|
|
41
|
-
actions: [
|
|
42
|
-
{ key: 'r', label: 'restart agents', importance: 1, applies: (id) => id !== START },
|
|
43
|
-
{ key: 'o', label: 'reopen last sessions', importance: 2 },
|
|
44
|
-
{ key: 'l', label: 'refresh', importance: 3 },
|
|
45
|
-
],
|
|
46
|
-
enterLabel: (_category, id) => (id === START ? 'start' : 'attach'),
|
|
47
|
-
};
|
|
13
|
+
const v = view(m);
|
|
14
|
+
return { path: [], items: v.items, actions: v.actions, enterLabel: v.enterLabel };
|
|
48
15
|
}
|
|
49
16
|
export class SessionsPage extends ListPage {
|
|
50
17
|
ctx;
|
|
51
18
|
label = 'Sessions';
|
|
52
19
|
model;
|
|
53
|
-
|
|
20
|
+
operations;
|
|
54
21
|
constructor(app, ctx) {
|
|
55
22
|
super(app);
|
|
56
23
|
this.ctx = ctx;
|
|
57
|
-
this.
|
|
58
|
-
this.model = { sandboxRunning: false, sessions: [], defaultAgent:
|
|
59
|
-
}
|
|
60
|
-
defaultAgent() {
|
|
61
|
-
return this.ctx.loaded.config.defaultHarness;
|
|
24
|
+
this.operations = new MenuOperations(app, ctx);
|
|
25
|
+
this.model = { sandboxRunning: false, sessions: [], defaultAgent: ctx.loaded.config.defaultHarness };
|
|
62
26
|
}
|
|
63
27
|
async load() {
|
|
64
|
-
|
|
65
|
-
try {
|
|
66
|
-
const list = sandboxRunning ? await this.service.list() : [];
|
|
67
|
-
this.model = { sandboxRunning, sessions: this.service.ordered(list), defaultAgent: this.defaultAgent() };
|
|
68
|
-
}
|
|
69
|
-
catch (e) {
|
|
70
|
-
this.model = { sandboxRunning, sessions: [], defaultAgent: this.defaultAgent() };
|
|
71
|
-
this.say(Theme.error(Theme.glyph.cross + ' ' + errMsg(e)));
|
|
72
|
-
}
|
|
28
|
+
this.model = await readQuery(listSessions, this.ctx);
|
|
73
29
|
}
|
|
74
30
|
options() {
|
|
75
31
|
return sessionsOptions(this.model);
|
|
76
32
|
}
|
|
77
33
|
async act(result) {
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
if (result.kind === 'pick')
|
|
81
|
-
return { exit: { kind: 'run', argv: ['attach', result.value] } };
|
|
82
|
-
if (result.kind !== 'action')
|
|
34
|
+
const chosen = view(this.model).resolve(result);
|
|
35
|
+
if (!chosen)
|
|
83
36
|
return {};
|
|
84
|
-
if (
|
|
37
|
+
if (chosen.kind === 'refresh')
|
|
85
38
|
return { reload: true };
|
|
86
|
-
|
|
87
|
-
return { exit: { kind: 'run', argv: ['resume'] } };
|
|
88
|
-
if (!this.model.sandboxRunning)
|
|
89
|
-
return { notice: Theme.warn('No sandbox is running.') };
|
|
90
|
-
const scope = this.service.restartScope(false);
|
|
91
|
-
const what = scope.guest ? 'the agents of ' + scope.projectName : 'every agent';
|
|
92
|
-
const ok = await this.app.ask('Restart ' + what + '?', [
|
|
93
|
-
'The agents are started again and continue their conversations where they can.',
|
|
94
|
-
...(scope.notAProject
|
|
95
|
-
? [scope.folder + ' is not a project of the running sandbox: every session restarts.']
|
|
96
|
-
: []),
|
|
97
|
-
], 'Restart');
|
|
98
|
-
if (!ok)
|
|
99
|
-
return {};
|
|
100
|
-
try {
|
|
101
|
-
return {
|
|
102
|
-
reload: true,
|
|
103
|
-
notice: Theme.ok(Theme.glyph.ok + ' ' + safeText(await this.service.restart(null, scope.guest))),
|
|
104
|
-
};
|
|
105
|
-
}
|
|
106
|
-
catch (e) {
|
|
107
|
-
return { notice: Theme.error(Theme.glyph.cross + ' ' + errMsg(e)) };
|
|
108
|
-
}
|
|
39
|
+
return this.operations.perform(chosen.action, [this.label], (text) => this.busy(text));
|
|
109
40
|
}
|
|
110
41
|
}
|
|
@@ -1,18 +1,10 @@
|
|
|
1
|
+
import { settingsOf, type ConfigFile, type Setting } from '../../../app/features/settings/index.js';
|
|
1
2
|
import type { Context } from '../../commands/context.js';
|
|
2
3
|
import { type App, type ListItem, type ListOptions, type ListResult } from '../../tui/index.js';
|
|
3
|
-
import type { ConfigFile } from '../settings/config-file.js';
|
|
4
4
|
import type { Draft } from '../settings/draft.js';
|
|
5
|
-
import type { SchemaNode } from '../settings/schema-node.js';
|
|
6
5
|
import { type Scope } from './scopes.js';
|
|
7
6
|
import { ListPage, type Outcome } from './list-page.js';
|
|
8
|
-
export
|
|
9
|
-
readonly key: string[];
|
|
10
|
-
readonly node: SchemaNode;
|
|
11
|
-
readonly category: string;
|
|
12
|
-
readonly section?: string;
|
|
13
|
-
}
|
|
14
|
-
/** Every editable setting with the category and heading it is shown under. */
|
|
15
|
-
export declare function settingsOf(file: ConfigFile): Setting[];
|
|
7
|
+
export { settingsOf, type Setting };
|
|
16
8
|
/** The row in General that opens the data folder flow (your own settings only). */
|
|
17
9
|
export declare const DATA_FOLDER = "@data-folder";
|
|
18
10
|
/** The list for the settings section. Pure (reads the files it is given). `extra` are rows that are not settings. */
|
|
@@ -1,125 +1,86 @@
|
|
|
1
1
|
// Section 5: every setting, for all projects or just this project (two scopes), grouped into categories on the left and
|
|
2
|
-
// searchable, with each value, its default and its description.
|
|
3
|
-
//
|
|
2
|
+
// searchable, with each value, its default and its description. The rows (which settings, their values, secrets as
|
|
3
|
+
// ***) are the settings feature's; this page lays the unsaved changes over them: changes are staged in the Draft
|
|
4
|
+
// (marked *) and written with Ctrl+S; Enter edits, r resets to the default, z undoes an unsaved change.
|
|
4
5
|
import _ from 'lodash';
|
|
5
|
-
import {
|
|
6
|
+
import { CATEGORIES, labelOf, nameOf, settingRow, settingsOf, } from '../../../app/features/settings/index.js';
|
|
7
|
+
import { valueText } from '../../../app/kernel/index.js';
|
|
6
8
|
import { errMsg } from '../../../core/util/index.js';
|
|
7
9
|
import { Text, Theme, } from '../../tui/index.js';
|
|
8
10
|
import { dataFolderRow, DataFolderFlow } from '../data-folder.js';
|
|
11
|
+
import { EXPORT_SETTINGS, IMPORT_SETTINGS, ShareSettingsFlow, shareSettingsRows } from '../share-settings.js';
|
|
9
12
|
import { VpnLoginFlow, vpnLoginRow, VPN_LOGIN } from '../vpn-login.js';
|
|
10
|
-
import { CATEGORIES, categoryOf, nameOf } from '../settings/categories.js';
|
|
11
|
-
import { formatValue } from '../settings/format.js';
|
|
12
13
|
import { ValueEditor } from '../settings/value-editor.js';
|
|
13
14
|
import { SCOPES, scopeStatus } from './scopes.js';
|
|
14
15
|
import { ListPage } from './list-page.js';
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
category: category.id,
|
|
28
|
-
section: several && category.id !== 'general' ? nameOf(top) : undefined,
|
|
29
|
-
},
|
|
30
|
-
];
|
|
31
|
-
return node.leaves([top]).map(({ key, node: leaf }) => {
|
|
32
|
-
const heading = [
|
|
33
|
-
several ? nameOf(top) : undefined,
|
|
34
|
-
key.length > 2 ? key.slice(1, -1).map(nameOf).join(' › ') : undefined,
|
|
35
|
-
]
|
|
36
|
-
.filter(Boolean)
|
|
37
|
-
.join(' › ');
|
|
38
|
-
return { key, node: leaf, category: category.id, section: heading || undefined };
|
|
39
|
-
});
|
|
40
|
-
});
|
|
41
|
-
}
|
|
42
|
-
/** What the file will say for a setting once the staged changes are saved (undefined = not set there). */
|
|
43
|
-
function written(file, draft, key) {
|
|
44
|
-
return draft.has(file, key) ? draft.value(file, key) : file.valueInFile(key);
|
|
45
|
-
}
|
|
46
|
-
/** What is in effect for a setting once the staged changes are saved. */
|
|
47
|
-
function effective(file, draft, key, config) {
|
|
48
|
-
if (file.isProject)
|
|
49
|
-
return written(file, draft, key);
|
|
50
|
-
return draft.has(file, key) ? (draft.value(file, key) ?? file.defaultOf(key)) : _.get(config, key);
|
|
16
|
+
export { settingsOf };
|
|
17
|
+
/** The files with the menu's unsaved changes laid over them. */
|
|
18
|
+
function draftSource(draft) {
|
|
19
|
+
const written = (file, key) => draft.has(file, key) ? draft.value(file, key) : file.valueInFile(key);
|
|
20
|
+
return {
|
|
21
|
+
written,
|
|
22
|
+
effective: (file, key, config) => file.isProject
|
|
23
|
+
? written(file, key)
|
|
24
|
+
: draft.has(file, key)
|
|
25
|
+
? (draft.value(file, key) ?? file.defaultOf(key))
|
|
26
|
+
: _.get(config, key),
|
|
27
|
+
};
|
|
51
28
|
}
|
|
52
|
-
/**
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
'
|
|
56
|
-
'sandbox.headless': 'Hide the sandbox window',
|
|
57
|
-
'sandbox.memoryMb': 'Memory (MB)',
|
|
58
|
-
'sandbox.pageFileMb': 'Swap file (MB)',
|
|
59
|
-
'network.dns': 'DNS servers',
|
|
60
|
-
'projects.wsbShare': 'Add folders while the sandbox runs',
|
|
61
|
-
'projects.all': 'Map all known projects at start',
|
|
62
|
-
'claudeProfile.hostDir': 'Claude folder on this PC',
|
|
63
|
-
'claudeProfile.globalStateFile': 'Claude state file on this PC',
|
|
64
|
-
};
|
|
65
|
-
function labelOf(key) {
|
|
66
|
-
return LABELS[key.join('.')] ?? Text.humanize(key[key.length - 1]);
|
|
29
|
+
/** A value of a row in one short line, painted like every value in the menu. */
|
|
30
|
+
function shown(row, value, max = 60) {
|
|
31
|
+
const v = valueText(value, row.field, max);
|
|
32
|
+
return v.tone === 'ok' ? Theme.ok(v.text) : v.tone === 'muted' ? Theme.muted(v.text) : v.text;
|
|
67
33
|
}
|
|
68
|
-
function item(
|
|
69
|
-
const
|
|
70
|
-
const id = s.key.join('.');
|
|
71
|
-
const set = written(file, draft, s.key) !== undefined;
|
|
72
|
-
const unsaved = draft.has(file, s.key);
|
|
73
|
-
const yours = effective(files.user, draft, s.key, config);
|
|
74
|
-
const project = files.project;
|
|
75
|
-
const inProject = project.schema.leaves().some((l) => l.key.join('.') === id)
|
|
76
|
-
? written(project, draft, s.key)
|
|
77
|
-
: undefined;
|
|
34
|
+
function item(row, file, draft) {
|
|
35
|
+
const unsaved = draft.has(file, row.key);
|
|
78
36
|
const paint = file.isProject ? Theme.project : Theme.changed;
|
|
79
|
-
const value = file.isProject && !set
|
|
80
|
-
? Theme.muted('all projects: ') + formatValue(yours, 40)
|
|
81
|
-
: formatValue(effective(file, draft, s.key, config));
|
|
37
|
+
const value = file.isProject && !row.set ? Theme.muted('all projects: ') + shown(row, row.yours, 40) : shown(row, row.value);
|
|
82
38
|
const details = [
|
|
83
|
-
Theme.muted('Setting ') + id,
|
|
39
|
+
Theme.muted('Setting ') + row.id,
|
|
84
40
|
Theme.muted('All projects ') +
|
|
85
|
-
|
|
86
|
-
Theme.muted(
|
|
41
|
+
shown(row, row.yours, 40) +
|
|
42
|
+
Theme.muted(row.yoursSet ? ' (your file)' : ' (built-in default)'),
|
|
87
43
|
Theme.muted('This project ') +
|
|
88
|
-
(inProject === undefined ? Theme.muted('not set') : Theme.project(Text.strip(
|
|
89
|
-
...(!file.isProject ? [Theme.muted('Default ') +
|
|
44
|
+
(row.inProject === undefined ? Theme.muted('not set') : Theme.project(Text.strip(shown(row, row.inProject, 40)))),
|
|
45
|
+
...(!file.isProject ? [Theme.muted('Default ') + shown(row, row.default, 40)] : []),
|
|
90
46
|
...(unsaved ? [Theme.warn('Unsaved: Ctrl+S saves, z undoes this change.')] : []),
|
|
91
|
-
...(file.isProject &&
|
|
47
|
+
...(file.isProject && row.locked
|
|
92
48
|
? [Theme.warn(Theme.glyph.lock + ' A project can only make this stricter than your own setting.')]
|
|
93
49
|
: []),
|
|
94
50
|
];
|
|
95
51
|
return {
|
|
96
|
-
value: id,
|
|
97
|
-
label:
|
|
52
|
+
value: row.id,
|
|
53
|
+
label: row.label,
|
|
98
54
|
hint: unsaved
|
|
99
55
|
? paint(Text.strip(value)) + ' ' + Theme.warn('*')
|
|
100
|
-
: set
|
|
56
|
+
: row.set
|
|
101
57
|
? paint(Text.strip(value)) + ' ' + paint(Theme.glyph.changed)
|
|
102
58
|
: value,
|
|
103
|
-
description:
|
|
59
|
+
description: row.field.help,
|
|
104
60
|
details,
|
|
105
|
-
section:
|
|
106
|
-
category:
|
|
107
|
-
keywords: id,
|
|
108
|
-
flip:
|
|
61
|
+
section: row.section,
|
|
62
|
+
category: row.category,
|
|
63
|
+
keywords: row.id,
|
|
64
|
+
flip: row.field.kind === 'boolean',
|
|
109
65
|
};
|
|
110
66
|
}
|
|
67
|
+
/** What a setting is now for editing: the staged value, else the file's (a project), else what is in effect. */
|
|
68
|
+
function current(file, draft, key, config) {
|
|
69
|
+
const source = draftSource(draft);
|
|
70
|
+
return file.isProject ? (source.written(file, key) ?? _.get(config, key)) : source.effective(file, key, config);
|
|
71
|
+
}
|
|
111
72
|
/** The row in General that opens the data folder flow (your own settings only). */
|
|
112
73
|
export const DATA_FOLDER = '@data-folder';
|
|
113
74
|
/** The list for the settings section. Pure (reads the files it is given). `extra` are rows that are not settings. */
|
|
114
75
|
export function settingsOptions(files, scope, draft, extra = []) {
|
|
115
76
|
const file = files[scope];
|
|
116
|
-
const config =
|
|
77
|
+
const config = files.user.userConfig();
|
|
117
78
|
// The Data folder row stands in for the storage folder setting (changing it moves the data, which is asked about).
|
|
118
79
|
const hideRoot = !file.isProject && extra.some((e) => e.value === DATA_FOLDER);
|
|
119
80
|
const settings = settingsOf(file).filter((s) => !(hideRoot && s.key.join('.') === 'storage.root'));
|
|
120
|
-
const
|
|
121
|
-
const set =
|
|
122
|
-
const unsaved =
|
|
81
|
+
const rows = settings.map((s) => settingRow(s, files, scope, draftSource(draft), config));
|
|
82
|
+
const set = new Set(rows.filter((r) => r.set).map((r) => r.id));
|
|
83
|
+
const unsaved = new Set(rows.filter((r) => draft.has(file, r.key)).map((r) => r.id));
|
|
123
84
|
const categories = CATEGORIES.filter((c) => settings.some((s) => s.category === c.id)).map((c) => ({
|
|
124
85
|
id: c.id,
|
|
125
86
|
label: c.label,
|
|
@@ -129,13 +90,17 @@ export function settingsOptions(files, scope, draft, extra = []) {
|
|
|
129
90
|
path: [],
|
|
130
91
|
status: scopeStatus(file),
|
|
131
92
|
tabs: { items: SCOPES.map((x) => x.tab), active: SCOPES.findIndex((x) => x.scope === scope) },
|
|
132
|
-
items: [...
|
|
93
|
+
items: [...rows.map((r) => item(r, file, draft)), ...(file.isProject ? [] : extra)],
|
|
133
94
|
categories,
|
|
134
95
|
actions: [
|
|
135
96
|
{ key: 'r', label: file.isProject ? 'remove' : 'reset to default', applies: (id) => set.has(id) },
|
|
136
97
|
{ key: 'z', label: 'undo', applies: (id) => unsaved.has(id) },
|
|
137
98
|
],
|
|
138
|
-
enterLabel: (_category, id) =>
|
|
99
|
+
enterLabel: (_category, id) => id === DATA_FOLDER || id === VPN_LOGIN
|
|
100
|
+
? 'change'
|
|
101
|
+
: id === EXPORT_SETTINGS || id === IMPORT_SETTINGS
|
|
102
|
+
? 'open'
|
|
103
|
+
: 'edit',
|
|
139
104
|
};
|
|
140
105
|
}
|
|
141
106
|
export class SettingsPage extends ListPage {
|
|
@@ -168,6 +133,7 @@ export class SettingsPage extends ListPage {
|
|
|
168
133
|
return settingsOptions(this.files, this.scope, this.draft, [
|
|
169
134
|
{ value: DATA_FOLDER, category: 'general', ...row },
|
|
170
135
|
{ value: VPN_LOGIN, category: 'network', ...vpnLoginRow(this.ctx) },
|
|
136
|
+
...shareSettingsRows().map((r) => ({ ...r, category: 'general' })),
|
|
171
137
|
]);
|
|
172
138
|
}
|
|
173
139
|
/** Stages a value; your own file never keeps a line that only repeats the default. */
|
|
@@ -196,6 +162,13 @@ export class SettingsPage extends ListPage {
|
|
|
196
162
|
const exit = await new DataFolderFlow(this.app, this.ctx).run();
|
|
197
163
|
return exit ? { exit } : { reload: true };
|
|
198
164
|
}
|
|
165
|
+
if (result.value === EXPORT_SETTINGS || result.value === IMPORT_SETTINGS) {
|
|
166
|
+
if (result.kind !== 'pick')
|
|
167
|
+
return {};
|
|
168
|
+
const flow = new ShareSettingsFlow(this.app, this.ctx);
|
|
169
|
+
const notice = await (result.value === EXPORT_SETTINGS ? flow.export() : flow.import());
|
|
170
|
+
return { reload: true, notice };
|
|
171
|
+
}
|
|
199
172
|
if (result.value === VPN_LOGIN) {
|
|
200
173
|
if (result.kind !== 'pick')
|
|
201
174
|
return {};
|
|
@@ -213,12 +186,9 @@ export class SettingsPage extends ListPage {
|
|
|
213
186
|
return {};
|
|
214
187
|
}
|
|
215
188
|
try {
|
|
216
|
-
const
|
|
217
|
-
const current = this.file.isProject
|
|
218
|
-
? (written(this.file, this.draft, setting.key) ?? _.get(config, setting.key))
|
|
219
|
-
: effective(this.file, this.draft, setting.key, config);
|
|
189
|
+
const now = current(this.file, this.draft, setting.key, this.file.userConfig());
|
|
220
190
|
const path = ['Settings', ...setting.key.slice(0, -1).map(nameOf), labelOf(setting.key)];
|
|
221
|
-
const edited = await this.editor.edit(path, setting.key, setting.node,
|
|
191
|
+
const edited = await this.editor.edit(path, setting.key, setting.node, now);
|
|
222
192
|
if (edited)
|
|
223
193
|
this.stage(setting.key, edited.value);
|
|
224
194
|
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { Action, Page } from '../../app/kernel/index.js';
|
|
2
|
+
import { type ListAction, type ListItem, type ListResult } from '../tui/index.js';
|
|
3
|
+
/** The row that stands for the empty state. */
|
|
4
|
+
export declare const EMPTY_ROW = "@empty";
|
|
5
|
+
/** What the list returned, as the page means it. */
|
|
6
|
+
export type Chosen = {
|
|
7
|
+
readonly kind: 'refresh';
|
|
8
|
+
} | {
|
|
9
|
+
readonly kind: 'action';
|
|
10
|
+
readonly action: Action;
|
|
11
|
+
};
|
|
12
|
+
export interface MenuView {
|
|
13
|
+
readonly items: ListItem<string>[];
|
|
14
|
+
readonly actions: ListAction<string>[];
|
|
15
|
+
/** What Enter does on a row ("" = it only shows information). */
|
|
16
|
+
enterLabel(category: string | undefined, id: string | undefined): string;
|
|
17
|
+
resolve(result: ListResult<string>): Chosen | undefined;
|
|
18
|
+
}
|
|
19
|
+
export interface MenuViewOptions {
|
|
20
|
+
/** Every row goes in this category (a view that is one category of a page). */
|
|
21
|
+
readonly category?: string;
|
|
22
|
+
/** Put before every row's value, so the rows cannot clash with the page's own rows. */
|
|
23
|
+
readonly prefix?: string;
|
|
24
|
+
/** Offer l to load the data again (default: yes). */
|
|
25
|
+
readonly refresh?: boolean;
|
|
26
|
+
}
|
|
27
|
+
/** The menu's rows, keys and Enter labels for a page. */
|
|
28
|
+
export declare function menuView(page: Page, o?: MenuViewOptions): MenuView;
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { pageHasContent } from '../../app/kernel/index.js';
|
|
2
|
+
import { safeText } from '../../core/util/index.js';
|
|
3
|
+
import { Theme } from '../tui/index.js';
|
|
4
|
+
/** The row that stands for the empty state. */
|
|
5
|
+
export const EMPTY_ROW = '@empty';
|
|
6
|
+
const FACT = 'fact:';
|
|
7
|
+
const ACTION = 'action:';
|
|
8
|
+
const REFRESH_KEY = 'l';
|
|
9
|
+
const PAINT = {
|
|
10
|
+
ok: Theme.ok,
|
|
11
|
+
warn: Theme.warn,
|
|
12
|
+
danger: Theme.error,
|
|
13
|
+
muted: Theme.muted,
|
|
14
|
+
accent: Theme.accent,
|
|
15
|
+
};
|
|
16
|
+
const paint = (text, tone) => text === undefined ? undefined : tone ? PAINT[tone](safeText(text)) : safeText(text);
|
|
17
|
+
/** The menu's rows, keys and Enter labels for a page. */
|
|
18
|
+
export function menuView(page, o = {}) {
|
|
19
|
+
const category = o.category ? { category: o.category } : {};
|
|
20
|
+
const prefix = o.prefix ?? '';
|
|
21
|
+
const items = [];
|
|
22
|
+
/** The action Enter runs, by row. */
|
|
23
|
+
const enter = new Map();
|
|
24
|
+
/** Key actions that apply to one row, by row. */
|
|
25
|
+
const keyed = new Map();
|
|
26
|
+
/** Key actions that apply everywhere. */
|
|
27
|
+
const everywhere = [...(page.actions ?? [])];
|
|
28
|
+
if (!pageHasContent(page) && page.empty) {
|
|
29
|
+
const e = page.empty;
|
|
30
|
+
items.push({
|
|
31
|
+
value: prefix + EMPTY_ROW,
|
|
32
|
+
label: e.action?.label ?? e.text,
|
|
33
|
+
section: e.title,
|
|
34
|
+
description: e.text,
|
|
35
|
+
...category,
|
|
36
|
+
});
|
|
37
|
+
if (e.action)
|
|
38
|
+
enter.set(prefix + EMPTY_ROW, e.action);
|
|
39
|
+
}
|
|
40
|
+
for (const section of page.sections) {
|
|
41
|
+
const heading = section.title ?? page.title;
|
|
42
|
+
for (const f of section.facts ?? [])
|
|
43
|
+
items.push({
|
|
44
|
+
value: prefix + FACT + f.id,
|
|
45
|
+
label: f.label,
|
|
46
|
+
hint: paint(f.value, f.tone),
|
|
47
|
+
description: f.description,
|
|
48
|
+
details: f.details?.map(safeText),
|
|
49
|
+
section: heading,
|
|
50
|
+
...category,
|
|
51
|
+
});
|
|
52
|
+
for (const item of section.items ?? []) {
|
|
53
|
+
const id = prefix + item.id;
|
|
54
|
+
items.push({
|
|
55
|
+
value: id,
|
|
56
|
+
label: safeText(item.label),
|
|
57
|
+
hint: paint(item.hint, item.tone),
|
|
58
|
+
description: item.description,
|
|
59
|
+
details: item.details?.map(safeText),
|
|
60
|
+
section: item.group ?? heading,
|
|
61
|
+
keywords: item.keywords,
|
|
62
|
+
...(item.disabled ? { disabled: item.disabled } : {}),
|
|
63
|
+
...category,
|
|
64
|
+
});
|
|
65
|
+
if (item.primary && !item.disabled)
|
|
66
|
+
enter.set(id, item.primary);
|
|
67
|
+
if (item.actions?.length)
|
|
68
|
+
keyed.set(id, [...item.actions]);
|
|
69
|
+
}
|
|
70
|
+
(section.actions ?? []).forEach((a, i) => {
|
|
71
|
+
const id = prefix + ACTION + section.id + ':' + i;
|
|
72
|
+
items.push({ value: id, label: a.label, hint: '', description: a.description, section: 'Actions', ...category });
|
|
73
|
+
enter.set(id, a);
|
|
74
|
+
everywhere.push(a);
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
const keys = [];
|
|
78
|
+
const addKey = (a, applies) => {
|
|
79
|
+
if (!a.key || keys.some((k) => k.key === a.key && k.label === (a.verb ?? a.label)))
|
|
80
|
+
return;
|
|
81
|
+
keys.push({ key: a.key, label: a.verb ?? a.label, importance: a.importance ?? 2, ...(applies ? { applies } : {}) });
|
|
82
|
+
};
|
|
83
|
+
for (const a of everywhere)
|
|
84
|
+
addKey(a);
|
|
85
|
+
for (const list of keyed.values())
|
|
86
|
+
for (const a of list)
|
|
87
|
+
addKey(a, (row) => keyed.get(row)?.some((x) => x.key === a.key) ?? false);
|
|
88
|
+
if (o.refresh !== false)
|
|
89
|
+
keys.push({ key: REFRESH_KEY, label: 'refresh', importance: 3 });
|
|
90
|
+
return {
|
|
91
|
+
items,
|
|
92
|
+
actions: keys,
|
|
93
|
+
enterLabel: (_category, id) => {
|
|
94
|
+
const a = id === undefined ? undefined : enter.get(id);
|
|
95
|
+
return a ? (a.verb ?? a.label.toLowerCase()) : '';
|
|
96
|
+
},
|
|
97
|
+
resolve: (result) => {
|
|
98
|
+
if (result.kind === 'pick') {
|
|
99
|
+
const a = enter.get(result.value);
|
|
100
|
+
return a ? { kind: 'action', action: a } : undefined;
|
|
101
|
+
}
|
|
102
|
+
if (result.kind !== 'action')
|
|
103
|
+
return undefined;
|
|
104
|
+
if (result.key === REFRESH_KEY && o.refresh !== false)
|
|
105
|
+
return { kind: 'refresh' };
|
|
106
|
+
const own = result.value === undefined ? undefined : keyed.get(result.value)?.find((a) => a.key === result.key);
|
|
107
|
+
const shared = everywhere.find((a) => a.key === result.key);
|
|
108
|
+
const a = own ?? shared;
|
|
109
|
+
return a ? { kind: 'action', action: a } : undefined;
|
|
110
|
+
},
|
|
111
|
+
};
|
|
112
|
+
}
|
|
@@ -1,11 +1,5 @@
|
|
|
1
|
+
import type { PathKind } from '../../../app/kernel/index.js';
|
|
1
2
|
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
3
|
export interface AskPathOptions {
|
|
10
4
|
readonly path: string[];
|
|
11
5
|
readonly title: string;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/** Picks a folder or file in the path picker; typing a path (or an allowed word) still works. */
|
|
2
|
+
export function askPath(app, o) {
|
|
3
|
+
return app.pickPath({
|
|
4
|
+
path: o.path,
|
|
5
|
+
title: o.title,
|
|
6
|
+
about: o.about,
|
|
7
|
+
initial: o.initial,
|
|
8
|
+
files: o.kind === 'file',
|
|
9
|
+
use: o.kind === 'file' ? 'use this file' : 'use this folder',
|
|
10
|
+
literals: o.literals,
|
|
11
|
+
relative: true,
|
|
12
|
+
validate: o.validate,
|
|
13
|
+
});
|
|
14
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type App, type ListItem } from '../../../tui/index.js';
|
|
2
|
-
import {
|
|
2
|
+
import type { SchemaNode } from '../../../../app/kernel/index.js';
|
|
3
3
|
import type { ValueEditor, Edited } from '../value-editor.js';
|
|
4
4
|
/**
|
|
5
5
|
* The shared shape of the list and map editors: a working copy shown as a list with "Add" at the top, Enter to change
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import type { App, ListItem } from '../../../tui/index.js';
|
|
2
2
|
import { CollectionEditor } from './collection-editor.js';
|
|
3
|
-
import {
|
|
4
|
-
import type { SchemaNode } from '../schema-node.js';
|
|
3
|
+
import type { PathKind, SchemaNode } from '../../../../app/kernel/index.js';
|
|
5
4
|
import type { ValueEditor } from '../value-editor.js';
|
|
6
5
|
/** A list of strings (project roots, scripts, extra packages ...). */
|
|
7
6
|
export declare class StringListEditor extends CollectionEditor<string[]> {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Theme } from '../../../tui/index.js';
|
|
2
2
|
import { CollectionEditor } from './collection-editor.js';
|
|
3
|
-
import { askPath } from '../path
|
|
3
|
+
import { askPath } from '../ask-path.js';
|
|
4
4
|
/** A list of strings (project roots, scripts, extra packages ...). */
|
|
5
5
|
export class StringListEditor extends CollectionEditor {
|
|
6
6
|
pathKind;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ConfigFile, SettingChange } from '
|
|
1
|
+
import type { ConfigFile, SettingChange } from '../../../app/features/settings/index.js';
|
|
2
2
|
/** What saving did: how many settings were written and why a file was refused. */
|
|
3
3
|
export interface DraftResult {
|
|
4
4
|
readonly saved: number;
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
+
export { choiceLabel, summary } from '../../../app/kernel/index.js';
|
|
1
2
|
/** A value in one short line, for the right-hand column. */
|
|
2
3
|
export declare function formatValue(value: unknown, max?: number): string;
|
|
3
|
-
/** A one-line name for an object in a list (a mapping's folders, an agent's package ...). */
|
|
4
|
-
export declare function summary(value: unknown): string;
|
|
5
|
-
export declare function choiceLabel(v: unknown): string;
|
|
@@ -1,39 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
import {
|
|
1
|
+
// A value in one short line for the menu's right-hand column: the kernel's valueText, painted with the theme.
|
|
2
|
+
import { valueText } from '../../../app/kernel/index.js';
|
|
3
|
+
import { Theme } from '../../tui/index.js';
|
|
4
|
+
export { choiceLabel, summary } from '../../../app/kernel/index.js';
|
|
3
5
|
/** A value in one short line, for the right-hand column. */
|
|
4
6
|
export function formatValue(value, max = 60) {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
if (value === true)
|
|
8
|
-
return Theme.ok('On');
|
|
9
|
-
if (value === false)
|
|
10
|
-
return Theme.muted('Off');
|
|
11
|
-
if (value === null)
|
|
12
|
-
return Theme.muted('none');
|
|
13
|
-
if (typeof value === 'string')
|
|
14
|
-
return value === '' ? Theme.muted('(empty)') : Text.truncate(value, max);
|
|
15
|
-
if (typeof value === 'number')
|
|
16
|
-
return String(value);
|
|
17
|
-
if (Array.isArray(value))
|
|
18
|
-
return value.length === 0
|
|
19
|
-
? Theme.muted('none')
|
|
20
|
-
: Text.truncate(value.length + ' · ' + value.map((v) => (typeof v === 'object' ? summary(v) : String(v))).join(', '), max);
|
|
21
|
-
const keys = Object.keys(value);
|
|
22
|
-
return keys.length ? Text.truncate(keys.length + ' · ' + keys.join(', '), max) : Theme.muted('none');
|
|
23
|
-
}
|
|
24
|
-
/** A one-line name for an object in a list (a mapping's folders, an agent's package ...). */
|
|
25
|
-
export function summary(value) {
|
|
26
|
-
if (!_.isPlainObject(value))
|
|
27
|
-
return String(value);
|
|
28
|
-
const o = value;
|
|
29
|
-
const strings = Object.entries(o).filter(([, v]) => typeof v === 'string' && v);
|
|
30
|
-
if (typeof o.host === 'string' && typeof o.guest === 'string')
|
|
31
|
-
return o.host + ' → ' + o.guest + (o.readOnly ? ' (read-only)' : '');
|
|
32
|
-
return (strings
|
|
33
|
-
.slice(0, 2)
|
|
34
|
-
.map(([, v]) => v)
|
|
35
|
-
.join(' · ') || '{ ' + Object.keys(o).join(', ') + ' }');
|
|
36
|
-
}
|
|
37
|
-
export function choiceLabel(v) {
|
|
38
|
-
return v === true ? 'On' : v === false ? 'Off' : String(v);
|
|
7
|
+
const shown = valueText(value, undefined, max);
|
|
8
|
+
return shown.tone === 'ok' ? Theme.ok(shown.text) : shown.tone === 'muted' ? Theme.muted(shown.text) : shown.text;
|
|
39
9
|
}
|