sootsim 0.1.51 → 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 (137) hide show
  1. package/dist-cli/bin.js +7 -7
  2. package/dist-cli/chunks/{agent-RLBVAUCW.js → agent-RUWGJCSS.js} +2 -2
  3. package/dist-cli/chunks/{agent-wrapper-TWLPNETE.js → agent-wrapper-FBCGP5N7.js} +2 -2
  4. package/dist-cli/chunks/{assert-JLQSBZPM.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-JZ65NOXB.js → chunk-2QNHBNWB.js} +2 -2
  8. package/dist-cli/chunks/{chunk-P45EZ2VW.js → chunk-3DDSYQHM.js} +2 -2
  9. package/dist-cli/chunks/{chunk-SLAAAEUZ.js → chunk-3MIWVHCX.js} +1 -1
  10. package/dist-cli/chunks/{chunk-PTW5KT4I.js → chunk-4TSGUAV3.js} +2 -2
  11. package/dist-cli/chunks/{chunk-3BUWCNVX.js → chunk-6QDFLMJL.js} +1 -1
  12. package/dist-cli/chunks/{chunk-VXLRXQER.js → chunk-7Y3FYPJH.js} +2 -2
  13. package/dist-cli/chunks/{chunk-2ZCJFJJN.js → chunk-A3YSGT76.js} +2 -2
  14. package/dist-cli/chunks/{chunk-ZT7672XM.js → chunk-ABEYZDD7.js} +3 -3
  15. package/dist-cli/chunks/{chunk-6NR6NFDC.js → chunk-BF7F45CZ.js} +2 -2
  16. package/dist-cli/chunks/{chunk-5PKYORP6.js → chunk-CTEXZ7BE.js} +1 -1
  17. package/dist-cli/chunks/{chunk-P2IC3VRD.js → chunk-DNKB2V2W.js} +2 -2
  18. package/dist-cli/chunks/chunk-DSJ7PGU3.js +2 -0
  19. package/dist-cli/chunks/{chunk-4QM4J2UK.js → chunk-DVCE2KQL.js} +1 -1
  20. package/dist-cli/chunks/{chunk-L4OPPOPY.js → chunk-EJYVXNQL.js} +2 -2
  21. package/dist-cli/chunks/{chunk-VDUWPVZT.js → chunk-EQPRFEHH.js} +2 -2
  22. package/dist-cli/chunks/{chunk-XWHWPFBE.js → chunk-EXQJSXDF.js} +1 -1
  23. package/dist-cli/chunks/{chunk-DBHV5S2L.js → chunk-EYRQG47K.js} +1 -1
  24. package/dist-cli/chunks/{chunk-SPMHQKNI.js → chunk-FPIJBBYW.js} +78 -78
  25. package/dist-cli/chunks/{chunk-RSEV5NWY.js → chunk-FVBSPGBR.js} +2 -2
  26. package/dist-cli/chunks/{chunk-45XEBYVX.js → chunk-GNQSOQXZ.js} +2 -2
  27. package/dist-cli/chunks/{chunk-265YGINI.js → chunk-H4G7IRXG.js} +6 -3
  28. package/dist-cli/chunks/{chunk-LMINUIAR.js → chunk-HRIQRZX3.js} +1 -1
  29. package/dist-cli/chunks/{chunk-DBYZF6KL.js → chunk-I5WEW3ES.js} +1 -1
  30. package/dist-cli/chunks/{chunk-54IIO5BV.js → chunk-IQU56D6C.js} +1 -1
  31. package/dist-cli/chunks/{chunk-IENPCJTB.js → chunk-IXITVIJV.js} +4 -4
  32. package/dist-cli/chunks/{chunk-FSTOUA6L.js → chunk-JPLTR6JM.js} +1 -1
  33. package/dist-cli/chunks/{chunk-FUHHRW7G.js → chunk-JPX7OS7B.js} +2 -2
  34. package/dist-cli/chunks/chunk-KVQWMXDV.js +2 -0
  35. package/dist-cli/chunks/{chunk-BKXH674Z.js → chunk-MBH3NFBC.js} +2 -2
  36. package/dist-cli/chunks/{chunk-HATEGE6O.js → chunk-MSKCUZ5B.js} +4 -4
  37. package/dist-cli/chunks/{chunk-BGZRRNK4.js → chunk-MTE3DEWY.js} +1 -1
  38. package/dist-cli/chunks/{chunk-IEYPDVW2.js → chunk-MWGIKDXO.js} +2 -2
  39. package/dist-cli/chunks/{chunk-EOYTPHOU.js → chunk-PDZ4JVAW.js} +1 -1
  40. package/dist-cli/chunks/{chunk-M7HK7MWE.js → chunk-PZJSYDQ7.js} +3 -3
  41. package/dist-cli/chunks/{chunk-67AZW4HJ.js → chunk-Q2424XB2.js} +1 -1
  42. package/dist-cli/chunks/chunk-SEETW74F.js +1 -0
  43. package/dist-cli/chunks/{chunk-AWQGGSDW.js → chunk-T6RAXKVI.js} +2 -2
  44. package/dist-cli/chunks/{chunk-ZEIDKF3M.js → chunk-U3UHXJNE.js} +1 -1
  45. package/dist-cli/chunks/{chunk-ET5NKJVL.js → chunk-UCCSXQ2P.js} +29 -29
  46. package/dist-cli/chunks/chunk-ULHAQFCE.js +1 -0
  47. package/dist-cli/chunks/{chunk-VR2UDTSA.js → chunk-USGUHWUJ.js} +2 -2
  48. package/dist-cli/chunks/{chunk-CLSZB5BN.js → chunk-UXE5BFPK.js} +2 -2
  49. package/dist-cli/chunks/{chunk-AQN3BB3D.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-WUI6VQPS.js → compat-ZBLH6EWV.js} +3 -3
  53. package/dist-cli/chunks/{config-XCFL4A6Z.js → config-DH2GG63H.js} +2 -2
  54. package/dist-cli/chunks/control-W3BOP6AT.js +2 -0
  55. package/dist-cli/chunks/{cpu-profile-CPOEDK5W.js → cpu-profile-3PRCXZMV.js} +2 -2
  56. package/dist-cli/chunks/{daemon-NFZOWPYN.js → daemon-XSFKUDKZ.js} +2 -2
  57. package/dist-cli/chunks/{debug-G6FBH3B4.js → debug-VAWCOXQ3.js} +3 -3
  58. package/dist-cli/chunks/demo-app-registry-7GNP7WE4.js +2 -0
  59. package/dist-cli/chunks/{detox-PUCPDKAO.js → detox-UABOFTDQ.js} +2 -2
  60. package/dist-cli/chunks/{device-IUUKTF7R.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-HGY5WSFG.js → electron-WVNFRA4S.js} +3 -3
  64. package/dist-cli/chunks/flow-OUOMEOSC.js +2 -0
  65. package/dist-cli/chunks/{hints-H7IVKEWB.js → hints-PFAKBGFX.js} +2 -2
  66. package/dist-cli/chunks/{home-paths-U5CDMYH5.js → home-paths-X6RB72PF.js} +2 -2
  67. package/dist-cli/chunks/{inspect-6WSCE3W3.js → inspect-UFYXDO6B.js} +74 -71
  68. package/dist-cli/chunks/install-NBUHIXEP.js +2 -0
  69. package/dist-cli/chunks/{install-desktop-QTZ3IBQW.js → install-desktop-W6QJX52Y.js} +3 -3
  70. package/dist-cli/chunks/{keys-DCQXAY66.js → keys-ORDSAMP7.js} +2 -2
  71. package/dist-cli/chunks/{launch-FTHBNATG.js → launch-NQZTWTPY.js} +3 -3
  72. package/dist-cli/chunks/{login-4GUBAGPQ.js → login-J2NVLHK5.js} +4 -4
  73. package/dist-cli/chunks/{logout-N25HFETU.js → logout-HI7A6PFH.js} +2 -2
  74. package/dist-cli/chunks/{maestro-WQBZZDTR.js → maestro-KIOOFK5M.js} +9 -9
  75. package/dist-cli/chunks/{preview-6MWJ6BSM.js → preview-QUJO4B4G.js} +2 -2
  76. package/dist-cli/chunks/{profile-UXJEGF4I.js → profile-U6RWYQV2.js} +2 -2
  77. package/dist-cli/chunks/{react-MHPIWH3F.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-IIDHK55K.js → runtime-delivery-BSRHUXJQ.js} +2 -2
  81. package/dist-cli/chunks/{screenshot-MDE5ZSST.js → screenshot-2S3BCN35.js} +2 -2
  82. package/dist-cli/chunks/{screenshot-mode-7W7L7IN3.js → screenshot-mode-SZCHOYZV.js} +2 -2
  83. package/dist-cli/chunks/{screenshots-24LEZPD7.js → screenshots-LGP7LA3M.js} +2 -2
  84. package/dist-cli/chunks/{server-52HFHX3S.js → server-G4BGS6GE.js} +11 -11
  85. package/dist-cli/chunks/setup-repo-5LUDPPSI.js +2 -0
  86. package/dist-cli/chunks/{skills-3DGYETTU.js → skills-2YOLQVV6.js} +2 -2
  87. package/dist-cli/chunks/{start-NFVPQX74.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-THI53N25.js → test-YYHXTVDI.js} +3 -3
  91. package/dist-cli/chunks/{three-mode-HUI4SESE.js → three-mode-5U3H4QDF.js} +2 -2
  92. package/dist-cli/chunks/{timeline-KAJ6PR4S.js → timeline-IOEIFEH2.js} +2 -2
  93. package/dist-cli/chunks/{upgrade-APDFMQCW.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-4VMBEL5Z.js → what-happened-DBI2RQVE.js} +2 -2
  97. package/dist-cli/chunks/{whoami-NJOQICNO.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 +63 -7
  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 +67 -7
  116. package/dist-lib/vite.cjs +1 -1
  117. package/package.json +1 -1
  118. package/dist-cli/chunks/auto-bootstrap-UKUFJBJA.js +0 -2
  119. package/dist-cli/chunks/beta-4OEWPO5F.js +0 -2
  120. package/dist-cli/chunks/chunk-3HO4Q25D.js +0 -1
  121. package/dist-cli/chunks/chunk-4D7Z64YQ.js +0 -2
  122. package/dist-cli/chunks/chunk-ACQXOAQI.js +0 -2
  123. package/dist-cli/chunks/chunk-DV3SI64Q.js +0 -1
  124. package/dist-cli/chunks/chunk-EWSS4C2R.js +0 -1
  125. package/dist-cli/chunks/control-KE4VM2BN.js +0 -2
  126. package/dist-cli/chunks/demo-app-registry-U4FCHIYP.js +0 -2
  127. package/dist-cli/chunks/diagnose-6RY4YXSP.js +0 -41
  128. package/dist-cli/chunks/drivers-2FY62QZA.js +0 -2
  129. package/dist-cli/chunks/flow-HEYPRCST.js +0 -2
  130. package/dist-cli/chunks/install-NPNUNOL6.js +0 -2
  131. package/dist-cli/chunks/record-K5DRP3G7.js +0 -18
  132. package/dist-cli/chunks/runtime-UVFYTDXE.js +0 -2
  133. package/dist-cli/chunks/setup-repo-ZHEBGISP.js +0 -2
  134. package/dist-cli/chunks/store-R2RI4XAS.js +0 -2
  135. package/dist-cli/chunks/telemetry-KGU6DBN6.js +0 -2
  136. package/dist-cli/chunks/upload-K7OWH74D.js +0 -2
  137. package/dist-cli/chunks/web-XDGC5KGT.js +0 -2
@@ -1,5 +1,5 @@
1
- /*! sootsim v0.1.51 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
- import{E as F,r as S,s as k,t as g}from"./chunk-4QM4J2UK.js";import{c as b,e as y}from"./chunk-BKXH674Z.js";import{b as w}from"./chunk-5PKYORP6.js";import"./chunk-ACQXOAQI.js";import"./chunk-FSTOUA6L.js";import"./chunk-3BUWCNVX.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.51 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
- import{d as i}from"./chunk-6NR6NFDC.js";import{d as n}from"./chunk-P2IC3VRD.js";import"./chunk-FSTOUA6L.js";import"./chunk-3BUWCNVX.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.51 | (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.51 | (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.51 | (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.51 | (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.51 | (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.51 | (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.51 | (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.51 | (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.51 | (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.51 | (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.51 | (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.51 | (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;
@@ -3263,8 +3263,19 @@ var SootSimBridgeHost = class _SootSimBridgeHost {
3263
3263
  // can't immediately reclaim while the user gets oriented.
3264
3264
  static USER_BOOT_LEASE_TTL_MS = 6e4;
3265
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;
3266
3276
  preferredPort;
3267
3277
  portFallbackCount;
3278
+ simIdleReapTtlMs;
3268
3279
  shouldWriteLockfile;
3269
3280
  sootbeanOrigin = null;
3270
3281
  effectivePort = 0;
@@ -3300,12 +3311,20 @@ var SootSimBridgeHost = class _SootSimBridgeHost {
3300
3311
  this.openUrlHandler = opts.openUrl;
3301
3312
  this.agentHost = new AgentHost({ getExcludePorts: opts.agentScanExcludes });
3302
3313
  this.sootbeanOrigin = opts.sootbeanOrigin?.replace(/\/$/, "") || null;
3314
+ this.simIdleReapTtlMs = opts.simIdleReapTtlMs ?? _SootSimBridgeHost.SIM_IDLE_REAP_TTL_MS;
3303
3315
  }
3304
3316
  /** expose the agent host so tests and embedders can inspect state or
3305
3317
  * inject behavior. not part of the public WS protocol. */
3306
3318
  getAgentHost() {
3307
3319
  return this.agentHost;
3308
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
+ }
3309
3328
  /** synchronous wrapper around startAsync for callers that don't care
3310
3329
  * about port fallback outcomes. returns immediately; actual binding
3311
3330
  * happens on the event loop. callers that need to know the bound port
@@ -3503,7 +3522,9 @@ var SootSimBridgeHost = class _SootSimBridgeHost {
3503
3522
  if (registration.meta && typeof registration.meta === "object") {
3504
3523
  sim.meta = registration.meta;
3505
3524
  }
3506
- if (restored) {
3525
+ const reElected = this.primarySimId !== sim.id && this.shouldPromoteSim(sim);
3526
+ if (reElected) this.primarySimId = sim.id;
3527
+ if (restored || reElected) {
3507
3528
  this.broadcastSimAssignments();
3508
3529
  this.broadcastSimClientStates();
3509
3530
  }
@@ -4261,6 +4282,34 @@ var SootSimBridgeHost = class _SootSimBridgeHost {
4261
4282
  this.broadcastSimClientStates();
4262
4283
  }
4263
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
+ }
4264
4313
  }
4265
4314
  // ping every connected ws; if the previous round's ping went unanswered,
4266
4315
  // terminate the socket so 'close' fires and the sim cleanup path
@@ -4572,11 +4621,15 @@ var SootSimBridgeHost = class _SootSimBridgeHost {
4572
4621
  return null;
4573
4622
  }
4574
4623
  const primary = this.primarySimId != null ? this.sims.get(this.primarySimId) : null;
4575
- 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;
4576
4626
  for (const sim of this.sims.values()) {
4577
- 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;
4578
4630
  }
4579
- return null;
4631
+ if (primary?.ws.readyState === import_ws.WebSocket.OPEN) return primary;
4632
+ return pagelessFallback;
4580
4633
  }
4581
4634
  async waitForSim(simId, options = {}) {
4582
4635
  const attempts = options.attempts ?? 10;
@@ -4590,9 +4643,12 @@ var SootSimBridgeHost = class _SootSimBridgeHost {
4590
4643
  }
4591
4644
  shouldPromoteSim(sim) {
4592
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;
4593
4649
  const isPrimaryCandidate = sim.origin?.includes(":5173");
4594
- const currentIsPrimary = current?.origin?.includes(":5173");
4595
- return !current || current.ws.readyState !== import_ws.WebSocket.OPEN || !!isPrimaryCandidate || !currentIsPrimary;
4650
+ const currentIsPrimary = current.origin?.includes(":5173");
4651
+ return !!isPrimaryCandidate || !currentIsPrimary;
4596
4652
  }
4597
4653
  broadcastSimAssignments() {
4598
4654
  for (const sim of this.sims.values()) {
@@ -1,4 +1,4 @@
1
- /*! sootsim v0.1.51 | (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.51 | (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.51 | (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.51 | (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.51 | (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.51 | (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;
@@ -3368,8 +3368,19 @@ var init_bridge_host = __esm({
3368
3368
  // can't immediately reclaim while the user gets oriented.
3369
3369
  static USER_BOOT_LEASE_TTL_MS = 6e4;
3370
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;
3371
3381
  preferredPort;
3372
3382
  portFallbackCount;
3383
+ simIdleReapTtlMs;
3373
3384
  shouldWriteLockfile;
3374
3385
  sootbeanOrigin = null;
3375
3386
  effectivePort = 0;
@@ -3405,12 +3416,20 @@ var init_bridge_host = __esm({
3405
3416
  this.openUrlHandler = opts.openUrl;
3406
3417
  this.agentHost = new AgentHost({ getExcludePorts: opts.agentScanExcludes });
3407
3418
  this.sootbeanOrigin = opts.sootbeanOrigin?.replace(/\/$/, "") || null;
3419
+ this.simIdleReapTtlMs = opts.simIdleReapTtlMs ?? _SootSimBridgeHost.SIM_IDLE_REAP_TTL_MS;
3408
3420
  }
3409
3421
  /** expose the agent host so tests and embedders can inspect state or
3410
3422
  * inject behavior. not part of the public WS protocol. */
3411
3423
  getAgentHost() {
3412
3424
  return this.agentHost;
3413
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
+ }
3414
3433
  /** synchronous wrapper around startAsync for callers that don't care
3415
3434
  * about port fallback outcomes. returns immediately; actual binding
3416
3435
  * happens on the event loop. callers that need to know the bound port
@@ -3608,7 +3627,9 @@ var init_bridge_host = __esm({
3608
3627
  if (registration.meta && typeof registration.meta === "object") {
3609
3628
  sim.meta = registration.meta;
3610
3629
  }
3611
- if (restored) {
3630
+ const reElected = this.primarySimId !== sim.id && this.shouldPromoteSim(sim);
3631
+ if (reElected) this.primarySimId = sim.id;
3632
+ if (restored || reElected) {
3612
3633
  this.broadcastSimAssignments();
3613
3634
  this.broadcastSimClientStates();
3614
3635
  }
@@ -4366,6 +4387,34 @@ var init_bridge_host = __esm({
4366
4387
  this.broadcastSimClientStates();
4367
4388
  }
4368
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
+ }
4369
4418
  }
4370
4419
  // ping every connected ws; if the previous round's ping went unanswered,
4371
4420
  // terminate the socket so 'close' fires and the sim cleanup path
@@ -4677,11 +4726,15 @@ var init_bridge_host = __esm({
4677
4726
  return null;
4678
4727
  }
4679
4728
  const primary = this.primarySimId != null ? this.sims.get(this.primarySimId) : null;
4680
- 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;
4681
4731
  for (const sim of this.sims.values()) {
4682
- 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;
4683
4735
  }
4684
- return null;
4736
+ if (primary?.ws.readyState === import_ws.WebSocket.OPEN) return primary;
4737
+ return pagelessFallback;
4685
4738
  }
4686
4739
  async waitForSim(simId, options = {}) {
4687
4740
  const attempts = options.attempts ?? 10;
@@ -4695,9 +4748,12 @@ var init_bridge_host = __esm({
4695
4748
  }
4696
4749
  shouldPromoteSim(sim) {
4697
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;
4698
4754
  const isPrimaryCandidate = sim.origin?.includes(":5173");
4699
- const currentIsPrimary = current?.origin?.includes(":5173");
4700
- return !current || current.ws.readyState !== import_ws.WebSocket.OPEN || !!isPrimaryCandidate || !currentIsPrimary;
4755
+ const currentIsPrimary = current.origin?.includes(":5173");
4756
+ return !!isPrimaryCandidate || !currentIsPrimary;
4701
4757
  }
4702
4758
  broadcastSimAssignments() {
4703
4759
  for (const sim of this.sims.values()) {
@@ -5474,6 +5530,10 @@ var SOOTSIM_COMPAT_WRAPPER_REAL_PACKAGES = {
5474
5530
  specifier: "@sootsim-internal/expo-brightness-real",
5475
5531
  packageName: "expo-brightness"
5476
5532
  },
5533
+ expoConstants: {
5534
+ specifier: "@sootsim-internal/expo-constants-real",
5535
+ packageName: "expo-constants"
5536
+ },
5477
5537
  expoCalendar: {
5478
5538
  specifier: "@sootsim-internal/expo-calendar-real",
5479
5539
  packageName: "expo-calendar"
package/dist-lib/vite.cjs CHANGED
@@ -1,4 +1,4 @@
1
- /*! sootsim v0.1.51 | (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.51",
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.51 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
- import{a,b,c,d}from"./chunk-HATEGE6O.js";import"./chunk-BKXH674Z.js";import"./chunk-5PKYORP6.js";import"./chunk-ACQXOAQI.js";import"./chunk-FSTOUA6L.js";import"./chunk-3BUWCNVX.js";export{c as ensureDaemonRunning,a as ensureRuntimeInstalled,d as ensureSootsimReady,b as resolveBootstrapPort};
@@ -1,2 +0,0 @@
1
- /*! sootsim v0.1.51 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
- import{a,b,c,d,e}from"./chunk-ZEIDKF3M.js";import"./chunk-3BUWCNVX.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 +0,0 @@
1
- /*! sootsim v0.1.51 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
@@ -1,2 +0,0 @@
1
- /*! sootsim v0.1.51 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
- var t="http://localhost:5173/";export{t as a};
@@ -1,2 +0,0 @@
1
- /*! sootsim v0.1.51 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
- var O="sootsim close";export{O as a};
@@ -1 +0,0 @@
1
- /*! sootsim v0.1.51 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
@@ -1 +0,0 @@
1
- /*! sootsim v0.1.51 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
@@ -1,2 +0,0 @@
1
- /*! sootsim v0.1.51 | (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-ZT7672XM.js";import"./chunk-SLAAAEUZ.js";import"./chunk-LMINUIAR.js";import"./chunk-265YGINI.js";import"./chunk-DBYZF6KL.js";import"./chunk-VDUWPVZT.js";import"./chunk-EWSS4C2R.js";import"./chunk-BGZRRNK4.js";import"./chunk-4D7Z64YQ.js";import"./chunk-BKXH674Z.js";import"./chunk-5PKYORP6.js";import"./chunk-ACQXOAQI.js";import"./chunk-FSTOUA6L.js";import"./chunk-3BUWCNVX.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.51 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
- import{a}from"./chunk-FUHHRW7G.js";import"./chunk-3BUWCNVX.js";export{a as APPS};
@@ -1,41 +0,0 @@
1
- /*! sootsim v0.1.51 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
- import{c as v,e as E,h as b}from"./chunk-BKXH674Z.js";import{b as $}from"./chunk-5PKYORP6.js";import"./chunk-ACQXOAQI.js";import"./chunk-FSTOUA6L.js";import"./chunk-3BUWCNVX.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.51 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
- import"./chunk-DV3SI64Q.js";import{a,b,c,d,e,f,g,h,i}from"./chunk-265YGINI.js";import"./chunk-DBYZF6KL.js";import"./chunk-VDUWPVZT.js";import"./chunk-EWSS4C2R.js";import"./chunk-BGZRRNK4.js";import"./chunk-FSTOUA6L.js";import"./chunk-3BUWCNVX.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.51 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
- import{a,b,c,d}from"./chunk-ET5NKJVL.js";import"./chunk-AWQGGSDW.js";import"./chunk-PTW5KT4I.js";import"./chunk-3HO4Q25D.js";import"./chunk-IEYPDVW2.js";import"./chunk-SPMHQKNI.js";import"./chunk-ZT7672XM.js";import"./chunk-SLAAAEUZ.js";import"./chunk-LMINUIAR.js";import"./chunk-265YGINI.js";import"./chunk-DBYZF6KL.js";import"./chunk-VDUWPVZT.js";import"./chunk-FUHHRW7G.js";import"./chunk-IENPCJTB.js";import"./chunk-6NR6NFDC.js";import"./chunk-EWSS4C2R.js";import"./chunk-BGZRRNK4.js";import"./chunk-VR2UDTSA.js";import"./chunk-4D7Z64YQ.js";import"./chunk-45XEBYVX.js";import"./chunk-67AZW4HJ.js";import"./chunk-BKXH674Z.js";import"./chunk-5PKYORP6.js";import"./chunk-VXLRXQER.js";import"./chunk-P2IC3VRD.js";import"./chunk-ACQXOAQI.js";import"./chunk-FSTOUA6L.js";import"./chunk-3BUWCNVX.js";export{b as discoverSootsimUrl,a as parseFlowFile,d as runFlow,c as runFlowPlayback};
@@ -1,2 +0,0 @@
1
- /*! sootsim v0.1.51 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
- import{a as o}from"./chunk-RSEV5NWY.js";import"./chunk-AQN3BB3D.js";import"./chunk-HATEGE6O.js";import"./chunk-BKXH674Z.js";import"./chunk-5PKYORP6.js";import"./chunk-VXLRXQER.js";import"./chunk-P2IC3VRD.js";import"./chunk-ACQXOAQI.js";import"./chunk-FSTOUA6L.js";import"./chunk-3BUWCNVX.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};
@@ -1,18 +0,0 @@
1
- /*! sootsim v0.1.51 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
- import{a as N}from"./chunk-IEYPDVW2.js";import"./chunk-IENPCJTB.js";import{d as j}from"./chunk-6NR6NFDC.js";import"./chunk-EWSS4C2R.js";import{d as L}from"./chunk-BGZRRNK4.js";import{c as b,e as v}from"./chunk-BKXH674Z.js";import{b as V}from"./chunk-5PKYORP6.js";import"./chunk-VXLRXQER.js";import"./chunk-P2IC3VRD.js";import"./chunk-ACQXOAQI.js";import"./chunk-FSTOUA6L.js";import"./chunk-3BUWCNVX.js";import{existsSync as de,mkdirSync as _,readdirSync as ce,readFileSync as le,rmSync as W,writeFileSync as M}from"fs";import{homedir as ue,tmpdir as me}from"os";import{dirname as P,extname as G,join as I,resolve as fe}from"path";var q=6e4,pe=new Set(["--sim","--port","-p","--mode","--duration","--fps","--format","--output","-o","--frames","--max-width","--origin"]),ge=new Set(["start","stop","cancel","status"]);function we(e){for(let t=0;t<e.length;t++){let o=e[t];if(o.startsWith("-")){pe.has(o)&&t++;continue}return ge.has(o)?{name:o,index:t}:null}return null}async function Ce(e,t){let o=we(e);if(o){let a=[...e.slice(0,o.index),...e.slice(o.index+1)];if(o.name==="start"){await Se(a,t);return}if(o.name==="stop"){await _e(a,t);return}if(o.name==="cancel"){await xe(a,t);return}await Re(a,t);return}let i=b(e,{port:t.port,stripBooleanFlags:["--no-shell","--shell-only","--open"],stripValueFlags:["--mode","--duration","--fps","--format","--output","--frames","--max-width","--origin"]}),r=X(l(e,"--mode")),n=e.includes("--shell-only")?"shell":e.includes("--no-shell")?"tenant":void 0,d=l(e,"--format");d&&!["webm","mp4","gif","png"].includes(d)&&(console.error(` invalid --format "${d}" \u2014 expected webm | mp4 | gif | png`),process.exit(1));let c=l(e,"--output"),s=Number(l(e,"--duration")??"10");(!Number.isFinite(s)||s<=0)&&(console.error(` invalid --duration "${l(e,"--duration")}" \u2014 expected a positive number of seconds`),process.exit(1));let u=Number(l(e,"--fps")??"30"),f=l(e,"--frames");if(f!==void 0){let a=Number(f);(!Number.isInteger(a)||a<=0)&&(console.error(` invalid --frames "${f}" \u2014 expected a positive integer count`),process.exit(1))}let S=e.includes("--open"),J=l(e,"--max-width")?Number(l(e,"--max-width")):void 0,y=Math.max(100,Math.round(s*1e3)),ie=l(e,"--origin");if(r==="live"||r==="combined"){c&&console.log(` note: --output is ignored for --mode ${r} \u2014 the recording uploads to /preview/<id>`),n&&r==="live"&&console.log(` note: --${n==="shell"?"shell-only":"no-shell"} is ignored for --mode live \u2014 live recordings capture events only, no video`),await N("record",{originOverride:ie});let a=v({...i,commandTimeoutMs:6e4});try{await Z(a),await ee(a),await oe(a,r,r==="combined"?n:void 0)||(console.error(` start failed: recording store refused to start (${r})`),process.exit(1)),console.log(` recording ${r} for ${s}s`),await new Promise($=>setTimeout($,y)),await te(a);let O=await re(a);ne(O,S,r)}finally{a.close()}return}let F=f?Number(f):null,R=he(d,c,F);S&&console.log(" note: --open is ignored for local-file capture \u2014 it applies to --mode live/combined");let g=v({...i,commandTimeoutMs:6e4});try{if(await H(g),R==="png"){let h=F??10,p=B(c,`sootsim-frames-${k()}`);c&&G(c)&&console.log(` note: --frames writes multiple pngs, so --output "${c}" is a directory \u2014 frame-NNN.png files land inside it`),_(p,{recursive:!0});for(let m of ce(p))/^frame-\d+\.png$/.test(m)&&W(I(p,m),{force:!0});console.log(` sampling ${h} frames over ${s}s \u2192 ${p}`);let w=await g.send({type:"evaluate",code:`window.__sootsimRecorder.startFrameCapture({ count: ${h}, durationMs: ${y}${n?`, layers: ${JSON.stringify(n)}`:""} })`});(!w.ok||!w.requestId)&&(console.error(` frame capture start failed: ${w.error??"unknown error"}`),process.exit(1)),await new Promise(m=>setTimeout(m,y));let se=Date.now()+Math.max(5e3,y),C=null;for(;;){let m=await g.send({type:"evaluate",code:`window.__sootsimRecorder.getFrameCaptureResult(${w.requestId})`});if(m||(console.error(" frame capture result missing"),process.exit(1)),m.done){m.ok||(console.error(` frame capture failed: ${m.error??"unknown error"}`),process.exit(1)),C=m.frames??[];break}Date.now()>=se&&(console.error(" frame capture timed out"),process.exit(1)),await new Promise(E=>setTimeout(E,100))}C.forEach((m,E)=>{let ae=`${p}/frame-${String(E+1).padStart(3,"0")}.png`;M(ae,Buffer.from(m.data,"base64"))}),console.log(` saved ${C.length} frames`);return}if(R==="gif"){let h=F??Math.max(10,Math.round(s*u/3)),p=B(c,`sootsim-${k()}.gif`);_(P(p),{recursive:!0}),console.log(` encoding gif: ${h} frames over ${s}s \u2192 ${p}`);let w=await g.send({type:"evaluate",code:`window.__sootsimRecorder.captureGif({ frames: ${h}, durationMs: ${y}${J?`, maxWidth: ${J}`:""}${n?`, layers: ${JSON.stringify(n)}`:""} })`});w||(console.error(" gif capture returned no frames"),process.exit(1)),M(p,Buffer.from(w.data,"base64")),console.log(` saved: ${p} (${T(w.size)})`);return}let a=B(c,`sootsim-${k()}.${R}`);_(P(a),{recursive:!0});let A={format:R,fps:u};n&&(A.layers=n);let O=await g.send({type:"evaluate",code:`window.__sootsimRecorder.start(${JSON.stringify(A)})`});O.ok||(console.error(` start failed: ${O.error??"unknown error"}`),process.exit(1)),console.log(` recording ${R} for ${s}s \u2192 ${a}`),await new Promise(h=>setTimeout(h,y));let $=await g.send({type:"evaluate",code:"window.__sootsimRecorder.stop()"});$.ok||(console.error(` stop failed: ${$.error??"unknown error"}`),process.exit(1)),$.size||(console.error(" recorder returned an empty blob \u2014 nothing written"),process.exit(1)),await Q(g,a),console.log(` saved: ${a} (${T($.size)})`)}finally{g.close()}}var be=6e3;async function K(e,t){try{return await e.send({type:"evaluate",code:t},{timeoutMs:be})}catch(o){let i=o instanceof Error?o.message:String(o);throw/^command timed out after \d+s$/.test(i)&&(console.error(" sim did not respond \u2014 it is connected to the bridge but has not\n loaded an app (or its page is unresponsive). run `sootsim list`\n and target a sim with a loaded app via --sim <id>."),process.exit(1)),o}}async function H(e){await K(e,'typeof window.__sootsimRecorder !== "undefined"')||(console.error(" window.__sootsimRecorder missing \u2014 is sootsim engine running in this sim?"),process.exit(1))}async function Q(e,t){let o=[],i=0;for(;;){let r=await e.send({type:"evaluate",code:`window.__sootsimRecorder.getBlobBase64({ offset: ${i}, chunk: 2097152 })`});if(!r)throw new Error("no blob available on recorder");if(o.push(Buffer.from(r.data,"base64")),i=r.offset,r.done)break}M(t,Buffer.concat(o))}function l(e,t){let o=e.indexOf(t);if(!(o<0||o===e.length-1))return e[o+1]}function ve(e){if(!e)return;let t=G(e).toLowerCase().replace(/^\./,"");if(t==="webm"||t==="mp4"||t==="gif")return t;if(t==="png")return"png"}function he(e,t,o){return e||(o!=null?"png":ve(t)??"webm")}function k(){return new Date().toISOString().replace(/[:T]/g,"-").replace(/\..+/,"")}function ye(){let e=I(ue(),".sootsim","recordings");return _(e,{recursive:!0}),e}function B(e,t){return e?fe(process.cwd(),e):I(ye(),t)}function T(e){return e<1024?`${e}B`:e<1024*1024?`${(e/1024).toFixed(1)}KB`:`${(e/(1024*1024)).toFixed(2)}MB`}function X(e){if(!e)return"video";if(e==="video"||e==="live"||e==="combined")return e;console.error(` invalid --mode "${e}" \u2014 expected video | live | combined`),process.exit(1)}function D(){return I(me(),`sootsim-recording-${V()}.json`)}function U(){let e=D();if(!de(e))return null;try{return{mode:"video",...JSON.parse(le(e,"utf8"))}}catch{return W(e,{force:!0}),null}}function $e(e){M(D(),JSON.stringify(e,null,2))}function x(){W(D(),{force:!0})}function z(e,t){e&&t.simId&&e!==t.simId&&console.log(` note: the tracked recording session is on sim ${t.simId}, not the
3
- requested sim ${e}. record state is global (not per-sim);
4
- this command acts on that session regardless of --sim.`)}async function Se(e,t){let o=U();o&&(console.error(` recording already in progress (started ${o.startedAt}, sim ${o.simId??"?"}). run \`sootsim record stop\` first, or \`sootsim record cancel\` to discard.`),process.exit(1));let i=b(e,{port:t.port,stripBooleanFlags:["--no-shell","--shell-only"],stripValueFlags:["--mode","--fps","--format","--max-width","--origin"]}),r=X(l(e,"--mode")),n=e.includes("--shell-only")?"shell":e.includes("--no-shell")?"tenant":void 0,d=l(e,"--format"),c=d==="mp4"?"mp4":"webm";d&&c!==d&&(console.error(` record start only supports webm or mp4 (got: ${d}). for gif/png use atomic mode: sootsim record --format ${d} --duration <s>`),process.exit(1));let s=Number(l(e,"--fps")??"30"),u=v({...i,commandTimeoutMs:15e3});try{if(r==="live"||r==="combined")n&&r==="live"&&console.log(` note: --${n==="shell"?"shell-only":"no-shell"} is ignored for --mode live \u2014 live recordings capture events only, no video`),await N("record",{originOverride:l(e,"--origin")}),await Z(u),await ee(u),await oe(u,r,r==="combined"?n:void 0)||(console.error(` start failed: recording store refused to start (${r})`),process.exit(1));else{await H(u);let f={format:c,fps:s};n&&(f.layers=n);let S=await u.send({type:"evaluate",code:`window.__sootsimRecorder.start(${JSON.stringify(f)})`});S.ok||(console.error(` start failed: ${S.error??"unknown error"}`),process.exit(1))}$e({simId:i.simId??null,mode:r,format:c,fps:s,layers:n,startedAt:new Date().toISOString()}),console.log(r==="video"?` recording ${c} @ ${s}fps${n?` (${n})`:""} \u2014 run \`sootsim record stop --output <path>\` when done`:` recording ${r} \u2014 run \`sootsim record stop\` when done (add --open to launch the preview URL)`)}finally{u.close()}}async function Y(e){try{let t=await e.send({type:"evaluate",code:`(() => {
5
- const store = window.SootSim?.bridges?.getRecordingState?.();
6
- const headless = window.__sootsimRecorder?.state?.();
7
- return { store: store ? store.state : undefined, headless };
8
- })()`});return t?t.store==="recording"||t.headless==="recording"?"recording":t.store==="processing"?"processing":t.store==="idle"||t.headless==="idle"?"idle":null:null}catch{return null}}async function Re(e,t){let o=U();if(o){z(b(e,{port:t.port}).simId,o),o.mode==="video"?console.log(` recording ${o.mode} (${o.format} @ ${o.fps}fps) on sim ${o.simId??"?"} since ${o.startedAt}`):console.log(` recording ${o.mode} on sim ${o.simId??"?"} since ${o.startedAt}`);return}let i=b(e,{port:t.port}),r=v({...i,commandTimeoutMs:8e3});try{let n=await Y(r);console.log(n==="recording"||n==="processing"?` a recording is in progress (engine state: ${n}), but not via
9
- \`record start\` \u2014 likely an atomic \`record --duration\` run or the
10
- in-browser record button. it will finish and upload on its own.
11
- \`record stop\` / \`record cancel\` only manage \`record start\` sessions.`:" no recording in progress")}finally{r.close()}}async function xe(e,t){let o=U();if(!o){let d=b(e,{port:t.port}),c=v({...d,commandTimeoutMs:8e3});try{let s=await Y(c);console.log(s==="recording"||s==="processing"?" a recording is in progress, but not via `record start` \u2014 it was\n started by an atomic `record --duration` run or the in-browser\n record button, which own their own lifecycle. it cannot be\n cancelled from here; it will finish on its own.":" no recording in progress")}finally{c.close()}return}let i=b(e,{port:t.port});z(i.simId,o);let r=o.simId??i.simId??void 0,n=v({...i,simId:r,commandTimeoutMs:15e3});try{o.mode==="live"||o.mode==="combined"?await n.send({type:"evaluate",code:"void window.SootSim?.bridges?.cancelRecording?.()"}):await n.send({type:"evaluate",code:"window.__sootsimRecorder.stop()"})}catch{}finally{x(),n.close()}console.log(" recording cancelled")}async function _e(e,t){let o=U();o||(console.error(" no recording in progress. start one with `sootsim record start`."),process.exit(1));let i=b(e,{port:t.port,stripBooleanFlags:["--open"],stripValueFlags:["--output"]});z(i.simId,o);let r=o.simId??i.simId??void 0,n=e.includes("--open"),d=v({...i,simId:r,commandTimeoutMs:6e4});try{if(o.mode==="live"||o.mode==="combined"){await te(d);let f=await re(d);x(),ne(f,n,o.mode);return}let c=l(e,"--output"),s=B(c,`sootsim-${k()}.${o.format}`);_(P(s),{recursive:!0});let u=await d.send({type:"evaluate",code:"window.__sootsimRecorder.stop()"});u.ok||(console.error(` stop failed: ${u.error??"unknown error"}`),x(),process.exit(1)),u.size||(console.error(" recorder returned an empty blob \u2014 nothing written"),x(),process.exit(1)),await Q(d,s),x(),console.log(` saved: ${s} (${T(u.size)})`)}finally{d.close()}}async function Z(e){await K(e,'typeof window.SootSim?.bridges?.startRecording === "function" && typeof window.SootSim?.bridges?.stopRecording === "function"')||(console.error(" SootSim.bridges.startRecording missing \u2014 is sootsim engine running in this sim?"),process.exit(1))}async function ee(e){let t=j();if(!t)return;let o=t.kind==="api-key"?t.secret:t.token;await e.send({type:"evaluate",code:`(() => {
12
- const set = window.SootSim && window.SootSim.bridges && window.SootSim.bridges.setSession
13
- if (typeof set !== 'function') return false
14
- set({ token: ${JSON.stringify(o)}, user: null })
15
- return true
16
- })()`})||(console.error(" SootSim.bridges.setSession missing \u2014 this sim is running an engine\n build without CLI-injected preview auth. reload the sim or open a\n fresh one (`sootsim open --new`); if it persists, update sootsim."),process.exit(1))}async function oe(e,t,o){return await e.send({type:"evaluate",code:`window.SootSim.bridges.startRecording(${JSON.stringify(t)}${o?`, ${JSON.stringify(o)}`:""})`})===!0}async function te(e){await e.send({type:"evaluate",code:"void window.SootSim.bridges.stopRecording()"})}async function re(e){let t=Date.now()+q;for(;Date.now()<t;){let o=await e.send({type:"evaluate",code:"(() => { const s = window.SootSim?.bridges?.getRecordingState?.(); return s ? { state: s.state, lastUpload: s.lastUpload, uploadError: s.uploadError } : null })()"});if(o&&o.state==="idle"){if(o.uploadError)return{uploadError:o.uploadError};if(o.lastUpload?.previewUrl)return{previewUrl:o.lastUpload.previewUrl,eventCount:o.lastUpload.eventCount}}await new Promise(i=>setTimeout(i,300))}return{uploadError:`upload did not settle within ${q/1e3}s`}}function ne(e,t,o){e.uploadError&&(console.error(` upload failed: ${e.uploadError}`),process.exit(1)),e.previewUrl||(console.error(" upload returned no preview URL"),process.exit(1)),console.log(` preview: ${e.previewUrl}`),(o==="live"||o==="combined")&&typeof e.eventCount=="number"&&console.log(` captured ${e.eventCount} event${e.eventCount===1?"":"s"}`),(o==="live"||o==="combined")&&e.eventCount===0&&console.log(o==="combined"?` note: this combined recording captured no events \u2014 the Live tab has
17
- nothing to replay, and the Video tab may stall with no events to drive it.`:` note: this live recording captured no events \u2014 the preview has nothing
18
- to replay and will boot a fresh interactive session instead.`),t&&L(e.previewUrl)}export{ve as extToFormat,he as resolveFormat,Ce as runRecord,l as valueOf};
@@ -1,2 +0,0 @@
1
- /*! sootsim v0.1.51 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
- import{a}from"./chunk-M7HK7MWE.js";import"./chunk-BKXH674Z.js";import"./chunk-5PKYORP6.js";import"./chunk-CLSZB5BN.js";import"./chunk-ACQXOAQI.js";import"./chunk-FSTOUA6L.js";import"./chunk-3BUWCNVX.js";export{a as runRuntime};
@@ -1,2 +0,0 @@
1
- /*! sootsim v0.1.51 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
- import{a}from"./chunk-RSEV5NWY.js";import"./chunk-AQN3BB3D.js";import"./chunk-HATEGE6O.js";import"./chunk-BKXH674Z.js";import"./chunk-5PKYORP6.js";import"./chunk-VXLRXQER.js";import"./chunk-P2IC3VRD.js";import"./chunk-ACQXOAQI.js";import"./chunk-FSTOUA6L.js";import"./chunk-3BUWCNVX.js";export{a as runSetupRepo};