windows-development-sandbox 1.17.0 → 1.18.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +92 -92
- 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-BKF43GJ3.js} +51 -16
- package/dist/bin/{chunk-REE3EMHD.js → chunk-YD3A67RS.js} +3812 -1702
- package/dist/bin/{chunk-XYUVIVJT.js → chunk-Z5D32FN3.js} +1 -1
- 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/agents/agent-files.d.ts +6 -0
- package/dist/guest/agents/agent-files.js +14 -0
- package/dist/guest/agents/local-state.d.ts +2 -0
- package/dist/guest/agents/local-state.js +13 -1
- 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 +36 -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 -155
- 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 +100 -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 -595
- package/dist/runtime/db.js +334 -11
- package/dist/runtime/main.js +2530 -709
- 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 +13 -1
- 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,18 @@
|
|
|
1
|
+
import { appstoreAdapter } from './kinds/appstore.js';
|
|
2
|
+
import { cfxAdapter } from './kinds/cfx.js';
|
|
3
|
+
import { epicAdapter } from './kinds/epic.js';
|
|
4
|
+
import { expoAdapter } from './kinds/expo.js';
|
|
5
|
+
import { keystoreAdapter } from './kinds/keystore.js';
|
|
6
|
+
import { playAdapter } from './kinds/play.js';
|
|
7
|
+
import { steamAdapter } from './kinds/steam.js';
|
|
8
|
+
import { unityAdapter } from './kinds/unity.js';
|
|
9
|
+
export const ADAPTERS = {
|
|
10
|
+
epic: epicAdapter,
|
|
11
|
+
steam: steamAdapter,
|
|
12
|
+
unity: unityAdapter,
|
|
13
|
+
cfx: cfxAdapter,
|
|
14
|
+
keystore: keystoreAdapter,
|
|
15
|
+
play: playAdapter,
|
|
16
|
+
expo: expoAdapter,
|
|
17
|
+
appstore: appstoreAdapter,
|
|
18
|
+
};
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { type ServiceKind } from '../../shared/accounts/kinds.js';
|
|
3
|
+
import type { ServiceAccounts } from '../../shared/accounts/payloads.js';
|
|
4
|
+
import { type GuestAdapter } from './adapter.js';
|
|
5
|
+
export declare const DeliveredSchema: z.ZodObject<{
|
|
6
|
+
fingerprints: z.ZodRecord<z.ZodEnum<{
|
|
7
|
+
unity: "unity";
|
|
8
|
+
steam: "steam";
|
|
9
|
+
epic: "epic";
|
|
10
|
+
cfx: "cfx";
|
|
11
|
+
keystore: "keystore";
|
|
12
|
+
play: "play";
|
|
13
|
+
expo: "expo";
|
|
14
|
+
appstore: "appstore";
|
|
15
|
+
}> & z.core.$partial, z.ZodString>;
|
|
16
|
+
leased: z.ZodArray<z.ZodEnum<{
|
|
17
|
+
unity: "unity";
|
|
18
|
+
steam: "steam";
|
|
19
|
+
epic: "epic";
|
|
20
|
+
cfx: "cfx";
|
|
21
|
+
keystore: "keystore";
|
|
22
|
+
play: "play";
|
|
23
|
+
expo: "expo";
|
|
24
|
+
appstore: "appstore";
|
|
25
|
+
}>>;
|
|
26
|
+
}, z.core.$strip>;
|
|
27
|
+
export type Delivered = z.output<typeof DeliveredSchema>;
|
|
28
|
+
export declare function deliveredFile(root?: string): string;
|
|
29
|
+
export declare function readDelivered(root?: string): Delivered;
|
|
30
|
+
export interface ApplyOptions {
|
|
31
|
+
/** The kinds whose lease this launch holds (session.json accountLeases). */
|
|
32
|
+
readonly leased?: readonly ServiceKind[];
|
|
33
|
+
/** The boot log. */
|
|
34
|
+
readonly say?: (line: string) => void;
|
|
35
|
+
readonly root?: string;
|
|
36
|
+
readonly adapters?: {
|
|
37
|
+
readonly [K in ServiceKind]?: GuestAdapter<K>;
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
/** Applies every sign-in given; returns the variables for the agent's sessions. A failing kind is a log line. */
|
|
41
|
+
export declare function applyServiceAccounts(given: ServiceAccounts | undefined, o?: ApplyOptions): Promise<Record<string, string>>;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
// At boot: each handed-over sign-in goes to its tool (the adapters), then is dropped from memory. What was delivered
|
|
2
|
+
// is remembered only as fingerprints, with the kinds whose lease this launch holds, in delivered.json on the
|
|
3
|
+
// sandbox's own disk: the daemon's watch starts from them, so its first look never hands back what it was given.
|
|
4
|
+
import fs from 'node:fs';
|
|
5
|
+
import path from 'node:path';
|
|
6
|
+
import { z } from 'zod';
|
|
7
|
+
import { fingerprint } from '../../shared/accounts/fingerprint.js';
|
|
8
|
+
import { SERVICE_KINDS } from '../../shared/accounts/kinds.js';
|
|
9
|
+
import { readValid, writeJsonAtomic } from '../../shared/io/json.js';
|
|
10
|
+
import { errMsg } from '../../core/util/errors.js';
|
|
11
|
+
import { accountsRoot } from './adapter.js';
|
|
12
|
+
import { ADAPTERS } from './adapters.js';
|
|
13
|
+
export const DeliveredSchema = z.object({
|
|
14
|
+
fingerprints: z.partialRecord(z.enum(SERVICE_KINDS), z.string().max(128)),
|
|
15
|
+
leased: z.array(z.enum(SERVICE_KINDS)),
|
|
16
|
+
});
|
|
17
|
+
export function deliveredFile(root = accountsRoot()) {
|
|
18
|
+
return path.join(root, 'delivered.json');
|
|
19
|
+
}
|
|
20
|
+
export function readDelivered(root = accountsRoot()) {
|
|
21
|
+
return readValid(DeliveredSchema, deliveredFile(root)) ?? { fingerprints: {}, leased: [] };
|
|
22
|
+
}
|
|
23
|
+
/** Applies every sign-in given; returns the variables for the agent's sessions. A failing kind is a log line. */
|
|
24
|
+
export async function applyServiceAccounts(given, o = {}) {
|
|
25
|
+
const say = o.say ?? (() => undefined);
|
|
26
|
+
const env = {};
|
|
27
|
+
const fingerprints = {};
|
|
28
|
+
for (const kind of SERVICE_KINDS) {
|
|
29
|
+
const payload = given?.[kind];
|
|
30
|
+
if (payload === undefined)
|
|
31
|
+
continue;
|
|
32
|
+
const adapter = (o.adapters?.[kind] ?? ADAPTERS[kind]);
|
|
33
|
+
try {
|
|
34
|
+
const applied = await adapter.apply(payload);
|
|
35
|
+
Object.assign(env, applied.env ?? {});
|
|
36
|
+
fingerprints[kind] = fingerprint(payload);
|
|
37
|
+
say(applied.summary);
|
|
38
|
+
}
|
|
39
|
+
catch (e) {
|
|
40
|
+
say(kind + ' sign-in: could not be used (' + errMsg(e) + ')');
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
const root = o.root ?? accountsRoot();
|
|
44
|
+
fs.mkdirSync(root, { recursive: true });
|
|
45
|
+
writeJsonAtomic(deliveredFile(root), { fingerprints, leased: [...(o.leased ?? [])] });
|
|
46
|
+
return env;
|
|
47
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
// Epic Games: the handed-over sign-in goes into the launcher's GameUserSettings.ini before anyone opens it (its other
|
|
2
|
+
// settings are kept, and the file keeps the encoding it had: the launcher often writes UTF-16). The watch reads it
|
|
3
|
+
// back to notice when the launcher renews it, or when you sign in here the first time.
|
|
4
|
+
import fs from 'node:fs';
|
|
5
|
+
import path from 'node:path';
|
|
6
|
+
import { epicSettingsFile, MAX_EPIC_INI_BYTES, readEpicLogin, withEpicLogin, } from '../../../shared/accounts/index.js';
|
|
7
|
+
import { decodeText, encodeText, readBoundedFile } from '../../../shared/io/index.js';
|
|
8
|
+
import { localAppData } from '../adapter.js';
|
|
9
|
+
function settingsFile() {
|
|
10
|
+
return epicSettingsFile(localAppData());
|
|
11
|
+
}
|
|
12
|
+
export const epicAdapter = {
|
|
13
|
+
kind: 'epic',
|
|
14
|
+
apply(p) {
|
|
15
|
+
const file = settingsFile();
|
|
16
|
+
const bytes = readBoundedFile(file, MAX_EPIC_INI_BYTES);
|
|
17
|
+
const read = bytes ? decodeText(bytes) : { text: '', encoding: 'utf8' };
|
|
18
|
+
fs.mkdirSync(path.dirname(file), { recursive: true });
|
|
19
|
+
fs.writeFileSync(file, encodeText(withEpicLogin(read.text, p), read.encoding));
|
|
20
|
+
return { summary: 'Epic Games Launcher: signed in with your saved sign-in' };
|
|
21
|
+
},
|
|
22
|
+
current() {
|
|
23
|
+
const bytes = readBoundedFile(settingsFile(), MAX_EPIC_INI_BYTES);
|
|
24
|
+
return bytes ? readEpicLogin(decodeText(bytes).text) : null;
|
|
25
|
+
},
|
|
26
|
+
};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
// Steam: SteamCMD's cached login goes into C:\SteamCMD\config (config.vdf, the account name) and the ssfn sentry files
|
|
2
|
+
// beside steamcmd.exe, on the sandbox's own disk, before the Steam step copies SteamCMD's binaries in (that copy never
|
|
3
|
+
// touches config\). The watch reads it back when SteamCMD renews it, or after a first `sbx-steam login` here.
|
|
4
|
+
import { readSteamCmdLogin, writeSteamCmdLogin } from '../../../shared/accounts/kinds/steam.js';
|
|
5
|
+
import { STEAMCMD_DIR } from '../../toolchains/steam/commands.js';
|
|
6
|
+
/** The adapter for a SteamCMD folder (the self-test passes its own). */
|
|
7
|
+
export function steamAdapterFor(steamcmdDir) {
|
|
8
|
+
return {
|
|
9
|
+
kind: 'steam',
|
|
10
|
+
apply(p) {
|
|
11
|
+
writeSteamCmdLogin(steamcmdDir, p);
|
|
12
|
+
return { summary: 'SteamCMD: signed in as ' + p.account + ' with your saved sign-in' };
|
|
13
|
+
},
|
|
14
|
+
current: () => readSteamCmdLogin(steamcmdDir),
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
export const steamAdapter = steamAdapterFor(STEAMCMD_DIR);
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { type ServiceKind } from '../../shared/accounts/kinds.js';
|
|
2
|
+
import type { GuestAdapter } from './adapter.js';
|
|
3
|
+
export interface WatchOptions {
|
|
4
|
+
/** The data folder (C:\AgentData); the handoffs go in its state\accounts. */
|
|
5
|
+
readonly dataDir: string;
|
|
6
|
+
readonly launchId: string;
|
|
7
|
+
/** Where delivered.json is (default: the sandbox's accounts folder). */
|
|
8
|
+
readonly root?: string;
|
|
9
|
+
readonly adapters?: {
|
|
10
|
+
readonly [K in ServiceKind]?: GuestAdapter<K>;
|
|
11
|
+
};
|
|
12
|
+
readonly warn?: (line: string) => void;
|
|
13
|
+
}
|
|
14
|
+
export declare class AccountWatch {
|
|
15
|
+
private readonly o;
|
|
16
|
+
private readonly last;
|
|
17
|
+
private readonly timers;
|
|
18
|
+
private readonly kinds;
|
|
19
|
+
constructor(kinds: readonly ServiceKind[], o: WatchOptions);
|
|
20
|
+
private adapter;
|
|
21
|
+
/** The kinds being watched. */
|
|
22
|
+
watched(): readonly ServiceKind[];
|
|
23
|
+
start(): void;
|
|
24
|
+
/** One look at one kind; true when a handoff was written. */
|
|
25
|
+
check(kind: ServiceKind): boolean;
|
|
26
|
+
/** Looks at every kind now; with `final` (the sandbox stops) each adapter also lets go of what it holds. */
|
|
27
|
+
flush(final?: boolean): Promise<void>;
|
|
28
|
+
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
// While the sandbox runs: each sign-in that may come back (Epic, Steam, Unity) is looked at every minute or so, and
|
|
2
|
+
// when the tool holds a different one (renewed, or a first sign-in made here) it is left for the PC in
|
|
3
|
+
// <data>\state\accounts\<kind>.json, which the PC seals and deletes on its next sync. Only kinds whose lease this
|
|
4
|
+
// launch holds; seeded with what was delivered, so the first look writes nothing. flush() looks once more now (the
|
|
5
|
+
// daemon calls it where claude-mem is saved) and, at the end, lets go of what must not stay taken.
|
|
6
|
+
import fs from 'node:fs';
|
|
7
|
+
import path from 'node:path';
|
|
8
|
+
import { fingerprint } from '../../shared/accounts/fingerprint.js';
|
|
9
|
+
import { HANDOFF_PARTS, SERVICE_SPECS } from '../../shared/accounts/kinds.js';
|
|
10
|
+
import { writeJsonAtomic } from '../../shared/io/json.js';
|
|
11
|
+
import { errMsg } from '../../core/util/errors.js';
|
|
12
|
+
import { ADAPTERS } from './adapters.js';
|
|
13
|
+
import { readDelivered } from './apply.js';
|
|
14
|
+
const DEFAULT_CHECK_MS = 60_000;
|
|
15
|
+
export class AccountWatch {
|
|
16
|
+
o;
|
|
17
|
+
last = new Map();
|
|
18
|
+
timers = [];
|
|
19
|
+
kinds;
|
|
20
|
+
constructor(kinds, o) {
|
|
21
|
+
this.o = o;
|
|
22
|
+
this.kinds = kinds.filter((k) => SERVICE_SPECS[k].returns && this.adapter(k).current);
|
|
23
|
+
const delivered = readDelivered(o.root);
|
|
24
|
+
for (const kind of this.kinds)
|
|
25
|
+
this.last.set(kind, delivered.fingerprints[kind] ?? null);
|
|
26
|
+
}
|
|
27
|
+
adapter(kind) {
|
|
28
|
+
return (this.o.adapters?.[kind] ?? ADAPTERS[kind]);
|
|
29
|
+
}
|
|
30
|
+
/** The kinds being watched. */
|
|
31
|
+
watched() {
|
|
32
|
+
return this.kinds;
|
|
33
|
+
}
|
|
34
|
+
start() {
|
|
35
|
+
for (const kind of this.kinds) {
|
|
36
|
+
const timer = setInterval(() => this.check(kind), this.adapter(kind).checkMs ?? DEFAULT_CHECK_MS);
|
|
37
|
+
timer.unref();
|
|
38
|
+
this.timers.push(timer);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
/** One look at one kind; true when a handoff was written. */
|
|
42
|
+
check(kind) {
|
|
43
|
+
try {
|
|
44
|
+
const now = this.adapter(kind).current?.() ?? null;
|
|
45
|
+
if (!now)
|
|
46
|
+
return false;
|
|
47
|
+
const print = fingerprint(now);
|
|
48
|
+
if (print === this.last.get(kind))
|
|
49
|
+
return false;
|
|
50
|
+
const file = path.join(this.o.dataDir, ...HANDOFF_PARTS, kind + '.json');
|
|
51
|
+
fs.mkdirSync(path.dirname(file), { recursive: true });
|
|
52
|
+
writeJsonAtomic(file, { kind, launchId: this.o.launchId, payload: now });
|
|
53
|
+
this.last.set(kind, print);
|
|
54
|
+
return true;
|
|
55
|
+
}
|
|
56
|
+
catch (e) {
|
|
57
|
+
this.o.warn?.(SERVICE_SPECS[kind].label + ' sign-in: could not keep it for the next sandbox: ' + errMsg(e));
|
|
58
|
+
return false;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
/** Looks at every kind now; with `final` (the sandbox stops) each adapter also lets go of what it holds. */
|
|
62
|
+
async flush(final = false) {
|
|
63
|
+
for (const kind of this.kinds)
|
|
64
|
+
this.check(kind);
|
|
65
|
+
if (!final)
|
|
66
|
+
return;
|
|
67
|
+
for (const timer of this.timers)
|
|
68
|
+
clearInterval(timer);
|
|
69
|
+
for (const kind of this.kinds) {
|
|
70
|
+
try {
|
|
71
|
+
await this.adapter(kind).release?.();
|
|
72
|
+
}
|
|
73
|
+
catch (e) {
|
|
74
|
+
this.o.warn?.(SERVICE_SPECS[kind].label + ': could not let go of the sign-in: ' + errMsg(e));
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
@@ -48,6 +48,12 @@ export declare function bootResetPaths(agents: Readonly<Record<string, Harness>>
|
|
|
48
48
|
agent: string;
|
|
49
49
|
path: string;
|
|
50
50
|
}[];
|
|
51
|
+
/**
|
|
52
|
+
* Codex's config.toml with its own command sandbox off, or null when it already says which one to use. Inside Windows
|
|
53
|
+
* Sandbox that inner sandbox only costs: its setup re-grants ACLs over the whole profile at every boot (minutes), and
|
|
54
|
+
* every command hangs until it is done. A `sandbox_mode` the user set (before the first [table]) is kept.
|
|
55
|
+
*/
|
|
56
|
+
export declare function codexConfigWithoutSandbox(toml: string): string | null;
|
|
51
57
|
/** A SQLite database file or one of its -wal / -shm siblings. */
|
|
52
58
|
export declare const isDatabaseFile: (name: string) => boolean;
|
|
53
59
|
/** Files that make a consistent copy: the databases and their -wal (the -shm is rebuilt by SQLite). */
|
|
@@ -61,6 +61,20 @@ export function localStateEntries(agents, stateDir, localRoot) {
|
|
|
61
61
|
export function bootResetPaths(agents, stateDir) {
|
|
62
62
|
return Object.entries(agents).flatMap(([agent, harness]) => (harness.bootReset ?? []).map((rel) => ({ agent, path: path.join(stateDir, agent, rel) })));
|
|
63
63
|
}
|
|
64
|
+
/**
|
|
65
|
+
* Codex's config.toml with its own command sandbox off, or null when it already says which one to use. Inside Windows
|
|
66
|
+
* Sandbox that inner sandbox only costs: its setup re-grants ACLs over the whole profile at every boot (minutes), and
|
|
67
|
+
* every command hangs until it is done. A `sandbox_mode` the user set (before the first [table]) is kept.
|
|
68
|
+
*/
|
|
69
|
+
export function codexConfigWithoutSandbox(toml) {
|
|
70
|
+
const firstTable = toml.search(/^\s*\[/m);
|
|
71
|
+
const topLevel = firstTable < 0 ? toml : toml.slice(0, firstTable);
|
|
72
|
+
if (/^\s*sandbox_mode\s*=/m.test(topLevel))
|
|
73
|
+
return null;
|
|
74
|
+
return ('# Set by the sandbox: Windows Sandbox already contains Codex, its own command sandbox would only slow it down.\n' +
|
|
75
|
+
'sandbox_mode = "danger-full-access"\n' +
|
|
76
|
+
(toml ? '\n' + toml : ''));
|
|
77
|
+
}
|
|
64
78
|
/** A SQLite database file or one of its -wal / -shm siblings. */
|
|
65
79
|
export const isDatabaseFile = (name) => /\.(sqlite3?|db)(-wal|-shm)?$/i.test(name);
|
|
66
80
|
/** Files that make a consistent copy: the databases and their -wal (the -shm is rebuilt by SQLite). */
|
|
@@ -5,6 +5,8 @@ export declare function agentLocalStates(): LocalState[];
|
|
|
5
5
|
export declare function localStateVars(): Record<string, string>;
|
|
6
6
|
/** Boot: what an agent sealed to the last sandbox (bootReset) is deleted, so it sets it up again. Links are left. */
|
|
7
7
|
export declare function resetMachineBound(): void;
|
|
8
|
+
/** Boot: Codex runs its commands without its own sandbox (codexConfigWithoutSandbox), unless the user picked one. */
|
|
9
|
+
export declare function codexWithoutInnerSandbox(): void;
|
|
8
10
|
/** Boot: the saved databases of every configured agent are copied to the sandbox's disk, where the agent runs them. */
|
|
9
11
|
export declare function restoreLocalState(): void;
|
|
10
12
|
/**
|
|
@@ -10,7 +10,7 @@ import { execOutput } from '../runtime/process.js';
|
|
|
10
10
|
import { log, warn } from '../runtime/log.js';
|
|
11
11
|
import { session, stateDir } from '../runtime/session.js';
|
|
12
12
|
import { errMsg } from '../../core/util/errors.js';
|
|
13
|
-
import { bootResetPaths, isCopyableDatabaseFile, isDatabaseFile, localStateEntries, } from './agent-files.js';
|
|
13
|
+
import { bootResetPaths, codexConfigWithoutSandbox, isCopyableDatabaseFile, isDatabaseFile, localStateEntries, } from './agent-files.js';
|
|
14
14
|
const SQLITE_HEADER = 'SQLite format 3\0';
|
|
15
15
|
/** The sandbox-disk folder that holds the working copies. */
|
|
16
16
|
const localRoot = () => path.join(localDir, 'agent-state');
|
|
@@ -102,6 +102,18 @@ export function resetMachineBound() {
|
|
|
102
102
|
}
|
|
103
103
|
}
|
|
104
104
|
}
|
|
105
|
+
/** Boot: Codex runs its commands without its own sandbox (codexConfigWithoutSandbox), unless the user picked one. */
|
|
106
|
+
export function codexWithoutInnerSandbox() {
|
|
107
|
+
if (dryRun || !session.agents?.codex)
|
|
108
|
+
return;
|
|
109
|
+
const file = path.join(stateDir, 'codex', 'config.toml');
|
|
110
|
+
const updated = codexConfigWithoutSandbox(exists(file) ? fs.readFileSync(file, 'utf8') : '');
|
|
111
|
+
if (updated === null)
|
|
112
|
+
return;
|
|
113
|
+
mkdirp(path.dirname(file));
|
|
114
|
+
fs.writeFileSync(file, updated, 'utf8');
|
|
115
|
+
log('codex: its own command sandbox is off (sandbox_mode = "danger-full-access" in config.toml).');
|
|
116
|
+
}
|
|
105
117
|
/** Boot: the saved databases of every configured agent are copied to the sandbox's disk, where the agent runs them. */
|
|
106
118
|
export function restoreLocalState() {
|
|
107
119
|
if (dryRun)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const GAMEDEV_RESOLVERS = {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const MOBILE_RESOLVERS = {};
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
// Where the latest version of an app is, for apps that are not a plain GitHub release: each looks it up on the
|
|
2
2
|
// vendor's own site (and its published checksum, where there is one). Named by AppSource.resolve in shared/apps.ts.
|
|
3
3
|
import { fetchJson, fetchText, githubAsset, latestGithubTag } from '../../shared/download/index.js';
|
|
4
|
+
import { GAMEDEV_RESOLVERS } from './resolvers-gamedev.js';
|
|
5
|
+
import { MOBILE_RESOLVERS } from './resolvers-mobile.js';
|
|
4
6
|
/** The SHA-256 on the line of a SHA256SUMS-style file that names `file`. */
|
|
5
7
|
const sumFor = (sums, file) => sums
|
|
6
8
|
.split(/\r?\n/)
|
|
@@ -10,6 +12,8 @@ const sumFor = (sums, file) => sums
|
|
|
10
12
|
const firstHash = (text) => /\b([0-9a-f]{64})\b/i.exec(text)?.[1].toLowerCase() ?? null;
|
|
11
13
|
const stripV = (tag) => tag.replace(/^v/, '');
|
|
12
14
|
export const RESOLVERS = {
|
|
15
|
+
...GAMEDEV_RESOLVERS,
|
|
16
|
+
...MOBILE_RESOLVERS,
|
|
13
17
|
sublime: async () => {
|
|
14
18
|
// Sublime publishes no checksums; the download is HTTPS from sublimetext.com.
|
|
15
19
|
const { latest_version: build } = await fetchJson('https://www.sublimetext.com/updates/4/stable_update_check');
|
|
@@ -6,6 +6,11 @@ export declare class Boot {
|
|
|
6
6
|
/** What the host handed over in its one-shot file (read and deleted at the start of run()). */
|
|
7
7
|
private secrets;
|
|
8
8
|
run(): Promise<void>;
|
|
9
|
+
/**
|
|
10
|
+
* Your saved service sign-ins (accounts.<kind>.share) go to their tools before anything opens them, and leave memory
|
|
11
|
+
* at once; what they give the agent (EXPO_TOKEN ...) joins its environment (in memory only).
|
|
12
|
+
*/
|
|
13
|
+
private serviceAccounts;
|
|
9
14
|
private networkAndSessionHost;
|
|
10
15
|
private hooksAndDesktop;
|
|
11
16
|
/** Toolchains, databases, apps, the network proxy and VS Code; then the agent environment, saved machine-wide. */
|
package/dist/guest/boot/boot.js
CHANGED
|
@@ -6,7 +6,7 @@ import { writeGuides } from './guide.js';
|
|
|
6
6
|
import { setupToolchains } from '../toolchains/index.js';
|
|
7
7
|
import { agents } from '../agents/agent-installer.js';
|
|
8
8
|
import { agentShims, sbxAgentText, shimText } from '../agents/agent-files.js';
|
|
9
|
-
import { resetMachineBound, restoreLocalState } from '../agents/local-state.js';
|
|
9
|
+
import { codexWithoutInnerSandbox, resetMachineBound, restoreLocalState } from '../agents/local-state.js';
|
|
10
10
|
import { installShellPath } from '../setup/shell-path.js';
|
|
11
11
|
import { linkProfileDirs } from '../agents/profile-links.js';
|
|
12
12
|
import { restoreClaudeMem } from '../setup/claude-mem.js';
|
|
@@ -22,6 +22,8 @@ import { applyPersonalization } from '../setup/desktop.js';
|
|
|
22
22
|
import { keepBrowsersOffGpu } from '../setup/browser-gpu.js';
|
|
23
23
|
import { setupGitConfig } from '../setup/git-identity.js';
|
|
24
24
|
import { loginGithub, prepareGithubFolder } from '../setup/github-token.js';
|
|
25
|
+
import { applyServiceAccounts } from '../accounts/apply.js';
|
|
26
|
+
import { devToolsFor } from '../devtools/registry.js';
|
|
25
27
|
import { ensurePtyHost } from '../sessions/pty-host.js';
|
|
26
28
|
import { pruneToolLeftovers } from '../toolchains/leftovers.js';
|
|
27
29
|
import { wanted } from '../toolchains/detect.js';
|
|
@@ -95,8 +97,23 @@ function writeDbCommand() {
|
|
|
95
97
|
const db = path.join(path.dirname(process.argv[1]), 'db.js');
|
|
96
98
|
fs.writeFileSync(path.join(dir, 'sbx-db.cmd'), '@setlocal\r\n@set AGENT_LOG_PREFIX=db\r\n@"' + process.execPath + '" "' + db + '" %*\r\n');
|
|
97
99
|
writeAgentCommands(dir);
|
|
100
|
+
writeDevToolCommands(dir);
|
|
98
101
|
return dir;
|
|
99
102
|
}
|
|
103
|
+
/** sbx-steam, sbx-fivem, sbx-unity, sbx-android for the toolchains that are on: runtime\tool.js with that helper. */
|
|
104
|
+
function writeDevToolCommands(dir) {
|
|
105
|
+
const script = path.join(path.dirname(process.argv[1]), 'tool.js');
|
|
106
|
+
for (const tool of devToolsFor(session.toolchains))
|
|
107
|
+
fs.writeFileSync(path.join(dir, 'sbx-' + tool.name + '.cmd'), '@setlocal\r\n@set AGENT_LOG_PREFIX=' +
|
|
108
|
+
tool.name +
|
|
109
|
+
'\r\n@"' +
|
|
110
|
+
process.execPath +
|
|
111
|
+
'" "' +
|
|
112
|
+
script +
|
|
113
|
+
'" ' +
|
|
114
|
+
tool.name +
|
|
115
|
+
' %*\r\n');
|
|
116
|
+
}
|
|
100
117
|
/**
|
|
101
118
|
* `claude`, `codex` ... by name in every terminal tab, installed yet or not (the command installs the agent on first
|
|
102
119
|
* use), and `sbx-agent`. Written to the sandbox's disk each boot, next to `sbx-db`.
|
|
@@ -146,6 +163,7 @@ export class Boot {
|
|
|
146
163
|
mkdirp(toolsDir);
|
|
147
164
|
mkdirp(run.root);
|
|
148
165
|
this.secrets = takeSecrets(session.launchId);
|
|
166
|
+
await this.serviceAccounts();
|
|
149
167
|
applyBootEnvironment(this.secrets.harnessEnvironment);
|
|
150
168
|
prepareGithubFolder(this.secrets.githubToken);
|
|
151
169
|
await this.networkAndSessionHost();
|
|
@@ -158,6 +176,21 @@ export class Boot {
|
|
|
158
176
|
this.preAgentHooks(env);
|
|
159
177
|
await this.start(env);
|
|
160
178
|
}
|
|
179
|
+
/**
|
|
180
|
+
* Your saved service sign-ins (accounts.<kind>.share) go to their tools before anything opens them, and leave memory
|
|
181
|
+
* at once; what they give the agent (EXPO_TOKEN ...) joins its environment (in memory only).
|
|
182
|
+
*/
|
|
183
|
+
async serviceAccounts() {
|
|
184
|
+
const given = this.secrets.serviceAccounts;
|
|
185
|
+
this.secrets = { ...this.secrets, serviceAccounts: undefined };
|
|
186
|
+
if (dryRun || (!given && !session.accountLeases?.length))
|
|
187
|
+
return;
|
|
188
|
+
await soft('Service sign-ins', async () => {
|
|
189
|
+
const env = await applyServiceAccounts(given, { leased: session.accountLeases ?? [], say: (line) => log(line) });
|
|
190
|
+
if (Object.keys(env).length)
|
|
191
|
+
this.secrets = { ...this.secrets, harnessEnvironment: { ...env, ...this.secrets.harnessEnvironment } };
|
|
192
|
+
});
|
|
193
|
+
}
|
|
161
194
|
async networkAndSessionHost() {
|
|
162
195
|
step(1, 'Network and session host');
|
|
163
196
|
if (isWin && !dryRun && session.attach.enabled)
|
|
@@ -186,6 +219,7 @@ export class Boot {
|
|
|
186
219
|
refresh: session.provisioning.refresh,
|
|
187
220
|
databases: session.databases ?? [],
|
|
188
221
|
apps: session.apps,
|
|
222
|
+
...(session.pcInstalls ? { pcInstalls: session.pcInstalls } : {}),
|
|
189
223
|
});
|
|
190
224
|
for (const p of networkProblems())
|
|
191
225
|
tools.summary.push('PROTECTION MISSING: ' + p);
|
|
@@ -246,6 +280,7 @@ export class Boot {
|
|
|
246
280
|
await soft('Claude settings', () => syncClaudeProfile(this.secrets.claudeCredentials));
|
|
247
281
|
await soft('claude-mem restore', restoreClaudeMem);
|
|
248
282
|
await soft('Agent files of the last sandbox', resetMachineBound);
|
|
283
|
+
await soft('Codex without its own sandbox', codexWithoutInnerSandbox);
|
|
249
284
|
await soft('Agent databases restore', restoreLocalState);
|
|
250
285
|
// Agent add-ons: MCP servers in the sandbox's Claude Code, and the Headroom proxy before the managed settings point
|
|
251
286
|
// Claude Code at it (the guide reads them back, so it comes last).
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
// The daemon's one watch over the service sign-ins this launch may hand back (session.json accountLeases), and its
|
|
2
|
+
// flush where claude-mem is saved (every 2 minutes, when a session ends, before an idle shutdown).
|
|
3
|
+
import { AccountWatch } from '../accounts/watch.js';
|
|
4
|
+
import { dataDir } from '../runtime/paths.js';
|
|
5
|
+
import { log, warn } from '../runtime/log.js';
|
|
6
|
+
import { session } from '../runtime/session.js';
|
|
7
|
+
let watch = null;
|
|
8
|
+
export function startAccountWatch() {
|
|
9
|
+
const kinds = session.accountLeases ?? [];
|
|
10
|
+
if (!kinds.length)
|
|
11
|
+
return;
|
|
12
|
+
watch = new AccountWatch(kinds, { dataDir, launchId: session.launchId, warn });
|
|
13
|
+
watch.start();
|
|
14
|
+
if (watch.watched().length)
|
|
15
|
+
log('Service sign-ins kept for the next sandbox: ' + watch.watched().join(', '));
|
|
16
|
+
}
|
|
17
|
+
/** Looks once more now; `final` (the sandbox stops) also lets go of what must not stay taken. Never throws. */
|
|
18
|
+
export async function flushAccounts(final = false) {
|
|
19
|
+
try {
|
|
20
|
+
await watch?.flush(final);
|
|
21
|
+
}
|
|
22
|
+
catch (e) {
|
|
23
|
+
warn('service sign-ins: ' + String(e));
|
|
24
|
+
}
|
|
25
|
+
}
|
|
@@ -11,6 +11,7 @@ import { withRequestSecrets } from '../runtime/secrets.js';
|
|
|
11
11
|
import { liveFolders } from './live.js';
|
|
12
12
|
import { warn } from '../runtime/log.js';
|
|
13
13
|
import { errMsg } from '../../core/util/errors.js';
|
|
14
|
+
import { flushAccounts } from './accounts.js';
|
|
14
15
|
const POLL_MS = 400;
|
|
15
16
|
const MEM_SAVE_MS = 120000;
|
|
16
17
|
export class Daemon {
|
|
@@ -45,6 +46,7 @@ export class Daemon {
|
|
|
45
46
|
this.lastMemSave = Date.now();
|
|
46
47
|
safely('claude-mem save', saveClaudeMem);
|
|
47
48
|
safely('agent databases save', saveLocalState);
|
|
49
|
+
void flushAccounts();
|
|
48
50
|
}
|
|
49
51
|
}
|
|
50
52
|
handle(req) {
|
|
@@ -8,6 +8,7 @@ import { isWin, run } from '../runtime/paths.js';
|
|
|
8
8
|
import { log } from '../runtime/log.js';
|
|
9
9
|
import { session } from '../runtime/session.js';
|
|
10
10
|
import { safely } from './state.js';
|
|
11
|
+
import { flushAccounts } from './accounts.js';
|
|
11
12
|
/** How long the sandbox must stay idle before it shuts down. */
|
|
12
13
|
const GRACE_MS = 15000;
|
|
13
14
|
export class IdleShutdown {
|
|
@@ -28,7 +29,8 @@ export class IdleShutdown {
|
|
|
28
29
|
log('Headless sandbox has no sessions left; shutting down.');
|
|
29
30
|
safely('claude-mem save', saveClaudeMem);
|
|
30
31
|
safely('agent databases save', saveLocalState);
|
|
31
|
-
|
|
32
|
+
// Renewed sign-ins go to the PC, and a held one (a Unity seat) is let go, before Windows stops.
|
|
33
|
+
void flushAccounts(true).finally(() => spawnSync(SYSTEM.shutdown(), ['/s', '/t', '5'], { windowsHide: true }));
|
|
32
34
|
}, GRACE_MS);
|
|
33
35
|
}
|
|
34
36
|
idle() {
|