windows-development-sandbox 1.11.7 → 1.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +13 -6
- package/config.example.json +15 -4
- package/dist/app/features/access/access.def.d.ts +190 -0
- package/dist/app/features/access/access.def.js +273 -0
- package/dist/app/features/access/access.run.d.ts +79 -0
- package/dist/app/features/access/access.run.js +129 -0
- package/dist/app/features/access/index.d.ts +2 -0
- package/dist/app/features/access/index.js +3 -0
- package/dist/app/features/agents/agent-entry.js +5 -0
- package/dist/app/features/agents/agents.def.js +1 -0
- package/dist/app/features/apps/apps-rows.d.ts +4 -1
- package/dist/app/features/apps/apps-rows.js +7 -2
- package/dist/app/features/apps/apps.def.d.ts +19 -0
- package/dist/app/features/apps/apps.def.js +50 -12
- package/dist/app/features/apps/apps.run.d.ts +2 -0
- package/dist/app/features/apps/apps.run.js +1 -1
- package/dist/app/features/audit/audit.def.d.ts +350 -0
- package/dist/app/features/audit/audit.def.js +457 -0
- package/dist/app/features/audit/audit.run.d.ts +110 -0
- package/dist/app/features/audit/audit.run.js +133 -0
- package/dist/app/features/audit/index.d.ts +2 -0
- package/dist/app/features/audit/index.js +3 -0
- package/dist/app/features/defs.d.ts +349 -4
- package/dist/app/features/defs.js +16 -1
- package/dist/app/features/files/files.def.js +1 -0
- package/dist/app/features/health/health.def.js +1 -0
- package/dist/app/features/sandbox/sandbox.def.js +3 -0
- package/dist/app/features/sessions/sessions.def.d.ts +36 -0
- package/dist/app/features/sessions/sessions.def.js +77 -9
- package/dist/app/features/sessions/sessions.run.d.ts +25 -2
- package/dist/app/features/sessions/sessions.run.js +71 -3
- package/dist/app/features/settings/settings.def.d.ts +8 -0
- package/dist/app/features/settings/settings.def.js +17 -0
- package/dist/app/features/settings/settings.run.d.ts +3 -0
- package/dist/app/features/settings/settings.run.js +16 -2
- package/dist/app/features/web/web.def.d.ts +9 -0
- package/dist/app/features/web/web.def.js +26 -1
- package/dist/app/features/web/web.run.d.ts +3 -0
- package/dist/app/features/web/web.run.js +11 -3
- package/dist/app/kernel/access.d.ts +33 -0
- package/dist/app/kernel/access.js +44 -0
- package/dist/app/kernel/define.d.ts +26 -2
- package/dist/app/kernel/index.d.ts +1 -0
- package/dist/app/kernel/index.js +1 -0
- package/dist/app/kernel/rpc.d.ts +5 -2
- package/dist/app/registry.d.ts +4 -1
- package/dist/app/registry.js +26 -4
- package/dist/cli/args.d.ts +0 -3
- package/dist/cli/args.js +3 -4
- package/dist/cli/commands/index.d.ts +1 -1
- package/dist/cli/commands/index.js +1 -1
- package/dist/cli/commands/launch/prepare.js +1 -1
- package/dist/cli/commands/maintenance/index.d.ts +0 -1
- package/dist/cli/commands/maintenance/index.js +0 -1
- package/dist/cli/commands/registry.js +3 -2
- package/dist/cli/commands/remote.d.ts +2 -0
- package/dist/cli/commands/remote.js +49 -0
- package/dist/cli/commands/sessions/reopen.js +3 -0
- package/dist/cli/commands/web.js +66 -0
- package/dist/cli/manifest.d.ts +63 -45
- package/dist/cli/manifest.js +33 -18
- package/dist/cli/menu/io-menu.d.ts +5 -3
- package/dist/cli/menu/io-menu.js +12 -5
- package/dist/cli/menu/pages/apps-page.js +2 -15
- package/dist/cli/menu/pages/maintenance-page.d.ts +4 -0
- package/dist/cli/menu/pages/maintenance-page.js +51 -8
- package/dist/cli/menu/remote-menu.d.ts +19 -0
- package/dist/cli/menu/remote-menu.js +108 -0
- package/dist/cli/menu/views.js +4 -0
- package/dist/cli/operations/handler.js +15 -1
- package/dist/cli/services/remote-client.d.ts +16 -0
- package/dist/cli/services/remote-client.js +141 -0
- package/dist/cli/services/sessions-service.d.ts +5 -0
- package/dist/cli/services/sessions-service.js +17 -1
- package/dist/core/config/defaults.js +12 -2
- package/dist/core/local-config/file.js +16 -2
- package/dist/core/local-config/overrides.js +7 -0
- package/dist/core/run/versions.js +9 -8
- package/dist/core/schema/apps.d.ts +9 -0
- package/dist/core/schema/apps.js +9 -0
- package/dist/core/schema/config.d.ts +23 -3
- package/dist/core/schema/config.js +42 -5
- package/dist/core/schema/sandbox.d.ts +1 -0
- package/dist/core/schema/sandbox.js +11 -3
- package/dist/core/schema/web.d.ts +51 -0
- package/dist/core/schema/web.js +46 -1
- package/dist/core/util/fs.d.ts +5 -0
- package/dist/core/util/fs.js +23 -0
- package/dist/core/util/index.d.ts +1 -1
- package/dist/core/util/index.js +1 -1
- package/dist/guest/apps/app-installer.js +50 -4
- package/dist/guest/apps/index.d.ts +1 -1
- package/dist/guest/apps/index.js +1 -1
- package/dist/guest/apps/sources.js +1 -1
- package/dist/guest/audit/parse.d.ts +32 -2
- package/dist/guest/audit/parse.js +43 -5
- package/dist/guest/audit/process-audit.d.ts +3 -1
- package/dist/guest/audit/process-audit.js +9 -6
- package/dist/guest/boot/boot.js +12 -3
- package/dist/guest/boot/guide.d.ts +1 -1
- package/dist/guest/boot/guide.js +27 -3
- package/dist/guest/daemon/daemon.js +2 -0
- package/dist/guest/daemon/idle-shutdown.js +2 -1
- package/dist/guest/daemon/sessions.d.ts +23 -2
- package/dist/guest/daemon/sessions.js +151 -20
- package/dist/guest/entries/daemon.js +2 -1
- package/dist/guest/git/decision.js +7 -0
- package/dist/guest/sessions/cmdline.d.ts +14 -0
- package/dist/guest/sessions/cmdline.js +10 -0
- package/dist/guest/setup/addon-mcp.d.ts +2 -0
- package/dist/guest/setup/addon-mcp.js +49 -0
- package/dist/guest/setup/agent-addons.d.ts +9 -0
- package/dist/guest/setup/agent-addons.js +22 -0
- package/dist/guest/setup/headroom.d.ts +7 -0
- package/dist/guest/setup/headroom.js +60 -0
- package/dist/guest/setup/managed-policy.d.ts +2 -1
- package/dist/guest/setup/managed-policy.js +15 -6
- package/dist/guest/toolchains/plan.js +8 -3
- package/dist/guest/toolchains/setup.js +3 -0
- package/dist/host/audit/attribute.d.ts +46 -0
- package/dist/host/audit/attribute.js +76 -0
- package/dist/host/audit/collect.d.ts +29 -3
- package/dist/host/audit/collect.js +256 -61
- package/dist/host/audit/git-commits.d.ts +29 -0
- package/dist/host/audit/git-commits.js +157 -0
- package/dist/host/audit/index.d.ts +5 -0
- package/dist/host/audit/index.js +6 -0
- package/dist/host/audit/log.d.ts +45 -7
- package/dist/host/audit/log.js +148 -45
- package/dist/host/audit/redact.d.ts +2 -0
- package/dist/host/audit/redact.js +67 -0
- package/dist/host/channel/channel.d.ts +5 -1
- package/dist/host/channel/channel.js +12 -0
- package/dist/host/guard/agent-files.js +7 -1
- package/dist/host/guard/commands.js +13 -1
- package/dist/host/guard/git-config.js +27 -7
- package/dist/host/guard/git-dirs.js +78 -3
- package/dist/host/guard/mark-of-the-web.js +3 -1
- package/dist/host/guard/nested-repos.js +7 -2
- package/dist/host/guard/store.js +1 -0
- package/dist/host/guard/types.d.ts +2 -0
- package/dist/host/launch/mappings.js +11 -1
- package/dist/host/launch/project-scan.js +2 -21
- package/dist/host/launch/stage.js +4 -0
- package/dist/host/life/session-ledger.js +2 -1
- package/dist/host/remote/access-store.d.ts +156 -0
- package/dist/host/remote/access-store.js +308 -0
- package/dist/host/remote/cert.d.ts +20 -0
- package/dist/host/remote/cert.js +103 -0
- package/dist/host/remote/door-client.d.ts +13 -0
- package/dist/host/remote/door-client.js +54 -0
- package/dist/host/remote/firewall.d.ts +44 -0
- package/dist/host/remote/firewall.js +118 -0
- package/dist/host/remote/gate.d.ts +125 -0
- package/dist/host/remote/gate.js +391 -0
- package/dist/host/remote/index.d.ts +8 -0
- package/dist/host/remote/index.js +10 -0
- package/dist/host/remote/lan.d.ts +24 -0
- package/dist/host/remote/lan.js +88 -0
- package/dist/host/remote/tls-store.d.ts +22 -0
- package/dist/host/remote/tls-store.js +63 -0
- package/dist/host/remote/windows-helper.d.ts +67 -0
- package/dist/host/remote/windows-helper.js +129 -0
- package/dist/host/web/bridge.d.ts +5 -1
- package/dist/host/web/bridge.js +6 -2
- package/dist/host/web/browser.js +1 -1
- package/dist/host/web/control.d.ts +4 -1
- package/dist/host/web/control.js +28 -4
- package/dist/host/web/rpc.d.ts +16 -2
- package/dist/host/web/rpc.js +37 -4
- package/dist/host/web/runner.d.ts +4 -0
- package/dist/host/web/runner.js +12 -0
- package/dist/host/web/server.d.ts +18 -2
- package/dist/host/web/server.js +97 -24
- package/dist/host/web/state.d.ts +5 -0
- package/dist/host/web/state.js +8 -0
- package/dist/runtime/agent.js +184 -18
- package/dist/runtime/daemon.js +772 -338
- package/dist/runtime/db.js +184 -18
- package/dist/runtime/gitguard.js +6 -0
- package/dist/runtime/main.js +966 -553
- package/dist/runtime/netproxy.js +184 -18
- package/dist/runtime/view.js +186 -18
- package/dist/selftest/app.test.js +66 -7
- package/dist/selftest/audit.test.js +354 -47
- package/dist/selftest/channel.test.js +16 -0
- package/dist/selftest/cmdline.test.js +16 -0
- package/dist/selftest/git-access.test.js +8 -0
- package/dist/selftest/hcs.test.js +35 -0
- package/dist/selftest/hostile-input.test.js +12 -1
- package/dist/selftest/index.js +2 -0
- package/dist/selftest/live-daemon.test.js +25 -0
- package/dist/selftest/local-config.test.js +30 -0
- package/dist/selftest/menu-screens.js +1 -1
- package/dist/selftest/menu.test.js +3 -3
- package/dist/selftest/remote.test.d.ts +2 -0
- package/dist/selftest/remote.test.js +536 -0
- package/dist/selftest/repo-guard.test.js +56 -2
- package/dist/selftest/resume.test.js +2 -1
- package/dist/selftest/sharing.test.js +9 -2
- package/dist/selftest/support/engine-golden.js +9 -0
- package/dist/selftest/support/fixtures.d.ts +14 -0
- package/dist/selftest/support/web-preview.js +157 -0
- package/dist/selftest/toolchains.test.js +147 -2
- package/dist/selftest/web.test.js +2 -0
- package/dist/shared/apps/agent-addons.d.ts +64 -0
- package/dist/shared/apps/agent-addons.js +95 -0
- package/dist/shared/apps/catalogue.d.ts +33 -2
- package/dist/shared/apps/catalogue.js +102 -11
- package/dist/shared/apps/index.d.ts +3 -2
- package/dist/shared/apps/index.js +3 -2
- package/dist/shared/apps/selection.d.ts +2 -0
- package/dist/shared/apps/selection.js +7 -0
- package/dist/shared/channel/schema.d.ts +23 -0
- package/dist/shared/channel/schema.js +8 -0
- package/dist/shared/pty/protocol.d.ts +2 -0
- package/dist/shared/pty/protocol.js +2 -0
- package/dist/sync/watcher.js +9 -1
- package/dist/web/index.html +2 -2
- package/dist/web/{main-RQFN4WBY.css → main-UAQPI5XD.css} +1 -1
- package/dist/web/main-Z2WYAE2Z.js +221 -0
- package/native/csharp/HcsHost/AssemblyInfo.cs +5 -3
- package/native/csharp/HcsHost/Hcs.cs +9 -0
- package/native/csharp/HcsHost/Program.cs +26 -1
- package/native/csharp/HcsHost/Share.cs +173 -0
- package/native/csharp/HostTools/AssemblyInfo.cs +3 -3
- package/native/csharp/HostTools/Program.cs +17 -1
- package/native/csharp/HostTools/WebHelper.cs +499 -0
- package/native/scripts/get-network-profile.ps1 +19 -0
- package/native/scripts/set-folder-access.ps1 +11 -0
- package/native/scripts/set-web-firewall.ps1 +103 -0
- package/package.json +1 -1
- package/sandbox/addons/ccusage/package-lock.json +111 -0
- package/sandbox/addons/ccusage/package.json +7 -0
- package/sandbox/addons/context7/package-lock.json +1313 -0
- package/sandbox/addons/context7/package.json +7 -0
- package/sandbox/addons/headroom/requirements.in +1 -0
- package/sandbox/addons/headroom/requirements.txt +2922 -0
- package/sandbox/addons/playwright-mcp/package-lock.json +56 -0
- package/sandbox/addons/playwright-mcp/package.json +7 -0
- package/sandbox/csharp/PtyHost.cs +20 -0
- package/schemas/config.schema.json +78 -4
- package/schemas/sandbox-config.schema.json +2 -20
- package/dist/cli/commands/maintenance/audit.d.ts +0 -3
- package/dist/cli/commands/maintenance/audit.js +0 -58
- package/dist/web/main-K2JMCAZI.js +0 -219
package/dist/cli/manifest.d.ts
CHANGED
|
@@ -499,47 +499,6 @@ declare const COMMAND_LIST: readonly [{
|
|
|
499
499
|
readonly group: "Data";
|
|
500
500
|
readonly args: readonly [];
|
|
501
501
|
readonly options: readonly [];
|
|
502
|
-
}, {
|
|
503
|
-
readonly name: "audit";
|
|
504
|
-
readonly summary: "what happened in your sandboxes: programs started, files changed, sessions, repo guard (turn it on: sandbox config set audit.enabled true)";
|
|
505
|
-
readonly group: "Health";
|
|
506
|
-
readonly json: true;
|
|
507
|
-
readonly args: readonly [];
|
|
508
|
-
readonly options: readonly [{
|
|
509
|
-
readonly flag: "--days";
|
|
510
|
-
readonly type: "number";
|
|
511
|
-
readonly value: "n";
|
|
512
|
-
readonly description: "the last n days (default: today)";
|
|
513
|
-
readonly default: 1;
|
|
514
|
-
}, {
|
|
515
|
-
flag: string;
|
|
516
|
-
type: "string" | "number" | "boolean" | "list";
|
|
517
|
-
description: string;
|
|
518
|
-
short?: string | undefined;
|
|
519
|
-
value?: string | undefined;
|
|
520
|
-
label?: string | undefined;
|
|
521
|
-
default?: string | number | undefined;
|
|
522
|
-
choices?: string[] | "harnesses" | "sessions" | "accounts" | undefined;
|
|
523
|
-
advanced?: boolean | undefined;
|
|
524
|
-
when?: string | undefined;
|
|
525
|
-
noMenu?: boolean | undefined;
|
|
526
|
-
group?: string | undefined;
|
|
527
|
-
shownAs?: string | undefined;
|
|
528
|
-
}, {
|
|
529
|
-
flag: string;
|
|
530
|
-
type: "string" | "number" | "boolean" | "list";
|
|
531
|
-
description: string;
|
|
532
|
-
short?: string | undefined;
|
|
533
|
-
value?: string | undefined;
|
|
534
|
-
label?: string | undefined;
|
|
535
|
-
default?: string | number | undefined;
|
|
536
|
-
choices?: string[] | "harnesses" | "sessions" | "accounts" | undefined;
|
|
537
|
-
advanced?: boolean | undefined;
|
|
538
|
-
when?: string | undefined;
|
|
539
|
-
noMenu?: boolean | undefined;
|
|
540
|
-
group?: string | undefined;
|
|
541
|
-
shownAs?: string | undefined;
|
|
542
|
-
}];
|
|
543
502
|
}, {
|
|
544
503
|
readonly name: "logs";
|
|
545
504
|
readonly summary: "print the newest sandbox log";
|
|
@@ -810,17 +769,76 @@ declare const COMMAND_LIST: readonly [{
|
|
|
810
769
|
readonly interactive: true;
|
|
811
770
|
}, {
|
|
812
771
|
readonly name: "web";
|
|
813
|
-
readonly summary: "(beta) your sandbox sessions in a browser on this PC
|
|
772
|
+
readonly summary: "(beta) your sandbox sessions in a browser on this PC (and, if you allow it, on your network)";
|
|
814
773
|
readonly group: "Web";
|
|
815
|
-
readonly examples: readonly ["sandbox web open start the web UI and open it in your browser"];
|
|
774
|
+
readonly examples: readonly ["sandbox web open start the web UI and open it in your browser", "sandbox web lan-on let devices you allow use it on your network", "sandbox web allow-device show a one-time code for a phone", "sandbox web devices who may use it; sandbox web revoke <id> signs one out"];
|
|
816
775
|
readonly args: readonly [{
|
|
817
776
|
readonly name: "action";
|
|
818
|
-
readonly description: "start
|
|
777
|
+
readonly description: "start, stop, status, open; devices, allow-device, revoke, revoke-all, lan-on, lan-off (remote access)";
|
|
819
778
|
readonly required: false;
|
|
820
779
|
readonly choices: readonly ["start", "stop", "status", "open"];
|
|
780
|
+
}, {
|
|
781
|
+
readonly name: "id";
|
|
782
|
+
readonly description: "(revoke) the device or sign-in id from sandbox web devices";
|
|
783
|
+
readonly required: false;
|
|
784
|
+
readonly when: "revoke";
|
|
785
|
+
}];
|
|
786
|
+
readonly options: readonly [{
|
|
787
|
+
flag: string;
|
|
788
|
+
type: "string" | "number" | "boolean" | "list";
|
|
789
|
+
description: string;
|
|
790
|
+
short?: string | undefined;
|
|
791
|
+
value?: string | undefined;
|
|
792
|
+
label?: string | undefined;
|
|
793
|
+
default?: string | number | undefined;
|
|
794
|
+
choices?: string[] | "harnesses" | "sessions" | "accounts" | undefined;
|
|
795
|
+
advanced?: boolean | undefined;
|
|
796
|
+
when?: string | undefined;
|
|
797
|
+
noMenu?: boolean | undefined;
|
|
798
|
+
group?: string | undefined;
|
|
799
|
+
shownAs?: string | undefined;
|
|
800
|
+
}, {
|
|
801
|
+
flag: string;
|
|
802
|
+
type: "string" | "number" | "boolean" | "list";
|
|
803
|
+
description: string;
|
|
804
|
+
short?: string | undefined;
|
|
805
|
+
value?: string | undefined;
|
|
806
|
+
label?: string | undefined;
|
|
807
|
+
default?: string | number | undefined;
|
|
808
|
+
choices?: string[] | "harnesses" | "sessions" | "accounts" | undefined;
|
|
809
|
+
advanced?: boolean | undefined;
|
|
810
|
+
when?: string | undefined;
|
|
811
|
+
noMenu?: boolean | undefined;
|
|
812
|
+
group?: string | undefined;
|
|
813
|
+
shownAs?: string | undefined;
|
|
821
814
|
}];
|
|
822
|
-
readonly options: readonly [];
|
|
823
815
|
readonly json: true;
|
|
816
|
+
}, {
|
|
817
|
+
readonly name: "remote";
|
|
818
|
+
readonly summary: "(beta) use another Windows user's web UI from here, signed in with your Windows account";
|
|
819
|
+
readonly group: "Web";
|
|
820
|
+
readonly examples: readonly ["sandbox remote the menu over the owner of the running sandbox (their program, your role)", "sandbox remote alice --browser open alice's web UI in your browser, signed in"];
|
|
821
|
+
readonly args: readonly [{
|
|
822
|
+
readonly name: "user";
|
|
823
|
+
readonly description: "whose web UI (default: the owner of the running sandbox)";
|
|
824
|
+
readonly required: false;
|
|
825
|
+
}];
|
|
826
|
+
readonly options: readonly [{
|
|
827
|
+
flag: string;
|
|
828
|
+
type: "string" | "number" | "boolean" | "list";
|
|
829
|
+
description: string;
|
|
830
|
+
short?: string | undefined;
|
|
831
|
+
value?: string | undefined;
|
|
832
|
+
label?: string | undefined;
|
|
833
|
+
default?: string | number | undefined;
|
|
834
|
+
choices?: string[] | "harnesses" | "sessions" | "accounts" | undefined;
|
|
835
|
+
advanced?: boolean | undefined;
|
|
836
|
+
when?: string | undefined;
|
|
837
|
+
noMenu?: boolean | undefined;
|
|
838
|
+
group?: string | undefined;
|
|
839
|
+
shownAs?: string | undefined;
|
|
840
|
+
}];
|
|
841
|
+
readonly interactive: true;
|
|
824
842
|
}, {
|
|
825
843
|
readonly name: "_watch";
|
|
826
844
|
readonly summary: "background history sync";
|
package/dist/cli/manifest.js
CHANGED
|
@@ -386,20 +386,6 @@ const COMMAND_LIST = [
|
|
|
386
386
|
json,
|
|
387
387
|
},
|
|
388
388
|
{ name: 'sync', summary: 'copy conversation history back to this PC now', group: 'Data', args: [], options: [] },
|
|
389
|
-
{
|
|
390
|
-
name: 'audit',
|
|
391
|
-
summary: 'what happened in your sandboxes: programs started, files changed, sessions, repo guard (turn it on: sandbox config set audit.enabled true)',
|
|
392
|
-
group: 'Health',
|
|
393
|
-
json,
|
|
394
|
-
args: [],
|
|
395
|
-
options: [
|
|
396
|
-
{ flag: '--days', type: 'number', value: 'n', description: 'the last n days (default: today)', default: 1 },
|
|
397
|
-
text('--kind', 'kind', 'only proc, file, session or guard events', {
|
|
398
|
-
choices: ['proc', 'file', 'session', 'guard'],
|
|
399
|
-
}),
|
|
400
|
-
text('--grep', 'text', 'only events containing this text'),
|
|
401
|
-
],
|
|
402
|
-
},
|
|
403
389
|
{
|
|
404
390
|
name: 'logs',
|
|
405
391
|
summary: 'print the newest sandbox log',
|
|
@@ -554,20 +540,49 @@ const COMMAND_LIST = [
|
|
|
554
540
|
},
|
|
555
541
|
{
|
|
556
542
|
name: 'web',
|
|
557
|
-
summary: '(beta) your sandbox sessions in a browser on this PC
|
|
543
|
+
summary: '(beta) your sandbox sessions in a browser on this PC (and, if you allow it, on your network)',
|
|
558
544
|
group: 'Web',
|
|
559
|
-
examples: [
|
|
545
|
+
examples: [
|
|
546
|
+
'sandbox web open start the web UI and open it in your browser',
|
|
547
|
+
'sandbox web lan-on let devices you allow use it on your network',
|
|
548
|
+
'sandbox web allow-device show a one-time code for a phone',
|
|
549
|
+
'sandbox web devices who may use it; sandbox web revoke <id> signs one out',
|
|
550
|
+
],
|
|
560
551
|
args: [
|
|
561
552
|
{
|
|
562
553
|
name: 'action',
|
|
563
|
-
description: 'start
|
|
554
|
+
description: 'start, stop, status, open; devices, allow-device, revoke, revoke-all, lan-on, lan-off (remote access)',
|
|
564
555
|
required: false,
|
|
565
556
|
choices: ['start', 'stop', 'status', 'open'],
|
|
566
557
|
},
|
|
558
|
+
{
|
|
559
|
+
name: 'id',
|
|
560
|
+
description: '(revoke) the device or sign-in id from sandbox web devices',
|
|
561
|
+
required: false,
|
|
562
|
+
when: 'revoke',
|
|
563
|
+
},
|
|
564
|
+
],
|
|
565
|
+
options: [
|
|
566
|
+
text('--role', 'view|control', '(allow-device) what the device may do (default view)', {
|
|
567
|
+
when: 'allow-device',
|
|
568
|
+
choices: ['view', 'control'],
|
|
569
|
+
}),
|
|
570
|
+
bool('--yes', '(revoke-all, lan-off) do not ask first', { short: '-y', noMenu: true }),
|
|
567
571
|
],
|
|
568
|
-
options: [],
|
|
569
572
|
json,
|
|
570
573
|
},
|
|
574
|
+
{
|
|
575
|
+
name: 'remote',
|
|
576
|
+
summary: "(beta) use another Windows user's web UI from here, signed in with your Windows account",
|
|
577
|
+
group: 'Web',
|
|
578
|
+
examples: [
|
|
579
|
+
'sandbox remote the menu over the owner of the running sandbox (their program, your role)',
|
|
580
|
+
"sandbox remote alice --browser open alice's web UI in your browser, signed in",
|
|
581
|
+
],
|
|
582
|
+
args: [{ name: 'user', description: 'whose web UI (default: the owner of the running sandbox)', required: false }],
|
|
583
|
+
options: [bool('--browser', 'open it in your browser instead of the menu')],
|
|
584
|
+
interactive: true,
|
|
585
|
+
},
|
|
571
586
|
{ name: '_watch', summary: 'background history sync', group: 'Data', args: [], options: [], hidden: true },
|
|
572
587
|
{
|
|
573
588
|
name: '_web',
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type Action, type AnyDefinition } from '../../app/kernel/index.js';
|
|
1
|
+
import { type Action, type AnyDefinition, type OperationIO } from '../../app/kernel/index.js';
|
|
2
2
|
import type { Context } from '../commands/context.js';
|
|
3
3
|
import { type App } from '../tui/index.js';
|
|
4
4
|
import type { ShellExit } from './shell.js';
|
|
@@ -12,10 +12,12 @@ export interface Performed {
|
|
|
12
12
|
readonly notice?: string;
|
|
13
13
|
readonly reload?: boolean;
|
|
14
14
|
}
|
|
15
|
+
/** How a definition is run: in this process (the menu), or on the owner's web UI (sandbox remote). */
|
|
16
|
+
export type DefinitionRunner = (id: string, input: unknown, io: OperationIO) => Promise<unknown>;
|
|
15
17
|
export declare class MenuOperations {
|
|
16
18
|
private readonly app;
|
|
17
|
-
private readonly
|
|
18
|
-
constructor(app: App, ctx: Context);
|
|
19
|
+
private readonly runner;
|
|
20
|
+
constructor(app: App, ctx: Context, runner?: DefinitionRunner);
|
|
19
21
|
/** Does what an action of a page says: follows a link, or asks for its fields and runs its operation. */
|
|
20
22
|
perform(action: Action, where: Where, busy?: ShowBusy, onOutput?: (output: unknown) => void): Promise<Performed>;
|
|
21
23
|
/** The values of an action's fields, from the editors that fit them (undefined: one was backed out of). */
|
package/dist/cli/menu/io-menu.js
CHANGED
|
@@ -66,10 +66,10 @@ function follow(target) {
|
|
|
66
66
|
}
|
|
67
67
|
export class MenuOperations {
|
|
68
68
|
app;
|
|
69
|
-
|
|
70
|
-
constructor(app, ctx) {
|
|
69
|
+
runner;
|
|
70
|
+
constructor(app, ctx, runner = (id, input, io) => runDefinition(id, ctx, input, io)) {
|
|
71
71
|
this.app = app;
|
|
72
|
-
this.
|
|
72
|
+
this.runner = runner;
|
|
73
73
|
}
|
|
74
74
|
/** Does what an action of a page says: follows a link, or asks for its fields and runs its operation. */
|
|
75
75
|
async perform(action, where, busy, onOutput) {
|
|
@@ -81,7 +81,14 @@ export class MenuOperations {
|
|
|
81
81
|
const answers = await this.fields(action, def, where);
|
|
82
82
|
if (!answers)
|
|
83
83
|
return {};
|
|
84
|
-
|
|
84
|
+
// An operation that opens a session's terminal (a new shell) leaves the menu to attach to it.
|
|
85
|
+
let opened;
|
|
86
|
+
const notice = await this.run(def, { ...action.input, ...answers }, where, busy, (output) => {
|
|
87
|
+
onOutput?.(output);
|
|
88
|
+
opened = def.kind === 'operation' ? def.opens?.(output) : undefined;
|
|
89
|
+
});
|
|
90
|
+
const exit = opened ? follow(opened).exit : undefined;
|
|
91
|
+
return { reload: true, notice, ...(exit ? { exit } : {}) };
|
|
85
92
|
}
|
|
86
93
|
/** The values of an action's fields, from the editors that fit them (undefined: one was backed out of). */
|
|
87
94
|
async fields(action, def, where) {
|
|
@@ -110,7 +117,7 @@ export class MenuOperations {
|
|
|
110
117
|
log: (text, tone) => said.push(tone === 'warn' || tone === 'danger' ? Theme.warn(text) : text),
|
|
111
118
|
});
|
|
112
119
|
try {
|
|
113
|
-
const output = await
|
|
120
|
+
const output = await this.runner(def.id, input, io);
|
|
114
121
|
onOutput?.(output);
|
|
115
122
|
// The notice is one line: an operation that says several lines (accounts use) runs them together.
|
|
116
123
|
const text = def.text?.(output)?.replace(/\n+/g, ' ');
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
// (apps.toggle), so the staging stays here: "r" runs the feature's request operation, "c" stages your own programs.
|
|
5
5
|
import _ from 'lodash';
|
|
6
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';
|
|
7
|
+
import { APP_GROUPS, appDetails, appIsOn, appRows, customRows, CUSTOM_KEY, entriesOf, INSTALL, ISSUES_URL, requestApp, REQUEST_APP, SAVED, } from '../../../app/features/apps/index.js';
|
|
8
8
|
import { action } from '../../../app/kernel/index.js';
|
|
9
9
|
import { Theme } from '../../tui/index.js';
|
|
10
10
|
import { ValueEditor } from '../settings/value-editor.js';
|
|
@@ -37,20 +37,7 @@ export function appsCategories(file) {
|
|
|
37
37
|
];
|
|
38
38
|
}
|
|
39
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
|
-
];
|
|
40
|
+
const notes = appDetails(row).map((d) => d.warn ? Theme.warn(d.text) : (d.label ? Theme.muted(d.label.padEnd(10)) : '') + d.text);
|
|
54
41
|
return {
|
|
55
42
|
value: row.id,
|
|
56
43
|
label: row.name,
|
|
@@ -3,6 +3,7 @@ import { type Engines, type Leftovers } from '../../../app/features/engine/index
|
|
|
3
3
|
import { type HealthLast } from '../../../app/features/health/index.js';
|
|
4
4
|
import { type ContainedStatus, type StorageShow } from '../../../app/features/storage/index.js';
|
|
5
5
|
import { type LogFiles } from '../../../app/features/logs/index.js';
|
|
6
|
+
import { type AuditList } from '../../../app/features/audit/index.js';
|
|
6
7
|
import { type UpdatesStatus } from '../../../app/features/updates/updates.def.js';
|
|
7
8
|
import { type WebStatus } from '../../../app/features/web/index.js';
|
|
8
9
|
import type { Context } from '../../commands/context.js';
|
|
@@ -31,6 +32,8 @@ export interface MaintenanceModel {
|
|
|
31
32
|
readonly engine: Engines | null;
|
|
32
33
|
/** HCS systems left running, read with the engines. */
|
|
33
34
|
readonly leftovers?: Leftovers | null;
|
|
35
|
+
/** The audit log today (the audit view's query; null: not read yet or unreadable). */
|
|
36
|
+
readonly audit?: AuditList | null;
|
|
34
37
|
/** The web UI's server (the web feature's status): running or not, and its address. */
|
|
35
38
|
readonly web: WebStatus;
|
|
36
39
|
/** The commands listed under "More commands". */
|
|
@@ -52,6 +55,7 @@ export declare class MaintenancePage extends ListPage<string> {
|
|
|
52
55
|
private engine;
|
|
53
56
|
private leftovers;
|
|
54
57
|
private web;
|
|
58
|
+
private audit;
|
|
55
59
|
private readonly operations;
|
|
56
60
|
/** The newer version the last check found (null: none, or not looked yet). */
|
|
57
61
|
private latest;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// Section 7: keeping things in shape. Updates (the program and your saved settings), Data & storage (the data folder,
|
|
2
|
-
// what is stored, clean-up), Health (doctor, repair and this PC's setup together), the
|
|
3
|
-
// commands. Each is a category on the left and loads when you open it.
|
|
2
|
+
// what is stored, clean-up), Health (doctor, repair and this PC's setup together), Activity (the audit log), the logs,
|
|
3
|
+
// and the less common commands. Each is a category on the left and loads when you open it.
|
|
4
4
|
import { dataPage, showData } from '../../../app/features/data/index.js';
|
|
5
5
|
import { readQuery } from '../../../app/registry.js';
|
|
6
6
|
import { errMsg } from '../../../core/util/index.js';
|
|
@@ -8,6 +8,7 @@ import { enginePage, engineLeftovers, engineStatus, } from '../../../app/feature
|
|
|
8
8
|
import { healthPage, lastHealth } from '../../../app/features/health/index.js';
|
|
9
9
|
import { containedStatus, showStorage, storagePage, } from '../../../app/features/storage/index.js';
|
|
10
10
|
import { CRASH, listLogs, logsPage } from '../../../app/features/logs/index.js';
|
|
11
|
+
import { auditArgv, auditPage, listAudit } from '../../../app/features/audit/index.js';
|
|
11
12
|
import { updatesPage, updatesStatus } from '../../../app/features/updates/updates.def.js';
|
|
12
13
|
import { webPage, webStatus } from '../../../app/features/web/index.js';
|
|
13
14
|
import { commandSpec } from '../../manifest.js';
|
|
@@ -32,6 +33,11 @@ const CATEGORIES = [
|
|
|
32
33
|
label: 'Health',
|
|
33
34
|
description: 'Checks this PC and your settings, repairs problems, and sets up Windows Sandbox.',
|
|
34
35
|
},
|
|
36
|
+
{
|
|
37
|
+
id: 'activity',
|
|
38
|
+
label: 'Activity',
|
|
39
|
+
description: 'What your agents ran, changed and committed in the last 24 hours (the audit log). Enter on a session shows all of it.',
|
|
40
|
+
},
|
|
35
41
|
{ id: 'logs', label: 'Logs', description: "The sandbox's own logs." },
|
|
36
42
|
{
|
|
37
43
|
id: 'web',
|
|
@@ -45,14 +51,13 @@ const CATEGORIES = [
|
|
|
45
51
|
},
|
|
46
52
|
{ id: 'more', label: 'More commands', description: 'Less common commands.' },
|
|
47
53
|
];
|
|
48
|
-
const MORE_COMMANDS = ['sync', '
|
|
54
|
+
const MORE_COMMANDS = ['sync', 'config', 'generate', 'exec', 'agent-commands'];
|
|
49
55
|
const NO_LOGS = { folder: '', files: [], crash: false };
|
|
50
56
|
/** Until the status is read: the server counts as not running. */
|
|
51
57
|
const NO_WEB = { running: false, port: null, address: null };
|
|
52
58
|
/** Plain names for the commands under More commands. */
|
|
53
59
|
const MORE_LABELS = {
|
|
54
60
|
sync: 'Copy history back now',
|
|
55
|
-
audit: 'What happened in the sandbox',
|
|
56
61
|
config: 'Your settings file',
|
|
57
62
|
generate: 'Preview a start',
|
|
58
63
|
exec: 'Run a command in the sandbox',
|
|
@@ -107,6 +112,10 @@ const NO_UPDATES = {
|
|
|
107
112
|
function logsMenu(files) {
|
|
108
113
|
return menuView({ ...logsPage(files), empty: undefined }, { category: 'logs', refresh: false });
|
|
109
114
|
}
|
|
115
|
+
/** The audit view (src/app/features/audit) as the Activity category's rows and keys (none until it was read). */
|
|
116
|
+
function auditMenu(m) {
|
|
117
|
+
return m.audit ? menuView(auditPage(m.audit), { category: 'activity', prefix: 'audit:', refresh: false }) : undefined;
|
|
118
|
+
}
|
|
110
119
|
/** The Web UI view (src/app/features/web) as the menu's rows, keys and Enter labels, for the Web UI category. */
|
|
111
120
|
function webMenu(m) {
|
|
112
121
|
return menuView(webPage(m.web), { category: 'web', prefix: 'web:', refresh: false });
|
|
@@ -120,6 +129,7 @@ export function maintenanceOptions(m) {
|
|
|
120
129
|
const updates = updatesMenu(m);
|
|
121
130
|
const engine = engineMenu(m);
|
|
122
131
|
const web = webMenu(m);
|
|
132
|
+
const audit = auditMenu(m);
|
|
123
133
|
const more = m.more.map((c) => ({
|
|
124
134
|
value: 'more:' + c.name,
|
|
125
135
|
label: MORE_LABELS[c.name] ?? Text.humanize(c.name),
|
|
@@ -129,7 +139,16 @@ export function maintenanceOptions(m) {
|
|
|
129
139
|
return {
|
|
130
140
|
path: [],
|
|
131
141
|
categories: CATEGORIES,
|
|
132
|
-
items: [
|
|
142
|
+
items: [
|
|
143
|
+
...updates.items,
|
|
144
|
+
...dataItems(m),
|
|
145
|
+
...health.items,
|
|
146
|
+
...(audit?.items ?? []),
|
|
147
|
+
...logs,
|
|
148
|
+
...web.items,
|
|
149
|
+
...engine.items,
|
|
150
|
+
...more,
|
|
151
|
+
],
|
|
133
152
|
empty: 'Nothing here yet.',
|
|
134
153
|
actions: maintenanceActions(m),
|
|
135
154
|
enterLabel: (category, id) => category === 'health'
|
|
@@ -140,9 +159,11 @@ export function maintenanceOptions(m) {
|
|
|
140
159
|
? engine.enterLabel(category, id)
|
|
141
160
|
: category === 'web'
|
|
142
161
|
? web.enterLabel(category, id)
|
|
143
|
-
:
|
|
144
|
-
?
|
|
145
|
-
:
|
|
162
|
+
: category === 'activity'
|
|
163
|
+
? (audit?.enterLabel(category, id) ?? '')
|
|
164
|
+
: (category === 'data'
|
|
165
|
+
? storageMenu(m.storage)?.enterLabel(category, id) || dataMenuView(m.data)?.enterLabel(category, id)
|
|
166
|
+
: undefined) || enterLabel(id ?? ''),
|
|
146
167
|
};
|
|
147
168
|
}
|
|
148
169
|
/**
|
|
@@ -201,6 +222,8 @@ function maintenanceActions(m) {
|
|
|
201
222
|
return [{ key: 'l', label: m.engine ? 'check again' : 'check' }, ...engineMenu(m).actions];
|
|
202
223
|
case 'web':
|
|
203
224
|
return webMenu(m).actions;
|
|
225
|
+
case 'activity':
|
|
226
|
+
return auditMenu(m)?.actions ?? [];
|
|
204
227
|
default:
|
|
205
228
|
return [];
|
|
206
229
|
}
|
|
@@ -217,6 +240,7 @@ export class MaintenancePage extends ListPage {
|
|
|
217
240
|
engine = null;
|
|
218
241
|
leftovers = null;
|
|
219
242
|
web = NO_WEB;
|
|
243
|
+
audit = null;
|
|
220
244
|
operations;
|
|
221
245
|
/** The newer version the last check found (null: none, or not looked yet). */
|
|
222
246
|
latest = null;
|
|
@@ -235,6 +259,7 @@ export class MaintenancePage extends ListPage {
|
|
|
235
259
|
engine: this.engine,
|
|
236
260
|
leftovers: this.leftovers,
|
|
237
261
|
web: this.web,
|
|
262
|
+
audit: this.audit,
|
|
238
263
|
more: MORE_COMMANDS.flatMap((name) => {
|
|
239
264
|
const spec = commandSpec(name);
|
|
240
265
|
return spec ? [{ name, summary: spec.summary }] : [];
|
|
@@ -259,6 +284,13 @@ export class MaintenancePage extends ListPage {
|
|
|
259
284
|
}
|
|
260
285
|
this.last = (await readQuery(lastHealth, this.ctx)).last;
|
|
261
286
|
this.updates = await readQuery(updatesStatus, this.ctx);
|
|
287
|
+
try {
|
|
288
|
+
this.audit = await readQuery(listAudit, this.ctx, { limit: 200 });
|
|
289
|
+
}
|
|
290
|
+
catch {
|
|
291
|
+
// An unreadable log: the category says there is nothing yet.
|
|
292
|
+
this.audit = null;
|
|
293
|
+
}
|
|
262
294
|
try {
|
|
263
295
|
this.web = await readQuery(webStatus, this.ctx);
|
|
264
296
|
}
|
|
@@ -306,6 +338,17 @@ export class MaintenancePage extends ListPage {
|
|
|
306
338
|
return await this.operations.perform(chosen.action, [this.label], (text) => this.busy(text));
|
|
307
339
|
return {};
|
|
308
340
|
}
|
|
341
|
+
// Activity: a session's row shows its events on the normal screen (sandbox audit --session ...); turning the
|
|
342
|
+
// log on runs the settings operation.
|
|
343
|
+
if (this.category === 'activity') {
|
|
344
|
+
const chosen = auditMenu(this.model())?.resolve(result);
|
|
345
|
+
if (chosen?.kind !== 'action')
|
|
346
|
+
return {};
|
|
347
|
+
const target = chosen.action.kind === 'link' ? chosen.action.target : undefined;
|
|
348
|
+
if (target?.kind === 'view')
|
|
349
|
+
return { exit: { kind: 'run', argv: auditArgv(target.params) } };
|
|
350
|
+
return await this.operations.perform(chosen.action, [this.label], (text) => this.busy(text));
|
|
351
|
+
}
|
|
309
352
|
if (key === 'm' || id === 'data:measure')
|
|
310
353
|
return await this.measure();
|
|
311
354
|
// Only the open category's rows and keys: `f` and Enter mean something else in Health.
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { type AnyView, type Caller } from '../../app/kernel/index.js';
|
|
2
|
+
import type { Context } from '../commands/context.js';
|
|
3
|
+
import type { RemoteClient } from '../services/remote-client.js';
|
|
4
|
+
import { type App } from '../tui/index.js';
|
|
5
|
+
/** The views of the owner's program this role may open (remote access itself is the owner's). */
|
|
6
|
+
export declare function remoteViews(role: Caller): AnyView[];
|
|
7
|
+
export declare class RemoteMenu {
|
|
8
|
+
private readonly app;
|
|
9
|
+
private readonly client;
|
|
10
|
+
private readonly owner;
|
|
11
|
+
private readonly caller;
|
|
12
|
+
private readonly operations;
|
|
13
|
+
constructor(app: App, ctx: Context, client: RemoteClient, owner: string, caller: Caller);
|
|
14
|
+
private title;
|
|
15
|
+
/** The list of areas, until Esc. */
|
|
16
|
+
start(): Promise<void>;
|
|
17
|
+
private page;
|
|
18
|
+
private showView;
|
|
19
|
+
}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
// `sandbox remote`: the menu drawn over another Windows user's program (docs/design/remote-access.md). Every view the
|
|
2
|
+
// web UI has is drawn by the menu's own renderer (menuView) from the shared core's pure definitions; its queries and
|
|
3
|
+
// operations run on the owner's web UI over the RPC socket, which checks the role this user was given and writes each
|
|
4
|
+
// action to the owner's audit log. Nothing here runs on this user's own settings or data.
|
|
5
|
+
import { NAV, navViews, viewById } from '../../app/features/defs.js';
|
|
6
|
+
import { NO_QUESTIONS, allows, viewInputs, } from '../../app/kernel/index.js';
|
|
7
|
+
import { errMsg, safeText } from '../../core/util/index.js';
|
|
8
|
+
import { Theme } from '../tui/index.js';
|
|
9
|
+
import { MenuOperations } from './io-menu.js';
|
|
10
|
+
import { menuView } from './render-view.js';
|
|
11
|
+
/** The views of the owner's program this role may open (remote access itself is the owner's). */
|
|
12
|
+
export function remoteViews(role) {
|
|
13
|
+
return navViews(NAV)
|
|
14
|
+
.map((id) => viewById(id))
|
|
15
|
+
.filter((v) => v !== undefined)
|
|
16
|
+
.filter((v) => Object.values(v.queries).every((q) => allows(role, q.access ?? 'view')));
|
|
17
|
+
}
|
|
18
|
+
export class RemoteMenu {
|
|
19
|
+
app;
|
|
20
|
+
client;
|
|
21
|
+
owner;
|
|
22
|
+
caller;
|
|
23
|
+
operations;
|
|
24
|
+
constructor(app, ctx, client, owner, caller) {
|
|
25
|
+
this.app = app;
|
|
26
|
+
this.client = client;
|
|
27
|
+
this.owner = owner;
|
|
28
|
+
this.caller = caller;
|
|
29
|
+
this.operations = new MenuOperations(app, ctx, (id, input, io) => client.run(id, input, io));
|
|
30
|
+
}
|
|
31
|
+
title() {
|
|
32
|
+
return safeText(this.owner) + "'s sandbox";
|
|
33
|
+
}
|
|
34
|
+
/** The list of areas, until Esc. */
|
|
35
|
+
async start() {
|
|
36
|
+
const views = remoteViews(this.caller);
|
|
37
|
+
const role = this.caller.kind === 'owner' ? 'owner' : this.caller.role;
|
|
38
|
+
let at;
|
|
39
|
+
for (;;) {
|
|
40
|
+
const picked = await this.app.list({
|
|
41
|
+
path: [this.title()],
|
|
42
|
+
intro: [
|
|
43
|
+
'You are using ' + safeText(this.owner) + "'s program with the role " + role + '.',
|
|
44
|
+
'What you do runs as ' + safeText(this.owner) + ' and is written to their audit log.',
|
|
45
|
+
],
|
|
46
|
+
items: views.map((v) => ({ value: v.id, label: v.title, description: v.summary })),
|
|
47
|
+
startAt: at,
|
|
48
|
+
escapeLabel: 'quit',
|
|
49
|
+
enterLabel: 'open',
|
|
50
|
+
});
|
|
51
|
+
if (picked.kind !== 'pick')
|
|
52
|
+
return;
|
|
53
|
+
at = picked.value;
|
|
54
|
+
const view = views.find((v) => v.id === picked.value);
|
|
55
|
+
if (view)
|
|
56
|
+
await this.showView(view);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
async page(view) {
|
|
60
|
+
const inputs = viewInputs(view, {});
|
|
61
|
+
const data = {};
|
|
62
|
+
for (const [name, query] of Object.entries(view.queries))
|
|
63
|
+
data[name] = await this.client.run(query.id, inputs[name], NO_QUESTIONS);
|
|
64
|
+
return view.build(data, {});
|
|
65
|
+
}
|
|
66
|
+
async showView(view) {
|
|
67
|
+
let notice;
|
|
68
|
+
for (;;) {
|
|
69
|
+
let page;
|
|
70
|
+
try {
|
|
71
|
+
page = await this.page(view);
|
|
72
|
+
}
|
|
73
|
+
catch (e) {
|
|
74
|
+
await this.app.message({ path: [this.title(), view.title], lines: [safeText(errMsg(e))], tone: 'error' });
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
const mv = menuView(page);
|
|
78
|
+
const result = await this.app.list({
|
|
79
|
+
path: [this.title(), view.title],
|
|
80
|
+
intro: page.notice ? [safeText(page.notice.text)] : undefined,
|
|
81
|
+
items: mv.items,
|
|
82
|
+
actions: mv.actions,
|
|
83
|
+
enterLabel: mv.enterLabel,
|
|
84
|
+
notice,
|
|
85
|
+
empty: page.empty?.text,
|
|
86
|
+
});
|
|
87
|
+
if (result.kind === 'back')
|
|
88
|
+
return;
|
|
89
|
+
const chosen = mv.resolve(result);
|
|
90
|
+
notice = undefined;
|
|
91
|
+
if (!chosen || chosen.kind === 'refresh')
|
|
92
|
+
continue;
|
|
93
|
+
const action = chosen.action;
|
|
94
|
+
if (action.kind === 'link') {
|
|
95
|
+
notice =
|
|
96
|
+
action.target.kind === 'terminal'
|
|
97
|
+
? Theme.muted('Attach to it from your own terminal: sandbox attach ' + safeText(action.target.session))
|
|
98
|
+
: Theme.muted('That opens on ' + safeText(this.owner) + "'s side only.");
|
|
99
|
+
continue;
|
|
100
|
+
}
|
|
101
|
+
const done = await this.operations.perform(action, [this.title(), view.title], (text) => {
|
|
102
|
+
notice = text;
|
|
103
|
+
this.app.redraw();
|
|
104
|
+
});
|
|
105
|
+
notice = done.notice;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
package/dist/cli/menu/views.js
CHANGED
|
@@ -7,6 +7,7 @@ import { accountsView } from '../../app/features/accounts/index.js';
|
|
|
7
7
|
import { appsView } from '../../app/features/apps/index.js';
|
|
8
8
|
import { healthView } from '../../app/features/health/index.js';
|
|
9
9
|
import { logsView } from '../../app/features/logs/index.js';
|
|
10
|
+
import { auditView } from '../../app/features/audit/index.js';
|
|
10
11
|
import { projectsView } from '../../app/features/projects/index.js';
|
|
11
12
|
import { sandboxView } from '../../app/features/sandbox/index.js';
|
|
12
13
|
import { sessionsView } from '../../app/features/sessions/index.js';
|
|
@@ -17,6 +18,7 @@ import { updatesView } from '../../app/features/updates/index.js';
|
|
|
17
18
|
import { webView } from '../../app/features/web/index.js';
|
|
18
19
|
import { vpnView } from '../../app/features/vpn/index.js';
|
|
19
20
|
import { githubView } from '../../app/features/github/index.js';
|
|
21
|
+
import { accessView } from '../../app/features/access/index.js';
|
|
20
22
|
export const MENU_VIEWS = [
|
|
21
23
|
{ view: agentsView, section: 'Agents' },
|
|
22
24
|
{ view: sessionsView, section: 'Sessions' },
|
|
@@ -29,9 +31,11 @@ export const MENU_VIEWS = [
|
|
|
29
31
|
{ view: dataView, section: 'Maintenance' },
|
|
30
32
|
{ view: storageView, section: 'Maintenance' },
|
|
31
33
|
{ view: logsView, section: 'Maintenance' },
|
|
34
|
+
{ view: auditView, section: 'Maintenance' },
|
|
32
35
|
{ view: updatesView, section: 'Maintenance' },
|
|
33
36
|
{ view: engineView, section: 'Maintenance' },
|
|
34
37
|
{ view: webView, section: 'Maintenance' },
|
|
38
|
+
{ view: accessView, section: 'Maintenance' },
|
|
35
39
|
// The Settings page draws the VPN row itself (its login is staged with the settings); the view lists its operations.
|
|
36
40
|
{ view: vpnView, section: 'Settings' },
|
|
37
41
|
// The same for the GitHub token row.
|