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
@@ -25678,7 +25678,7 @@ var ToolchainsSchema = external_exports.strictObject({
25678
25678
  `"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.`
25679
25679
  ),
25680
25680
  linker: external_exports.enum(["lld", "gnu"]).describe(
25681
- `GNU host: "lld" links with Rust's own lld through MinGW's gcc (much less memory than GNU ld), "gnu" with GNU ld.`
25681
+ `"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.`
25682
25682
  ),
25683
25683
  linkSlots: external_exports.union([external_exports.literal("auto"), external_exports.number().int().min(1).max(32)]).describe(
25684
25684
  '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).'
@@ -25697,7 +25697,7 @@ var ToolchainsSchema = external_exports.strictObject({
25697
25697
  }),
25698
25698
  unreal: external_exports.strictObject({
25699
25699
  enabled: enabled(
25700
- "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.",
25700
+ "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.",
25701
25701
  "a .uproject or .uplugin"
25702
25702
  ),
25703
25703
  acceptLicense: external_exports.boolean().describe(
@@ -25706,11 +25706,8 @@ var ToolchainsSchema = external_exports.strictObject({
25706
25706
  components: StringsSchema.describe(
25707
25707
  'More Visual Studio workload or component IDs to add, e.g. ["Microsoft.VisualStudio.Component.VC.Llvm.Clang"].'
25708
25708
  ),
25709
- keepInstallFiles: external_exports.boolean().describe(
25710
- "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."
25711
- ),
25712
- visualStudio: external_exports.enum(["full", "autosdk"]).describe(
25713
- `"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).`
25709
+ visualStudio: external_exports.enum(["full", "buildtools"]).describe(
25710
+ '"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.'
25714
25711
  ),
25715
25712
  persistEngines: external_exports.boolean().describe(
25716
25713
  "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)."
@@ -25939,7 +25936,7 @@ var CHROME_DEVTOOLS_MCP_VERSION = "1.12.0";
25939
25936
  var BROWSER_USE_VERSION = "0.13.14";
25940
25937
  var PERPLEXITY_COMPUTER_MCP_URL = "https://www.perplexity.ai/rest/computer/mcp";
25941
25938
  var COMET_SIGNER = {
25942
- subject: ['^CN="?PERPLEXITY AI, INC\\.?"?(,|$)', '(^|, )O="?PERPLEXITY AI, INC\\.?"?(,|$)'],
25939
+ subject: ['(^|, )CN="?PERPLEXITY AI, INC\\.?"?(,|$)', '(^|, )O="?PERPLEXITY AI, INC\\.?"?(,|$)'],
25943
25940
  issuer: ["^CN=GlobalSign GCC R45 EV CodeSigning CA 2020(,|$)"]
25944
25941
  };
25945
25942
  var EDGE_EXE = "C:\\Program Files (x86)\\Microsoft\\Edge\\Application\\msedge.exe";
@@ -26041,7 +26038,77 @@ var AGENTS_WEB_APPS = [
26041
26038
  ];
26042
26039
 
26043
26040
  // src/shared/apps/catalogue-gamedev.ts
26044
- var GAMEDEV_APPS = [];
26041
+ var GAMEDEV_APPS = [
26042
+ {
26043
+ id: "krita",
26044
+ name: "Krita",
26045
+ category: "gamedev",
26046
+ about: "Painting and texture editor (PSD, layers, brushes), checked against the SHA-256 download.kde.org publishes.",
26047
+ size: "450 MB",
26048
+ source: { resolve: "krita" },
26049
+ exe: "krita.exe",
26050
+ needs: ["mesa"]
26051
+ },
26052
+ {
26053
+ id: "inkscape",
26054
+ name: "Inkscape",
26055
+ category: "gamedev",
26056
+ about: "Vector graphics for UI, icons and 2D art (SVG), checked against the SHA-256 inkscape.org publishes.",
26057
+ size: "400 MB",
26058
+ source: { resolve: "inkscape" },
26059
+ exe: "inkscape.exe",
26060
+ needs: ["7zip"]
26061
+ },
26062
+ {
26063
+ id: "audacity",
26064
+ name: "Audacity",
26065
+ category: "gamedev",
26066
+ about: "Records and edits sound effects and music (WAV, OGG, FLAC).",
26067
+ size: "80 MB",
26068
+ source: { github: "audacity/audacity", asset: "^audacity-win-[\\d.]+-(?:64bit\\.zip|x86_64\\.7z)$" },
26069
+ exe: "Audacity.exe",
26070
+ needs: ["7zip"]
26071
+ },
26072
+ {
26073
+ id: "renderdoc",
26074
+ name: "RenderDoc",
26075
+ category: "gamedev",
26076
+ about: "Captures a frame of a game (Unreal's -d3d12/-vulkan builds) to inspect every draw call, texture and shader. Needs the sandbox's GPU (vGPU) for live captures.",
26077
+ size: "70 MB",
26078
+ source: { resolve: "renderdoc" },
26079
+ exe: "qrenderdoc.exe"
26080
+ },
26081
+ {
26082
+ id: "f3d",
26083
+ name: "F3D",
26084
+ category: "gamedev",
26085
+ about: "Fast 3D viewer (FBX, glTF/GLB, OBJ, STL, PLY, 3DS, USD); renders still previews from the command line.",
26086
+ size: "100 MB",
26087
+ source: { github: "f3d-app/f3d", asset: "^F3D-[\\d.]+-Windows-x86_64\\.zip$" },
26088
+ exe: "f3d.exe",
26089
+ needs: ["mesa"]
26090
+ },
26091
+ {
26092
+ id: "imagemagick",
26093
+ name: "ImageMagick",
26094
+ category: "gamedev",
26095
+ about: "Converts and thumbnails textures (TGA, PSD, DDS, EXR, HDR) and builds contact sheets (magick montage).",
26096
+ size: "150 MB",
26097
+ source: { github: "ImageMagick/ImageMagick", asset: "^ImageMagick-[\\d.]+-\\d+-portable-Q16-HDRI-x64\\.7z$" },
26098
+ exe: "magick.exe",
26099
+ cli: true,
26100
+ needs: ["7zip"]
26101
+ },
26102
+ {
26103
+ id: "nomacs",
26104
+ name: "nomacs",
26105
+ category: "gamedev",
26106
+ about: "Image viewer for textures (TGA, PSD, DDS, EXR).",
26107
+ size: "60 MB",
26108
+ source: { github: "nomacs/nomacs", asset: "^nomacs-portable-win\\.zip$" },
26109
+ exe: "nomacs.exe"
26110
+ }
26111
+ ];
26045
26112
 
26046
26113
  // src/shared/apps/catalogue-mobile.ts
26047
26114
  var MOBILE_APPS = [];
@@ -27270,10 +27337,14 @@ var PcInstallsSchema = external_exports.strictObject({
27270
27337
  "Epic Games Launcher games (by their app name)",
27271
27338
  '["Fortnite"]'
27272
27339
  ),
27273
- unrealEngines: pick2(
27274
- external_exports.string().regex(/^(UE_)?\d+\.\d+$/),
27275
- "Unreal Engine versions installed with the Epic Games Launcher",
27276
- '["5.4"]'
27340
+ unrealEngines: external_exports.union([external_exports.literal("auto"), external_exports.boolean(), external_exports.array(external_exports.string().regex(/^(UE_)?\d+\.\d+$/))]).describe(
27341
+ '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"]).'
27342
+ ),
27343
+ unrealEngineFolders: external_exports.array(external_exports.string().min(3).max(260)).max(8).describe(
27344
+ "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."
27345
+ ),
27346
+ unrealAssets: external_exports.union([external_exports.literal("auto"), external_exports.boolean()]).describe(
27347
+ `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.`
27277
27348
  ),
27278
27349
  unityEditors: pick2(
27279
27350
  external_exports.string().regex(/^\d+\.\d+\.\d+[abfp]\d+$/),
@@ -26051,7 +26051,7 @@ var ToolchainsSchema = external_exports.strictObject({
26051
26051
  `"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.`
26052
26052
  ),
26053
26053
  linker: external_exports.enum(["lld", "gnu"]).describe(
26054
- `GNU host: "lld" links with Rust's own lld through MinGW's gcc (much less memory than GNU ld), "gnu" with GNU ld.`
26054
+ `"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.`
26055
26055
  ),
26056
26056
  linkSlots: external_exports.union([external_exports.literal("auto"), external_exports.number().int().min(1).max(32)]).describe(
26057
26057
  '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).'
@@ -26070,7 +26070,7 @@ var ToolchainsSchema = external_exports.strictObject({
26070
26070
  }),
26071
26071
  unreal: external_exports.strictObject({
26072
26072
  enabled: enabled(
26073
- "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.",
26073
+ "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.",
26074
26074
  "a .uproject or .uplugin"
26075
26075
  ),
26076
26076
  acceptLicense: external_exports.boolean().describe(
@@ -26079,11 +26079,8 @@ var ToolchainsSchema = external_exports.strictObject({
26079
26079
  components: StringsSchema.describe(
26080
26080
  'More Visual Studio workload or component IDs to add, e.g. ["Microsoft.VisualStudio.Component.VC.Llvm.Clang"].'
26081
26081
  ),
26082
- keepInstallFiles: external_exports.boolean().describe(
26083
- "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."
26084
- ),
26085
- visualStudio: external_exports.enum(["full", "autosdk"]).describe(
26086
- `"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).`
26082
+ visualStudio: external_exports.enum(["full", "buildtools"]).describe(
26083
+ '"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.'
26087
26084
  ),
26088
26085
  persistEngines: external_exports.boolean().describe(
26089
26086
  "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)."
@@ -26312,7 +26309,7 @@ var CHROME_DEVTOOLS_MCP_VERSION = "1.12.0";
26312
26309
  var BROWSER_USE_VERSION = "0.13.14";
26313
26310
  var PERPLEXITY_COMPUTER_MCP_URL = "https://www.perplexity.ai/rest/computer/mcp";
26314
26311
  var COMET_SIGNER = {
26315
- subject: ['^CN="?PERPLEXITY AI, INC\\.?"?(,|$)', '(^|, )O="?PERPLEXITY AI, INC\\.?"?(,|$)'],
26312
+ subject: ['(^|, )CN="?PERPLEXITY AI, INC\\.?"?(,|$)', '(^|, )O="?PERPLEXITY AI, INC\\.?"?(,|$)'],
26316
26313
  issuer: ["^CN=GlobalSign GCC R45 EV CodeSigning CA 2020(,|$)"]
26317
26314
  };
26318
26315
  var EDGE_EXE = "C:\\Program Files (x86)\\Microsoft\\Edge\\Application\\msedge.exe";
@@ -26414,7 +26411,77 @@ var AGENTS_WEB_APPS = [
26414
26411
  ];
26415
26412
 
26416
26413
  // src/shared/apps/catalogue-gamedev.ts
26417
- var GAMEDEV_APPS = [];
26414
+ var GAMEDEV_APPS = [
26415
+ {
26416
+ id: "krita",
26417
+ name: "Krita",
26418
+ category: "gamedev",
26419
+ about: "Painting and texture editor (PSD, layers, brushes), checked against the SHA-256 download.kde.org publishes.",
26420
+ size: "450 MB",
26421
+ source: { resolve: "krita" },
26422
+ exe: "krita.exe",
26423
+ needs: ["mesa"]
26424
+ },
26425
+ {
26426
+ id: "inkscape",
26427
+ name: "Inkscape",
26428
+ category: "gamedev",
26429
+ about: "Vector graphics for UI, icons and 2D art (SVG), checked against the SHA-256 inkscape.org publishes.",
26430
+ size: "400 MB",
26431
+ source: { resolve: "inkscape" },
26432
+ exe: "inkscape.exe",
26433
+ needs: ["7zip"]
26434
+ },
26435
+ {
26436
+ id: "audacity",
26437
+ name: "Audacity",
26438
+ category: "gamedev",
26439
+ about: "Records and edits sound effects and music (WAV, OGG, FLAC).",
26440
+ size: "80 MB",
26441
+ source: { github: "audacity/audacity", asset: "^audacity-win-[\\d.]+-(?:64bit\\.zip|x86_64\\.7z)$" },
26442
+ exe: "Audacity.exe",
26443
+ needs: ["7zip"]
26444
+ },
26445
+ {
26446
+ id: "renderdoc",
26447
+ name: "RenderDoc",
26448
+ category: "gamedev",
26449
+ about: "Captures a frame of a game (Unreal's -d3d12/-vulkan builds) to inspect every draw call, texture and shader. Needs the sandbox's GPU (vGPU) for live captures.",
26450
+ size: "70 MB",
26451
+ source: { resolve: "renderdoc" },
26452
+ exe: "qrenderdoc.exe"
26453
+ },
26454
+ {
26455
+ id: "f3d",
26456
+ name: "F3D",
26457
+ category: "gamedev",
26458
+ about: "Fast 3D viewer (FBX, glTF/GLB, OBJ, STL, PLY, 3DS, USD); renders still previews from the command line.",
26459
+ size: "100 MB",
26460
+ source: { github: "f3d-app/f3d", asset: "^F3D-[\\d.]+-Windows-x86_64\\.zip$" },
26461
+ exe: "f3d.exe",
26462
+ needs: ["mesa"]
26463
+ },
26464
+ {
26465
+ id: "imagemagick",
26466
+ name: "ImageMagick",
26467
+ category: "gamedev",
26468
+ about: "Converts and thumbnails textures (TGA, PSD, DDS, EXR, HDR) and builds contact sheets (magick montage).",
26469
+ size: "150 MB",
26470
+ source: { github: "ImageMagick/ImageMagick", asset: "^ImageMagick-[\\d.]+-\\d+-portable-Q16-HDRI-x64\\.7z$" },
26471
+ exe: "magick.exe",
26472
+ cli: true,
26473
+ needs: ["7zip"]
26474
+ },
26475
+ {
26476
+ id: "nomacs",
26477
+ name: "nomacs",
26478
+ category: "gamedev",
26479
+ about: "Image viewer for textures (TGA, PSD, DDS, EXR).",
26480
+ size: "60 MB",
26481
+ source: { github: "nomacs/nomacs", asset: "^nomacs-portable-win\\.zip$" },
26482
+ exe: "nomacs.exe"
26483
+ }
26484
+ ];
26418
26485
 
26419
26486
  // src/shared/apps/catalogue-mobile.ts
26420
26487
  var MOBILE_APPS = [];
@@ -27643,10 +27710,14 @@ var PcInstallsSchema = external_exports.strictObject({
27643
27710
  "Epic Games Launcher games (by their app name)",
27644
27711
  '["Fortnite"]'
27645
27712
  ),
27646
- unrealEngines: pick2(
27647
- external_exports.string().regex(/^(UE_)?\d+\.\d+$/),
27648
- "Unreal Engine versions installed with the Epic Games Launcher",
27649
- '["5.4"]'
27713
+ unrealEngines: external_exports.union([external_exports.literal("auto"), external_exports.boolean(), external_exports.array(external_exports.string().regex(/^(UE_)?\d+\.\d+$/))]).describe(
27714
+ '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"]).'
27715
+ ),
27716
+ unrealEngineFolders: external_exports.array(external_exports.string().min(3).max(260)).max(8).describe(
27717
+ "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."
27718
+ ),
27719
+ unrealAssets: external_exports.union([external_exports.literal("auto"), external_exports.boolean()]).describe(
27720
+ `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.`
27650
27721
  ),
27651
27722
  unityEditors: pick2(
27652
27723
  external_exports.string().regex(/^\d+\.\d+\.\d+[abfp]\d+$/),
@@ -28127,19 +28198,33 @@ var run = new RunDir(dataDir);
28127
28198
 
28128
28199
  // src/guest/runtime/process.ts
28129
28200
  import { spawn as spawn2, spawnSync } from "node:child_process";
28201
+ var outputSink = null;
28202
+ var captureOutput = () => outputSink?.capturing() ?? false;
28203
+ function logOutput(text) {
28204
+ for (const line of text.split(/\r?\n/)) if (line.trim()) outputSink?.line(line.trimEnd());
28205
+ }
28206
+ var CAPTURE_BYTES = 64 * 1024 * 1024;
28207
+ function scriptErrors(errors) {
28208
+ if (!errors) return;
28209
+ if (captureOutput()) logOutput(errors);
28210
+ else process.stderr.write(errors + "\n");
28211
+ }
28130
28212
  function execOutput(file2, args2, options = {}) {
28131
28213
  const result = spawnSync(file2, args2, { encoding: "utf8", windowsHide: true, ...options });
28132
28214
  return result.status === 0 ? String(result.stdout ?? "").trim() : "";
28133
28215
  }
28134
28216
  function runScript(name2, args2 = []) {
28217
+ const capture = captureOutput();
28135
28218
  const result = spawnSync(SYSTEM.powershell(), scriptArgs(name2, args2), {
28136
- stdio: ["inherit", "inherit", "pipe"],
28219
+ stdio: ["inherit", capture ? "pipe" : "inherit", "pipe"],
28137
28220
  encoding: "utf8",
28138
- windowsHide: true
28221
+ windowsHide: true,
28222
+ ...capture ? { maxBuffer: CAPTURE_BYTES } : {}
28139
28223
  });
28224
+ if (capture) logOutput(String(result.stdout ?? ""));
28140
28225
  if (result.error) throw result.error;
28141
28226
  const errors = String(result.stderr ?? "").trim();
28142
- if (errors) process.stderr.write(errors + "\n");
28227
+ scriptErrors(errors);
28143
28228
  if (result.status !== 0)
28144
28229
  throw new Error(name2 + " failed with exit code " + result.status + (errors ? ": " + errors.slice(0, 400) : ""));
28145
28230
  }
@@ -28250,36 +28335,45 @@ import path17 from "node:path";
28250
28335
  import fs11 from "node:fs";
28251
28336
  import path12 from "node:path";
28252
28337
  import { AsyncLocalStorage } from "node:async_hooks";
28338
+
28339
+ // src/guest/runtime/log-line.ts
28340
+ var ESCAPES = /\x1b\[[0-9;?]{0,32}[A-Za-z]/g;
28341
+ function plainText(text) {
28342
+ return text.replace(ESCAPES, "");
28343
+ }
28344
+ function fileLines(message, at = /* @__PURE__ */ new Date(), task) {
28345
+ const stamp = at.toISOString() + " " + (task ? "[" + task + "] " : "");
28346
+ return plainText(message).split(/\r?\n/).filter((line) => line.trim() !== "").map((line) => stamp + line.trimEnd());
28347
+ }
28348
+
28349
+ // src/guest/runtime/log.ts
28253
28350
  fs11.mkdirSync(logsDir, { recursive: true });
28254
28351
  var logFile = path12.join(
28255
28352
  logsDir,
28256
28353
  (process.env.AGENT_LOG_PREFIX ?? "guest") + "-" + (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-") + ".log"
28257
28354
  );
28258
28355
  var context = new AsyncLocalStorage();
28259
- function fileLine(message, at = /* @__PURE__ */ new Date()) {
28260
- return at.toISOString() + " " + message;
28261
- }
28262
- var append = (line) => {
28356
+ var sink = null;
28357
+ var append = (message, ctx) => {
28263
28358
  try {
28264
- fs11.appendFileSync(logFile, fileLine(line) + "\n");
28359
+ const lines = fileLines(message, /* @__PURE__ */ new Date(), ctx?.task);
28360
+ if (lines.length) fs11.appendFileSync(logFile, lines.join("\n") + "\n");
28265
28361
  } catch {
28266
28362
  }
28267
28363
  };
28268
- var tagged = (message, ctx) => {
28269
- const prefix = ctx?.prefix?.();
28270
- return prefix ? prefix + " | " + message : message;
28271
- };
28272
28364
  function log(message) {
28273
28365
  const ctx = context.getStore();
28274
- const line = tagged(message, ctx);
28275
- if (!ctx?.quiet) console.log(line);
28276
- append(line);
28366
+ append(message, ctx);
28367
+ if (ctx?.quiet) return;
28368
+ if (sink) sink.line(message, ctx?.stage);
28369
+ else console.log(message);
28277
28370
  }
28278
28371
  function warn(message) {
28279
28372
  const ctx = context.getStore();
28280
- const line = tagged(message, ctx);
28281
- if (!ctx?.quiet) console.warn("\x1B[33mWARNING: " + line + "\x1B[0m");
28282
- append("WARNING: " + line);
28373
+ append("WARNING: " + message, ctx);
28374
+ if (ctx?.quiet) return;
28375
+ if (sink) sink.warning(message);
28376
+ else console.warn("\x1B[33mWARNING: " + message + "\x1B[0m");
28283
28377
  }
28284
28378
 
28285
28379
  // src/guest/toolchains/signature.ts
@@ -6176,7 +6176,7 @@ function runTerminalClient(socket, token, options = {}) {
6176
6176
  socket.on("close", () => finish({ reason: "closed" }));
6177
6177
  socket.on("error", () => finish({ reason: "closed" }));
6178
6178
  const [c, r] = size();
6179
- stdout.write("\x1B[2J\x1B[3J\x1B[H");
6179
+ stdout.write("\x1B[2J\x1B[H");
6180
6180
  socket.write(helloFrame(token, c, r));
6181
6181
  if (stdin.isTTY) stdin.setRawMode(true);
6182
6182
  vtInput = enableVtInput();
@@ -26254,7 +26254,7 @@ var ToolchainsSchema = external_exports.strictObject({
26254
26254
  `"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.`
26255
26255
  ),
26256
26256
  linker: external_exports.enum(["lld", "gnu"]).describe(
26257
- `GNU host: "lld" links with Rust's own lld through MinGW's gcc (much less memory than GNU ld), "gnu" with GNU ld.`
26257
+ `"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.`
26258
26258
  ),
26259
26259
  linkSlots: external_exports.union([external_exports.literal("auto"), external_exports.number().int().min(1).max(32)]).describe(
26260
26260
  '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).'
@@ -26273,7 +26273,7 @@ var ToolchainsSchema = external_exports.strictObject({
26273
26273
  }),
26274
26274
  unreal: external_exports.strictObject({
26275
26275
  enabled: enabled(
26276
- "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.",
26276
+ "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.",
26277
26277
  "a .uproject or .uplugin"
26278
26278
  ),
26279
26279
  acceptLicense: external_exports.boolean().describe(
@@ -26282,11 +26282,8 @@ var ToolchainsSchema = external_exports.strictObject({
26282
26282
  components: StringsSchema.describe(
26283
26283
  'More Visual Studio workload or component IDs to add, e.g. ["Microsoft.VisualStudio.Component.VC.Llvm.Clang"].'
26284
26284
  ),
26285
- keepInstallFiles: external_exports.boolean().describe(
26286
- "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."
26287
- ),
26288
- visualStudio: external_exports.enum(["full", "autosdk"]).describe(
26289
- `"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).`
26285
+ visualStudio: external_exports.enum(["full", "buildtools"]).describe(
26286
+ '"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.'
26290
26287
  ),
26291
26288
  persistEngines: external_exports.boolean().describe(
26292
26289
  "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)."
@@ -26515,7 +26512,7 @@ var CHROME_DEVTOOLS_MCP_VERSION = "1.12.0";
26515
26512
  var BROWSER_USE_VERSION = "0.13.14";
26516
26513
  var PERPLEXITY_COMPUTER_MCP_URL = "https://www.perplexity.ai/rest/computer/mcp";
26517
26514
  var COMET_SIGNER = {
26518
- subject: ['^CN="?PERPLEXITY AI, INC\\.?"?(,|$)', '(^|, )O="?PERPLEXITY AI, INC\\.?"?(,|$)'],
26515
+ subject: ['(^|, )CN="?PERPLEXITY AI, INC\\.?"?(,|$)', '(^|, )O="?PERPLEXITY AI, INC\\.?"?(,|$)'],
26519
26516
  issuer: ["^CN=GlobalSign GCC R45 EV CodeSigning CA 2020(,|$)"]
26520
26517
  };
26521
26518
  var EDGE_EXE = "C:\\Program Files (x86)\\Microsoft\\Edge\\Application\\msedge.exe";
@@ -26617,7 +26614,77 @@ var AGENTS_WEB_APPS = [
26617
26614
  ];
26618
26615
 
26619
26616
  // src/shared/apps/catalogue-gamedev.ts
26620
- var GAMEDEV_APPS = [];
26617
+ var GAMEDEV_APPS = [
26618
+ {
26619
+ id: "krita",
26620
+ name: "Krita",
26621
+ category: "gamedev",
26622
+ about: "Painting and texture editor (PSD, layers, brushes), checked against the SHA-256 download.kde.org publishes.",
26623
+ size: "450 MB",
26624
+ source: { resolve: "krita" },
26625
+ exe: "krita.exe",
26626
+ needs: ["mesa"]
26627
+ },
26628
+ {
26629
+ id: "inkscape",
26630
+ name: "Inkscape",
26631
+ category: "gamedev",
26632
+ about: "Vector graphics for UI, icons and 2D art (SVG), checked against the SHA-256 inkscape.org publishes.",
26633
+ size: "400 MB",
26634
+ source: { resolve: "inkscape" },
26635
+ exe: "inkscape.exe",
26636
+ needs: ["7zip"]
26637
+ },
26638
+ {
26639
+ id: "audacity",
26640
+ name: "Audacity",
26641
+ category: "gamedev",
26642
+ about: "Records and edits sound effects and music (WAV, OGG, FLAC).",
26643
+ size: "80 MB",
26644
+ source: { github: "audacity/audacity", asset: "^audacity-win-[\\d.]+-(?:64bit\\.zip|x86_64\\.7z)$" },
26645
+ exe: "Audacity.exe",
26646
+ needs: ["7zip"]
26647
+ },
26648
+ {
26649
+ id: "renderdoc",
26650
+ name: "RenderDoc",
26651
+ category: "gamedev",
26652
+ about: "Captures a frame of a game (Unreal's -d3d12/-vulkan builds) to inspect every draw call, texture and shader. Needs the sandbox's GPU (vGPU) for live captures.",
26653
+ size: "70 MB",
26654
+ source: { resolve: "renderdoc" },
26655
+ exe: "qrenderdoc.exe"
26656
+ },
26657
+ {
26658
+ id: "f3d",
26659
+ name: "F3D",
26660
+ category: "gamedev",
26661
+ about: "Fast 3D viewer (FBX, glTF/GLB, OBJ, STL, PLY, 3DS, USD); renders still previews from the command line.",
26662
+ size: "100 MB",
26663
+ source: { github: "f3d-app/f3d", asset: "^F3D-[\\d.]+-Windows-x86_64\\.zip$" },
26664
+ exe: "f3d.exe",
26665
+ needs: ["mesa"]
26666
+ },
26667
+ {
26668
+ id: "imagemagick",
26669
+ name: "ImageMagick",
26670
+ category: "gamedev",
26671
+ about: "Converts and thumbnails textures (TGA, PSD, DDS, EXR, HDR) and builds contact sheets (magick montage).",
26672
+ size: "150 MB",
26673
+ source: { github: "ImageMagick/ImageMagick", asset: "^ImageMagick-[\\d.]+-\\d+-portable-Q16-HDRI-x64\\.7z$" },
26674
+ exe: "magick.exe",
26675
+ cli: true,
26676
+ needs: ["7zip"]
26677
+ },
26678
+ {
26679
+ id: "nomacs",
26680
+ name: "nomacs",
26681
+ category: "gamedev",
26682
+ about: "Image viewer for textures (TGA, PSD, DDS, EXR).",
26683
+ size: "60 MB",
26684
+ source: { github: "nomacs/nomacs", asset: "^nomacs-portable-win\\.zip$" },
26685
+ exe: "nomacs.exe"
26686
+ }
26687
+ ];
26621
26688
 
26622
26689
  // src/shared/apps/catalogue-mobile.ts
26623
26690
  var MOBILE_APPS = [];
@@ -27846,10 +27913,14 @@ var PcInstallsSchema = external_exports.strictObject({
27846
27913
  "Epic Games Launcher games (by their app name)",
27847
27914
  '["Fortnite"]'
27848
27915
  ),
27849
- unrealEngines: pick2(
27850
- external_exports.string().regex(/^(UE_)?\d+\.\d+$/),
27851
- "Unreal Engine versions installed with the Epic Games Launcher",
27852
- '["5.4"]'
27916
+ unrealEngines: external_exports.union([external_exports.literal("auto"), external_exports.boolean(), external_exports.array(external_exports.string().regex(/^(UE_)?\d+\.\d+$/))]).describe(
27917
+ '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"]).'
27918
+ ),
27919
+ unrealEngineFolders: external_exports.array(external_exports.string().min(3).max(260)).max(8).describe(
27920
+ "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."
27921
+ ),
27922
+ unrealAssets: external_exports.union([external_exports.literal("auto"), external_exports.boolean()]).describe(
27923
+ `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.`
27853
27924
  ),
27854
27925
  unityEditors: pick2(
27855
27926
  external_exports.string().regex(/^\d+\.\d+\.\d+[abfp]\d+$/),
@@ -6,7 +6,7 @@ import { DEFAULTS, mergeConfig, validateConfig } from '../core/config/index.js';
6
6
  import { isWin } from '../core/util/index.js';
7
7
  import { SYSTEM } from '../shared/system.js';
8
8
  import { agentCommand, agentShims, bootResetPaths, isCopyableDatabaseFile, isDatabaseFile, localStateEntries, shimText, } from '../guest/agents/agent-files.js';
9
- import { appendMissing, expandVars, installedToolPaths, isGitUsrBin, isMsvcToolsDir, isPinnedNodeDir, msvcBeforeGitUsr, parseRegPath, pathKey, planPath, rebuildPath, splitPath, } from '../guest/setup/path-plan.js';
9
+ import { appendMissing, expandVars, installedToolPaths, isGitUsrBin, isMsvcToolsDir, isPinnedNodeDir, msvcBeforeGitUsr, parseRegPath, pathKey, planPath, rebuildPath, sessionPath, splitPath, } from '../guest/setup/path-plan.js';
10
10
  import { withReloadEnvironment } from '../host/tools/index.js';
11
11
  import { HarnessSchema } from '../core/schema/index.js';
12
12
  export const agentPathsSuite = {
@@ -56,6 +56,7 @@ export const agentPathsSuite = {
56
56
  'C:\\AgentData\\state\\codex\\.sandbox\\setup_marker.json',
57
57
  'C:\\AgentData\\state\\codex\\.sandbox\\deny_read_acl_state.json',
58
58
  'C:\\AgentData\\state\\codex\\tmp\\arg0',
59
+ 'C:\\AgentData\\state\\codex\\tmp\\arg0-windows',
59
60
  ], "codex's DPAPI-sealed sandbox users and setup marker are removed at boot (CryptUnprotectData otherwise)");
60
61
  t.check(HarnessSchema.safeParse({ ...DEFAULTS.harnesses.codex, bootReset: ['..\\login'] }).success === false &&
61
62
  HarnessSchema.safeParse({ ...DEFAULTS.harnesses.codex, bootReset: ['C:\\Windows'] }).success === false, 'bootReset takes only plain paths below the agent state folder');
@@ -64,6 +65,22 @@ export const agentPathsSuite = {
64
65
  const exists = (f) => present.has(pathKey(f));
65
66
  t.equal(planPath({ entries: ['C:\\A\\;c:\\b', 'C:\\a', 'C:\\missing;"C:\\C\\D"', '', 'c:/B'], exists }), ['C:\\A\\', 'c:\\b', 'C:\\C\\D'], 'ordered, no duplicates (case, slash, quotes), no missing folders');
66
67
  t.equal(planPath({ entries: ['C:\\a;C:\\nvm\\v24.1.0'], exists, drop: (f) => isPinnedNodeDir(f, 'C:\\NVM') }), ['C:\\a'], 'a pinned node version is never machine-wide');
68
+ const agentPath = sessionPath({
69
+ commands: 'C:\\nvm\\bin',
70
+ prepend: ['C:\\AgentData\\tools\\bin', 'C:\\AgentData\\tools\\nvm', 'C:\\nvm\\nodejs'],
71
+ base: ['C:\\Windows\\system32', 'c:\\NVM\\bin\\'],
72
+ append: ['C:\\AgentData\\tools\\agents\\codex'],
73
+ });
74
+ t.equal(agentPath, [
75
+ 'C:\\nvm\\bin',
76
+ 'C:\\AgentData\\tools\\bin',
77
+ 'C:\\AgentData\\tools\\nvm',
78
+ 'C:\\nvm\\nodejs',
79
+ 'C:\\Windows\\system32',
80
+ 'C:\\AgentData\\tools\\agents\\codex',
81
+ ], "the sandbox's agent shims come first, before nvm's node folder (an npm -g codex there) and the agent's own folder");
82
+ t.equal(planPath({ entries: [agentPath.join(';')], exists: () => true })[0], 'C:\\nvm\\bin', 'and stay first on the machine PATH that terminal tabs get');
83
+ t.equal(rebuildPath({ machine: agentPath.join(';'), user: 'C:\\nvm\\nodejs', process: '', env: {} }).split(';')[0], 'C:\\nvm\\bin', 'a new shell keeps them first');
67
84
  t.check(isPinnedNodeDir('C:\\nvm\\v24.1.0\\', 'C:\\nvm') && !isPinnedNodeDir('C:\\nvm', 'C:\\nvm'), 'only versions are pinned');
68
85
  t.equal(pathKey('C:\\'), 'c:\\', 'a drive root keeps its slash');
69
86
  t.equal(splitPath(' "C:\\a" ;; C:\\b;'), ['C:\\a', 'C:\\b'], 'splitting drops empty parts and quotes');
@@ -30,14 +30,45 @@ export const agentSettingsSuite = {
30
30
  t.section('codex config.toml');
31
31
  const old = '# Set by the sandbox: x\nsandbox_mode = "danger-full-access"\n\n[tui]\nscreen_reader_detection_done = true\n\n[windows]\nsandbox = "elevated"\n';
32
32
  const owned = codexConfigOwned(old, CODEX);
33
- t.check(!owned.includes('sandbox_mode') && !owned.includes('Set by the sandbox') && !owned.includes('sandbox = '), 'the old sandbox_mode lines and [windows] sandbox are removed', owned);
34
- t.check(owned.includes('mcp_oauth_credentials_store = "file"') &&
35
- owned.includes('[tui]\nscreen_reader_detection_done = true\n') &&
36
- owned.includes('[windows]'), 'MCP logins go to a file; every other line stays', owned);
33
+ const marker = owned.split('\n')[0];
34
+ t.check(marker.startsWith('# Set by the sandbox'), 'the marked lines start the file', owned);
35
+ t.equal(owned, marker +
36
+ '\nsandbox_mode = "danger-full-access"\napproval_policy = "never"\n\nmcp_oauth_credentials_store = "file"\n\n' +
37
+ '[tui]\nscreen_reader_detection_done = true\n\n[windows]\n', 'sandbox_mode and approval_policy are written above the first table (the old marked lines replaced), MCP logins go to a file, [windows] sandbox is removed for "off", every other line stays');
37
38
  t.equal(codexConfigOwned(owned, CODEX), owned, 'running it again changes nothing');
39
+ t.equal(codexConfigOwned(owned, { ...CODEX, sandboxMode: 'workspace-write', approvalPolicy: 'on-request' }), owned
40
+ .replace('"danger-full-access"', '"workspace-write"')
41
+ .replace('approval_policy = "never"', 'approval_policy = "on-request"'), 'changed settings replace the marked lines in place');
42
+ const tuned = codexConfigOwned('', { ...CODEX, model: 'gpt-5', reasoningEffort: 'high', mcpLoginsInFile: false });
43
+ t.equal(tuned.split('\n').slice(1), [
44
+ 'sandbox_mode = "danger-full-access"',
45
+ 'approval_policy = "never"',
46
+ 'model = "gpt-5"',
47
+ 'model_reasoning_effort = "high"',
48
+ '',
49
+ ], 'model and reasoning effort are written when set (an empty file gets only the marked lines)');
50
+ t.equal(codexConfigOwned(tuned, { ...CODEX, mcpLoginsInFile: false }), tuned.replace('model = "gpt-5"\nmodel_reasoning_effort = "high"\n', ''), 'and removed again when cleared');
51
+ const mine = 'approval_policy = "on-request"\n\n[windows]\nsandbox = "elevated"\n';
52
+ const respected = codexConfigOwned(mine, { ...CODEX, mcpLoginsInFile: false });
53
+ t.check(respected.includes('sandbox_mode = "danger-full-access"') &&
54
+ respected.includes('approval_policy = "on-request"') &&
55
+ !respected.includes('approval_policy = "never"') &&
56
+ !respected.includes('sandbox = "elevated"'), "a user's own unmarked line is kept and not written again", respected);
57
+ t.equal(codexConfigOwned(respected, { ...CODEX, mcpLoginsInFile: false }), respected, 'stable with it too');
58
+ const crlf = old.replace(/\n/g, '\r\n');
59
+ const ownedCrlf = codexConfigOwned(crlf, CODEX);
60
+ t.equal(ownedCrlf, owned.replace(/\n/g, '\r\n'), 'a CRLF file is edited the same way and keeps CRLF');
61
+ t.equal(codexConfigOwned(ownedCrlf, CODEX), ownedCrlf, 'running it again on CRLF changes nothing');
62
+ const byHand = '# agent-sandbox: Windows Sandbox already contains Codex; its own command sandbox is off.\n' +
63
+ 'sandbox_mode = "danger-full-access"\napproval_policy = "never"\nmcp_oauth_credentials_store = "file"\n\n' +
64
+ '[tui]\nscreen_reader_detection_done = true\n\n[projects.\'c:\\x\']\ntrust_level = "trusted"\n';
65
+ const adopted = codexConfigOwned(byHand, CODEX);
66
+ t.equal(adopted, marker +
67
+ '\nsandbox_mode = "danger-full-access"\napproval_policy = "never"\n\nmcp_oauth_credentials_store = "file"\n\n' +
68
+ '[tui]\nscreen_reader_detection_done = true\n\n[projects.\'c:\\x\']\ntrust_level = "trusted"\n', 'lines under the hand-made "# agent-sandbox:" marker count as the sandbox\'s and are replaced');
69
+ t.equal(codexConfigOwned(adopted, CODEX), adopted, 'and stay stable after that');
38
70
  t.includes(codexConfigOwned(old, { ...CODEX, windowsSandbox: 'unelevated' }), '[windows]\nsandbox = "unelevated"', 'a Windows sandbox mode is written when asked for');
39
71
  t.includes(codexConfigOwned('mcp_oauth_credentials_store = "keyring"\n', CODEX), 'mcp_oauth_credentials_store = "keyring"', "a user's own mcp_oauth_credentials_store is kept");
40
- t.equal(codexConfigOwned('', { ...CODEX, mcpLoginsInFile: false }), '', 'an empty file stays empty when nothing is owned');
41
72
  t.section('Anthropic key pattern');
42
73
  const body = 'a'.repeat(60);
43
74
  t.check(ANTHROPIC_KEY_PATTERN.test('sk-ant-usr01-' + body) && ANTHROPIC_KEY_PATTERN.test('sk-ant-api03-' + body), 'sk-ant-api03- and sk-ant-usr01- keys are accepted');