sootsim 0.1.209 → 0.1.211
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.
- package/README.md +10 -9
- package/dist-cli/bin.js +4 -4
- package/dist-cli/chunks/{agent-KEC5PILM.js → agent-YMWIMQSZ.js} +2 -2
- package/dist-cli/chunks/{agent-wrapper-PVXYV2Z5.js → agent-wrapper-6MN4L5WR.js} +2 -2
- package/dist-cli/chunks/{app-fonts-ANPET46E.js → app-fonts-C7OF7H5G.js} +2 -2
- package/dist-cli/chunks/{assert-TIABJI4M.js → assert-JVVKDGJZ.js} +2 -2
- package/dist-cli/chunks/{auth-R7PMD6TZ.js → auth-K5PLXC65.js} +2 -2
- package/dist-cli/chunks/beta-FFPVM735.js +2 -0
- package/dist-cli/chunks/{camera-7UFJSFK7.js → camera-LN5T6FHN.js} +2 -2
- package/dist-cli/chunks/chunk-2OE3UXXF.js +119 -0
- package/dist-cli/chunks/{chunk-2OT4F6F2.js → chunk-33FTN3AV.js} +3 -3
- package/dist-cli/chunks/{chunk-OVT65DWK.js → chunk-3AMN64TG.js} +1 -1
- package/dist-cli/chunks/{chunk-RGRLM7AT.js → chunk-4L4WXCMZ.js} +2 -2
- package/dist-cli/chunks/{chunk-5MEH5VHS.js → chunk-75ZI44EE.js} +4 -4
- package/dist-cli/chunks/{chunk-CXBNEQNP.js → chunk-ADHPC2X3.js} +2 -2
- package/dist-cli/chunks/{chunk-GGRLGKFC.js → chunk-AQXWKFSQ.js} +1 -1
- package/dist-cli/chunks/{chunk-QYOLP7E2.js → chunk-AVJOEZLW.js} +2 -2
- package/dist-cli/chunks/chunk-BVOMJLZJ.js +1 -0
- package/dist-cli/chunks/chunk-CA53GTDU.js +2 -0
- package/dist-cli/chunks/{chunk-JXOQBX5R.js → chunk-CDMWW44J.js} +2 -2
- package/dist-cli/chunks/{chunk-GGPPDEWU.js → chunk-CNMIJNUJ.js} +2 -2
- package/dist-cli/chunks/chunk-CZJWXULV.js +13 -0
- package/dist-cli/chunks/{chunk-IE3M7UCB.js → chunk-E2HECQS5.js} +48 -48
- package/dist-cli/chunks/{chunk-2N7YUIB6.js → chunk-E2TCQ5AD.js} +1 -1
- package/dist-cli/chunks/{chunk-DNAKPQ56.js → chunk-FLQJ4E4B.js} +2 -2
- package/dist-cli/chunks/{chunk-VUTSNH77.js → chunk-FUUQJQ6D.js} +1 -1
- package/dist-cli/chunks/{chunk-VCUGCWFW.js → chunk-GDIUF4LO.js} +2 -2
- package/dist-cli/chunks/{chunk-Y2YT6G2K.js → chunk-GIPNU35K.js} +2 -2
- package/dist-cli/chunks/{chunk-H7I4QQBU.js → chunk-HYCIJ46S.js} +1 -1
- package/dist-cli/chunks/{chunk-3MSLDFKZ.js → chunk-IHQXMMQA.js} +2 -2
- package/dist-cli/chunks/{chunk-KUFSYYKY.js → chunk-KDCFEKQG.js} +1 -1
- package/dist-cli/chunks/{chunk-CNHZWLE3.js → chunk-KKOQCQ7C.js} +1 -1
- package/dist-cli/chunks/{chunk-44EPIO7S.js → chunk-LN2YBE53.js} +3 -3
- package/dist-cli/chunks/{chunk-IUG5LGAH.js → chunk-MRVFOA46.js} +2 -2
- package/dist-cli/chunks/{chunk-JUBCRVXK.js → chunk-NLHBFC44.js} +8 -8
- package/dist-cli/chunks/{chunk-VHUEJNYT.js → chunk-OEVW6X6O.js} +1 -1
- package/dist-cli/chunks/{chunk-UQX3RDUO.js → chunk-OJXQDTQP.js} +1 -1
- package/dist-cli/chunks/{chunk-4N2A7WPD.js → chunk-OYKIZT5Q.js} +1 -1
- package/dist-cli/chunks/{chunk-7XXN43QW.js → chunk-PC3RU3SN.js} +1 -1
- package/dist-cli/chunks/{chunk-56YCENXG.js → chunk-RCNPJNHG.js} +1 -1
- package/dist-cli/chunks/{chunk-TCIUR5IB.js → chunk-RNCB3OP2.js} +2 -2
- package/dist-cli/chunks/{chunk-IELT7YPL.js → chunk-SSYQZ5IN.js} +2 -2
- package/dist-cli/chunks/{chunk-EYISIVUC.js → chunk-T3L3I3XN.js} +2 -2
- package/dist-cli/chunks/{chunk-YC4E3DRA.js → chunk-TBBKY5QW.js} +2 -2
- package/dist-cli/chunks/{chunk-W2SLUPGS.js → chunk-TYJ7RKBZ.js} +1 -1
- package/dist-cli/chunks/{chunk-5HAEGTT5.js → chunk-U74PRAD5.js} +2 -2
- package/dist-cli/chunks/{chunk-JOFHXMRG.js → chunk-UMBVQZ22.js} +2 -2
- package/dist-cli/chunks/{chunk-YB7GMFBR.js → chunk-UXJC5TWI.js} +1 -1
- package/dist-cli/chunks/{chunk-IEDKCUPC.js → chunk-VDLNYLQ3.js} +1 -1
- package/dist-cli/chunks/chunk-X5F2XRCT.js +1 -0
- package/dist-cli/chunks/{chunk-L23EEIDG.js → chunk-XNJNWR34.js} +2 -2
- package/dist-cli/chunks/cli-version-6ZGU3OMS.js +2 -0
- package/dist-cli/chunks/{compat-MR7RNAP6.js → compat-FHMWPGR4.js} +3 -3
- package/dist-cli/chunks/{config-MMRF4WYY.js → config-OKQY5P52.js} +2 -2
- package/dist-cli/chunks/{control-ULQKJBAD.js → control-7WL54I6D.js} +2 -2
- package/dist-cli/chunks/daemon-MJAW7WLB.js +2 -0
- package/dist-cli/chunks/{debug-QRTBFTZC.js → debug-QWZHZQPU.js} +3 -3
- package/dist-cli/chunks/{desktop-WTUZLOEG.js → desktop-FXGRW74A.js} +3 -3
- package/dist-cli/chunks/{detox-I4NFW53N.js → detox-3EDUFJTL.js} +4 -4
- package/dist-cli/chunks/{device-UL3V6W3S.js → device-QCRIH4UL.js} +2 -2
- package/dist-cli/chunks/{diagnose-63E4BQXG.js → diagnose-URCT4GRE.js} +2 -2
- package/dist-cli/chunks/drivers-K6AYJ4K4.js +2 -0
- package/dist-cli/chunks/flow-FJK6CFCI.js +2 -0
- package/dist-cli/chunks/help-GCSPMIWH.js +2 -0
- package/dist-cli/chunks/{home-paths-U6VSF2D3.js → home-paths-EO6LWXWX.js} +2 -2
- package/dist-cli/chunks/inspect-DLPOHI65.js +2 -0
- package/dist-cli/chunks/install-desktop-LKSETTBL.js +2 -0
- package/dist-cli/chunks/{login-4Y32SP3B.js → login-7NUQAWXS.js} +4 -4
- package/dist-cli/chunks/{logout-HRGK2TLN.js → logout-BH53ZI7B.js} +2 -2
- package/dist-cli/chunks/{maestro-UOOWOSMW.js → maestro-C3RK43L7.js} +17 -11
- package/dist-cli/chunks/maestro-generate-NJBAT2VF.js +34 -0
- package/dist-cli/chunks/{mode-6PO2NWNV.js → mode-2LMGYLFI.js} +2 -2
- package/dist-cli/chunks/optional-demo-registry-A27PORZB.js +2 -0
- package/dist-cli/chunks/{perf-6ZGFXV7T.js → perf-LA7ZSQ7P.js} +2 -2
- package/dist-cli/chunks/{record-IIVWF5QW.js → record-3RNPPFI5.js} +3 -3
- package/dist-cli/chunks/runtime-7VEUKPNE.js +2 -0
- package/dist-cli/chunks/{screenshot-command-JLSF5QJO.js → screenshot-command-KIWXTT6Q.js} +6 -6
- package/dist-cli/chunks/{screenshots-capture-GW4YS6YN.js → screenshots-capture-ZADO3BSL.js} +2 -2
- package/dist-cli/chunks/{serve-ZINIYVBO.js → serve-64IOEG4C.js} +2 -2
- package/dist-cli/chunks/{setup-T4TUKR5N.js → setup-GANEERC5.js} +3 -3
- package/dist-cli/chunks/{skills-VMVA5KMV.js → skills-DYN4EKIN.js} +2 -2
- package/dist-cli/chunks/{storage-2I3TEBEI.js → storage-773UY5XZ.js} +2 -2
- package/dist-cli/chunks/store-LSC33DBI.js +2 -0
- package/dist-cli/chunks/telemetry-4DVRYGKH.js +2 -0
- package/dist-cli/chunks/{timeline-DSZIKBSD.js → timeline-HLF3CJNH.js} +2 -2
- package/dist-cli/chunks/upgrade-RDAUF53R.js +4 -0
- package/dist-cli/chunks/upload-KI23CKE4.js +2 -0
- package/dist-cli/chunks/{version-HNDOSSV6.js → version-63PZYMY6.js} +2 -2
- package/dist-cli/chunks/{web-YFMICNP2.js → web-XN5ZVSZR.js} +2 -2
- package/dist-cli/chunks/{what-happened-RJNSVNUE.js → what-happened-T3WJ7LTW.js} +2 -2
- package/dist-lib/agent-daemon-client.cjs +1 -1
- package/dist-lib/agent-events.cjs +1 -1
- package/dist-lib/agent-identity.cjs +1 -1
- package/dist-lib/agent-sessions.cjs +1 -1
- package/dist-lib/attached-projects.cjs +1 -1
- package/dist-lib/auth/shared-session.cjs +1 -1
- package/dist-lib/backend-origin.cjs +1 -1
- package/dist-lib/beta.cjs +1 -1
- package/dist-lib/beta.mjs +1 -1
- package/dist-lib/bridge-constants.cjs +1 -1
- package/dist-lib/cli-constants.cjs +1 -1
- package/dist-lib/config.cjs +1 -1
- package/dist-lib/detox/index.cjs +1 -1
- package/dist-lib/dev-bundle-resolution.cjs +1 -1
- package/dist-lib/home-paths.cjs +1 -1
- package/dist-lib/host/bridge-host.cjs +1 -1
- package/dist-lib/host/fetch-proxy-handler.cjs +1 -1
- package/dist-lib/host/fetch-proxy-overrides.cjs +1 -1
- package/dist-lib/host/fetch-proxy-overrides.mjs +1 -1
- package/dist-lib/host/websocket-proxy.cjs +1 -1
- package/dist-lib/index.cjs +1 -1
- package/dist-lib/jump-to-source-babel.cjs +1 -1
- package/dist-lib/menu.cjs +1 -1
- package/dist-lib/menu.mjs +1 -1
- package/dist-lib/metro.cjs +1 -1
- package/dist-lib/profiles.cjs +1 -1
- package/dist-lib/render-mode.cjs +1 -1
- package/dist-lib/scripts/dev-server-scanner.cjs +1 -1
- package/dist-lib/sdk.cjs +1 -1
- package/dist-lib/sdk.mjs +1 -1
- package/dist-lib/skills.cjs +108 -108
- package/dist-lib/vite.cjs +1 -1
- package/package.json +1 -1
- package/skills/soot/SKILL.md +5 -7
- package/skills/sootsim-debug/SKILL.md +1 -1
- package/skills/sootsim-perf/SKILL.md +1 -1
- package/skills/sootsim-test/SKILL.md +36 -40
- package/src/skills/builtin/{test-flow.ts → maestro-test.ts} +6 -6
- package/src/skills/registry.ts +3 -3
- package/dist-cli/chunks/beta-FFASIXKH.js +0 -2
- package/dist-cli/chunks/chunk-2PGB3DOK.js +0 -119
- package/dist-cli/chunks/chunk-3RVUM7UI.js +0 -1
- package/dist-cli/chunks/chunk-CYDWIYRJ.js +0 -1
- package/dist-cli/chunks/chunk-OL7X4HKV.js +0 -2
- package/dist-cli/chunks/chunk-S73LN4A3.js +0 -13
- package/dist-cli/chunks/cli-version-VMYLWAMI.js +0 -2
- package/dist-cli/chunks/daemon-KLIQUGQB.js +0 -2
- package/dist-cli/chunks/drivers-FSTNEQAE.js +0 -2
- package/dist-cli/chunks/flow-JHQNIALS.js +0 -2
- package/dist-cli/chunks/help-S7U65PPA.js +0 -2
- package/dist-cli/chunks/inspect-Z4GQNIWJ.js +0 -2
- package/dist-cli/chunks/install-desktop-AEDLWUK6.js +0 -2
- package/dist-cli/chunks/optional-demo-registry-RVVVXHLS.js +0 -2
- package/dist-cli/chunks/runtime-CQCSXHC2.js +0 -2
- package/dist-cli/chunks/store-IAFN6XPI.js +0 -2
- package/dist-cli/chunks/telemetry-G2XJWKVX.js +0 -2
- package/dist-cli/chunks/test-PR7EPXIP.js +0 -69
- package/dist-cli/chunks/upgrade-EM7AEJCX.js +0 -4
- package/dist-cli/chunks/upload-BU5GF2ZF.js +0 -2
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
/*! sootsim v0.1.209 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
|
|
2
|
-
var m={"--help":{type:"boolean",short:"-h"},"--version":{type:"boolean",short:"-V"},"--verbose":{type:"boolean",short:"-v"},"--port":{type:"number",short:"-p"},"--device":{type:"string",short:"-d"},"--theme":{type:"string",short:"-t"},"--headless":{type:"boolean"},"--driver":{type:"string"},"--sim":{type:"string"},"--session":{type:"string"},"--tab":{type:"string"}},p=new Set(["list","describe","find","get","do","wait","network","logs","shell"]),b=new Set(["do","get","wait","shell","debug"]),d=new Set(["test","detox","maestro","flow","record","storage","perf","screenshot","mode","inspect","debug","timeline","what-happened","shell","assert","device","open","list","use","claim","close","compat","desktop","login","logout","auth","setup","serve","daemon","runtime","upgrade","version","skill","config","app-fonts","agent-wrapper","agent",...p]);function h(c){let r=c.slice(2),e={command:null,commandArgs:[],globalFlags:{},help:!1,version:!1,verbose:!1},s=0;for(;s<r.length;){let o=r[s];if(o==="--"){e.commandArgs.push(...r.slice(s+1));break}let i=Object.entries(m).find(([l,t])=>l===o||t.short===o);if(i){let[l,t]=i,a=l.replace(/^--/,"");if(t.type==="boolean")e.globalFlags[a]=!0,s++;else{let n=r[s+1];if(n===void 0||n.startsWith("-")){console.error(` warning: ${o} requires a value`),s++;continue}if(t.type==="number"){let g=Number(n);if(Number.isNaN(g)){console.error(` warning: ${o} requires a number, got "${n}"`),s+=2;continue}e.globalFlags[a]=g}else e.globalFlags[a]=n;s+=2}continue}if(!e.command&&!o.startsWith("-")){let l=o.indexOf("-");if(l>0){let t=o.slice(0,l),a=o.slice(l+1);if(b.has(t)&&a.length>0){e.command=t;let n=r.slice(s+1);e.commandArgs=[a,...n[0]==="--"?n.slice(1):n];break}}if(d.has(o)){e.command=o;let t=r.slice(s+1);e.commandArgs=t[0]==="--"?t.slice(1):t;break}e.commandArgs=r.slice(s);break}e.commandArgs.push(o),s++}return e.help=!!e.globalFlags.help,e.version=!!e.globalFlags.version,e.verbose=!!e.globalFlags.verbose,e}export{p as a,h as b};
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
/*! sootsim v0.1.209 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
|
|
2
|
-
import{a as j,b as oe,c as ne,d as xe,e as ke,g as Pe}from"./chunk-CXBNEQNP.js";import{a as Me,b as Te}from"./chunk-CNHZWLE3.js";import{a as Ce,b as re,c as Ee}from"./chunk-UQX3RDUO.js";import{m as R}from"./chunk-VCUGCWFW.js";import{m as Ue,o as Re}from"./chunk-IEDKCUPC.js";import{a as Oe,b as _e,c as se,e as Be,f as De,g as C,h as v,i as E}from"./chunk-YC4E3DRA.js";import{b as Ie,l as le}from"./chunk-TCIUR5IB.js";import{a as O,b as ie}from"./chunk-H7I4QQBU.js";import{d as ae}from"./chunk-56YCENXG.js";import{d as T,e as b,f as U}from"./chunk-2N7YUIB6.js";import{H as Se,M as ee,O as W,l as ve}from"./chunk-OVT65DWK.js";import{g as te,i as $e}from"./chunk-W2SLUPGS.js";import{spawn as je}from"node:child_process";import D from"node:fs";import ut from"node:os";import M from"node:path";import{WebSocket as pt}from"ws";function rt(e){return e.replace(/^\[|\]$/g,"").toLowerCase()}function K(e){let t=rt(e);return t==="localhost"||t.endsWith(".localhost")||t==="0.0.0.0"||t==="::1"||/^127(?:\.\d{1,3}){3}$/.test(t)}function Ae(e){return new Error(`could not resolve a native bundle for ${e}. pass an explicit bundle URL or open Connect and choose the app there.`)}function st(e,t){return e?.includes("/one/metro-entry.bundle")?"one":typeof t=="string"&&t?"expo":"unknown"}function Ne(e,t,o){return`${e}//${t}:${o}`}function it(e){if(typeof window>"u")return!1;try{let t=new URL(e);return K(t.hostname)&&K(window.location.hostname)&&t.origin!==window.location.origin}catch{return!1}}async function Le(e,t){let o={...t,cache:t?.cache??"no-store"};return it(e)?fetch(`/__fetch-proxy?url=${encodeURIComponent(e)}`,o):fetch(e,o)}function at(e){return e==="https:"?443:80}function lt(e){let t=e.pathname||"/";return(t==="/"||t==="")&&!e.search&&!e.hash}async function ct(e){try{let t=await fetch("/__server-scan",{cache:"no-store"});if(!t.ok||!(t.headers.get("content-type")||"").toLowerCase().includes("json"))return null;let o=await t.json();if(!Array.isArray(o))return null;let n=o.find(r=>!!r&&typeof r=="object"&&r.port===e&&typeof r.bundleUrl=="string");return n?{bundleUrl:ne(n.bundleUrl),port:e,framework:typeof n.framework=="string"?n.framework:"unknown",projectName:typeof n.projectName=="string"?n.projectName:void 0}:null}catch{return null}}async function Fe(e,t){let o=e.replace(/\/+$/,"");try{if(K(new URL(o).hostname)){let n=await ct(t);if(n)return n}}catch{}try{let n=await Le(`${o}/`,{headers:{"expo-platform":"ios"}});if(n.ok){let r=await n.json(),s=r?.extra?.expoClient||r?.extra||{},i=typeof r?.launchAsset?.url=="string"?r.launchAsset.url:void 0;if(i||s.name)return{bundleUrl:ne(i||`${o}${oe}`),port:t,framework:st(i,s.sdkVersion),projectName:s.name}}}catch{}try{let n=await Le(`${o}/status`);if(n.ok&&(await n.text()).includes("packager-status:running"))return{bundleUrl:`${o}${oe}`,port:t,framework:"metro"}}catch{}return null}async function dt(e){return Fe(Ne("http:","localhost",e),e)}async function He(e){let t=e.trim();if(/^\d+$/.test(t)){let a=parseInt(t,10),l=await dt(a);if(l)return l;throw Ae(`localhost:${a}`)}let o=t.startsWith("http")?t:`http://${t}`,n;try{n=new URL(o)}catch{throw new Error(`could not parse "${e}". pass a dev-server port, a dev-server base URL, or a full bundle URL.`)}let r=n.protocol||"http:",s=n.port?parseInt(n.port,10):at(r),i=Ne(r,n.hostname,s);if(lt(n)){let a=await Fe(i,s);if(a)return a;throw Ae(i)}return{bundleUrl:n.toString(),port:s,framework:"unknown"}}function ro(){console.error(" no sootsim desktop companion found."),console.error(""),console.error(" install the desktop app:"),console.error(" sootsim desktop install"),console.error(""),console.error(" or run setup to install the background daemon:"),console.error(" sootsim setup"),console.error("")}function We(e){let t=O();if(console.log(` note: no sootsim bridge detected on port ${e}`),t){console.log(" launch the installed companion with:"),console.log(" sootsim desktop");return}console.log(""),console.log(" run `sootsim setup` to install the background daemon,"),console.log(" or run `sootsim serve` in another shell for a foreground bridge.")}function mt(e){console.error(""),console.error(` no sim is connected to the sootsim bridge on port ${e}.`),console.error(""),console.error(" start your app dev server, then open it in sootsim:"),console.error(" npx expo start --localhost --port 8081"),console.error(" sootsim open 8081"),console.error(""),console.error(" then inspect the live app:"),console.error(" sootsim describe")}async function so(e,t,o){let n=[];try{n=await e.listSims()}catch{}if(console.error(""),n.length===0){mt(t);return}console.error(` no sim with id "${o}" is connected to the bridge on port ${t}.`),console.error(""),console.error(" connected sims:");for(let r of n){let s=[r.isPrimary?"primary":null,r.readyState,r.userVisible===!1?"hidden":r.userVisible===!0?"visible":null,r.userFocused?"focused":null].filter(Boolean).join(", ");console.error(` ${r.id} (${s})`)}console.error(""),console.error(" pass a valid --sim id, or run `sootsim list` to see all sessions.")}var ft=12e4,Ke=100,ht=5e3,ze=1e4,gt={rn:"/rn",connectrn:"/rn","connect-rn":"/rn",clock:"/app/clock","native-ui":"/app/native-ui",tamagui:"/app/tamagui",settings:"/app/settings",photos:"/app/photos",camera:"/app/camera"};function $(e){return new Promise(t=>setTimeout(t,e))}function qe(e){let t=process.env[e]?.trim();if(!t)return null;let o=Number(t);return Number.isInteger(o)&&o>0?o:null}function wt(){let e=qe("SOOTSIM_DRIVER_CONNECT_TIMEOUT_MS")??qe("SOOTSIM_PW_CONNECT_TIMEOUT_MS")??ft;return{timeoutMs:e,hostTimeoutMs:e+ht,intervalMs:Ke,attempts:Math.max(1,Math.ceil(e/Ke))}}function bt(e){return e==="chromium"||e==="electron"||e==="playwright"||e==="system"}function yt(e,t){return e.includes("--headless")?!0:e.includes("--headed")?!1:t==="playwright"&&process.platform==="linux"&&!process.env.DISPLAY&&!process.env.WAYLAND_DISPLAY?(console.error(" no display detected \u2192 running playwright headless (override with --headed)"),!0):!1}function G(e){return e.trim()}var Qe=/^[A-Za-z][A-Za-z0-9+.-]*:/;function vt(e){let t=e.trim();if(!t)throw new Error("expected <url-or-route>");return Qe.test(t)||t.startsWith("/")?t:`/${t}`}function St(e){return e!==null&&typeof e=="object"}function $t(e){let t=e.trim();return t?t.startsWith("/")?!0:Qe.test(t)?!/^https?:\/\//i.test(t):!1:!1}async function xt(e){if(await z(e,250))return e;let t=ee();if(t&&W(t)&&await z(t.bridgePort,500))return t.bridgePort;if(t&&W(t))throw new Error(`sootsim bridge lockfile is fresh (port ${t.bridgePort}) but the bridge is not reachable. run \`sootsim daemon restart\` or \`sootsim daemon uninstall\`.`);await kt();let o=It(["serve","--quiet","--port",String(e)]),n=null;o.once("exit",(s,i)=>{n=String(s??i??"unknown")}),o.unref();let r=Date.now()+ze;for(;Date.now()<r;){let s=ee();if(s&&W(s)&&await z(s.bridgePort,250))return console.error(` started local bridge on port ${s.bridgePort}; run \`sootsim setup\` to install the background daemon`),s.bridgePort;if(await z(e,250))return console.error(` started local bridge on port ${e}; run \`sootsim setup\` to install the background daemon`),e;if(n)throw new Error(`sootsim bridge exited before becoming ready (exit ${n})`);await $(150)}throw new Error(`sootsim bridge did not start within ${Math.round(ze/1e3)}s`)}async function kt(){let e=Se();if(e&&D.existsSync(ve(e)))return;console.error(" installing sootsim engine runtime...");let{runRuntime:t}=await import("./runtime-CQCSXHC2.js");await t(["install"],{})}function It(e){let t=process.argv[1];return t&&D.existsSync(t)?je(process.execPath,[t,...e],{detached:!0,stdio:"ignore",env:process.env}):je("sootsim",e,{detached:!0,stdio:"ignore",env:process.env})}function z(e,t){return new Promise(o=>{let n=new pt(`ws://127.0.0.1:${e}`,{handshakeTimeout:t}),r=!1,s=i=>{if(!r){r=!0;try{n.close()}catch{}o(i)}};n.once("open",()=>s(!0)),n.once("error",()=>s(!1)),setTimeout(()=>s(!1),t)})}function me(e){try{let t=new URL(e),o=t.pathname.replace(/\/+$/,"")||"/";return t.searchParams.has("open")||t.searchParams.has("port")||t.searchParams.has("bundle")||t.searchParams.has("demo")||t.pathname.includes("/sootsim/index.html")||o==="/sootsim"||t.pathname==="/__soot"||t.pathname==="/__soot/"||o==="/rn"||/^\/rn\/[^/]+$/i.test(o)||/^\/app\/[^/]+$/i.test(o)||o==="/__soot/rn"||/^\/__soot\/rn\/[^/]+$/i.test(o)||/^\/__soot\/app\/[^/]+$/i.test(o)}catch{return!1}}function Pt(e){try{let t=new URL(e).pathname.replace(/\/+$/,"")||"/";return/^\/preview\/[^/]+$/.test(t)||/^\/build\/.+/.test(t)}catch{return!1}}async function Uo(e){let t=G(e);return(await Ye(t)).bundleUrl}function Ct(e){try{let t=new URL(e.startsWith("http")?e:`http://${e}`),o=t.pathname||"/";if(o!=="/"&&o!==""||t.search||t.hash||!/^(localhost|127\.0\.0\.1|\[::1\]|::1)$/i.test(t.hostname))return null;let n=t.port?Number(t.port):t.protocol==="https:"?443:80;return Number.isFinite(n)&&n>0?n:null}catch{return null}}async function Ye(e){let t=G(e),o=/^\d+$/.test(t)?Number(t):Ct(t);if(o&&o>0){let n=await ke(o);if(n)return{bundleUrl:n.bundleUrl,port:n.port,framework:n.framework,projectName:n.projectName}}return He(t)}function pe(e){let t=e.replace(/\/+$/,"")||"/";return t==="/__soot"||t.startsWith("/__soot/")?"/__soot":""}function Et(e,t){let o=G(e),n=new URL(t),r=pe(n.pathname);return n.pathname=`${r}/rn`,n.searchParams.delete("bundle"),n.searchParams.delete("demo"),n.searchParams.delete("app"),n.searchParams.delete("open"),n.searchParams.delete("port"),/^\d+$/.test(o)?n.pathname=`${r}/rn/${o}`:(n.pathname=`${r}/rn`,n.searchParams.set("open",o)),n.toString()}function Mt(e){let t=G(e);return/^\d+$/.test(t)||/^https?:\/\//i.test(t)?!0:/^(localhost|127\.0\.0\.1|\[::1\]|[^/]+\.localhost):\d+(?:\/.*)?$/i.test(t)}async function Tt(e,t,o={}){let n=await Ye(e),r=new URL(t),s=pe(r.pathname);r.pathname=`${s}/rn`,r.searchParams.delete("open"),r.searchParams.delete("port"),r.searchParams.delete("demo"),r.searchParams.delete("app");let i=o.hot===void 0?n.bundleUrl:xe(n.bundleUrl,o.hot);return r.searchParams.set("bundle",i),r.toString()}function Ut(e){return e.startsWith("~/")?M.join(ut.homedir(),e.slice(2)):M.isAbsolute(e)?e:M.resolve(process.cwd(),e)}function Rt(e){let t={},o={};for(let r=0;r<e.length;r++){if(e[r]==="--replace"){let s=e[r+1];s||(console.error(" sootsim open: --replace expects <module>=<file>"),process.exit(1));let i=s.indexOf("=");(i<=0||i===s.length-1)&&(console.error(" sootsim open: --replace expects <module>=<file>"),process.exit(1));let a=s.slice(0,i).trim(),l=Ut(s.slice(i+1).trim());D.existsSync(l)||(console.error(` sootsim open: replacement file not found: ${l}`),process.exit(1)),t[a]={file:l},r++;continue}if(e[r]==="--remap"){let s=e[r+1],i=s?s.indexOf("="):-1;(!s||i<=0||i===s.length-1)&&(console.error(" sootsim open: --remap expects <host:port>=<host:port>"),process.exit(1)),o[s.slice(0,i).trim()]=s.slice(i+1).trim(),r++;continue}}let n={};return Object.keys(t).length>0&&(n.modules=t),Object.keys(o).length>0&&(n.network={remap:o}),n.modules||n.network?n:void 0}function Ze(){return Oe().shellBaseUrl}async function Ot(e){try{let t=new URL(e),o=t.searchParams.get("bundle")||"";if(!o)return e;let n=process.env.SOOT_REPO_DIR||await re(o)||void 0,r=Ce({bundleUrl:o,repoDir:n});if(r.length===0)return e;let s=await _t(r);return s.length===0?e:(t.searchParams.set("appFonts",Ee(s)),t.toString())}catch{return e}}async function _t(e){let t=await Promise.all(e.map(async n=>{let r=new AbortController,s=setTimeout(()=>r.abort(),1500);try{let i=await fetch(n.url,{method:"HEAD",signal:r.signal});return i.status>=200&&i.status<400?n:null}catch{return null}finally{clearTimeout(s)}})),o=[];for(let n of t)n!==null&&o.push(n);return o}async function Bt(e,t,o={}){if(!e)return new URL(t).toString();if(me(e))return new URL(e).toString();let n=gt[e.toLowerCase()];if(n){let r=new URL(t),s=pe(r.pathname);return r.pathname=`${s}${n}`,r.toString()}return Mt(e)?Tt(e,t,o):Et(e,t)}async function Dt(e){try{let t=new URL(e),o=t.searchParams.get("bundle")||"";if(!o)return e;let n=process.env.SOOT_REPO_DIR||await re(o)||void 0,r=Me({bundleUrl:o,repoDir:n});return!r||r.imageUrl&&!await At(r.imageUrl)?e:(t.searchParams.set("appSplash",Te(r)),t.toString())}catch{return e}}async function At(e){let t=new AbortController,o=setTimeout(()=>t.abort(),1500);try{let n=await fetch(e,{method:"HEAD",signal:t.signal});return n.status>=200&&n.status<400}catch{return!1}finally{clearTimeout(o)}}async function q(e,t=Ze(),o={}){let n=await Bt(e,t,o),r=await Dt(await Ot(n));if(!o.device)return r;let s=new URL(r);return s.searchParams.set("device",o.device),s.toString()}function Ge(e,t){let o=e?.url||e?.origin||t;try{let n=new URL(o);return n.searchParams.delete("bundle"),n.searchParams.delete("demo"),n.searchParams.delete("app"),n.searchParams.delete("open"),n.searchParams.delete("port"),n.searchParams.delete("inspectOpen"),n.searchParams.delete("appFonts"),n.searchParams.delete("appSplash"),n.toString()}catch{return t}}async function Lt(e,t,o,n={}){let r=new URL(await q(e,t,n));return r.searchParams.set("inspectOpen",o),r.toString()}async function Nt(e,t,o,n={}){let r=n.attempts??30,s=n.intervalMs??500,i=n.minNodeCount??10;for(let a=0;a<r;a++){let l=v(e,{commandTimeoutMs:t,simId:o,simIdSource:"flag"});try{let d=await l.send({type:"evaluate",code:"(async () => (await window.__sootsimTest?.getNodeCount()) || 0)()"});if(typeof d=="number"&&d>i)return{bridge:l,count:d}}catch{}l.close(),await $(s)}return null}function Ft(e){if(!e)return null;try{let t=new URL(e);if(t.searchParams.has("bundle")){let o=t.searchParams.get("bundle")||"";try{let n=new URL(o),r=n.pathname.length>36?`...${n.pathname.slice(-36)}`:n.pathname;return`bundle ${n.host}${r}`}catch{return"bundle"}}return t.searchParams.has("port")?`connect :${t.searchParams.get("port")||""}`:t.searchParams.has("open")?`connect ${t.searchParams.get("open")||""}`:t.searchParams.has("demo")?`demo ${t.searchParams.get("demo")||"default"}`:t.pathname.includes("/sootsim/index.html")||t.pathname==="/sootsim/"||t.pathname==="/sootsim"?"embedded sootsim":null}catch{return null}}function Ht(e){let t=e.indexOf(":");if(t<=0)return e.length>24?`${e.slice(0,21)}\u2026`:e;let o=e.slice(0,t),n=e.slice(t+1),r=n.length>12?`${n.slice(0,8)}\u2026`:n;return o==="AGENTBUS_SESSION"||o==="CLAUDE_CODE_SESSION_ID"||o==="CODEX_THREAD_ID"?`agent ${r}`:`${o} ${r}`}function Ro(e,t){if(e.length===0){console.log(" no sims connected");return}console.log(` connected sims (${e.length}):
|
|
3
|
-
`);for(let o of e){let n=o.lockedBy&&o.lockExpiresAt?`locked by ${Ht(o.lockedBy)} (${Math.max(0,Math.round((o.lockExpiresAt-Date.now())/1e3))}s)`:"",r=[o.isPrimary?"primary":"",o.id===t?"selected":"",o.readyState,o.userVisible===!1?"hidden":o.userVisible===!0?"visible":"",o.attachedCliCount&&o.attachedCliCount>0?"in use":"",o.userFocused?"focused":"",n].filter(Boolean);console.log(` ${o.id}${r.length?` [${r.join(", ")}]`:""}`);let s=Ft(o.url);if(s)console.log(` loaded: ${s}`);else if(o.url){let a=o.url.length>96?`${o.url.slice(0,93)}\u2026`:o.url;console.log(` url: ${a}`)}else o.origin&&console.log(` origin: ${o.origin}`);let i=Wt(o);i&&console.log(` engine: ${i}`),o.title&&console.log(` title: ${o.title}`),o.visibilityState&&o.visibilityState!=="visible"&&console.log(` visibility: ${o.visibilityState}`),console.log(` connected: ${Ve(Date.now()-o.connectedAt)}`),o.lastActiveAt&&o.lastActiveAt>0&&console.log(` last active: ${Ve(Date.now()-o.lastActiveAt)}`)}}function Wt(e){let t=e.url||e.origin||"";if(!t)return null;try{let o=new URL(t).port;return o==="5173"?"dev \u2014 local source (:5173)":o==="3000"?"soot app embedded (:3000)":Pe()?`dev \u2014 local build (:${o||"?"})`:`runtime \u2014 published engine (:${o||"?"})`}catch{return null}}function Ve(e){let t=Math.max(0,Math.round(e/1e3));return t<60?`${t}s ago`:t<3600?`${Math.round(t/60)}m ago`:t<86400?`${Math.round(t/3600)}h ago`:`${Math.round(t/86400)}d ago`}async function ce(e,t,o,n={}){let r=n.attempts??30,s=n.intervalMs??500;for(let i=0;i<r;i++){let a=v(e,{commandTimeoutMs:t});try{let d=(await a.listSims()).find(o);if(d)return d}catch{}finally{a.close()}await $(s)}return null}async function jt(e,t,o,n,r={}){let s=r.attempts??30,i=r.intervalMs??500,a=!!n&&Number.isInteger(n)&&n>1,l=()=>a&&n!==void 0&&!ue(n);for(let d=0;d<s;d++){if(l())return{kind:"host-exit"};let m=v(e,{commandTimeoutMs:t});try{let g=(await m.listSims()).find(o);if(g)return l()?{kind:"host-exit"}:{kind:"match",sim:g}}catch{}finally{m.close()}if(l())return{kind:"host-exit"};await $(i)}return{kind:"timeout"}}async function Kt(e,t,o,n={}){let r=n.attempts??20,s=n.intervalMs??250;for(let i=0;i<r;i++){let a=v(e,{commandTimeoutMs:t});try{let d=(await a.listSims()).find(m=>m.id===o);if(!d||d.readyState!=="open")return!0}catch{return!0}finally{a.close()}await $(s)}return!1}function zt(e){let t=e.meta;if(!t||t.sootsimHostDriver!=="playwright")return null;let o=Number(t.sootsimHostPid);return!Number.isInteger(o)||o<=1||o===process.pid?null:o}function qt(e){if(!e.connectAckFile)return!1;try{return D.writeFileSync(e.connectAckFile,`${JSON.stringify({connectedAt:Date.now(),pid:e.pid??null})}
|
|
4
|
-
`,{flag:"w"}),!0}catch{return!1}}function Je(e){if(e.diagnosticLogPath)try{let t=D.readFileSync(e.diagnosticLogPath,"utf8").trim();if(!t){console.error(` ${M.basename(e.diagnosticLogPath)} was empty`);return}let o=t.length>4e3?`\u2026
|
|
5
|
-
${t.slice(-4e3)}`:t;console.error(` ${M.basename(e.diagnosticLogPath)}:`),console.error(o)}catch(t){let o=t instanceof Error?t.message:String(t);console.error(` failed to read ${M.basename(e.diagnosticLogPath)}: ${o}`)}}function ue(e){try{return process.kill(e,0),!0}catch(t){return t?.code==="EPERM"}}async function Gt(e,t=2500){let o=Date.now()+t;for(;Date.now()<o;){if(!ue(e))return!0;await $(100)}return!ue(e)}async function de(e,t){let o=new Set(t),n=new Set;for(let r of e){if(!o.has(r.id))continue;let s=zt(r);s&&n.add(s)}for(let r of n){try{process.kill(r,"SIGTERM")}catch{}if(await Gt(r)){console.log(` closed playwright host process ${r}`);continue}try{process.kill(r,"SIGKILL"),console.log(` force-closed playwright host process ${r}`)}catch{}}}function V(e,t){if(t){let r=t.trim(),s=e.find(i=>i.id===r);if(!s)throw new Error(`no sim connected with id ${r}`);return s}let o=e.find(r=>r.isPrimary&&r.readyState==="open");if(o)return o;let n=e.find(r=>r.readyState==="open");if(n)return n;throw new Error("no sim connected")}function _(e,t,o){console.log(` ${o==="current sim"?"loaded":"opened"}: ${e} [${o}]`),console.log(` current sim: ${t.id}`),console.log(JSON.stringify({simId:t.id,url:t.url},null,2))}async function B(e,t,o){if(o.includes("--no-describe"))return;let n=process.env.SOOTSIM_QUIET_TARGET_NOTICE;process.env.SOOTSIM_QUIET_TARGET_NOTICE="1";try{await Vt(e,t,{stableMs:150,maxMs:400});let r=v(e,{commandTimeoutMs:3e3,simId:t,cliLabel:"open --describe",simIdSource:"flag"});try{let s=null;try{s=await r.send({type:"evaluate",code:Ue})}catch{}if(s&&!(s.flag===!0&&!s.loadingText&&Re(s))){let m=s.loadingText?`still showing "${s.loadingText}"`:s.flag!==!0?"guest ready event has not fired":s.targets<=0?"no visible app content is inspectable yet":"app tree is still stabilizing";console.log(` app still loading: ${m} (nodes: ${s.nodes}, targets: ${s.targets})`),console.log(" before interacting, run: sootsim wait ready --max-ms 120000")}let a=`(async () => {
|
|
6
|
-
const t = window.__sootsimTest
|
|
7
|
-
const ms = window.SootSim?.bridges?.mainShell
|
|
8
|
-
if (!t) return null
|
|
9
|
-
let shell = null
|
|
10
|
-
try { shell = ms?.getState ? await ms.getState() : null } catch {}
|
|
11
|
-
const tree = await t.dumpTree(12, ${JSON.stringify({describe:!0,verbose:!1,filter:""})})
|
|
12
|
-
return { tree, shell }
|
|
13
|
-
})()`,l=await r.send({type:"evaluate",code:a});if(!l?.tree)return;if(console.log(""),l.shell?.state){let d=[`state=${l.shell.state}`,l.shell.activeApp?`app=${l.shell.activeApp}`:null].filter(Boolean);console.log(` shell: ${d.join(" ")}`)}console.log(l.tree)}finally{r.close()}}catch{}finally{n===void 0?delete process.env.SOOTSIM_QUIET_TARGET_NOTICE:process.env.SOOTSIM_QUIET_TARGET_NOTICE=n}}async function Vt(e,t,o){let n=Date.now()+o.maxMs,r="(async () => (await window.__sootsimTest?.getNodeCount?.()) || 0)()",s=v(e,{commandTimeoutMs:2e3,simId:t,simIdSource:"flag"});try{let i=-1,a=0;for(;Date.now()<n;){let l=-1;try{let d=await s.send({type:"evaluate",code:r});typeof d=="number"&&(l=d)}catch{}if(l>=0&&l===i){if(Date.now()-a>=o.stableMs)return}else i=l,a=Date.now();await $(50)}}finally{s.close()}}async function Jt(e,t={}){let o=C(e,{port:t.port,commandTimeoutMs:t.timeoutMs});o.positional.length!==1&&(console.error(" sootsim open: expected exactly one <url-or-route>"),console.error(" examples: sootsim open /settings | sootsim open myapp://settings"),process.exit(1));let n;try{n=vt(o.positional[0]??"")}catch(i){console.error(` sootsim open: ${i instanceof Error?i.message:String(i)}`),process.exit(1)}let r=E(o),s=o.simId?` --sim ${o.simId}`:"";try{let i=await r.send({type:"call",path:"SootSim.bridges.test.openDeepLink",args:[n]});if(St(i)&&i.ok===!1)throw new Error(typeof i.error=="string"?i.error:"deep-link dispatch failed");console.log(` opened deep link: ${n}`)}catch(i){console.error(` link failed: ${i instanceof Error?i.message:String(i)}`),await R(r,{errorsCommand:`sootsim get errors 5${s}`,warningsCommand:`sootsim get warnings 5${s}`,requestsCommand:`sootsim get requests 5${s}`}),process.exit(1)}finally{r.close()}}async function Oo(e,t={}){let o=C(e,{port:t.port,commandTimeoutMs:t.timeoutMs,stripBooleanFlags:["--new","--headless","--headed","--ephemeral","--hot","--no-hmr","--no-describe"],stripValueFlags:["--base-url","--replace","--driver","--profile","--cdp-port","--browser","--device"]}),n=e.find((c,p)=>e[p-1]==="--profile"),r=e.includes("--ephemeral"),s=e.find((c,p)=>e[p-1]==="--cdp-port"),i=s?Number(s):void 0;s&&(!Number.isFinite(i)||i<=0)&&(console.error(` sootsim open: --cdp-port must be a positive port number, got "${s}"`),process.exit(1)),n&&r&&(console.error(" sootsim open: --profile cannot be combined with --ephemeral"),process.exit(1));let a=n?Ie(n).id:void 0,l=!!a||r,d=e.includes("--new")||l,m=Rt(e);d&&o.simIdSource==="flag"&&(console.error(" sootsim open: --new, --profile, and --ephemeral cannot be combined with --sim"),process.exit(1));let u=o.positional[0]||"";if($t(u)){d&&(console.error(" sootsim open: deep links target the current app; remove --new, --profile, or --ephemeral"),process.exit(1)),await Jt(e,t);return}if(Pt(u)){let c=(()=>{try{return/^(localhost|127\.0\.0\.1|\[::1\]|::1)$/i.test(new URL(u).hostname)}catch{return!1}})();console.log(" that\u2019s a SootSim preview/build link \u2014 a full player page, not a driveable sim."),console.log(" opening it in your browser for viewing\u2026");try{await ae(u,{background:!1})}catch(p){console.error(` could not launch a browser: ${p instanceof Error?p.message:String(p)}`),console.error(` open it yourself: ${u}`),process.exit(1)}console.log(c?" to drive it under the CLI, point `sootsim open` at the app\u2019s dev port instead (e.g. `sootsim open 8081`).":" the CLI can\u2019t drive a remote preview (the engine only attaches to the local bridge from localhost). to drive the app, run it locally and `sootsim open <port>`.");return}let g=e.find((c,p)=>e[p-1]==="--base-url"),J=t.port!==void 0||e.some(c=>c==="--port"||c==="-p"||c.startsWith("--port="));if(g&&!J){let c=se(g);c&&(o.wsPort=c)}o.wsPort=await xt(o.wsPort);let y=e.find((c,p)=>e[p-1]==="--driver")||"",et=yt(e,y);i&&y!=="playwright"&&(console.error(" sootsim open: --cdp-port is only honored by the playwright driver \u2014 add `--driver playwright`"),process.exit(1));let x=e.find((c,p)=>e[p-1]==="--browser");x&&y!=="playwright"&&(console.error(" sootsim open: --browser is only honored by the playwright driver \u2014 add `--driver playwright`"),process.exit(1));let A=x==="chromium"||x==="webkit"||x==="firefox"?x:void 0;x&&!A&&(console.error(` sootsim open: --browser must be chromium, webkit, or firefox \u2014 got "${x}"`),process.exit(1)),i&&A&&A!=="chromium"&&(console.error(" sootsim open: --cdp-port requires the chromium engine"),process.exit(1));let fe=e.includes("--hot"),he=e.includes("--no-hmr");fe&&he&&(console.error(" sootsim open: --hot and --no-hmr cannot be combined"),process.exit(1));let tt=fe?!0:he?!1:y!=="playwright",k=e.find((c,p)=>e[p-1]==="--device");k&&!(k in te)&&(console.error(` sootsim open: unknown device "${k}"`),console.error(` known devices: ${$e().join(", ")}`),process.exit(1));let Q=k?te[k]:void 0,L={hot:tt,device:k},ot=_e(o.wsPort),I=g||ot?.shellBaseUrl||Ze(),ge=e.includes("--base-url");Be(o.wsPort,I);let we=T();if(!y&&!d&&(o.simIdSource==="flag"||o.simIdSource==="saved"&&!!we)){let c=E(o),p=o.simId?` --sim ${o.simId}`:"",f=!1;try{let h=null;try{let w=await c.listSims();if(o.simIdSource==="saved"?(h=w.find(P=>P.id===we&&P.readyState==="open")??null,h||U()):h=V(w,o.simId),!h)if(o.simIdSource==="saved")f=!0;else throw new Error("no sim connected");if(!f&&h){let P=ge||me(u)?I:Ge(h,I),H=await q(u,j(P,m),L);c.send({type:"evaluate",simId:h.id,code:`window.location.href = ${JSON.stringify(H)}`}).catch(()=>{})}}catch(w){console.error(` open failed: ${w instanceof Error?w.message:String(w)}`),await R(c,{errorsCommand:`sootsim get errors 5${p}`,warningsCommand:`sootsim get warnings 5${p}`,requestsCommand:`sootsim get requests 5${p}`}),process.exit(1)}if(!f&&h){await $(1500);let w=await Nt(o.wsPort,o.commandTimeoutMs,h.id);w||(console.error(" timed out waiting for current sim to load target"),process.exit(1)),w.bridge.close(),b(h.id);let P=ge||me(u)?I:Ge(h,I),H=await q(u,j(P,m),L);_(H,{...h,url:H},"current sim"),await B(o.wsPort,h.id,e);return}}finally{c.close()}}let be=j(I,m),nt=await q(u,be,L),ye=`cli-${Date.now().toString(36)}-${Math.random().toString(36).slice(2,8)}`,S=await Lt(u,be,ye,L),Y={newWindow:!0},N=c=>c.url?.includes(`inspectOpen=${ye}`)??!1;if(y){bt(y)||(console.error(` unknown driver "${y}" \u2014 run \`sootsim list --drivers\``),process.exit(1));let c=le(y);c||(console.error(` unknown driver "${y}" \u2014 run \`sootsim list --drivers\``),process.exit(1));let p=wt(),f=await c.launch({url:S,bridgePort:se(I)??void 0,headless:et,newWindow:Y.newWindow,profileId:a,ephemeralProfile:r,cdpPort:i,browser:A,device:k,viewport:Q?{width:Q.width+120,height:Q.height+60}:void 0,connectTimeoutMs:p.hostTimeoutMs});f.launched||(console.error(` ${c.name} driver: ${f.message}`),process.exit(1));let h=await jt(o.wsPort,o.commandTimeoutMs,N,f.pid,{attempts:p.attempts,intervalMs:p.intervalMs});if(h.kind==="host-exit"&&(Je(f),console.error(` ${c.name} host crashed \u2014 sim is no longer attached`),process.exit(1)),h.kind==="timeout"){if(f.pid)try{process.kill(f.pid,"SIGTERM"),console.error(` closed ${c.name} host process ${f.pid}`)}catch{}Je(f),console.error(` timed out after ${p.timeoutMs}ms waiting for opened sim to connect`),process.exit(1)}let w=h.sim;b(w.id),qt(f),_(S,w,`${c.name} driver`),await B(o.wsPort,w.id,e);return}if(l){let c=O();c||(console.error(" profiles require electron or playwright; install the desktop companion or use `--driver playwright`"),process.exit(1));try{(await ie(S,c,{profileId:a,ephemeralProfile:r})).launched||(console.error(" desktop companion failed to start"),process.exit(1))}catch(f){console.error(` desktop companion failed: ${f instanceof Error?f.message:String(f)}`),process.exit(1)}let p=await ce(o.wsPort,o.commandTimeoutMs,N,{attempts:40,intervalMs:500});p||(console.error(" timed out waiting for profiled sim to connect"),process.exit(1)),b(p.id),_(S,p,"desktop companion"),await B(o.wsPort,p.id,e);return}let Z=!1,X=!1;try{let c=v(o.wsPort,{commandTimeoutMs:2e3});try{await c.listSims(),Z=!0}finally{c.close()}}catch{}if(Z)try{let c=v(o.wsPort,{commandTimeoutMs:3e3});try{await c.openUrl(S,Y),X=!0}finally{c.close()}}catch{}if(!X){let c=O();if(c)try{if((await ie(S,c)).launched){let f=await ce(o.wsPort,o.commandTimeoutMs,N,{attempts:20,intervalMs:500});if(f){b(f.id),_(S,f,"desktop companion"),await B(o.wsPort,f.id,e);return}}}catch{}try{await ae(S,Y)}catch(p){console.error(` open failed: ${p instanceof Error?p.message:String(p)}`),le("playwright")?.availability().available?console.error(" no system browser found \u2014 retry with `sootsim open \u2026 --driver playwright` for a headless sim."):console.error(" run `sootsim list --drivers` to see available drivers."),process.exit(1)}if(!Z){console.log(` opened: ${nt}`),We(o.wsPort);return}}let F=await ce(o.wsPort,o.commandTimeoutMs,N,{attempts:30,intervalMs:500});F||(console.error(" timed out waiting for opened sim to connect"),process.exit(1)),b(F.id),_(S,F,X?"bridge":"direct shell open"),await B(o.wsPort,F.id,e)}async function Xe(e,t={}){let o=C(e,{port:t.port,commandTimeoutMs:t.timeoutMs,stripBooleanFlags:["--force"]}),n=e.includes("--force"),r=E(o),s=o.simId?` --sim ${o.simId}`:"";try{try{let i=await r.listSims(),a=V(i,o.positional[0]||o.simId);if(a.lockedBy&&a.lockExpiresAt&&a.lockExpiresAt>Date.now()){let l=Math.max(0,Math.round((a.lockExpiresAt-Date.now())/1e3));a.lockedByKind==="user-active"&&(console.error(` refused: ${a.id} is locked by the active user (${l}s) \u2014 that's a live human tab`),console.error(" run `sootsim open --new` for a fresh investigation sim"),process.exit(1)),n||(console.error(` refused: ${a.id} is leased by ${a.lockedBy} (${l}s)`),console.error(` \`sootsim use ${a.id} --force\` to take it, or \`sootsim open --new\` for a fresh sim`),process.exit(1))}await r.focusSim(a.id),b(a.id),console.log(` using: ${a.id}`)}catch(i){console.error(` use failed: ${i instanceof Error?i.message:String(i)}`),await R(r,{errorsCommand:`sootsim get errors 5${s}`,warningsCommand:`sootsim get warnings 5${s}`,requestsCommand:`sootsim get requests 5${s}`}),process.exit(1)}}finally{r.close()}}async function _o(e,t={}){await Xe(e,t)}async function Bo(e,t={}){await Xe(e,t)}async function Do(e,t={}){let o=C(e,{port:t.port,commandTimeoutMs:t.timeoutMs,stripBooleanFlags:["--force"]}),n=e.includes("--force"),r=E(o);try{try{let s=await r.listSims(),i=V(s,o.positional[0]||o.simId),a=n&&i.lockedBy&&i.lockedByKind!=="user-active"?i.lockedBy:null,l=await r.claim(i.id,{force:n});b(i.id);let d=Math.max(0,Math.round((l.lockExpiresAt-Date.now())/1e3)),m=l.bootedCount>0?` (booted ${l.bootedCount})`:"";console.log(` claimed: ${l.simId} [${d}s]${m}`),a&&console.log(` took over from: ${a}`)}catch(s){if(s instanceof De){let i=Math.max(0,Math.round(s.lock.expiresInMs/1e3));console.error(` claim failed: locked by ${s.lock.by} for ${i}s more`),console.error(" use --force to take it, or `sootsim open --new` for a fresh sim"),process.exit(1)}console.error(` claim failed: ${s instanceof Error?s.message:String(s)}`),process.exit(1)}}finally{r.close()}}async function Qt(e,t,o,n){if(n.length===0)return{closed:[],remaining:[]};await Promise.all(n.map(s=>e.closeSim(s).catch(()=>{})));let r=new Set(n);for(let s=0;s<40;s++){let i=[];try{let a=v(t,{commandTimeoutMs:o});try{i=(await a.listSims()).filter(d=>r.has(d.id)&&d.readyState==="open").map(d=>d.id)}finally{a.close()}}catch{i=[]}if(i.length===0)return{closed:[...r],remaining:[]};if(s===39)return{closed:[...r].filter(a=>!i.includes(a)),remaining:i};await $(250)}return{closed:[...r],remaining:[]}}function Yt(e,t){let o=e.filter(u=>u.readyState==="open"),n=o.map(u=>u.id),r=t.explicitKeepId?.trim()||"",s=t.savedKeepId?.trim()||"",i=s?o.some(u=>u.id===s):!1,a=s&&!i?s:null,l=null,d=null,m=null;if(t.closeOthers)if(r){let u=o.find(g=>g.id===r);u?l=u.id:d=r}else if(s&&i)l=s;else{let u=o.find(g=>g.isPrimary)??o[0]??null;u&&(l=u.id,s&&!i&&(m=u.id))}return{openIds:n,keepId:l,targets:d?[]:n.filter(u=>u!==l),staleSavedId:a,missingExplicitKeepId:d,fallbackKeepId:m}}async function Ao(e,t={}){let o=C(e,{port:t.port,commandTimeoutMs:t.timeoutMs,stripBooleanFlags:["--all","--others"]}),n=E(o),r=o.simId?` --sim ${o.simId}`:"",s=e.includes("--all"),i=e.includes("--others");if(s||i){try{let a=await n.listSims(),l=T(),d=o.positional[0]||(o.simIdSource==="flag"?o.simId:void 0),m=Yt(a,{closeOthers:i,explicitKeepId:d,savedKeepId:l});if(m.staleSavedId&&U(),m.fallbackKeepId&&(b(m.fallbackKeepId),console.log(` saved sim ${m.staleSavedId} is gone \u2014 keeping primary ${m.fallbackKeepId}`)),m.missingExplicitKeepId&&(console.error(` close failed: keep sim ${m.missingExplicitKeepId} is not connected; not closing other sims`),process.exit(1)),m.targets.length===0){console.log(m.keepId?` nothing to close \u2014 only the kept sim ${m.keepId} is connected`:m.staleSavedId?` nothing to close \u2014 no sims connected (cleared stale current sim ${m.staleSavedId})`:" nothing to close \u2014 no sims connected");return}let u=await Qt(n,o.wsPort,o.commandTimeoutMs,m.targets);await de(a,m.targets);let g=T();g&&u.closed.includes(g)&&(m.keepId?b(m.keepId):U());let J=` closed ${u.closed.length} sim(s)${m.keepId?` (kept ${m.keepId})`:""}`;console.log(J),u.remaining.length>0&&(console.error(` close failed: still connected: ${u.remaining.join(", ")}`),process.exit(1))}catch(a){console.error(` close failed: ${a instanceof Error?a.message:String(a)}`),process.exit(1)}finally{n.close()}return}try{try{let a=await n.listSims(),l=V(a,o.positional[0]||o.simId),d=a.find(u=>u.id!==l.id&&u.readyState==="open");await n.closeSim(l.id),await Kt(o.wsPort,o.commandTimeoutMs,l.id)||(await de(a,[l.id]),console.error(` close failed: ${l.id} is still connected`),process.exit(1)),await de(a,[l.id]),T()===l.id&&(d?b(d.id):U()),console.log(` closed: ${l.id}`)}catch(a){console.error(` close failed: ${a instanceof Error?a.message:String(a)}`),await R(n,{errorsCommand:`sootsim get errors 5${r}`,warningsCommand:`sootsim get warnings 5${r}`,requestsCommand:`sootsim get requests 5${r}`}),process.exit(1)}}finally{n.close()}}export{ro as a,mt as b,so as c,wt as d,vt as e,Uo as f,Ze as g,q as h,Lt as i,Ft as j,Ro as k,ce as l,jt as m,zt as n,qt as o,de as p,Jt as q,Oo as r,_o as s,Bo as t,Do as u,Qt as v,Yt as w,Ao as x};
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
/*! sootsim v0.1.209 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
|
|
2
|
-
import{a,b,c,d,e}from"./chunk-IUG5LGAH.js";import"./chunk-JXOQBX5R.js";import"./chunk-IELT7YPL.js";import"./chunk-JOFHXMRG.js";import"./chunk-L23EEIDG.js";import"./chunk-2PGB3DOK.js";import"./chunk-Y2YT6G2K.js";import"./chunk-4N2A7WPD.js";import"./chunk-2N7YUIB6.js";import"./chunk-OVT65DWK.js";import"./chunk-7XXN43QW.js";import"./chunk-KUFSYYKY.js";import"./chunk-W2SLUPGS.js";import"./chunk-YB7GMFBR.js";export{c as daemonInstall,b as getDaemonServiceStatus,a as runDaemon,d as teardownDaemonService,e as teardownSootsimHome};
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
/*! sootsim v0.1.209 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
|
|
2
|
-
import"./chunk-CYDWIYRJ.js";import{f as a,g as b,h as c,i as d,j as e,k as f,l as g,m as h,n as i}from"./chunk-TCIUR5IB.js";import"./chunk-H7I4QQBU.js";import"./chunk-56YCENXG.js";import"./chunk-2N7YUIB6.js";import"./chunk-OVT65DWK.js";import"./chunk-YB7GMFBR.js";export{e as ALL_DRIVERS,i as buildDriverListRows,a as chromiumDriver,b as electronDriver,f as getAllDrivers,g as getDriver,c as playwrightDriver,h as resolveDriver,d as systemDriver};
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
/*! sootsim v0.1.209 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
|
|
2
|
-
import{c,d,e,f,g,h}from"./chunk-IE3M7UCB.js";import{c as a,d as b}from"./chunk-5MEH5VHS.js";import"./chunk-5HAEGTT5.js";import"./chunk-EYISIVUC.js";import"./chunk-JUBCRVXK.js";import"./chunk-3MSLDFKZ.js";import"./chunk-S73LN4A3.js";import"./chunk-CXBNEQNP.js";import"./chunk-3RVUM7UI.js";import"./chunk-CNHZWLE3.js";import"./chunk-UQX3RDUO.js";import"./chunk-GGRLGKFC.js";import"./chunk-VCUGCWFW.js";import"./chunk-IEDKCUPC.js";import"./chunk-YC4E3DRA.js";import"./chunk-TCIUR5IB.js";import"./chunk-H7I4QQBU.js";import"./chunk-56YCENXG.js";import"./chunk-OL7X4HKV.js";import"./chunk-DNAKPQ56.js";import"./chunk-JXOQBX5R.js";import"./chunk-IELT7YPL.js";import"./chunk-2PGB3DOK.js";import"./chunk-Y2YT6G2K.js";import"./chunk-4N2A7WPD.js";import"./chunk-2N7YUIB6.js";import"./chunk-OVT65DWK.js";import"./chunk-W2SLUPGS.js";import"./chunk-YB7GMFBR.js";export{e as discoverSootsimUrl,c as getLastFlowPreviewUploadResult,d as getLastFlowTraceSteps,g as hoistLeadingSimFlag,a as parseFlowFile,h as runFlow,f as runFlowPlayback,b as validateFlowFile};
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
/*! sootsim v0.1.209 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
|
|
2
|
-
import{a,b,c}from"./chunk-JOFHXMRG.js";import"./chunk-L23EEIDG.js";import"./chunk-2PGB3DOK.js";import"./chunk-Y2YT6G2K.js";import"./chunk-4N2A7WPD.js";import"./chunk-2N7YUIB6.js";import"./chunk-OVT65DWK.js";import"./chunk-7XXN43QW.js";import"./chunk-KUFSYYKY.js";import"./chunk-W2SLUPGS.js";import"./chunk-YB7GMFBR.js";export{c as printCommandHelp,b as printGroupHelp,a as printHelp};
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
/*! sootsim v0.1.209 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
|
|
2
|
-
import{j as a,k as b}from"./chunk-5MEH5VHS.js";import"./chunk-5HAEGTT5.js";import"./chunk-S73LN4A3.js";import"./chunk-CXBNEQNP.js";import"./chunk-3RVUM7UI.js";import"./chunk-CNHZWLE3.js";import"./chunk-UQX3RDUO.js";import"./chunk-GGRLGKFC.js";import"./chunk-VCUGCWFW.js";import"./chunk-IEDKCUPC.js";import"./chunk-YC4E3DRA.js";import"./chunk-TCIUR5IB.js";import"./chunk-H7I4QQBU.js";import"./chunk-56YCENXG.js";import"./chunk-OL7X4HKV.js";import"./chunk-DNAKPQ56.js";import"./chunk-2PGB3DOK.js";import"./chunk-Y2YT6G2K.js";import"./chunk-4N2A7WPD.js";import"./chunk-2N7YUIB6.js";import"./chunk-OVT65DWK.js";import"./chunk-W2SLUPGS.js";import"./chunk-YB7GMFBR.js";export{a as printShellPerfReport,b as runInspect};
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
/*! sootsim v0.1.209 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
|
|
2
|
-
import{a}from"./chunk-44EPIO7S.js";import"./chunk-GGPPDEWU.js";import"./chunk-YC4E3DRA.js";import"./chunk-4N2A7WPD.js";import"./chunk-2N7YUIB6.js";import"./chunk-OVT65DWK.js";import"./chunk-YB7GMFBR.js";export{a as runRuntime};
|
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
/*! sootsim v0.1.209 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
|
|
2
|
-
import{a as P,b as N,c as A}from"./chunk-QYOLP7E2.js";import{a as L}from"./chunk-5HAEGTT5.js";import{a as k}from"./chunk-JUBCRVXK.js";import{a as O,b as M}from"./chunk-3MSLDFKZ.js";import"./chunk-CNHZWLE3.js";import"./chunk-UQX3RDUO.js";import{f as F}from"./chunk-IEDKCUPC.js";import{g as D,i as E}from"./chunk-YC4E3DRA.js";import"./chunk-56YCENXG.js";import"./chunk-JXOQBX5R.js";import"./chunk-IELT7YPL.js";import"./chunk-4N2A7WPD.js";import"./chunk-2N7YUIB6.js";import"./chunk-OVT65DWK.js";import"./chunk-YB7GMFBR.js";import{spawn as Y}from"child_process";import{existsSync as _,mkdtempSync as H,readdirSync as I,writeFileSync as G}from"fs";import{tmpdir as K}from"os";import{resolve as S,dirname as z,join as R,relative as X}from"path";import{fileURLToPath as q}from"url";var $=z(q(import.meta.resolve("sootsim-engine/package.json"))),Q=process.env.SOOTSIM_TEST_MODEL||"deepseek-v4-flash",j=18e3,Z=18e4;async function Te(e,t){let n=e.includes("--flows"),u=e.includes("--detox"),l=e.includes("--parallel"),s=e.includes("--watch"),a=e.find((i,c)=>e[c-1]==="--reporter")||"console",o=ee(e);if((e.includes("--help")||e.includes("-h"))&&(console.log(`
|
|
3
|
-
sootsim test \u2014 run tests against sootsim
|
|
4
|
-
|
|
5
|
-
usage:
|
|
6
|
-
sootsim test [options]
|
|
7
|
-
sootsim test "natural language goal" [--owner <org> --repo <repo>]
|
|
8
|
-
|
|
9
|
-
modes:
|
|
10
|
-
(default) run package-local playwright tests
|
|
11
|
-
"<prompt>" generate, run, upload, and register a replayable flow
|
|
12
|
-
--flows run YAML flows
|
|
13
|
-
--detox run shared Detox-style conformance suites
|
|
14
|
-
|
|
15
|
-
options:
|
|
16
|
-
--parallel run tests in parallel
|
|
17
|
-
--watch re-run on changes
|
|
18
|
-
--reporter output format (console|json|junit)
|
|
19
|
-
--origin sootbean upload / LLM origin (default: auto)
|
|
20
|
-
--owner org account to attach the uploaded run to
|
|
21
|
-
--repo repo name for --owner
|
|
22
|
-
-t, --testNamePattern <pat>
|
|
23
|
-
filter tests by name
|
|
24
|
-
|
|
25
|
-
examples:
|
|
26
|
-
sootsim test
|
|
27
|
-
sootsim test "tap the login button and verify the welcome screen"
|
|
28
|
-
sootsim test --flows
|
|
29
|
-
sootsim test --detox --watch
|
|
30
|
-
sootsim test -t "login"
|
|
31
|
-
|
|
32
|
-
notes:
|
|
33
|
-
playwright is best for smoke and package-local debugging
|
|
34
|
-
--detox is the preferred parity lane for behavior that should match real RN
|
|
35
|
-
`),process.exit(0)),o&&!n&&!u)await ce(o.prompt,o.index,e,t);else if(n)await pe(e,t,l,a);else if(u){let{runDetox:i}=await import("./detox-I4NFW53N.js");await i(e.filter(c=>c!=="--detox"),t)}else await ue(e,t)}function h(e,t){let n=e.indexOf(t);return n>=0?e[n+1]:void 0}function C(e,t){for(let n of t){let u=h(e,n);if(u)return u}}var J=new Set(["--reporter","-t","--testNamePattern","--grep","--origin","--preview-origin","--public-origin","--preview-public-origin","--owner","--repo","--url","--driver","--sim","--device","--slow","--tail-wait","--remap","--replace"]);function ee(e){for(let t=0;t<e.length;t++){let n=e[t];if(n){if(J.has(n)){t+=1;continue}if(!n.startsWith("-"))return _(n)||/\.(?:[cm]?[jt]sx?|ya?ml|json)$/i.test(n)||!/\s/.test(n)&&n.length<16?null:{prompt:n,index:t}}}return null}function te(e,t){return e.filter((n,u)=>u!==t)}async function ne(e,t){let n=te(e,t),u=D(n,{stripBooleanFlags:["--parallel","--watch","--flows","--detox","--new","--headless","--headed","--electron","--preview-open"],stripValueFlags:[...J]}),l=E(u);try{let s=await F(l,{describe:!0,verbose:!1,filter:"",compact:!0,hideXy:!0}),o=[s.shell?`shell: ${JSON.stringify(s.shell)}`:"",s.keyboard?`keyboard: ${JSON.stringify(s.keyboard)}`:"",typeof s.nodeCount=="number"?`nodes: ${s.nodeCount}`:"",s.tree||""].filter(Boolean).join(`
|
|
36
|
-
`);return o.length>j?o.slice(0,j)+`
|
|
37
|
-
[tree truncated]`:o}finally{l.close()}}var oe=`
|
|
38
|
-
You write SootSim YAML flows from a user's natural-language test goal.
|
|
39
|
-
Return only JSON, no markdown, with this exact shape:
|
|
40
|
-
{"summary":"short human-readable result goal","steps":[{"waitFor":{"text":"...","timeout":10000}}]}
|
|
41
|
-
|
|
42
|
-
Use only these flow commands:
|
|
43
|
-
- waitFor: { "text"?: string, "id"?: string, "timeout"?: number }
|
|
44
|
-
- assertVisible: string or { "text"?: string, "id"?: string }
|
|
45
|
-
- assertNotVisible: string or { "text"?: string, "id"?: string }
|
|
46
|
-
- tapOn: string or { "text"?: string, "id"?: string, "index"?: number }
|
|
47
|
-
- inputText: string
|
|
48
|
-
- pressKey: string
|
|
49
|
-
- hideKeyboard: true
|
|
50
|
-
- swipe: { "direction": "UP" | "DOWN" | "LEFT" | "RIGHT", "duration"?: number }
|
|
51
|
-
- waitForAnimationToEnd: true
|
|
52
|
-
- takeScreenshot: "label"
|
|
53
|
-
|
|
54
|
-
Prefer ids/testIDs from the tree. Prefer visible text when no id exists.
|
|
55
|
-
Do not invent app-specific data that is not visible. Keep the flow short.
|
|
56
|
-
End with an assertion or wait that proves the user's goal.
|
|
57
|
-
`.trim();function re(e,t){return`
|
|
58
|
-
User goal:
|
|
59
|
-
${e}
|
|
60
|
-
|
|
61
|
-
Current SootSim visible tree:
|
|
62
|
-
${t||"[no tree available]"}
|
|
63
|
-
|
|
64
|
-
Generate the shortest replayable flow that verifies the goal from this current state.
|
|
65
|
-
`.trim()}function U(e){return typeof e=="string"?e:Array.isArray(e)?e.map(t=>t&&typeof t=="object"&&t.type==="text"?String(t.text??""):"").join(""):""}async function se(e){let t=await fetch(`${e.origin.replace(/\/$/,"")}/api/llm`,{method:"POST",headers:{"content-type":"application/json",authorization:e.authHeader},body:JSON.stringify({modelId:Q,context:{systemPrompt:oe,messages:[{role:"user",content:re(e.prompt,e.describe),timestamp:Date.now()}]},options:{maxTokens:1800,temperature:.2},threadId:null}),signal:AbortSignal.timeout(Z)});if(!t.ok||!t.body){let c=await t.text().catch(()=>"");throw new Error(`/api/llm ${t.status}${c?`: ${c}`:""}`)}let n=t.body.getReader(),u=new TextDecoder,l=[],s="",a="",o=c=>{let p=c.trim();if(!p)return;let r=JSON.parse(p);if(r.type==="text_delta"&&r.delta)l.push(r.delta);else if(r.type==="text_end"&&r.content)s=r.content;else if(r.type==="done")s=U(r.message?.content);else if(r.type==="error")throw new Error(r.error?.errorMessage||U(r.error?.content)||"llm error")};for(;;){let{value:c,done:p}=await n.read();if(p)break;a+=u.decode(c,{stream:!0});let r;for(;(r=a.indexOf(`
|
|
66
|
-
`))>=0;)o(a.slice(0,r)),a=a.slice(r+1)}a+=u.decode(),a.trim()&&o(a);let i=(s||l.join("")).trim();if(!i)throw new Error("llm returned an empty test flow");return i}function ie(e){let t=e.match(/```(?:json)?\s*([\s\S]*?)```/i),n=t?t[1]:e.slice(e.indexOf("{"),e.lastIndexOf("}")+1);return JSON.parse(n)}function B(e){return!!(e&&typeof e=="object"&&!Array.isArray(e))}function le(e){let t=ie(e);if(!B(t))throw new Error("llm did not return a JSON object");let n=typeof t.summary=="string"&&t.summary.trim()?t.summary.trim().slice(0,500):"SootSim generated test",u=t.steps;if(!Array.isArray(u)||u.length===0)throw new Error("llm returned no flow steps");let l=u.map((s,a)=>{if(!B(s))throw new Error(`flow step ${a+1} is not an object`);return s});return{summary:n,steps:l,yamlText:L.stringify(l)}}function ae(e,t,n,u){let l=[n,"--preview","--preview-origin",u,"--billing-kind","test_run"],s=new Set(["--public-origin","--preview-public-origin","--owner","--repo","--url","--driver","--sim","--device","--slow","--tail-wait","--remap","--replace"]),a=new Set(["--new","--headless","--headed","--electron","--preview-open","--no-shell","--shell-only"]);for(let o=0;o<e.length;o++){if(o===t)continue;let i=e[o];if(i==="--origin"||i==="--preview-origin"){o+=1;continue}if(i==="--public-origin"){let c=e[o+1];c&&l.push("--preview-public-origin",c),o+=1;continue}if(s.has(i)){let c=e[o+1];c&&l.push(i,c),o+=1;continue}a.has(i)&&l.push(i)}return l}async function ce(e,t,n,u){let l=O();(!l||l.kind==="github")&&(console.error(' sootsim test "<prompt>" needs a login or SOOTSIM_API_KEY.'),console.error(" API keys must include preview_upload and llm scopes."),process.exit(1));let s=M(l),a=await k(C(n,["--origin","--preview-origin"]));console.log(" inspecting current sim\u2026");let o=await ne(n,t);console.log(" generating flow\u2026");let i=await se({prompt:e,describe:o,origin:a,authHeader:s}),c=le(i),p=H(R(K(),"sootsim-test-")),r=R(p,"flow.yaml");G(r,c.yamlText),console.log(` flow: ${r}`);let m=Date.now(),{runFlowPlayback:d,getLastFlowPreviewUploadResult:v,getLastFlowTraceSteps:y}=await import("./flow-JHQNIALS.js"),w=ae(n,t,r,a),g=await d(w),f=v(),b=y(),V=b.find(W=>W.status==="failure"),T=g===0?"passed":"failed",x=await A({origin:a,kind:"nl",prompt:e,summary:c.summary,status:T,failureMessage:T==="failed"?V?.error??"flow playback failed":null,previewShareId:f?.shareId??null,owner:h(n,"--owner")??null,repo:h(n,"--repo")??null,durationMs:Date.now()-m,flowYamlSizeBytes:Buffer.byteLength(c.yamlText,"utf8"),...P(b),auth:l});console.log(`
|
|
67
|
-
result: ${T}`),x&&console.log(` run: ${x.id}`),f?.previewUrl&&console.log(` preview: ${f.previewUrl}`),x?.traceUrl&&console.log(` replay: ${x.traceUrl}`),process.exit(g)}async function ue(e,t){let n=["playwright","test"],u=e.find((o,i)=>e[i-1]==="-t")||e.find((o,i)=>e[i-1]==="--testNamePattern")||e.find((o,i)=>e[i-1]==="--grep");u&&n.push("-g",u),e.includes("--watch")&&n.push("--ui");let l=new Set(["--flows","--detox","--parallel","--watch","--reporter","-t","--testNamePattern","--grep"]);for(let o=0;o<e.length;o++){if(l.has(e[o])){(e[o]==="-t"||e[o]==="--testNamePattern"||e[o]==="--grep"||e[o]==="--reporter")&&o++;continue}n.push(e[o])}console.log(` running: npx ${n.join(" ")}`);let s=Y("npx",n,{cwd:$,stdio:"inherit",env:{...process.env}}),a=await new Promise(o=>{s.on("exit",i=>o(i||0))});process.exit(a)}async function pe(e,t,n,u){let l=["flows","test/flows","e2e/flows",".maestro","maestro"],s=[];for(let p of l){let r=S($,p);if(_(r)){let m=I(r).filter(d=>d.endsWith(".yaml")||d.endsWith(".yml"));for(let d of m)s.push(S(r,d))}}for(let p of l){let r=S(process.cwd(),p);if(!r.startsWith($)&&_(r)){let m=I(r).filter(d=>d.endsWith(".yaml")||d.endsWith(".yml"));for(let d of m)s.push(S(r,d))}}s.length===0&&(console.log(" no flow files found in flows/, test/flows/, or e2e/flows/"),process.exit(0)),console.log(` found ${s.length} flow(s)`);let a=O(),o=await k(C(e,["--origin","--preview-origin"])),i=0,c=0;for(let p of s){let r=1,m=Date.now();try{let{runFlowPlayback:w}=await import("./flow-JHQNIALS.js"),g=t.port?`http://localhost:${t.port}`:"http://localhost:5173";r=await w([p,"--url",g,"--new"])}catch{r=1}r===0?i++:c++;let{getLastFlowPreviewUploadResult:d,getLastFlowTraceSteps:v}=await import("./flow-JHQNIALS.js"),y=d();if(N({uploadedShare:!!y,auth:a})){let w=v(),g=w.find(b=>b.status==="failure"),f=await A({origin:o,kind:"flow",name:X(process.cwd(),p),status:r===0?"passed":"failed",failureMessage:r===0?null:g?.error??"flow playback failed",previewShareId:y?.shareId??null,owner:h(e,"--owner")??null,repo:h(e,"--repo")??null,durationMs:Date.now()-m,...P(w),auth:a});f&&console.log(` run: ${f.id}${f.traceUrl?` \xB7 replay: ${f.traceUrl}`:""}`)}}console.log(`
|
|
68
|
-
results: ${i} passed, ${c} failed (${s.length} total)
|
|
69
|
-
`),process.exit(c>0?1:0)}export{Te as runTest};
|
|
@@ -1,4 +0,0 @@
|
|
|
1
|
-
/*! sootsim v0.1.209 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
|
|
2
|
-
import{a as c}from"./chunk-44EPIO7S.js";import{e as a}from"./chunk-GGPPDEWU.js";import"./chunk-YC4E3DRA.js";import"./chunk-4N2A7WPD.js";import"./chunk-2N7YUIB6.js";import{K as l,h as s}from"./chunk-OVT65DWK.js";import{a as r}from"./chunk-7XXN43QW.js";import"./chunk-YB7GMFBR.js";import{spawn as u}from"node:child_process";import d from"node:fs";import m from"node:path";var g="https://registry.npmjs.org/sootsim/latest";async function I(o){let n=o.indexOf("--channel"),t=n>=0&&o[n+1]?o[n+1]:void 0;console.log(`sootsim upgrade
|
|
3
|
-
`),console.log("runtime:");let e=a();e&&(console.log(` pinned to ${e} \u2014 installing the pin, not channel latest`),console.log(" (run `sootsim runtime unpin` to follow latest again)")),await c(["install",...t?["--channel",t]:[]],{}),console.log(`
|
|
4
|
-
cli:`),await f()}function p(){if(s())return{kind:"dev"};let o=process.argv[1]??"";try{o=d.realpathSync(o)}catch{}let n=m.sep;return o.includes(`${n}_npx${n}`)||o.includes(`${n}.bunx${n}`)?{kind:"npx"}:o.includes(`${n}.bun${n}`)?{kind:"global",command:"bun",args:["add","-g","sootsim@latest"]}:o.includes(`${n}pnpm${n}`)?{kind:"global",command:"pnpm",args:["add","-g","sootsim@latest"]}:{kind:"global",command:"npm",args:["i","-g","sootsim@latest"]}}async function f(){let o=r(),n=await v();if(!n){console.log(` v${o} \u2014 couldn't reach the npm registry, skipped`);return}if(l(n,o)<=0){console.log(` v${o} (latest)`);return}let t=p();if(console.log(` v${o} \u2192 v${n}`),t.kind==="dev"){console.log(" running from the soot dev checkout \u2014 pull instead of upgrading");return}if(t.kind==="npx"){console.log(" running from the npx cache \u2014 get the latest with:"),console.log(" npx sootsim@latest");return}let e=`${t.command} ${t.args.join(" ")}`;console.log(` updating global install (${e})\u2026`),await h(t.command,t.args)?console.log(` updated to v${n}`):(console.log(" update failed \u2014 run it yourself:"),console.log(` ${e}`))}function h(o,n){return new Promise(t=>{let e=u(o,n,{stdio:"inherit"});e.on("error",()=>t(!1)),e.on("exit",i=>t(i===0))})}async function v(){try{let o=await fetch(g,{headers:{accept:"application/json"},signal:AbortSignal.timeout(8e3)});if(!o.ok)return null;let n=await o.json();return typeof n.version=="string"&&n.version?n.version:null}catch{return null}}export{I as runUpgrade};
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
/*! sootsim v0.1.209 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
|
|
2
|
-
import{a,b,c}from"./chunk-JUBCRVXK.js";import"./chunk-3MSLDFKZ.js";import"./chunk-CNHZWLE3.js";import"./chunk-UQX3RDUO.js";import"./chunk-YC4E3DRA.js";import"./chunk-56YCENXG.js";import"./chunk-JXOQBX5R.js";import"./chunk-IELT7YPL.js";import"./chunk-4N2A7WPD.js";import"./chunk-2N7YUIB6.js";import"./chunk-OVT65DWK.js";import"./chunk-YB7GMFBR.js";export{a as resolveDefaultUploadOrigin,b as resolvePublicPreviewOrigin,c as runUpload};
|