windows-development-sandbox 1.17.0 → 1.18.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 (319) hide show
  1. package/README.md +92 -92
  2. package/config.example.json +97 -4
  3. package/dist/app/features/accounts/accounts.def.d.ts +116 -2
  4. package/dist/app/features/accounts/accounts.def.js +80 -12
  5. package/dist/app/features/accounts/accounts.run.d.ts +29 -0
  6. package/dist/app/features/accounts/accounts.run.js +36 -6
  7. package/dist/app/features/accounts/index.d.ts +2 -0
  8. package/dist/app/features/accounts/index.js +4 -1
  9. package/dist/app/features/accounts/services.def.d.ts +111 -0
  10. package/dist/app/features/accounts/services.def.js +187 -0
  11. package/dist/app/features/accounts/services.run.d.ts +65 -0
  12. package/dist/app/features/accounts/services.run.js +212 -0
  13. package/dist/app/features/defs.d.ts +112 -1
  14. package/dist/app/features/defs.js +5 -0
  15. package/dist/app/features/settings/categories.def.js +21 -4
  16. package/dist/app/registry.js +5 -1
  17. package/dist/bin/agent-sandbox.js +2 -2
  18. package/dist/bin/{chunk-QLGGAG3D.js → chunk-BKF43GJ3.js} +51 -16
  19. package/dist/bin/{chunk-REE3EMHD.js → chunk-YD3A67RS.js} +3812 -1702
  20. package/dist/bin/{chunk-XYUVIVJT.js → chunk-Z5D32FN3.js} +1 -1
  21. package/dist/bin/claude-host.js +2 -2
  22. package/dist/bin/claude-sbx.js +2 -2
  23. package/dist/bin/codex-sbx.js +2 -2
  24. package/dist/bin/gemini-sbx.js +2 -2
  25. package/dist/bin/sandbox.js +2 -2
  26. package/dist/bin/sbx-hide.js +2 -2
  27. package/dist/bin/sbx-show.js +2 -2
  28. package/dist/cli/commands/launch/launch.js +30 -1
  29. package/dist/cli/manifest.d.ts +93 -65
  30. package/dist/cli/manifest.js +23 -5
  31. package/dist/cli/menu/pages/accounts-page.js +31 -16
  32. package/dist/cli/services/accounts-service.d.ts +14 -4
  33. package/dist/cli/services/accounts-service.js +19 -6
  34. package/dist/cli/services/data-collect.js +26 -1
  35. package/dist/core/config/defaults.js +47 -4
  36. package/dist/core/detect/toolchains.d.ts +15 -1
  37. package/dist/core/detect/toolchains.js +45 -12
  38. package/dist/core/local-config/overrides.js +6 -0
  39. package/dist/core/schema/accounts.d.ts +27 -0
  40. package/dist/core/schema/accounts.js +32 -0
  41. package/dist/core/schema/config.d.ts +239 -0
  42. package/dist/core/schema/config.js +6 -0
  43. package/dist/core/schema/pc-installs.d.ts +7 -0
  44. package/dist/core/schema/pc-installs.js +17 -0
  45. package/dist/core/schema/toolchains.d.ts +61 -0
  46. package/dist/core/schema/toolchains.js +106 -0
  47. package/dist/core/types.d.ts +18 -0
  48. package/dist/guest/accounts/adapter.d.ts +25 -0
  49. package/dist/guest/accounts/adapter.js +21 -0
  50. package/dist/guest/accounts/adapters.d.ts +5 -0
  51. package/dist/guest/accounts/adapters.js +18 -0
  52. package/dist/guest/accounts/apply.d.ts +41 -0
  53. package/dist/guest/accounts/apply.js +47 -0
  54. package/dist/guest/accounts/kinds/appstore.d.ts +2 -0
  55. package/dist/guest/accounts/kinds/appstore.js +7 -0
  56. package/dist/guest/accounts/kinds/cfx.d.ts +2 -0
  57. package/dist/guest/accounts/kinds/cfx.js +7 -0
  58. package/dist/guest/accounts/kinds/epic.d.ts +2 -0
  59. package/dist/guest/accounts/kinds/epic.js +26 -0
  60. package/dist/guest/accounts/kinds/expo.d.ts +2 -0
  61. package/dist/guest/accounts/kinds/expo.js +7 -0
  62. package/dist/guest/accounts/kinds/keystore.d.ts +2 -0
  63. package/dist/guest/accounts/kinds/keystore.js +7 -0
  64. package/dist/guest/accounts/kinds/play.d.ts +2 -0
  65. package/dist/guest/accounts/kinds/play.js +7 -0
  66. package/dist/guest/accounts/kinds/steam.d.ts +4 -0
  67. package/dist/guest/accounts/kinds/steam.js +17 -0
  68. package/dist/guest/accounts/kinds/unity.d.ts +2 -0
  69. package/dist/guest/accounts/kinds/unity.js +7 -0
  70. package/dist/guest/accounts/watch.d.ts +28 -0
  71. package/dist/guest/accounts/watch.js +78 -0
  72. package/dist/guest/agents/agent-files.d.ts +6 -0
  73. package/dist/guest/agents/agent-files.js +14 -0
  74. package/dist/guest/agents/local-state.d.ts +2 -0
  75. package/dist/guest/agents/local-state.js +13 -1
  76. package/dist/guest/apps/resolvers-gamedev.d.ts +2 -0
  77. package/dist/guest/apps/resolvers-gamedev.js +1 -0
  78. package/dist/guest/apps/resolvers-mobile.d.ts +2 -0
  79. package/dist/guest/apps/resolvers-mobile.js +1 -0
  80. package/dist/guest/apps/resolvers.js +4 -0
  81. package/dist/guest/boot/boot.d.ts +5 -0
  82. package/dist/guest/boot/boot.js +36 -1
  83. package/dist/guest/daemon/accounts.d.ts +3 -0
  84. package/dist/guest/daemon/accounts.js +25 -0
  85. package/dist/guest/daemon/daemon.js +2 -0
  86. package/dist/guest/daemon/idle-shutdown.js +3 -1
  87. package/dist/guest/daemon/sessions.js +2 -0
  88. package/dist/guest/devtools/android.d.ts +2 -0
  89. package/dist/guest/devtools/android.js +7 -0
  90. package/dist/guest/devtools/devtool.d.ts +9 -0
  91. package/dist/guest/devtools/devtool.js +5 -0
  92. package/dist/guest/devtools/fivem.d.ts +2 -0
  93. package/dist/guest/devtools/fivem.js +7 -0
  94. package/dist/guest/devtools/registry.d.ts +6 -0
  95. package/dist/guest/devtools/registry.js +12 -0
  96. package/dist/guest/devtools/steam.d.ts +2 -0
  97. package/dist/guest/devtools/steam.js +228 -0
  98. package/dist/guest/devtools/unity.d.ts +2 -0
  99. package/dist/guest/devtools/unity.js +7 -0
  100. package/dist/guest/entries/daemon.js +2 -0
  101. package/dist/guest/entries/tool.d.ts +1 -0
  102. package/dist/guest/entries/tool.js +17 -0
  103. package/dist/guest/toolchains/engines/godot.d.ts +4 -0
  104. package/dist/guest/toolchains/engines/godot.js +4 -0
  105. package/dist/guest/toolchains/engines/unity-release.d.ts +15 -0
  106. package/dist/guest/toolchains/engines/unity-release.js +6 -0
  107. package/dist/guest/toolchains/engines/unity.d.ts +4 -0
  108. package/dist/guest/toolchains/engines/unity.js +4 -0
  109. package/dist/guest/toolchains/engines/unreal-engines.d.ts +4 -0
  110. package/dist/guest/toolchains/engines/unreal-engines.js +4 -0
  111. package/dist/guest/toolchains/fivem/artifacts.d.ts +6 -0
  112. package/dist/guest/toolchains/fivem/artifacts.js +7 -0
  113. package/dist/guest/toolchains/fivem/fivem.d.ts +4 -0
  114. package/dist/guest/toolchains/fivem/fivem.js +4 -0
  115. package/dist/guest/toolchains/installers.d.ts +12 -0
  116. package/dist/guest/toolchains/installers.js +39 -0
  117. package/dist/guest/toolchains/languages/java.js +1 -1
  118. package/dist/guest/toolchains/languages/kotlin.d.ts +3 -0
  119. package/dist/guest/toolchains/languages/kotlin.js +6 -0
  120. package/dist/guest/toolchains/mobile/android-repo.d.ts +11 -0
  121. package/dist/guest/toolchains/mobile/android-repo.js +10 -0
  122. package/dist/guest/toolchains/mobile/android.d.ts +17 -0
  123. package/dist/guest/toolchains/mobile/android.js +16 -0
  124. package/dist/guest/toolchains/mobile/dart.d.ts +4 -0
  125. package/dist/guest/toolchains/mobile/dart.js +4 -0
  126. package/dist/guest/toolchains/mobile/flutter.d.ts +4 -0
  127. package/dist/guest/toolchains/mobile/flutter.js +4 -0
  128. package/dist/guest/toolchains/mobile/react-native.d.ts +4 -0
  129. package/dist/guest/toolchains/mobile/react-native.js +4 -0
  130. package/dist/guest/toolchains/native/unreal.d.ts +3 -7
  131. package/dist/guest/toolchains/native/unreal.js +16 -155
  132. package/dist/guest/toolchains/native/visual-studio.d.ts +15 -0
  133. package/dist/guest/toolchains/native/visual-studio.js +159 -0
  134. package/dist/guest/toolchains/native/vs-request.d.ts +19 -0
  135. package/dist/guest/toolchains/native/vs-request.js +46 -0
  136. package/dist/guest/toolchains/not-yet.d.ts +2 -0
  137. package/dist/guest/toolchains/not-yet.js +6 -0
  138. package/dist/guest/toolchains/persisted.d.ts +48 -0
  139. package/dist/guest/toolchains/persisted.js +159 -0
  140. package/dist/guest/toolchains/plan.js +80 -4
  141. package/dist/guest/toolchains/steam/apps.d.ts +27 -0
  142. package/dist/guest/toolchains/steam/apps.js +112 -0
  143. package/dist/guest/toolchains/steam/client.d.ts +5 -0
  144. package/dist/guest/toolchains/steam/client.js +67 -0
  145. package/dist/guest/toolchains/steam/commands.d.ts +58 -0
  146. package/dist/guest/toolchains/steam/commands.js +155 -0
  147. package/dist/guest/toolchains/steam/steam.d.ts +4 -0
  148. package/dist/guest/toolchains/steam/steam.js +61 -0
  149. package/dist/guest/toolchains/steam/steamcmd-install.d.ts +29 -0
  150. package/dist/guest/toolchains/steam/steamcmd-install.js +177 -0
  151. package/dist/guest/toolchains/steam/steamcmd.d.ts +6 -0
  152. package/dist/guest/toolchains/steam/steamcmd.js +23 -0
  153. package/dist/guest/toolchains/step.d.ts +10 -0
  154. package/dist/host/accounts/deliver.d.ts +26 -0
  155. package/dist/host/accounts/deliver.js +80 -0
  156. package/dist/host/accounts/handoff.d.ts +17 -0
  157. package/dist/host/accounts/handoff.js +110 -0
  158. package/dist/host/accounts/index.d.ts +6 -0
  159. package/dist/host/accounts/index.js +8 -0
  160. package/dist/host/accounts/kinds/appstore.d.ts +2 -0
  161. package/dist/host/accounts/kinds/appstore.js +10 -0
  162. package/dist/host/accounts/kinds/cfx.d.ts +2 -0
  163. package/dist/host/accounts/kinds/cfx.js +7 -0
  164. package/dist/host/accounts/kinds/epic.d.ts +2 -0
  165. package/dist/host/accounts/kinds/epic.js +15 -0
  166. package/dist/host/accounts/kinds/expo.d.ts +2 -0
  167. package/dist/host/accounts/kinds/expo.js +7 -0
  168. package/dist/host/accounts/kinds/keystore.d.ts +2 -0
  169. package/dist/host/accounts/kinds/keystore.js +7 -0
  170. package/dist/host/accounts/kinds/play.d.ts +2 -0
  171. package/dist/host/accounts/kinds/play.js +7 -0
  172. package/dist/host/accounts/kinds/steam.d.ts +6 -0
  173. package/dist/host/accounts/kinds/steam.js +31 -0
  174. package/dist/host/accounts/kinds/unity.d.ts +2 -0
  175. package/dist/host/accounts/kinds/unity.js +13 -0
  176. package/dist/host/accounts/leases.d.ts +40 -0
  177. package/dist/host/accounts/leases.js +62 -0
  178. package/dist/host/accounts/source.d.ts +21 -0
  179. package/dist/host/accounts/source.js +15 -0
  180. package/dist/host/accounts/sources.d.ts +5 -0
  181. package/dist/host/accounts/sources.js +18 -0
  182. package/dist/host/accounts/store.d.ts +23 -0
  183. package/dist/host/accounts/store.js +74 -0
  184. package/dist/host/audit/log.d.ts +1 -1
  185. package/dist/host/launch/generate.d.ts +2 -0
  186. package/dist/host/launch/generate.js +16 -1
  187. package/dist/host/launch/hints/android.d.ts +3 -0
  188. package/dist/host/launch/hints/android.js +3 -0
  189. package/dist/host/launch/hints/engines.d.ts +3 -0
  190. package/dist/host/launch/hints/engines.js +3 -0
  191. package/dist/host/launch/hints/fivem.d.ts +3 -0
  192. package/dist/host/launch/hints/fivem.js +3 -0
  193. package/dist/host/launch/hints/hint.d.ts +2 -0
  194. package/dist/host/launch/hints/hint.js +1 -0
  195. package/dist/host/launch/hints/index.d.ts +5 -0
  196. package/dist/host/launch/hints/index.js +29 -0
  197. package/dist/host/launch/hints/mobile.d.ts +3 -0
  198. package/dist/host/launch/hints/mobile.js +3 -0
  199. package/dist/host/launch/hints/steam.d.ts +7 -0
  200. package/dist/host/launch/hints/steam.js +59 -0
  201. package/dist/host/launch/index.d.ts +2 -2
  202. package/dist/host/launch/index.js +2 -2
  203. package/dist/host/launch/mappings.js +2 -0
  204. package/dist/host/launch/session-file.js +2 -0
  205. package/dist/host/launch/stage.js +10 -1
  206. package/dist/host/launch/toolchains.d.ts +7 -0
  207. package/dist/host/launch/toolchains.js +11 -0
  208. package/dist/host/pc-installs/discover.d.ts +19 -0
  209. package/dist/host/pc-installs/discover.js +59 -0
  210. package/dist/host/pc-installs/epic.d.ts +2 -0
  211. package/dist/host/pc-installs/epic.js +7 -0
  212. package/dist/host/pc-installs/index.d.ts +3 -0
  213. package/dist/host/pc-installs/index.js +2 -0
  214. package/dist/host/pc-installs/source.d.ts +9 -0
  215. package/dist/host/pc-installs/source.js +1 -0
  216. package/dist/host/pc-installs/steam.d.ts +16 -0
  217. package/dist/host/pc-installs/steam.js +143 -0
  218. package/dist/host/pc-installs/unity.d.ts +2 -0
  219. package/dist/host/pc-installs/unity.js +7 -0
  220. package/dist/host/pc-installs/unreal.d.ts +2 -0
  221. package/dist/host/pc-installs/unreal.js +7 -0
  222. package/dist/host/profile/accounts.d.ts +21 -6
  223. package/dist/host/profile/accounts.js +108 -28
  224. package/dist/host/profile/claude-login.d.ts +32 -2
  225. package/dist/host/profile/claude-login.js +100 -8
  226. package/dist/host/profile/index.d.ts +1 -1
  227. package/dist/host/profile/index.js +1 -1
  228. package/dist/host/secrets/launch-secrets.js +1 -0
  229. package/dist/runtime/agent.js +321 -9
  230. package/dist/runtime/daemon.js +1987 -595
  231. package/dist/runtime/db.js +334 -11
  232. package/dist/runtime/main.js +2530 -709
  233. package/dist/runtime/netproxy.js +321 -9
  234. package/dist/runtime/tool.js +28549 -0
  235. package/dist/runtime/view.js +321 -9
  236. package/dist/selftest/accounts.test.js +172 -1
  237. package/dist/selftest/agent-paths.test.js +13 -1
  238. package/dist/selftest/android.test.d.ts +2 -0
  239. package/dist/selftest/android.test.js +7 -0
  240. package/dist/selftest/app.test.js +1 -1
  241. package/dist/selftest/engines.test.d.ts +2 -0
  242. package/dist/selftest/engines.test.js +7 -0
  243. package/dist/selftest/fivem.test.d.ts +2 -0
  244. package/dist/selftest/fivem.test.js +7 -0
  245. package/dist/selftest/generate.test.js +1 -1
  246. package/dist/selftest/index.js +18 -0
  247. package/dist/selftest/menu-screens.js +1 -0
  248. package/dist/selftest/menu.test.js +2 -1
  249. package/dist/selftest/mobile.test.d.ts +2 -0
  250. package/dist/selftest/mobile.test.js +7 -0
  251. package/dist/selftest/pc-installs.test.d.ts +2 -0
  252. package/dist/selftest/pc-installs.test.js +111 -0
  253. package/dist/selftest/persisted-installs.test.d.ts +2 -0
  254. package/dist/selftest/persisted-installs.test.js +107 -0
  255. package/dist/selftest/projects.test.js +6 -4
  256. package/dist/selftest/service-accounts.test.d.ts +2 -0
  257. package/dist/selftest/service-accounts.test.js +320 -0
  258. package/dist/selftest/steam.test.d.ts +2 -0
  259. package/dist/selftest/steam.test.js +316 -0
  260. package/dist/selftest/storage-helper.test.js +31 -8
  261. package/dist/selftest/support/engine-golden.js +3 -0
  262. package/dist/selftest/support/fixtures.d.ts +87 -0
  263. package/dist/selftest/support/fixtures.js +4 -3
  264. package/dist/selftest/support/pc-memory.d.ts +2 -0
  265. package/dist/selftest/support/pc-memory.js +17 -0
  266. package/dist/selftest/support/web-preview.js +20 -1
  267. package/dist/selftest/unity.test.d.ts +2 -0
  268. package/dist/selftest/unity.test.js +7 -0
  269. package/dist/shared/accounts/fingerprint.d.ts +1 -0
  270. package/dist/shared/accounts/fingerprint.js +20 -0
  271. package/dist/shared/accounts/index.d.ts +5 -0
  272. package/dist/shared/accounts/index.js +7 -0
  273. package/dist/shared/accounts/kinds/epic.d.ts +10 -0
  274. package/dist/shared/accounts/kinds/epic.js +56 -0
  275. package/dist/shared/accounts/kinds/steam.d.ts +28 -0
  276. package/dist/shared/accounts/kinds/steam.js +99 -0
  277. package/dist/shared/accounts/kinds.d.ts +41 -0
  278. package/dist/shared/accounts/kinds.js +154 -0
  279. package/dist/shared/accounts/payloads.d.ts +151 -0
  280. package/dist/shared/accounts/payloads.js +128 -0
  281. package/dist/shared/apps/catalogue-gamedev.d.ts +2 -0
  282. package/dist/shared/apps/catalogue-gamedev.js +1 -0
  283. package/dist/shared/apps/catalogue-mobile.d.ts +2 -0
  284. package/dist/shared/apps/catalogue-mobile.js +1 -0
  285. package/dist/shared/apps/catalogue-modding.d.ts +2 -0
  286. package/dist/shared/apps/catalogue-modding.js +1 -0
  287. package/dist/shared/apps/catalogue.d.ts +1 -0
  288. package/dist/shared/apps/catalogue.js +6 -1
  289. package/dist/shared/channel/schema.d.ts +183 -0
  290. package/dist/shared/channel/secrets.d.ts +42 -0
  291. package/dist/shared/channel/secrets.js +3 -0
  292. package/dist/shared/download/downloader.d.ts +7 -0
  293. package/dist/shared/download/downloader.js +10 -3
  294. package/dist/shared/installs.d.ts +19 -0
  295. package/dist/shared/installs.js +13 -0
  296. package/dist/shared/io/bounded.d.ts +6 -0
  297. package/dist/shared/io/bounded.js +38 -0
  298. package/dist/shared/io/index.d.ts +2 -0
  299. package/dist/shared/io/index.js +2 -0
  300. package/dist/shared/io/text.d.ts +9 -0
  301. package/dist/shared/io/text.js +18 -0
  302. package/dist/shared/paths/guest-paths.js +1 -1
  303. package/dist/shared/paths/index.d.ts +1 -0
  304. package/dist/shared/paths/index.js +1 -0
  305. package/dist/shared/paths/pc-installs.d.ts +20 -0
  306. package/dist/shared/paths/pc-installs.js +19 -0
  307. package/dist/shared/vdf.d.ts +25 -0
  308. package/dist/shared/vdf.js +151 -0
  309. package/dist/sync/sync-cycle.js +9 -0
  310. package/dist/web/index.html +1 -1
  311. package/dist/web/{main-JTH3FT4O.js → main-CWIF4VQI.js} +63 -61
  312. package/native/csharp/HcsHost/AssemblyInfo.cs +3 -3
  313. package/native/csharp/HostTools/AssemblyInfo.cs +3 -3
  314. package/native/csharp/StorageHelper/AssemblyInfo.cs +3 -3
  315. package/package.json +1 -1
  316. package/sandbox/scripts/add-firewall-port.ps1 +13 -0
  317. package/sandbox/templates/fivem/README.txt +2 -0
  318. package/schemas/config.schema.json +485 -0
  319. package/schemas/sandbox-config.schema.json +416 -0
@@ -0,0 +1,18 @@
1
+ // Text files Windows programs write in either UTF-8 or UTF-16LE (the Epic launcher's ini, Unity's files): decoded by
2
+ // their byte-order mark, and written back in the encoding they were read in.
3
+ /** The text of a file's bytes: UTF-16LE with its mark, UTF-8 with or without one (the mark is not part of the text). */
4
+ export function decodeText(bytes) {
5
+ if (bytes.length >= 2 && bytes[0] === 0xff && bytes[1] === 0xfe)
6
+ return { text: bytes.subarray(2).toString('utf16le'), encoding: 'utf16le' };
7
+ if (bytes.length >= 3 && bytes[0] === 0xef && bytes[1] === 0xbb && bytes[2] === 0xbf)
8
+ return { text: bytes.subarray(3).toString('utf8'), encoding: 'utf8bom' };
9
+ return { text: bytes.toString('utf8'), encoding: 'utf8' };
10
+ }
11
+ /** The bytes of a text in an encoding (with its mark for UTF-16LE and UTF-8 with a mark). */
12
+ export function encodeText(text, encoding) {
13
+ if (encoding === 'utf16le')
14
+ return Buffer.concat([Buffer.from([0xff, 0xfe]), Buffer.from(text, 'utf16le')]);
15
+ if (encoding === 'utf8bom')
16
+ return Buffer.concat([Buffer.from([0xef, 0xbb, 0xbf]), Buffer.from(text, 'utf8')]);
17
+ return Buffer.from(text, 'utf8');
18
+ }
@@ -4,7 +4,7 @@
4
4
  // Pure functions only: used by the schema, the host (.wsb, session.json) and history sync.
5
5
  import { win32 } from 'node:path';
6
6
  /** Guest folders no mapping may use: the OS, the sandbox's own folders and the mirror root. */
7
- export const RESERVED_GUEST = /^C:\\(?:Windows|Program Files|Program Files \(x86\)|ProgramData|Users|AgentLaunch|AgentData|HostTools|nvm|Mirror)(?:\\|$)/i;
7
+ export const RESERVED_GUEST = /^C:\\(?:Windows|Program Files|Program Files \(x86\)|ProgramData|Users|AgentLaunch|AgentData|HostTools|nvm|Mirror|PcInstalls)(?:\\|$)/i;
8
8
  /** Where folders for other drive letters really live inside the sandbox: C:\Mirror\<letter>. */
9
9
  export const MIRROR_ROOT = 'C:\\Mirror';
10
10
  /** Letters a mirrored path may use. Never C: (the sandbox's own disk); A:/B: are left alone (floppy-era tools). */
@@ -3,3 +3,4 @@ export * from './claude-paths.js';
3
3
  export * from './agent-profile.js';
4
4
  export * from './conversation.js';
5
5
  export * from './projects.js';
6
+ export * from './pc-installs.js';
@@ -3,3 +3,4 @@ export * from './claude-paths.js';
3
3
  export * from './agent-profile.js';
4
4
  export * from './conversation.js';
5
5
  export * from './projects.js';
6
+ export * from './pc-installs.js';
@@ -0,0 +1,20 @@
1
+ /** Where this PC's installs appear in the sandbox (reserved: RESERVED_GUEST). */
2
+ export declare const PC_INSTALLS_GUEST = "C:\\PcInstalls";
3
+ export type PcInstallKind = 'steam-game' | 'steam-library' | 'epic-game' | 'unreal' | 'unity';
4
+ export interface PcInstall {
5
+ readonly kind: PcInstallKind;
6
+ /** The Steam app ID or library (library1), the Epic app name, the engine (UE_5.4) or editor version. */
7
+ readonly id: string;
8
+ readonly name: string;
9
+ readonly version?: string;
10
+ /** The folder on this PC (never sent to the sandbox). */
11
+ readonly host: string;
12
+ /** Where it appears in the sandbox, read-only. */
13
+ readonly guest: string;
14
+ }
15
+ /** What session.json says about them: no host paths. */
16
+ export interface PcInstallManifest {
17
+ readonly items: readonly Omit<PcInstall, 'host'>[];
18
+ }
19
+ /** The guest folder of one install: C:\PcInstalls\steam\<appid>, \epic\<AppName>, \unreal\UE_5.4, \unity\<ver>. */
20
+ export declare function pcInstallGuest(kind: PcInstallKind, id: string): string;
@@ -0,0 +1,19 @@
1
+ // Read-only installs of this PC (pcInstalls: Steam and Epic games, Unreal engines, Unity editors) as the sandbox sees
2
+ // them: each one under C:\PcInstalls, which no other mapping may use. Pure: the host places them, the sandbox reads
3
+ // the manifest (paths only) from session.json.
4
+ /** Where this PC's installs appear in the sandbox (reserved: RESERVED_GUEST). */
5
+ export const PC_INSTALLS_GUEST = 'C:\\PcInstalls';
6
+ const SAFE_ID = /^[A-Za-z0-9._-]{1,100}$/;
7
+ const AREA = {
8
+ 'steam-game': 'steam',
9
+ 'steam-library': 'steam',
10
+ 'epic-game': 'epic',
11
+ unreal: 'unreal',
12
+ unity: 'unity',
13
+ };
14
+ /** The guest folder of one install: C:\PcInstalls\steam\<appid>, \epic\<AppName>, \unreal\UE_5.4, \unity\<ver>. */
15
+ export function pcInstallGuest(kind, id) {
16
+ if (!SAFE_ID.test(id) || /^\.+$/.test(id))
17
+ throw new Error('not a usable install id: ' + id);
18
+ return PC_INSTALLS_GUEST + '\\' + AREA[kind] + '\\' + id;
19
+ }
@@ -0,0 +1,25 @@
1
+ export type VdfValue = string | VdfObject;
2
+ export interface VdfObject {
3
+ readonly [key: string]: VdfValue;
4
+ }
5
+ export interface VdfLimits {
6
+ /** The most characters read (default 1 MB). */
7
+ readonly maxBytes?: number;
8
+ /** The deepest nesting of { } (default 32). */
9
+ readonly maxDepth?: number;
10
+ /** The most keys in the whole text (default 100000). */
11
+ readonly maxKeys?: number;
12
+ /**
13
+ * Backslash escapes in quoted text (\\ \" \n \t; default true), as Steam writes libraryfolders.vdf and config.vdf.
14
+ * Hand-written build scripts ("ContentRoot" "..\content\") need false.
15
+ */
16
+ readonly escapes?: boolean;
17
+ }
18
+ /** The root object of a .vdf text, or null when it is not one (or breaks a limit). */
19
+ export declare function parseVdf(text: string, limits?: VdfLimits): VdfObject | null;
20
+ /** The value at a path of keys (any case), or undefined. */
21
+ export declare function vdfGet(root: VdfValue | null | undefined, ...keys: readonly string[]): VdfValue | undefined;
22
+ /** The text at a path of keys (any case), or undefined when it is missing or a block. */
23
+ export declare function vdfText(root: VdfValue | null | undefined, ...keys: readonly string[]): string | undefined;
24
+ /** The block at a path of keys (any case), or undefined when it is missing or a text. */
25
+ export declare function vdfObject(root: VdfValue | null | undefined, ...keys: readonly string[]): VdfObject | undefined;
@@ -0,0 +1,151 @@
1
+ // Valve's KeyValues text format (.vdf: libraryfolders.vdf, appmanifest_*.acf, config.vdf, app_build and
2
+ // workshop_item scripts), parsed with hard limits on size, depth and keys (the files may come from a sandbox or a
3
+ // repo). One pass over the text, no regular expressions on it, no recursion, objects without a prototype. Pure.
4
+ const DEFAULT_MAX_BYTES = 1024 * 1024;
5
+ const DEFAULT_MAX_DEPTH = 32;
6
+ const DEFAULT_MAX_KEYS = 100_000;
7
+ const isSpace = (c) => c === ' ' || c === '\t' || c === '\r' || c === '\n' || c === '\f';
8
+ const ESCAPED = { '\\': '\\', '"': '"', n: '\n', t: '\t' };
9
+ /** The tokens of a text, or null when a quote or a [condition] is not closed. */
10
+ function tokenize(text, escapes) {
11
+ const tokens = [];
12
+ let i = 0;
13
+ const n = text.length;
14
+ while (i < n) {
15
+ const c = text[i];
16
+ if (isSpace(c)) {
17
+ i++;
18
+ }
19
+ else if (c === '/' && text[i + 1] === '/') {
20
+ while (i < n && text[i] !== '\n')
21
+ i++;
22
+ }
23
+ else if (c === '{') {
24
+ tokens.push({ kind: 'open' });
25
+ i++;
26
+ }
27
+ else if (c === '}') {
28
+ tokens.push({ kind: 'close' });
29
+ i++;
30
+ }
31
+ else if (c === '[') {
32
+ // A platform condition ([$WIN32]) after a value: not used here, skipped.
33
+ const end = text.indexOf(']', i);
34
+ if (end < 0)
35
+ return null;
36
+ i = end + 1;
37
+ }
38
+ else if (c === '"') {
39
+ let out = '';
40
+ let start = ++i;
41
+ for (;;) {
42
+ if (i >= n)
43
+ return null;
44
+ const d = text[i];
45
+ if (d === '"')
46
+ break;
47
+ if (escapes && d === '\\' && i + 1 < n && ESCAPED[text[i + 1]] !== undefined) {
48
+ out += text.slice(start, i) + ESCAPED[text[i + 1]];
49
+ i += 2;
50
+ start = i;
51
+ continue;
52
+ }
53
+ i++;
54
+ }
55
+ tokens.push({ kind: 'text', text: out + text.slice(start, i) });
56
+ i++;
57
+ }
58
+ else {
59
+ const start = i;
60
+ while (i < n && !isSpace(text[i]) && text[i] !== '{' && text[i] !== '}' && text[i] !== '"')
61
+ i++;
62
+ tokens.push({ kind: 'text', text: text.slice(start, i) });
63
+ }
64
+ }
65
+ return tokens;
66
+ }
67
+ function open() {
68
+ return { target: Object.create(null), seen: new Set() };
69
+ }
70
+ /** Sets a key unless the object has it already in any case (the first one wins); false when it was there. */
71
+ function setFirst(o, key, value) {
72
+ const lower = key.toLowerCase();
73
+ if (o.seen.has(lower))
74
+ return false;
75
+ o.seen.add(lower);
76
+ o.target[key] = value;
77
+ return true;
78
+ }
79
+ /** The root object of a .vdf text, or null when it is not one (or breaks a limit). */
80
+ export function parseVdf(text, limits = {}) {
81
+ const maxBytes = limits.maxBytes ?? DEFAULT_MAX_BYTES;
82
+ const maxDepth = limits.maxDepth ?? DEFAULT_MAX_DEPTH;
83
+ const maxKeys = limits.maxKeys ?? DEFAULT_MAX_KEYS;
84
+ if (typeof text !== 'string' || text.length > maxBytes)
85
+ return null;
86
+ const tokens = tokenize(text.charCodeAt(0) === 0xfeff ? text.slice(1) : text, limits.escapes ?? true);
87
+ if (!tokens)
88
+ return null;
89
+ const root = open();
90
+ const stack = [root];
91
+ let keys = 0;
92
+ let i = 0;
93
+ while (i < tokens.length) {
94
+ const token = tokens[i];
95
+ const current = stack[stack.length - 1];
96
+ if (token.kind === 'close') {
97
+ if (stack.length === 1)
98
+ return null;
99
+ stack.pop();
100
+ i++;
101
+ continue;
102
+ }
103
+ if (token.kind === 'open')
104
+ return null;
105
+ if (++keys > maxKeys)
106
+ return null;
107
+ const next = tokens[i + 1];
108
+ if (!next || next.kind === 'close')
109
+ return null;
110
+ if (next.kind === 'open') {
111
+ if (stack.length > maxDepth)
112
+ return null;
113
+ const child = open();
114
+ // A duplicate key's block is still read (into one that is dropped) so the braces stay balanced.
115
+ setFirst(current, token.text, child.target);
116
+ stack.push(child);
117
+ }
118
+ else {
119
+ setFirst(current, token.text, next.text);
120
+ }
121
+ i += 2;
122
+ }
123
+ return stack.length === 1 ? root.target : null;
124
+ }
125
+ /** The value at a path of keys (any case), or undefined. */
126
+ export function vdfGet(root, ...keys) {
127
+ let at = root ?? undefined;
128
+ for (const key of keys) {
129
+ if (at === undefined || typeof at === 'string')
130
+ return undefined;
131
+ const lower = key.toLowerCase();
132
+ let found;
133
+ for (const k in at)
134
+ if (k.toLowerCase() === lower) {
135
+ found = at[k];
136
+ break;
137
+ }
138
+ at = found;
139
+ }
140
+ return at;
141
+ }
142
+ /** The text at a path of keys (any case), or undefined when it is missing or a block. */
143
+ export function vdfText(root, ...keys) {
144
+ const value = vdfGet(root, ...keys);
145
+ return typeof value === 'string' ? value : undefined;
146
+ }
147
+ /** The block at a path of keys (any case), or undefined when it is missing or a text. */
148
+ export function vdfObject(root, ...keys) {
149
+ const value = vdfGet(root, ...keys);
150
+ return value !== undefined && typeof value !== 'string' ? value : undefined;
151
+ }
@@ -1,5 +1,6 @@
1
1
  import path from 'node:path';
2
2
  import { assertNoLinks } from '../core/util/index.js';
3
+ import { takeHandoffs } from '../host/accounts/index.js';
3
4
  import { hostClaudeDir, PluginShare } from '../host/profile/index.js';
4
5
  import { hostDataFolder, hostDataRoot, storageOf } from '../host/storage/index.js';
5
6
  import { hostClaudeMemDir, syncClaudeMem } from './claude-mem.js';
@@ -74,6 +75,14 @@ export function syncBeforeLaunch(config, dataPath, hostWorkspace) {
74
75
  }
75
76
  /** Syncs the sandbox's history (and, when `final`, claude-mem) back to this PC, as configured for the last launch. */
76
77
  export function syncBack(dataPath, final) {
78
+ // Service sign-ins the sandbox renewed or you made there (accounts.<kind>.share): sealed here, the plain copy gone;
79
+ // the last sync of a sandbox lets go of its leases.
80
+ try {
81
+ takeHandoffs(dataPath, final);
82
+ }
83
+ catch {
84
+ // Never stops a sync: a sign-in that could not be taken stays in the data folder for the next cycle.
85
+ }
77
86
  const state = readSyncState(dataPath);
78
87
  const summary = { history: 0, claudeMem: 'disabled' };
79
88
  if (!state)
@@ -6,7 +6,7 @@
6
6
  <title>Sandbox</title>
7
7
  <link rel="icon" href="data:," />
8
8
  <link rel="stylesheet" href="/main-XT7T6ODM.css" />
9
- <script type="module" src="/main-JTH3FT4O.js"></script>
9
+ <script type="module" src="/main-CWIF4VQI.js"></script>
10
10
  </head>
11
11
  <body>
12
12
  <div id="root"></div>