windows-development-sandbox 1.20.0 → 1.23.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/config.example.json +8 -1
- package/dist/app/features/access/access.def.js +5 -2
- package/dist/app/features/access/access.run.js +7 -3
- package/dist/app/features/accounts/accounts.def.d.ts +29 -1
- package/dist/app/features/accounts/accounts.def.js +10 -4
- package/dist/app/features/accounts/accounts.run.d.ts +1 -0
- package/dist/app/features/accounts/accounts.run.js +7 -2
- package/dist/app/features/accounts/services.def.d.ts +4 -1
- package/dist/app/features/accounts/services.def.js +15 -14
- package/dist/app/features/accounts/services.run.d.ts +1 -0
- package/dist/app/features/accounts/services.run.js +41 -15
- package/dist/app/features/defs.d.ts +39 -2
- package/dist/app/features/engine/engine.run.js +1 -1
- package/dist/app/features/github/github.def.d.ts +44 -3
- package/dist/app/features/github/github.def.js +145 -63
- package/dist/app/features/github/github.run.d.ts +9 -2
- package/dist/app/features/github/github.run.js +43 -5
- package/dist/app/features/health/health.def.js +8 -2
- package/dist/app/features/logs/logs.def.js +0 -8
- package/dist/app/features/projects/projects.def.js +2 -2
- package/dist/app/features/projects/projects.run.js +5 -5
- package/dist/app/features/sandbox/sandbox.def.js +7 -3
- package/dist/app/features/sessions/sessions.def.d.ts +4 -4
- package/dist/app/features/sessions/sessions.def.js +0 -5
- package/dist/app/features/sessions/sessions.run.d.ts +1 -1
- package/dist/app/features/sessions/sessions.run.js +2 -2
- package/dist/app/features/settings/categories.def.js +2 -0
- package/dist/app/features/settings/settings-rows.js +1 -1
- package/dist/app/features/settings/settings.def.js +1 -1
- package/dist/app/features/settings/settings.run.js +3 -3
- package/dist/app/features/storage/storage.run.js +18 -9
- package/dist/app/features/updates/update-lines.js +2 -2
- package/dist/app/features/updates/updates.def.js +1 -1
- package/dist/app/features/updates/updates.run.js +1 -1
- package/dist/app/features/web/web.def.js +2 -2
- package/dist/app/features/web/web.run.js +12 -4
- package/dist/app/kernel/errors.d.ts +7 -0
- package/dist/app/kernel/errors.js +18 -3
- package/dist/app/kernel/rpc.d.ts +5 -0
- package/dist/app/kernel/view.d.ts +11 -1
- package/dist/bin/agent-sandbox.js +2 -2
- package/dist/bin/{chunk-DK4NTBUF.js → chunk-7YPEDAJD.js} +172 -48
- package/dist/bin/{chunk-2IMT7ZCT.js → chunk-QFSJX2KW.js} +1 -1
- package/dist/bin/{chunk-Z2P5OGKL.js → chunk-USTRSHIE.js} +2436 -1693
- package/dist/bin/claude-host.js +2 -2
- package/dist/bin/claude-sbx.js +2 -2
- package/dist/bin/codex-sbx.js +2 -2
- package/dist/bin/gemini-sbx.js +2 -2
- package/dist/bin/sandbox.js +2 -2
- package/dist/bin/sbx-hide.js +2 -2
- package/dist/bin/sbx-show.js +2 -2
- package/dist/cli/manifest.d.ts +2 -2
- package/dist/cli/manifest.js +2 -1
- package/dist/cli/menu/coverage-exempt.d.ts +17 -0
- package/dist/cli/menu/coverage-exempt.js +61 -0
- package/dist/cli/menu/io-menu.d.ts +2 -0
- package/dist/cli/menu/io-menu.js +50 -5
- package/dist/cli/menu/pages/accounts-page.js +1 -1
- package/dist/cli/menu/pages/agents-page.js +8 -2
- package/dist/cli/menu/pages/maintenance-page.d.ts +6 -0
- package/dist/cli/menu/pages/maintenance-page.js +9 -2
- package/dist/cli/menu/pages/sessions-page.d.ts +2 -0
- package/dist/cli/menu/pages/sessions-page.js +12 -4
- package/dist/cli/menu/pages/settings-page.js +12 -1
- package/dist/cli/menu/remote-menu.js +1 -1
- package/dist/cli/menu/shell.d.ts +5 -0
- package/dist/cli/menu/shell.js +13 -0
- package/dist/cli/report.js +2 -0
- package/dist/cli/tui/app.d.ts +5 -0
- package/dist/cli/tui/app.js +2 -0
- package/dist/core/config/defaults.js +3 -1
- package/dist/core/schema/accounts.d.ts +6 -0
- package/dist/core/schema/accounts.js +13 -11
- package/dist/core/schema/config.d.ts +20 -8
- package/dist/core/schema/config.js +4 -4
- package/dist/core/schema/github.js +1 -1
- package/dist/core/schema/profile.js +8 -4
- package/dist/core/schema/resume.js +1 -1
- package/dist/core/schema/sandbox.js +3 -3
- package/dist/core/schema/vpn.js +1 -1
- package/dist/core/schema/web.js +3 -3
- package/dist/core/types.d.ts +6 -0
- package/dist/core/util/errors.d.ts +11 -1
- package/dist/core/util/errors.js +7 -1
- package/dist/core/util/index.d.ts +1 -1
- package/dist/core/util/index.js +1 -1
- package/dist/guest/accounts/adapter.d.ts +2 -0
- package/dist/guest/accounts/adapters.js +4 -0
- package/dist/guest/accounts/apply.d.ts +6 -2
- package/dist/guest/accounts/kinds/cfx.d.ts +7 -0
- package/dist/guest/accounts/kinds/cfx.js +33 -3
- package/dist/guest/accounts/kinds/comet.d.ts +7 -0
- package/dist/guest/accounts/kinds/comet.js +50 -0
- package/dist/guest/accounts/kinds/perplexity.d.ts +2 -0
- package/dist/guest/accounts/kinds/perplexity.js +12 -0
- package/dist/guest/accounts/watch.d.ts +2 -0
- package/dist/guest/accounts/watch.js +12 -2
- package/dist/guest/agents/agent-installer.js +1 -1
- package/dist/guest/agents/profile-links.d.ts +2 -0
- package/dist/guest/agents/profile-links.js +18 -4
- package/dist/guest/apps/after-install.js +19 -0
- package/dist/guest/apps/app-installer.d.ts +11 -0
- package/dist/guest/apps/app-installer.js +69 -6
- package/dist/guest/apps/comet-unpack.d.ts +20 -0
- package/dist/guest/apps/comet-unpack.js +127 -0
- package/dist/guest/apps/index.d.ts +1 -1
- package/dist/guest/apps/index.js +1 -1
- package/dist/guest/apps/resolvers-agents-web.d.ts +2 -0
- package/dist/guest/apps/resolvers-agents-web.js +7 -0
- package/dist/guest/apps/resolvers.js +2 -0
- package/dist/guest/apps/shortcuts.d.ts +2 -0
- package/dist/guest/apps/shortcuts.js +1 -0
- package/dist/guest/apps/unpack.js +14 -4
- package/dist/guest/boot/boot.d.ts +45 -16
- package/dist/guest/boot/boot.js +316 -145
- package/dist/guest/boot/graph.d.ts +252 -0
- package/dist/guest/boot/graph.js +257 -0
- package/dist/guest/boot/guide-lines.d.ts +25 -0
- package/dist/guest/boot/guide-lines.js +41 -0
- package/dist/guest/boot/guide.d.ts +1 -4
- package/dist/guest/boot/guide.js +6 -8
- package/dist/guest/boot/runner.d.ts +77 -0
- package/dist/guest/boot/runner.js +215 -0
- package/dist/guest/browser/cdp.d.ts +71 -0
- package/dist/guest/browser/cdp.js +306 -0
- package/dist/guest/browser/comet.d.ts +28 -0
- package/dist/guest/browser/comet.js +155 -0
- package/dist/guest/daemon/project-provisioner.js +6 -1
- package/dist/guest/devtools/fivem.d.ts +1 -1
- package/dist/guest/devtools/fivem.js +243 -3
- package/dist/guest/entries/daemon.js +2 -0
- package/dist/guest/runtime/log.d.ts +12 -0
- package/dist/guest/runtime/log.js +29 -5
- package/dist/guest/runtime/pools.d.ts +24 -0
- package/dist/guest/runtime/pools.js +60 -0
- package/dist/guest/runtime/process.d.ts +4 -0
- package/dist/guest/runtime/process.js +38 -1
- package/dist/guest/runtime/status.d.ts +5 -1
- package/dist/guest/runtime/status.js +19 -0
- package/dist/guest/setup/addon-mcp.d.ts +1 -1
- package/dist/guest/setup/addon-mcp.js +52 -12
- package/dist/guest/setup/agent-addons.d.ts +3 -2
- package/dist/guest/setup/agent-addons.js +12 -3
- package/dist/guest/setup/environment.d.ts +1 -1
- package/dist/guest/setup/environment.js +25 -12
- package/dist/guest/setup/headroom.d.ts +8 -3
- package/dist/guest/setup/headroom.js +44 -15
- package/dist/guest/setup/path-plan.d.ts +28 -0
- package/dist/guest/setup/path-plan.js +69 -2
- package/dist/guest/setup/shell-path.d.ts +1 -1
- package/dist/guest/setup/shell-path.js +3 -3
- package/dist/guest/toolchains/fivem/artifacts.d.ts +48 -1
- package/dist/guest/toolchains/fivem/artifacts.js +97 -4
- package/dist/guest/toolchains/fivem/fivem.d.ts +32 -1
- package/dist/guest/toolchains/fivem/fivem.js +168 -3
- package/dist/guest/toolchains/fivem/scaffold.d.ts +35 -0
- package/dist/guest/toolchains/fivem/scaffold.js +105 -0
- package/dist/guest/toolchains/fivem/serve-plan.d.ts +34 -0
- package/dist/guest/toolchains/fivem/serve-plan.js +61 -0
- package/dist/guest/toolchains/languages/go.js +1 -1
- package/dist/guest/toolchains/languages/node.js +2 -1
- package/dist/guest/toolchains/languages/php.d.ts +2 -0
- package/dist/guest/toolchains/languages/php.js +13 -1
- package/dist/guest/toolchains/languages/python-tools.js +1 -1
- package/dist/guest/toolchains/languages/ruby.js +1 -1
- package/dist/guest/toolchains/native/binstall.js +1 -1
- package/dist/guest/toolchains/native/msvc/packages.js +10 -4
- package/dist/guest/toolchains/native/rust.d.ts +2 -0
- package/dist/guest/toolchains/native/rust.js +11 -4
- package/dist/guest/toolchains/native/unreal.d.ts +2 -0
- package/dist/guest/toolchains/native/unreal.js +16 -6
- package/dist/guest/toolchains/native/vcruntime.d.ts +2 -0
- package/dist/guest/toolchains/native/vcruntime.js +10 -2
- package/dist/guest/toolchains/native/visual-studio.d.ts +3 -0
- package/dist/guest/toolchains/native/visual-studio.js +44 -26
- package/dist/guest/toolchains/native/vs-request.d.ts +2 -0
- package/dist/guest/toolchains/native/vs-request.js +2 -0
- package/dist/guest/toolchains/plan.js +19 -8
- package/dist/guest/toolchains/scheduler.d.ts +2 -21
- package/dist/guest/toolchains/scheduler.js +7 -121
- package/dist/guest/toolchains/setup.d.ts +15 -2
- package/dist/guest/toolchains/setup.js +39 -20
- package/dist/guest/toolchains/split.d.ts +28 -0
- package/dist/guest/toolchains/split.js +60 -0
- package/dist/guest/toolchains/steam/client.js +2 -1
- package/dist/guest/toolchains/step-scheduler.d.ts +51 -0
- package/dist/guest/toolchains/step-scheduler.js +147 -0
- package/dist/guest/toolchains/step.d.ts +13 -0
- package/dist/guest/toolchains/tools/git.js +18 -0
- package/dist/guest/vpn/openvpn.js +3 -4
- package/dist/guest/vpn/wireguard.js +11 -4
- package/dist/host/accounts/deliver.js +7 -0
- package/dist/host/accounts/handoff.js +2 -6
- package/dist/host/accounts/index.d.ts +1 -1
- package/dist/host/accounts/index.js +1 -1
- package/dist/host/accounts/kinds/cfx.d.ts +1 -1
- package/dist/host/accounts/kinds/cfx.js +47 -4
- package/dist/host/accounts/kinds/comet.d.ts +2 -0
- package/dist/host/accounts/kinds/comet.js +6 -0
- package/dist/host/accounts/kinds/perplexity.d.ts +2 -0
- package/dist/host/accounts/kinds/perplexity.js +30 -0
- package/dist/host/accounts/leases.d.ts +7 -1
- package/dist/host/accounts/leases.js +13 -2
- package/dist/host/accounts/source.d.ts +7 -1
- package/dist/host/accounts/source.js +27 -0
- package/dist/host/accounts/sources.js +4 -0
- package/dist/host/github/deliver.d.ts +1 -1
- package/dist/host/github/deliver.js +20 -1
- package/dist/host/github/index.d.ts +2 -1
- package/dist/host/github/index.js +1 -0
- package/dist/host/github/token.d.ts +13 -1
- package/dist/host/github/token.js +19 -2
- package/dist/host/github/verify.d.ts +27 -0
- package/dist/host/github/verify.js +61 -0
- package/dist/host/launch/hints/fivem.d.ts +3 -1
- package/dist/host/launch/hints/fivem.js +68 -2
- package/dist/host/launch/session-file.js +4 -0
- package/dist/host/launch/toolchains.d.ts +2 -1
- package/dist/host/launch/toolchains.js +5 -3
- package/dist/host/profile/claude-login.d.ts +2 -2
- package/dist/host/profile/claude-login.js +4 -3
- package/dist/host/vpn/nordvpn.d.ts +2 -4
- package/dist/host/vpn/nordvpn.js +2 -24
- package/dist/runtime/agent.js +405 -90
- package/dist/runtime/daemon.js +3010 -1383
- package/dist/runtime/db.js +333 -90
- package/dist/runtime/main.js +4720 -1954
- package/dist/runtime/netproxy.js +286 -69
- package/dist/runtime/tool.js +2852 -1780
- package/dist/runtime/view.js +286 -69
- package/dist/selftest/accounts.test.js +1 -1
- package/dist/selftest/agent-paths.test.js +39 -1
- package/dist/selftest/agent-settings.test.js +6 -0
- package/dist/selftest/agents-web.test.d.ts +2 -0
- package/dist/selftest/agents-web.test.js +647 -0
- package/dist/selftest/app.test.js +5 -2
- package/dist/selftest/boot-runner.test.d.ts +2 -0
- package/dist/selftest/boot-runner.test.js +456 -0
- package/dist/selftest/channel.test.js +15 -0
- package/dist/selftest/fivem.test.js +249 -3
- package/dist/selftest/github.test.js +94 -9
- package/dist/selftest/guest-boot.test.js +3 -0
- package/dist/selftest/health.test.js +1 -1
- package/dist/selftest/index.js +8 -0
- package/dist/selftest/layout.test.js +5 -0
- package/dist/selftest/menu-coverage.test.d.ts +2 -0
- package/dist/selftest/menu-coverage.test.js +46 -0
- package/dist/selftest/menu-screens.js +37 -1
- package/dist/selftest/persisted-installs.test.js +6 -3
- package/dist/selftest/service-accounts.test.js +3 -2
- package/dist/selftest/support/engine-golden.js +27 -0
- package/dist/selftest/support/fixtures.d.ts +6 -0
- package/dist/selftest/support/web-preview.d.ts +34 -1
- package/dist/selftest/support/web-preview.js +21 -18
- package/dist/selftest/toolchains.test.js +23 -1
- package/dist/selftest/ui-text.test.d.ts +7 -0
- package/dist/selftest/ui-text.test.js +300 -0
- package/dist/shared/accounts/anthropic.d.ts +1 -1
- package/dist/shared/accounts/anthropic.js +9 -8
- package/dist/shared/accounts/index.d.ts +2 -0
- package/dist/shared/accounts/index.js +2 -0
- package/dist/shared/accounts/kinds/comet.d.ts +12 -0
- package/dist/shared/accounts/kinds/comet.js +64 -0
- package/dist/shared/accounts/kinds/perplexity.d.ts +8 -0
- package/dist/shared/accounts/kinds/perplexity.js +37 -0
- package/dist/shared/accounts/kinds.d.ts +24 -5
- package/dist/shared/accounts/kinds.js +86 -4
- package/dist/shared/accounts/payloads.d.ts +81 -0
- package/dist/shared/accounts/payloads.js +39 -1
- package/dist/shared/apps/agent-addons.d.ts +33 -5
- package/dist/shared/apps/agent-addons.js +95 -3
- package/dist/shared/apps/catalogue-agents-web.d.ts +14 -0
- package/dist/shared/apps/catalogue-agents-web.js +112 -0
- package/dist/shared/apps/catalogue-modding.js +32 -1
- package/dist/shared/apps/catalogue.d.ts +27 -3
- package/dist/shared/apps/catalogue.js +2 -1
- package/dist/shared/apps/index.d.ts +3 -1
- package/dist/shared/apps/index.js +3 -1
- package/dist/shared/channel/schema.d.ts +21 -3
- package/dist/shared/channel/schema.js +7 -0
- package/dist/shared/channel/secrets.d.ts +19 -0
- package/dist/shared/concurrency/index.d.ts +3 -0
- package/dist/shared/concurrency/index.js +3 -0
- package/dist/shared/concurrency/installer-retry.d.ts +6 -0
- package/dist/shared/concurrency/installer-retry.js +10 -0
- package/dist/shared/concurrency/limiter.d.ts +19 -0
- package/dist/shared/concurrency/limiter.js +67 -0
- package/dist/shared/concurrency/pools.d.ts +7 -0
- package/dist/shared/concurrency/pools.js +9 -0
- package/dist/shared/download/archive.d.ts +2 -0
- package/dist/shared/download/archive.js +11 -1
- package/dist/shared/download/bounded-fetch.d.ts +13 -0
- package/dist/shared/download/bounded-fetch.js +40 -0
- package/dist/shared/download/downloader.d.ts +5 -0
- package/dist/shared/download/downloader.js +50 -38
- package/dist/shared/download/index.d.ts +2 -1
- package/dist/shared/download/index.js +2 -1
- package/dist/shared/readiness.d.ts +2 -2
- package/dist/shared/readiness.js +2 -2
- package/dist/web/index.html +1 -1
- package/dist/web/{main-OUUQYNK4.js → main-CCILLX2M.js} +67 -67
- package/native/csharp/HcsHost/AssemblyInfo.cs +3 -3
- package/native/csharp/HostTools/AssemblyInfo.cs +3 -3
- package/native/csharp/StorageHelper/AssemblyInfo.cs +3 -3
- package/package.json +1 -1
- package/sandbox/addons/browser-use-mcp/requirements.in +1 -0
- package/sandbox/addons/browser-use-mcp/requirements.txt +2350 -0
- package/sandbox/addons/chrome-devtools-mcp/package-lock.json +38 -0
- package/sandbox/addons/chrome-devtools-mcp/package.json +7 -0
- package/sandbox/addons/comet-mcp/package-lock.json +1277 -0
- package/sandbox/addons/comet-mcp/package.json +7 -0
- package/sandbox/addons/perplexity-mcp/package-lock.json +1655 -0
- package/sandbox/addons/perplexity-mcp/package.json +7 -0
- package/sandbox/scripts/add-firewall-port.ps1 +18 -4
- package/sandbox/scripts/set-machine-environment.ps1 +30 -15
- package/sandbox/templates/fivem/README.txt +6 -2
- package/sandbox/templates/fivem/cs/Client/Client.csproj +15 -0
- package/sandbox/templates/fivem/cs/Client/ClientMain.cs +20 -0
- package/sandbox/templates/fivem/cs/Server/Server.csproj +14 -0
- package/sandbox/templates/fivem/cs/Server/ServerMain.cs +20 -0
- package/sandbox/templates/fivem/cs/fxmanifest.lua +11 -0
- package/sandbox/templates/fivem/js/client.js +12 -0
- package/sandbox/templates/fivem/js/fxmanifest.lua +9 -0
- package/sandbox/templates/fivem/js/server.js +6 -0
- package/sandbox/templates/fivem/lua/client.lua +8 -0
- package/sandbox/templates/fivem/lua/fxmanifest.lua +10 -0
- package/sandbox/templates/fivem/lua/server.lua +6 -0
- package/sandbox/templates/fivem/server.cfg +37 -0
- package/sandbox/templates/fivem/ts/build.js +17 -0
- package/sandbox/templates/fivem/ts/fxmanifest.lua +9 -0
- package/sandbox/templates/fivem/ts/package.json +16 -0
- package/sandbox/templates/fivem/ts/src/client/client.ts +12 -0
- package/sandbox/templates/fivem/ts/src/client/tsconfig.json +13 -0
- package/sandbox/templates/fivem/ts/src/server/server.ts +6 -0
- package/sandbox/templates/fivem/ts/src/server/tsconfig.json +13 -0
- package/schemas/config.schema.json +56 -27
- package/schemas/sandbox-config.schema.json +37 -14
|
@@ -1,7 +1,21 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
|
-
import { type Page } from '../../kernel/index.js';
|
|
2
|
+
import { type Item, type Page, type Section } from '../../kernel/index.js';
|
|
3
3
|
/** Where GitHub makes a fine-grained token. */
|
|
4
4
|
export declare const NEW_TOKEN_URL = "https://github.com/settings/personal-access-tokens/new";
|
|
5
|
+
/** What a token for sandboxes needs (GitHub's names for the permissions), asked for in the pre-filled form. */
|
|
6
|
+
export declare const TOKEN_PERMISSIONS: Readonly<Record<string, 'read' | 'write'>>;
|
|
7
|
+
/**
|
|
8
|
+
* The link that opens GitHub's "new fine-grained token" form already filled in (name, description, days until it
|
|
9
|
+
* expires, permissions): docs.github.com, "Creating a fine-grained personal access token". Pure.
|
|
10
|
+
*/
|
|
11
|
+
export declare function newTokenUrl(o: {
|
|
12
|
+
readonly name: string;
|
|
13
|
+
readonly description?: string;
|
|
14
|
+
readonly days: number;
|
|
15
|
+
readonly permissions: Readonly<Record<string, 'read' | 'write'>>;
|
|
16
|
+
}): string;
|
|
17
|
+
/** The pre-filled link for this PC (the name says which PC the token is for). */
|
|
18
|
+
export declare function tokenUrlFor(host: string): string;
|
|
5
19
|
/** The steps to make a token for sandboxes (shown before asking for it). */
|
|
6
20
|
export declare const GITHUB_STEPS: readonly string[];
|
|
7
21
|
/** What everyone who shares a token must know: on every surface. */
|
|
@@ -23,6 +37,11 @@ export declare const GithubStatusSchema: z.ZodObject<{
|
|
|
23
37
|
classic: "classic";
|
|
24
38
|
}>>;
|
|
25
39
|
savedAt: z.ZodNullable<z.ZodString>;
|
|
40
|
+
login: z.ZodNullable<z.ZodString>;
|
|
41
|
+
expiresAt: z.ZodNullable<z.ZodString>;
|
|
42
|
+
repoCount: z.ZodNullable<z.ZodNumber>;
|
|
43
|
+
checkedAt: z.ZodNullable<z.ZodString>;
|
|
44
|
+
tokenUrl: z.ZodString;
|
|
26
45
|
}, z.core.$strip>;
|
|
27
46
|
export type GithubStatus = z.output<typeof GithubStatusSchema>;
|
|
28
47
|
export declare const githubStatus: import("../../kernel/define.js").QueryDef<z.ZodObject<{}, z.core.$strict>, z.ZodObject<{
|
|
@@ -42,6 +61,11 @@ export declare const githubStatus: import("../../kernel/define.js").QueryDef<z.Z
|
|
|
42
61
|
classic: "classic";
|
|
43
62
|
}>>;
|
|
44
63
|
savedAt: z.ZodNullable<z.ZodString>;
|
|
64
|
+
login: z.ZodNullable<z.ZodString>;
|
|
65
|
+
expiresAt: z.ZodNullable<z.ZodString>;
|
|
66
|
+
repoCount: z.ZodNullable<z.ZodNumber>;
|
|
67
|
+
checkedAt: z.ZodNullable<z.ZodString>;
|
|
68
|
+
tokenUrl: z.ZodString;
|
|
45
69
|
}, z.core.$strip>, "github.status">;
|
|
46
70
|
export declare const githubLogin: import("../../kernel/define.js").OperationDef<z.ZodObject<{}, z.core.$strict>, z.ZodObject<{
|
|
47
71
|
message: z.ZodString;
|
|
@@ -56,8 +80,20 @@ export declare function githubTokenRowOf(s: GithubStatus): {
|
|
|
56
80
|
hint: string;
|
|
57
81
|
description: string;
|
|
58
82
|
};
|
|
59
|
-
/**
|
|
60
|
-
export declare
|
|
83
|
+
/** A token that expires within this many days is flagged. */
|
|
84
|
+
export declare const EXPIRY_WARN_DAYS = 14;
|
|
85
|
+
/** How the expiry reads: "Expires 3 Feb 2027 (in 12 days)", "Expired 3 Feb 2027", and its tone. */
|
|
86
|
+
export declare function expiryOf(expiresAt: string | null, now?: number): {
|
|
87
|
+
readonly text: string;
|
|
88
|
+
readonly tone: 'ok' | 'warn' | 'danger';
|
|
89
|
+
readonly days: number;
|
|
90
|
+
} | null;
|
|
91
|
+
/** The GitHub card (the "thing you connect" pattern): used by the GitHub page and the Accounts page. */
|
|
92
|
+
export declare function githubItem(s: GithubStatus, now?: number): Item;
|
|
93
|
+
/** The GitHub section (the card, the git-access fact, the warnings and the link that opens GitHub's form). */
|
|
94
|
+
export declare function githubSection(s: GithubStatus, now?: number): Section;
|
|
95
|
+
/** The status page: the card, the git access it needs, the warnings and how to make a new token. */
|
|
96
|
+
export declare function githubPage(s: GithubStatus, now?: number): Page;
|
|
61
97
|
export declare const githubView: import("../../kernel/define.js").ViewDef<{
|
|
62
98
|
status: import("../../kernel/define.js").QueryDef<z.ZodObject<{}, z.core.$strict>, z.ZodObject<{
|
|
63
99
|
shareToken: z.ZodBoolean;
|
|
@@ -76,5 +112,10 @@ export declare const githubView: import("../../kernel/define.js").ViewDef<{
|
|
|
76
112
|
classic: "classic";
|
|
77
113
|
}>>;
|
|
78
114
|
savedAt: z.ZodNullable<z.ZodString>;
|
|
115
|
+
login: z.ZodNullable<z.ZodString>;
|
|
116
|
+
expiresAt: z.ZodNullable<z.ZodString>;
|
|
117
|
+
repoCount: z.ZodNullable<z.ZodNumber>;
|
|
118
|
+
checkedAt: z.ZodNullable<z.ZodString>;
|
|
119
|
+
tokenUrl: z.ZodString;
|
|
79
120
|
}, z.core.$strip>, "github.status">;
|
|
80
121
|
}, Record<string, never>, "github">;
|
|
@@ -2,12 +2,44 @@
|
|
|
2
2
|
// and saving or deleting it. Pure: schemas, labels and the view; github.run.ts does the work. The token itself is never
|
|
3
3
|
// an input or an output.
|
|
4
4
|
import { z } from 'zod';
|
|
5
|
-
import { action, defineOperation, defineQuery, defineView, } from '../../kernel/index.js';
|
|
5
|
+
import { action, defineOperation, defineQuery, defineView, link, plural, } from '../../kernel/index.js';
|
|
6
|
+
import { setSetting } from '../settings/settings.def.js';
|
|
6
7
|
/** Where GitHub makes a fine-grained token. */
|
|
7
8
|
export const NEW_TOKEN_URL = 'https://github.com/settings/personal-access-tokens/new';
|
|
9
|
+
/** What a token for sandboxes needs (GitHub's names for the permissions), asked for in the pre-filled form. */
|
|
10
|
+
export const TOKEN_PERMISSIONS = {
|
|
11
|
+
contents: 'write',
|
|
12
|
+
pull_requests: 'write',
|
|
13
|
+
metadata: 'read',
|
|
14
|
+
workflows: 'write',
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* The link that opens GitHub's "new fine-grained token" form already filled in (name, description, days until it
|
|
18
|
+
* expires, permissions): docs.github.com, "Creating a fine-grained personal access token". Pure.
|
|
19
|
+
*/
|
|
20
|
+
export function newTokenUrl(o) {
|
|
21
|
+
const query = new URLSearchParams();
|
|
22
|
+
query.set('name', o.name.slice(0, 40));
|
|
23
|
+
if (o.description)
|
|
24
|
+
query.set('description', o.description.slice(0, 1024));
|
|
25
|
+
query.set('expires_in', String(Math.max(1, Math.min(366, Math.round(o.days)))));
|
|
26
|
+
for (const [permission, level] of Object.entries(o.permissions))
|
|
27
|
+
query.set(permission, level);
|
|
28
|
+
// GitHub reads %20 as well as +; spaces are written %20 so the link reads the same everywhere.
|
|
29
|
+
return NEW_TOKEN_URL + '?' + query.toString().replace(/\+/g, '%20');
|
|
30
|
+
}
|
|
31
|
+
/** The pre-filled link for this PC (the name says which PC the token is for). */
|
|
32
|
+
export function tokenUrlFor(host) {
|
|
33
|
+
return newTokenUrl({
|
|
34
|
+
name: 'Windows Sandbox ' + host,
|
|
35
|
+
description: 'For the agents in my Windows Sandbox. Limit it to the repositories they need.',
|
|
36
|
+
days: 90,
|
|
37
|
+
permissions: TOKEN_PERMISSIONS,
|
|
38
|
+
});
|
|
39
|
+
}
|
|
8
40
|
/** The steps to make a token for sandboxes (shown before asking for it). */
|
|
9
41
|
export const GITHUB_STEPS = [
|
|
10
|
-
'
|
|
42
|
+
'Make a fine-grained personal access token (the "Make a new token" button opens GitHub with the form filled in).',
|
|
11
43
|
'Under "Repository access" choose "Only select repositories" and pick only the ones the agent should reach.',
|
|
12
44
|
'Give only the permissions it needs, for example Contents (read and write), Pull requests (read and write) and Actions (read).',
|
|
13
45
|
'Set an expiry date, then generate the token and copy it.',
|
|
@@ -26,6 +58,11 @@ export const GithubStatusSchema = z.object({
|
|
|
26
58
|
token: TokenStateSchema,
|
|
27
59
|
kind: z.enum(['fine-grained', 'classic']).nullable().describe('What kind of token is saved (never the token)'),
|
|
28
60
|
savedAt: z.string().nullable().describe('When the token was saved (the date and time, never the token)'),
|
|
61
|
+
login: z.string().nullable().describe('The GitHub user the token belongs to, as GitHub said when it was saved'),
|
|
62
|
+
expiresAt: z.string().nullable().describe('When the token expires (ISO time), when GitHub said'),
|
|
63
|
+
repoCount: z.number().nullable().describe('How many repositories it reaches (at most 100 are counted)'),
|
|
64
|
+
checkedAt: z.string().nullable().describe('When GitHub was asked about it'),
|
|
65
|
+
tokenUrl: z.string().describe("GitHub's new-token form for this PC, filled in"),
|
|
29
66
|
});
|
|
30
67
|
export const githubStatus = defineQuery({
|
|
31
68
|
id: 'github.status',
|
|
@@ -57,20 +94,6 @@ export const githubLogout = defineOperation({
|
|
|
57
94
|
text: (o) => o.message,
|
|
58
95
|
cli: { name: 'github', action: 'logout' },
|
|
59
96
|
});
|
|
60
|
-
const TOKEN_TEXT = {
|
|
61
|
-
none: 'not saved',
|
|
62
|
-
saved: 'saved (encrypted)',
|
|
63
|
-
unreadable: 'cannot be read',
|
|
64
|
-
};
|
|
65
|
-
const TOKEN_TONE = {
|
|
66
|
-
none: 'warn',
|
|
67
|
-
saved: 'ok',
|
|
68
|
-
unreadable: 'danger',
|
|
69
|
-
};
|
|
70
|
-
const KIND_TEXT = {
|
|
71
|
-
'fine-grained': 'fine-grained',
|
|
72
|
-
classic: 'classic (reaches every repository you can: a fine-grained token is safer)',
|
|
73
|
-
};
|
|
74
97
|
/** The Settings row of the menu (label, hint, description), from the status. Pure. */
|
|
75
98
|
export function githubTokenRowOf(s) {
|
|
76
99
|
return {
|
|
@@ -80,63 +103,122 @@ export function githubTokenRowOf(s) {
|
|
|
80
103
|
GITHUB_WARNINGS.join(' '),
|
|
81
104
|
};
|
|
82
105
|
}
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
106
|
+
const MONTHS = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
|
|
107
|
+
const DAY_MS = 86_400_000;
|
|
108
|
+
/** A token that expires within this many days is flagged. */
|
|
109
|
+
export const EXPIRY_WARN_DAYS = 14;
|
|
110
|
+
/** "3 Feb 2027". */
|
|
111
|
+
function dateText(iso) {
|
|
112
|
+
const d = new Date(iso);
|
|
113
|
+
return d.getUTCDate() + ' ' + MONTHS[d.getUTCMonth()] + ' ' + d.getUTCFullYear();
|
|
114
|
+
}
|
|
115
|
+
/** How the expiry reads: "Expires 3 Feb 2027 (in 12 days)", "Expired 3 Feb 2027", and its tone. */
|
|
116
|
+
export function expiryOf(expiresAt, now = Date.now()) {
|
|
117
|
+
if (!expiresAt || Number.isNaN(Date.parse(expiresAt)))
|
|
118
|
+
return null;
|
|
119
|
+
const left = Date.parse(expiresAt) - now;
|
|
120
|
+
const days = Math.ceil(left / DAY_MS);
|
|
121
|
+
if (left <= 0)
|
|
122
|
+
return { text: 'Expired ' + dateText(expiresAt), tone: 'danger', days };
|
|
123
|
+
return {
|
|
124
|
+
text: 'Expires ' + dateText(expiresAt) + ' (' + (days <= 1 ? 'today or tomorrow' : 'in ' + days + ' days') + ')',
|
|
125
|
+
tone: days < EXPIRY_WARN_DAYS ? 'warn' : 'ok',
|
|
126
|
+
days,
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
/** The state badge of a GitHub card (the B5 words), then "shared". */
|
|
130
|
+
function badgesOf(s, now) {
|
|
131
|
+
const expiry = s.token === 'saved' ? expiryOf(s.expiresAt, now) : null;
|
|
132
|
+
const state = s.token === 'unreadable'
|
|
133
|
+
? { text: "can't be read", tone: 'danger' }
|
|
134
|
+
: s.token === 'none'
|
|
135
|
+
? { text: 'not saved', tone: 'muted' }
|
|
136
|
+
: expiry?.tone === 'danger'
|
|
137
|
+
? { text: 'expired', tone: 'danger' }
|
|
138
|
+
: expiry?.tone === 'warn'
|
|
139
|
+
? { text: 'expires soon', tone: 'warn' }
|
|
140
|
+
: { text: 'saved', tone: 'ok' };
|
|
141
|
+
return [state, ...(s.shareToken && s.token !== 'none' ? [{ text: 'shared', tone: 'accent' }] : [])];
|
|
142
|
+
}
|
|
143
|
+
/** The GitHub card (the "thing you connect" pattern): used by the GitHub page and the Accounts page. */
|
|
144
|
+
export function githubItem(s, now = Date.now()) {
|
|
145
|
+
const expiry = s.token === 'saved' ? expiryOf(s.expiresAt, now) : null;
|
|
146
|
+
const badges = badgesOf(s, now);
|
|
147
|
+
const who = s.login && s.token === 'saved'
|
|
148
|
+
? 'Signed in as ' +
|
|
149
|
+
s.login +
|
|
150
|
+
(s.repoCount !== null
|
|
151
|
+
? ', reaches ' + (s.repoCount >= 100 ? '100 or more' : plural(s.repoCount, 'repository', 'repositories'))
|
|
152
|
+
: '')
|
|
153
|
+
: undefined;
|
|
154
|
+
const details = [
|
|
155
|
+
...(who ? [who] : []),
|
|
156
|
+
...(expiry ? [expiry.text] : []),
|
|
157
|
+
...(s.token === 'unreadable' ? ['Only the Windows user that saved it can read it.'] : []),
|
|
158
|
+
...(s.kind === 'classic' ? ['A classic token reaches every repository you can: a fine-grained one is safer.'] : []),
|
|
159
|
+
].slice(0, 2);
|
|
160
|
+
const signIn = action(githubLogin, {}, { key: 'g', verb: 'sign in', label: s.token === 'none' ? 'Sign in…' : 'Sign in again…' });
|
|
161
|
+
const share = action(setSetting, { scope: 'user', key: 'github.shareToken', value: !s.shareToken }, {
|
|
162
|
+
key: 't',
|
|
163
|
+
verb: s.shareToken ? 'stop sharing' : 'share',
|
|
164
|
+
label: s.shareToken ? 'Stop sharing' : 'Share with sandboxes',
|
|
165
|
+
importance: 1,
|
|
166
|
+
});
|
|
167
|
+
return {
|
|
168
|
+
id: 'github',
|
|
169
|
+
label: 'GitHub',
|
|
170
|
+
hint: badges[0].text,
|
|
171
|
+
tone: badges[0].tone,
|
|
172
|
+
badges,
|
|
173
|
+
description: 'A token that lets agents in a sandbox use gh and git over https.',
|
|
174
|
+
...(details.length ? { details } : {}),
|
|
175
|
+
primary: s.token === 'saved' ? share : signIn,
|
|
176
|
+
actions: s.token === 'none'
|
|
177
|
+
? []
|
|
178
|
+
: [
|
|
179
|
+
...(s.token === 'saved' ? [signIn] : []),
|
|
180
|
+
action(githubLogout, {}, { key: 'x', verb: 'remove', label: 'Remove…' }),
|
|
181
|
+
],
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
/** The GitHub section (the card, the git-access fact, the warnings and the link that opens GitHub's form). */
|
|
185
|
+
export function githubSection(s, now = Date.now()) {
|
|
186
|
+
const facts = s.gitAccess === 'full'
|
|
187
|
+
? []
|
|
188
|
+
: [
|
|
189
|
+
{
|
|
97
190
|
id: 'gitAccess',
|
|
98
191
|
label: 'Git access',
|
|
99
192
|
value: s.gitAccess + ' (the token is only handed over with "full")',
|
|
100
193
|
tone: 'warn',
|
|
194
|
+
description: 'Change it in Settings (provisioning.git.access).',
|
|
101
195
|
},
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
tone: 'muted',
|
|
123
|
-
},
|
|
124
|
-
]
|
|
125
|
-
: []),
|
|
126
|
-
...GITHUB_WARNINGS.map((text) => ({ text, tone: 'muted' })),
|
|
127
|
-
];
|
|
128
|
-
const actions = [
|
|
129
|
-
action(githubLogin, {}, { key: 'g', verb: 'save token' }),
|
|
130
|
-
...(s.token !== 'none' ? [action(githubLogout, {}, { key: 'x', verb: 'delete token' })] : []),
|
|
131
|
-
];
|
|
132
|
-
const section = { id: 'github', facts, notes, actions };
|
|
133
|
-
return { title: 'GitHub', sections: [section] };
|
|
196
|
+
];
|
|
197
|
+
const notes = GITHUB_WARNINGS.map((text) => ({ text, tone: 'muted' }));
|
|
198
|
+
const make = link({ kind: 'url', href: s.tokenUrl }, 'Make a new token…', {
|
|
199
|
+
key: 'n',
|
|
200
|
+
verb: 'new token',
|
|
201
|
+
importance: 2,
|
|
202
|
+
description: "Opens GitHub's form with a name, an expiry and the permissions already filled in.",
|
|
203
|
+
});
|
|
204
|
+
return {
|
|
205
|
+
id: 'github',
|
|
206
|
+
title: 'GitHub',
|
|
207
|
+
facts,
|
|
208
|
+
items: [githubItem(s, now)],
|
|
209
|
+
notes,
|
|
210
|
+
actions: [make],
|
|
211
|
+
};
|
|
212
|
+
}
|
|
213
|
+
/** The status page: the card, the git access it needs, the warnings and how to make a new token. */
|
|
214
|
+
export function githubPage(s, now = Date.now()) {
|
|
215
|
+
return { title: 'GitHub', sections: [githubSection(s, now)] };
|
|
134
216
|
}
|
|
135
217
|
export const githubView = defineView({
|
|
136
218
|
id: 'github',
|
|
137
219
|
title: 'GitHub',
|
|
138
220
|
summary: 'A GitHub token for sandboxes: whether they get it, and the saved token.',
|
|
139
221
|
queries: { status: githubStatus },
|
|
140
|
-
operations: [githubLogin, githubLogout],
|
|
222
|
+
operations: [githubLogin, githubLogout, setSetting],
|
|
141
223
|
build: ({ status }) => githubPage(status),
|
|
142
224
|
});
|
|
@@ -1,7 +1,9 @@
|
|
|
1
|
-
import { GithubToken } from '../../../host/github/index.js';
|
|
1
|
+
import { GithubToken, type GithubVerdict } from '../../../host/github/index.js';
|
|
2
2
|
import { type OperationIO } from '../../kernel/index.js';
|
|
3
|
+
/** Asks GitHub about a token just typed (the self-test passes its own). */
|
|
4
|
+
export type VerifyToken = (token: string) => Promise<GithubVerdict>;
|
|
3
5
|
/** Asks for the token (one hidden question) and saves it. The validator answers with fixed texts only. */
|
|
4
|
-
export declare function saveGithubTokenFlow(io: OperationIO, store: GithubToken): Promise<{
|
|
6
|
+
export declare function saveGithubTokenFlow(io: OperationIO, store: GithubToken, verify?: VerifyToken): Promise<{
|
|
5
7
|
message: string;
|
|
6
8
|
}>;
|
|
7
9
|
/** Deletes the saved token after asking (the CLI's typed logout is the answer). */
|
|
@@ -26,6 +28,11 @@ export declare const githubStatusRun: import("../../kernel/define.js").Implement
|
|
|
26
28
|
classic: "classic";
|
|
27
29
|
}>>;
|
|
28
30
|
savedAt: import("zod").ZodNullable<import("zod").ZodString>;
|
|
31
|
+
login: import("zod").ZodNullable<import("zod").ZodString>;
|
|
32
|
+
expiresAt: import("zod").ZodNullable<import("zod").ZodString>;
|
|
33
|
+
repoCount: import("zod").ZodNullable<import("zod").ZodNumber>;
|
|
34
|
+
checkedAt: import("zod").ZodNullable<import("zod").ZodString>;
|
|
35
|
+
tokenUrl: import("zod").ZodString;
|
|
29
36
|
}, import("zod/v4/core").$strip>, "github.status">, import("../../../cli/commands/context.js").Context>;
|
|
30
37
|
export declare const githubLoginRun: import("../../kernel/define.js").Implementation<import("../../kernel/define.js").OperationDef<import("zod").ZodObject<{}, import("zod/v4/core").$strict>, import("zod").ZodObject<{
|
|
31
38
|
message: import("zod").ZodString;
|
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
// The GitHub feature's work: its status, saving the token through io.secret (kept only for the save, never returned,
|
|
2
2
|
// logged or shown), and deleting it after a confirmation. The flows take the store, so the self-test runs them with a
|
|
3
3
|
// store of its own.
|
|
4
|
+
import os from 'node:os';
|
|
4
5
|
import { requireOnPc } from '../../../cli/commands/context.js';
|
|
5
|
-
import {
|
|
6
|
+
import { fail } from '../../../core/util/index.js';
|
|
7
|
+
import { GithubToken, verifyGithubToken } from '../../../host/github/index.js';
|
|
6
8
|
import { githubTokenProblem } from '../../../shared/github/index.js';
|
|
7
9
|
import { implement } from '../../context.js';
|
|
8
10
|
import { cancelled } from '../../kernel/index.js';
|
|
9
|
-
import { GITHUB_STEPS, GITHUB_WARNINGS, githubLogin, githubLogout, githubStatus } from './github.def.js';
|
|
11
|
+
import { GITHUB_STEPS, GITHUB_WARNINGS, expiryOf, githubLogin, githubLogout, githubStatus, tokenUrlFor, } from './github.def.js';
|
|
10
12
|
/** Asks for the token (one hidden question) and saves it. The validator answers with fixed texts only. */
|
|
11
|
-
export async function saveGithubTokenFlow(io, store) {
|
|
13
|
+
export async function saveGithubTokenFlow(io, store, verify = verifyGithubToken) {
|
|
12
14
|
io.log('Make a GitHub token only for sandboxes:');
|
|
13
15
|
GITHUB_STEPS.forEach((s, i) => io.log(' ' + (i + 1) + '. ' + s));
|
|
14
16
|
io.log('What you type is not shown. It is kept encrypted for your Windows user and never printed.', 'muted');
|
|
@@ -18,11 +20,42 @@ export async function saveGithubTokenFlow(io, store) {
|
|
|
18
20
|
});
|
|
19
21
|
if (token === undefined)
|
|
20
22
|
cancelled();
|
|
21
|
-
|
|
23
|
+
// GitHub says whose token it is and when it ends; one it refuses is not saved. No answer (offline) is not a refusal.
|
|
24
|
+
io.progress('Asking GitHub about the token');
|
|
25
|
+
const verdict = await verify(token.trim());
|
|
26
|
+
if (verdict.kind === 'refused')
|
|
27
|
+
fail('GitHub refused this token.', 'Copy it again from GitHub, and check that it has not expired or been revoked.');
|
|
28
|
+
if (verdict.kind === 'unreachable')
|
|
29
|
+
io.log('The token could not be checked (' + verdict.reason + ') and is saved without a check.', 'warn');
|
|
30
|
+
const check = verdict.kind === 'ok'
|
|
31
|
+
? {
|
|
32
|
+
login: verdict.check.login,
|
|
33
|
+
expiresAt: verdict.check.expiresAt,
|
|
34
|
+
repoCount: verdict.check.repos.count,
|
|
35
|
+
checkedAt: new Date().toISOString(),
|
|
36
|
+
}
|
|
37
|
+
: undefined;
|
|
38
|
+
const kind = store.save(token.trim(), check);
|
|
39
|
+
if (verdict.kind === 'ok') {
|
|
40
|
+
const { repos } = verdict.check;
|
|
41
|
+
io.log('GitHub says this is ' +
|
|
42
|
+
verdict.check.login +
|
|
43
|
+
'. It reaches ' +
|
|
44
|
+
repos.count +
|
|
45
|
+
(repos.count >= 100 ? ' or more' : '') +
|
|
46
|
+
' repositories' +
|
|
47
|
+
(repos.sample.length
|
|
48
|
+
? ' (' + repos.sample.join(', ') + (repos.count > repos.sample.length ? ', ...' : '') + ')'
|
|
49
|
+
: '') +
|
|
50
|
+
'.', 'ok');
|
|
51
|
+
const expiry = expiryOf(verdict.check.expiresAt);
|
|
52
|
+
if (expiry)
|
|
53
|
+
io.log(expiry.text + '.', expiry.tone === 'ok' ? 'muted' : 'warn');
|
|
54
|
+
}
|
|
22
55
|
GITHUB_WARNINGS.forEach((w) => io.log(w, 'warn'));
|
|
23
56
|
if (kind === 'classic')
|
|
24
57
|
io.log('This is a classic token: it reaches every repository you can. A fine-grained one is safer.', 'warn');
|
|
25
|
-
return { message: 'Saved. Sandboxes get it once you turn
|
|
58
|
+
return { message: 'Saved. Sandboxes get it once you turn on Share the token with sandboxes.' };
|
|
26
59
|
}
|
|
27
60
|
/** Deletes the saved token after asking (the CLI's typed logout is the answer). */
|
|
28
61
|
export async function deleteGithubTokenFlow(io, store) {
|
|
@@ -47,6 +80,11 @@ export const githubStatusRun = implement(githubStatus, async (ctx) => {
|
|
|
47
80
|
token,
|
|
48
81
|
kind: token === 'none' ? null : store.kind(),
|
|
49
82
|
savedAt: token === 'none' ? null : store.savedAt(),
|
|
83
|
+
login: token === 'none' ? null : (store.check()?.login ?? null),
|
|
84
|
+
expiresAt: token === 'none' ? null : (store.check()?.expiresAt ?? null),
|
|
85
|
+
repoCount: token === 'none' ? null : (store.check()?.repoCount ?? null),
|
|
86
|
+
checkedAt: token === 'none' ? null : (store.check()?.checkedAt ?? null),
|
|
87
|
+
tokenUrl: tokenUrlFor(os.hostname()),
|
|
50
88
|
};
|
|
51
89
|
});
|
|
52
90
|
export const githubLoginRun = implement(githubLogin, async (ctx, _input, io) => {
|
|
@@ -96,7 +96,7 @@ export function resultLines(r) {
|
|
|
96
96
|
if (r.means)
|
|
97
97
|
out.push({ text: ' What it means: ' + r.means });
|
|
98
98
|
if (r.fixable && r.plan)
|
|
99
|
-
out.push({ text: ' Fix:
|
|
99
|
+
out.push({ text: ' Fix: repair will ' + r.plan });
|
|
100
100
|
else if (r.fix)
|
|
101
101
|
out.push({ text: ' Fix: ' + r.fix });
|
|
102
102
|
const lines = r.lines ?? [];
|
|
@@ -277,7 +277,13 @@ export function healthPage(o) {
|
|
|
277
277
|
],
|
|
278
278
|
})),
|
|
279
279
|
notes: canEnable
|
|
280
|
-
? [
|
|
280
|
+
? [
|
|
281
|
+
{
|
|
282
|
+
text: 'Windows asks for administrator permission to turn this on, so do it at this PC from Maintenance > Health in the menu.',
|
|
283
|
+
tone: 'muted',
|
|
284
|
+
only: 'web',
|
|
285
|
+
},
|
|
286
|
+
]
|
|
281
287
|
: [],
|
|
282
288
|
});
|
|
283
289
|
}
|
|
@@ -92,14 +92,6 @@ export function logsPage(files, tail) {
|
|
|
92
92
|
return {
|
|
93
93
|
title: 'Logs',
|
|
94
94
|
sections: [{ id: 'files', items }, ...tailSection],
|
|
95
|
-
actions: [
|
|
96
|
-
// The web hides command links (it follows live instead); this one stays because `logs` is a hand-written command.
|
|
97
|
-
link({ kind: 'command', argv: ['logs', '--follow'] }, 'Follow the newest log', {
|
|
98
|
-
key: 'f',
|
|
99
|
-
verb: 'follow in the terminal',
|
|
100
|
-
importance: 2,
|
|
101
|
-
}),
|
|
102
|
-
],
|
|
103
95
|
empty: { title: 'No logs yet', text: 'Logs appear after the first start.', cliText: 'No sandbox logs yet.' },
|
|
104
96
|
};
|
|
105
97
|
}
|
|
@@ -151,7 +151,7 @@ export function projectsPage(o) {
|
|
|
151
151
|
{
|
|
152
152
|
id: 'roots',
|
|
153
153
|
label: 'Roots',
|
|
154
|
-
value: o.roots.length ? o.roots.join(', ') : 'none
|
|
154
|
+
value: o.roots.length ? o.roots.join(', ') : 'none',
|
|
155
155
|
},
|
|
156
156
|
],
|
|
157
157
|
actions: [
|
|
@@ -185,7 +185,7 @@ export function projectsPage(o) {
|
|
|
185
185
|
columnsOn: 'cli',
|
|
186
186
|
items: o.projects.map(projectItem),
|
|
187
187
|
notes: o.projects.length === 0
|
|
188
|
-
? [{ text: 'No projects yet: start
|
|
188
|
+
? [{ text: 'No projects yet: start an agent in a project folder.', tone: 'muted' }]
|
|
189
189
|
: [{ text: '* = this folder. Choose with: sandbox projects choose', tone: 'muted', only: 'cli' }],
|
|
190
190
|
};
|
|
191
191
|
return {
|
|
@@ -11,7 +11,7 @@ import { addProject, allProjects, chooseProjects, excludeProject, includeProject
|
|
|
11
11
|
const NEXT_START = 'This changes what is mapped from the next start.';
|
|
12
12
|
function runningNote() {
|
|
13
13
|
return isSandboxRunning()
|
|
14
|
-
? ' The running sandbox keeps what it has; start a project in it (
|
|
14
|
+
? ' The running sandbox keeps what it has; start a project in it (from its folder) and it joins without a restart when it can, or you are offered one.'
|
|
15
15
|
: '';
|
|
16
16
|
}
|
|
17
17
|
/** The folder given, or one picked from the known projects (or this folder) when it was left out. */
|
|
@@ -39,7 +39,7 @@ export const chooseProjectsRun = implement(chooseProjects, async (ctx, _input, i
|
|
|
39
39
|
const rows = service.rows().filter((r) => !r.root);
|
|
40
40
|
if (!rows.length)
|
|
41
41
|
return {
|
|
42
|
-
message: 'No projects to choose from yet (projects in a root are always mapped with it). Start
|
|
42
|
+
message: 'No projects to choose from yet (projects in a root are always mapped with it). Start an agent in a project folder first.',
|
|
43
43
|
};
|
|
44
44
|
const all = service.settings().all;
|
|
45
45
|
const picked = await io.checklist({
|
|
@@ -108,7 +108,7 @@ function includeOrExcludeText(service, action, dir, changed) {
|
|
|
108
108
|
? (action === 'exclude' ? 'Excluded ' : 'Included ') + path.resolve(dir) + '. ' + NEXT_START
|
|
109
109
|
: 'Nothing changed.') +
|
|
110
110
|
(action === 'include' && !service.settings().all
|
|
111
|
-
? ' Mapping all projects is off:
|
|
111
|
+
? ' Mapping all projects is off: turn it on in Projects to map them at every start.'
|
|
112
112
|
: '') +
|
|
113
113
|
(changed ? runningNote() : ''));
|
|
114
114
|
}
|
|
@@ -131,11 +131,11 @@ export const projectRootsRun = implement(projectRoots, async (ctx, input, io) =>
|
|
|
131
131
|
if (input.change === 'list') {
|
|
132
132
|
const list = service.settings().roots;
|
|
133
133
|
return {
|
|
134
|
-
message: list.length ? list.join('\n') : 'No project roots. Add one
|
|
134
|
+
message: list.length ? list.join('\n') : 'No project roots. Add one on the Projects page.',
|
|
135
135
|
};
|
|
136
136
|
}
|
|
137
137
|
if (!input.rootFolder)
|
|
138
|
-
fail('Which folder?', '
|
|
138
|
+
fail('Which folder?', 'Give the folder to ' + input.change + '.');
|
|
139
139
|
if (input.change === 'add') {
|
|
140
140
|
const { dir, added } = service.addRoot(input.rootFolder);
|
|
141
141
|
return {
|
|
@@ -191,7 +191,7 @@ function facts(o) {
|
|
|
191
191
|
}),
|
|
192
192
|
...(s.running
|
|
193
193
|
? [
|
|
194
|
-
fact('window', 'Window', s.headless ? 'hidden
|
|
194
|
+
fact('window', 'Window', s.headless ? 'hidden' : 'shown'),
|
|
195
195
|
fact('uptime', 'Uptime', uptime(s) ?? '-'),
|
|
196
196
|
// The session count is its own fact: the helper only says whether it answers.
|
|
197
197
|
fact('helper', 'Helper', s.daemon === '-' ? '-' : s.daemon.startsWith('pong') ? 'Responding' : s.daemon),
|
|
@@ -200,7 +200,7 @@ function facts(o) {
|
|
|
200
200
|
: []),
|
|
201
201
|
...(o.leftover ? [fact('leftover', 'Windows Sandbox', o.leftover.text, { tone: 'warn' })] : []),
|
|
202
202
|
...(o.lastEnd ? [fact('lastEnd', 'Last sandbox', o.lastEnd.text, { tone: 'warn' })] : []),
|
|
203
|
-
fact('account', 'Account', s.account ?? 'none selected
|
|
203
|
+
fact('account', 'Account', s.account ?? 'none selected'),
|
|
204
204
|
fact('sync', 'Background sync', s.syncWatcher ? 'on' : 'off'),
|
|
205
205
|
];
|
|
206
206
|
}
|
|
@@ -216,10 +216,11 @@ function projectsSection(o) {
|
|
|
216
216
|
id: 'projects',
|
|
217
217
|
title: 'Projects',
|
|
218
218
|
items: [...o.projects.map(projectItem), ...roots],
|
|
219
|
+
...(here ? {} : { actions: [link({ kind: 'view', view: 'agents' }, 'Start an agent here…', { verb: 'start' })] }),
|
|
219
220
|
notes: [
|
|
220
221
|
here
|
|
221
222
|
? { text: '* = the project of this folder', tone: 'muted' }
|
|
222
|
-
: { text: o.here.folder + ' is not in this sandbox
|
|
223
|
+
: { text: o.here.folder + ' is not in this sandbox.', tone: 'muted' },
|
|
223
224
|
],
|
|
224
225
|
};
|
|
225
226
|
}
|
|
@@ -254,6 +255,9 @@ export function sandboxPage(o) {
|
|
|
254
255
|
facts: facts(o),
|
|
255
256
|
// Only the window action that changes something: show a hidden window, hide a shown one.
|
|
256
257
|
actions: [
|
|
258
|
+
...(running && !o.sandbox.account
|
|
259
|
+
? [link({ kind: 'view', view: 'accounts' }, 'Choose an account…', { verb: 'choose', importance: 4 })]
|
|
260
|
+
: []),
|
|
257
261
|
...(o.leftover ? [action(cleanUpSandbox, {}, { key: 'c', verb: 'clean up', importance: 1 })] : []),
|
|
258
262
|
...(running
|
|
259
263
|
? [
|
|
@@ -12,9 +12,9 @@ export declare const SessionRowSchema: z.ZodObject<{
|
|
|
12
12
|
cwd: z.ZodString;
|
|
13
13
|
project: z.ZodOptional<z.ZodString>;
|
|
14
14
|
phase: z.ZodEnum<{
|
|
15
|
+
running: "running";
|
|
15
16
|
failed: "failed";
|
|
16
17
|
starting: "starting";
|
|
17
|
-
running: "running";
|
|
18
18
|
exited: "exited";
|
|
19
19
|
}>;
|
|
20
20
|
message: z.ZodString;
|
|
@@ -47,9 +47,9 @@ export declare const SessionsListSchema: z.ZodObject<{
|
|
|
47
47
|
cwd: z.ZodString;
|
|
48
48
|
project: z.ZodOptional<z.ZodString>;
|
|
49
49
|
phase: z.ZodEnum<{
|
|
50
|
+
running: "running";
|
|
50
51
|
failed: "failed";
|
|
51
52
|
starting: "starting";
|
|
52
|
-
running: "running";
|
|
53
53
|
exited: "exited";
|
|
54
54
|
}>;
|
|
55
55
|
message: z.ZodString;
|
|
@@ -89,9 +89,9 @@ export declare const listSessions: import("../../kernel/define.js").QueryDef<z.Z
|
|
|
89
89
|
cwd: z.ZodString;
|
|
90
90
|
project: z.ZodOptional<z.ZodString>;
|
|
91
91
|
phase: z.ZodEnum<{
|
|
92
|
+
running: "running";
|
|
92
93
|
failed: "failed";
|
|
93
94
|
starting: "starting";
|
|
94
|
-
running: "running";
|
|
95
95
|
exited: "exited";
|
|
96
96
|
}>;
|
|
97
97
|
message: z.ZodString;
|
|
@@ -155,9 +155,9 @@ export declare const sessionsView: import("../../kernel/define.js").ViewDef<{
|
|
|
155
155
|
cwd: z.ZodString;
|
|
156
156
|
project: z.ZodOptional<z.ZodString>;
|
|
157
157
|
phase: z.ZodEnum<{
|
|
158
|
+
running: "running";
|
|
158
159
|
failed: "failed";
|
|
159
160
|
starting: "starting";
|
|
160
|
-
running: "running";
|
|
161
161
|
exited: "exited";
|
|
162
162
|
}>;
|
|
163
163
|
message: z.ZodString;
|
|
@@ -221,11 +221,6 @@ export function sessionsPage(o) {
|
|
|
221
221
|
...(sessions.length
|
|
222
222
|
? [action(restartSessions, { all: false }, { key: 'r', verb: 'restart agents', importance: 1 })]
|
|
223
223
|
: []),
|
|
224
|
-
link({ kind: 'command', argv: ['resume'] }, 'Reopen last sessions', {
|
|
225
|
-
key: 'o',
|
|
226
|
-
verb: 'reopen last sessions',
|
|
227
|
-
importance: 2,
|
|
228
|
-
}),
|
|
229
224
|
],
|
|
230
225
|
empty: {
|
|
231
226
|
title: o.sandboxRunning ? 'No sessions' : 'No sandbox is running',
|
|
@@ -17,9 +17,9 @@ export declare const listSessionsRun: import("../../kernel/define.js").Implement
|
|
|
17
17
|
cwd: import("zod").ZodString;
|
|
18
18
|
project: import("zod").ZodOptional<import("zod").ZodString>;
|
|
19
19
|
phase: import("zod").ZodEnum<{
|
|
20
|
+
running: "running";
|
|
20
21
|
failed: "failed";
|
|
21
22
|
starting: "starting";
|
|
22
|
-
running: "running";
|
|
23
23
|
exited: "exited";
|
|
24
24
|
}>;
|
|
25
25
|
message: import("zod").ZodString;
|