windows-development-sandbox 1.16.0 → 1.17.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.
Files changed (58) hide show
  1. package/config.example.json +6 -0
  2. package/dist/app/features/access/access.run.js +1 -1
  3. package/dist/bin/agent-sandbox.js +2 -2
  4. package/dist/bin/{chunk-7EXDUNE7.js → chunk-QLGGAG3D.js} +1 -1
  5. package/dist/bin/{chunk-HIC4CUMY.js → chunk-REE3EMHD.js} +73 -16
  6. package/dist/bin/{chunk-PXTLKIV4.js → chunk-XYUVIVJT.js} +1 -1
  7. package/dist/bin/claude-host.js +2 -2
  8. package/dist/bin/claude-sbx.js +2 -2
  9. package/dist/bin/codex-sbx.js +2 -2
  10. package/dist/bin/gemini-sbx.js +2 -2
  11. package/dist/bin/sandbox.js +2 -2
  12. package/dist/bin/sbx-hide.js +2 -2
  13. package/dist/bin/sbx-show.js +2 -2
  14. package/dist/cli/commands/web.js +1 -1
  15. package/dist/core/config/defaults.js +1 -0
  16. package/dist/core/detect/toolchains.d.ts +1 -0
  17. package/dist/core/detect/toolchains.js +7 -0
  18. package/dist/core/schema/config.d.ts +21 -0
  19. package/dist/core/schema/sandbox.js +1 -1
  20. package/dist/core/schema/toolchains.d.ts +6 -0
  21. package/dist/core/schema/toolchains.js +10 -0
  22. package/dist/guest/boot/boot.js +2 -0
  23. package/dist/guest/setup/browser-gpu.d.ts +1 -0
  24. package/dist/guest/setup/browser-gpu.js +18 -0
  25. package/dist/guest/toolchains/native/rust-extras.js +3 -1
  26. package/dist/guest/toolchains/native/unreal.d.ts +9 -0
  27. package/dist/guest/toolchains/native/unreal.js +186 -0
  28. package/dist/guest/toolchains/native/vcruntime.d.ts +3 -0
  29. package/dist/guest/toolchains/native/vcruntime.js +2 -2
  30. package/dist/guest/toolchains/plan.js +10 -2
  31. package/dist/host/engines/hcs/live-folders.js +1 -1
  32. package/dist/host/github/token.js +1 -1
  33. package/dist/host/profile/accounts.js +1 -1
  34. package/dist/host/profile/agent-accounts.js +1 -1
  35. package/dist/host/profile/plugin-share.d.ts +5 -0
  36. package/dist/host/profile/plugin-share.js +22 -1
  37. package/dist/host/secrets/secret-store.d.ts +3 -3
  38. package/dist/host/secrets/secret-store.js +37 -10
  39. package/dist/host/vpn/login.js +1 -1
  40. package/dist/runtime/agent.js +16 -1
  41. package/dist/runtime/daemon.js +522 -337
  42. package/dist/runtime/db.js +17 -1
  43. package/dist/runtime/main.js +669 -472
  44. package/dist/runtime/netproxy.js +16 -1
  45. package/dist/runtime/view.js +16 -1
  46. package/dist/selftest/accounts.test.js +7 -0
  47. package/dist/selftest/detect.test.js +7 -0
  48. package/dist/selftest/live-network.test.js +5 -0
  49. package/dist/selftest/support/fixtures.d.ts +6 -0
  50. package/dist/shared/channel/schema.d.ts +18 -0
  51. package/native/csharp/HcsHost/AssemblyInfo.cs +3 -3
  52. package/native/csharp/HostTools/AssemblyInfo.cs +3 -3
  53. package/native/csharp/HostTools/Program.cs +6 -1
  54. package/native/csharp/HostTools/Protect.cs +41 -0
  55. package/native/csharp/StorageHelper/AssemblyInfo.cs +3 -3
  56. package/package.json +1 -1
  57. package/schemas/config.schema.json +34 -1
  58. package/schemas/sandbox-config.schema.json +34 -1
@@ -118,6 +118,12 @@
118
118
  "msvcVersion": "latest",
119
119
  "sdkVersion": "latest"
120
120
  },
121
+ "unreal": {
122
+ "enabled": "auto",
123
+ "acceptLicense": false,
124
+ "components": [],
125
+ "keepInstallFiles": true
126
+ },
121
127
  "cpp": {
122
128
  "enabled": "auto",
123
129
  "flexBison": true
@@ -14,7 +14,7 @@ import { ConfigFile } from '../settings/index.js';
14
14
  import { accessStatus, allowDevice, lanOff, lanOn, revokeAccess, revokeAllAccess } from './access.def.js';
15
15
  /** The access list of this user (the folder is the web state's private one). */
16
16
  export function accessStoreOf(ctx) {
17
- return AccessStore.at(ctx.storageRoot, SecretStore.standard(), {
17
+ return AccessStore.at(ctx.storageRoot, SecretStore.standard(ctx.storageRoot), {
18
18
  // The self-test never changes folder permissions; its storage is a temp folder.
19
19
  protect: selfTestRunning() ? undefined : (dir) => protectPrivateFolder(dir),
20
20
  });
@@ -2,8 +2,8 @@
2
2
  import { createRequire as __createRequire } from 'node:module'; const require = __createRequire(import.meta.url);
3
3
  import {
4
4
  run
5
- } from "./chunk-7EXDUNE7.js";
6
- import "./chunk-HIC4CUMY.js";
5
+ } from "./chunk-QLGGAG3D.js";
6
+ import "./chunk-REE3EMHD.js";
7
7
 
8
8
  // src/bin/agent-sandbox.ts
9
9
  run(process.argv.slice(2));
@@ -226,7 +226,7 @@ import {
226
226
  withOperationCommands,
227
227
  working,
228
228
  writeJson
229
- } from "./chunk-HIC4CUMY.js";
229
+ } from "./chunk-REE3EMHD.js";
230
230
 
231
231
  // node_modules/commander/lib/error.js
232
232
  var require_error = __commonJS({
@@ -25938,6 +25938,7 @@ var DEFAULTS = {
25938
25938
  linkSlots: "auto"
25939
25939
  },
25940
25940
  msvc: { enabled: "auto", acceptLicense: false, msvcVersion: "latest", sdkVersion: "latest" },
25941
+ unreal: { enabled: "auto", acceptLicense: false, components: [], keepInstallFiles: true },
25941
25942
  cpp: { enabled: "auto", flexBison: true },
25942
25943
  dotnet: {
25943
25944
  enabled: "auto",
@@ -46053,7 +46054,7 @@ var SandboxSchema = external_exports.strictObject({
46053
46054
  "When the sandbox (or this PC) runs low on memory, slow builds down in steps, like a PC that gets slower instead of failing: build programs get lower CPU and memory priority, then less CPU, then compilers take turns (the waiting ones briefly suspended and trimmed to the paging file). Nothing is stopped or killed, and the agents themselves are never touched. Yours only: a project file cannot change it."
46054
46055
  ),
46055
46056
  vGpu: external_exports.boolean().describe(
46056
- "Virtual GPU. Off by default: Microsoft notes it widens the sandbox attack surface. The sandbox then uses this PC's graphics card, and with some graphics drivers heavy use can freeze the whole PC: turn it on only when a program in the sandbox needs the GPU (the mesa toolchain gives software OpenGL without it)."
46057
+ "Virtual GPU. Off by default: Microsoft notes it widens the sandbox attack surface. The sandbox then uses this PC's graphics card, and with some graphics drivers heavy use can freeze the whole PC: turn it on only when a program in the sandbox needs the GPU (the mesa toolchain gives software OpenGL without it). Browsers in the sandbox never use it (they draw in software)."
46057
46058
  ),
46058
46059
  networking: external_exports.boolean().describe("Internet access. false is the only hard network isolation Windows Sandbox offers."),
46059
46060
  clipboard: external_exports.boolean().describe(
@@ -46215,6 +46216,21 @@ var ToolchainsSchema = external_exports.strictObject({
46215
46216
  msvcVersion: external_exports.string().min(1).describe('"latest" or an MSVC tools version prefix, e.g. "14.44".'),
46216
46217
  sdkVersion: external_exports.string().min(1).describe('"latest" or a Windows SDK build, e.g. "26100" or "10.0.22621".')
46217
46218
  }),
46219
+ unreal: external_exports.strictObject({
46220
+ enabled: enabled(
46221
+ "Unreal Engine development: Visual Studio Community 2022 with the C++ game workload (MSVC, a Windows 11 SDK, .NET Framework targeting packs, Unreal integration and the Epic Games Launcher) and the DirectX End-User Runtime. A real installer: it runs every boot (~10 GB on the sandbox disk). The engine itself comes from the Epic Games Launcher or its source.",
46222
+ "a .uproject or .uplugin"
46223
+ ),
46224
+ acceptLicense: external_exports.boolean().describe(
46225
+ "Required to install: you accept the Visual Studio Community licence terms (https://visualstudio.microsoft.com/license-terms/) and the DirectX End-User Runtime licence."
46226
+ ),
46227
+ components: StringsSchema.describe(
46228
+ 'More Visual Studio workload or component IDs to add, e.g. ["Microsoft.VisualStudio.Component.VC.Llvm.Clang"].'
46229
+ ),
46230
+ keepInstallFiles: external_exports.boolean().describe(
46231
+ "Keep an offline copy of the Visual Studio install files in tools\\visualstudio (~10 GB, made once), so later boots install without downloading them again. Skipped while that disk has too little room."
46232
+ )
46233
+ }),
46218
46234
  cpp: external_exports.strictObject({
46219
46235
  enabled: enabled(
46220
46236
  "MinGW-w64 GCC with CMake, Ninja, premake5 and mingw32-make (also Rust's linker).",
@@ -54689,7 +54705,23 @@ import { spawn as spawn8 } from "node:child_process";
54689
54705
  // src/host/secrets/secret-store.ts
54690
54706
  import { spawnSync as spawnSync19 } from "node:child_process";
54691
54707
  var TIMEOUT_MS2 = 6e4;
54708
+ var toolsFor = /* @__PURE__ */ new Map();
54709
+ function dpapiTool(storageRoot) {
54710
+ if (!toolsFor.has(storageRoot)) {
54711
+ let exe = null;
54712
+ try {
54713
+ exe = hostToolsExe(storageRoot);
54714
+ } catch {
54715
+ }
54716
+ toolsFor.set(storageRoot, exe);
54717
+ }
54718
+ return toolsFor.get(storageRoot) ?? null;
54719
+ }
54692
54720
  var DpapiBox = class {
54721
+ constructor(storageRoot) {
54722
+ this.storageRoot = storageRoot;
54723
+ }
54724
+ storageRoot;
54693
54725
  kind = "dpapi1";
54694
54726
  seal(plain2) {
54695
54727
  return this.run("protect", plain2.toString("base64"));
@@ -54698,7 +54730,9 @@ var DpapiBox = class {
54698
54730
  return Buffer.from(this.run("unprotect", sealed), "base64");
54699
54731
  }
54700
54732
  run(mode, input2) {
54701
- const result = spawnSync19(SYSTEM.powershell(), nativeScript("protect-data.ps1", ["-Mode", mode]), {
54733
+ const tools = this.storageRoot ? dpapiTool(this.storageRoot) : null;
54734
+ const [exe, args] = tools ? [tools, [mode]] : [SYSTEM.powershell(), nativeScript("protect-data.ps1", ["-Mode", mode])];
54735
+ const result = spawnSync19(exe, args, {
54702
54736
  input: input2,
54703
54737
  encoding: "utf8",
54704
54738
  windowsHide: true,
@@ -54726,17 +54760,17 @@ var SecretStore = class _SecretStore {
54726
54760
  this.box = box;
54727
54761
  }
54728
54762
  box;
54729
- /** Windows DPAPI, current user. */
54730
- static dpapi() {
54731
- return new _SecretStore(new DpapiBox());
54763
+ /** Windows DPAPI, current user; with a storage folder, through its HostTools.exe (much faster than PowerShell). */
54764
+ static dpapi(storageRoot = null) {
54765
+ return new _SecretStore(new DpapiBox(storageRoot));
54732
54766
  }
54733
54767
  /** The test stand-in (not secure). */
54734
54768
  static memory() {
54735
54769
  return new _SecretStore(new MemoryBox());
54736
54770
  }
54737
54771
  /** What the program uses: DPAPI, except during the self-test (it never spawns Windows for this). */
54738
- static standard() {
54739
- return selfTestRunning() ? _SecretStore.memory() : _SecretStore.dpapi();
54772
+ static standard(storageRoot = null) {
54773
+ return selfTestRunning() ? _SecretStore.memory() : _SecretStore.dpapi(storageRoot);
54740
54774
  }
54741
54775
  /** True when `value` looks like something seal() made (any box). */
54742
54776
  static isSealed(value) {
@@ -55134,7 +55168,7 @@ function realLiveFolders(storageRoot, dataPath) {
55134
55168
  return new LiveFolders({
55135
55169
  storageRoot,
55136
55170
  dataPath,
55137
- secrets: SecretStore.standard(),
55171
+ secrets: SecretStore.standard(storageRoot),
55138
55172
  elevated: new ScriptLivePort(),
55139
55173
  userSid: currentUserSid,
55140
55174
  isAlive: isSandboxRunning
@@ -56008,6 +56042,8 @@ var MAX_PLUGIN_BYTES = 1024 * 1024 * 1024;
56008
56042
  var MAX_SETTINGS_BYTES = 4 * 1024 * 1024;
56009
56043
  var MAX_DEPTH = 24;
56010
56044
  var INSTALLED = "installed_plugins.json";
56045
+ var RECORDS = [INSTALLED, "known_marketplaces.json"];
56046
+ var MAX_RECORD_BYTES2 = 4 * 1024 * 1024;
56011
56047
  function isObject2(value) {
56012
56048
  return typeof value === "object" && value !== null && !Array.isArray(value);
56013
56049
  }
@@ -56054,7 +56090,7 @@ var PluginShare = class _PluginShare {
56054
56090
  /** When a sandbox ends: its plugins refresh the shared set. Never throws; returns the problem, if any. */
56055
56091
  saveQuietly(dataPath, claudeDir) {
56056
56092
  try {
56057
- if (_PluginShare.hasPlugins(claudeDir)) this.save(dataPath, claudeDir);
56093
+ if (_PluginShare.hasPlugins(claudeDir) && !this.matches(claudeDir)) this.save(dataPath, claudeDir);
56058
56094
  return null;
56059
56095
  } catch (e) {
56060
56096
  return errMsg(e);
@@ -56108,9 +56144,24 @@ var PluginShare = class _PluginShare {
56108
56144
  if (isObject2(shared[key3])) merged[key3] = { ...shared[key3], ...isObject2(merged[key3]) ? merged[key3] : {} };
56109
56145
  writeSandboxJson(file2, merged);
56110
56146
  }
56147
+ /**
56148
+ * Whether the shared set already holds this Claude folder's plugins: the same plugin records and plugin settings.
56149
+ * Copying a big plugins folder takes seconds, so a switch between accounts with the same plugins skips it.
56150
+ */
56151
+ matches(claudeDir) {
56152
+ if (!this.hasShared()) return false;
56153
+ const same3 = (a, b) => JSON.stringify(a) === JSON.stringify(b);
56154
+ for (const name2 of RECORDS) {
56155
+ const own2 = readUntrusted(path67.join(claudeDir, "plugins", name2), MAX_RECORD_BYTES2);
56156
+ if (!same3(own2, readUntrusted(path67.join(this.pluginsDir, name2), MAX_RECORD_BYTES2))) return false;
56157
+ }
56158
+ const shared = readUntrusted(this.settingsFile, MAX_SETTINGS_BYTES);
56159
+ return same3(pluginSettings(claudeDir), isObject2(shared) ? shared : {});
56160
+ }
56111
56161
  /** One step when an account is switched to. */
56112
56162
  sync(dataPath, claudeDir) {
56113
56163
  if (_PluginShare.hasPlugins(claudeDir)) {
56164
+ if (this.matches(claudeDir)) return "nothing";
56114
56165
  this.save(dataPath, claudeDir);
56115
56166
  return "saved";
56116
56167
  }
@@ -56170,7 +56221,7 @@ function assertName(name2) {
56170
56221
  }
56171
56222
  var AccountStore = class {
56172
56223
  /** @param sharePlugins claudeProfile.sharePluginsAcrossAccounts: carry Claude plugins to the account switched to */
56173
- constructor(storageRoot, sharePlugins = false, secrets = SecretStore.standard()) {
56224
+ constructor(storageRoot, sharePlugins = false, secrets = SecretStore.standard(storageRoot)) {
56174
56225
  this.storageRoot = storageRoot;
56175
56226
  this.sharePlugins = sharePlugins;
56176
56227
  this.secrets = secrets;
@@ -56345,7 +56396,7 @@ var AgentAccountStore = class {
56345
56396
  /**
56346
56397
  * @param loginFiles files of the login, relative to the folder they are read from and written to
56347
56398
  */
56348
- constructor(storageRoot, agent, loginFiles, secrets = SecretStore.standard()) {
56399
+ constructor(storageRoot, agent, loginFiles, secrets = SecretStore.standard(storageRoot)) {
56349
56400
  this.storageRoot = storageRoot;
56350
56401
  this.agent = agent;
56351
56402
  this.loginFiles = loginFiles;
@@ -56508,7 +56559,7 @@ function checkGithubToken(token) {
56508
56559
  return githubTokenKind(token) ?? fail("That is not a GitHub personal access token.", "Run: sandbox github login");
56509
56560
  }
56510
56561
  var GithubToken = class {
56511
- constructor(storageRoot, secrets = SecretStore.standard()) {
56562
+ constructor(storageRoot, secrets = SecretStore.standard(storageRoot)) {
56512
56563
  this.storageRoot = storageRoot;
56513
56564
  this.secrets = secrets;
56514
56565
  }
@@ -57191,6 +57242,7 @@ var MARKERS = {
57191
57242
  ],
57192
57243
  rust: ["Cargo.toml", "rust-toolchain", "rust-toolchain.toml"],
57193
57244
  msvc: ["*.vcxproj", "CMakePresets.json", "CMakeUserPresets.json"],
57245
+ unreal: ["*.uproject", "*.uplugin"],
57194
57246
  cpp: [
57195
57247
  "CMakeLists.txt",
57196
57248
  "Makefile",
@@ -57249,6 +57301,11 @@ function decideToolchains(settings, entries, pcHas, hints = {}) {
57249
57301
  on: false,
57250
57302
  reason: "would be used (" + result.msvc.reason + "); set toolchains.msvc.acceptLicense to install it"
57251
57303
  };
57304
+ if (settings.unreal.enabled === "auto" && result.unreal.on && !settings.unreal.acceptLicense)
57305
+ result.unreal = {
57306
+ on: false,
57307
+ reason: "would be used (" + result.unreal.reason + "); set toolchains.unreal.acceptLicense to install it"
57308
+ };
57252
57309
  if (result.rust.on && !result.msvc.on && !result.cpp.on && settings.cpp.enabled !== false)
57253
57310
  result.cpp = { on: true, reason: "the linker for Rust" };
57254
57311
  if (result.python.on && settings.uv.enabled === "auto" && settings.python.tools.length > 0 && !result.uv.on)
@@ -59144,7 +59201,7 @@ function loginProblem(c2) {
59144
59201
  return null;
59145
59202
  }
59146
59203
  var VpnLogin = class {
59147
- constructor(storageRoot, secrets = SecretStore.standard()) {
59204
+ constructor(storageRoot, secrets = SecretStore.standard(storageRoot)) {
59148
59205
  this.storageRoot = storageRoot;
59149
59206
  this.secrets = secrets;
59150
59207
  }
@@ -70288,7 +70345,7 @@ var TlsStore = class {
70288
70345
 
70289
70346
  // src/app/features/access/access.run.ts
70290
70347
  function accessStoreOf(ctx) {
70291
- return AccessStore.at(ctx.storageRoot, SecretStore.standard(), {
70348
+ return AccessStore.at(ctx.storageRoot, SecretStore.standard(ctx.storageRoot), {
70292
70349
  // The self-test never changes folder permissions; its storage is a temp folder.
70293
70350
  protect: selfTestRunning() ? void 0 : (dir) => protectPrivateFolder(dir)
70294
70351
  });
@@ -78297,7 +78354,7 @@ async function attachOpened(ctx, session) {
78297
78354
  nextStep("sandbox attach " + session);
78298
78355
  return 0;
78299
78356
  }
78300
- const { attach: attach2 } = await import("./chunk-PXTLKIV4.js");
78357
+ const { attach: attach2 } = await import("./chunk-XYUVIVJT.js");
78301
78358
  return attach2({ ...ctx, options: { ...ctx.options, positionals: [session] } });
78302
78359
  }
78303
78360
  function definitionHandler(def) {
@@ -78389,7 +78446,7 @@ function remoteAudit(ctx) {
78389
78446
  };
78390
78447
  }
78391
78448
  function remoteGate(ctx) {
78392
- const secrets = SecretStore.standard();
78449
+ const secrets = SecretStore.standard(ctx.storageRoot);
78393
78450
  let ownerSid = "";
78394
78451
  try {
78395
78452
  ownerSid = currentUserSid();
@@ -1,7 +1,7 @@
1
1
  import { createRequire as __createRequire } from 'node:module'; const require = __createRequire(import.meta.url);
2
2
  import {
3
3
  attach
4
- } from "./chunk-HIC4CUMY.js";
4
+ } from "./chunk-REE3EMHD.js";
5
5
  export {
6
6
  attach
7
7
  };
@@ -2,8 +2,8 @@
2
2
  import { createRequire as __createRequire } from 'node:module'; const require = __createRequire(import.meta.url);
3
3
  import {
4
4
  run
5
- } from "./chunk-7EXDUNE7.js";
6
- import "./chunk-HIC4CUMY.js";
5
+ } from "./chunk-QLGGAG3D.js";
6
+ import "./chunk-REE3EMHD.js";
7
7
 
8
8
  // src/bin/claude-host.ts
9
9
  var args = process.argv.slice(2);
@@ -2,8 +2,8 @@
2
2
  import { createRequire as __createRequire } from 'node:module'; const require = __createRequire(import.meta.url);
3
3
  import {
4
4
  run
5
- } from "./chunk-7EXDUNE7.js";
6
- import "./chunk-HIC4CUMY.js";
5
+ } from "./chunk-QLGGAG3D.js";
6
+ import "./chunk-REE3EMHD.js";
7
7
 
8
8
  // src/bin/claude-sbx.ts
9
9
  run(process.argv.slice(2), { harness: "claude" });
@@ -2,8 +2,8 @@
2
2
  import { createRequire as __createRequire } from 'node:module'; const require = __createRequire(import.meta.url);
3
3
  import {
4
4
  run
5
- } from "./chunk-7EXDUNE7.js";
6
- import "./chunk-HIC4CUMY.js";
5
+ } from "./chunk-QLGGAG3D.js";
6
+ import "./chunk-REE3EMHD.js";
7
7
 
8
8
  // src/bin/codex-sbx.ts
9
9
  run(process.argv.slice(2), { harness: "codex" });
@@ -2,8 +2,8 @@
2
2
  import { createRequire as __createRequire } from 'node:module'; const require = __createRequire(import.meta.url);
3
3
  import {
4
4
  run
5
- } from "./chunk-7EXDUNE7.js";
6
- import "./chunk-HIC4CUMY.js";
5
+ } from "./chunk-QLGGAG3D.js";
6
+ import "./chunk-REE3EMHD.js";
7
7
 
8
8
  // src/bin/gemini-sbx.ts
9
9
  run(process.argv.slice(2), { harness: "gemini" });
@@ -2,8 +2,8 @@
2
2
  import { createRequire as __createRequire } from 'node:module'; const require = __createRequire(import.meta.url);
3
3
  import {
4
4
  run
5
- } from "./chunk-7EXDUNE7.js";
6
- import "./chunk-HIC4CUMY.js";
5
+ } from "./chunk-QLGGAG3D.js";
6
+ import "./chunk-REE3EMHD.js";
7
7
 
8
8
  // src/bin/sandbox.ts
9
9
  run(process.argv.slice(2));
@@ -2,8 +2,8 @@
2
2
  import { createRequire as __createRequire } from 'node:module'; const require = __createRequire(import.meta.url);
3
3
  import {
4
4
  run
5
- } from "./chunk-7EXDUNE7.js";
6
- import "./chunk-HIC4CUMY.js";
5
+ } from "./chunk-QLGGAG3D.js";
6
+ import "./chunk-REE3EMHD.js";
7
7
 
8
8
  // src/bin/sbx-hide.ts
9
9
  run(process.argv.slice(2), { command: "hide" });
@@ -2,8 +2,8 @@
2
2
  import { createRequire as __createRequire } from 'node:module'; const require = __createRequire(import.meta.url);
3
3
  import {
4
4
  run
5
- } from "./chunk-7EXDUNE7.js";
6
- import "./chunk-HIC4CUMY.js";
5
+ } from "./chunk-QLGGAG3D.js";
6
+ import "./chunk-REE3EMHD.js";
7
7
 
8
8
  // src/bin/sbx-show.ts
9
9
  run(process.argv.slice(2), { command: "show" });
@@ -95,7 +95,7 @@ function remoteAudit(ctx) {
95
95
  * served (it refuses everyone while web.remote.windowsSignIn is off).
96
96
  */
97
97
  function remoteGate(ctx) {
98
- const secrets = SecretStore.standard();
98
+ const secrets = SecretStore.standard(ctx.storageRoot);
99
99
  let ownerSid = '';
100
100
  try {
101
101
  ownerSid = currentUserSid();
@@ -62,6 +62,7 @@ export const DEFAULTS = {
62
62
  linkSlots: 'auto',
63
63
  },
64
64
  msvc: { enabled: 'auto', acceptLicense: false, msvcVersion: 'latest', sdkVersion: 'latest' },
65
+ unreal: { enabled: 'auto', acceptLicense: false, components: [], keepInstallFiles: true },
65
66
  cpp: { enabled: 'auto', flexBison: true },
66
67
  dotnet: {
67
68
  enabled: 'auto',
@@ -4,6 +4,7 @@ export declare const MARKERS: {
4
4
  readonly python: readonly ["pyproject.toml", "requirements.txt", "setup.py", "setup.cfg", "Pipfile", "uv.lock", "poetry.lock", ".python-version", "*.py", "*.ipynb"];
5
5
  readonly rust: readonly ["Cargo.toml", "rust-toolchain", "rust-toolchain.toml"];
6
6
  readonly msvc: readonly ["*.vcxproj", "CMakePresets.json", "CMakeUserPresets.json"];
7
+ readonly unreal: readonly ["*.uproject", "*.uplugin"];
7
8
  readonly cpp: readonly ["CMakeLists.txt", "Makefile", "meson.build", "premake5.lua", "Cargo.toml", "*.vcxproj", "*.c", "*.cpp", "*.cc", "*.h", "*.hpp"];
8
9
  readonly dotnet: readonly ["*.sln", "*.slnx", "*.csproj", "*.fsproj", "*.vbproj", "global.json", "*.cs"];
9
10
  readonly go: readonly ["go.mod", "go.work", "*.go"];
@@ -15,6 +15,7 @@ export const MARKERS = {
15
15
  ],
16
16
  rust: ['Cargo.toml', 'rust-toolchain', 'rust-toolchain.toml'],
17
17
  msvc: ['*.vcxproj', 'CMakePresets.json', 'CMakeUserPresets.json'],
18
+ unreal: ['*.uproject', '*.uplugin'],
18
19
  cpp: [
19
20
  'CMakeLists.txt',
20
21
  'Makefile',
@@ -86,6 +87,12 @@ export function decideToolchains(settings, entries, pcHas, hints = {}) {
86
87
  on: false,
87
88
  reason: 'would be used (' + result.msvc.reason + '); set toolchains.msvc.acceptLicense to install it',
88
89
  };
90
+ // Unreal is a ~10 GB licensed install every boot: "auto" only installs it once its licence is accepted.
91
+ if (settings.unreal.enabled === 'auto' && result.unreal.on && !settings.unreal.acceptLicense)
92
+ result.unreal = {
93
+ on: false,
94
+ reason: 'would be used (' + result.unreal.reason + '); set toolchains.unreal.acceptLicense to install it',
95
+ };
89
96
  if (result.rust.on && !result.msvc.on && !result.cpp.on && settings.cpp.enabled !== false)
90
97
  result.cpp = { on: true, reason: 'the linker for Rust' };
91
98
  // uv installs the Python tools (`uv tool install`), so Python tools turn an "auto" uv on.
@@ -153,6 +153,12 @@ export declare const ConfigSchema: z.ZodObject<{
153
153
  msvcVersion: z.ZodString;
154
154
  sdkVersion: z.ZodString;
155
155
  }, z.core.$strict>;
156
+ unreal: z.ZodObject<{
157
+ enabled: z.ZodUnion<readonly [z.ZodBoolean, z.ZodLiteral<"auto">]>;
158
+ acceptLicense: z.ZodBoolean;
159
+ components: z.ZodArray<z.ZodString>;
160
+ keepInstallFiles: z.ZodBoolean;
161
+ }, z.core.$strict>;
156
162
  cpp: z.ZodObject<{
157
163
  enabled: z.ZodUnion<readonly [z.ZodBoolean, z.ZodLiteral<"auto">]>;
158
164
  flexBison: z.ZodBoolean;
@@ -506,6 +512,21 @@ export declare const LocalOverridesSchema: z.ZodObject<{
506
512
  zstd: z.ZodOptional<z.ZodUnion<readonly [z.ZodBoolean, z.ZodLiteral<"auto">]>>;
507
513
  openssl: z.ZodOptional<z.ZodUnion<readonly [z.ZodBoolean, z.ZodLiteral<"auto">]>>;
508
514
  }, z.core.$strict>>;
515
+ unreal: z.ZodOptional<z.ZodObject<{
516
+ enabled: z.ZodOptional<z.ZodBoolean>;
517
+ }, z.core.$strict> | z.ZodObject<{
518
+ version: z.ZodOptional<z.ZodString>;
519
+ extraVersions: z.ZodOptional<z.ZodArray<z.ZodString>>;
520
+ corepack: z.ZodOptional<z.ZodBoolean>;
521
+ volta: z.ZodOptional<z.ZodUnion<readonly [z.ZodBoolean, z.ZodLiteral<"auto">]>>;
522
+ globalPackages: z.ZodOptional<z.ZodArray<z.ZodString>>;
523
+ }, z.core.$strict> | z.ZodObject<{
524
+ enabled: z.ZodOptional<z.ZodUnion<readonly [z.ZodBoolean, z.ZodLiteral<"auto">]>>;
525
+ }, z.core.$strict> | z.ZodObject<{
526
+ gh: z.ZodOptional<z.ZodUnion<readonly [z.ZodBoolean, z.ZodLiteral<"auto">]>>;
527
+ zstd: z.ZodOptional<z.ZodUnion<readonly [z.ZodBoolean, z.ZodLiteral<"auto">]>>;
528
+ openssl: z.ZodOptional<z.ZodUnion<readonly [z.ZodBoolean, z.ZodLiteral<"auto">]>>;
529
+ }, z.core.$strict>>;
509
530
  cpp: z.ZodOptional<z.ZodObject<{
510
531
  enabled: z.ZodOptional<z.ZodBoolean>;
511
532
  }, z.core.$strict> | z.ZodObject<{
@@ -51,7 +51,7 @@ export const SandboxSchema = z.strictObject({
51
51
  .describe('When the sandbox (or this PC) runs low on memory, slow builds down in steps, like a PC that gets slower instead of failing: build programs get lower CPU and memory priority, then less CPU, then compilers take turns (the waiting ones briefly suspended and trimmed to the paging file). Nothing is stopped or killed, and the agents themselves are never touched. Yours only: a project file cannot change it.'),
52
52
  vGpu: z
53
53
  .boolean()
54
- .describe("Virtual GPU. Off by default: Microsoft notes it widens the sandbox attack surface. The sandbox then uses this PC's graphics card, and with some graphics drivers heavy use can freeze the whole PC: turn it on only when a program in the sandbox needs the GPU (the mesa toolchain gives software OpenGL without it)."),
54
+ .describe("Virtual GPU. Off by default: Microsoft notes it widens the sandbox attack surface. The sandbox then uses this PC's graphics card, and with some graphics drivers heavy use can freeze the whole PC: turn it on only when a program in the sandbox needs the GPU (the mesa toolchain gives software OpenGL without it). Browsers in the sandbox never use it (they draw in software)."),
55
55
  networking: z.boolean().describe('Internet access. false is the only hard network isolation Windows Sandbox offers.'),
56
56
  clipboard: z
57
57
  .boolean()
@@ -34,6 +34,12 @@ export declare const ToolchainsSchema: z.ZodObject<{
34
34
  msvcVersion: z.ZodString;
35
35
  sdkVersion: z.ZodString;
36
36
  }, z.core.$strict>;
37
+ unreal: z.ZodObject<{
38
+ enabled: z.ZodUnion<readonly [z.ZodBoolean, z.ZodLiteral<"auto">]>;
39
+ acceptLicense: z.ZodBoolean;
40
+ components: z.ZodArray<z.ZodString>;
41
+ keepInstallFiles: z.ZodBoolean;
42
+ }, z.core.$strict>;
37
43
  cpp: z.ZodObject<{
38
44
  enabled: z.ZodUnion<readonly [z.ZodBoolean, z.ZodLiteral<"auto">]>;
39
45
  flexBison: z.ZodBoolean;
@@ -53,6 +53,16 @@ export const ToolchainsSchema = z.strictObject({
53
53
  msvcVersion: z.string().min(1).describe('"latest" or an MSVC tools version prefix, e.g. "14.44".'),
54
54
  sdkVersion: z.string().min(1).describe('"latest" or a Windows SDK build, e.g. "26100" or "10.0.22621".'),
55
55
  }),
56
+ unreal: z.strictObject({
57
+ enabled: enabled('Unreal Engine development: Visual Studio Community 2022 with the C++ game workload (MSVC, a Windows 11 SDK, .NET Framework targeting packs, Unreal integration and the Epic Games Launcher) and the DirectX End-User Runtime. A real installer: it runs every boot (~10 GB on the sandbox disk). The engine itself comes from the Epic Games Launcher or its source.', 'a .uproject or .uplugin'),
58
+ acceptLicense: z
59
+ .boolean()
60
+ .describe('Required to install: you accept the Visual Studio Community licence terms (https://visualstudio.microsoft.com/license-terms/) and the DirectX End-User Runtime licence.'),
61
+ components: StringsSchema.describe('More Visual Studio workload or component IDs to add, e.g. ["Microsoft.VisualStudio.Component.VC.Llvm.Clang"].'),
62
+ keepInstallFiles: z
63
+ .boolean()
64
+ .describe('Keep an offline copy of the Visual Studio install files in tools\\visualstudio (~10 GB, made once), so later boots install without downloading them again. Skipped while that disk has too little room.'),
65
+ }),
56
66
  cpp: z.strictObject({
57
67
  enabled: enabled("MinGW-w64 GCC with CMake, Ninja, premake5 and mingw32-make (also Rust's linker).", 'CMakeLists.txt, Makefile, meson.build, premake5.lua or Cargo.toml'),
58
68
  flexBison: z
@@ -19,6 +19,7 @@ import { writeManagedSettings } from '../setup/managed-policy.js';
19
19
  import { writeAddonMcpServers } from '../setup/addon-mcp.js';
20
20
  import { startHeadroom } from '../setup/headroom.js';
21
21
  import { applyPersonalization } from '../setup/desktop.js';
22
+ import { keepBrowsersOffGpu } from '../setup/browser-gpu.js';
22
23
  import { setupGitConfig } from '../setup/git-identity.js';
23
24
  import { loginGithub, prepareGithubFolder } from '../setup/github-token.js';
24
25
  import { ensurePtyHost } from '../sessions/pty-host.js';
@@ -172,6 +173,7 @@ export class Boot {
172
173
  step(2, 'Pre-provision hooks and desktop');
173
174
  runHooks('pre-provision', process.env);
174
175
  await soft('Personalisation', applyPersonalization);
176
+ await soft('Browsers without the GPU', keepBrowsersOffGpu);
175
177
  }
176
178
  /** Toolchains, databases, apps, the network proxy and VS Code; then the agent environment, saved machine-wide. */
177
179
  async developerTools() {
@@ -0,0 +1 @@
1
+ export declare function keepBrowsersOffGpu(): void;
@@ -0,0 +1,18 @@
1
+ // Browsers in the sandbox draw without the GPU (Edge and Chrome machine policy, written every boot). With sandbox.vGpu
2
+ // the sandbox shares this PC's graphics card through one virtual GPU: a browser's GPU process starting next to a game
3
+ // or other Direct3D program there has taken the whole sandbox down. Pages still render, WebGL included, in software;
4
+ // programs that need the GPU keep it. Without vGPU nothing changes (there is no GPU to use).
5
+ import { SYSTEM } from '../../shared/system.js';
6
+ import { dryRun, isWin } from '../runtime/paths.js';
7
+ import { exec } from '../runtime/process.js';
8
+ import { log } from '../runtime/log.js';
9
+ const POLICY_KEYS = ['HKLM\\SOFTWARE\\Policies\\Microsoft\\Edge', 'HKLM\\SOFTWARE\\Policies\\Google\\Chrome'];
10
+ export function keepBrowsersOffGpu() {
11
+ if (dryRun || !isWin)
12
+ return;
13
+ for (const key of POLICY_KEYS)
14
+ exec(SYSTEM.reg(), ['add', key, '/v', 'HardwareAccelerationModeEnabled', '/t', 'REG_DWORD', '/d', '0', '/f'], {
15
+ stdio: 'ignore',
16
+ });
17
+ log('Browsers draw without the GPU (Edge and Chrome policy).');
18
+ }
@@ -98,5 +98,7 @@ export function rustHost(config) {
98
98
  if (config.rust.host !== 'auto')
99
99
  return config.rust.host;
100
100
  const cpu = arch === 'arm64' ? 'aarch64' : 'x86_64';
101
- return cpu + (wanted(config.msvc.enabled, 'msvc') ? '-pc-windows-msvc' : '-pc-windows-gnu');
101
+ // Unreal's Visual Studio is a full MSVC too (rustc finds it through the Setup API).
102
+ const msvc = wanted(config.msvc.enabled, 'msvc') || wanted(config.unreal.enabled, 'unreal');
103
+ return cpu + (msvc ? '-pc-windows-msvc' : '-pc-windows-gnu');
102
104
  }
@@ -0,0 +1,9 @@
1
+ import type { Toolchains } from '../../../core/types.js';
2
+ import { type ToolEnv } from '../tool-env.js';
3
+ /**
4
+ * What Epic lists for Unreal Engine 5 with Visual Studio 2022: the game workload, MSVC v143, a Windows SDK of
5
+ * 10.0.18362 or newer, the C++ profiling tools, the .NET Framework targeting packs some engine tools build against,
6
+ * Visual Studio's Unreal support and the Unreal Engine installer (the Epic Games Launcher).
7
+ */
8
+ export declare const UNREAL_COMPONENTS: readonly ["Microsoft.VisualStudio.Workload.NativeGame", "Microsoft.VisualStudio.Component.VC.Tools.x86.x64", "Microsoft.VisualStudio.Component.Windows11SDK.22621", "Microsoft.VisualStudio.Component.VC.DiagnosticTools", "Microsoft.Net.Component.4.6.2.TargetingPack", "Microsoft.Net.Component.4.8.SDK", "Component.Unreal.Ide", "Component.Unreal"];
9
+ export declare function setupUnreal(env: ToolEnv, config: Toolchains['unreal']): Promise<void>;