windows-development-sandbox 1.17.3 → 1.18.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/config.example.json +97 -4
- package/dist/app/features/accounts/accounts.def.d.ts +116 -2
- package/dist/app/features/accounts/accounts.def.js +80 -12
- package/dist/app/features/accounts/accounts.run.d.ts +29 -0
- package/dist/app/features/accounts/accounts.run.js +36 -6
- package/dist/app/features/accounts/index.d.ts +2 -0
- package/dist/app/features/accounts/index.js +4 -1
- package/dist/app/features/accounts/services.def.d.ts +111 -0
- package/dist/app/features/accounts/services.def.js +187 -0
- package/dist/app/features/accounts/services.run.d.ts +65 -0
- package/dist/app/features/accounts/services.run.js +212 -0
- package/dist/app/features/defs.d.ts +112 -1
- package/dist/app/features/defs.js +5 -0
- package/dist/app/features/settings/categories.def.js +21 -4
- package/dist/app/registry.js +5 -1
- package/dist/bin/agent-sandbox.js +2 -2
- package/dist/bin/{chunk-QLGGAG3D.js → chunk-IIHL7W6B.js} +51 -16
- package/dist/bin/{chunk-XYUVIVJT.js → chunk-M4OM632I.js} +1 -1
- package/dist/bin/{chunk-REE3EMHD.js → chunk-MQIA7GNB.js} +3813 -1702
- 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/commands/launch/launch.js +30 -1
- package/dist/cli/manifest.d.ts +93 -65
- package/dist/cli/manifest.js +23 -5
- package/dist/cli/menu/pages/accounts-page.js +31 -16
- package/dist/cli/services/accounts-service.d.ts +14 -4
- package/dist/cli/services/accounts-service.js +19 -6
- package/dist/cli/services/data-collect.js +26 -1
- package/dist/core/config/defaults.js +47 -4
- package/dist/core/detect/toolchains.d.ts +15 -1
- package/dist/core/detect/toolchains.js +45 -12
- package/dist/core/local-config/overrides.js +6 -0
- package/dist/core/schema/accounts.d.ts +27 -0
- package/dist/core/schema/accounts.js +32 -0
- package/dist/core/schema/config.d.ts +239 -0
- package/dist/core/schema/config.js +6 -0
- package/dist/core/schema/pc-installs.d.ts +7 -0
- package/dist/core/schema/pc-installs.js +17 -0
- package/dist/core/schema/toolchains.d.ts +61 -0
- package/dist/core/schema/toolchains.js +106 -0
- package/dist/core/types.d.ts +18 -0
- package/dist/guest/accounts/adapter.d.ts +25 -0
- package/dist/guest/accounts/adapter.js +21 -0
- package/dist/guest/accounts/adapters.d.ts +5 -0
- package/dist/guest/accounts/adapters.js +18 -0
- package/dist/guest/accounts/apply.d.ts +41 -0
- package/dist/guest/accounts/apply.js +47 -0
- package/dist/guest/accounts/kinds/appstore.d.ts +2 -0
- package/dist/guest/accounts/kinds/appstore.js +7 -0
- package/dist/guest/accounts/kinds/cfx.d.ts +2 -0
- package/dist/guest/accounts/kinds/cfx.js +7 -0
- package/dist/guest/accounts/kinds/epic.d.ts +2 -0
- package/dist/guest/accounts/kinds/epic.js +26 -0
- package/dist/guest/accounts/kinds/expo.d.ts +2 -0
- package/dist/guest/accounts/kinds/expo.js +7 -0
- package/dist/guest/accounts/kinds/keystore.d.ts +2 -0
- package/dist/guest/accounts/kinds/keystore.js +7 -0
- package/dist/guest/accounts/kinds/play.d.ts +2 -0
- package/dist/guest/accounts/kinds/play.js +7 -0
- package/dist/guest/accounts/kinds/steam.d.ts +4 -0
- package/dist/guest/accounts/kinds/steam.js +17 -0
- package/dist/guest/accounts/kinds/unity.d.ts +2 -0
- package/dist/guest/accounts/kinds/unity.js +7 -0
- package/dist/guest/accounts/watch.d.ts +28 -0
- package/dist/guest/accounts/watch.js +78 -0
- package/dist/guest/apps/resolvers-gamedev.d.ts +2 -0
- package/dist/guest/apps/resolvers-gamedev.js +1 -0
- package/dist/guest/apps/resolvers-mobile.d.ts +2 -0
- package/dist/guest/apps/resolvers-mobile.js +1 -0
- package/dist/guest/apps/resolvers.js +4 -0
- package/dist/guest/boot/boot.d.ts +5 -0
- package/dist/guest/boot/boot.js +35 -1
- package/dist/guest/daemon/accounts.d.ts +3 -0
- package/dist/guest/daemon/accounts.js +25 -0
- package/dist/guest/daemon/daemon.js +2 -0
- package/dist/guest/daemon/idle-shutdown.js +3 -1
- package/dist/guest/daemon/sessions.js +2 -0
- package/dist/guest/devtools/android.d.ts +2 -0
- package/dist/guest/devtools/android.js +7 -0
- package/dist/guest/devtools/devtool.d.ts +9 -0
- package/dist/guest/devtools/devtool.js +5 -0
- package/dist/guest/devtools/fivem.d.ts +2 -0
- package/dist/guest/devtools/fivem.js +7 -0
- package/dist/guest/devtools/registry.d.ts +6 -0
- package/dist/guest/devtools/registry.js +12 -0
- package/dist/guest/devtools/steam.d.ts +2 -0
- package/dist/guest/devtools/steam.js +228 -0
- package/dist/guest/devtools/unity.d.ts +2 -0
- package/dist/guest/devtools/unity.js +7 -0
- package/dist/guest/entries/daemon.js +2 -0
- package/dist/guest/entries/tool.d.ts +1 -0
- package/dist/guest/entries/tool.js +17 -0
- package/dist/guest/toolchains/engines/godot.d.ts +4 -0
- package/dist/guest/toolchains/engines/godot.js +4 -0
- package/dist/guest/toolchains/engines/unity-release.d.ts +15 -0
- package/dist/guest/toolchains/engines/unity-release.js +6 -0
- package/dist/guest/toolchains/engines/unity.d.ts +4 -0
- package/dist/guest/toolchains/engines/unity.js +4 -0
- package/dist/guest/toolchains/engines/unreal-engines.d.ts +4 -0
- package/dist/guest/toolchains/engines/unreal-engines.js +4 -0
- package/dist/guest/toolchains/fivem/artifacts.d.ts +6 -0
- package/dist/guest/toolchains/fivem/artifacts.js +7 -0
- package/dist/guest/toolchains/fivem/fivem.d.ts +4 -0
- package/dist/guest/toolchains/fivem/fivem.js +4 -0
- package/dist/guest/toolchains/installers.d.ts +12 -0
- package/dist/guest/toolchains/installers.js +39 -0
- package/dist/guest/toolchains/languages/java.js +1 -1
- package/dist/guest/toolchains/languages/kotlin.d.ts +3 -0
- package/dist/guest/toolchains/languages/kotlin.js +6 -0
- package/dist/guest/toolchains/mobile/android-repo.d.ts +11 -0
- package/dist/guest/toolchains/mobile/android-repo.js +10 -0
- package/dist/guest/toolchains/mobile/android.d.ts +17 -0
- package/dist/guest/toolchains/mobile/android.js +16 -0
- package/dist/guest/toolchains/mobile/dart.d.ts +4 -0
- package/dist/guest/toolchains/mobile/dart.js +4 -0
- package/dist/guest/toolchains/mobile/flutter.d.ts +4 -0
- package/dist/guest/toolchains/mobile/flutter.js +4 -0
- package/dist/guest/toolchains/mobile/react-native.d.ts +4 -0
- package/dist/guest/toolchains/mobile/react-native.js +4 -0
- package/dist/guest/toolchains/native/unreal.d.ts +3 -7
- package/dist/guest/toolchains/native/unreal.js +16 -167
- package/dist/guest/toolchains/native/visual-studio.d.ts +15 -0
- package/dist/guest/toolchains/native/visual-studio.js +159 -0
- package/dist/guest/toolchains/native/vs-request.d.ts +19 -0
- package/dist/guest/toolchains/native/vs-request.js +46 -0
- package/dist/guest/toolchains/not-yet.d.ts +2 -0
- package/dist/guest/toolchains/not-yet.js +6 -0
- package/dist/guest/toolchains/persisted.d.ts +48 -0
- package/dist/guest/toolchains/persisted.js +159 -0
- package/dist/guest/toolchains/plan.js +80 -4
- package/dist/guest/toolchains/steam/apps.d.ts +27 -0
- package/dist/guest/toolchains/steam/apps.js +112 -0
- package/dist/guest/toolchains/steam/client.d.ts +5 -0
- package/dist/guest/toolchains/steam/client.js +67 -0
- package/dist/guest/toolchains/steam/commands.d.ts +58 -0
- package/dist/guest/toolchains/steam/commands.js +155 -0
- package/dist/guest/toolchains/steam/steam.d.ts +4 -0
- package/dist/guest/toolchains/steam/steam.js +61 -0
- package/dist/guest/toolchains/steam/steamcmd-install.d.ts +29 -0
- package/dist/guest/toolchains/steam/steamcmd-install.js +177 -0
- package/dist/guest/toolchains/steam/steamcmd.d.ts +6 -0
- package/dist/guest/toolchains/steam/steamcmd.js +23 -0
- package/dist/guest/toolchains/step.d.ts +10 -0
- package/dist/host/accounts/deliver.d.ts +26 -0
- package/dist/host/accounts/deliver.js +80 -0
- package/dist/host/accounts/handoff.d.ts +17 -0
- package/dist/host/accounts/handoff.js +110 -0
- package/dist/host/accounts/index.d.ts +6 -0
- package/dist/host/accounts/index.js +8 -0
- package/dist/host/accounts/kinds/appstore.d.ts +2 -0
- package/dist/host/accounts/kinds/appstore.js +10 -0
- package/dist/host/accounts/kinds/cfx.d.ts +2 -0
- package/dist/host/accounts/kinds/cfx.js +7 -0
- package/dist/host/accounts/kinds/epic.d.ts +2 -0
- package/dist/host/accounts/kinds/epic.js +15 -0
- package/dist/host/accounts/kinds/expo.d.ts +2 -0
- package/dist/host/accounts/kinds/expo.js +7 -0
- package/dist/host/accounts/kinds/keystore.d.ts +2 -0
- package/dist/host/accounts/kinds/keystore.js +7 -0
- package/dist/host/accounts/kinds/play.d.ts +2 -0
- package/dist/host/accounts/kinds/play.js +7 -0
- package/dist/host/accounts/kinds/steam.d.ts +6 -0
- package/dist/host/accounts/kinds/steam.js +31 -0
- package/dist/host/accounts/kinds/unity.d.ts +2 -0
- package/dist/host/accounts/kinds/unity.js +13 -0
- package/dist/host/accounts/leases.d.ts +40 -0
- package/dist/host/accounts/leases.js +62 -0
- package/dist/host/accounts/source.d.ts +21 -0
- package/dist/host/accounts/source.js +15 -0
- package/dist/host/accounts/sources.d.ts +5 -0
- package/dist/host/accounts/sources.js +18 -0
- package/dist/host/accounts/store.d.ts +23 -0
- package/dist/host/accounts/store.js +74 -0
- package/dist/host/audit/log.d.ts +1 -1
- package/dist/host/launch/generate.d.ts +2 -0
- package/dist/host/launch/generate.js +16 -1
- package/dist/host/launch/hints/android.d.ts +3 -0
- package/dist/host/launch/hints/android.js +3 -0
- package/dist/host/launch/hints/engines.d.ts +3 -0
- package/dist/host/launch/hints/engines.js +3 -0
- package/dist/host/launch/hints/fivem.d.ts +3 -0
- package/dist/host/launch/hints/fivem.js +3 -0
- package/dist/host/launch/hints/hint.d.ts +2 -0
- package/dist/host/launch/hints/hint.js +1 -0
- package/dist/host/launch/hints/index.d.ts +5 -0
- package/dist/host/launch/hints/index.js +29 -0
- package/dist/host/launch/hints/mobile.d.ts +3 -0
- package/dist/host/launch/hints/mobile.js +3 -0
- package/dist/host/launch/hints/steam.d.ts +7 -0
- package/dist/host/launch/hints/steam.js +59 -0
- package/dist/host/launch/index.d.ts +2 -2
- package/dist/host/launch/index.js +2 -2
- package/dist/host/launch/mappings.js +2 -0
- package/dist/host/launch/session-file.js +2 -0
- package/dist/host/launch/stage.js +10 -1
- package/dist/host/launch/toolchains.d.ts +7 -0
- package/dist/host/launch/toolchains.js +11 -0
- package/dist/host/pc-installs/discover.d.ts +19 -0
- package/dist/host/pc-installs/discover.js +59 -0
- package/dist/host/pc-installs/epic.d.ts +2 -0
- package/dist/host/pc-installs/epic.js +7 -0
- package/dist/host/pc-installs/index.d.ts +3 -0
- package/dist/host/pc-installs/index.js +2 -0
- package/dist/host/pc-installs/source.d.ts +9 -0
- package/dist/host/pc-installs/source.js +1 -0
- package/dist/host/pc-installs/steam.d.ts +16 -0
- package/dist/host/pc-installs/steam.js +143 -0
- package/dist/host/pc-installs/unity.d.ts +2 -0
- package/dist/host/pc-installs/unity.js +7 -0
- package/dist/host/pc-installs/unreal.d.ts +2 -0
- package/dist/host/pc-installs/unreal.js +7 -0
- package/dist/host/profile/accounts.d.ts +21 -6
- package/dist/host/profile/accounts.js +108 -28
- package/dist/host/profile/claude-login.d.ts +32 -2
- package/dist/host/profile/claude-login.js +101 -8
- package/dist/host/profile/index.d.ts +1 -1
- package/dist/host/profile/index.js +1 -1
- package/dist/host/secrets/launch-secrets.js +1 -0
- package/dist/runtime/agent.js +321 -9
- package/dist/runtime/daemon.js +1987 -604
- package/dist/runtime/db.js +334 -11
- package/dist/runtime/main.js +2519 -723
- package/dist/runtime/netproxy.js +321 -9
- package/dist/runtime/tool.js +28549 -0
- package/dist/runtime/view.js +321 -9
- package/dist/selftest/accounts.test.js +172 -1
- package/dist/selftest/agent-paths.test.js +1 -0
- package/dist/selftest/android.test.d.ts +2 -0
- package/dist/selftest/android.test.js +7 -0
- package/dist/selftest/app.test.js +1 -1
- package/dist/selftest/engines.test.d.ts +2 -0
- package/dist/selftest/engines.test.js +7 -0
- package/dist/selftest/fivem.test.d.ts +2 -0
- package/dist/selftest/fivem.test.js +7 -0
- package/dist/selftest/generate.test.js +1 -1
- package/dist/selftest/index.js +18 -0
- package/dist/selftest/menu-screens.js +1 -0
- package/dist/selftest/menu.test.js +2 -1
- package/dist/selftest/mobile.test.d.ts +2 -0
- package/dist/selftest/mobile.test.js +7 -0
- package/dist/selftest/pc-installs.test.d.ts +2 -0
- package/dist/selftest/pc-installs.test.js +111 -0
- package/dist/selftest/persisted-installs.test.d.ts +2 -0
- package/dist/selftest/persisted-installs.test.js +107 -0
- package/dist/selftest/projects.test.js +6 -4
- package/dist/selftest/service-accounts.test.d.ts +2 -0
- package/dist/selftest/service-accounts.test.js +320 -0
- package/dist/selftest/steam.test.d.ts +2 -0
- package/dist/selftest/steam.test.js +316 -0
- package/dist/selftest/storage-helper.test.js +31 -8
- package/dist/selftest/support/engine-golden.js +3 -0
- package/dist/selftest/support/fixtures.d.ts +87 -0
- package/dist/selftest/support/fixtures.js +4 -3
- package/dist/selftest/support/pc-memory.d.ts +2 -0
- package/dist/selftest/support/pc-memory.js +17 -0
- package/dist/selftest/support/web-preview.js +20 -1
- package/dist/selftest/unity.test.d.ts +2 -0
- package/dist/selftest/unity.test.js +7 -0
- package/dist/shared/accounts/fingerprint.d.ts +1 -0
- package/dist/shared/accounts/fingerprint.js +20 -0
- package/dist/shared/accounts/index.d.ts +5 -0
- package/dist/shared/accounts/index.js +7 -0
- package/dist/shared/accounts/kinds/epic.d.ts +10 -0
- package/dist/shared/accounts/kinds/epic.js +56 -0
- package/dist/shared/accounts/kinds/steam.d.ts +28 -0
- package/dist/shared/accounts/kinds/steam.js +99 -0
- package/dist/shared/accounts/kinds.d.ts +41 -0
- package/dist/shared/accounts/kinds.js +154 -0
- package/dist/shared/accounts/payloads.d.ts +151 -0
- package/dist/shared/accounts/payloads.js +128 -0
- package/dist/shared/apps/catalogue-gamedev.d.ts +2 -0
- package/dist/shared/apps/catalogue-gamedev.js +1 -0
- package/dist/shared/apps/catalogue-mobile.d.ts +2 -0
- package/dist/shared/apps/catalogue-mobile.js +1 -0
- package/dist/shared/apps/catalogue-modding.d.ts +2 -0
- package/dist/shared/apps/catalogue-modding.js +1 -0
- package/dist/shared/apps/catalogue.d.ts +1 -0
- package/dist/shared/apps/catalogue.js +6 -1
- package/dist/shared/channel/schema.d.ts +183 -0
- package/dist/shared/channel/secrets.d.ts +42 -0
- package/dist/shared/channel/secrets.js +3 -0
- package/dist/shared/download/downloader.d.ts +7 -0
- package/dist/shared/download/downloader.js +10 -3
- package/dist/shared/installs.d.ts +19 -0
- package/dist/shared/installs.js +13 -0
- package/dist/shared/io/bounded.d.ts +6 -0
- package/dist/shared/io/bounded.js +38 -0
- package/dist/shared/io/index.d.ts +2 -0
- package/dist/shared/io/index.js +2 -0
- package/dist/shared/io/text.d.ts +9 -0
- package/dist/shared/io/text.js +18 -0
- package/dist/shared/paths/guest-paths.js +1 -1
- package/dist/shared/paths/index.d.ts +1 -0
- package/dist/shared/paths/index.js +1 -0
- package/dist/shared/paths/pc-installs.d.ts +20 -0
- package/dist/shared/paths/pc-installs.js +19 -0
- package/dist/shared/vdf.d.ts +25 -0
- package/dist/shared/vdf.js +151 -0
- package/dist/sync/sync-cycle.js +9 -0
- package/dist/web/index.html +1 -1
- package/dist/web/{main-JTH3FT4O.js → main-CWIF4VQI.js} +63 -61
- 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/scripts/add-firewall-port.ps1 +13 -0
- package/sandbox/templates/fivem/README.txt +2 -0
- package/schemas/config.schema.json +485 -0
- package/schemas/sandbox-config.schema.json +416 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { Toolchains } from '../../../core/types.js';
|
|
2
|
+
import type { ToolchainHints } from './hint.js';
|
|
3
|
+
export type { ToolchainHints } from './hint.js';
|
|
4
|
+
/** Every area's hints for this project; the first reason found for a toolchain wins. A failing area adds none. */
|
|
5
|
+
export declare function areaHints(root: string, settings: Toolchains): ToolchainHints;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { androidHints } from './android.js';
|
|
2
|
+
import { engineHints } from './engines.js';
|
|
3
|
+
import { fivemHints } from './fivem.js';
|
|
4
|
+
import { mobileHints } from './mobile.js';
|
|
5
|
+
import { steamHints } from './steam.js';
|
|
6
|
+
const AREAS = [
|
|
7
|
+
steamHints,
|
|
8
|
+
engineHints,
|
|
9
|
+
fivemHints,
|
|
10
|
+
androidHints,
|
|
11
|
+
mobileHints,
|
|
12
|
+
];
|
|
13
|
+
/** Every area's hints for this project; the first reason found for a toolchain wins. A failing area adds none. */
|
|
14
|
+
export function areaHints(root, settings) {
|
|
15
|
+
const all = {};
|
|
16
|
+
for (const area of AREAS) {
|
|
17
|
+
let found = {};
|
|
18
|
+
try {
|
|
19
|
+
found = area(root, settings);
|
|
20
|
+
}
|
|
21
|
+
catch {
|
|
22
|
+
// A file that cannot be read gives no hint; the toolchain stays as its settings and markers say.
|
|
23
|
+
}
|
|
24
|
+
for (const [name, reason] of Object.entries(found))
|
|
25
|
+
if (reason && !all[name])
|
|
26
|
+
all[name] = reason;
|
|
27
|
+
}
|
|
28
|
+
return all;
|
|
29
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { Toolchains } from '../../../core/types.js';
|
|
2
|
+
import type { ToolchainHints } from './hint.js';
|
|
3
|
+
/** The .vdf files of a project (bounded walk, no links). */
|
|
4
|
+
export declare function projectVdfFiles(root: string): string[];
|
|
5
|
+
/** What a SteamCMD script is for, or null: "AppBuild" (a build upload) or "workshopitem". */
|
|
6
|
+
export declare function steamScriptOf(text: string): 'AppBuild' | 'workshopitem' | null;
|
|
7
|
+
export declare function steamHints(root: string, settings: Toolchains): ToolchainHints;
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
// Steam: toolchain hints from file contents: a .vdf whose first block is "AppBuild" (a ContentBuilder build script) or
|
|
2
|
+
// "workshopitem" (a workshop upload) turns toolchains.steam on. Files are found by name, a few folders deep, and
|
|
3
|
+
// size-checked before they are read; links are not followed (the project may be hostile).
|
|
4
|
+
import fs from 'node:fs';
|
|
5
|
+
import path from 'node:path';
|
|
6
|
+
import { readBoundedFile } from '../../../shared/io/index.js';
|
|
7
|
+
import { parseVdf } from '../../../shared/vdf.js';
|
|
8
|
+
const SKIP = /^(node_modules|\.git|\.hg|\.svn|vendor|target|obj|dist|out|\.next|\.venv|venv|__pycache__|\.gradle|\.idea|\.vs|coverage|Library|Temp|Intermediate|Saved|DerivedDataCache|Binaries)$/i;
|
|
9
|
+
const MAX_DEPTH = 4;
|
|
10
|
+
const MAX_FOLDERS = 1500;
|
|
11
|
+
const MAX_ENTRIES = 2000;
|
|
12
|
+
const MAX_FILES = 40;
|
|
13
|
+
const MAX_BYTES = 64 * 1024;
|
|
14
|
+
/** The .vdf files of a project (bounded walk, no links). */
|
|
15
|
+
export function projectVdfFiles(root) {
|
|
16
|
+
const found = [];
|
|
17
|
+
let folders = 0;
|
|
18
|
+
const queue = [[root, 0]];
|
|
19
|
+
while (queue.length && found.length < MAX_FILES) {
|
|
20
|
+
const [dir, depth] = queue.shift();
|
|
21
|
+
if (++folders > MAX_FOLDERS)
|
|
22
|
+
break;
|
|
23
|
+
let entries;
|
|
24
|
+
try {
|
|
25
|
+
entries = fs.readdirSync(dir, { withFileTypes: true }).slice(0, MAX_ENTRIES);
|
|
26
|
+
}
|
|
27
|
+
catch {
|
|
28
|
+
continue;
|
|
29
|
+
}
|
|
30
|
+
for (const e of entries) {
|
|
31
|
+
if (e.isFile() && e.name.toLowerCase().endsWith('.vdf'))
|
|
32
|
+
found.push(path.join(dir, e.name));
|
|
33
|
+
else if (e.isDirectory() && depth < MAX_DEPTH && !SKIP.test(e.name))
|
|
34
|
+
queue.push([path.join(dir, e.name), depth + 1]);
|
|
35
|
+
if (found.length >= MAX_FILES)
|
|
36
|
+
break;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
return found;
|
|
40
|
+
}
|
|
41
|
+
/** What a SteamCMD script is for, or null: "AppBuild" (a build upload) or "workshopitem". */
|
|
42
|
+
export function steamScriptOf(text) {
|
|
43
|
+
const root = parseVdf(text, { maxBytes: MAX_BYTES, escapes: false, maxDepth: 16, maxKeys: 5000 });
|
|
44
|
+
const first = root ? Object.keys(root)[0]?.toLowerCase() : undefined;
|
|
45
|
+
return first === 'appbuild' ? 'AppBuild' : first === 'workshopitem' ? 'workshopitem' : null;
|
|
46
|
+
}
|
|
47
|
+
export function steamHints(root, settings) {
|
|
48
|
+
if (settings.steam.enabled !== 'auto')
|
|
49
|
+
return {};
|
|
50
|
+
for (const file of projectVdfFiles(root)) {
|
|
51
|
+
const bytes = readBoundedFile(file, MAX_BYTES);
|
|
52
|
+
const kind = bytes ? steamScriptOf(bytes.toString('utf8')) : null;
|
|
53
|
+
if (!kind)
|
|
54
|
+
continue;
|
|
55
|
+
const rel = path.relative(root, file).split(path.sep).join('/');
|
|
56
|
+
return { steam: rel + (kind === 'AppBuild' ? ' is a Steam build script' : ' is a Steam workshop item') };
|
|
57
|
+
}
|
|
58
|
+
return {};
|
|
59
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
export { generateSandbox } from './generate.js';
|
|
2
|
-
export { decideProjectToolchains } from './toolchains.js';
|
|
1
|
+
export { generateSandbox, newLaunchId } from './generate.js';
|
|
2
|
+
export { decideProjectToolchains, toolchainsOnForBoot } from './toolchains.js';
|
|
3
3
|
export { hostToolsOf, logonEnv } from './session-file.js';
|
|
4
4
|
export { cappedMemoryMb, decideMemory, GUEST, memoryNote, residentCapMb, residentNote, resolveMemoryMb, } from './wsb-file.js';
|
|
5
5
|
export { GENTLE_NOTE, vgpuSource, vgpuWarning } from './risk-notes.js';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
export { generateSandbox } from './generate.js';
|
|
2
|
-
export { decideProjectToolchains } from './toolchains.js';
|
|
1
|
+
export { generateSandbox, newLaunchId } from './generate.js';
|
|
2
|
+
export { decideProjectToolchains, toolchainsOnForBoot } from './toolchains.js';
|
|
3
3
|
export { hostToolsOf, logonEnv } from './session-file.js';
|
|
4
4
|
export { cappedMemoryMb, decideMemory, GUEST, memoryNote, residentCapMb, residentNote, resolveMemoryMb, } from './wsb-file.js';
|
|
5
5
|
export { GENTLE_NOTE, vgpuSource, vgpuWarning } from './risk-notes.js';
|
|
@@ -113,6 +113,8 @@ export function collectMappings(o, launchPath, boot = { roots: [], projects: [],
|
|
|
113
113
|
mappings.push({ host: probe.gitDir, guest: GUEST.hostTools + '\\git', readOnly: true });
|
|
114
114
|
if (probe.nvmDir)
|
|
115
115
|
mappings.push({ host: probe.nvmDir, guest: GUEST.hostTools + '\\nvm', readOnly: true });
|
|
116
|
+
// pcInstalls: this PC's games, engines and editors, read-only under C:\PcInstalls (checked by host/pc-installs).
|
|
117
|
+
mappings.push(...(o.pcInstalls?.mappings ?? []));
|
|
116
118
|
// Placement keeps extra folders apart; this guards the rest (and where the folders really are: F:\x is
|
|
117
119
|
// C:\Mirror\F\x).
|
|
118
120
|
assertNoGuestOverlap(mappings);
|
|
@@ -71,6 +71,8 @@ export function guestSession(o, parts) {
|
|
|
71
71
|
agentHomes: Object.assign({}, ...Object.values(config.harnesses).map((h) => h.home?.env ?? {})),
|
|
72
72
|
agentProfileDirs: Object.fromEntries(Object.entries(config.harnesses).flatMap(([name, h]) => h.home?.profileDirs?.length ? [[name, h.home.profileDirs]] : [])),
|
|
73
73
|
agents: Object.fromEntries(Object.entries(config.harnesses).map(([name, h]) => [name, { ...h, environment: {} }])),
|
|
74
|
+
...(o.pcInstalls?.manifest.items.length ? { pcInstalls: o.pcInstalls.manifest } : {}),
|
|
75
|
+
...(o.accountLeases?.length ? { accountLeases: [...o.accountLeases] } : {}),
|
|
74
76
|
};
|
|
75
77
|
}
|
|
76
78
|
/**
|
|
@@ -30,7 +30,16 @@ export function stageScripts(target, scripts) {
|
|
|
30
30
|
fs.copyFileSync(script, path.join(target, '90-extra-' + index + '-' + path.basename(script)));
|
|
31
31
|
});
|
|
32
32
|
}
|
|
33
|
-
export const RUNTIME_FILES = [
|
|
33
|
+
export const RUNTIME_FILES = [
|
|
34
|
+
'main.js',
|
|
35
|
+
'daemon.js',
|
|
36
|
+
'view.js',
|
|
37
|
+
'gitguard.js',
|
|
38
|
+
'db.js',
|
|
39
|
+
'netproxy.js',
|
|
40
|
+
'agent.js',
|
|
41
|
+
'tool.js',
|
|
42
|
+
];
|
|
34
43
|
/** The bundled sandbox runtime (dist/runtime: one self-contained file per entry point) and the sandbox/ scripts. */
|
|
35
44
|
export function copyRuntime(packageRoot, launchPath) {
|
|
36
45
|
const runtime = path.join(packageRoot, 'dist', 'runtime');
|
|
@@ -1,4 +1,11 @@
|
|
|
1
|
+
import type { BootWant } from '../../core/local-config/index.js';
|
|
1
2
|
import type { GenerateOptions } from '../../core/types.js';
|
|
3
|
+
import { type UsedBy } from '../../shared/accounts/index.js';
|
|
2
4
|
import { decideToolchains } from '../../core/detect/index.js';
|
|
3
5
|
/** Which toolchains the project needs ("auto" settings follow the project's files and what this PC has). */
|
|
4
6
|
export declare function decideProjectToolchains(o: Pick<GenerateOptions, 'run' | 'pcLanguages'>): ReturnType<typeof decideToolchains>;
|
|
7
|
+
/**
|
|
8
|
+
* The toolchains a service sign-in may serve that are on for this boot: the launch's own project (its files decide
|
|
9
|
+
* "auto") and the other boot projects that turn one on in their settings.
|
|
10
|
+
*/
|
|
11
|
+
export declare function toolchainsOnForBoot(o: Pick<GenerateOptions, 'run' | 'pcLanguages'>, others?: readonly BootWant[]): Set<UsedBy>;
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
+
import { USED_BY } from '../../shared/accounts/index.js';
|
|
1
2
|
import { decideToolchains, readPwshScripts, usesPwsh } from '../../core/detect/index.js';
|
|
2
3
|
import { pcLanguages } from './pc-scan.js';
|
|
3
4
|
import { msvcHint, projectEntries, uvHint } from './project-scan.js';
|
|
5
|
+
import { areaHints } from './hints/index.js';
|
|
4
6
|
/** Which toolchains the project needs ("auto" settings follow the project's files and what this PC has). */
|
|
5
7
|
export function decideProjectToolchains(o) {
|
|
6
8
|
const { config, workspaceHost } = o.run;
|
|
@@ -12,6 +14,7 @@ export function decideProjectToolchains(o) {
|
|
|
12
14
|
const uvScript = config.toolchains.uv.enabled === 'auto' ? uvHint(workspaceHost) : undefined;
|
|
13
15
|
const uvText = uvScript ?? memHint;
|
|
14
16
|
const hints = {
|
|
17
|
+
...areaHints(workspaceHost, config.toolchains),
|
|
15
18
|
...(msvcScript ? { msvc: msvcScript } : {}),
|
|
16
19
|
...(pwshScript ? { pwsh: pwshScript } : {}),
|
|
17
20
|
...(memHint ? { bun: memHint } : {}),
|
|
@@ -19,3 +22,11 @@ export function decideProjectToolchains(o) {
|
|
|
19
22
|
};
|
|
20
23
|
return decideToolchains(config.toolchains, projectEntries(workspaceHost), o.pcLanguages ?? pcLanguages(), hints);
|
|
21
24
|
}
|
|
25
|
+
/**
|
|
26
|
+
* The toolchains a service sign-in may serve that are on for this boot: the launch's own project (its files decide
|
|
27
|
+
* "auto") and the other boot projects that turn one on in their settings.
|
|
28
|
+
*/
|
|
29
|
+
export function toolchainsOnForBoot(o, others = []) {
|
|
30
|
+
const decisions = decideProjectToolchains(o);
|
|
31
|
+
return new Set(USED_BY.filter((u) => decisions[u].on || others.some((p) => p.config.toolchains[u].enabled === true)));
|
|
32
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { Config, ResolvedMapping } from '../../core/types.js';
|
|
2
|
+
import { type PcInstallManifest } from '../../shared/paths/index.js';
|
|
3
|
+
import { type PcEnv } from '../accounts/index.js';
|
|
4
|
+
import type { PcInstallSource } from './source.js';
|
|
5
|
+
export type PcInstalls = Config['pcInstalls'];
|
|
6
|
+
/** At most this many installs are mapped (each one is a mapping in the .wsb). */
|
|
7
|
+
export declare const MAX_PC_INSTALLS = 40;
|
|
8
|
+
export declare const PC_INSTALL_SOURCES: readonly PcInstallSource[];
|
|
9
|
+
export interface DiscoverOptions {
|
|
10
|
+
readonly packageRoot: string;
|
|
11
|
+
readonly storageRoot: string;
|
|
12
|
+
readonly sources?: readonly PcInstallSource[];
|
|
13
|
+
}
|
|
14
|
+
export interface DiscoveredInstalls {
|
|
15
|
+
readonly mappings: ResolvedMapping[];
|
|
16
|
+
readonly manifest: PcInstallManifest;
|
|
17
|
+
readonly notes: string[];
|
|
18
|
+
}
|
|
19
|
+
export declare function discoverPcInstalls(s: PcInstalls, o: DiscoverOptions, pc?: PcEnv): DiscoveredInstalls;
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { assertSafeMapping } from '../../core/safe-paths.js';
|
|
2
|
+
import { dirExists, errMsg } from '../../core/util/index.js';
|
|
3
|
+
import { pcInstallGuest } from '../../shared/paths/index.js';
|
|
4
|
+
import { pcEnv } from '../accounts/index.js';
|
|
5
|
+
import { epicInstalls } from './epic.js';
|
|
6
|
+
import { steamInstalls } from './steam.js';
|
|
7
|
+
import { unityInstalls } from './unity.js';
|
|
8
|
+
import { unrealInstalls } from './unreal.js';
|
|
9
|
+
/** At most this many installs are mapped (each one is a mapping in the .wsb). */
|
|
10
|
+
export const MAX_PC_INSTALLS = 40;
|
|
11
|
+
export const PC_INSTALL_SOURCES = [
|
|
12
|
+
steamInstalls,
|
|
13
|
+
epicInstalls,
|
|
14
|
+
unrealInstalls,
|
|
15
|
+
unityInstalls,
|
|
16
|
+
];
|
|
17
|
+
export function discoverPcInstalls(s, o, pc = pcEnv()) {
|
|
18
|
+
const mappings = [];
|
|
19
|
+
const items = [];
|
|
20
|
+
const notes = [];
|
|
21
|
+
for (const source of o.sources ?? PC_INSTALL_SOURCES) {
|
|
22
|
+
const wanted = s[source.setting];
|
|
23
|
+
if (wanted === false || (Array.isArray(wanted) && !wanted.length))
|
|
24
|
+
continue;
|
|
25
|
+
let found = [];
|
|
26
|
+
try {
|
|
27
|
+
found = source.find(wanted, pc);
|
|
28
|
+
}
|
|
29
|
+
catch (e) {
|
|
30
|
+
notes.push('pcInstalls.' + source.setting + ': could not look on this PC (' + errMsg(e) + ').');
|
|
31
|
+
continue;
|
|
32
|
+
}
|
|
33
|
+
for (const install of found) {
|
|
34
|
+
if (mappings.length >= MAX_PC_INSTALLS) {
|
|
35
|
+
notes.push('pcInstalls: only the first ' + MAX_PC_INSTALLS + ' installs are mapped.');
|
|
36
|
+
break;
|
|
37
|
+
}
|
|
38
|
+
try {
|
|
39
|
+
const guest = pcInstallGuest(install.kind, install.id);
|
|
40
|
+
if (mappings.some((m) => m.guest.toLowerCase() === guest.toLowerCase()))
|
|
41
|
+
continue;
|
|
42
|
+
if (!dirExists(install.host)) {
|
|
43
|
+
notes.push('pcInstalls: ' + install.name + ' is not there any more (' + install.host + ').');
|
|
44
|
+
continue;
|
|
45
|
+
}
|
|
46
|
+
assertSafeMapping(install.host, o.packageRoot, o.storageRoot);
|
|
47
|
+
mappings.push({ host: install.host, guest, readOnly: true, label: 'this PC, read-only' });
|
|
48
|
+
const { host: _host, ...shown } = install;
|
|
49
|
+
items.push({ ...shown, guest });
|
|
50
|
+
}
|
|
51
|
+
catch (e) {
|
|
52
|
+
notes.push('pcInstalls: ' + install.name + ' is not mapped: ' + errMsg(e));
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
if (Array.isArray(wanted) && found.length < wanted.length)
|
|
56
|
+
notes.push('pcInstalls.' + source.setting + ': some of the listed ones are not installed on this PC.');
|
|
57
|
+
}
|
|
58
|
+
return { mappings, manifest: { items }, notes };
|
|
59
|
+
}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export { discoverPcInstalls, MAX_PC_INSTALLS, PC_INSTALL_SOURCES, type DiscoveredInstalls, type DiscoverOptions, type PcInstalls, } from './discover.js';
|
|
2
|
+
export type { PcInstallSource } from './source.js';
|
|
3
|
+
export type { PcInstall, PcInstallManifest } from '../../shared/paths/index.js';
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { PcInstall } from '../../shared/paths/index.js';
|
|
2
|
+
import type { PcEnv } from '../accounts/index.js';
|
|
3
|
+
export interface PcInstallSource {
|
|
4
|
+
readonly kind: PcInstall['kind'];
|
|
5
|
+
/** The settings key that turns it on (pcInstalls.<setting>). */
|
|
6
|
+
readonly setting: 'steamGames' | 'epicGames' | 'unrealEngines' | 'unityEditors';
|
|
7
|
+
/** What is installed: everything (true) or the ones listed. Bounded reads only (registry, manifests). */
|
|
8
|
+
find(wanted: true | readonly (string | number)[], pc: PcEnv): PcInstall[];
|
|
9
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { PcInstall } from '../../shared/paths/index.js';
|
|
2
|
+
import type { PcInstallSource } from './source.js';
|
|
3
|
+
/** Where Steam is installed on this PC (HKCU SteamPath, else HKLM InstallPath), or null. */
|
|
4
|
+
export declare function steamRootFromRegistry(): string | null;
|
|
5
|
+
export interface SteamLibrary {
|
|
6
|
+
readonly path: string;
|
|
7
|
+
/** The app IDs the library lists (empty in the old format: the manifests tell). */
|
|
8
|
+
readonly apps: readonly string[];
|
|
9
|
+
}
|
|
10
|
+
/** The libraries a libraryfolders.vdf lists (both the current and the old format), in order. */
|
|
11
|
+
export declare function steamLibraries(text: string): SteamLibrary[];
|
|
12
|
+
/** The libraries of a Steam install: its own folder first, then the ones libraryfolders.vdf lists. */
|
|
13
|
+
export declare function librariesOf(steamRoot: string): SteamLibrary[];
|
|
14
|
+
/** What `wanted` maps from a Steam install: every library's steamapps (true), or the listed games. */
|
|
15
|
+
export declare function findSteamInstalls(steamRoot: string, wanted: true | readonly (string | number)[]): PcInstall[];
|
|
16
|
+
export declare const steamInstalls: PcInstallSource;
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
// Steam games of this PC: SteamPath from the registry (reg.exe through system32), libraryfolders.vdf and the app
|
|
2
|
+
// manifests. true maps each library's steamapps (C:\PcInstalls\steam\library<N>), a list of app IDs only those games
|
|
3
|
+
// (C:\PcInstalls\steam\<appid>). Every file is read bounded; names from them never carry a path of this PC.
|
|
4
|
+
import { spawnSync } from 'node:child_process';
|
|
5
|
+
import fs from 'node:fs';
|
|
6
|
+
import path from 'node:path';
|
|
7
|
+
import { readBoundedFile } from '../../shared/io/index.js';
|
|
8
|
+
import { SYSTEM } from '../../shared/system.js';
|
|
9
|
+
import { parseVdf, vdfObject, vdfText } from '../../shared/vdf.js';
|
|
10
|
+
const MAX_LIBRARIES = 32;
|
|
11
|
+
const MAX_VDF_BYTES = 1024 * 1024;
|
|
12
|
+
const MAX_MANIFEST_BYTES = 256 * 1024;
|
|
13
|
+
const APP_ID = /^[1-9]\d{0,9}$/;
|
|
14
|
+
/** Where Steam is installed on this PC (HKCU SteamPath, else HKLM InstallPath), or null. */
|
|
15
|
+
export function steamRootFromRegistry() {
|
|
16
|
+
const queries = [
|
|
17
|
+
['HKCU\\Software\\Valve\\Steam', 'SteamPath'],
|
|
18
|
+
['HKLM\\SOFTWARE\\WOW6432Node\\Valve\\Steam', 'InstallPath'],
|
|
19
|
+
['HKLM\\SOFTWARE\\Valve\\Steam', 'InstallPath'],
|
|
20
|
+
];
|
|
21
|
+
for (const [key, name] of queries) {
|
|
22
|
+
const result = spawnSync(SYSTEM.reg(), ['query', key, '/v', name], {
|
|
23
|
+
encoding: 'utf8',
|
|
24
|
+
windowsHide: true,
|
|
25
|
+
timeout: 10_000,
|
|
26
|
+
});
|
|
27
|
+
if (result.status !== 0)
|
|
28
|
+
continue;
|
|
29
|
+
const line = String(result.stdout ?? '')
|
|
30
|
+
.split(/\r?\n/)
|
|
31
|
+
.slice(0, 50)
|
|
32
|
+
.find((l) => l
|
|
33
|
+
.trim()
|
|
34
|
+
.toLowerCase()
|
|
35
|
+
.startsWith(name.toLowerCase() + ' '));
|
|
36
|
+
const value = line
|
|
37
|
+
?.trim()
|
|
38
|
+
.split(/\s+REG_(?:EXPAND_)?SZ\s+/)[1]
|
|
39
|
+
?.trim();
|
|
40
|
+
if (value && path.isAbsolute(value))
|
|
41
|
+
return path.normalize(value.replace(/\//g, '\\'));
|
|
42
|
+
}
|
|
43
|
+
return null;
|
|
44
|
+
}
|
|
45
|
+
/** The libraries a libraryfolders.vdf lists (both the current and the old format), in order. */
|
|
46
|
+
export function steamLibraries(text) {
|
|
47
|
+
const root = parseVdf(text, { maxBytes: MAX_VDF_BYTES });
|
|
48
|
+
const folders = vdfObject(root, 'libraryfolders');
|
|
49
|
+
if (!folders)
|
|
50
|
+
return [];
|
|
51
|
+
const found = [];
|
|
52
|
+
for (const [key, value] of Object.entries(folders)) {
|
|
53
|
+
if (!/^\d{1,3}$/.test(key))
|
|
54
|
+
continue;
|
|
55
|
+
const at = typeof value === 'string' ? value : vdfText(value, 'path');
|
|
56
|
+
if (!at || !path.win32.isAbsolute(at))
|
|
57
|
+
continue;
|
|
58
|
+
const apps = typeof value === 'string' ? [] : Object.keys(vdfObject(value, 'apps') ?? {}).filter((a) => APP_ID.test(a));
|
|
59
|
+
if (!found.some((l) => l.path.toLowerCase() === at.toLowerCase()))
|
|
60
|
+
found.push({ path: at, apps });
|
|
61
|
+
if (found.length >= MAX_LIBRARIES)
|
|
62
|
+
break;
|
|
63
|
+
}
|
|
64
|
+
return found;
|
|
65
|
+
}
|
|
66
|
+
/** The libraries of a Steam install: its own folder first, then the ones libraryfolders.vdf lists. */
|
|
67
|
+
export function librariesOf(steamRoot) {
|
|
68
|
+
const bytes = readBoundedFile(path.join(steamRoot, 'steamapps', 'libraryfolders.vdf'), MAX_VDF_BYTES);
|
|
69
|
+
const listed = bytes ? steamLibraries(bytes.toString('utf8')) : [];
|
|
70
|
+
const own = listed.find((l) => path.resolve(l.path).toLowerCase() === path.resolve(steamRoot).toLowerCase());
|
|
71
|
+
return [own ?? { path: steamRoot, apps: [] }, ...listed.filter((l) => l !== own)];
|
|
72
|
+
}
|
|
73
|
+
function readManifest(file) {
|
|
74
|
+
const bytes = readBoundedFile(file, MAX_MANIFEST_BYTES);
|
|
75
|
+
const root = bytes ? parseVdf(bytes.toString('utf8'), { maxBytes: MAX_MANIFEST_BYTES }) : null;
|
|
76
|
+
const appId = vdfText(root, 'AppState', 'appid');
|
|
77
|
+
const installDir = vdfText(root, 'AppState', 'installdir');
|
|
78
|
+
if (!appId || !APP_ID.test(appId) || !installDir)
|
|
79
|
+
return null;
|
|
80
|
+
// One folder name under steamapps\common: never a path that climbs out of it.
|
|
81
|
+
if (/[\\/:]/.test(installDir) || /^\.+$/.test(installDir.trim()))
|
|
82
|
+
return null;
|
|
83
|
+
const buildId = vdfText(root, 'AppState', 'buildid');
|
|
84
|
+
const name = (vdfText(root, 'AppState', 'name') ?? '').replace(/[^\x20-\x7e\u00a0-\uffff]/g, '').slice(0, 100);
|
|
85
|
+
return {
|
|
86
|
+
appId,
|
|
87
|
+
name: name || 'Steam app ' + appId,
|
|
88
|
+
installDir,
|
|
89
|
+
...(buildId && /^\d{1,20}$/.test(buildId) ? { buildId } : {}),
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
/** What `wanted` maps from a Steam install: every library's steamapps (true), or the listed games. */
|
|
93
|
+
export function findSteamInstalls(steamRoot, wanted) {
|
|
94
|
+
const libraries = librariesOf(steamRoot);
|
|
95
|
+
if (wanted === true)
|
|
96
|
+
return libraries.flatMap((lib, i) => {
|
|
97
|
+
const steamapps = path.join(lib.path, 'steamapps');
|
|
98
|
+
try {
|
|
99
|
+
if (!fs.lstatSync(steamapps).isDirectory())
|
|
100
|
+
return [];
|
|
101
|
+
}
|
|
102
|
+
catch {
|
|
103
|
+
return [];
|
|
104
|
+
}
|
|
105
|
+
return [
|
|
106
|
+
{
|
|
107
|
+
kind: 'steam-library',
|
|
108
|
+
id: 'library' + (i + 1),
|
|
109
|
+
name: 'Steam library ' + (i + 1),
|
|
110
|
+
host: steamapps,
|
|
111
|
+
guest: '',
|
|
112
|
+
},
|
|
113
|
+
];
|
|
114
|
+
});
|
|
115
|
+
const found = [];
|
|
116
|
+
for (const id of new Set(wanted.map(String).filter((w) => APP_ID.test(w)))) {
|
|
117
|
+
for (const lib of libraries) {
|
|
118
|
+
const manifest = readManifest(path.join(lib.path, 'steamapps', 'appmanifest_' + id + '.acf'));
|
|
119
|
+
if (!manifest || manifest.appId !== id)
|
|
120
|
+
continue;
|
|
121
|
+
found.push({
|
|
122
|
+
kind: 'steam-game',
|
|
123
|
+
id,
|
|
124
|
+
name: manifest.name,
|
|
125
|
+
...(manifest.buildId ? { version: manifest.buildId } : {}),
|
|
126
|
+
host: path.join(lib.path, 'steamapps', 'common', manifest.installDir),
|
|
127
|
+
guest: '',
|
|
128
|
+
});
|
|
129
|
+
break;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
return found;
|
|
133
|
+
}
|
|
134
|
+
export const steamInstalls = {
|
|
135
|
+
kind: 'steam-game',
|
|
136
|
+
setting: 'steamGames',
|
|
137
|
+
find(wanted, _pc) {
|
|
138
|
+
const root = steamRootFromRegistry();
|
|
139
|
+
if (!root)
|
|
140
|
+
throw new Error('Steam is not installed (the registry has no SteamPath)');
|
|
141
|
+
return findSteamInstalls(root, wanted);
|
|
142
|
+
},
|
|
143
|
+
};
|
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
import { SecretStore } from '../secrets/index.js';
|
|
2
|
-
import { type LoginFiles } from './claude-login.js';
|
|
2
|
+
import { type CaptureOptions, type LoginFiles, type LoginKind } from './claude-login.js';
|
|
3
3
|
export interface Account {
|
|
4
4
|
readonly name: string;
|
|
5
5
|
readonly savedAt: string;
|
|
6
6
|
readonly email: string | null;
|
|
7
|
+
readonly kind: LoginKind;
|
|
8
|
+
/** sk-ant-...abcd for a key; null for a subscription. */
|
|
9
|
+
readonly keyHint: string | null;
|
|
7
10
|
readonly credentials: unknown;
|
|
8
11
|
readonly oauthAccount: unknown;
|
|
12
|
+
readonly apiKey?: string;
|
|
9
13
|
}
|
|
10
14
|
export interface AccountRow {
|
|
11
15
|
readonly name: string;
|
|
@@ -13,12 +17,17 @@ export interface AccountRow {
|
|
|
13
17
|
readonly isDefault: boolean;
|
|
14
18
|
readonly isActive: boolean;
|
|
15
19
|
readonly savedAt: string;
|
|
20
|
+
/** Claude accounts only. */
|
|
21
|
+
readonly kind?: LoginKind;
|
|
22
|
+
readonly keyHint?: string | null;
|
|
16
23
|
}
|
|
17
24
|
/** What lists need: no decryption. */
|
|
18
25
|
export interface AccountMeta {
|
|
19
26
|
readonly name: string;
|
|
20
27
|
readonly savedAt: string;
|
|
21
28
|
readonly email: string | null;
|
|
29
|
+
readonly kind: LoginKind;
|
|
30
|
+
readonly keyHint: string | null;
|
|
22
31
|
}
|
|
23
32
|
export declare function accountsDir(storageRoot: string): string;
|
|
24
33
|
/** The saved Claude logins under <storage>\accounts, and which one each sandbox data folder uses. */
|
|
@@ -36,7 +45,7 @@ export declare class AccountStore {
|
|
|
36
45
|
private file;
|
|
37
46
|
private seal;
|
|
38
47
|
private store;
|
|
39
|
-
/** The saved account's name, date
|
|
48
|
+
/** The saved account's name, date, e-mail and kind (nothing is decrypted). */
|
|
40
49
|
meta(name: string): AccountMeta | null;
|
|
41
50
|
/**
|
|
42
51
|
* The saved account with its login decrypted. A plain file from an older version is encrypted on the spot (it stays
|
|
@@ -49,11 +58,17 @@ export declare class AccountStore {
|
|
|
49
58
|
/** The account a data folder uses (kept in the index of the storage folder that data folder is in). */
|
|
50
59
|
activeFor(dataPath: string): string | null;
|
|
51
60
|
list(dataPath: string): AccountRow[];
|
|
52
|
-
/** Saves the sandbox's current login (or this PC's, with fromHost) under `name`. */
|
|
53
|
-
save(dataPath: string, name: string, fromHost: LoginFiles | null): Account;
|
|
54
61
|
/**
|
|
55
|
-
*
|
|
56
|
-
*
|
|
62
|
+
* Saves the sandbox's current login (or this PC's, with fromHost) under `name`, whichever kind it is (`how.keyOnly`:
|
|
63
|
+
* only an API key; `how.envKey`: this PC's ANTHROPIC_API_KEY when nothing else is found).
|
|
64
|
+
*/
|
|
65
|
+
save(dataPath: string, name: string, fromHost: LoginFiles | null, how?: CaptureOptions): Account;
|
|
66
|
+
/** Saves an API key you gave (typed in) under `name`. */
|
|
67
|
+
saveApiKey(dataPath: string, name: string, apiKey: string): Account;
|
|
68
|
+
private keep;
|
|
69
|
+
/**
|
|
70
|
+
* Makes `name` the sandbox's login. Claude refreshes (rotates) subscription tokens while it runs, so the outgoing
|
|
71
|
+
* subscription's current tokens are saved back first; otherwise its stored refresh token could already be invalid.
|
|
57
72
|
*/
|
|
58
73
|
activate(dataPath: string, name: string): Account;
|
|
59
74
|
setDefault(name: string | null): void;
|