sootsim 0.0.4 → 0.1.36

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 (129) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +4 -4
  3. package/dist-cli/bin.js +12 -12
  4. package/dist-cli/chunks/{agent-PJAOF4JS.js → agent-YZB6D3DR.js} +4 -4
  5. package/dist-cli/chunks/agent-wrapper-VHCVS22I.js +15 -0
  6. package/dist-cli/chunks/{assert-P47NW4AF.js → assert-AIVCKKLG.js} +2 -2
  7. package/dist-cli/chunks/auto-bootstrap-MLNTX23H.js +2 -0
  8. package/dist-cli/chunks/chunk-27P763IZ.js +61 -0
  9. package/dist-cli/chunks/chunk-3UIWOHC2.js +62 -0
  10. package/dist-cli/chunks/chunk-5KGFHWVR.js +1 -0
  11. package/dist-cli/chunks/chunk-5QIUJNT3.js +5 -0
  12. package/dist-cli/chunks/{chunk-W7CYWXRZ.js → chunk-6GGMKFWJ.js} +1 -1
  13. package/dist-cli/chunks/{chunk-EHMSE3Q3.js → chunk-6Z275LCY.js} +2 -2
  14. package/dist-cli/chunks/chunk-75LBYBKW.js +11 -0
  15. package/dist-cli/chunks/chunk-A5BRCXYE.js +2 -0
  16. package/dist-cli/chunks/{chunk-UQ3N6FZF.js → chunk-CYCXOAVZ.js} +2 -2
  17. package/dist-cli/chunks/{chunk-QIP7LYQI.js → chunk-DFN3GGH7.js} +2 -2
  18. package/dist-cli/chunks/chunk-EBEHZJRG.js +117 -0
  19. package/dist-cli/chunks/{chunk-UKYK63H6.js → chunk-EJLNUMMP.js} +1 -1
  20. package/dist-cli/chunks/{chunk-DQKQYPIG.js → chunk-EWSQSALM.js} +2 -2
  21. package/dist-cli/chunks/{chunk-BQRM4E66.js → chunk-FE7UI3MT.js} +4 -4
  22. package/dist-cli/chunks/chunk-G663654J.js +1 -0
  23. package/dist-cli/chunks/chunk-G7XQD4KC.js +4 -0
  24. package/dist-cli/chunks/chunk-GW7XY5KC.js +2 -0
  25. package/dist-cli/chunks/{chunk-QQOBLF7O.js → chunk-H2QO4TDV.js} +2 -2
  26. package/dist-cli/chunks/{chunk-I6XGFZPA.js → chunk-HWCKZXNJ.js} +2 -2
  27. package/dist-cli/chunks/{chunk-UNFERMZ3.js → chunk-HWFHBMAQ.js} +2 -2
  28. package/dist-cli/chunks/chunk-IJMYFYDZ.js +2 -0
  29. package/dist-cli/chunks/chunk-J7CTD37P.js +1 -0
  30. package/dist-cli/chunks/{chunk-432TMHBG.js → chunk-KAXZHEKM.js} +1 -1
  31. package/dist-cli/chunks/{chunk-WWDJCKMI.js → chunk-LHDWH7VS.js} +1 -1
  32. package/dist-cli/chunks/{chunk-VGXARPIH.js → chunk-N32NCVL2.js} +2 -2
  33. package/dist-cli/chunks/{chunk-XJF46GU2.js → chunk-NIZBR7EK.js} +2 -2
  34. package/dist-cli/chunks/{chunk-MQDPKSCK.js → chunk-NYY36OKU.js} +12 -12
  35. package/dist-cli/chunks/{chunk-5TTQKPGH.js → chunk-OXN2PEB7.js} +1 -1
  36. package/dist-cli/chunks/{chunk-SY74J6F4.js → chunk-PJL25JQV.js} +1 -1
  37. package/dist-cli/chunks/{chunk-4XBPZQLW.js → chunk-RMW5BO3S.js} +2 -2
  38. package/dist-cli/chunks/chunk-SHO54NET.js +2 -0
  39. package/dist-cli/chunks/chunk-SMVJOWSV.js +16 -0
  40. package/dist-cli/chunks/chunk-TC6V7YFC.js +3 -0
  41. package/dist-cli/chunks/{chunk-6SZMLFCR.js → chunk-VFDRZNPN.js} +1 -1
  42. package/dist-cli/chunks/{chunk-AFQBSK2J.js → chunk-YIO6S3R5.js} +1 -1
  43. package/dist-cli/chunks/{chunk-AUR2LTNX.js → chunk-YLIIVTTQ.js} +2 -2
  44. package/dist-cli/chunks/chunk-YR7BGGYE.js +2 -0
  45. package/dist-cli/chunks/chunk-ZEW3RF5Q.js +1 -0
  46. package/dist-cli/chunks/{compat-ILLJ7VDL.js → compat-Y2O2U7FL.js} +2 -2
  47. package/dist-cli/chunks/{config-CDIAJIIT.js → config-SRBOFUCI.js} +2 -2
  48. package/dist-cli/chunks/control-PL2V2O6S.js +2 -0
  49. package/dist-cli/chunks/daemon-IZC32PZW.js +50 -0
  50. package/dist-cli/chunks/{debug-6SMCTPMC.js → debug-BIDMW2PE.js} +3 -3
  51. package/dist-cli/chunks/demo-app-registry-5JFOUU3D.js +2 -0
  52. package/dist-cli/chunks/{detox-R4G5INNB.js → detox-B3FDOIS3.js} +2 -2
  53. package/dist-cli/chunks/{device-YSLCWS4E.js → device-ZZSI363W.js} +2 -2
  54. package/dist-cli/chunks/drivers-S4NGK4DB.js +2 -0
  55. package/dist-cli/chunks/{electron-JZOFO37G.js → electron-5YFHXEOI.js} +3 -3
  56. package/dist-cli/chunks/flow-JJBO6TFY.js +2 -0
  57. package/dist-cli/chunks/{hints-O4QR6UGI.js → hints-G5HBBV2O.js} +2 -2
  58. package/dist-cli/chunks/home-paths-VWC3FWA3.js +2 -0
  59. package/dist-cli/chunks/{inspect-DRFAUJUH.js → inspect-POOPWUQI.js} +56 -52
  60. package/dist-cli/chunks/install-MP6FHXNZ.js +2 -0
  61. package/dist-cli/chunks/install-desktop-2MYEI4FM.js +23 -0
  62. package/dist-cli/chunks/{install-dev-desktop-CAJHPRNP.js → install-dev-desktop-SKH3KEHY.js} +2 -2
  63. package/dist-cli/chunks/{keys-OWQ7SOTM.js → keys-7PNASIQR.js} +2 -2
  64. package/dist-cli/chunks/{launch-WUEDHSO5.js → launch-JNS47LAQ.js} +3 -3
  65. package/dist-cli/chunks/login-YWZWUHBS.js +26 -0
  66. package/dist-cli/chunks/logout-O6SXMSBP.js +2 -0
  67. package/dist-cli/chunks/{maestro-PMHK6EHI.js → maestro-CW6XVUKV.js} +3 -3
  68. package/dist-cli/chunks/{preview-4RVHA2PP.js → preview-WGKJO5FS.js} +2 -2
  69. package/dist-cli/chunks/{profile-3IVNHUS6.js → profile-SUOBRPIC.js} +2 -2
  70. package/dist-cli/chunks/{record-KEWLM5JR.js → record-QPWLYH5R.js} +2 -2
  71. package/dist-cli/chunks/runtime-KEMO2MSB.js +25 -0
  72. package/dist-cli/chunks/{screenshot-BXRAQERZ.js → screenshot-JTY46V7G.js} +2 -2
  73. package/dist-cli/chunks/{screenshot-mode-5IXEDIUS.js → screenshot-mode-7OYBBX6D.js} +2 -2
  74. package/dist-cli/chunks/{screenshots-T4MQF3TB.js → screenshots-QISKC4GD.js} +2 -2
  75. package/dist-cli/chunks/server-YSFJAKAV.js +34 -0
  76. package/dist-cli/chunks/setup-repo-LFB3HBEO.js +2 -0
  77. package/dist-cli/chunks/{skills-DJA6QEVR.js → skills-MO7BFNVM.js} +2 -2
  78. package/dist-cli/chunks/store-6MFL53I4.js +2 -0
  79. package/dist-cli/chunks/telemetry-CN42GMVC.js +2 -0
  80. package/dist-cli/chunks/{test-IWUHNFXV.js → test-XUI3KNNQ.js} +3 -3
  81. package/dist-cli/chunks/upload-6FUT7AX5.js +2 -0
  82. package/dist-cli/chunks/{whoami-MCXFWKIH.js → whoami-TQFHY42N.js} +2 -2
  83. package/dist-lib/agent-daemon-client.cjs +3 -1
  84. package/dist-lib/agent-events.cjs +1 -1
  85. package/dist-lib/agent-sessions.cjs +2 -1
  86. package/dist-lib/attached-projects.cjs +1 -1
  87. package/dist-lib/auth/shared-session.cjs +1 -1
  88. package/dist-lib/backend-origin.cjs +1 -1
  89. package/dist-lib/bridge-constants.cjs +1 -1
  90. package/dist-lib/cli-constants.cjs +1 -1
  91. package/dist-lib/config.cjs +1 -1
  92. package/dist-lib/dev-bundle-resolution.cjs +3 -1
  93. package/dist-lib/home-paths.cjs +29 -3
  94. package/dist-lib/host/bridge-host.cjs +499 -59
  95. package/dist-lib/index.cjs +2 -2
  96. package/dist-lib/metro.cjs +2 -2
  97. package/dist-lib/render-mode.cjs +1 -1
  98. package/dist-lib/vite-base.cjs +800 -102
  99. package/dist-lib/vite.cjs +1 -1
  100. package/package.json +5 -3
  101. package/dist-cli/chunks/agent-wrapper-STO7PLQD.js +0 -15
  102. package/dist-cli/chunks/auto-bootstrap-SC2LMI2H.js +0 -2
  103. package/dist-cli/chunks/chunk-47S5DXXX.js +0 -11
  104. package/dist-cli/chunks/chunk-4VXB2DBA.js +0 -119
  105. package/dist-cli/chunks/chunk-C3QLIYCS.js +0 -16
  106. package/dist-cli/chunks/chunk-F4ARVCRR.js +0 -1
  107. package/dist-cli/chunks/chunk-HAKR72LJ.js +0 -2
  108. package/dist-cli/chunks/chunk-HGFIS26A.js +0 -2
  109. package/dist-cli/chunks/chunk-MZPAJ5PQ.js +0 -1
  110. package/dist-cli/chunks/chunk-OAHMYSMD.js +0 -2
  111. package/dist-cli/chunks/chunk-W3TYN64D.js +0 -62
  112. package/dist-cli/chunks/chunk-WRF43M33.js +0 -4
  113. package/dist-cli/chunks/chunk-WVBPATRA.js +0 -2
  114. package/dist-cli/chunks/chunk-ZF5FCFLD.js +0 -2
  115. package/dist-cli/chunks/chunk-ZKNI5MRD.js +0 -1
  116. package/dist-cli/chunks/control-7QGKUCAX.js +0 -2
  117. package/dist-cli/chunks/daemon-4BLYGM5N.js +0 -49
  118. package/dist-cli/chunks/demo-app-registry-HLI5UGGI.js +0 -2
  119. package/dist-cli/chunks/drivers-YIXRFFBQ.js +0 -2
  120. package/dist-cli/chunks/flow-L7X5FGIN.js +0 -2
  121. package/dist-cli/chunks/home-paths-4YJJYGR6.js +0 -2
  122. package/dist-cli/chunks/install-BATRTWRI.js +0 -65
  123. package/dist-cli/chunks/install-desktop-6X474IQ3.js +0 -23
  124. package/dist-cli/chunks/login-54YJ2KH6.js +0 -26
  125. package/dist-cli/chunks/logout-XECXLEXW.js +0 -2
  126. package/dist-cli/chunks/runtime-PJKHEB36.js +0 -25
  127. package/dist-cli/chunks/server-CIP3LH45.js +0 -29
  128. package/dist-cli/chunks/store-SPC247DB.js +0 -2
  129. package/dist-cli/chunks/upload-UPD2RSYF.js +0 -2
@@ -1,6 +1,6 @@
1
- /*! sootsim v0.0.4 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
- import{a as U}from"./chunk-VGXARPIH.js";import{a as Ne,b as _e}from"./chunk-AFQBSK2J.js";import{a as Y,b as E,c as C,d as z,e as ie,f as V,g as te,h as Ie,i as Fe,j as fe}from"./chunk-UQ3N6FZF.js";import{a as Te,e as ae}from"./chunk-I6XGFZPA.js";import{a as me,c as pe,d as xe}from"./chunk-4VXB2DBA.js";import{b as Ae,h as Pe}from"./chunk-47S5DXXX.js";import"./chunk-OAHMYSMD.js";import{a as Me}from"./chunk-5TTQKPGH.js";import"./chunk-WVBPATRA.js";import{a as we}from"./chunk-HGFIS26A.js";import{c as $e,e as Se,f as ke,h as ve}from"./chunk-C3QLIYCS.js";import"./chunk-W7CYWXRZ.js";import"./chunk-MZPAJ5PQ.js";import"./chunk-WRF43M33.js";import"./chunk-ZF5FCFLD.js";import"./chunk-SY74J6F4.js";import"./chunk-WWDJCKMI.js";import{existsSync as mt,mkdirSync as pt,readFileSync as ft,rmSync as Oe,writeFileSync as gt}from"fs";import{tmpdir as yt}from"os";import{dirname as bt,join as ht,resolve as wt}from"path";var oe=1,xt="SOOTSIM_INSPECT_NOTICE_PATH",$t=300*1e3,St=15e3;function Ee(){return wt(process.env[xt]||ht(yt(),"sootsim-inspect-notice-state.json"))}function kt(o,c){return Object.fromEntries(Object.entries(o).filter(([,i])=>typeof i?.signature=="string"&&Number.isFinite(i?.updatedAt)&&c-i.updatedAt<=$t))}function vt(o){let c=Ee();if(!mt(c))return{version:oe,entries:{}};try{let i=JSON.parse(ft(c,"utf8"));return i.version!==oe||!i.entries||typeof i.entries!="object"?(Oe(c,{force:!0}),{version:oe,entries:{}}):{version:oe,entries:kt(i.entries,o)}}catch{return Oe(c,{force:!0}),{version:oe,entries:{}}}}function Tt(o){let c=Ee();pt(bt(c),{recursive:!0}),gt(c,JSON.stringify(o,null,2)+`
3
- `)}function Mt(o,c){let i=c.trim()||"default";return`${o}:${i}`}function ge(o,c,i,d={}){let u=d.nowMs??Date.now(),a=d.cooldownMs??St,b=vt(u),k=Mt(o,c),$=b.entries[k];return $&&$.signature===i&&u-$.updatedAt<a?!1:(b.entries[k]={signature:i,updatedAt:u},Tt(b),!0)}async function Re(o,c={args:[]}){let i=await o.send({type:"evaluate",code:"(async () => await window.__sootsimTest.getNodeCount())()"}),d=typeof i=="number"?i:0;if(E(c.args)){C({nodes:d});return}console.log(` nodes: ${d}`)}function ye(o,c){let i=o.indexOf(c);return i>=0&&i+1<o.length?o[i+1]:null}async function Ce(o){let{bridge:c,args:i,positional:d}=o,u=i.includes("--verbose")||i.includes("-v"),a=E(i),b=u&&!a,k=i.includes("--watch")||i.includes("-w"),$=1e3,I=i.includes("--compact"),y=i.includes("--no-xy"),S=ye(i,"--testid-like"),A=ye(i,"--only"),v=ye(i,"--subtree"),j=d[1],l=j?/[*?]/.test(j):!1,R=!l&&!A?j:void 0,D=A??(l?j:void 0),q=async()=>{await ie(c,{verbose:b});let Z=`(async () => {
1
+ /*! sootsim v0.1.36 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
+ import{a as U}from"./chunk-N32NCVL2.js";import{a as Ne,b as _e}from"./chunk-YIO6S3R5.js";import{a as Y,b as E,c as C,d as z,e as ie,f as V,g as te,h as Ie,i as Fe,j as fe}from"./chunk-CYCXOAVZ.js";import{a as Te,e as ae}from"./chunk-HWCKZXNJ.js";import{a as me,c as pe,d as xe}from"./chunk-EBEHZJRG.js";import{b as Ae,h as Pe}from"./chunk-75LBYBKW.js";import"./chunk-GW7XY5KC.js";import{a as Me}from"./chunk-OXN2PEB7.js";import"./chunk-YR7BGGYE.js";import"./chunk-PJL25JQV.js";import"./chunk-G663654J.js";import"./chunk-A5BRCXYE.js";import{a as we}from"./chunk-SHO54NET.js";import{c as $e,e as Se,f as ve,h as ke}from"./chunk-SMVJOWSV.js";import"./chunk-6GGMKFWJ.js";import"./chunk-ZEW3RF5Q.js";import"./chunk-5QIUJNT3.js";import"./chunk-LHDWH7VS.js";import{existsSync as mt,mkdirSync as pt,readFileSync as ft,rmSync as Oe,writeFileSync as gt}from"fs";import{tmpdir as yt}from"os";import{dirname as ht,join as bt,resolve as wt}from"path";var oe=1,xt="SOOTSIM_INSPECT_NOTICE_PATH",$t=300*1e3,St=15e3;function Ee(){return wt(process.env[xt]||bt(yt(),"sootsim-inspect-notice-state.json"))}function vt(o,c){return Object.fromEntries(Object.entries(o).filter(([,i])=>typeof i?.signature=="string"&&Number.isFinite(i?.updatedAt)&&c-i.updatedAt<=$t))}function kt(o){let c=Ee();if(!mt(c))return{version:oe,entries:{}};try{let i=JSON.parse(ft(c,"utf8"));return i.version!==oe||!i.entries||typeof i.entries!="object"?(Oe(c,{force:!0}),{version:oe,entries:{}}):{version:oe,entries:vt(i.entries,o)}}catch{return Oe(c,{force:!0}),{version:oe,entries:{}}}}function Tt(o){let c=Ee();pt(ht(c),{recursive:!0}),gt(c,JSON.stringify(o,null,2)+`
3
+ `)}function Mt(o,c){let i=c.trim()||"default";return`${o}:${i}`}function ge(o,c,i,d={}){let u=d.nowMs??Date.now(),a=d.cooldownMs??St,h=kt(u),v=Mt(o,c),$=h.entries[v];return $&&$.signature===i&&u-$.updatedAt<a?!1:(h.entries[v]={signature:i,updatedAt:u},Tt(h),!0)}async function Re(o,c={args:[]}){let i=await o.send({type:"evaluate",code:"(async () => await window.__sootsimTest.getNodeCount())()"}),d=typeof i=="number"?i:0;if(E(c.args)){C({nodes:d});return}console.log(` nodes: ${d}`)}function ye(o,c){let i=o.indexOf(c);return i>=0&&i+1<o.length?o[i+1]:null}async function Ce(o){let{bridge:c,args:i,positional:d}=o,u=i.includes("--verbose")||i.includes("-v"),a=E(i),h=u&&!a,v=i.includes("--watch")||i.includes("-w"),$=1e3,I=i.includes("--compact"),y=i.includes("--no-xy"),S=ye(i,"--testid-like"),A=ye(i,"--only"),k=ye(i,"--subtree"),j=d[1],l=j?/[*?]/.test(j):!1,R=!l&&!A?j:void 0,D=A??(l?j:void 0),q=async()=>{await ie(c,{verbose:h});let Z=`(async () => {
4
4
  const t = window.__sootsimTest
5
5
  const mainShell = window.SootSim?.bridges?.mainShell
6
6
  const kb = window.__sootsimKeyboard
@@ -11,21 +11,21 @@ import{a as U}from"./chunk-VGXARPIH.js";import{a as Ne,b as _e}from"./chunk-AFQB
11
11
  shell = typeof mainShell?.getState === 'function' ? await mainShell.getState() : null
12
12
  } catch {}
13
13
 
14
- const tree = await t.dumpTree(12, ${JSON.stringify({describe:!0,verbose:u,filter:R||"",testIdLike:S||void 0,onlyGlob:D||void 0,subtreeRoot:v||void 0,compact:I,hideXy:y})})
14
+ const tree = await t.dumpTree(12, ${JSON.stringify({describe:!0,verbose:u,filter:R||"",testIdLike:S||void 0,onlyGlob:D||void 0,subtreeRoot:k||void 0,compact:I,hideXy:y})})
15
15
  const nodeCount = (await t.getNodeCount?.()) || 0
16
16
  const keyboard = kb && typeof kb.getLayout === 'function' ? kb.getLayout() : null
17
17
  return { tree, shell, nodeCount, keyboard }
18
- })()`,x=await c.send({type:"evaluate",code:Z}),J=x?.tree,H=x?.shell,K=x?.keyboard;if(a){C({shell:H,tree:J??"",keyboard:K});return}if(H&&typeof H=="object"){let e=[H.state?`state=${H.state}`:null,H.activeApp?`app=${H.activeApp}`:null,H.showSwitcher?"switcher":null,H.switcherPhase&&H.switcherPhase!=="idle"?`phase=${H.switcherPhase}`:null].filter(Boolean);e.length>0&&console.log(` shell: ${e.join(" ")}`)}if(typeof J=="string"&&J.startsWith("__SUBTREE_NOT_FOUND__:")){let e=J.slice(22);console.log(` subtree root not found: ${e}`),U("subtree-root-not-found",e);return}if(!J){let e=x?.nodeCount??0;console.log(" no matching nodes found"),!(R||S||D||v)&&e<10&&U("app-still-loading",e);return}if(console.log(J),!(R||S||D||v)&&!k&&J.split(`
18
+ })()`,x=await c.send({type:"evaluate",code:Z}),J=x?.tree,H=x?.shell,K=x?.keyboard;if(a){C({shell:H,tree:J??"",keyboard:K});return}if(H&&typeof H=="object"){let e=[H.state?`state=${H.state}`:null,H.activeApp?`app=${H.activeApp}`:null,H.showSwitcher?"switcher":null,H.switcherPhase&&H.switcherPhase!=="idle"?`phase=${H.switcherPhase}`:null].filter(Boolean);e.length>0&&console.log(` shell: ${e.join(" ")}`)}if(typeof J=="string"&&J.startsWith("__SUBTREE_NOT_FOUND__:")){let e=J.slice(22);console.log(` subtree root not found: ${e}`),U("subtree-root-not-found",e);return}if(!J){let e=x?.nodeCount??0;console.log(" no matching nodes found"),!(R||S||D||k)&&e<10&&U("app-still-loading",e);return}if(console.log(J),!(R||S||D||k)&&!v&&J.split(`
19
19
  `).length>=80&&U("describe-use-filters"),K&&K.visible){let e=K.spec,t=[e?.keyboardType?`type=${e.keyboardType}`:null,e?.returnKeyType&&e.returnKeyType!=="default"?`return=${e.returnKeyType}`:null,K.mode!=="letters"?`mode=${K.mode}`:null,K.shifted?"shift":null,K.capsLock?"caps":null,e?.autoCapitalize&&e.autoCapitalize!=="sentences"?`autoCap=${e.autoCapitalize}`:null,K.accessoryBarId?`accessory=${K.accessoryBarId}`:null].filter(Boolean);console.log(`
20
- keyboard: ${t.join(" ")||"visible"}`)}};if(k)for(console.log(` watching... (Ctrl+C to stop)
21
- `);;)console.clear(),await q(),await Y($);else await q()}var Nt=["SOOTSIM_AGENT","CLAUDECODE","CLAUDE_CODE_ENTRYPOINT","CLAUDE_CODE_SESSION_ID","CODEX_THREAD_ID","CURSOR_TRACE_ID","AIDER_MODEL"];function De(){if(process.env.SOOTSIM_AGENT==="0")return!1;for(let o of Nt){let c=process.env[o];if(c&&c.trim()&&c!=="0")return!0}return!1}async function Le(o){let{bridge:c,args:i,effectiveArgs:d,positional:u,inspectUsage:a}=o,b=x=>{let J=d.indexOf(x);return J>=0&&J+1<d.length?d[J+1]:null},k=x=>d.includes(x),$=b("--testid")||b("--test-id"),I=b("--role"),y=b("--type"),S=b("--text"),A=k("--pressable"),v=k("--visible"),j=!$&&!I&&!y&&!S&&!A&&!v?u[1]:null,l=S??j,R,D;$?(D="testid",R=`(async () => {
20
+ keyboard: ${t.join(" ")||"visible"}`)}};if(v)for(console.log(` watching... (Ctrl+C to stop)
21
+ `);;)console.clear(),await q(),await Y($);else await q()}var Nt=["SOOTSIM_AGENT","CLAUDECODE","CLAUDE_CODE_ENTRYPOINT","CLAUDE_CODE_SESSION_ID","CODEX_THREAD_ID","CURSOR_TRACE_ID","AIDER_MODEL"];function De(){if(process.env.SOOTSIM_AGENT==="0")return!1;for(let o of Nt){let c=process.env[o];if(c&&c.trim()&&c!=="0")return!0}return!1}async function Le(o){let{bridge:c,args:i,effectiveArgs:d,positional:u,inspectUsage:a}=o,h=x=>{let J=d.indexOf(x);return J>=0&&J+1<d.length?d[J+1]:null},v=x=>d.includes(x),$=h("--testid")||h("--test-id"),I=h("--role"),y=h("--type"),S=h("--text"),A=v("--pressable"),k=v("--visible"),j=!$&&!I&&!y&&!S&&!A&&!k?u[1]:null,l=S??j,R,D;$?(D="testid",R=`(async () => {
22
22
  const t = window.__sootsimTest
23
23
  return (await t.findByTestId(${JSON.stringify($)})) || (await t.findById(${JSON.stringify($)}))
24
24
  })()`):I?(D="role",R=`(async () => await window.__sootsimTest.queryAll({ hasRole: ${JSON.stringify(I)}, pruneHidden: true }))()`):y?(D="type",R=`(async () => await window.__sootsimTest.queryAll({ type: ${JSON.stringify(y)}, pruneHidden: true }))()`):A?(D="pressable",R=`(async () => {
25
25
  const t = window.__sootsimTest
26
26
  const all = await t.queryAll({ pruneHidden: true })
27
27
  return all.filter(n => n.pressable)
28
- })()`):v?(D="visible",R=`(async () => {
28
+ })()`):k?(D="visible",R=`(async () => {
29
29
  const all = await window.__sootsimTest.queryAll({ pruneHidden: true })
30
30
  return all.filter(n => n.layout && n.layout.width > 0 && n.layout.height > 0)
31
31
  })()`):l?(D="text",R=`(async () => await window.__sootsimTest.findByText(${JSON.stringify(l)}))()`):(console.error(a("find","<text> | --text <t> | --testid <id> | --role <r> | --type <t> | --pressable | --visible")),process.exit(1));let q=await c.send({type:"evaluate",code:R}),ne=E(i),Z=i.includes("--verbose")||i.includes("--dump");if(ne)C(q??null);else if(Array.isArray(q))if(q.length===0){console.log(` no ${D} nodes found`);let x=await c.send({type:"evaluate",code:"(async () => (await window.__sootsimTest?.getNodeCount?.()) || 0)()"});typeof x=="number"&&x<10&&U("app-still-loading",x)}else{console.log(` found ${q.length} node${q.length===1?"":"s"} (${D}):`);for(let x of q.slice(0,20)){let J=x.absolutePosition?`@(${Math.round(x.absolutePosition.x)},${Math.round(x.absolutePosition.y)})`:"",H=x.layout?`${Math.round(x.layout.width)}x${Math.round(x.layout.height)}`:"?x?",K=x.text?` "${x.text.slice(0,30)}"`:"",Q=x.testID?` #${x.testID}`:"",e=x.pressable?" (tap)":"",t=x.accessibilityRole?`[${x.accessibilityRole}]`:x.type;console.log(` ${t}${K}${Q} ${H} ${J}${e}`),Z&&console.log(Be(JSON.stringify(x,null,2)," "))}q.length>20&&console.log(` ... and ${q.length-20} more`)}else if(q==null)console.log(` not found: ${l||$||I||y||""||D}`),$&&U("wait-selector-for-missing-testid",$);else{let x=q;if(x.type&&x.absolutePosition){let J=`@(${Math.round(x.absolutePosition.x)},${Math.round(x.absolutePosition.y)})`,H=x.layout?`${Math.round(x.layout.width)}x${Math.round(x.layout.height)}`:"?x?",K=x.text?` "${x.text.slice(0,40)}"`:"",Q=x.testID?` #${x.testID}`:"",e=x.pressable?" (tap)":"",t=x.accessibilityRole?`[${x.accessibilityRole}]`:x.type;console.log(` ${t}${K}${Q} ${H} ${J}${e}`),Z&&console.log(Be(JSON.stringify(x,null,2)," "))}else console.log(JSON.stringify(q,null,2))}}function Be(o,c){return o.split(`
@@ -36,7 +36,7 @@ import{a as U}from"./chunk-VGXARPIH.js";import{a as Ne,b as _e}from"./chunk-AFQB
36
36
  return { error: 'keyboard bridge getLayout() not available' }
37
37
  }
38
38
  return kb.getLayout()
39
- })()`});if("error"in i&&(console.error(i.error),process.exit(1)),c.json){console.log(JSON.stringify(i,null,2));return}let{visible:d,spec:u,mode:a,shifted:b,capsLock:k,accessoryBarId:$}=i,I=[];I.push(`keyboard: ${d?"visible":"hidden"}`),u?(I.push(` type: ${u.keyboardType}`),I.push(` returnKey: ${u.returnKeyType}`),I.push(` autoCap: ${u.autoCapitalize}`),I.push(` autoCorrect: ${u.autoCorrect?"on":"off"}`),I.push(` appearance: ${u.keyboardAppearance}`),u.secureTextEntry&&I.push(" secureTextEntry: true"),u.enablesReturnKeyAutomatically&&I.push(` return: ${u.currentTextIsEmpty?"disabled (empty)":"enabled"}`)):I.push(" spec: <none> (shown via dev-tools with no TextInput)"),I.push(` mode: ${a}${b?" (shifted)":""}${k?" (caps)":""}`),$&&I.push(` accessoryBar: ${$}`),console.log(I.join(`
39
+ })()`});if("error"in i&&(console.error(i.error),process.exit(1)),c.json){console.log(JSON.stringify(i,null,2));return}let{visible:d,spec:u,mode:a,shifted:h,capsLock:v,accessoryBarId:$}=i,I=[];I.push(`keyboard: ${d?"visible":"hidden"}`),u?(I.push(` type: ${u.keyboardType}`),I.push(` returnKey: ${u.returnKeyType}`),I.push(` autoCap: ${u.autoCapitalize}`),I.push(` autoCorrect: ${u.autoCorrect?"on":"off"}`),I.push(` appearance: ${u.keyboardAppearance}`),u.secureTextEntry&&I.push(" secureTextEntry: true"),u.enablesReturnKeyAutomatically&&I.push(` return: ${u.currentTextIsEmpty?"disabled (empty)":"enabled"}`)):I.push(" spec: <none> (shown via dev-tools with no TextInput)"),I.push(` mode: ${a}${h?" (shifted)":""}${v?" (caps)":""}`),$&&I.push(` accessoryBar: ${$}`),console.log(I.join(`
40
40
  `))}async function Je(o){let c=await o.bridge.listBrowsers();if(E(o.args)){C(c.map(i=>({...i,active:i.id===o.browserId})));return}Pe(c,o.browserId)}function X(o){return o<1024?`${o}B`:o<1024*1024?`${(o/1024).toFixed(1)}KB`:`${(o/1024/1024).toFixed(1)}MB`}function le(o,c){return c<=0?"?":`${(o/c*100).toFixed(0)}%`}async function He(o,c={args:[]}){let d=await o.send({type:"evaluate",code:`(async () => {
41
41
  const host = window.__sootsimRenderHost
42
42
  const stats = host?.queryStats ? await host.queryStats() : null
@@ -73,9 +73,11 @@ import{a as U}from"./chunk-VGXARPIH.js";import{a as Ne,b as _e}from"./chunk-AFQB
73
73
  })()`})??null}async function qe(o,c={}){let i=await o.send({type:"evaluate",code:`(async () => {
74
74
  const test = window.__sootsimTest
75
75
  const kb = window.__sootsimKeyboard
76
+ // host-side __sootsimTest is a Proxy that forwards every call to the
77
+ // tenant worker \u2014 every method returns a Promise, so we must await.
76
78
  const navSnap =
77
79
  test && typeof test.getNavigationSnapshot === 'function'
78
- ? test.getNavigationSnapshot()
80
+ ? await test.getNavigationSnapshot()
79
81
  : null
80
82
  const keyboard =
81
83
  kb && typeof kb.getLayout === 'function'
@@ -94,7 +96,7 @@ import{a as U}from"./chunk-VGXARPIH.js";import{a as Ne,b as _e}from"./chunk-AFQB
94
96
  })()
95
97
  : null
96
98
  return { nav: navSnap, keyboard }
97
- })()`}),d=i?.nav??null,u=i?.keyboard??null,a=await V(o,500).catch(()=>null);if(c.json){console.log(JSON.stringify({shell:a??null,nav:d,keyboard:u},null,2));return}let b=[];if(a){let k=a.activeApp??a.state??"<none>",$=a.showSwitcher?" (app switcher open)":"",I=typeof a.launchProgress=="number"&&a.launchProgress<.98?` launching (${Math.round(a.launchProgress*100)}%)`:"";b.push(`shell: ${k}${$}${I}`)}else b.push("shell: <unavailable>");if(d){let k=d.transitionPhase!=="idle"?` (${d.transitionPhase}, ${d.activeTransitionCount} active)`:"";if(b.push(`nav: phase=${d.transitionPhase}${k}`),d.screens.length===0)b.push(" <no registered screens \u2014 app may not use react-native-screens>");else for(let $ of d.screens){let I=$.isActive?"\u25B6":" ",y=$.routeName?` ${$.routeName}`:"",S=$.headerHeight>0?` header=${$.headerHeight}`:"",A=$.largeTitleState&&$.largeTitleState!=="expanded"?` large-title=${$.largeTitleState}`:"";b.push(` ${I} #${$.id}${y}${S}${A}`)}}else b.push("nav: <runtime not available>");if(u&&u.visible){let k=u.spec?.keyboardType??"default",$=u.spec?.returnKeyType??"default";b.push(`keyboard: visible (${k}, return=${$}, mode=${u.mode??"?"})`)}else b.push("keyboard: hidden");console.log(b.join(`
99
+ })()`}),d=i?.nav??null,u=i?.keyboard??null,a=await V(o,500).catch(()=>null);if(c.json){console.log(JSON.stringify({shell:a??null,nav:d,keyboard:u},null,2));return}let h=[];if(a){let v=a.activeApp??a.state??"<none>",$=a.showSwitcher?" (app switcher open)":"",I=typeof a.launchProgress=="number"&&a.launchProgress<.98?` launching (${Math.round(a.launchProgress*100)}%)`:"";h.push(`shell: ${v}${$}${I}`)}else h.push("shell: <unavailable>");if(d){let v=d.transitionPhase!=="idle"?` (${d.transitionPhase}, ${d.activeTransitionCount} active)`:"";if(h.push(`nav: phase=${d.transitionPhase}${v}`),d.screens.length===0)h.push(" <no registered screens \u2014 app may not use react-native-screens>");else for(let $ of d.screens){let I=$.isActive?"\u25B6":" ",y=$.routeName?` ${$.routeName}`:"",S=$.headerHeight>0?` header=${$.headerHeight}`:"",A=$.largeTitleState&&$.largeTitleState!=="expanded"?` large-title=${$.largeTitleState}`:"";h.push(` ${I} #${$.id}${y}${S}${A}`)}}else h.push("nav: <runtime not available>");if(u&&u.visible){let v=u.spec?.keyboardType??"default",$=u.spec?.returnKeyType??"default";h.push(`keyboard: visible (${v}, return=${$}, mode=${u.mode??"?"})`)}else h.push("keyboard: hidden");console.log(h.join(`
98
100
  `))}async function ee({bridge:o,maxMs:c,pollMs:i=50,stablePolls:d=3,strict:u=!1}){let a=await o.send({type:"evaluate",code:`(async () => {
99
101
  const start = Date.now()
100
102
  const deadline = start + ${Math.max(0,Math.round(c))}
@@ -144,7 +146,7 @@ import{a as U}from"./chunk-VGXARPIH.js";import{a as Ne,b as _e}from"./chunk-AFQB
144
146
  await sleep(pollMs)
145
147
  }
146
148
  return { settled: false, elapsed: Date.now() - start }
147
- })()`}),{elapsed:b,settled:k}=a??{};return{elapsed:typeof b=="number"?b:c,settled:k===!0}}async function We(o){let{bridge:c,args:i,positional:d}=o,u=d[1]?Number(d[1])*1e3:3e3,a=i.includes("--strict"),{elapsed:b,settled:k}=await ee({bridge:c,maxMs:u,strict:a});console.log(k?` settled in ${b}ms`:` timed out after ${b}ms (may still be animating)`)}async function ze(o){let c=o.positional[1]?Number(o.positional[1]):.5;(!Number.isFinite(c)||c<0)&&(console.error(o.inspectUsage("sleep","[seconds]")),process.exit(1)),await Y(c*1e3),console.log(` slept ${c}s`)}async function Ke(o){let{bridge:c,args:i,positional:d}=o,u=d[1]?Number(d[1]):5,a=await c.send({type:"evaluate",code:`(async () => await window.__sootsimTest.dumpTree(${u}))()`});if(E(i)){C({depth:u,tree:a??null});return}console.log(typeof a=="string"?a:JSON.stringify(a,null,2))}async function Ue(o,c={args:[]}){let i=await o.send({type:"evaluate",code:"window.location.href"}),d=typeof i=="string"?i:"";if(E(c.args)){C({url:d});return}console.log(d)}async function Ye(o){let{wsPort:c,commandTimeoutMs:i,browserId:d,positional:u}=o,a=u[1]?Number(u[1]):30,b=Math.max(1e3,(Number.isFinite(a)?a:30)*1e3),k=Math.max(1,Math.ceil(b/500));console.log(" waiting for browser reconnect...");let $=await Ie(c,i,d,{attempts:k});$||(console.error(" timed out waiting for browser reconnect"),process.exit(1)),$.bridge.close(),ae({source:"inspect wait",step:{wait:b},summary:`wait ${Math.round(b/1e3)}s`}),console.log(` ready: ${$.count} nodes`)}async function Ge(o){let{bridge:c,args:i}=o,d=i.includes("--strict"),u=i.indexOf("--max-ms"),a=u>=0&&i[u+1]?Math.max(100,Number(i[u+1])):3e3,{elapsed:b,settled:k}=await ee({bridge:c,maxMs:a,strict:d});k?console.log(` idle in ${b}ms`):(console.error(` \u26A0 wait idle timed out after ${b}ms (may still be animating)`),process.exit(1))}async function Xe(o){let{bridge:c,args:i}=o,d=2e4,u=i.indexOf("--max-ms");u>=0&&i[u+1]&&(d=Math.max(100,Number(i[u+1])));let a=Date.now(),b=a+d,k=`(async () => {
149
+ })()`}),{elapsed:h,settled:v}=a??{};return{elapsed:typeof h=="number"?h:c,settled:v===!0}}async function We(o){let{bridge:c,args:i,positional:d}=o,u=d[1]?Number(d[1])*1e3:3e3,a=i.includes("--strict"),{elapsed:h,settled:v}=await ee({bridge:c,maxMs:u,strict:a});console.log(v?` settled in ${h}ms`:` timed out after ${h}ms (may still be animating)`)}async function ze(o){let c=o.positional[1]?Number(o.positional[1]):.5;(!Number.isFinite(c)||c<0)&&(console.error(o.inspectUsage("sleep","[seconds]")),process.exit(1)),await Y(c*1e3),console.log(` slept ${c}s`)}async function Ke(o){let{bridge:c,args:i,positional:d}=o,u=d[1]?Number(d[1]):5,a=await c.send({type:"evaluate",code:`(async () => await window.__sootsimTest.dumpTree(${u}))()`});if(E(i)){C({depth:u,tree:a??null});return}console.log(typeof a=="string"?a:JSON.stringify(a,null,2))}async function Ue(o,c={args:[]}){let i=await o.send({type:"evaluate",code:"window.location.href"}),d=typeof i=="string"?i:"";if(E(c.args)){C({url:d});return}console.log(d)}async function Ye(o){let{wsPort:c,commandTimeoutMs:i,browserId:d,positional:u}=o,a=u[1]?Number(u[1]):30,h=Math.max(1e3,(Number.isFinite(a)?a:30)*1e3),v=Math.max(1,Math.ceil(h/500));console.log(" waiting for browser reconnect...");let $=await Ie(c,i,d,{attempts:v});$||(console.error(" timed out waiting for browser reconnect"),process.exit(1)),$.bridge.close(),ae({source:"inspect wait",step:{wait:h},summary:`wait ${Math.round(h/1e3)}s`}),console.log(` ready: ${$.count} nodes`)}async function Ge(o){let{bridge:c,args:i}=o,d=i.includes("--strict"),u=i.indexOf("--max-ms"),a=u>=0&&i[u+1]?Math.max(100,Number(i[u+1])):3e3,{elapsed:h,settled:v}=await ee({bridge:c,maxMs:a,strict:d});v?console.log(` idle in ${h}ms`):(console.error(` \u26A0 wait idle timed out after ${h}ms (may still be animating)`),process.exit(1))}async function Xe(o){let{bridge:c,args:i}=o,d=2e4,u=i.indexOf("--max-ms");u>=0&&i[u+1]&&(d=Math.max(100,Number(i[u+1])));let a=Date.now(),h=a+d,v=`(async () => {
148
150
  const t = window.__sootsimTest
149
151
  let nodes = 0
150
152
  try { nodes = (await t?.getNodeCount?.()) || 0 } catch {}
@@ -153,9 +155,9 @@ import{a as U}from"./chunk-VGXARPIH.js";import{a as Ne,b as _e}from"./chunk-AFQB
153
155
  at: (window).__sootsimExternalAppReadyAt || 0,
154
156
  nodes,
155
157
  }
156
- })()`,$={flag:void 0,at:0,nodes:0};for(;Date.now()<b;){try{$=await c.send({type:"evaluate",code:k})??$}catch{}if($.flag===!0){console.log(` ready in ${Date.now()-a}ms: ${$.nodes} nodes (flag)`);return}await new Promise(I=>setTimeout(I,150))}console.error(` \u26A0 wait ready timed out after ${Date.now()-a}ms \u2014 guest app did not emit sootsim:externalAppReady (nodes: ${$.nodes})`),process.exit(1)}async function Ve(o){let{bridge:c,args:i,positional:d,inspectUsage:u}=o,a=d[1];a||(console.error(u("wait selector","<testid> [--max-ms 5000]")),process.exit(1));let b=i.indexOf("--max-ms"),k=b>=0&&i[b+1]?Math.max(100,Number(i[b+1])):5e3,$=await c.send({type:"evaluate",code:`(async () => {
158
+ })()`,$={flag:void 0,at:0,nodes:0};for(;Date.now()<h;){try{$=await c.send({type:"evaluate",code:v})??$}catch{}if($.flag===!0){console.log(` ready in ${Date.now()-a}ms: ${$.nodes} nodes (flag)`);return}await new Promise(I=>setTimeout(I,150))}console.error(` \u26A0 wait ready timed out after ${Date.now()-a}ms \u2014 guest app did not emit sootsim:externalAppReady (nodes: ${$.nodes})`),process.exit(1)}async function Ve(o){let{bridge:c,args:i,positional:d,inspectUsage:u}=o,a=d[1];a||(console.error(u("wait selector","<testid> [--max-ms 5000]")),process.exit(1));let h=i.indexOf("--max-ms"),v=h>=0&&i[h+1]?Math.max(100,Number(i[h+1])):5e3,$=await c.send({type:"evaluate",code:`(async () => {
157
159
  const start = Date.now()
158
- const deadline = start + ${k}
160
+ const deadline = start + ${v}
159
161
  const t = window.__sootsimTest
160
162
  const find = async () => {
161
163
  try {
@@ -172,8 +174,8 @@ import{a as U}from"./chunk-VGXARPIH.js";import{a as Ne,b as _e}from"./chunk-AFQB
172
174
  await new Promise((r) => setTimeout(r, 80))
173
175
  }
174
176
  return { found: false, elapsed: Date.now() - start }
175
- })()`}),{found:I,node:y,elapsed:S}=$??{};if(I&&y){let A=y.absolutePosition?`@(${Math.round(y.absolutePosition.x)},${Math.round(y.absolutePosition.y)})`:"",v=y.layout?`${Math.round(y.layout.width)}x${Math.round(y.layout.height)}`:"?x?";console.log(` found #${a} in ${S}ms ${v} ${A}`)}else console.error(` \u26A0 wait selector #${a} timed out after ${S??k}ms`),process.exit(1)}function nt(o){return o==null?"\u2014":o<1024?`${o}B`:o<1024*1024?`${(o/1024).toFixed(1)}K`:`${(o/1024/1024).toFixed(1)}M`}function rt(o){return o==null?" \u2026":o<1e3?`${o}ms`.padStart(5):`${(o/1e3).toFixed(2)}s`.padStart(5)}function It(o){return o.error?"err":o.status==null?" \u2026 ":String(o.status)}function Ze(o){let c=new Date(o.startTs).toLocaleTimeString(),i=It(o).padEnd(3),d=o.method.padEnd(5),u=nt(o.size).padStart(6),a=rt(o.durationMs);console.log(` [${c}] ${i} ${d} ${u} ${a} ${o.displayUrl}`),o.error&&console.log(` error: ${o.error}`)}function Ft(o){let c=[["id",o.id],["source",o.source],["kind",o.kind],["method",o.method],["status",o.error?`error: ${o.error}`:`${o.status??"\u2014"} ${o.statusText??""}`.trim()],["url",o.url],["started",new Date(o.startTs).toLocaleTimeString()],["duration",rt(o.durationMs).trim()],["size",nt(o.size)],["content-type",o.type??"\u2014"]];for(let[i,d]of c)console.log(` ${i.padEnd(13)} ${d}`)}var At={error:"\x1B[31m",warn:"\x1B[33m",info:"\x1B[36m",debug:"\x1B[35m",log:"\x1B[37m"},Qe="\x1B[0m",Pt="\x1B[2m";function et(o,c){let i=new Date(o.ts).toLocaleTimeString(),d=o.level.toUpperCase().padEnd(5),u=o.args.join(" ");if(c){let a=At[o.level];console.log(` ${Pt}[${i}]${Qe} ${a}${d}${Qe} ${u}`)}else console.log(` [${i}] ${d} ${u}`);if(o.stack&&o.level==="error"){let a=o.stack.split(`
176
- `).slice(0,5);for(let b of a)console.log(` ${b.trim()}`)}}var G="__sootsimCliPerf",Ot=120;async function tt(o,c){let i=o.find((A,v)=>o[v-1]==="--id"),d=o.find((A,v)=>o[v-1]==="--text");if(i||d){let A=await c.send({type:"evaluate",code:Ne({id:i,text:d})});if(!A)throw new Error(i?`no node with id "${i}"`:`no node matching text "${d}"`);let{x:v,y:j,w:l,h:R}=A;return{x:v,y:j,w:l,h:R}}let u=o.find((A,v)=>o[v-1]==="--area");if(u){let A=u.split(",").map(D=>Number(D.trim()));if(A.length!==4||A.some(D=>!Number.isFinite(D)))throw new Error(`--area expects x,y,w,h (got "${u}")`);let[v,j,l,R]=A;return{x:v,y:j,w:l,h:R}}let a=A=>{let v=o.find((l,R)=>o[R-1]===A);if(v==null)return null;let j=Number(v);return Number.isFinite(j)?j:null},b=a("--x"),k=a("--y"),$=a("--w"),I=a("--h");if(b!=null||k!=null||$!=null||I!=null)return{x:b??0,y:k??0,w:$??1,h:I??1};let S=o.filter((A,v)=>v>0&&!A.startsWith("-")&&o[v-1]!=="--output"&&o[v-1]!=="--area"&&o[v-1]!=="--id"&&o[v-1]!=="--text"&&o[v-1]!=="--x"&&o[v-1]!=="--y"&&o[v-1]!=="--w"&&o[v-1]!=="--h").map(Number).filter(A=>Number.isFinite(A));if(S.length>=2){let[A,v,j=1,l=1]=S;return{x:A,y:v,w:j,h:l}}return null}function be(o){let c={"<8":0,"8-12":0,"12-16":0,"16-20":0,"20-33":0,">33":0};for(let i of o)i<8?c["<8"]++:i<12?c["8-12"]++:i<16?c["12-16"]++:i<20?c["16-20"]++:i<33?c["20-33"]++:c[">33"]++;console.log(" histogram:");for(let[i,d]of Object.entries(c)){let u="\u2588".repeat(Math.ceil(d/o.length*40));console.log(` ${i.padEnd(6)} ${u} ${d}`)}}async function de(o,c,i){let d=Date.now()+c,u=await V(o,c);for(;;){if(i(u))return{settled:!0,state:u};if(Date.now()>=d)return{settled:!1,state:u};await Y(16),u=await V(o)}}async function he(o){return o.send({type:"evaluate",code:`(async () => {
177
+ })()`}),{found:I,node:y,elapsed:S}=$??{};if(I&&y){let A=y.absolutePosition?`@(${Math.round(y.absolutePosition.x)},${Math.round(y.absolutePosition.y)})`:"",k=y.layout?`${Math.round(y.layout.width)}x${Math.round(y.layout.height)}`:"?x?";console.log(` found #${a} in ${S}ms ${k} ${A}`)}else console.error(` \u26A0 wait selector #${a} timed out after ${S??v}ms`),process.exit(1)}function nt(o){return o==null?"\u2014":o<1024?`${o}B`:o<1024*1024?`${(o/1024).toFixed(1)}K`:`${(o/1024/1024).toFixed(1)}M`}function rt(o){return o==null?" \u2026":o<1e3?`${o}ms`.padStart(5):`${(o/1e3).toFixed(2)}s`.padStart(5)}function It(o){return o.error?"err":o.status==null?" \u2026 ":String(o.status)}function Ze(o){let c=new Date(o.startTs).toLocaleTimeString(),i=It(o).padEnd(3),d=o.method.padEnd(5),u=nt(o.size).padStart(6),a=rt(o.durationMs);console.log(` [${c}] ${i} ${d} ${u} ${a} ${o.displayUrl}`),o.error&&console.log(` error: ${o.error}`)}function Ft(o){let c=[["id",o.id],["source",o.source],["kind",o.kind],["method",o.method],["status",o.error?`error: ${o.error}`:`${o.status??"\u2014"} ${o.statusText??""}`.trim()],["url",o.url],["started",new Date(o.startTs).toLocaleTimeString()],["duration",rt(o.durationMs).trim()],["size",nt(o.size)],["content-type",o.type??"\u2014"]];for(let[i,d]of c)console.log(` ${i.padEnd(13)} ${d}`)}var At={error:"\x1B[31m",warn:"\x1B[33m",info:"\x1B[36m",debug:"\x1B[35m",log:"\x1B[37m"},Qe="\x1B[0m",Pt="\x1B[2m";function et(o,c){let i=new Date(o.ts).toLocaleTimeString(),d=o.level.toUpperCase().padEnd(5),u=o.args.join(" ");if(c){let a=At[o.level];console.log(` ${Pt}[${i}]${Qe} ${a}${d}${Qe} ${u}`)}else console.log(` [${i}] ${d} ${u}`);if(o.stack&&o.level==="error"){let a=o.stack.split(`
178
+ `).slice(0,5);for(let h of a)console.log(` ${h.trim()}`)}}var G="__sootsimCliPerf",Ot=120;async function tt(o,c){let i=o.find((A,k)=>o[k-1]==="--id"),d=o.find((A,k)=>o[k-1]==="--text");if(i||d){let A=await c.send({type:"evaluate",code:Ne({id:i,text:d})});if(!A)throw new Error(i?`no node with id "${i}"`:`no node matching text "${d}"`);let{x:k,y:j,w:l,h:R}=A;return{x:k,y:j,w:l,h:R}}let u=o.find((A,k)=>o[k-1]==="--area");if(u){let A=u.split(",").map(D=>Number(D.trim()));if(A.length!==4||A.some(D=>!Number.isFinite(D)))throw new Error(`--area expects x,y,w,h (got "${u}")`);let[k,j,l,R]=A;return{x:k,y:j,w:l,h:R}}let a=A=>{let k=o.find((l,R)=>o[R-1]===A);if(k==null)return null;let j=Number(k);return Number.isFinite(j)?j:null},h=a("--x"),v=a("--y"),$=a("--w"),I=a("--h");if(h!=null||v!=null||$!=null||I!=null)return{x:h??0,y:v??0,w:$??1,h:I??1};let S=o.filter((A,k)=>k>0&&!A.startsWith("-")&&o[k-1]!=="--output"&&o[k-1]!=="--area"&&o[k-1]!=="--id"&&o[k-1]!=="--text"&&o[k-1]!=="--x"&&o[k-1]!=="--y"&&o[k-1]!=="--w"&&o[k-1]!=="--h").map(Number).filter(A=>Number.isFinite(A));if(S.length>=2){let[A,k,j=1,l=1]=S;return{x:A,y:k,w:j,h:l}}return null}function he(o){let c={"<8":0,"8-12":0,"12-16":0,"16-20":0,"20-33":0,">33":0};for(let i of o)i<8?c["<8"]++:i<12?c["8-12"]++:i<16?c["12-16"]++:i<20?c["16-20"]++:i<33?c["20-33"]++:c[">33"]++;console.log(" histogram:");for(let[i,d]of Object.entries(c)){let u="\u2588".repeat(Math.ceil(d/o.length*40));console.log(` ${i.padEnd(6)} ${u} ${d}`)}}async function de(o,c,i){let d=Date.now()+c,u=await V(o,c);for(;;){if(i(u))return{settled:!0,state:u};if(Date.now()>=d)return{settled:!1,state:u};await Y(16),u=await V(o)}}async function be(o){return o.send({type:"evaluate",code:`(async () => {
177
179
  const kb = window.__sootsimKeyboard
178
180
  const test = window.__sootsimTest
179
181
  if (!kb) return { error: 'keyboard bridge not available' }
@@ -205,30 +207,32 @@ import{a as U}from"./chunk-VGXARPIH.js";import{a as Ne,b as _e}from"./chunk-AFQB
205
207
  frame: runtimeSnapshot?.keyboard?.frame ?? null,
206
208
  focusedRect: runtimeSnapshot?.focused?.rect ?? null,
207
209
  }
208
- })()`})}async function Et(o,c=600){let i=Date.now()+c;for(;Date.now()<=i;){let d=await he(o);if(d.visible)return d;await Y(30)}return he(o)}async function ue(o,c){let i=await he(o);if(i.visible)return i;console.error(` ${c} requires the iOS keyboard to be visible. focus an input first with sootsim do tap-id/tap-text or sootsim do type-into.`),process.exit(1)}async function ot(o,c,i){return c==="appearance"?o.send({type:"evaluate",code:`(async () => {
210
+ })()`})}async function Et(o,c=600){let i=Date.now()+c;for(;Date.now()<=i;){let d=await be(o);if(d.visible)return d;await Y(30)}return be(o)}async function ue(o,c){let i=await be(o);if(i.visible)return i;console.error(` ${c} requires the iOS keyboard to be visible. focus an input first with sootsim do tap-id/tap-text or sootsim do type-into.`),process.exit(1)}async function ot(o,c,i){return c==="appearance"?o.send({type:"evaluate",code:`(async () => {
209
211
  const requested = ${JSON.stringify(i??"toggle")}
210
212
  const rootBg = (document.documentElement?.style?.background || '').toLowerCase()
211
213
  const inferredCurrent = rootBg.includes('33') ? 'dark' : 'light'
212
- let applied = requested
214
+ let next = requested
213
215
  if (requested === 'toggle') {
214
- applied = inferredCurrent === 'dark' ? 'light' : 'dark'
215
- } else if (requested === 'auto') {
216
- applied = window.matchMedia?.('(prefers-color-scheme: dark)')?.matches ? 'dark' : 'light'
216
+ next = inferredCurrent === 'dark' ? 'light' : 'dark'
217
217
  }
218
- window.postMessage({ type: 'soot-action', action: 'set-appearance', value: applied }, '*')
219
- return { ok: true, requested, applied }
218
+ // engine accepts 'auto' since the schema picker landed; pass through.
219
+ window.postMessage({ type: 'soot-action', action: 'set-appearance', value: next }, '*')
220
+ const applied = next === 'auto'
221
+ ? (window.matchMedia?.('(prefers-color-scheme: dark)')?.matches ? 'dark' : 'light')
222
+ : next
223
+ return { ok: true, requested, value: next, applied }
220
224
  })()`}):o.send({type:"evaluate",code:`(async () => {
221
225
  window.dispatchEvent(new CustomEvent(${JSON.stringify(c==="lock"?"sootsim:toggleLock":"sootsim:shake")}))
222
226
  return { ok: true, action: ${JSON.stringify(c)} }
223
- })()`})}function Rt(o){let c={Enter:"return",NumpadEnter:"return",Backspace:"delete",Delete:"delete",Space:"space",ShiftLeft:"shift",ShiftRight:"shift"};if(c[o])return c[o];let i=o.match(/^Digit([0-9])$/);if(i)return i[1];let d=o.match(/^Key([A-Z])$/);return d?d[1].toLowerCase():null}function Ct(o){if(typeof o!="string")return null;let c=o.replace(/\s+/g," ").trim();return c?c.slice(0,80):null}function at(...o){for(let c of o){if(typeof c!="string")continue;let i=c.trim();if(i)return i}return null}async function L(o,c,i){ae({source:o,step:c,summary:i})}function Dt(o,c,i){if(!i||i.hit===!1)return null;let d=at(i.responderTestID,i.testID);if(d)return{step:{tapOn:{id:d}},summary:`tap #${d}`};let u=Ct(i.text);return u?{step:{tapOn:u},summary:`tap "${u}"`}:{step:{tapAtCoords:{x:o,y:c}},summary:`tap @${Math.round(o)},${Math.round(c)}`}}function st(o,c,i){let d=at(c?.testID,c?.id);return d?{step:{tapOn:{id:d}},summary:`tap #${d}`}:i==="id"?{step:{tapOn:{id:o}},summary:`tap #${o}`}:{step:{tapOn:o},summary:`tap "${o}"`}}async function rs(o,c){let i=o[0]==="get"||o[0]==="do"||o[0]==="debug"||o[0]==="wait"?o[0]:null,d=i?o.slice(1):o,u=$e(d,{port:c.port,commandTimeoutMs:c.timeoutMs,stripBooleanFlags:["--verbose","-v","--help","-h","--clear-state","--json","--all","--watch","-w","--strict","--no-wait","--dump","--failed","--tail","-f","--internal"],stripValueFlags:["--output","--nth","--index","--testid","--test-id","--text","--max-ms","--filter","--limit","--level"]}),a=u.positional,b=a[0],k=i==="get"||i==="do"||i==="debug"||i==="wait"?i:"inspect",$=typeof d[0]=="string"&&xe.has(d[0]),I=$?d[0]:null,y=e=>$&&e===d[0]?`sootsim ${e}`:`sootsim ${k} ${e}`,S=(e,t)=>` usage: ${y(e)}${t?` ${t}`:""}`;if(!b||o.includes("--help")||o.includes("-h")){let e={bridgePort:7668,defaultShellUrl:we};if(k==="do"||k==="get"||k==="debug"||k==="wait"){let r=me(k,e);r&&(console.log(`${r}
227
+ })()`})}function Rt(o){let c={Enter:"return",NumpadEnter:"return",Backspace:"delete",Delete:"delete",Space:"space",ShiftLeft:"shift",ShiftRight:"shift"};if(c[o])return c[o];let i=o.match(/^Digit([0-9])$/);if(i)return i[1];let d=o.match(/^Key([A-Z])$/);return d?d[1].toLowerCase():null}function Ct(o){if(typeof o!="string")return null;let c=o.replace(/\s+/g," ").trim();return c?c.slice(0,80):null}function at(...o){for(let c of o){if(typeof c!="string")continue;let i=c.trim();if(i)return i}return null}async function L(o,c,i){ae({source:o,step:c,summary:i})}function Dt(o,c,i){if(!i||i.hit===!1)return null;let d=at(i.responderTestID,i.testID);if(d)return{step:{tapOn:{id:d}},summary:`tap #${d}`};let u=Ct(i.text);return u?{step:{tapOn:u},summary:`tap "${u}"`}:{step:{tapAtCoords:{x:o,y:c}},summary:`tap @${Math.round(o)},${Math.round(c)}`}}function st(o,c,i){let d=at(c?.testID,c?.id);return d?{step:{tapOn:{id:d}},summary:`tap #${d}`}:i==="id"?{step:{tapOn:{id:o}},summary:`tap #${o}`}:{step:{tapOn:o},summary:`tap "${o}"`}}async function rs(o,c){let i=o[0]==="get"||o[0]==="do"||o[0]==="debug"||o[0]==="wait"?o[0]:null,d=i?o.slice(1):o,u=$e(d,{port:c.port,commandTimeoutMs:c.timeoutMs,stripBooleanFlags:["--verbose","-v","--help","-h","--clear-state","--json","--all","--watch","-w","--strict","--no-wait","--dump","--failed","--tail","-f","--internal"],stripValueFlags:["--output","--nth","--index","--testid","--test-id","--text","--max-ms","--filter","--limit","--level"]}),a=u.positional,h=a[0],v=i==="get"||i==="do"||i==="debug"||i==="wait"?i:"inspect",$=typeof d[0]=="string"&&xe.has(d[0]),I=$?d[0]:null,y=e=>$&&e===d[0]?`sootsim ${e}`:`sootsim ${v} ${e}`,S=(e,t)=>` usage: ${y(e)}${t?` ${t}`:""}`;if(!h||o.includes("--help")||o.includes("-h")){let e={bridgePort:7668,defaultShellUrl:we};if(v==="do"||v==="get"||v==="debug"||v==="wait"){let r=me(v,e);r&&(console.log(`${r}
224
228
  `),process.exit(0))}if(I==="shell"){let r=pe("shell",e);r&&(console.log(`${r}
225
229
  `),process.exit(0))}let t=pe("inspect",e),s=["do","get","debug","wait"].map(r=>me(r,e)).filter(r=>r!=null).join(`
226
230
 
227
231
  `);console.log(`${t??""}
228
232
 
229
233
  ${s}
230
- `),process.exit(0)}let A=u.wsPort,v=u.browserId,j=u.commandTimeoutMs;if(b==="list"&&d.some(e=>e==="--drivers"||e==="-D")){let{buildDriverListRows:e}=await import("./drivers-YIXRFFBQ.js"),t=e();console.log(` available drivers (${t.length}):
231
- `);let s=Math.max(...t.map(n=>n.id.length),6),r=Math.max(...t.map(n=>n.kind.length),4);for(let n of t){let m=n.available?"\u2713":"\u2717",p=n.id.padEnd(s),h=n.kind.padEnd(r);console.log(` ${m} ${p} ${h} ${n.description}`),n.available&&n.detail?console.log(` ${n.detail}`):!n.available&&n.reason&&console.log(` unavailable: ${n.reason}`)}return}let l=Se(u),R=v||"default",D=new Set(["errors","warnings","requests","js","eval","reload","globals","perf","list","wait","sleep"]);function q(e){let t=e.displayUrl||e.url;return e.status!=null?`${e.method} ${t} -> ${e.status}${e.statusText?` ${e.statusText}`:""}`:e.error?`${e.method} ${t} -> ${e.error}`:`${e.method} ${t}`}async function ne(e){let t=De()?1200:350;try{let{settled:s,elapsed:r}=await ee({bridge:e,maxMs:t,pollMs:32,stablePolls:2});s||process.stderr.write(` \u26A0 auto-wait timed out after ${r??t}ms \u2014 next command may see mid-animation state. use \`sootsim do settle\` for a longer wait.
234
+ `),process.exit(0)}let A=u.wsPort,k=u.browserId,j=u.commandTimeoutMs;if(h==="list"&&d.some(e=>e==="--drivers"||e==="-D")){let{buildDriverListRows:e}=await import("./drivers-S4NGK4DB.js"),t=e();console.log(` available drivers (${t.length}):
235
+ `);let s=Math.max(...t.map(n=>n.id.length),6),r=Math.max(...t.map(n=>n.kind.length),4);for(let n of t){let m=n.available?"\u2713":"\u2717",p=n.id.padEnd(s),b=n.kind.padEnd(r);console.log(` ${m} ${p} ${b} ${n.description}`),n.available&&n.detail?console.log(` ${n.detail}`):!n.available&&n.reason&&console.log(` unavailable: ${n.reason}`)}return}let l=Se(u),R=k||"default",D=new Set(["errors","warnings","requests","js","eval","reload","globals","perf","list","wait","sleep"]);function q(e){let t=e.displayUrl||e.url;return e.status!=null?`${e.method} ${t} -> ${e.status}${e.statusText?` ${e.statusText}`:""}`:e.error?`${e.method} ${t} -> ${e.error}`:`${e.method} ${t}`}async function ne(e){let t=De()?1200:350;try{let{settled:s,elapsed:r}=await ee({bridge:e,maxMs:t,pollMs:32,stablePolls:2});s||process.stderr.write(` \u26A0 auto-wait timed out after ${r??t}ms \u2014 next command may see mid-animation state. use \`sootsim do settle\` for a longer wait.
232
236
  `)}catch{}}async function Z(){try{return await l.send({type:"evaluate",code:`(() => ({
233
237
  console: window.__sootsimConsole?.count?.() || null,
234
238
  requests: window.__sootsimTest?.getRequestCounts?.() || null,
@@ -238,7 +242,7 @@ ${s}
238
242
  `);for(let n of r){let m=new Date(n.timestamp).toLocaleTimeString();console.log(` [${m}] ${q(n)}`),n.responseBody?console.log(` ${n.responseBody}`):n.error&&console.log(` ${n.error}`)}}}async function J(e={}){let t=e.counts!==void 0?e.counts:await l.send({type:"evaluate",code:"window.__sootsimConsole?.count?.() || { errors: 0, warnings: 0, total: 0 }"});if(!t||typeof t!="object")return;let s=t,r=Math.max(0,Number(s.errors)||0),n=Math.max(0,Number(s.warnings)||0);if(r===0&&n===0||!e.includeTail&&!ge("console",R,`${r}:${n}`))return;let m=[];if(r>0&&m.push(`${r} console error${r===1?"":"s"}`),n>0&&m.push(`${n} console warning${n===1?"":"s"}`),console.log(`
239
243
  console: ${m.join(", ")}`),console.log(` inspect: ${y("errors")} 5`),n>0&&console.log(` inspect: ${y("warnings")} 5`),!e.includeTail||r===0)return;let p=await l.send({type:"evaluate",code:"window.__sootsimConsole?.getErrors?.(5) || []"});if(!(!Array.isArray(p)||p.length===0)){console.log(`
240
244
  recent console errors:
241
- `);for(let h of p){let f=new Date(h.timestamp).toLocaleTimeString(),w=Array.isArray(h.args)?h.args.map(O=>typeof O=="object"?JSON.stringify(O):String(O)).join(" "):String(h);console.log(` [${f}] ${w}`)}}}let H=new Set(["tap","double-tap","tap-text","tap-id","type","type-into","key","key-sequence","keycode","drag","swipe","long-press","touch","gesture","pinch","scroll","shell"]),K=new Set(["a11y","capture","count","double-tap","drag","find","gesture","layout","long-press","node","pinch","sample-color","scroll","screenshot","swipe","tap","tap-id","tap-text","touch","tree","type-into"]),Q=(o.includes("--verbose")||o.includes("-v"))&&!o.includes("--json");k==="do"&&b==="shell"&&(console.error(" `sootsim do shell` was removed. use `sootsim shell ...` instead."),process.exit(1)),H.has(b)&&await ke(l),K.has(b)&&await ie(l,{verbose:Q});try{switch(b){case"list":{await Je({bridge:l,browserId:v,args:d});break}case"tree":{await Ke({bridge:l,args:d,positional:a});break}case"a11y":{let e=a[1]?Number(a[1]):5,t=await l.send({type:"evaluate",code:`(async () => {
245
+ `);for(let b of p){let f=new Date(b.timestamp).toLocaleTimeString(),w=Array.isArray(b.args)?b.args.map(O=>typeof O=="object"?JSON.stringify(O):String(O)).join(" "):String(b);console.log(` [${f}] ${w}`)}}}let H=new Set(["tap","double-tap","tap-text","tap-id","type","type-into","key","key-sequence","keycode","drag","swipe","long-press","touch","gesture","pinch","scroll","shell"]),K=new Set(["a11y","capture","count","double-tap","drag","find","gesture","layout","long-press","node","pinch","sample-color","scroll","screenshot","swipe","tap","tap-id","tap-text","touch","tree","type-into"]),Q=(o.includes("--verbose")||o.includes("-v"))&&!o.includes("--json");v==="do"&&h==="shell"&&(console.error(" `sootsim do shell` was removed. use `sootsim shell ...` instead."),process.exit(1)),H.has(h)&&await ve(l),K.has(h)&&await ie(l,{verbose:Q});try{switch(h){case"list":{await Je({bridge:l,browserId:k,args:d});break}case"tree":{await Ke({bridge:l,args:d,positional:a});break}case"a11y":{let e=a[1]?Number(a[1]):5,t=await l.send({type:"evaluate",code:`(async () => {
242
246
  const t = window.__sootsimTest
243
247
  if (!t) return []
244
248
  const all = await t.queryAll({ pruneHidden: true })
@@ -267,7 +271,7 @@ ${s}
267
271
  size: n.layout ? { w: Math.round(n.layout.width), h: Math.round(n.layout.height) } : null,
268
272
  }))
269
273
  })()`});if(!Array.isArray(t)||t.length===0){console.log(" no accessible nodes found");break}if(o.includes("--json"))console.log(JSON.stringify(t,null,2));else{console.log(` accessibility tree (${t.length} nodes):
270
- `);for(let s of t){let r=[];if(r.push(`[${s.role}]`),s.label){let n=s.label.length>50?s.label.slice(0,47)+"...":s.label;r.push(`"${n}"`)}if(s.hint&&r.push(`(hint: "${s.hint}")`),s.testID&&r.push(`#${s.testID}`),s.state){let n=[];s.state.disabled&&n.push("disabled"),s.state.selected&&n.push("selected"),s.state.checked===!0&&n.push("checked"),s.state.checked==="mixed"&&n.push("mixed"),s.state.busy&&n.push("busy"),s.state.expanded===!0&&n.push("expanded"),s.state.expanded===!1&&n.push("collapsed"),n.length&&r.push(`{${n.join(", ")}}`)}s.position&&r.push(`@(${s.position.x},${s.position.y})`),s.size&&r.push(`${s.size.w}x${s.size.h}`),console.log(" "+r.join(" "))}}break}case"find":{await Le({bridge:l,args:o,effectiveArgs:d,positional:a,inspectUsage:S});break}case"count":{await Re(l,{args:d});break}case"keyboard":{await je(l,{json:o.includes("--json")});break}case"screens":{await qe(l,{json:o.includes("--json")});break}case"memory":{await He(l,{args:d});break}case"wait":{await Ye({wsPort:A,commandTimeoutMs:j,browserId:v,positional:a});break}case"sleep":{await ze({positional:a,inspectUsage:S});break}case"settle":{await We({bridge:l,args:o,positional:a});break}case"ready":{await Xe({bridge:l,args:o});break}case"idle":{await Ge({bridge:l,args:o,positional:a});break}case"selector":{await Ve({bridge:l,args:o,positional:a,inspectUsage:S});break}case"layout":{let e=a[1];e||(console.error(S("layout","<id>")),process.exit(1));let t=await l.send({type:"evaluate",code:`(async () => await window.__sootsimTest.getLayout(${JSON.stringify(e)}))()`});console.log(JSON.stringify(t,null,2));break}case"capture":case"screenshot":{let t=o.find((h,f)=>o[f-1]==="--output")||"/tmp/sootsim-inspect.png",s=await tt(o,l),r={type:"screenshot"};s&&(r.crop=s);let m=(await l.send(r)).replace(/^data:image\/png;base64,/,"");s&&console.log(` area: x=${s.x} y=${s.y} w=${s.w} h=${s.h}`),(await import("fs")).writeFileSync(t,Buffer.from(m,"base64")),console.log(` saved: ${t}`);break}case"sample-color":{let e=await tt(o,l);e||(console.error(S("sample-color","<x> <y> [w] [h] | --id <testID> | --text <text>")),console.error(" samples an averaged color from the canvas. coords are logical sootsim units."),process.exit(1));let t=await l.send({type:"evaluate",code:_e(e)});if(o.includes("--json"))console.log(JSON.stringify(t,null,2));else{let{r:s,g:r,b:n,a:m,hex:p,samples:h}=t,f=e.w===1&&e.h===1?`@(${e.x},${e.y})`:`@(${e.x},${e.y}) ${e.w}x${e.h}`;console.log(` ${p} rgba(${s}, ${r}, ${n}, ${m}) ${f} ${h} samples`)}break}case"node":{let e=a[1];e||(console.error(S("node","<matcher>")),console.error(" resolves testID, id, then text \u2014 dumps full node info as JSON"),process.exit(1));let t=await l.send({type:"evaluate",code:`(async () => {
274
+ `);for(let s of t){let r=[];if(r.push(`[${s.role}]`),s.label){let n=s.label.length>50?s.label.slice(0,47)+"...":s.label;r.push(`"${n}"`)}if(s.hint&&r.push(`(hint: "${s.hint}")`),s.testID&&r.push(`#${s.testID}`),s.state){let n=[];s.state.disabled&&n.push("disabled"),s.state.selected&&n.push("selected"),s.state.checked===!0&&n.push("checked"),s.state.checked==="mixed"&&n.push("mixed"),s.state.busy&&n.push("busy"),s.state.expanded===!0&&n.push("expanded"),s.state.expanded===!1&&n.push("collapsed"),n.length&&r.push(`{${n.join(", ")}}`)}s.position&&r.push(`@(${s.position.x},${s.position.y})`),s.size&&r.push(`${s.size.w}x${s.size.h}`),console.log(" "+r.join(" "))}}break}case"find":{await Le({bridge:l,args:o,effectiveArgs:d,positional:a,inspectUsage:S});break}case"count":{await Re(l,{args:d});break}case"keyboard":{await je(l,{json:o.includes("--json")});break}case"screens":{await qe(l,{json:o.includes("--json")});break}case"memory":{await He(l,{args:d});break}case"wait":{await Ye({wsPort:A,commandTimeoutMs:j,browserId:k,positional:a});break}case"sleep":{await ze({positional:a,inspectUsage:S});break}case"settle":{await We({bridge:l,args:o,positional:a});break}case"ready":{await Xe({bridge:l,args:o});break}case"idle":{await Ge({bridge:l,args:o,positional:a});break}case"selector":{await Ve({bridge:l,args:o,positional:a,inspectUsage:S});break}case"layout":{let e=a[1];e||(console.error(S("layout","<id>")),process.exit(1));let t=await l.send({type:"evaluate",code:`(async () => await window.__sootsimTest.getLayout(${JSON.stringify(e)}))()`});console.log(JSON.stringify(t,null,2));break}case"capture":case"screenshot":{let t=o.find((b,f)=>o[f-1]==="--output")||"/tmp/sootsim-inspect.png",s=await tt(o,l),r={type:"screenshot"};s&&(r.crop=s);let m=(await l.send(r)).replace(/^data:image\/png;base64,/,"");s&&console.log(` area: x=${s.x} y=${s.y} w=${s.w} h=${s.h}`),(await import("fs")).writeFileSync(t,Buffer.from(m,"base64")),console.log(` saved: ${t}`);break}case"sample-color":{let e=await tt(o,l);e||(console.error(S("sample-color","<x> <y> [w] [h] | --id <testID> | --text <text>")),console.error(" samples an averaged color from the canvas. coords are logical sootsim units."),process.exit(1));let t=await l.send({type:"evaluate",code:_e(e)});if(o.includes("--json"))console.log(JSON.stringify(t,null,2));else{let{r:s,g:r,b:n,a:m,hex:p,samples:b}=t,f=e.w===1&&e.h===1?`@(${e.x},${e.y})`:`@(${e.x},${e.y}) ${e.w}x${e.h}`;console.log(` ${p} rgba(${s}, ${r}, ${n}, ${m}) ${f} ${b} samples`)}break}case"node":{let e=a[1];e||(console.error(S("node","<matcher>")),console.error(" resolves testID, id, then text \u2014 dumps full node info as JSON"),process.exit(1));let t=await l.send({type:"evaluate",code:`(async () => {
271
275
  const t = window.__sootsimTest
272
276
  const q = ${JSON.stringify(e)}
273
277
  let node = null
@@ -323,17 +327,17 @@ ${s}
323
327
  transform,
324
328
  parentChain,
325
329
  }
326
- })()`});console.log(JSON.stringify(t,null,2));break}case"tap":{let e=Number(a[1]),t=Number(a[2]),s=se(o);if(s){let m=await ce(l,s);m||(console.error(` not found: ${s.value}`),s.mode==="testid"&&U("wait-selector-for-missing-testid",s.value),process.exit(1)),e=m.x,t=m.y}(!Number.isFinite(e)||!Number.isFinite(t))&&(console.error(S("tap","<x> <y> | --testid <id> | --text <t>")),process.exit(1));let r=await l.send({type:"tap",x:e,y:t}),n=Dt(e,t,r);n&&await L("inspect tap",n.step,n.summary),console.log(JSON.stringify(r,null,2));break}case"drag":case"swipe":{let e=Number(a[1]),t=Number(a[2]),s=Number(a[3]),r=Number(a[4]),n=b==="swipe"?10:12,m=b==="swipe"?8:16,p=a[5]?Number(a[5]):n,h=a[6]?Number(a[6]):m;(!Number.isFinite(e)||!Number.isFinite(t)||!Number.isFinite(s)||!Number.isFinite(r)||!Number.isFinite(p)||!Number.isFinite(h))&&(console.error(S(b,"<x1> <y1> <x2> <y2> [steps] [stepMs]")),process.exit(1));let f=await l.send({type:"evaluate",code:`(async () => {
330
+ })()`});console.log(JSON.stringify(t,null,2));break}case"tap":{let e=Number(a[1]),t=Number(a[2]),s=se(o);if(s){let m=await ce(l,s);m||(console.error(` not found: ${s.value}`),s.mode==="testid"&&U("wait-selector-for-missing-testid",s.value),process.exit(1)),e=m.x,t=m.y}(!Number.isFinite(e)||!Number.isFinite(t))&&(console.error(S("tap","<x> <y> | --testid <id> | --text <t>")),process.exit(1));let r=await l.send({type:"tap",x:e,y:t}),n=Dt(e,t,r);n&&await L("inspect tap",n.step,n.summary),console.log(JSON.stringify(r,null,2));break}case"drag":case"swipe":{let e=Number(a[1]),t=Number(a[2]),s=Number(a[3]),r=Number(a[4]),n=h==="swipe"?10:12,m=h==="swipe"?8:16,p=a[5]?Number(a[5]):n,b=a[6]?Number(a[6]):m;(!Number.isFinite(e)||!Number.isFinite(t)||!Number.isFinite(s)||!Number.isFinite(r)||!Number.isFinite(p)||!Number.isFinite(b))&&(console.error(S(h,"<x1> <y1> <x2> <y2> [steps] [stepMs]")),process.exit(1));let f=await l.send({type:"evaluate",code:`(async () => {
327
331
  const interact = window.__sootsimInteract
328
332
  if (!interact?.drag) return { ok: false, reason: 'no interact.drag' }
329
- const value = await interact.drag(${e}, ${t}, ${s}, ${r}, ${Math.max(1,Math.round(p))}, ${Math.max(0,Math.round(h))})
333
+ const value = await interact.drag(${e}, ${t}, ${s}, ${r}, ${Math.max(1,Math.round(p))}, ${Math.max(0,Math.round(b))})
330
334
  return { ok: !!value, value }
331
- })()`});if(f?.ok){let w=Math.max(1,Math.round(Math.max(1,p)*Math.max(0,h)));await L(`inspect ${b}`,{swipe:{start:`${e}, ${t}`,end:`${s}, ${r}`,duration:w}},`${b} ${e},${t} -> ${s},${r}`)}console.log(JSON.stringify(f,null,2));break}case"pinch":{let e=Number(a[1]),t=Number(a[2]),s=Number(a[3]),r=Number(a[4]),n=Number(a[5]),m=Number(a[6]),p=Number(a[7]),h=Number(a[8]),f=a[9]?Number(a[9]):12,w=a[10]?Number(a[10]):16;(!Number.isFinite(e)||!Number.isFinite(t)||!Number.isFinite(s)||!Number.isFinite(r)||!Number.isFinite(n)||!Number.isFinite(m)||!Number.isFinite(p)||!Number.isFinite(h)||!Number.isFinite(f)||!Number.isFinite(w))&&(console.error(S("pinch","<x1> <y1> <x2> <y2> <x1'> <y1'> <x2'> <y2'> [steps] [stepMs]")),process.exit(1));let O=await l.send({type:"evaluate",code:`(async () => {
335
+ })()`});if(f?.ok){let w=Math.max(1,Math.round(Math.max(1,p)*Math.max(0,b)));await L(`inspect ${h}`,{swipe:{start:`${e}, ${t}`,end:`${s}, ${r}`,duration:w}},`${h} ${e},${t} -> ${s},${r}`)}console.log(JSON.stringify(f,null,2));break}case"pinch":{let e=Number(a[1]),t=Number(a[2]),s=Number(a[3]),r=Number(a[4]),n=Number(a[5]),m=Number(a[6]),p=Number(a[7]),b=Number(a[8]),f=a[9]?Number(a[9]):12,w=a[10]?Number(a[10]):16;(!Number.isFinite(e)||!Number.isFinite(t)||!Number.isFinite(s)||!Number.isFinite(r)||!Number.isFinite(n)||!Number.isFinite(m)||!Number.isFinite(p)||!Number.isFinite(b)||!Number.isFinite(f)||!Number.isFinite(w))&&(console.error(S("pinch","<x1> <y1> <x2> <y2> <x1'> <y1'> <x2'> <y2'> [steps] [stepMs]")),process.exit(1));let O=await l.send({type:"evaluate",code:`(async () => {
332
336
  const interact = window.__sootsimInteract
333
337
  if (!interact?.pinch) return { ok: false, reason: 'no interact.pinch' }
334
- const value = await interact.pinch(${e}, ${t}, ${s}, ${r}, ${n}, ${m}, ${p}, ${h}, ${Math.max(1,Math.round(f))}, ${Math.max(0,Math.round(w))})
338
+ const value = await interact.pinch(${e}, ${t}, ${s}, ${r}, ${n}, ${m}, ${p}, ${b}, ${Math.max(1,Math.round(f))}, ${Math.max(0,Math.round(w))})
335
339
  return { ok: !!value, value }
336
- })()`});O?.ok&&await L("inspect pinch",{pinch:{from:[e,t,s,r],to:[n,m,p,h],steps:Math.max(1,Math.round(f)),stepMs:Math.max(0,Math.round(w))}},`pinch (${e},${t}) (${s},${r}) -> (${n},${m}) (${p},${h})`),console.log(JSON.stringify(O,null,2));break}case"tap-text":{let e=a[1];e||(console.error(S("tap-text","<text>")),process.exit(1));let t=_=>{let P=o.indexOf(_);return P>=0&&P+1<o.length?o[P+1]:null},s=_=>o.includes(_),r=t("--nth")??t("--index"),n=r!==null?Number(r):null;n!==null&&!Number.isFinite(n)&&(console.error(` --nth/--index requires an integer, got: ${r}`),process.exit(1));let m=t("--within"),p=t("--role"),h=s("--exact"),f=s("--first"),w=t("--min-y"),O=t("--max-y"),B=t("--min-x"),N=t("--max-x");for(let[_,P]of[["--min-y",w],["--max-y",O],["--min-x",B],["--max-x",N]])P!==null&&!Number.isFinite(Number(P))&&(console.error(` ${_} requires a number, got: ${P}`),process.exit(1));let M=o.indexOf("--near"),F=null;if(M>=0){let _=Number(o[M+1]),P=Number(o[M+2]);(!Number.isFinite(_)||!Number.isFinite(P))&&(console.error(" --near requires two numbers: --near <x> <y>"),process.exit(1)),F={x:_,y:P}}let W=JSON.stringify({query:e,exact:h,role:p,within:m,minX:B!==null?Number(B):null,maxX:N!==null?Number(N):null,minY:w!==null?Number(w):null,maxY:O!==null?Number(O):null,near:F,nth:n,first:f}),g=await l.send({type:"evaluate",code:`(async () => {
340
+ })()`});O?.ok&&await L("inspect pinch",{pinch:{from:[e,t,s,r],to:[n,m,p,b],steps:Math.max(1,Math.round(f)),stepMs:Math.max(0,Math.round(w))}},`pinch (${e},${t}) (${s},${r}) -> (${n},${m}) (${p},${b})`),console.log(JSON.stringify(O,null,2));break}case"tap-text":{let e=a[1];e||(console.error(S("tap-text","<text>")),process.exit(1));let t=_=>{let P=o.indexOf(_);return P>=0&&P+1<o.length?o[P+1]:null},s=_=>o.includes(_),r=t("--nth")??t("--index"),n=r!==null?Number(r):null;n!==null&&!Number.isFinite(n)&&(console.error(` --nth/--index requires an integer, got: ${r}`),process.exit(1));let m=t("--within"),p=t("--role"),b=s("--exact"),f=s("--first"),w=t("--min-y"),O=t("--max-y"),B=t("--min-x"),N=t("--max-x");for(let[_,P]of[["--min-y",w],["--max-y",O],["--min-x",B],["--max-x",N]])P!==null&&!Number.isFinite(Number(P))&&(console.error(` ${_} requires a number, got: ${P}`),process.exit(1));let M=o.indexOf("--near"),F=null;if(M>=0){let _=Number(o[M+1]),P=Number(o[M+2]);(!Number.isFinite(_)||!Number.isFinite(P))&&(console.error(" --near requires two numbers: --near <x> <y>"),process.exit(1)),F={x:_,y:P}}let W=JSON.stringify({query:e,exact:b,role:p,within:m,minX:B!==null?Number(B):null,maxX:N!==null?Number(N):null,minY:w!==null?Number(w):null,maxY:O!==null?Number(O):null,near:F,nth:n,first:f}),g=await l.send({type:"evaluate",code:`(async () => {
337
341
  const t = window.__sootsimTest
338
342
  if (!t) return { error: 'bridge-not-ready' }
339
343
  const F = ${W}
@@ -522,13 +526,13 @@ ${s}
522
526
  if (!interact?.longPress) return { ok: false, reason: 'no interact.longPress' }
523
527
  const value = await interact.longPress(${e}, ${t}, ${Math.max(0,Math.round(r))})
524
528
  return { ok: !!value, value }
525
- })()`});n?.ok&&await L("inspect long-press",{tapAtCoords:{x:e,y:t}},`long-press @${e},${t}`),console.log(JSON.stringify(n,null,2));break}case"touch":{let e=a[1],t=Number(a[2]),s=Number(a[3]),r=a[4]?Number(a[4]):999,n=e==="down"?"touchDown":e==="move"?"touchMove":e==="up"?"touchUp":e==="cancel"?"touchCancel":null;n||(console.error(S("touch","<down|move|up|cancel> <x> <y> [pointerId]")),process.exit(1)),e!=="cancel"&&(!Number.isFinite(t)||!Number.isFinite(s))&&(console.error(S("touch","<down|move|up|cancel> <x> <y> [pointerId]")),process.exit(1));let m=e==="down"?"tap":e==="move"?"move":null,p=m&&Number.isFinite(t)&&Number.isFinite(s)?`window.dispatchEvent(new CustomEvent('sootsim:agentAction', { detail: { type: '${m}', x: ${t}, y: ${s} } }));`:"",h=await l.send({type:"evaluate",code:`(async () => {
529
+ })()`});n?.ok&&await L("inspect long-press",{tapAtCoords:{x:e,y:t}},`long-press @${e},${t}`),console.log(JSON.stringify(n,null,2));break}case"touch":{let e=a[1],t=Number(a[2]),s=Number(a[3]),r=a[4]?Number(a[4]):999,n=e==="down"?"touchDown":e==="move"?"touchMove":e==="up"?"touchUp":e==="cancel"?"touchCancel":null;n||(console.error(S("touch","<down|move|up|cancel> <x> <y> [pointerId]")),process.exit(1)),e!=="cancel"&&(!Number.isFinite(t)||!Number.isFinite(s))&&(console.error(S("touch","<down|move|up|cancel> <x> <y> [pointerId]")),process.exit(1));let m=e==="down"?"tap":e==="move"?"move":null,p=m&&Number.isFinite(t)&&Number.isFinite(s)?`window.dispatchEvent(new CustomEvent('sootsim:agentAction', { detail: { type: '${m}', x: ${t}, y: ${s} } }));`:"",b=await l.send({type:"evaluate",code:`(async () => {
526
530
  ${p}
527
531
  const interact = window.__sootsimInteract
528
532
  if (!interact?.${n}) return { ok: false, reason: 'no interact.${n}' }
529
533
  const value = ${e==="cancel"?`await interact.${n}(${Math.max(1,Math.round(r))})`:`await interact.${n}(${t}, ${s}, ${Math.max(1,Math.round(r))})`}
530
534
  return { ok: !!value, value }
531
- })()`});h?.ok&&e!=="cancel"&&await L("inspect touch",{tapAtCoords:{x:t,y:s}},`touch ${e} @${t},${s}`),console.log(JSON.stringify(h,null,2));break}case"gesture":{let e=a[1],t=a[2]?Number(a[2]):220;(!e||!Number.isFinite(t))&&(console.error(S("gesture","<preset> [durationMs]")),process.exit(1));let s=await l.send({type:"evaluate",code:`(async () => {
535
+ })()`});b?.ok&&e!=="cancel"&&await L("inspect touch",{tapAtCoords:{x:t,y:s}},`touch ${e} @${t},${s}`),console.log(JSON.stringify(b,null,2));break}case"gesture":{let e=a[1],t=a[2]?Number(a[2]):220;(!e||!Number.isFinite(t))&&(console.error(S("gesture","<preset> [durationMs]")),process.exit(1));let s=await l.send({type:"evaluate",code:`(async () => {
532
536
  const spec = globalThis.__sootsimDeviceSpec || {}
533
537
  return {
534
538
  width: spec.width || window.innerWidth || 393,
@@ -536,7 +540,7 @@ ${s}
536
540
  statusBarHeight: spec.statusBarHeight || 0,
537
541
  homeIndicatorHeight: spec.homeIndicatorHeight || 0,
538
542
  }
539
- })()`}),r=Number(s?.width)||393,n=Number(s?.height)||852,m=Number(s?.statusBarHeight)||0,p=Number(s?.homeIndicatorHeight)||0,h=Math.round(r/2),f=Math.round(n/2),w=Math.max(24,m+18),O=Math.max(24,p+18),B=18,N=Math.min(220,Math.round(n*.24)),M=Math.min(180,Math.round(r*.32)),F=h,W=f,g=h,T=f;switch(e){case"scroll-up":W=f+Math.round(N/2),T=f-Math.round(N/2);break;case"scroll-down":W=f-Math.round(N/2),T=f+Math.round(N/2);break;case"scroll-left":F=h+Math.round(M/2),g=h-Math.round(M/2);break;case"scroll-right":F=h-Math.round(M/2),g=h+Math.round(M/2);break;case"swipe-from-left-edge":F=B,W=f,g=Math.min(r-B,B+M);break;case"swipe-from-right-edge":F=r-B,W=f,g=Math.max(B,r-B-M);break;case"swipe-from-top-edge":F=h,W=w,T=Math.min(n-O,w+N);break;case"swipe-from-bottom-edge":F=h,W=n-O,T=Math.max(w,n-O-N);break;default:console.error(` unknown gesture preset: ${e}`),process.exit(1)}let _=Math.max(8,Math.round(t/16)),P=Math.max(1,Math.round(t/_)),re=await l.send({type:"evaluate",code:`(async () => {
543
+ })()`}),r=Number(s?.width)||393,n=Number(s?.height)||852,m=Number(s?.statusBarHeight)||0,p=Number(s?.homeIndicatorHeight)||0,b=Math.round(r/2),f=Math.round(n/2),w=Math.max(24,m+18),O=Math.max(24,p+18),B=18,N=Math.min(220,Math.round(n*.24)),M=Math.min(180,Math.round(r*.32)),F=b,W=f,g=b,T=f;switch(e){case"scroll-up":W=f+Math.round(N/2),T=f-Math.round(N/2);break;case"scroll-down":W=f-Math.round(N/2),T=f+Math.round(N/2);break;case"scroll-left":F=b+Math.round(M/2),g=b-Math.round(M/2);break;case"scroll-right":F=b-Math.round(M/2),g=b+Math.round(M/2);break;case"swipe-from-left-edge":F=B,W=f,g=Math.min(r-B,B+M);break;case"swipe-from-right-edge":F=r-B,W=f,g=Math.max(B,r-B-M);break;case"swipe-from-top-edge":F=b,W=w,T=Math.min(n-O,w+N);break;case"swipe-from-bottom-edge":F=b,W=n-O,T=Math.max(w,n-O-N);break;default:console.error(` unknown gesture preset: ${e}`),process.exit(1)}let _=Math.max(8,Math.round(t/16)),P=Math.max(1,Math.round(t/_)),re=await l.send({type:"evaluate",code:`(async () => {
540
544
  const interact = window.__sootsimInteract
541
545
  if (!interact?.drag) return { ok: false, reason: 'no interact.drag' }
542
546
  const value = await interact.drag(${F}, ${W}, ${g}, ${T}, ${_}, ${P})
@@ -577,7 +581,7 @@ ${s}
577
581
  ${y("state")} scroll feed
578
582
  ${y("state")} scroll-hit 360 420
579
583
  ${y("state")} hit 200 720
580
- `);break}let t;switch(e){case"shell":t=await V(l,500);break;case"worker":t=await ve(l,"__sootsimRenderHost.queryStats");break;case"ownership":t=await l.send({type:"evaluate",code:`(() => {
584
+ `);break}let t;switch(e){case"shell":t=await V(l,500);break;case"worker":t=await ke(l,"__sootsimRenderHost.queryStats");break;case"ownership":t=await l.send({type:"evaluate",code:`(() => {
581
585
  const h = window.__sootsimRenderHost
582
586
  if (!h || typeof h.getOwnershipSnapshot !== 'function') {
583
587
  return { error: 'getOwnershipSnapshot not available' }
@@ -632,7 +636,7 @@ ${s}
632
636
  ${y("shell")} open-card clock 800
633
637
  ${y("shell")} appearance dark
634
638
  ${y("shell")} lock
635
- `);break}let t=e==="launch"||e==="open-card"||e==="home"||e==="switcher",s=e==="launch"||e==="open-card"?a[3]:a[2],r=s?Number(s):350;t&&(!Number.isFinite(r)||r<0)&&(console.error(S("shell",e==="launch"||e==="open-card"?"<launch|open-card> <appId> [settleMs]":"<home|switcher> [settleMs]")),process.exit(1));let n=!1,m=!1,p=null,h=o.includes("--clear-state");if(e==="launch"){let f=a[2];f||(console.error(S("shell","launch <appId> [settleMs] [--clear-state]")),process.exit(1)),h&&await l.send({type:"evaluate",code:Te}),n=!!await te(l,"launchApp",r,f),{settled:m,state:p}=await de(l,Math.round(r),w=>!!w&&w.state==="app"&&w.activeApp===f&&w.showSwitcher===!1&&w.switcherPhase==="idle"&&typeof w.launchProgress=="number"&&w.launchProgress>=.98),n&&await L("inspect shell launch",h?{launchApp:{clearState:!0}}:{launchApp:{}},h?"launch app (clear state)":"launch app")}else if(e==="home")n=!!await te(l,"goHome",r),{settled:m,state:p}=await de(l,Math.round(r),f=>!!f&&f.state==="home"&&f.activeApp==null&&f.showSwitcher===!1&&f.switcherPhase==="idle"&&typeof f.launchProgress=="number"&&f.launchProgress>=.98);else if(e==="switcher")n=!!await te(l,"openSwitcher",r),{settled:m,state:p}=await de(l,Math.round(r),f=>!!f&&f.state==="app"&&f.showSwitcher===!0&&f.switcherPhase==="idle"&&typeof f.zoomLevel=="number"&&Math.abs(f.zoomLevel)<=.02&&typeof f.horizontalZoom=="number"&&Math.abs(f.horizontalZoom)<=.02),m&&(await Y(Ot),p=await V(l));else if(e==="open-card"){let f=a[2];f||(console.error(S("shell","open-card <appId> [settleMs]")),process.exit(1)),n=!!await te(l,"openSwitcherCard",r,f),{settled:m,state:p}=await de(l,Math.round(r),w=>!!w&&w.state==="app"&&w.activeApp===f&&w.showSwitcher===!1&&w.switcherPhase==="idle"&&typeof w.zoomLevel=="number"&&w.zoomLevel>=.98&&typeof w.horizontalZoom=="number"&&w.horizontalZoom>=.98),n&&await L("inspect shell open-card",{openSwitcherCard:{appId:f}},`open switcher card ${f}`)}else if(e==="appearance"){let f=a[2];(!f||!["light","dark","auto","toggle"].includes(f))&&(console.error(S("shell","appearance <light|dark|auto|toggle>")),process.exit(1));let w=await ot(l,"appearance",f);n=!!w?.ok,p={appearance:w}}else if(e==="lock"||e==="shake"){let f=await ot(l,e);n=!!f?.ok,p={[e]:f}}else console.error(` unknown shell subcommand: ${e}`),process.exit(1);console.log(JSON.stringify({ok:n,settled:m,state:p},null,2));break}case"url":{await Ue(l,{args:d});break}case"reload":{let s=!1,r=!1;try{await l.send({type:"evaluate",code:"window.__sootsimConsole?.clear()"});let p=await l.send({type:"evaluate",code:`;(() => {
639
+ `);break}let t=e==="launch"||e==="open-card"||e==="home"||e==="switcher",s=e==="launch"||e==="open-card"?a[3]:a[2],r=s?Number(s):350;t&&(!Number.isFinite(r)||r<0)&&(console.error(S("shell",e==="launch"||e==="open-card"?"<launch|open-card> <appId> [settleMs]":"<home|switcher> [settleMs]")),process.exit(1));let n=!1,m=!1,p=null,b=o.includes("--clear-state");if(e==="launch"){let f=a[2];f||(console.error(S("shell","launch <appId> [settleMs] [--clear-state]")),process.exit(1)),b&&await l.send({type:"evaluate",code:Te}),n=!!await te(l,"launchApp",r,f),{settled:m,state:p}=await de(l,Math.round(r),w=>!!w&&w.state==="app"&&w.activeApp===f&&w.showSwitcher===!1&&w.switcherPhase==="idle"&&typeof w.launchProgress=="number"&&w.launchProgress>=.98),n&&await L("inspect shell launch",b?{launchApp:{clearState:!0}}:{launchApp:{}},b?"launch app (clear state)":"launch app")}else if(e==="home")n=!!await te(l,"goHome",r),{settled:m,state:p}=await de(l,Math.round(r),f=>!!f&&f.state==="home"&&f.activeApp==null&&f.showSwitcher===!1&&f.switcherPhase==="idle"&&typeof f.launchProgress=="number"&&f.launchProgress>=.98);else if(e==="switcher")n=!!await te(l,"openSwitcher",r),{settled:m,state:p}=await de(l,Math.round(r),f=>!!f&&f.state==="app"&&f.showSwitcher===!0&&f.switcherPhase==="idle"&&typeof f.zoomLevel=="number"&&Math.abs(f.zoomLevel)<=.02&&typeof f.horizontalZoom=="number"&&Math.abs(f.horizontalZoom)<=.02),m&&(await Y(Ot),p=await V(l));else if(e==="open-card"){let f=a[2];f||(console.error(S("shell","open-card <appId> [settleMs]")),process.exit(1)),n=!!await te(l,"openSwitcherCard",r,f),{settled:m,state:p}=await de(l,Math.round(r),w=>!!w&&w.state==="app"&&w.activeApp===f&&w.showSwitcher===!1&&w.switcherPhase==="idle"&&typeof w.zoomLevel=="number"&&w.zoomLevel>=.98&&typeof w.horizontalZoom=="number"&&w.horizontalZoom>=.98),n&&await L("inspect shell open-card",{openSwitcherCard:{appId:f}},`open switcher card ${f}`)}else if(e==="appearance"){let f=a[2];(!f||!["light","dark","auto","toggle"].includes(f))&&(console.error(S("shell","appearance <light|dark|auto|toggle>")),process.exit(1));let w=await ot(l,"appearance",f);n=!!w?.ok,p={appearance:w}}else if(e==="lock"||e==="shake"){let f=await ot(l,e);n=!!f?.ok,p={[e]:f}}else console.error(` unknown shell subcommand: ${e}`),process.exit(1);console.log(JSON.stringify({ok:n,settled:m,state:p},null,2));break}case"url":{await Ue(l,{args:d});break}case"reload":{let s=!1,r=!1;try{await l.send({type:"evaluate",code:"window.__sootsimConsole?.clear()"});let p=await l.send({type:"evaluate",code:`;(() => {
636
640
  const reloadExternalApp = window.SootSim?.bridges?.hotRemount?.reloadExternalApp
637
641
  if (typeof reloadExternalApp === 'function') {
638
642
  reloadExternalApp()
@@ -640,9 +644,9 @@ ${s}
640
644
  }
641
645
  window.location.reload()
642
646
  return { kind: 'page' }
643
- })()`});r=!!p&&p.kind==="external-app",s=!0}catch{}console.log(" reloading...");let n=l,m=null;if(r)m=await fe(l,{timeoutMs:1e4,errorGraceMs:3e3});else{s&&await Y(300);let p=await Fe(A,j,v,{timeoutMs:1e4});p?(n=p,m=await fe(p,{timeoutMs:1e4,errorGraceMs:3e3})):(console.log(" \u26A0 reload: bridge never reconnected within 10000ms"),n=null)}if(m)if(m.ready){let p=m.source==="nodes-fallback"?" (no ready signal, node-count fallback)":"";console.log(` ready in ${m.elapsedMs}ms: ${m.nodes} nodes${p}`)}else m.source==="error-bail"?console.log(` \u26A0 reload bailed after ${m.elapsedMs}ms: ${m.errors} console error(s), ready signal never fired`):console.log(` \u26A0 reload timed out after ${m.elapsedMs}ms (${m.nodes} nodes, ${m.errors} errors)`);if(n)try{let p=await n.send({type:"evaluate",code:"window.__sootsimConsole?.getErrors(10) || []"});if(n!==l&&n.close(),Array.isArray(p)&&p.length>0){console.log(`
647
+ })()`});r=!!p&&p.kind==="external-app",s=!0}catch{}console.log(" reloading...");let n=l,m=null;if(r)m=await fe(l,{timeoutMs:1e4,errorGraceMs:3e3});else{s&&await Y(300);let p=await Fe(A,j,k,{timeoutMs:1e4});p?(n=p,m=await fe(p,{timeoutMs:1e4,errorGraceMs:3e3})):(console.log(" \u26A0 reload: bridge never reconnected within 10000ms"),n=null)}if(m)if(m.ready){let p=m.source==="nodes-fallback"?" (no ready signal, node-count fallback)":"";console.log(` ready in ${m.elapsedMs}ms: ${m.nodes} nodes${p}`)}else m.source==="error-bail"?console.log(` \u26A0 reload bailed after ${m.elapsedMs}ms: ${m.errors} console error(s), ready signal never fired`):console.log(` \u26A0 reload timed out after ${m.elapsedMs}ms (${m.nodes} nodes, ${m.errors} errors)`);if(n)try{let p=await n.send({type:"evaluate",code:"window.__sootsimConsole?.getErrors(10) || []"});if(n!==l&&n.close(),Array.isArray(p)&&p.length>0){console.log(`
644
648
  \u26A0 ${p.length} error(s) during mount:
645
- `);for(let h of p){let f=h.args.map(w=>typeof w=="object"?JSON.stringify(w):w).join(" ");if(console.log(` ${f}`),h.stack){let w=h.stack.split(`
649
+ `);for(let b of p){let f=b.args.map(w=>typeof w=="object"?JSON.stringify(w):w).join(" ");if(console.log(` ${f}`),b.stack){let w=b.stack.split(`
646
650
  `).slice(0,2);for(let O of w)console.log(` ${O.trim()}`)}}}}catch{}m&&!m.ready&&(process.exitCode=1);break}case"eval":case"js":{let e=a.slice(1).join(" ");e||(console.error(S("js","<javascript>")),console.error(""),console.error(" runs the snippet in the engine realm. SootSim is the"),console.error(" canonical state surface \u2014 reach into it directly."),console.error(""),console.error(" examples:"),console.error(` ${y("js")} SootSim.bridges.test.findByText("Sign in")`),console.error(` ${y("js")} SootSim.bridges.debug.snapshot("before")`),console.error(` ${y("js")} SootSim.bridges.keyboard.type("hello")`),console.error(` ${y("js")} SootSim.state.root.children.length`),process.exit(1));let t=e;t.startsWith("(async")||(t=`(async () => ${t})()`);let s=await l.send({type:"evaluate",code:t});console.log(JSON.stringify(s,null,2));let r=e.toLowerCase(),n=[];(r.includes("sootsim:gohome")||r.includes("gohome"))&&n.push("sootsim shell home"),(r.includes("sootsim:appswitcher")||r.includes("appswitcher"))&&n.push("sootsim shell switcher"),(r.includes("keyboard.isvisible")||r.includes("keyboard.getmode"))&&n.push("sootsim debug state keyboard"),r.includes("interact.tap")&&n.push("sootsim do tap <x> <y>"),r.includes("keyboard.type")&&n.push("sootsim do type <text>"),(r.includes("keyboard.press")||r.includes("keyboard.dispatchkey"))&&n.push("sootsim do key <name>"),r.includes("keyboard.dismiss")&&n.push("sootsim do dismiss"),r.includes("dumptree")&&n.push("sootsim get tree"),r.includes("dumpaccessibilitytree")&&n.push("sootsim get a11y"),r.includes("getnodecount")&&n.push("sootsim get count"),r.includes("findbytext")&&n.push("sootsim find <text>"),(r.includes("findbytestid")||r.includes("findbyid"))&&n.push("sootsim find --testid <id>"),r.includes("document.hidden")&&n.push("sootsim debug state keyboard (includes tab health)"),n.length>0&&U("prefer-cli-over-eval",n);break}case"globals":{let e=await l.send({type:"evaluate",code:`(async () => {
647
651
  const globals = {}
648
652
 
@@ -874,7 +878,7 @@ ${s}
874
878
  mode: 'main-thread',
875
879
  frames: (stats.recentFrames || []).slice(-${t}),
876
880
  }
877
- })()`});if(s.error&&(console.error(` error: ${s.error}`),process.exit(1)),s.mode==="render-worker"){let n=Array.isArray(s.samples)?s.samples:[];if(n.length===0){console.log(` no frame data \u2014 run '${y("perf")} start' first`);break}console.log(` last ${n.length} sampled frames (ms):`),console.log(" total layout render copy aux other t+");for(let[m,p,h,f,w,O,B]of n)console.log(` ${p.toFixed(2).padStart(7)} ${h.toFixed(2).padStart(7)} ${f.toFixed(2).padStart(7)} ${w.toFixed(2).padStart(7)} ${O.toFixed(2).padStart(6)} ${B.toFixed(2).padStart(7)} ${String(m).padStart(5)}`);console.log(""),be(n.map(m=>m[1])),s.live&&console.log(" sampling continues");break}let r=Array.isArray(s.frames)?s.frames:Array.isArray(s)?s:[];if(r.length===0){console.log(` no frame data \u2014 run '${y("perf")} start' first`);break}console.log(` last ${r.length} frame times (ms):`),console.log(` ${r.map(n=>n.toFixed(2)).join(", ")}`),be(r);break}case"worst":{let t=a[2]?Number(a[2]):20;(!Number.isFinite(t)||t<=0)&&(console.error(` error: expected a positive frame count, got "${a[2]}"`),process.exit(1));let s=await l.send({type:"evaluate",code:`(async () => {
881
+ })()`});if(s.error&&(console.error(` error: ${s.error}`),process.exit(1)),s.mode==="render-worker"){let n=Array.isArray(s.samples)?s.samples:[];if(n.length===0){console.log(` no frame data \u2014 run '${y("perf")} start' first`);break}console.log(` last ${n.length} sampled frames (ms):`),console.log(" total layout render copy aux other t+");for(let[m,p,b,f,w,O,B]of n)console.log(` ${p.toFixed(2).padStart(7)} ${b.toFixed(2).padStart(7)} ${f.toFixed(2).padStart(7)} ${w.toFixed(2).padStart(7)} ${O.toFixed(2).padStart(6)} ${B.toFixed(2).padStart(7)} ${String(m).padStart(5)}`);console.log(""),he(n.map(m=>m[1])),s.live&&console.log(" sampling continues");break}let r=Array.isArray(s.frames)?s.frames:Array.isArray(s)?s:[];if(r.length===0){console.log(` no frame data \u2014 run '${y("perf")} start' first`);break}console.log(` last ${r.length} frame times (ms):`),console.log(` ${r.map(n=>n.toFixed(2)).join(", ")}`),he(r);break}case"worst":{let t=a[2]?Number(a[2]):20;(!Number.isFinite(t)||t<=0)&&(console.error(` error: expected a positive frame count, got "${a[2]}"`),process.exit(1));let s=await l.send({type:"evaluate",code:`(async () => {
878
882
  if (window.__sootsimRenderHost) {
879
883
  const session = window.${G} || {}
880
884
  if (session.active) {
@@ -916,7 +920,7 @@ ${s}
916
920
  mode: 'main-thread',
917
921
  frames: recent.slice().sort((a, b) => b - a).slice(0, ${t}),
918
922
  }
919
- })()`});if(s.error&&(console.error(` error: ${s.error}`),process.exit(1)),s.mode==="render-worker"){let n=Array.isArray(s.samples)?s.samples:[];if(n.length===0){console.log(` no frame data \u2014 run '${y("perf")} start' first`);break}console.log(` worst ${n.length} sampled frames (ms):`),console.log(" total layout render copy aux other t+");for(let[m,p,h,f,w,O,B]of n)console.log(` ${p.toFixed(2).padStart(7)} ${h.toFixed(2).padStart(7)} ${f.toFixed(2).padStart(7)} ${w.toFixed(2).padStart(7)} ${O.toFixed(2).padStart(6)} ${B.toFixed(2).padStart(7)} ${String(m).padStart(5)}`);s.live&&(console.log(""),console.log(" sampling continues"));break}let r=Array.isArray(s.frames)?s.frames:Array.isArray(s)?s:[];if(r.length===0){console.log(` no frame data \u2014 run '${y("perf")} start' first`);break}console.log(` worst ${r.length} frame times (ms):`),console.log(` ${r.map(n=>n.toFixed(2)).join(", ")}`);break}case"transition":{let t=a[2];if(!t||!["goHome","appSwitcher","lockScreen"].includes(t)){console.log(`
923
+ })()`});if(s.error&&(console.error(` error: ${s.error}`),process.exit(1)),s.mode==="render-worker"){let n=Array.isArray(s.samples)?s.samples:[];if(n.length===0){console.log(` no frame data \u2014 run '${y("perf")} start' first`);break}console.log(` worst ${n.length} sampled frames (ms):`),console.log(" total layout render copy aux other t+");for(let[m,p,b,f,w,O,B]of n)console.log(` ${p.toFixed(2).padStart(7)} ${b.toFixed(2).padStart(7)} ${f.toFixed(2).padStart(7)} ${w.toFixed(2).padStart(7)} ${O.toFixed(2).padStart(6)} ${B.toFixed(2).padStart(7)} ${String(m).padStart(5)}`);s.live&&(console.log(""),console.log(" sampling continues"));break}let r=Array.isArray(s.frames)?s.frames:Array.isArray(s)?s:[];if(r.length===0){console.log(` no frame data \u2014 run '${y("perf")} start' first`);break}console.log(` worst ${r.length} frame times (ms):`),console.log(` ${r.map(n=>n.toFixed(2)).join(", ")}`);break}case"transition":{let t=a[2];if(!t||!["goHome","appSwitcher","lockScreen"].includes(t)){console.log(`
920
924
  ${y("perf")} transition <event> \u2014 profile a shell transition
921
925
 
922
926
  events:
@@ -1006,25 +1010,25 @@ ${s}
1006
1010
  p50: ${n.p50.toFixed(2)}ms
1007
1011
  p95: ${n.p95.toFixed(2)}ms
1008
1012
  p99: ${n.p99.toFixed(2)}ms
1009
- jank: ${n.jankFrames} frames (${p}%) >16.67ms`),Array.isArray(n.samples)&&n.samples.length>0&&(console.log(""),be(n.samples.map(h=>h[1])));break}default:console.error(` unknown perf subcommand: ${e}`),process.exit(1)}break}case"errors":{let e=a[1];if(e==="clear"){await l.send({type:"evaluate",code:'window.__sootsimConsole?.clear(); "cleared"'}),E(d)?C({cleared:!0}):console.log(" error buffer cleared");break}let t=e?Number(e):20,s=await l.send({type:"evaluate",code:`window.__sootsimConsole?.getErrors(${t}) || []`}),r=Array.isArray(s)?s:[];if(E(d)){C(r);break}if(r.length===0){console.log(" no errors captured");break}console.log(` ${r.length} error(s):
1010
- `);for(let n of r){let m=new Date(n.timestamp).toLocaleTimeString(),p=n.args.map(h=>typeof h=="object"?JSON.stringify(h):h).join(" ");if(console.log(` [${m}] ${p}`),n.stack){let h=n.stack.split(`
1011
- `).slice(0,3);for(let f of h)console.log(` ${f.trim()}`)}}break}case"warnings":{let e=a[1]?Number(a[1]):20,t=await l.send({type:"evaluate",code:`window.__sootsimConsole?.getWarnings(${e}) || []`}),s=Array.isArray(t)?t:[];if(E(d)){C(s);break}if(s.length===0){console.log(" no warnings captured");break}console.log(` ${s.length} warning(s):
1013
+ jank: ${n.jankFrames} frames (${p}%) >16.67ms`),Array.isArray(n.samples)&&n.samples.length>0&&(console.log(""),he(n.samples.map(b=>b[1])));break}default:console.error(` unknown perf subcommand: ${e}`),process.exit(1)}break}case"errors":{let e=a[1];if(e==="clear"){await l.send({type:"evaluate",code:'window.__sootsimConsole?.clear(); "cleared"'}),E(d)?C({cleared:!0}):console.log(" error buffer cleared");break}let t=e?Number(e):20,s=await l.send({type:"evaluate",code:`window.__sootsimConsole?.getErrors(${t}) || []`}),r=Array.isArray(s)?s:[];if(E(d)){C(r);break}if(r.length===0){console.log(" no errors captured");break}console.log(` ${r.length} error(s):
1014
+ `);for(let n of r){let m=new Date(n.timestamp).toLocaleTimeString(),p=n.args.map(b=>typeof b=="object"?JSON.stringify(b):b).join(" ");if(console.log(` [${m}] ${p}`),n.stack){let b=n.stack.split(`
1015
+ `).slice(0,3);for(let f of b)console.log(` ${f.trim()}`)}}break}case"warnings":{let e=a[1]?Number(a[1]):20,t=await l.send({type:"evaluate",code:`window.__sootsimConsole?.getWarnings(${e}) || []`}),s=Array.isArray(t)?t:[];if(E(d)){C(s);break}if(s.length===0){console.log(" no warnings captured");break}console.log(` ${s.length} warning(s):
1012
1016
  `);for(let r of s){let n=new Date(r.timestamp).toLocaleTimeString(),m=r.args.map(p=>typeof p=="object"?JSON.stringify(p):p).join(" ");console.log(` [${n}] ${m}`)}break}case"animations":{let e=await z(l,"listAnimations")??[];if(o.includes("--json")){console.log(JSON.stringify(e,null,2));break}if(e.length===0){console.log(" no active animations");break}console.log(` ${e.length} active animation(s):
1013
- `);for(let t of e){let s=String(t.kind).padEnd(6),r=`${Number(t.from).toFixed(2)}\u2192${Number(t.to).toFixed(2)}`,n=Number(t.current??0).toFixed(2),m=`${Math.round((t.progress??0)*100)}%`,p=`${Math.round(t.elapsedMs??0)}ms`,h=t.loop?" loop":"",f=t.layoutBound?" layout":"";console.log(` #${t.id} ${s} ${r.padEnd(14)} cur=${n.padEnd(7)} ${m.padStart(4)} ${p}${h}${f}`)}break}case"animation":{let e=a[1];(!e||e==="--help"||e==="-h")&&(console.error(` usage: ${y("animation")} <id>`),process.exit(1));let t=Number(e);Number.isFinite(t)||(console.error(` invalid id: ${e}`),process.exit(1));let s=await z(l,"getAnimation",t);console.log(JSON.stringify(s,null,2));break}case"stop-animation":{let e=a[1];(!e||e==="--help"||e==="-h")&&(console.error(` usage: ${y("stop-animation")} <id|all>`),process.exit(1));let t=e==="all"?"all":Number(e);t!=="all"&&!Number.isFinite(t)&&(console.error(` invalid id: ${e}`),process.exit(1));let s=await z(l,"stopAnimation",t);console.log(` stopped ${s??0} animation(s)`);break}case"requests":{let e=a[1];if(e==="clear"){await z(l,"clearRequests"),E(d)?C({cleared:!0}):console.log(" request buffer cleared");break}let t=e==="all",s=t?a[2]:e,r=s?Number(s):20,n=t?await z(l,"getRequests",r):await z(l,"getFailedRequests",r),m=Array.isArray(n)?n:[];if(E(d)){C(m);break}if(m.length===0){console.log(t?" no requests captured":" no failed requests captured");break}console.log(` ${m.length} ${t?"request(s)":"failed request(s)"}:
1014
- `);for(let p of m){let h=new Date(p.timestamp).toLocaleTimeString();console.log(` [${h}] ${q(p)}`),p.responseBody?console.log(` ${p.responseBody}`):p.error&&console.log(` ${p.error}`)}break}case"network":{let e=a[1],t=null,s=null,r=!1,n=!1,m=!1;for(let N=0;N<d.length;N++){let M=d[N];if(M==="--filter")t=d[N+1]??null,N++;else if(M==="--limit"){let F=Number(d[N+1]);Number.isFinite(F)&&(s=F),N++}else M==="--failed"?r=!0:M==="--tail"||M==="-f"?n=!0:M==="--json"&&(m=!0)}if(e==="clear"){await l.send({type:"evaluate",code:'window.__sootsimObservability?.network.clear(); "cleared"'}),console.log(" network buffer cleared");break}if(e==="get"){let N=a[2];N||(console.error(" usage: sootsim network get <id>"),process.exit(1));let M=await l.send({type:"evaluate",code:`(() => {
1017
+ `);for(let t of e){let s=String(t.kind).padEnd(6),r=`${Number(t.from).toFixed(2)}\u2192${Number(t.to).toFixed(2)}`,n=Number(t.current??0).toFixed(2),m=`${Math.round((t.progress??0)*100)}%`,p=`${Math.round(t.elapsedMs??0)}ms`,b=t.loop?" loop":"",f=t.layoutBound?" layout":"";console.log(` #${t.id} ${s} ${r.padEnd(14)} cur=${n.padEnd(7)} ${m.padStart(4)} ${p}${b}${f}`)}break}case"animation":{let e=a[1];(!e||e==="--help"||e==="-h")&&(console.error(` usage: ${y("animation")} <id>`),process.exit(1));let t=Number(e);Number.isFinite(t)||(console.error(` invalid id: ${e}`),process.exit(1));let s=await z(l,"getAnimation",t);console.log(JSON.stringify(s,null,2));break}case"stop-animation":{let e=a[1];(!e||e==="--help"||e==="-h")&&(console.error(` usage: ${y("stop-animation")} <id|all>`),process.exit(1));let t=e==="all"?"all":Number(e);t!=="all"&&!Number.isFinite(t)&&(console.error(` invalid id: ${e}`),process.exit(1));let s=await z(l,"stopAnimation",t);console.log(` stopped ${s??0} animation(s)`);break}case"requests":{let e=a[1];if(e==="clear"){await z(l,"clearRequests"),E(d)?C({cleared:!0}):console.log(" request buffer cleared");break}let t=e==="all",s=t?a[2]:e,r=s?Number(s):20,n=t?await z(l,"getRequests",r):await z(l,"getFailedRequests",r),m=Array.isArray(n)?n:[];if(E(d)){C(m);break}if(m.length===0){console.log(t?" no requests captured":" no failed requests captured");break}console.log(` ${m.length} ${t?"request(s)":"failed request(s)"}:
1018
+ `);for(let p of m){let b=new Date(p.timestamp).toLocaleTimeString();console.log(` [${b}] ${q(p)}`),p.responseBody?console.log(` ${p.responseBody}`):p.error&&console.log(` ${p.error}`)}break}case"network":{let e=a[1],t=null,s=null,r=!1,n=!1,m=!1;for(let N=0;N<d.length;N++){let M=d[N];if(M==="--filter")t=d[N+1]??null,N++;else if(M==="--limit"){let F=Number(d[N+1]);Number.isFinite(F)&&(s=F),N++}else M==="--failed"?r=!0:M==="--tail"||M==="-f"?n=!0:M==="--json"&&(m=!0)}if(e==="clear"){await l.send({type:"evaluate",code:'window.__sootsimObservability?.network.clear(); "cleared"'}),console.log(" network buffer cleared");break}if(e==="get"){let N=a[2];N||(console.error(" usage: sootsim network get <id>"),process.exit(1));let M=await l.send({type:"evaluate",code:`(() => {
1015
1019
  const obs = window.__sootsimObservability;
1016
1020
  if (!obs) return null;
1017
1021
  return obs.network.getSnapshot().find(e => e.id === ${JSON.stringify(N)}) || null;
1018
- })()`});M||(console.error(` no entry with id ${N}`),process.exit(1)),m?console.log(JSON.stringify(M,null,2)):Ft(M);break}let p=s??(n?200:e?Number(e):20);Number.isFinite(p)||(console.error(` invalid limit: ${e}`),process.exit(1));let h=async()=>{let N=await l.send({type:"evaluate",code:`(() => {
1022
+ })()`});M||(console.error(` no entry with id ${N}`),process.exit(1)),m?console.log(JSON.stringify(M,null,2)):Ft(M);break}let p=s??(n?200:e?Number(e):20);Number.isFinite(p)||(console.error(` invalid limit: ${e}`),process.exit(1));let b=async()=>{let N=await l.send({type:"evaluate",code:`(() => {
1019
1023
  const obs = window.__sootsimObservability;
1020
1024
  if (!obs) return { ok: false };
1021
1025
  return { ok: true, entries: obs.network.getSnapshot() };
1022
- })()`});if(!N||!N.ok)throw new Error("observability bridge not installed \u2014 is the engine running?");return N.entries??[]},f=N=>{let M=N;if(r&&(M=M.filter(F=>!!F.error||F.status!=null&&F.status>=400)),t){let F=t.toLowerCase();M=M.filter(W=>(W.displayUrl||W.url).toLowerCase().includes(F))}return M};if(!n){let N=await h(),M=f(N).slice(-p);if(m){console.log(JSON.stringify(M,null,2));break}if(M.length===0){console.log(N.length===0?" no network requests captured":" no matching requests");break}console.log(` ${M.length} request(s):
1026
+ })()`});if(!N||!N.ok)throw new Error("observability bridge not installed \u2014 is the engine running?");return N.entries??[]},f=N=>{let M=N;if(r&&(M=M.filter(F=>!!F.error||F.status!=null&&F.status>=400)),t){let F=t.toLowerCase();M=M.filter(W=>(W.displayUrl||W.url).toLowerCase().includes(F))}return M};if(!n){let N=await b(),M=f(N).slice(-p);if(m){console.log(JSON.stringify(M,null,2));break}if(M.length===0){console.log(N.length===0?" no network requests captured":" no matching requests");break}console.log(` ${M.length} request(s):
1023
1027
  `);for(let F of M)Ze(F);break}console.log(` tailing network (ctrl-c to stop)...
1024
- `);let w=new Set,O=!0,B=()=>{O=!1};process.on("SIGINT",B);try{for(;O;){let N=await h(),M=f(N);for(let F of M)F.durationMs!=null&&(w.has(F.id)||(w.add(F.id),m?console.log(JSON.stringify(F)):Ze(F)));await Y(250)}}finally{process.off("SIGINT",B)}break}case"logs":{let e=a[1],t=null,s=null,r=null,n=!1,m=!1,p=!1;for(let g=0;g<d.length;g++){let T=d[g];if(T==="--filter")t=d[g+1]??null,g++;else if(T==="--limit"){let _=Number(d[g+1]);Number.isFinite(_)&&(s=_),g++}else T==="--level"?(r=d[g+1]??null,g++):T==="--tail"||T==="-f"?n=!0:T==="--json"?m=!0:(T==="--internal"||T==="--all")&&(p=!0)}let h=r?new Set(r.split(",").map(g=>g.trim()).filter(g=>g==="log"||g==="info"||g==="warn"||g==="error"||g==="debug")):null;if(e==="clear"){await l.send({type:"evaluate",code:'window.__sootsimObservability?.logs.clear(); "cleared"'}),console.log(" log buffer cleared");break}let f=!m&&process.stdout.isTTY===!0,w=s??(n?500:e?Number(e):50);Number.isFinite(w)||(console.error(` invalid limit: ${e}`),process.exit(1));let O=async()=>{let g=await l.send({type:"evaluate",code:`(() => {
1028
+ `);let w=new Set,O=!0,B=()=>{O=!1};process.on("SIGINT",B);try{for(;O;){let N=await b(),M=f(N);for(let F of M)F.durationMs!=null&&(w.has(F.id)||(w.add(F.id),m?console.log(JSON.stringify(F)):Ze(F)));await Y(250)}}finally{process.off("SIGINT",B)}break}case"logs":{let e=a[1],t=null,s=null,r=null,n=!1,m=!1,p=!1;for(let g=0;g<d.length;g++){let T=d[g];if(T==="--filter")t=d[g+1]??null,g++;else if(T==="--limit"){let _=Number(d[g+1]);Number.isFinite(_)&&(s=_),g++}else T==="--level"?(r=d[g+1]??null,g++):T==="--tail"||T==="-f"?n=!0:T==="--json"?m=!0:(T==="--internal"||T==="--all")&&(p=!0)}let b=r?new Set(r.split(",").map(g=>g.trim()).filter(g=>g==="log"||g==="info"||g==="warn"||g==="error"||g==="debug")):null;if(e==="clear"){await l.send({type:"evaluate",code:'window.__sootsimObservability?.logs.clear(); "cleared"'}),console.log(" log buffer cleared");break}let f=!m&&process.stdout.isTTY===!0,w=s??(n?500:e?Number(e):50);Number.isFinite(w)||(console.error(` invalid limit: ${e}`),process.exit(1));let O=async()=>{let g=await l.send({type:"evaluate",code:`(() => {
1025
1029
  const obs = window.__sootsimObservability;
1026
1030
  if (!obs) return { ok: false };
1027
1031
  return { ok: true, entries: obs.logs.getSnapshot() };
1028
- })()`});if(!g||!g.ok)throw new Error("observability bridge not installed \u2014 is the engine running?");return g.entries??[]},B=g=>{let T=g.args[0];return typeof T!="string"?!1:T.startsWith("[sootsim]")},N=g=>{let T=g;if(p||(T=T.filter(_=>!B(_))),h&&(T=T.filter(_=>h.has(_.level))),t){let _=t.toLowerCase();T=T.filter(P=>P.args.join(" ").toLowerCase().includes(_))}return T};if(!n){let g=await O(),T=N(g).slice(-w);if(m){console.log(JSON.stringify(T,null,2));break}if(T.length===0){console.log(g.length===0?" no logs captured":" no matching logs");break}console.log(` ${T.length} log(s):
1032
+ })()`});if(!g||!g.ok)throw new Error("observability bridge not installed \u2014 is the engine running?");return g.entries??[]},B=g=>{let T=g.args[0];return typeof T!="string"?!1:T.startsWith("[sootsim]")},N=g=>{let T=g;if(p||(T=T.filter(_=>!B(_))),b&&(T=T.filter(_=>b.has(_.level))),t){let _=t.toLowerCase();T=T.filter(P=>P.args.join(" ").toLowerCase().includes(_))}return T};if(!n){let g=await O(),T=N(g).slice(-w);if(m){console.log(JSON.stringify(T,null,2));break}if(T.length===0){console.log(g.length===0?" no logs captured":" no matching logs");break}console.log(` ${T.length} log(s):
1029
1033
  `);for(let _ of T)et(_,f);break}console.log(` tailing logs (ctrl-c to stop)...
1030
- `);let M=new Set,F=!0,W=()=>{F=!1};process.on("SIGINT",W);try{for(;F;){let g=await O(),T=N(g);for(let _ of T)M.has(_.id)||(M.add(_.id),m?console.log(JSON.stringify(_)):et(_,f));await Y(250)}}finally{process.off("SIGINT",W)}break}default:console.error(` unknown subcommand: ${b}`),process.exit(1)}if(H.has(b)&&!o.includes("--no-wait")&&process.env.SOOTSIM_NO_AUTO_WAIT!=="1"&&await ne(l),!D.has(b)&&!E(d)){let e=await Z();try{await J({counts:e.console})}catch{}try{await x({counts:e.requests})}catch{}}}catch(e){let t=e instanceof Error?e.message:String(e);if(console.error(` ${b??"inspect"} failed: ${t}`),/^no browser connected( with id .+)?$/.test(t))Ae(A);else{try{await Me(l)}catch{}try{await J({includeTail:!0})}catch{}try{await x({includeTail:!0})}catch{}}process.exit(1)}finally{l.close()}}export{rs as runInspect};
1034
+ `);let M=new Set,F=!0,W=()=>{F=!1};process.on("SIGINT",W);try{for(;F;){let g=await O(),T=N(g);for(let _ of T)M.has(_.id)||(M.add(_.id),m?console.log(JSON.stringify(_)):et(_,f));await Y(250)}}finally{process.off("SIGINT",W)}break}default:console.error(` unknown subcommand: ${h}`),process.exit(1)}if(H.has(h)&&!o.includes("--no-wait")&&process.env.SOOTSIM_NO_AUTO_WAIT!=="1"&&await ne(l),!D.has(h)&&!E(d)){let e=await Z();try{await J({counts:e.console})}catch{}try{await x({counts:e.requests})}catch{}}}catch(e){let t=e instanceof Error?e.message:String(e);if(console.error(` ${h??"inspect"} failed: ${t}`),/^no browser connected( with id .+)?$/.test(t))Ae(A);else{try{await Me(l)}catch{}try{await J({includeTail:!0})}catch{}try{await x({includeTail:!0})}catch{}}process.exit(1)}finally{l.close()}}export{rs as runInspect};
@@ -0,0 +1,2 @@
1
+ /*! sootsim v0.1.36 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
+ import{a as o}from"./chunk-27P763IZ.js";import"./chunk-VFDRZNPN.js";import"./chunk-IJMYFYDZ.js";import"./chunk-EJLNUMMP.js";import"./chunk-TC6V7YFC.js";import"./chunk-SMVJOWSV.js";import"./chunk-6GGMKFWJ.js";import"./chunk-ZEW3RF5Q.js";import"./chunk-5QIUJNT3.js";import"./chunk-LHDWH7VS.js";async function t(n){console.error(" note: `sootsim install` is now `sootsim setup-repo`. forwarding\u2026\n"),await o(n)}export{t as runInstall};
@@ -0,0 +1,23 @@
1
+ /*! sootsim v0.1.36 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
+ import{a as b}from"./chunk-VFDRZNPN.js";import{a as x}from"./chunk-PJL25JQV.js";import"./chunk-LHDWH7VS.js";import{spawn as k,spawnSync as u}from"child_process";import{chmodSync as S,createWriteStream as E,existsSync as w,mkdirSync as y,renameSync as T,rmSync as g,statSync as P}from"fs";import{tmpdir as D}from"os";import{dirname as M,join as f,resolve as v}from"path";var h="https://sootbean.com/api/electron-release";function A(){let r=process.arch;if(process.platform==="darwin"){let o=r==="arm64"?"mac-arm64":"mac-x64",n=`sootsim-latest-${o}.dmg`;return{platform:o,filename:n,url:`${h}/${n}`,install:_}}if(process.platform==="linux"){let o="sootsim-latest-linux-x64.AppImage";return{platform:"linux-x64",filename:o,url:`${h}/${o}`,install:L}}if(process.platform==="win32"){let o="sootsim-latest-win-x64.exe";return{platform:"win-x64",filename:o,url:`${h}/${o}`,install:C}}return null}async function O({url:r,dest:o,onProgress:n}){let s=await fetch(r,{redirect:"follow"});if(!s.ok)throw new Error(`download failed: ${s.status} ${s.statusText} (${r})`);let t=s.headers.get("content-length"),a=t?Number(t):null;if(!s.body)throw new Error("download failed: empty response body");y(M(o),{recursive:!0});let i=E(o),d=s.body.getReader(),c=0;try{for(;;){let{done:l,value:p}=await d.read();if(l)break;i.write(Buffer.from(p)),c+=p.byteLength,n?.(c,a)}}finally{await new Promise((l,p)=>{i.end(e=>e?p(e):l())})}}function I(r,o){let n=(r/1048576).toFixed(1);if(!o)return` ${n} MB`;let s=Math.min(100,Math.round(r/o*100)),t=(o/(1024*1024)).toFixed(1),a=24,i=Math.round(s/100*a);return` ${"\u2588".repeat(i)+"\u2591".repeat(a-i)} ${s}% ${n} / ${t} MB`}async function _(r){let o=u("hdiutil",["attach","-nobrowse","-readonly",r],{encoding:"utf8"});if(o.status!==0)throw new Error(`hdiutil attach failed: ${o.stderr||o.stdout}`.trim());let n=o.stdout.trim().split(`
3
+ `),t=n[n.length-1].split(" ").pop()?.trim();if(!t||!w(t))throw new Error(`could not determine dmg mount point (output: ${o.stdout})`);let a=f(t,"sootsim.app");if(!w(a))throw u("hdiutil",["detach","-force",t]),new Error(`sootsim.app not found inside ${t}`);let i="/Applications",d=v(process.env.HOME||"","Applications"),c=i;try{let m=f(i,`.sootsim-write-probe-${process.pid}`);u("touch",[m]),w(m)?g(m,{force:!0}):c=d}catch{c=d}c===d&&y(c,{recursive:!0});let l=f(c,"sootsim.app");w(l)&&g(l,{recursive:!0,force:!0});let p=u("cp",["-R",a,l]),e=u("hdiutil",["detach","-force",t]);if(p.status!==0)throw new Error(`copy to ${l} failed: ${p.stderr?.toString()||""}`.trim());return e.status!==0&&console.warn(` warning: failed to unmount ${t} (${e.stderr?.toString().trim()||"unknown error"})`),u("xattr",["-dr","com.apple.quarantine",l]),l}async function L(r){let o=v(process.env.HOME||"","Applications");y(o,{recursive:!0});let n=f(o,"sootsim.AppImage");return w(n)&&g(n,{force:!0}),T(r,n),S(n,493),n}async function C(r){return await new Promise((o,n)=>{let s=k("cmd",["/c","start",'""',"/wait",r],{stdio:"inherit"});s.once("error",n),s.once("exit",t=>{t===0?o():n(new Error(`installer exited with code ${t}`))})}),r}async function Y(r){(r.includes("--help")||r.includes("-h"))&&(console.log(`
4
+ sootsim install-desktop \u2014 download and install the optional desktop GUI
5
+
6
+ the CLI + daemon are the canonical sootsim surface; the GUI is optional.
7
+ if you just want to drive a running metro/expo dev server from the
8
+ terminal, you don't need this.
9
+
10
+ usage:
11
+ sootsim install-desktop [options]
12
+
13
+ options:
14
+ -y, --yes skip confirmation and install immediately
15
+ --force reinstall even if the companion is already present
16
+
17
+ examples:
18
+ sootsim install-desktop
19
+ sootsim install-desktop --yes
20
+ `),process.exit(0));let o=r.includes("--yes")||r.includes("-y")||process.env.SOOTSIM_NO_PROMPT==="1"||process.env.CI==="1"||!process.stdin.isTTY,n=r.includes("--force"),s=x();if(s&&!n){console.log(` sootsim desktop already installed at: ${s.path}`),console.log(" pass --force to reinstall.");return}let t=A();if(t||(console.error(` no desktop build available for ${process.platform}/${process.arch}.`),console.error(" supported: darwin-arm64, darwin-x64, linux-x64, win32-x64"),process.exit(1)),console.log(` platform: ${t.platform}`),console.log(` download: ${t.url}`),console.log(),!o){if(!await b("download and install now?",!0)){console.log(" cancelled.");return}console.log()}let a=f(D(),`sootsim-install-${Date.now()}`),i=f(a,t.filename),d=0;process.stdout.write(` downloading ${t.filename}...
21
+ `);try{await O({url:t.url,dest:i,onProgress:(e,m)=>{let $=Date.now();$-d<100&&e<(m??1/0)||(d=$,process.stdout.isTTY&&process.stdout.write(`\r\x1B[2K${I(e,m)}`))}})}catch(e){g(a,{recursive:!0,force:!0}),console.error(`
22
+ download failed: ${e instanceof Error?e.message:String(e)}`),process.exit(1)}process.stdout.isTTY&&process.stdout.write(`
23
+ `);let c=P(i).size;console.log(` downloaded ${(c/(1024*1024)).toFixed(1)} MB`),console.log(),console.log(" installing...");let{trackCliEvent:l,flushCliTelemetry:p}=await import("./telemetry-CN42GMVC.js");try{let e=await t.install(i);l({event:"cli_install_desktop_succeeded",properties:{platform:t.platform,size_bytes:c}}),console.log(` installed: ${e}`)}catch(e){l({event:"cli_install_desktop_failed",properties:{platform:t.platform,error:e instanceof Error?e.message:String(e)}}),await p(),console.error(` install failed: ${e instanceof Error?e.message:String(e)}`),console.error(` keeping download at ${i} for manual install.`),process.exit(1)}finally{g(a,{recursive:!0,force:!0})}console.log(),console.log(" next steps:"),console.log(" sootsim electron launch the desktop app"),console.log(" sootsim open <target> open a demo or bundle in it")}export{Y as runInstallDesktop};
@@ -1,5 +1,5 @@
1
- /*! sootsim v0.0.4 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
- import{a as b}from"./chunk-6SZMLFCR.js";import"./chunk-WWDJCKMI.js";import{spawnSync as m}from"child_process";import{chmodSync as $,existsSync as u,mkdirSync as y,rmSync as N,writeFileSync as g,cpSync as B}from"fs";import{dirname as p,join as s,resolve as k}from"path";import{fileURLToPath as S}from"url";var C=p(S(import.meta.resolve("sootsim-engine/package.json"))),I="sootsim-dev",E="dev.sootsim.simulator.dev";function w(e){let n={yes:e.includes("--yes")||e.includes("-y")||process.env.SOOTSIM_NO_PROMPT==="1"||process.env.CI==="1"||!process.stdin.isTTY,force:e.includes("--force"),appName:I,bundleId:E};for(let o=0;o<e.length;o++){let t=e[o];t==="--name"&&e[o+1]?n.appName=e[++o]:t==="--bundle-id"&&e[o+1]?n.bundleId=e[++o]:t==="--path"&&e[o+1]&&(n.installRoot=e[++o])}return n}function T(e){let r=process.platform==="darwin"?"electron/dist/Electron.app/Contents/MacOS/Electron":process.platform==="win32"?"electron/dist/electron.exe":"electron/dist/electron",c=e;for(let l=0;l<6;l++){let d=s(c,"node_modules",r);if(u(d))return d;let i=p(c);if(i===c)break;c=i}return null}function D(e){if(e)return k(e);let n="/Applications",o=k(process.env.HOME||"","Applications");try{let t=s(n,`.sootsim-dev-write-probe-${process.pid}`);if(m("touch",[t]).status===0&&u(t))return N(t,{force:!0}),n}catch{}return y(o,{recursive:!0}),o}function L(e){return`<?xml version="1.0" encoding="UTF-8"?>
1
+ /*! sootsim v0.1.36 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
+ import{a as b}from"./chunk-VFDRZNPN.js";import"./chunk-LHDWH7VS.js";import{spawnSync as m}from"child_process";import{chmodSync as $,existsSync as u,mkdirSync as y,rmSync as N,writeFileSync as g,cpSync as B}from"fs";import{dirname as p,join as s,resolve as k}from"path";import{fileURLToPath as S}from"url";var C=p(S(import.meta.resolve("sootsim-engine/package.json"))),I="sootsim-dev",E="dev.sootsim.simulator.dev";function w(e){let n={yes:e.includes("--yes")||e.includes("-y")||process.env.SOOTSIM_NO_PROMPT==="1"||process.env.CI==="1"||!process.stdin.isTTY,force:e.includes("--force"),appName:I,bundleId:E};for(let o=0;o<e.length;o++){let t=e[o];t==="--name"&&e[o+1]?n.appName=e[++o]:t==="--bundle-id"&&e[o+1]?n.bundleId=e[++o]:t==="--path"&&e[o+1]&&(n.installRoot=e[++o])}return n}function T(e){let r=process.platform==="darwin"?"electron/dist/Electron.app/Contents/MacOS/Electron":process.platform==="win32"?"electron/dist/electron.exe":"electron/dist/electron",c=e;for(let l=0;l<6;l++){let d=s(c,"node_modules",r);if(u(d))return d;let i=p(c);if(i===c)break;c=i}return null}function D(e){if(e)return k(e);let n="/Applications",o=k(process.env.HOME||"","Applications");try{let t=s(n,`.sootsim-dev-write-probe-${process.pid}`);if(m("touch",[t]).status===0&&u(t))return N(t,{force:!0}),n}catch{}return y(o,{recursive:!0}),o}function L(e){return`<?xml version="1.0" encoding="UTF-8"?>
3
3
  <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
4
4
  <plist version="1.0">
5
5
  <dict>
@@ -1,5 +1,5 @@
1
- /*! sootsim v0.0.4 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
- import{a as l,b as d,c as k,d as y,e as g}from"./chunk-AUR2LTNX.js";import{d as c}from"./chunk-UKYK63H6.js";import"./chunk-WWDJCKMI.js";async function a(){let s=await c();return s?.token||(process.stderr.write(" sootsim keys ... needs you to be signed in.\n run `sootsim login` first.\n"),process.exit(1)),{origin:s.origin,token:s.token}}function f(s){if(!s)return"never";try{return new Date(s).toLocaleString()}catch{return s}}async function h(s){let i=s[0];if(!i||i==="--help"||i==="-h"){u();return}if(i==="list"){let{origin:o,token:e}=await a(),n=await fetch(`${o.replace(/\/$/,"")}/api/sootsim/billing/keys`,{headers:{authorization:`Bearer ${e}`}});n.ok||(console.error(` keys list failed (${n.status})`),process.exit(1));let{keys:r}=await n.json();if(r.length===0){console.log(" no keys. create one with `sootsim keys create <label>`.");return}for(let t of r)console.log(` ${t.keyPrefix}\u2026 ${t.label.padEnd(24)} scopes=${t.scopes.join(",")} last=${f(t.lastUsedAt)} id=${t.id}`);return}if(i==="create"){let o=s[1]?.trim();o||(console.error(" usage: sootsim keys create <label>"),process.exit(1));let{origin:e,token:n}=await a(),r=await fetch(`${e.replace(/\/$/,"")}/api/sootsim/billing/keys`,{method:"POST",headers:{authorization:`Bearer ${n}`,"content-type":"application/json"},body:JSON.stringify({label:o})});r.ok||(console.error(` keys create failed (${r.status}): ${await r.text()}`),process.exit(1));let t=await r.json();console.log(`
1
+ /*! sootsim v0.1.36 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
+ import{a as l,b as d,c as k,d as y,e as g}from"./chunk-YLIIVTTQ.js";import{d as c}from"./chunk-EJLNUMMP.js";import"./chunk-LHDWH7VS.js";async function a(){let s=await c();return s?.token||(process.stderr.write(" sootsim keys ... needs you to be signed in.\n run `sootsim login` first.\n"),process.exit(1)),{origin:s.origin,token:s.token}}function f(s){if(!s)return"never";try{return new Date(s).toLocaleString()}catch{return s}}async function h(s){let i=s[0];if(!i||i==="--help"||i==="-h"){u();return}if(i==="list"){let{origin:o,token:e}=await a(),n=await fetch(`${o.replace(/\/$/,"")}/api/sootsim/billing/keys`,{headers:{authorization:`Bearer ${e}`}});n.ok||(console.error(` keys list failed (${n.status})`),process.exit(1));let{keys:r}=await n.json();if(r.length===0){console.log(" no keys. create one with `sootsim keys create <label>`.");return}for(let t of r)console.log(` ${t.keyPrefix}\u2026 ${t.label.padEnd(24)} scopes=${t.scopes.join(",")} last=${f(t.lastUsedAt)} id=${t.id}`);return}if(i==="create"){let o=s[1]?.trim();o||(console.error(" usage: sootsim keys create <label>"),process.exit(1));let{origin:e,token:n}=await a(),r=await fetch(`${e.replace(/\/$/,"")}/api/sootsim/billing/keys`,{method:"POST",headers:{authorization:`Bearer ${n}`,"content-type":"application/json"},body:JSON.stringify({label:o})});r.ok||(console.error(` keys create failed (${r.status}): ${await r.text()}`),process.exit(1));let t=await r.json();console.log(`
3
3
  created: ${t.record.label} (${t.record.keyPrefix}\u2026)`),console.log(` scopes: ${t.record.scopes.join(",")}`),console.log(`
4
4
  secret: ${t.secret}
5
5
  `),console.log(` copy this now \u2014 we can't show it again.
@@ -1,5 +1,5 @@
1
- /*! sootsim v0.0.4 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
- import"./chunk-F4ARVCRR.js";import{o as s,p as a,t as c,u as r,v as l}from"./chunk-WRF43M33.js";import{b as m}from"./chunk-ZF5FCFLD.js";import{a as u}from"./chunk-SY74J6F4.js";import"./chunk-WWDJCKMI.js";import{spawn as p}from"child_process";import{existsSync as h}from"fs";async function I(n){if(n.includes("--help")||n.includes("-h")){console.log(`
1
+ /*! sootsim v0.1.36 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
+ import"./chunk-J7CTD37P.js";import{b as m}from"./chunk-YR7BGGYE.js";import{a as u}from"./chunk-PJL25JQV.js";import"./chunk-G663654J.js";import"./chunk-A5BRCXYE.js";import{q as s,r as a,v as c,w as r,x as l}from"./chunk-5QIUJNT3.js";import"./chunk-LHDWH7VS.js";import{spawn as p}from"child_process";import{existsSync as h}from"fs";async function I(n){if(n.includes("--help")||n.includes("-h")){console.log(`
3
3
  sootsim launch \u2014 one-shot: install runtime if needed, start daemon, open app
4
4
 
5
5
  usage:
@@ -13,4 +13,4 @@ options:
13
13
  examples:
14
14
  sootsim launch
15
15
  sootsim launch --version 1.2.3
16
- `);return}let e=n.includes("--no-runtime-install"),i=n.indexOf("--channel"),t=i>=0&&n[i+1]?n[i+1]:"stable",o=n.indexOf("--version"),f=o>=0&&n[o+1]?n[o+1]:void 0;s(),await v({skipAutoInstall:e,channel:t,explicitVersion:f}),await d(),await x()}async function v(n){let e=a(),i=c();if(e&&i)return;n.skipAutoInstall&&(console.error(" no sootsim runtime installed. run `sootsim runtime install` first, or drop --no-runtime-install."),process.exit(1)),console.log("sootsim: first run \u2014 installing runtime");let{runRuntime:t}=await import("./runtime-PJKHEB36.js"),o=[];n.explicitVersion&&o.push(n.explicitVersion),n.channel!=="stable"&&o.push("--channel",n.channel),await t(["install",...o],{channel:n.channel})}async function d(){let n=r();if(l(n))return;console.log("sootsim: starting daemon");let e=w();p(e,["server","--quiet"],{detached:!0,stdio:"ignore",env:process.env}).unref();let t=Date.now()+8e3;for(;Date.now()<t;){let o=r();if(l(o))return;await g(150)}console.error(" daemon didn't become ready within 8s \u2014 check ~/.sootsim/ or run `sootsim server` in a terminal to see errors"),process.exit(1)}async function x(){u()||(console.error(" no sootsim desktop companion installed. run `sootsim install-desktop` to download electron + the shell."),process.exit(1));let e=await m.launch({});e.launched||(console.error(` ${e.message}`),process.exit(1)),console.log(` ${e.message}`)}function w(){let n=process.argv[1];return n&&h(n)?n:"sootsim"}function g(n){return new Promise(e=>setTimeout(e,n))}async function R(){s(),await d()}export{R as ensureDaemonRunning,I as runLaunch};
16
+ `);return}let e=n.includes("--no-runtime-install"),i=n.indexOf("--channel"),t=i>=0&&n[i+1]?n[i+1]:"stable",o=n.indexOf("--version"),f=o>=0&&n[o+1]?n[o+1]:void 0;s(),await v({skipAutoInstall:e,channel:t,explicitVersion:f}),await d(),await x()}async function v(n){let e=a(),i=c();if(e&&i)return;n.skipAutoInstall&&(console.error(" no sootsim runtime installed. run `sootsim runtime install` first, or drop --no-runtime-install."),process.exit(1)),console.log("sootsim: first run \u2014 installing runtime");let{runRuntime:t}=await import("./runtime-KEMO2MSB.js"),o=[];n.explicitVersion&&o.push(n.explicitVersion),n.channel!=="stable"&&o.push("--channel",n.channel),await t(["install",...o],{channel:n.channel})}async function d(){let n=r();if(l(n))return;console.log("sootsim: starting daemon");let e=w();p(e,["server","--quiet"],{detached:!0,stdio:"ignore",env:process.env}).unref();let t=Date.now()+8e3;for(;Date.now()<t;){let o=r();if(l(o))return;await g(150)}console.error(" daemon didn't become ready within 8s \u2014 check ~/.sootsim/ or run `sootsim server` in a terminal to see errors"),process.exit(1)}async function x(){u()||(console.error(" no sootsim desktop companion installed. run `sootsim install-desktop` to download electron + the shell."),process.exit(1));let e=await m.launch({});e.launched||(console.error(` ${e.message}`),process.exit(1)),console.log(` ${e.message}`)}function w(){let n=process.argv[1];return n&&h(n)?n:"sootsim"}function g(n){return new Promise(e=>setTimeout(e,n))}async function R(){s(),await d()}export{R as ensureDaemonRunning,I as runLaunch};