windows-development-sandbox 1.23.2 → 1.25.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (211) hide show
  1. package/config.example.json +5 -3
  2. package/dist/app/features/data/data.def.d.ts +4 -4
  3. package/dist/app/features/data/data.run.d.ts +1 -1
  4. package/dist/app/features/defs.d.ts +161 -6
  5. package/dist/app/features/defs.js +7 -0
  6. package/dist/app/features/projects/projects.def.d.ts +1 -1
  7. package/dist/app/features/projects/projects.run.d.ts +1 -1
  8. package/dist/app/features/unreal/index.d.ts +2 -0
  9. package/dist/app/features/unreal/index.js +3 -0
  10. package/dist/app/features/unreal/unreal.def.d.ts +236 -0
  11. package/dist/app/features/unreal/unreal.def.js +379 -0
  12. package/dist/app/features/unreal/unreal.run.d.ts +96 -0
  13. package/dist/app/features/unreal/unreal.run.js +217 -0
  14. package/dist/app/registry.js +5 -0
  15. package/dist/bin/agent-sandbox.js +2 -2
  16. package/dist/bin/{chunk-7YPEDAJD.js → chunk-3GAXLATK.js} +58 -5
  17. package/dist/bin/{chunk-USTRSHIE.js → chunk-F4PVBN23.js} +2615 -1515
  18. package/dist/bin/{chunk-QFSJX2KW.js → chunk-G3TG4ZT7.js} +1 -1
  19. package/dist/bin/claude-host.js +2 -2
  20. package/dist/bin/claude-sbx.js +2 -2
  21. package/dist/bin/codex-sbx.js +2 -2
  22. package/dist/bin/gemini-sbx.js +2 -2
  23. package/dist/bin/sandbox.js +2 -2
  24. package/dist/bin/sbx-hide.js +2 -2
  25. package/dist/bin/sbx-show.js +2 -2
  26. package/dist/cli/commands/launch/launch.js +5 -2
  27. package/dist/cli/commands/registry.js +3 -0
  28. package/dist/cli/manifest.d.ts +18 -0
  29. package/dist/cli/manifest.js +26 -0
  30. package/dist/cli/menu/coverage-exempt.js +1 -0
  31. package/dist/cli/menu/pages/sandbox-page.d.ts +3 -0
  32. package/dist/cli/menu/pages/sandbox-page.js +34 -4
  33. package/dist/cli/menu/views.js +2 -0
  34. package/dist/core/config/defaults.js +18 -5
  35. package/dist/core/detect/toolchains.js +0 -6
  36. package/dist/core/schema/config.d.ts +10 -9
  37. package/dist/core/schema/pc-installs.d.ts +3 -1
  38. package/dist/core/schema/pc-installs.js +10 -1
  39. package/dist/core/schema/toolchains.d.ts +1 -2
  40. package/dist/core/schema/toolchains.js +4 -7
  41. package/dist/guest/accounts/kinds/epic.js +18 -13
  42. package/dist/guest/agents/agent-files.d.ts +11 -7
  43. package/dist/guest/agents/agent-files.js +37 -11
  44. package/dist/guest/agents/local-state.d.ts +2 -1
  45. package/dist/guest/agents/local-state.js +2 -1
  46. package/dist/guest/apps/after-install.d.ts +1 -1
  47. package/dist/guest/apps/after-install.js +6 -1
  48. package/dist/guest/apps/app-installer.d.ts +1 -0
  49. package/dist/guest/apps/app-installer.js +13 -3
  50. package/dist/guest/apps/comet-unpack.js +3 -2
  51. package/dist/guest/apps/resolvers-gamedev.js +55 -1
  52. package/dist/guest/boot/boot-console.d.ts +28 -0
  53. package/dist/guest/boot/boot-console.js +98 -0
  54. package/dist/guest/boot/boot.d.ts +8 -1
  55. package/dist/guest/boot/boot.js +80 -43
  56. package/dist/guest/boot/graph.d.ts +9 -5
  57. package/dist/guest/boot/graph.js +8 -2
  58. package/dist/guest/boot/guide.js +24 -0
  59. package/dist/guest/boot/progress-view.d.ts +116 -0
  60. package/dist/guest/boot/progress-view.js +456 -0
  61. package/dist/guest/boot/runner.d.ts +20 -10
  62. package/dist/guest/boot/runner.js +39 -47
  63. package/dist/guest/daemon/daemon.js +3 -0
  64. package/dist/guest/runtime/log-line.d.ts +7 -0
  65. package/dist/guest/runtime/log-line.js +18 -0
  66. package/dist/guest/runtime/log.d.ts +17 -4
  67. package/dist/guest/runtime/log.js +40 -17
  68. package/dist/guest/runtime/process.d.ts +9 -0
  69. package/dist/guest/runtime/process.js +69 -8
  70. package/dist/guest/setup/addon-mcp.d.ts +7 -0
  71. package/dist/guest/setup/addon-mcp.js +19 -4
  72. package/dist/guest/setup/browser-gpu.js +14 -11
  73. package/dist/guest/setup/environment.js +9 -4
  74. package/dist/guest/setup/headroom.js +4 -0
  75. package/dist/guest/setup/hooks.d.ts +2 -0
  76. package/dist/guest/setup/hooks.js +4 -0
  77. package/dist/guest/setup/path-plan.d.ts +12 -0
  78. package/dist/guest/setup/path-plan.js +18 -0
  79. package/dist/guest/toolchains/engines/epic-launcher.d.ts +26 -0
  80. package/dist/guest/toolchains/engines/epic-launcher.js +127 -0
  81. package/dist/guest/toolchains/engines/unreal-engines.d.ts +21 -1
  82. package/dist/guest/toolchains/engines/unreal-engines.js +163 -3
  83. package/dist/guest/toolchains/engines/unreal-status.d.ts +13 -0
  84. package/dist/guest/toolchains/engines/unreal-status.js +41 -0
  85. package/dist/guest/toolchains/native/debuggers.d.ts +6 -0
  86. package/dist/guest/toolchains/native/debuggers.js +57 -0
  87. package/dist/guest/toolchains/native/mesa.js +15 -8
  88. package/dist/guest/toolchains/native/rust-extras.d.ts +7 -0
  89. package/dist/guest/toolchains/native/rust-extras.js +23 -1
  90. package/dist/guest/toolchains/native/unreal.d.ts +2 -2
  91. package/dist/guest/toolchains/native/unreal.js +96 -20
  92. package/dist/guest/toolchains/native/visual-studio.d.ts +14 -14
  93. package/dist/guest/toolchains/native/visual-studio.js +145 -174
  94. package/dist/guest/toolchains/native/vs-persist.d.ts +189 -0
  95. package/dist/guest/toolchains/native/vs-persist.js +256 -0
  96. package/dist/guest/toolchains/native/vs-request.d.ts +6 -26
  97. package/dist/guest/toolchains/native/vs-request.js +16 -50
  98. package/dist/guest/toolchains/plan.js +23 -15
  99. package/dist/guest/toolchains/tools/vscode-profile.js +2 -0
  100. package/dist/host/accounts/kinds/epic.js +11 -5
  101. package/dist/host/accounts/source.d.ts +2 -0
  102. package/dist/host/accounts/source.js +1 -0
  103. package/dist/host/migrate/migrations/drop-vs-install-files.d.ts +5 -0
  104. package/dist/host/migrate/migrations/drop-vs-install-files.js +34 -0
  105. package/dist/host/migrate/registry.js +7 -1
  106. package/dist/host/pc-installs/discover.d.ts +2 -0
  107. package/dist/host/pc-installs/discover.js +25 -5
  108. package/dist/host/pc-installs/epic.d.ts +3 -0
  109. package/dist/host/pc-installs/epic.js +33 -2
  110. package/dist/host/pc-installs/source.d.ts +1 -1
  111. package/dist/host/pc-installs/unreal-vault.d.ts +11 -0
  112. package/dist/host/pc-installs/unreal-vault.js +78 -0
  113. package/dist/host/pc-installs/unreal.d.ts +36 -0
  114. package/dist/host/pc-installs/unreal.js +145 -2
  115. package/dist/host/profile/claude-profile.d.ts +8 -0
  116. package/dist/host/profile/claude-profile.js +43 -4
  117. package/dist/host/profile/index.d.ts +1 -1
  118. package/dist/host/profile/index.js +1 -1
  119. package/dist/runtime/agent.js +148 -33
  120. package/dist/runtime/daemon.js +3146 -1546
  121. package/dist/runtime/db.js +148 -33
  122. package/dist/runtime/main.js +3982 -2049
  123. package/dist/runtime/netproxy.js +84 -13
  124. package/dist/runtime/tool.js +125 -31
  125. package/dist/runtime/view.js +85 -14
  126. package/dist/selftest/agent-paths.test.js +18 -1
  127. package/dist/selftest/agent-settings.test.js +36 -5
  128. package/dist/selftest/agents-web.test.js +12 -0
  129. package/dist/selftest/boot-console.test.d.ts +2 -0
  130. package/dist/selftest/boot-console.test.js +291 -0
  131. package/dist/selftest/boot-runner.test.js +10 -12
  132. package/dist/selftest/engines.test.js +602 -3
  133. package/dist/selftest/guest-boot.test.js +7 -1
  134. package/dist/selftest/heavy-load.test.js +3 -1
  135. package/dist/selftest/hostile-input.test.js +11 -1
  136. package/dist/selftest/index.js +4 -0
  137. package/dist/selftest/layout.test.js +4 -0
  138. package/dist/selftest/menu-screens.js +3 -1
  139. package/dist/selftest/migrate.test.js +21 -0
  140. package/dist/selftest/mixamo.test.d.ts +2 -0
  141. package/dist/selftest/mixamo.test.js +60 -0
  142. package/dist/selftest/persisted-installs.test.js +169 -33
  143. package/dist/selftest/secrets.test.js +36 -1
  144. package/dist/selftest/support/engine-golden.js +5 -0
  145. package/dist/selftest/support/fixtures.d.ts +4 -3
  146. package/dist/selftest/support/unreal-sample.d.ts +2 -0
  147. package/dist/selftest/support/unreal-sample.js +83 -0
  148. package/dist/selftest/toolchains.test.js +32 -2
  149. package/dist/shared/accounts/index.d.ts +1 -1
  150. package/dist/shared/accounts/index.js +1 -1
  151. package/dist/shared/accounts/kinds/epic.d.ts +6 -1
  152. package/dist/shared/accounts/kinds/epic.js +11 -1
  153. package/dist/shared/apps/associations.d.ts +7 -0
  154. package/dist/shared/apps/associations.js +26 -0
  155. package/dist/shared/apps/catalogue-agents-web.d.ts +4 -1
  156. package/dist/shared/apps/catalogue-agents-web.js +5 -2
  157. package/dist/shared/apps/catalogue-gamedev.js +71 -1
  158. package/dist/shared/apps/index.d.ts +2 -0
  159. package/dist/shared/apps/index.js +2 -0
  160. package/dist/shared/apps/preview.d.ts +2 -0
  161. package/dist/shared/apps/preview.js +10 -0
  162. package/dist/shared/browser-policy.d.ts +14 -0
  163. package/dist/shared/browser-policy.js +22 -0
  164. package/dist/shared/channel/schema.d.ts +3 -6
  165. package/dist/shared/io/index.d.ts +1 -0
  166. package/dist/shared/io/index.js +1 -0
  167. package/dist/shared/io/rotate-log.d.ts +2 -0
  168. package/dist/shared/io/rotate-log.js +16 -0
  169. package/dist/shared/memory/policy.d.ts +5 -0
  170. package/dist/shared/memory/policy.js +7 -0
  171. package/dist/shared/paths/pc-installs.d.ts +13 -2
  172. package/dist/shared/paths/pc-installs.js +1 -0
  173. package/dist/shared/pty/terminal.js +2 -1
  174. package/dist/shared/readiness.d.ts +0 -1
  175. package/dist/shared/readiness.js +0 -1
  176. package/dist/shared/signer.d.ts +4 -0
  177. package/dist/shared/signer.js +2 -0
  178. package/dist/shared/unreal/engines.d.ts +161 -0
  179. package/dist/shared/unreal/engines.js +308 -0
  180. package/dist/shared/unreal/guide.d.ts +19 -0
  181. package/dist/shared/unreal/guide.js +105 -0
  182. package/dist/shared/unreal/index.d.ts +7 -0
  183. package/dist/shared/unreal/index.js +8 -0
  184. package/dist/shared/unreal/launcher-files.d.ts +88 -0
  185. package/dist/shared/unreal/launcher-files.js +292 -0
  186. package/dist/shared/unreal/mixamo.d.ts +5 -0
  187. package/dist/shared/unreal/mixamo.js +16 -0
  188. package/dist/shared/unreal/room.d.ts +17 -0
  189. package/dist/shared/unreal/room.js +34 -0
  190. package/dist/shared/unreal/status.d.ts +54 -0
  191. package/dist/shared/unreal/status.js +57 -0
  192. package/dist/shared/unreal/vault.d.ts +21 -0
  193. package/dist/shared/unreal/vault.js +67 -0
  194. package/dist/shared/unreal/vs-check.d.ts +39 -0
  195. package/dist/shared/unreal/vs-check.js +79 -0
  196. package/dist/sync/watcher.js +5 -1
  197. package/dist/web/index.html +1 -1
  198. package/dist/web/{main-CCILLX2M.js → main-FNE6XEHA.js} +84 -84
  199. package/native/csharp/HcsHost/AssemblyInfo.cs +3 -3
  200. package/native/csharp/HostTools/AssemblyInfo.cs +3 -3
  201. package/native/csharp/StorageHelper/AssemblyInfo.cs +3 -3
  202. package/package.json +1 -1
  203. package/sandbox/csharp/VsSetup.cs +210 -0
  204. package/sandbox/scripts/get-vs-setup.ps1 +93 -0
  205. package/sandbox/scripts/restore-visual-studio.ps1 +78 -0
  206. package/sandbox/scripts/save-visual-studio.ps1 +106 -0
  207. package/sandbox/scripts/set-registry-values.ps1 +35 -0
  208. package/schemas/config.schema.json +38 -9
  209. package/schemas/sandbox-config.schema.json +11 -8
  210. package/dist/guest/toolchains/native/autosdk.d.ts +0 -3
  211. package/dist/guest/toolchains/native/autosdk.js +0 -50
@@ -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-USTRSHIE.js";
4
+ } from "./chunk-F4PVBN23.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-7YPEDAJD.js";
6
- import "./chunk-USTRSHIE.js";
5
+ } from "./chunk-3GAXLATK.js";
6
+ import "./chunk-F4PVBN23.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-7YPEDAJD.js";
6
- import "./chunk-USTRSHIE.js";
5
+ } from "./chunk-3GAXLATK.js";
6
+ import "./chunk-F4PVBN23.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-7YPEDAJD.js";
6
- import "./chunk-USTRSHIE.js";
5
+ } from "./chunk-3GAXLATK.js";
6
+ import "./chunk-F4PVBN23.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-7YPEDAJD.js";
6
- import "./chunk-USTRSHIE.js";
5
+ } from "./chunk-3GAXLATK.js";
6
+ import "./chunk-F4PVBN23.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-7YPEDAJD.js";
6
- import "./chunk-USTRSHIE.js";
5
+ } from "./chunk-3GAXLATK.js";
6
+ import "./chunk-F4PVBN23.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-7YPEDAJD.js";
6
- import "./chunk-USTRSHIE.js";
5
+ } from "./chunk-3GAXLATK.js";
6
+ import "./chunk-F4PVBN23.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-7YPEDAJD.js";
6
- import "./chunk-USTRSHIE.js";
5
+ } from "./chunk-3GAXLATK.js";
6
+ import "./chunk-F4PVBN23.js";
7
7
 
8
8
  // src/bin/sbx-show.ts
9
9
  run(process.argv.slice(2), { command: "show" });
@@ -180,22 +180,25 @@ class Launcher {
180
180
  : prepareGithubToken(config, ctx.storageRoot, undefined, bootWants.wants.projects);
181
181
  // accounts.<kind>.share: the saved service sign-ins this boot's toolchains use, for the one-shot file only.
182
182
  const launchId = newLaunchId();
183
+ const toolchainsOn = toolchainsOnForBoot({ run }, bootWants.wants.projects);
183
184
  const accounts = generateOnly
184
185
  ? null
185
186
  : prepareServiceAccounts({
186
187
  config,
187
188
  others: bootWants.wants.projects,
188
- on: toolchainsOnForBoot({ run }, bootWants.wants.projects),
189
+ on: toolchainsOn,
189
190
  storageRoot: ctx.storageRoot,
190
191
  dataPath: run.dataPath,
191
192
  launchId,
192
193
  // A new launch needs no sandbox running, so a lease held elsewhere is from one that stopped.
193
194
  isRunning: () => isSandboxRunning(),
194
195
  });
195
- // pcInstalls: this PC's games, engines and editors, read-only (yours only: never from a project file).
196
+ // pcInstalls: this PC's games, engines and editors, read-only (yours only: never from a project file). The
197
+ // engines ("auto") come along whenever this launch sets the sandbox up for Unreal.
196
198
  const pcInstalls = discoverPcInstalls(ctx.loaded.config.pcInstalls, {
197
199
  packageRoot: ctx.packageRoot,
198
200
  storageRoot: ctx.storageRoot,
201
+ unrealOn: toolchainsOn.has('unreal'),
199
202
  });
200
203
  // This PC's commit (RAM plus paging file) bounds the sandbox's memory as much as free RAM does.
201
204
  const hostMemory = generateOnly ? null : readHostMemory(ctx.storageRoot);
@@ -7,6 +7,7 @@ import { agentCommandsStatus } from '../../app/features/agent-commands/index.js'
7
7
  import { listAccounts } from '../../app/features/accounts/index.js';
8
8
  import { containedStatus, showStorage } from '../../app/features/storage/index.js';
9
9
  import { listProjects } from '../../app/features/projects/index.js';
10
+ import { unrealOverview } from '../../app/features/unreal/index.js';
10
11
  import { definitionHandler } from '../operations/index.js';
11
12
  import { fail } from '../../core/util/index.js';
12
13
  import { claudeHost, config, doctor, hostCommand, logs, sync, watcher } from './maintenance/index.js';
@@ -48,6 +49,8 @@ export const HANDLERS = {
48
49
  return fail('Unknown storage action "' + action + '".', 'Use: sandbox storage, sandbox storage move <folder>, sandbox storage use <folder> or sandbox storage contained on|off|status');
49
50
  },
50
51
  engine: engine,
52
+ // The bare command shows the overview; its actions (add-engine, forget-engine, launcher) are the operations' hints.
53
+ unreal: definitionHandler(unrealOverview),
51
54
  'host-claude': claudeHost,
52
55
  host: hostCommand,
53
56
  _watch: watcher,
@@ -488,6 +488,24 @@ declare const COMMAND_LIST: readonly [{
488
488
  shownAs?: string | undefined;
489
489
  }];
490
490
  readonly json: true;
491
+ }, {
492
+ readonly name: "unreal";
493
+ readonly summary: "Unreal Engine: the sandbox's engines, this PC's engines and assets, register an engine folder, open the launcher";
494
+ readonly group: "Projects & accounts";
495
+ readonly json: true;
496
+ readonly examples: readonly ["sandbox unreal engines, which project uses which, Visual Studio", "sandbox unreal add-engine D:\\UE5 use this engine folder in sandboxes (writable)", "sandbox unreal launcher open the Epic Games Launcher in the running sandbox"];
497
+ readonly args: readonly [{
498
+ readonly name: "action";
499
+ readonly description: "status, add-engine, forget-engine, launcher";
500
+ readonly required: false;
501
+ readonly choices: readonly ["status"];
502
+ }, {
503
+ readonly name: "folder";
504
+ readonly description: "(add-engine, forget-engine) the engine folder";
505
+ readonly required: false;
506
+ readonly when: readonly [];
507
+ }];
508
+ readonly options: readonly [];
491
509
  }, {
492
510
  readonly name: "engine";
493
511
  readonly summary: "(beta) what runs your sandbox (Windows Sandbox or HCS) and what each engine can do on this PC";
@@ -381,6 +381,32 @@ const COMMAND_LIST = [
381
381
  ],
382
382
  json,
383
383
  },
384
+ {
385
+ name: 'unreal',
386
+ summary: "Unreal Engine: the sandbox's engines, this PC's engines and assets, register an engine folder, open the launcher",
387
+ group: 'Projects & accounts',
388
+ json,
389
+ examples: [
390
+ 'sandbox unreal engines, which project uses which, Visual Studio',
391
+ 'sandbox unreal add-engine D:\\UE5 use this engine folder in sandboxes (writable)',
392
+ 'sandbox unreal launcher open the Epic Games Launcher in the running sandbox',
393
+ ],
394
+ args: [
395
+ {
396
+ name: 'action',
397
+ description: 'status, add-engine, forget-engine, launcher',
398
+ required: false,
399
+ choices: ['status'],
400
+ },
401
+ {
402
+ name: 'folder',
403
+ description: '(add-engine, forget-engine) the engine folder',
404
+ required: false,
405
+ when: [],
406
+ },
407
+ ],
408
+ options: [],
409
+ },
384
410
  {
385
411
  name: 'engine',
386
412
  summary: '(beta) what runs your sandbox (Windows Sandbox or HCS) and what each engine can do on this PC',
@@ -12,6 +12,7 @@ export const COMMAND_PLACES = {
12
12
  data: { place: 'Maintenance > Data' },
13
13
  storage: { place: 'Maintenance > Storage' },
14
14
  engine: { place: 'Maintenance > Engine' },
15
+ unreal: { place: 'Sandbox > Unreal Engine' },
15
16
  sync: { place: 'Maintenance > More commands' },
16
17
  logs: { place: 'Maintenance > Logs (key f follows)' },
17
18
  setup: { place: 'Maintenance > Health' },
@@ -1,5 +1,6 @@
1
1
  import { type ProjectsList } from '../../../app/features/projects/index.js';
2
2
  import { type SandboxStatus } from '../../../app/features/sandbox/index.js';
3
+ import { type UnrealOverview } from '../../../app/features/unreal/index.js';
3
4
  import type { Context } from '../../commands/context.js';
4
5
  import { type DatabaseRow } from '../../services/index.js';
5
6
  import { type App, type ListOptions, type ListResult } from '../../tui/index.js';
@@ -11,6 +12,8 @@ export interface SandboxModel {
11
12
  readonly databases: DatabaseRow[] | null;
12
13
  /** The agent "Start the sandbox" offers while nothing runs. */
13
14
  readonly defaultAgent: string;
15
+ /** The Unreal overview; null when it could not be read. */
16
+ readonly unreal: UnrealOverview | null;
14
17
  }
15
18
  /** The list for the sandbox tab. Pure. */
16
19
  export declare function sandboxOptions(m: SandboxModel): ListOptions<string>;
@@ -1,9 +1,10 @@
1
1
  // Section 3: the sandbox as a whole. Status (the sandbox view: its facts, the window, stopping it), Projects (the
2
- // projects view: roots, the projects and the all-projects setting) and Databases (start and stop), each a category on
3
- // the left.
2
+ // projects view: roots, the projects and the all-projects setting), Databases (start and stop) and Unreal Engine (the
3
+ // unreal view), each a category on the left.
4
4
  import { listProjects, projectsPage } from '../../../app/features/projects/index.js';
5
5
  import { sandboxPage, sandboxStatus } from '../../../app/features/sandbox/index.js';
6
6
  import { readQuery } from '../../../app/registry.js';
7
+ import { unrealOverview, unrealPage } from '../../../app/features/unreal/index.js';
7
8
  import { errMsg, safeText } from '../../../core/util/index.js';
8
9
  import { RunDir } from '../../../shared/channel/index.js';
9
10
  import { DatabasesService } from '../../services/index.js';
@@ -19,7 +20,18 @@ const CATEGORIES = [
19
20
  description: 'Project roots (folders of projects, opened without a restart) and the projects started before.',
20
21
  },
21
22
  { id: 'databases', label: 'Databases', description: 'Databases the sandbox can run: start and stop them.' },
23
+ {
24
+ id: 'unreal',
25
+ label: 'Unreal Engine',
26
+ description: "Engines, which project uses which, this PC's engines and assets, Visual Studio and the debugger.",
27
+ },
22
28
  ];
29
+ /** The Unreal category: the Unreal view's rows and keys (prefixed, so they never clash with other rows). */
30
+ function unrealMenu(m) {
31
+ return m.unreal
32
+ ? menuView(unrealPage(m.unreal), { category: 'unreal', prefix: 'unreal:', refresh: false })
33
+ : undefined;
34
+ }
23
35
  /** The status category: the sandbox view's rows (prefixed, so they never clash with the projects' rows). */
24
36
  function statusView(m) {
25
37
  return menuView(sandboxPage(m.report), { category: 'status', prefix: 'status:', refresh: false });
@@ -32,6 +44,8 @@ function projectsView(m) {
32
44
  function viewFor(m, category) {
33
45
  if (category === 'projects')
34
46
  return projectsView(m);
47
+ if (category === 'unreal')
48
+ return unrealMenu(m);
35
49
  if (category === 'status' || category === undefined)
36
50
  return statusView(m);
37
51
  return undefined;
@@ -64,16 +78,31 @@ export function sandboxOptions(m) {
64
78
  section: 'Databases',
65
79
  description: d.title + '. Enter ' + (d.running ? 'stops' : 'starts') + ' it (the first start downloads it).',
66
80
  }));
81
+ const unreal = unrealMenu(m);
82
+ const noUnreal = unreal
83
+ ? []
84
+ : [
85
+ {
86
+ value: 'info:unreal',
87
+ label: 'Could not read the Unreal set-up',
88
+ category: 'unreal',
89
+ section: 'Unreal Engine',
90
+ description: 'l looks again.',
91
+ disabled: 'l looks again.',
92
+ },
93
+ ];
67
94
  return {
68
95
  path: [],
69
- items: [...statusItems, ...projects.items, ...databases, ...noDatabases],
96
+ items: [...statusItems, ...projects.items, ...databases, ...noDatabases, ...(unreal?.items ?? []), ...noUnreal],
70
97
  categories: CATEGORIES,
71
98
  empty: 'Nothing here yet.',
72
99
  actions: (category) => category === 'projects'
73
100
  ? [...projects.actions, REFRESH]
74
101
  : category === 'databases'
75
102
  ? [REFRESH]
76
- : [...status.actions, REFRESH],
103
+ : category === 'unreal'
104
+ ? [...(unreal?.actions ?? []), REFRESH]
105
+ : [...status.actions, REFRESH],
77
106
  enterLabel: (category, id) => viewFor(m, category)?.enterLabel(category, id) || enterLabel(id ?? '', m),
78
107
  };
79
108
  }
@@ -133,6 +162,7 @@ export class SandboxPage extends ListPage {
133
162
  projects: await readQuery(listProjects, this.ctx),
134
163
  databases,
135
164
  defaultAgent: this.defaultAgent(),
165
+ unreal: await readQuery(unrealOverview, this.ctx).catch(() => null),
136
166
  };
137
167
  }
138
168
  /** The folder `sbx-db` runs in: the sandbox's own workspace. */
@@ -19,6 +19,7 @@ import { webView } from '../../app/features/web/index.js';
19
19
  import { vpnView } from '../../app/features/vpn/index.js';
20
20
  import { githubView } from '../../app/features/github/index.js';
21
21
  import { accessView } from '../../app/features/access/index.js';
22
+ import { unrealView } from '../../app/features/unreal/index.js';
22
23
  export const MENU_VIEWS = [
23
24
  { view: agentsView, section: 'Agents' },
24
25
  { view: agentEnvView, section: 'Agents' },
@@ -28,6 +29,7 @@ export const MENU_VIEWS = [
28
29
  { view: accountsView, section: 'Accounts' },
29
30
  { view: appsView, section: 'Apps' },
30
31
  { view: projectsView, section: 'Sandbox' },
32
+ { view: unrealView, section: 'Sandbox' },
31
33
  { view: healthView, section: 'Maintenance' },
32
34
  { view: dataView, section: 'Maintenance' },
33
35
  { view: storageView, section: 'Maintenance' },
@@ -58,7 +58,14 @@ export const DEFAULTS = {
58
58
  perplexity: { share: false },
59
59
  comet: { share: false },
60
60
  },
61
- pcInstalls: { steamGames: false, epicGames: false, unrealEngines: false, unityEditors: false },
61
+ pcInstalls: {
62
+ steamGames: false,
63
+ epicGames: false,
64
+ unrealEngines: 'auto',
65
+ unrealEngineFolders: [],
66
+ unrealAssets: 'auto',
67
+ unityEditors: false,
68
+ },
62
69
  provisioning: {
63
70
  copyFromHost: true,
64
71
  fallbackToInstall: true,
@@ -87,7 +94,6 @@ export const DEFAULTS = {
87
94
  enabled: 'auto',
88
95
  acceptLicense: false,
89
96
  components: [],
90
- keepInstallFiles: true,
91
97
  visualStudio: 'full',
92
98
  persistEngines: true,
93
99
  derivedDataCache: 'persisted',
@@ -197,9 +203,16 @@ export const DEFAULTS = {
197
203
  home: { env: { CODEX_HOME: 'codex' }, loginFiles: ['auth.json', '.credentials.json'], hostDir: '~/.codex' },
198
204
  localState: { CODEX_SQLITE_HOME: 'sqlite' },
199
205
  // Its own command sandbox keeps local users' passwords sealed with DPAPI: unreadable in the next sandbox
200
- // ("CryptUnprotectData" on every command), so it sets that sandbox up again at each boot. tmp\arg0: folders
201
- // Codex cannot remove in a mapped folder (os error 145, a warning at every start); nothing holds them at boot.
202
- bootReset: ['.sandbox-secrets', '.sandbox\\setup_marker.json', '.sandbox\\deny_read_acl_state.json', 'tmp\\arg0'],
206
+ // ("CryptUnprotectData" on every command), so it sets that sandbox up again at each boot. tmp\arg0 and
207
+ // tmp\arg0-windows (newer Codex): folders Codex cannot remove in a mapped folder (os error 145, a warning at
208
+ // every start); nothing holds them at boot.
209
+ bootReset: [
210
+ '.sandbox-secrets',
211
+ '.sandbox\\setup_marker.json',
212
+ '.sandbox\\deny_read_acl_state.json',
213
+ 'tmp\\arg0',
214
+ 'tmp\\arg0-windows',
215
+ ],
203
216
  resumeArguments: ['resume', '--last'],
204
217
  },
205
218
  gemini: {
@@ -127,15 +127,9 @@ function applyImplications(settings, result) {
127
127
  imply(settings, result, 'android', 'React Native builds for Android');
128
128
  if (result.godot.on && settings.godot.dotnet === true)
129
129
  imply(settings, result, 'dotnet', "Godot's .NET build");
130
- if (result.unreal.on && settings.unreal.visualStudio === 'autosdk')
131
- imply(settings, result, 'msvc', 'Unreal builds from the portable MSVC (AutoSDK)');
132
- // Unreal's licence acceptance covers the MSVC it builds from (the same Visual Studio terms).
133
- const autosdkLicence = settings.unreal.visualStudio === 'autosdk' && settings.unreal.acceptLicense;
134
130
  for (const name of LICENSED_TOOLCHAINS) {
135
131
  if (settings[name].enabled !== 'auto' || !result[name].on || settings[name].acceptLicense)
136
132
  continue;
137
- if (name === 'msvc' && autosdkLicence)
138
- continue;
139
133
  result[name] = {
140
134
  on: false,
141
135
  reason: 'would be used (' + result[name].reason + '); set toolchains.' + name + '.acceptLicense to install it',
@@ -131,7 +131,9 @@ export declare const ConfigSchema: z.ZodObject<{
131
131
  pcInstalls: z.ZodObject<{
132
132
  steamGames: z.ZodUnion<readonly [z.ZodBoolean, z.ZodArray<z.ZodNumber>]>;
133
133
  epicGames: z.ZodUnion<readonly [z.ZodBoolean, z.ZodArray<z.ZodString>]>;
134
- unrealEngines: z.ZodUnion<readonly [z.ZodBoolean, z.ZodArray<z.ZodString>]>;
134
+ unrealEngines: z.ZodUnion<readonly [z.ZodLiteral<"auto">, z.ZodBoolean, z.ZodArray<z.ZodString>]>;
135
+ unrealEngineFolders: z.ZodArray<z.ZodString>;
136
+ unrealAssets: z.ZodUnion<readonly [z.ZodLiteral<"auto">, z.ZodBoolean]>;
135
137
  unityEditors: z.ZodUnion<readonly [z.ZodBoolean, z.ZodArray<z.ZodString>]>;
136
138
  }, z.core.$strict>;
137
139
  provisioning: z.ZodObject<{
@@ -195,10 +197,9 @@ export declare const ConfigSchema: z.ZodObject<{
195
197
  enabled: z.ZodUnion<readonly [z.ZodBoolean, z.ZodLiteral<"auto">]>;
196
198
  acceptLicense: z.ZodBoolean;
197
199
  components: z.ZodArray<z.ZodString>;
198
- keepInstallFiles: z.ZodBoolean;
199
200
  visualStudio: z.ZodEnum<{
200
201
  full: "full";
201
- autosdk: "autosdk";
202
+ buildtools: "buildtools";
202
203
  }>;
203
204
  persistEngines: z.ZodBoolean;
204
205
  derivedDataCache: z.ZodEnum<{
@@ -690,7 +691,7 @@ export declare const LocalOverridesSchema: z.ZodObject<{
690
691
  zstd: z.ZodOptional<z.ZodUnion<readonly [z.ZodBoolean, z.ZodLiteral<"auto">]>>;
691
692
  openssl: z.ZodOptional<z.ZodUnion<readonly [z.ZodBoolean, z.ZodLiteral<"auto">]>>;
692
693
  }, z.core.$strict>>;
693
- unreal: z.ZodOptional<z.ZodObject<{
694
+ node: z.ZodOptional<z.ZodObject<{
694
695
  enabled: z.ZodOptional<z.ZodBoolean>;
695
696
  }, z.core.$strict> | z.ZodObject<{
696
697
  version: z.ZodOptional<z.ZodString>;
@@ -705,7 +706,7 @@ export declare const LocalOverridesSchema: z.ZodObject<{
705
706
  zstd: z.ZodOptional<z.ZodUnion<readonly [z.ZodBoolean, z.ZodLiteral<"auto">]>>;
706
707
  openssl: z.ZodOptional<z.ZodUnion<readonly [z.ZodBoolean, z.ZodLiteral<"auto">]>>;
707
708
  }, z.core.$strict>>;
708
- node: z.ZodOptional<z.ZodObject<{
709
+ go: z.ZodOptional<z.ZodObject<{
709
710
  enabled: z.ZodOptional<z.ZodBoolean>;
710
711
  }, z.core.$strict> | z.ZodObject<{
711
712
  version: z.ZodOptional<z.ZodString>;
@@ -720,7 +721,7 @@ export declare const LocalOverridesSchema: z.ZodObject<{
720
721
  zstd: z.ZodOptional<z.ZodUnion<readonly [z.ZodBoolean, z.ZodLiteral<"auto">]>>;
721
722
  openssl: z.ZodOptional<z.ZodUnion<readonly [z.ZodBoolean, z.ZodLiteral<"auto">]>>;
722
723
  }, z.core.$strict>>;
723
- go: z.ZodOptional<z.ZodObject<{
724
+ python: z.ZodOptional<z.ZodObject<{
724
725
  enabled: z.ZodOptional<z.ZodBoolean>;
725
726
  }, z.core.$strict> | z.ZodObject<{
726
727
  version: z.ZodOptional<z.ZodString>;
@@ -735,7 +736,7 @@ export declare const LocalOverridesSchema: z.ZodObject<{
735
736
  zstd: z.ZodOptional<z.ZodUnion<readonly [z.ZodBoolean, z.ZodLiteral<"auto">]>>;
736
737
  openssl: z.ZodOptional<z.ZodUnion<readonly [z.ZodBoolean, z.ZodLiteral<"auto">]>>;
737
738
  }, z.core.$strict>>;
738
- python: z.ZodOptional<z.ZodObject<{
739
+ rust: z.ZodOptional<z.ZodObject<{
739
740
  enabled: z.ZodOptional<z.ZodBoolean>;
740
741
  }, z.core.$strict> | z.ZodObject<{
741
742
  version: z.ZodOptional<z.ZodString>;
@@ -750,7 +751,7 @@ export declare const LocalOverridesSchema: z.ZodObject<{
750
751
  zstd: z.ZodOptional<z.ZodUnion<readonly [z.ZodBoolean, z.ZodLiteral<"auto">]>>;
751
752
  openssl: z.ZodOptional<z.ZodUnion<readonly [z.ZodBoolean, z.ZodLiteral<"auto">]>>;
752
753
  }, z.core.$strict>>;
753
- rust: z.ZodOptional<z.ZodObject<{
754
+ msvc: z.ZodOptional<z.ZodObject<{
754
755
  enabled: z.ZodOptional<z.ZodBoolean>;
755
756
  }, z.core.$strict> | z.ZodObject<{
756
757
  version: z.ZodOptional<z.ZodString>;
@@ -765,7 +766,7 @@ export declare const LocalOverridesSchema: z.ZodObject<{
765
766
  zstd: z.ZodOptional<z.ZodUnion<readonly [z.ZodBoolean, z.ZodLiteral<"auto">]>>;
766
767
  openssl: z.ZodOptional<z.ZodUnion<readonly [z.ZodBoolean, z.ZodLiteral<"auto">]>>;
767
768
  }, z.core.$strict>>;
768
- msvc: z.ZodOptional<z.ZodObject<{
769
+ unreal: z.ZodOptional<z.ZodObject<{
769
770
  enabled: z.ZodOptional<z.ZodBoolean>;
770
771
  }, z.core.$strict> | z.ZodObject<{
771
772
  version: z.ZodOptional<z.ZodString>;
@@ -2,6 +2,8 @@ import { z } from 'zod';
2
2
  export declare const PcInstallsSchema: z.ZodObject<{
3
3
  steamGames: z.ZodUnion<readonly [z.ZodBoolean, z.ZodArray<z.ZodNumber>]>;
4
4
  epicGames: z.ZodUnion<readonly [z.ZodBoolean, z.ZodArray<z.ZodString>]>;
5
- unrealEngines: z.ZodUnion<readonly [z.ZodBoolean, z.ZodArray<z.ZodString>]>;
5
+ unrealEngines: z.ZodUnion<readonly [z.ZodLiteral<"auto">, z.ZodBoolean, z.ZodArray<z.ZodString>]>;
6
+ unrealEngineFolders: z.ZodArray<z.ZodString>;
7
+ unrealAssets: z.ZodUnion<readonly [z.ZodLiteral<"auto">, z.ZodBoolean]>;
6
8
  unityEditors: z.ZodUnion<readonly [z.ZodBoolean, z.ZodArray<z.ZodString>]>;
7
9
  }, z.core.$strict>;
@@ -11,7 +11,16 @@ export const PcInstallsSchema = z
11
11
  .strictObject({
12
12
  steamGames: pick(z.number().int().positive(), 'Steam games (true maps each library; a list of app IDs maps only those games)', '[480, 730]'),
13
13
  epicGames: pick(z.string().regex(/^[A-Za-z0-9._-]{1,100}$/), 'Epic Games Launcher games (by their app name)', '["Fortnite"]'),
14
- unrealEngines: pick(z.string().regex(/^(UE_)?\d+\.\d+$/), 'Unreal Engine versions installed with the Epic Games Launcher', '["5.4"]'),
14
+ unrealEngines: z
15
+ .union([z.literal('auto'), z.boolean(), z.array(z.string().regex(/^(UE_)?\d+\.\d+$/))])
16
+ .describe('Unreal Engine versions installed on this PC (with the Epic Games Launcher, or source builds it lists), read-only in the sandbox under C:\\PcInstalls\\unreal and registered there, so projects build with them without a download. "auto" = all of them whenever the sandbox is set up for Unreal, true = always, false = never, or a list (e.g. ["5.4"]).'),
17
+ unrealEngineFolders: z
18
+ .array(z.string().min(3).max(260))
19
+ .max(8)
20
+ .describe('Unreal Engine folders of this PC to use in the sandbox, writable (a source build, or a copy you build plugins into): each must hold Engine\\Build\\Build.version. Mapped under C:\\PcInstalls\\unreal and registered there.'),
21
+ unrealAssets: z
22
+ .union([z.literal('auto'), z.boolean()])
23
+ .describe('The Epic Games Launcher\'s vault cache of this PC (the Fab and Marketplace packs you downloaded), read-only in the sandbox at C:\\PcInstalls\\unreal\\Vault: what you download on your PC is there for the agents at once. "auto" = whenever the sandbox is set up for Unreal, true = always, false = never.'),
15
24
  unityEditors: pick(z.string().regex(/^\d+\.\d+\.\d+[abfp]\d+$/), 'Unity editors installed with Unity Hub', '["6000.0.32f1"]'),
16
25
  })
17
26
  .describe("Games, engines and editors installed on this PC, mapped read-only into sandboxes (no copy, no room on the sandbox's disk).");
@@ -38,10 +38,9 @@ export declare const ToolchainsSchema: z.ZodObject<{
38
38
  enabled: z.ZodUnion<readonly [z.ZodBoolean, z.ZodLiteral<"auto">]>;
39
39
  acceptLicense: z.ZodBoolean;
40
40
  components: z.ZodArray<z.ZodString>;
41
- keepInstallFiles: z.ZodBoolean;
42
41
  visualStudio: z.ZodEnum<{
43
42
  full: "full";
44
- autosdk: "autosdk";
43
+ buildtools: "buildtools";
45
44
  }>;
46
45
  persistEngines: z.ZodBoolean;
47
46
  derivedDataCache: z.ZodEnum<{
@@ -40,7 +40,7 @@ export const ToolchainsSchema = z.strictObject({
40
40
  .describe('"auto" (default): on the sandbox\'s own disk when C: has 25 GB free at boot, else "separate" (builds then write through the mapped workspace, which can overload this PC\'s disk). "shared": cargo\'s default target\\ (shared with builds on this PC, so builds on either side invalidate the other), "separate": <workspace>\\target\\sandbox (kept, no cross-talk), "local": on the sandbox\'s own disk (fastest, lost every boot), or a guest path.'),
41
41
  linker: z
42
42
  .enum(['lld', 'gnu'])
43
- .describe('GNU host: "lld" links with Rust\'s own lld through MinGW\'s gcc (much less memory than GNU ld), "gnu" with GNU ld.'),
43
+ .describe('"lld" (default) links with Rust\'s own lld: through MinGW\'s gcc on the GNU host (much less memory than GNU ld), and instead of link.exe on the MSVC host (link.exe writes executables into mapped folders as all zeros: os error 1392). "gnu" keeps GNU ld / link.exe.'),
44
44
  linkSlots: z
45
45
  .union([z.literal('auto'), z.number().int().min(1).max(32)])
46
46
  .describe('GNU host: how many programs may link at the same time in the whole sandbox (other links wait). "auto" = one per 6 GB of sandbox memory, 1 to 4 (the memory governor slows links down too when memory runs short).'),
@@ -54,17 +54,14 @@ export const ToolchainsSchema = z.strictObject({
54
54
  sdkVersion: z.string().min(1).describe('"latest" or a Windows SDK build, e.g. "26100" or "10.0.22621".'),
55
55
  }),
56
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'),
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. Visual Studio is installed once and kept on the data disk (~6.5 GB); later boots put it back in seconds. The engine itself comes from the Epic Games Launcher or its source.', 'a .uproject or .uplugin'),
58
58
  acceptLicense: z
59
59
  .boolean()
60
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
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
62
  visualStudio: z
66
- .enum(['full', 'autosdk'])
67
- .describe('"full": install Visual Studio Community (the engine finds it through the Setup API; ~10 GB, redone every boot). "autosdk" (experimental): skip Visual Studio and build an Unreal AutoSDK tree from the portable MSVC in tools\\unreal\\autosdk (kept between sandboxes); UnrealBuildTool finds MSVC through AutoSDK, but the editor\'s Visual Studio integration is not available. Needs toolchains.msvc (turned on for you).'),
63
+ .enum(['full', 'buildtools'])
64
+ .describe('"full": Visual Studio Community with the C++ game workload (the IDE, its debugger and Unreal integration). "buildtools": only the Visual Studio Build Tools (MSVC, the Windows SDK and the .NET Framework parts UnrealBuildTool needs; no IDE). Either is installed once and kept on the data disk (tools\\visualstudio\\persist, ~6.5 GB for Community); later boots put it back in seconds.'),
68
65
  persistEngines: z
69
66
  .boolean()
70
67
  .describe('Engines the Epic Games Launcher installs go to tools\\unreal\\engines (kept between sandboxes, 40-60 GB each) and are registered with the launcher again every boot. Off: they go on the sandbox disk and are lost when it closes. Engines installed on this PC can be mapped instead (pcInstalls.unrealEngines).'),
@@ -1,26 +1,31 @@
1
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.
2
+ // settings are kept, and the file keeps the encoding it had: the launcher often writes UTF-16). Launcher 17+ reads
3
+ // Config\WindowsEditor, older ones Config\Windows: both get it. The watch reads it back to notice when the launcher
4
+ // renews it, or when you sign in here the first time.
4
5
  import fs from 'node:fs';
5
6
  import path from 'node:path';
6
- import { epicSettingsFile, MAX_EPIC_INI_BYTES, readEpicLogin, withEpicLogin, } from '../../../shared/accounts/index.js';
7
+ import { epicSettingsFiles, MAX_EPIC_INI_BYTES, readEpicLogin, withEpicLogin, } from '../../../shared/accounts/index.js';
7
8
  import { decodeText, encodeText, readBoundedFile } from '../../../shared/io/index.js';
8
9
  import { localAppData } from '../adapter.js';
9
- function settingsFile() {
10
- return epicSettingsFile(localAppData());
11
- }
12
10
  export const epicAdapter = {
13
11
  kind: 'epic',
14
12
  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));
13
+ for (const file of epicSettingsFiles(localAppData())) {
14
+ const bytes = readBoundedFile(file, MAX_EPIC_INI_BYTES);
15
+ const read = bytes ? decodeText(bytes) : { text: '', encoding: 'utf8' };
16
+ fs.mkdirSync(path.dirname(file), { recursive: true });
17
+ fs.writeFileSync(file, encodeText(withEpicLogin(read.text, p), read.encoding));
18
+ }
20
19
  return { summary: 'Epic Games Launcher: signed in with your saved sign-in' };
21
20
  },
22
21
  current() {
23
- const bytes = readBoundedFile(settingsFile(), MAX_EPIC_INI_BYTES);
24
- return bytes ? readEpicLogin(decodeText(bytes).text) : null;
22
+ // The newest place first: the one the launcher in this sandbox writes when it renews the sign-in.
23
+ for (const file of epicSettingsFiles(localAppData())) {
24
+ const bytes = readBoundedFile(file, MAX_EPIC_INI_BYTES);
25
+ const login = bytes ? readEpicLogin(decodeText(bytes).text) : null;
26
+ if (login)
27
+ return login;
28
+ }
29
+ return null;
25
30
  },
26
31
  };
@@ -52,9 +52,10 @@ export declare function bootResetPaths(agents: Readonly<Record<string, Harness>>
52
52
  }[];
53
53
  type CodexSettings = Config['codex'];
54
54
  /**
55
- * The flags every Codex start gets. Flags beat config.toml and a resumed thread's saved permissions, which is why the
56
- * sandbox does not rely on the file. Full access with no questions is the one flag that skips Codex's Windows sandbox
57
- * setup for certain. Pure.
55
+ * The flags every Codex start through the sandbox gets (the codex.cmd shim, the daemon's sessions). Flags beat
56
+ * config.toml and a resumed thread's saved permissions; config.toml carries the same settings for a start without
57
+ * them (codexConfigOwned). Full access with no questions is the one flag that skips Codex's Windows sandbox setup for
58
+ * certain. Pure.
58
59
  */
59
60
  export declare function codexArguments(c: CodexSettings): string[];
60
61
  /** The arguments an agent always starts with: its own, and for codex the sandbox's settings. */
@@ -62,10 +63,13 @@ export declare function agentArguments(name: string, harness: Harness, codex: Co
62
63
  /** The largest config.toml the sandbox edits. */
63
64
  export declare const MAX_CODEX_CONFIG_BYTES: number;
64
65
  /**
65
- * Codex's config.toml as the sandbox wants it, every other line byte for byte: the lines an older version wrote above
66
- * the first table (sandbox_mode, approval_policy, under the marker comment) are gone, `[windows] sandbox` follows
67
- * windowsSandbox ("off" removes the line, so Codex does not set up its own sandbox users), and
68
- * mcp_oauth_credentials_store = "file" is added when it is not set. Running it again changes nothing. Pure.
66
+ * Codex's config.toml as the sandbox wants it, every other line byte for byte. Above the first table, under the
67
+ * marker comment: sandbox_mode, approval_policy (and model, model_reasoning_effort when set), so ANY start of Codex
68
+ * obeys the codex settings, also one without the shim's flags (a copy installed with npm -g). The marked lines are
69
+ * replaced each time; a key the user set on a line of their own above the first table is left to them.
70
+ * `[windows] sandbox` follows windowsSandbox ("off" removes the line, which Codex adds back after its own setup, so it
71
+ * does not set up its own sandbox users), and mcp_oauth_credentials_store = "file" is added when it is not set.
72
+ * Keeps the file's line endings; running it again changes nothing. Pure.
69
73
  */
70
74
  export declare function codexConfigOwned(toml: string, c: CodexSettings): string;
71
75
  /**