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,31 @@
1
+ import {
2
+ clearSharedDesktopAuthSession,
3
+ readSharedDesktopAuthSession,
4
+ } from '../../src/auth/shared-session'
5
+ import { flushCliTelemetry, trackCliEvent } from '../telemetry'
6
+
7
+ export async function runLogout() {
8
+ const current = readSharedDesktopAuthSession()
9
+ if (!current?.token) {
10
+ console.log(' not signed in')
11
+ return
12
+ }
13
+
14
+ try {
15
+ await fetch(`${current.origin.replace(/\/$/, '')}/api/auth/sign-out`, {
16
+ method: 'POST',
17
+ headers: { authorization: `Bearer ${current.token}` },
18
+ })
19
+ } catch {
20
+ // best-effort only
21
+ }
22
+
23
+ clearSharedDesktopAuthSession()
24
+ trackCliEvent({
25
+ event: 'cli_logout',
26
+ identity: { userId: current.user?.id ?? null },
27
+ properties: { origin: current.origin },
28
+ })
29
+ await flushCliTelemetry()
30
+ console.log(' signed out')
31
+ }
@@ -0,0 +1,361 @@
1
+ // plain-language Maestro authoring for `sootsim maestro generate`.
2
+
3
+ import { mkdtempSync, writeFileSync } from 'fs'
4
+ import { tmpdir } from 'os'
5
+ import { join } from 'path'
6
+ import yaml from 'yaml'
7
+ import { authHeaderValue, resolveCliAuth } from '../auth'
8
+ import { registerRun, stepSummaryFromTrace } from '../run-registry'
9
+ import { createBridgeFromParsed, parseBridgeCliArgs } from '../ws-bridge'
10
+ import { inspectDescribe } from './inspect/core'
11
+ import { resolveDefaultUploadOrigin } from './upload'
12
+
13
+ const DEFAULT_TEST_MODEL = process.env.SOOTSIM_TEST_MODEL || 'deepseek-v4-flash'
14
+ const DESCRIBE_CONTEXT_LIMIT = 18_000
15
+ const LLM_TIMEOUT_MS = 180_000
16
+
17
+ function flagValue(args: string[], name: string): string | undefined {
18
+ const index = args.indexOf(name)
19
+ return index >= 0 ? args[index + 1] : undefined
20
+ }
21
+
22
+ function flagValueAny(args: string[], names: string[]): string | undefined {
23
+ for (const name of names) {
24
+ const value = flagValue(args, name)
25
+ if (value) return value
26
+ }
27
+ return undefined
28
+ }
29
+
30
+ const VALUE_FLAGS = new Set([
31
+ '--origin',
32
+ '--preview-origin',
33
+ '--public-origin',
34
+ '--preview-public-origin',
35
+ '--owner',
36
+ '--repo',
37
+ '--url',
38
+ '--driver',
39
+ '--sim',
40
+ '--device',
41
+ '--slow',
42
+ '--tail-wait',
43
+ '--remap',
44
+ '--replace',
45
+ ])
46
+
47
+ function findPrompt(args: string[]): { prompt: string; index: number } | null {
48
+ for (let i = 0; i < args.length; i++) {
49
+ const arg = args[i]
50
+ if (!arg) continue
51
+ if (VALUE_FLAGS.has(arg)) {
52
+ i += 1
53
+ continue
54
+ }
55
+ if (arg.startsWith('-')) continue
56
+ return { prompt: arg, index: i }
57
+ }
58
+ return null
59
+ }
60
+
61
+ function stripPromptForBridge(args: string[], promptIndex: number): string[] {
62
+ return args.filter((_, index) => index !== promptIndex)
63
+ }
64
+
65
+ async function describeCurrentSim(args: string[], promptIndex: number): Promise<string> {
66
+ const bridgeArgs = stripPromptForBridge(args, promptIndex)
67
+ const parsedBridgeArgs = parseBridgeCliArgs(bridgeArgs, {
68
+ stripBooleanFlags: [
69
+ '--new',
70
+ '--headless',
71
+ '--headed',
72
+ '--electron',
73
+ '--preview-open',
74
+ ],
75
+ stripValueFlags: [...VALUE_FLAGS],
76
+ })
77
+ const bridge = createBridgeFromParsed(parsedBridgeArgs)
78
+ try {
79
+ const describe = await inspectDescribe(bridge, {
80
+ describe: true,
81
+ verbose: false,
82
+ filter: '',
83
+ compact: true,
84
+ hideXy: true,
85
+ })
86
+ const parts = [
87
+ describe.shell ? `shell: ${JSON.stringify(describe.shell)}` : '',
88
+ describe.keyboard ? `keyboard: ${JSON.stringify(describe.keyboard)}` : '',
89
+ typeof describe.nodeCount === 'number' ? `nodes: ${describe.nodeCount}` : '',
90
+ describe.tree || '',
91
+ ].filter(Boolean)
92
+ const text = parts.join('\n')
93
+ return text.length > DESCRIBE_CONTEXT_LIMIT
94
+ ? text.slice(0, DESCRIBE_CONTEXT_LIMIT) + '\n[tree truncated]'
95
+ : text
96
+ } finally {
97
+ bridge.close()
98
+ }
99
+ }
100
+
101
+ const SOOTSIM_TEST_SYSTEM_PROMPT = `
102
+ You write Maestro-compatible rnx YAML flows from a user's plain-language test goal.
103
+ Return only JSON, no markdown, with this exact shape:
104
+ {"summary":"short human-readable result goal","steps":[{"waitFor":{"text":"...","timeout":10000}}]}
105
+
106
+ Use only these flow commands:
107
+ - waitFor: { "text"?: string, "id"?: string, "timeout"?: number }
108
+ - assertVisible: string or { "text"?: string, "id"?: string }
109
+ - assertNotVisible: string or { "text"?: string, "id"?: string }
110
+ - tapOn: string or { "text"?: string, "id"?: string, "index"?: number }
111
+ - inputText: string
112
+ - pressKey: string
113
+ - hideKeyboard: true
114
+ - swipe: { "direction": "UP" | "DOWN" | "LEFT" | "RIGHT", "duration"?: number }
115
+ - waitForAnimationToEnd: true
116
+ - takeScreenshot: "label"
117
+
118
+ Prefer ids/testIDs from the tree. Prefer visible text when no id exists.
119
+ Do not invent app-specific data that is not visible. Keep the flow short.
120
+ End with an assertion or wait that proves the user's goal.
121
+ `.trim()
122
+
123
+ function buildPromptRequest(prompt: string, describe: string): string {
124
+ return `
125
+ User goal:
126
+ ${prompt}
127
+
128
+ Current rnx visible tree:
129
+ ${describe || '[no tree available]'}
130
+
131
+ Generate the shortest replayable flow that verifies the goal from this current state.
132
+ `.trim()
133
+ }
134
+
135
+ async function generateFlowJson(args: {
136
+ prompt: string
137
+ describe: string
138
+ origin: string
139
+ authHeader: string
140
+ }): Promise<string> {
141
+ const res = await fetch(`${args.origin.replace(/\/$/, '')}/api/llm`, {
142
+ method: 'POST',
143
+ headers: {
144
+ 'content-type': 'application/json',
145
+ authorization: args.authHeader,
146
+ },
147
+ body: JSON.stringify({
148
+ modelId: DEFAULT_TEST_MODEL,
149
+ context: {
150
+ systemPrompt: SOOTSIM_TEST_SYSTEM_PROMPT,
151
+ messages: [
152
+ {
153
+ role: 'user',
154
+ content: buildPromptRequest(args.prompt, args.describe),
155
+ timestamp: Date.now(),
156
+ },
157
+ ],
158
+ },
159
+ options: { maxTokens: 1800, temperature: 0.2 },
160
+ threadId: null,
161
+ }),
162
+ signal: AbortSignal.timeout(LLM_TIMEOUT_MS),
163
+ })
164
+ if (!res.ok || !res.body) {
165
+ const text = await res.text().catch(() => '')
166
+ throw new Error(`/api/llm ${res.status}${text ? `: ${text}` : ''}`)
167
+ }
168
+
169
+ const reader = res.body.getReader()
170
+ const decoder = new TextDecoder()
171
+ const deltas: string[] = []
172
+ let buffer = ''
173
+ // /api/llm speaks pi-agent-core's proxy event protocol. text events carry
174
+ // visible deltas; transport diagnostics and keepalives are ignored here.
175
+ const handleLine = (line: string) => {
176
+ const trimmed = line.trim()
177
+ if (!trimmed) return
178
+ const event = JSON.parse(trimmed) as {
179
+ type?: string
180
+ delta?: string
181
+ errorMessage?: string
182
+ }
183
+ if (event.type === 'text_delta' && event.delta) {
184
+ deltas.push(event.delta)
185
+ } else if (event.type === 'error') {
186
+ throw new Error(event.errorMessage || 'llm error')
187
+ }
188
+ }
189
+
190
+ for (;;) {
191
+ const { value, done } = await reader.read()
192
+ if (done) break
193
+ buffer += decoder.decode(value, { stream: true })
194
+ let newline: number
195
+ while ((newline = buffer.indexOf('\n')) >= 0) {
196
+ handleLine(buffer.slice(0, newline))
197
+ buffer = buffer.slice(newline + 1)
198
+ }
199
+ }
200
+ buffer += decoder.decode()
201
+ if (buffer.trim()) handleLine(buffer)
202
+
203
+ const text = deltas.join('').trim()
204
+ if (!text) throw new Error('llm returned an empty test flow')
205
+ return text
206
+ }
207
+
208
+ function extractJson(text: string): unknown {
209
+ const fenced = text.match(/```(?:json)?\s*([\s\S]*?)```/i)
210
+ const candidate = fenced
211
+ ? fenced[1]
212
+ : text.slice(text.indexOf('{'), text.lastIndexOf('}') + 1)
213
+ return JSON.parse(candidate)
214
+ }
215
+
216
+ function isRecord(value: unknown): value is Record<string, unknown> {
217
+ return Boolean(value && typeof value === 'object' && !Array.isArray(value))
218
+ }
219
+
220
+ function parseGeneratedFlow(text: string): {
221
+ summary: string
222
+ steps: Record<string, unknown>[]
223
+ yamlText: string
224
+ } {
225
+ const parsed = extractJson(text)
226
+ if (!isRecord(parsed)) throw new Error('llm did not return a JSON object')
227
+ const summary =
228
+ typeof parsed.summary === 'string' && parsed.summary.trim()
229
+ ? parsed.summary.trim().slice(0, 500)
230
+ : 'rnx generated test'
231
+ const rawSteps = parsed.steps
232
+ if (!Array.isArray(rawSteps) || rawSteps.length === 0) {
233
+ throw new Error('llm returned no flow steps')
234
+ }
235
+ const steps = rawSteps.map((step, index) => {
236
+ if (!isRecord(step)) throw new Error(`flow step ${index + 1} is not an object`)
237
+ return step
238
+ })
239
+ return { summary, steps, yamlText: yaml.stringify(steps) }
240
+ }
241
+
242
+ function buildFlowArgs(
243
+ args: string[],
244
+ promptIndex: number,
245
+ flowPath: string,
246
+ origin: string,
247
+ ) {
248
+ const out = [
249
+ flowPath,
250
+ '--preview',
251
+ '--preview-origin',
252
+ origin,
253
+ '--billing-kind',
254
+ 'test_run',
255
+ ]
256
+ const passthroughValues = new Set([
257
+ '--public-origin',
258
+ '--preview-public-origin',
259
+ '--owner',
260
+ '--repo',
261
+ '--url',
262
+ '--driver',
263
+ '--sim',
264
+ '--device',
265
+ '--slow',
266
+ '--tail-wait',
267
+ '--remap',
268
+ '--replace',
269
+ ])
270
+ const passthroughBooleans = new Set([
271
+ '--new',
272
+ '--headless',
273
+ '--headed',
274
+ '--electron',
275
+ '--preview-open',
276
+ '--no-shell',
277
+ '--shell-only',
278
+ ])
279
+ for (let i = 0; i < args.length; i++) {
280
+ if (i === promptIndex) continue
281
+ const arg = args[i]
282
+ if (arg === '--origin' || arg === '--preview-origin') {
283
+ i += 1
284
+ continue
285
+ }
286
+ if (arg === '--public-origin') {
287
+ const value = args[i + 1]
288
+ if (value) out.push('--preview-public-origin', value)
289
+ i += 1
290
+ continue
291
+ }
292
+ if (passthroughValues.has(arg)) {
293
+ const value = args[i + 1]
294
+ if (value) out.push(arg, value)
295
+ i += 1
296
+ continue
297
+ }
298
+ if (passthroughBooleans.has(arg)) out.push(arg)
299
+ }
300
+ return out
301
+ }
302
+
303
+ export async function runMaestroGenerate(args: string[]): Promise<number> {
304
+ const promptArg = findPrompt(args)
305
+ if (!promptArg) {
306
+ console.error(' usage: rnxsim maestro generate "test goal"')
307
+ return 1
308
+ }
309
+ const { prompt, index: promptIndex } = promptArg
310
+ const cliAuth = resolveCliAuth()
311
+ if (!cliAuth || cliAuth.kind === 'github') {
312
+ console.error(' rnxsim maestro generate "<goal>" needs a login or RNX_API_KEY.')
313
+ console.error(' API keys must include preview_upload and llm scopes.')
314
+ return 1
315
+ }
316
+ const authHeader = authHeaderValue(cliAuth)
317
+ const origin = await resolveDefaultUploadOrigin(
318
+ flagValueAny(args, ['--origin', '--preview-origin']),
319
+ )
320
+ console.log(' inspecting current sim…')
321
+ const describe = await describeCurrentSim(args, promptIndex)
322
+ console.log(' generating Maestro flow…')
323
+ const generated = await generateFlowJson({ prompt, describe, origin, authHeader })
324
+ const flow = parseGeneratedFlow(generated)
325
+ const tempDir = mkdtempSync(join(tmpdir(), 'sootsim-maestro-generate-'))
326
+ const flowPath = join(tempDir, 'flow.yaml')
327
+ writeFileSync(flowPath, flow.yamlText)
328
+ console.log(` flow: ${flowPath}`)
329
+
330
+ const startedAt = Date.now()
331
+ const { runFlowPlayback, getLastFlowPreviewUploadResult, getLastFlowTraceSteps } =
332
+ await import('./flow')
333
+ const flowArgs = buildFlowArgs(args, promptIndex, flowPath, origin)
334
+ const exitCode = await runFlowPlayback(flowArgs)
335
+ const upload = getLastFlowPreviewUploadResult()
336
+ const traceSteps = getLastFlowTraceSteps()
337
+ const failedStep = traceSteps.find((step) => step.status === 'failure')
338
+ const status = exitCode === 0 ? 'passed' : 'failed'
339
+ const run = await registerRun({
340
+ origin,
341
+ kind: 'maestro',
342
+ prompt,
343
+ summary: flow.summary,
344
+ status,
345
+ failureMessage:
346
+ status === 'failed' ? (failedStep?.error ?? 'flow playback failed') : null,
347
+ previewShareId: upload?.shareId ?? null,
348
+ owner: flagValue(args, '--owner') ?? null,
349
+ repo: flagValue(args, '--repo') ?? null,
350
+ durationMs: Date.now() - startedAt,
351
+ flowYamlSizeBytes: Buffer.byteLength(flow.yamlText, 'utf8'),
352
+ ...stepSummaryFromTrace(traceSteps),
353
+ auth: cliAuth,
354
+ })
355
+
356
+ console.log(`\n result: ${status}`)
357
+ if (run) console.log(` run: ${run.id}`)
358
+ if (upload?.previewUrl) console.log(` preview: ${upload.previewUrl}`)
359
+ if (run?.traceUrl) console.log(` replay: ${run.traceUrl}`)
360
+ return exitCode
361
+ }