rnxsim 0.1.313 → 0.1.314

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 (297) hide show
  1. package/LICENSE +11 -10
  2. package/README.md +5 -0
  3. package/cli/app-config.ts +65 -0
  4. package/cli/app-fonts.ts +408 -0
  5. package/cli/app-project.ts +231 -0
  6. package/cli/app-splash.ts +185 -0
  7. package/cli/app-state-reset.ts +24 -0
  8. package/cli/auth.ts +155 -0
  9. package/cli/bin.ts +594 -0
  10. package/cli/bridge-diagnostics.ts +226 -0
  11. package/cli/bridge-flow-runner.ts +2830 -0
  12. package/cli/browser-evals.ts +96 -0
  13. package/cli/commands/agent-wrapper.ts +986 -0
  14. package/cli/commands/agent.ts +423 -0
  15. package/cli/commands/app-fonts.ts +98 -0
  16. package/cli/commands/assert.ts +541 -0
  17. package/cli/commands/auth.ts +59 -0
  18. package/cli/commands/camera.ts +266 -0
  19. package/cli/commands/cleanup.ts +169 -0
  20. package/cli/commands/compat.ts +87 -0
  21. package/cli/commands/config.ts +32 -0
  22. package/cli/commands/control.ts +2142 -0
  23. package/cli/commands/cpu-profile.ts +269 -0
  24. package/cli/commands/daemon-mac-app.ts +169 -0
  25. package/cli/commands/daemon.ts +874 -0
  26. package/cli/commands/debug.ts +719 -0
  27. package/cli/commands/desktop.ts +39 -0
  28. package/cli/commands/detect.ts +197 -0
  29. package/cli/commands/detox.ts +385 -0
  30. package/cli/commands/device.ts +133 -0
  31. package/cli/commands/diagnose.ts +589 -0
  32. package/cli/commands/electron.ts +95 -0
  33. package/cli/commands/film.ts +379 -0
  34. package/cli/commands/flow.ts +1124 -0
  35. package/cli/commands/inspect/actions.ts +622 -0
  36. package/cli/commands/inspect/core.ts +2405 -0
  37. package/cli/commands/inspect/count.ts +17 -0
  38. package/cli/commands/inspect/describe.ts +192 -0
  39. package/cli/commands/inspect/env.ts +23 -0
  40. package/cli/commands/inspect/find.ts +171 -0
  41. package/cli/commands/inspect/get-layout.ts +39 -0
  42. package/cli/commands/inspect/keyboard.ts +52 -0
  43. package/cli/commands/inspect/list.ts +58 -0
  44. package/cli/commands/inspect/memory.ts +215 -0
  45. package/cli/commands/inspect/redaction.ts +39 -0
  46. package/cli/commands/inspect/resolve-target.ts +82 -0
  47. package/cli/commands/inspect/screens.ts +78 -0
  48. package/cli/commands/inspect/settle.ts +22 -0
  49. package/cli/commands/inspect/settling.ts +158 -0
  50. package/cli/commands/inspect/shared.ts +353 -0
  51. package/cli/commands/inspect/sleep.ts +14 -0
  52. package/cli/commands/inspect/tree.ts +32 -0
  53. package/cli/commands/inspect/url.ts +17 -0
  54. package/cli/commands/inspect/wait-event.ts +210 -0
  55. package/cli/commands/inspect/wait-idle.ts +24 -0
  56. package/cli/commands/inspect/wait-ready.ts +74 -0
  57. package/cli/commands/inspect/wait-selector.ts +54 -0
  58. package/cli/commands/inspect/wait.ts +31 -0
  59. package/cli/commands/inspect.ts +4519 -0
  60. package/cli/commands/install-desktop.ts +351 -0
  61. package/cli/commands/login.ts +331 -0
  62. package/cli/commands/logout.ts +31 -0
  63. package/cli/commands/maestro-generate.ts +361 -0
  64. package/cli/commands/maestro.ts +453 -0
  65. package/cli/commands/mode.ts +57 -0
  66. package/cli/commands/no-bridge-hint.ts +80 -0
  67. package/cli/commands/perf.ts +66 -0
  68. package/cli/commands/permissions.ts +203 -0
  69. package/cli/commands/profile.ts +108 -0
  70. package/cli/commands/react.ts +353 -0
  71. package/cli/commands/record.ts +1434 -0
  72. package/cli/commands/report-issue.ts +305 -0
  73. package/cli/commands/reset.ts +85 -0
  74. package/cli/commands/runtime.ts +351 -0
  75. package/cli/commands/screenshot-command.ts +106 -0
  76. package/cli/commands/screenshot-layers.ts +143 -0
  77. package/cli/commands/screenshot-mode.ts +37 -0
  78. package/cli/commands/screenshot.ts +488 -0
  79. package/cli/commands/screenshots-capture.ts +607 -0
  80. package/cli/commands/screenshots.ts +127 -0
  81. package/cli/commands/serve.ts +168 -0
  82. package/cli/commands/setup.ts +545 -0
  83. package/cli/commands/shell-boolean-mode.ts +81 -0
  84. package/cli/commands/skills.ts +467 -0
  85. package/cli/commands/slides.ts +361 -0
  86. package/cli/commands/state.ts +87 -0
  87. package/cli/commands/storage.ts +58 -0
  88. package/cli/commands/telemetry.ts +54 -0
  89. package/cli/commands/three-mode.ts +763 -0
  90. package/cli/commands/timeline.ts +122 -0
  91. package/cli/commands/upgrade.ts +208 -0
  92. package/cli/commands/upload.ts +1225 -0
  93. package/cli/commands/version.ts +54 -0
  94. package/cli/commands/what-happened.ts +327 -0
  95. package/cli/current-sim.ts +204 -0
  96. package/cli/desktop-companion.ts +300 -0
  97. package/cli/drivers/electron.ts +70 -0
  98. package/cli/drivers/index.ts +20 -0
  99. package/cli/drivers/playwright-provisioning.ts +180 -0
  100. package/cli/drivers/playwright.ts +698 -0
  101. package/cli/drivers/registry.ts +65 -0
  102. package/cli/drivers/types.ts +102 -0
  103. package/cli/flow-file.ts +142 -0
  104. package/cli/flow-live-status.ts +120 -0
  105. package/cli/flow-session.ts +187 -0
  106. package/cli/help.ts +80 -0
  107. package/cli/hidden-runtime-alias.ts +19 -0
  108. package/cli/hints.ts +216 -0
  109. package/cli/inspect-notice-state.ts +114 -0
  110. package/cli/maestro-js.ts +334 -0
  111. package/cli/open-url.ts +8 -0
  112. package/cli/parent-pid.ts +204 -0
  113. package/cli/parse-args.ts +211 -0
  114. package/cli/prompt.ts +51 -0
  115. package/cli/recording-access.ts +107 -0
  116. package/cli/registry.ts +1 -0
  117. package/cli/resolve-assets.ts +63 -0
  118. package/cli/run-registry.ts +226 -0
  119. package/cli/runtime-notes.ts +66 -0
  120. package/cli/runtime-summary.ts +25 -0
  121. package/cli/setup-repository.ts +187 -0
  122. package/cli/telemetry.ts +187 -0
  123. package/cli/ws-bridge.ts +798 -0
  124. package/dist-cli/bin.js +5 -5
  125. package/dist-cli/chunks/{agent-XZ2KTPCU.js → agent-7YBDCYMA.js} +2 -2
  126. package/dist-cli/chunks/{agent-wrapper-JJYYW2WH.js → agent-wrapper-2GHFBHCR.js} +2 -2
  127. package/dist-cli/chunks/{app-fonts-IXRNQG6B.js → app-fonts-RSNVPQSU.js} +2 -2
  128. package/dist-cli/chunks/{assert-54T5SK5F.js → assert-XCMX3XJX.js} +2 -2
  129. package/dist-cli/chunks/{auth-FI5UDI45.js → auth-B442HRAX.js} +2 -2
  130. package/dist-cli/chunks/{beta-JV6UKADW.js → beta-XJ55JK3M.js} +2 -2
  131. package/dist-cli/chunks/camera-UGYSSLIK.js +33 -0
  132. package/dist-cli/chunks/{chunk-3NV2NCNX.js → chunk-277AEQZX.js} +2 -2
  133. package/dist-cli/chunks/{chunk-2YR5BGA5.js → chunk-2JNSK774.js} +2 -2
  134. package/dist-cli/chunks/{chunk-RSZWCKNT.js → chunk-32WOTSTR.js} +3 -3
  135. package/dist-cli/chunks/{chunk-WEXDAC74.js → chunk-3S753SNQ.js} +2 -2
  136. package/dist-cli/chunks/{chunk-IJO63TDP.js → chunk-46ZOLOYA.js} +2 -2
  137. package/dist-cli/chunks/{chunk-WUSWBCWA.js → chunk-5L7ELDQL.js} +8 -9
  138. package/dist-cli/chunks/{chunk-WF3T4SVI.js → chunk-7OOPFSQS.js} +2 -2
  139. package/dist-cli/chunks/{chunk-TZFFR3SD.js → chunk-7SV3RPRW.js} +2 -2
  140. package/dist-cli/chunks/{chunk-WWZIXIRD.js → chunk-7ZC35MOU.js} +1 -1
  141. package/dist-cli/chunks/chunk-AMG5E6CC.js +9 -0
  142. package/dist-cli/chunks/{chunk-WINYQ44O.js → chunk-APWNH3A4.js} +1 -1
  143. package/dist-cli/chunks/chunk-B57XUKY3.js +4 -0
  144. package/dist-cli/chunks/{chunk-YDGQTMQL.js → chunk-C2NL26TD.js} +1 -1
  145. package/dist-cli/chunks/{chunk-NMF2ZMZQ.js → chunk-D2FNUWAB.js} +4 -4
  146. package/dist-cli/chunks/{chunk-YIFT42WN.js → chunk-E5T4XSJ3.js} +2 -2
  147. package/dist-cli/chunks/{chunk-46EUUFJ5.js → chunk-EAC34EQS.js} +1 -1
  148. package/dist-cli/chunks/{chunk-OVFJFXUD.js → chunk-EG32ML36.js} +2 -2
  149. package/dist-cli/chunks/{chunk-5YJCOWCH.js → chunk-FXUAC6D5.js} +1 -1
  150. package/dist-cli/chunks/chunk-GQSL4USA.js +6 -0
  151. package/dist-cli/chunks/{chunk-VFCMSYZK.js → chunk-HAXW27SS.js} +2 -2
  152. package/dist-cli/chunks/{chunk-2D2UPBBR.js → chunk-IZAHPAN6.js} +1 -1
  153. package/dist-cli/chunks/{chunk-7GN3LVWB.js → chunk-J62KM5TB.js} +2 -2
  154. package/dist-cli/chunks/{chunk-BTWORNNG.js → chunk-JEMCD5E4.js} +1 -1
  155. package/dist-cli/chunks/{chunk-DCEMHR2Y.js → chunk-JZS3Q37N.js} +2 -2
  156. package/dist-cli/chunks/{chunk-D4FFVGI5.js → chunk-KR4JON7D.js} +1 -1
  157. package/dist-cli/chunks/chunk-KWCYKQIQ.js +4 -0
  158. package/dist-cli/chunks/{chunk-VNQEB4L7.js → chunk-MCWPL644.js} +2 -2
  159. package/dist-cli/chunks/chunk-MJYK3N2I.js +4 -0
  160. package/dist-cli/chunks/{chunk-5TEF3ET3.js → chunk-O6TRIZNS.js} +2 -2
  161. package/dist-cli/chunks/{chunk-QKDWYITG.js → chunk-P7XL2E73.js} +3 -3
  162. package/dist-cli/chunks/{chunk-BBULZ7CG.js → chunk-PFQTUKQ4.js} +62 -87
  163. package/dist-cli/chunks/{chunk-GGRX24GF.js → chunk-PG5RZCTN.js} +2 -2
  164. package/dist-cli/chunks/{chunk-W6K4EFPH.js → chunk-QGRI2Z4M.js} +2 -2
  165. package/dist-cli/chunks/{chunk-ZMJD5GEC.js → chunk-QLXXE7GE.js} +1 -1
  166. package/dist-cli/chunks/{chunk-VZXWHRUZ.js → chunk-QOJJJWJE.js} +89 -133
  167. package/dist-cli/chunks/{chunk-OZSSI4WN.js → chunk-RWZY5427.js} +2 -2
  168. package/dist-cli/chunks/{chunk-UC6U3MML.js → chunk-RZKU2K3J.js} +2 -2
  169. package/dist-cli/chunks/{chunk-IJ5CAZZC.js → chunk-SBV4IK4H.js} +1 -1
  170. package/dist-cli/chunks/{chunk-DZS6WPUI.js → chunk-SGMVFFMK.js} +1 -1
  171. package/dist-cli/chunks/{chunk-OHAZNXLK.js → chunk-TAX4UT2N.js} +1 -1
  172. package/dist-cli/chunks/{chunk-5DHC6KHQ.js → chunk-TUOFAWXT.js} +1 -1
  173. package/dist-cli/chunks/{chunk-GASE6UBA.js → chunk-UHZLOHGP.js} +1 -1
  174. package/dist-cli/chunks/{chunk-F5ZRSS3C.js → chunk-VC7V76U3.js} +1 -1
  175. package/dist-cli/chunks/{chunk-RTN5C5RL.js → chunk-VQVMLW4U.js} +1 -1
  176. package/dist-cli/chunks/{chunk-WMIIKMGK.js → chunk-VUKKYPZN.js} +2 -2
  177. package/dist-cli/chunks/{chunk-5TPRP5QT.js → chunk-WGGRJDRE.js} +1 -1
  178. package/dist-cli/chunks/chunk-X6H76EKP.js +15 -0
  179. package/dist-cli/chunks/chunk-XLZ5FNRT.js +27 -0
  180. package/dist-cli/chunks/{chunk-HI5TFJWN.js → chunk-XULEACM4.js} +2 -2
  181. package/dist-cli/chunks/{chunk-MJRLLB4R.js → chunk-YFSDM7AX.js} +4 -4
  182. package/dist-cli/chunks/chunk-YWI3UEVX.js +5 -0
  183. package/dist-cli/chunks/{chunk-XEVZYVIW.js → chunk-ZBSJO4NB.js} +10 -9
  184. package/dist-cli/chunks/{cleanup-P27PA6JI.js → cleanup-EYLGCA6Z.js} +2 -2
  185. package/dist-cli/chunks/cli-version-LL2UGIHE.js +4 -0
  186. package/dist-cli/chunks/{compat-ZD65FED3.js → compat-TLJYHB4E.js} +2 -2
  187. package/dist-cli/chunks/{config-XMJRNM2A.js → config-4JWUOEXK.js} +2 -2
  188. package/dist-cli/chunks/{control-KMIQT3QP.js → control-HPAOYF4N.js} +2 -2
  189. package/dist-cli/chunks/daemon-OYLASXLE.js +4 -0
  190. package/dist-cli/chunks/{debug-PT4HOP7N.js → debug-4BKXF6KI.js} +5 -5
  191. package/dist-cli/chunks/{desktop-S3FG72AK.js → desktop-ZQ6ZD2S6.js} +3 -3
  192. package/dist-cli/chunks/{detox-B3D4IFCN.js → detox-WNPASSS3.js} +2 -2
  193. package/dist-cli/chunks/{device-XBNDSB2R.js → device-BXLXVG3V.js} +2 -2
  194. package/dist-cli/chunks/{diagnose-HMQXJE5N.js → diagnose-3QX7W5RW.js} +2 -2
  195. package/dist-cli/chunks/{disk-cleanup-BLCZ5BSZ.js → disk-cleanup-KSWKI7WB.js} +2 -2
  196. package/dist-cli/chunks/drivers-EPIEFF7P.js +4 -0
  197. package/dist-cli/chunks/{film-BJGTBYZB.js → film-GDMR33VO.js} +3 -3
  198. package/dist-cli/chunks/flow-NKMPBYCJ.js +4 -0
  199. package/dist-cli/chunks/help-OGCBHOKA.js +4 -0
  200. package/dist-cli/chunks/{hidden-runtime-alias-ANOYADHM.js → hidden-runtime-alias-S2GTDX3T.js} +2 -2
  201. package/dist-cli/chunks/home-paths-QRCDLTTV.js +4 -0
  202. package/dist-cli/chunks/inspect-FUYMOZPY.js +4 -0
  203. package/dist-cli/chunks/install-desktop-FR6YKW7Y.js +4 -0
  204. package/dist-cli/chunks/{login-FJ737MWG.js → login-IJAPUZHI.js} +4 -4
  205. package/dist-cli/chunks/{logout-ZCNMMHMY.js → logout-QMXDFU2X.js} +2 -2
  206. package/dist-cli/chunks/{maestro-SZTNKLDF.js → maestro-ZXU3YCVX.js} +3 -3
  207. package/dist-cli/chunks/{maestro-generate-DCFAIZ4H.js → maestro-generate-PYB5QY7K.js} +3 -3
  208. package/dist-cli/chunks/{mode-GRMQCRXR.js → mode-WGUCL5FZ.js} +2 -2
  209. package/dist-cli/chunks/{optional-demo-registry-W36EWFFB.js → optional-demo-registry-WH2O6H36.js} +2 -2
  210. package/dist-cli/chunks/{perf-QYBAAUZG.js → perf-TOD3UFAH.js} +2 -2
  211. package/dist-cli/chunks/{permissions-3QCQ6VF4.js → permissions-I5BRJGTB.js} +2 -2
  212. package/dist-cli/chunks/{record-QPPC2S4E.js → record-ZYL2FYSK.js} +3 -3
  213. package/dist-cli/chunks/{report-issue-7NMFP4HK.js → report-issue-TAI6DYZO.js} +2 -2
  214. package/dist-cli/chunks/reset-7YGYKQPQ.js +4 -0
  215. package/dist-cli/chunks/runtime-B4JO6QRI.js +4 -0
  216. package/dist-cli/chunks/{screenshot-command-67AECJFB.js → screenshot-command-7ANLODZY.js} +7 -7
  217. package/dist-cli/chunks/{screenshot-layers-ASWBYPJL.js → screenshot-layers-A7FYXSVU.js} +3 -3
  218. package/dist-cli/chunks/{screenshots-capture-PXA3HFQK.js → screenshots-capture-WT2ZY6CB.js} +2 -2
  219. package/dist-cli/chunks/serve-TG5WKA4V.js +44 -0
  220. package/dist-cli/chunks/{setup-7DWPMRSB.js → setup-PCWLD22V.js} +2 -2
  221. package/dist-cli/chunks/{skills-S3Y22TUA.js → skills-27ZHWCQS.js} +2 -2
  222. package/dist-cli/chunks/state-ZQVY46ZO.js +14 -0
  223. package/dist-cli/chunks/{storage-XUIMJWAJ.js → storage-OYC57C4X.js} +6 -6
  224. package/dist-cli/chunks/store-32HSPZHI.js +4 -0
  225. package/dist-cli/chunks/telemetry-PBJR7XHR.js +4 -0
  226. package/dist-cli/chunks/{timeline-TMPLQPSP.js → timeline-RAJJFQT6.js} +2 -2
  227. package/dist-cli/chunks/{upgrade-7HDSIM7K.js → upgrade-OEFNZRIP.js} +2 -2
  228. package/dist-cli/chunks/upload-LQJITLKK.js +4 -0
  229. package/dist-cli/chunks/version-NIXTY6PL.js +6 -0
  230. package/dist-cli/chunks/{web-DG3WBYD3.js → web-XBUTBVGR.js} +2 -2
  231. package/dist-cli/chunks/{what-happened-XFVUTZR7.js → what-happened-YNHRFUDX.js} +3 -3
  232. package/dist-lib/agent-daemon-client.cjs +1 -1
  233. package/dist-lib/agent-events.cjs +1 -1
  234. package/dist-lib/agent-identity.cjs +1 -1
  235. package/dist-lib/agent-sessions.cjs +1 -1
  236. package/dist-lib/attached-projects.cjs +1 -1
  237. package/dist-lib/auth/shared-session.cjs +1 -1
  238. package/dist-lib/backend-origin.cjs +1 -1
  239. package/dist-lib/beta.cjs +1 -1
  240. package/dist-lib/beta.mjs +1 -1
  241. package/dist-lib/bridge-constants.cjs +1 -1
  242. package/dist-lib/bridge-contract.cjs +20 -0
  243. package/dist-lib/cli-constants.cjs +1 -1
  244. package/dist-lib/config.cjs +1 -1
  245. package/dist-lib/detox/index.cjs +1 -1
  246. package/dist-lib/dev-bundle-resolution.cjs +1 -1
  247. package/dist-lib/home-paths.cjs +67 -28
  248. package/dist-lib/host/bridge-host.cjs +140 -12
  249. package/dist-lib/host/fetch-proxy-handler.cjs +1 -1
  250. package/dist-lib/host/fetch-proxy-overrides.cjs +1 -1
  251. package/dist-lib/host/fetch-proxy-overrides.mjs +1 -1
  252. package/dist-lib/host/websocket-proxy.cjs +1 -1
  253. package/dist-lib/index.cjs +2815 -40
  254. package/dist-lib/jump-to-source-babel.cjs +1 -1
  255. package/dist-lib/menu.cjs +1 -1
  256. package/dist-lib/menu.mjs +1 -1
  257. package/dist-lib/metro.cjs +1 -1
  258. package/dist-lib/profiles.cjs +1 -1
  259. package/dist-lib/public-brand.cjs +1 -1
  260. package/dist-lib/render-mode.cjs +1 -1
  261. package/dist-lib/scripts/dev-server-scanner.cjs +1 -1
  262. package/dist-lib/sdk.cjs +2549 -2061
  263. package/dist-lib/sdk.mjs +2543 -2061
  264. package/dist-lib/skills.cjs +480 -280
  265. package/dist-lib/vite.cjs +1 -1
  266. package/package.json +8 -2
  267. package/src/bridge-constants.ts +3 -4
  268. package/src/bridge-contract.ts +251 -0
  269. package/src/connect.ts +83 -0
  270. package/src/disk-cleanup.ts +30 -0
  271. package/src/home-paths.ts +81 -38
  272. package/src/host/bridge-host.ts +134 -6
  273. package/src/index.ts +27 -1
  274. package/src/sdk.ts +8 -0
  275. package/src/sim-client.ts +660 -0
  276. package/dist-cli/chunks/camera-VL73YIKP.js +0 -22
  277. package/dist-cli/chunks/chunk-4NPPOV2N.js +0 -5
  278. package/dist-cli/chunks/chunk-FSUYIVJ6.js +0 -9
  279. package/dist-cli/chunks/chunk-G2WW6L2C.js +0 -23
  280. package/dist-cli/chunks/chunk-KTHV3RUS.js +0 -26
  281. package/dist-cli/chunks/chunk-LF2ZVT7O.js +0 -6
  282. package/dist-cli/chunks/chunk-NFK7T35W.js +0 -4
  283. package/dist-cli/chunks/chunk-TIVZIMMW.js +0 -4
  284. package/dist-cli/chunks/cli-version-WWLPBDQ7.js +0 -4
  285. package/dist-cli/chunks/daemon-G2ME7NLB.js +0 -4
  286. package/dist-cli/chunks/drivers-LDECZGP2.js +0 -4
  287. package/dist-cli/chunks/flow-UEQNVTU7.js +0 -4
  288. package/dist-cli/chunks/help-T5FYSVGB.js +0 -4
  289. package/dist-cli/chunks/home-paths-GT3LFNOR.js +0 -4
  290. package/dist-cli/chunks/inspect-ZA6XF5LD.js +0 -4
  291. package/dist-cli/chunks/install-desktop-TIMUDHPL.js +0 -4
  292. package/dist-cli/chunks/runtime-XOAXMSTU.js +0 -4
  293. package/dist-cli/chunks/serve-BI2NBAXG.js +0 -44
  294. package/dist-cli/chunks/store-JTHEJLAZ.js +0 -4
  295. package/dist-cli/chunks/telemetry-ZYJGD2DB.js +0 -4
  296. package/dist-cli/chunks/upload-GMSZPWM6.js +0 -4
  297. package/dist-cli/chunks/version-HOCHZ37L.js +0 -6
@@ -0,0 +1,127 @@
1
+ import { runScreenshotsPlan } from '../../src/screenshots/orchestrate'
2
+ import { fetchOrgDeckFrames, type OrgDeckFrame } from '../../src/screenshots/org-deck'
3
+ import { authHeaderValue, resolveCliAuth } from '../auth'
4
+
5
+ interface RunScreenshotsOptions {
6
+ port?: number
7
+ verbose?: boolean
8
+ }
9
+
10
+ export async function runScreenshots(
11
+ args: string[],
12
+ _opts: RunScreenshotsOptions = {},
13
+ ): Promise<number> {
14
+ if (args.includes('--help') || args.includes('-h')) {
15
+ console.log(`
16
+ rnxsim screenshot appstore — capture and compose app-store screenshot sets
17
+
18
+ usage:
19
+ rnxsim screenshot appstore --plan <plan.yaml> [options]
20
+
21
+ options:
22
+ --plan <path> screenshot plan yaml
23
+ --sim <id> reuse a live sim for capture
24
+ --app <target> override plan app target (port, url, or shell url)
25
+ --device <model> override plan capture device for this run
26
+ --org <slug> overlay copy/colors from a team's org screenshot deck
27
+ --repo <name> repo for --org (both required to pull the org deck)
28
+ --api-origin <url> contrast origin to fetch the deck from (default: the
29
+ signed-in session origin, else https://contrast.dev)
30
+ --capture-only stop after raw/framed intermediates
31
+ --compose-only skip flow capture, reuse existing raw screenshots
32
+
33
+ examples:
34
+ rnxsim screenshot appstore --plan app-store.yaml
35
+ rnxsim screenshot appstore --plan app-store.yaml --sim a9
36
+ rnxsim screenshot appstore --plan app-store.yaml --org acme --repo mobile
37
+ `)
38
+ return 0
39
+ }
40
+
41
+ const getFlag = (name: string) => args.find((_, i) => args[i - 1] === name)
42
+ const consumedValueFlags = new Set([
43
+ '--plan',
44
+ '--sim',
45
+ '--app',
46
+ '--device',
47
+ '--org',
48
+ '--repo',
49
+ '--api-origin',
50
+ ])
51
+ const positional = args.filter((arg, index) => {
52
+ if (arg.startsWith('-')) return false
53
+ const previous = args[index - 1]
54
+ return !previous || !consumedValueFlags.has(previous)
55
+ })
56
+ const planPath = getFlag('--plan') || positional[0]
57
+ if (!planPath) {
58
+ console.error(' error: screenshots plan path is required (`--plan <path>`).')
59
+ return 1
60
+ }
61
+
62
+ const simId = getFlag('--sim')?.trim() || null
63
+ const appTarget = getFlag('--app')?.trim() || null
64
+ const deviceModel = getFlag('--device')?.trim() || null
65
+ const org = getFlag('--org')?.trim() || null
66
+ const repo = getFlag('--repo')?.trim() || null
67
+ const apiOrigin = getFlag('--api-origin')?.trim() || null
68
+ const captureOnly = args.includes('--capture-only')
69
+ const composeOnly = args.includes('--compose-only')
70
+
71
+ let orgDeckFrames: OrgDeckFrame[] | null = null
72
+ if (org || repo) {
73
+ if (!org || !repo) {
74
+ console.error(' error: --org and --repo must be passed together.')
75
+ return 1
76
+ }
77
+ const auth = resolveCliAuth()
78
+ if (!auth) {
79
+ console.error(
80
+ ' error: --org/--repo needs auth — run `rnxsim login` or set RNX_API_KEY.',
81
+ )
82
+ return 1
83
+ }
84
+ const origin =
85
+ apiOrigin || (auth.kind === 'session' ? auth.origin : 'https://contrast.dev')
86
+ try {
87
+ orgDeckFrames = await fetchOrgDeckFrames({
88
+ org,
89
+ repo,
90
+ origin,
91
+ authHeader: authHeaderValue(auth),
92
+ })
93
+ } catch (err) {
94
+ console.error(` ${(err as Error).message}`)
95
+ return 1
96
+ }
97
+ if (!orgDeckFrames || orgDeckFrames.length === 0) {
98
+ console.log(
99
+ ` note: no org deck for ${org}/${repo} — composing with the plan's copy/colors.`,
100
+ )
101
+ } else {
102
+ console.log(` org deck: ${orgDeckFrames.length} slide(s) from ${org}/${repo}`)
103
+ }
104
+ }
105
+
106
+ try {
107
+ const result = await runScreenshotsPlan(planPath, {
108
+ simId,
109
+ appTarget,
110
+ deviceModel,
111
+ captureOnly,
112
+ composeOnly,
113
+ orgDeckFrames,
114
+ })
115
+ console.log(` capture manifest: ${result.capture.manifestPath}`)
116
+ if (result.compose) {
117
+ console.log(` compose manifest: ${result.compose.manifestPath}`)
118
+ console.log(` exports: ${result.compose.outputs.length}`)
119
+ } else {
120
+ console.log(' compose skipped')
121
+ }
122
+ return 0
123
+ } catch (err) {
124
+ console.error(` screenshots failed: ${(err as Error).message}`)
125
+ return 1
126
+ }
127
+ }
@@ -0,0 +1,168 @@
1
+ // sootsim serve — foreground bridge host
2
+ //
3
+ // hosts the WS bridge + runtime HTTP server on port 7668 (or --port) so
4
+ // CLI commands and electron windows both work against one bridge. sims
5
+ // connect over ws to register themselves; cli clients connect to drive
6
+ // them; electron fetches renderer assets over http from the same port.
7
+ //
8
+ // run in the foreground (ctrl-c to stop). the persistent launchd/systemd
9
+ // daemon installation is handled by `sootsim setup`.
10
+
11
+ import { DEFAULT_SOOTSIM_BRIDGE_PORT } from '../../src/bridge-constants'
12
+ import {
13
+ ensureSootsimHome,
14
+ isDaemonLockfileFresh,
15
+ readDaemonLockfile,
16
+ } from '../../src/home-paths'
17
+ import { SootSimBridgeHost } from '../../src/host/bridge-host'
18
+ import { flushCliTelemetry, trackCliEvent } from '../telemetry'
19
+ import { resolveDefaultUploadOrigin } from './upload'
20
+
21
+ // launchd sets `XPC_SERVICE_NAME` to the agent label and systemd sets
22
+ // `INVOCATION_ID` for unit-managed processes. either tells us this bridge
23
+ // boot is the daemon firing rather than a user running `sootsim serve`
24
+ // in a terminal — useful for filtering daemon traffic in posthog.
25
+ //
26
+ function runningUnderDaemon(): boolean {
27
+ const xpc = process.env.XPC_SERVICE_NAME || ''
28
+ if (xpc.includes('dev.sootsim.daemon')) return true
29
+ if (process.env.INVOCATION_ID) return true
30
+ return false
31
+ }
32
+
33
+ interface ServeOptions {
34
+ port?: number
35
+ }
36
+
37
+ export async function runServe(args: string[], opts: ServeOptions = {}) {
38
+ if (args.includes('--help') || args.includes('-h')) {
39
+ console.log(`
40
+ rnxsim serve — run the rnx bridge in the foreground
41
+
42
+ hosts the WS bridge that CLI commands talk to. once running, any rnx
43
+ renderer (browser, electron, headless playwright) that connects to port 7668
44
+ becomes drivable from 'rnxsim describe', 'rnxsim do tap', etc.
45
+
46
+ usage:
47
+ rnxsim serve [options]
48
+
49
+ options:
50
+ --port <n> bridge port (defaults to ${DEFAULT_SOOTSIM_BRIDGE_PORT})
51
+ --quiet suppress per-connection logging
52
+
53
+ examples:
54
+ rnxsim serve
55
+ rnxsim serve --port 7668 --quiet
56
+ `)
57
+ process.exit(0)
58
+ }
59
+
60
+ const portArgIdx = args.indexOf('--port')
61
+ const port =
62
+ portArgIdx >= 0 && args[portArgIdx + 1]
63
+ ? Number(args[portArgIdx + 1])
64
+ : (opts.port ?? DEFAULT_SOOTSIM_BRIDGE_PORT)
65
+ if (Number.isNaN(port)) {
66
+ console.error(` invalid --port value: ${args[portArgIdx + 1]}`)
67
+ process.exit(1)
68
+ }
69
+ const quiet = args.includes('--quiet') || args.includes('-q')
70
+
71
+ // only one bridge per sootsim home. refuse to start a second one
72
+ // regardless of requested port, since both would try to write the same
73
+ // daemon.json and electron/cli clients only read one lockfile.
74
+ const existingLock = readDaemonLockfile()
75
+ if (existingLock && isDaemonLockfileFresh(existingLock)) {
76
+ console.error(
77
+ ` an rnx bridge is already running (pid ${existingLock.pid}, port ${existingLock.bridgePort})`,
78
+ )
79
+ console.error(` stop it with 'rnxsim daemon stop' first`)
80
+ process.exit(1)
81
+ }
82
+
83
+ ensureSootsimHome()
84
+ // resolve the contrast origin the same way uploads do (probe a local
85
+ // :3000 stack, else prod) so served runtimes talk auth/billing/preview
86
+ // to the same origin the CLI's own entitlement + upload paths use.
87
+ const contrastOrigin = await resolveDefaultUploadOrigin()
88
+ const host = new SootSimBridgeHost({
89
+ port,
90
+ writeLockfile: true,
91
+ contrastOrigin,
92
+ })
93
+ const boundPort = await host.startAsync({ silent: quiet })
94
+
95
+ const started = Date.now()
96
+ const log = (line: string) => {
97
+ if (quiet) return
98
+ process.stdout.write(`${line}\n`)
99
+ }
100
+
101
+ const lastSimIds = new Set<string>()
102
+ const tickInterval = setInterval(() => {
103
+ const sims = host.listSims()
104
+ const currentIds = new Set(sims.map((b) => b.id))
105
+ for (const b of sims) {
106
+ if (!lastSimIds.has(b.id)) {
107
+ const label = b.title || b.url || b.origin || '(unknown)'
108
+ log(` + ${b.id} ${label}`)
109
+ }
110
+ }
111
+ for (const id of lastSimIds) {
112
+ if (!currentIds.has(id)) log(` - ${id}`)
113
+ }
114
+ lastSimIds.clear()
115
+ for (const id of currentIds) lastSimIds.add(id)
116
+ }, 500)
117
+
118
+ // single boot heartbeat so we know the bridge is alive on this machine.
119
+ // not periodic — frequency would pollute posthog volumes for no signal.
120
+ // explicitly flush: this process pins the event loop with a never-
121
+ // resolving promise (line 155), so beforeExit will not fire and the
122
+ // event would otherwise sit in the queue until SIGTERM dropped it.
123
+ trackCliEvent({
124
+ event: 'daemon_heartbeat',
125
+ properties: {
126
+ bridge_port: boundPort,
127
+ under_daemon: runningUnderDaemon(),
128
+ platform: process.platform,
129
+ subsource: 'daemon',
130
+ },
131
+ })
132
+ void flushCliTelemetry()
133
+
134
+ log(`rnx bridge listening on ws://localhost:${boundPort} (runtime http on same port)`)
135
+ if (boundPort !== port) {
136
+ log(` (preferred port ${port} was taken — fell back to ${boundPort})`)
137
+ }
138
+ log(` ready for browser, electron, or headless playwright sims to connect`)
139
+ log(` (ctrl-c to stop)`)
140
+
141
+ const shutdown = async (signal: NodeJS.Signals) => {
142
+ clearInterval(tickInterval)
143
+ log(
144
+ `\n ${signal} received — shutting down after ${Math.round((Date.now() - started) / 1000)}s`,
145
+ )
146
+ try {
147
+ await host.close()
148
+ } catch {}
149
+ process.exit(0)
150
+ }
151
+ process.on('SIGINT', () => shutdown('SIGINT'))
152
+ process.on('SIGTERM', () => shutdown('SIGTERM'))
153
+ // closing the terminal that spawned us sends SIGHUP — treat it like a
154
+ // clean shutdown so the lockfile doesn't linger.
155
+ process.on('SIGHUP', () => shutdown('SIGHUP'))
156
+ // last-ditch lockfile cleanup on any synchronous exit path. the
157
+ // close() call above is async so we can't await it here, but removing
158
+ // the lockfile is cheap + idempotent.
159
+ process.on('exit', () => {
160
+ try {
161
+ host.removeLockfile()
162
+ } catch {}
163
+ })
164
+
165
+ // keep the event loop alive even if ws/http servers all close — we want
166
+ // the process to live until an explicit signal.
167
+ await new Promise<never>(() => {})
168
+ }