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
@@ -0,0 +1,83 @@
1
+ export const UNREAL_SAMPLE = {
2
+ setUp: true,
3
+ checkedAt: '2026-11-04T12:00:00.000Z',
4
+ engines: [
5
+ {
6
+ id: 'UE_5.6',
7
+ version: '5.6.1',
8
+ dir: 'C:\\PcInstalls\\unreal\\UE_5.6',
9
+ where: 'this PC, read-only',
10
+ writable: false,
11
+ build: 'installed',
12
+ sizeBytes: null,
13
+ projects: ['ShooterGame'],
14
+ },
15
+ {
16
+ id: 'UE_5.4',
17
+ version: '5.4.4',
18
+ dir: 'C:\\AgentData\\tools\\unreal\\engines\\UE_5.4',
19
+ where: 'Epic Games Launcher, data disk',
20
+ writable: true,
21
+ build: 'installed',
22
+ sizeBytes: 48 * 1024 ** 3,
23
+ projects: [],
24
+ },
25
+ ],
26
+ projects: [{ project: 'ShooterGame', engine: 'UE_5.6', reason: 'the project asks for 5.6' }],
27
+ launcher: {
28
+ installed: true,
29
+ installLocation: 'C:\\AgentData\\tools\\unreal\\engines',
30
+ problem: null,
31
+ free: '812 GB',
32
+ },
33
+ visualStudio: {
34
+ version: '17.14.37827.9',
35
+ path: 'C:\\AgentData\\tools\\visualstudio\\persist\\Community',
36
+ how: 'kept on the data disk',
37
+ check: 'Visual Studio 17.14.37827.9, MSVC 14.44.35207, Windows SDK 10.0.22621.0',
38
+ ok: true,
39
+ },
40
+ debugger: 'C:\\AgentData\\tools\\visualstudio\\persist\\WindowsKits10\\Debuggers\\x64\\cdb.exe',
41
+ ddc: 'C:\\AgentData\\tools\\unreal\\ddc',
42
+ mcpUrl: null,
43
+ pc: {
44
+ setting: 'auto',
45
+ engines: [
46
+ {
47
+ id: 'UE_5.6',
48
+ name: 'Unreal Engine 5.6.1',
49
+ folder: 'C:\\Program Files\\Epic Games\\UE_5.6',
50
+ writable: false,
51
+ source: false,
52
+ },
53
+ {
54
+ id: 'dir-UnrealEngine',
55
+ name: 'Unreal Engine 5.7.0 (UnrealEngine)',
56
+ folder: 'D:\\Src\\UnrealEngine',
57
+ writable: true,
58
+ source: false,
59
+ },
60
+ ],
61
+ problem: null,
62
+ },
63
+ vault: {
64
+ setting: 'auto',
65
+ folders: [
66
+ {
67
+ folder: 'C:\\ProgramData\\Epic\\EpicGamesLauncher\\VaultCache',
68
+ packs: [
69
+ { name: 'CityParkEnvironment', size: '2.1 GB', kind: 'content' },
70
+ { name: 'ToolkitPlugin', size: '45 MB', kind: 'plugin' },
71
+ ],
72
+ more: 0,
73
+ },
74
+ ],
75
+ },
76
+ settings: {
77
+ enabled: 'auto',
78
+ acceptLicense: true,
79
+ persistEngines: true,
80
+ derivedDataCache: 'persisted',
81
+ visualStudio: 'full',
82
+ },
83
+ };
@@ -8,12 +8,12 @@ import { decidePwsh, pcHasPwsh, PWSH_MAX_BYTES, readPwshScripts, usesPwsh } from
8
8
  import { projectFolderLines, toolLines } from '../guest/boot/guide-lines.js';
9
9
  import { binstallAsset, CLI_TOOLS, decideCli, pwshAsset } from '../guest/toolchains/catalogue.js';
10
10
  import { missingExtensions, vscodeExtensions, vscodeSettings } from '../guest/toolchains/tools/vscode-profile.js';
11
- import { addonGuideLine, addonMcpServer, APP_CATEGORIES, APPS, appsNeedMesa, appsNeedUv, appsToInstall, CCUSAGE_VERSION, claudeManagedSettings, CONTEXT7_MCP_VERSION, exeMatcher, HEADROOM_VERSION, headroomArgs, headroomEnv, headroomUrl, PLAYWRIGHT_MCP_VERSION, RTK_VERSION, withAddonMcpServers, } from '../shared/apps/index.js';
11
+ import { addonGuideLine, addonMcpServer, APP_CATEGORIES, APPS, associationPlan, appsNeedMesa, appsNeedUv, appsToInstall, CCUSAGE_VERSION, claudeManagedSettings, CONTEXT7_MCP_VERSION, exeMatcher, HEADROOM_VERSION, headroomArgs, headroomEnv, headroomUrl, PLAYWRIGHT_MCP_VERSION, previewGuideLine, RTK_VERSION, withAddonMcpServers, } from '../shared/apps/index.js';
12
12
  import { ConfigSchema, LocalOverridesSchema } from '../core/schema/index.js';
13
13
  export const toolchainsSuite = {
14
14
  name: 'toolchains',
15
15
  title: 'version pickers, release assets, PowerShell 7 and CLI tool decisions',
16
- run: (t) => {
16
+ run: async (t) => {
17
17
  t.section('version pickers');
18
18
  const releases = [
19
19
  { version: 'v23.1.0', lts: false },
@@ -198,6 +198,36 @@ export const toolchainsSuite = {
198
198
  t.check(ids.every((id, i) => ids.indexOf(id) === i) &&
199
199
  APPS.every((a) => APP_CATEGORIES.some((c) => c.id === a.category)) &&
200
200
  !APPS.some(badPattern), 'apps: ids are unique, every app is in a known category, every GitHub asset pattern compiles');
201
+ t.section('asset preview apps');
202
+ const previewPick = (id, files) => {
203
+ const source = APPS.find((x) => x.id === id)?.source;
204
+ const re = new RegExp(source && 'github' in source ? source.asset : '$^');
205
+ return files.filter((f) => re.test(f));
206
+ };
207
+ t.check(['f3d', 'imagemagick', 'nomacs'].every((id) => APPS.some((a) => a.id === id && a.category === 'gamedev')) &&
208
+ previewPick('f3d', [
209
+ 'F3D-4.0.1-Windows-x86_64.zip',
210
+ 'F3D-4.0.1-Windows-x86_64.exe',
211
+ 'F3D-4.0.1-Windows-x86_64-raytracing.zip',
212
+ ]).join() === 'F3D-4.0.1-Windows-x86_64.zip' &&
213
+ previewPick('imagemagick', [
214
+ 'ImageMagick-7.1.2-35-portable-Q16-HDRI-x64.7z',
215
+ 'ImageMagick-7.1.2-35-portable-Q16-x64.7z',
216
+ 'ImageMagick-7.1.2-35-portable-Q16-HDRI-arm64.7z',
217
+ ]).join() === 'ImageMagick-7.1.2-35-portable-Q16-HDRI-x64.7z' &&
218
+ previewPick('nomacs', ['nomacs-portable-win.zip', 'nomacs-setup.exe']).join() === 'nomacs-portable-win.zip', 'preview apps: F3D, ImageMagick and nomacs are in the catalogue and pick the portable download only');
219
+ const f3d = associationPlan('f3d', 'C:\\x\\f3d.exe');
220
+ t.check(f3d.some((v) => v.key === 'Software\\Classes\\.fbx' && v.value === 'Sandbox.f3d') &&
221
+ f3d.some((v) => v.key.endsWith('\\shell\\open\\command') && v.value === '"C:\\x\\f3d.exe" "%1"') &&
222
+ f3d.every((v) => v.hive === 'HKCU' && v.name === '') &&
223
+ associationPlan('nomacs', 'C:\\x\\nomacs.exe').some((v) => v.key === 'Software\\Classes\\.tga') &&
224
+ associationPlan('krita', 'C:\\x\\k.exe').length === 0, 'preview apps: double-click associations name the app per extension; an app without any gets none');
225
+ await t.throws(() => associationPlan('f3d', 'f3d.exe'), 'not a program path', 'a relative program path is refused');
226
+ await t.throws(() => associationPlan('f3d', 'C:\\a"b.exe'), 'not a program path', 'a quoted program path is refused');
227
+ t.check(previewGuideLine([]) === null &&
228
+ previewGuideLine(['jq']) === null &&
229
+ (previewGuideLine(['f3d']) ?? '').includes('--output=') &&
230
+ previewGuideLine(['imagemagick']) !== null, 'preview apps: the agent preview line appears only when F3D or ImageMagick is installed');
201
231
  t.check(exeMatcher('/^Godot_v[\\d.]+-stable_win64\\.exe$/')('Godot_v4.7.2-stable_win64.exe') &&
202
232
  !exeMatcher('/^Godot_v[\\d.]+-stable_win64\\.exe$/')('Godot_v4.7.2-stable_win64_console.exe') &&
203
233
  exeMatcher('Code.exe')('code.EXE'), 'apps: the program is found by name or by pattern');
@@ -1,7 +1,7 @@
1
1
  export * from './kinds.js';
2
2
  export * from './payloads.js';
3
3
  export { fingerprint } from './fingerprint.js';
4
- export { epicSettingsFile, MAX_EPIC_INI_BYTES, readEpicLogin, withEpicLogin, type EpicPayload } from './kinds/epic.js';
4
+ export { epicSettingsFile, epicSettingsFiles, MAX_EPIC_INI_BYTES, readEpicLogin, withEpicLogin, type EpicPayload, } from './kinds/epic.js';
5
5
  export * from './kinds/steam.js';
6
6
  export { PERPLEXITY_ENV, perplexityKeyFromText, perplexitySummary, type PerplexityPayload, } from './kinds/perplexity.js';
7
7
  export { cometPayloadFromCookies, cometSummary, cookiesToRestore, type CometPayload } from './kinds/comet.js';
@@ -3,7 +3,7 @@
3
3
  export * from './kinds.js';
4
4
  export * from './payloads.js';
5
5
  export { fingerprint } from './fingerprint.js';
6
- export { epicSettingsFile, MAX_EPIC_INI_BYTES, readEpicLogin, withEpicLogin } from './kinds/epic.js';
6
+ export { epicSettingsFile, epicSettingsFiles, MAX_EPIC_INI_BYTES, readEpicLogin, withEpicLogin, } from './kinds/epic.js';
7
7
  export * from './kinds/steam.js';
8
8
  export { PERPLEXITY_ENV, perplexityKeyFromText, perplexitySummary, } from './kinds/perplexity.js';
9
9
  export { cometPayloadFromCookies, cometSummary, cookiesToRestore } from './kinds/comet.js';
@@ -2,8 +2,13 @@ import type { Payload } from '../payloads.js';
2
2
  /** At most this much of a GameUserSettings.ini is read. */
3
3
  export declare const MAX_EPIC_INI_BYTES: number;
4
4
  export type EpicPayload = Payload<'epic'>;
5
- /** GameUserSettings.ini under a LocalAppData folder (the PC's or the sandbox's). */
5
+ /** GameUserSettings.ini under a LocalAppData folder (the PC's or the sandbox's), where launchers before 17 keep it. */
6
6
  export declare function epicSettingsFile(localAppData: string): string;
7
+ /**
8
+ * Every GameUserSettings.ini the launcher may read, newest place first: launcher 17 and later (20.3 checked) keep it in
9
+ * Config\WindowsEditor, older ones in Config\Windows.
10
+ */
11
+ export declare function epicSettingsFiles(localAppData: string): string[];
7
12
  /** The saved sign-in in an ini text, or null (none, turned off, or not the expected shape). */
8
13
  export declare function readEpicLogin(ini: string): EpicPayload | null;
9
14
  /** The ini text with its [RememberMe] section replaced by this sign-in (the other sections are kept). */
@@ -6,10 +6,20 @@ import { EpicPayloadSchema } from '../payloads.js';
6
6
  /** At most this much of a GameUserSettings.ini is read. */
7
7
  export const MAX_EPIC_INI_BYTES = 1024 * 1024;
8
8
  const SECTION = '[rememberme]';
9
- /** GameUserSettings.ini under a LocalAppData folder (the PC's or the sandbox's). */
9
+ /** GameUserSettings.ini under a LocalAppData folder (the PC's or the sandbox's), where launchers before 17 keep it. */
10
10
  export function epicSettingsFile(localAppData) {
11
11
  return localAppData + '\\EpicGamesLauncher\\Saved\\Config\\Windows\\GameUserSettings.ini';
12
12
  }
13
+ /**
14
+ * Every GameUserSettings.ini the launcher may read, newest place first: launcher 17 and later (20.3 checked) keep it in
15
+ * Config\WindowsEditor, older ones in Config\Windows.
16
+ */
17
+ export function epicSettingsFiles(localAppData) {
18
+ return [
19
+ localAppData + '\\EpicGamesLauncher\\Saved\\Config\\WindowsEditor\\GameUserSettings.ini',
20
+ epicSettingsFile(localAppData),
21
+ ];
22
+ }
13
23
  const isHeader = (line) => line.trimStart().startsWith('[');
14
24
  /** The saved sign-in in an ini text, or null (none, turned off, or not the expected shape). */
15
25
  export function readEpicLogin(ini) {
@@ -0,0 +1,7 @@
1
+ import type { RegistryValue } from '../unreal/engines.js';
2
+ export declare const ASSOCIATIONS: {
3
+ readonly f3d: readonly [".fbx", ".glb", ".gltf", ".obj", ".stl", ".ply", ".3ds", ".usd", ".usdz"];
4
+ readonly nomacs: readonly [".tga", ".psd", ".dds", ".exr"];
5
+ };
6
+ /** The registry values that make `appId` open its file types; no values for an app that opens none. */
7
+ export declare function associationPlan(appId: string, exe: string): RegistryValue[];
@@ -0,0 +1,26 @@
1
+ // Which apps open which game-asset files when you double-click them (per user, written to the registry each boot
2
+ // because the sandbox's registry is new every time). Pure: the guest writes the plan with set-registry-values.ps1.
3
+ import path from 'node:path';
4
+ export const ASSOCIATIONS = {
5
+ f3d: ['.fbx', '.glb', '.gltf', '.obj', '.stl', '.ply', '.3ds', '.usd', '.usdz'],
6
+ nomacs: ['.tga', '.psd', '.dds', '.exr'],
7
+ };
8
+ const NAMES = { f3d: 'F3D', nomacs: 'nomacs' };
9
+ /** The registry values that make `appId` open its file types; no values for an app that opens none. */
10
+ export function associationPlan(appId, exe) {
11
+ if (!Object.hasOwn(ASSOCIATIONS, appId))
12
+ return [];
13
+ const id = appId;
14
+ if (!path.win32.isAbsolute(exe) || /["\r\n]/.test(exe))
15
+ throw new Error('not a program path: ' + exe);
16
+ const classes = 'Software\\Classes';
17
+ const type = classes + '\\Sandbox.' + id;
18
+ const quoted = '"' + exe + '"';
19
+ const v = (key, value) => ({ hive: 'HKCU', key, name: '', value });
20
+ return [
21
+ ...ASSOCIATIONS[id].map((ext) => v(classes + '\\' + ext, 'Sandbox.' + id)),
22
+ v(type, NAMES[id] + ' file'),
23
+ v(type + '\\DefaultIcon', quoted + ',0'),
24
+ v(type + '\\shell\\open\\command', quoted + ' "%1"'),
25
+ ];
26
+ }
@@ -9,6 +9,9 @@ export declare const BROWSER_USE_VERSION = "0.13.14";
9
9
  export declare const PERPLEXITY_COMPUTER_MCP_URL = "https://www.perplexity.ai/rest/computer/mcp";
10
10
  /** Comet's Windows installer: a redirect to the current release (no checksum is published; its signer is checked). */
11
11
  export declare const COMET_DOWNLOAD_URL = "https://www.perplexity.ai/rest/browser/download?platform=win_x64&channel=stable";
12
- /** Who signs Comet: Perplexity AI, Inc., with an EV code-signing certificate from GlobalSign. */
12
+ /**
13
+ * Who signs Comet: Perplexity AI, Inc., with an EV code-signing certificate from GlobalSign. Windows reports the
14
+ * subject with E=<contact address> first (E=..., CN="PERPLEXITY AI, INC.", O=...), so CN is not at the start.
15
+ */
13
16
  export declare const COMET_SIGNER: AppSigner;
14
17
  export declare const AGENTS_WEB_APPS: readonly AppEntry[];
@@ -7,9 +7,12 @@ export const BROWSER_USE_VERSION = '0.13.14';
7
7
  export const PERPLEXITY_COMPUTER_MCP_URL = 'https://www.perplexity.ai/rest/computer/mcp';
8
8
  /** Comet's Windows installer: a redirect to the current release (no checksum is published; its signer is checked). */
9
9
  export const COMET_DOWNLOAD_URL = 'https://www.perplexity.ai/rest/browser/download?platform=win_x64&channel=stable';
10
- /** Who signs Comet: Perplexity AI, Inc., with an EV code-signing certificate from GlobalSign. */
10
+ /**
11
+ * Who signs Comet: Perplexity AI, Inc., with an EV code-signing certificate from GlobalSign. Windows reports the
12
+ * subject with E=<contact address> first (E=..., CN="PERPLEXITY AI, INC.", O=...), so CN is not at the start.
13
+ */
11
14
  export const COMET_SIGNER = {
12
- subject: ['^CN="?PERPLEXITY AI, INC\\.?"?(,|$)', '(^|, )O="?PERPLEXITY AI, INC\\.?"?(,|$)'],
15
+ subject: ['(^|, )CN="?PERPLEXITY AI, INC\\.?"?(,|$)', '(^|, )O="?PERPLEXITY AI, INC\\.?"?(,|$)'],
13
16
  issuer: ['^CN=GlobalSign GCC R45 EV CodeSigning CA 2020(,|$)'],
14
17
  };
15
18
  /** Microsoft Edge, already in every sandbox: the browser Chrome DevTools MCP starts. */
@@ -1 +1,71 @@
1
- export const GAMEDEV_APPS = [];
1
+ export const GAMEDEV_APPS = [
2
+ {
3
+ id: 'krita',
4
+ name: 'Krita',
5
+ category: 'gamedev',
6
+ about: 'Painting and texture editor (PSD, layers, brushes), checked against the SHA-256 download.kde.org publishes.',
7
+ size: '450 MB',
8
+ source: { resolve: 'krita' },
9
+ exe: 'krita.exe',
10
+ needs: ['mesa'],
11
+ },
12
+ {
13
+ id: 'inkscape',
14
+ name: 'Inkscape',
15
+ category: 'gamedev',
16
+ about: 'Vector graphics for UI, icons and 2D art (SVG), checked against the SHA-256 inkscape.org publishes.',
17
+ size: '400 MB',
18
+ source: { resolve: 'inkscape' },
19
+ exe: 'inkscape.exe',
20
+ needs: ['7zip'],
21
+ },
22
+ {
23
+ id: 'audacity',
24
+ name: 'Audacity',
25
+ category: 'gamedev',
26
+ about: 'Records and edits sound effects and music (WAV, OGG, FLAC).',
27
+ size: '80 MB',
28
+ source: { github: 'audacity/audacity', asset: '^audacity-win-[\\d.]+-(?:64bit\\.zip|x86_64\\.7z)$' },
29
+ exe: 'Audacity.exe',
30
+ needs: ['7zip'],
31
+ },
32
+ {
33
+ id: 'renderdoc',
34
+ name: 'RenderDoc',
35
+ category: 'gamedev',
36
+ 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.",
37
+ size: '70 MB',
38
+ source: { resolve: 'renderdoc' },
39
+ exe: 'qrenderdoc.exe',
40
+ },
41
+ {
42
+ id: 'f3d',
43
+ name: 'F3D',
44
+ category: 'gamedev',
45
+ about: 'Fast 3D viewer (FBX, glTF/GLB, OBJ, STL, PLY, 3DS, USD); renders still previews from the command line.',
46
+ size: '100 MB',
47
+ source: { github: 'f3d-app/f3d', asset: '^F3D-[\\d.]+-Windows-x86_64\\.zip$' },
48
+ exe: 'f3d.exe',
49
+ needs: ['mesa'],
50
+ },
51
+ {
52
+ id: 'imagemagick',
53
+ name: 'ImageMagick',
54
+ category: 'gamedev',
55
+ about: 'Converts and thumbnails textures (TGA, PSD, DDS, EXR, HDR) and builds contact sheets (magick montage).',
56
+ size: '150 MB',
57
+ source: { github: 'ImageMagick/ImageMagick', asset: '^ImageMagick-[\\d.]+-\\d+-portable-Q16-HDRI-x64\\.7z$' },
58
+ exe: 'magick.exe',
59
+ cli: true,
60
+ needs: ['7zip'],
61
+ },
62
+ {
63
+ id: 'nomacs',
64
+ name: 'nomacs',
65
+ category: 'gamedev',
66
+ about: 'Image viewer for textures (TGA, PSD, DDS, EXR).',
67
+ size: '60 MB',
68
+ source: { github: 'nomacs/nomacs', asset: '^nomacs-portable-win\\.zip$' },
69
+ exe: 'nomacs.exe',
70
+ },
71
+ ];
@@ -1,4 +1,6 @@
1
1
  export { type AddonMcp, type AppCategory, APP_CATEGORIES, type AppSource, type AppEntry, APPS, appById, CCUSAGE_VERSION, CONTEXT7_MCP_VERSION, HEADROOM_VERSION, PLAYWRIGHT_MCP_VERSION, RTK_VERSION, } from './catalogue.js';
2
+ export { ASSOCIATIONS, associationPlan } from './associations.js';
3
+ export { previewGuideLine } from './preview.js';
2
4
  export { exeMatcher, appsToInstall, appsNeedMesa, appsNeedUv } from './selection.js';
3
5
  export { signerMatches, type AppSigner, type Signature } from '../signer.js';
4
6
  export { AGENTS_WEB_APPS, BROWSER_USE_VERSION, CHROME_DEVTOOLS_MCP_VERSION, COMET_DOWNLOAD_URL, COMET_MCP_VERSION, COMET_SIGNER, PERPLEXITY_COMPUTER_MCP_URL, PERPLEXITY_MCP_VERSION, } from './catalogue-agents-web.js';
@@ -1,4 +1,6 @@
1
1
  export { APP_CATEGORIES, APPS, appById, CCUSAGE_VERSION, CONTEXT7_MCP_VERSION, HEADROOM_VERSION, PLAYWRIGHT_MCP_VERSION, RTK_VERSION, } from './catalogue.js';
2
+ export { ASSOCIATIONS, associationPlan } from './associations.js';
3
+ export { previewGuideLine } from './preview.js';
2
4
  export { exeMatcher, appsToInstall, appsNeedMesa, appsNeedUv } from './selection.js';
3
5
  export { signerMatches } from '../signer.js';
4
6
  export { AGENTS_WEB_APPS, BROWSER_USE_VERSION, CHROME_DEVTOOLS_MCP_VERSION, COMET_DOWNLOAD_URL, COMET_MCP_VERSION, COMET_SIGNER, PERPLEXITY_COMPUTER_MCP_URL, PERPLEXITY_MCP_VERSION, } from './catalogue-agents-web.js';
@@ -0,0 +1,2 @@
1
+ /** Null unless F3D or ImageMagick is installed; `installed` holds app ids. */
2
+ export declare function previewGuideLine(installed: readonly string[]): string | null;
@@ -0,0 +1,10 @@
1
+ // The one line that tells an agent how to render previews of meshes and textures for the owner (pure).
2
+ /** Null unless F3D or ImageMagick is installed; `installed` holds app ids. */
3
+ export function previewGuideLine(installed) {
4
+ if (!installed.includes('f3d') && !installed.includes('imagemagick'))
5
+ return null;
6
+ return ('asset previews: `f3d "<mesh>" --output="<pkg>\\previews\\<name>.png" --resolution=1024,768 --up=+Y` per mesh ' +
7
+ '(--up=+Z for Unreal-space files), `magick montage "<pkg>\\source\\**\\*.png" -thumbnail 256x256 -geometry +4+4 ' +
8
+ '-label %f "<pkg>\\previews\\textures.png"` for textures (convert TGA/PSD/DDS/EXR to PNG first with magick); ' +
9
+ "leave them in the package's previews\\ folder for the owner to look at before import");
10
+ }
@@ -0,0 +1,14 @@
1
+ export interface BrowserPolicy {
2
+ readonly key: string;
3
+ readonly name: string;
4
+ readonly type: 'REG_DWORD' | 'REG_SZ';
5
+ readonly data: string;
6
+ }
7
+ export declare const BROWSER_POLICY_KEYS: readonly ["HKLM\\SOFTWARE\\Policies\\Microsoft\\Edge", "HKLM\\SOFTWARE\\Policies\\Google\\Chrome"];
8
+ /**
9
+ * The policies for each browser: no hardware acceleration (today's behaviour) and, when a downloads folder is given,
10
+ * DefaultDownloadDirectory (the default only: Playwright's download path and the user's own choice still win).
11
+ */
12
+ export declare function browserPolicies(o: {
13
+ readonly downloads: string | null;
14
+ }): BrowserPolicy[];
@@ -0,0 +1,22 @@
1
+ // The machine policy of the sandbox's browsers (Edge and Chrome), written under HKLM at every boot by the guest: no GPU
2
+ // and the folder downloads go to. Pure (no reads or writes here): the guest runs reg.exe with these entries and the
3
+ // self-test checks them.
4
+ import path from 'node:path';
5
+ export const BROWSER_POLICY_KEYS = [
6
+ 'HKLM\\SOFTWARE\\Policies\\Microsoft\\Edge',
7
+ 'HKLM\\SOFTWARE\\Policies\\Google\\Chrome',
8
+ ];
9
+ /**
10
+ * The policies for each browser: no hardware acceleration (today's behaviour) and, when a downloads folder is given,
11
+ * DefaultDownloadDirectory (the default only: Playwright's download path and the user's own choice still win).
12
+ */
13
+ export function browserPolicies(o) {
14
+ if (o.downloads !== null && (!path.win32.isAbsolute(o.downloads) || /["\r\n%]/.test(o.downloads)))
15
+ throw new Error('not a folder');
16
+ return BROWSER_POLICY_KEYS.flatMap((key) => [
17
+ { key, name: 'HardwareAccelerationModeEnabled', type: 'REG_DWORD', data: '0' },
18
+ ...(o.downloads === null
19
+ ? []
20
+ : [{ key, name: 'DefaultDownloadDirectory', type: 'REG_SZ', data: o.downloads }]),
21
+ ]);
22
+ }
@@ -109,10 +109,9 @@ export declare const ProjectSpecSchema: z.ZodObject<{
109
109
  enabled: z.ZodUnion<readonly [z.ZodBoolean, z.ZodLiteral<"auto">]>;
110
110
  acceptLicense: z.ZodBoolean;
111
111
  components: z.ZodArray<z.ZodString>;
112
- keepInstallFiles: z.ZodBoolean;
113
112
  visualStudio: z.ZodEnum<{
114
113
  full: "full";
115
- autosdk: "autosdk";
114
+ buildtools: "buildtools";
116
115
  }>;
117
116
  persistEngines: z.ZodBoolean;
118
117
  derivedDataCache: z.ZodEnum<{
@@ -346,10 +345,9 @@ export declare const GuestRequestSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
346
345
  enabled: z.ZodUnion<readonly [z.ZodBoolean, z.ZodLiteral<"auto">]>;
347
346
  acceptLicense: z.ZodBoolean;
348
347
  components: z.ZodArray<z.ZodString>;
349
- keepInstallFiles: z.ZodBoolean;
350
348
  visualStudio: z.ZodEnum<{
351
349
  full: "full";
352
- autosdk: "autosdk";
350
+ buildtools: "buildtools";
353
351
  }>;
354
352
  persistEngines: z.ZodBoolean;
355
353
  derivedDataCache: z.ZodEnum<{
@@ -603,10 +601,9 @@ export declare const GuestRequestSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
603
601
  enabled: z.ZodUnion<readonly [z.ZodBoolean, z.ZodLiteral<"auto">]>;
604
602
  acceptLicense: z.ZodBoolean;
605
603
  components: z.ZodArray<z.ZodString>;
606
- keepInstallFiles: z.ZodBoolean;
607
604
  visualStudio: z.ZodEnum<{
608
605
  full: "full";
609
- autosdk: "autosdk";
606
+ buildtools: "buildtools";
610
607
  }>;
611
608
  persistEngines: z.ZodBoolean;
612
609
  derivedDataCache: z.ZodEnum<{
@@ -6,3 +6,4 @@ export * from './copy-tree.js';
6
6
  export * from './bounded.js';
7
7
  export * from './text.js';
8
8
  export * from './disk.js';
9
+ export * from './rotate-log.js';
@@ -6,3 +6,4 @@ export * from './copy-tree.js';
6
6
  export * from './bounded.js';
7
7
  export * from './text.js';
8
8
  export * from './disk.js';
9
+ export * from './rotate-log.js';
@@ -0,0 +1,2 @@
1
+ /** Moves `file` to `file + '.1'` (replacing the older copy) when it is over `maxBytes`; true when it moved. */
2
+ export declare function rotateLog(file: string, maxBytes: number): boolean;
@@ -0,0 +1,16 @@
1
+ // Keeps a log that a detached program appends to from growing for ever: past the limit it becomes <log>.1.
2
+ import fs from 'node:fs';
3
+ /** Moves `file` to `file + '.1'` (replacing the older copy) when it is over `maxBytes`; true when it moved. */
4
+ export function rotateLog(file, maxBytes) {
5
+ try {
6
+ if (fs.statSync(file).size <= maxBytes)
7
+ return false;
8
+ fs.rmSync(file + '.1', { force: true });
9
+ fs.renameSync(file, file + '.1');
10
+ return true;
11
+ }
12
+ catch {
13
+ // No log yet, or it is held open: the next start tries again.
14
+ return false;
15
+ }
16
+ }
@@ -67,3 +67,8 @@ export declare function chooseTargetDir(targetDir: string, freeBytes: number): {
67
67
  };
68
68
  /** The most heavy compilers (rustc, clippy-driver, link ...) that run at once in the agents' job: only with vGPU on. */
69
69
  export declare function maxCompilers(cpus: number, profile: LoadProfile): number | null;
70
+ /**
71
+ * The cargo variable that names the linker of a Rust host (`x86_64-pc-windows-msvc` ->
72
+ * `CARGO_TARGET_X86_64_PC_WINDOWS_MSVC_LINKER`).
73
+ */
74
+ export declare function cargoLinkerVar(host: string): string;
@@ -108,3 +108,10 @@ export function chooseTargetDir(targetDir, freeBytes) {
108
108
  export function maxCompilers(cpus, profile) {
109
109
  return profile === 'gentle' ? Math.min(4, Math.max(2, Math.floor(cpus / 4))) : null;
110
110
  }
111
+ /**
112
+ * The cargo variable that names the linker of a Rust host (`x86_64-pc-windows-msvc` ->
113
+ * `CARGO_TARGET_X86_64_PC_WINDOWS_MSVC_LINKER`).
114
+ */
115
+ export function cargoLinkerVar(host) {
116
+ return 'CARGO_TARGET_' + host.toUpperCase().replace(/[^A-Z0-9]/g, '_') + '_LINKER';
117
+ }
@@ -1,6 +1,6 @@
1
1
  /** Where this PC's installs appear in the sandbox (reserved: RESERVED_GUEST). */
2
2
  export declare const PC_INSTALLS_GUEST = "C:\\PcInstalls";
3
- export type PcInstallKind = 'steam-game' | 'steam-library' | 'epic-game' | 'unreal' | 'unity';
3
+ export type PcInstallKind = 'steam-game' | 'steam-library' | 'epic-game' | 'unreal' | 'unreal-vault' | 'unity';
4
4
  export interface PcInstall {
5
5
  readonly kind: PcInstallKind;
6
6
  /** The Steam app ID or library (library1), the Epic app name, the engine (UE_5.4) or editor version. */
@@ -9,8 +9,19 @@ export interface PcInstall {
9
9
  readonly version?: string;
10
10
  /** The folder on this PC (never sent to the sandbox). */
11
11
  readonly host: string;
12
- /** Where it appears in the sandbox, read-only. */
12
+ /** Where it appears in the sandbox, read-only unless `writable`. */
13
13
  readonly guest: string;
14
+ /** Mapped writable: an engine folder you registered (pcInstalls.unrealEngineFolders). */
15
+ readonly writable?: boolean;
16
+ /** An Unreal source build's registered name on this PC (HKCU\Software\Epic Games\Unreal Engine\Builds). */
17
+ readonly buildId?: string;
18
+ /** The Epic Games Launcher's own ids of the app (from this PC's LauncherInstalled.dat). */
19
+ readonly launcher?: {
20
+ readonly namespaceId: string;
21
+ readonly itemId: string;
22
+ readonly artifactId: string;
23
+ readonly appVersion: string;
24
+ };
14
25
  }
15
26
  /** What session.json says about them: no host paths. */
16
27
  export interface PcInstallManifest {
@@ -9,6 +9,7 @@ const AREA = {
9
9
  'steam-library': 'steam',
10
10
  'epic-game': 'epic',
11
11
  unreal: 'unreal',
12
+ 'unreal-vault': 'unreal',
12
13
  unity: 'unity',
13
14
  };
14
15
  /** The guest folder of one install: C:\PcInstalls\steam\<appid>, \epic\<AppName>, \unreal\UE_5.4, \unity\<ver>. */
@@ -185,7 +185,8 @@ options = {}) {
185
185
  socket.on('close', () => finish({ reason: 'closed' }));
186
186
  socket.on('error', () => finish({ reason: 'closed' }));
187
187
  const [c, r] = size();
188
- stdout.write('\x1b[2J\x1b[3J\x1b[H');
188
+ // A clean screen, but the scrollback stays: the boot's summary (warnings, tools, Ready) is just above the session.
189
+ stdout.write('\x1b[2J\x1b[H');
189
190
  socket.write(helloFrame(token, c, r));
190
191
  if (stdin.isTTY)
191
192
  stdin.setRawMode(true);
@@ -3,7 +3,6 @@ export declare const NOT_READY: {
3
3
  readonly toolchains: readonly ["unity", "godot", "android", "flutter", "dart", "reactNative"];
4
4
  /** Service sign-ins whose host or guest side is a stub: the menu and the web do not list them. */
5
5
  readonly kinds: readonly ["unity", "keystore", "play", "expo", "appstore"];
6
- readonly unreal: readonly ["engines"];
7
6
  };
8
7
  export declare const isToolchainReady: (name: string) => boolean;
9
8
  export declare const isKindReady: (kind: string) => boolean;
@@ -5,7 +5,6 @@ export const NOT_READY = {
5
5
  toolchains: ['unity', 'godot', 'android', 'flutter', 'dart', 'reactNative'],
6
6
  /** Service sign-ins whose host or guest side is a stub: the menu and the web do not list them. */
7
7
  kinds: ['unity', 'keystore', 'play', 'expo', 'appstore'],
8
- unreal: ['engines'],
9
8
  };
10
9
  export const isToolchainReady = (name) => !NOT_READY.toolchains.includes(name);
11
10
  export const isKindReady = (kind) => !NOT_READY.kinds.includes(kind);
@@ -21,4 +21,8 @@ export declare const SIGNERS: {
21
21
  readonly unity: {
22
22
  readonly subject: readonly ["^CN=\"?Unity Technologies"];
23
23
  };
24
+ /** The Epic Games Launcher's MSI (checked on EpicInstaller-20.3.3.msi). */
25
+ readonly epic: {
26
+ readonly subject: readonly ["^CN=Epic Games Inc\\., O=Epic Games Inc\\., L=Cary, S=North Carolina, C=US"];
27
+ };
24
28
  };
@@ -12,4 +12,6 @@ export const SIGNERS = {
12
12
  microsoft: { subject: ['^CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US$'] },
13
13
  valve: { subject: ['^CN="?Valve(,| Corp)'] },
14
14
  unity: { subject: ['^CN="?Unity Technologies'] },
15
+ /** The Epic Games Launcher's MSI (checked on EpicInstaller-20.3.3.msi). */
16
+ epic: { subject: ['^CN=Epic Games Inc\\., O=Epic Games Inc\\., L=Cary, S=North Carolina, C=US'] },
15
17
  };