sootsim 0.1.201 → 0.1.203

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 (151) hide show
  1. package/dist-cli/bin.js +5 -4
  2. package/dist-cli/chunks/{agent-SHGFOKZN.js → agent-PWM4XT5H.js} +2 -2
  3. package/dist-cli/chunks/{agent-wrapper-3O4ZW24C.js → agent-wrapper-V2BSTANB.js} +2 -2
  4. package/dist-cli/chunks/{app-fonts-KZOBGGZQ.js → app-fonts-7M4PTF6W.js} +2 -2
  5. package/dist-cli/chunks/{assert-RZCBKONA.js → assert-SEW5OJL3.js} +2 -2
  6. package/dist-cli/chunks/{auth-PBD7GLXL.js → auth-3YY55NBL.js} +2 -2
  7. package/dist-cli/chunks/beta-Y4ZJUKAM.js +2 -0
  8. package/dist-cli/chunks/{camera-5OOLGGLN.js → camera-CYXCASB3.js} +2 -2
  9. package/dist-cli/chunks/{chunk-HVSDT56M.js → chunk-4NHPXU3X.js} +1 -1
  10. package/dist-cli/chunks/{chunk-423YVBZK.js → chunk-62AKBZTO.js} +1 -1
  11. package/dist-cli/chunks/{chunk-WJ7YQAKC.js → chunk-6DN4BD7O.js} +38 -38
  12. package/dist-cli/chunks/{chunk-FITJFYBO.js → chunk-6M56UHEY.js} +2 -2
  13. package/dist-cli/chunks/{chunk-T6WXCSWP.js → chunk-A3FIOG7U.js} +2 -2
  14. package/dist-cli/chunks/{chunk-7672K2JN.js → chunk-B7VBDZ3U.js} +1 -1
  15. package/dist-cli/chunks/{chunk-63EDUOKZ.js → chunk-BBOFH45Q.js} +2 -2
  16. package/dist-cli/chunks/{chunk-SKGV3OSH.js → chunk-BJJXNQHO.js} +2 -2
  17. package/dist-cli/chunks/{chunk-7GG4TZ4L.js → chunk-BL67OSVN.js} +2 -2
  18. package/dist-cli/chunks/{chunk-EVCOHQPK.js → chunk-EBH65V62.js} +3 -3
  19. package/dist-cli/chunks/{chunk-NYNAI5PO.js → chunk-FF3C57T5.js} +2 -2
  20. package/dist-cli/chunks/{chunk-JEJV3UHZ.js → chunk-FUC7C5HS.js} +2 -2
  21. package/dist-cli/chunks/{chunk-XAFLM5JS.js → chunk-G5GRLVYA.js} +2 -2
  22. package/dist-cli/chunks/chunk-G5VOIXM7.js +1 -0
  23. package/dist-cli/chunks/{chunk-D6CTB275.js → chunk-GMVAXDHH.js} +1 -1
  24. package/dist-cli/chunks/{chunk-S2AQ4WGX.js → chunk-GTBF3M2H.js} +1 -1
  25. package/dist-cli/chunks/{chunk-RN662UDP.js → chunk-GYTATFQA.js} +2 -2
  26. package/dist-cli/chunks/{chunk-AHJ2WJST.js → chunk-JLOAWSX6.js} +1 -1
  27. package/dist-cli/chunks/{chunk-ENY46QHT.js → chunk-K3CRSIGS.js} +2 -2
  28. package/dist-cli/chunks/{chunk-SVM25PDV.js → chunk-LKJ5LA6K.js} +6 -6
  29. package/dist-cli/chunks/{chunk-SZVYOFMB.js → chunk-LTRNOX6N.js} +2 -2
  30. package/dist-cli/chunks/{chunk-3RAGDMGM.js → chunk-MQHSWXDS.js} +1 -1
  31. package/dist-cli/chunks/{chunk-SQXH3XGO.js → chunk-NHSO4473.js} +2 -2
  32. package/dist-cli/chunks/chunk-ODW7RHSD.js +97 -0
  33. package/dist-cli/chunks/{chunk-FPRZHFV2.js → chunk-OK7QEDHD.js} +2 -2
  34. package/dist-cli/chunks/{chunk-CHVGDYQJ.js → chunk-OXQOPTTB.js} +1 -1
  35. package/dist-cli/chunks/{chunk-F5TOTCUW.js → chunk-P4GJL7OH.js} +2 -2
  36. package/dist-cli/chunks/chunk-PELEQURX.js +4 -0
  37. package/dist-cli/chunks/chunk-QKDII5UB.js +1 -0
  38. package/dist-cli/chunks/chunk-R7GIVBTY.js +2 -0
  39. package/dist-cli/chunks/{chunk-GBUUYMPP.js → chunk-RVOF6RIE.js} +1 -1
  40. package/dist-cli/chunks/chunk-RZU5TDPJ.js +29 -0
  41. package/dist-cli/chunks/{chunk-HIWE4YYN.js → chunk-U6OCMLMU.js} +2 -2
  42. package/dist-cli/chunks/{chunk-MQEEYPOK.js → chunk-UJ64GJSZ.js} +1 -1
  43. package/dist-cli/chunks/{chunk-YOPEO6SA.js → chunk-UZGLGCLM.js} +1 -1
  44. package/dist-cli/chunks/{chunk-QTI33DV5.js → chunk-WSOZGPIX.js} +2 -2
  45. package/dist-cli/chunks/{chunk-CPVTNQAS.js → chunk-WVF2EDZF.js} +1 -1
  46. package/dist-cli/chunks/{chunk-ZSWQLDDQ.js → chunk-XYMOH3HP.js} +1 -1
  47. package/dist-cli/chunks/{chunk-WHNPGZX4.js → chunk-YJNJ5GVC.js} +3 -3
  48. package/dist-cli/chunks/{chunk-USGQNFAM.js → chunk-YP3NIRTK.js} +1 -1
  49. package/dist-cli/chunks/chunk-ZGM7N2AV.js +7 -0
  50. package/dist-cli/chunks/{chunk-NIDV74L2.js → chunk-ZRWVLKFL.js} +1 -1
  51. package/dist-cli/chunks/cli-version-N2RKZ2CU.js +2 -0
  52. package/dist-cli/chunks/{compat-NNM7DTTO.js → compat-FK5MP535.js} +3 -3
  53. package/dist-cli/chunks/{config-LBGQRC2P.js → config-T3W2HI67.js} +2 -2
  54. package/dist-cli/chunks/{control-5DHHQZ26.js → control-ONFLGDEC.js} +2 -2
  55. package/dist-cli/chunks/daemon-FDI5YYZN.js +2 -0
  56. package/dist-cli/chunks/{debug-PILWFGN3.js → debug-Z6NG4KY2.js} +3 -3
  57. package/dist-cli/chunks/{desktop-CZ43IZFV.js → desktop-BIWB2UYC.js} +3 -3
  58. package/dist-cli/chunks/detox-6K7WFLQO.js +50 -0
  59. package/dist-cli/chunks/{device-M26JCUHY.js → device-TPD5WAP2.js} +2 -2
  60. package/dist-cli/chunks/{diagnose-HZZMVPQZ.js → diagnose-NACPOTYX.js} +2 -2
  61. package/dist-cli/chunks/drivers-G2YZR6G6.js +2 -0
  62. package/dist-cli/chunks/flow-OAW2MZCD.js +2 -0
  63. package/dist-cli/chunks/help-MY2CBECX.js +2 -0
  64. package/dist-cli/chunks/home-paths-WWFDX6YU.js +2 -0
  65. package/dist-cli/chunks/inspect-ZPVPUSAK.js +2 -0
  66. package/dist-cli/chunks/install-desktop-QZWSSGJV.js +2 -0
  67. package/dist-cli/chunks/{login-VBCYZKJ6.js → login-WGCO2V4S.js} +4 -4
  68. package/dist-cli/chunks/{logout-J22GLKHX.js → logout-VWSSNYF5.js} +2 -2
  69. package/dist-cli/chunks/maestro-YED424Y6.js +96 -0
  70. package/dist-cli/chunks/{mode-XN46XIMK.js → mode-QCOM4UM4.js} +2 -2
  71. package/dist-cli/chunks/optional-demo-registry-3KZFUZZD.js +2 -0
  72. package/dist-cli/chunks/{perf-ZIYESQRA.js → perf-FZHCFAID.js} +2 -2
  73. package/dist-cli/chunks/{record-L74E3HCL.js → record-NF3PKBSW.js} +3 -3
  74. package/dist-cli/chunks/runtime-ETELTKFT.js +2 -0
  75. package/dist-cli/chunks/screenshot-command-KLPOA5TW.js +151 -0
  76. package/dist-cli/chunks/screenshots-capture-MCTZSXLE.js +41 -0
  77. package/dist-cli/chunks/{serve-CNDRR7XN.js → serve-XBWYWHMC.js} +18 -18
  78. package/dist-cli/chunks/{setup-XZDN7XMI.js → setup-W7EROACZ.js} +3 -3
  79. package/dist-cli/chunks/{skills-KJK67CVB.js → skills-RBGNF7GS.js} +2 -2
  80. package/dist-cli/chunks/{storage-UOLMRHLQ.js → storage-3SFE2DUE.js} +2 -2
  81. package/dist-cli/chunks/store-Z3CHVRR3.js +2 -0
  82. package/dist-cli/chunks/telemetry-SWFOAVWP.js +2 -0
  83. package/dist-cli/chunks/test-UP6VTFKE.js +69 -0
  84. package/dist-cli/chunks/{timeline-UJFIJ2GT.js → timeline-A54JB74A.js} +2 -2
  85. package/dist-cli/chunks/upgrade-H7XE3N76.js +4 -0
  86. package/dist-cli/chunks/upload-X2BRKPBJ.js +2 -0
  87. package/dist-cli/chunks/version-4JV7HX23.js +4 -0
  88. package/dist-cli/chunks/{web-QP4KDHR6.js → web-5OLZXKVF.js} +2 -2
  89. package/dist-cli/chunks/{what-happened-VW274SXG.js → what-happened-Q4L6SI4I.js} +2 -2
  90. package/dist-lib/agent-daemon-client.cjs +1 -1
  91. package/dist-lib/agent-events.cjs +1 -1
  92. package/dist-lib/agent-identity.cjs +1 -1
  93. package/dist-lib/agent-sessions.cjs +1 -1
  94. package/dist-lib/attached-projects.cjs +1 -1
  95. package/dist-lib/auth/shared-session.cjs +1 -1
  96. package/dist-lib/backend-origin.cjs +1 -1
  97. package/dist-lib/beta.cjs +1 -1
  98. package/dist-lib/beta.mjs +1 -1
  99. package/dist-lib/bridge-constants.cjs +1 -1
  100. package/dist-lib/cli-constants.cjs +1 -1
  101. package/dist-lib/config.cjs +1 -1
  102. package/dist-lib/detox/index.cjs +1 -1
  103. package/dist-lib/dev-bundle-resolution.cjs +1 -1
  104. package/dist-lib/home-paths.cjs +32 -1
  105. package/dist-lib/host/bridge-host.cjs +51 -2
  106. package/dist-lib/host/fetch-proxy-handler.cjs +1 -1
  107. package/dist-lib/host/fetch-proxy-overrides.cjs +1 -1
  108. package/dist-lib/host/fetch-proxy-overrides.mjs +1 -1
  109. package/dist-lib/host/websocket-proxy.cjs +1 -1
  110. package/dist-lib/index.cjs +1 -1
  111. package/dist-lib/jump-to-source-babel.cjs +1 -1
  112. package/dist-lib/menu.cjs +1 -1
  113. package/dist-lib/menu.mjs +1 -1
  114. package/dist-lib/metro.cjs +1 -1
  115. package/dist-lib/profiles.cjs +1 -1
  116. package/dist-lib/render-mode.cjs +1 -1
  117. package/dist-lib/scripts/dev-server-scanner.cjs +1 -1
  118. package/dist-lib/sdk.cjs +1 -1
  119. package/dist-lib/sdk.mjs +1 -1
  120. package/dist-lib/skills.cjs +104 -19
  121. package/dist-lib/vite.cjs +1 -1
  122. package/package.json +1 -1
  123. package/src/home-paths.ts +48 -1
  124. package/src/host/bridge-host.ts +12 -0
  125. package/src/runtime-delivery.ts +59 -9
  126. package/dist-cli/chunks/beta-EJBRLRKG.js +0 -2
  127. package/dist-cli/chunks/chunk-3W273A5J.js +0 -4
  128. package/dist-cli/chunks/chunk-5GICTRK5.js +0 -1
  129. package/dist-cli/chunks/chunk-AGSCFR4P.js +0 -27
  130. package/dist-cli/chunks/chunk-O56GZV3H.js +0 -1
  131. package/dist-cli/chunks/chunk-ORIISY22.js +0 -6
  132. package/dist-cli/chunks/chunk-PMPQ57UY.js +0 -92
  133. package/dist-cli/chunks/cli-version-WTA2LUDV.js +0 -2
  134. package/dist-cli/chunks/daemon-3KGXTPXJ.js +0 -2
  135. package/dist-cli/chunks/detox-D6XW7Y4V.js +0 -49
  136. package/dist-cli/chunks/drivers-7ZM3KW22.js +0 -2
  137. package/dist-cli/chunks/flow-DDDWJ4KD.js +0 -2
  138. package/dist-cli/chunks/help-23GXSWP3.js +0 -2
  139. package/dist-cli/chunks/home-paths-746ZDH2I.js +0 -2
  140. package/dist-cli/chunks/inspect-T37ALZRL.js +0 -2
  141. package/dist-cli/chunks/install-desktop-FSY2ND5S.js +0 -2
  142. package/dist-cli/chunks/maestro-5LWJ2S6K.js +0 -96
  143. package/dist-cli/chunks/optional-demo-registry-YF4W5LPU.js +0 -2
  144. package/dist-cli/chunks/runtime-7WSR27U6.js +0 -2
  145. package/dist-cli/chunks/screenshot-command-ZCI5QE4T.js +0 -190
  146. package/dist-cli/chunks/store-FGCNPJBA.js +0 -2
  147. package/dist-cli/chunks/telemetry-QEO7INJC.js +0 -2
  148. package/dist-cli/chunks/test-5DK2XCRU.js +0 -69
  149. package/dist-cli/chunks/upgrade-CXZFJIH7.js +0 -4
  150. package/dist-cli/chunks/upload-ZFINR6K3.js +0 -2
  151. package/dist-cli/chunks/version-XMSYOSAX.js +0 -4
@@ -1,5 +1,5 @@
1
- /*! sootsim v0.1.201 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
- import{a as ue,c as pe,d as he,e as ze,f as fe,g as me,h as Ke,i as ge,j as qe}from"./chunk-WHNPGZX4.js";import{a as Ge}from"./chunk-XAFLM5JS.js";import{a as Ze}from"./chunk-SZVYOFMB.js";import{a as Ye}from"./chunk-PMPQ57UY.js";import{h as je,p as Ue,r as Ve,v as Je}from"./chunk-ENY46QHT.js";import{f as _e}from"./chunk-63EDUOKZ.js";import{a as Oe}from"./chunk-HVSDT56M.js";import{h as de,m as He}from"./chunk-F5TOTCUW.js";import{I as U,m as De,n as Be,o as Ce,p as Ne}from"./chunk-ZSWQLDDQ.js";import{g as le,h as ce,i as Le}from"./chunk-HIWE4YYN.js";import{a as We}from"./chunk-CPVTNQAS.js";import{a as Pe,b as se}from"./chunk-QTI33DV5.js";import{d as ae,e as Me}from"./chunk-CHVGDYQJ.js";import{g as Ae,h as Re}from"./chunk-423YVBZK.js";import*as $ from"fs";import{tmpdir as te}from"os";import*as b from"path";import*as S from"fs";import*as y from"path";var wt="inset 0 0 0 0.5px #000, inset 0 0 0 2px #757575, inset 0 0 0 5px #212121",Qe=1;function yt(n){let e=Re(n),t=e.scale,r=e.statusBarHeight>0&&!e.dynamicIsland&&e.homeIndicatorHeight===0&&e.cornerRadius===0,i=e.width,o=e.height,a=r?e.width+58:e.width+e.bezelWidth*2,s=r?e.height+111+111:e.height+e.bezelWidth*2,l=9.5,p=Qe,h=a+l*2,g=s+Qe*2,E=l+(r?29:e.bezelWidth),m=r?111:e.bezelWidth,k=r?52:e.cornerRadius+e.bezelWidth,_=[{side:"right",top:e.hardwareButtons.lock.top,height:e.hardwareButtons.lock.height,width:e.hardwareButtons.width},{side:"left",top:e.hardwareButtons.ringToggle.top,height:e.hardwareButtons.ringToggle.height,width:e.hardwareButtons.width},{side:"left",top:e.hardwareButtons.volumeUp.top,height:e.hardwareButtons.volumeUp.height,width:e.hardwareButtons.width},{side:"left",top:e.hardwareButtons.volumeDown.top,height:e.hardwareButtons.volumeDown.height,width:e.hardwareButtons.width}];return{model:n,renderScale:t,outerWidth:Math.round(h*t),outerHeight:Math.round(g*t),logicalOuterWidth:h,logicalOuterHeight:g,logicalFrameWidth:a,logicalFrameHeight:s,logicalFrameLeft:l,logicalFrameTop:p,logicalScreenWidth:i,logicalScreenHeight:o,logicalScreenLeft:E,logicalScreenTop:m,logicalScreenRadius:r?0:e.cornerRadius,logicalFrameRadius:k,frameBackground:r?"linear-gradient(180deg, #1b1c20 0%, #0f1012 42%, #050608 100%)":"#000000",frameOutline:r?"0 0 0 1px #1f2125":"0 0 0 1px #333",metallicRingShadow:r?null:wt,buttons:_,legacyHomeButton:r?{top:111+e.height+47/2,left:e.width/2-64/2+29,size:64,ring:1.5}:null,showHomeIndicator:e.homeIndicatorHeight>0,logicalHomeIndicatorStripHeight:e.homeIndicatorHeight}}function bt(n){let e=n.side==="right",t=e?"inset(-3px -3px -3px 0)":"inset(-3px 0 -3px -3px)";return`
1
+ /*! sootsim v0.1.203 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
+ import{a as he,c as fe,d as me,e as Ye,f as ge,g as we,h as Ze,i as ye,j as Xe}from"./chunk-YJNJ5GVC.js";import{a as qe}from"./chunk-G5GRLVYA.js";import{a as et}from"./chunk-LTRNOX6N.js";import{a as Qe}from"./chunk-ODW7RHSD.js";import{h as Je,p as Ge,r as ze,v as Ke}from"./chunk-K3CRSIGS.js";import{f as Le}from"./chunk-BBOFH45Q.js";import{a as Be}from"./chunk-4NHPXU3X.js";import{h as pe,m as Ue}from"./chunk-P4GJL7OH.js";import{I as V,m as Ce,n as Ne,o as He,p as We}from"./chunk-XYMOH3HP.js";import{g as ce,h as ue,i as je}from"./chunk-U6OCMLMU.js";import{a as Ve}from"./chunk-WVF2EDZF.js";import{a as Me,b as le}from"./chunk-WSOZGPIX.js";import{d as de,e as De}from"./chunk-OXQOPTTB.js";import{g as Oe,h as _e}from"./chunk-62AKBZTO.js";import*as k from"fs";import{tmpdir as ie}from"os";import*as w from"path";import*as S from"fs";import*as b from"path";var vt="inset 0 0 0 0.5px #000, inset 0 0 0 2px #757575, inset 0 0 0 5px #212121",it=1;function xt(n){let e=_e(n),t=e.scale,i=e.statusBarHeight>0&&!e.dynamicIsland&&e.homeIndicatorHeight===0&&e.cornerRadius===0,r=e.width,o=e.height,a=i?e.width+58:e.width+e.bezelWidth*2,s=i?e.height+111+111:e.height+e.bezelWidth*2,l=9.5,u=it,p=a+l*2,m=s+it*2,x=l+(i?29:e.bezelWidth),g=i?111:e.bezelWidth,P=i?52:e.cornerRadius+e.bezelWidth,_=[{side:"right",top:e.hardwareButtons.lock.top,height:e.hardwareButtons.lock.height,width:e.hardwareButtons.width},{side:"left",top:e.hardwareButtons.ringToggle.top,height:e.hardwareButtons.ringToggle.height,width:e.hardwareButtons.width},{side:"left",top:e.hardwareButtons.volumeUp.top,height:e.hardwareButtons.volumeUp.height,width:e.hardwareButtons.width},{side:"left",top:e.hardwareButtons.volumeDown.top,height:e.hardwareButtons.volumeDown.height,width:e.hardwareButtons.width}];return{model:n,renderScale:t,outerWidth:Math.round(p*t),outerHeight:Math.round(m*t),logicalOuterWidth:p,logicalOuterHeight:m,logicalFrameWidth:a,logicalFrameHeight:s,logicalFrameLeft:l,logicalFrameTop:u,logicalScreenWidth:r,logicalScreenHeight:o,logicalScreenLeft:x,logicalScreenTop:g,logicalScreenRadius:i?0:e.cornerRadius,logicalFrameRadius:P,frameBackground:i?"linear-gradient(180deg, #1b1c20 0%, #0f1012 42%, #050608 100%)":"#000000",frameOutline:i?"0 0 0 1px #1f2125":"0 0 0 1px #333",metallicRingShadow:i?null:vt,buttons:_,legacyHomeButton:i?{top:111+e.height+47/2,left:e.width/2-64/2+29,size:64,ring:1.5}:null,showHomeIndicator:e.homeIndicatorHeight>0,logicalHomeIndicatorStripHeight:e.homeIndicatorHeight}}function Tt(n){let e=n.side==="right",t=e?"inset(-3px -3px -3px 0)":"inset(-3px 0 -3px -3px)";return`
3
3
  <div
4
4
  aria-hidden="true"
5
5
  style="
@@ -24,7 +24,7 @@ import{a as ue,c as pe,d as he,e as ze,f as fe,g as me,h as Ke,i as ge,j as qe}f
24
24
  z-index:2;
25
25
  "
26
26
  ></div>
27
- `}function St(n,e){let t=n.buttons.map(bt).join(""),r=n.metallicRingShadow?`
27
+ `}function Et(n,e){let t=n.buttons.map(Tt).join(""),i=n.metallicRingShadow?`
28
28
  <div
29
29
  aria-hidden="true"
30
30
  style="
@@ -36,7 +36,7 @@ import{a as ue,c as pe,d as he,e as ze,f as fe,g as me,h as Ke,i as ge,j as qe}f
36
36
  z-index:10;
37
37
  "
38
38
  ></div>
39
- `:"",i=n.legacyHomeButton?`
39
+ `:"",r=n.legacyHomeButton?`
40
40
  <div
41
41
  aria-hidden="true"
42
42
  style="
@@ -155,8 +155,8 @@ import{a as ue,c as pe,d as he,e as ze,f as fe,g as me,h as Ke,i as ge,j as qe}f
155
155
  "
156
156
  >
157
157
  ${t}
158
- ${r}
159
158
  ${i}
159
+ ${r}
160
160
  <div
161
161
  id="screen"
162
162
  style="
@@ -177,7 +177,7 @@ import{a as ue,c as pe,d as he,e as ze,f as fe,g as me,h as Ke,i as ge,j as qe}f
177
177
  </div>
178
178
  </div>
179
179
  </body>
180
- </html>`}async function et(n,e){let{chromium:t}=await import("playwright"),r=await t.launch({headless:!0});try{let i=await vt(r);try{return await i.compose(n,e)}finally{await i.close()}}finally{await r.close()}}async function vt(n){let e=new Map;async function t(r){let i=e.get(r);if(i)return i;let o=yt(r),a=await n.newContext({viewport:{width:o.outerWidth,height:o.outerHeight},deviceScaleFactor:1}),s=await a.newPage(),l={layout:o,context:a,page:s};return e.set(r,l),l}return{async compose(r,i){let o=await t(i),a=`data:image/png;base64,${r.toString("base64")}`;return await o.page.setContent(St(o.layout,a),{waitUntil:"load"}),await o.page.waitForTimeout(20),await o.page.screenshot({type:"png",clip:{x:0,y:0,width:o.layout.outerWidth,height:o.layout.outerHeight},omitBackground:!0})},async close(){for(let r of e.values())await r.context.close();e.clear()}}}import{spawnSync as xt}from"child_process";import*as N from"vm";var Tt=3e5,Et=`
180
+ </html>`}async function rt(n,e){let{chromium:t}=await import("playwright"),i=await t.launch({headless:!0});try{let r=await Ft(i);try{return await r.compose(n,e)}finally{await r.close()}}finally{await i.close()}}async function Ft(n){let e=new Map;async function t(i){let r=e.get(i);if(r)return r;let o=xt(i),a=await n.newContext({viewport:{width:o.outerWidth,height:o.outerHeight},deviceScaleFactor:1}),s=await a.newPage(),l={layout:o,context:a,page:s};return e.set(i,l),l}return{async compose(i,r){let o=await t(r),a=`data:image/png;base64,${i.toString("base64")}`;return await o.page.setContent(Et(o.layout,a),{waitUntil:"load"}),await o.page.waitForTimeout(20),await o.page.screenshot({type:"png",clip:{x:0,y:0,width:o.layout.outerWidth,height:o.layout.outerHeight},omitBackground:!0})},async close(){for(let i of e.values())await i.context.close();e.clear()}}}import{spawnSync as It}from"child_process";import*as C from"vm";var $t=3e5,kt=`
181
181
  let input = '';
182
182
  process.stdin.on('data', (c) => { input += c });
183
183
  process.stdin.on('end', async () => {
@@ -199,7 +199,7 @@ process.stdin.on('end', async () => {
199
199
  process.exitCode = 1;
200
200
  }
201
201
  });
202
- `;function V(n,e,t){if(t?.multipartForm)throw new Error("http: multipartForm is not supported by sootsim yet");let r={...process.env};for(let s of Object.keys(r))(s.startsWith("BUN_INSPECT")||s==="NODE_OPTIONS")&&delete r[s];let i=xt(process.execPath,["-e",Et],{input:JSON.stringify({url:n,method:e,headers:t?.headers,body:t?.body}),encoding:"utf8",timeout:Tt,maxBuffer:64*1024*1024,env:r});if(i.error)throw new Error(`http ${e} ${n} failed: ${i.error.message}`);let o;try{o=JSON.parse(i.stdout||"")}catch{throw new Error(`http ${e} ${n} failed: no response (${(i.stderr||"").trim().slice(0,200)})`)}let a=o;if(a.__error)throw new Error(`http ${e} ${n} failed: ${a.__error}`);return a}var Ft=/(?<!\\)\$\{([^$]*)\}/g,It=/\\(\$\{[^$]*\})/g,$t=/^[A-Za-z_$][A-Za-z0-9_$]*$/,Y=class{context;envBinding=new Map;envScopeStack=[];syncedEnvKeys=new Set;output={};maestro;constructor(e={}){this.maestro={copiedText:null,platform:e.platform??"ios"};let t=e.onLog??(i=>console.log(`[flow] js: ${i}`)),r={output:this.output,maestro:this.maestro,http:{get:(i,o)=>V(i,"GET",o),post:(i,o)=>V(i,"POST",o),put:(i,o)=>V(i,"PUT",o),delete:(i,o)=>V(i,"DELETE",o),request:(i,o)=>V(i,(o?.method??"GET").toUpperCase(),o)},console:{log:(...i)=>t(i.map(o=>typeof o=="string"?o:tt(o)).join(" "))}};this.context=N.createContext(r),N.runInContext(`
202
+ `;function J(n,e,t){if(t?.multipartForm)throw new Error("http: multipartForm is not supported by sootsim yet");let i={...process.env};for(let s of Object.keys(i))(s.startsWith("BUN_INSPECT")||s==="NODE_OPTIONS")&&delete i[s];let r=It(process.execPath,["-e",kt],{input:JSON.stringify({url:n,method:e,headers:t?.headers,body:t?.body}),encoding:"utf8",timeout:$t,maxBuffer:64*1024*1024,env:i});if(r.error)throw new Error(`http ${e} ${n} failed: ${r.error.message}`);let o;try{o=JSON.parse(r.stdout||"")}catch{throw new Error(`http ${e} ${n} failed: no response (${(r.stderr||"").trim().slice(0,200)})`)}let a=o;if(a.__error)throw new Error(`http ${e} ${n} failed: ${a.__error}`);return a}var Pt=/(?<!\\)\$\{([^$]*)\}/g,At=/\\(\$\{[^$]*\})/g,Rt=/^[A-Za-z_$][A-Za-z0-9_$]*$/,Y=class{context;envBinding=new Map;envScopeStack=[];syncedEnvKeys=new Set;output={};maestro;constructor(e={}){this.maestro={copiedText:null,platform:e.platform??"ios"};let t=e.onLog??(r=>console.log(`[flow] js: ${r}`)),i={output:this.output,maestro:this.maestro,http:{get:(r,o)=>J(r,"GET",o),post:(r,o)=>J(r,"POST",o),put:(r,o)=>J(r,"PUT",o),delete:(r,o)=>J(r,"DELETE",o),request:(r,o)=>J(r,(o?.method??"GET").toUpperCase(),o)},console:{log:(...r)=>t(r.map(o=>typeof o=="string"?o:nt(o)).join(" "))}};this.context=C.createContext(i),C.runInContext(`
203
203
  globalThis.__maestroScope = new Proxy(globalThis, {
204
204
  has() { return true },
205
205
  get(target, key) { return target[key] },
@@ -210,13 +210,13 @@ process.stdin.on('end', async () => {
210
210
  var yPercent = Math.ceil(y * 100) + '%'
211
211
  return xPercent + ',' + yPercent
212
212
  }
213
- `,this.context);for(let[i,o]of Object.entries(process.env))o!==void 0&&this.envBinding.set(i,o)}putEnv(e,t){this.envBinding.set(e,t)}setCopiedText(e){this.maestro.copiedText=e}enterEnvScope(){this.envScopeStack.push(new Map(this.envBinding))}leaveEnvScope(){let e=this.envScopeStack.pop();if(e){this.envBinding.clear();for(let[t,r]of e)this.envBinding.set(t,r)}}evaluate(e,t={}){let r=t.env;if(r&&Object.keys(r).length>0){this.enterEnvScope();try{for(let[i,o]of Object.entries(r))this.envBinding.set(i,o);return this.evalRaw(e)}finally{this.leaveEnvScope()}}return this.evalRaw(e)}evalRaw(e){this.syncEnvToContext();let t=e.replace(/\\/g,"\\\\").replace(/`/g,"\\`").replace(/\$\{/g,"\\${");return N.runInContext(`(function(){ with(__maestroScope){ return eval(\`${t}\`) } })()`,this.context)}syncEnvToContext(){let e=N.runInContext("globalThis",this.context);for(let t of this.syncedEnvKeys)this.envBinding.has(t)||delete e[t];this.syncedEnvKeys=new Set;for(let[t,r]of this.envBinding)try{e[t]=r,this.syncedEnvKeys.add(t)}catch{}}evaluateStringTemplate(e){return e.replace(Ft,(r,i)=>{if(i.trim().length===0)return"";let o=this.evaluate(i);if(o===void 0&&$t.test(i.trim()))throw new Error(`missing variable for flow placeholder: ${i.trim()}`);return tt(o)}).replace(It,(r,i)=>i)}interpolateStep(e){return this.interpolateValue(e,null)}interpolateValue(e,t){return typeof e=="string"?t==="evalScript"?e:this.evaluateStringTemplate(e):Array.isArray(e)?t==="commands"||t==="onFlowStart"||t==="onFlowComplete"?e:e.map(r=>this.interpolateValue(r,t)):e&&typeof e=="object"?Object.fromEntries(Object.entries(e).map(([r,i])=>[r,this.interpolateValue(i,r)])):e}};function tt(n){if(n===void 0)return"undefined";if(n===null)return"null";if(typeof n=="object")try{return JSON.stringify(n)}catch{return String(n)}return String(n)}function rt(n){if(n==null)return!1;if(typeof n=="boolean")return n;let e=String(n);if(e.trim().length===0||e.toLowerCase()==="false"||e==="undefined"||e==="null")return!1;let t=Number(e);return!(!Number.isNaN(t)&&t===0)}var Z=1e4,Q=393,L=852;function f(n){return new Promise(e=>setTimeout(e,n))}function Se(n){return!!(n&&typeof n=="object"&&!Array.isArray(n))}function J(n,e){if(!Se(n))return null;let t=n[e];return typeof t=="string"&&t.length>0?t:null}function kt(n,e){return Se(n)?n[e]===!0:!1}function Pt(n){if(!n)return null;let e=n.recentApps;if(Array.isArray(e))for(let r of e){let i=J(r,"id");if(i)return i}let t=n.surfaceBindings;return J(t,"app:one")||J(t,"app:two")||null}function At(n){return n?y.basename(n)===".maestro"?y.dirname(n):n:process.cwd()}function Rt(n,e,t){let r=e.endsWith(".png")?e:`${e}.png`;if(y.isAbsolute(r))return r;if(t.mode==="flow"&&/[\\/]/.test(r)){let i=r.startsWith("./")||r.startsWith("../")?t.flowDir??process.cwd():At(t.flowDir);return y.resolve(i,r)}return y.join(n,r)}function Mt(n){if(typeof n=="string")return{path:n,withFrame:!1};let e=n.path?.trim()||n.name?.trim();if(!e)throw new Error("takeScreenshot object form requires path or name");return{path:e,withFrame:n.withFrame===!0,layers:n.layers}}function X(n,e){let[t,r]=n.split(",").map(s=>s.trim()),i=(s,l)=>s.endsWith("%")?Number.parseFloat(s)/100*l:Number.parseFloat(s),o=e?.x??0,a=e?.y??0;return{x:o+i(t,e?.width??Q),y:a+i(r,e?.height??L)}}function Ot(n){switch(n){case"back":return{back:!0};case"hideKeyboard":return{hideKeyboard:!0};case"waitForAnimationToEnd":return{waitForAnimationToEnd:!0};case"stopApp":return{stopApp:!0};case"clearState":return{clearState:!0};case"clearKeychain":return{clearKeychain:!0};case"eraseText":return{eraseText:50};case"scroll":case"scrollDown":return{scroll:{direction:"DOWN"}};case"scrollUp":return{scroll:{direction:"UP"}};default:return{[n]:!0}}}function _t(n){let e=n.split(/^---$/m),t=e.length>1?e[e.length-1]:n,r=Ge.parse(t);return Array.isArray(r)?r:[]}var ee=class{constructor(e,t){this.bridge=e;this.opts=t}stepDelay=0;js=new Y({platform:"ios",onLog:e=>console.log(`[flow] js: ${e}`)});firstLaunchDone=!1;profilingEnabled=!1;recordingEnabled=!1;recordingAccessChecked=!1;recordingStartedAtMs=null;lastRecordingStartedAtMs=null;lastRecordingDurationMs=null;lastRecordingFrameStats=null;flowTraceSteps=[];lastVisualSettledAtMs=0;simRouteHint=null;lastFailedStep=null;get simId(){return this.opts.simId}setSimRouteHint(e){this.simRouteHint=this.normalizeSimRoute(e)}normalizeSimRoute(e){if(!e)return null;try{let t=new URL(e);t.searchParams.delete("inspectOpen");let r=t.searchParams.toString();return`${t.origin}${t.pathname}${r?`?${r}`:""}`}catch{return e}}async refreshSimId(){if(this.opts.simId)try{let e=await this.bridge.listSims(),t=e.find(l=>l.id===this.opts.simId);if(t&&(this.simRouteHint=this.normalizeSimRoute(t.url||t.origin)),e.find(l=>l.id===this.opts.simId&&l.readyState==="open")||!this.simRouteHint)return;let i=this.simRouteHint&&e.find(l=>l.readyState==="open"&&this.normalizeSimRoute(l.url||l.origin)===this.simRouteHint);if(!i)return;let o=e.find(l=>l.isPrimary&&l.readyState==="open"),a=e.find(l=>l.readyState==="open"),s=i??o??a;s&&(this.opts.simId=s.id,console.log(` [flow] sim rotated to ${s.id}`))}catch{}}async evaluate(e,t){return this.bridge.send({type:"evaluate",simId:this.opts.simId,code:e},t?{timeoutMs:t}:void 0)}async callTest(e,...t){return this.bridge.send({type:"call",simId:this.opts.simId,path:`__sootsimTest.${e}`,args:t})}async waitForTree(e=Z){let t=Date.now()+e,r=Date.now(),i=null,o=0,a=0,s=-1,l=r;for(;Date.now()<t;){try{let h=await this.evaluate(De,8e3);if(o=0,h?.externalError)throw new Error(`app failed to load: ${h.externalError}`);if(h){let g=Date.now();h.nodes!==s&&(s=h.nodes,l=g);let E=h.flag===!0&&Ce(h),m=h.flag!==!0&&Ne(h);if((E||m)&&h.externalReady!==!1&&!h.externalError&&!h.loadingText&&g-l>=Be)return}}catch(h){if(i=h instanceof Error?h:new Error(String(h)),i.message.startsWith("app failed to load:"))throw i;if(o++,o>=4)throw new Error(`target sim is not responding to the bridge (${i.message}). it is likely a stale orphan \u2014 run \`sootsim list\`, then close it with \`sootsim close <id>\` or start a fresh one with \`sootsim open --new <port>\`.`);await this.refreshSimId()}let p=Date.now()-r;p-a>=5e3&&(a=p,console.log(` [flow] waiting for app to be ready\u2026 (${Math.round(p/1e3)}s)`)),await f(500)}throw i?.message.startsWith("app failed to load:")?i:new Error(`app not ready after ${e}ms`)}async ensureRecordingStarted(){if(!this.opts.recordingOutputDir)throw new Error("recording output directory not configured");this.recordingAccessChecked||(this.opts.requireRecordingEntitlement&&await Ze("flow --video",{originOverride:this.opts.billingOriginOverride,allowGitHubAuth:this.opts.allowGitHubRecording}),this.recordingAccessChecked=!0);let e=Date.now(),t=await this.evaluate(`(() => {
213
+ `,this.context);for(let[r,o]of Object.entries(process.env))o!==void 0&&this.envBinding.set(r,o)}putEnv(e,t){this.envBinding.set(e,t)}setCopiedText(e){this.maestro.copiedText=e}enterEnvScope(){this.envScopeStack.push(new Map(this.envBinding))}leaveEnvScope(){let e=this.envScopeStack.pop();if(e){this.envBinding.clear();for(let[t,i]of e)this.envBinding.set(t,i)}}evaluate(e,t={}){let i=t.env;if(i&&Object.keys(i).length>0){this.enterEnvScope();try{for(let[r,o]of Object.entries(i))this.envBinding.set(r,o);return this.evalRaw(e)}finally{this.leaveEnvScope()}}return this.evalRaw(e)}evalRaw(e){this.syncEnvToContext();let t=e.replace(/\\/g,"\\\\").replace(/`/g,"\\`").replace(/\$\{/g,"\\${");return C.runInContext(`(function(){ with(__maestroScope){ return eval(\`${t}\`) } })()`,this.context)}syncEnvToContext(){let e=C.runInContext("globalThis",this.context);for(let t of this.syncedEnvKeys)this.envBinding.has(t)||delete e[t];this.syncedEnvKeys=new Set;for(let[t,i]of this.envBinding)try{e[t]=i,this.syncedEnvKeys.add(t)}catch{}}evaluateStringTemplate(e){return e.replace(Pt,(i,r)=>{if(r.trim().length===0)return"";let o=this.evaluate(r);if(o===void 0&&Rt.test(r.trim()))throw new Error(`missing variable for flow placeholder: ${r.trim()}`);return nt(o)}).replace(At,(i,r)=>r)}interpolateStep(e){return this.interpolateValue(e,null)}interpolateValue(e,t){return typeof e=="string"?t==="evalScript"?e:this.evaluateStringTemplate(e):Array.isArray(e)?t==="commands"||t==="onFlowStart"||t==="onFlowComplete"?e:e.map(i=>this.interpolateValue(i,t)):e&&typeof e=="object"?Object.fromEntries(Object.entries(e).map(([i,r])=>[i,this.interpolateValue(r,i)])):e}};function nt(n){if(n===void 0)return"undefined";if(n===null)return"null";if(typeof n=="object")try{return JSON.stringify(n)}catch{return String(n)}return String(n)}function ot(n){if(n==null)return!1;if(typeof n=="boolean")return n;let e=String(n);if(e.trim().length===0||e.toLowerCase()==="false"||e==="undefined"||e==="null")return!1;let t=Number(e);return!(!Number.isNaN(t)&&t===0)}var Z=1e4,Q=393,N=852;function f(n){return new Promise(e=>setTimeout(e,n))}function xe(n){return!!(n&&typeof n=="object"&&!Array.isArray(n))}function G(n,e){if(!xe(n))return null;let t=n[e];return typeof t=="string"&&t.length>0?t:null}function Mt(n,e){return xe(n)?n[e]===!0:!1}function Ot(n){if(!n)return null;let e=n.recentApps;if(Array.isArray(e))for(let i of e){let r=G(i,"id");if(r)return r}let t=n.surfaceBindings;return G(t,"app:one")||G(t,"app:two")||null}function _t(n){return n?b.basename(n)===".maestro"?b.dirname(n):n:process.cwd()}function Dt(n,e,t){let i=e.endsWith(".png")?e:`${e}.png`;if(b.isAbsolute(i))return i;if(t.mode==="flow"&&/[\\/]/.test(i)){let r=i.startsWith("./")||i.startsWith("../")?t.flowDir??process.cwd():_t(t.flowDir);return b.resolve(r,i)}return b.join(n,i)}function Bt(n){if(typeof n=="string")return{path:n,withFrame:!1};let e=n.path?.trim()||n.name?.trim();if(!e)throw new Error("takeScreenshot object form requires path or name");return{path:e,withFrame:n.withFrame===!0,layers:n.layers}}function X(n,e){let[t,i]=n.split(",").map(s=>s.trim()),r=(s,l)=>s.endsWith("%")?Number.parseFloat(s)/100*l:Number.parseFloat(s),o=e?.x??0,a=e?.y??0;return{x:o+r(t,e?.width??Q),y:a+r(i,e?.height??N)}}function st(n){switch(n){case"back":return{back:!0};case"hideKeyboard":return{hideKeyboard:!0};case"waitForAnimationToEnd":return{waitForAnimationToEnd:!0};case"stopApp":return{stopApp:!0};case"clearState":return{clearState:!0};case"clearKeychain":return{clearKeychain:!0};case"eraseText":return{eraseText:50};case"scroll":case"scrollDown":return{scroll:{direction:"DOWN"}};case"scrollUp":return{scroll:{direction:"UP"}};default:return{[n]:!0}}}function Lt(n){let e=n.split(/^---$/m),t=e.length>1?e[e.length-1]:n,i=qe.parse(t);return Array.isArray(i)?i:[]}var ee=class{constructor(e,t){this.bridge=e;this.opts=t}stepDelay=0;js=new Y({platform:"ios",onLog:e=>console.log(`[flow] js: ${e}`)});firstLaunchDone=!1;profilingEnabled=!1;recordingEnabled=!1;recordingAccessChecked=!1;recordingStartedAtMs=null;lastRecordingStartedAtMs=null;lastRecordingDurationMs=null;lastRecordingFrameStats=null;flowTraceSteps=[];lastVisualSettledAtMs=0;simRouteHint=null;lastFailedStep=null;get simId(){return this.opts.simId}setSimRouteHint(e){this.simRouteHint=this.normalizeSimRoute(e)}normalizeSimRoute(e){if(!e)return null;try{let t=new URL(e);t.searchParams.delete("inspectOpen");let i=t.searchParams.toString();return`${t.origin}${t.pathname}${i?`?${i}`:""}`}catch{return e}}async refreshSimId(){if(this.opts.simId)try{let e=await this.bridge.listSims(),t=e.find(l=>l.id===this.opts.simId);if(t&&(this.simRouteHint=this.normalizeSimRoute(t.url||t.origin)),e.find(l=>l.id===this.opts.simId&&l.readyState==="open")||!this.simRouteHint)return;let r=this.simRouteHint&&e.find(l=>l.readyState==="open"&&this.normalizeSimRoute(l.url||l.origin)===this.simRouteHint);if(!r)return;let o=e.find(l=>l.isPrimary&&l.readyState==="open"),a=e.find(l=>l.readyState==="open"),s=r??o??a;s&&(this.opts.simId=s.id,console.log(` [flow] sim rotated to ${s.id}`))}catch{}}async evaluate(e,t){return this.bridge.send({type:"evaluate",simId:this.opts.simId,code:e},t?{timeoutMs:t}:void 0)}async callTest(e,...t){return this.bridge.send({type:"call",simId:this.opts.simId,path:`__sootsimTest.${e}`,args:t})}async waitForTree(e=Z){let t=Date.now()+e,i=Date.now(),r=null,o=0,a=0,s=-1,l=i;for(;Date.now()<t;){try{let p=await this.evaluate(Ce,8e3);if(o=0,p?.externalError)throw new Error(`app failed to load: ${p.externalError}`);if(p){let m=Date.now();p.nodes!==s&&(s=p.nodes,l=m);let x=p.flag===!0&&He(p),g=p.flag!==!0&&We(p);if((x||g)&&p.externalReady!==!1&&!p.externalError&&!p.loadingText&&m-l>=Ne)return}}catch(p){if(r=p instanceof Error?p:new Error(String(p)),r.message.startsWith("app failed to load:"))throw r;if(o++,o>=4)throw new Error(`target sim is not responding to the bridge (${r.message}). it is likely a stale orphan \u2014 run \`sootsim list\`, then close it with \`sootsim close <id>\` or start a fresh one with \`sootsim open --new <port>\`.`);await this.refreshSimId()}let u=Date.now()-i;u-a>=5e3&&(a=u,console.log(` [flow] waiting for app to be ready\u2026 (${Math.round(u/1e3)}s)`)),await f(500)}throw r?.message.startsWith("app failed to load:")?r:new Error(`app not ready after ${e}ms`)}async ensureRecordingStarted(){if(!this.opts.recordingOutputDir)throw new Error("recording output directory not configured");this.recordingAccessChecked||(this.opts.requireRecordingEntitlement&&await et("flow --video",{originOverride:this.opts.billingOriginOverride,allowGitHubAuth:this.opts.allowGitHubRecording}),this.recordingAccessChecked=!0);let e=Date.now(),t=await this.evaluate(`(() => {
214
214
  const rec = window.__sootsimRecorder
215
215
  if (!rec) return { ok: false, error: 'recorder unavailable on this page' }
216
216
  const format = ${JSON.stringify(this.opts.recordingFormat??"webm")}
217
217
  if (rec.state() === 'recording') return { ok: true, format }
218
218
  return rec.start({ format, fps: 24 })
219
- })()`);if(!t?.ok)throw new Error(t?.error||"recording unavailable on this page");this.recordingStartedAtMs||(this.recordingStartedAtMs=typeof t.startedAtMs=="number"&&Number.isFinite(t.startedAtMs)?t.startedAtMs:e)}async startRecording(){this.recordingEnabled=!0,await this.ensureRecordingStarted()}prepareRecording(){this.recordingEnabled=!0}getLastRecordingDurationMs(){return this.lastRecordingDurationMs}getLastRecordingStartedAtMs(){return this.lastRecordingStartedAtMs}getLastRecordingFrameStats(){return this.lastRecordingFrameStats}getFlowTraceSteps(){return[...this.flowTraceSteps]}flowStepTargetLabel(e,t){if(t==="inputText"||t==="runScript"||t==="evalScript")return;let r=e[t];if(typeof r=="string")return r.slice(0,80);if(typeof r=="number"||typeof r=="boolean")return String(r);if(!r||typeof r!="object")return;let i=r,o=i.id??i.text??i.name??i.path;if(typeof o=="string"&&o)return o.slice(0,80);if(i.point&&typeof i.point=="string")return i.point.slice(0,80);if(typeof i.x=="number"&&typeof i.y=="number")return`${Math.round(i.x)}, ${Math.round(i.y)}`}recordFlowTraceStep(e){let t=Date.now(),r={stepIndex:e.stepIndex,stepName:e.stepName,...e.targetLabel?{targetLabel:e.targetLabel}:{},startedAtMs:e.startedAtMs,endedAtMs:t,durationMs:Math.max(0,t-e.startedAtMs),status:e.status};e.error!=null&&(r.error=e.error instanceof Error?e.error.message:String(e.error)),this.flowTraceSteps.push(r)}async stopRecording(){if(!this.recordingEnabled||!this.opts.recordingOutputDir)return null;this.recordingEnabled=!1;let e=Date.now(),t=await this.evaluate("window.__sootsimRecorder.stop()");if(!t?.ok)throw this.recordingStartedAtMs=null,this.lastRecordingFrameStats=null,new Error(t?.error||"recording stop failed");this.lastRecordingStartedAtMs=this.recordingStartedAtMs,this.lastRecordingDurationMs=this.recordingStartedAtMs?Math.max(1,e-this.recordingStartedAtMs):null,this.lastRecordingFrameStats=t.frameStats??null,this.recordingStartedAtMs=null;let r=[],i=0;for(;;){let l=await this.evaluate(`window.__sootsimRecorder.getBlobBase64({ offset: ${i}, chunk: 2097152 })`);if(!l||(r.push(Buffer.from(l.data,"base64")),i=l.offset,l.done))break}if(r.length===0)throw new Error("recording requested but no video buffer was produced");S.mkdirSync(this.opts.recordingOutputDir,{recursive:!0});let a=(t.mime||this.opts.recordingFormat||"video/webm").includes("mp4")?"mp4":"webm",s=y.join(this.opts.recordingOutputDir,`sootsim-${Date.now()}.${a}`);return S.writeFileSync(s,Buffer.concat(r)),s}async waitForRecordingTail(e){if(!this.recordingEnabled)return;let t=Math.max(0,Math.round(e.maxMs));if(t<=0)return;if(!e.smart){await f(t);return}let r=await ge({bridge:this.bridge,simId:this.opts.simId,maxMs:t,pollMs:80,stablePolls:6,strict:!0});await this.waitForVisualSettle(),console.log(r.settled?` [flow] recording tail settled in ${r.elapsed}ms`:` [flow] recording tail reached ${r.elapsed}ms budget`)}async findElement(e){if(e.childOf!=null||typeof e.index=="number")return this.findElementScoped(e);let t=!!e.text&&/[.*+?^$()[\]{}|\\]/.test(e.text);return this.evaluate(`(async () => {
219
+ })()`);if(!t?.ok)throw new Error(t?.error||"recording unavailable on this page");this.recordingStartedAtMs||(this.recordingStartedAtMs=typeof t.startedAtMs=="number"&&Number.isFinite(t.startedAtMs)?t.startedAtMs:e)}async startRecording(){this.recordingEnabled=!0,await this.ensureRecordingStarted()}prepareRecording(){this.recordingEnabled=!0}getLastRecordingDurationMs(){return this.lastRecordingDurationMs}getLastRecordingStartedAtMs(){return this.lastRecordingStartedAtMs}getLastRecordingFrameStats(){return this.lastRecordingFrameStats}getFlowTraceSteps(){return[...this.flowTraceSteps]}flowStepTargetLabel(e,t){if(t==="inputText"||t==="runScript"||t==="evalScript")return;let i=e[t];if(typeof i=="string")return i.slice(0,80);if(typeof i=="number"||typeof i=="boolean")return String(i);if(!i||typeof i!="object")return;let r=i,o=r.id??r.text??r.name??r.path;if(typeof o=="string"&&o)return o.slice(0,80);if(r.point&&typeof r.point=="string")return r.point.slice(0,80);if(typeof r.x=="number"&&typeof r.y=="number")return`${Math.round(r.x)}, ${Math.round(r.y)}`}recordFlowTraceStep(e){let t=Date.now(),i={stepIndex:e.stepIndex,stepName:e.stepName,...e.targetLabel?{targetLabel:e.targetLabel}:{},startedAtMs:e.startedAtMs,endedAtMs:t,durationMs:Math.max(0,t-e.startedAtMs),status:e.status};e.error!=null&&(i.error=e.error instanceof Error?e.error.message:String(e.error)),this.flowTraceSteps.push(i)}async stopRecording(){if(!this.recordingEnabled||!this.opts.recordingOutputDir)return null;this.recordingEnabled=!1;let e=Date.now(),t=await this.evaluate("window.__sootsimRecorder.stop()");if(!t?.ok)throw this.recordingStartedAtMs=null,this.lastRecordingFrameStats=null,new Error(t?.error||"recording stop failed");this.lastRecordingStartedAtMs=this.recordingStartedAtMs,this.lastRecordingDurationMs=this.recordingStartedAtMs?Math.max(1,e-this.recordingStartedAtMs):null,this.lastRecordingFrameStats=t.frameStats??null,this.recordingStartedAtMs=null;let i=[],r=0;for(;;){let l=await this.evaluate(`window.__sootsimRecorder.getBlobBase64({ offset: ${r}, chunk: 2097152 })`);if(!l||(i.push(Buffer.from(l.data,"base64")),r=l.offset,l.done))break}if(i.length===0)throw new Error("recording requested but no video buffer was produced");S.mkdirSync(this.opts.recordingOutputDir,{recursive:!0});let a=(t.mime||this.opts.recordingFormat||"video/webm").includes("mp4")?"mp4":"webm",s=b.join(this.opts.recordingOutputDir,`sootsim-${Date.now()}.${a}`);return S.writeFileSync(s,Buffer.concat(i)),s}async waitForRecordingTail(e){if(!this.recordingEnabled)return;let t=Math.max(0,Math.round(e.maxMs));if(t<=0)return;if(!e.smart){await f(t);return}let i=await ye({bridge:this.bridge,simId:this.opts.simId,maxMs:t,pollMs:80,stablePolls:6,strict:!0});await this.waitForVisualSettle(),console.log(i.settled?` [flow] recording tail settled in ${i.elapsed}ms`:` [flow] recording tail reached ${i.elapsed}ms budget`)}async findElement(e){if(e.childOf!=null||typeof e.index=="number")return this.findElementScoped(e);let t=!!e.text&&/[.*+?^$()[\]{}|\\]/.test(e.text);return this.evaluate(`(async () => {
220
220
  const test = window.__sootsimTest
221
221
  if (!test) return null
222
222
  let node = null
@@ -293,7 +293,7 @@ process.stdin.on('end', async () => {
293
293
  // resolves a target that needs scrolling into view.
294
294
  const onScreen = candidates.filter((n) => {
295
295
  const cy = n.absolutePosition.y + n.layout.height / 2
296
- return cy > 0 && cy < ${L}
296
+ return cy > 0 && cy < ${N}
297
297
  })
298
298
  if (onScreen.length > 0) candidates = onScreen
299
299
  ${e.childOf?`
@@ -365,18 +365,18 @@ process.stdin.on('end', async () => {
365
365
  )
366
366
  }
367
367
  return direct
368
- })()`)}async tap(e,t,r){return await this.bridge.send({type:"tap",simId:this.opts.simId,x:e,y:t,target:r})}async longPress(e,t,r,i){return await this.bridge.send({type:"longPress",simId:this.opts.simId,x:e,y:t,durationMs:r,target:i})}async waitForElement(e,t=5e3){let r=Date.now()+t,i=await this.findElement(e);for(;!i&&Date.now()<r;)await f(150),i=await this.findElement(e);return i}replayTargetForElement(e,t,r){return{id:e.id??r?.target?.id??t.id??null,testID:e.id??r?.target?.testID??t.testID??null,text:e.text??r?.target?.text??r?.target?.accessibilityLabel??t.text??t.accessibilityLabel??null,type:r?.target?.type??t.type??null}}async resolveInteractionPoint(e){if(e.point&&!e.id&&!e.text&&e.index===void 0&&!e.childOf)return{...X(e.point),element:null,target:void 0};let t=await this.waitForElement(e);if(!t)return null;let r=typeof t.nodeId=="number"?await this.resolveTapTarget(t.nodeId):null,i=this.replayTargetForElement(e,t,r);return e.point?{...X(e.point,{x:t.absolutePosition.x,y:t.absolutePosition.y,width:t.layout.width,height:t.layout.height}),element:t,target:i}:{x:r?.cx??t.absolutePosition.x+t.layout.width/2,y:r?.cy??t.absolutePosition.y+t.layout.height/2,element:t,target:i}}async tapOn(e){let t=typeof e=="string"?{text:e}:e;if(t.point){let o=await this.resolveInteractionPoint(t);if(!o)throw new Error(`tapOn: element not found: ${JSON.stringify(t)}`);(await this.activatePressAt(o.x,o.y))?.ok||await this.tap(o.x,o.y,o.target),await f(300);return}let r=await this.waitForElement(t);if(r){let o=r.isTextInput?4:1;for(let a=0;a<o;a++){let s=a===0?r:await this.findElement({text:t.text,id:t.id});if(!s)break;let l=typeof s.nodeId=="number"?await this.resolveTapTarget(s.nodeId):null,p=l?.cx??s.absolutePosition.x+s.layout.width/2,h=l?.cy??s.absolutePosition.y+s.layout.height/2;if((await this.tap(p,h,this.replayTargetForElement(t,s,l)))?.hit===!0){if(await f(300),!s.isTextInput||await this.waitForFocusedTextInput(600,s))return;continue}break}}if((await this.activatePressTarget(t))?.ok){await f(300);return}throw new Error(`tapOn: element not found: ${JSON.stringify(t)}`)}async longPressOn(e){let t=typeof e=="string"?{text:e}:e,r=await this.resolveInteractionPoint(t);if(!r)throw new Error(`longPressOn: element not found: ${JSON.stringify(t)}`);let i=await this.longPress(r.x,r.y,3e3,r.target);if(i?.ok===!1||i?.value===!1)throw new Error(`longPressOn: long press missed: ${JSON.stringify(t)}`);await f(300)}async tapAtCoords(e,t){await this.tap(e,t),await f(300)}async doubleTapAtCoords(e,t,r=80){let i=Math.max(0,Math.round(r));if(!await this.evaluate(`(async () => {
368
+ })()`)}async tap(e,t,i){return await this.bridge.send({type:"tap",simId:this.opts.simId,x:e,y:t,target:i})}async longPress(e,t,i,r){return await this.bridge.send({type:"longPress",simId:this.opts.simId,x:e,y:t,durationMs:i,target:r})}async waitForElement(e,t=5e3){let i=Date.now()+t,r=await this.findElement(e);for(;!r&&Date.now()<i;)await f(150),r=await this.findElement(e);return r}replayTargetForElement(e,t,i){return{id:e.id??i?.target?.id??t.id??null,testID:e.id??i?.target?.testID??t.testID??null,text:e.text??i?.target?.text??i?.target?.accessibilityLabel??t.text??t.accessibilityLabel??null,type:i?.target?.type??t.type??null}}async resolveInteractionPoint(e){if(e.point&&!e.id&&!e.text&&e.index===void 0&&!e.childOf)return{...X(e.point),element:null,target:void 0};let t=await this.waitForElement(e);if(!t)return null;let i=typeof t.nodeId=="number"?await this.resolveTapTarget(t.nodeId):null,r=this.replayTargetForElement(e,t,i);return e.point?{...X(e.point,{x:t.absolutePosition.x,y:t.absolutePosition.y,width:t.layout.width,height:t.layout.height}),element:t,target:r}:{x:i?.cx??t.absolutePosition.x+t.layout.width/2,y:i?.cy??t.absolutePosition.y+t.layout.height/2,element:t,target:r}}async tapOn(e){let t=typeof e=="string"?{text:e}:e;if(t.point){let o=await this.resolveInteractionPoint(t);if(!o)throw new Error(`tapOn: element not found: ${JSON.stringify(t)}`);(await this.activatePressAt(o.x,o.y))?.ok||await this.tap(o.x,o.y,o.target),await f(300);return}let i=await this.waitForElement(t);if(i){let o=i.isTextInput?4:1;for(let a=0;a<o;a++){let s=a===0?i:await this.findElement({text:t.text,id:t.id});if(!s)break;let l=typeof s.nodeId=="number"?await this.resolveTapTarget(s.nodeId):null,u=l?.cx??s.absolutePosition.x+s.layout.width/2,p=l?.cy??s.absolutePosition.y+s.layout.height/2;if((await this.tap(u,p,this.replayTargetForElement(t,s,l)))?.hit===!0){if(await f(300),!s.isTextInput||await this.waitForFocusedTextInput(600,s))return;continue}break}}if((await this.activatePressTarget(t))?.ok){await f(300);return}throw new Error(`tapOn: element not found: ${JSON.stringify(t)}`)}async longPressOn(e){let t=typeof e=="string"?{text:e}:e,i=await this.resolveInteractionPoint(t);if(!i)throw new Error(`longPressOn: element not found: ${JSON.stringify(t)}`);let r=await this.longPress(i.x,i.y,3e3,i.target);if(r?.ok===!1||r?.value===!1)throw new Error(`longPressOn: long press missed: ${JSON.stringify(t)}`);await f(300)}async tapAtCoords(e,t){await this.tap(e,t),await f(300)}async doubleTapAtCoords(e,t,i=80){let r=Math.max(0,Math.round(i));if(!await this.evaluate(`(async () => {
369
369
  const interact = window.__sootsimInteract
370
370
  if (interact?.doubleTap) {
371
- return !!(await interact.doubleTap(${e}, ${t}, ${i}))
371
+ return !!(await interact.doubleTap(${e}, ${t}, ${r}))
372
372
  }
373
373
  if (!interact?.tap) return false
374
374
  const first = await interact.tap(${e}, ${t})
375
375
  if (!first || first.hit === false) return false
376
- await new Promise((resolve) => setTimeout(resolve, ${i}))
376
+ await new Promise((resolve) => setTimeout(resolve, ${r}))
377
377
  const second = await interact.tap(${e}, ${t})
378
378
  return !!second && second.hit !== false
379
- })()`))throw new Error(`doubleTapAtCoords failed at (${e}, ${t})`);await f(300)}async assertVisible(e){let t=typeof e=="string"?{text:e}:e;for(let o=0;o<15;o++){if(await this.isElementVisible(t))return;await f(200)}let r=await this.findElement(t),i=r?` (matched node at y=${Math.round(r.absolutePosition.y)} h=${Math.round(r.layout.height)} \u2014 off-screen)`:" (no matching node in tree)";throw new Error(`assertVisible: ${JSON.stringify(t)} not visible${i}`)}async assertNotVisible(e){let t=typeof e=="string"?{text:e}:e;if(await this.isElementVisible(t)){let r=await this.findElement(t),i=r?` at (${Math.round(r.absolutePosition.x)},${Math.round(r.absolutePosition.y)})`:"";throw new Error(`assertNotVisible: ${JSON.stringify(t)} IS visible${i}`)}}async isElementVisible(e){let t=await this.findElement(e);return!!(t&&t.absolutePosition.y+t.layout.height>0&&t.absolutePosition.y<L)}async inputText(e){if(!await this.waitForFocusedTextInput())throw new Error("inputText: no focused TextInput; tap the input and wait for focus before typing");await this.bridge.send({type:"keyboard",simId:this.opts.simId,action:"type",text:e}),await f(200)}focusedTextInputMatches(e,t){if(!t||typeof t.nodeId=="number"&&typeof e.nodeId=="number"&&t.nodeId===e.nodeId)return!0;let r=t.testID??null,i=e.testID??null;if(r&&i&&r===i)return!0;let o=t.id??null,a=e.id??null;return!!(o&&a&&o===a)}async waitForFocusedTextInput(e=1500,t){let r=Date.now()+e;for(;Date.now()<r;){try{let i=await this.callTest("getFocusedNode");if(i&&this.focusedTextInputMatches(i,t))return!0}catch{}await f(50)}return!1}async pressKey(e){await this.bridge.send({type:"keyboard",simId:this.opts.simId,action:"press",text:e}),await f(120)}async dispatchKey(e){await this.bridge.send({type:"keyboard",simId:this.opts.simId,action:"dispatchKey",text:e}),await f(120)}async hideKeyboard(){try{await this.callTest("blurFocusedTextInput")}catch{}await this.bridge.send({type:"keyboard",simId:this.opts.simId,action:"dismiss"});let e=Date.now()+3e3;for(;Date.now()<e;){let t=await this.evaluate(`(() => {
379
+ })()`))throw new Error(`doubleTapAtCoords failed at (${e}, ${t})`);await f(300)}async assertVisible(e){let t=typeof e=="string"?{text:e}:e;for(let o=0;o<15;o++){if(await this.isElementVisible(t))return;await f(200)}let i=await this.findElement(t),r=i?` (matched node at y=${Math.round(i.absolutePosition.y)} h=${Math.round(i.layout.height)} \u2014 off-screen)`:" (no matching node in tree)";throw new Error(`assertVisible: ${JSON.stringify(t)} not visible${r}`)}async assertNotVisible(e){let t=typeof e=="string"?{text:e}:e;if(await this.isElementVisible(t)){let i=await this.findElement(t),r=i?` at (${Math.round(i.absolutePosition.x)},${Math.round(i.absolutePosition.y)})`:"";throw new Error(`assertNotVisible: ${JSON.stringify(t)} IS visible${r}`)}}async isElementVisible(e){let t=await this.findElement(e);return!!(t&&t.absolutePosition.y+t.layout.height>0&&t.absolutePosition.y<N)}async inputText(e){if(!await this.waitForFocusedTextInput())throw new Error("inputText: no focused TextInput; tap the input and wait for focus before typing");await this.bridge.send({type:"keyboard",simId:this.opts.simId,action:"type",text:e}),await f(200)}focusedTextInputMatches(e,t){if(!t||typeof t.nodeId=="number"&&typeof e.nodeId=="number"&&t.nodeId===e.nodeId)return!0;let i=t.testID??null,r=e.testID??null;if(i&&r&&i===r)return!0;let o=t.id??null,a=e.id??null;return!!(o&&a&&o===a)}async waitForFocusedTextInput(e=1500,t){let i=Date.now()+e;for(;Date.now()<i;){try{let r=await this.callTest("getFocusedNode");if(r&&this.focusedTextInputMatches(r,t))return!0}catch{}await f(50)}return!1}async pressKey(e){await this.bridge.send({type:"keyboard",simId:this.opts.simId,action:"press",text:e}),await f(120)}async dispatchKey(e){await this.bridge.send({type:"keyboard",simId:this.opts.simId,action:"dispatchKey",text:e}),await f(120)}async hideKeyboard(){try{await this.callTest("blurFocusedTextInput")}catch{}await this.bridge.send({type:"keyboard",simId:this.opts.simId,action:"dismiss"});let e=Date.now()+3e3;for(;Date.now()<e;){let t=await this.evaluate(`(() => {
380
380
  const keyboard =
381
381
  window.__sootsimKeyboard ??
382
382
  window.SootSim?.bridges?.keyboard ??
@@ -386,7 +386,7 @@ process.stdin.on('end', async () => {
386
386
  visible: !!keyboard?.isVisible?.(),
387
387
  focused: !!test?.isTextInputFocused?.(),
388
388
  }
389
- })()`);if(!t?.visible&&!t?.focused){await f(80);return}await f(80)}}async eraseText(e){for(let t=0;t<e;t++)await this.bridge.send({type:"keyboard",simId:this.opts.simId,action:"dispatchKey",text:"Backspace"});await f(100)}async waitFor(e){let t=Date.now()+(e.timeout||Z);for(;Date.now()<t;){if(await this.findElement(e))return;await f(200)}let r=await this.findElement(e),i=r?` (matched node y=${Math.round(r.absolutePosition.y)} \u2014 still off-screen at deadline)`:"";throw new Error(`waitFor: ${JSON.stringify(e)} not found after ${e.timeout||Z}ms${i}`)}async takeScreenshot(e){if(!this.hasFreshVisualSettle())try{await this.waitForVisualSettle(),await f(250)}catch{}let t=Mt(e),r=Rt(this.opts.screenshotDir,t.path,{mode:this.opts.screenshotPathMode??"dir",flowDir:this.opts.flowDir});S.mkdirSync(y.dirname(r),{recursive:!0});let i=t.layers??this.opts.screenshotLayers,o={type:"screenshot",simId:this.opts.simId};i&&i!=="full"&&(o.layers=i);let s=(await this.bridge.send(o)).replace(/^data:image\/png;base64,/,""),l=Buffer.from(s,"base64");if(t.withFrame){let p=await this.readCurrentDeviceModel();if(!p)throw new Error("could not read current device model for framed screenshot");let h=await et(l,p);S.writeFileSync(r,h),console.log(`[flow] screenshot: ${r} (frame: ${p})`);return}S.writeFileSync(r,l),console.log(`[flow] screenshot: ${r}`)}async readCurrentDeviceModel(){let e=await this.bridge.send({type:"call",simId:this.opts.simId,path:"SootSim.bridges.settings.get",args:[]}),t=e&&typeof e.deviceModel=="string"?e.deviceModel:null;return!t||!(t in Ae)?null:t}async captureFailureScreenshot(e){S.mkdirSync(y.dirname(e),{recursive:!0});let r=(await this.bridge.send({type:"screenshot",simId:this.opts.simId})).replace(/^data:image\/png;base64,/,"");S.writeFileSync(e,Buffer.from(r,"base64"))}async captureFailureBundle(e,t){S.mkdirSync(e,{recursive:!0});let r=(h,g)=>{try{S.writeFileSync(y.join(e,h),g)}catch{}},i=async h=>{try{return await this.bridge.send({type:"evaluate",simId:this.opts.simId,code:h})}catch{return null}},o=await i(`(async () => {
389
+ })()`);if(!t?.visible&&!t?.focused){await f(80);return}await f(80)}}async eraseText(e){for(let t=0;t<e;t++)await this.bridge.send({type:"keyboard",simId:this.opts.simId,action:"dispatchKey",text:"Backspace"});await f(100)}async waitFor(e){let t=Date.now()+(e.timeout||Z);for(;Date.now()<t;){if(await this.findElement(e))return;await f(200)}let i=await this.findElement(e),r=i?` (matched node y=${Math.round(i.absolutePosition.y)} \u2014 still off-screen at deadline)`:"";throw new Error(`waitFor: ${JSON.stringify(e)} not found after ${e.timeout||Z}ms${r}`)}async takeScreenshot(e){if(!this.hasFreshVisualSettle())try{await this.waitForVisualSettle(),await f(250)}catch{}let t=Bt(e),i=Dt(this.opts.screenshotDir,t.path,{mode:this.opts.screenshotPathMode??"dir",flowDir:this.opts.flowDir});S.mkdirSync(b.dirname(i),{recursive:!0});let r=t.layers??this.opts.screenshotLayers,o={type:"screenshot",simId:this.opts.simId};r&&r!=="full"&&(o.layers=r);let s=(await this.bridge.send(o)).replace(/^data:image\/png;base64,/,""),l=Buffer.from(s,"base64");if(t.withFrame){let u=await this.readCurrentDeviceModel();if(!u)throw new Error("could not read current device model for framed screenshot");let p=await rt(l,u);S.writeFileSync(i,p),console.log(`[flow] screenshot: ${i} (frame: ${u})`);return}S.writeFileSync(i,l),console.log(`[flow] screenshot: ${i}`)}async readCurrentDeviceModel(){let e=await this.bridge.send({type:"call",simId:this.opts.simId,path:"SootSim.bridges.settings.get",args:[]}),t=e&&typeof e.deviceModel=="string"?e.deviceModel:null;return!t||!(t in Oe)?null:t}async captureFailureScreenshot(e){S.mkdirSync(b.dirname(e),{recursive:!0});let i=(await this.bridge.send({type:"screenshot",simId:this.opts.simId})).replace(/^data:image\/png;base64,/,"");S.writeFileSync(e,Buffer.from(i,"base64"))}async captureFailureBundle(e,t){S.mkdirSync(e,{recursive:!0});let i=(p,m)=>{try{S.writeFileSync(b.join(e,p),m)}catch{}},r=async p=>{try{return await this.bridge.send({type:"evaluate",simId:this.opts.simId,code:p})}catch{return null}},o=await r(`(async () => {
390
390
  const out = {
391
391
  simId: window.__sootsimBridge?.id ?? window.SootSim?.state?.simId ?? null,
392
392
  url: location.href,
@@ -410,7 +410,7 @@ process.stdin.on('end', async () => {
410
410
  }
411
411
  } catch {}
412
412
  return out
413
- })()`);r("error.json",JSON.stringify({message:t.error.message,stack:t.error.stack,stepIndex:t.stepIndex,stepKind:t.stepKind,stepTarget:t.stepTarget,capturedAt:new Date().toISOString(),sim:o??null},null,2));try{let g=(await this.bridge.send({type:"screenshot",simId:this.opts.simId})).replace(/^data:image\/png;base64,/,"");r("screenshot.png",Buffer.from(g,"base64"))}catch{}let a=await i(`(async () => {
413
+ })()`);i("error.json",JSON.stringify({message:t.error.message,stack:t.error.stack,stepIndex:t.stepIndex,stepKind:t.stepKind,stepTarget:t.stepTarget,capturedAt:new Date().toISOString(),sim:o??null},null,2));try{let m=(await this.bridge.send({type:"screenshot",simId:this.opts.simId})).replace(/^data:image\/png;base64,/,"");i("screenshot.png",Buffer.from(m,"base64"))}catch{}let a=await r(`(async () => {
414
414
  const t = window.__sootsimTest
415
415
  const mainShell = window.SootSim?.bridges?.mainShell
416
416
  if (!t) return { error: 'no test bridge' }
@@ -420,19 +420,19 @@ process.stdin.on('end', async () => {
420
420
  } catch {}
421
421
  const all = await t.queryAll({ pruneHidden: true })
422
422
  return { shell, nodes: all, url: location.href, title: document.title }
423
- })()`);a&&r("describe.json",JSON.stringify(a,null,2));let s=await i("(async () => await window.__sootsimTest?.dumpAccessibilityTree?.(20))()");typeof s=="string"&&r("a11y.txt",s);let l=await i("(async () => await window.__sootsimTest?.dumpTree?.(15))()");typeof l=="string"&&r("tree.txt",l);let p=await i(`(() => {
423
+ })()`);a&&i("describe.json",JSON.stringify(a,null,2));let s=await r("(async () => await window.__sootsimTest?.dumpAccessibilityTree?.(20))()");typeof s=="string"&&i("a11y.txt",s);let l=await r("(async () => await window.__sootsimTest?.dumpTree?.(15))()");typeof l=="string"&&i("tree.txt",l);let u=await r(`(() => {
424
424
  const c = window.__sootsimConsole
425
425
  return {
426
426
  errors: c?.getErrors?.() ?? [],
427
427
  warnings: c?.getWarnings?.() ?? [],
428
428
  requests: (window.__sootsimGetFailedRequests?.() ?? []),
429
429
  }
430
- })()`);return p&&r("console.json",JSON.stringify(p,null,2)),e}async swipe(e="UP",t=300){let r=Q/2,i=L/2,o=200,a=r,s=i,l=r,p=i;switch(e.toUpperCase()){case"UP":s+=o,p-=o;break;case"DOWN":s-=o,p+=o;break;case"LEFT":a+=o,l-=o;break;case"RIGHT":a-=o,l+=o;break}let h=Math.max(10,Math.round(t/16));await this.drag(a,s,l,p,h,16)}async drag(e,t,r,i,o=12,a=16){if(!(await this.evaluate(`(async () => {
430
+ })()`);return u&&i("console.json",JSON.stringify(u,null,2)),e}async swipe(e="UP",t=300){let i=Q/2,r=N/2,o=200,a=i,s=r,l=i,u=r;switch(e.toUpperCase()){case"UP":s+=o,u-=o;break;case"DOWN":s-=o,u+=o;break;case"LEFT":a+=o,l-=o;break;case"RIGHT":a-=o,l+=o;break}let p=Math.max(10,Math.round(t/16));await this.drag(a,s,l,u,p,16)}async drag(e,t,i,r,o=12,a=16){if(!(await this.evaluate(`(async () => {
431
431
  const interact = window.__sootsimInteract
432
432
  if (!interact?.drag) return { ok: false }
433
- const value = await interact.drag(${e}, ${t}, ${r}, ${i}, ${Math.max(1,Math.round(o))}, ${Math.max(0,Math.round(a))})
433
+ const value = await interact.drag(${e}, ${t}, ${i}, ${r}, ${Math.max(1,Math.round(o))}, ${Math.max(0,Math.round(a))})
434
434
  return { ok: !!value, value }
435
- })()`))?.ok)throw new Error("drag failed");await f(300)}async swipeCoords(e,t,r=300){let i=X(e),o=X(t),a=Math.max(10,Math.round(r/16));await this.drag(i.x,i.y,o.x,o.y,a,16)}async swipeFrom(e,t="UP",r=300){let i=await this.findElement(e);if(!i)throw new Error(`swipeFrom: element not found: ${JSON.stringify(e)}`);let o=i.absolutePosition.x+i.layout.width/2,a=i.absolutePosition.y+i.layout.height/2,s=180,l=o,p=a;switch(t.toUpperCase()){case"UP":p-=s;break;case"DOWN":p+=s;break;case"LEFT":l-=s;break;case"RIGHT":l+=s;break}let h=Math.max(10,Math.round(r/16));await this.drag(o,a,l,p,h,16)}async scrollTo(e,t,r){let i=await this.callTest("scrollTo",e,t,r,!1);if(!i?.ok)throw new Error(`scrollTo failed: ${i?.reason||"unknown error"}`);await f(250)}async pinch(e){let t=await this.evaluate(`(async () => {
435
+ })()`))?.ok)throw new Error("drag failed");await f(300)}async swipeCoords(e,t,i=300){let r=X(e),o=X(t),a=Math.max(10,Math.round(i/16));await this.drag(r.x,r.y,o.x,o.y,a,16)}async swipeFrom(e,t="UP",i=300){let r=await this.findElement(e);if(!r)throw new Error(`swipeFrom: element not found: ${JSON.stringify(e)}`);let o=r.absolutePosition.x+r.layout.width/2,a=r.absolutePosition.y+r.layout.height/2,s=180,l=o,u=a;switch(t.toUpperCase()){case"UP":u-=s;break;case"DOWN":u+=s;break;case"LEFT":l-=s;break;case"RIGHT":l+=s;break}let p=Math.max(10,Math.round(i/16));await this.drag(o,a,l,u,p,16)}async scrollTo(e,t,i){let r=await this.callTest("scrollTo",e,t,i,!1);if(!r?.ok)throw new Error(`scrollTo failed: ${r?.reason||"unknown error"}`);await f(250)}async pinch(e){let t=await this.evaluate(`(async () => {
436
436
  const interact = window.__sootsimInteract
437
437
  if (!interact?.pinch) return { ok: false, reason: 'no interact.pinch' }
438
438
  const ok = await interact.pinch(
@@ -441,7 +441,7 @@ process.stdin.on('end', async () => {
441
441
  ${e.steps||12}, ${e.stepMs||16}
442
442
  )
443
443
  return { ok: !!ok, reason: ok ? null : 'pinch returned false' }
444
- })()`);if(!t?.ok)throw new Error(`pinch failed: ${t?.reason||"unknown error"}`);await f(250)}async dumpTree(e=6){let t=await this.bridge.send({type:"tree",simId:this.opts.simId,depth:e});return console.log("[flow] tree:"),console.log(typeof t=="string"?t:JSON.stringify(t,null,2)),typeof t=="string"?t:JSON.stringify(t)}async assertTreeContains(e){if(!(await this.dumpTree(8)).includes(e))throw new Error(`assertTreeContains: "${e}" not in tree`)}async waitForAnimationToEnd(e=2e3){let t=Math.max(0,Math.round(e));if(t<=0)return;(await ge({bridge:this.bridge,simId:this.opts.simId,maxMs:t,pollMs:32,stablePolls:2,strict:!0})).settled&&this.markVisualSettled()}async back(){try{await this.tapOn("\u2039")}catch{await this.tapOn("<")}}async scrollUntilVisible(e){let t=Date.now()+(e.timeout||15e3),r=e.direction?.toUpperCase()||"DOWN",i=r==="DOWN"?"UP":r==="UP"?"DOWN":r;for(;Date.now()<t;){let o=await this.findElement({text:e.element});if(o&&o.absolutePosition.y>=0&&o.absolutePosition.y+o.layout.height>0&&o.absolutePosition.y<L-50){if(e.centerElement){let a=L/2,s=o.absolutePosition.y-a;if(Math.abs(s)>100){let l=Math.min(150,Math.abs(s)*.5),p=s>0?a-l:a+l;await this.drag(Q/2,a,Q/2,p,10,16)}}return}await this.swipe(i,250),await f(500)}throw new Error(`scrollUntilVisible: "${e.element}" not found`)}async extendedWaitUntil(e){let t=Date.now()+(e.timeout||Z);for(;Date.now()<t;){let r=e.visible?await this.isElementVisible(typeof e.visible=="string"?{text:e.visible}:e.visible):!0,i=e.notVisible?!await this.isElementVisible(typeof e.notVisible=="string"?{text:e.notVisible}:e.notVisible):!0;if(r&&i)return;await f(200)}throw new Error("extendedWaitUntil timed out")}async reloadGuestApp(e){if(e){let i=!1;for(let o=0;o<3&&!i;o++)try{i=await this.evaluate(ue(!0),2e4)}catch{await f(1e3)}i||console.warn(" warn: tenant storage clear did not ack \u2014 hard-reloading anyway (worker reset follows)")}await this.evaluate("window.location.reload()").catch(()=>{}),await f(500),await this.refreshSimId()}async softReloadGuestApp(e){if(!await this.evaluate(ue(e),12e4))throw new Error("guest app soft reload bridge unavailable")}async rearmCaptureAfterRuntimeReload(){if(!this.recordingEnabled&&!this.profilingEnabled)return;let e=Date.now()+1e4,t=null;for(;Date.now()<e;){await this.refreshSimId();try{this.recordingEnabled&&await this.ensureRecordingStarted(),this.profilingEnabled&&await this.startProfile();return}catch(r){t=r,await f(250)}}throw new Error(`capture re-arm failed after app reload: ${t instanceof Error?t.message:String(t)}`)}async launchApp(e){await this.refreshSimId(),e&&typeof e=="object"&&e.arguments&&console.log("[flow] launchApp.arguments ignored (sootsim has no native process)");let t=!!(e&&typeof e=="object"&&e.clearState),r=kt(e,"resetRuntime");if(!this.firstLaunchDone&&!t){if(this.firstLaunchDone=!0,r){let i=await U(this.bridge).catch(()=>null),o=i?.state==="home"&&i.activeApp==null;await this.softReloadGuestApp(!1),await this.waitForTree(12e4),o&&(await de(this.bridge,"goHome",1e3),await this.waitForShellHome(1e3)),await this.launchShellAppFromHomeIfNeeded(e,o?{...i??{},state:"home",activeApp:null}:null)}else await this.launchShellAppFromHomeIfNeeded(e);await this.waitForTree(3e4)}else if(this.firstLaunchDone=!0,await this.reloadGuestApp(t),await this.waitForTree(12e4),this.opts.onAfterLaunch)try{await this.opts.onAfterLaunch()}catch(i){console.warn(` warn: onAfterLaunch hook threw: ${i instanceof Error?i.message:i}`)}this.profilingEnabled&&await this.startProfile(),this.recordingEnabled&&(await this.waitForVisualSettle(),await this.ensureRecordingStarted())}async waitForVisualSettle(){try{await this.evaluate(`new Promise((resolve) => {
444
+ })()`);if(!t?.ok)throw new Error(`pinch failed: ${t?.reason||"unknown error"}`);await f(250)}async dumpTree(e=6){let t=await this.bridge.send({type:"tree",simId:this.opts.simId,depth:e});return console.log("[flow] tree:"),console.log(typeof t=="string"?t:JSON.stringify(t,null,2)),typeof t=="string"?t:JSON.stringify(t)}async assertTreeContains(e){if(!(await this.dumpTree(8)).includes(e))throw new Error(`assertTreeContains: "${e}" not in tree`)}async waitForAnimationToEnd(e=2e3){let t=Math.max(0,Math.round(e));if(t<=0)return;(await ye({bridge:this.bridge,simId:this.opts.simId,maxMs:t,pollMs:32,stablePolls:2,strict:!0})).settled&&this.markVisualSettled()}async back(){try{await this.tapOn("\u2039")}catch{await this.tapOn("<")}}async scrollUntilVisible(e){let t=Date.now()+(e.timeout||15e3),i=e.direction?.toUpperCase()||"DOWN",r=i==="DOWN"?"UP":i==="UP"?"DOWN":i;for(;Date.now()<t;){let o=await this.findElement({text:e.element});if(o&&o.absolutePosition.y>=0&&o.absolutePosition.y+o.layout.height>0&&o.absolutePosition.y<N-50){if(e.centerElement){let a=N/2,s=o.absolutePosition.y-a;if(Math.abs(s)>100){let l=Math.min(150,Math.abs(s)*.5),u=s>0?a-l:a+l;await this.drag(Q/2,a,Q/2,u,10,16)}}return}await this.swipe(r,250),await f(500)}throw new Error(`scrollUntilVisible: "${e.element}" not found`)}async extendedWaitUntil(e){let t=Date.now()+(e.timeout||Z);for(;Date.now()<t;){let i=e.visible?await this.isElementVisible(typeof e.visible=="string"?{text:e.visible}:e.visible):!0,r=e.notVisible?!await this.isElementVisible(typeof e.notVisible=="string"?{text:e.notVisible}:e.notVisible):!0;if(i&&r)return;await f(200)}throw new Error("extendedWaitUntil timed out")}async reloadGuestApp(e){if(e){let r=!1;for(let o=0;o<3&&!r;o++)try{r=await this.evaluate(he(!0),2e4)}catch{await f(1e3)}r||console.warn(" warn: tenant storage clear did not ack \u2014 hard-reloading anyway (worker reset follows)")}await this.evaluate("window.location.reload()").catch(()=>{}),await f(500),await this.refreshSimId()}async softReloadGuestApp(e){if(!await this.evaluate(he(e),12e4))throw new Error("guest app soft reload bridge unavailable")}async rearmCaptureAfterRuntimeReload(){if(!this.recordingEnabled&&!this.profilingEnabled)return;let e=Date.now()+1e4,t=null;for(;Date.now()<e;){await this.refreshSimId();try{this.recordingEnabled&&await this.ensureRecordingStarted(),this.profilingEnabled&&await this.startProfile();return}catch(i){t=i,await f(250)}}throw new Error(`capture re-arm failed after app reload: ${t instanceof Error?t.message:String(t)}`)}async launchApp(e){await this.refreshSimId(),e&&typeof e=="object"&&e.arguments&&console.log("[flow] launchApp.arguments ignored (sootsim has no native process)");let t=!!(e&&typeof e=="object"&&e.clearState),i=Mt(e,"resetRuntime");if(!this.firstLaunchDone&&!t){if(this.firstLaunchDone=!0,i){let r=await V(this.bridge).catch(()=>null),o=r?.state==="home"&&r.activeApp==null;await this.softReloadGuestApp(!1),await this.waitForTree(12e4),o&&(await pe(this.bridge,"goHome",1e3),await this.waitForShellHome(1e3)),await this.launchShellAppFromHomeIfNeeded(e,o?{...r??{},state:"home",activeApp:null}:null)}else await this.launchShellAppFromHomeIfNeeded(e);await this.waitForTree(3e4)}else if(this.firstLaunchDone=!0,await this.reloadGuestApp(t),await this.waitForTree(12e4),this.opts.onAfterLaunch)try{await this.opts.onAfterLaunch()}catch(r){console.warn(` warn: onAfterLaunch hook threw: ${r instanceof Error?r.message:r}`)}this.profilingEnabled&&await this.startProfile(),this.recordingEnabled&&(await this.waitForVisualSettle(),await this.ensureRecordingStarted())}async waitForVisualSettle(){try{await this.evaluate(`new Promise((resolve) => {
445
445
  requestAnimationFrame(() => {
446
446
  requestAnimationFrame(() => {
447
447
  requestAnimationFrame(() => {
@@ -449,7 +449,7 @@ process.stdin.on('end', async () => {
449
449
  })
450
450
  })
451
451
  })
452
- })`),this.markVisualSettled()}catch{await f(180),this.markVisualSettled()}}markVisualSettled(){this.lastVisualSettledAtMs=Date.now()}hasFreshVisualSettle(){return Date.now()-this.lastVisualSettledAtMs<750}resolveShellLaunchAppId(e,t){if(typeof e=="string"&&e.length>0)return e;if(Se(e)){let r=J(e,"appId")||J(e,"id");if(r)return r}return Pt(t)||"connect"}async waitForShellAppLaunched(e,t){let r=Date.now()+t,i=null;for(;Date.now()<r;){try{i=await U(this.bridge)}catch{i=null}if(i?.state==="app"&&i.activeApp===e&&i.showSwitcher===!1&&typeof i.launchProgress=="number"&&i.launchProgress>=.98)return;await f(16)}}async waitForShellHome(e){let t=Date.now()+e;for(;Date.now()<t;){let r=await U(this.bridge).catch(()=>null);if(r?.state==="home"&&r.activeApp==null&&r.showSwitcher===!1)return;await f(16)}}async launchShellAppFromHomeIfNeeded(e,t){let r=null;if(t)r=t;else try{r=await U(this.bridge)}catch{return!1}if(r?.state!=="home"||r.activeApp!=null)return!1;let i=this.resolveShellLaunchAppId(e,r);return this.recordingEnabled&&await this.ensureRecordingStarted(),await de(this.bridge,"launchApp",1e3,i),await this.waitForShellAppLaunched(i,1e3),!0}async startProfile(){let e=await this.evaluate(`(() => {
452
+ })`),this.markVisualSettled()}catch{await f(180),this.markVisualSettled()}}markVisualSettled(){this.lastVisualSettledAtMs=Date.now()}hasFreshVisualSettle(){return Date.now()-this.lastVisualSettledAtMs<750}resolveShellLaunchAppId(e,t){if(typeof e=="string"&&e.length>0)return e;if(xe(e)){let i=G(e,"appId")||G(e,"id");if(i)return i}return Ot(t)||"connect"}async waitForShellAppLaunched(e,t){let i=Date.now()+t,r=null;for(;Date.now()<i;){try{r=await V(this.bridge)}catch{r=null}if(r?.state==="app"&&r.activeApp===e&&r.showSwitcher===!1&&typeof r.launchProgress=="number"&&r.launchProgress>=.98)return;await f(16)}}async waitForShellHome(e){let t=Date.now()+e;for(;Date.now()<t;){let i=await V(this.bridge).catch(()=>null);if(i?.state==="home"&&i.activeApp==null&&i.showSwitcher===!1)return;await f(16)}}async launchShellAppFromHomeIfNeeded(e,t){let i=null;if(t)i=t;else try{i=await V(this.bridge)}catch{return!1}if(i?.state!=="home"||i.activeApp!=null)return!1;let r=this.resolveShellLaunchAppId(e,i);return this.recordingEnabled&&await this.ensureRecordingStarted(),await pe(this.bridge,"launchApp",1e3,r),await this.waitForShellAppLaunched(r,1e3),!0}async startProfile(){let e=await this.evaluate(`(() => {
453
453
  if (!window.__sootsimShellPerf) {
454
454
  return { error: "shell frame profile unavailable (__sootsimShellPerf missing on the page)" }
455
455
  }
@@ -460,7 +460,7 @@ process.stdin.on('end', async () => {
460
460
  return { error: "shell frame profile unavailable (__sootsimShellPerf missing on the page)" }
461
461
  }
462
462
  return await window.__sootsimShellPerf.stop()
463
- })()`);if(this.profilingEnabled=!1,e?.error)throw new Error(e.error);return e}async stopApp(){await this.reloadGuestApp(!1),await this.rearmCaptureAfterRuntimeReload()}async clearState(){await this.reloadGuestApp(!0),await this.rearmCaptureAfterRuntimeReload()}clearKeychain(){console.warn("[flow] clearKeychain: sootsim has no keychain surface \u2014 no-op (warning)")}async copyTextFrom(e){let t=typeof e=="string"?{id:e}:e,r=await this.findElement(t);if(!r)throw new Error(`copyTextFrom: element not found: ${JSON.stringify(t)}`);let i=r.text??r.testID??"";this.js.setCopiedText(i),this.js.putEnv("maestroCopiedText",i),console.log(`[flow] copied text: ${JSON.stringify(i)}`)}evalScript(e){let r=/(?<!\\)\$\{[^$]*\}/.test(e)?this.js.evaluateStringTemplate(e):this.js.evaluate(e);r!==void 0&&r!==""&&console.log("[flow] evalScript ->",r)}runScript(e){let t=typeof e=="string"?{file:e}:e;if(!t.file)throw new Error("runScript requires a file");let r=y.resolve(this.opts.flowDir,t.file),i=S.readFileSync(r,"utf8");this.js.evaluate(i,{env:t.env}),console.log(`[flow] runScript: ${t.file} done`)}async openLink(e){let t=typeof e=="string"?e:e.link;if(!t)throw new Error("openLink: missing link");let r=await this.callTest("openDeepLink",t);if(!r?.ok)throw new Error(`openLink failed: ${r?.error||"no test bridge"}`);await f(300)}async evaluateWhen(e){if(e.visible!==void 0){let t=typeof e.visible=="string"?{text:e.visible}:e.visible;return!!await this.findElement(t)}if(e.notVisible!==void 0){let t=typeof e.notVisible=="string"?{text:e.notVisible}:e.notVisible;return!await this.findElement(t)}return e.platform!==void 0?e.platform.toLowerCase()===this.js.maestro.platform.toLowerCase():e.true!==void 0?rt(e.true):!0}isOptional(e){if(e.optional===!0)return!0;let r=Object.entries(e).find(([o])=>o!=="when"&&o!=="optional"),i=r?r[1]:void 0;return!!(i&&typeof i=="object"&&"optional"in i&&i.optional)}async runStep(e,t){let r=typeof e=="string"?Ot(e):e,i=Object.keys(r).find(l=>l!=="when")||Object.keys(r)[0];console.log(`[flow] step ${t+1}: ${i}`);let o=Date.now(),a=this.flowStepTargetLabel(r,i),s;try{s=this.js.interpolateStep(r),a=this.flowStepTargetLabel(s,i)??a}catch(l){if(this.isOptional(r)){console.log(`[flow] (optional, skipped: ${l.message.slice(0,80)})`),this.recordFlowTraceStep({stepIndex:t,stepName:i,targetLabel:a,startedAtMs:o,status:"skipped",error:l});return}throw this.lastFailedStep={index:t,kind:i,target:r[i]},this.recordFlowTraceStep({stepIndex:t,stepName:i,targetLabel:a,startedAtMs:o,status:"failure",error:l}),l}if(s.when&&!await this.evaluateWhen(s.when)){console.log("[flow] (when: predicate false, skipped)"),this.recordFlowTraceStep({stepIndex:t,stepName:i,targetLabel:a,startedAtMs:o,status:"skipped"});return}try{let l=!!(s.extendedWaitUntil||s.waitFor||s.scrollUntilVisible||s.launchApp||s.runFlow||s.runScript),p=1e4,h=this.runStepInner(s);if(l)await h;else{let E=null,m=new Promise((k,_)=>{E=setTimeout(()=>{_(new Error(`step watchdog: ${i} made no progress in ${p}ms \u2014 bridge or bundle probably hung`))},p)});try{await Promise.race([h,m])}finally{E&&clearTimeout(E)}}let g=!!(s.assertVisible||s.assertNotVisible||s.extendedWaitUntil||s.waitFor);this.stepDelay>0&&!g&&await f(this.stepDelay),this.recordFlowTraceStep({stepIndex:t,stepName:i,targetLabel:a,startedAtMs:o,status:"success"})}catch(l){if(this.isOptional(s)){console.log(`[flow] (optional, skipped: ${l.message.slice(0,80)})`),this.recordFlowTraceStep({stepIndex:t,stepName:i,targetLabel:a,startedAtMs:o,status:"skipped",error:l});return}throw this.lastFailedStep={index:t,kind:i,target:s[i]},this.recordFlowTraceStep({stepIndex:t,stepName:i,targetLabel:a,startedAtMs:o,status:"failure",error:l}),l}}async runStepInner(e){if(e.tapOn)await this.tapOn(e.tapOn);else if(e.longPressOn)await this.longPressOn(e.longPressOn);else if(e.scrollUntilVisible)await this.scrollUntilVisible(e.scrollUntilVisible);else if(e.extendedWaitUntil)await this.extendedWaitUntil(e.extendedWaitUntil);else if(e.assertVisible)await this.assertVisible(e.assertVisible);else if(e.assertNotVisible)await this.assertNotVisible(e.assertNotVisible);else if(e.inputText)await this.inputText(e.inputText);else if(e.pressKey)await this.pressKey(e.pressKey);else if(e.dispatchKey)await this.dispatchKey(e.dispatchKey);else if(e.waitFor)await this.waitFor(e.waitFor);else if(e.takeScreenshot)await this.takeScreenshot(e.takeScreenshot);else if(e.swipe)e.swipe.start&&e.swipe.end?await this.swipeCoords(e.swipe.start,e.swipe.end,e.swipe.duration):e.swipe.from?await this.swipeFrom(e.swipe.from,e.swipe.direction,e.swipe.duration):await this.swipe(e.swipe.direction,e.swipe.duration);else if(e.scroll)await this.swipe(e.scroll.direction==="DOWN"?"UP":"DOWN");else if(e.scrollTo){let t=typeof e.scrollTo.nodeId=="number"?{nodeId:e.scrollTo.nodeId}:e.scrollTo.id;if(!t)throw new Error("scrollTo requires id or nodeId");await this.scrollTo(t,e.scrollTo.x,e.scrollTo.y)}else if(e.pinch)await this.pinch(e.pinch);else if(e.waitForAnimationToEnd){let t=e.waitForAnimationToEnd;await this.waitForAnimationToEnd(typeof t=="number"?t:typeof t=="object"&&typeof t.timeout=="number"?t.timeout:2e3)}else if(e.back)await this.back();else if(e.hideKeyboard)await this.hideKeyboard();else if(e.launchApp)await this.launchApp(e.launchApp);else if(typeof e.wait=="number")await f(e.wait);else if(e.dumpTree)await this.dumpTree(e.dumpTree);else if(e.tapAtCoords)await this.tapAtCoords(e.tapAtCoords.x,e.tapAtCoords.y);else if(e.doubleTapAtCoords)await this.doubleTapAtCoords(e.doubleTapAtCoords.x,e.doubleTapAtCoords.y,e.doubleTapAtCoords.gapMs);else if(e.assertTreeContains)await this.assertTreeContains(e.assertTreeContains);else if(typeof e.eraseText=="number")await this.eraseText(e.eraseText);else if(e.repeat&&Array.isArray(e.repeat.commands)){let t=e.repeat.times,r=t==null||t===""?Number.MAX_SAFE_INTEGER:Number(t);if(!Number.isFinite(r))throw new Error(`repeat.times is not a number: ${t}`);let i=e.repeat.when??e.repeat.condition,o=async()=>i?this.evaluateWhen(i):!0,a=i?r:Math.min(r,1e3),s=0;for(;s<a&&await o();){for(let l=0;l<e.repeat.commands.length;l++)await this.runStep(e.repeat.commands[l],l);s++}}else if(e.stopApp!==void 0)await this.stopApp();else if(e.clearState!==void 0)await this.clearState();else if(e.clearKeychain!==void 0)this.clearKeychain();else if(e.copyTextFrom!==void 0)await this.copyTextFrom(e.copyTextFrom);else if(typeof e.evalScript=="string")this.evalScript(e.evalScript);else if(e.runScript){let t=e.runScript,r=typeof t=="string"?void 0:t.when;if(r&&!await this.evaluateWhen(r)){console.log("[flow] runScript skipped (when predicate false)");return}this.runScript(t)}else if(e.openLink!==void 0)await this.openLink(e.openLink);else if(e.runFlow){let t=e.runFlow,r=typeof t=="string"?t:t.file,i=typeof t=="string"?void 0:t.commands,o=typeof t=="string"?void 0:t.env,a=typeof t=="string"?void 0:t.when;if(a&&!await this.evaluateWhen(a)){console.log(`[flow] runFlow skipped (when predicate false): ${r??"inline commands"}`);return}if(!r&&!i)throw new Error("runFlow requires either file or commands");this.js.enterEnvScope();try{if(o)for(let[s,l]of Object.entries(o))this.js.putEnv(s,l);if(r){let s=y.resolve(this.opts.flowDir,r),l=S.readFileSync(s,"utf8"),p=this.opts.flowDir;this.opts.flowDir=y.dirname(s);try{await this.runFlow(_t(l))}finally{this.opts.flowDir=p}}else if(i)for(let s=0;s<i.length;s++)await this.runStep(i[s],s)}finally{this.js.leaveEnvScope()}}else throw new Error(`unsupported flow step: ${JSON.stringify(e)}`)}async runFlow(e){let t=[],r=[],i=[];for(let a of e){let s=Object.keys(a);if(s.length===1&&s[0]==="onFlowStart"&&Array.isArray(a.onFlowStart)){t.push(...a.onFlowStart);continue}if(s.length===1&&s[0]==="onFlowComplete"&&Array.isArray(a.onFlowComplete)){r.push(...a.onFlowComplete);continue}i.push(a)}if(t.length>0){console.log(`[flow] onFlowStart (${t.length} steps)`);for(let a=0;a<t.length;a++)await this.runStep(t[a],a)}let o=null;try{await this.runFlowBody(i)}catch(a){o=a instanceof Error?a:new Error(String(a))}if(r.length>0){console.log(`[flow] onFlowComplete (${r.length} steps)`);for(let a=0;a<r.length;a++)try{await this.runStep(r[a],a)}catch(s){console.warn(`[flow] onFlowComplete step ${a+1} failed: ${s instanceof Error?s.message:s}`)}}if(o)throw o}async runFlowBody(e){for(let t=0;t<e.length;t++){let r=e[t],i=typeof r.wait=="number"?r.wait:0,o=typeof r.waitFor?.timeout=="number"?r.waitFor.timeout:0,a=Math.max(6e4,i+15e3,o+15e3);if(r.runFlow||r.launchApp){await this.runStep(r,t);continue}await Promise.race([this.runStep(r,t),new Promise((s,l)=>setTimeout(()=>l(new Error(`step ${t+1} (${Object.keys(r)[0]}) exceeded ${a}ms deadline`)),a))])}}};var ve=null;function vr(){return ve}async function Dt(n){if(!n)return"";let e=n.trim();if(!e)return"";if(/^\d+$/.test(e)||e.startsWith("http://")||e.startsWith("https://"))return e;let r=(await Oe()).find(i=>i.name.toLowerCase()===e.toLowerCase());return r?String(r.preferredPort):e}async function Bt(){let n=await _e(),e=n.find(r=>r.patched);if(e)return`http://localhost:${e.port}/__soot/`;let t=n[0];return t?`http://localhost:${t.port}/__soot/`:null}async function nt(n){ve=null,(n.length===0||n.includes("--help")||n.includes("-h"))&&(console.log(`
463
+ })()`);if(this.profilingEnabled=!1,e?.error)throw new Error(e.error);return e}async stopApp(){await this.reloadGuestApp(!1),await this.rearmCaptureAfterRuntimeReload()}async clearState(){await this.reloadGuestApp(!0),await this.rearmCaptureAfterRuntimeReload()}clearKeychain(){console.warn("[flow] clearKeychain: sootsim has no keychain surface \u2014 no-op (warning)")}async copyTextFrom(e){let t=typeof e=="string"?{id:e}:e,i=await this.findElement(t);if(!i)throw new Error(`copyTextFrom: element not found: ${JSON.stringify(t)}`);let r=i.text??i.testID??"";this.js.setCopiedText(r),this.js.putEnv("maestroCopiedText",r),console.log(`[flow] copied text: ${JSON.stringify(r)}`)}evalScript(e){let i=/(?<!\\)\$\{[^$]*\}/.test(e)?this.js.evaluateStringTemplate(e):this.js.evaluate(e);i!==void 0&&i!==""&&console.log("[flow] evalScript ->",i)}runScript(e){let t=typeof e=="string"?{file:e}:e;if(!t.file)throw new Error("runScript requires a file");let i=b.resolve(this.opts.flowDir,t.file),r=S.readFileSync(i,"utf8");this.js.evaluate(r,{env:t.env}),console.log(`[flow] runScript: ${t.file} done`)}async openLink(e){let t=typeof e=="string"?e:e.link;if(!t)throw new Error("openLink: missing link");let i=await this.callTest("openDeepLink",t);if(!i?.ok)throw new Error(`openLink failed: ${i?.error||"no test bridge"}`);await f(300)}async evaluateWhen(e){if(e.visible!==void 0){let t=typeof e.visible=="string"?{text:e.visible}:e.visible;return!!await this.findElement(t)}if(e.notVisible!==void 0){let t=typeof e.notVisible=="string"?{text:e.notVisible}:e.notVisible;return!await this.findElement(t)}return e.platform!==void 0?e.platform.toLowerCase()===this.js.maestro.platform.toLowerCase():e.true!==void 0?ot(e.true):!0}isOptional(e){if(e.optional===!0)return!0;let i=Object.entries(e).find(([o])=>o!=="when"&&o!=="optional"),r=i?i[1]:void 0;return!!(r&&typeof r=="object"&&"optional"in r&&r.optional)}async runStep(e,t){let i=typeof e=="string"?st(e):e,r=Object.keys(i).find(l=>l!=="when")||Object.keys(i)[0];console.log(`[flow] step ${t+1}: ${r}`);let o=Date.now(),a=this.flowStepTargetLabel(i,r),s;try{s=this.js.interpolateStep(i),a=this.flowStepTargetLabel(s,r)??a}catch(l){if(this.isOptional(i)){console.log(`[flow] (optional, skipped: ${l.message.slice(0,80)})`),this.recordFlowTraceStep({stepIndex:t,stepName:r,targetLabel:a,startedAtMs:o,status:"skipped",error:l});return}throw this.lastFailedStep={index:t,kind:r,target:i[r]},this.recordFlowTraceStep({stepIndex:t,stepName:r,targetLabel:a,startedAtMs:o,status:"failure",error:l}),l}if(s.when&&!await this.evaluateWhen(s.when)){console.log("[flow] (when: predicate false, skipped)"),this.recordFlowTraceStep({stepIndex:t,stepName:r,targetLabel:a,startedAtMs:o,status:"skipped"});return}try{let l=!!(s.extendedWaitUntil||s.waitFor||s.scrollUntilVisible||s.launchApp||s.runFlow||s.runScript),u=1e4,p=this.runStepInner(s);if(l)await p;else{let x=null,g=new Promise((P,_)=>{x=setTimeout(()=>{_(new Error(`step watchdog: ${r} made no progress in ${u}ms \u2014 bridge or bundle probably hung`))},u)});try{await Promise.race([p,g])}finally{x&&clearTimeout(x)}}let m=!!(s.assertVisible||s.assertNotVisible||s.extendedWaitUntil||s.waitFor);this.stepDelay>0&&!m&&await f(this.stepDelay),this.recordFlowTraceStep({stepIndex:t,stepName:r,targetLabel:a,startedAtMs:o,status:"success"})}catch(l){if(this.isOptional(s)){console.log(`[flow] (optional, skipped: ${l.message.slice(0,80)})`),this.recordFlowTraceStep({stepIndex:t,stepName:r,targetLabel:a,startedAtMs:o,status:"skipped",error:l});return}throw this.lastFailedStep={index:t,kind:r,target:s[r]},this.recordFlowTraceStep({stepIndex:t,stepName:r,targetLabel:a,startedAtMs:o,status:"failure",error:l}),l}}async runStepInner(e){if(e.tapOn)await this.tapOn(e.tapOn);else if(e.longPressOn)await this.longPressOn(e.longPressOn);else if(e.scrollUntilVisible)await this.scrollUntilVisible(e.scrollUntilVisible);else if(e.extendedWaitUntil)await this.extendedWaitUntil(e.extendedWaitUntil);else if(e.assertVisible)await this.assertVisible(e.assertVisible);else if(e.assertNotVisible)await this.assertNotVisible(e.assertNotVisible);else if(e.inputText)await this.inputText(e.inputText);else if(e.pressKey)await this.pressKey(e.pressKey);else if(e.dispatchKey)await this.dispatchKey(e.dispatchKey);else if(e.waitFor)await this.waitFor(e.waitFor);else if(e.takeScreenshot)await this.takeScreenshot(e.takeScreenshot);else if(e.swipe)e.swipe.start&&e.swipe.end?await this.swipeCoords(e.swipe.start,e.swipe.end,e.swipe.duration):e.swipe.from?await this.swipeFrom(e.swipe.from,e.swipe.direction,e.swipe.duration):await this.swipe(e.swipe.direction,e.swipe.duration);else if(e.scroll)await this.swipe(e.scroll.direction==="DOWN"?"UP":"DOWN");else if(e.scrollTo){let t=typeof e.scrollTo.nodeId=="number"?{nodeId:e.scrollTo.nodeId}:e.scrollTo.id;if(!t)throw new Error("scrollTo requires id or nodeId");await this.scrollTo(t,e.scrollTo.x,e.scrollTo.y)}else if(e.pinch)await this.pinch(e.pinch);else if(e.waitForAnimationToEnd){let t=e.waitForAnimationToEnd;await this.waitForAnimationToEnd(typeof t=="number"?t:typeof t=="object"&&typeof t.timeout=="number"?t.timeout:2e3)}else if(e.back)await this.back();else if(e.hideKeyboard)await this.hideKeyboard();else if(e.launchApp)await this.launchApp(e.launchApp);else if(typeof e.wait=="number")await f(e.wait);else if(e.dumpTree)await this.dumpTree(e.dumpTree);else if(e.tapAtCoords)await this.tapAtCoords(e.tapAtCoords.x,e.tapAtCoords.y);else if(e.doubleTapAtCoords)await this.doubleTapAtCoords(e.doubleTapAtCoords.x,e.doubleTapAtCoords.y,e.doubleTapAtCoords.gapMs);else if(e.assertTreeContains)await this.assertTreeContains(e.assertTreeContains);else if(typeof e.eraseText=="number")await this.eraseText(e.eraseText);else if(e.repeat&&Array.isArray(e.repeat.commands)){let t=e.repeat.times,i=t==null||t===""?Number.MAX_SAFE_INTEGER:Number(t);if(!Number.isFinite(i))throw new Error(`repeat.times is not a number: ${t}`);let r=e.repeat.when??e.repeat.condition,o=async()=>r?this.evaluateWhen(r):!0,a=r?i:Math.min(i,1e3),s=0;for(;s<a&&await o();){for(let l=0;l<e.repeat.commands.length;l++)await this.runStep(e.repeat.commands[l],l);s++}}else if(e.stopApp!==void 0)await this.stopApp();else if(e.clearState!==void 0)await this.clearState();else if(e.clearKeychain!==void 0)this.clearKeychain();else if(e.copyTextFrom!==void 0)await this.copyTextFrom(e.copyTextFrom);else if(typeof e.evalScript=="string")this.evalScript(e.evalScript);else if(e.runScript){let t=e.runScript,i=typeof t=="string"?void 0:t.when;if(i&&!await this.evaluateWhen(i)){console.log("[flow] runScript skipped (when predicate false)");return}this.runScript(t)}else if(e.openLink!==void 0)await this.openLink(e.openLink);else if(e.runFlow){let t=e.runFlow,i=typeof t=="string"?t:t.file,r=typeof t=="string"?void 0:t.commands,o=typeof t=="string"?void 0:t.env,a=typeof t=="string"?void 0:t.when;if(a&&!await this.evaluateWhen(a)){console.log(`[flow] runFlow skipped (when predicate false): ${i??"inline commands"}`);return}if(!i&&!r)throw new Error("runFlow requires either file or commands");this.js.enterEnvScope();try{if(o)for(let[s,l]of Object.entries(o))this.js.putEnv(s,l);if(i){let s=b.resolve(this.opts.flowDir,i),l=S.readFileSync(s,"utf8"),u=this.opts.flowDir;this.opts.flowDir=b.dirname(s);try{await this.runFlow(Lt(l))}finally{this.opts.flowDir=u}}else if(r)for(let s=0;s<r.length;s++)await this.runStep(r[s],s)}finally{this.js.leaveEnvScope()}}else throw new Error(`unsupported flow step: ${JSON.stringify(e)}`)}liveStatus=null;async runFlow(e){let t=[],i=[],r=[];for(let a of e){let s=Object.keys(a);if(s.length===1&&s[0]==="onFlowStart"&&Array.isArray(a.onFlowStart)){t.push(...a.onFlowStart);continue}if(s.length===1&&s[0]==="onFlowComplete"&&Array.isArray(a.onFlowComplete)){i.push(...a.onFlowComplete);continue}r.push(a)}if(this.liveStatus&&await this.liveStatus.plan(r.map((a,s)=>{let l=typeof a=="string"?st(a):a,u=Object.keys(l).find(p=>p!=="when")??Object.keys(l)[0];return{index:s,name:u,target:this.flowStepTargetLabel(l,u)}})),t.length>0){console.log(`[flow] onFlowStart (${t.length} steps)`);for(let a=0;a<t.length;a++)await this.runStep(t[a],a)}let o=null;try{await this.runFlowBody(r)}catch(a){o=a instanceof Error?a:new Error(String(a))}if(i.length>0){console.log(`[flow] onFlowComplete (${i.length} steps)`);for(let a=0;a<i.length;a++)try{await this.runStep(i[a],a)}catch(s){console.warn(`[flow] onFlowComplete step ${a+1} failed: ${s instanceof Error?s.message:s}`)}}if(o)throw o}async runFlowBody(e){for(let t=0;t<e.length;t++){let i=e[t],r=typeof i.wait=="number"?i.wait:0,o=typeof i.waitFor?.timeout=="number"?i.waitFor.timeout:0,a=Math.max(6e4,r+15e3,o+15e3);this.liveStatus&&(await this.liveStatus.waitWhilePaused(),await this.liveStatus.step(t,"running"));let s=Date.now(),l=async(u,p)=>{if(!this.liveStatus)return;let m=this.flowTraceSteps[this.flowTraceSteps.length-1],x=m&&m.stepIndex===t&&m.startedAtMs>=s;await this.liveStatus.step(t,u?"failure":x&&m.status==="skipped"?"skipped":"success",{durationMs:Date.now()-s,error:u?p instanceof Error?p.message.slice(0,300):String(p).slice(0,300):x&&m.error||void 0})};try{i.runFlow||i.launchApp?await this.runStep(i,t):await Promise.race([this.runStep(i,t),new Promise((u,p)=>setTimeout(()=>p(new Error(`step ${t+1} (${Object.keys(i)[0]}) exceeded ${a}ms deadline`)),a))])}catch(u){throw await l(!0,u),u}await l(!1)}}};var te=class{constructor(e,t){this.bridge=e;this.flowName=t}disabled=!1;paused=!1;runId=`flr_${Date.now().toString(36)}_${Math.random().toString(36).slice(2,8)}`;async push(e){if(!this.disabled)try{let t=await this.bridge.send({type:"flowStatus",status:{runId:this.runId,flowName:this.flowName,...e}});this.paused=t?.control?.paused===!0}catch(t){this.disabled=!0,console.log(`[flow] live status unavailable (${t instanceof Error?t.message.slice(0,120):t}) \u2014 continuing without the devtools rail`)}}async plan(e){await this.push({phase:"plan",state:"running",steps:e})}async step(e,t,i){await this.push({phase:"step",state:"running",step:{index:e,status:t,...i}})}async end(e){await this.push({phase:"end",state:e})}async waitWhilePaused(){if(!this.disabled)for(;this.paused;){for(console.log("[flow] paused from devtools \u2014 waiting\u2026");this.paused&&!this.disabled;)await new Promise(e=>setTimeout(e,400)),await this.push({phase:"heartbeat",state:"paused"});this.disabled||console.log("[flow] resumed")}}};var Te=null;function Ii(){return Te}var Ee=[];function $i(){return Ee}async function Ct(n){if(!n)return"";let e=n.trim();if(!e)return"";if(/^\d+$/.test(e)||e.startsWith("http://")||e.startsWith("https://"))return e;let i=(await Be()).find(r=>r.name.toLowerCase()===e.toLowerCase());return i?String(i.preferredPort):e}async function Nt(){let n=await Le(),e=n.find(i=>i.patched);if(e)return`http://localhost:${e.port}/__soot/`;let t=n[0];return t?`http://localhost:${t.port}/__soot/`:null}async function lt(n){Te=null,Ee=[],(n.length===0||n.includes("--help")||n.includes("-h"))&&(console.log(`
464
464
  sootsim flow \u2014 run flows or manage a draft
465
465
 
466
466
  usage:
@@ -540,28 +540,28 @@ flow extension:
540
540
  takeScreenshot:
541
541
  path: marketing/hero
542
542
  withFrame: true
543
- `),process.exit(0));let e=n[0];$.existsSync(e)||(console.error(` error: ${e} not found`),process.exit(1));let t=u=>n.find((c,w)=>n[w-1]===u),r=n.includes("--profile"),i=n.includes("--headed"),o=n.includes("--new")||i,a=t("--out")||"/tmp/sootsim-recordings",s=t("--screenshots")||(t("--out")?a:"/tmp/sootsim-flow"),l=t("--screenshot-paths")==="flow"?"flow":"dir",p=n.includes("--no-shell")?"tenant":n.includes("--shell-only")?"shell":void 0,h=t("--device")?.trim()||"",g=n.includes("--slow")?+(t("--slow")||"500"):0,E=n.includes("--electron"),m=n.includes("--preview"),k=await Ye(t("--preview-origin")),_=t("--preview-public-origin"),ot=n.includes("--preview-open"),xe=t("--owner")?.trim()||"",Te=t("--repo")?.trim()||"",H=t("--billing-kind")?.trim()||"";H&&H!=="test_run"&&(console.error(` error: invalid --billing-kind: ${H}`),process.exit(1));let st=n.flatMap((u,c)=>n[c-1]==="--replace"?["--replace",u]:[]),at=n.flatMap((u,c)=>n[c-1]==="--remap"?["--remap",u]:[]),P=n.includes("--record")||m,lt=n.includes("--tail-wait")?Math.max(0,+(t("--tail-wait")||"2000")):P?m?6e3:2e3:0,ct=$.readFileSync(e,"utf8"),{frontmatter:T,steps:A}=pe(ct);A.length===0&&(console.error(" error: flow file must contain a YAML array of steps"),process.exit(1));let W=h||T.device||"",G=E||T.electron===!0,dt=T.app===void 0||T.app===null?"":typeof T.app=="number"?String(T.app):T.app,re=await Dt(dt),Ee={stripBooleanFlags:["--record","--profile","--electron","--new","--preview","--preview-open","--headless","--headed"],stripValueFlags:["--out","--device","--slow","--tail-wait","--url","--replace","--remap","--screenshots","--screenshot-paths","--preview-origin","--preview-public-origin","--driver","--billing-kind","--owner","--repo"]},v=le(n,Ee),ut=t("--url")||"";G&&!We()&&(console.error(" error: desktop companion not found. install or build it first with `bun run build:electron`"),process.exit(1));let Fe=G?"desktop companion":"bridge",pt=re?` | target: ${re}`:"";console.log(`
544
- sootsim flow \u2014 ${b.basename(e)}
545
- ${A.length} steps | ${Fe}${pt}${P?" | recording":""}${r?" | profiling":""}${g?` | ${g}ms delay`:""}
546
- `),m&&Pe({event:"preview_flow_started",properties:{flowName:b.basename(e),stepCount:A.length,mode:Fe,electron:G,record:P,profile:r,previewOrigin:k}});let I=ut||re||"",ie=o||G&&v.simIdSource!=="flag",Ie=t("--driver")||"",ne=!1,oe=new Set,$e=!1;if(!I&&!ie&&v.simIdSource==="none"){let u=Le(v);try{let c=await u.listSims(),w=c.find(C=>C.isPrimary&&C.readyState==="open"),O=c.find(C=>C.readyState==="open"),j=w??O;j&&($e=!0,console.log(` reusing active sim: ${j.id}`))}catch{}finally{u.close()}}if(!I&&!$e&&(ie||v.simIdSource==="none")){let u=await Bt();u||(console.error(" error: no current sim and no sootsim target found"),await se(),process.exit(1)),I=u}if(I&&W){let u=new URL(await je(I));u.searchParams.set("device",W),I=u.toString()}if(I){let u=[I];if(u.push(...st),u.push(...at),ie&&u.push("--new"),u.push("--no-describe"),v.simIdSource==="flag"&&v.simId&&u.push("--sim",v.simId),Ie&&(u.push("--driver",Ie),ne=!0),n.includes("--headless")&&!i&&u.push("--headless"),await Ve(u,{port:v.wsPort,timeoutMs:v.commandTimeoutMs}),ne){let c=ae();c&&oe.add(c)}}let D=le(n,Ee),z=D.simIdSource==="flag"?D.simId:ae()||D.simId,ht=D.simIdSource==="flag"?"flag":z?"saved":"none",F=ce(D.wsPort,{commandTimeoutMs:D.commandTimeoutMs,simId:z,simIdSource:ht}),d,ke=async()=>{if(!W)return!1;let u=await F.send({type:"evaluate",simId:d.simId,code:"window.location.href"});if(typeof u=="string"&&u.length>0){let c=new URL(u);c.searchParams.set("device",W),d.setSimRouteHint(c.toString())}return!!await F.send({type:"call",simId:d.simId,path:"SootSim.bridges.settings.set",args:["deviceModel",W]})};if(d=new ee(F,{screenshotDir:s,flowDir:b.dirname(b.resolve(e)),screenshotPathMode:l,screenshotLayers:p,simId:z,recordingOutputDir:P?a:void 0,recordingFormat:m?"mp4":"webm",billingOriginOverride:m?k:void 0,allowGitHubRecording:m,requireRecordingEntitlement:m,onAfterLaunch:async()=>{await ke()&&await d.waitForTree(12e4),m&&await F.send({type:"evaluate",simId:d.simId,code:`(() => {
543
+ `),process.exit(0));let e=n[0];k.existsSync(e)||(console.error(` error: ${e} not found`),process.exit(1));let t=h=>n.find((d,y)=>n[y-1]===h),i=n.includes("--profile"),r=n.includes("--headed"),o=n.includes("--new")||r,a=t("--out")||"/tmp/sootsim-recordings",s=t("--screenshots")||(t("--out")?a:"/tmp/sootsim-flow"),l=t("--screenshot-paths")==="flow"?"flow":"dir",u=n.includes("--no-shell")?"tenant":n.includes("--shell-only")?"shell":void 0,p=t("--device")?.trim()||"",m=n.includes("--slow")?+(t("--slow")||"500"):0,x=n.includes("--electron"),g=n.includes("--preview"),P=await Qe(t("--preview-origin")),_=t("--preview-public-origin"),dt=n.includes("--preview-open"),Fe=t("--owner")?.trim()||"",Ie=t("--repo")?.trim()||"",H=t("--billing-kind")?.trim()||"";H&&H!=="test_run"&&(console.error(` error: invalid --billing-kind: ${H}`),process.exit(1));let ct=n.flatMap((h,d)=>n[d-1]==="--replace"?["--replace",h]:[]),ut=n.flatMap((h,d)=>n[d-1]==="--remap"?["--remap",h]:[]),A=n.includes("--record")||g,pt=n.includes("--tail-wait")?Math.max(0,+(t("--tail-wait")||"2000")):A?g?6e3:2e3:0,ht=k.readFileSync(e,"utf8"),{frontmatter:E,steps:R}=fe(ht);R.length===0&&(console.error(" error: flow file must contain a YAML array of steps"),process.exit(1));let W=p||E.device||"",z=x||E.electron===!0,ft=E.app===void 0||E.app===null?"":typeof E.app=="number"?String(E.app):E.app,re=await Ct(ft),$e={stripBooleanFlags:["--record","--profile","--electron","--new","--preview","--preview-open","--headless","--headed"],stripValueFlags:["--out","--device","--slow","--tail-wait","--url","--replace","--remap","--screenshots","--screenshot-paths","--preview-origin","--preview-public-origin","--driver","--billing-kind","--owner","--repo"]},v=ce(n,$e),mt=t("--url")||"";z&&!Ve()&&(console.error(" error: desktop companion not found. install or build it first with `bun run build:electron`"),process.exit(1));let ke=z?"desktop companion":"bridge",gt=re?` | target: ${re}`:"";console.log(`
544
+ sootsim flow \u2014 ${w.basename(e)}
545
+ ${R.length} steps | ${ke}${gt}${A?" | recording":""}${i?" | profiling":""}${m?` | ${m}ms delay`:""}
546
+ `),g&&Me({event:"preview_flow_started",properties:{flowName:w.basename(e),stepCount:R.length,mode:ke,electron:z,record:A,profile:i,previewOrigin:P}});let I=mt||re||"",ne=o||z&&v.simIdSource!=="flag",Pe=t("--driver")||"",oe=!1,se=new Set,Ae=!1;if(!I&&!ne&&v.simIdSource==="none"){let h=je(v);try{let d=await h.listSims(),y=d.find(L=>L.isPrimary&&L.readyState==="open"),$=d.find(L=>L.readyState==="open"),U=y??$;U&&(Ae=!0,console.log(` reusing active sim: ${U.id}`))}catch{}finally{h.close()}}if(!I&&!Ae&&(ne||v.simIdSource==="none")){let h=await Nt();h||(console.error(" error: no current sim and no sootsim target found"),await le(),process.exit(1)),I=h}if(I&&W){let h=new URL(await Je(I));h.searchParams.set("device",W),I=h.toString()}if(I){let h=[I];if(h.push(...ct),h.push(...ut),ne&&h.push("--new"),h.push("--no-describe"),v.simIdSource==="flag"&&v.simId&&h.push("--sim",v.simId),Pe&&(h.push("--driver",Pe),oe=!0),n.includes("--headless")&&!r&&h.push("--headless"),await ze(h,{port:v.wsPort,timeoutMs:v.commandTimeoutMs}),oe){let d=de();d&&se.add(d)}}let D=ce(n,$e),K=D.simIdSource==="flag"?D.simId:de()||D.simId,wt=D.simIdSource==="flag"?"flag":K?"saved":"none",F=ue(D.wsPort,{commandTimeoutMs:D.commandTimeoutMs,simId:K,simIdSource:wt}),c,Re=async()=>{if(!W)return!1;let h=await F.send({type:"evaluate",simId:c.simId,code:"window.location.href"});if(typeof h=="string"&&h.length>0){let d=new URL(h);d.searchParams.set("device",W),c.setSimRouteHint(d.toString())}return!!await F.send({type:"call",simId:c.simId,path:"SootSim.bridges.settings.set",args:["deviceModel",W]})};if(c=new ee(F,{screenshotDir:s,flowDir:w.dirname(w.resolve(e)),screenshotPathMode:l,screenshotLayers:u,simId:K,recordingOutputDir:A?a:void 0,recordingFormat:g?"mp4":"webm",billingOriginOverride:g?P:void 0,allowGitHubRecording:g,requireRecordingEntitlement:g,onAfterLaunch:async()=>{await Re()&&await c.waitForTree(12e4),g&&await F.send({type:"evaluate",simId:c.simId,code:`(() => {
547
547
  const r = window.SootSim?.bridges?.eventRecorder ?? window.__sootsimEventRecorder
548
548
  return r?.start?.() ?? false
549
- })()`})}}),g&&(d.stepDelay=g),d.js.putEnv("MAESTRO_FILENAME",b.basename(e,b.extname(e))),T.env&&typeof T.env=="object")for(let[u,c]of Object.entries(T.env))d.js.putEnv(u,c);let R=null,x=null,B=null,M=null,K=0,q=!!A[0]?.launchApp;try{q||await d.waitForTree(12e4),await ke()&&!q&&await d.waitForTree(12e4),m&&!q&&!process.env.SOOTSIM_PREVIEW_RESET_DONE&&await d.launchApp({clearState:!0}),P&&(q?d.prepareRecording():await d.startRecording()),r&&await d.startProfile(),m&&(await F.send({type:"evaluate",simId:d.simId,code:`(() => {
549
+ })()`})}}),m&&(c.stepDelay=m),c.liveStatus=new te(F,w.basename(e)),c.js.putEnv("MAESTRO_FILENAME",w.basename(e,w.extname(e))),E.env&&typeof E.env=="object")for(let[h,d]of Object.entries(E.env))c.js.putEnv(h,d);let M=null,T=null,B=null,O=null,ae=null,j=0,q=!!R[0]?.launchApp;try{q||await c.waitForTree(12e4),await Re()&&!q&&await c.waitForTree(12e4),g&&!q&&!process.env.SOOTSIM_PREVIEW_RESET_DONE&&await c.launchApp({clearState:!0}),A&&(q?c.prepareRecording():await c.startRecording()),i&&await c.startProfile(),g&&(await F.send({type:"evaluate",simId:c.simId,code:`(() => {
550
550
  const r = window.SootSim?.bridges?.eventRecorder ?? window.__sootsimEventRecorder
551
551
  return r?.start?.() ?? false
552
- })()`})||console.warn(" warn: eventRecorder.start() returned false \u2014 preview will upload bundle without replay events")),await d.runFlow(A),r&&(R=await d.stopProfile()),await d.waitForRecordingTail({maxMs:lt,smart:m}),P&&(x=await d.stopRecording(),B=d.getLastRecordingDurationMs()),m&&(M=await F.send({type:"evaluate",simId:d.simId,code:`(() => {
552
+ })()`})||console.warn(" warn: eventRecorder.start() returned false \u2014 preview will upload bundle without replay events")),await c.runFlow(R),i&&(M=await c.stopProfile()),await c.waitForRecordingTail({maxMs:pt,smart:g}),A&&(T=await c.stopRecording(),B=c.getLastRecordingDurationMs()),g&&(O=await F.send({type:"evaluate",simId:c.simId,code:`(() => {
553
553
  const r = window.SootSim?.bridges?.eventRecorder ?? window.__sootsimEventRecorder
554
554
  return r?.stop?.() ?? []
555
- })()`}),console.log(` captured ${M.length} replay events`));let c=A.filter(w=>w&&typeof w=="object"&&"takeScreenshot"in w).length;console.log(`
556
- + completed (${A.length} steps)`),c>0&&console.log(` screenshots: ${c} \u2192 ${s}`),R&&it(R),x&&console.log(` video: ${x}`),console.log()}catch(u){if(r&&!R)try{R=await d.stopProfile()}catch{}if(P&&!x)try{x=await d.stopRecording(),B=d.getLastRecordingDurationMs()}catch(c){console.warn(` recording stop failed: ${c?.message||String(c)}`)}if(m&&!M)try{M=await F.send({type:"evaluate",simId:d.simId,code:`(() => {
555
+ })()`}),console.log(` captured ${O.length} replay events`));let d=R.filter(y=>y&&typeof y=="object"&&"takeScreenshot"in y).length;console.log(`
556
+ + completed (${R.length} steps)`),d>0&&console.log(` screenshots: ${d} \u2192 ${s}`),M&&at(M),T&&console.log(` video: ${T}`),console.log()}catch(h){if(i&&!M)try{M=await c.stopProfile()}catch{}if(A&&!T)try{T=await c.stopRecording(),B=c.getLastRecordingDurationMs()}catch(d){console.warn(` recording stop failed: ${d?.message||String(d)}`)}if(g&&!O)try{O=await F.send({type:"evaluate",simId:c.simId,code:`(() => {
557
557
  const r = window.SootSim?.bridges?.eventRecorder ?? window.__sootsimEventRecorder
558
558
  return r?.stop?.() ?? []
559
- })()`}),console.log(` captured ${M.length} partial replay events`)}catch(c){console.warn(` event recorder stop failed: ${c?.message||String(c)}`)}console.error(`
560
- x failed: ${u.message}
561
- `),R&&(console.log(" partial profile:"),it(R)),x&&console.log(` partial video: ${x}`);try{let c=d.lastFailedStep,w=c?`step-${String(c.index+1).padStart(2,"0")}-${c.kind}`:"unstaged",O=b.join(s,w);await d.captureFailureBundle(O,{error:u,stepIndex:c?.index,stepKind:c?.kind,stepTarget:c?.target}),console.log(` failure bundle: ${O}`),console.log(" (contents: screenshot.png, describe.json, a11y.txt, tree.txt, console.json, error.json)")}catch(c){try{let w=b.join(s,"error.png");await d.captureFailureScreenshot(w),console.log(` error screenshot: ${w}`)}catch{}console.log(` (failure bundle capture failed: ${c instanceof Error?c.message:String(c)})`)}await He(F,{errorsCommand:`sootsim get errors 5${d.simId?` --sim ${d.simId}`:""}`,warningsCommand:`sootsim get warnings 5${d.simId?` --sim ${d.simId}`:""}`,requestsCommand:`sootsim get requests 5${d.simId?` --sim ${d.simId}`:""}`}),K=1}if(m&&(K===0||x||M))try{let u=await Nt(M??[]),c=["--origin",k,"--events",u];_&&c.push("--public-origin",_),x&&c.push("--video",x),x&&B&&Number.isFinite(B)&&(c.push("--video-duration-ms",String(Math.round(B))),c.push("--recorded-duration-ms",String(Math.round(B))));let w=d.getLastRecordingStartedAtMs();w&&Number.isFinite(w)&&c.push("--recording-started-at-ms",String(Math.round(w))),v.wsPort&&c.push("--port",String(v.wsPort)),d.simId&&c.push("--sim",d.simId),ot&&c.push("--open"),xe&&c.push("--owner",xe),Te&&c.push("--repo",Te),H&&c.push("--billing-kind",H),console.log(`
562
- preparing preview upload\u2026`);let O=d.getFlowTraceSteps();O.length>0&&c.push("--timeline-events",await Lt(O));let j=d.getLastRecordingFrameStats();j&&c.push("--trace-frame-stats",await Ht(j));let{runUpload:C}=await import("./upload-ZFINR6K3.js");ve=await C(c,{})}catch(u){console.error(` preview upload failed: ${u?.message||u}`),K=1}return F.close(),ne?(d.simId&&oe.add(d.simId),await Ct(v.wsPort,v.commandTimeoutMs,[...oe])):d.simId&&d.simId!==z&&Me(d.simId),await se(),K}async function Ct(n,e,t){let r=[...new Set(t.filter(Boolean))];if(r.length===0)return;let i=ce(n,{commandTimeoutMs:e});try{let o=await i.listSims(),a=r.filter(l=>o.some(p=>p.id===l&&p.readyState==="open"));if(a.length===0)return;let s=await Je(i,n,e,a);await Ue(o,a),s.closed.length>0&&console.log(` closed flow sim(s): ${s.closed.join(", ")}`),s.remaining.length>0&&console.warn(` warn: flow sim(s) still connected after close: ${s.remaining.join(", ")}`)}catch(o){console.warn(` warn: failed to close flow sim(s): ${o instanceof Error?o.message:String(o)}`)}finally{i.close()}}async function Nt(n){let{gzipSync:e}=await import("zlib"),t=n.map(o=>JSON.stringify(o)).join(`
559
+ })()`}),console.log(` captured ${O.length} partial replay events`)}catch(d){console.warn(` event recorder stop failed: ${d?.message||String(d)}`)}console.error(`
560
+ x failed: ${h.message}
561
+ `),M&&(console.log(" partial profile:"),at(M)),T&&console.log(` partial video: ${T}`);try{let d=c.lastFailedStep,y=d?`step-${String(d.index+1).padStart(2,"0")}-${d.kind}`:"unstaged",$=w.join(s,y);await c.captureFailureBundle($,{error:h,stepIndex:d?.index,stepKind:d?.kind,stepTarget:d?.target}),ae=$,console.log(` failure bundle: ${$}`),console.log(" (contents: screenshot.png, describe.json, a11y.txt, tree.txt, console.json, error.json)")}catch(d){try{let y=w.join(s,"error.png");await c.captureFailureScreenshot(y),console.log(` error screenshot: ${y}`)}catch{}console.log(` (failure bundle capture failed: ${d instanceof Error?d.message:String(d)})`)}await Ue(F,{errorsCommand:`sootsim get errors 5${c.simId?` --sim ${c.simId}`:""}`,warningsCommand:`sootsim get warnings 5${c.simId?` --sim ${c.simId}`:""}`,requestsCommand:`sootsim get requests 5${c.simId?` --sim ${c.simId}`:""}`}),j=1}if(await c.liveStatus?.end(j===0?"passed":"failed"),g&&(j===0||T||O))try{let h=await Wt(O??[]),d=["--origin",P,"--events",h];_&&d.push("--public-origin",_),T&&d.push("--video",T),T&&B&&Number.isFinite(B)&&(d.push("--video-duration-ms",String(Math.round(B))),d.push("--recorded-duration-ms",String(Math.round(B))));let y=c.getLastRecordingStartedAtMs();y&&Number.isFinite(y)&&d.push("--recording-started-at-ms",String(Math.round(y))),v.wsPort&&d.push("--port",String(v.wsPort)),c.simId&&d.push("--sim",c.simId),dt&&d.push("--open"),Fe&&d.push("--owner",Fe),Ie&&d.push("--repo",Ie),H&&d.push("--billing-kind",H),console.log(`
562
+ preparing preview upload\u2026`);let $=c.getFlowTraceSteps();$.length>0&&d.push("--timeline-events",await jt($)),ae&&d.push("--failure-bundle",ae);let U=c.getLastRecordingFrameStats();U&&d.push("--trace-frame-stats",await Ut(U));let{runUpload:L}=await import("./upload-X2BRKPBJ.js");Te=await L(d,{})}catch(h){console.error(` preview upload failed: ${h?.message||h}`),j=1}return Ee=c.getFlowTraceSteps(),F.close(),oe?(c.simId&&se.add(c.simId),await Ht(v.wsPort,v.commandTimeoutMs,[...se])):c.simId&&c.simId!==K&&De(c.simId),await le(),j}async function Ht(n,e,t){let i=[...new Set(t.filter(Boolean))];if(i.length===0)return;let r=ue(n,{commandTimeoutMs:e});try{let o=await r.listSims(),a=i.filter(l=>o.some(u=>u.id===l&&u.readyState==="open"));if(a.length===0)return;let s=await Ke(r,n,e,a);await Ge(o,a),s.closed.length>0&&console.log(` closed flow sim(s): ${s.closed.join(", ")}`),s.remaining.length>0&&console.warn(` warn: flow sim(s) still connected after close: ${s.remaining.join(", ")}`)}catch(o){console.warn(` warn: failed to close flow sim(s): ${o instanceof Error?o.message:String(o)}`)}finally{r.close()}}async function Wt(n){let{gzipSync:e}=await import("zlib"),t=n.map(o=>JSON.stringify(o)).join(`
563
563
  `)+(n.length?`
564
- `:""),r=e(Buffer.from(t,"utf8")),i=b.join(te(),`sootsim-events-${Date.now()}.jsonl.gz`);return $.writeFileSync(i,r),console.log(` events: ${n.length} written to ${i} (${r.length} bytes gz)`),i}async function Lt(n){let{gzipSync:e}=await import("zlib"),t=n.map((a,s)=>({schemaVersion:1,t:a.endedAtMs,seq:1e6+s,context:"host",kind:"flow-step",id:`flow-step-${a.stepIndex}`,data:{stepIndex:a.stepIndex,stepNumber:a.stepIndex+1,stepName:a.stepName,...a.targetLabel?{targetLabel:a.targetLabel}:{},status:a.status,durationMs:a.durationMs,startedAtMs:a.startedAtMs,endedAtMs:a.endedAtMs,...a.error?{error:a.error}:{}}})),r=t.map(a=>JSON.stringify(a)).join(`
564
+ `:""),i=e(Buffer.from(t,"utf8")),r=w.join(ie(),`sootsim-events-${Date.now()}.jsonl.gz`);return k.writeFileSync(r,i),console.log(` events: ${n.length} written to ${r} (${i.length} bytes gz)`),r}async function jt(n){let{gzipSync:e}=await import("zlib"),t=n.map((a,s)=>({schemaVersion:1,t:a.endedAtMs,seq:1e6+s,context:"host",kind:"flow-step",id:`flow-step-${a.stepIndex}`,data:{stepIndex:a.stepIndex,stepNumber:a.stepIndex+1,stepName:a.stepName,...a.targetLabel?{targetLabel:a.targetLabel}:{},status:a.status,durationMs:a.durationMs,startedAtMs:a.startedAtMs,endedAtMs:a.endedAtMs,...a.error?{error:a.error}:{}}})),i=t.map(a=>JSON.stringify(a)).join(`
565
565
  `)+`
566
- `,i=e(Buffer.from(r,"utf8")),o=b.join(te(),`sootsim-flow-steps-${Date.now()}.jsonl.gz`);return $.writeFileSync(o,i),console.log(` flow trace: ${t.length} step events written to ${o} (${i.length} bytes gz)`),o}async function Ht(n){let e=b.join(te(),`sootsim-frame-stats-${Date.now()}.json`);return $.writeFileSync(e,JSON.stringify(n)),console.log(` frame stats: written to ${e}`),e}async function Wt(n){let e=n[0],t=r=>n.find((i,o)=>n[o-1]===r);switch(e){case"start":{let{path:r,state:i}=ze();console.log(" flow draft started"),console.log(` session: ${r}`),console.log(` steps: ${i.steps.length}`);return}case"keep":case"good":{let r=me();if(r.active||(console.error(" no active flow draft \u2014 run `sootsim flow start` first"),process.exit(1)),!r.kept){console.log(" no pending action to keep");return}console.log(` kept: ${r.candidate.summary}`),console.log(` steps: ${r.stepCount}`);return}case"end":{let r=t("--output")||(n[1]&&!n[1].startsWith("-")?n[1]:void 0),i=n.includes("--validate")||n.includes("--video"),o=n.includes("--video"),a=me();a.active&&a.kept&&console.log(` auto-kept trailing action: ${a.candidate.summary}`);let s=Ke(r||(i?Ut():void 0));if(s.active||(console.error(" no active flow draft \u2014 run `sootsim flow start` first"),process.exit(1)),!s.valid){console.error(" flow draft is not valid:");for(let l of s.issues)console.error(` - ${l}`);console.error(" draft preserved \u2014 keep at least one real interaction or run `sootsim flow start` to reset"),process.exit(1)}if(i){let l=Vt(n,s.outputPath),p=await nt(l);if(p!==0){console.error(`
567
- validation failed \u2014 draft preserved so you can keep iterating`),process.exitCode=p;return}fe(),console.log(` flow draft validated (${s.stepCount} step${s.stepCount===1?"":"s"})`),s.outputPath&&console.log(` saved: ${s.outputPath}`),o&&console.log(" video: recorded during validation run");return}if(fe(),console.log(` flow draft ended (${s.stepCount} step${s.stepCount===1?"":"s"})`),s.outputPath){console.log(` saved: ${s.outputPath}`),console.log(` next: sootsim flow ${s.outputPath} --record`);return}console.log(""),process.stdout.write(s.yaml);return}case"validate":{let r=n[1];(!r||r.startsWith("-"))&&(console.error(" usage: sootsim flow validate <path>"),process.exit(1));let i=he(r);if(i.length>0){console.error(` x ${r} failed validation:`);for(let o of i)console.error(` - ${o}`);process.exit(1)}console.log(` + ${r} looks valid`);return}}}function jt(n){return n[0]==="--sim"&&n.length>=2?[...n.slice(2),"--sim",n[1]]:n}async function xr(n){let e=jt(n),t=e[0];if(t==="start"||t==="keep"||t==="good"||t==="end"||t==="validate")return await Wt(e),0;let r=await nt(e);return r!==0&&(process.exitCode=r),r}function it(n){console.log(""),qe(n)}function Ut(){return b.join(te(),`sootsim-flow-draft-${Date.now()}.yaml`)}function Vt(n,e){if(!e)throw new Error("validated flow draft requires an output path");let t=[e];for(let r=1;r<n.length;r++){let i=n[r];if(!(i==="--validate"||i==="--video")){if(i==="--output"){r+=1;continue}r===1&&!i.startsWith("-")||t.push(i)}}return!t.includes("--record")&&n.includes("--video")&&t.push("--record"),t}export{et as a,vt as b,vr as c,Bt as d,nt as e,jt as f,xr as g};
566
+ `,r=e(Buffer.from(i,"utf8")),o=w.join(ie(),`sootsim-flow-steps-${Date.now()}.jsonl.gz`);return k.writeFileSync(o,r),console.log(` flow trace: ${t.length} step events written to ${o} (${r.length} bytes gz)`),o}async function Ut(n){let e=w.join(ie(),`sootsim-frame-stats-${Date.now()}.json`);return k.writeFileSync(e,JSON.stringify(n)),console.log(` frame stats: written to ${e}`),e}async function Vt(n){let e=n[0],t=i=>n.find((r,o)=>n[o-1]===i);switch(e){case"start":{let{path:i,state:r}=Ye();console.log(" flow draft started"),console.log(` session: ${i}`),console.log(` steps: ${r.steps.length}`);return}case"keep":case"good":{let i=we();if(i.active||(console.error(" no active flow draft \u2014 run `sootsim flow start` first"),process.exit(1)),!i.kept){console.log(" no pending action to keep");return}console.log(` kept: ${i.candidate.summary}`),console.log(` steps: ${i.stepCount}`);return}case"end":{let i=t("--output")||(n[1]&&!n[1].startsWith("-")?n[1]:void 0),r=n.includes("--validate")||n.includes("--video"),o=n.includes("--video"),a=we();a.active&&a.kept&&console.log(` auto-kept trailing action: ${a.candidate.summary}`);let s=Ze(i||(r?Gt():void 0));if(s.active||(console.error(" no active flow draft \u2014 run `sootsim flow start` first"),process.exit(1)),!s.valid){console.error(" flow draft is not valid:");for(let l of s.issues)console.error(` - ${l}`);console.error(" draft preserved \u2014 keep at least one real interaction or run `sootsim flow start` to reset"),process.exit(1)}if(r){let l=zt(n,s.outputPath),u=await lt(l);if(u!==0){console.error(`
567
+ validation failed \u2014 draft preserved so you can keep iterating`),process.exitCode=u;return}ge(),console.log(` flow draft validated (${s.stepCount} step${s.stepCount===1?"":"s"})`),s.outputPath&&console.log(` saved: ${s.outputPath}`),o&&console.log(" video: recorded during validation run");return}if(ge(),console.log(` flow draft ended (${s.stepCount} step${s.stepCount===1?"":"s"})`),s.outputPath){console.log(` saved: ${s.outputPath}`),console.log(` next: sootsim flow ${s.outputPath} --record`);return}console.log(""),process.stdout.write(s.yaml);return}case"validate":{let i=n[1];(!i||i.startsWith("-"))&&(console.error(" usage: sootsim flow validate <path>"),process.exit(1));let r=me(i);if(r.length>0){console.error(` x ${i} failed validation:`);for(let o of r)console.error(` - ${o}`);process.exit(1)}console.log(` + ${i} looks valid`);return}}}function Jt(n){return n[0]==="--sim"&&n.length>=2?[...n.slice(2),"--sim",n[1]]:n}async function ki(n){let e=Jt(n),t=e[0];if(t==="start"||t==="keep"||t==="good"||t==="end"||t==="validate")return await Vt(e),0;let i=await lt(e);return i!==0&&(process.exitCode=i),i}function at(n){console.log(""),Xe(n)}function Gt(){return w.join(ie(),`sootsim-flow-draft-${Date.now()}.yaml`)}function zt(n,e){if(!e)throw new Error("validated flow draft requires an output path");let t=[e];for(let i=1;i<n.length;i++){let r=n[i];if(!(r==="--validate"||r==="--video")){if(r==="--output"){i+=1;continue}i===1&&!r.startsWith("-")||t.push(r)}}return!t.includes("--record")&&n.includes("--video")&&t.push("--record"),t}export{rt as a,Ft as b,Ii as c,$i as d,Nt as e,lt as f,Jt as g,ki as h};
@@ -1,3 +1,3 @@
1
- /*! sootsim v0.1.201 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
- import{o as d}from"./chunk-ORIISY22.js";import{chmodSync as S,existsSync as f,mkdirSync as k,readFileSync as A,rmSync as i,writeFileSync as y}from"node:fs";import{dirname as c,join as D,resolve as m}from"node:path";var s=1,p="SOOTSIM_SHARED_AUTH_FILE",u="https://sootbean.com";function w(){let t=process.env[p];return t?.trim()?c(m(t)):d()}function a(){let t=process.env[p];return t?.trim()?m(t):D(w(),"desktop-auth.json")}function g(t){if(!t||typeof t!="object")return null;let e=t;return typeof e.id!="string"||!e.id.trim()?null:{id:e.id.trim(),name:typeof e.name=="string"?e.name:void 0,email:typeof e.email=="string"?e.email:void 0,image:typeof e.image=="string"?e.image:void 0,githubUsername:typeof e.githubUsername=="string"?e.githubUsername:void 0,teams:Array.isArray(e.teams)?e.teams.map(r=>{if(!r||typeof r!="object")return null;let n=r;return typeof n.id!="string"||typeof n.name!="string"?null:{id:n.id,name:n.name,role:n.role==="owner"?"owner":"member",githubOrg:typeof n.githubOrg=="string"?n.githubOrg:null}}).filter(r=>!!r):void 0}}function v(t){if(!t||typeof t!="object")return null;let e=t;if(e.version!==s||typeof e.token!="string"||!e.token.trim())return null;let r=typeof e.origin=="string"&&e.origin.trim()?e.origin.trim():u,n=e.source==="cli"||e.source==="electron"||e.source==="browser"||e.source==="unknown"?e.source:"unknown",o=typeof e.updatedAt=="string"&&e.updatedAt?e.updatedAt:new Date().toISOString(),h=typeof e.validatedAt=="string"&&e.validatedAt?e.validatedAt:void 0;return{version:s,token:e.token.trim(),user:g(e.user),origin:r,source:n,updatedAt:o,validatedAt:h}}function b(){let t=a();if(!f(t))return null;try{let e=JSON.parse(A(t,"utf8")),r=v(e);return r||(i(t,{force:!0}),null)}catch{return i(t,{force:!0}),null}}function O(t){let e=a();k(c(e),{recursive:!0});let r={version:s,token:t.token.trim(),user:t.user?g(t.user):null,origin:t.origin?.trim()||u,source:t.source,updatedAt:t.updatedAt||new Date().toISOString(),validatedAt:t.validatedAt};y(e,JSON.stringify(r,null,2)+`
1
+ /*! sootsim v0.1.203 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
+ import{o as d}from"./chunk-ZGM7N2AV.js";import{chmodSync as S,existsSync as f,mkdirSync as k,readFileSync as A,rmSync as i,writeFileSync as y}from"node:fs";import{dirname as c,join as D,resolve as m}from"node:path";var s=1,p="SOOTSIM_SHARED_AUTH_FILE",u="https://sootbean.com";function w(){let t=process.env[p];return t?.trim()?c(m(t)):d()}function a(){let t=process.env[p];return t?.trim()?m(t):D(w(),"desktop-auth.json")}function g(t){if(!t||typeof t!="object")return null;let e=t;return typeof e.id!="string"||!e.id.trim()?null:{id:e.id.trim(),name:typeof e.name=="string"?e.name:void 0,email:typeof e.email=="string"?e.email:void 0,image:typeof e.image=="string"?e.image:void 0,githubUsername:typeof e.githubUsername=="string"?e.githubUsername:void 0,teams:Array.isArray(e.teams)?e.teams.map(r=>{if(!r||typeof r!="object")return null;let n=r;return typeof n.id!="string"||typeof n.name!="string"?null:{id:n.id,name:n.name,role:n.role==="owner"?"owner":"member",githubOrg:typeof n.githubOrg=="string"?n.githubOrg:null}}).filter(r=>!!r):void 0}}function v(t){if(!t||typeof t!="object")return null;let e=t;if(e.version!==s||typeof e.token!="string"||!e.token.trim())return null;let r=typeof e.origin=="string"&&e.origin.trim()?e.origin.trim():u,n=e.source==="cli"||e.source==="electron"||e.source==="browser"||e.source==="unknown"?e.source:"unknown",o=typeof e.updatedAt=="string"&&e.updatedAt?e.updatedAt:new Date().toISOString(),h=typeof e.validatedAt=="string"&&e.validatedAt?e.validatedAt:void 0;return{version:s,token:e.token.trim(),user:g(e.user),origin:r,source:n,updatedAt:o,validatedAt:h}}function b(){let t=a();if(!f(t))return null;try{let e=JSON.parse(A(t,"utf8")),r=v(e);return r||(i(t,{force:!0}),null)}catch{return i(t,{force:!0}),null}}function O(t){let e=a();k(c(e),{recursive:!0});let r={version:s,token:t.token.trim(),user:t.user?g(t.user):null,origin:t.origin?.trim()||u,source:t.source,updatedAt:t.updatedAt||new Date().toISOString(),validatedAt:t.validatedAt};y(e,JSON.stringify(r,null,2)+`
3
3
  `);try{S(e,384)}catch{}return r}function l(){i(a(),{force:!0})}async function E(t){let e=b();if(!e?.token)return null;let r=t||e.origin||u;try{let n=await fetch(`${r.replace(/\/$/,"")}/api/auth/me`,{headers:{authorization:`Bearer ${e.token}`}});if(n.status===401)return l(),null;if(!n.ok)return e;let o=await n.json();return o.user?.id?O({token:e.token,user:o.user,origin:r,source:e.source,validatedAt:new Date().toISOString()}):(l(),null)}catch{return e}}export{b as a,O as b,l as c,E as d};
@@ -1,3 +1,3 @@
1
- /*! sootsim v0.1.201 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
- import{j as n}from"./chunk-423YVBZK.js";var i=[];for(let[t,e]of Object.entries(n))e.cliFlag&&i.push({name:`--${e.cliFlag}`,short:e.cliFlagShort?`-${e.cliFlagShort}`:void 0,key:t,type:e.type==="enum"?"string":e.type,description:e.description,options:e.options,default:e.default});var a=i;function g(){let t=[];for(let e of a){let s=e.short?`${e.short}, ${e.name}`:` ${e.name}`,o=e.options?` [${e.options.join("|")}]`:"",r=e.default!==void 0?` (default: ${e.default})`:"";t.push(` ${s.padEnd(24)}${e.description}${o}${r}`)}return t.join(`
1
+ /*! sootsim v0.1.203 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
+ import{j as n}from"./chunk-62AKBZTO.js";var i=[];for(let[t,e]of Object.entries(n))e.cliFlag&&i.push({name:`--${e.cliFlag}`,short:e.cliFlagShort?`-${e.cliFlagShort}`:void 0,key:t,type:e.type==="enum"?"string":e.type,description:e.description,options:e.options,default:e.default});var a=i;function g(){let t=[];for(let e of a){let s=e.short?`${e.short}, ${e.name}`:` ${e.name}`,o=e.options?` [${e.options.join("|")}]`:"",r=e.default!==void 0?` (default: ${e.default})`:"";t.push(` ${s.padEnd(24)}${e.description}${o}${r}`)}return t.join(`
3
3
  `)}export{g as a};
@@ -1,2 +1,2 @@
1
- /*! sootsim v0.1.201 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! sootsim v0.1.203 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  var c="sootsim-agent-prompt-v1";function r(n){return typeof n=="string"?n.trim():""}function m(n){let e=r(n.text);if(!e)return"";let t=r(n.displayText),s=r(n.inspectSummary),o=r(n.inspectTrace);return!!s||!!o||/[\r\n]/.test(e)||!!t&&t!==e?JSON.stringify({__sootsimAgentPrompt:c,text:e,displayText:t,inspectSummary:s,inspectTrace:o}):e}function u(n){let e=r(n);if(!e)return null;try{let t=JSON.parse(e);if(t.__sootsimAgentPrompt!==c)return{text:e};let s=r(typeof t.text=="string"?t.text:void 0);if(!s)return null;let o=r(typeof t.displayText=="string"?t.displayText:void 0),i=r(typeof t.inspectSummary=="string"?t.inspectSummary:void 0),p=r(typeof t.inspectTrace=="string"?t.inspectTrace:void 0);return{text:s,...o?{displayText:o}:{},...i?{inspectSummary:i}:{},...p?{inspectTrace:p}:{}}}catch{return{text:e}}}export{m as a,u as b};
@@ -1,5 +1,5 @@
1
- /*! sootsim v0.1.201 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
- import{a as E,b as D}from"./chunk-HVSDT56M.js";import{E as T}from"./chunk-ORIISY22.js";var N="sootsimConfig";function p(e){return!!e&&Object.keys(e).length>0}function $(e){return e?p(e.modules)||p(e.turboModules)||p(e.nativeModules)||p(e.env)||p(e.network?.remap)||p(e.settings)||p(e.initialState):!1}function j(e,t){let n=new URL(e);return $(t)?n.searchParams.set(N,JSON.stringify(t)):n.searchParams.delete(N),n.toString()}var me="/index.bundle?platform=ios&dev=true&hot=true&minify=false";function A(e){return/^https?:\/\//i.test(e)}function O(e){return e.endsWith(".bundle")}function H(e){process.env.SOOTSIM_PREVIEW_PROD_BUNDLE&&(e.searchParams.set("dev","false"),e.searchParams.set("minify","true"),e.searchParams.has("hot")&&e.searchParams.set("hot","false"))}function I(e){try{let t=A(e),n=new URL(e,"http://soot.local");return n.pathname=n.pathname.replace(/\.\.bundle$/,".bundle"),O(n.pathname)?(n.searchParams.delete("transform.bytecode"),n.searchParams.get("lazy")==="true"&&n.searchParams.set("lazy","false"),H(n),t?n.toString():`${n.pathname}${n.search}${n.hash}`):e}catch{return e}}function pe(e,t){try{let n=A(e),o=new URL(e,"http://soot.local");return O(o.pathname)?(o.searchParams.set("hot",t?"true":"false"),n?o.toString():`${o.pathname}${o.search}${o.hash}`):e}catch{return e}}import{exec as W}from"child_process";import B from"http";import F from"net";import{promisify as G}from"util";var _=G(W);E();var z=250,J=1500,K=120;function V(e,t=K){return new Promise(n=>{let o=new F.Socket,s=!1,i=a=>{s||(s=!0,o.destroy(),n(a))};o.setTimeout(t),o.once("connect",()=>i(!0)),o.once("timeout",()=>i(!1)),o.once("error",()=>i(!1)),o.connect(e,"localhost")})}function h(e,t,n="GET",o=z,s={}){return new Promise(i=>{let a=B.request({hostname:"localhost",port:e,path:t,method:n,timeout:o,headers:s},r=>{let c="";r.on("data",l=>c+=l.toString());let u=(()=>{let l=r.headers["content-type"];if(typeof l=="string")return l;if(Array.isArray(l))return l[0]})();r.on("end",()=>i({statusCode:r.statusCode||0,body:c,contentType:u}))});a.on("error",()=>i(null)),a.setTimeout(o,()=>{a.destroy(),i(null)}),a.end()})}var q=[8081,8082,8083,8084,8085,8086,3e3,3001,19e3].map(e=>({port:e,pid:0}));function C(e,t){return!(e<=0||e>=2e4||t.has(e)||e>=5170&&e<=5200)}async function Y(e=[]){let t=new Set(e);try{let{stdout:n}=await _("lsof -iTCP -sTCP:LISTEN -P -n 2>/dev/null | grep -E '^(node|bun)'",{encoding:"utf8",timeout:2e3});if(n.trim()){let o=new Map;for(let s of n.trim().split(`
1
+ /*! sootsim v0.1.203 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
+ import{a as E,b as D}from"./chunk-4NHPXU3X.js";import{H as T}from"./chunk-ZGM7N2AV.js";var N="sootsimConfig";function p(e){return!!e&&Object.keys(e).length>0}function $(e){return e?p(e.modules)||p(e.turboModules)||p(e.nativeModules)||p(e.env)||p(e.network?.remap)||p(e.settings)||p(e.initialState):!1}function j(e,t){let n=new URL(e);return $(t)?n.searchParams.set(N,JSON.stringify(t)):n.searchParams.delete(N),n.toString()}var me="/index.bundle?platform=ios&dev=true&hot=true&minify=false";function A(e){return/^https?:\/\//i.test(e)}function O(e){return e.endsWith(".bundle")}function H(e){process.env.SOOTSIM_PREVIEW_PROD_BUNDLE&&(e.searchParams.set("dev","false"),e.searchParams.set("minify","true"),e.searchParams.has("hot")&&e.searchParams.set("hot","false"))}function I(e){try{let t=A(e),n=new URL(e,"http://soot.local");return n.pathname=n.pathname.replace(/\.\.bundle$/,".bundle"),O(n.pathname)?(n.searchParams.delete("transform.bytecode"),n.searchParams.get("lazy")==="true"&&n.searchParams.set("lazy","false"),H(n),t?n.toString():`${n.pathname}${n.search}${n.hash}`):e}catch{return e}}function pe(e,t){try{let n=A(e),o=new URL(e,"http://soot.local");return O(o.pathname)?(o.searchParams.set("hot",t?"true":"false"),n?o.toString():`${o.pathname}${o.search}${o.hash}`):e}catch{return e}}import{exec as W}from"child_process";import B from"http";import F from"net";import{promisify as G}from"util";var _=G(W);E();var z=250,J=1500,K=120;function V(e,t=K){return new Promise(n=>{let o=new F.Socket,s=!1,i=a=>{s||(s=!0,o.destroy(),n(a))};o.setTimeout(t),o.once("connect",()=>i(!0)),o.once("timeout",()=>i(!1)),o.once("error",()=>i(!1)),o.connect(e,"localhost")})}function h(e,t,n="GET",o=z,s={}){return new Promise(i=>{let a=B.request({hostname:"localhost",port:e,path:t,method:n,timeout:o,headers:s},r=>{let c="";r.on("data",l=>c+=l.toString());let u=(()=>{let l=r.headers["content-type"];if(typeof l=="string")return l;if(Array.isArray(l))return l[0]})();r.on("end",()=>i({statusCode:r.statusCode||0,body:c,contentType:u}))});a.on("error",()=>i(null)),a.setTimeout(o,()=>{a.destroy(),i(null)}),a.end()})}var q=[8081,8082,8083,8084,8085,8086,3e3,3001,19e3].map(e=>({port:e,pid:0}));function C(e,t){return!(e<=0||e>=2e4||t.has(e)||e>=5170&&e<=5200)}async function Y(e=[]){let t=new Set(e);try{let{stdout:n}=await _("lsof -iTCP -sTCP:LISTEN -P -n 2>/dev/null | grep -E '^(node|bun)'",{encoding:"utf8",timeout:2e3});if(n.trim()){let o=new Map;for(let s of n.trim().split(`
3
3
  `)){let i=s.trim().split(/\s+/);if(i.length<9)continue;let a=Number(i[1]),c=i[8].match(/:(\d+)$/);if(!c)continue;let u=Number(c[1]);C(u,t)&&(o.has(u)||o.set(u,a))}if(o.size>0)return[...o.entries()].map(([s,i])=>({port:s,pid:i}))}}catch{}try{let{stdout:n}=await _(`ss -tlnp 2>/dev/null | grep -E '"(node|bun)"'`,{encoding:"utf8",timeout:2e3});if(n.trim()){let o=new Map;for(let s of n.trim().split(`
4
4
  `)){let i=s.match(/:(\d+)\s/),a=s.match(/pid=(\d+)/);if(!i)continue;let r=Number(i[1]),c=a?Number(a[1]):0;C(r,t)&&(o.has(r)||o.set(r,c))}if(o.size>0)return[...o.entries()].map(([s,i])=>({port:s,pid:i}))}}catch{}return q.filter(n=>C(n.port,t))}var x=new Map;async function Q(e){if(e<=0)return null;let t=x.get(e);if(t)return t;try{let{stdout:n}=await _(`lsof -p ${e} -a -d cwd -Fn 2>/dev/null`,{encoding:"utf8",timeout:1500});for(let o of n.split(`
5
5
  `))if(o.startsWith("n")&&o.length>1){let s=o.slice(1).trim();if(s)return x.set(e,s),s}}catch{}return null}function X(e,t){return{port:e,framework:t,bundleUrl:S(e,`http://localhost:${e}/index.bundle?platform=ios&dev=true&hot=true&minify=false`),hmrUrl:`ws://localhost:${e}/hot`,lastSeen:Date.now()}}function S(e,t){let n=D().find(s=>s.preferredPort===e),o=n?.runtimeConfig?j(t,n.runtimeConfig):t;return I(o)}function Z(e){return e.includes("/node_modules/one/metro-entry.bundle")}function ee(e){try{let t=JSON.parse(e);return t&&typeof t=="object"?t:null}catch{return null}}function w(e,t,n){if(!t)return e;try{let o=JSON.parse(t.body),s=o?.extra?.expoClient||o?.extra||{};s.name&&(e.projectName=s.name),s.ios?.bundleIdentifier&&(e.bundleId=s.ios.bundleIdentifier),e.framework==="metro"&&s.sdkVersion&&(e.framework="expo");let i=o?.launchAsset?.url;i&&!e.patched&&!Z(e.bundleUrl)&&(e.bundleUrl=S(e.port,i));let a=s.iconUrl||s.ios?.iconUrl||s.icon||s.ios?.icon;if(a)if(e.iconPath=a,n)if(a.startsWith("http"))e.iconUrl=n(a);else{let r=a.replace(/^\.\//,"");e.iconUrl=n(`http://localhost:${e.port}/assets/${r}`)}else e.iconUrl=a.startsWith("http")?a:`http://localhost:${e.port}/assets/${a.replace(/^\.\//,"")}`}catch{}return e}var ne=2e4,v=new Map,k=new Set;function M(e,t){if(e.projectName)return e;let n=v.get(e.port);if(n)return n.projectName&&(e.projectName=n.projectName),n.iconUrl&&!e.iconUrl&&(e.iconUrl=n.iconUrl,e.iconPath=n.iconPath),n.bundleId&&!e.bundleId&&(e.bundleId=n.bundleId),e;if(!k.has(e.port)){k.add(e.port);let o=e.port;te(o,t).finally(()=>k.delete(o))}return e}async function te(e,t){let n=await h(e,"/","GET",ne,{"expo-platform":"ios"});if(!n||n.statusCode!==200)return;let o=w({port:e,framework:"one",bundleUrl:"",lastSeen:0},n,t);!o.projectName&&!o.iconUrl||(v.set(e,{projectName:o.projectName,iconUrl:o.iconUrl,iconPath:o.iconPath,bundleId:o.bundleId}),b.delete(e))}var d=new Set,g=new Set,y=new Set;async function oe(e,t){if(!await V(e))return null;let n="/node_modules/one/metro-entry.bundle?platform=ios&dev=true",[o,s,i,a]=await Promise.all([d.has(e)?Promise.resolve(null):h(e,"/__soot/"),h(e,"/status"),y.has(e)?Promise.resolve(null):h(e,"/","GET",J,{"expo-platform":"ios"}),g.has(e)?Promise.resolve(null):h(e,"/_expo/status")]);a&&a.statusCode===200?g.delete(e):g.has(e)||g.add(e);let r=i?ee(i.body):null,c=typeof r?.launchAsset?.url=="string"?r.launchAsset.url:null,u=r?.extra?.expoClient||r?.extra||{};if(r&&(c||typeof u.name=="string")){d.add(e);let U=c||`http://localhost:${e}/index.bundle?platform=ios&dev=true&hot=true&minify=false`,L=U.includes("/one/metro-entry.bundle")?"one":"expo";return w({port:e,framework:L,bundleUrl:S(e,U),hmrUrl:`ws://localhost:${e}/hot`,lastSeen:Date.now()},i,t)}if(s&&s.body.includes("packager-status:running"))return d.add(e),M(w(X(e,a&&a.statusCode===200?"expo":"metro"),i,t),t);if(o&&o.statusCode===200&&o.body.includes("sootsim-patched"))return d.delete(e),M(w({port:e,framework:"one",bundleUrl:S(e,`http://localhost:${e}/__soot/bundle.js`),hmrUrl:`ws://localhost:${e}/hot`,lastSeen:Date.now(),patched:!0},i,t),t);if(s&&s.statusCode===200||a&&a.statusCode===200||i&&i.statusCode===200&&r!=null)return null;let m=await h(e,n,"HEAD");return m&&m.statusCode>0&&m.statusCode<400&&/application\/javascript/i.test(m.contentType||"")?(d.add(e),y.add(e),M(w({port:e,framework:"one",bundleUrl:S(e,`http://localhost:${e}${n}&minify=false`),hmrUrl:`ws://localhost:${e}/hot`,lastSeen:Date.now()},i,t),t)):(d.add(e),null)}function re(e){return!!e.bundleId?.trim().toLowerCase()?.startsWith("dev.sootsim.")}var b=new Map,se=3e4,ie=1500;function ae(e){return!e||e.framework==="metro"||e.framework==="unknown"}function ce(e){return e?S(e.port,e.bundleUrl)===e.bundleUrl:!0}function ue(e,t,n=Date.now()){if(t===0||e.pid!==t||!ce(e.result))return!1;let o=n-e.cachedAt;return!(e.result===null&&o>=se||ae(e.result)&&o>=ie)}async function xe(e={}){let t=await Y(e.excludePorts),n=new Set(t.map(r=>r.port));for(let r of[...b.keys()])n.has(r)||b.delete(r);for(let r of[...d])n.has(r)||d.delete(r);for(let r of[...g])n.has(r)||g.delete(r);for(let r of[...y])n.has(r)||y.delete(r);for(let r of[...v.keys()])n.has(r)||v.delete(r);let o=[],s=[];for(let{port:r,pid:c}of t){let u=b.get(r);if(u&&ue(u,c)){u.result&&o.push(u.result);continue}u&&u.pid!==c&&(d.delete(r),g.delete(r),y.delete(r),v.delete(r)),s.push({port:r,pid:c})}s.length>0&&(await Promise.all(s.map(c=>oe(c.port,e.buildIconProxyUrl)))).forEach((c,u)=>{let{port:l,pid:m}=s[u];m!==0&&b.set(l,{pid:m,result:c,cachedAt:Date.now()}),c&&o.push(c)});let i=new Map;for(let{port:r,pid:c}of t)c>0&&i.set(r,c);await Promise.all(o.map(async r=>{let c=i.get(r.port);if(!c)return;r.pid=c;let u=await Q(c);u&&(r.cwd=u)}));let a=new Set(i.values());for(let r of[...x.keys()])a.has(r)||x.delete(r);return o.filter(r=>!re(r))}import R from"fs";import f from"path";import{fileURLToPath as le}from"url";var P;function de(){if(P!==void 0)return P;let e=f.dirname(le(import.meta.url));for(let t=0;t<12&&e!==f.dirname(e);t++){if(R.existsSync(f.join(e,"packages/sootsim-engine/package.json"))&&R.existsSync(f.join(e,"public/sootsim")))return P=e,e;e=f.dirname(e)}return P=null,null}function Te(){if(process.env.SOOTSIM_HOME&&T())return null;let e=de();if(!e)return null;let t=f.join(e,"public/sootsim");return R.existsSync(f.join(t,"index.html"))&&R.existsSync(f.join(t,"engine/index.html"))&&R.existsSync(f.join(t,"engine-tenant/worker.js"))?t:null}export{j as a,me as b,I as c,pe as d,oe as e,xe as f,Te as g};
@@ -1,5 +1,5 @@
1
- /*! sootsim v0.1.201 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
- import{a as c}from"./chunk-RN662UDP.js";import{a as u,b as f,c as s,d as a}from"./chunk-SVM25PDV.js";import{a as e}from"./chunk-T6WXCSWP.js";import{c as n}from"./chunk-AHJ2WJST.js";import{a as i}from"./chunk-3RAGDMGM.js";import{a as m,c as p}from"./chunk-MQEEYPOK.js";function g(){return`sootsim CLI v${i()} \xB7 ${c().primary}`}function C(){let r=f({bridgePort:7668,defaultShellUrl:n},e()),o=`
1
+ /*! sootsim v0.1.203 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
+ import{a as c}from"./chunk-GYTATFQA.js";import{a as u,b as f,c as s,d as a}from"./chunk-LKJ5LA6K.js";import{a as e}from"./chunk-A3FIOG7U.js";import{c as n}from"./chunk-JLOAWSX6.js";import{a as i}from"./chunk-MQHSWXDS.js";import{a as m,c as p}from"./chunk-UJ64GJSZ.js";function g(){return`sootsim CLI v${i()} \xB7 ${c().primary}`}function C(){let r=f({bridgePort:7668,defaultShellUrl:n},e()),o=`
3
3
  ${p}
4
4
  `;console.log(`${g()}
5
5
  ${o}${r}