windows-development-sandbox 1.10.0 → 1.11.4
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 +64 -17
- package/config.example.json +5 -1
- package/dist/app/features/accounts/accounts.def.d.ts +122 -0
- package/dist/app/features/accounts/accounts.def.js +243 -0
- package/dist/app/features/accounts/accounts.run.d.ts +51 -0
- package/dist/app/features/accounts/accounts.run.js +125 -0
- package/dist/app/features/accounts/index.d.ts +2 -0
- package/dist/app/features/accounts/index.js +3 -0
- package/dist/app/features/agents/agent-entry.d.ts +17 -0
- package/dist/app/features/agents/agent-entry.js +50 -0
- package/dist/app/features/agents/agents.def.d.ts +65 -0
- package/dist/app/features/agents/agents.def.js +142 -0
- package/dist/app/features/agents/agents.run.d.ts +31 -0
- package/dist/app/features/agents/agents.run.js +189 -0
- package/dist/app/features/agents/index.d.ts +3 -0
- package/dist/app/features/agents/index.js +4 -0
- package/dist/app/features/apps/apps-rows.d.ts +31 -0
- package/dist/app/features/apps/apps-rows.js +73 -0
- package/dist/app/features/apps/apps.def.d.ts +181 -0
- package/dist/app/features/apps/apps.def.js +264 -0
- package/dist/app/features/apps/apps.run.d.ts +58 -0
- package/dist/app/features/apps/apps.run.js +76 -0
- package/dist/app/features/apps/index.d.ts +3 -0
- package/dist/app/features/apps/index.js +4 -0
- package/dist/app/features/data/data.def.d.ts +154 -0
- package/dist/app/features/data/data.def.js +194 -0
- package/dist/app/features/data/data.run.d.ts +46 -0
- package/dist/app/features/data/data.run.js +141 -0
- package/dist/app/features/data/index.d.ts +2 -0
- package/dist/app/features/data/index.js +3 -0
- package/dist/app/features/defs.d.ts +959 -4
- package/dist/app/features/defs.js +151 -10
- package/dist/app/features/engine/engine.def.d.ts +228 -0
- package/dist/app/features/engine/engine.def.js +194 -0
- package/dist/app/features/engine/engine.run.d.ts +72 -0
- package/dist/app/features/engine/engine.run.js +77 -0
- package/dist/app/features/engine/index.d.ts +2 -0
- package/dist/app/features/engine/index.js +4 -0
- package/dist/app/features/files/files.def.d.ts +51 -0
- package/dist/app/features/files/files.def.js +38 -0
- package/dist/app/features/files/files.run.d.ts +20 -0
- package/dist/app/features/files/files.run.js +59 -0
- package/dist/app/features/files/index.d.ts +2 -0
- package/dist/app/features/files/index.js +3 -0
- package/dist/app/features/github/github.def.d.ts +80 -0
- package/dist/app/features/github/github.def.js +142 -0
- package/dist/app/features/github/github.run.d.ts +36 -0
- package/dist/app/features/github/github.run.js +59 -0
- package/dist/app/features/github/index.d.ts +2 -0
- package/dist/app/features/github/index.js +3 -0
- package/dist/app/features/health/health.def.d.ts +275 -0
- package/dist/app/features/health/health.def.js +297 -0
- package/dist/app/features/health/health.run.d.ts +125 -0
- package/dist/app/features/health/health.run.js +204 -0
- package/dist/app/features/health/index.d.ts +2 -0
- package/dist/app/features/health/index.js +3 -0
- package/dist/app/features/logs/index.d.ts +2 -0
- package/dist/app/features/logs/index.js +3 -0
- package/dist/app/features/logs/logs.def.d.ts +78 -0
- package/dist/app/features/logs/logs.def.js +115 -0
- package/dist/app/features/logs/logs.run.d.ts +20 -0
- package/dist/app/features/logs/logs.run.js +42 -0
- package/dist/app/features/projects/index.d.ts +2 -0
- package/dist/app/features/projects/index.js +3 -0
- package/dist/app/features/projects/projects.def.d.ts +101 -0
- package/dist/app/features/projects/projects.def.js +208 -0
- package/dist/app/features/projects/projects.run.d.ts +56 -0
- package/dist/app/features/projects/projects.run.js +155 -0
- package/dist/app/features/sandbox/sandbox.def.js +11 -5
- package/dist/app/features/sessions/sessions.def.js +3 -0
- package/dist/app/features/settings/categories.def.js +3 -2
- package/dist/{cli/menu/settings/share.d.ts → app/features/settings/settings-share.d.ts} +1 -1
- package/dist/{cli/menu/settings/share.js → app/features/settings/settings-share.js} +3 -2
- package/dist/app/features/settings/settings.def.d.ts +22 -5
- package/dist/app/features/settings/settings.def.js +81 -6
- package/dist/app/features/settings/settings.run.d.ts +17 -0
- package/dist/app/features/settings/settings.run.js +89 -4
- package/dist/app/features/storage/index.d.ts +2 -0
- package/dist/app/features/storage/index.js +3 -0
- package/dist/app/features/storage/storage.def.d.ts +133 -0
- package/dist/app/features/storage/storage.def.js +220 -0
- package/dist/app/features/storage/storage.run.d.ts +62 -0
- package/dist/app/features/storage/storage.run.js +370 -0
- package/dist/app/features/updates/index.d.ts +3 -0
- package/dist/app/features/updates/index.js +4 -0
- package/dist/app/features/updates/update-lines.d.ts +13 -0
- package/dist/app/features/updates/update-lines.js +61 -0
- package/dist/app/features/updates/updates.def.d.ts +89 -0
- package/dist/app/features/updates/updates.def.js +224 -0
- package/dist/app/features/updates/updates.run.d.ts +48 -0
- package/dist/app/features/updates/updates.run.js +154 -0
- package/dist/app/features/vpn/index.d.ts +2 -0
- package/dist/app/features/vpn/index.js +3 -0
- package/dist/app/features/vpn/vpn.def.d.ts +112 -0
- package/dist/app/features/vpn/vpn.def.js +174 -0
- package/dist/app/features/vpn/vpn.run.d.ts +37 -0
- package/dist/app/features/vpn/vpn.run.js +54 -0
- package/dist/app/features/web/index.d.ts +2 -0
- package/dist/app/features/web/index.js +3 -0
- package/dist/app/features/web/web.def.d.ts +33 -0
- package/dist/app/features/web/web.def.js +90 -0
- package/dist/app/features/web/web.run.d.ts +24 -0
- package/dist/app/features/web/web.run.js +93 -0
- package/dist/app/kernel/define.d.ts +10 -1
- package/dist/app/kernel/io.d.ts +34 -0
- package/dist/app/kernel/io.js +9 -0
- package/dist/app/kernel/rpc.d.ts +17 -0
- package/dist/app/kernel/text.d.ts +2 -0
- package/dist/app/kernel/text.js +7 -0
- package/dist/app/kernel/view.d.ts +24 -1
- package/dist/app/kernel/view.js +1 -1
- package/dist/app/registry.js +74 -1
- package/dist/cli/args.js +1 -1
- package/dist/cli/commands/context.d.ts +7 -0
- package/dist/cli/commands/context.js +29 -2
- package/dist/cli/commands/engine.js +5 -58
- package/dist/cli/commands/github.d.ts +2 -0
- package/dist/cli/commands/github.js +11 -0
- package/dist/cli/commands/index.d.ts +3 -5
- package/dist/cli/commands/index.js +3 -5
- package/dist/cli/commands/launch/launch.js +21 -4
- package/dist/cli/commands/launch/running.js +4 -1
- package/dist/cli/commands/maintenance/config.js +1 -6
- package/dist/cli/commands/maintenance/index.d.ts +0 -1
- package/dist/cli/commands/maintenance/index.js +1 -2
- package/dist/cli/commands/maintenance/logs.js +27 -32
- package/dist/cli/commands/maintenance/migrate.d.ts +0 -8
- package/dist/cli/commands/maintenance/migrate.js +2 -44
- package/dist/cli/commands/maintenance/update.d.ts +0 -19
- package/dist/cli/commands/maintenance/update.js +1 -99
- package/dist/cli/commands/projects/index.d.ts +0 -1
- package/dist/cli/commands/projects/index.js +0 -1
- package/dist/cli/commands/registry.d.ts +1 -1
- package/dist/cli/commands/registry.js +29 -11
- package/dist/cli/commands/repair/checks/data.js +1 -1
- package/dist/cli/commands/repair/checks/hcs.js +28 -1
- package/dist/cli/commands/repair/checks/sandbox.js +1 -1
- package/dist/cli/commands/repair/health-run.d.ts +30 -0
- package/dist/cli/commands/repair/health-run.js +32 -0
- package/dist/cli/commands/repair/printer.d.ts +2 -2
- package/dist/cli/commands/repair/printer.js +2 -11
- package/dist/cli/commands/repair/run.d.ts +1 -21
- package/dist/cli/commands/repair/run.js +13 -70
- package/dist/cli/commands/storage/index.d.ts +0 -1
- package/dist/cli/commands/storage/index.js +0 -1
- package/dist/cli/commands/storage/offer.js +6 -2
- package/dist/cli/commands/vpn.d.ts +1 -3
- package/dist/cli/commands/vpn.js +8 -89
- package/dist/cli/commands/web.d.ts +2 -1
- package/dist/cli/commands/web.js +14 -78
- package/dist/cli/index.js +3 -2
- package/dist/cli/manifest.d.ts +16 -153
- package/dist/cli/manifest.js +20 -50
- package/dist/cli/menu/command-form.js +1 -2
- package/dist/cli/menu/io-menu.d.ts +2 -2
- package/dist/cli/menu/io-menu.js +6 -4
- package/dist/cli/menu/menu.js +1 -1
- package/dist/cli/menu/pages/accounts-page.d.ts +5 -17
- package/dist/cli/menu/pages/accounts-page.js +28 -170
- package/dist/cli/menu/pages/agents-page.d.ts +17 -18
- package/dist/cli/menu/pages/agents-page.js +67 -124
- package/dist/cli/menu/pages/apps-page.d.ts +15 -8
- package/dist/cli/menu/pages/apps-page.js +121 -29
- package/dist/cli/menu/pages/list-page.js +10 -1
- package/dist/cli/menu/pages/maintenance-page.d.ts +51 -52
- package/dist/cli/menu/pages/maintenance-page.js +246 -427
- package/dist/cli/menu/pages/sandbox-page.d.ts +3 -5
- package/dist/cli/menu/pages/sandbox-page.js +34 -112
- package/dist/cli/menu/pages/settings-page.d.ts +21 -3
- package/dist/cli/menu/pages/settings-page.js +89 -17
- package/dist/cli/menu/render-view.js +2 -1
- package/dist/cli/menu/settings/index.d.ts +0 -1
- package/dist/cli/menu/settings/index.js +3 -3
- package/dist/cli/menu/views.js +28 -0
- package/dist/cli/operations/handler.js +7 -3
- package/dist/cli/operations/input.d.ts +1 -1
- package/dist/cli/operations/input.js +29 -5
- package/dist/cli/operations/io-cli.js +9 -1
- package/dist/cli/operations/spec.js +8 -2
- package/dist/cli/output/render-view.js +2 -0
- package/dist/cli/{commands/data/collect.js → services/data-collect.js} +2 -2
- package/dist/cli/{commands/data/remove.js → services/data-remove.js} +2 -2
- package/dist/cli/services/data-service.d.ts +1 -1
- package/dist/cli/services/data-service.js +2 -2
- package/dist/cli/services/databases-service.d.ts +5 -0
- package/dist/cli/services/databases-service.js +15 -0
- package/dist/cli/services/health-service.d.ts +8 -4
- package/dist/cli/services/health-service.js +10 -8
- package/dist/cli/services/index.d.ts +4 -1
- package/dist/cli/services/index.js +4 -1
- package/dist/cli/services/logs-service.d.ts +7 -0
- package/dist/cli/services/logs-service.js +13 -0
- package/dist/cli/services/storage-service.d.ts +19 -0
- package/dist/cli/services/storage-service.js +71 -0
- package/dist/cli/services/vpn-service.d.ts +6 -4
- package/dist/cli/services/vpn-service.js +5 -11
- package/dist/cli/services/web-service.d.ts +4 -3
- package/dist/cli/services/web-service.js +12 -32
- package/dist/core/config/defaults.js +2 -1
- package/dist/core/schema/config.d.ts +5 -0
- package/dist/core/schema/config.js +2 -0
- package/dist/core/schema/github.d.ts +4 -0
- package/dist/core/schema/github.js +7 -0
- package/dist/core/schema/index.d.ts +1 -0
- package/dist/core/schema/index.js +1 -0
- package/dist/core/schema/profile.d.ts +1 -0
- package/dist/core/schema/profile.js +3 -0
- package/dist/core/schema/sandbox.js +3 -3
- package/dist/core/schema/toolchains.js +2 -2
- package/dist/core/types.d.ts +6 -3
- package/dist/guest/boot/boot.js +8 -0
- package/dist/guest/daemon/daemon.js +1 -1
- package/dist/guest/daemon/sessions.d.ts +3 -2
- package/dist/guest/daemon/sessions.js +38 -7
- package/dist/guest/governor/core.d.ts +44 -0
- package/dist/guest/governor/core.js +124 -0
- package/dist/guest/governor/decide.d.ts +46 -18
- package/dist/guest/governor/decide.js +136 -82
- package/dist/guest/governor/governor.d.ts +2 -38
- package/dist/guest/governor/governor.js +33 -113
- package/dist/guest/governor/index.d.ts +1 -0
- package/dist/guest/governor/index.js +1 -0
- package/dist/guest/network/firewall.d.ts +2 -0
- package/dist/guest/network/firewall.js +3 -3
- package/dist/guest/sessions/viewer.js +5 -1
- package/dist/guest/setup/github-token.d.ts +7 -0
- package/dist/guest/setup/github-token.js +65 -0
- package/dist/guest/toolchains/languages/node.js +11 -1
- package/dist/guest/toolchains/native/rust-extras.js +2 -2
- package/dist/guest/toolchains/tools/cli.d.ts +8 -0
- package/dist/guest/toolchains/tools/cli.js +35 -2
- package/dist/guest/vpn/openvpn.d.ts +5 -0
- package/dist/guest/vpn/openvpn.js +14 -1
- package/dist/guest/vpn/vpn.js +55 -16
- package/dist/guest/vpn/wireguard.js +2 -0
- package/dist/host/channel/attach.d.ts +1 -0
- package/dist/host/channel/attach.js +1 -0
- package/dist/host/channel/channel.d.ts +1 -1
- package/dist/host/channel/channel.js +2 -2
- package/dist/host/engines/hcs/check.d.ts +1 -0
- package/dist/host/engines/hcs/check.js +1 -1
- package/dist/host/engines/hcs/engine.d.ts +1 -1
- package/dist/host/engines/hcs/engine.js +6 -4
- package/dist/host/engines/hcs/helper.d.ts +11 -0
- package/dist/host/engines/hcs/helper.js +31 -2
- package/dist/host/engines/hcs/leftovers.d.ts +42 -0
- package/dist/host/engines/hcs/leftovers.js +101 -0
- package/dist/host/engines/index.d.ts +1 -0
- package/dist/host/engines/index.js +1 -0
- package/dist/host/github/deliver.d.ts +13 -0
- package/dist/host/github/deliver.js +51 -0
- package/dist/host/github/index.d.ts +2 -0
- package/dist/host/github/index.js +3 -0
- package/dist/host/github/token.d.ts +21 -0
- package/dist/host/github/token.js +74 -0
- package/dist/host/launch/generate.js +11 -5
- package/dist/host/launch/index.d.ts +1 -1
- package/dist/host/launch/index.js +1 -1
- package/dist/host/launch/session-file.js +1 -2
- package/dist/host/launch/wsb-file.d.ts +11 -7
- package/dist/host/launch/wsb-file.js +30 -12
- package/dist/host/life/host-memory.d.ts +18 -0
- package/dist/host/life/host-memory.js +66 -0
- package/dist/host/life/watchdog.d.ts +9 -0
- package/dist/host/life/watchdog.js +17 -1
- package/dist/host/sandbox/tasklist.d.ts +6 -0
- package/dist/host/sandbox/tasklist.js +37 -0
- package/dist/host/secrets/launch-secrets.d.ts +2 -1
- package/dist/host/secrets/launch-secrets.js +4 -2
- package/dist/host/vpn/status.js +13 -3
- package/dist/host/web/backend.d.ts +1 -3
- package/dist/host/web/index.d.ts +2 -1
- package/dist/host/web/index.js +2 -1
- package/dist/host/web/live.d.ts +23 -0
- package/dist/host/web/live.js +107 -0
- package/dist/host/web/rpc.d.ts +6 -1
- package/dist/host/web/rpc.js +23 -31
- package/dist/host/web/runner.d.ts +4 -0
- package/dist/host/web/runner.js +12 -1
- package/dist/host/web/server.d.ts +30 -2
- package/dist/host/web/server.js +87 -29
- package/dist/host/web/state.d.ts +1 -0
- package/dist/host/web/state.js +2 -0
- package/dist/runtime/agent.js +30 -6
- package/dist/runtime/daemon.js +337 -177
- package/dist/runtime/db.js +30 -6
- package/dist/runtime/main.js +389 -77
- package/dist/runtime/netproxy.js +30 -6
- package/dist/runtime/view.js +495 -146
- package/dist/selftest/app.test.js +632 -12
- package/dist/selftest/channel.test.js +18 -1
- package/dist/selftest/cli.test.js +1 -1
- package/dist/selftest/config.test.js +1 -1
- package/dist/selftest/contained.test.js +1 -1
- package/dist/selftest/data.test.js +1 -2
- package/dist/selftest/engine.test.js +3 -1
- package/dist/selftest/github.test.d.ts +2 -0
- package/dist/selftest/github.test.js +243 -0
- package/dist/selftest/hcs.test.js +105 -8
- package/dist/selftest/health.test.js +71 -0
- package/dist/selftest/heavy-load.test.js +132 -72
- package/dist/selftest/index.js +4 -0
- package/dist/selftest/layout.test.js +8 -0
- package/dist/selftest/live-terminal.test.js +74 -0
- package/dist/selftest/menu-screens.js +171 -56
- package/dist/selftest/menu.test.js +54 -37
- package/dist/selftest/migrate.test.js +14 -12
- package/dist/selftest/powershell-variables.test.d.ts +2 -0
- package/dist/selftest/powershell-variables.test.js +61 -0
- package/dist/selftest/support/engine-golden.js +1 -0
- package/dist/selftest/support/fixtures.d.ts +4 -0
- package/dist/selftest/support/web-preview.d.ts +1 -0
- package/dist/selftest/support/web-preview.js +856 -0
- package/dist/selftest/update-service.test.js +15 -8
- package/dist/selftest/vpn.test.js +86 -2
- package/dist/selftest/web.test.js +58 -11
- package/dist/shared/channel/run-dir.d.ts +2 -0
- package/dist/shared/channel/run-dir.js +3 -0
- package/dist/shared/channel/schema.d.ts +7 -0
- package/dist/shared/channel/schema.js +9 -1
- package/dist/shared/channel/secrets.d.ts +1 -0
- package/dist/shared/channel/secrets.js +3 -0
- package/dist/shared/github/index.d.ts +1 -0
- package/dist/shared/github/index.js +2 -0
- package/dist/shared/github/token.d.ts +29 -0
- package/dist/shared/github/token.js +89 -0
- package/dist/shared/memory/policy.d.ts +33 -12
- package/dist/shared/memory/policy.js +50 -19
- package/dist/shared/pty/ctrl-c.d.ts +18 -0
- package/dist/shared/pty/ctrl-c.js +36 -0
- package/dist/shared/pty/index.d.ts +1 -0
- package/dist/shared/pty/index.js +1 -0
- package/dist/shared/pty/terminal.d.ts +2 -0
- package/dist/shared/pty/terminal.js +21 -2
- package/dist/shared/vpn/kill-switch.d.ts +13 -2
- package/dist/shared/vpn/kill-switch.js +88 -8
- package/dist/shared/web/protocol.d.ts +0 -4
- package/dist/sync/watcher.d.ts +2 -0
- package/dist/sync/watcher.js +8 -3
- package/dist/web/index.html +2 -2
- package/dist/web/{main-T5DMCHYV.css → main-MU5XWZMS.css} +1 -1
- package/dist/web/main-SLQNJRXD.js +219 -0
- package/native/csharp/HcsHost/AssemblyInfo.cs +3 -3
- package/native/csharp/HostTools/AssemblyInfo.cs +3 -3
- package/native/csharp/HostTools/MemoryStatus.cs +58 -2
- package/native/csharp/HostTools/Program.cs +7 -1
- package/package.json +10 -3
- package/sandbox/csharp/MemGov.cs +240 -38
- package/sandbox/csharp/PtyHost.cs +104 -15
- package/sandbox/csharp/SandboxTools/CpuCap.cs +50 -1
- package/sandbox/csharp/SandboxTools/Program.cs +1 -1
- package/sandbox/scripts/repair-wmi-services.ps1 +26 -0
- package/schemas/config.schema.json +19 -5
- package/schemas/sandbox-config.schema.json +7 -3
- package/dist/cli/commands/accounts.d.ts +0 -2
- package/dist/cli/commands/accounts.js +0 -96
- package/dist/cli/commands/data/clean.d.ts +0 -3
- package/dist/cli/commands/data/clean.js +0 -60
- package/dist/cli/commands/data/index.d.ts +0 -4
- package/dist/cli/commands/data/index.js +0 -62
- package/dist/cli/commands/maintenance/clean.d.ts +0 -2
- package/dist/cli/commands/maintenance/clean.js +0 -24
- package/dist/cli/commands/maintenance/config-share.d.ts +0 -12
- package/dist/cli/commands/maintenance/config-share.js +0 -80
- package/dist/cli/commands/projects/projects.d.ts +0 -2
- package/dist/cli/commands/projects/projects.js +0 -162
- package/dist/cli/commands/storage/contained.d.ts +0 -3
- package/dist/cli/commands/storage/contained.js +0 -179
- package/dist/cli/commands/storage/storage.d.ts +0 -8
- package/dist/cli/commands/storage/storage.js +0 -179
- package/dist/cli/menu/add-agent.d.ts +0 -47
- package/dist/cli/menu/add-agent.js +0 -168
- package/dist/cli/menu/apps.d.ts +0 -69
- package/dist/cli/menu/apps.js +0 -214
- package/dist/cli/menu/data-folder.d.ts +0 -18
- package/dist/cli/menu/data-folder.js +0 -99
- package/dist/cli/menu/share-settings.d.ts +0 -21
- package/dist/cli/menu/share-settings.js +0 -112
- package/dist/cli/menu/vpn-login.d.ts +0 -16
- package/dist/cli/menu/vpn-login.js +0 -74
- package/dist/web/main-NRRS5O6Z.js +0 -157
- /package/dist/cli/{commands/data/collect.d.ts → services/data-collect.d.ts} +0 -0
- /package/dist/cli/{commands/data/remove.d.ts → services/data-remove.d.ts} +0 -0
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import type
|
|
2
|
-
import { type App, type Category, type ListAction, type ListOptions, type ListResult } from '../../tui/index.js';
|
|
1
|
+
import { type AgentsList } from '../../../app/features/agents/index.js';
|
|
3
2
|
import type { ConfigFile } from '../../../app/features/settings/index.js';
|
|
3
|
+
import type { Context } from '../../commands/context.js';
|
|
4
|
+
import { type App, type Category, type ListOptions, type ListResult } from '../../tui/index.js';
|
|
4
5
|
import type { Draft } from '../settings/draft.js';
|
|
5
6
|
import { ListPage, type Outcome } from './list-page.js';
|
|
6
7
|
export type WindowChoice = 'config' | 'hide' | 'show';
|
|
@@ -19,10 +20,8 @@ export interface AgentsModel {
|
|
|
19
20
|
/** The agents you added yourself: only these can be removed (the built-in ones stay). */
|
|
20
21
|
readonly removable?: readonly string[];
|
|
21
22
|
}
|
|
22
|
-
/** The agents
|
|
23
|
-
export declare function
|
|
24
|
-
/** The keys of the Start category: make an agent the default, remove one you added. Pure. */
|
|
25
|
-
export declare function agentActions(m: Pick<AgentsModel, 'defaultAgent' | 'removable'>): ListAction<string>[];
|
|
23
|
+
/** The agents page's data as the agents view takes it. Pure. */
|
|
24
|
+
export declare function agentsList(m: AgentsModel): AgentsList;
|
|
26
25
|
/**
|
|
27
26
|
* The "not sandboxed" entries: only while agent commands are on (typing the agent then starts the sandbox, so a way to
|
|
28
27
|
* run the real one is needed), one per agent found installed on this PC.
|
|
@@ -32,37 +31,37 @@ export declare function hostAgentsToShow(enabled: boolean, found: readonly {
|
|
|
32
31
|
}[]): string[];
|
|
33
32
|
/** The command line a start stands for. Pure. */
|
|
34
33
|
export declare function startArgv(m: AgentsModel, agent: string, cwd: string): string[];
|
|
34
|
+
/** Settings has unsaved changes to the agents (their list or the default): the agent operations wait for them. */
|
|
35
|
+
export declare function agentsHaveStagedChanges(file: ConfigFile, draft: Draft): boolean;
|
|
35
36
|
/** The categories of the agents section; "On this PC" only when there is something in it. Pure. */
|
|
36
37
|
export declare function agentCategories(m: Pick<AgentsModel, 'folder' | 'hostAgents'>): Category[];
|
|
37
38
|
/** The list for the agents section. Pure. */
|
|
38
39
|
export declare function agentsOptions(m: AgentsModel, cwd?: string): ListOptions<string>;
|
|
39
40
|
export declare class AgentsPage extends ListPage<string> {
|
|
40
41
|
private readonly ctx;
|
|
41
|
-
/** Your own config file
|
|
42
|
+
/** Your own config file: the default agent's name for where the cursor starts. */
|
|
42
43
|
private readonly file;
|
|
44
|
+
/** Unsaved changes in Settings: while there are some to the agents, the agent operations wait for them. */
|
|
43
45
|
private readonly draft;
|
|
44
46
|
readonly label = "Agents";
|
|
45
47
|
private attach;
|
|
46
48
|
private window;
|
|
47
49
|
private folder;
|
|
48
50
|
private model;
|
|
49
|
-
|
|
51
|
+
private readonly operations;
|
|
52
|
+
/** What load() looked up: the agents view, programs on PATH, the history file. */
|
|
50
53
|
private facts;
|
|
51
54
|
constructor(app: App, ctx: Context,
|
|
52
|
-
/** Your own config file
|
|
53
|
-
file: ConfigFile,
|
|
54
|
-
/**
|
|
55
|
-
|
|
56
|
-
/** Is this agent already in the sandbox's persistent storage (so starting it needs no install)? */
|
|
57
|
-
private installed;
|
|
55
|
+
/** Your own config file: the default agent's name for where the cursor starts. */
|
|
56
|
+
file: ConfigFile,
|
|
57
|
+
/** Unsaved changes in Settings: while there are some to the agents, the agent operations wait for them. */
|
|
58
|
+
draft: Draft);
|
|
58
59
|
private current;
|
|
59
60
|
/** The cursor starts on the default agent. */
|
|
60
61
|
protected initialFocus(): string;
|
|
61
62
|
protected load(): Promise<void>;
|
|
62
63
|
protected options(): ListOptions<string>;
|
|
63
64
|
protected act(result: ListResult<string>): Promise<Outcome<string>>;
|
|
64
|
-
/**
|
|
65
|
-
private
|
|
66
|
-
/** "Add an agent…": the new agent shows in the list, with the cursor on it. */
|
|
67
|
-
private add;
|
|
65
|
+
/** Add, make default and remove run through the menu's dialogs, unless Settings has unsaved changes to the agents. */
|
|
66
|
+
private operate;
|
|
68
67
|
}
|
|
@@ -1,39 +1,38 @@
|
|
|
1
1
|
// Section 1: the agents. "Start" lists the agents you can start here (Enter starts one) after "Repeat last", and ends
|
|
2
|
-
// with "Add an agent…" (the
|
|
3
|
-
// the other ways to start; "On this PC" has the not-sandboxed entries while agent commands
|
|
2
|
+
// with "Add an agent…" (the agents view's rows and keys: src/app/features/agents); "Options" holds how a start goes
|
|
3
|
+
// (attach, window, folder) and the other ways to start; "On this PC" has the not-sandboxed entries while agent commands
|
|
4
|
+
// are on.
|
|
4
5
|
import fs from 'node:fs';
|
|
5
6
|
import path from 'node:path';
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
7
|
+
import { agentsPage, listAgents } from '../../../app/features/agents/index.js';
|
|
8
|
+
import { readQuery } from '../../../app/registry.js';
|
|
8
9
|
import { commandLine, readHistory } from '../../history.js';
|
|
9
10
|
import { AgentCommandsService } from '../../services/index.js';
|
|
10
11
|
import { commandSpec } from '../../manifest.js';
|
|
11
12
|
import { Text, Theme, } from '../../tui/index.js';
|
|
12
|
-
import { AddAgent, makeDefaultAgent, removeAgent } from '../add-agent.js';
|
|
13
13
|
import { CommandForm } from '../command-form.js';
|
|
14
|
+
import { MenuOperations } from '../io-menu.js';
|
|
15
|
+
import { menuView } from '../render-view.js';
|
|
14
16
|
import { askPath } from '../settings/ask-path.js';
|
|
15
17
|
import { SeveralAgents } from '../several.js';
|
|
16
18
|
import { ListPage } from './list-page.js';
|
|
17
|
-
/** The agents
|
|
18
|
-
export function
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
19
|
+
/** The agents page's data as the agents view takes it. Pure. */
|
|
20
|
+
export function agentsList(m) {
|
|
21
|
+
const removable = m.removable ?? [];
|
|
22
|
+
return {
|
|
23
|
+
folder: m.folder,
|
|
24
|
+
defaultAgent: m.defaultAgent,
|
|
25
|
+
agents: m.agents.map((a) => ({
|
|
26
|
+
name: a.name,
|
|
27
|
+
ready: a.ready,
|
|
28
|
+
isDefault: a.name === m.defaultAgent,
|
|
29
|
+
removable: removable.includes(a.name),
|
|
30
|
+
})),
|
|
27
31
|
};
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
label: 'remove',
|
|
33
|
-
importance: 1,
|
|
34
|
-
applies: (id) => isOther(id) && (m.removable ?? []).includes(agentOf(id) ?? ''),
|
|
35
|
-
},
|
|
36
|
-
];
|
|
32
|
+
}
|
|
33
|
+
/** The Start category: the agents view's rows and keys, as the menu draws them. Pure. */
|
|
34
|
+
function startView(m) {
|
|
35
|
+
return menuView(agentsPage(agentsList(m)), { category: 'start', refresh: false });
|
|
37
36
|
}
|
|
38
37
|
/**
|
|
39
38
|
* The "not sandboxed" entries: only while agent commands are on (typing the agent then starts the sandbox, so a way to
|
|
@@ -54,6 +53,10 @@ export function startArgv(m, agent, cwd) {
|
|
|
54
53
|
...(path.resolve(m.folder).toLowerCase() === path.resolve(cwd).toLowerCase() ? [] : ['--workspace', m.folder]),
|
|
55
54
|
];
|
|
56
55
|
}
|
|
56
|
+
/** Settings has unsaved changes to the agents (their list or the default): the agent operations wait for them. */
|
|
57
|
+
export function agentsHaveStagedChanges(file, draft) {
|
|
58
|
+
return draft.has(file, ['harnesses']) || draft.has(file, ['defaultHarness']);
|
|
59
|
+
}
|
|
57
60
|
/** The categories of the agents section; "On this PC" only when there is something in it. Pure. */
|
|
58
61
|
export function agentCategories(m) {
|
|
59
62
|
return [
|
|
@@ -74,10 +77,20 @@ export function agentCategories(m) {
|
|
|
74
77
|
: []),
|
|
75
78
|
];
|
|
76
79
|
}
|
|
80
|
+
/** A Start row of the view with the menu's own lines: the default's accent and the command a start runs. Pure. */
|
|
81
|
+
function startRow(item, m, cwd) {
|
|
82
|
+
const name = item.value.startsWith('agent:') ? item.value.slice(6) : undefined;
|
|
83
|
+
if (name === undefined)
|
|
84
|
+
return item;
|
|
85
|
+
return {
|
|
86
|
+
...item,
|
|
87
|
+
hint: (name === m.defaultAgent ? Theme.accent('default ') : '') + (item.hint ?? ''),
|
|
88
|
+
details: [Theme.muted('Command ') + commandLine(startArgv(m, name, cwd))],
|
|
89
|
+
};
|
|
90
|
+
}
|
|
77
91
|
/** The list for the agents section. Pure. */
|
|
78
92
|
export function agentsOptions(m, cwd = process.cwd()) {
|
|
79
|
-
const
|
|
80
|
-
const agents = [...m.agents].sort((a, b) => Number(b.name === m.defaultAgent) - Number(a.name === m.defaultAgent));
|
|
93
|
+
const view = startView(m);
|
|
81
94
|
return {
|
|
82
95
|
path: [],
|
|
83
96
|
categories: agentCategories(m),
|
|
@@ -94,33 +107,7 @@ export function agentsOptions(m, cwd = process.cwd()) {
|
|
|
94
107
|
},
|
|
95
108
|
]
|
|
96
109
|
: []),
|
|
97
|
-
...
|
|
98
|
-
value: 'agent:' + a.name,
|
|
99
|
-
label: a.name,
|
|
100
|
-
category: 'start',
|
|
101
|
-
section,
|
|
102
|
-
hint: (a.name === m.defaultAgent ? Theme.accent('default ') : '') +
|
|
103
|
-
(a.ready ? Theme.ok('ready') : Theme.muted('installs on first start')),
|
|
104
|
-
description: 'Starts ' +
|
|
105
|
-
a.name +
|
|
106
|
-
' in ' +
|
|
107
|
-
path.basename(m.folder) +
|
|
108
|
-
'.' +
|
|
109
|
-
(a.name === m.defaultAgent ? ' It is the default agent.' : '') +
|
|
110
|
-
((m.removable ?? []).includes(a.name) && a.name !== m.defaultAgent
|
|
111
|
-
? ' You added it: x removes it.'
|
|
112
|
-
: (m.removable ?? []).includes(a.name)
|
|
113
|
-
? ' You added it. Make another agent the default to remove it.'
|
|
114
|
-
: ''),
|
|
115
|
-
details: [Theme.muted('Command ') + commandLine(startArgv(m, a.name, cwd))],
|
|
116
|
-
})),
|
|
117
|
-
{
|
|
118
|
-
value: 'add',
|
|
119
|
-
label: 'Add an agent…',
|
|
120
|
-
category: 'start',
|
|
121
|
-
section,
|
|
122
|
-
description: 'Add another agent by its npm or Python package, or a program on this PC. It is saved in your settings and appears in this list.',
|
|
123
|
-
},
|
|
110
|
+
...view.items.map((item) => startRow(item, m, cwd)),
|
|
124
111
|
{
|
|
125
112
|
value: 'opt:attach',
|
|
126
113
|
label: 'Attach this terminal',
|
|
@@ -175,7 +162,7 @@ export function agentsOptions(m, cwd = process.cwd()) {
|
|
|
175
162
|
})),
|
|
176
163
|
],
|
|
177
164
|
enterLabel: (_category, id) => ENTER[id ?? ''] ?? (id?.startsWith('agent:') ? 'start' : id?.startsWith('host:') ? 'run' : 'open'),
|
|
178
|
-
actions: (category) => (category === 'start' ?
|
|
165
|
+
actions: (category) => (category === 'start' ? view.actions : []),
|
|
179
166
|
};
|
|
180
167
|
}
|
|
181
168
|
/** What Enter does on the rows that are not an agent. */
|
|
@@ -195,45 +182,33 @@ export class AgentsPage extends ListPage {
|
|
|
195
182
|
window = 'config';
|
|
196
183
|
folder = process.cwd();
|
|
197
184
|
model;
|
|
198
|
-
|
|
185
|
+
operations;
|
|
186
|
+
/** What load() looked up: the agents view, programs on PATH, the history file. */
|
|
199
187
|
facts;
|
|
200
188
|
constructor(app, ctx,
|
|
201
|
-
/** Your own config file
|
|
202
|
-
file,
|
|
189
|
+
/** Your own config file: the default agent's name for where the cursor starts. */
|
|
190
|
+
file,
|
|
191
|
+
/** Unsaved changes in Settings: while there are some to the agents, the agent operations wait for them. */
|
|
192
|
+
draft) {
|
|
203
193
|
super(app);
|
|
204
194
|
this.ctx = ctx;
|
|
205
195
|
this.file = file;
|
|
206
196
|
this.draft = draft;
|
|
207
|
-
|
|
208
|
-
/** Every agent: the configured ones, and any added in Settings that is not saved yet. */
|
|
209
|
-
harnesses() {
|
|
210
|
-
const config = this.file.userConfig();
|
|
211
|
-
const staged = this.draft.has(this.file, ['harnesses'])
|
|
212
|
-
? this.draft.value(this.file, ['harnesses'])
|
|
213
|
-
: undefined;
|
|
214
|
-
return { ...config.harnesses, ...staged };
|
|
215
|
-
}
|
|
216
|
-
/** Is this agent already in the sandbox's persistent storage (so starting it needs no install)? */
|
|
217
|
-
installed(name, harnesses) {
|
|
218
|
-
const h = harnesses[name];
|
|
219
|
-
const dir = path.join(this.ctx.dataPath, 'tools', 'agents', name);
|
|
220
|
-
return (Boolean(h) &&
|
|
221
|
-
[h.hostExecutable, h.npmBin && h.npmBin + '.cmd', h.uvBin && h.uvBin + '.exe'].some((f) => f && fs.existsSync(path.join(dir, f))));
|
|
197
|
+
this.operations = new MenuOperations(app, ctx);
|
|
222
198
|
}
|
|
223
199
|
current() {
|
|
224
|
-
const harnesses = this.harnesses();
|
|
225
200
|
if (!this.facts)
|
|
226
201
|
throw new Error('The agents tab was not loaded');
|
|
227
|
-
const { commands, last } = this.facts;
|
|
202
|
+
const { agents, commands, last } = this.facts;
|
|
228
203
|
return {
|
|
229
204
|
folder: this.folder,
|
|
230
|
-
defaultAgent:
|
|
231
|
-
agents:
|
|
205
|
+
defaultAgent: agents.defaultAgent,
|
|
206
|
+
agents: agents.agents.map((a) => ({ name: a.name, ready: a.ready })),
|
|
232
207
|
last,
|
|
233
208
|
attach: this.attach,
|
|
234
209
|
window: this.window,
|
|
235
210
|
hostAgents: hostAgentsToShow(commands.enabled, commands.found),
|
|
236
|
-
removable:
|
|
211
|
+
removable: agents.agents.filter((a) => a.removable).map((a) => a.name),
|
|
237
212
|
};
|
|
238
213
|
}
|
|
239
214
|
/** The cursor starts on the default agent. */
|
|
@@ -242,6 +217,7 @@ export class AgentsPage extends ListPage {
|
|
|
242
217
|
}
|
|
243
218
|
async load() {
|
|
244
219
|
this.facts = {
|
|
220
|
+
agents: await readQuery(listAgents, this.ctx),
|
|
245
221
|
commands: await new AgentCommandsService(this.ctx).statusAsync(),
|
|
246
222
|
last: readHistory()[0]?.argv,
|
|
247
223
|
};
|
|
@@ -252,21 +228,23 @@ export class AgentsPage extends ListPage {
|
|
|
252
228
|
return agentsOptions(this.model);
|
|
253
229
|
}
|
|
254
230
|
async act(result) {
|
|
255
|
-
|
|
256
|
-
|
|
231
|
+
const model = this.current();
|
|
232
|
+
const chosen = startView(model).resolve(result);
|
|
233
|
+
if (chosen?.kind === 'action') {
|
|
234
|
+
const { action } = chosen;
|
|
235
|
+
// A start keeps the options of this page (attach, window, folder), which the plain link does not know.
|
|
236
|
+
if (action.kind === 'link' && action.target.kind === 'start-agent')
|
|
237
|
+
return { exit: { kind: 'run', argv: startArgv(model, action.target.agent, process.cwd()) } };
|
|
238
|
+
return this.operate(action);
|
|
239
|
+
}
|
|
257
240
|
if (result.kind !== 'pick')
|
|
258
241
|
return {};
|
|
259
242
|
const id = result.value;
|
|
260
|
-
const model = this.current();
|
|
261
243
|
if (id.startsWith('host:'))
|
|
262
244
|
return { exit: { kind: 'run', argv: ['host', id.slice(5)] } };
|
|
263
|
-
if (id.startsWith('agent:'))
|
|
264
|
-
return { exit: { kind: 'run', argv: startArgv(model, id.slice(6), process.cwd()) } };
|
|
265
245
|
switch (id) {
|
|
266
246
|
case 'repeat':
|
|
267
247
|
return model.last ? { exit: { kind: 'run', argv: model.last } } : {};
|
|
268
|
-
case 'add':
|
|
269
|
-
return this.add(model);
|
|
270
248
|
case 'opt:attach':
|
|
271
249
|
this.attach = !this.attach;
|
|
272
250
|
return {};
|
|
@@ -301,45 +279,10 @@ export class AgentsPage extends ListPage {
|
|
|
301
279
|
return {};
|
|
302
280
|
}
|
|
303
281
|
}
|
|
304
|
-
/**
|
|
305
|
-
async action
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
try {
|
|
310
|
-
if (key === 'd') {
|
|
311
|
-
makeDefaultAgent(this.file, this.draft, name);
|
|
312
|
-
return { focus: id, notice: Theme.ok(Theme.glyph.ok + ' ' + name + ' is the default agent.') };
|
|
313
|
-
}
|
|
314
|
-
if (key !== 'x')
|
|
315
|
-
return {};
|
|
316
|
-
const ok = await this.app.ask('Remove ' + name + '?', ['It is taken out of your settings. Its files in the sandbox stay until you clean them up.'], 'Remove', true);
|
|
317
|
-
if (!ok)
|
|
318
|
-
return {};
|
|
319
|
-
removeAgent(this.file, this.draft, name);
|
|
320
|
-
return {
|
|
321
|
-
focus: 'agent:' + this.file.userConfig().defaultHarness,
|
|
322
|
-
notice: Theme.ok(Theme.glyph.ok + ' Removed ' + name + '.'),
|
|
323
|
-
};
|
|
324
|
-
}
|
|
325
|
-
catch (e) {
|
|
326
|
-
return { notice: Theme.error(Theme.glyph.cross + ' ' + errMsg(e)) };
|
|
327
|
-
}
|
|
328
|
-
}
|
|
329
|
-
/** "Add an agent…": the new agent shows in the list, with the cursor on it. */
|
|
330
|
-
async add(model) {
|
|
331
|
-
try {
|
|
332
|
-
const added = await new AddAgent(this.app, this.file, this.draft, model.agents.map((a) => a.name)).run();
|
|
333
|
-
if (!added)
|
|
334
|
-
return {};
|
|
335
|
-
return {
|
|
336
|
-
focus: 'agent:' + added.name,
|
|
337
|
-
notice: Theme.ok(Theme.glyph.ok + ' Added ' + added.name + '.') +
|
|
338
|
-
Theme.muted(added.saved ? ' Enter starts it.' : ' Ctrl+S saves it.'),
|
|
339
|
-
};
|
|
340
|
-
}
|
|
341
|
-
catch (e) {
|
|
342
|
-
return { notice: Theme.error(Theme.glyph.cross + ' ' + errMsg(e)) };
|
|
343
|
-
}
|
|
282
|
+
/** Add, make default and remove run through the menu's dialogs, unless Settings has unsaved changes to the agents. */
|
|
283
|
+
async operate(action) {
|
|
284
|
+
if (agentsHaveStagedChanges(this.file, this.draft))
|
|
285
|
+
return { notice: Theme.warn('Agents have unsaved changes in Settings: save them (Ctrl+S) or undo them first.') };
|
|
286
|
+
return this.operations.perform(action, [this.label], (text) => this.busy(text));
|
|
344
287
|
}
|
|
345
288
|
}
|
|
@@ -1,28 +1,35 @@
|
|
|
1
|
-
import { type
|
|
2
|
-
import { AppsModel } from '../apps.js';
|
|
1
|
+
import { type AppsSource } from '../../../app/features/apps/index.js';
|
|
3
2
|
import type { ConfigFile } from '../../../app/features/settings/index.js';
|
|
3
|
+
import { type App, type Category, type ListItem, type ListOptions, type ListResult } from '../../tui/index.js';
|
|
4
|
+
import type { Context } from '../../commands/context.js';
|
|
4
5
|
import type { Draft } from '../settings/draft.js';
|
|
5
6
|
import { type Scope } from './scopes.js';
|
|
6
7
|
import { ListPage, type Outcome } from './list-page.js';
|
|
7
8
|
import type { ShellExit } from '../shell.js';
|
|
8
9
|
import type { Step } from '../../tui/index.js';
|
|
10
|
+
/** The apps as the menu shows them: the saved files with this page's staged ticks laid over them. */
|
|
11
|
+
export declare function draftSource(draft: Draft): AppsSource;
|
|
12
|
+
/** The menu's groups: the feature's groups, and in your own scope "Your own programs". */
|
|
13
|
+
export declare function appsCategories(file: ConfigFile): Category[];
|
|
14
|
+
/** The menu's rows for a scope, with the staged ticks. */
|
|
15
|
+
export declare function appsItems(file: ConfigFile, dataPath: string, draft: Draft): ListItem<string>[];
|
|
9
16
|
/** The list for the apps tab. Pure. */
|
|
10
|
-
export declare function appsOptions(
|
|
17
|
+
export declare function appsOptions(file: ConfigFile, dataPath: string, draft: Draft, scope: Scope): ListOptions<string>;
|
|
18
|
+
/** Stages the ticks of the list: only what differs from the saved file is kept in the draft. */
|
|
19
|
+
export declare function stageTicks(file: ConfigFile, draft: Draft, ticked: readonly string[]): void;
|
|
11
20
|
export declare class AppsPage extends ListPage<string> {
|
|
21
|
+
private readonly ctx;
|
|
12
22
|
private readonly files;
|
|
13
23
|
private readonly draft;
|
|
14
|
-
private readonly dataPath;
|
|
15
24
|
readonly label = "Apps";
|
|
16
25
|
readonly stages = true;
|
|
17
26
|
private scope;
|
|
18
|
-
|
|
27
|
+
private readonly operations;
|
|
28
|
+
constructor(app: App, ctx: Context, files: Record<Scope, ConfigFile>, draft: Draft);
|
|
19
29
|
private get file();
|
|
20
|
-
private get model();
|
|
21
30
|
protected load(): Promise<void>;
|
|
22
31
|
protected options(): ListOptions<string>;
|
|
23
32
|
/** Every tick is staged as it happens, so leaving or saving always sees it. */
|
|
24
33
|
protected afterKey(): Step<ShellExit>;
|
|
25
|
-
/** Opens the GitHub request form in the browser and says where it is. */
|
|
26
|
-
private request;
|
|
27
34
|
protected act(result: ListResult<string>): Promise<Outcome<string>>;
|
|
28
35
|
}
|
|
@@ -1,14 +1,100 @@
|
|
|
1
1
|
// Section 4: the apps catalogue. Groups on the left, space ticks, and the ticks are staged until Ctrl+S saves them. Two
|
|
2
|
-
// scopes like Settings: apps for every project, or for this project only.
|
|
2
|
+
// scopes like Settings: apps for every project, or for this project only. The rows come from the apps feature
|
|
3
|
+
// (features/apps/apps-rows.ts); the menu only lays its staged ticks over them. The web and the feature write at once
|
|
4
|
+
// (apps.toggle), so the staging stays here: "r" runs the feature's request operation, "c" stages your own programs.
|
|
5
|
+
import _ from 'lodash';
|
|
3
6
|
import { errMsg } from '../../../core/util/index.js';
|
|
7
|
+
import { APP_GROUPS, appIsOn, appRows, customRows, CUSTOM_KEY, entriesOf, INSTALL, ISSUES_URL, requestApp, REQUEST_APP, SAVED, } from '../../../app/features/apps/index.js';
|
|
8
|
+
import { action } from '../../../app/kernel/index.js';
|
|
4
9
|
import { Theme } from '../../tui/index.js';
|
|
5
|
-
import { openIssuePage } from '../../../host/web/index.js';
|
|
6
|
-
import { AppsModel, requestAppUrl } from '../apps.js';
|
|
7
10
|
import { ValueEditor } from '../settings/value-editor.js';
|
|
11
|
+
import { MenuOperations } from '../io-menu.js';
|
|
8
12
|
import { SCOPES, scopeStatus } from './scopes.js';
|
|
9
13
|
import { ListPage } from './list-page.js';
|
|
14
|
+
/** The apps as the menu shows them: the saved files with this page's staged ticks laid over them. */
|
|
15
|
+
export function draftSource(draft) {
|
|
16
|
+
return {
|
|
17
|
+
install: (file) => draft.has(file, INSTALL) ? draft.value(file, INSTALL) : SAVED.install(file),
|
|
18
|
+
setting: (file, key) => (draft.has(file, key) ? draft.value(file, key) : SAVED.setting(file, key)),
|
|
19
|
+
custom: (file) => draft.has(file, CUSTOM_KEY)
|
|
20
|
+
? draft.value(file, CUSTOM_KEY)
|
|
21
|
+
: SAVED.custom(file),
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
/** The menu's groups: the feature's groups, and in your own scope "Your own programs". */
|
|
25
|
+
export function appsCategories(file) {
|
|
26
|
+
return [
|
|
27
|
+
...APP_GROUPS.map(({ id, label, description }) => ({ id, label, description })),
|
|
28
|
+
...(file.isProject
|
|
29
|
+
? []
|
|
30
|
+
: [
|
|
31
|
+
{
|
|
32
|
+
id: 'custom',
|
|
33
|
+
label: 'Your own programs',
|
|
34
|
+
description: 'Programs you added yourself (c to add or change them).',
|
|
35
|
+
},
|
|
36
|
+
]),
|
|
37
|
+
];
|
|
38
|
+
}
|
|
39
|
+
function appItem(row) {
|
|
40
|
+
const notes = [
|
|
41
|
+
Theme.muted('Download ') +
|
|
42
|
+
'~' +
|
|
43
|
+
row.size +
|
|
44
|
+
' once, kept in C:\\AgentData\\tools\\' +
|
|
45
|
+
(row.setting ? '' : 'apps\\') +
|
|
46
|
+
row.id,
|
|
47
|
+
Theme.muted('Starts ') + (row.cli ? 'from a terminal (on PATH)' : 'from the desktop or Start > Sandbox apps'),
|
|
48
|
+
...(row.mesa ? [Theme.muted('Graphics ') + 'OpenGL on the CPU (Mesa) is added for it'] : []),
|
|
49
|
+
...(row.fullGitOnly
|
|
50
|
+
? [Theme.warn('Needs full git access (Settings > Projects & setup > Git): it pushes with its own git.')]
|
|
51
|
+
: []),
|
|
52
|
+
...(row.setting ? [Theme.muted('Setting ') + row.setting] : []),
|
|
53
|
+
];
|
|
54
|
+
return {
|
|
55
|
+
value: row.id,
|
|
56
|
+
label: row.name,
|
|
57
|
+
category: row.group,
|
|
58
|
+
description: row.about,
|
|
59
|
+
details: notes,
|
|
60
|
+
keywords: row.id,
|
|
61
|
+
hint: (row.installed ? Theme.ok('installed ') : '') + Theme.muted(row.size),
|
|
62
|
+
checked: row.on,
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
function customItem(row) {
|
|
66
|
+
return {
|
|
67
|
+
value: '@custom:' + row.id,
|
|
68
|
+
label: row.name,
|
|
69
|
+
category: 'custom',
|
|
70
|
+
description: row.from,
|
|
71
|
+
hint: Theme.muted(row.cli ? 'command line' : 'desktop'),
|
|
72
|
+
checked: true,
|
|
73
|
+
disabled: 'Your own programs are always installed; c to change or remove them.',
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
/** The menu's rows for a scope, with the staged ticks. */
|
|
77
|
+
export function appsItems(file, dataPath, draft) {
|
|
78
|
+
const source = draftSource(draft);
|
|
79
|
+
return [
|
|
80
|
+
...appRows(file, dataPath, source).map(appItem),
|
|
81
|
+
...(file.isProject
|
|
82
|
+
? []
|
|
83
|
+
: [
|
|
84
|
+
{
|
|
85
|
+
value: REQUEST_APP,
|
|
86
|
+
label: 'Request an app…',
|
|
87
|
+
category: 'custom',
|
|
88
|
+
description: 'Not in the list? Press r: your browser opens a prefilled request on GitHub (' + ISSUES_URL + ').',
|
|
89
|
+
hint: Theme.muted('press r'),
|
|
90
|
+
disabled: 'Press r to open the request form on GitHub.',
|
|
91
|
+
},
|
|
92
|
+
]),
|
|
93
|
+
...customRows(file, source).map(customItem),
|
|
94
|
+
];
|
|
95
|
+
}
|
|
10
96
|
/** The list for the apps tab. Pure. */
|
|
11
|
-
export function appsOptions(
|
|
97
|
+
export function appsOptions(file, dataPath, draft, scope) {
|
|
12
98
|
return {
|
|
13
99
|
path: [],
|
|
14
100
|
status: scopeStatus(file),
|
|
@@ -16,72 +102,78 @@ export function appsOptions(model, file, draft, scope) {
|
|
|
16
102
|
tabs: { items: SCOPES.map((s) => s.tab), active: SCOPES.findIndex((s) => s.scope === scope) },
|
|
17
103
|
multi: true,
|
|
18
104
|
enterTicks: true,
|
|
19
|
-
categories:
|
|
20
|
-
items:
|
|
105
|
+
categories: appsCategories(file),
|
|
106
|
+
items: appsItems(file, dataPath, draft),
|
|
21
107
|
actions: [
|
|
22
108
|
...(file.isProject ? [] : [{ key: 'c', label: 'your own programs' }]),
|
|
23
109
|
{ key: 'r', label: 'request an app' },
|
|
24
110
|
],
|
|
25
111
|
};
|
|
26
112
|
}
|
|
113
|
+
/** Stages the ticks of the list: only what differs from the saved file is kept in the draft. */
|
|
114
|
+
export function stageTicks(file, draft, ticked) {
|
|
115
|
+
const entries = entriesOf(file);
|
|
116
|
+
for (const entry of entries.filter((a) => a.setting)) {
|
|
117
|
+
const key = entry.setting.split('.');
|
|
118
|
+
const on = ticked.includes(entry.id);
|
|
119
|
+
if (on === appIsOn(entry, file, SAVED))
|
|
120
|
+
draft.unstage(file, key);
|
|
121
|
+
else
|
|
122
|
+
draft.stage(file, key, on);
|
|
123
|
+
}
|
|
124
|
+
const wanted = entries.filter((a) => !a.setting && ticked.includes(a.id)).map((a) => a.id);
|
|
125
|
+
const savedInstall = SAVED.install(file) ?? [];
|
|
126
|
+
if (_.isEqual([...wanted].sort(), [...savedInstall].sort()))
|
|
127
|
+
draft.unstage(file, INSTALL);
|
|
128
|
+
else
|
|
129
|
+
draft.stage(file, INSTALL, wanted.length || file.isProject ? wanted : undefined);
|
|
130
|
+
}
|
|
27
131
|
export class AppsPage extends ListPage {
|
|
132
|
+
ctx;
|
|
28
133
|
files;
|
|
29
134
|
draft;
|
|
30
|
-
dataPath;
|
|
31
135
|
label = 'Apps';
|
|
32
136
|
stages = true;
|
|
33
137
|
scope = 'user';
|
|
34
|
-
|
|
138
|
+
operations;
|
|
139
|
+
constructor(app, ctx, files, draft) {
|
|
35
140
|
super(app);
|
|
141
|
+
this.ctx = ctx;
|
|
36
142
|
this.files = files;
|
|
37
143
|
this.draft = draft;
|
|
38
|
-
this.
|
|
144
|
+
this.operations = new MenuOperations(app, ctx);
|
|
39
145
|
}
|
|
40
146
|
get file() {
|
|
41
147
|
return this.files[this.scope];
|
|
42
148
|
}
|
|
43
|
-
get model() {
|
|
44
|
-
return new AppsModel(this.file, this.dataPath);
|
|
45
|
-
}
|
|
46
149
|
load() {
|
|
47
150
|
return Promise.resolve();
|
|
48
151
|
}
|
|
49
152
|
options() {
|
|
50
|
-
return appsOptions(this.
|
|
153
|
+
return appsOptions(this.file, this.ctx.dataPath, this.draft, this.scope);
|
|
51
154
|
}
|
|
52
155
|
/** Every tick is staged as it happens, so leaving or saving always sees it. */
|
|
53
156
|
afterKey() {
|
|
54
|
-
|
|
157
|
+
stageTicks(this.file, this.draft, this.ticked());
|
|
55
158
|
return;
|
|
56
159
|
}
|
|
57
|
-
/** Opens the GitHub request form in the browser and says where it is. */
|
|
58
|
-
request() {
|
|
59
|
-
const url = requestAppUrl();
|
|
60
|
-
try {
|
|
61
|
-
openIssuePage(url);
|
|
62
|
-
return Theme.ok(Theme.glyph.ok + ' Opened the request form in your browser: ') + Theme.muted(url);
|
|
63
|
-
}
|
|
64
|
-
catch (e) {
|
|
65
|
-
return Theme.error(Theme.glyph.cross + ' ' + errMsg(e)) + Theme.muted(' Open it yourself: ' + url);
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
160
|
async act(result) {
|
|
69
|
-
|
|
161
|
+
stageTicks(this.file, this.draft, this.ticked());
|
|
70
162
|
if (result.kind === 'tab') {
|
|
71
163
|
this.scope = SCOPES[result.index].scope;
|
|
72
164
|
return {};
|
|
73
165
|
}
|
|
74
166
|
if (result.kind === 'action' && result.key === 'r')
|
|
75
|
-
return {
|
|
167
|
+
return this.operations.perform(action(requestApp, {}), [this.label]);
|
|
76
168
|
if (result.kind !== 'action' || result.key !== 'c')
|
|
77
169
|
return {};
|
|
78
170
|
const node = this.file.schema.child('apps')?.child('custom');
|
|
79
171
|
if (!node)
|
|
80
172
|
return {};
|
|
81
173
|
try {
|
|
82
|
-
const edited = await new ValueEditor(this.app).edit(['Apps', 'Your own programs'],
|
|
174
|
+
const edited = await new ValueEditor(this.app).edit(['Apps', 'Your own programs'], CUSTOM_KEY, node, draftSource(this.draft).custom(this.file));
|
|
83
175
|
if (edited)
|
|
84
|
-
this.draft.stage(this.file,
|
|
176
|
+
this.draft.stage(this.file, CUSTOM_KEY, edited.value);
|
|
85
177
|
}
|
|
86
178
|
catch (e) {
|
|
87
179
|
return { notice: Theme.error(Theme.glyph.cross + ' ' + errMsg(e)) };
|
|
@@ -178,7 +178,16 @@ export class ListPage {
|
|
|
178
178
|
if (!step)
|
|
179
179
|
return this.afterKey();
|
|
180
180
|
const result = step.done;
|
|
181
|
-
|
|
181
|
+
let outcome;
|
|
182
|
+
try {
|
|
183
|
+
outcome = result.kind === 'back' ? { exit: { kind: 'quit' } } : await this.act(result);
|
|
184
|
+
}
|
|
185
|
+
catch (e) {
|
|
186
|
+
// Whatever an action does wrong, the menu stays: the problem is shown where the action was chosen.
|
|
187
|
+
if (e instanceof Error && (e.name === 'ExitRequested' || e.name === 'ExitPromptError'))
|
|
188
|
+
throw e;
|
|
189
|
+
outcome = { notice: Theme.error(Theme.glyph.cross + ' ' + errMsg(e)) };
|
|
190
|
+
}
|
|
182
191
|
if (outcome.exit)
|
|
183
192
|
return { done: outcome.exit };
|
|
184
193
|
// What the action changed (a stop, a restart) is known to the menu before the page loads again. An action that
|