windows-development-sandbox 1.25.1 → 1.27.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (196) hide show
  1. package/config.example.json +12 -3
  2. package/dist/app/features/accounts/services.def.d.ts +1 -1
  3. package/dist/app/features/accounts/services.def.js +1 -1
  4. package/dist/app/features/defs.d.ts +198 -3
  5. package/dist/app/features/defs.js +8 -0
  6. package/dist/app/features/settings/categories.def.js +1 -0
  7. package/dist/app/features/unity/index.d.ts +2 -0
  8. package/dist/app/features/unity/index.js +3 -0
  9. package/dist/app/features/unity/unity.def.d.ts +294 -0
  10. package/dist/app/features/unity/unity.def.js +471 -0
  11. package/dist/app/features/unity/unity.run.d.ts +142 -0
  12. package/dist/app/features/unity/unity.run.js +363 -0
  13. package/dist/app/registry.js +6 -0
  14. package/dist/bin/agent-sandbox.js +2 -2
  15. package/dist/bin/{chunk-F4PVBN23.js → chunk-6WWMBCT2.js} +3580 -1962
  16. package/dist/bin/{chunk-3GAXLATK.js → chunk-JXL6ZOO3.js} +72 -5
  17. package/dist/bin/{chunk-G3TG4ZT7.js → chunk-ZXCAVVS4.js} +1 -1
  18. package/dist/bin/claude-host.js +2 -2
  19. package/dist/bin/claude-sbx.js +2 -2
  20. package/dist/bin/codex-sbx.js +2 -2
  21. package/dist/bin/gemini-sbx.js +2 -2
  22. package/dist/bin/sandbox.js +2 -2
  23. package/dist/bin/sbx-hide.js +2 -2
  24. package/dist/bin/sbx-show.js +2 -2
  25. package/dist/cli/commands/launch/launch.js +12 -0
  26. package/dist/cli/commands/registry.js +3 -0
  27. package/dist/cli/manifest.d.ts +33 -1
  28. package/dist/cli/manifest.js +32 -1
  29. package/dist/cli/menu/coverage-exempt.js +1 -0
  30. package/dist/cli/menu/pages/sandbox-page.d.ts +3 -0
  31. package/dist/cli/menu/pages/sandbox-page.js +40 -3
  32. package/dist/cli/menu/views.js +2 -0
  33. package/dist/core/config/defaults.js +16 -3
  34. package/dist/core/schema/accounts.d.ts +3 -0
  35. package/dist/core/schema/accounts.js +1 -0
  36. package/dist/core/schema/config.d.ts +29 -13
  37. package/dist/core/schema/github.d.ts +1 -0
  38. package/dist/core/schema/github.js +3 -0
  39. package/dist/core/schema/pc-installs.d.ts +2 -1
  40. package/dist/core/schema/pc-installs.js +6 -1
  41. package/dist/core/schema/toolchains.d.ts +8 -0
  42. package/dist/core/schema/toolchains.js +19 -4
  43. package/dist/guest/accounts/adapters.js +2 -0
  44. package/dist/guest/accounts/apply.d.ts +4 -2
  45. package/dist/guest/accounts/kinds/perplexityapp.d.ts +7 -0
  46. package/dist/guest/accounts/kinds/perplexityapp.js +53 -0
  47. package/dist/guest/accounts/kinds/unity.d.ts +27 -0
  48. package/dist/guest/accounts/kinds/unity.js +164 -7
  49. package/dist/guest/apps/app-installer.js +18 -0
  50. package/dist/guest/apps/store-app.d.ts +4 -0
  51. package/dist/guest/apps/store-app.js +19 -0
  52. package/dist/guest/apps/store-check.d.ts +8 -0
  53. package/dist/guest/apps/store-check.js +33 -0
  54. package/dist/guest/boot/boot.js +1 -1
  55. package/dist/guest/boot/guide.js +18 -0
  56. package/dist/guest/browser/comet.d.ts +3 -1
  57. package/dist/guest/browser/comet.js +1 -1
  58. package/dist/guest/browser/perplexity-app.d.ts +12 -0
  59. package/dist/guest/browser/perplexity-app.js +60 -0
  60. package/dist/guest/daemon/daemon.js +2 -0
  61. package/dist/guest/devtools/devtool.d.ts +1 -1
  62. package/dist/guest/devtools/registry.js +1 -2
  63. package/dist/guest/entries/tool.js +1 -1
  64. package/dist/guest/setup/addon-mcp.d.ts +7 -2
  65. package/dist/guest/setup/addon-mcp.js +19 -9
  66. package/dist/guest/setup/github-token.js +4 -4
  67. package/dist/guest/setup/unity-agent.d.ts +11 -0
  68. package/dist/guest/setup/unity-agent.js +36 -0
  69. package/dist/guest/toolchains/engines/unity-cli.d.ts +24 -0
  70. package/dist/guest/toolchains/engines/unity-cli.js +74 -0
  71. package/dist/guest/toolchains/engines/unity-hub.d.ts +2 -0
  72. package/dist/guest/toolchains/engines/unity-hub.js +27 -0
  73. package/dist/guest/toolchains/engines/unity-release.d.ts +4 -15
  74. package/dist/guest/toolchains/engines/unity-release.js +17 -5
  75. package/dist/guest/toolchains/engines/unity-status.d.ts +11 -0
  76. package/dist/guest/toolchains/engines/unity-status.js +39 -0
  77. package/dist/guest/toolchains/engines/unity.d.ts +20 -1
  78. package/dist/guest/toolchains/engines/unity.js +250 -3
  79. package/dist/guest/toolchains/plan.js +5 -1
  80. package/dist/guest/toolchains/tools/cli.js +2 -2
  81. package/dist/host/accounts/deliver.js +4 -0
  82. package/dist/host/accounts/kinds/perplexityapp.d.ts +2 -0
  83. package/dist/host/accounts/kinds/perplexityapp.js +8 -0
  84. package/dist/host/accounts/kinds/unity.d.ts +1 -1
  85. package/dist/host/accounts/kinds/unity.js +60 -8
  86. package/dist/host/accounts/leases.d.ts +2 -1
  87. package/dist/host/accounts/sources.js +2 -0
  88. package/dist/host/apps/index.d.ts +1 -0
  89. package/dist/host/apps/index.js +2 -0
  90. package/dist/host/apps/store-package.d.ts +51 -0
  91. package/dist/host/apps/store-package.js +209 -0
  92. package/dist/host/github/deliver.d.ts +8 -3
  93. package/dist/host/github/deliver.js +42 -29
  94. package/dist/host/github/index.d.ts +1 -0
  95. package/dist/host/github/index.js +1 -0
  96. package/dist/host/github/pc-login.d.ts +27 -0
  97. package/dist/host/github/pc-login.js +129 -0
  98. package/dist/host/pc-installs/discover.d.ts +4 -0
  99. package/dist/host/pc-installs/discover.js +16 -4
  100. package/dist/host/pc-installs/source.d.ts +1 -1
  101. package/dist/host/pc-installs/unity-assets.d.ts +5 -0
  102. package/dist/host/pc-installs/unity-assets.js +18 -0
  103. package/dist/host/pc-installs/unity.d.ts +20 -0
  104. package/dist/host/pc-installs/unity.js +135 -2
  105. package/dist/runtime/agent.js +116 -11
  106. package/dist/runtime/daemon.js +2170 -976
  107. package/dist/runtime/db.js +116 -11
  108. package/dist/runtime/main.js +2543 -1364
  109. package/dist/runtime/netproxy.js +116 -11
  110. package/dist/runtime/tool.js +133 -31
  111. package/dist/runtime/view.js +116 -11
  112. package/dist/selftest/agents-web.test.js +2 -1
  113. package/dist/selftest/engines.test.js +2 -2
  114. package/dist/selftest/github.test.js +64 -1
  115. package/dist/selftest/index.js +10 -0
  116. package/dist/selftest/menu-screens.js +3 -1
  117. package/dist/selftest/persisted-installs.test.js +1 -1
  118. package/dist/selftest/service-accounts.test.js +1 -1
  119. package/dist/selftest/store-app.test.d.ts +2 -0
  120. package/dist/selftest/store-app.test.js +162 -0
  121. package/dist/selftest/support/engine-golden.js +7 -0
  122. package/dist/selftest/support/fixtures.d.ts +10 -1
  123. package/dist/selftest/support/unity-sample.d.ts +2 -0
  124. package/dist/selftest/support/unity-sample.js +80 -0
  125. package/dist/selftest/unity-accounts.test.d.ts +2 -0
  126. package/dist/selftest/unity-accounts.test.js +106 -0
  127. package/dist/selftest/unity-agent.test.d.ts +2 -0
  128. package/dist/selftest/unity-agent.test.js +47 -0
  129. package/dist/selftest/unity-page.test.d.ts +2 -0
  130. package/dist/selftest/unity-page.test.js +177 -0
  131. package/dist/selftest/unity-setup.test.d.ts +2 -0
  132. package/dist/selftest/unity-setup.test.js +49 -0
  133. package/dist/selftest/unity.test.js +238 -3
  134. package/dist/shared/accounts/index.d.ts +1 -0
  135. package/dist/shared/accounts/index.js +1 -0
  136. package/dist/shared/accounts/kinds/unity.d.ts +28 -0
  137. package/dist/shared/accounts/kinds/unity.js +88 -0
  138. package/dist/shared/accounts/kinds.d.ts +2 -2
  139. package/dist/shared/accounts/kinds.js +23 -1
  140. package/dist/shared/accounts/payloads.d.ts +52 -0
  141. package/dist/shared/accounts/payloads.js +14 -2
  142. package/dist/shared/apps/catalogue-agents-web.d.ts +7 -0
  143. package/dist/shared/apps/catalogue-agents-web.js +23 -0
  144. package/dist/shared/apps/catalogue-gamedev.d.ts +3 -0
  145. package/dist/shared/apps/catalogue-gamedev.js +31 -0
  146. package/dist/shared/apps/catalogue.d.ts +8 -0
  147. package/dist/shared/apps/index.d.ts +3 -2
  148. package/dist/shared/apps/index.js +3 -2
  149. package/dist/shared/apps/selection.d.ts +6 -0
  150. package/dist/shared/apps/selection.js +9 -0
  151. package/dist/shared/apps/store-package.d.ts +31 -0
  152. package/dist/shared/apps/store-package.js +34 -0
  153. package/dist/shared/channel/schema.d.ts +24 -0
  154. package/dist/shared/channel/secrets.d.ts +17 -0
  155. package/dist/shared/paths/pc-installs.d.ts +1 -1
  156. package/dist/shared/paths/pc-installs.js +1 -0
  157. package/dist/shared/readiness.d.ts +2 -2
  158. package/dist/shared/readiness.js +2 -2
  159. package/dist/shared/unity/asset-cache.d.ts +20 -0
  160. package/dist/shared/unity/asset-cache.js +44 -0
  161. package/dist/shared/unity/cli.d.ts +40 -0
  162. package/dist/shared/unity/cli.js +77 -0
  163. package/dist/shared/unity/editors.d.ts +46 -0
  164. package/dist/shared/unity/editors.js +89 -0
  165. package/dist/shared/unity/guide.d.ts +9 -0
  166. package/dist/shared/unity/guide.js +84 -0
  167. package/dist/shared/unity/index.d.ts +9 -0
  168. package/dist/shared/unity/index.js +11 -0
  169. package/dist/shared/unity/manifest.d.ts +10 -0
  170. package/dist/shared/unity/manifest.js +53 -0
  171. package/dist/shared/unity/mcp.d.ts +8 -0
  172. package/dist/shared/unity/mcp.js +12 -0
  173. package/dist/shared/unity/release.d.ts +28 -0
  174. package/dist/shared/unity/release.js +83 -0
  175. package/dist/shared/unity/status.d.ts +59 -0
  176. package/dist/shared/unity/status.js +45 -0
  177. package/dist/shared/unity/version.d.ts +27 -0
  178. package/dist/shared/unity/version.js +75 -0
  179. package/dist/web/index.html +1 -1
  180. package/dist/web/{main-FNE6XEHA.js → main-VPMYTSUL.js} +67 -67
  181. package/native/csharp/HcsHost/AssemblyInfo.cs +3 -3
  182. package/native/csharp/HostTools/AssemblyInfo.cs +3 -3
  183. package/native/csharp/StorageHelper/AssemblyInfo.cs +3 -3
  184. package/native/scripts/get-store-package.ps1 +58 -0
  185. package/package.json +1 -1
  186. package/sandbox/addons/openupm-cli/package-lock.json +2921 -0
  187. package/sandbox/addons/openupm-cli/package.json +7 -0
  188. package/sandbox/addons/unity-mcp/requirements.in +1 -0
  189. package/sandbox/addons/unity-mcp/requirements.txt +1165 -0
  190. package/sandbox/csharp/AppActivation.cs +38 -0
  191. package/sandbox/scripts/install-store-package.ps1 +28 -0
  192. package/sandbox/scripts/start-store-app.ps1 +29 -0
  193. package/schemas/config.schema.json +61 -6
  194. package/schemas/sandbox-config.schema.json +38 -5
  195. package/dist/guest/devtools/unity.d.ts +0 -2
  196. package/dist/guest/devtools/unity.js +0 -7
@@ -95,6 +95,7 @@ export declare const ConfigSchema: z.ZodObject<{
95
95
  }, z.core.$strict>;
96
96
  github: z.ZodObject<{
97
97
  shareToken: z.ZodBoolean;
98
+ usePcLogin: z.ZodBoolean;
98
99
  }, z.core.$strict>;
99
100
  accounts: z.ZodObject<{
100
101
  epic: z.ZodObject<{
@@ -127,6 +128,9 @@ export declare const ConfigSchema: z.ZodObject<{
127
128
  comet: z.ZodObject<{
128
129
  share: z.ZodBoolean;
129
130
  }, z.core.$strict>;
131
+ perplexityapp: z.ZodObject<{
132
+ share: z.ZodBoolean;
133
+ }, z.core.$strict>;
130
134
  }, z.core.$strict>;
131
135
  pcInstalls: z.ZodObject<{
132
136
  steamGames: z.ZodUnion<readonly [z.ZodBoolean, z.ZodArray<z.ZodNumber>]>;
@@ -134,7 +138,8 @@ export declare const ConfigSchema: z.ZodObject<{
134
138
  unrealEngines: z.ZodUnion<readonly [z.ZodLiteral<"auto">, z.ZodBoolean, z.ZodArray<z.ZodString>]>;
135
139
  unrealEngineFolders: z.ZodArray<z.ZodString>;
136
140
  unrealAssets: z.ZodUnion<readonly [z.ZodLiteral<"auto">, z.ZodBoolean]>;
137
- unityEditors: z.ZodUnion<readonly [z.ZodBoolean, z.ZodArray<z.ZodString>]>;
141
+ unityEditors: z.ZodUnion<readonly [z.ZodLiteral<"auto">, z.ZodBoolean, z.ZodArray<z.ZodString>]>;
142
+ unityAssets: z.ZodUnion<readonly [z.ZodLiteral<"auto">, z.ZodBoolean]>;
138
143
  }, z.core.$strict>;
139
144
  provisioning: z.ZodObject<{
140
145
  copyFromHost: z.ZodBoolean;
@@ -214,6 +219,14 @@ export declare const ConfigSchema: z.ZodObject<{
214
219
  modules: z.ZodArray<z.ZodString>;
215
220
  hub: z.ZodBoolean;
216
221
  keepVersions: z.ZodNumber;
222
+ mcp: z.ZodBoolean;
223
+ agentSkills: z.ZodBoolean;
224
+ cliVersion: z.ZodString;
225
+ assetCache: z.ZodEnum<{
226
+ pc: "pc";
227
+ persisted: "persisted";
228
+ local: "local";
229
+ }>;
217
230
  }, z.core.$strict>;
218
231
  godot: z.ZodObject<{
219
232
  enabled: z.ZodUnion<readonly [z.ZodBoolean, z.ZodLiteral<"auto">]>;
@@ -579,6 +592,9 @@ export declare const LocalOverridesSchema: z.ZodObject<{
579
592
  comet: z.ZodOptional<z.ZodObject<{
580
593
  share: z.ZodOptional<z.ZodBoolean>;
581
594
  }, z.core.$strict>>;
595
+ perplexityapp: z.ZodOptional<z.ZodObject<{
596
+ share: z.ZodOptional<z.ZodBoolean>;
597
+ }, z.core.$strict>>;
582
598
  }, z.core.$strict>>;
583
599
  provisioning: z.ZodOptional<z.ZodObject<{
584
600
  copyFromHost: z.ZodOptional<z.ZodBoolean>;
@@ -601,7 +617,7 @@ export declare const LocalOverridesSchema: z.ZodObject<{
601
617
  }, z.core.$strict>>;
602
618
  toolchains: z.ZodOptional<z.ZodObject<{
603
619
  environment: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
604
- unity: z.ZodOptional<z.ZodObject<{
620
+ godot: z.ZodOptional<z.ZodObject<{
605
621
  enabled: z.ZodOptional<z.ZodBoolean>;
606
622
  }, z.core.$strict> | z.ZodObject<{
607
623
  version: z.ZodOptional<z.ZodString>;
@@ -616,7 +632,7 @@ export declare const LocalOverridesSchema: z.ZodObject<{
616
632
  zstd: z.ZodOptional<z.ZodUnion<readonly [z.ZodBoolean, z.ZodLiteral<"auto">]>>;
617
633
  openssl: z.ZodOptional<z.ZodUnion<readonly [z.ZodBoolean, z.ZodLiteral<"auto">]>>;
618
634
  }, z.core.$strict>>;
619
- godot: z.ZodOptional<z.ZodObject<{
635
+ android: z.ZodOptional<z.ZodObject<{
620
636
  enabled: z.ZodOptional<z.ZodBoolean>;
621
637
  }, z.core.$strict> | z.ZodObject<{
622
638
  version: z.ZodOptional<z.ZodString>;
@@ -631,7 +647,7 @@ export declare const LocalOverridesSchema: z.ZodObject<{
631
647
  zstd: z.ZodOptional<z.ZodUnion<readonly [z.ZodBoolean, z.ZodLiteral<"auto">]>>;
632
648
  openssl: z.ZodOptional<z.ZodUnion<readonly [z.ZodBoolean, z.ZodLiteral<"auto">]>>;
633
649
  }, z.core.$strict>>;
634
- android: z.ZodOptional<z.ZodObject<{
650
+ flutter: z.ZodOptional<z.ZodObject<{
635
651
  enabled: z.ZodOptional<z.ZodBoolean>;
636
652
  }, z.core.$strict> | z.ZodObject<{
637
653
  version: z.ZodOptional<z.ZodString>;
@@ -646,7 +662,7 @@ export declare const LocalOverridesSchema: z.ZodObject<{
646
662
  zstd: z.ZodOptional<z.ZodUnion<readonly [z.ZodBoolean, z.ZodLiteral<"auto">]>>;
647
663
  openssl: z.ZodOptional<z.ZodUnion<readonly [z.ZodBoolean, z.ZodLiteral<"auto">]>>;
648
664
  }, z.core.$strict>>;
649
- flutter: z.ZodOptional<z.ZodObject<{
665
+ dart: z.ZodOptional<z.ZodObject<{
650
666
  enabled: z.ZodOptional<z.ZodBoolean>;
651
667
  }, z.core.$strict> | z.ZodObject<{
652
668
  version: z.ZodOptional<z.ZodString>;
@@ -661,7 +677,7 @@ export declare const LocalOverridesSchema: z.ZodObject<{
661
677
  zstd: z.ZodOptional<z.ZodUnion<readonly [z.ZodBoolean, z.ZodLiteral<"auto">]>>;
662
678
  openssl: z.ZodOptional<z.ZodUnion<readonly [z.ZodBoolean, z.ZodLiteral<"auto">]>>;
663
679
  }, z.core.$strict>>;
664
- dart: z.ZodOptional<z.ZodObject<{
680
+ reactNative: z.ZodOptional<z.ZodObject<{
665
681
  enabled: z.ZodOptional<z.ZodBoolean>;
666
682
  }, z.core.$strict> | z.ZodObject<{
667
683
  version: z.ZodOptional<z.ZodString>;
@@ -676,7 +692,7 @@ export declare const LocalOverridesSchema: z.ZodObject<{
676
692
  zstd: z.ZodOptional<z.ZodUnion<readonly [z.ZodBoolean, z.ZodLiteral<"auto">]>>;
677
693
  openssl: z.ZodOptional<z.ZodUnion<readonly [z.ZodBoolean, z.ZodLiteral<"auto">]>>;
678
694
  }, z.core.$strict>>;
679
- reactNative: z.ZodOptional<z.ZodObject<{
695
+ node: z.ZodOptional<z.ZodObject<{
680
696
  enabled: z.ZodOptional<z.ZodBoolean>;
681
697
  }, z.core.$strict> | z.ZodObject<{
682
698
  version: z.ZodOptional<z.ZodString>;
@@ -691,7 +707,7 @@ export declare const LocalOverridesSchema: z.ZodObject<{
691
707
  zstd: z.ZodOptional<z.ZodUnion<readonly [z.ZodBoolean, z.ZodLiteral<"auto">]>>;
692
708
  openssl: z.ZodOptional<z.ZodUnion<readonly [z.ZodBoolean, z.ZodLiteral<"auto">]>>;
693
709
  }, z.core.$strict>>;
694
- node: z.ZodOptional<z.ZodObject<{
710
+ go: z.ZodOptional<z.ZodObject<{
695
711
  enabled: z.ZodOptional<z.ZodBoolean>;
696
712
  }, z.core.$strict> | z.ZodObject<{
697
713
  version: z.ZodOptional<z.ZodString>;
@@ -706,7 +722,7 @@ export declare const LocalOverridesSchema: z.ZodObject<{
706
722
  zstd: z.ZodOptional<z.ZodUnion<readonly [z.ZodBoolean, z.ZodLiteral<"auto">]>>;
707
723
  openssl: z.ZodOptional<z.ZodUnion<readonly [z.ZodBoolean, z.ZodLiteral<"auto">]>>;
708
724
  }, z.core.$strict>>;
709
- go: z.ZodOptional<z.ZodObject<{
725
+ python: z.ZodOptional<z.ZodObject<{
710
726
  enabled: z.ZodOptional<z.ZodBoolean>;
711
727
  }, z.core.$strict> | z.ZodObject<{
712
728
  version: z.ZodOptional<z.ZodString>;
@@ -721,7 +737,7 @@ export declare const LocalOverridesSchema: z.ZodObject<{
721
737
  zstd: z.ZodOptional<z.ZodUnion<readonly [z.ZodBoolean, z.ZodLiteral<"auto">]>>;
722
738
  openssl: z.ZodOptional<z.ZodUnion<readonly [z.ZodBoolean, z.ZodLiteral<"auto">]>>;
723
739
  }, z.core.$strict>>;
724
- python: z.ZodOptional<z.ZodObject<{
740
+ rust: z.ZodOptional<z.ZodObject<{
725
741
  enabled: z.ZodOptional<z.ZodBoolean>;
726
742
  }, z.core.$strict> | z.ZodObject<{
727
743
  version: z.ZodOptional<z.ZodString>;
@@ -736,7 +752,7 @@ export declare const LocalOverridesSchema: z.ZodObject<{
736
752
  zstd: z.ZodOptional<z.ZodUnion<readonly [z.ZodBoolean, z.ZodLiteral<"auto">]>>;
737
753
  openssl: z.ZodOptional<z.ZodUnion<readonly [z.ZodBoolean, z.ZodLiteral<"auto">]>>;
738
754
  }, z.core.$strict>>;
739
- rust: z.ZodOptional<z.ZodObject<{
755
+ msvc: z.ZodOptional<z.ZodObject<{
740
756
  enabled: z.ZodOptional<z.ZodBoolean>;
741
757
  }, z.core.$strict> | z.ZodObject<{
742
758
  version: z.ZodOptional<z.ZodString>;
@@ -751,7 +767,7 @@ export declare const LocalOverridesSchema: z.ZodObject<{
751
767
  zstd: z.ZodOptional<z.ZodUnion<readonly [z.ZodBoolean, z.ZodLiteral<"auto">]>>;
752
768
  openssl: z.ZodOptional<z.ZodUnion<readonly [z.ZodBoolean, z.ZodLiteral<"auto">]>>;
753
769
  }, z.core.$strict>>;
754
- msvc: z.ZodOptional<z.ZodObject<{
770
+ unreal: z.ZodOptional<z.ZodObject<{
755
771
  enabled: z.ZodOptional<z.ZodBoolean>;
756
772
  }, z.core.$strict> | z.ZodObject<{
757
773
  version: z.ZodOptional<z.ZodString>;
@@ -766,7 +782,7 @@ export declare const LocalOverridesSchema: z.ZodObject<{
766
782
  zstd: z.ZodOptional<z.ZodUnion<readonly [z.ZodBoolean, z.ZodLiteral<"auto">]>>;
767
783
  openssl: z.ZodOptional<z.ZodUnion<readonly [z.ZodBoolean, z.ZodLiteral<"auto">]>>;
768
784
  }, z.core.$strict>>;
769
- unreal: z.ZodOptional<z.ZodObject<{
785
+ unity: z.ZodOptional<z.ZodObject<{
770
786
  enabled: z.ZodOptional<z.ZodBoolean>;
771
787
  }, z.core.$strict> | z.ZodObject<{
772
788
  version: z.ZodOptional<z.ZodString>;
@@ -1,4 +1,5 @@
1
1
  import { z } from 'zod';
2
2
  export declare const GithubSchema: z.ZodObject<{
3
3
  shareToken: z.ZodBoolean;
4
+ usePcLogin: z.ZodBoolean;
4
5
  }, z.core.$strict>;
@@ -4,4 +4,7 @@ export const GithubSchema = z.strictObject({
4
4
  shareToken: z
5
5
  .boolean()
6
6
  .describe('Give each sandbox the GitHub token you saved in Accounts (best a fine-grained token limited to some repositories and permissions), so gh and https git work there without logging in. Only with provisioning.git.access "full". The agent in the sandbox can read the token and use it for whatever it allows. A project file (.sandbox-config.json) cannot turn this on.'),
7
+ usePcLogin: z
8
+ .boolean()
9
+ .describe('Give each sandbox the GitHub CLI (gh) login from this PC, when there is one, so gh and https git work there without logging in. Used when no token saved for sandboxes is handed over. Only with provisioning.git.access "full". Without a gh login on the PC nothing happens. The login reaches everything your account can, and the agent in the sandbox can read it. A project file (.sandbox-config.json) cannot turn this on.'),
7
10
  });
@@ -5,5 +5,6 @@ export declare const PcInstallsSchema: z.ZodObject<{
5
5
  unrealEngines: z.ZodUnion<readonly [z.ZodLiteral<"auto">, z.ZodBoolean, z.ZodArray<z.ZodString>]>;
6
6
  unrealEngineFolders: z.ZodArray<z.ZodString>;
7
7
  unrealAssets: z.ZodUnion<readonly [z.ZodLiteral<"auto">, z.ZodBoolean]>;
8
- unityEditors: z.ZodUnion<readonly [z.ZodBoolean, z.ZodArray<z.ZodString>]>;
8
+ unityEditors: z.ZodUnion<readonly [z.ZodLiteral<"auto">, z.ZodBoolean, z.ZodArray<z.ZodString>]>;
9
+ unityAssets: z.ZodUnion<readonly [z.ZodLiteral<"auto">, z.ZodBoolean]>;
9
10
  }, z.core.$strict>;
@@ -21,6 +21,11 @@ export const PcInstallsSchema = z
21
21
  unrealAssets: z
22
22
  .union([z.literal('auto'), z.boolean()])
23
23
  .describe('The Epic Games Launcher\'s vault cache of this PC (the Fab and Marketplace packs you downloaded), read-only in the sandbox at C:\\PcInstalls\\unreal\\Vault: what you download on your PC is there for the agents at once. "auto" = whenever the sandbox is set up for Unreal, true = always, false = never.'),
24
- unityEditors: pick(z.string().regex(/^\d+\.\d+\.\d+[abfp]\d+$/), 'Unity editors installed with Unity Hub', '["6000.0.32f1"]'),
24
+ unityEditors: z
25
+ .union([z.literal('auto'), z.boolean(), z.array(z.string().regex(/^\d+\.\d+\.\d+[abfp]\d+$/))])
26
+ .describe('Unity editors installed on this PC (with Unity Hub), read-only in the sandbox under C:\\PcInstalls\\unity: a project opens with the PC\'s editor without a download. "auto" = all of them whenever the sandbox is set up for Unity, true = always, false = never, or a list (e.g. ["6000.0.32f1"]).'),
27
+ unityAssets: z
28
+ .union([z.literal('auto'), z.boolean()])
29
+ .describe('This PC\'s Unity Asset Store downloads (.unitypackage files), read-only at C:\\PcInstalls\\unity\\AssetStore: what you download on your PC is there for the agents at once. "auto" = whenever the sandbox is set up for Unity, true = always, false = never.'),
25
30
  })
26
31
  .describe("Games, engines and editors installed on this PC, mapped read-only into sandboxes (no copy, no room on the sandbox's disk).");
@@ -55,6 +55,14 @@ export declare const ToolchainsSchema: z.ZodObject<{
55
55
  modules: z.ZodArray<z.ZodString>;
56
56
  hub: z.ZodBoolean;
57
57
  keepVersions: z.ZodNumber;
58
+ mcp: z.ZodBoolean;
59
+ agentSkills: z.ZodBoolean;
60
+ cliVersion: z.ZodString;
61
+ assetCache: z.ZodEnum<{
62
+ pc: "pc";
63
+ persisted: "persisted";
64
+ local: "local";
65
+ }>;
58
66
  }, z.core.$strict>;
59
67
  godot: z.ZodObject<{
60
68
  enabled: z.ZodUnion<readonly [z.ZodBoolean, z.ZodLiteral<"auto">]>;
@@ -70,24 +70,39 @@ export const ToolchainsSchema = z.strictObject({
70
70
  .describe('"persisted": the engine\'s local derived data cache (compiled shaders, 10-50 GB) in tools\\unreal\\ddc, kept between sandboxes. "local": Unreal\'s own place on the sandbox disk (rebuilt every boot).'),
71
71
  }),
72
72
  unity: z.strictObject({
73
- enabled: enabled("Unity: the editor version a project asks for, from Unity's release API (checked against its published hash), installed into tools\\unity\\<version> (6-7 GB each), with the modules you list.", 'ProjectSettings/ProjectVersion.txt'),
73
+ enabled: enabled("Unity: the editor version a project asks for, from Unity's release API (checked against its published hash), installed on the data disk (tools\\unity\\editors\\<version>, 8-13 GB each, kept between sandboxes), with the modules you list. This PC's editors (pcInstalls.unityEditors) are used first.", 'ProjectSettings/ProjectVersion.txt'),
74
74
  acceptLicense: z
75
75
  .boolean()
76
76
  .describe('Required to install: you accept the Unity terms of service (https://unity.com/legal/terms-of-service), and the editor needs a Unity licence (Personal is free). A project file cannot accept it for you.'),
77
77
  version: z
78
78
  .string()
79
79
  .min(1)
80
- .describe('"project" = the version in ProjectSettings/ProjectVersion.txt, or an editor version such as "6000.0.32f1".'),
80
+ .describe('"project" = the version in ProjectSettings/ProjectVersion.txt, or an editor version such as "6000.0.32f1" for folders without one (a project\'s own version always wins).'),
81
81
  modules: z
82
82
  .array(z.string().regex(/^[a-z0-9-]+$/))
83
83
  .describe('Editor modules to add: "android" (4-5 GB, also the Android SDK), "webgl" (1.5 GB), "windows-il2cpp" (adds Visual Studio\'s C++ parts), "ios" (Xcode project export only: iOS builds need a Mac).'),
84
- hub: z.boolean().describe('Also Unity Hub, with the installed editors listed in it.'),
84
+ hub: z
85
+ .boolean()
86
+ .describe('Also Unity Hub (kept on the data disk), for signing in to Unity Personal and installing editors by hand.'),
85
87
  keepVersions: z
86
88
  .number()
87
89
  .int()
88
90
  .min(1)
89
91
  .max(20)
90
92
  .describe('How many editor versions to keep in tools\\unity; older ones are removed (the least recently used first).'),
93
+ mcp: z
94
+ .boolean()
95
+ .describe("The Unity CLI's MCP server (unity mcp) in Claude Code and Codex as sbx-unity: Unity's read-only tools always, the open editor's tools when the project has the Unity Pipeline package (Unity 6 and later). Nothing in your project changes."),
96
+ agentSkills: z
97
+ .boolean()
98
+ .describe("Unity's skills for Claude Code and Codex, from Unity-Technologies/skills at the commit the Unity CLI pins."),
99
+ cliVersion: z
100
+ .string()
101
+ .regex(/^(latest|\d+\.\d+\.\d+(-[A-Za-z0-9.]+)?)$/)
102
+ .describe('The Unity CLI version, checked against the SHA-256 Unity publishes: a version such as "1.0.0-beta.16", or "latest". It never updates itself.'),
103
+ assetCache: z
104
+ .enum(['persisted', 'pc', 'local'])
105
+ .describe('"persisted": Asset Store downloads made in the sandbox go to tools\\unity\\asset-store (kept). "pc": the sandbox uses this PC\'s Asset Store downloads (read-only; download new ones on your PC). "local": Unity\'s own place on the sandbox disk (lost when it closes).'),
91
106
  }),
92
107
  godot: z.strictObject({
93
108
  enabled: enabled('Godot from its official builds (checked against the published SHA-512 sums), self-contained in tools\\godot\\<version> with `godot` (the console build) on PATH.', 'project.godot'),
@@ -218,7 +233,7 @@ export const ToolchainsSchema = z.strictObject({
218
233
  }),
219
234
  cli: z
220
235
  .strictObject({
221
- gh: EnabledSchema.describe('GitHub CLI (gh). Only with provisioning.git.access "full": gh can push and merge through the GitHub API, past a read-only git. Your PC\'s gh login is never copied; `gh auth login` inside persists (GH_CONFIG_DIR), unless a token you saved for sandboxes is handed over (github.shareToken). "auto" = when the project has a .github folder.'),
236
+ gh: EnabledSchema.describe('GitHub CLI (gh). Only with provisioning.git.access "full": gh can push and merge through the GitHub API, past a read-only git. Your PC\'s gh login is copied only with github.usePcLogin (or a token you saved for sandboxes with github.shareToken); otherwise `gh auth login` inside persists (GH_CONFIG_DIR). "auto" = when the project has a .github folder.'),
222
237
  zstd: EnabledSchema.describe('Zstandard (zstd). "auto" = off; set true to get it.'),
223
238
  openssl: EnabledSchema.describe('`openssl` on PATH, from the copy Git for Windows ships (its mingw64\\bin is not put on PATH, so it cannot shadow MinGW\'s gcc). "auto" = on.'),
224
239
  })
@@ -5,6 +5,7 @@ import { epicAdapter } from './kinds/epic.js';
5
5
  import { expoAdapter } from './kinds/expo.js';
6
6
  import { keystoreAdapter } from './kinds/keystore.js';
7
7
  import { perplexityAdapter } from './kinds/perplexity.js';
8
+ import { perplexityAppAdapter } from './kinds/perplexityapp.js';
8
9
  import { playAdapter } from './kinds/play.js';
9
10
  import { steamAdapter } from './kinds/steam.js';
10
11
  import { unityAdapter } from './kinds/unity.js';
@@ -19,4 +20,5 @@ export const ADAPTERS = {
19
20
  appstore: appstoreAdapter,
20
21
  perplexity: perplexityAdapter,
21
22
  comet: cometAdapter,
23
+ perplexityapp: perplexityAppAdapter,
22
24
  };
@@ -4,28 +4,30 @@ import type { ServiceAccounts } from '../../shared/accounts/payloads.js';
4
4
  import { type GuestAdapter } from './adapter.js';
5
5
  export declare const DeliveredSchema: z.ZodObject<{
6
6
  fingerprints: z.ZodRecord<z.ZodEnum<{
7
- unity: "unity";
8
7
  keystore: "keystore";
9
8
  play: "play";
10
9
  expo: "expo";
11
10
  appstore: "appstore";
11
+ unity: "unity";
12
12
  steam: "steam";
13
13
  epic: "epic";
14
14
  cfx: "cfx";
15
15
  perplexity: "perplexity";
16
16
  comet: "comet";
17
+ perplexityapp: "perplexityapp";
17
18
  }> & z.core.$partial, z.ZodString>;
18
19
  leased: z.ZodArray<z.ZodEnum<{
19
- unity: "unity";
20
20
  keystore: "keystore";
21
21
  play: "play";
22
22
  expo: "expo";
23
23
  appstore: "appstore";
24
+ unity: "unity";
24
25
  steam: "steam";
25
26
  epic: "epic";
26
27
  cfx: "cfx";
27
28
  perplexity: "perplexity";
28
29
  comet: "comet";
30
+ perplexityapp: "perplexityapp";
29
31
  }>>;
30
32
  }, z.core.$strip>;
31
33
  export type Delivered = z.output<typeof DeliveredSchema>;
@@ -0,0 +1,7 @@
1
+ import { type CometPayload } from '../../../shared/accounts/index.js';
2
+ import { type GuestAdapter } from '../adapter.js';
3
+ /** Where the sign-in waits for the app. */
4
+ export declare function perplexityAppPendingFile(root?: string): string;
5
+ /** The sign-in waiting for the app (left in place), or null (none, or not the expected shape). */
6
+ export declare function peekPendingPerplexityApp(root?: string): CometPayload | null;
7
+ export declare const perplexityAppAdapter: GuestAdapter<'perplexityapp'>;
@@ -0,0 +1,53 @@
1
+ // Perplexity desktop app: the saved perplexity.ai sign-in cookies wait in secretDir('perplexityapp') (the sandbox's own
2
+ // disk) until the app runs; the watch then writes them into it over its DevTools port and deletes the file. While the
3
+ // sandbox runs, the watch asks the running app for its perplexity.ai cookies, so a sign-in made here (or renewed) is
4
+ // kept for the next sandbox. When the app is not running, the last sign-in seen stands.
5
+ import fs from 'node:fs';
6
+ import path from 'node:path';
7
+ import { cometSummary, PAYLOADS } from '../../../shared/accounts/index.js';
8
+ import { readBoundedFile } from '../../../shared/io/bounded.js';
9
+ import { readAppSignIn, restoreAppSignIn } from '../../browser/perplexity-app.js';
10
+ import { secretDir } from '../adapter.js';
11
+ /** Where the sign-in waits for the app. */
12
+ export function perplexityAppPendingFile(root = secretDir('perplexityapp')) {
13
+ return path.join(root, 'restore.json');
14
+ }
15
+ /** The sign-in waiting for the app (left in place), or null (none, or not the expected shape). */
16
+ export function peekPendingPerplexityApp(root) {
17
+ const bytes = readBoundedFile(perplexityAppPendingFile(root), 512 * 1024);
18
+ if (!bytes)
19
+ return null;
20
+ try {
21
+ const parsed = PAYLOADS.perplexityapp.safeParse(JSON.parse(bytes.toString('utf8')));
22
+ return parsed.success ? parsed.data : null;
23
+ }
24
+ catch {
25
+ return null; // Not JSON: nothing to restore.
26
+ }
27
+ }
28
+ /** The last sign-in seen in this process (the daemon's watch). */
29
+ let held = null;
30
+ export const perplexityAppAdapter = {
31
+ kind: 'perplexityapp',
32
+ apply(p) {
33
+ const file = perplexityAppPendingFile();
34
+ fs.mkdirSync(path.dirname(file), { recursive: true });
35
+ fs.writeFileSync(file, JSON.stringify(p), { encoding: 'utf8', mode: 0o600 });
36
+ held = p;
37
+ return {
38
+ summary: 'Perplexity app: your saved sign-in (' + cometSummary(p) + ') goes into it once it runs (reload its window)',
39
+ };
40
+ },
41
+ async refresh() {
42
+ const pending = peekPendingPerplexityApp();
43
+ if (pending && (await restoreAppSignIn(pending).catch(() => false)))
44
+ fs.rmSync(perplexityAppPendingFile(), { force: true });
45
+ const now = await readAppSignIn();
46
+ if (now)
47
+ held = now;
48
+ },
49
+ current() {
50
+ return held;
51
+ },
52
+ checkMs: 30_000,
53
+ };
@@ -1,2 +1,29 @@
1
+ import type { UnityStatus } from '../../../shared/unity/status.js';
1
2
  import { type GuestAdapter } from '../adapter.js';
3
+ /** Runs a program to its end (or its time limit); the exit code and what it printed. Injected by the self-test. */
4
+ export type UnityRunner = (file: string, args: readonly string[], o: {
5
+ readonly timeoutMs: number;
6
+ readonly env?: Readonly<Record<string, string>>;
7
+ }) => Promise<{
8
+ readonly code: number;
9
+ readonly stdout: string;
10
+ }>;
11
+ export declare const runUnityProgram: UnityRunner;
12
+ export interface UnityDirs {
13
+ readonly programData: string;
14
+ readonly localAppData: string;
15
+ /** secretDir('unity'). */
16
+ readonly secrets: string;
17
+ }
18
+ /** The adapter for these folders and this runner (the self-test passes its own). */
19
+ export declare function unityAdapterFor(dirs: UnityDirs, run?: UnityRunner): GuestAdapter<'unity'>;
2
20
  export declare const unityAdapter: GuestAdapter<'unity'>;
21
+ /**
22
+ * Activates the serial the sandbox holds once an editor exists, then asks `unity license status` where the licence
23
+ * stands. The detail never holds a secret.
24
+ */
25
+ export declare function activateUnityLicence(o: {
26
+ readonly editorExe: string | null;
27
+ readonly unityExe: string | null;
28
+ readonly source?: string;
29
+ }, dirs?: UnityDirs, run?: UnityRunner): Promise<UnityStatus['licence']>;
@@ -1,7 +1,164 @@
1
- import { notAvailableYet } from '../adapter.js';
2
- export const unityAdapter = {
3
- kind: 'unity',
4
- apply(_p) {
5
- return notAvailableYet('unity');
6
- },
7
- };
1
+ // Unity: the licence file (Unity_lic.ulf) goes to %ProgramData%\Unity and the named-user licence to
2
+ // %LOCALAPPDATA%\Unity\licenses, where the editor reads them. The Unity ID (and a Plus or Pro serial) are kept in
3
+ // secretDir('unity')\activation.json, on the sandbox's own disk, for the editor to sign in with. A serial seat is
4
+ // returned when the sandbox stops. Nothing here puts a password, serial or licence text in a log or a summary.
5
+ import { execFile } from 'node:child_process';
6
+ import fs from 'node:fs';
7
+ import path from 'node:path';
8
+ import { z } from 'zod';
9
+ import { MAX_ULF_BYTES, parseLicenceStatus, unityEntitlementFile, unityUlfFile, } from '../../../shared/accounts/index.js';
10
+ import { decodeText, readBoundedFile } from '../../../shared/io/index.js';
11
+ import { licenceStatusArgs, UNITY_CLI_ENV } from '../../../shared/unity/cli.js';
12
+ import { localAppData, secretDir } from '../adapter.js';
13
+ const MAX_JSON_BYTES = 16 * 1024;
14
+ const RETURN_MS = 120_000;
15
+ const ACTIVATE_MS = 180_000;
16
+ const STATUS_MS = 60_000;
17
+ const ActivationSchema = z.object({
18
+ email: z.string().max(256).optional(),
19
+ password: z.string().max(1024).optional(),
20
+ serial: z.string().max(64).optional(),
21
+ });
22
+ const ActivatedSchema = z.object({ editorExe: z.string().min(1).max(520), serial: z.literal(true) });
23
+ export const runUnityProgram = (file, args, o) => new Promise((resolve) => {
24
+ execFile(file, [...args], { windowsHide: true, timeout: o.timeoutMs, maxBuffer: 1024 * 1024, env: { ...process.env, ...o.env } }, (error, stdout) => {
25
+ const code = error ? (typeof error.code === 'number' ? error.code : -1) : 0;
26
+ resolve({ code, stdout: String(stdout ?? '') });
27
+ });
28
+ });
29
+ function readText(file) {
30
+ const bytes = readBoundedFile(file, MAX_ULF_BYTES);
31
+ return bytes ? decodeText(bytes).text : null;
32
+ }
33
+ function readSecretJson(schema, file) {
34
+ const bytes = readBoundedFile(file, MAX_JSON_BYTES);
35
+ if (!bytes)
36
+ return null;
37
+ try {
38
+ const parsed = schema.safeParse(JSON.parse(decodeText(bytes).text));
39
+ return parsed.success ? parsed.data : null;
40
+ }
41
+ catch {
42
+ return null; // not JSON: treated as absent
43
+ }
44
+ }
45
+ function writeText(file, text) {
46
+ fs.mkdirSync(path.dirname(file), { recursive: true });
47
+ fs.writeFileSync(file, text, 'utf8');
48
+ }
49
+ /** The adapter for these folders and this runner (the self-test passes its own). */
50
+ export function unityAdapterFor(dirs, run = runUnityProgram) {
51
+ const activation = path.join(dirs.secrets, 'activation.json');
52
+ const activated = path.join(dirs.secrets, 'activated.json');
53
+ return {
54
+ kind: 'unity',
55
+ apply(p) {
56
+ if (p.ulf)
57
+ writeText(unityUlfFile(dirs.programData), p.ulf);
58
+ if (p.entitlement)
59
+ writeText(unityEntitlementFile(dirs.localAppData), p.entitlement);
60
+ const sign = {};
61
+ if (p.email)
62
+ sign.email = p.email;
63
+ if (p.password)
64
+ sign.password = p.password;
65
+ if (p.serial)
66
+ sign.serial = p.serial;
67
+ if (Object.keys(sign).length)
68
+ writeText(activation, JSON.stringify(sign));
69
+ return {
70
+ summary: p.ulf || p.entitlement
71
+ ? 'Unity: your licence file is in place'
72
+ : 'Unity: your Unity ID is ready to activate the serial',
73
+ };
74
+ },
75
+ current() {
76
+ const ulf = readText(unityUlfFile(dirs.programData));
77
+ const entitlement = readText(unityEntitlementFile(dirs.localAppData));
78
+ const sign = readSecretJson(ActivationSchema, activation) ?? {};
79
+ const out = {
80
+ ...(ulf ? { ulf } : {}),
81
+ ...(entitlement ? { entitlement } : {}),
82
+ ...sign,
83
+ };
84
+ return Object.keys(out).length ? out : null;
85
+ },
86
+ async release() {
87
+ const marker = readSecretJson(ActivatedSchema, activated);
88
+ if (!marker)
89
+ return;
90
+ const sign = readSecretJson(ActivationSchema, activation);
91
+ if (!sign?.email || !sign.password)
92
+ return;
93
+ await run(marker.editorExe, [
94
+ '-batchmode',
95
+ '-nographics',
96
+ '-quit',
97
+ '-returnlicense',
98
+ '-username',
99
+ sign.email,
100
+ '-password',
101
+ sign.password,
102
+ '-logFile',
103
+ path.join(dirs.secrets, 'return.log'),
104
+ ], { timeoutMs: RETURN_MS });
105
+ },
106
+ };
107
+ }
108
+ function defaultDirs() {
109
+ return {
110
+ programData: process.env.ProgramData ?? process.env.PROGRAMDATA ?? 'C:\\ProgramData',
111
+ localAppData: localAppData(),
112
+ secrets: secretDir('unity'),
113
+ };
114
+ }
115
+ export const unityAdapter = unityAdapterFor(defaultDirs());
116
+ /**
117
+ * Activates the serial the sandbox holds once an editor exists, then asks `unity license status` where the licence
118
+ * stands. The detail never holds a secret.
119
+ */
120
+ export async function activateUnityLicence(o, dirs = defaultDirs(), run = runUnityProgram) {
121
+ const sign = readSecretJson(ActivationSchema, path.join(dirs.secrets, 'activation.json'));
122
+ if (sign?.serial && sign.email && sign.password && o.editorExe) {
123
+ await run(o.editorExe, [
124
+ '-batchmode',
125
+ '-nographics',
126
+ '-quit',
127
+ '-serial',
128
+ sign.serial,
129
+ '-username',
130
+ sign.email,
131
+ '-password',
132
+ sign.password,
133
+ '-logFile',
134
+ path.join(dirs.secrets, 'activate.log'),
135
+ ], { timeoutMs: ACTIVATE_MS });
136
+ writeText(path.join(dirs.secrets, 'activated.json'), JSON.stringify({ editorExe: o.editorExe, serial: true }));
137
+ }
138
+ const user = sign?.email ?? null;
139
+ if (!o.unityExe)
140
+ return { state: 'unknown', kind: '', detail: 'not checked', user };
141
+ let parsed = null;
142
+ try {
143
+ const r = await run(o.unityExe, licenceStatusArgs(), { timeoutMs: STATUS_MS, env: UNITY_CLI_ENV });
144
+ parsed = r.code === 0 ? JSON.parse(r.stdout) : null;
145
+ }
146
+ catch {
147
+ parsed = null; // not JSON: reported as not recognised
148
+ }
149
+ const s = parseLicenceStatus(parsed);
150
+ if (s.state === 'active')
151
+ return { state: 'active', kind: s.kind, detail: 'active (' + (s.kind || 'licensed') + ')', user };
152
+ if (s.state === 'none') {
153
+ const hasFile = readText(unityUlfFile(dirs.programData)) !== null || readText(unityEntitlementFile(dirs.localAppData)) !== null;
154
+ return hasFile
155
+ ? {
156
+ state: 'invalid',
157
+ kind: '',
158
+ detail: 'the licence file from ' + (o.source ?? 'your saved sign-in') + ' is not accepted here: sign in again',
159
+ user,
160
+ }
161
+ : { state: 'none', kind: '', detail: 'none: sign in to Unity once in this sandbox', user };
162
+ }
163
+ return { state: 'unknown', kind: '', detail: s.detail, user };
164
+ }
@@ -13,10 +13,13 @@ import { errMsg } from '../../core/util/errors.js';
13
13
  import { emptyEnv, tool } from '../toolchains/tool-env.js';
14
14
  import { uvVars } from '../toolchains/runtimes.js';
15
15
  import { COMET_MCP_PORT, cometShortcutArgs } from '../browser/comet.js';
16
+ import { perplexityAppShortcutArgs } from '../browser/perplexity-app.js';
16
17
  import { afterInstall } from './after-install.js';
17
18
  import { installFromKept } from './comet-unpack.js';
18
19
  import { findExe } from './find-exe.js';
20
+ import { installStoreApp } from './store-app.js';
19
21
  import { shortcuts } from './shortcuts.js';
22
+ import { SYSTEM } from '../../shared/system.js';
20
23
  import { signatureCheck } from '../toolchains/installers.js';
21
24
  import { resolve } from './sources.js';
22
25
  import { unpack } from './unpack.js';
@@ -46,6 +49,7 @@ export class AppInstaller {
46
49
  async prefetch(entries) {
47
50
  const todo = entries.filter((e) => !('remote' in e.source) &&
48
51
  !('locked' in e.source) &&
52
+ !('store' in e.source) &&
49
53
  !('npm' in e.source) &&
50
54
  e.id !== '7zip' &&
51
55
  (this.options.refresh || !exists(path.join(tool('apps', ...e.id.split('/')), MARKER))));
@@ -97,6 +101,20 @@ export class AppInstaller {
97
101
  this.installed.push(entry.name);
98
102
  return;
99
103
  }
104
+ if ('store' in entry.source) {
105
+ // A Store app: Windows in the sandbox is new on every boot, so it is installed again from the PC's package.
106
+ log('Installing ' + entry.name + ' (Microsoft Store package) ...');
107
+ await installStoreApp(entry.id, entry.source.store.packageName);
108
+ fs.writeFileSync(path.join(mkdirp(dest), MARKER), JSON.stringify({ id: entry.id, at: new Date().toISOString() }));
109
+ this.gui.push({
110
+ name: entry.name,
111
+ exe: SYSTEM.powershell(),
112
+ args: perplexityAppShortcutArgs(path.join(launchDir, 'sandbox', 'scripts', 'start-store-app.ps1')),
113
+ });
114
+ this.installed.push(entry.name);
115
+ this.installedIds.push(entry.id);
116
+ return;
117
+ }
100
118
  if (!exists(path.join(dest, MARKER)) || this.options.refresh)
101
119
  await this.download(entry, dest);
102
120
  // A Chromium installer that could not be unpacked is kept and installed into the sandbox each boot instead.
@@ -0,0 +1,4 @@
1
+ /** Where the PC left an app's package. */
2
+ export declare function storePackageDir(appId: string): string;
3
+ /** Installs the app from its kept package; resolves when Windows has it. */
4
+ export declare function installStoreApp(appId: string, packageName: string): Promise<void>;