sootsim 0.1.183 → 0.1.185
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 +22 -19
- package/dist-cli/bin.js +6 -6
- package/dist-cli/chunks/{agent-AFAFZKMT.js → agent-VF756RZU.js} +2 -2
- package/dist-cli/chunks/{agent-wrapper-MV5WGYCS.js → agent-wrapper-IAFL7ROV.js} +2 -2
- package/dist-cli/chunks/{app-fonts-ERD5J644.js → app-fonts-VWLEC7ZA.js} +2 -2
- package/dist-cli/chunks/{assert-IBMYHSKD.js → assert-I55QVGG7.js} +2 -2
- package/dist-cli/chunks/beta-X6YPQVZH.js +2 -0
- package/dist-cli/chunks/{camera-Y6XUIEAP.js → camera-CYYBJH7W.js} +2 -2
- package/dist-cli/chunks/{chunk-XGVVYY6P.js → chunk-2T73IGB2.js} +2 -2
- package/dist-cli/chunks/{chunk-BTIARV2B.js → chunk-4NUQVW5P.js} +17 -4
- package/dist-cli/chunks/{chunk-FODJBAWY.js → chunk-4OUQAR34.js} +1 -1
- package/dist-cli/chunks/{chunk-RQDJPT6N.js → chunk-7OAUPGLN.js} +2 -2
- package/dist-cli/chunks/{chunk-BYKEWDZO.js → chunk-ARNLQPMQ.js} +4 -4
- package/dist-cli/chunks/{chunk-AP22KA3Q.js → chunk-BI56RR3G.js} +1 -1
- package/dist-cli/chunks/{chunk-WN6XO6JV.js → chunk-BMCBPMTC.js} +1 -1
- package/dist-cli/chunks/{chunk-64EKAMA3.js → chunk-C3UEINOZ.js} +2 -2
- package/dist-cli/chunks/{chunk-VSDVOOWG.js → chunk-C63EVPDN.js} +2 -2
- package/dist-cli/chunks/{chunk-CD3KUHS3.js → chunk-CYBRFHPU.js} +2 -2
- package/dist-cli/chunks/chunk-DZLBZGHN.js +62 -0
- package/dist-cli/chunks/{chunk-QP4W3SGO.js → chunk-E5DE33BU.js} +1 -1
- package/dist-cli/chunks/{chunk-WV7QBUFY.js → chunk-EXFB33AZ.js} +2 -2
- package/dist-cli/chunks/{chunk-QF6RJQ2U.js → chunk-FHJTTB3W.js} +2 -2
- package/dist-cli/chunks/{chunk-UXHEGFHQ.js → chunk-FUHXL6BW.js} +1 -1
- package/dist-cli/chunks/{chunk-WOOWTKM7.js → chunk-FY6DJGOS.js} +1 -1
- package/dist-cli/chunks/{chunk-YSTCZI6L.js → chunk-GX6MKIFC.js} +1 -1
- package/dist-cli/chunks/{chunk-JR7LKXPB.js → chunk-HQG4DRQ3.js} +1 -1
- package/dist-cli/chunks/chunk-IGJHME3T.js +1 -0
- package/dist-cli/chunks/{chunk-C7BIPAXT.js → chunk-IJP257WP.js} +1 -1
- package/dist-cli/chunks/chunk-JRL7PFNZ.js +463 -0
- package/dist-cli/chunks/{chunk-7SP7PFUR.js → chunk-K2THZIVC.js} +1 -1
- package/dist-cli/chunks/chunk-KOKIECMB.js +118 -0
- package/dist-cli/chunks/{chunk-IJMDXS7N.js → chunk-LI4RLX6B.js} +1 -1
- package/dist-cli/chunks/{chunk-3JW7SSYR.js → chunk-LJ3SOZBF.js} +2 -2
- package/dist-cli/chunks/{chunk-6TNJLDAQ.js → chunk-M3P67TBN.js} +1 -1
- package/dist-cli/chunks/{chunk-OIFGVAV2.js → chunk-MADEJDFD.js} +1 -1
- package/dist-cli/chunks/{chunk-RC3FKTYP.js → chunk-NL5IFN4T.js} +2 -2
- package/dist-cli/chunks/chunk-OAHGYDJR.js +13 -0
- package/dist-cli/chunks/{chunk-RQXZANGL.js → chunk-PDLQWZN4.js} +1 -1
- package/dist-cli/chunks/{chunk-KSV6H2IC.js → chunk-PIUKLO3W.js} +1 -1
- package/dist-cli/chunks/{chunk-FO3RPGBR.js → chunk-PKZNXDUJ.js} +2 -2
- package/dist-cli/chunks/{chunk-N2EXJ7HK.js → chunk-QQ4NSPAD.js} +2 -2
- package/dist-cli/chunks/{chunk-W3G5M4UB.js → chunk-QTFCJYBF.js} +3 -3
- package/dist-cli/chunks/{chunk-CPZNH3B3.js → chunk-R4KLD4P4.js} +3 -3
- package/dist-cli/chunks/chunk-SL6565MR.js +1 -0
- package/dist-cli/chunks/{chunk-QQDPEM7F.js → chunk-TFZO277G.js} +1 -1
- package/dist-cli/chunks/{chunk-4FVYQIRB.js → chunk-TNHF6BON.js} +1 -1
- package/dist-cli/chunks/{chunk-L3FPLPA4.js → chunk-TUF6EPCQ.js} +2 -2
- package/dist-cli/chunks/chunk-V4M2R6FZ.js +2 -0
- package/dist-cli/chunks/{chunk-6GCEDCO5.js → chunk-V5JEPE3P.js} +2 -2
- package/dist-cli/chunks/{chunk-PY4P54SD.js → chunk-WBY4JJ2K.js} +2 -2
- package/dist-cli/chunks/{chunk-RAEIXWER.js → chunk-WEJKLJ4B.js} +2 -2
- package/dist-cli/chunks/{chunk-SGWTX6CO.js → chunk-X4KS33ZC.js} +2 -2
- package/dist-cli/chunks/{chunk-HW65ZTXM.js → chunk-XU5EMZ4B.js} +2 -2
- package/dist-cli/chunks/cli-version-ICHQMND6.js +2 -0
- package/dist-cli/chunks/{compat-ZTFIQOVI.js → compat-ZJA3N4ZT.js} +3 -3
- package/dist-cli/chunks/{control-XWU7LZWC.js → control-CZFSYSYG.js} +2 -2
- package/dist-cli/chunks/{cpu-profile-3F2OQNCM.js → cpu-profile-ACSQMVXY.js} +2 -2
- package/dist-cli/chunks/daemon-337B4P3B.js +2 -0
- package/dist-cli/chunks/{debug-7MIHREPG.js → debug-W2ZOVTQO.js} +3 -3
- package/dist-cli/chunks/{detox-CDYD54PS.js → detox-ANJO6T27.js} +2 -2
- package/dist-cli/chunks/{device-H53IDQ67.js → device-KPPN4KYD.js} +2 -2
- package/dist-cli/chunks/{diagnose-YWSZCFPG.js → diagnose-5PEJYGES.js} +2 -2
- package/dist-cli/chunks/drivers-MSDIFHBD.js +2 -0
- package/dist-cli/chunks/electron-U456QLSQ.js +19 -0
- package/dist-cli/chunks/flow-JL3SC6HC.js +2 -0
- package/dist-cli/chunks/help-PA4RTR5X.js +2 -0
- package/dist-cli/chunks/{hints-BYH6BMHP.js → hints-MBBQLMQU.js} +2 -2
- package/dist-cli/chunks/{home-paths-AXKOJS62.js → home-paths-KQKYP2SE.js} +2 -2
- package/dist-cli/chunks/{inspect-TGQU6MZQ.js → inspect-ZP5SM4EW.js} +62 -62
- package/dist-cli/chunks/{install-desktop-AOJACCWA.js → install-desktop-OR6ZJ43X.js} +4 -4
- package/dist-cli/chunks/{keys-RC6SP7XY.js → keys-JSQMBUE7.js} +2 -2
- package/dist-cli/chunks/{login-EQDNEJFU.js → login-DVMWAI3G.js} +4 -4
- package/dist-cli/chunks/{logout-QEDUWSSY.js → logout-RIVPFE5N.js} +2 -2
- package/dist-cli/chunks/{maestro-6SVETVRL.js → maestro-TX6FPTVH.js} +8 -6
- package/dist-cli/chunks/optional-demo-registry-ONYG6DUI.js +2 -0
- package/dist-cli/chunks/{preview-UNXWRROE.js → preview-3AD7WNA6.js} +2 -2
- package/dist-cli/chunks/{profile-UBHQS25I.js → profile-HY55VFNR.js} +2 -2
- package/dist-cli/chunks/{react-THVP5NZX.js → react-HDRCKCKV.js} +2 -2
- package/dist-cli/chunks/{record-SOACBRM3.js → record-HW4C7QYN.js} +2 -2
- package/dist-cli/chunks/runtime-RHHPW5WO.js +2 -0
- package/dist-cli/chunks/{screenshot-MJKWIVV6.js → screenshot-XFR3QN5T.js} +2 -2
- package/dist-cli/chunks/{screenshot-mode-RP67FQSA.js → screenshot-mode-Y5CVO267.js} +2 -2
- package/dist-cli/chunks/{screenshots-LWDOE4RD.js → screenshots-RKUL2ZZT.js} +2 -2
- package/dist-cli/chunks/{screenshots-capture-RUXUL5GO.js → screenshots-capture-RVNF75ZD.js} +8 -8
- package/dist-cli/chunks/{serve-TMMMRVTI.js → serve-QMRYLWL5.js} +2 -2
- package/dist-cli/chunks/setup-ELNJS7AI.js +97 -0
- package/dist-cli/chunks/{skills-P3HEQGPB.js → skills-GPSJYS4W.js} +2 -2
- package/dist-cli/chunks/{slides-MICILFXO.js → slides-OCFNPIFG.js} +2 -2
- package/dist-cli/chunks/store-MBKDUQEQ.js +2 -0
- package/dist-cli/chunks/telemetry-46XXIUEE.js +2 -0
- package/dist-cli/chunks/{telemetry-7ZVCPD7R.js → telemetry-KFZQUFG5.js} +2 -2
- package/dist-cli/chunks/{test-NT7SGPG5.js → test-Z2HZXCZM.js} +3 -3
- package/dist-cli/chunks/{three-mode-6ADYURNM.js → three-mode-NKJFCDYS.js} +2 -2
- package/dist-cli/chunks/{timeline-JZNPRKEH.js → timeline-PRGQMQRR.js} +2 -2
- package/dist-cli/chunks/upgrade-3NW7JRRX.js +4 -0
- package/dist-cli/chunks/upload-QVDVJ6ZK.js +2 -0
- package/dist-cli/chunks/{version-GS2J6SFA.js → version-FDTZRIYT.js} +2 -2
- package/dist-cli/chunks/{web-J2XC4OK4.js → web-4N5QQEQJ.js} +2 -2
- package/dist-cli/chunks/{what-happened-O5MCMYJL.js → what-happened-IX2RRCOS.js} +2 -2
- package/dist-cli/chunks/{whoami-Z2Y2X2DN.js → whoami-QZ42FYYF.js} +2 -2
- package/dist-lib/agent-daemon-client.cjs +1 -1
- package/dist-lib/agent-events.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 +218 -47
- package/dist-lib/vite.cjs +1 -1
- package/package.json +1 -1
- package/scripts/postinstall.cjs +1 -1
- package/skills/soot.md +2 -2
- package/skills/sootsim-setup.md +7 -6
- package/dist-cli/chunks/beta-T7Z7WSTK.js +0 -2
- package/dist-cli/chunks/chunk-4HJKPRWO.js +0 -463
- package/dist-cli/chunks/chunk-77GTIGLV.js +0 -1
- package/dist-cli/chunks/chunk-B3W63SZA.js +0 -13
- package/dist-cli/chunks/chunk-D7ZB6A5T.js +0 -2
- package/dist-cli/chunks/chunk-F6DIP2WH.js +0 -62
- package/dist-cli/chunks/chunk-MBR6TG2P.js +0 -118
- package/dist-cli/chunks/chunk-NLI4YQOY.js +0 -1
- package/dist-cli/chunks/cli-version-P4SZNBPQ.js +0 -2
- package/dist-cli/chunks/daemon-CUQB4QAP.js +0 -2
- package/dist-cli/chunks/drivers-RRCIIDGS.js +0 -2
- package/dist-cli/chunks/electron-UPH35PTF.js +0 -18
- package/dist-cli/chunks/flow-ZDJI7ICC.js +0 -2
- package/dist-cli/chunks/help-U5QGSMDR.js +0 -2
- package/dist-cli/chunks/optional-demo-registry-KXYBVP4S.js +0 -2
- package/dist-cli/chunks/runtime-BAS2IZFB.js +0 -2
- package/dist-cli/chunks/setup-WYKWQPJW.js +0 -77
- package/dist-cli/chunks/store-7CIU7X6W.js +0 -2
- package/dist-cli/chunks/telemetry-LVBDBPPV.js +0 -2
- package/dist-cli/chunks/upgrade-K6V3HYCU.js +0 -4
- package/dist-cli/chunks/upload-Q2ZFKOSR.js +0 -2
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
/*! sootsim v0.1.183 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
|
|
2
|
-
import{a as F,b as Q,c as Y,d as ye,e as Se}from"./chunk-6GCEDCO5.js";import{m as T}from"./chunk-QF6RJQ2U.js";import{m as he,o as we}from"./chunk-WOOWTKM7.js";import{g as te}from"./chunk-BTIARV2B.js";import{a as O,b as X}from"./chunk-WN6XO6JV.js";import{c as ve}from"./chunk-PY4P54SD.js";import{a as Ie,b as ke}from"./chunk-4FVYQIRB.js";import{a as $e,b as Z,c as xe}from"./chunk-C7BIPAXT.js";import{b as be,c as $,d as y,e as x}from"./chunk-RQDJPT6N.js";import{d as ee}from"./chunk-JR7LKXPB.js";import{a as ge}from"./chunk-D7ZB6A5T.js";import{d as E,e as b,f as M}from"./chunk-QP4W3SGO.js";import{D as fe,I as N,K as C,l as pe}from"./chunk-AP22KA3Q.js";import{spawn as Ue}from"node:child_process";import _ from"node:fs";import Ye from"node:os";import k from"node:path";import{WebSocket as Ze}from"ws";function We(e){return e.replace(/^\[|\]$/g,"").toLowerCase()}function H(e){let t=We(e);return t==="localhost"||t.endsWith(".localhost")||t==="0.0.0.0"||t==="::1"||/^127(?:\.\d{1,3}){3}$/.test(t)}function Pe(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 je(e,t){return e?.includes("/one/metro-entry.bundle")?"one":typeof t=="string"&&t?"expo":"unknown"}function Ee(e,t,o){return`${e}//${t}:${o}`}function ze(e){if(typeof window>"u")return!1;try{let t=new URL(e);return H(t.hostname)&&H(window.location.hostname)&&t.origin!==window.location.origin}catch{return!1}}async function Ce(e,t){let o={...t,cache:t?.cache??"no-store"};return ze(e)?fetch(`/__fetch-proxy?url=${encodeURIComponent(e)}`,o):fetch(e,o)}function qe(e){return e==="https:"?443:80}function Ge(e){let t=e.pathname||"/";return(t==="/"||t==="")&&!e.search&&!e.hash}async function Ve(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:Y(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 Me(e,t){let o=e.replace(/\/+$/,"");try{if(H(new URL(o).hostname)){let n=await Ve(t);if(n)return n}}catch{}try{let n=await Ce(`${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:Y(i||`${o}${Q}`),port:t,framework:je(i,s.sdkVersion),projectName:s.name}}}catch{}try{let n=await Ce(`${o}/status`);if(n.ok&&(await n.text()).includes("packager-status:running"))return{bundleUrl:`${o}${Q}`,port:t,framework:"metro"}}catch{}return null}async function Je(e){return Me(Ee("http:","localhost",e),e)}async function Te(e){let t=e.trim();if(/^\d+$/.test(t)){let a=parseInt(t,10),l=await Je(a);if(l)return l;throw Pe(`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):qe(r),i=Ee(r,n.hostname,s);if(Ge(n)){let a=await Me(i,s);if(a)return a;throw Pe(i)}return{bundleUrl:n.toString(),port:s,framework:"unknown"}}function jt(){console.error(" no sootsim desktop companion found."),console.error(""),console.error(" install the desktop app:"),console.error(" sootsim install-desktop"),console.error(""),console.error(" or run setup to install the background daemon:"),console.error(" sootsim setup"),console.error("")}function Oe(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 electron");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 Qe(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 zt(e,t,o){let n=[];try{n=await e.listSims()}catch{}if(console.error(""),n.length===0){Qe(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 Xe=12e4,Re=100,et=5e3,_e=1e4,tt={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 v(e){return new Promise(t=>setTimeout(t,e))}function Be(e){let t=process.env[e]?.trim();if(!t)return null;let o=Number(t);return Number.isInteger(o)&&o>0?o:null}function ot(){let e=Be("SOOTSIM_DRIVER_CONNECT_TIMEOUT_MS")??Be("SOOTSIM_PW_CONNECT_TIMEOUT_MS")??Xe;return{timeoutMs:e,hostTimeoutMs:e+et,intervalMs:Re,attempts:Math.max(1,Math.ceil(e/Re))}}function nt(e){return e==="chromium"||e==="electron"||e==="playwright"||e==="system"}function rt(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 j(e){return e.trim()}var st=/^[A-Za-z][A-Za-z0-9+.-]*:/;function it(e){let t=e.trim();if(!t)throw new Error("expected <url-or-route>");return st.test(t)||t.startsWith("/")?t:`/${t}`}function at(e){return e!==null&&typeof e=="object"}async function lt(e){if(await K(e,250))return e;let t=N();if(t&&C(t)&&await K(t.bridgePort,500))return t.bridgePort;if(t&&C(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 ct();let o=dt(["serve","--quiet","--port",String(e)]),n=null;o.once("exit",(s,i)=>{n=String(s??i??"unknown")}),o.unref();let r=Date.now()+_e;for(;Date.now()<r;){let s=N();if(s&&C(s)&&await K(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 K(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 v(150)}throw new Error(`sootsim bridge did not start within ${Math.round(_e/1e3)}s`)}async function ct(){let e=fe();if(e&&_.existsSync(pe(e)))return;console.error(" installing sootsim engine runtime...");let{runRuntime:t}=await import("./runtime-BAS2IZFB.js");await t(["install"],{})}function dt(e){let t=process.argv[1];return t&&_.existsSync(t)?Ue(process.execPath,[t,...e],{detached:!0,stdio:"ignore",env:process.env}):Ue("sootsim",e,{detached:!0,stdio:"ignore",env:process.env})}function K(e,t){return new Promise(o=>{let n=new Ze(`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 re(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 mt(e){try{let t=new URL(e).pathname.replace(/\/+$/,"")||"/";return/^\/preview\/[^/]+$/.test(t)||/^\/build\/.+/.test(t)}catch{return!1}}async function ho(e){let t=j(e);return(await Ne(t)).bundleUrl}function ut(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 Ne(e){let t=j(e),o=/^\d+$/.test(t)?Number(t):ut(t);if(o&&o>0){let n=await Se(o);if(n)return{bundleUrl:n.bundleUrl,port:n.port,framework:n.framework,projectName:n.projectName}}return Te(t)}function ie(e){let t=e.replace(/\/+$/,"")||"/";return t==="/__soot"||t.startsWith("/__soot/")?"/__soot":""}function pt(e,t){let o=j(e),n=new URL(t),r=ie(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 ft(e){let t=j(e);return/^\d+$/.test(t)||/^https?:\/\//i.test(t)?!0:/^(localhost|127\.0\.0\.1|\[::1\]|[^/]+\.localhost):\d+(?:\/.*)?$/i.test(t)}async function gt(e,t,o={}){let n=await Ne(e),r=new URL(t),s=ie(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:ye(n.bundleUrl,o.hot);return r.searchParams.set("bundle",i),r.toString()}function ht(e){return e.startsWith("~/")?k.join(Ye.homedir(),e.slice(2)):k.isAbsolute(e)?e:k.resolve(process.cwd(),e)}function wt(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=ht(s.slice(i+1).trim());_.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 Fe(){let e=N();return C(e)&&e.runtimePort>0?`http://localhost:${e.runtimePort}/`:ge}async function bt(e){try{let t=new URL(e),o=t.searchParams.get("bundle")||"";if(!o)return e;let n=process.env.SOOT_REPO_DIR||await Z(o)||void 0,r=$e({bundleUrl:o,repoDir:n});if(r.length===0)return e;let s=await yt(r);return s.length===0?e:(t.searchParams.set("appFonts",xe(s)),t.toString())}catch{return e}}async function yt(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 St(e,t,o={}){if(!e)return new URL(t).toString();if(re(e))return new URL(e).toString();let n=tt[e.toLowerCase()];if(n){let r=new URL(t),s=ie(r.pathname);return r.pathname=`${s}${n}`,r.toString()}return ft(e)?gt(e,t,o):pt(e,t)}async function vt(e){try{let t=new URL(e),o=t.searchParams.get("bundle")||"";if(!o)return e;let n=process.env.SOOT_REPO_DIR||await Z(o)||void 0,r=Ie({bundleUrl:o,repoDir:n});return!r||r.imageUrl&&!await $t(r.imageUrl)?e:(t.searchParams.set("appSplash",ke(r)),t.toString())}catch{return e}}async function $t(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 W(e,t=Fe(),o={}){let n=await St(e,t,o);return vt(await bt(n))}function De(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 xt(e,t,o,n={}){let r=new URL(await W(e,t,n));return r.searchParams.set("inspectOpen",o),r.toString()}async function It(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=y(e,{commandTimeoutMs:t,simId:o,simIdSource:"flag"});try{let c=await l.send({type:"evaluate",code:"(async () => (await window.__sootsimTest?.getNodeCount()) || 0)()"});if(typeof c=="number"&&c>i)return{bridge:l,count:c}}catch{}l.close(),await v(s)}return null}function kt(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 Pt(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 Ct(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 ${Pt(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=kt(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=Et(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: ${Le(Date.now()-o.connectedAt)}`),o.lastActiveAt&&o.lastActiveAt>0&&console.log(` last active: ${Le(Date.now()-o.lastActiveAt)}`)}}function Et(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)":`runtime \u2014 published engine (:${o||"?"})`}catch{return null}}function Le(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 oe(e,t,o,n={}){let r=n.attempts??30,s=n.intervalMs??500;for(let i=0;i<r;i++){let a=y(e,{commandTimeoutMs:t});try{let c=(await a.listSims()).find(o);if(c)return c}catch{}finally{a.close()}await v(s)}return null}async function Mt(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&&!se(n);for(let c=0;c<s;c++){if(l())return{kind:"host-exit"};let d=y(e,{commandTimeoutMs:t});try{let g=(await d.listSims()).find(o);if(g)return l()?{kind:"host-exit"}:{kind:"match",sim:g}}catch{}finally{d.close()}if(l())return{kind:"host-exit"};await v(i)}return{kind:"timeout"}}async function Tt(e,t,o,n={}){let r=n.attempts??20,s=n.intervalMs??250;for(let i=0;i<r;i++){let a=y(e,{commandTimeoutMs:t});try{let c=(await a.listSims()).find(d=>d.id===o);if(!c||c.readyState!=="open")return!0}catch{return!0}finally{a.close()}await v(s)}return!1}function Ot(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 Ut(e){if(!e.connectAckFile)return!1;try{return _.writeFileSync(e.connectAckFile,`${JSON.stringify({connectedAt:Date.now(),pid:e.pid??null})}
|
|
4
|
-
`,{flag:"w"}),!0}catch{return!1}}function Ae(e){if(e.diagnosticLogPath)try{let t=_.readFileSync(e.diagnosticLogPath,"utf8").trim();if(!t){console.error(` ${k.basename(e.diagnosticLogPath)} was empty`);return}let o=t.length>4e3?`\u2026
|
|
5
|
-
${t.slice(-4e3)}`:t;console.error(` ${k.basename(e.diagnosticLogPath)}:`),console.error(o)}catch(t){let o=t instanceof Error?t.message:String(t);console.error(` failed to read ${k.basename(e.diagnosticLogPath)}: ${o}`)}}function se(e){try{return process.kill(e,0),!0}catch(t){return t?.code==="EPERM"}}async function Rt(e,t=2500){let o=Date.now()+t;for(;Date.now()<o;){if(!se(e))return!0;await v(100)}return!se(e)}async function ne(e,t){let o=new Set(t),n=new Set;for(let r of e){if(!o.has(r.id))continue;let s=Ot(r);s&&n.add(s)}for(let r of n){try{process.kill(r,"SIGTERM")}catch{}if(await Rt(r)){console.log(` closed playwright host process ${r}`);continue}try{process.kill(r,"SIGKILL"),console.log(` force-closed playwright host process ${r}`)}catch{}}}function z(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 U(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 R(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 _t(e,t,{stableMs:150,maxMs:400});let r=y(e,{commandTimeoutMs:3e3,simId:t,cliLabel:"open --describe",simIdSource:"flag"});try{let s=null;try{s=await r.send({type:"evaluate",code:he})}catch{}if(s&&!(s.flag===!0&&!s.loadingText&&we(s))){let d=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: ${d} (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 c=[`state=${l.shell.state}`,l.shell.activeApp?`app=${l.shell.activeApp}`:null].filter(Boolean);console.log(` shell: ${c.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 _t(e,t,o){let n=Date.now()+o.maxMs,r="(async () => (await window.__sootsimTest?.getNodeCount?.()) || 0)()",s=y(e,{commandTimeoutMs:2e3,simId:t,simIdSource:"flag"});try{let i=-1,a=0;for(;Date.now()<n;){let l=-1;try{let c=await s.send({type:"evaluate",code:r});typeof c=="number"&&(l=c)}catch{}if(l>=0&&l===i){if(Date.now()-a>=o.stableMs)return}else i=l,a=Date.now();await v(50)}}finally{s.close()}}async function wo(e,t={}){let o=$(e,{port:t.port,commandTimeoutMs:t.timeoutMs}),n=x(o);try{let r=await n.listSims();Ct(r,o.simId)}finally{n.close()}}async function bo(e,t={}){let o=$(e,{port:t.port,commandTimeoutMs:t.timeoutMs});o.positional.length!==1&&(console.error(" sootsim link: expected exactly one <url-or-route>"),console.error(" examples: sootsim link /settings | sootsim link myapp://settings"),process.exit(1));let n;try{n=it(o.positional[0]??"")}catch(i){console.error(` sootsim link: ${i instanceof Error?i.message:String(i)}`),process.exit(1)}let r=x(o),s=o.simId?` --sim ${o.simId}`:"";try{let i=await r.send({type:"call",path:"SootSim.bridges.test.openDeepLink",args:[n]});if(at(i)&&i.ok===!1)throw new Error(typeof i.error=="string"?i.error:"deep-link dispatch failed");console.log(` linked: ${n}`)}catch(i){console.error(` link failed: ${i instanceof Error?i.message:String(i)}`),await T(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 yo(e,t={}){let o=$(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"]}),n=e.find((u,p)=>e[p-1]==="--profile"),r=e.includes("--ephemeral"),s=e.find((u,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?ve(n).id:void 0,l=!!a||r,c=e.includes("--new")||l,d=wt(e);c&&o.simIdSource==="flag"&&(console.error(" sootsim open: --new, --profile, and --ephemeral cannot be combined with --sim"),process.exit(1));let m=o.positional[0]||"";if(mt(m)){let u=(()=>{try{return/^(localhost|127\.0\.0\.1|\[::1\]|::1)$/i.test(new URL(m).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 ee(m,{background:!1})}catch(p){console.error(` could not launch a browser: ${p instanceof Error?p.message:String(p)}`),console.error(` open it yourself: ${m}`),process.exit(1)}console.log(u?" 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}o.wsPort=await lt(o.wsPort);let g=e.find((u,p)=>e[p-1]==="--driver")||"",q=rt(e,g);i&&g!=="playwright"&&(console.error(" sootsim open: --cdp-port is only honored by the playwright driver \u2014 add `--driver playwright`"),process.exit(1));let ae=e.includes("--hot"),le=e.includes("--no-hmr");ae&&le&&(console.error(" sootsim open: --hot and --no-hmr cannot be combined"),process.exit(1));let B={hot:ae?!0:le?!1:g!=="playwright"},P=e.find((u,p)=>e[p-1]==="--base-url")||Fe(),ce=e.includes("--base-url"),de=E();if(!g&&!c&&(o.simIdSource==="flag"||o.simIdSource==="saved"&&!!de)){let u=x(o),p=o.simId?` --sim ${o.simId}`:"",f=!1;try{let h=null;try{let w=await u.listSims();if(o.simIdSource==="saved"?(h=w.find(I=>I.id===de&&I.readyState==="open")??null,h||M()):h=z(w,o.simId),!h)if(o.simIdSource==="saved")f=!0;else throw new Error("no sim connected");if(!f&&h){let I=ce||re(m)?P:De(h,P),A=await W(m,F(I,d),B);u.send({type:"evaluate",simId:h.id,code:`window.location.href = ${JSON.stringify(A)}`}).catch(()=>{})}}catch(w){console.error(` open failed: ${w instanceof Error?w.message:String(w)}`),await T(u,{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 v(1500);let w=await It(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 I=ce||re(m)?P:De(h,P),A=await W(m,F(I,d),B);U(A,{...h,url:A},"current sim"),await R(o.wsPort,h.id,e);return}}finally{u.close()}}let me=F(P,d),Ke=await W(m,me,B),ue=`cli-${Date.now().toString(36)}-${Math.random().toString(36).slice(2,8)}`,S=await xt(m,me,ue,B),G={newWindow:!0},D=u=>u.url?.includes(`inspectOpen=${ue}`)??!1;if(g){nt(g)||(console.error(` unknown driver "${g}" \u2014 run \`sootsim list --drivers\``),process.exit(1));let u=te(g);u||(console.error(` unknown driver "${g}" \u2014 run \`sootsim list --drivers\``),process.exit(1));let p=ot(),f=await u.launch({url:S,headless:q,newWindow:G.newWindow,profileId:a,ephemeralProfile:r,cdpPort:i,connectTimeoutMs:p.hostTimeoutMs});f.launched||(console.error(` ${u.name} driver: ${f.message}`),process.exit(1));let h=await Mt(o.wsPort,o.commandTimeoutMs,D,f.pid,{attempts:p.attempts,intervalMs:p.intervalMs});if(h.kind==="host-exit"&&(Ae(f),console.error(` ${u.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 ${u.name} host process ${f.pid}`)}catch{}Ae(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),Ut(f),U(S,w,`${u.name} driver`),await R(o.wsPort,w.id,e);return}if(l){let u=O();u||(console.error(" profiles require electron or playwright; install the desktop companion or use `--driver playwright`"),process.exit(1));try{(await X(S,u,{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 oe(o.wsPort,o.commandTimeoutMs,D,{attempts:40,intervalMs:500});p||(console.error(" timed out waiting for profiled sim to connect"),process.exit(1)),b(p.id),U(S,p,"desktop companion"),await R(o.wsPort,p.id,e);return}let V=!1,J=!1;try{let u=y(o.wsPort,{commandTimeoutMs:2e3});try{await u.listSims(),V=!0}finally{u.close()}}catch{}if(V)try{let u=y(o.wsPort,{commandTimeoutMs:3e3});try{await u.openUrl(S,G),J=!0}finally{u.close()}}catch{}if(!J){let u=O();if(u)try{if((await X(S,u)).launched){let f=await oe(o.wsPort,o.commandTimeoutMs,D,{attempts:20,intervalMs:500});if(f){b(f.id),U(S,f,"desktop companion"),await R(o.wsPort,f.id,e);return}}}catch{}try{await ee(S,G)}catch(p){console.error(` open failed: ${p instanceof Error?p.message:String(p)}`),te("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(!V){console.log(` opened: ${Ke}`),Oe(o.wsPort);return}}let L=await oe(o.wsPort,o.commandTimeoutMs,D,{attempts:30,intervalMs:500});L||(console.error(" timed out waiting for opened sim to connect"),process.exit(1)),b(L.id),U(S,L,J?"bridge":"direct shell open"),await R(o.wsPort,L.id,e)}async function He(e,t={}){let o=$(e,{port:t.port,commandTimeoutMs:t.timeoutMs,stripBooleanFlags:["--force"]}),n=e.includes("--force"),r=x(o),s=o.simId?` --sim ${o.simId}`:"";try{try{let i=await r.listSims(),a=z(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 T(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 So(e,t={}){await He(e,t)}async function vo(e,t={}){await He(e,t)}async function $o(e,t={}){let o=$(e,{port:t.port,commandTimeoutMs:t.timeoutMs,stripBooleanFlags:["--force"]}),n=e.includes("--force"),r=x(o);try{try{let s=await r.listSims(),i=z(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 c=Math.max(0,Math.round((l.lockExpiresAt-Date.now())/1e3)),d=l.bootedCount>0?` (booted ${l.bootedCount})`:"";console.log(` claimed: ${l.simId} [${c}s]${d}`),a&&console.log(` took over from: ${a}`)}catch(s){if(s instanceof be){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 Bt(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=y(t,{commandTimeoutMs:o});try{i=(await a.listSims()).filter(c=>r.has(c.id)&&c.readyState==="open").map(c=>c.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 v(250)}return{closed:[...r],remaining:[]}}function Dt(e,t){let o=e.filter(m=>m.readyState==="open"),n=o.map(m=>m.id),r=t.explicitKeepId?.trim()||"",s=t.savedKeepId?.trim()||"",i=s?o.some(m=>m.id===s):!1,a=s&&!i?s:null,l=null,c=null,d=null;if(t.closeOthers)if(r){let m=o.find(g=>g.id===r);m?l=m.id:c=r}else if(s&&i)l=s;else{let m=o.find(g=>g.isPrimary)??o[0]??null;m&&(l=m.id,s&&!i&&(d=m.id))}return{openIds:n,keepId:l,targets:c?[]:n.filter(m=>m!==l),staleSavedId:a,missingExplicitKeepId:c,fallbackKeepId:d}}async function xo(e,t={}){let o=$(e,{port:t.port,commandTimeoutMs:t.timeoutMs,stripBooleanFlags:["--all","--others"]}),n=x(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=E(),c=o.positional[0]||(o.simIdSource==="flag"?o.simId:void 0),d=Dt(a,{closeOthers:i,explicitKeepId:c,savedKeepId:l});if(d.staleSavedId&&M(),d.fallbackKeepId&&(b(d.fallbackKeepId),console.log(` saved sim ${d.staleSavedId} is gone \u2014 keeping primary ${d.fallbackKeepId}`)),d.missingExplicitKeepId&&(console.error(` close failed: keep sim ${d.missingExplicitKeepId} is not connected; not closing other sims`),process.exit(1)),d.targets.length===0){console.log(d.keepId?` nothing to close \u2014 only the kept sim ${d.keepId} is connected`:d.staleSavedId?` nothing to close \u2014 no sims connected (cleared stale current sim ${d.staleSavedId})`:" nothing to close \u2014 no sims connected");return}let m=await Bt(n,o.wsPort,o.commandTimeoutMs,d.targets);await ne(a,d.targets);let g=E();g&&m.closed.includes(g)&&(d.keepId?b(d.keepId):M());let q=` closed ${m.closed.length} sim(s)${d.keepId?` (kept ${d.keepId})`:""}`;console.log(q),m.remaining.length>0&&(console.error(` close failed: still connected: ${m.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=z(a,o.positional[0]||o.simId),c=a.find(m=>m.id!==l.id&&m.readyState==="open");await n.closeSim(l.id),await Tt(o.wsPort,o.commandTimeoutMs,l.id)||(await ne(a,[l.id]),console.error(` close failed: ${l.id} is still connected`),process.exit(1)),await ne(a,[l.id]),E()===l.id&&(c?b(c.id):M()),console.log(` closed: ${l.id}`)}catch(a){console.error(` close failed: ${a instanceof Error?a.message:String(a)}`),await T(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{jt as a,Qe as b,zt as c,ot as d,it as e,ho as f,Fe as g,W as h,xt as i,kt as j,Ct as k,oe as l,Mt as m,Ot as n,Ut as o,ne as p,wo as q,bo as r,yo as s,So as t,vo as u,$o as v,Bt as w,Dt as x,xo as y};
|
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
/*! sootsim v0.1.183 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
|
|
2
|
-
import{a as C,b as _}from"./chunk-VSDVOOWG.js";import{c as R}from"./chunk-SGWTX6CO.js";import{g as T,j as E,r as N,s as b,t as B}from"./chunk-AP22KA3Q.js";import{a as Y}from"./chunk-YSTCZI6L.js";import{execFileSync as tt,spawnSync as s}from"child_process";import{existsSync as c,mkdirSync as x,readFileSync as et,rmSync as $,writeFileSync as M}from"fs";import{homedir as D}from"os";import{dirname as j,resolve as f}from"path";import{execFileSync as G}from"child_process";import{chmodSync as W,mkdirSync as P,rmSync as K,writeFileSync as L}from"fs";import{dirname as A}from"path";var X="dev.sootsim.daemon",U="SootSim Daemon",O="0.1.36";function F(t,e,r){let o=b(),n=B(),a=A(A(n)),l=A(n),u=`${a}/Resources`;K(o,{recursive:!0,force:!0}),P(N(),{recursive:!0}),P(l,{recursive:!0}),P(u,{recursive:!0}),L(`${a}/Info.plist`,Q()),L(`${a}/PkgInfo`,"APPL????"),L(n,z(t,e,r)),W(n,493);try{G("codesign",["--force","--sign","-","--deep",o],{stdio:"pipe"})}catch(i){let p=i instanceof Error?i.message:String(i);console.warn(` warning: ad-hoc codesign of ${o} failed: ${p}
|
|
3
|
-
the daemon will still run, but Login Items may show a generic name.`)}return{bundlePath:o,launcherPath:n}}function Q(){return`<?xml version="1.0" encoding="UTF-8"?>
|
|
4
|
-
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
5
|
-
<plist version="1.0">
|
|
6
|
-
<dict>
|
|
7
|
-
<key>CFBundleDevelopmentRegion</key><string>en</string>
|
|
8
|
-
<key>CFBundleDisplayName</key><string>${U}</string>
|
|
9
|
-
<key>CFBundleExecutable</key><string>sootsim-daemon</string>
|
|
10
|
-
<key>CFBundleIdentifier</key><string>${X}</string>
|
|
11
|
-
<key>CFBundleInfoDictionaryVersion</key><string>6.0</string>
|
|
12
|
-
<key>CFBundleName</key><string>${U}</string>
|
|
13
|
-
<key>CFBundlePackageType</key><string>APPL</string>
|
|
14
|
-
<key>CFBundleShortVersionString</key><string>${O}</string>
|
|
15
|
-
<key>CFBundleSignature</key><string>????</string>
|
|
16
|
-
<key>CFBundleVersion</key><string>${O}</string>
|
|
17
|
-
<key>LSBackgroundOnly</key><true/>
|
|
18
|
-
<key>LSUIElement</key><true/>
|
|
19
|
-
<key>LSMinimumSystemVersion</key><string>13.0</string>
|
|
20
|
-
<key>NSHumanReadableCopyright</key><string>Tamagui LLC</string>
|
|
21
|
-
</dict>
|
|
22
|
-
</plist>
|
|
23
|
-
`}function z(t,e,r){let n=[t.executable,...t.prefixArgs,"serve","--quiet","--port",String(e)].map(J).join(" ");return`#!/bin/sh
|
|
24
|
-
# SootSim Daemon launcher \u2014 auto-generated by 'sootsim setup'.
|
|
25
|
-
# launchd spawns this; we exec the real sootsim invocation in place so
|
|
26
|
-
# launchd tracks the daemon process, not the shell wrapper.
|
|
27
|
-
#
|
|
28
|
-
# stdout: ${r.stdout}
|
|
29
|
-
# stderr: ${r.stderr}
|
|
30
|
-
exec ${n}
|
|
31
|
-
`}function J(t){return`'${t.replace(/'/g,"'\\''")}'`}var q=60,y="dev.sootsim.daemon",m="sootsim-daemon",g=f(D(),"Library/Logs/sootsim"),v=f(D(),".local/state/sootsim");async function Tt(t,e={}){let[r,...o]=t,n=e.port??7668;if(!r||r==="--help"||r==="-h"){V();return}new Set(["uninstall","restart","start","stop","logs"]).has(r)&&C({event:`daemon_${r}`,properties:{platform:process.platform,subsource:"daemon"}});try{switch(r){case"uninstall":return await ut();case"status":return await pt();case"restart":return await dt();case"start":return await mt();case"stop":return await gt();case"logs":return await ft(o);default:console.error(` unknown daemon subcommand: ${r}`),V(),process.exit(1)}}finally{await _()}}function V(){R("daemon")}function rt(){let t=ot();return{executable:process.execPath,prefixArgs:[t]}}function ot(){try{let e=tt("which",["sootsim"],{encoding:"utf8"}).trim();if(e&&c(e))return H(e)}catch{}let t=process.argv[1];if(t&&c(t))return H(t);throw new Error("could not locate the sootsim binary")}function H(t){try{return Y("fs").realpathSync(t)}catch{return t}}function nt(t,e){x(g,{recursive:!0});let r=f(g,"bridge.out.log"),o=f(g,"bridge.err.log"),{launcherPath:n}=F(t,e,{stdout:r,stderr:o}),a=` <string>${it(n)}</string>`;return`<?xml version="1.0" encoding="UTF-8"?>
|
|
32
|
-
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
33
|
-
<plist version="1.0">
|
|
34
|
-
<dict>
|
|
35
|
-
<key>Label</key><string>${y}</string>
|
|
36
|
-
<key>ProgramArguments</key>
|
|
37
|
-
<array>
|
|
38
|
-
${a}
|
|
39
|
-
</array>
|
|
40
|
-
<key>RunAtLoad</key><true/>
|
|
41
|
-
<key>KeepAlive</key><true/>
|
|
42
|
-
<key>ThrottleInterval</key><integer>${q}</integer>
|
|
43
|
-
<key>ProcessType</key><string>Background</string>
|
|
44
|
-
<key>StandardOutPath</key><string>${r}</string>
|
|
45
|
-
<key>StandardErrorPath</key><string>${o}</string>
|
|
46
|
-
</dict>
|
|
47
|
-
</plist>
|
|
48
|
-
`}function st(t,e){return x(v,{recursive:!0}),`[Unit]
|
|
49
|
-
Description=sootsim bridge daemon
|
|
50
|
-
After=default.target
|
|
51
|
-
|
|
52
|
-
[Service]
|
|
53
|
-
Type=simple
|
|
54
|
-
ExecStart=${[t.executable,...t.prefixArgs].map(at).join(" ")} serve --quiet --port ${e}
|
|
55
|
-
Restart=always
|
|
56
|
-
RestartSec=${q}
|
|
57
|
-
|
|
58
|
-
[Install]
|
|
59
|
-
WantedBy=default.target
|
|
60
|
-
`}function it(t){return t.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'")}function at(t){return/[^\w@%+=:,./-]/.test(t)?`'${t.replace(/'/g,"'\\''")}'`:t}function S(){return f(D(),"Library/LaunchAgents",`${y}.plist`)}function w(){return f(D(),".config/systemd/user",`${m}.service`)}function Nt(){if(E())return{supported:!1,installed:!1};if(process.platform==="darwin"){let t=S();return{supported:!0,installed:c(t),path:t}}if(process.platform==="linux"){let t=w();return{supported:!0,installed:c(t),path:t}}return{supported:!1,installed:!1}}async function Bt({port:t,force:e}){if(E())throw new Error("background daemon setup is unavailable in this environment");let r=rt();if(console.log(` binary: ${[r.executable,...r.prefixArgs].join(" ")}`),console.log(` port: ${t}`),process.platform==="darwin"){let o=S();if(c(o)&&!e){console.log(` already installed at ${o}`),console.log(" pass --force to overwrite, or use 'sootsim daemon restart' to reload");return}x(j(o),{recursive:!0}),M(o,nt(r,t)),console.log(` wrote ${o}`);let n=`gui/${process.getuid()}`,a=`${n}/${y}`,l=()=>{let d=s("launchctl",["bootstrap",n,o],{stdio:"pipe",encoding:"utf8"}),k=(d.stderr||d.stdout||"").trim();if(d.status!==0)return{ok:!1,reason:`bootstrap exit ${d.status}${k?`: ${k}`:""}`};let I=s("launchctl",["print",a],{encoding:"utf8"});return I.status!==0?{ok:!1,reason:`bootstrap returned 0 but service not registered (print exit ${I.status})`}:{ok:!0}},u=l();if(!u.ok){let d=u.reason;if(s("launchctl",["bootout",a],{stdio:"ignore"}),u=l(),!u.ok)throw new Error(`launchctl bootstrap failed: ${u.reason}`+(d!==u.reason?` (initial: ${d})`:"")+" \u2014 try `sootsim daemon uninstall` then retry, or reboot if launchd state is stuck.")}let i=Date.now()+4e3,p,h;for(;Date.now()<i;){let d=s("launchctl",["print",a],{encoding:"utf8"});if(d.status===0&&(p=d.stdout?.match(/state\s*=\s*(\w+)/)?.[1],h=d.stdout?.match(/pid\s*=\s*(\d+)/)?.[1],p==="running"||h))break;await new Promise(k=>setTimeout(k,150))}if(p!=="running"&&!h)throw new Error(`daemon registered but did not reach running state within 4s (last state: ${p||"unknown"}). check ${f(g,"bridge.err.log")} \u2014 typically a stale runtime or a port already bound by another process.`);console.log(` registered (state: ${p||"unknown"}${h?`, pid ${h}`:""}, log: ${f(g,"bridge.err.log")})`);return}if(process.platform==="linux"){let o=w();if(c(o)&&!e){console.log(` already installed at ${o}`),console.log(" pass --force to overwrite, or use 'sootsim daemon restart' to reload");return}x(j(o),{recursive:!0}),M(o,st(r,t)),console.log(` wrote ${o}`);let n=s("systemctl",["--user","daemon-reload"],{stdio:"pipe",encoding:"utf8"});if(n.status!==0){let i=(n.stderr||n.stdout||"").trim();throw new Error(`systemctl daemon-reload failed${i?`: ${i}`:""}`)}let a=s("systemctl",["--user","enable","--now",m],{stdio:"pipe",encoding:"utf8"});if(a.status!==0){let i=(a.stderr||a.stdout||"").trim();throw new Error(`systemctl enable --now failed${i?`: ${i}`:""} \u2014 try \`sootsim daemon uninstall\` then retry.`)}let u=(s("systemctl",["--user","is-active",m],{encoding:"utf8"}).stdout||"").trim()||"unknown";console.log(` registered (state: ${u}, journalctl --user -u ${m} to tail logs)`);try{let i=process.env.USER||process.env.LOGNAME||"";if(i){let p=s("loginctl",["show-user",i,"--property=Linger","--value"],{encoding:"utf8"});!((p.stdout||"").trim().toLowerCase()==="yes")&&p.status===0&&console.log(` note: linger is not enabled for "${i}". the daemon will exit at logout.
|
|
61
|
-
enable persistence with: sudo loginctl enable-linger ${i}`)}}catch{}return}console.error(` background daemon is not supported on ${process.platform}`),console.error(" run 'sootsim serve' in a persistent shell instead"),process.exit(1)}function ct(){let t=[];if(process.platform==="darwin"){let e=S();c(e)&&(s("launchctl",["bootout",`gui/${process.getuid()}/${y}`],{stdio:"ignore"}),$(e,{force:!0}),t.push(e));let r=b();return c(r)&&($(r,{recursive:!0,force:!0}),t.push(r)),c(g)&&($(g,{recursive:!0,force:!0}),t.push(g)),{removed:t,missing:t.length===0}}if(process.platform==="linux"){let e=w();return c(e)&&(s("systemctl",["--user","disable","--now",m],{stdio:"ignore"}),$(e,{force:!0}),s("systemctl",["--user","daemon-reload"],{stdio:"ignore"}),s("systemctl",["--user","reset-failed",m],{stdio:"ignore"}),t.push(e)),c(v)&&($(v,{recursive:!0,force:!0}),t.push(v)),{removed:t,missing:t.length===0}}return{removed:t,missing:!0}}function lt(){let t=[],e=T();return c(e)&&($(e,{recursive:!0,force:!0}),t.push(e)),{removed:t,missing:t.length===0}}async function ut(){let t=ct();for(let r of t.removed)console.log(` removed ${r}`);let e=lt();for(let r of e.removed)console.log(` removed ${r}`);t.missing&&e.missing&&console.log(" not installed")}async function pt(){if(process.platform==="darwin"){let t=S();if(!c(t)){console.log(" installed: no");return}console.log(` installed: yes (${t})`);let e=yt(t);e&&console.log(` binary: ${e}`);let r=s("launchctl",["print",`gui/${process.getuid()}/${y}`],{encoding:"utf8"});if(r.status===0){let o=r.stdout.match(/state\s*=\s*(\w+)/)?.[1],n=r.stdout.match(/pid\s*=\s*(\d+)/)?.[1];console.log(` state: ${o||"unknown"}${n?` (pid ${n})`:""}`)}else console.log(" state: not running");return}if(process.platform==="linux"){let t=w();if(!c(t)){console.log(" installed: no");return}console.log(` installed: yes (${t})`);let e=s("systemctl",["--user","is-active",m],{encoding:"utf8"});console.log(` state: ${e.stdout.trim()||"unknown"}`);return}console.error(` unsupported platform: ${process.platform}`),process.exit(1)}async function dt(){if(process.platform==="darwin"){let t=S();c(t)||(console.error(" daemon not registered \u2014 run `sootsim setup`"),process.exit(1));let e=s("launchctl",["kickstart","-k",`gui/${process.getuid()}/${y}`],{stdio:"pipe",encoding:"utf8"});e.status!==0&&(console.error(` kickstart failed: ${e.stderr?.trim()}`),process.exit(1)),console.log(" restarted");return}if(process.platform==="linux"){let t=w();c(t)||(console.error(" daemon not registered \u2014 run `sootsim setup`"),process.exit(1));let e=s("systemctl",["--user","restart",m],{stdio:"pipe",encoding:"utf8"});e.status!==0&&(console.error(` restart failed: ${e.stderr?.trim()}`),process.exit(1)),console.log(" restarted");return}console.error(` unsupported platform: ${process.platform}`),process.exit(1)}async function mt(){if(process.platform==="darwin"){s("launchctl",["kickstart",`gui/${process.getuid()}/${y}`],{stdio:"inherit"});return}if(process.platform==="linux"){s("systemctl",["--user","start",m],{stdio:"inherit"});return}console.error(` unsupported platform: ${process.platform}`),process.exit(1)}async function gt(){if(process.platform==="darwin"){s("launchctl",["bootout",`gui/${process.getuid()}/${y}`],{stdio:"inherit"});return}if(process.platform==="linux"){s("systemctl",["--user","stop",m],{stdio:"inherit"});return}console.error(` unsupported platform: ${process.platform}`),process.exit(1)}async function ft(t){let e=t.find(n=>/^-n\d+$|^--lines=\d+$|^\d+$/.test(n)),r=e?Number(e.replace(/\D/g,"")):200,o=t.includes("-f")||t.includes("--follow");if(process.platform==="darwin"){let n=f(g,"bridge.out.log"),a=f(g,"bridge.err.log"),l=[n,a].filter(i=>c(i));l.length===0&&(console.error(` no daemon logs yet at ${g} \u2014 run \`sootsim setup\` to install the daemon`),process.exit(1));let u=o?["-n",String(r),"-F",...l]:["-n",String(r),...l];s("tail",u,{stdio:"inherit"});return}if(process.platform==="linux"){let n=`${m}.service`,a=["--user","-u",n,"-n",String(r),"--no-pager"],l=s("journalctl",o?[...a,"-f"]:a,{encoding:"utf8",stdio:o?"inherit":"pipe"});if(o)return;let u=`${l.stdout||""}${l.stderr||""}`,i=/insufficient permissions|No journal files were opened/i.test(u);if(l.status===0&&!i){process.stdout.write(l.stdout||"");return}let p=s("journalctl",[`_SYSTEMD_USER_UNIT=${n}`,"-n",String(r),"--no-pager"],{encoding:"utf8"});if(p.status===0&&(p.stdout||"").trim()){process.stdout.write(p.stdout);return}console.error(` could not read --user journal for ${n} (this user isn't in the systemd-journal group yet).
|
|
62
|
-
run: sudo journalctl _SYSTEMD_USER_UNIT=${n} -n ${r} --no-pager`),process.exit(1)}console.error(` unsupported platform: ${process.platform}`),process.exit(1)}function yt(t){try{return et(t,"utf8").match(/<array>\s*<string>([^<]+)<\/string>/)?.[1]||null}catch{return null}}export{Tt as a,Nt as b,Bt as c,ct as d,lt as e};
|