sootsim 0.1.50 → 0.1.52

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (138) hide show
  1. package/dist-cli/bin.js +7 -7
  2. package/dist-cli/chunks/{agent-K264P3HZ.js → agent-RUWGJCSS.js} +2 -2
  3. package/dist-cli/chunks/{agent-wrapper-XS4C3CTX.js → agent-wrapper-FBCGP5N7.js} +2 -2
  4. package/dist-cli/chunks/{assert-BZSHUDEX.js → assert-IOU2NWE2.js} +2 -2
  5. package/dist-cli/chunks/auto-bootstrap-OYBDYAZM.js +2 -0
  6. package/dist-cli/chunks/beta-D4OEPOSE.js +2 -0
  7. package/dist-cli/chunks/{chunk-7X5HYDMF.js → chunk-2QNHBNWB.js} +2 -2
  8. package/dist-cli/chunks/{chunk-ZHM2SOR5.js → chunk-3DDSYQHM.js} +2 -2
  9. package/dist-cli/chunks/{chunk-RYELNIVV.js → chunk-3MIWVHCX.js} +1 -1
  10. package/dist-cli/chunks/{chunk-C3PQYWFU.js → chunk-4TSGUAV3.js} +2 -2
  11. package/dist-cli/chunks/{chunk-6N3DIHG4.js → chunk-6QDFLMJL.js} +1 -1
  12. package/dist-cli/chunks/{chunk-5E3D5ITF.js → chunk-7Y3FYPJH.js} +2 -2
  13. package/dist-cli/chunks/{chunk-3GV2KSZR.js → chunk-A3YSGT76.js} +2 -2
  14. package/dist-cli/chunks/{chunk-LB33X5FX.js → chunk-ABEYZDD7.js} +3 -3
  15. package/dist-cli/chunks/{chunk-W2MG4OA3.js → chunk-BF7F45CZ.js} +2 -2
  16. package/dist-cli/chunks/{chunk-7VUK4YQR.js → chunk-CTEXZ7BE.js} +1 -1
  17. package/dist-cli/chunks/{chunk-CDOIENTA.js → chunk-DNKB2V2W.js} +2 -2
  18. package/dist-cli/chunks/chunk-DSJ7PGU3.js +2 -0
  19. package/dist-cli/chunks/{chunk-CCXT5QH6.js → chunk-DVCE2KQL.js} +1 -1
  20. package/dist-cli/chunks/{chunk-5BU4OSGL.js → chunk-EJYVXNQL.js} +2 -2
  21. package/dist-cli/chunks/{chunk-SZLTF3BI.js → chunk-EQPRFEHH.js} +2 -2
  22. package/dist-cli/chunks/{chunk-VKH25FIQ.js → chunk-EXQJSXDF.js} +1 -1
  23. package/dist-cli/chunks/{chunk-V3KUGR6L.js → chunk-EYRQG47K.js} +1 -1
  24. package/dist-cli/chunks/{chunk-HZUXWRA6.js → chunk-FPIJBBYW.js} +78 -78
  25. package/dist-cli/chunks/{chunk-BRR2YUB4.js → chunk-FVBSPGBR.js} +2 -2
  26. package/dist-cli/chunks/{chunk-FOD2CTAF.js → chunk-GNQSOQXZ.js} +2 -2
  27. package/dist-cli/chunks/{chunk-V4WRHKMT.js → chunk-H4G7IRXG.js} +6 -3
  28. package/dist-cli/chunks/{chunk-ZPCMI5QG.js → chunk-HRIQRZX3.js} +1 -1
  29. package/dist-cli/chunks/{chunk-5IT4FCX4.js → chunk-I5WEW3ES.js} +1 -1
  30. package/dist-cli/chunks/{chunk-EIPLV35T.js → chunk-IQU56D6C.js} +1 -1
  31. package/dist-cli/chunks/{chunk-WL7OCV4P.js → chunk-IXITVIJV.js} +4 -4
  32. package/dist-cli/chunks/{chunk-7R2MEQJF.js → chunk-JPLTR6JM.js} +1 -1
  33. package/dist-cli/chunks/{chunk-7Z6VEDY6.js → chunk-JPX7OS7B.js} +2 -2
  34. package/dist-cli/chunks/chunk-KVQWMXDV.js +2 -0
  35. package/dist-cli/chunks/{chunk-MOQ456TZ.js → chunk-MBH3NFBC.js} +2 -2
  36. package/dist-cli/chunks/{chunk-BZCJZDQG.js → chunk-MSKCUZ5B.js} +4 -4
  37. package/dist-cli/chunks/{chunk-7WL5NDA7.js → chunk-MTE3DEWY.js} +1 -1
  38. package/dist-cli/chunks/{chunk-LE6TYGAB.js → chunk-MWGIKDXO.js} +2 -2
  39. package/dist-cli/chunks/{chunk-Z4QEWLPO.js → chunk-PDZ4JVAW.js} +1 -1
  40. package/dist-cli/chunks/{chunk-H72JYVSH.js → chunk-PZJSYDQ7.js} +3 -3
  41. package/dist-cli/chunks/{chunk-54FJM6VZ.js → chunk-Q2424XB2.js} +1 -1
  42. package/dist-cli/chunks/chunk-SEETW74F.js +1 -0
  43. package/dist-cli/chunks/{chunk-UWXIWNZA.js → chunk-T6RAXKVI.js} +2 -2
  44. package/dist-cli/chunks/{chunk-YQDXPF2Z.js → chunk-U3UHXJNE.js} +1 -1
  45. package/dist-cli/chunks/{chunk-L32B24J6.js → chunk-UCCSXQ2P.js} +29 -29
  46. package/dist-cli/chunks/chunk-ULHAQFCE.js +1 -0
  47. package/dist-cli/chunks/{chunk-CY3MAPVL.js → chunk-USGUHWUJ.js} +2 -2
  48. package/dist-cli/chunks/{chunk-VFYDSE5J.js → chunk-UXE5BFPK.js} +2 -2
  49. package/dist-cli/chunks/{chunk-Q223YQKG.js → chunk-YDKXZS7D.js} +1 -1
  50. package/dist-cli/chunks/chunk-YVGHAT6Q.js +1 -0
  51. package/dist-cli/chunks/cli-version-2VO66OZ6.js +2 -0
  52. package/dist-cli/chunks/{compat-GHXFTPVU.js → compat-ZBLH6EWV.js} +3 -3
  53. package/dist-cli/chunks/{config-2CZ2X42N.js → config-DH2GG63H.js} +2 -2
  54. package/dist-cli/chunks/control-W3BOP6AT.js +2 -0
  55. package/dist-cli/chunks/{cpu-profile-AXUDQSZF.js → cpu-profile-3PRCXZMV.js} +2 -2
  56. package/dist-cli/chunks/{daemon-OYT4MNW5.js → daemon-XSFKUDKZ.js} +2 -2
  57. package/dist-cli/chunks/{debug-GSPR2FNZ.js → debug-VAWCOXQ3.js} +3 -3
  58. package/dist-cli/chunks/demo-app-registry-7GNP7WE4.js +2 -0
  59. package/dist-cli/chunks/{detox-PCDMPG7C.js → detox-UABOFTDQ.js} +2 -2
  60. package/dist-cli/chunks/{device-HAOQGYQ5.js → device-LCB4N66D.js} +2 -2
  61. package/dist-cli/chunks/diagnose-MT3WMY4M.js +41 -0
  62. package/dist-cli/chunks/drivers-YGVUWGMB.js +2 -0
  63. package/dist-cli/chunks/{electron-DEZKIML3.js → electron-WVNFRA4S.js} +3 -3
  64. package/dist-cli/chunks/flow-OUOMEOSC.js +2 -0
  65. package/dist-cli/chunks/{hints-5B7UEOTA.js → hints-PFAKBGFX.js} +2 -2
  66. package/dist-cli/chunks/{home-paths-PGYAOSK4.js → home-paths-X6RB72PF.js} +2 -2
  67. package/dist-cli/chunks/{inspect-QUBG2EE3.js → inspect-UFYXDO6B.js} +74 -71
  68. package/dist-cli/chunks/install-NBUHIXEP.js +2 -0
  69. package/dist-cli/chunks/{install-desktop-F6H6MZ24.js → install-desktop-W6QJX52Y.js} +3 -3
  70. package/dist-cli/chunks/{keys-JDM4S4NA.js → keys-ORDSAMP7.js} +2 -2
  71. package/dist-cli/chunks/{launch-A6MX4EZ6.js → launch-NQZTWTPY.js} +3 -3
  72. package/dist-cli/chunks/{login-2ZHP4WJ5.js → login-J2NVLHK5.js} +4 -4
  73. package/dist-cli/chunks/{logout-ZXQX634G.js → logout-HI7A6PFH.js} +2 -2
  74. package/dist-cli/chunks/{maestro-35BUDZJN.js → maestro-KIOOFK5M.js} +9 -9
  75. package/dist-cli/chunks/{preview-KGBAJEH2.js → preview-QUJO4B4G.js} +2 -2
  76. package/dist-cli/chunks/{profile-BVWQI3HR.js → profile-U6RWYQV2.js} +2 -2
  77. package/dist-cli/chunks/{react-JROJZ3IQ.js → react-3V65RTQC.js} +2 -2
  78. package/dist-cli/chunks/record-476LFCQV.js +41 -0
  79. package/dist-cli/chunks/runtime-4TK5DY5R.js +2 -0
  80. package/dist-cli/chunks/{runtime-delivery-GKTXDKTG.js → runtime-delivery-BSRHUXJQ.js} +2 -2
  81. package/dist-cli/chunks/{screenshot-HJOUIADZ.js → screenshot-2S3BCN35.js} +2 -2
  82. package/dist-cli/chunks/{screenshot-mode-CZWXUAOB.js → screenshot-mode-SZCHOYZV.js} +2 -2
  83. package/dist-cli/chunks/{screenshots-XRDHWLVP.js → screenshots-LGP7LA3M.js} +2 -2
  84. package/dist-cli/chunks/server-G4BGS6GE.js +35 -0
  85. package/dist-cli/chunks/setup-repo-5LUDPPSI.js +2 -0
  86. package/dist-cli/chunks/{skills-NIJL5BJB.js → skills-2YOLQVV6.js} +2 -2
  87. package/dist-cli/chunks/{start-MYAVE26X.js → start-SF3I4SLN.js} +4 -4
  88. package/dist-cli/chunks/store-LLUQKQB7.js +2 -0
  89. package/dist-cli/chunks/telemetry-RDTORLS2.js +2 -0
  90. package/dist-cli/chunks/{test-NO4O5W4H.js → test-YYHXTVDI.js} +3 -3
  91. package/dist-cli/chunks/{three-mode-YGT4C3B3.js → three-mode-5U3H4QDF.js} +2 -2
  92. package/dist-cli/chunks/{timeline-Y7524K3O.js → timeline-IOEIFEH2.js} +2 -2
  93. package/dist-cli/chunks/{upgrade-ZFAPXF7U.js → upgrade-YF2U5QJY.js} +2 -2
  94. package/dist-cli/chunks/upload-3DFSK4NV.js +2 -0
  95. package/dist-cli/chunks/web-GAOXH77P.js +2 -0
  96. package/dist-cli/chunks/{what-happened-3GWD7CES.js → what-happened-DBI2RQVE.js} +2 -2
  97. package/dist-cli/chunks/{whoami-TQW5UROJ.js → whoami-YDAMLYNA.js} +2 -2
  98. package/dist-lib/agent-daemon-client.cjs +1 -1
  99. package/dist-lib/agent-events.cjs +1 -1
  100. package/dist-lib/agent-sessions.cjs +1 -1
  101. package/dist-lib/attached-projects.cjs +1 -1
  102. package/dist-lib/auth/shared-session.cjs +1 -1
  103. package/dist-lib/backend-origin.cjs +1 -1
  104. package/dist-lib/bridge-constants.cjs +1 -1
  105. package/dist-lib/cli-constants.cjs +1 -1
  106. package/dist-lib/config.cjs +1 -1
  107. package/dist-lib/dev-bundle-resolution.cjs +1 -1
  108. package/dist-lib/home-paths.cjs +1 -1
  109. package/dist-lib/host/bridge-host.cjs +71 -9
  110. package/dist-lib/host/fetch-proxy-handler.cjs +1 -1
  111. package/dist-lib/index.cjs +1 -1
  112. package/dist-lib/metro.cjs +1 -1
  113. package/dist-lib/profiles.cjs +1 -1
  114. package/dist-lib/render-mode.cjs +1 -1
  115. package/dist-lib/vite-base.cjs +75 -9
  116. package/dist-lib/vite.cjs +1 -1
  117. package/package.json +1 -1
  118. package/dist-cli/chunks/auto-bootstrap-UI3237L3.js +0 -2
  119. package/dist-cli/chunks/beta-RZOPHEAW.js +0 -2
  120. package/dist-cli/chunks/chunk-3NNIP2AU.js +0 -2
  121. package/dist-cli/chunks/chunk-5ZNFCGBB.js +0 -1
  122. package/dist-cli/chunks/chunk-HPUM7LZG.js +0 -1
  123. package/dist-cli/chunks/chunk-MC5ZKPVM.js +0 -2
  124. package/dist-cli/chunks/chunk-RIQ6GZZL.js +0 -1
  125. package/dist-cli/chunks/control-RTC726XA.js +0 -2
  126. package/dist-cli/chunks/demo-app-registry-TCS63ZRQ.js +0 -2
  127. package/dist-cli/chunks/diagnose-4W66H3TN.js +0 -41
  128. package/dist-cli/chunks/drivers-TA3LWZ5X.js +0 -2
  129. package/dist-cli/chunks/flow-KD74WWWV.js +0 -2
  130. package/dist-cli/chunks/install-5S3T2PJH.js +0 -2
  131. package/dist-cli/chunks/record-VIAGV72T.js +0 -18
  132. package/dist-cli/chunks/runtime-V3JIGNUF.js +0 -2
  133. package/dist-cli/chunks/server-URN2JGBT.js +0 -35
  134. package/dist-cli/chunks/setup-repo-LT5NHTRW.js +0 -2
  135. package/dist-cli/chunks/store-BNKVWXJ7.js +0 -2
  136. package/dist-cli/chunks/telemetry-VSTRFNEA.js +0 -2
  137. package/dist-cli/chunks/upload-4OOPAZEV.js +0 -2
  138. package/dist-cli/chunks/web-THLK2NNP.js +0 -2
@@ -1,5 +1,5 @@
1
- /*! sootsim v0.1.50 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
- import{E as F,r as S,s as k,t as g}from"./chunk-CCXT5QH6.js";import{c as b,e as y}from"./chunk-MOQ456TZ.js";import{b as w}from"./chunk-7VUK4YQR.js";import"./chunk-3NNIP2AU.js";import"./chunk-7R2MEQJF.js";import"./chunk-6N3DIHG4.js";function M(t){let e=[];for(let n=0;n<t.length;n++)if(t[n]==="--since"&&n+1<t.length){e.push(n,n+1);let s=t[n+1].trim(),a=/^(\d+(?:\.\d+)?)(ms|s|m)?$/.exec(s);if(a){let l=Number(a[1]),u=a[2]??"ms",r=u==="s"?l*1e3:u==="m"?l*6e4:l;return{since:Date.now()-r,consumed:e}}let o=Number(s);if(Number.isFinite(o)&&o>1e12)return{since:o,consumed:e}}return{consumed:e}}function E(t){let e=[];for(let n=0;n<t.length;n++)if(t[n]==="--kinds"&&n+1<t.length)return e.push(n,n+1),{kinds:t[n+1].split(",").map(s=>s.trim()).filter(Boolean),consumed:e};return{consumed:e}}function C(t){let e=[];for(let n=0;n<t.length;n++)if(t[n]==="--limit"&&n+1<t.length){e.push(n,n+1);let s=Number(t[n+1]);if(Number.isFinite(s)&&s>0)return{limit:s,consumed:e}}return{consumed:e}}function _(t,e){if(e===null)return new Date(t).toLocaleTimeString();let n=(t-e)/1e3;return`${n>=0?"+":""}${n.toFixed(2)}s`}function j(t,e){switch(t){case"app-launch":return e.phase==="launch"?`launch ${e.appName??e.toAppId??""}`:`dismiss ${e.appName??e.fromAppId??""} \u2192 ${e.toAppId??""}`;case"toast":return`"${e.text??""}"${e.durationMs?` (${e.durationMs}ms)`:""}`;case"keyboard":return`${e.phase??"?"}${e.heightPx?` h=${e.heightPx}`:""}${e.mode?` ${e.mode}`:""}`;case"screen":return`${e.phase??"?"} ${e.name??e.activeName??""}`;case"route":return`${e.phase??"?"} ${e.path??e.pathname??""}`;case"alert":case"actionsheet":case"picker":return`${e.phase??"?"} ${e.title??e.message??""}`;case"notification":return`${e.title??""}${e.body?` \u2014 ${e.body}`:""}`;case"fetch":return`${e.method??"GET"} ${e.url??""}${e.status?` -> ${e.status}`:""}`;case"console":return`${e.level??"log"}: ${(e.message??"").toString().slice(0,120)}`;case"shell":return`${e.event??e.type??e.phase??""}`;case"scroll":return`${e.phase??"?"} ${e.target??""}`;case"gesture":return`${e.phase??"?"} ${e.type??""}`;case"text-input":return`${e.phase??"?"}${e.value!==void 0?` "${String(e.value).slice(0,40)}"`:""}`;case"react-commit":{let n=e.slowest;return`${e.fiberCount??"?"} fibers ${e.durationMs??"?"}ms${n?.displayName?` \xB7 ${n.displayName} ${n.durationMs??"?"}ms`:""}`}case"reanimated":case"animation":return`${e.kind??""} ${e.target??""}${e.durationMs?` ${e.durationMs}ms`:""}`}}function N(t,e){let n=_(t.t,e).padStart(8),s=t.context.padEnd(6),a=`[${t.kind}]`.padEnd(15),o="",l=t.data;return l&&typeof l=="object"&&(o=j(t.kind,l)),` ${n} ${s} ${a} ${o}`}function T(t){let e=[],n={label:"initial state",events:[],startedAt:t[0]?.t??null};e.push(n);for(let s of t)if(n.events.push(s),s.kind==="screen"||s.kind==="route"){let a=s.data,o=a?.phase;if(!o||o==="enter"||o==="appear"||o==="active"){let l=a?.name||a?.activeName||a?.path||a?.pathname||s.kind;e.length===1&&n.events.length===1?n.label=`${s.kind}: ${l}`:(n={label:`${s.kind}: ${l}`,events:[],startedAt:s.t},e.push(n))}}return e}async function O(t,e){let n=b(t,{port:e.port,stripBooleanFlags:["--summary","--all","--json","--no-advance","--help","-h","--flow"],stripValueFlags:["--since","--kinds","--limit"]});(t.includes("--help")||t.includes("-h"))&&(console.log(`
1
+ /*! sootsim v0.1.52 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
+ import{E as F,r as S,s as k,t as g}from"./chunk-DVCE2KQL.js";import{c as b,e as y}from"./chunk-MBH3NFBC.js";import{b as w}from"./chunk-CTEXZ7BE.js";import"./chunk-DSJ7PGU3.js";import"./chunk-JPLTR6JM.js";import"./chunk-6QDFLMJL.js";function M(t){let e=[];for(let n=0;n<t.length;n++)if(t[n]==="--since"&&n+1<t.length){e.push(n,n+1);let s=t[n+1].trim(),a=/^(\d+(?:\.\d+)?)(ms|s|m)?$/.exec(s);if(a){let l=Number(a[1]),u=a[2]??"ms",r=u==="s"?l*1e3:u==="m"?l*6e4:l;return{since:Date.now()-r,consumed:e}}let o=Number(s);if(Number.isFinite(o)&&o>1e12)return{since:o,consumed:e}}return{consumed:e}}function E(t){let e=[];for(let n=0;n<t.length;n++)if(t[n]==="--kinds"&&n+1<t.length)return e.push(n,n+1),{kinds:t[n+1].split(",").map(s=>s.trim()).filter(Boolean),consumed:e};return{consumed:e}}function C(t){let e=[];for(let n=0;n<t.length;n++)if(t[n]==="--limit"&&n+1<t.length){e.push(n,n+1);let s=Number(t[n+1]);if(Number.isFinite(s)&&s>0)return{limit:s,consumed:e}}return{consumed:e}}function _(t,e){if(e===null)return new Date(t).toLocaleTimeString();let n=(t-e)/1e3;return`${n>=0?"+":""}${n.toFixed(2)}s`}function j(t,e){switch(t){case"app-launch":return e.phase==="launch"?`launch ${e.appName??e.toAppId??""}`:`dismiss ${e.appName??e.fromAppId??""} \u2192 ${e.toAppId??""}`;case"toast":return`"${e.text??""}"${e.durationMs?` (${e.durationMs}ms)`:""}`;case"keyboard":return`${e.phase??"?"}${e.heightPx?` h=${e.heightPx}`:""}${e.mode?` ${e.mode}`:""}`;case"screen":return`${e.phase??"?"} ${e.name??e.activeName??""}`;case"route":return`${e.phase??"?"} ${e.path??e.pathname??""}`;case"alert":case"actionsheet":case"picker":return`${e.phase??"?"} ${e.title??e.message??""}`;case"notification":return`${e.title??""}${e.body?` \u2014 ${e.body}`:""}`;case"fetch":return`${e.method??"GET"} ${e.url??""}${e.status?` -> ${e.status}`:""}`;case"console":return`${e.level??"log"}: ${(e.message??"").toString().slice(0,120)}`;case"shell":return`${e.event??e.type??e.phase??""}`;case"scroll":return`${e.phase??"?"} ${e.target??""}`;case"gesture":return`${e.phase??"?"} ${e.type??""}`;case"text-input":return`${e.phase??"?"}${e.value!==void 0?` "${String(e.value).slice(0,40)}"`:""}`;case"react-commit":{let n=e.slowest;return`${e.fiberCount??"?"} fibers ${e.durationMs??"?"}ms${n?.displayName?` \xB7 ${n.displayName} ${n.durationMs??"?"}ms`:""}`}case"reanimated":case"animation":return`${e.kind??""} ${e.target??""}${e.durationMs?` ${e.durationMs}ms`:""}`}}function N(t,e){let n=_(t.t,e).padStart(8),s=t.context.padEnd(6),a=`[${t.kind}]`.padEnd(15),o="",l=t.data;return l&&typeof l=="object"&&(o=j(t.kind,l)),` ${n} ${s} ${a} ${o}`}function T(t){let e=[],n={label:"initial state",events:[],startedAt:t[0]?.t??null};e.push(n);for(let s of t)if(n.events.push(s),s.kind==="screen"||s.kind==="route"){let a=s.data,o=a?.phase;if(!o||o==="enter"||o==="appear"||o==="active"){let l=a?.name||a?.activeName||a?.path||a?.pathname||s.kind;e.length===1&&n.events.length===1?n.label=`${s.kind}: ${l}`:(n={label:`${s.kind}: ${l}`,events:[],startedAt:s.t},e.push(n))}}return e}async function O(t,e){let n=b(t,{port:e.port,stripBooleanFlags:["--summary","--all","--json","--no-advance","--help","-h","--flow"],stripValueFlags:["--since","--kinds","--limit"]});(t.includes("--help")||t.includes("-h"))&&(console.log(`
3
3
  sootsim what-happened \u2014 show recent events from the semantic timeline
4
4
 
5
5
  usage:
@@ -1,2 +1,2 @@
1
- /*! sootsim v0.1.50 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
- import{d as i}from"./chunk-W2MG4OA3.js";import{d as n}from"./chunk-CDOIENTA.js";import"./chunk-7R2MEQJF.js";import"./chunk-6N3DIHG4.js";async function u(){let o=i();if(o||(console.log(" not signed in"),console.log(" set SOOTSIM_API_KEY=sk_sootsim_\u2026 or run `sootsim login`"),process.exit(1)),o.kind==="api-key"){let r=`${o.secret.slice(0,14)}\u2026`,t=o.source==="env"?"SOOTSIM_API_KEY env var":"saved key (~/.config/sootsim/credentials.json)";console.log(` api key ${r}`),console.log(` source: ${t}`);return}if(o.kind==="github"){console.log(` github token (${o.source})`),console.log(` repo: ${o.repoId}`);return}let e=await n(),s=e?.user;console.log(` ${s?.email||s?.name||s?.id||"signed in"}`),console.log(` origin: ${e?.origin??o.origin}`),e?.updatedAt&&console.log(` updated: ${e.updatedAt}`)}export{u as runWhoami};
1
+ /*! sootsim v0.1.52 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
+ import{d as i}from"./chunk-BF7F45CZ.js";import{d as n}from"./chunk-DNKB2V2W.js";import"./chunk-JPLTR6JM.js";import"./chunk-6QDFLMJL.js";async function u(){let o=i();if(o||(console.log(" not signed in"),console.log(" set SOOTSIM_API_KEY=sk_sootsim_\u2026 or run `sootsim login`"),process.exit(1)),o.kind==="api-key"){let r=`${o.secret.slice(0,14)}\u2026`,t=o.source==="env"?"SOOTSIM_API_KEY env var":"saved key (~/.config/sootsim/credentials.json)";console.log(` api key ${r}`),console.log(` source: ${t}`);return}if(o.kind==="github"){console.log(` github token (${o.source})`),console.log(` repo: ${o.repoId}`);return}let e=await n(),s=e?.user;console.log(` ${s?.email||s?.name||s?.id||"signed in"}`),console.log(` origin: ${e?.origin??o.origin}`),e?.updatedAt&&console.log(` updated: ${e.updatedAt}`)}export{u as runWhoami};
@@ -1,4 +1,4 @@
1
- /*! sootsim v0.1.50 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! sootsim v0.1.52 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __create = Object.create;
@@ -1,4 +1,4 @@
1
- /*! sootsim v0.1.50 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! sootsim v0.1.52 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __defProp = Object.defineProperty;
@@ -1,4 +1,4 @@
1
- /*! sootsim v0.1.50 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! sootsim v0.1.52 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __create = Object.create;
@@ -1,4 +1,4 @@
1
- /*! sootsim v0.1.50 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! sootsim v0.1.52 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __create = Object.create;
@@ -1,4 +1,4 @@
1
- /*! sootsim v0.1.50 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! sootsim v0.1.52 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __create = Object.create;
@@ -1,4 +1,4 @@
1
- /*! sootsim v0.1.50 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! sootsim v0.1.52 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __defProp = Object.defineProperty;
@@ -1,4 +1,4 @@
1
- /*! sootsim v0.1.50 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! sootsim v0.1.52 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __defProp = Object.defineProperty;
@@ -1,4 +1,4 @@
1
- /*! sootsim v0.1.50 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! sootsim v0.1.52 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __defProp = Object.defineProperty;
@@ -1,4 +1,4 @@
1
- /*! sootsim v0.1.50 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! sootsim v0.1.52 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __defProp = Object.defineProperty;
@@ -1,4 +1,4 @@
1
- /*! sootsim v0.1.50 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! sootsim v0.1.52 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __defProp = Object.defineProperty;
@@ -1,4 +1,4 @@
1
- /*! sootsim v0.1.50 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! sootsim v0.1.52 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __create = Object.create;
@@ -1,4 +1,4 @@
1
- /*! sootsim v0.1.50 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! sootsim v0.1.52 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __create = Object.create;
@@ -3230,6 +3230,12 @@ function injectSharedConfigIntoHtml(data, bridgePort, sootbeanOrigin) {
3230
3230
  if (html.includes("</body>")) return html.replace("</body>", tag + "</body>");
3231
3231
  return tag + html;
3232
3232
  }
3233
+ function unrefTimer(timer) {
3234
+ if (typeof timer === "object" && timer !== null && "unref" in timer) {
3235
+ ;
3236
+ timer.unref();
3237
+ }
3238
+ }
3233
3239
  var SootSimBridgeHost = class _SootSimBridgeHost {
3234
3240
  port;
3235
3241
  openUrlHandler;
@@ -3257,8 +3263,19 @@ var SootSimBridgeHost = class _SootSimBridgeHost {
3257
3263
  // can't immediately reclaim while the user gets oriented.
3258
3264
  static USER_BOOT_LEASE_TTL_MS = 6e4;
3259
3265
  static SIM_RECONNECT_TTL_MS = 3e4;
3266
+ // abandoned-tab GC. the ws heartbeat only reaps sims whose socket went
3267
+ // dead — but a background tab from a prior `sootsim open` / QA / test run
3268
+ // keeps its socket alive (the page still pongs) forever, so `sootsim list`
3269
+ // accretes dozens of zombie sims that all time out on every command (QA
3270
+ // F21-3, carried F19-2). reap a sim only when it is provably nobody's:
3271
+ // not primary, not user-focused, no CLI attached, no active lease, and no
3272
+ // CLI-driven activity for this long. closeSimSocketFromHost sends the
3273
+ // terminal 4001 code, so the client closes the abandoned window instead
3274
+ // of reconnecting the zombie straight back in.
3275
+ static SIM_IDLE_REAP_TTL_MS = 30 * 6e4;
3260
3276
  preferredPort;
3261
3277
  portFallbackCount;
3278
+ simIdleReapTtlMs;
3262
3279
  shouldWriteLockfile;
3263
3280
  sootbeanOrigin = null;
3264
3281
  effectivePort = 0;
@@ -3294,12 +3311,20 @@ var SootSimBridgeHost = class _SootSimBridgeHost {
3294
3311
  this.openUrlHandler = opts.openUrl;
3295
3312
  this.agentHost = new AgentHost({ getExcludePorts: opts.agentScanExcludes });
3296
3313
  this.sootbeanOrigin = opts.sootbeanOrigin?.replace(/\/$/, "") || null;
3314
+ this.simIdleReapTtlMs = opts.simIdleReapTtlMs ?? _SootSimBridgeHost.SIM_IDLE_REAP_TTL_MS;
3297
3315
  }
3298
3316
  /** expose the agent host so tests and embedders can inspect state or
3299
3317
  * inject behavior. not part of the public WS protocol. */
3300
3318
  getAgentHost() {
3301
3319
  return this.agentHost;
3302
3320
  }
3321
+ /** run the abandoned-sim GC pass on demand. the reaper normally fires off
3322
+ * the 30s idle-sweep timer; this lets the F21-3 integration test drive
3323
+ * the real path without waiting for the timer. not part of the public
3324
+ * WS protocol. */
3325
+ reapIdleSimsForTest(now = Date.now()) {
3326
+ this.reapIdleSims(now);
3327
+ }
3303
3328
  /** synchronous wrapper around startAsync for callers that don't care
3304
3329
  * about port fallback outcomes. returns immediately; actual binding
3305
3330
  * happens on the event loop. callers that need to know the bound port
@@ -3497,7 +3522,9 @@ var SootSimBridgeHost = class _SootSimBridgeHost {
3497
3522
  if (registration.meta && typeof registration.meta === "object") {
3498
3523
  sim.meta = registration.meta;
3499
3524
  }
3500
- if (restored) {
3525
+ const reElected = this.primarySimId !== sim.id && this.shouldPromoteSim(sim);
3526
+ if (reElected) this.primarySimId = sim.id;
3527
+ if (restored || reElected) {
3501
3528
  this.broadcastSimAssignments();
3502
3529
  this.broadcastSimClientStates();
3503
3530
  }
@@ -3733,7 +3760,7 @@ var SootSimBridgeHost = class _SootSimBridgeHost {
3733
3760
  const closeTimer = setTimeout(() => {
3734
3761
  this.closeSimSocketFromHost(simWs);
3735
3762
  }, FORCE_CLOSE_GRACE_MS);
3736
- closeTimer.unref();
3763
+ unrefTimer(closeTimer);
3737
3764
  }
3738
3765
  } catch (err) {
3739
3766
  if (ws.readyState === import_ws.WebSocket.OPEN) {
@@ -4255,6 +4282,34 @@ var SootSimBridgeHost = class _SootSimBridgeHost {
4255
4282
  this.broadcastSimClientStates();
4256
4283
  }
4257
4284
  this.sweepRestorableSims(now);
4285
+ this.reapIdleSims(now);
4286
+ }
4287
+ // GC abandoned sims so `sootsim list` stays usable across long dev / QA /
4288
+ // test sessions (F21-3). conservative on purpose: a sim is only reaped
4289
+ // when every "someone cares about this" signal is absent.
4290
+ //
4291
+ // NOTE: `sim.userFocused` is deliberately NOT an exemption. focus is
4292
+ // advisory in this design — see updateUserFocusLease: "focus alone never
4293
+ // creates a blocking lease … use updateUserActivity() to lock on real
4294
+ // interaction instead." real interaction (pointer/key/wheel/touch)
4295
+ // refreshes a `user-active` lease, which the getActiveLease() guard below
4296
+ // already honors. a headless playwright tab reports `focused:true` once
4297
+ // and never `false` (nothing else competes for focus in headless), so a
4298
+ // userFocused exemption permanently shielded exactly the abandoned-tab
4299
+ // zombie class F21-3 / F19-2 target (QA F22-2). a sim a human is genuinely
4300
+ // using is the primary and/or holds a fresh user-active lease; one that is
4301
+ // none of those and idle past the TTL is abandoned regardless of a stale
4302
+ // focus flag.
4303
+ reapIdleSims(now = Date.now()) {
4304
+ const attachedSimIds = new Set(this.cliSimBySocket.values());
4305
+ for (const sim of this.sims.values()) {
4306
+ if (sim.id === this.primarySimId) continue;
4307
+ if (attachedSimIds.has(sim.id)) continue;
4308
+ if (this.getActiveLease(sim)) continue;
4309
+ const lastTouched = Math.max(sim.lastActiveAt, sim.connectedAt);
4310
+ if (now - lastTouched < this.simIdleReapTtlMs) continue;
4311
+ this.closeSimSocketFromHost(sim.ws);
4312
+ }
4258
4313
  }
4259
4314
  // ping every connected ws; if the previous round's ping went unanswered,
4260
4315
  // terminate the socket so 'close' fires and the sim cleanup path
@@ -4300,7 +4355,7 @@ var SootSimBridgeHost = class _SootSimBridgeHost {
4300
4355
  } catch {
4301
4356
  }
4302
4357
  }, FORCE_CLOSE_TERMINATE_MS);
4303
- terminateTimer.unref();
4358
+ unrefTimer(terminateTimer);
4304
4359
  }
4305
4360
  listSims() {
4306
4361
  return Array.from(this.sims.values()).sort((a, b) => {
@@ -4566,11 +4621,15 @@ var SootSimBridgeHost = class _SootSimBridgeHost {
4566
4621
  return null;
4567
4622
  }
4568
4623
  const primary = this.primarySimId != null ? this.sims.get(this.primarySimId) : null;
4569
- if (primary?.ws.readyState === import_ws.WebSocket.OPEN) return primary;
4624
+ if (primary?.ws.readyState === import_ws.WebSocket.OPEN && primary.url) return primary;
4625
+ let pagelessFallback = null;
4570
4626
  for (const sim of this.sims.values()) {
4571
- if (sim.ws.readyState === import_ws.WebSocket.OPEN) return sim;
4627
+ if (sim.ws.readyState !== import_ws.WebSocket.OPEN) continue;
4628
+ if (sim.url) return sim;
4629
+ pagelessFallback ??= sim;
4572
4630
  }
4573
- return null;
4631
+ if (primary?.ws.readyState === import_ws.WebSocket.OPEN) return primary;
4632
+ return pagelessFallback;
4574
4633
  }
4575
4634
  async waitForSim(simId, options = {}) {
4576
4635
  const attempts = options.attempts ?? 10;
@@ -4584,9 +4643,12 @@ var SootSimBridgeHost = class _SootSimBridgeHost {
4584
4643
  }
4585
4644
  shouldPromoteSim(sim) {
4586
4645
  const current = this.primarySimId ? this.sims.get(this.primarySimId) : null;
4646
+ if (!sim.url) return !current;
4647
+ const currentAlive = current?.ws.readyState === import_ws.WebSocket.OPEN;
4648
+ if (!current || !currentAlive || !current.url) return true;
4587
4649
  const isPrimaryCandidate = sim.origin?.includes(":5173");
4588
- const currentIsPrimary = current?.origin?.includes(":5173");
4589
- return !current || current.ws.readyState !== import_ws.WebSocket.OPEN || !!isPrimaryCandidate || !currentIsPrimary;
4650
+ const currentIsPrimary = current.origin?.includes(":5173");
4651
+ return !!isPrimaryCandidate || !currentIsPrimary;
4590
4652
  }
4591
4653
  broadcastSimAssignments() {
4592
4654
  for (const sim of this.sims.values()) {
@@ -1,4 +1,4 @@
1
- /*! sootsim v0.1.50 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! sootsim v0.1.52 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __create = Object.create;
@@ -1,4 +1,4 @@
1
- /*! sootsim v0.1.50 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! sootsim v0.1.52 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __create = Object.create;
@@ -1,4 +1,4 @@
1
- /*! sootsim v0.1.50 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! sootsim v0.1.52 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __create = Object.create;
@@ -1,4 +1,4 @@
1
- /*! sootsim v0.1.50 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! sootsim v0.1.52 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __create = Object.create;
@@ -1,4 +1,4 @@
1
- /*! sootsim v0.1.50 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! sootsim v0.1.52 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __defProp = Object.defineProperty;
@@ -1,4 +1,4 @@
1
- /*! sootsim v0.1.50 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! sootsim v0.1.52 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __create = Object.create;
@@ -3289,6 +3289,12 @@ function injectSharedConfigIntoHtml(data, bridgePort, sootbeanOrigin) {
3289
3289
  if (html.includes("</body>")) return html.replace("</body>", tag + "</body>");
3290
3290
  return tag + html;
3291
3291
  }
3292
+ function unrefTimer(timer) {
3293
+ if (typeof timer === "object" && timer !== null && "unref" in timer) {
3294
+ ;
3295
+ timer.unref();
3296
+ }
3297
+ }
3292
3298
  var import_child_process4, import_fs3, import_http3, import_path3, import_ws, WRITE_COMMAND_TYPES, FORCE_CLOSE_GRACE_MS, FORCE_CLOSE_TERMINATE_MS, DAEMON_HEARTBEAT_INTERVAL_MS, DEFAULT_RUNTIME_UPDATE_INTERVAL_MS, RUNTIME_UPDATE_INTERVAL_ENV, HTTP_MIME_TYPES, SootSimBridgeHost;
3293
3299
  var init_bridge_host = __esm({
3294
3300
  "src/host/bridge-host.ts"() {
@@ -3362,8 +3368,19 @@ var init_bridge_host = __esm({
3362
3368
  // can't immediately reclaim while the user gets oriented.
3363
3369
  static USER_BOOT_LEASE_TTL_MS = 6e4;
3364
3370
  static SIM_RECONNECT_TTL_MS = 3e4;
3371
+ // abandoned-tab GC. the ws heartbeat only reaps sims whose socket went
3372
+ // dead — but a background tab from a prior `sootsim open` / QA / test run
3373
+ // keeps its socket alive (the page still pongs) forever, so `sootsim list`
3374
+ // accretes dozens of zombie sims that all time out on every command (QA
3375
+ // F21-3, carried F19-2). reap a sim only when it is provably nobody's:
3376
+ // not primary, not user-focused, no CLI attached, no active lease, and no
3377
+ // CLI-driven activity for this long. closeSimSocketFromHost sends the
3378
+ // terminal 4001 code, so the client closes the abandoned window instead
3379
+ // of reconnecting the zombie straight back in.
3380
+ static SIM_IDLE_REAP_TTL_MS = 30 * 6e4;
3365
3381
  preferredPort;
3366
3382
  portFallbackCount;
3383
+ simIdleReapTtlMs;
3367
3384
  shouldWriteLockfile;
3368
3385
  sootbeanOrigin = null;
3369
3386
  effectivePort = 0;
@@ -3399,12 +3416,20 @@ var init_bridge_host = __esm({
3399
3416
  this.openUrlHandler = opts.openUrl;
3400
3417
  this.agentHost = new AgentHost({ getExcludePorts: opts.agentScanExcludes });
3401
3418
  this.sootbeanOrigin = opts.sootbeanOrigin?.replace(/\/$/, "") || null;
3419
+ this.simIdleReapTtlMs = opts.simIdleReapTtlMs ?? _SootSimBridgeHost.SIM_IDLE_REAP_TTL_MS;
3402
3420
  }
3403
3421
  /** expose the agent host so tests and embedders can inspect state or
3404
3422
  * inject behavior. not part of the public WS protocol. */
3405
3423
  getAgentHost() {
3406
3424
  return this.agentHost;
3407
3425
  }
3426
+ /** run the abandoned-sim GC pass on demand. the reaper normally fires off
3427
+ * the 30s idle-sweep timer; this lets the F21-3 integration test drive
3428
+ * the real path without waiting for the timer. not part of the public
3429
+ * WS protocol. */
3430
+ reapIdleSimsForTest(now = Date.now()) {
3431
+ this.reapIdleSims(now);
3432
+ }
3408
3433
  /** synchronous wrapper around startAsync for callers that don't care
3409
3434
  * about port fallback outcomes. returns immediately; actual binding
3410
3435
  * happens on the event loop. callers that need to know the bound port
@@ -3602,7 +3627,9 @@ var init_bridge_host = __esm({
3602
3627
  if (registration.meta && typeof registration.meta === "object") {
3603
3628
  sim.meta = registration.meta;
3604
3629
  }
3605
- if (restored) {
3630
+ const reElected = this.primarySimId !== sim.id && this.shouldPromoteSim(sim);
3631
+ if (reElected) this.primarySimId = sim.id;
3632
+ if (restored || reElected) {
3606
3633
  this.broadcastSimAssignments();
3607
3634
  this.broadcastSimClientStates();
3608
3635
  }
@@ -3838,7 +3865,7 @@ var init_bridge_host = __esm({
3838
3865
  const closeTimer = setTimeout(() => {
3839
3866
  this.closeSimSocketFromHost(simWs);
3840
3867
  }, FORCE_CLOSE_GRACE_MS);
3841
- closeTimer.unref();
3868
+ unrefTimer(closeTimer);
3842
3869
  }
3843
3870
  } catch (err) {
3844
3871
  if (ws.readyState === import_ws.WebSocket.OPEN) {
@@ -4360,6 +4387,34 @@ var init_bridge_host = __esm({
4360
4387
  this.broadcastSimClientStates();
4361
4388
  }
4362
4389
  this.sweepRestorableSims(now);
4390
+ this.reapIdleSims(now);
4391
+ }
4392
+ // GC abandoned sims so `sootsim list` stays usable across long dev / QA /
4393
+ // test sessions (F21-3). conservative on purpose: a sim is only reaped
4394
+ // when every "someone cares about this" signal is absent.
4395
+ //
4396
+ // NOTE: `sim.userFocused` is deliberately NOT an exemption. focus is
4397
+ // advisory in this design — see updateUserFocusLease: "focus alone never
4398
+ // creates a blocking lease … use updateUserActivity() to lock on real
4399
+ // interaction instead." real interaction (pointer/key/wheel/touch)
4400
+ // refreshes a `user-active` lease, which the getActiveLease() guard below
4401
+ // already honors. a headless playwright tab reports `focused:true` once
4402
+ // and never `false` (nothing else competes for focus in headless), so a
4403
+ // userFocused exemption permanently shielded exactly the abandoned-tab
4404
+ // zombie class F21-3 / F19-2 target (QA F22-2). a sim a human is genuinely
4405
+ // using is the primary and/or holds a fresh user-active lease; one that is
4406
+ // none of those and idle past the TTL is abandoned regardless of a stale
4407
+ // focus flag.
4408
+ reapIdleSims(now = Date.now()) {
4409
+ const attachedSimIds = new Set(this.cliSimBySocket.values());
4410
+ for (const sim of this.sims.values()) {
4411
+ if (sim.id === this.primarySimId) continue;
4412
+ if (attachedSimIds.has(sim.id)) continue;
4413
+ if (this.getActiveLease(sim)) continue;
4414
+ const lastTouched = Math.max(sim.lastActiveAt, sim.connectedAt);
4415
+ if (now - lastTouched < this.simIdleReapTtlMs) continue;
4416
+ this.closeSimSocketFromHost(sim.ws);
4417
+ }
4363
4418
  }
4364
4419
  // ping every connected ws; if the previous round's ping went unanswered,
4365
4420
  // terminate the socket so 'close' fires and the sim cleanup path
@@ -4405,7 +4460,7 @@ var init_bridge_host = __esm({
4405
4460
  } catch {
4406
4461
  }
4407
4462
  }, FORCE_CLOSE_TERMINATE_MS);
4408
- terminateTimer.unref();
4463
+ unrefTimer(terminateTimer);
4409
4464
  }
4410
4465
  listSims() {
4411
4466
  return Array.from(this.sims.values()).sort((a, b) => {
@@ -4671,11 +4726,15 @@ var init_bridge_host = __esm({
4671
4726
  return null;
4672
4727
  }
4673
4728
  const primary = this.primarySimId != null ? this.sims.get(this.primarySimId) : null;
4674
- if (primary?.ws.readyState === import_ws.WebSocket.OPEN) return primary;
4729
+ if (primary?.ws.readyState === import_ws.WebSocket.OPEN && primary.url) return primary;
4730
+ let pagelessFallback = null;
4675
4731
  for (const sim of this.sims.values()) {
4676
- if (sim.ws.readyState === import_ws.WebSocket.OPEN) return sim;
4732
+ if (sim.ws.readyState !== import_ws.WebSocket.OPEN) continue;
4733
+ if (sim.url) return sim;
4734
+ pagelessFallback ??= sim;
4677
4735
  }
4678
- return null;
4736
+ if (primary?.ws.readyState === import_ws.WebSocket.OPEN) return primary;
4737
+ return pagelessFallback;
4679
4738
  }
4680
4739
  async waitForSim(simId, options = {}) {
4681
4740
  const attempts = options.attempts ?? 10;
@@ -4689,9 +4748,12 @@ var init_bridge_host = __esm({
4689
4748
  }
4690
4749
  shouldPromoteSim(sim) {
4691
4750
  const current = this.primarySimId ? this.sims.get(this.primarySimId) : null;
4751
+ if (!sim.url) return !current;
4752
+ const currentAlive = current?.ws.readyState === import_ws.WebSocket.OPEN;
4753
+ if (!current || !currentAlive || !current.url) return true;
4692
4754
  const isPrimaryCandidate = sim.origin?.includes(":5173");
4693
- const currentIsPrimary = current?.origin?.includes(":5173");
4694
- return !current || current.ws.readyState !== import_ws.WebSocket.OPEN || !!isPrimaryCandidate || !currentIsPrimary;
4755
+ const currentIsPrimary = current.origin?.includes(":5173");
4756
+ return !!isPrimaryCandidate || !currentIsPrimary;
4695
4757
  }
4696
4758
  broadcastSimAssignments() {
4697
4759
  for (const sim of this.sims.values()) {
@@ -5468,6 +5530,10 @@ var SOOTSIM_COMPAT_WRAPPER_REAL_PACKAGES = {
5468
5530
  specifier: "@sootsim-internal/expo-brightness-real",
5469
5531
  packageName: "expo-brightness"
5470
5532
  },
5533
+ expoConstants: {
5534
+ specifier: "@sootsim-internal/expo-constants-real",
5535
+ packageName: "expo-constants"
5536
+ },
5471
5537
  expoCalendar: {
5472
5538
  specifier: "@sootsim-internal/expo-calendar-real",
5473
5539
  packageName: "expo-calendar"
package/dist-lib/vite.cjs CHANGED
@@ -1,4 +1,4 @@
1
- /*! sootsim v0.1.50 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! sootsim v0.1.52 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __create = Object.create;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sootsim",
3
- "version": "0.1.50",
3
+ "version": "0.1.52",
4
4
  "description": "sootsim CLI + vite/metro plugins + skills registry. bridge client for driving the proprietary sootsim-engine over WebSocket.",
5
5
  "author": "Tamagui LLC",
6
6
  "license": "MIT",
@@ -1,2 +0,0 @@
1
- /*! sootsim v0.1.50 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
- import{a,b,c,d}from"./chunk-BZCJZDQG.js";import"./chunk-MOQ456TZ.js";import"./chunk-7VUK4YQR.js";import"./chunk-3NNIP2AU.js";import"./chunk-7R2MEQJF.js";import"./chunk-6N3DIHG4.js";export{c as ensureDaemonRunning,a as ensureRuntimeInstalled,d as ensureSootsimReady,b as resolveBootstrapPort};
@@ -1,2 +0,0 @@
1
- /*! sootsim v0.1.50 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
- import{a,b,c,d,e}from"./chunk-YQDXPF2Z.js";import"./chunk-6N3DIHG4.js";export{e as BETA_ASK_HEADLINE,c as BETA_LABEL,d as BETA_TAGLINE,b as BETA_VERSION_TARGET,a as IS_BETA};
@@ -1,2 +0,0 @@
1
- /*! sootsim v0.1.50 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
- var O="sootsim close";export{O as a};
@@ -1 +0,0 @@
1
- /*! sootsim v0.1.50 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
@@ -1 +0,0 @@
1
- /*! sootsim v0.1.50 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
@@ -1,2 +0,0 @@
1
- /*! sootsim v0.1.50 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
- var t="http://localhost:5173/";export{t as a};
@@ -1 +0,0 @@
1
- /*! sootsim v0.1.50 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
@@ -1,2 +0,0 @@
1
- /*! sootsim v0.1.50 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
- import{d as a,e as b,f as c,g as d,h as e,i as f,j as g,k as h,l as i,m as j,n as k,o as l,p as m}from"./chunk-LB33X5FX.js";import"./chunk-RYELNIVV.js";import"./chunk-ZPCMI5QG.js";import"./chunk-V4WRHKMT.js";import"./chunk-5IT4FCX4.js";import"./chunk-SZLTF3BI.js";import"./chunk-5ZNFCGBB.js";import"./chunk-7WL5NDA7.js";import"./chunk-MC5ZKPVM.js";import"./chunk-MOQ456TZ.js";import"./chunk-7VUK4YQR.js";import"./chunk-3NNIP2AU.js";import"./chunk-7R2MEQJF.js";import"./chunk-6N3DIHG4.js";export{d as buildOpenUrl,c as buildShellUrl,f as printConnectedSims,a as resolveBundleTarget,b as resolveDefaultShellBaseUrl,l as runClaimCommand,m as runCloseCommand,k as runFocusCommand,h as runListCommand,i as runOpenCommand,j as runUseCommand,e as summarizeSimUrl,g as waitForSimMatch};
@@ -1,2 +0,0 @@
1
- /*! sootsim v0.1.50 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
- import{a}from"./chunk-7Z6VEDY6.js";import"./chunk-6N3DIHG4.js";export{a as APPS};
@@ -1,41 +0,0 @@
1
- /*! sootsim v0.1.50 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
- import{c as v,e as E,h as b}from"./chunk-MOQ456TZ.js";import{b as $}from"./chunk-7VUK4YQR.js";import"./chunk-3NNIP2AU.js";import"./chunk-7R2MEQJF.js";import"./chunk-6N3DIHG4.js";function j(e){return e.ts??e.t??0}function F(e){return typeof e.message=="string"&&e.message.length>0?e.message:Array.isArray(e.args)?e.args.map(r=>typeof r=="string"?r:JSON.stringify(r)).join(" "):""}var W=new Set(["timeline","network","react","console","screen"]);function P(){console.log(`
3
- sootsim diagnose \u2014 compact "what just went wrong?" report
4
-
5
- usage:
6
- sootsim diagnose recent [--since <duration>] [--include <csv>] [--json]
7
-
8
- options:
9
- --since <d> absolute window for timeline + network (e.g. 90s, 2m, 500ms; default 90s)
10
- --include <csv> comma-separated dimensions: timeline, network, react, console, screen
11
- (default: all)
12
- --slow-threshold <n> network slow-request threshold in ms (default 1000)
13
- --limit <n> rows to print per react table (default 8)
14
- --json emit a single structured JSON document
15
-
16
- the diagnose report runs every dimension in parallel against the same
17
- sim and returns a grouped summary. use \`sootsim what-happened\`
18
- for chronological events, \`sootsim network\` for full request inspection,
19
- \`sootsim react summary\` for the React tables on their own.
20
-
21
- examples:
22
- sootsim diagnose recent
23
- sootsim diagnose recent --since 30s --include network,react
24
- sootsim diagnose recent --json > /tmp/diagnose.json
25
- `)}function A(e,r){if(!e)return r;let o=/^(\d+(?:\.\d+)?)(ms|s|m)?$/.exec(e.trim());if(!o)return r;let s=Number(o[1]),t=o[2]??"ms";return t==="s"?s*1e3:t==="m"?s*6e4:s}function D(e){if(!e)return W;let r=new Set;for(let o of e.split(",")){let s=o.trim().toLowerCase();s&&r.add(s)}return r}function k(e,r){let o=e.indexOf(r);if(o>=0&&o+1<e.length)return e[o+1];let s=`${r}=`;return e.find(t=>t.startsWith(s))?.slice(s.length)}function R(e,r,o){let s=k(e,r);if(s===void 0)return o;let t=Number(s);return Number.isFinite(t)&&t>0?Math.round(t):o}async function O(e,r){let o={limit:500,since:Date.now()-r},t=(await b(e,"SootSim.bridges.timeline.recent",o)).events??[],i={},c=[],d=[],p=[];for(let m of t){i[m.kind]=(i[m.kind]??0)+1;let l=m.data,u=l&&typeof l=="object"?l.level:void 0;m.kind==="console"&&(u==="error"||u==="warn")&&c.push(m),(m.kind==="alert"||m.kind==="actionsheet"||m.kind==="picker")&&d.push(m),(m.kind==="screen"||m.kind==="route")&&p.push(m)}return{events:t,byKind:i,total:t.length,errors:c,alerts:d,screens:p}}async function B(e,r,o){let s=await e.send({type:"evaluate",code:`(() => {
26
- const obs = window.__sootsimObservability;
27
- if (!obs) return { ok: false };
28
- return { ok: true, entries: obs.network.getSnapshot() };
29
- })()`});if(!s||!s.ok)return{error:"observability bridge not installed"};let t=s.entries??[],i=Date.now()-r,c=t.filter(l=>(l.startTs??l.startedAt??0)>=i),d=c.filter(l=>!!l.error||l.status!=null&&l.status>=400),p=c.filter(l=>l.durationMs!=null&&l.durationMs>=o).sort((l,u)=>(u.durationMs??0)-(l.durationMs??0)),m=c.filter(l=>l.durationMs==null).length;return{total:c.length,failed:d,slow:p,inFlight:m,slowThresholdMs:o}}async function L(e,r){let[o,s]=await Promise.all([b(e,"SootSim.bridges.reactProfile.slow",{limit:r}),b(e,"SootSim.bridges.reactProfile.rerenders",{limit:r})]);return{commits:o.commits??s.commits??0,slow:o.rows??[],rerenders:s.rows??[],durationWarning:o.durationWarning,error:o.error??s.error}}async function C(e,r){let o=await e.send({type:"evaluate",code:`(() => {
30
- const obs = window.__sootsimObservability;
31
- if (!obs) return { ok: false };
32
- return { ok: true, entries: obs.logs.getSnapshot() };
33
- })()`});if(!o||!o.ok)return{error:"observability bridge not installed"};let s=Date.now()-r,i=(o.entries??[]).filter(c=>j(c)>=s&&(c.level==="error"||c.level==="warn"));return{entries:i.slice(-20),total:i.length}}function T(e){let r=e.error?"err":e.status!=null?String(e.status):"...",o=(e.method??"GET").padEnd(6),s=e.durationMs!=null?`${e.durationMs.toFixed(0)}ms`:"...",t=e.displayUrl??e.url,i=t.length>96?`${t.slice(0,92)}\u2026`:t;return` ${r.padStart(3)} ${o} ${s.padStart(7)} ${i} (${e.id})`}function N(e,r){let o=((e.t-r)/1e3).toFixed(2),s=e.t>=r?"-":"+",t=e.data,i="";if(t&&typeof t=="object"){let c=(t.message??"").toString().slice(0,120),d=(t.title??t.name??t.path??t.url??"").toString();i=[(t.phase??"").toString(),d,c].filter(Boolean).join(" \xB7 ")}return` -${o.padStart(5)}s [${e.kind}] ${i}`}function M(e,r,o){if(r.length===0)return`${o}(no rows)`;let s=e.map((i,c)=>Math.max(i.length,...r.map(d=>d[c]?.length??0))),t=i=>i.map((c,d)=>c.padEnd(s[d])).join(" ").trimEnd();return[t(e),t(e.map(i=>"-".repeat(i.length))),...r.map(t)].map(i=>`${o}${i}`).join(`
34
- `)}async function q(e,r){if(e.includes("--help")||e.includes("-h"))return P(),0;let o=v(e,{port:r.port,stripBooleanFlags:["--json","--help","-h"],stripValueFlags:["--since","--include","--limit","--slow-threshold"]}),s=o.positional[0]??"recent";if(s!=="recent")return console.error(` unknown subcommand: ${s}`),console.error(" did you mean: sootsim diagnose recent ?"),1;let t=A(k(e,"--since"),9e4),i=D(k(e,"--include")),c=R(e,"--limit",8),d=R(e,"--slow-threshold",1e3),p=e.includes("--json"),m=E(o);try{let l=[],u=[];(i.has("timeline")||i.has("screen")||i.has("alert"))&&(u.push("timeline"),l.push(O(m,t))),(i.has("network")||i.has("fetch"))&&(u.push("network"),l.push(B(m,t,d))),i.has("react")&&(u.push("react"),l.push(L(m,c))),i.has("console")&&(u.push("console"),l.push(C(m,t)));let x=await Promise.all(l),w={};for(let n=0;n<u.length;n++)w[u[n]]=x[n];if(p)return console.log(JSON.stringify({generatedAt:Date.now(),sinceMs:t,include:Array.from(i),slices:w},null,2)),0;let S=Date.now();if(console.log(` diagnose recent (last ${(t/1e3).toFixed(0)}s, include: ${Array.from(i).sort().join(",")}):`),w.timeline){let n=w.timeline;console.log(`
35
- timeline \u2014 ${n.total} event(s) in window`);let f=Object.entries(n.byKind).sort((a,g)=>g[1]-a[1]).map(([a,g])=>`${g} ${a}`).join(" \xB7 ");if(f&&console.log(` summary: ${f}`),n.screens.length){let g=n.screens[n.screens.length-1].data,h=g?g.name??g.activeName??g.path??"?":"?";console.log(` last screen: ${String(h)}`)}if(n.alerts.length){console.log(` alerts (${n.alerts.length}):`);for(let a of n.alerts.slice(-5))console.log(N(a,S))}if(n.errors.length){console.log(` console errors/warns from timeline (${n.errors.length}):`);for(let a of n.errors.slice(-5))console.log(N(a,S))}}if(w.network){let n=w.network;if("error"in n)console.log(`
36
- network \u2014 ${n.error}`);else{if(console.log(`
37
- network \u2014 ${n.total} request(s), ${n.failed.length} failed, ${n.slow.length} slow (>${n.slowThresholdMs}ms), ${n.inFlight} in-flight`),n.failed.length){console.log(" failed:");for(let f of n.failed.slice(-8))console.log(T(f))}if(n.slow.length){console.log(" slowest:");for(let f of n.slow.slice(0,5))console.log(T(f))}}}if(w.react){let n=w.react;console.log(`
38
- react \u2014 ${n.commits} commit(s)`),n.error&&console.log(` warning: ${n.error}`),n.durationWarning&&console.log(` warning: ${n.durationWarning}`),n.slow.length>0&&n.slow.every(a=>a.totalMs<=0&&a.slowestMs<=0)&&!n.durationWarning&&console.log(" warning: every commit reports actualDuration=0ms \u2014 bundle has React profiler timer disabled"),n.slow.length&&(console.log(" slowest:"),console.log(M(["component","total","commits","slowest"],n.slow.slice(0,c).map(a=>[a.displayName,`${a.totalMs.toFixed(2)}ms`,String(a.commitCount),`${a.slowestMs.toFixed(2)}ms`])," "))),n.rerenders.length&&(console.log(" most rerenders:"),console.log(M(["component","renders","top causes"],n.rerenders.slice(0,c).map(a=>{let g=Object.entries(a.causes??{}).filter(([,h])=>h>0).sort((h,y)=>y[1]-h[1]).slice(0,3).map(([h,y])=>`${h}:${y}`).join(", ");return[a.displayName,String(a.renders??a.count??0),g||"-"]})," ")))}if(w.console){let n=w.console;if("error"in n)console.log(`
39
- console \u2014 ${n.error}`);else{console.log(`
40
- console errors/warns \u2014 ${n.total} in window`);for(let f of n.entries.slice(-8)){let a=((j(f)-S)/1e3).toFixed(2),g=F(f).slice(0,160);console.log(` -${a.padStart(5)}s [${f.level}] ${g}`)}}}return $()&&console.log(`
41
- next: sootsim what-happened (cursor advances) \xB7 sootsim network get <id> \xB7 sootsim react why <fiber-id>`),0}catch(l){let u=l instanceof Error?l.message:String(l);return/no sim connected/i.test(u)?console.error(" no sim connected \u2014 open one first: sootsim open <metroPort>"):console.error(` diagnose failed: ${u}`),1}finally{m.close()}}export{q as runDiagnose};
@@ -1,2 +0,0 @@
1
- /*! sootsim v0.1.50 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
- import"./chunk-HPUM7LZG.js";import{a,b,c,d,e,f,g,h,i}from"./chunk-V4WRHKMT.js";import"./chunk-5IT4FCX4.js";import"./chunk-SZLTF3BI.js";import"./chunk-5ZNFCGBB.js";import"./chunk-7WL5NDA7.js";import"./chunk-7R2MEQJF.js";import"./chunk-6N3DIHG4.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.50 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
- import{a,b,c,d}from"./chunk-L32B24J6.js";import"./chunk-UWXIWNZA.js";import"./chunk-C3PQYWFU.js";import"./chunk-RIQ6GZZL.js";import"./chunk-LE6TYGAB.js";import"./chunk-HZUXWRA6.js";import"./chunk-LB33X5FX.js";import"./chunk-RYELNIVV.js";import"./chunk-ZPCMI5QG.js";import"./chunk-V4WRHKMT.js";import"./chunk-5IT4FCX4.js";import"./chunk-SZLTF3BI.js";import"./chunk-7Z6VEDY6.js";import"./chunk-WL7OCV4P.js";import"./chunk-W2MG4OA3.js";import"./chunk-5ZNFCGBB.js";import"./chunk-7WL5NDA7.js";import"./chunk-CY3MAPVL.js";import"./chunk-MC5ZKPVM.js";import"./chunk-FOD2CTAF.js";import"./chunk-54FJM6VZ.js";import"./chunk-MOQ456TZ.js";import"./chunk-7VUK4YQR.js";import"./chunk-5E3D5ITF.js";import"./chunk-CDOIENTA.js";import"./chunk-3NNIP2AU.js";import"./chunk-7R2MEQJF.js";import"./chunk-6N3DIHG4.js";export{b as discoverSootsimUrl,a as parseFlowFile,d as runFlow,c as runFlowPlayback};
@@ -1,2 +0,0 @@
1
- /*! sootsim v0.1.50 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
- import{a as o}from"./chunk-BRR2YUB4.js";import"./chunk-Q223YQKG.js";import"./chunk-BZCJZDQG.js";import"./chunk-MOQ456TZ.js";import"./chunk-7VUK4YQR.js";import"./chunk-5E3D5ITF.js";import"./chunk-CDOIENTA.js";import"./chunk-3NNIP2AU.js";import"./chunk-7R2MEQJF.js";import"./chunk-6N3DIHG4.js";async function t(n){console.error(" note: `sootsim install` is now `sootsim setup-repo`. forwarding\u2026\n"),await o(n)}export{t as runInstall};