rnxsim 0.1.312 → 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 (299) 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-NXVDDCFG.js → agent-7YBDCYMA.js} +2 -2
  126. package/dist-cli/chunks/{agent-wrapper-DXJCFKL3.js → agent-wrapper-2GHFBHCR.js} +2 -2
  127. package/dist-cli/chunks/{app-fonts-W5AJZQJF.js → app-fonts-RSNVPQSU.js} +2 -2
  128. package/dist-cli/chunks/{assert-3LOJEUDT.js → assert-XCMX3XJX.js} +2 -2
  129. package/dist-cli/chunks/{auth-MFTYYPNX.js → auth-B442HRAX.js} +2 -2
  130. package/dist-cli/chunks/{beta-GT3NN67B.js → beta-XJ55JK3M.js} +2 -2
  131. package/dist-cli/chunks/camera-UGYSSLIK.js +33 -0
  132. package/dist-cli/chunks/{chunk-EUAVBTKU.js → chunk-277AEQZX.js} +2 -2
  133. package/dist-cli/chunks/{chunk-5OX7ANRA.js → chunk-2JNSK774.js} +2 -2
  134. package/dist-cli/chunks/{chunk-L24Z3CRS.js → chunk-32WOTSTR.js} +3 -3
  135. package/dist-cli/chunks/{chunk-BKNOLP3J.js → chunk-3S753SNQ.js} +2 -2
  136. package/dist-cli/chunks/{chunk-N6A3SXMR.js → chunk-46ZOLOYA.js} +2 -2
  137. package/dist-cli/chunks/{chunk-GZDHEONW.js → chunk-5L7ELDQL.js} +8 -9
  138. package/dist-cli/chunks/{chunk-YZRFF4YA.js → chunk-7OOPFSQS.js} +2 -2
  139. package/dist-cli/chunks/{chunk-TBMVBI26.js → chunk-7SV3RPRW.js} +2 -2
  140. package/dist-cli/chunks/{chunk-JG6S4RSH.js → chunk-7ZC35MOU.js} +1 -1
  141. package/dist-cli/chunks/chunk-AMG5E6CC.js +9 -0
  142. package/dist-cli/chunks/{chunk-MENV7VLD.js → chunk-APWNH3A4.js} +1 -1
  143. package/dist-cli/chunks/chunk-B57XUKY3.js +4 -0
  144. package/dist-cli/chunks/{chunk-3D57IBPC.js → chunk-C2NL26TD.js} +1 -1
  145. package/dist-cli/chunks/chunk-D2FNUWAB.js +15 -0
  146. package/dist-cli/chunks/{chunk-4BXCZHAU.js → chunk-E5T4XSJ3.js} +2 -2
  147. package/dist-cli/chunks/{chunk-FTC4M26Q.js → chunk-EAC34EQS.js} +1 -1
  148. package/dist-cli/chunks/{chunk-NPVGMH2N.js → chunk-EG32ML36.js} +2 -2
  149. package/dist-cli/chunks/{chunk-DM6KUAOZ.js → chunk-FXUAC6D5.js} +1 -1
  150. package/dist-cli/chunks/chunk-GQSL4USA.js +6 -0
  151. package/dist-cli/chunks/{chunk-U4PN6JOT.js → chunk-HAXW27SS.js} +2 -2
  152. package/dist-cli/chunks/{chunk-ZMZTHU7V.js → chunk-IZAHPAN6.js} +1 -1
  153. package/dist-cli/chunks/{chunk-SI3BUTQR.js → chunk-J62KM5TB.js} +2 -2
  154. package/dist-cli/chunks/{chunk-Y2FSZSO7.js → chunk-JEMCD5E4.js} +1 -1
  155. package/dist-cli/chunks/{chunk-T4FT6CM7.js → chunk-JZS3Q37N.js} +2 -2
  156. package/dist-cli/chunks/{chunk-2SA2VTGP.js → chunk-KR4JON7D.js} +1 -1
  157. package/dist-cli/chunks/chunk-KWCYKQIQ.js +4 -0
  158. package/dist-cli/chunks/{chunk-HG7ORJMT.js → chunk-MCWPL644.js} +2 -2
  159. package/dist-cli/chunks/chunk-MJYK3N2I.js +4 -0
  160. package/dist-cli/chunks/{chunk-YRV7HR3P.js → chunk-O6TRIZNS.js} +2 -2
  161. package/dist-cli/chunks/{chunk-WBT32R6N.js → chunk-P7XL2E73.js} +3 -3
  162. package/dist-cli/chunks/{chunk-MNGQ42QE.js → chunk-PFQTUKQ4.js} +62 -87
  163. package/dist-cli/chunks/{chunk-Q3RGLERJ.js → chunk-PG5RZCTN.js} +2 -2
  164. package/dist-cli/chunks/{chunk-OR3XTXEB.js → chunk-QGRI2Z4M.js} +2 -2
  165. package/dist-cli/chunks/chunk-QLXXE7GE.js +125 -0
  166. package/dist-cli/chunks/{chunk-KZW5WBGU.js → chunk-QOJJJWJE.js} +89 -133
  167. package/dist-cli/chunks/{chunk-BRIZOR4K.js → chunk-RWZY5427.js} +2 -2
  168. package/dist-cli/chunks/{chunk-TYE3WBSR.js → chunk-RZKU2K3J.js} +2 -2
  169. package/dist-cli/chunks/{chunk-7VWOSTD5.js → chunk-SBV4IK4H.js} +1 -1
  170. package/dist-cli/chunks/{chunk-FWYYCUAZ.js → chunk-SGMVFFMK.js} +1 -1
  171. package/dist-cli/chunks/{chunk-LDQ7HVCW.js → chunk-TAX4UT2N.js} +1 -1
  172. package/dist-cli/chunks/{chunk-G74YIEVS.js → chunk-TUOFAWXT.js} +1 -1
  173. package/dist-cli/chunks/{chunk-274UD5FD.js → chunk-UHZLOHGP.js} +1 -1
  174. package/dist-cli/chunks/{chunk-37I5AIS7.js → chunk-VC7V76U3.js} +1 -1
  175. package/dist-cli/chunks/{chunk-B7KMNHX7.js → chunk-VQVMLW4U.js} +1 -1
  176. package/dist-cli/chunks/{chunk-VZBLFMYC.js → chunk-VUKKYPZN.js} +2 -2
  177. package/dist-cli/chunks/{chunk-VUFRB347.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-TCWQJILS.js → chunk-XULEACM4.js} +2 -2
  181. package/dist-cli/chunks/{chunk-XRGEEPJ5.js → chunk-YFSDM7AX.js} +4 -4
  182. package/dist-cli/chunks/chunk-YWI3UEVX.js +5 -0
  183. package/dist-cli/chunks/{chunk-TGQNQ6XT.js → chunk-ZBSJO4NB.js} +10 -9
  184. package/dist-cli/chunks/{cleanup-H3GWQB63.js → cleanup-EYLGCA6Z.js} +2 -2
  185. package/dist-cli/chunks/cli-version-LL2UGIHE.js +4 -0
  186. package/dist-cli/chunks/{compat-5WG2XJV7.js → compat-TLJYHB4E.js} +2 -2
  187. package/dist-cli/chunks/{config-ANMBVVLL.js → config-4JWUOEXK.js} +2 -2
  188. package/dist-cli/chunks/{control-NSGNQFJG.js → control-HPAOYF4N.js} +2 -2
  189. package/dist-cli/chunks/daemon-OYLASXLE.js +4 -0
  190. package/dist-cli/chunks/{debug-CHV2O2KF.js → debug-4BKXF6KI.js} +5 -5
  191. package/dist-cli/chunks/{desktop-FIPIK4CH.js → desktop-ZQ6ZD2S6.js} +3 -3
  192. package/dist-cli/chunks/{detox-CVUJP7K6.js → detox-WNPASSS3.js} +2 -2
  193. package/dist-cli/chunks/{device-6WCUM4W6.js → device-BXLXVG3V.js} +2 -2
  194. package/dist-cli/chunks/{diagnose-I6EMWEII.js → diagnose-3QX7W5RW.js} +2 -2
  195. package/dist-cli/chunks/{disk-cleanup-P27CYFTN.js → disk-cleanup-KSWKI7WB.js} +2 -2
  196. package/dist-cli/chunks/drivers-EPIEFF7P.js +4 -0
  197. package/dist-cli/chunks/{film-UOQFFYNF.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-NJYFSJKZ.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-BPFQENCX.js → login-IJAPUZHI.js} +4 -4
  205. package/dist-cli/chunks/{logout-5A45ZGY7.js → logout-QMXDFU2X.js} +2 -2
  206. package/dist-cli/chunks/{maestro-E4CSDMLM.js → maestro-ZXU3YCVX.js} +3 -3
  207. package/dist-cli/chunks/{maestro-generate-CKMOJQX2.js → maestro-generate-PYB5QY7K.js} +3 -3
  208. package/dist-cli/chunks/{mode-SZYNMIQF.js → mode-WGUCL5FZ.js} +2 -2
  209. package/dist-cli/chunks/{optional-demo-registry-FRH4SFVG.js → optional-demo-registry-WH2O6H36.js} +2 -2
  210. package/dist-cli/chunks/{perf-VXU2XJAX.js → perf-TOD3UFAH.js} +2 -2
  211. package/dist-cli/chunks/{permissions-IRIAOVND.js → permissions-I5BRJGTB.js} +2 -2
  212. package/dist-cli/chunks/{record-RY7FPLLH.js → record-ZYL2FYSK.js} +3 -3
  213. package/dist-cli/chunks/{report-issue-KNWXOE53.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-QLALR6GY.js → screenshot-command-7ANLODZY.js} +7 -7
  217. package/dist-cli/chunks/{screenshot-layers-OQFMFVRL.js → screenshot-layers-A7FYXSVU.js} +3 -3
  218. package/dist-cli/chunks/{screenshots-capture-6TSRJFGB.js → screenshots-capture-WT2ZY6CB.js} +2 -2
  219. package/dist-cli/chunks/serve-TG5WKA4V.js +44 -0
  220. package/dist-cli/chunks/{setup-7V6UKX4U.js → setup-PCWLD22V.js} +2 -2
  221. package/dist-cli/chunks/{skills-QQBOSETH.js → skills-27ZHWCQS.js} +2 -2
  222. package/dist-cli/chunks/state-ZQVY46ZO.js +14 -0
  223. package/dist-cli/chunks/{storage-TAPMKK5O.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-IAM564NA.js → timeline-RAJJFQT6.js} +2 -2
  227. package/dist-cli/chunks/{upgrade-CD55QXIX.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-6NW6YLPI.js → web-XBUTBVGR.js} +2 -2
  231. package/dist-cli/chunks/{what-happened-CZZDOOVG.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 +493 -282
  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-6EAK7CUL.js +0 -22
  277. package/dist-cli/chunks/chunk-33FKQH54.js +0 -5
  278. package/dist-cli/chunks/chunk-66NF2KNG.js +0 -9
  279. package/dist-cli/chunks/chunk-6UKJB2VC.js +0 -125
  280. package/dist-cli/chunks/chunk-7INBNA3U.js +0 -26
  281. package/dist-cli/chunks/chunk-AY47WKS5.js +0 -23
  282. package/dist-cli/chunks/chunk-HMDOLCKG.js +0 -15
  283. package/dist-cli/chunks/chunk-KR5BGMBZ.js +0 -4
  284. package/dist-cli/chunks/chunk-NLEMQ4PY.js +0 -6
  285. package/dist-cli/chunks/chunk-PEPUGJVI.js +0 -4
  286. package/dist-cli/chunks/cli-version-3QPAJ3LC.js +0 -4
  287. package/dist-cli/chunks/daemon-JHF4BJ3U.js +0 -4
  288. package/dist-cli/chunks/drivers-HQ6AKZT6.js +0 -4
  289. package/dist-cli/chunks/flow-N27MRRNL.js +0 -4
  290. package/dist-cli/chunks/help-SF6FEGEE.js +0 -4
  291. package/dist-cli/chunks/home-paths-XOV44JEF.js +0 -4
  292. package/dist-cli/chunks/inspect-CWFRFQTY.js +0 -4
  293. package/dist-cli/chunks/install-desktop-KLQDNXZQ.js +0 -4
  294. package/dist-cli/chunks/runtime-AR3GJTGK.js +0 -4
  295. package/dist-cli/chunks/serve-F54J2NQO.js +0 -44
  296. package/dist-cli/chunks/store-7NX3S43H.js +0 -4
  297. package/dist-cli/chunks/telemetry-E7BUK6RA.js +0 -4
  298. package/dist-cli/chunks/upload-GZ6LIMYM.js +0 -4
  299. package/dist-cli/chunks/version-3DYJ5AS3.js +0 -6
@@ -0,0 +1,423 @@
1
+ // user-facing `sootsim agent` command tree.
2
+ //
3
+ // session-lifecycle commands (start, prompt, end, watch) route through
4
+ // the bridge daemon — the daemon owns the single FIFO reader per
5
+ // session, so concurrent cli watches + electron UI subscribers no longer
6
+ // steal bytes from each other. the daemon auto-spawns on first use via
7
+ // `connectToDaemon`.
8
+ //
9
+ // disk-only inspection commands (projects, sessions, paths, transcript,
10
+ // attach, project show/remove) read the attached-projects JSON directly —
11
+ // no daemon needed, so `sootsim agent projects` stays fast when no
12
+ // wrapper is live.
13
+
14
+ import fs from 'node:fs'
15
+ import path from 'node:path'
16
+ import {
17
+ AgentDaemonError,
18
+ connectToDaemon,
19
+ type AgentDaemonClient,
20
+ } from '../../src/agent-daemon-client'
21
+ import { parseAgentEventLine, type AgentEvent } from '../../src/agent-events'
22
+ import {
23
+ eventsFifoPath,
24
+ pidIsAlive,
25
+ promptFifoPath,
26
+ sessionDir,
27
+ transcriptPath,
28
+ type Provider,
29
+ } from '../../src/agent-sessions'
30
+ import {
31
+ costThisWeek,
32
+ deleteProject,
33
+ findProjectById,
34
+ getUserDataDir,
35
+ listProjects,
36
+ listSessions,
37
+ upsertProject,
38
+ type AgentSession,
39
+ type AttachedProject,
40
+ } from '../../src/attached-projects'
41
+ import { printCommandHelp } from '../help'
42
+
43
+ export async function runAgentCommand(argv: string[]): Promise<number> {
44
+ const [sub, ...rest] = argv
45
+ try {
46
+ switch (sub) {
47
+ case undefined:
48
+ case '--help':
49
+ case '-h':
50
+ case 'help':
51
+ printHelp()
52
+ return 0
53
+ case 'attach':
54
+ return await cmdAttach(rest)
55
+ case 'projects':
56
+ return await cmdProjects()
57
+ case 'project':
58
+ return await cmdProject(rest)
59
+ case 'sessions':
60
+ return await cmdSessions(rest)
61
+ case 'start':
62
+ return await cmdStart(rest)
63
+ case 'prompt':
64
+ return await cmdPrompt(rest)
65
+ case 'watch':
66
+ return await cmdWatch(rest)
67
+ case 'transcript':
68
+ return await cmdTranscript(rest)
69
+ case 'end':
70
+ return await cmdEnd(rest)
71
+ case 'paths':
72
+ return await cmdPaths()
73
+ default:
74
+ process.stderr.write(`unknown agent subcommand: ${sub}\n`)
75
+ printHelp()
76
+ return 2
77
+ }
78
+ } catch (err) {
79
+ if (err instanceof AgentDaemonError) {
80
+ process.stderr.write(`${err.message}\n`)
81
+ return 1
82
+ }
83
+ throw err
84
+ }
85
+ }
86
+
87
+ /** open a daemon client for a single command. callers are responsible for
88
+ * closing the client when done so the CLI process exits promptly. */
89
+ async function withDaemon<T>(fn: (client: AgentDaemonClient) => Promise<T>): Promise<T> {
90
+ const client = await connectToDaemon({ clientLabel: 'sootsim-agent-cli' })
91
+ try {
92
+ return await fn(client)
93
+ } finally {
94
+ client.close()
95
+ }
96
+ }
97
+
98
+ function printHelp(): void {
99
+ // delegate to the meta-driven renderer so bare `sootsim agent`, `--help`,
100
+ // and `unknown subcommand` paths all show the same rich help (header,
101
+ // options, examples) instead of a sparse hand-coded summary.
102
+ printCommandHelp('agent')
103
+ }
104
+
105
+ // --- arg parsing ---
106
+
107
+ function parseFlags(
108
+ argv: string[],
109
+ known: Record<string, 'value' | 'bool'>,
110
+ ): { flags: Record<string, string | boolean>; positional: string[] } {
111
+ const flags: Record<string, string | boolean> = {}
112
+ const positional: string[] = []
113
+ for (let i = 0; i < argv.length; i++) {
114
+ const arg = argv[i]
115
+ const kind = known[arg]
116
+ if (kind === 'value') {
117
+ flags[arg] = argv[i + 1] ?? ''
118
+ i++
119
+ } else if (kind === 'bool') {
120
+ flags[arg] = true
121
+ } else {
122
+ positional.push(arg)
123
+ }
124
+ }
125
+ return { flags, positional }
126
+ }
127
+
128
+ function resolveProvider(raw: unknown, fallback: Provider = 'codex'): Provider {
129
+ if (raw === 'codex' || raw === 'claude') return raw
130
+ return fallback
131
+ }
132
+
133
+ // --- subcommands ---
134
+
135
+ async function cmdAttach(argv: string[]): Promise<number> {
136
+ const { flags, positional } = parseFlags(argv, {
137
+ '--name': 'value',
138
+ '--provider': 'value',
139
+ })
140
+ const dir = positional[0]
141
+ if (!dir) {
142
+ process.stderr.write(
143
+ 'usage: rnxsim agent attach <dir> [--name X] [--provider codex|claude]\n',
144
+ )
145
+ return 2
146
+ }
147
+ const absolute = path.resolve(dir)
148
+ if (!fs.existsSync(absolute)) {
149
+ process.stderr.write(`directory does not exist: ${absolute}\n`)
150
+ return 1
151
+ }
152
+ const project = upsertProject({
153
+ cwd: absolute,
154
+ name: (flags['--name'] as string) || path.basename(absolute),
155
+ preferredProvider: resolveProvider(flags['--provider']),
156
+ sourceRoots: [absolute],
157
+ })
158
+ process.stdout.write(
159
+ `✓ attached "${project.name}" (id: ${project.id})\n` +
160
+ ` cwd: ${project.cwd}\n` +
161
+ ` framework: ${project.framework}\n` +
162
+ ` preferred provider: ${project.preferredProvider}\n`,
163
+ )
164
+ return 0
165
+ }
166
+
167
+ async function cmdProjects(): Promise<number> {
168
+ const projects = [...listProjects()].sort((a, b) => b.updatedAt - a.updatedAt)
169
+ if (projects.length === 0) {
170
+ process.stdout.write('no attached projects yet. try `rnxsim agent attach <dir>`.\n')
171
+ return 0
172
+ }
173
+ const header = `${'ID'.padEnd(18)} ${'NAME'.padEnd(20)} ${'FRAMEWORK'.padEnd(10)} ${'PROVIDER'.padEnd(8)} ${'7D COST'.padEnd(10)} CWD\n`
174
+ process.stdout.write(header)
175
+ for (const p of projects) {
176
+ const cost = costThisWeek(p)
177
+ const costCell = cost > 0 ? `$${cost.toFixed(2)}` : '—'
178
+ process.stdout.write(
179
+ `${p.id.padEnd(18)} ${truncate(p.name, 20).padEnd(20)} ${p.framework.padEnd(10)} ${p.preferredProvider.padEnd(8)} ${costCell.padEnd(10)} ${p.cwd}\n`,
180
+ )
181
+ }
182
+ return 0
183
+ }
184
+
185
+ async function cmdProject(argv: string[]): Promise<number> {
186
+ const [action, id] = argv
187
+ if (action === 'show') {
188
+ if (!id) {
189
+ process.stderr.write('usage: rnxsim agent project show <id>\n')
190
+ return 2
191
+ }
192
+ const project = findProjectById(id)
193
+ if (!project) {
194
+ process.stderr.write(`no project with id=${id}\n`)
195
+ return 1
196
+ }
197
+ process.stdout.write(JSON.stringify(project, null, 2) + '\n')
198
+ return 0
199
+ }
200
+ if (action === 'remove') {
201
+ if (!id) {
202
+ process.stderr.write('usage: rnxsim agent project remove <id>\n')
203
+ return 2
204
+ }
205
+ deleteProject(id)
206
+ process.stdout.write(`✓ removed project ${id}\n`)
207
+ return 0
208
+ }
209
+ process.stderr.write('usage: rnxsim agent project [show|remove] <id>\n')
210
+ return 2
211
+ }
212
+
213
+ async function cmdSessions(argv: string[]): Promise<number> {
214
+ const { flags } = parseFlags(argv, { '--project': 'value', '--all': 'bool' })
215
+ const projectId = (flags['--project'] as string) || undefined
216
+ const showAll = flags['--all'] === true
217
+ let sessions = listSessions(projectId)
218
+ if (!showAll) {
219
+ sessions = sessions.filter((s) => s.status !== 'ended')
220
+ }
221
+ sessions = sessions.sort((a, b) => b.lastSeenAt - a.lastSeenAt)
222
+ if (sessions.length === 0) {
223
+ process.stdout.write(
224
+ showAll ? 'no sessions.\n' : 'no active sessions. pass --all to include ended.\n',
225
+ )
226
+ return 0
227
+ }
228
+ const header = `${'SESSION'.padEnd(26)} ${'PROJECT'.padEnd(18)} ${'PROVIDER'.padEnd(8)} ${'STATUS'.padEnd(16)} ${'ALIVE'.padEnd(5)} LAST PROMPT\n`
229
+ process.stdout.write(header)
230
+ for (const s of sessions) {
231
+ const alive = pidIsAlive(s.wrapperPid, s.id) ? 'yes' : 'no'
232
+ const prompt = s.lastPrompt ? truncate(s.lastPrompt, 40) : ''
233
+ process.stdout.write(
234
+ `${shortId(s.id).padEnd(26)} ${shortId(s.projectId).padEnd(18)} ${s.provider.padEnd(8)} ${s.status.padEnd(16)} ${alive.padEnd(5)} ${prompt}\n`,
235
+ )
236
+ }
237
+ return 0
238
+ }
239
+
240
+ async function cmdStart(argv: string[]): Promise<number> {
241
+ const { flags, positional } = parseFlags(argv, {
242
+ '--provider': 'value',
243
+ '--codex-bin': 'value',
244
+ '--claude-bin': 'value',
245
+ '--fresh-thread': 'bool',
246
+ })
247
+ const projectId = positional[0]
248
+ if (!projectId) {
249
+ process.stderr.write(
250
+ 'usage: rnxsim agent start <projectId> [--provider codex|claude] [--fresh-thread]\n',
251
+ )
252
+ return 2
253
+ }
254
+ const result = await withDaemon((client) =>
255
+ client.startSession({
256
+ projectId,
257
+ provider:
258
+ resolveProvider(flags['--provider'], undefined as unknown as Provider) ||
259
+ undefined,
260
+ codexBin: (flags['--codex-bin'] as string) || undefined,
261
+ claudeBin: (flags['--claude-bin'] as string) || undefined,
262
+ freshThread: flags['--fresh-thread'] === true,
263
+ }),
264
+ )
265
+ const project = findProjectById(result.session.projectId)!
266
+ process.stdout.write(
267
+ `✓ session ${result.session.id} started\n` +
268
+ ` project: ${project.name} (${project.id})\n` +
269
+ ` provider: ${result.session.provider}\n` +
270
+ ` pid: ${result.wrapperPid}\n` +
271
+ ` prompt with: rnxsim agent prompt ${result.session.id} "<text>"\n` +
272
+ ` watch events: rnxsim agent watch ${result.session.id}\n`,
273
+ )
274
+ return 0
275
+ }
276
+
277
+ async function cmdPrompt(argv: string[]): Promise<number> {
278
+ const [sessionId, ...rest] = argv
279
+ const text = rest.join(' ')
280
+ if (!sessionId || !text) {
281
+ process.stderr.write('usage: rnxsim agent prompt <sessionId> "<text>"\n')
282
+ return 2
283
+ }
284
+ await withDaemon((client) => client.sendPrompt(sessionId, { text }))
285
+ process.stdout.write(`✓ prompt sent to ${sessionId}\n`)
286
+ return 0
287
+ }
288
+
289
+ async function cmdWatch(argv: string[]): Promise<number> {
290
+ const sessionId = argv[0]
291
+ if (!sessionId) {
292
+ process.stderr.write('usage: rnxsim agent watch <sessionId>\n')
293
+ return 2
294
+ }
295
+ process.stdout.write(`watching ${sessionId}\n---\n`)
296
+ // the daemon owns the FIFO reader. we stay subscribed until SIGINT —
297
+ // this is the one command that requires a persistent daemon client.
298
+ const client = await connectToDaemon({ clientLabel: 'sootsim-agent-watch' })
299
+ let resolveExit: (code: number) => void
300
+ const exit = new Promise<number>((resolve) => {
301
+ resolveExit = resolve
302
+ })
303
+ const offEvent = client.onAgentEvent(({ sessionId: sid, event }) => {
304
+ if (sid !== sessionId) return
305
+ process.stdout.write(formatEvent(event) + '\n')
306
+ })
307
+ const offDisconnect = client.onDisconnect(() => {
308
+ process.stderr.write('\n[rnx] daemon disconnected; exiting watch.\n')
309
+ resolveExit(1)
310
+ })
311
+ try {
312
+ await client.subscribeEvents(sessionId)
313
+ } catch (err) {
314
+ offEvent()
315
+ offDisconnect()
316
+ client.close()
317
+ throw err
318
+ }
319
+ process.on('SIGINT', () => {
320
+ offEvent()
321
+ offDisconnect()
322
+ void client.unsubscribeEvents(sessionId).catch(() => {})
323
+ client.close()
324
+ resolveExit(130)
325
+ })
326
+ return exit
327
+ }
328
+
329
+ function formatEvent(ev: AgentEvent): string {
330
+ const ts = fmtTs(ev.ts)
331
+ switch (ev.type) {
332
+ case 'ready':
333
+ return `[${ts}] ready ${ev.provider} @ ${ev.cwd}`
334
+ case 'prompt-received':
335
+ return `[${ts}] prompt "${truncate(ev.text, 120)}"`
336
+ case 'turn-started':
337
+ return `[${ts}] turn-started ${ev.turnId ?? ''}`
338
+ case 'turn-message':
339
+ return `[${ts}] turn-message ${ev.delta.replace(/\s+$/, '')}`
340
+ case 'turn-reasoning':
341
+ return `[${ts}] turn-reasoning ${truncate(ev.delta, 200)}`
342
+ case 'tool-call':
343
+ return `[${ts}] tool-call ${ev.name}`
344
+ case 'file-edited':
345
+ return `[${ts}] file-edited ${ev.kind.padEnd(6)} ${ev.path}`
346
+ case 'turn-completed':
347
+ return `[${ts}] turn-completed ${ev.durationMs}ms files=${ev.filesTouched.length}`
348
+ case 'approval-needed':
349
+ return `[${ts}] approval ${ev.kind}`
350
+ case 'error':
351
+ return `[${ts}] error ${ev.message}`
352
+ case 'exited':
353
+ return `[${ts}] exited code=${ev.code}`
354
+ case 'file-diff-delta':
355
+ return `[${ts}] file-diff-delta ${ev.path}`
356
+ case 'turn-plan':
357
+ return `[${ts}] turn-plan steps=${ev.steps.length}`
358
+ default:
359
+ return `[${ts}] ${(ev as { type: string }).type}`
360
+ }
361
+ }
362
+
363
+ async function cmdTranscript(argv: string[]): Promise<number> {
364
+ const sessionId = argv[0]
365
+ if (!sessionId) {
366
+ process.stderr.write('usage: rnxsim agent transcript <sessionId>\n')
367
+ return 2
368
+ }
369
+ const p = transcriptPath(sessionId)
370
+ if (!fs.existsSync(p)) {
371
+ process.stderr.write(`transcript not found: ${p}\n`)
372
+ return 1
373
+ }
374
+ process.stdout.write(fs.readFileSync(p, 'utf8'))
375
+ return 0
376
+ }
377
+
378
+ async function cmdEnd(argv: string[]): Promise<number> {
379
+ const sessionId = argv[0]
380
+ if (!sessionId) {
381
+ process.stderr.write('usage: rnxsim agent end <sessionId>\n')
382
+ return 2
383
+ }
384
+ await withDaemon((client) => client.endSession(sessionId))
385
+ process.stdout.write(`✓ ended session ${sessionId}\n`)
386
+ return 0
387
+ }
388
+
389
+ async function cmdPaths(): Promise<number> {
390
+ const dir = getUserDataDir()
391
+ process.stdout.write(
392
+ `userData: ${dir}\n` +
393
+ `state: ${path.join(dir, 'attached-projects.json')}\n` +
394
+ `sessions: ${path.join(dir, 'sessions')}\n` +
395
+ `transcripts: ${path.join(dir, 'transcripts')}\n` +
396
+ `locks: ${path.join(dir, 'locks')}\n`,
397
+ )
398
+ return 0
399
+ }
400
+
401
+ // --- utilities ---
402
+
403
+ function truncate(s: string, max: number): string {
404
+ if (s.length <= max) return s
405
+ return s.slice(0, max - 1) + '…'
406
+ }
407
+ function shortId(id: string): string {
408
+ return id.length > 14 ? `${id.slice(0, 14)}…` : id
409
+ }
410
+ function fmtTs(ts: number): string {
411
+ return new Date(ts).toISOString().replace('T', ' ').slice(0, 19)
412
+ }
413
+
414
+ // keep these importable for the legacy e2e script paths — the canonical
415
+ // source of truth is now `sootsim/agent-sessions`.
416
+ export const __internals = {
417
+ sessionDir,
418
+ promptFifoPath,
419
+ eventsFifoPath,
420
+ transcriptPath,
421
+ parseAgentEventLine,
422
+ }
423
+ export type { AgentSession, AttachedProject }
@@ -0,0 +1,98 @@
1
+ // sootsim app-fonts stage — fetch the config-plugin fonts declared on an
2
+ // engine `?appFonts=` wire, gzip them, and merge asset descriptors into a
3
+ // build's asset manifest.
4
+ //
5
+ // the branch-build path (app/api/github/agent/run.sh) captures the metro
6
+ // __packager_asset graph itself, but config-plugin fonts (expo-font etc.) only
7
+ // live in the native binary — never the bundle — so that capture misses them.
8
+ // rather than reimplement font fetch/gzip/hash in bash, run.sh calls this once
9
+ // after the asset capture; the descriptors land in the same manifest the
10
+ // upload step already PUTs, keyed by sha256(url) so the rendered build resolves
11
+ // each font through /api/preview/share/fetch?url=<fontUrl> identically to the
12
+ // preview path (`sootsim record upload`). both pipelines share fetchAppFontFiles.
13
+
14
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs'
15
+ import { join } from 'node:path'
16
+ import { gzipSync } from 'node:zlib'
17
+ import { fetchAppFontFiles } from '../app-fonts'
18
+
19
+ type ManifestEntry = {
20
+ url: string
21
+ urlhash: string
22
+ contentType: string
23
+ encoding: 'gzip'
24
+ sizeBytes: number
25
+ rawBytes: number
26
+ }
27
+
28
+ function flag(args: string[], name: string): string | undefined {
29
+ const idx = args.indexOf(`--${name}`)
30
+ if (idx !== -1 && idx + 1 < args.length) return args[idx + 1]
31
+ const inline = args.find((a) => a.startsWith(`--${name}=`))
32
+ return inline ? inline.slice(name.length + 3) : undefined
33
+ }
34
+
35
+ async function stage(args: string[]): Promise<void> {
36
+ const wire = flag(args, 'wire') || ''
37
+ const outDir = flag(args, 'out-dir')
38
+ const manifestPath = flag(args, 'manifest')
39
+ if (!outDir || !manifestPath) {
40
+ console.error(
41
+ ' usage: rnxsim app-fonts stage --wire <wire> --out-dir <dir> --manifest <path>',
42
+ )
43
+ process.exit(1)
44
+ }
45
+ if (!wire.trim()) {
46
+ console.log('no app fonts declared — nothing to stage')
47
+ return
48
+ }
49
+
50
+ mkdirSync(outDir, { recursive: true })
51
+ const fonts = await fetchAppFontFiles(wire, {
52
+ onStaged: ({ url, byteLength }) =>
53
+ console.log(` staged app font: ${url} (${(byteLength / 1024).toFixed(1)} KiB)`),
54
+ onError: (url, err) =>
55
+ console.error(
56
+ ` warning: failed to fetch app font ${url}: ${err instanceof Error ? err.message : err}`,
57
+ ),
58
+ })
59
+
60
+ const descriptors: ManifestEntry[] = []
61
+ for (const font of fonts) {
62
+ const gz = gzipSync(font.bytes)
63
+ writeFileSync(join(outDir, font.urlhash), gz)
64
+ descriptors.push({
65
+ url: font.url,
66
+ urlhash: font.urlhash,
67
+ contentType: font.contentType,
68
+ encoding: 'gzip',
69
+ sizeBytes: gz.length,
70
+ rawBytes: font.bytes.byteLength,
71
+ })
72
+ }
73
+
74
+ let existing: ManifestEntry[] = []
75
+ if (existsSync(manifestPath)) {
76
+ try {
77
+ const parsed: unknown = JSON.parse(readFileSync(manifestPath, 'utf8'))
78
+ if (Array.isArray(parsed)) existing = parsed as ManifestEntry[]
79
+ } catch {}
80
+ }
81
+ const seen = new Set(existing.map((e) => e.urlhash))
82
+ const merged = [...existing, ...descriptors.filter((d) => !seen.has(d.urlhash))]
83
+ writeFileSync(manifestPath, JSON.stringify(merged))
84
+ console.log(
85
+ `staged ${descriptors.length} app font(s); manifest now has ${merged.length} file(s)`,
86
+ )
87
+ }
88
+
89
+ export async function runAppFonts(args: string[]): Promise<void> {
90
+ const sub = args[0]
91
+ if (sub === 'stage') {
92
+ await stage(args.slice(1))
93
+ return
94
+ }
95
+ console.error(` unknown app-fonts subcommand: ${sub ?? '(none)'}`)
96
+ console.error(' available: stage')
97
+ process.exit(1)
98
+ }