windows-development-sandbox 1.17.3 → 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 (315) hide show
  1. package/README.md +1 -1
  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/apps/resolvers-gamedev.d.ts +2 -0
  73. package/dist/guest/apps/resolvers-gamedev.js +1 -0
  74. package/dist/guest/apps/resolvers-mobile.d.ts +2 -0
  75. package/dist/guest/apps/resolvers-mobile.js +1 -0
  76. package/dist/guest/apps/resolvers.js +4 -0
  77. package/dist/guest/boot/boot.d.ts +5 -0
  78. package/dist/guest/boot/boot.js +35 -1
  79. package/dist/guest/daemon/accounts.d.ts +3 -0
  80. package/dist/guest/daemon/accounts.js +25 -0
  81. package/dist/guest/daemon/daemon.js +2 -0
  82. package/dist/guest/daemon/idle-shutdown.js +3 -1
  83. package/dist/guest/daemon/sessions.js +2 -0
  84. package/dist/guest/devtools/android.d.ts +2 -0
  85. package/dist/guest/devtools/android.js +7 -0
  86. package/dist/guest/devtools/devtool.d.ts +9 -0
  87. package/dist/guest/devtools/devtool.js +5 -0
  88. package/dist/guest/devtools/fivem.d.ts +2 -0
  89. package/dist/guest/devtools/fivem.js +7 -0
  90. package/dist/guest/devtools/registry.d.ts +6 -0
  91. package/dist/guest/devtools/registry.js +12 -0
  92. package/dist/guest/devtools/steam.d.ts +2 -0
  93. package/dist/guest/devtools/steam.js +228 -0
  94. package/dist/guest/devtools/unity.d.ts +2 -0
  95. package/dist/guest/devtools/unity.js +7 -0
  96. package/dist/guest/entries/daemon.js +2 -0
  97. package/dist/guest/entries/tool.d.ts +1 -0
  98. package/dist/guest/entries/tool.js +17 -0
  99. package/dist/guest/toolchains/engines/godot.d.ts +4 -0
  100. package/dist/guest/toolchains/engines/godot.js +4 -0
  101. package/dist/guest/toolchains/engines/unity-release.d.ts +15 -0
  102. package/dist/guest/toolchains/engines/unity-release.js +6 -0
  103. package/dist/guest/toolchains/engines/unity.d.ts +4 -0
  104. package/dist/guest/toolchains/engines/unity.js +4 -0
  105. package/dist/guest/toolchains/engines/unreal-engines.d.ts +4 -0
  106. package/dist/guest/toolchains/engines/unreal-engines.js +4 -0
  107. package/dist/guest/toolchains/fivem/artifacts.d.ts +6 -0
  108. package/dist/guest/toolchains/fivem/artifacts.js +7 -0
  109. package/dist/guest/toolchains/fivem/fivem.d.ts +4 -0
  110. package/dist/guest/toolchains/fivem/fivem.js +4 -0
  111. package/dist/guest/toolchains/installers.d.ts +12 -0
  112. package/dist/guest/toolchains/installers.js +39 -0
  113. package/dist/guest/toolchains/languages/java.js +1 -1
  114. package/dist/guest/toolchains/languages/kotlin.d.ts +3 -0
  115. package/dist/guest/toolchains/languages/kotlin.js +6 -0
  116. package/dist/guest/toolchains/mobile/android-repo.d.ts +11 -0
  117. package/dist/guest/toolchains/mobile/android-repo.js +10 -0
  118. package/dist/guest/toolchains/mobile/android.d.ts +17 -0
  119. package/dist/guest/toolchains/mobile/android.js +16 -0
  120. package/dist/guest/toolchains/mobile/dart.d.ts +4 -0
  121. package/dist/guest/toolchains/mobile/dart.js +4 -0
  122. package/dist/guest/toolchains/mobile/flutter.d.ts +4 -0
  123. package/dist/guest/toolchains/mobile/flutter.js +4 -0
  124. package/dist/guest/toolchains/mobile/react-native.d.ts +4 -0
  125. package/dist/guest/toolchains/mobile/react-native.js +4 -0
  126. package/dist/guest/toolchains/native/unreal.d.ts +3 -7
  127. package/dist/guest/toolchains/native/unreal.js +16 -167
  128. package/dist/guest/toolchains/native/visual-studio.d.ts +15 -0
  129. package/dist/guest/toolchains/native/visual-studio.js +159 -0
  130. package/dist/guest/toolchains/native/vs-request.d.ts +19 -0
  131. package/dist/guest/toolchains/native/vs-request.js +46 -0
  132. package/dist/guest/toolchains/not-yet.d.ts +2 -0
  133. package/dist/guest/toolchains/not-yet.js +6 -0
  134. package/dist/guest/toolchains/persisted.d.ts +48 -0
  135. package/dist/guest/toolchains/persisted.js +159 -0
  136. package/dist/guest/toolchains/plan.js +80 -4
  137. package/dist/guest/toolchains/steam/apps.d.ts +27 -0
  138. package/dist/guest/toolchains/steam/apps.js +112 -0
  139. package/dist/guest/toolchains/steam/client.d.ts +5 -0
  140. package/dist/guest/toolchains/steam/client.js +67 -0
  141. package/dist/guest/toolchains/steam/commands.d.ts +58 -0
  142. package/dist/guest/toolchains/steam/commands.js +155 -0
  143. package/dist/guest/toolchains/steam/steam.d.ts +4 -0
  144. package/dist/guest/toolchains/steam/steam.js +61 -0
  145. package/dist/guest/toolchains/steam/steamcmd-install.d.ts +29 -0
  146. package/dist/guest/toolchains/steam/steamcmd-install.js +177 -0
  147. package/dist/guest/toolchains/steam/steamcmd.d.ts +6 -0
  148. package/dist/guest/toolchains/steam/steamcmd.js +23 -0
  149. package/dist/guest/toolchains/step.d.ts +10 -0
  150. package/dist/host/accounts/deliver.d.ts +26 -0
  151. package/dist/host/accounts/deliver.js +80 -0
  152. package/dist/host/accounts/handoff.d.ts +17 -0
  153. package/dist/host/accounts/handoff.js +110 -0
  154. package/dist/host/accounts/index.d.ts +6 -0
  155. package/dist/host/accounts/index.js +8 -0
  156. package/dist/host/accounts/kinds/appstore.d.ts +2 -0
  157. package/dist/host/accounts/kinds/appstore.js +10 -0
  158. package/dist/host/accounts/kinds/cfx.d.ts +2 -0
  159. package/dist/host/accounts/kinds/cfx.js +7 -0
  160. package/dist/host/accounts/kinds/epic.d.ts +2 -0
  161. package/dist/host/accounts/kinds/epic.js +15 -0
  162. package/dist/host/accounts/kinds/expo.d.ts +2 -0
  163. package/dist/host/accounts/kinds/expo.js +7 -0
  164. package/dist/host/accounts/kinds/keystore.d.ts +2 -0
  165. package/dist/host/accounts/kinds/keystore.js +7 -0
  166. package/dist/host/accounts/kinds/play.d.ts +2 -0
  167. package/dist/host/accounts/kinds/play.js +7 -0
  168. package/dist/host/accounts/kinds/steam.d.ts +6 -0
  169. package/dist/host/accounts/kinds/steam.js +31 -0
  170. package/dist/host/accounts/kinds/unity.d.ts +2 -0
  171. package/dist/host/accounts/kinds/unity.js +13 -0
  172. package/dist/host/accounts/leases.d.ts +40 -0
  173. package/dist/host/accounts/leases.js +62 -0
  174. package/dist/host/accounts/source.d.ts +21 -0
  175. package/dist/host/accounts/source.js +15 -0
  176. package/dist/host/accounts/sources.d.ts +5 -0
  177. package/dist/host/accounts/sources.js +18 -0
  178. package/dist/host/accounts/store.d.ts +23 -0
  179. package/dist/host/accounts/store.js +74 -0
  180. package/dist/host/audit/log.d.ts +1 -1
  181. package/dist/host/launch/generate.d.ts +2 -0
  182. package/dist/host/launch/generate.js +16 -1
  183. package/dist/host/launch/hints/android.d.ts +3 -0
  184. package/dist/host/launch/hints/android.js +3 -0
  185. package/dist/host/launch/hints/engines.d.ts +3 -0
  186. package/dist/host/launch/hints/engines.js +3 -0
  187. package/dist/host/launch/hints/fivem.d.ts +3 -0
  188. package/dist/host/launch/hints/fivem.js +3 -0
  189. package/dist/host/launch/hints/hint.d.ts +2 -0
  190. package/dist/host/launch/hints/hint.js +1 -0
  191. package/dist/host/launch/hints/index.d.ts +5 -0
  192. package/dist/host/launch/hints/index.js +29 -0
  193. package/dist/host/launch/hints/mobile.d.ts +3 -0
  194. package/dist/host/launch/hints/mobile.js +3 -0
  195. package/dist/host/launch/hints/steam.d.ts +7 -0
  196. package/dist/host/launch/hints/steam.js +59 -0
  197. package/dist/host/launch/index.d.ts +2 -2
  198. package/dist/host/launch/index.js +2 -2
  199. package/dist/host/launch/mappings.js +2 -0
  200. package/dist/host/launch/session-file.js +2 -0
  201. package/dist/host/launch/stage.js +10 -1
  202. package/dist/host/launch/toolchains.d.ts +7 -0
  203. package/dist/host/launch/toolchains.js +11 -0
  204. package/dist/host/pc-installs/discover.d.ts +19 -0
  205. package/dist/host/pc-installs/discover.js +59 -0
  206. package/dist/host/pc-installs/epic.d.ts +2 -0
  207. package/dist/host/pc-installs/epic.js +7 -0
  208. package/dist/host/pc-installs/index.d.ts +3 -0
  209. package/dist/host/pc-installs/index.js +2 -0
  210. package/dist/host/pc-installs/source.d.ts +9 -0
  211. package/dist/host/pc-installs/source.js +1 -0
  212. package/dist/host/pc-installs/steam.d.ts +16 -0
  213. package/dist/host/pc-installs/steam.js +143 -0
  214. package/dist/host/pc-installs/unity.d.ts +2 -0
  215. package/dist/host/pc-installs/unity.js +7 -0
  216. package/dist/host/pc-installs/unreal.d.ts +2 -0
  217. package/dist/host/pc-installs/unreal.js +7 -0
  218. package/dist/host/profile/accounts.d.ts +21 -6
  219. package/dist/host/profile/accounts.js +108 -28
  220. package/dist/host/profile/claude-login.d.ts +32 -2
  221. package/dist/host/profile/claude-login.js +100 -8
  222. package/dist/host/profile/index.d.ts +1 -1
  223. package/dist/host/profile/index.js +1 -1
  224. package/dist/host/secrets/launch-secrets.js +1 -0
  225. package/dist/runtime/agent.js +321 -9
  226. package/dist/runtime/daemon.js +1987 -604
  227. package/dist/runtime/db.js +334 -11
  228. package/dist/runtime/main.js +2519 -723
  229. package/dist/runtime/netproxy.js +321 -9
  230. package/dist/runtime/tool.js +28549 -0
  231. package/dist/runtime/view.js +321 -9
  232. package/dist/selftest/accounts.test.js +172 -1
  233. package/dist/selftest/agent-paths.test.js +1 -0
  234. package/dist/selftest/android.test.d.ts +2 -0
  235. package/dist/selftest/android.test.js +7 -0
  236. package/dist/selftest/app.test.js +1 -1
  237. package/dist/selftest/engines.test.d.ts +2 -0
  238. package/dist/selftest/engines.test.js +7 -0
  239. package/dist/selftest/fivem.test.d.ts +2 -0
  240. package/dist/selftest/fivem.test.js +7 -0
  241. package/dist/selftest/generate.test.js +1 -1
  242. package/dist/selftest/index.js +18 -0
  243. package/dist/selftest/menu-screens.js +1 -0
  244. package/dist/selftest/menu.test.js +2 -1
  245. package/dist/selftest/mobile.test.d.ts +2 -0
  246. package/dist/selftest/mobile.test.js +7 -0
  247. package/dist/selftest/pc-installs.test.d.ts +2 -0
  248. package/dist/selftest/pc-installs.test.js +111 -0
  249. package/dist/selftest/persisted-installs.test.d.ts +2 -0
  250. package/dist/selftest/persisted-installs.test.js +107 -0
  251. package/dist/selftest/projects.test.js +6 -4
  252. package/dist/selftest/service-accounts.test.d.ts +2 -0
  253. package/dist/selftest/service-accounts.test.js +320 -0
  254. package/dist/selftest/steam.test.d.ts +2 -0
  255. package/dist/selftest/steam.test.js +316 -0
  256. package/dist/selftest/storage-helper.test.js +31 -8
  257. package/dist/selftest/support/engine-golden.js +3 -0
  258. package/dist/selftest/support/fixtures.d.ts +87 -0
  259. package/dist/selftest/support/fixtures.js +4 -3
  260. package/dist/selftest/support/pc-memory.d.ts +2 -0
  261. package/dist/selftest/support/pc-memory.js +17 -0
  262. package/dist/selftest/support/web-preview.js +20 -1
  263. package/dist/selftest/unity.test.d.ts +2 -0
  264. package/dist/selftest/unity.test.js +7 -0
  265. package/dist/shared/accounts/fingerprint.d.ts +1 -0
  266. package/dist/shared/accounts/fingerprint.js +20 -0
  267. package/dist/shared/accounts/index.d.ts +5 -0
  268. package/dist/shared/accounts/index.js +7 -0
  269. package/dist/shared/accounts/kinds/epic.d.ts +10 -0
  270. package/dist/shared/accounts/kinds/epic.js +56 -0
  271. package/dist/shared/accounts/kinds/steam.d.ts +28 -0
  272. package/dist/shared/accounts/kinds/steam.js +99 -0
  273. package/dist/shared/accounts/kinds.d.ts +41 -0
  274. package/dist/shared/accounts/kinds.js +154 -0
  275. package/dist/shared/accounts/payloads.d.ts +151 -0
  276. package/dist/shared/accounts/payloads.js +128 -0
  277. package/dist/shared/apps/catalogue-gamedev.d.ts +2 -0
  278. package/dist/shared/apps/catalogue-gamedev.js +1 -0
  279. package/dist/shared/apps/catalogue-mobile.d.ts +2 -0
  280. package/dist/shared/apps/catalogue-mobile.js +1 -0
  281. package/dist/shared/apps/catalogue-modding.d.ts +2 -0
  282. package/dist/shared/apps/catalogue-modding.js +1 -0
  283. package/dist/shared/apps/catalogue.d.ts +1 -0
  284. package/dist/shared/apps/catalogue.js +6 -1
  285. package/dist/shared/channel/schema.d.ts +183 -0
  286. package/dist/shared/channel/secrets.d.ts +42 -0
  287. package/dist/shared/channel/secrets.js +3 -0
  288. package/dist/shared/download/downloader.d.ts +7 -0
  289. package/dist/shared/download/downloader.js +10 -3
  290. package/dist/shared/installs.d.ts +19 -0
  291. package/dist/shared/installs.js +13 -0
  292. package/dist/shared/io/bounded.d.ts +6 -0
  293. package/dist/shared/io/bounded.js +38 -0
  294. package/dist/shared/io/index.d.ts +2 -0
  295. package/dist/shared/io/index.js +2 -0
  296. package/dist/shared/io/text.d.ts +9 -0
  297. package/dist/shared/io/text.js +18 -0
  298. package/dist/shared/paths/guest-paths.js +1 -1
  299. package/dist/shared/paths/index.d.ts +1 -0
  300. package/dist/shared/paths/index.js +1 -0
  301. package/dist/shared/paths/pc-installs.d.ts +20 -0
  302. package/dist/shared/paths/pc-installs.js +19 -0
  303. package/dist/shared/vdf.d.ts +25 -0
  304. package/dist/shared/vdf.js +151 -0
  305. package/dist/sync/sync-cycle.js +9 -0
  306. package/dist/web/index.html +1 -1
  307. package/dist/web/{main-JTH3FT4O.js → main-CWIF4VQI.js} +63 -61
  308. package/native/csharp/HcsHost/AssemblyInfo.cs +3 -3
  309. package/native/csharp/HostTools/AssemblyInfo.cs +3 -3
  310. package/native/csharp/StorageHelper/AssemblyInfo.cs +3 -3
  311. package/package.json +1 -1
  312. package/sandbox/scripts/add-firewall-port.ps1 +13 -0
  313. package/sandbox/templates/fivem/README.txt +2 -0
  314. package/schemas/config.schema.json +485 -0
  315. package/schemas/sandbox-config.schema.json +416 -0
@@ -0,0 +1,18 @@
1
+ import { appstoreAdapter } from './kinds/appstore.js';
2
+ import { cfxAdapter } from './kinds/cfx.js';
3
+ import { epicAdapter } from './kinds/epic.js';
4
+ import { expoAdapter } from './kinds/expo.js';
5
+ import { keystoreAdapter } from './kinds/keystore.js';
6
+ import { playAdapter } from './kinds/play.js';
7
+ import { steamAdapter } from './kinds/steam.js';
8
+ import { unityAdapter } from './kinds/unity.js';
9
+ export const ADAPTERS = {
10
+ epic: epicAdapter,
11
+ steam: steamAdapter,
12
+ unity: unityAdapter,
13
+ cfx: cfxAdapter,
14
+ keystore: keystoreAdapter,
15
+ play: playAdapter,
16
+ expo: expoAdapter,
17
+ appstore: appstoreAdapter,
18
+ };
@@ -0,0 +1,41 @@
1
+ import { z } from 'zod';
2
+ import { type ServiceKind } from '../../shared/accounts/kinds.js';
3
+ import type { ServiceAccounts } from '../../shared/accounts/payloads.js';
4
+ import { type GuestAdapter } from './adapter.js';
5
+ export declare const DeliveredSchema: z.ZodObject<{
6
+ fingerprints: z.ZodRecord<z.ZodEnum<{
7
+ unity: "unity";
8
+ steam: "steam";
9
+ epic: "epic";
10
+ cfx: "cfx";
11
+ keystore: "keystore";
12
+ play: "play";
13
+ expo: "expo";
14
+ appstore: "appstore";
15
+ }> & z.core.$partial, z.ZodString>;
16
+ leased: z.ZodArray<z.ZodEnum<{
17
+ unity: "unity";
18
+ steam: "steam";
19
+ epic: "epic";
20
+ cfx: "cfx";
21
+ keystore: "keystore";
22
+ play: "play";
23
+ expo: "expo";
24
+ appstore: "appstore";
25
+ }>>;
26
+ }, z.core.$strip>;
27
+ export type Delivered = z.output<typeof DeliveredSchema>;
28
+ export declare function deliveredFile(root?: string): string;
29
+ export declare function readDelivered(root?: string): Delivered;
30
+ export interface ApplyOptions {
31
+ /** The kinds whose lease this launch holds (session.json accountLeases). */
32
+ readonly leased?: readonly ServiceKind[];
33
+ /** The boot log. */
34
+ readonly say?: (line: string) => void;
35
+ readonly root?: string;
36
+ readonly adapters?: {
37
+ readonly [K in ServiceKind]?: GuestAdapter<K>;
38
+ };
39
+ }
40
+ /** Applies every sign-in given; returns the variables for the agent's sessions. A failing kind is a log line. */
41
+ export declare function applyServiceAccounts(given: ServiceAccounts | undefined, o?: ApplyOptions): Promise<Record<string, string>>;
@@ -0,0 +1,47 @@
1
+ // At boot: each handed-over sign-in goes to its tool (the adapters), then is dropped from memory. What was delivered
2
+ // is remembered only as fingerprints, with the kinds whose lease this launch holds, in delivered.json on the
3
+ // sandbox's own disk: the daemon's watch starts from them, so its first look never hands back what it was given.
4
+ import fs from 'node:fs';
5
+ import path from 'node:path';
6
+ import { z } from 'zod';
7
+ import { fingerprint } from '../../shared/accounts/fingerprint.js';
8
+ import { SERVICE_KINDS } from '../../shared/accounts/kinds.js';
9
+ import { readValid, writeJsonAtomic } from '../../shared/io/json.js';
10
+ import { errMsg } from '../../core/util/errors.js';
11
+ import { accountsRoot } from './adapter.js';
12
+ import { ADAPTERS } from './adapters.js';
13
+ export const DeliveredSchema = z.object({
14
+ fingerprints: z.partialRecord(z.enum(SERVICE_KINDS), z.string().max(128)),
15
+ leased: z.array(z.enum(SERVICE_KINDS)),
16
+ });
17
+ export function deliveredFile(root = accountsRoot()) {
18
+ return path.join(root, 'delivered.json');
19
+ }
20
+ export function readDelivered(root = accountsRoot()) {
21
+ return readValid(DeliveredSchema, deliveredFile(root)) ?? { fingerprints: {}, leased: [] };
22
+ }
23
+ /** Applies every sign-in given; returns the variables for the agent's sessions. A failing kind is a log line. */
24
+ export async function applyServiceAccounts(given, o = {}) {
25
+ const say = o.say ?? (() => undefined);
26
+ const env = {};
27
+ const fingerprints = {};
28
+ for (const kind of SERVICE_KINDS) {
29
+ const payload = given?.[kind];
30
+ if (payload === undefined)
31
+ continue;
32
+ const adapter = (o.adapters?.[kind] ?? ADAPTERS[kind]);
33
+ try {
34
+ const applied = await adapter.apply(payload);
35
+ Object.assign(env, applied.env ?? {});
36
+ fingerprints[kind] = fingerprint(payload);
37
+ say(applied.summary);
38
+ }
39
+ catch (e) {
40
+ say(kind + ' sign-in: could not be used (' + errMsg(e) + ')');
41
+ }
42
+ }
43
+ const root = o.root ?? accountsRoot();
44
+ fs.mkdirSync(root, { recursive: true });
45
+ writeJsonAtomic(deliveredFile(root), { fingerprints, leased: [...(o.leased ?? [])] });
46
+ return env;
47
+ }
@@ -0,0 +1,2 @@
1
+ import { type GuestAdapter } from '../adapter.js';
2
+ export declare const appstoreAdapter: GuestAdapter<'appstore'>;
@@ -0,0 +1,7 @@
1
+ import { notAvailableYet } from '../adapter.js';
2
+ export const appstoreAdapter = {
3
+ kind: 'appstore',
4
+ apply(_p) {
5
+ return notAvailableYet('appstore');
6
+ },
7
+ };
@@ -0,0 +1,2 @@
1
+ import { type GuestAdapter } from '../adapter.js';
2
+ export declare const cfxAdapter: GuestAdapter<'cfx'>;
@@ -0,0 +1,7 @@
1
+ import { notAvailableYet } from '../adapter.js';
2
+ export const cfxAdapter = {
3
+ kind: 'cfx',
4
+ apply(_p) {
5
+ return notAvailableYet('cfx');
6
+ },
7
+ };
@@ -0,0 +1,2 @@
1
+ import { type GuestAdapter } from '../adapter.js';
2
+ export declare const epicAdapter: GuestAdapter<'epic'>;
@@ -0,0 +1,26 @@
1
+ // Epic Games: the handed-over sign-in goes into the launcher's GameUserSettings.ini before anyone opens it (its other
2
+ // settings are kept, and the file keeps the encoding it had: the launcher often writes UTF-16). The watch reads it
3
+ // back to notice when the launcher renews it, or when you sign in here the first time.
4
+ import fs from 'node:fs';
5
+ import path from 'node:path';
6
+ import { epicSettingsFile, MAX_EPIC_INI_BYTES, readEpicLogin, withEpicLogin, } from '../../../shared/accounts/index.js';
7
+ import { decodeText, encodeText, readBoundedFile } from '../../../shared/io/index.js';
8
+ import { localAppData } from '../adapter.js';
9
+ function settingsFile() {
10
+ return epicSettingsFile(localAppData());
11
+ }
12
+ export const epicAdapter = {
13
+ kind: 'epic',
14
+ apply(p) {
15
+ const file = settingsFile();
16
+ const bytes = readBoundedFile(file, MAX_EPIC_INI_BYTES);
17
+ const read = bytes ? decodeText(bytes) : { text: '', encoding: 'utf8' };
18
+ fs.mkdirSync(path.dirname(file), { recursive: true });
19
+ fs.writeFileSync(file, encodeText(withEpicLogin(read.text, p), read.encoding));
20
+ return { summary: 'Epic Games Launcher: signed in with your saved sign-in' };
21
+ },
22
+ current() {
23
+ const bytes = readBoundedFile(settingsFile(), MAX_EPIC_INI_BYTES);
24
+ return bytes ? readEpicLogin(decodeText(bytes).text) : null;
25
+ },
26
+ };
@@ -0,0 +1,2 @@
1
+ import { type GuestAdapter } from '../adapter.js';
2
+ export declare const expoAdapter: GuestAdapter<'expo'>;
@@ -0,0 +1,7 @@
1
+ import { notAvailableYet } from '../adapter.js';
2
+ export const expoAdapter = {
3
+ kind: 'expo',
4
+ apply(_p) {
5
+ return notAvailableYet('expo');
6
+ },
7
+ };
@@ -0,0 +1,2 @@
1
+ import { type GuestAdapter } from '../adapter.js';
2
+ export declare const keystoreAdapter: GuestAdapter<'keystore'>;
@@ -0,0 +1,7 @@
1
+ import { notAvailableYet } from '../adapter.js';
2
+ export const keystoreAdapter = {
3
+ kind: 'keystore',
4
+ apply(_p) {
5
+ return notAvailableYet('keystore');
6
+ },
7
+ };
@@ -0,0 +1,2 @@
1
+ import { type GuestAdapter } from '../adapter.js';
2
+ export declare const playAdapter: GuestAdapter<'play'>;
@@ -0,0 +1,7 @@
1
+ import { notAvailableYet } from '../adapter.js';
2
+ export const playAdapter = {
3
+ kind: 'play',
4
+ apply(_p) {
5
+ return notAvailableYet('play');
6
+ },
7
+ };
@@ -0,0 +1,4 @@
1
+ import type { GuestAdapter } from '../adapter.js';
2
+ /** The adapter for a SteamCMD folder (the self-test passes its own). */
3
+ export declare function steamAdapterFor(steamcmdDir: string): GuestAdapter<'steam'>;
4
+ export declare const steamAdapter: GuestAdapter<'steam'>;
@@ -0,0 +1,17 @@
1
+ // Steam: SteamCMD's cached login goes into C:\SteamCMD\config (config.vdf, the account name) and the ssfn sentry files
2
+ // beside steamcmd.exe, on the sandbox's own disk, before the Steam step copies SteamCMD's binaries in (that copy never
3
+ // touches config\). The watch reads it back when SteamCMD renews it, or after a first `sbx-steam login` here.
4
+ import { readSteamCmdLogin, writeSteamCmdLogin } from '../../../shared/accounts/kinds/steam.js';
5
+ import { STEAMCMD_DIR } from '../../toolchains/steam/commands.js';
6
+ /** The adapter for a SteamCMD folder (the self-test passes its own). */
7
+ export function steamAdapterFor(steamcmdDir) {
8
+ return {
9
+ kind: 'steam',
10
+ apply(p) {
11
+ writeSteamCmdLogin(steamcmdDir, p);
12
+ return { summary: 'SteamCMD: signed in as ' + p.account + ' with your saved sign-in' };
13
+ },
14
+ current: () => readSteamCmdLogin(steamcmdDir),
15
+ };
16
+ }
17
+ export const steamAdapter = steamAdapterFor(STEAMCMD_DIR);
@@ -0,0 +1,2 @@
1
+ import { type GuestAdapter } from '../adapter.js';
2
+ export declare const unityAdapter: GuestAdapter<'unity'>;
@@ -0,0 +1,7 @@
1
+ import { notAvailableYet } from '../adapter.js';
2
+ export const unityAdapter = {
3
+ kind: 'unity',
4
+ apply(_p) {
5
+ return notAvailableYet('unity');
6
+ },
7
+ };
@@ -0,0 +1,28 @@
1
+ import { type ServiceKind } from '../../shared/accounts/kinds.js';
2
+ import type { GuestAdapter } from './adapter.js';
3
+ export interface WatchOptions {
4
+ /** The data folder (C:\AgentData); the handoffs go in its state\accounts. */
5
+ readonly dataDir: string;
6
+ readonly launchId: string;
7
+ /** Where delivered.json is (default: the sandbox's accounts folder). */
8
+ readonly root?: string;
9
+ readonly adapters?: {
10
+ readonly [K in ServiceKind]?: GuestAdapter<K>;
11
+ };
12
+ readonly warn?: (line: string) => void;
13
+ }
14
+ export declare class AccountWatch {
15
+ private readonly o;
16
+ private readonly last;
17
+ private readonly timers;
18
+ private readonly kinds;
19
+ constructor(kinds: readonly ServiceKind[], o: WatchOptions);
20
+ private adapter;
21
+ /** The kinds being watched. */
22
+ watched(): readonly ServiceKind[];
23
+ start(): void;
24
+ /** One look at one kind; true when a handoff was written. */
25
+ check(kind: ServiceKind): boolean;
26
+ /** Looks at every kind now; with `final` (the sandbox stops) each adapter also lets go of what it holds. */
27
+ flush(final?: boolean): Promise<void>;
28
+ }
@@ -0,0 +1,78 @@
1
+ // While the sandbox runs: each sign-in that may come back (Epic, Steam, Unity) is looked at every minute or so, and
2
+ // when the tool holds a different one (renewed, or a first sign-in made here) it is left for the PC in
3
+ // <data>\state\accounts\<kind>.json, which the PC seals and deletes on its next sync. Only kinds whose lease this
4
+ // launch holds; seeded with what was delivered, so the first look writes nothing. flush() looks once more now (the
5
+ // daemon calls it where claude-mem is saved) and, at the end, lets go of what must not stay taken.
6
+ import fs from 'node:fs';
7
+ import path from 'node:path';
8
+ import { fingerprint } from '../../shared/accounts/fingerprint.js';
9
+ import { HANDOFF_PARTS, SERVICE_SPECS } from '../../shared/accounts/kinds.js';
10
+ import { writeJsonAtomic } from '../../shared/io/json.js';
11
+ import { errMsg } from '../../core/util/errors.js';
12
+ import { ADAPTERS } from './adapters.js';
13
+ import { readDelivered } from './apply.js';
14
+ const DEFAULT_CHECK_MS = 60_000;
15
+ export class AccountWatch {
16
+ o;
17
+ last = new Map();
18
+ timers = [];
19
+ kinds;
20
+ constructor(kinds, o) {
21
+ this.o = o;
22
+ this.kinds = kinds.filter((k) => SERVICE_SPECS[k].returns && this.adapter(k).current);
23
+ const delivered = readDelivered(o.root);
24
+ for (const kind of this.kinds)
25
+ this.last.set(kind, delivered.fingerprints[kind] ?? null);
26
+ }
27
+ adapter(kind) {
28
+ return (this.o.adapters?.[kind] ?? ADAPTERS[kind]);
29
+ }
30
+ /** The kinds being watched. */
31
+ watched() {
32
+ return this.kinds;
33
+ }
34
+ start() {
35
+ for (const kind of this.kinds) {
36
+ const timer = setInterval(() => this.check(kind), this.adapter(kind).checkMs ?? DEFAULT_CHECK_MS);
37
+ timer.unref();
38
+ this.timers.push(timer);
39
+ }
40
+ }
41
+ /** One look at one kind; true when a handoff was written. */
42
+ check(kind) {
43
+ try {
44
+ const now = this.adapter(kind).current?.() ?? null;
45
+ if (!now)
46
+ return false;
47
+ const print = fingerprint(now);
48
+ if (print === this.last.get(kind))
49
+ return false;
50
+ const file = path.join(this.o.dataDir, ...HANDOFF_PARTS, kind + '.json');
51
+ fs.mkdirSync(path.dirname(file), { recursive: true });
52
+ writeJsonAtomic(file, { kind, launchId: this.o.launchId, payload: now });
53
+ this.last.set(kind, print);
54
+ return true;
55
+ }
56
+ catch (e) {
57
+ this.o.warn?.(SERVICE_SPECS[kind].label + ' sign-in: could not keep it for the next sandbox: ' + errMsg(e));
58
+ return false;
59
+ }
60
+ }
61
+ /** Looks at every kind now; with `final` (the sandbox stops) each adapter also lets go of what it holds. */
62
+ async flush(final = false) {
63
+ for (const kind of this.kinds)
64
+ this.check(kind);
65
+ if (!final)
66
+ return;
67
+ for (const timer of this.timers)
68
+ clearInterval(timer);
69
+ for (const kind of this.kinds) {
70
+ try {
71
+ await this.adapter(kind).release?.();
72
+ }
73
+ catch (e) {
74
+ this.o.warn?.(SERVICE_SPECS[kind].label + ': could not let go of the sign-in: ' + errMsg(e));
75
+ }
76
+ }
77
+ }
78
+ }
@@ -0,0 +1,2 @@
1
+ import type { Download } from './resolvers.js';
2
+ export declare const GAMEDEV_RESOLVERS: Readonly<Record<string, () => Promise<Download>>>;
@@ -0,0 +1 @@
1
+ export const GAMEDEV_RESOLVERS = {};
@@ -0,0 +1,2 @@
1
+ import type { Download } from './resolvers.js';
2
+ export declare const MOBILE_RESOLVERS: Readonly<Record<string, () => Promise<Download>>>;
@@ -0,0 +1 @@
1
+ export const MOBILE_RESOLVERS = {};
@@ -1,6 +1,8 @@
1
1
  // Where the latest version of an app is, for apps that are not a plain GitHub release: each looks it up on the
2
2
  // vendor's own site (and its published checksum, where there is one). Named by AppSource.resolve in shared/apps.ts.
3
3
  import { fetchJson, fetchText, githubAsset, latestGithubTag } from '../../shared/download/index.js';
4
+ import { GAMEDEV_RESOLVERS } from './resolvers-gamedev.js';
5
+ import { MOBILE_RESOLVERS } from './resolvers-mobile.js';
4
6
  /** The SHA-256 on the line of a SHA256SUMS-style file that names `file`. */
5
7
  const sumFor = (sums, file) => sums
6
8
  .split(/\r?\n/)
@@ -10,6 +12,8 @@ const sumFor = (sums, file) => sums
10
12
  const firstHash = (text) => /\b([0-9a-f]{64})\b/i.exec(text)?.[1].toLowerCase() ?? null;
11
13
  const stripV = (tag) => tag.replace(/^v/, '');
12
14
  export const RESOLVERS = {
15
+ ...GAMEDEV_RESOLVERS,
16
+ ...MOBILE_RESOLVERS,
13
17
  sublime: async () => {
14
18
  // Sublime publishes no checksums; the download is HTTPS from sublimetext.com.
15
19
  const { latest_version: build } = await fetchJson('https://www.sublimetext.com/updates/4/stable_update_check');
@@ -6,6 +6,11 @@ export declare class Boot {
6
6
  /** What the host handed over in its one-shot file (read and deleted at the start of run()). */
7
7
  private secrets;
8
8
  run(): Promise<void>;
9
+ /**
10
+ * Your saved service sign-ins (accounts.<kind>.share) go to their tools before anything opens them, and leave memory
11
+ * at once; what they give the agent (EXPO_TOKEN ...) joins its environment (in memory only).
12
+ */
13
+ private serviceAccounts;
9
14
  private networkAndSessionHost;
10
15
  private hooksAndDesktop;
11
16
  /** Toolchains, databases, apps, the network proxy and VS Code; then the agent environment, saved machine-wide. */
@@ -22,6 +22,8 @@ import { applyPersonalization } from '../setup/desktop.js';
22
22
  import { keepBrowsersOffGpu } from '../setup/browser-gpu.js';
23
23
  import { setupGitConfig } from '../setup/git-identity.js';
24
24
  import { loginGithub, prepareGithubFolder } from '../setup/github-token.js';
25
+ import { applyServiceAccounts } from '../accounts/apply.js';
26
+ import { devToolsFor } from '../devtools/registry.js';
25
27
  import { ensurePtyHost } from '../sessions/pty-host.js';
26
28
  import { pruneToolLeftovers } from '../toolchains/leftovers.js';
27
29
  import { wanted } from '../toolchains/detect.js';
@@ -95,8 +97,23 @@ function writeDbCommand() {
95
97
  const db = path.join(path.dirname(process.argv[1]), 'db.js');
96
98
  fs.writeFileSync(path.join(dir, 'sbx-db.cmd'), '@setlocal\r\n@set AGENT_LOG_PREFIX=db\r\n@"' + process.execPath + '" "' + db + '" %*\r\n');
97
99
  writeAgentCommands(dir);
100
+ writeDevToolCommands(dir);
98
101
  return dir;
99
102
  }
103
+ /** sbx-steam, sbx-fivem, sbx-unity, sbx-android for the toolchains that are on: runtime\tool.js with that helper. */
104
+ function writeDevToolCommands(dir) {
105
+ const script = path.join(path.dirname(process.argv[1]), 'tool.js');
106
+ for (const tool of devToolsFor(session.toolchains))
107
+ fs.writeFileSync(path.join(dir, 'sbx-' + tool.name + '.cmd'), '@setlocal\r\n@set AGENT_LOG_PREFIX=' +
108
+ tool.name +
109
+ '\r\n@"' +
110
+ process.execPath +
111
+ '" "' +
112
+ script +
113
+ '" ' +
114
+ tool.name +
115
+ ' %*\r\n');
116
+ }
100
117
  /**
101
118
  * `claude`, `codex` ... by name in every terminal tab, installed yet or not (the command installs the agent on first
102
119
  * use), and `sbx-agent`. Written to the sandbox's disk each boot, next to `sbx-db`.
@@ -146,6 +163,7 @@ export class Boot {
146
163
  mkdirp(toolsDir);
147
164
  mkdirp(run.root);
148
165
  this.secrets = takeSecrets(session.launchId);
166
+ await this.serviceAccounts();
149
167
  applyBootEnvironment(this.secrets.harnessEnvironment);
150
168
  prepareGithubFolder(this.secrets.githubToken);
151
169
  await this.networkAndSessionHost();
@@ -158,6 +176,21 @@ export class Boot {
158
176
  this.preAgentHooks(env);
159
177
  await this.start(env);
160
178
  }
179
+ /**
180
+ * Your saved service sign-ins (accounts.<kind>.share) go to their tools before anything opens them, and leave memory
181
+ * at once; what they give the agent (EXPO_TOKEN ...) joins its environment (in memory only).
182
+ */
183
+ async serviceAccounts() {
184
+ const given = this.secrets.serviceAccounts;
185
+ this.secrets = { ...this.secrets, serviceAccounts: undefined };
186
+ if (dryRun || (!given && !session.accountLeases?.length))
187
+ return;
188
+ await soft('Service sign-ins', async () => {
189
+ const env = await applyServiceAccounts(given, { leased: session.accountLeases ?? [], say: (line) => log(line) });
190
+ if (Object.keys(env).length)
191
+ this.secrets = { ...this.secrets, harnessEnvironment: { ...env, ...this.secrets.harnessEnvironment } };
192
+ });
193
+ }
161
194
  async networkAndSessionHost() {
162
195
  step(1, 'Network and session host');
163
196
  if (isWin && !dryRun && session.attach.enabled)
@@ -186,6 +219,7 @@ export class Boot {
186
219
  refresh: session.provisioning.refresh,
187
220
  databases: session.databases ?? [],
188
221
  apps: session.apps,
222
+ ...(session.pcInstalls ? { pcInstalls: session.pcInstalls } : {}),
189
223
  });
190
224
  for (const p of networkProblems())
191
225
  tools.summary.push('PROTECTION MISSING: ' + p);
@@ -246,10 +280,10 @@ export class Boot {
246
280
  await soft('Claude settings', () => syncClaudeProfile(this.secrets.claudeCredentials));
247
281
  await soft('claude-mem restore', restoreClaudeMem);
248
282
  await soft('Agent files of the last sandbox', resetMachineBound);
283
+ await soft('Codex without its own sandbox', codexWithoutInnerSandbox);
249
284
  await soft('Agent databases restore', restoreLocalState);
250
285
  // Agent add-ons: MCP servers in the sandbox's Claude Code, and the Headroom proxy before the managed settings point
251
286
  // Claude Code at it (the guide reads them back, so it comes last).
252
- await soft('Codex without its own sandbox', codexWithoutInnerSandbox);
253
287
  let headroom = null;
254
288
  await soft('MCP servers from Apps', writeAddonMcpServers);
255
289
  await soft('Headroom proxy', async () => {
@@ -0,0 +1,3 @@
1
+ export declare function startAccountWatch(): void;
2
+ /** Looks once more now; `final` (the sandbox stops) also lets go of what must not stay taken. Never throws. */
3
+ export declare function flushAccounts(final?: boolean): Promise<void>;
@@ -0,0 +1,25 @@
1
+ // The daemon's one watch over the service sign-ins this launch may hand back (session.json accountLeases), and its
2
+ // flush where claude-mem is saved (every 2 minutes, when a session ends, before an idle shutdown).
3
+ import { AccountWatch } from '../accounts/watch.js';
4
+ import { dataDir } from '../runtime/paths.js';
5
+ import { log, warn } from '../runtime/log.js';
6
+ import { session } from '../runtime/session.js';
7
+ let watch = null;
8
+ export function startAccountWatch() {
9
+ const kinds = session.accountLeases ?? [];
10
+ if (!kinds.length)
11
+ return;
12
+ watch = new AccountWatch(kinds, { dataDir, launchId: session.launchId, warn });
13
+ watch.start();
14
+ if (watch.watched().length)
15
+ log('Service sign-ins kept for the next sandbox: ' + watch.watched().join(', '));
16
+ }
17
+ /** Looks once more now; `final` (the sandbox stops) also lets go of what must not stay taken. Never throws. */
18
+ export async function flushAccounts(final = false) {
19
+ try {
20
+ await watch?.flush(final);
21
+ }
22
+ catch (e) {
23
+ warn('service sign-ins: ' + String(e));
24
+ }
25
+ }
@@ -11,6 +11,7 @@ import { withRequestSecrets } from '../runtime/secrets.js';
11
11
  import { liveFolders } from './live.js';
12
12
  import { warn } from '../runtime/log.js';
13
13
  import { errMsg } from '../../core/util/errors.js';
14
+ import { flushAccounts } from './accounts.js';
14
15
  const POLL_MS = 400;
15
16
  const MEM_SAVE_MS = 120000;
16
17
  export class Daemon {
@@ -45,6 +46,7 @@ export class Daemon {
45
46
  this.lastMemSave = Date.now();
46
47
  safely('claude-mem save', saveClaudeMem);
47
48
  safely('agent databases save', saveLocalState);
49
+ void flushAccounts();
48
50
  }
49
51
  }
50
52
  handle(req) {
@@ -8,6 +8,7 @@ import { isWin, run } from '../runtime/paths.js';
8
8
  import { log } from '../runtime/log.js';
9
9
  import { session } from '../runtime/session.js';
10
10
  import { safely } from './state.js';
11
+ import { flushAccounts } from './accounts.js';
11
12
  /** How long the sandbox must stay idle before it shuts down. */
12
13
  const GRACE_MS = 15000;
13
14
  export class IdleShutdown {
@@ -28,7 +29,8 @@ export class IdleShutdown {
28
29
  log('Headless sandbox has no sessions left; shutting down.');
29
30
  safely('claude-mem save', saveClaudeMem);
30
31
  safely('agent databases save', saveLocalState);
31
- spawnSync(SYSTEM.shutdown(), ['/s', '/t', '5'], { windowsHide: true });
32
+ // Renewed sign-ins go to the PC, and a held one (a Unity seat) is let go, before Windows stops.
33
+ void flushAccounts(true).finally(() => spawnSync(SYSTEM.shutdown(), ['/s', '/t', '5'], { windowsHide: true }));
32
34
  }, GRACE_MS);
33
35
  }
34
36
  idle() {
@@ -34,6 +34,7 @@ import { errMsg } from '../../core/util/errors.js';
34
34
  import { provisioner } from './project-provisioner.js';
35
35
  import { IdleShutdown } from './idle-shutdown.js';
36
36
  import { insidePrimary, insideWorkspace, respond, safely, saveStatus } from './state.js';
37
+ import { flushAccounts } from './accounts.js';
37
38
  /** How long a close waits for the session to end before it ends its ptyhost instead. */
38
39
  const CLOSE_WAIT_MS = 8000;
39
40
  /** An ended session's ptyhost is remembered this long: its last programs reach the audit up to 15 s later. */
@@ -457,6 +458,7 @@ export class SessionManager {
457
458
  safely('post-agent hooks', () => runHooks('post-agent', process.env));
458
459
  safely('claude-mem save', saveClaudeMem);
459
460
  safely('agent databases save', saveLocalState);
461
+ void flushAccounts();
460
462
  this.idle.check();
461
463
  }
462
464
  }
@@ -0,0 +1,2 @@
1
+ import { type DevTool } from './devtool.js';
2
+ export declare const androidTool: DevTool;
@@ -0,0 +1,7 @@
1
+ // sbx-android: the SDK, devices, connect to a device over the network. Not available yet.
2
+ import { notAvailableYet } from './devtool.js';
3
+ export const androidTool = {
4
+ name: 'android',
5
+ summary: 'the SDK, devices, connect to a device over the network',
6
+ run: () => notAvailableYet('android'),
7
+ };
@@ -0,0 +1,9 @@
1
+ export type DevToolName = 'steam' | 'fivem' | 'unity' | 'android';
2
+ export interface DevTool {
3
+ readonly name: DevToolName;
4
+ /** One line for its usage and the agent's guide. */
5
+ readonly summary: string;
6
+ run(args: readonly string[]): Promise<number>;
7
+ }
8
+ /** What a helper whose commands are not written yet does. */
9
+ export declare function notAvailableYet(name: DevToolName): Promise<number>;
@@ -0,0 +1,5 @@
1
+ /** What a helper whose commands are not written yet does. */
2
+ export function notAvailableYet(name) {
3
+ console.error('sbx-' + name + ': not available yet.');
4
+ return Promise.resolve(1);
5
+ }
@@ -0,0 +1,2 @@
1
+ import { type DevTool } from './devtool.js';
2
+ export declare const fivemTool: DevTool;
@@ -0,0 +1,7 @@
1
+ // sbx-fivem: start the FiveM / RedM server, pick a server build, make a new resource. Not available yet.
2
+ import { notAvailableYet } from './devtool.js';
3
+ export const fivemTool = {
4
+ name: 'fivem',
5
+ summary: 'start the FiveM / RedM server, pick a server build, make a new resource',
6
+ run: () => notAvailableYet('fivem'),
7
+ };
@@ -0,0 +1,6 @@
1
+ import type { Toolchains } from '../../core/types.js';
2
+ import type { DevTool } from './devtool.js';
3
+ export declare const DEVTOOLS: readonly DevTool[];
4
+ /** The helpers for the toolchains that are on (resolved by the host; "auto" counts as off here). */
5
+ export declare function devToolsFor(t: Toolchains): DevTool[];
6
+ export declare function devToolByName(name: string): DevTool | undefined;
@@ -0,0 +1,12 @@
1
+ import { androidTool } from './android.js';
2
+ import { fivemTool } from './fivem.js';
3
+ import { steamTool } from './steam.js';
4
+ import { unityTool } from './unity.js';
5
+ export const DEVTOOLS = [steamTool, fivemTool, unityTool, androidTool];
6
+ /** The helpers for the toolchains that are on (resolved by the host; "auto" counts as off here). */
7
+ export function devToolsFor(t) {
8
+ return DEVTOOLS.filter((tool) => t[tool.name].enabled === true);
9
+ }
10
+ export function devToolByName(name) {
11
+ return DEVTOOLS.find((t) => t.name === name);
12
+ }
@@ -0,0 +1,2 @@
1
+ import type { DevTool } from './devtool.js';
2
+ export declare const steamTool: DevTool;