sootsim 0.0.2 → 0.0.4

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 (105) hide show
  1. package/dist-cli/bin.js +7 -7
  2. package/dist-cli/chunks/{agent-3T4BJEZM.js → agent-PJAOF4JS.js} +2 -2
  3. package/dist-cli/chunks/{agent-wrapper-WCYNLWHZ.js → agent-wrapper-STO7PLQD.js} +2 -2
  4. package/dist-cli/chunks/{assert-FPFJEFF3.js → assert-P47NW4AF.js} +2 -2
  5. package/dist-cli/chunks/auto-bootstrap-SC2LMI2H.js +2 -0
  6. package/dist-cli/chunks/{chunk-KZ2LIDW6.js → chunk-432TMHBG.js} +1 -1
  7. package/dist-cli/chunks/{chunk-6IPY24VM.js → chunk-47S5DXXX.js} +3 -3
  8. package/dist-cli/chunks/{chunk-DW54UPRZ.js → chunk-4VXB2DBA.js} +1 -1
  9. package/dist-cli/chunks/{chunk-ET3NNZAR.js → chunk-4XBPZQLW.js} +2 -2
  10. package/dist-cli/chunks/{chunk-TGDP3D3V.js → chunk-5TTQKPGH.js} +1 -1
  11. package/dist-cli/chunks/{chunk-RJUBGX5M.js → chunk-6SZMLFCR.js} +1 -1
  12. package/dist-cli/chunks/{chunk-LOV766MI.js → chunk-AFQBSK2J.js} +1 -1
  13. package/dist-cli/chunks/{chunk-CZZB4DWG.js → chunk-AUR2LTNX.js} +2 -2
  14. package/dist-cli/chunks/{chunk-SLCVEGTW.js → chunk-BQRM4E66.js} +2 -2
  15. package/dist-cli/chunks/chunk-C3QLIYCS.js +16 -0
  16. package/dist-cli/chunks/{chunk-5C5I5OFM.js → chunk-DQKQYPIG.js} +2 -2
  17. package/dist-cli/chunks/{chunk-ISAMAM3I.js → chunk-EHMSE3Q3.js} +1 -1
  18. package/dist-cli/chunks/chunk-F4ARVCRR.js +1 -0
  19. package/dist-cli/chunks/chunk-HAKR72LJ.js +2 -0
  20. package/dist-cli/chunks/chunk-HGFIS26A.js +2 -0
  21. package/dist-cli/chunks/{chunk-EWMYTXM2.js → chunk-I6XGFZPA.js} +2 -2
  22. package/dist-cli/chunks/{chunk-4372UQHZ.js → chunk-MQDPKSCK.js} +3 -3
  23. package/dist-cli/chunks/chunk-MZPAJ5PQ.js +1 -0
  24. package/dist-cli/chunks/{chunk-AS4V7TZU.js → chunk-OAHMYSMD.js} +1 -1
  25. package/dist-cli/chunks/{chunk-EWEKADK4.js → chunk-QIP7LYQI.js} +2 -2
  26. package/dist-cli/chunks/{chunk-NHA3G6A3.js → chunk-QQOBLF7O.js} +2 -2
  27. package/dist-cli/chunks/{chunk-B5R4K2DG.js → chunk-SY74J6F4.js} +1 -1
  28. package/dist-cli/chunks/{chunk-NE62JSI6.js → chunk-UKYK63H6.js} +1 -1
  29. package/dist-cli/chunks/{chunk-GQUOQNTP.js → chunk-UNFERMZ3.js} +2 -2
  30. package/dist-cli/chunks/{chunk-HORCHQT7.js → chunk-UQ3N6FZF.js} +2 -2
  31. package/dist-cli/chunks/{chunk-K6YUSCAC.js → chunk-VGXARPIH.js} +2 -2
  32. package/dist-cli/chunks/{chunk-TSZBQS6W.js → chunk-W3TYN64D.js} +2 -2
  33. package/dist-cli/chunks/{chunk-XXUAOYYT.js → chunk-W7CYWXRZ.js} +1 -1
  34. package/dist-cli/chunks/{chunk-CXTA5VGA.js → chunk-WRF43M33.js} +1 -1
  35. package/dist-cli/chunks/{chunk-LXCFGKL2.js → chunk-WVBPATRA.js} +1 -1
  36. package/dist-cli/chunks/{chunk-K7LDP7JL.js → chunk-WWDJCKMI.js} +1 -1
  37. package/dist-cli/chunks/{chunk-HBNVKYSC.js → chunk-XJF46GU2.js} +2 -2
  38. package/dist-cli/chunks/{chunk-YVSZHVLU.js → chunk-ZF5FCFLD.js} +2 -2
  39. package/dist-cli/chunks/chunk-ZKNI5MRD.js +1 -0
  40. package/dist-cli/chunks/{compat-3HMKLGXL.js → compat-ILLJ7VDL.js} +2 -2
  41. package/dist-cli/chunks/{config-IJQ3KANN.js → config-CDIAJIIT.js} +2 -2
  42. package/dist-cli/chunks/control-7QGKUCAX.js +2 -0
  43. package/dist-cli/chunks/{daemon-BBEQJLRY.js → daemon-4BLYGM5N.js} +2 -2
  44. package/dist-cli/chunks/{debug-SGZ5ZFQI.js → debug-6SMCTPMC.js} +3 -3
  45. package/dist-cli/chunks/demo-app-registry-HLI5UGGI.js +2 -0
  46. package/dist-cli/chunks/{detox-PK74V2Y7.js → detox-R4G5INNB.js} +2 -2
  47. package/dist-cli/chunks/{device-MWNFX54L.js → device-YSLCWS4E.js} +2 -2
  48. package/dist-cli/chunks/drivers-YIXRFFBQ.js +2 -0
  49. package/dist-cli/chunks/{electron-3NIHSU2K.js → electron-JZOFO37G.js} +3 -3
  50. package/dist-cli/chunks/flow-L7X5FGIN.js +2 -0
  51. package/dist-cli/chunks/{hints-XZJLBIXW.js → hints-O4QR6UGI.js} +2 -2
  52. package/dist-cli/chunks/{home-paths-BNRMUBJA.js → home-paths-4YJJYGR6.js} +2 -2
  53. package/dist-cli/chunks/{inspect-FGTUAK4C.js → inspect-DRFAUJUH.js} +29 -29
  54. package/dist-cli/chunks/{install-LCXALH26.js → install-BATRTWRI.js} +2 -2
  55. package/dist-cli/chunks/{install-desktop-U3RQ6XUX.js → install-desktop-6X474IQ3.js} +2 -2
  56. package/dist-cli/chunks/{install-dev-desktop-BLKRFI42.js → install-dev-desktop-CAJHPRNP.js} +2 -2
  57. package/dist-cli/chunks/{keys-N5LBDSD5.js → keys-OWQ7SOTM.js} +2 -2
  58. package/dist-cli/chunks/{launch-NIMSJH5I.js → launch-WUEDHSO5.js} +3 -3
  59. package/dist-cli/chunks/{login-CQV2XBRM.js → login-54YJ2KH6.js} +2 -2
  60. package/dist-cli/chunks/{logout-R56NWAWQ.js → logout-XECXLEXW.js} +2 -2
  61. package/dist-cli/chunks/{maestro-ZYUVTM7H.js → maestro-PMHK6EHI.js} +2 -2
  62. package/dist-cli/chunks/{preview-AOAWAYEQ.js → preview-4RVHA2PP.js} +2 -2
  63. package/dist-cli/chunks/{profile-DDADDPRW.js → profile-3IVNHUS6.js} +2 -2
  64. package/dist-cli/chunks/{record-3OIOTHP6.js → record-KEWLM5JR.js} +2 -2
  65. package/dist-cli/chunks/{runtime-JTLZYEXK.js → runtime-PJKHEB36.js} +3 -3
  66. package/dist-cli/chunks/{screenshot-Q6N2V5LL.js → screenshot-BXRAQERZ.js} +2 -2
  67. package/dist-cli/chunks/{screenshot-mode-WWLWJWQD.js → screenshot-mode-5IXEDIUS.js} +2 -2
  68. package/dist-cli/chunks/{screenshots-2JEPJGZO.js → screenshots-T4MQF3TB.js} +2 -2
  69. package/dist-cli/chunks/{server-VH34RVAX.js → server-CIP3LH45.js} +2 -2
  70. package/dist-cli/chunks/{skills-PU4627FY.js → skills-DJA6QEVR.js} +2 -2
  71. package/dist-cli/chunks/store-SPC247DB.js +2 -0
  72. package/dist-cli/chunks/{test-AECE56E7.js → test-IWUHNFXV.js} +3 -3
  73. package/dist-cli/chunks/upload-UPD2RSYF.js +2 -0
  74. package/dist-cli/chunks/{whoami-NCGRRR7X.js → whoami-MCXFWKIH.js} +2 -2
  75. package/dist-lib/agent-daemon-client.cjs +1 -1
  76. package/dist-lib/agent-events.cjs +1 -1
  77. package/dist-lib/agent-sessions.cjs +1 -1
  78. package/dist-lib/attached-projects.cjs +1 -1
  79. package/dist-lib/auth/shared-session.cjs +1 -1
  80. package/dist-lib/backend-origin.cjs +1 -1
  81. package/dist-lib/bridge-constants.cjs +1 -1
  82. package/dist-lib/cli-constants.cjs +1 -1
  83. package/dist-lib/config.cjs +1 -1
  84. package/dist-lib/dev-bundle-resolution.cjs +1 -1
  85. package/dist-lib/home-paths.cjs +1 -1
  86. package/dist-lib/host/bridge-host.cjs +1 -1
  87. package/dist-lib/index.cjs +1 -1
  88. package/dist-lib/metro.cjs +1 -1
  89. package/dist-lib/render-mode.cjs +1 -1
  90. package/dist-lib/vite-base.cjs +1 -1
  91. package/dist-lib/vite.cjs +1 -1
  92. package/package.json +1 -1
  93. package/dist-cli/chunks/auto-bootstrap-HDW6N77H.js +0 -2
  94. package/dist-cli/chunks/chunk-3HBBSRLE.js +0 -2
  95. package/dist-cli/chunks/chunk-4GWEO5CL.js +0 -1
  96. package/dist-cli/chunks/chunk-EIZCWDRE.js +0 -1
  97. package/dist-cli/chunks/chunk-FUQ4XA6I.js +0 -16
  98. package/dist-cli/chunks/chunk-NXWCDGWS.js +0 -2
  99. package/dist-cli/chunks/chunk-XKDQEYTE.js +0 -1
  100. package/dist-cli/chunks/control-3RAFI4AW.js +0 -2
  101. package/dist-cli/chunks/demo-app-registry-NCYP3WA6.js +0 -2
  102. package/dist-cli/chunks/drivers-EXUREU4B.js +0 -2
  103. package/dist-cli/chunks/flow-6Y3E6E5P.js +0 -2
  104. package/dist-cli/chunks/store-U2VDD2S4.js +0 -2
  105. package/dist-cli/chunks/upload-KPP7KG6E.js +0 -2
@@ -1,6 +1,6 @@
1
- /*! sootsim v0.0.2 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
- import{a as U}from"./chunk-K6YUSCAC.js";import{a as Ne,b as _e}from"./chunk-LOV766MI.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-HORCHQT7.js";import{a as Te,e as ae}from"./chunk-EWMYTXM2.js";import{a as me,c as pe,d as xe}from"./chunk-DW54UPRZ.js";import{g as Ae}from"./chunk-6IPY24VM.js";import"./chunk-AS4V7TZU.js";import{a as Me}from"./chunk-TGDP3D3V.js";import"./chunk-LXCFGKL2.js";import{a as we}from"./chunk-3HBBSRLE.js";import{c as $e,e as Se,f as ke,h as ve}from"./chunk-FUQ4XA6I.js";import"./chunk-XXUAOYYT.js";import"./chunk-EIZCWDRE.js";import"./chunk-CXTA5VGA.js";import"./chunk-YVSZHVLU.js";import"./chunk-B5R4K2DG.js";import"./chunk-K7LDP7JL.js";import{existsSync as ut,mkdirSync as mt,readFileSync as pt,rmSync as Pe,writeFileSync as ft}from"fs";import{tmpdir as gt}from"os";import{dirname as yt,join as bt,resolve as ht}from"path";var oe=1,wt="SOOTSIM_INSPECT_NOTICE_PATH",xt=300*1e3,$t=15e3;function Oe(){return ht(process.env[wt]||bt(gt(),"sootsim-inspect-notice-state.json"))}function St(o,c){return Object.fromEntries(Object.entries(o).filter(([,i])=>typeof i?.signature=="string"&&Number.isFinite(i?.updatedAt)&&c-i.updatedAt<=xt))}function kt(o){let c=Oe();if(!ut(c))return{version:oe,entries:{}};try{let i=JSON.parse(pt(c,"utf8"));return i.version!==oe||!i.entries||typeof i.entries!="object"?(Pe(c,{force:!0}),{version:oe,entries:{}}):{version:oe,entries:St(i.entries,o)}}catch{return Pe(c,{force:!0}),{version:oe,entries:{}}}}function vt(o){let c=Oe();mt(yt(c),{recursive:!0}),ft(c,JSON.stringify(o,null,2)+`
3
- `)}function Tt(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??$t,b=kt(u),k=Tt(o,c),$=b.entries[k];return $&&$.signature===i&&u-$.updatedAt<a?!1:(b.entries[k]={signature:i,updatedAt:u},vt(b),!0)}async function Ee(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 Re(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.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 () => {
4
4
  const t = window.__sootsimTest
5
5
  const mainShell = window.SootSim?.bridges?.mainShell
6
6
  const kb = window.__sootsimKeyboard
@@ -18,7 +18,7 @@ import{a as U}from"./chunk-K6YUSCAC.js";import{a as Ne,b as _e}from"./chunk-LOV7
18
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(`
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
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 Mt=["SOOTSIM_AGENT","CLAUDECODE","CLAUDE_CODE_ENTRYPOINT","CLAUDE_CODE_SESSION_ID","CODEX_THREAD_ID","CURSOR_TRACE_ID","AIDER_MODEL"];function Ce(){if(process.env.SOOTSIM_AGENT==="0")return!1;for(let o of Mt){let c=process.env[o];if(c&&c.trim()&&c!=="0")return!0}return!1}async function Be(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 () => {
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 () => {
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 () => {
@@ -28,16 +28,16 @@ import{a as U}from"./chunk-K6YUSCAC.js";import{a as Ne,b as _e}from"./chunk-LOV7
28
28
  })()`):v?(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
- })()`):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(De(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(De(JSON.stringify(x,null,2)," "))}else console.log(JSON.stringify(q,null,2))}}function De(o,c){return o.split(`
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(`
32
32
  `).map(i=>c+i).join(`
33
- `)}async function Le(o,c={}){let i=await o.send({type:"evaluate",code:`(() => {
33
+ `)}async function je(o,c={}){let i=await o.send({type:"evaluate",code:`(() => {
34
34
  const kb = window.__sootsimKeyboard
35
35
  if (!kb || typeof kb.getLayout !== 'function') {
36
36
  return { error: 'keyboard bridge getLayout() not available' }
37
37
  }
38
38
  return kb.getLayout()
39
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(`
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}Ae(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 Je(o,c={args:[]}){let d=await o.send({type:"evaluate",code:`(async () => {
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
43
43
  const hostMem = performance.memory
@@ -70,7 +70,7 @@ import{a as U}from"./chunk-K6YUSCAC.js";import{a as Ne,b as _e}from"./chunk-LOV7
70
70
  ? resolved.cy
71
71
  : n.absolutePosition.y + (n.layout.height || 0) / 2
72
72
  return { x: cx, y: cy, testID: n.testID, text: n.text }
73
- })()`})??null}async function He(o,c={}){let i=await o.send({type:"evaluate",code:`(async () => {
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
76
  const navSnap =
@@ -144,7 +144,7 @@ import{a as U}from"./chunk-K6YUSCAC.js";import{a as Ne,b as _e}from"./chunk-LOV7
144
144
  await sleep(pollMs)
145
145
  }
146
146
  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 qe(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 We(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 ze(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 Ke(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 Ue(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 Ye(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 Ge(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 () => {
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 () => {
148
148
  const t = window.__sootsimTest
149
149
  let nodes = 0
150
150
  try { nodes = (await t?.getNodeCount?.()) || 0 } catch {}
@@ -153,7 +153,7 @@ import{a as U}from"./chunk-K6YUSCAC.js";import{a as Ne,b as _e}from"./chunk-LOV7
153
153
  at: (window).__sootsimExternalAppReadyAt || 0,
154
154
  nodes,
155
155
  }
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 Xe(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 () => {
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 () => {
157
157
  const start = Date.now()
158
158
  const deadline = start + ${k}
159
159
  const t = window.__sootsimTest
@@ -172,8 +172,8 @@ import{a as U}from"./chunk-K6YUSCAC.js";import{a as Ne,b as _e}from"./chunk-LOV7
172
172
  await new Promise((r) => setTimeout(r, 80))
173
173
  }
174
174
  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 st(o){return o==null?"\u2014":o<1024?`${o}B`:o<1024*1024?`${(o/1024).toFixed(1)}K`:`${(o/1024/1024).toFixed(1)}M`}function nt(o){return o==null?" \u2026":o<1e3?`${o}ms`.padStart(5):`${(o/1e3).toFixed(2)}s`.padStart(5)}function _t(o){return o.error?"err":o.status==null?" \u2026 ":String(o.status)}function Ve(o){let c=new Date(o.startTs).toLocaleTimeString(),i=_t(o).padEnd(3),d=o.method.padEnd(5),u=st(o.size).padStart(6),a=nt(o.durationMs);console.log(` [${c}] ${i} ${d} ${u} ${a} ${o.displayUrl}`),o.error&&console.log(` error: ${o.error}`)}function It(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",nt(o.durationMs).trim()],["size",st(o.size)],["content-type",o.type??"\u2014"]];for(let[i,d]of c)console.log(` ${i.padEnd(13)} ${d}`)}var Ft={error:"\x1B[31m",warn:"\x1B[33m",info:"\x1B[36m",debug:"\x1B[35m",log:"\x1B[37m"},Ze="\x1B[0m",At="\x1B[2m";function Qe(o,c){let i=new Date(o.ts).toLocaleTimeString(),d=o.level.toUpperCase().padEnd(5),u=o.args.join(" ");if(c){let a=Ft[o.level];console.log(` ${At}[${i}]${Ze} ${a}${d}${Ze} ${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",Pt=120;async function et(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 () => {
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
177
  const kb = window.__sootsimKeyboard
178
178
  const test = window.__sootsimTest
179
179
  if (!kb) return { error: 'keyboard bridge not available' }
@@ -205,7 +205,7 @@ import{a as U}from"./chunk-K6YUSCAC.js";import{a as Ne,b as _e}from"./chunk-LOV7
205
205
  frame: runtimeSnapshot?.keyboard?.frame ?? null,
206
206
  focusedRect: runtimeSnapshot?.focused?.rect ?? null,
207
207
  }
208
- })()`})}async function Ot(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 tt(o,c,i){return c==="appearance"?o.send({type:"evaluate",code:`(async () => {
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 () => {
209
209
  const requested = ${JSON.stringify(i??"toggle")}
210
210
  const rootBg = (document.documentElement?.style?.background || '').toLowerCase()
211
211
  const inferredCurrent = rootBg.includes('33') ? 'dark' : 'light'
@@ -220,15 +220,15 @@ import{a as U}from"./chunk-K6YUSCAC.js";import{a as Ne,b as _e}from"./chunk-LOV7
220
220
  })()`}):o.send({type:"evaluate",code:`(async () => {
221
221
  window.dispatchEvent(new CustomEvent(${JSON.stringify(c==="lock"?"sootsim:toggleLock":"sootsim:shake")}))
222
222
  return { ok: true, action: ${JSON.stringify(c)} }
223
- })()`})}function Et(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 Rt(o){if(typeof o!="string")return null;let c=o.replace(/\s+/g," ").trim();return c?c.slice(0,80):null}function rt(...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 Ct(o,c,i){if(!i||i.hit===!1)return null;let d=rt(i.responderTestID,i.testID);if(d)return{step:{tapOn:{id:d}},summary:`tap #${d}`};let u=Rt(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 ot(o,c,i){let d=rt(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 ss(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}
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}
224
224
  `),process.exit(0))}if(I==="shell"){let r=pe("shell",e);r&&(console.log(`${r}
225
225
  `),process.exit(0))}let t=pe("inspect",e),s=["do","get","debug","wait"].map(r=>me(r,e)).filter(r=>r!=null).join(`
226
226
 
227
227
  `);console.log(`${t??""}
228
228
 
229
229
  ${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-EXUREU4B.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=Ce()?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.
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.
232
232
  `)}catch{}}async function Z(){try{return await l.send({type:"evaluate",code:`(() => ({
233
233
  console: window.__sootsimConsole?.count?.() || null,
234
234
  requests: window.__sootsimTest?.getRequestCounts?.() || null,
@@ -238,7 +238,7 @@ ${s}
238
238
  `);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
239
  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
240
  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 ze({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 () => {
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 () => {
242
242
  const t = window.__sootsimTest
243
243
  if (!t) return []
244
244
  const all = await t.queryAll({ pruneHidden: true })
@@ -267,7 +267,7 @@ ${s}
267
267
  size: n.layout ? { w: Math.round(n.layout.width), h: Math.round(n.layout.height) } : null,
268
268
  }))
269
269
  })()`});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 Be({bridge:l,args:o,effectiveArgs:d,positional:a,inspectUsage:S});break}case"count":{await Ee(l,{args:d});break}case"keyboard":{await Le(l,{json:o.includes("--json")});break}case"screens":{await He(l,{json:o.includes("--json")});break}case"memory":{await Je(l,{args:d});break}case"wait":{await Ue({wsPort:A,commandTimeoutMs:j,browserId:v,positional:a});break}case"sleep":{await We({positional:a,inspectUsage:S});break}case"settle":{await qe({bridge:l,args:o,positional:a});break}case"ready":{await Ge({bridge:l,args:o});break}case"idle":{await Ye({bridge:l,args:o,positional:a});break}case"selector":{await Xe({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 et(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 et(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 () => {
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 () => {
271
271
  const t = window.__sootsimTest
272
272
  const q = ${JSON.stringify(e)}
273
273
  let node = null
@@ -323,7 +323,7 @@ ${s}
323
323
  transform,
324
324
  parentChain,
325
325
  }
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=Ct(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 () => {
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 () => {
327
327
  const interact = window.__sootsimInteract
328
328
  if (!interact?.drag) return { ok: false, reason: 'no interact.drag' }
329
329
  const value = await interact.drag(${e}, ${t}, ${s}, ${r}, ${Math.max(1,Math.round(p))}, ${Math.max(0,Math.round(h))})
@@ -447,7 +447,7 @@ ${s}
447
447
  total,
448
448
  idx,
449
449
  }
450
- })()`});if(g?.error==="bridge-not-ready"&&(console.error(" sootsim test bridge not ready"),process.exit(1)),g?.ambiguous){let _=g.candidates;console.error(` ambiguous: ${g.total} matches for "${e}"`);for(let P of _){let re=P.abs?`@(${Math.round(P.abs.x)},${Math.round(P.abs.y)})`:"",at=P.layout?` ${P.layout.width}x${P.layout.height}`:"",it=P.testID?` #${P.testID}`:"",lt=P.text?` "${P.text}"`:"",ct=P.ancestorTestIDs.length>0?` within ${P.ancestorTestIDs.slice(0,3).map(dt=>`#${dt}`).join(" > ")}`:"";console.error(` [${P.idx}] <${P.type}>${lt}${it} ${re}${at}${ct}`)}g.total>_.length&&console.error(` ... and ${g.total-_.length} more`),console.error(" pick one:"),console.error(" --nth <index> pick the nth match (top-to-bottom, left-to-right; negatives from end)"),console.error(" --within <testID> narrow to descendants of a node"),console.error(" --min-y / --max-y geometric filter (pixels, absolute)"),console.error(" --min-x / --max-x geometric filter (pixels, absolute)"),console.error(" --near <x> <y> pick the closest match to a point"),console.error(" --exact exact text match (default is substring)"),console.error(" --role <role> narrow to accessibilityRole"),console.error(" --first keep the old pick-first-silently behavior"),process.exit(2)}g?.nthOutOfRange&&(console.error(` not found: nth ${g.nth} of ${g.total} match${g.total===1?"":"es"} for "${e}"`),process.exit(1)),(!g||typeof g.cx!="number")&&(console.error(` not found: ${e}`),process.exit(1));let T=await l.send({type:"tap",x:g.cx,y:g.cy});if(T?.hit!==!1&&T?.ok!==!1){let _=ot(e,{id:g.target?.id??null,testID:g.target?.testID??null,type:g.target?.type??null,cx:g.cx,cy:g.cy},"text");await L("inspect tap-text",_.step,_.summary)}console.log(JSON.stringify({matched:g.match,tapped:{nodeId:g.target?.nodeId??null,id:g.target?.id??null,testID:g.target?.testID??null,type:g.target?.type??null,cx:g.cx,cy:g.cy},...g.strategy&&g.strategy!=="matched-node"?{strategy:g.strategy}:{},...g.total>1||n!==null?{nth:{index:g.idx,total:g.total}}:{},result:T},null,2));break}case"tap-id":{let e=a[1];e||(console.error(S("tap-id","<id>")),process.exit(1));let t=JSON.stringify(e),s=await l.send({type:"evaluate",code:`(async () => {
450
+ })()`});if(g?.error==="bridge-not-ready"&&(console.error(" sootsim test bridge not ready"),process.exit(1)),g?.ambiguous){let _=g.candidates;console.error(` ambiguous: ${g.total} matches for "${e}"`);for(let P of _){let re=P.abs?`@(${Math.round(P.abs.x)},${Math.round(P.abs.y)})`:"",it=P.layout?` ${P.layout.width}x${P.layout.height}`:"",lt=P.testID?` #${P.testID}`:"",ct=P.text?` "${P.text}"`:"",dt=P.ancestorTestIDs.length>0?` within ${P.ancestorTestIDs.slice(0,3).map(ut=>`#${ut}`).join(" > ")}`:"";console.error(` [${P.idx}] <${P.type}>${ct}${lt} ${re}${it}${dt}`)}g.total>_.length&&console.error(` ... and ${g.total-_.length} more`),console.error(" pick one:"),console.error(" --nth <index> pick the nth match (top-to-bottom, left-to-right; negatives from end)"),console.error(" --within <testID> narrow to descendants of a node"),console.error(" --min-y / --max-y geometric filter (pixels, absolute)"),console.error(" --min-x / --max-x geometric filter (pixels, absolute)"),console.error(" --near <x> <y> pick the closest match to a point"),console.error(" --exact exact text match (default is substring)"),console.error(" --role <role> narrow to accessibilityRole"),console.error(" --first keep the old pick-first-silently behavior"),process.exit(2)}g?.nthOutOfRange&&(console.error(` not found: nth ${g.nth} of ${g.total} match${g.total===1?"":"es"} for "${e}"`),process.exit(1)),(!g||typeof g.cx!="number")&&(console.error(` not found: ${e}`),process.exit(1));let T=await l.send({type:"tap",x:g.cx,y:g.cy});if(T?.hit!==!1&&T?.ok!==!1){let _=st(e,{id:g.target?.id??null,testID:g.target?.testID??null,type:g.target?.type??null,cx:g.cx,cy:g.cy},"text");await L("inspect tap-text",_.step,_.summary)}console.log(JSON.stringify({matched:g.match,tapped:{nodeId:g.target?.nodeId??null,id:g.target?.id??null,testID:g.target?.testID??null,type:g.target?.type??null,cx:g.cx,cy:g.cy},...g.strategy&&g.strategy!=="matched-node"?{strategy:g.strategy}:{},...g.total>1||n!==null?{nth:{index:g.idx,total:g.total}}:{},result:T},null,2));break}case"tap-id":{let e=a[1];e||(console.error(S("tap-id","<id>")),process.exit(1));let t=JSON.stringify(e),s=await l.send({type:"evaluate",code:`(async () => {
451
451
  const t = window.__sootsimTest
452
452
  if (!t) return null
453
453
  const n = (await t.findByTestId(${t})) || (await t.findById(${t}))
@@ -482,7 +482,7 @@ ${s}
482
482
  },
483
483
  strategy: (resolved && resolved.strategy) || 'matched-node',
484
484
  }
485
- })()`});(!s||typeof s.cx!="number")&&(console.error(` not found: ${e}`),process.exit(1));let r=await l.send({type:"tap",x:s.cx,y:s.cy});if(r?.hit!==!1&&r?.ok!==!1){let n=ot(e,{id:s.target?.id??null,testID:s.target?.testID??null,type:s.target?.type??null,cx:s.cx,cy:s.cy},"id");await L("inspect tap-id",n.step,n.summary)}console.log(JSON.stringify({matched:s.match,tapped:{nodeId:s.target?.nodeId??null,id:s.target?.id??null,testID:s.target?.testID??null,type:s.target?.type??null,cx:s.cx,cy:s.cy},...s.strategy&&s.strategy!=="matched-node"?{strategy:s.strategy}:{},result:r},null,2));break}case"type-into":{let e=a[1],t=a.slice(2).join(" ");(!e||!t)&&(console.error(S("type-into","<id> <text>")),process.exit(1));let s=JSON.stringify(e),r=await l.send({type:"evaluate",code:`(async () => {
485
+ })()`});(!s||typeof s.cx!="number")&&(console.error(` not found: ${e}`),process.exit(1));let r=await l.send({type:"tap",x:s.cx,y:s.cy});if(r?.hit!==!1&&r?.ok!==!1){let n=st(e,{id:s.target?.id??null,testID:s.target?.testID??null,type:s.target?.type??null,cx:s.cx,cy:s.cy},"id");await L("inspect tap-id",n.step,n.summary)}console.log(JSON.stringify({matched:s.match,tapped:{nodeId:s.target?.nodeId??null,id:s.target?.id??null,testID:s.target?.testID??null,type:s.target?.type??null,cx:s.cx,cy:s.cy},...s.strategy&&s.strategy!=="matched-node"?{strategy:s.strategy}:{},result:r},null,2));break}case"type-into":{let e=a[1],t=a.slice(2).join(" ");(!e||!t)&&(console.error(S("type-into","<id> <text>")),process.exit(1));let s=JSON.stringify(e),r=await l.send({type:"evaluate",code:`(async () => {
486
486
  const t = window.__sootsimTest
487
487
  if (!t) return null
488
488
  const n = await (t.findByTestId(${s}) || t.findById(${s}))
@@ -494,7 +494,7 @@ ${s}
494
494
  isTextInput: !!n.isTextInput,
495
495
  placeholder: n.placeholder || null,
496
496
  }
497
- })()`});(!r||typeof r.cx!="number")&&(console.error(` not found: ${e}`),process.exit(1)),r.isTextInput||console.error(` warning: ${e} is not a text input (isTextInput: false)`);let n=await l.send({type:"tap",x:r.cx,y:r.cy}),m=await Ot(l);m.visible||(console.error(` keyboard did not open after tapping ${e}`),process.exit(1));let p=m.focusedInput;p&&(p.testID===e||p.id===e||(console.error(` focus routing mismatch after tap: requested ${JSON.stringify(e)} but focus is on ${JSON.stringify(p.testID??p.id??null)}. did the tap land on an outer Pressable wrapper?`),process.exit(1))),await l.send({type:"keyboard",action:"type",text:t}),await L("inspect type-into",{tapOn:{id:e},inputText:t},`type-into #${e} ${JSON.stringify(t)}`),console.log(JSON.stringify({target:e,isTextInput:r.isTextInput,keyboardOpened:m.visible??n?.keyboardOpened??!1,focusedInput:m.focusedInput??null,typed:t},null,2));break}case"type":{let e=a.slice(1).join(" ");e||(console.error(S("type","<text>")),process.exit(1)),await ue(l,"type"),await l.send({type:"keyboard",action:"type",text:e}),await L("inspect type",{inputText:e},`type ${JSON.stringify(e)}`),console.log(` typed: ${JSON.stringify(e)}`);break}case"key":{let e=a[1];e||(console.error(S("key","<name>")),process.exit(1)),await ue(l,"key"),await l.send({type:"keyboard",action:"press",text:e}),await L("inspect key",{pressKey:e},`key ${e}`),console.log(` pressed: ${e}`);break}case"key-sequence":{let e=a.slice(1);e.length===0&&(console.error(S("key-sequence","<key> [<key> ...]")),process.exit(1)),await ue(l,"key-sequence");for(let t of e)await l.send({type:"keyboard",action:"press",text:t});await L("inspect key-sequence",{pressKey:e.join(" ")},`key-sequence ${e.join(" ")}`),console.log(` pressed: ${e.join(", ")}`);break}case"keycode":{let e=a.slice(1);e.length===0&&(console.error(S("keycode","<code> [<code> ...]")),process.exit(1));let t=e.map(r=>({code:r,key:Et(r)})),s=t.filter(r=>!r.key);s.length>0&&(console.error(` unsupported keycode(s): ${s.map(r=>r.code).join(", ")}`),process.exit(1)),await ue(l,"keycode");for(let r of t)await l.send({type:"keyboard",action:"press",text:r.key});await L("inspect keycode",{pressKey:t.map(r=>r.key).join(" ")},`keycode ${e.join(" ")}`),console.log(` pressed: ${e.join(", ")}`);break}case"dispatch":{let e=a[1];e||(console.error(S("dispatch","<char>")),process.exit(1)),await l.send({type:"keyboard",action:"dispatchKey",text:e}),await L("inspect dispatch",{dispatchKey:e},`dispatch ${JSON.stringify(e)}`),console.log(` dispatched: ${e}`);break}case"dismiss":{await l.send({type:"keyboard",action:"dismiss"}),await L("inspect dismiss",{hideKeyboard:!0},"dismiss keyboard"),console.log(" keyboard dismissed");break}case"double-tap":{let e=Number(a[1]),t=Number(a[2]),s=se(o);if(s){let p=await ce(l,s);p||(console.error(` not found: ${s.value}`),s.mode==="testid"&&U("wait-selector-for-missing-testid",s.value),process.exit(1)),e=p.x,t=p.y}let r=a[3]?Number(a[3]):80;(!Number.isFinite(e)||!Number.isFinite(t)||!Number.isFinite(r))&&(console.error(S("double-tap","<x> <y> [gapMs] | --testid <id>")),process.exit(1));let n=Math.max(0,Math.round(r)),m=await l.send({type:"evaluate",code:`(async () => {
497
+ })()`});(!r||typeof r.cx!="number")&&(console.error(` not found: ${e}`),process.exit(1)),r.isTextInput||console.error(` warning: ${e} is not a text input (isTextInput: false)`);let n=await l.send({type:"tap",x:r.cx,y:r.cy}),m=await Et(l);m.visible||(console.error(` keyboard did not open after tapping ${e}`),process.exit(1));let p=m.focusedInput;p&&(p.testID===e||p.id===e||(console.error(` focus routing mismatch after tap: requested ${JSON.stringify(e)} but focus is on ${JSON.stringify(p.testID??p.id??null)}. did the tap land on an outer Pressable wrapper?`),process.exit(1))),await l.send({type:"keyboard",action:"type",text:t}),await L("inspect type-into",{tapOn:{id:e},inputText:t},`type-into #${e} ${JSON.stringify(t)}`),console.log(JSON.stringify({target:e,isTextInput:r.isTextInput,keyboardOpened:m.visible??n?.keyboardOpened??!1,focusedInput:m.focusedInput??null,typed:t},null,2));break}case"type":{let e=a.slice(1).join(" ");e||(console.error(S("type","<text>")),process.exit(1)),await ue(l,"type"),await l.send({type:"keyboard",action:"type",text:e}),await L("inspect type",{inputText:e},`type ${JSON.stringify(e)}`),console.log(` typed: ${JSON.stringify(e)}`);break}case"key":{let e=a[1];e||(console.error(S("key","<name>")),process.exit(1)),await ue(l,"key"),await l.send({type:"keyboard",action:"press",text:e}),await L("inspect key",{pressKey:e},`key ${e}`),console.log(` pressed: ${e}`);break}case"key-sequence":{let e=a.slice(1);e.length===0&&(console.error(S("key-sequence","<key> [<key> ...]")),process.exit(1)),await ue(l,"key-sequence");for(let t of e)await l.send({type:"keyboard",action:"press",text:t});await L("inspect key-sequence",{pressKey:e.join(" ")},`key-sequence ${e.join(" ")}`),console.log(` pressed: ${e.join(", ")}`);break}case"keycode":{let e=a.slice(1);e.length===0&&(console.error(S("keycode","<code> [<code> ...]")),process.exit(1));let t=e.map(r=>({code:r,key:Rt(r)})),s=t.filter(r=>!r.key);s.length>0&&(console.error(` unsupported keycode(s): ${s.map(r=>r.code).join(", ")}`),process.exit(1)),await ue(l,"keycode");for(let r of t)await l.send({type:"keyboard",action:"press",text:r.key});await L("inspect keycode",{pressKey:t.map(r=>r.key).join(" ")},`keycode ${e.join(" ")}`),console.log(` pressed: ${e.join(", ")}`);break}case"dispatch":{let e=a[1];e||(console.error(S("dispatch","<char>")),process.exit(1)),await l.send({type:"keyboard",action:"dispatchKey",text:e}),await L("inspect dispatch",{dispatchKey:e},`dispatch ${JSON.stringify(e)}`),console.log(` dispatched: ${e}`);break}case"dismiss":{await l.send({type:"keyboard",action:"dismiss"}),await L("inspect dismiss",{hideKeyboard:!0},"dismiss keyboard"),console.log(" keyboard dismissed");break}case"double-tap":{let e=Number(a[1]),t=Number(a[2]),s=se(o);if(s){let p=await ce(l,s);p||(console.error(` not found: ${s.value}`),s.mode==="testid"&&U("wait-selector-for-missing-testid",s.value),process.exit(1)),e=p.x,t=p.y}let r=a[3]?Number(a[3]):80;(!Number.isFinite(e)||!Number.isFinite(t)||!Number.isFinite(r))&&(console.error(S("double-tap","<x> <y> [gapMs] | --testid <id>")),process.exit(1));let n=Math.max(0,Math.round(r)),m=await l.send({type:"evaluate",code:`(async () => {
498
498
  const interact = window.__sootsimInteract
499
499
  if (interact?.doubleTap) {
500
500
  return {
@@ -632,7 +632,7 @@ ${s}
632
632
  ${y("shell")} open-card clock 800
633
633
  ${y("shell")} appearance dark
634
634
  ${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(Pt),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 tt(l,"appearance",f);n=!!w?.ok,p={appearance:w}}else if(e==="lock"||e==="shake"){let f=await tt(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 Ke(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:`;(() => {
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:`;(() => {
636
636
  const reloadExternalApp = window.SootSim?.bridges?.hotRemount?.reloadExternalApp
637
637
  if (typeof reloadExternalApp === 'function') {
638
638
  reloadExternalApp()
@@ -681,7 +681,7 @@ ${s}
681
681
 
682
682
  return globals
683
683
  })()`});console.log(` sootsim JS API:
684
- `);for(let[t,s]of Object.entries(e)){console.log(` ${t}:`);for(let r of s)console.log(` .${r}`);console.log("")}console.log(` use: ${y("js")} <expression>`),console.log(` example: ${y("js")} test.findByText("Sign in")`);break}case"describe":{await Re({bridge:l,args:o,positional:a});break}case"perf":{let e=a[1];if(!e||e==="--help"||e==="-h"){console.log(`
684
+ `);for(let[t,s]of Object.entries(e)){console.log(` ${t}:`);for(let r of s)console.log(` .${r}`);console.log("")}console.log(` use: ${y("js")} <expression>`),console.log(` example: ${y("js")} test.findByText("Sign in")`);break}case"describe":{await Ce({bridge:l,args:o,positional:a});break}case"perf":{let e=a[1];if(!e||e==="--help"||e==="-h"){console.log(`
685
685
  ${y("perf")} \u2014 performance profiling
686
686
 
687
687
  subcommands:
@@ -1015,16 +1015,16 @@ ${s}
1015
1015
  const obs = window.__sootsimObservability;
1016
1016
  if (!obs) return null;
1017
1017
  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)):It(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:`(() => {
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:`(() => {
1019
1019
  const obs = window.__sootsimObservability;
1020
1020
  if (!obs) return { ok: false };
1021
1021
  return { ok: true, entries: obs.network.getSnapshot() };
1022
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):
1023
- `);for(let F of M)Ve(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)):Ve(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:`(() => {
1023
+ `);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:`(() => {
1025
1025
  const obs = window.__sootsimObservability;
1026
1026
  if (!obs) return { ok: false };
1027
1027
  return { ok: true, entries: obs.logs.getSnapshot() };
1028
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):
1029
- `);for(let _ of T)Qe(_,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(_)):Qe(_,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){console.error(` ${b??"inspect"} failed: ${e.message}`);try{await Me(l)}catch{}try{await J({includeTail:!0})}catch{}try{await x({includeTail:!0})}catch{}process.exit(1)}finally{l.close()}}export{ss as runInspect};
1029
+ `);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};
@@ -1,5 +1,5 @@
1
- /*! sootsim v0.0.2 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
- import{a as j,b as P}from"./chunk-RJUBGX5M.js";import{c as b}from"./chunk-NXWCDGWS.js";import"./chunk-EIZCWDRE.js";import"./chunk-CXTA5VGA.js";import"./chunk-K7LDP7JL.js";import{execSync as V}from"child_process";import{existsSync as w,readFileSync as C,writeFileSync as x}from"fs";import{relative as A,resolve as u}from"path";import{existsSync as a,readFileSync as d,readdirSync as O,statSync as L}from"fs";import{basename as R,dirname as T,join as c}from"path";function S(e){let n=e;for(;;){if(a(c(n,"turbo.json"))||a(c(n,"nx.json"))||a(c(n,"lerna.json"))||a(c(n,"pnpm-workspace.yaml")))return n;let s=c(n,"package.json");if(a(s))try{if(JSON.parse(d(s,"utf8")).workspaces)return n}catch{}let i=T(n);if(i===n)break;n=i}return e}function W(e){return a(c(e,"bun.lock"))||a(c(e,"bun.lockb"))?"bun":a(c(e,"pnpm-lock.yaml"))?"pnpm":a(c(e,"yarn.lock"))?"yarn":"npm"}function _(e){if(a(c(e,"turbo.json")))return"turbo";if(a(c(e,"nx.json")))return"nx";if(a(c(e,"pnpm-workspace.yaml")))return"pnpm";let n=c(e,"package.json");if(a(n))try{if(JSON.parse(d(n,"utf8")).workspaces)return"npm-workspaces"}catch{}return"single"}function J(e){return e.one?"one":e.expo?"expo":e["react-native"]?"bare":"unknown"}function y(e){let n=c(e,"package.json");if(!a(n))return null;let s;try{s=JSON.parse(d(n,"utf8"))}catch{return null}let i={...s.dependencies,...s.devDependencies},r=J(i);return r==="unknown"?null:{dir:e,name:s.name||R(e),framework:r,hasViteConfig:a(c(e,"vite.config.ts"))||a(c(e,"vite.config.js")),hasMetroConfig:a(c(e,"metro.config.js"))||a(c(e,"metro.config.ts")),hasSootsimDependency:!!i.sootsim,devCommand:s.scripts?.dev||null}}function N(e){let n=[],s=c(e,"pnpm-workspace.yaml");if(a(s)){let o=d(s,"utf8").match(/packages:\s*\n((?:\s+-\s+.+\n?)+)/);if(o){let t=o[1].split(`
1
+ /*! sootsim v0.0.4 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
+ import{a as j,b as P}from"./chunk-6SZMLFCR.js";import{d as b}from"./chunk-HAKR72LJ.js";import"./chunk-C3QLIYCS.js";import"./chunk-W7CYWXRZ.js";import"./chunk-MZPAJ5PQ.js";import"./chunk-WRF43M33.js";import"./chunk-WWDJCKMI.js";import{execSync as V}from"child_process";import{existsSync as w,readFileSync as C,writeFileSync as x}from"fs";import{relative as A,resolve as u}from"path";import{existsSync as a,readFileSync as d,readdirSync as O,statSync as L}from"fs";import{basename as R,dirname as T,join as c}from"path";function S(e){let n=e;for(;;){if(a(c(n,"turbo.json"))||a(c(n,"nx.json"))||a(c(n,"lerna.json"))||a(c(n,"pnpm-workspace.yaml")))return n;let s=c(n,"package.json");if(a(s))try{if(JSON.parse(d(s,"utf8")).workspaces)return n}catch{}let i=T(n);if(i===n)break;n=i}return e}function W(e){return a(c(e,"bun.lock"))||a(c(e,"bun.lockb"))?"bun":a(c(e,"pnpm-lock.yaml"))?"pnpm":a(c(e,"yarn.lock"))?"yarn":"npm"}function _(e){if(a(c(e,"turbo.json")))return"turbo";if(a(c(e,"nx.json")))return"nx";if(a(c(e,"pnpm-workspace.yaml")))return"pnpm";let n=c(e,"package.json");if(a(n))try{if(JSON.parse(d(n,"utf8")).workspaces)return"npm-workspaces"}catch{}return"single"}function J(e){return e.one?"one":e.expo?"expo":e["react-native"]?"bare":"unknown"}function y(e){let n=c(e,"package.json");if(!a(n))return null;let s;try{s=JSON.parse(d(n,"utf8"))}catch{return null}let i={...s.dependencies,...s.devDependencies},r=J(i);return r==="unknown"?null:{dir:e,name:s.name||R(e),framework:r,hasViteConfig:a(c(e,"vite.config.ts"))||a(c(e,"vite.config.js")),hasMetroConfig:a(c(e,"metro.config.js"))||a(c(e,"metro.config.ts")),hasSootsimDependency:!!i.sootsim,devCommand:s.scripts?.dev||null}}function N(e){let n=[],s=c(e,"pnpm-workspace.yaml");if(a(s)){let o=d(s,"utf8").match(/packages:\s*\n((?:\s+-\s+.+\n?)+)/);if(o){let t=o[1].split(`
3
3
  `).filter(Boolean);for(let g of t){let l=g.replace(/^\s*-\s*['"]?/,"").replace(/['"]?\s*$/,"");l&&n.push(...v(e,l))}}return n}let i=c(e,"package.json");if(a(i))try{let r=JSON.parse(d(i,"utf8")),o=Array.isArray(r.workspaces)?r.workspaces:r.workspaces?.packages||[];for(let t of o)n.push(...v(e,t))}catch{}return n}function v(e,n){let s=n.replace(/\/\*\*?$/,"").replace(/\*$/,""),i=c(e,s);if(!a(i))return[];try{return O(i).map(o=>c(i,o)).filter(o=>{try{return L(o).isDirectory()&&a(c(o,"package.json"))}catch{return!1}})}catch{return[]}}function D(e){let n=_(e),s=W(e);if(n==="single"){let t=y(e);return{root:e,type:n,packageManager:s,apps:t?[t]:[]}}let i=N(e),r=[],o=y(e);o&&r.push(o);for(let t of i){if(t===e)continue;let g=y(t);g&&r.push(g)}return{root:e,type:n,packageManager:s,apps:r}}function M(e){switch(e){case"bun":return"bun add -d sootsim";case"pnpm":return"pnpm add -D sootsim";case"yarn":return"yarn add -D sootsim";case"npm":return"npm install -D sootsim"}}async function re(e){(e.includes("--help")||e.includes("-h"))&&(console.log(`
4
4
  sootsim install \u2014 set up sootsim in your project
5
5
 
@@ -1,5 +1,5 @@
1
- /*! sootsim v0.0.2 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
- import{a as x}from"./chunk-RJUBGX5M.js";import{a as $}from"./chunk-B5R4K2DG.js";import"./chunk-K7LDP7JL.js";import{spawn as v,spawnSync as u}from"child_process";import{chmodSync as k,createWriteStream as S,existsSync as f,mkdirSync as y,renameSync as P,rmSync as w,statSync as T}from"fs";import{tmpdir as E}from"os";import{dirname as D,join as m,resolve as b}from"path";var h="https://sootbean.com/api/electron-release";function M(){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:I}}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:B}}return null}async function A({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 e=s.headers.get("content-length"),l=e?Number(e):null;if(!s.body)throw new Error("download failed: empty response body");y(D(o),{recursive:!0});let i=S(o),d=s.body.getReader(),a=0;try{for(;;){let{done:t,value:c}=await d.read();if(t)break;i.write(Buffer.from(c)),a+=c.byteLength,n?.(a,l)}}finally{await new Promise((t,c)=>{i.end(p=>p?c(p):t())})}}function O(r,o){let n=(r/1048576).toFixed(1);if(!o)return` ${n} MB`;let s=Math.min(100,Math.round(r/o*100)),e=(o/(1024*1024)).toFixed(1),l=24,i=Math.round(s/100*l);return` ${"\u2588".repeat(i)+"\u2591".repeat(l-i)} ${s}% ${n} / ${e} MB`}async function I(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(`
1
+ /*! sootsim v0.0.4 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
+ import{a as x}from"./chunk-6SZMLFCR.js";import{a as $}from"./chunk-SY74J6F4.js";import"./chunk-WWDJCKMI.js";import{spawn as v,spawnSync as u}from"child_process";import{chmodSync as k,createWriteStream as S,existsSync as f,mkdirSync as y,renameSync as P,rmSync as w,statSync as T}from"fs";import{tmpdir as E}from"os";import{dirname as D,join as m,resolve as b}from"path";var h="https://sootbean.com/api/electron-release";function M(){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:I}}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:B}}return null}async function A({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 e=s.headers.get("content-length"),l=e?Number(e):null;if(!s.body)throw new Error("download failed: empty response body");y(D(o),{recursive:!0});let i=S(o),d=s.body.getReader(),a=0;try{for(;;){let{done:t,value:c}=await d.read();if(t)break;i.write(Buffer.from(c)),a+=c.byteLength,n?.(a,l)}}finally{await new Promise((t,c)=>{i.end(p=>p?c(p):t())})}}function O(r,o){let n=(r/1048576).toFixed(1);if(!o)return` ${n} MB`;let s=Math.min(100,Math.round(r/o*100)),e=(o/(1024*1024)).toFixed(1),l=24,i=Math.round(s/100*l);return` ${"\u2588".repeat(i)+"\u2591".repeat(l-i)} ${s}% ${n} / ${e} MB`}async function I(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
3
  `),e=n[n.length-1].split(" ").pop()?.trim();if(!e||!f(e))throw new Error(`could not determine dmg mount point (output: ${o.stdout})`);let l=m(e,"sootsim.app");if(!f(l))throw u("hdiutil",["detach","-force",e]),new Error(`sootsim.app not found inside ${e}`);let i="/Applications",d=b(process.env.HOME||"","Applications"),a=i;try{let g=m(i,`.sootsim-write-probe-${process.pid}`);u("touch",[g]),f(g)?w(g,{force:!0}):a=d}catch{a=d}a===d&&y(a,{recursive:!0});let t=m(a,"sootsim.app");f(t)&&w(t,{recursive:!0,force:!0});let c=u("cp",["-R",l,t]),p=u("hdiutil",["detach","-force",e]);if(c.status!==0)throw new Error(`copy to ${t} failed: ${c.stderr?.toString()||""}`.trim());return p.status!==0&&console.warn(` warning: failed to unmount ${e} (${p.stderr?.toString().trim()||"unknown error"})`),u("xattr",["-dr","com.apple.quarantine",t]),t}async function L(r){let o=b(process.env.HOME||"","Applications");y(o,{recursive:!0});let n=m(o,"sootsim.AppImage");return f(n)&&w(n,{force:!0}),P(r,n),k(n,493),n}async function B(r){return await new Promise((o,n)=>{let s=v("cmd",["/c","start",'""',"/wait",r],{stdio:"inherit"});s.once("error",n),s.once("exit",e=>{e===0?o():n(new Error(`installer exited with code ${e}`))})}),r}async function _(r){(r.includes("--help")||r.includes("-h"))&&(console.log(`
4
4
  sootsim install-desktop \u2014 download and install the optional desktop GUI
5
5
 
@@ -1,5 +1,5 @@
1
- /*! sootsim v0.0.2 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
- import{a as b}from"./chunk-RJUBGX5M.js";import"./chunk-K7LDP7JL.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.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"?>
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.2 | (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-CZZB4DWG.js";import{d as c}from"./chunk-NE62JSI6.js";import"./chunk-K7LDP7JL.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.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(`
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.2 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
- import"./chunk-XKDQEYTE.js";import{o as s,p as a,t as c,u as r,v as l}from"./chunk-CXTA5VGA.js";import{b as m}from"./chunk-YVSZHVLU.js";import{a as u}from"./chunk-B5R4K2DG.js";import"./chunk-K7LDP7JL.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.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(`
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-JTLZYEXK.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-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};
@@ -1,5 +1,5 @@
1
- /*! sootsim v0.0.2 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
- import{b as g,d as f}from"./chunk-NE62JSI6.js";import"./chunk-K7LDP7JL.js";import{exec as S}from"node:child_process";import{randomBytes as v}from"node:crypto";import w from"node:http";var I=process.env.SOOTSIM_AUTH_ORIGIN||"https://sootbean.com",m="http://localhost:3000";async function $(e){if(e)return e;if(process.env.SOOTSIM_AUTH_ORIGIN)return process.env.SOOTSIM_AUTH_ORIGIN;if(process.env.SOOTSIM_UPLOAD_ORIGIN)return process.env.SOOTSIM_UPLOAD_ORIGIN;try{if((await fetch(`${m}/api/auth/me`)).ok)return m}catch{}return I}function x(){console.log(`
1
+ /*! sootsim v0.0.4 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
+ import{b as g,d as f}from"./chunk-UKYK63H6.js";import"./chunk-WWDJCKMI.js";import{exec as S}from"node:child_process";import{randomBytes as v}from"node:crypto";import w from"node:http";var I=process.env.SOOTSIM_AUTH_ORIGIN||"https://sootbean.com",m="http://localhost:3000";async function $(e){if(e)return e;if(process.env.SOOTSIM_AUTH_ORIGIN)return process.env.SOOTSIM_AUTH_ORIGIN;if(process.env.SOOTSIM_UPLOAD_ORIGIN)return process.env.SOOTSIM_UPLOAD_ORIGIN;try{if((await fetch(`${m}/api/auth/me`)).ok)return m}catch{}return I}function x(){console.log(`
3
3
  sootsim login \u2014 sign in so desktop uploads can attach to your account
4
4
 
5
5
  usage:
@@ -1,2 +1,2 @@
1
- /*! sootsim v0.0.2 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
- import{a as e,c as t}from"./chunk-NE62JSI6.js";import"./chunk-K7LDP7JL.js";async function r(){let o=e();if(!o?.token){console.log(" not signed in");return}try{await fetch(`${o.origin.replace(/\/$/,"")}/api/auth/sign-out`,{method:"POST",headers:{authorization:`Bearer ${o.token}`}})}catch{}t(),console.log(" signed out")}export{r as runLogout};
1
+ /*! sootsim v0.0.4 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
+ import{a as e,c as t}from"./chunk-UKYK63H6.js";import"./chunk-WWDJCKMI.js";async function r(){let o=e();if(!o?.token){console.log(" not signed in");return}try{await fetch(`${o.origin.replace(/\/$/,"")}/api/auth/sign-out`,{method:"POST",headers:{authorization:`Bearer ${o.token}`}})}catch{}t(),console.log(" signed out")}export{r as runLogout};
@@ -1,5 +1,5 @@
1
- /*! sootsim v0.0.2 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
- import{c as h}from"./chunk-4372UQHZ.js";import"./chunk-EWEKADK4.js";import"./chunk-GQUOQNTP.js";import"./chunk-5C5I5OFM.js";import"./chunk-4GWEO5CL.js";import"./chunk-NHA3G6A3.js";import"./chunk-TSZBQS6W.js";import"./chunk-CZZB4DWG.js";import"./chunk-NE62JSI6.js";import"./chunk-ET3NNZAR.js";import"./chunk-HBNVKYSC.js";import"./chunk-ISAMAM3I.js";import"./chunk-EWMYTXM2.js";import"./chunk-6IPY24VM.js";import"./chunk-AS4V7TZU.js";import"./chunk-TGDP3D3V.js";import"./chunk-LXCFGKL2.js";import"./chunk-3HBBSRLE.js";import"./chunk-FUQ4XA6I.js";import"./chunk-XXUAOYYT.js";import"./chunk-EIZCWDRE.js";import"./chunk-CXTA5VGA.js";import"./chunk-YVSZHVLU.js";import"./chunk-B5R4K2DG.js";import"./chunk-K7LDP7JL.js";import*as i from"fs";import*as l from"path";var w=[".maestro","maestro"];function v(){console.log(`
1
+ /*! sootsim v0.0.4 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
+ import{c as h}from"./chunk-MQDPKSCK.js";import"./chunk-QIP7LYQI.js";import"./chunk-UNFERMZ3.js";import"./chunk-DQKQYPIG.js";import"./chunk-ZKNI5MRD.js";import"./chunk-QQOBLF7O.js";import"./chunk-W3TYN64D.js";import"./chunk-AUR2LTNX.js";import"./chunk-UKYK63H6.js";import"./chunk-4XBPZQLW.js";import"./chunk-XJF46GU2.js";import"./chunk-EHMSE3Q3.js";import"./chunk-I6XGFZPA.js";import"./chunk-47S5DXXX.js";import"./chunk-OAHMYSMD.js";import"./chunk-5TTQKPGH.js";import"./chunk-WVBPATRA.js";import"./chunk-HGFIS26A.js";import"./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*as i from"fs";import*as l from"path";var w=[".maestro","maestro"];function v(){console.log(`
3
3
  sootsim maestro \u2014 run maestro YAML flows against sootsim (drop-in)
4
4
 
5
5
  usage:
@@ -1,5 +1,5 @@
1
- /*! sootsim v0.0.2 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
- import"./chunk-K7LDP7JL.js";import{resolve as c,dirname as m}from"path";import{fileURLToPath as a}from"url";var t=m(a(import.meta.resolve("sootsim-engine/package.json")));async function g(o,r){(o.includes("--help")||o.includes("-h"))&&(console.log(`
1
+ /*! sootsim v0.0.4 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
+ import"./chunk-WWDJCKMI.js";import{resolve as c,dirname as m}from"path";import{fileURLToPath as a}from"url";var t=m(a(import.meta.resolve("sootsim-engine/package.json")));async function g(o,r){(o.includes("--help")||o.includes("-h"))&&(console.log(`
3
3
  sootsim preview \u2014 production-like preview
4
4
 
5
5
  usage:
@@ -1,5 +1,5 @@
1
- /*! sootsim v0.0.2 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
- import{c as I,e as N,i as S}from"./chunk-FUQ4XA6I.js";import"./chunk-XXUAOYYT.js";import"./chunk-EIZCWDRE.js";import"./chunk-CXTA5VGA.js";import"./chunk-K7LDP7JL.js";import{createWriteStream as v,mkdirSync as k,writeFileSync as w}from"fs";import{dirname as T,resolve as x}from"path";import{Readable as y}from"stream";import{pipeline as C}from"stream/promises";import{createGzip as F}from"zlib";async function E(r,m){if(r.includes("--help")||r.includes("-h"))return console.log(`
1
+ /*! sootsim v0.0.4 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
+ import{c as I,e as N,i as S}from"./chunk-C3QLIYCS.js";import"./chunk-W7CYWXRZ.js";import"./chunk-MZPAJ5PQ.js";import"./chunk-WRF43M33.js";import"./chunk-WWDJCKMI.js";import{createWriteStream as v,mkdirSync as k,writeFileSync as w}from"fs";import{dirname as T,resolve as x}from"path";import{Readable as y}from"stream";import{pipeline as C}from"stream/promises";import{createGzip as F}from"zlib";async function E(r,m){if(r.includes("--help")||r.includes("-h"))return console.log(`
3
3
  sootsim profile \u2014 capture a sampled CPU trace from the tenant worker
4
4
 
5
5
  usage:
@@ -1,5 +1,5 @@
1
- /*! sootsim v0.0.2 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
- import{a as z}from"./chunk-GQUOQNTP.js";import"./chunk-CZZB4DWG.js";import"./chunk-NE62JSI6.js";import{a as C}from"./chunk-LXCFGKL2.js";import{c as R,e as $}from"./chunk-FUQ4XA6I.js";import{c as W}from"./chunk-XXUAOYYT.js";import"./chunk-EIZCWDRE.js";import"./chunk-CXTA5VGA.js";import"./chunk-K7LDP7JL.js";import{existsSync as Z,mkdirSync as _,readFileSync as ee,rmSync as L,writeFileSync as U}from"fs";import{tmpdir as oe}from"os";import{dirname as T,extname as re,join as te,resolve as O}from"path";var D=6e4;async function ve(e,r){if((e.includes("--help")||e.includes("-h"))&&(console.log(`
1
+ /*! sootsim v0.0.4 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
+ import{a as z}from"./chunk-UNFERMZ3.js";import"./chunk-AUR2LTNX.js";import"./chunk-UKYK63H6.js";import{a as C}from"./chunk-WVBPATRA.js";import{c as R,e as $}from"./chunk-C3QLIYCS.js";import{c as W}from"./chunk-W7CYWXRZ.js";import"./chunk-MZPAJ5PQ.js";import"./chunk-WRF43M33.js";import"./chunk-WWDJCKMI.js";import{existsSync as Z,mkdirSync as _,readFileSync as ee,rmSync as L,writeFileSync as U}from"fs";import{tmpdir as oe}from"os";import{dirname as T,extname as re,join as te,resolve as O}from"path";var D=6e4;async function ve(e,r){if((e.includes("--help")||e.includes("-h"))&&(console.log(`
3
3
  sootsim record \u2014 capture the running session
4
4
 
5
5
  usage:
@@ -1,5 +1,5 @@
1
- /*! sootsim v0.0.2 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
- import{a as k}from"./chunk-FUQ4XA6I.js";import"./chunk-XXUAOYYT.js";import"./chunk-EIZCWDRE.js";import{h as v,l as S,o as p,p as d,q as R,r as w}from"./chunk-CXTA5VGA.js";import"./chunk-K7LDP7JL.js";import{spawn as T}from"child_process";import N from"crypto";import i from"fs";import g from"path";import{Readable as A}from"stream";import{pipeline as C}from"stream/promises";import{WebSocket as M}from"ws";var O="https://sootbean.com",j="SOOTSIM_CDN_ORIGIN";function y(){let e=process.env[j];return e&&e.length>0?e.replace(/\/+$/,""):O}function P(){return`${y()}/runtimes/manifest.json`}function _(e){return`${y()}/runtimes/sootsim-runtime-${e}.tar.gz`}async function se(e,n={}){let[s,...t]=e;if(!s||s==="--help"||s==="-h"){I();return}switch(s){case"install":return E(t,n);case"list":case"ls":return U(t);case"use":return W(t);case"remove":case"rm":return L(t);case"which":case"active":return V();default:console.error(` unknown runtime subcommand: ${s}`),I(),process.exit(1)}}function I(){console.log(`
1
+ /*! sootsim v0.0.4 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
+ import{a as k}from"./chunk-C3QLIYCS.js";import"./chunk-W7CYWXRZ.js";import"./chunk-MZPAJ5PQ.js";import{h as v,l as S,o as p,p as d,q as R,r as w}from"./chunk-WRF43M33.js";import"./chunk-WWDJCKMI.js";import{spawn as T}from"child_process";import N from"crypto";import i from"fs";import g from"path";import{Readable as A}from"stream";import{pipeline as C}from"stream/promises";import{WebSocket as M}from"ws";var O="https://sootbean.com",P="SOOTSIM_CDN_ORIGIN";function y(){let e=process.env[P];return e&&e.length>0?e.replace(/\/+$/,""):O}function j(){let e=new URL(`${y()}/runtimes/manifest.json`);return e.searchParams.set("t",String(Date.now())),e.toString()}function _(e){return`${y()}/runtimes/sootsim-runtime-${e}.tar.gz`}async function se(e,n={}){let[s,...t]=e;if(!s||s==="--help"||s==="-h"){I();return}switch(s){case"install":return E(t,n);case"list":case"ls":return U(t);case"use":return L(t);case"remove":case"rm":return W(t);case"which":case"active":return V();default:console.error(` unknown runtime subcommand: ${s}`),I(),process.exit(1)}}function I(){console.log(`
3
3
  sootsim runtime \u2014 manage engine runtimes under ~/.sootsim/runtimes/
4
4
 
5
5
  usage:
@@ -22,4 +22,4 @@ examples:
22
22
  sootsim runtime install 1.2.3
23
23
  sootsim runtime install --channel beta
24
24
  sootsim runtime use 1.2.3
25
- `)}async function E(e,n){let{version:s,flags:t}=z(e),o=t.channel??n.channel??"stable",a=t.force===!0,f=t.setActive!==!1;p(),console.log("sootsim runtime install"),console.log(` cdn: ${y()}`);let l=await D(),m=s||l.channels[o]?.latest;m||(console.error(` no version specified and channel '${o}' has no latest entry in the manifest`),process.exit(1));let r=m,u=l.versions[r];u||(console.error(` version ${r} not found in manifest`),console.error(` available: ${Object.keys(l.versions).slice(-10).join(", ")||"(none)"}`),process.exit(1)),console.log(` version: ${r} (channel: ${o})`);let c=v(r);if(!a&&i.existsSync(g.join(c,"index.html"))){console.log(` already installed at ${c}`),f&&await $(r);return}let b=u.tarball||_(r),h=g.join(S(),`sootsim-runtime-${r}.tar.gz`);console.log(` fetch: ${b}`),await G(b,h),console.log(" verify: sha256");let x=await H(h);x!==u.sha256&&(i.rmSync(h,{force:!0}),console.error(" sha256 mismatch"),console.error(` expected: ${u.sha256}`),console.error(` actual: ${x}`),process.exit(1)),console.log(` extract: ${c}`),i.rmSync(c,{recursive:!0,force:!0}),i.mkdirSync(c,{recursive:!0}),await q(h,c),i.existsSync(g.join(c,"index.html"))||(console.error(" extracted tarball is missing index.html \u2014 corrupted runtime"),process.exit(1)),console.log(` installed ${r}`),f&&await $(r)}async function $(e){R(e),console.log(` active: ${e}`),await F(e)||console.log(` (no daemon running \u2014 next sootsim/electron launch will pick up ${e})`)}async function F(e){let{isDaemonLockfileFresh:n,readDaemonLockfile:s}=await import("./home-paths-BNRMUBJA.js"),t=s();if(!n(t))return!1;let o=k();return new Promise(a=>{let f=!1,l=!1,m=c=>{f||(f=!0,a(c))},r=new M(`ws://127.0.0.1:${o}`,{handshakeTimeout:800}),u=setTimeout(()=>{try{r.close()}catch{}m(l)},1500);r.on("open",()=>{try{r.send(JSON.stringify({type:"runtime:use",version:e,id:0})),l=!0}catch{}setTimeout(()=>{try{r.close()}catch{}},100)}),r.on("close",()=>{clearTimeout(u),m(l)}),r.on("error",()=>{clearTimeout(u),m(!1)})})}async function U(e){p();let n=w(),s=d();if(console.log("installed:"),n.length===0)console.log(" (none)");else for(let t of n)console.log(` ${t===s?"*":" "} ${t}`);try{let t=await D();console.log("available (latest per channel):");for(let[o,a]of Object.entries(t.channels))console.log(` ${o.padEnd(8)} ${a.latest}`)}catch(t){console.log(`available: (could not fetch manifest: ${B(t)})`)}}async function W(e){let n=e[0];n||(console.error(" usage: sootsim runtime use <version>"),process.exit(1));let s=w();s.includes(n)||(console.error(` version ${n} is not installed`),console.error(` installed: ${s.join(", ")||"(none)"}`),console.error(` run \`sootsim runtime install ${n}\` first`),process.exit(1)),await $(n)}async function L(e){let n=e[0];n||(console.error(" usage: sootsim runtime remove <version>"),process.exit(1)),d()===n&&(console.error(` cannot remove active runtime ${n}`),console.error(" switch with `sootsim runtime use <other>` first, or install another version"),process.exit(1));let t=v(n);if(!i.existsSync(t)){console.error(` ${n} is not installed`);return}i.rmSync(t,{recursive:!0,force:!0}),console.log(` removed ${n}`)}async function V(){let e=d();if(!e){console.log(" no active runtime");return}console.log(e)}function z(e){let n={},s=[];for(let t=0;t<e.length;t++){let o=e[t];if(o==="--channel"&&t+1<e.length){n.channel=e[t+1],t++;continue}if(o.startsWith("--channel=")){n.channel=o.slice(10);continue}if(o==="--force"){n.force=!0;continue}if(o==="--set-active=false"||o==="--no-set-active"){n.setActive=!1;continue}s.push(o)}return{version:s[0]??null,flags:n}}async function D(){let e=P(),n=await fetch(e,{headers:{Accept:"application/json"}});if(!n.ok)throw new Error(`manifest fetch failed: ${n.status} ${n.statusText} (${e})`);return await n.json()}async function G(e,n){let s=await fetch(e);if(!s.ok||!s.body)throw new Error(`download failed: ${s.status} ${s.statusText} (${e})`);i.mkdirSync(g.dirname(n),{recursive:!0});let t=`${n}.partial`;try{await C(A.fromWeb(s.body),i.createWriteStream(t)),i.renameSync(t,n)}catch(o){try{i.unlinkSync(t)}catch{}throw o}}function H(e){return new Promise((n,s)=>{let t=N.createHash("sha256"),o=i.createReadStream(e);o.on("data",a=>t.update(a)),o.on("error",s),o.on("end",()=>n(t.digest("hex")))})}function q(e,n){return new Promise((s,t)=>{let o=T("tar",["-xzf",e,"-C",n],{stdio:["ignore","inherit","inherit"]});o.on("error",t),o.on("exit",a=>{a===0?s():t(new Error(`tar exited with code ${a}`))})})}function B(e){return e instanceof Error?e.message:String(e)}export{se as runRuntime};
25
+ `)}async function E(e,n){let{version:s,flags:t}=z(e),o=t.channel??n.channel??"stable",a=t.force===!0,f=t.setActive!==!1;p(),console.log("sootsim runtime install"),console.log(` cdn: ${y()}`);let l=await D(),m=s||l.channels[o]?.latest;m||(console.error(` no version specified and channel '${o}' has no latest entry in the manifest`),process.exit(1));let r=m,u=l.versions[r];u||(console.error(` version ${r} not found in manifest`),console.error(` available: ${Object.keys(l.versions).slice(-10).join(", ")||"(none)"}`),process.exit(1)),console.log(` version: ${r} (channel: ${o})`);let c=v(r);if(!a&&i.existsSync(g.join(c,"index.html"))){console.log(` already installed at ${c}`),f&&await $(r);return}let b=u.tarball||_(r),h=g.join(S(),`sootsim-runtime-${r}.tar.gz`);console.log(` fetch: ${b}`),await G(b,h),console.log(" verify: sha256");let x=await H(h);x!==u.sha256&&(i.rmSync(h,{force:!0}),console.error(" sha256 mismatch"),console.error(` expected: ${u.sha256}`),console.error(` actual: ${x}`),process.exit(1)),console.log(` extract: ${c}`),i.rmSync(c,{recursive:!0,force:!0}),i.mkdirSync(c,{recursive:!0}),await q(h,c),i.existsSync(g.join(c,"index.html"))||(console.error(" extracted tarball is missing index.html \u2014 corrupted runtime"),process.exit(1)),console.log(` installed ${r}`),f&&await $(r)}async function $(e){R(e),console.log(` active: ${e}`),await F(e)||console.log(` (no daemon running \u2014 next sootsim/electron launch will pick up ${e})`)}async function F(e){let{isDaemonLockfileFresh:n,readDaemonLockfile:s}=await import("./home-paths-4YJJYGR6.js"),t=s();if(!n(t))return!1;let o=k();return new Promise(a=>{let f=!1,l=!1,m=c=>{f||(f=!0,a(c))},r=new M(`ws://127.0.0.1:${o}`,{handshakeTimeout:800}),u=setTimeout(()=>{try{r.close()}catch{}m(l)},1500);r.on("open",()=>{try{r.send(JSON.stringify({type:"runtime:use",version:e,id:0})),l=!0}catch{}setTimeout(()=>{try{r.close()}catch{}},100)}),r.on("close",()=>{clearTimeout(u),m(l)}),r.on("error",()=>{clearTimeout(u),m(!1)})})}async function U(e){p();let n=w(),s=d();if(console.log("installed:"),n.length===0)console.log(" (none)");else for(let t of n)console.log(` ${t===s?"*":" "} ${t}`);try{let t=await D();console.log("available (latest per channel):");for(let[o,a]of Object.entries(t.channels))console.log(` ${o.padEnd(8)} ${a.latest}`)}catch(t){console.log(`available: (could not fetch manifest: ${B(t)})`)}}async function L(e){let n=e[0];n||(console.error(" usage: sootsim runtime use <version>"),process.exit(1));let s=w();s.includes(n)||(console.error(` version ${n} is not installed`),console.error(` installed: ${s.join(", ")||"(none)"}`),console.error(` run \`sootsim runtime install ${n}\` first`),process.exit(1)),await $(n)}async function W(e){let n=e[0];n||(console.error(" usage: sootsim runtime remove <version>"),process.exit(1)),d()===n&&(console.error(` cannot remove active runtime ${n}`),console.error(" switch with `sootsim runtime use <other>` first, or install another version"),process.exit(1));let t=v(n);if(!i.existsSync(t)){console.error(` ${n} is not installed`);return}i.rmSync(t,{recursive:!0,force:!0}),console.log(` removed ${n}`)}async function V(){let e=d();if(!e){console.log(" no active runtime");return}console.log(e)}function z(e){let n={},s=[];for(let t=0;t<e.length;t++){let o=e[t];if(o==="--channel"&&t+1<e.length){n.channel=e[t+1],t++;continue}if(o.startsWith("--channel=")){n.channel=o.slice(10);continue}if(o==="--force"){n.force=!0;continue}if(o==="--set-active=false"||o==="--no-set-active"){n.setActive=!1;continue}s.push(o)}return{version:s[0]??null,flags:n}}async function D(){let e=j(),n=await fetch(e,{headers:{Accept:"application/json"}});if(!n.ok)throw new Error(`manifest fetch failed: ${n.status} ${n.statusText} (${e})`);return await n.json()}async function G(e,n){let s=await fetch(e);if(!s.ok||!s.body)throw new Error(`download failed: ${s.status} ${s.statusText} (${e})`);i.mkdirSync(g.dirname(n),{recursive:!0});let t=`${n}.partial`;try{await C(A.fromWeb(s.body),i.createWriteStream(t)),i.renameSync(t,n)}catch(o){try{i.unlinkSync(t)}catch{}throw o}}function H(e){return new Promise((n,s)=>{let t=N.createHash("sha256"),o=i.createReadStream(e);o.on("data",a=>t.update(a)),o.on("error",s),o.on("end",()=>n(t.digest("hex")))})}function q(e,n){return new Promise((s,t)=>{let o=T("tar",["-xzf",e,"-C",n],{stdio:["ignore","inherit","inherit"]});o.on("error",t),o.on("exit",a=>{a===0?s():t(new Error(`tar exited with code ${a}`))})})}function B(e){return e instanceof Error?e.message:String(e)}export{se as runRuntime};
@@ -1,5 +1,5 @@
1
- /*! sootsim v0.0.2 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
- import{a as v}from"./chunk-5C5I5OFM.js";import"./chunk-4GWEO5CL.js";import"./chunk-ET3NNZAR.js";import"./chunk-HBNVKYSC.js";import{f}from"./chunk-ISAMAM3I.js";import{a as x}from"./chunk-LOV766MI.js";import{c as h,d as g,e as w,h as y}from"./chunk-FUQ4XA6I.js";import"./chunk-XXUAOYYT.js";import"./chunk-EIZCWDRE.js";import"./chunk-CXTA5VGA.js";import"./chunk-K7LDP7JL.js";import{mkdirSync as _,writeFileSync as S}from"fs";import{dirname as R,resolve as B}from"path";async function V(e,t){(e.includes("--help")||e.includes("-h"))&&(console.log(`
1
+ /*! sootsim v0.0.4 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
+ import{a as v}from"./chunk-DQKQYPIG.js";import"./chunk-ZKNI5MRD.js";import"./chunk-4XBPZQLW.js";import"./chunk-XJF46GU2.js";import{f}from"./chunk-EHMSE3Q3.js";import{a as x}from"./chunk-AFQBSK2J.js";import{c as h,d as g,e as w,h as y}from"./chunk-C3QLIYCS.js";import"./chunk-W7CYWXRZ.js";import"./chunk-MZPAJ5PQ.js";import"./chunk-WRF43M33.js";import"./chunk-WWDJCKMI.js";import{mkdirSync as _,writeFileSync as S}from"fs";import{dirname as R,resolve as B}from"path";async function V(e,t){(e.includes("--help")||e.includes("-h"))&&(console.log(`
3
3
  sootsim screenshot \u2014 capture the canvas as a PNG
4
4
 
5
5
  usage: