sootsim 0.1.211 → 0.1.213

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 (139) hide show
  1. package/README.md +6 -6
  2. package/dist-cli/bin.js +4 -4
  3. package/dist-cli/chunks/{agent-YMWIMQSZ.js → agent-PXBOBQCI.js} +2 -2
  4. package/dist-cli/chunks/{agent-wrapper-6MN4L5WR.js → agent-wrapper-PJWCDUES.js} +2 -2
  5. package/dist-cli/chunks/{app-fonts-C7OF7H5G.js → app-fonts-5BFK3BPJ.js} +2 -2
  6. package/dist-cli/chunks/{assert-JVVKDGJZ.js → assert-ZQBH2FHK.js} +2 -2
  7. package/dist-cli/chunks/{auth-K5PLXC65.js → auth-6VN3LBWW.js} +2 -2
  8. package/dist-cli/chunks/beta-ICE6G2X3.js +2 -0
  9. package/dist-cli/chunks/{camera-LN5T6FHN.js → camera-3EVST4X2.js} +2 -2
  10. package/dist-cli/chunks/{chunk-U74PRAD5.js → chunk-345SCUPN.js} +2 -2
  11. package/dist-cli/chunks/{chunk-CNMIJNUJ.js → chunk-34R2XUUH.js} +2 -2
  12. package/dist-cli/chunks/{chunk-IHQXMMQA.js → chunk-34ZLNSTB.js} +2 -2
  13. package/dist-cli/chunks/{chunk-VDLNYLQ3.js → chunk-6A64BUDU.js} +1 -1
  14. package/dist-cli/chunks/{chunk-FLQJ4E4B.js → chunk-6GF7AYWF.js} +2 -2
  15. package/dist-cli/chunks/{chunk-CDMWW44J.js → chunk-7ETH4QC5.js} +2 -2
  16. package/dist-cli/chunks/{chunk-CZJWXULV.js → chunk-A5PGH6GU.js} +3 -3
  17. package/dist-cli/chunks/{chunk-RNCB3OP2.js → chunk-A5W26KZ2.js} +20 -8
  18. package/dist-cli/chunks/{chunk-PC3RU3SN.js → chunk-B4ZHF6HX.js} +1 -1
  19. package/dist-cli/chunks/{chunk-SSYQZ5IN.js → chunk-BBHSIDL7.js} +2 -2
  20. package/dist-cli/chunks/{chunk-OJXQDTQP.js → chunk-CK5W32IL.js} +1 -1
  21. package/dist-cli/chunks/{chunk-LN2YBE53.js → chunk-DCNE55YI.js} +3 -3
  22. package/dist-cli/chunks/{chunk-UXJC5TWI.js → chunk-DL5UW643.js} +1 -1
  23. package/dist-cli/chunks/{chunk-XNJNWR34.js → chunk-E3UTRL4K.js} +2 -2
  24. package/dist-cli/chunks/{chunk-ADHPC2X3.js → chunk-GGNU6KXJ.js} +2 -2
  25. package/dist-cli/chunks/{chunk-75ZI44EE.js → chunk-IV5EGT4L.js} +3 -3
  26. package/dist-cli/chunks/{chunk-RCNPJNHG.js → chunk-KWPTKVOD.js} +1 -1
  27. package/dist-cli/chunks/{chunk-FUUQJQ6D.js → chunk-L6CUBNOP.js} +1 -1
  28. package/dist-cli/chunks/{chunk-CA53GTDU.js → chunk-M6QAVNUD.js} +1 -1
  29. package/dist-cli/chunks/{chunk-TBBKY5QW.js → chunk-MBTZ72OK.js} +2 -2
  30. package/dist-cli/chunks/{chunk-UMBVQZ22.js → chunk-MF7JDUE4.js} +2 -2
  31. package/dist-cli/chunks/{chunk-AVJOEZLW.js → chunk-MHZUULXC.js} +2 -2
  32. package/dist-cli/chunks/{chunk-2OE3UXXF.js → chunk-NYBRCPXY.js} +2 -2
  33. package/dist-cli/chunks/{chunk-3AMN64TG.js → chunk-PMZU2MXQ.js} +1 -1
  34. package/dist-cli/chunks/{chunk-T3L3I3XN.js → chunk-PQRTN7R3.js} +2 -2
  35. package/dist-cli/chunks/{chunk-NLHBFC44.js → chunk-QYAABDHA.js} +9 -9
  36. package/dist-cli/chunks/{chunk-KDCFEKQG.js → chunk-R3Z6QS26.js} +1 -1
  37. package/dist-cli/chunks/{chunk-4L4WXCMZ.js → chunk-RRMXW3OZ.js} +2 -2
  38. package/dist-cli/chunks/{chunk-GDIUF4LO.js → chunk-SAJDH6T4.js} +2 -2
  39. package/dist-cli/chunks/{chunk-OEVW6X6O.js → chunk-SNDRRWLJ.js} +1 -1
  40. package/dist-cli/chunks/{chunk-33FTN3AV.js → chunk-URSWUWMB.js} +3 -3
  41. package/dist-cli/chunks/{chunk-E2HECQS5.js → chunk-VCU23PAS.js} +28 -28
  42. package/dist-cli/chunks/{chunk-HYCIJ46S.js → chunk-W77R37C6.js} +1 -1
  43. package/dist-cli/chunks/{chunk-MRVFOA46.js → chunk-W7XLNK6M.js} +2 -2
  44. package/dist-cli/chunks/{chunk-E2TCQ5AD.js → chunk-WWCLVFFT.js} +1 -1
  45. package/dist-cli/chunks/{chunk-OYKIZT5Q.js → chunk-XKYWN32Q.js} +1 -1
  46. package/dist-cli/chunks/{chunk-AQXWKFSQ.js → chunk-XRTETVLA.js} +1 -1
  47. package/dist-cli/chunks/chunk-YBSLFZF2.js +1 -0
  48. package/dist-cli/chunks/{chunk-KKOQCQ7C.js → chunk-YIRGMOQC.js} +1 -1
  49. package/dist-cli/chunks/chunk-YKTGO7GR.js +1 -0
  50. package/dist-cli/chunks/{chunk-TYJ7RKBZ.js → chunk-ZCIJF6TG.js} +2 -2
  51. package/dist-cli/chunks/{chunk-GIPNU35K.js → chunk-ZMCH7LNI.js} +2 -2
  52. package/dist-cli/chunks/cli-version-X6SBWYZR.js +2 -0
  53. package/dist-cli/chunks/{compat-FHMWPGR4.js → compat-2EYTY3H2.js} +3 -3
  54. package/dist-cli/chunks/{config-OKQY5P52.js → config-RE5F2ANP.js} +2 -2
  55. package/dist-cli/chunks/{control-7WL54I6D.js → control-XATEDZ5J.js} +2 -2
  56. package/dist-cli/chunks/daemon-JLQHIAJB.js +2 -0
  57. package/dist-cli/chunks/{debug-QWZHZQPU.js → debug-YBWZ46PB.js} +3 -3
  58. package/dist-cli/chunks/{desktop-FXGRW74A.js → desktop-Q7I2G5LT.js} +3 -3
  59. package/dist-cli/chunks/{detox-3EDUFJTL.js → detox-RIAPIQLU.js} +2 -2
  60. package/dist-cli/chunks/{device-QCRIH4UL.js → device-PPHHQL47.js} +2 -2
  61. package/dist-cli/chunks/{diagnose-URCT4GRE.js → diagnose-FAMYDGKH.js} +2 -2
  62. package/dist-cli/chunks/drivers-DUQEV3GT.js +2 -0
  63. package/dist-cli/chunks/flow-BKVP4VKL.js +2 -0
  64. package/dist-cli/chunks/help-KDPPO3QK.js +2 -0
  65. package/dist-cli/chunks/{home-paths-EO6LWXWX.js → home-paths-H34FDUJS.js} +2 -2
  66. package/dist-cli/chunks/inspect-BASDWZYD.js +2 -0
  67. package/dist-cli/chunks/install-desktop-RMAWV6JZ.js +2 -0
  68. package/dist-cli/chunks/{login-7NUQAWXS.js → login-DVCETH23.js} +4 -4
  69. package/dist-cli/chunks/{logout-BH53ZI7B.js → logout-MJ5323X4.js} +2 -2
  70. package/dist-cli/chunks/{maestro-C3RK43L7.js → maestro-Y6GUYLSM.js} +3 -3
  71. package/dist-cli/chunks/{maestro-generate-NJBAT2VF.js → maestro-generate-22RWS4QX.js} +3 -3
  72. package/dist-cli/chunks/{mode-2LMGYLFI.js → mode-OLGFFUSY.js} +2 -2
  73. package/dist-cli/chunks/optional-demo-registry-OYI5WQN4.js +2 -0
  74. package/dist-cli/chunks/{perf-LA7ZSQ7P.js → perf-UXEZYT3O.js} +2 -2
  75. package/dist-cli/chunks/{record-3RNPPFI5.js → record-VS4A3B4Y.js} +3 -3
  76. package/dist-cli/chunks/runtime-IYN3SKFL.js +2 -0
  77. package/dist-cli/chunks/{screenshot-command-KIWXTT6Q.js → screenshot-command-4X3ERV33.js} +3 -3
  78. package/dist-cli/chunks/{screenshots-capture-ZADO3BSL.js → screenshots-capture-NJTPWWPZ.js} +2 -2
  79. package/dist-cli/chunks/{serve-64IOEG4C.js → serve-Q3AHVMOA.js} +2 -2
  80. package/dist-cli/chunks/{setup-GANEERC5.js → setup-4I2YQGRE.js} +3 -3
  81. package/dist-cli/chunks/{skills-DYN4EKIN.js → skills-HR56BS2S.js} +2 -2
  82. package/dist-cli/chunks/{storage-773UY5XZ.js → storage-2CG4U25V.js} +2 -2
  83. package/dist-cli/chunks/store-YITXNLYN.js +2 -0
  84. package/dist-cli/chunks/telemetry-XQHZBPJE.js +2 -0
  85. package/dist-cli/chunks/{timeline-HLF3CJNH.js → timeline-YCT2GPZU.js} +2 -2
  86. package/dist-cli/chunks/{upgrade-RDAUF53R.js → upgrade-WBNIAFCB.js} +2 -2
  87. package/dist-cli/chunks/upload-QG3WB6P6.js +2 -0
  88. package/dist-cli/chunks/{version-63PZYMY6.js → version-PDUFTOM7.js} +2 -2
  89. package/dist-cli/chunks/web-DQQDPOON.js +2 -0
  90. package/dist-cli/chunks/{what-happened-T3WJ7LTW.js → what-happened-CGNTKFOU.js} +2 -2
  91. package/dist-lib/agent-daemon-client.cjs +1 -1
  92. package/dist-lib/agent-events.cjs +1 -1
  93. package/dist-lib/agent-identity.cjs +1 -1
  94. package/dist-lib/agent-sessions.cjs +1 -1
  95. package/dist-lib/attached-projects.cjs +1 -1
  96. package/dist-lib/auth/shared-session.cjs +1 -1
  97. package/dist-lib/backend-origin.cjs +1 -1
  98. package/dist-lib/beta.cjs +1 -1
  99. package/dist-lib/beta.mjs +1 -1
  100. package/dist-lib/bridge-constants.cjs +1 -1
  101. package/dist-lib/cli-constants.cjs +1 -1
  102. package/dist-lib/config.cjs +1 -1
  103. package/dist-lib/detox/index.cjs +1 -1
  104. package/dist-lib/dev-bundle-resolution.cjs +1 -1
  105. package/dist-lib/home-paths.cjs +1 -1
  106. package/dist-lib/host/bridge-host.cjs +1 -1
  107. package/dist-lib/host/fetch-proxy-handler.cjs +1 -1
  108. package/dist-lib/host/fetch-proxy-overrides.cjs +1 -1
  109. package/dist-lib/host/fetch-proxy-overrides.mjs +1 -1
  110. package/dist-lib/host/websocket-proxy.cjs +1 -1
  111. package/dist-lib/index.cjs +1 -1
  112. package/dist-lib/jump-to-source-babel.cjs +1 -1
  113. package/dist-lib/menu.cjs +1 -1
  114. package/dist-lib/menu.mjs +1 -1
  115. package/dist-lib/metro.cjs +1 -1
  116. package/dist-lib/profiles.cjs +1 -1
  117. package/dist-lib/render-mode.cjs +1 -1
  118. package/dist-lib/scripts/dev-server-scanner.cjs +1 -1
  119. package/dist-lib/sdk.cjs +1 -1
  120. package/dist-lib/sdk.mjs +1 -1
  121. package/dist-lib/skills.cjs +4 -4
  122. package/dist-lib/vite.cjs +1 -1
  123. package/package.json +1 -1
  124. package/dist-cli/chunks/beta-FFPVM735.js +0 -2
  125. package/dist-cli/chunks/chunk-BVOMJLZJ.js +0 -1
  126. package/dist-cli/chunks/chunk-X5F2XRCT.js +0 -1
  127. package/dist-cli/chunks/cli-version-6ZGU3OMS.js +0 -2
  128. package/dist-cli/chunks/daemon-MJAW7WLB.js +0 -2
  129. package/dist-cli/chunks/drivers-K6AYJ4K4.js +0 -2
  130. package/dist-cli/chunks/flow-FJK6CFCI.js +0 -2
  131. package/dist-cli/chunks/help-GCSPMIWH.js +0 -2
  132. package/dist-cli/chunks/inspect-DLPOHI65.js +0 -2
  133. package/dist-cli/chunks/install-desktop-LKSETTBL.js +0 -2
  134. package/dist-cli/chunks/optional-demo-registry-A27PORZB.js +0 -2
  135. package/dist-cli/chunks/runtime-7VEUKPNE.js +0 -2
  136. package/dist-cli/chunks/store-LSC33DBI.js +0 -2
  137. package/dist-cli/chunks/telemetry-4DVRYGKH.js +0 -2
  138. package/dist-cli/chunks/upload-KI23CKE4.js +0 -2
  139. package/dist-cli/chunks/web-XN5ZVSZR.js +0 -2
@@ -1,6 +1,6 @@
1
- /*! sootsim v0.1.211 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
- import{a as Ie,b as Ae,c as Ue}from"./chunk-IHQXMMQA.js";import{c as ke}from"./chunk-KKOQCQ7C.js";import{d as xe}from"./chunk-OJXQDTQP.js";import{g as Be,i as Ee,k as B}from"./chunk-TBBKY5QW.js";import{d as Re}from"./chunk-RCNPJNHG.js";import{a as ve,b as k}from"./chunk-CDMWW44J.js";import{a as Se}from"./chunk-SSYQZ5IN.js";import{createHash as mt}from"crypto";import{readFileSync as U}from"fs";import Oe from"path";import{gzipSync as ae,gunzipSync as ft}from"zlib";function _e(e){let t=(e||"").toLowerCase().split(";")[0].trim();return t?!(t.startsWith("image/")||t.startsWith("video/")||t.startsWith("audio/")||t==="font/woff2"||t==="application/font-woff2"||t==="application/zip"||t==="application/gzip"):!0}import{brotliCompressSync as nt,constants as rt}from"node:zlib";var st=9;function Pe(e){return nt(e,{params:{[rt.BROTLI_PARAM_QUALITY]:st}})}function oe(e,t){let r=new AbortController,o=setTimeout(()=>r.abort(new Error(`${t} timed out after ${e/1e3}s`)),e);return{signal:r.signal,cancel:()=>clearTimeout(o)}}async function ot(e){let t=oe(12e4,`PUT ${e.url}`),r;try{r=await fetch(e.url,{method:"PUT",headers:{"content-type":e.contentType},body:e.bytes,signal:t.signal})}finally{t.cancel()}if(!r.ok){let o=await r.text().catch(()=>"");throw new Error(`PUT ${e.url} failed ${r.status}: ${o.slice(0,200)}`)}}async function it(e,t=8,r){let o=0,i=0,a=e.length;await Promise.all(Array.from({length:Math.min(t,a)},async()=>{for(;o<a;){let u=e[o++];await ot(u),i++,r?.(i,a)}}))}function at(e,t,r,o){let i=[];i.push({url:e.bundle.putUrl,contentType:e.bundle.contentType,bytes:t});for(let a of e.files){let u=r.get(a.urlhash);u&&i.push({url:a.putUrl,contentType:a.contentType,bytes:u})}e.events&&o?.eventsBytes&&i.push({url:e.events.putUrl,contentType:e.events.contentType,bytes:o.eventsBytes}),e.timeline&&o?.timelineBytes&&i.push({url:e.timeline.putUrl,contentType:e.timeline.contentType,bytes:o.timelineBytes}),e.flowVideo&&o?.videoBytes&&i.push({url:e.flowVideo.putUrl,contentType:e.flowVideo.contentType,bytes:o.videoBytes}),e.storage&&o?.storageBytes&&i.push({url:e.storage.putUrl,contentType:e.storage.contentType,bytes:o.storageBytes}),e.failureBundle&&o?.failureBundleBytes&&i.push({url:e.failureBundle.putUrl,contentType:e.failureBundle.contentType,bytes:o.failureBundleBytes});for(let a of e.snapshots??[]){let u=o?.snapshotBytes?.get(a.id);u&&i.push({url:a.putUrl,contentType:a.contentType,bytes:u})}return i}function lt(e){return e.replace(/\/+$/,"")}var J=class extends Error{constructor(r,o,i,a=""){super(r);this.status=o;this.phase=i;this.responseText=a;this.name="PresignedUploadError"}};async function Le(e){let t=lt(e.originBase),r={"content-type":"application/json"};e.authHeader&&(r.authorization=e.authHeader),e.adminBypassToken&&(r["x-soot-admin-upload-bypass"]=e.adminBypassToken);let o=oe(3e4,"init"),i;try{i=await fetch(`${t}/api/preview/upload/init`,{method:"POST",headers:r,body:JSON.stringify(e.initBody),signal:o.signal})}finally{o.cancel()}if(!i.ok){let g=await i.text().catch(()=>"");throw new J(`init failed: ${i.status} ${g.slice(0,200)}`,i.status,"init",g)}let a=await i.json(),u=at(a,e.bundleBytes,e.filesByHash,e.extras);await it(u,e.concurrency??8,e.onPutProgress);let b=oe(3e4,"finalize"),f;try{f=await fetch(`${t}/api/preview/upload/finalize`,{method:"POST",headers:r,body:JSON.stringify({token:a.token}),signal:b.signal})}finally{b.cancel()}if(!f.ok){let g=await f.text().catch(()=>"");throw new J(`finalize failed: ${f.status} ${g.slice(0,200)}`,f.status,"finalize",g)}let C=await f.json();return{init:a,finalize:C}}function ut(e){return e!==null&&typeof e=="object"?e:null}function Fe(e){return typeof e=="number"&&Number.isFinite(e)?e:void 0}function ie(e){let t=ut(e);return t?t.schemaVersion===1&&Fe(t.t)!==void 0&&Fe(t.seq)!==void 0&&typeof t.context=="string"&&typeof t.kind=="string"&&"data"in t:!1}function ct(e,t){let r=[];for(let o of e.split(`
3
- `)){let i=o.trim();if(i)try{let a=JSON.parse(i);t(a)&&r.push(a)}catch{}}return r}function $e(e){return ct(e,ie)}function gt(e){if(!e)return null;try{let t=JSON.parse(e);return typeof t.message=="string"&&t.message?t.message:null}catch{return null}}var je=process.env.SOOTSIM_UPLOAD_ORIGIN||"https://sootbean.com",He=process.env.SOOTSIM_PREVIEW_ORIGIN||"https://sootsim.com",ue="http://localhost:3000",ht=2e3;async function yt(e){if(e)return e;if(process.env.SOOTSIM_UPLOAD_ORIGIN)return process.env.SOOTSIM_UPLOAD_ORIGIN;try{let t=await fetch(`${ue}/api/preview/upload/init`,{method:"OPTIONS",signal:AbortSignal.timeout(ht)});if(t.ok||t.status===204||t.status===405)return ue}catch{}return je}function F(e){return e.replace(/\/$/,"")}function bt(e){try{let r=new URL(e).hostname.replace(/^\[|\]$/g,"").toLowerCase();return r==="localhost"||r.endsWith(".localhost")||r==="0.0.0.0"||r==="::1"||/^127(?:\.\d{1,3}){3}$/.test(r)}catch{return!1}}function Mt(e){try{let t=new URL(e).hostname.toLowerCase();return t==="sootbean.com"||t.endsWith(".sootbean.com")}catch{return!1}}function wt(e,t){return t?F(t):process.env.SOOTSIM_PREVIEW_ORIGIN?F(process.env.SOOTSIM_PREVIEW_ORIGIN):bt(e)?F(e):Mt(e)?F(He):F(e)}function Tt(){console.log(`
1
+ /*! sootsim v0.1.213 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
+ import{a as Ie,b as Ae,c as Ue}from"./chunk-34ZLNSTB.js";import{c as ke}from"./chunk-YIRGMOQC.js";import{d as xe}from"./chunk-CK5W32IL.js";import{g as Be,i as Ee,k as B}from"./chunk-MBTZ72OK.js";import{d as Re}from"./chunk-KWPTKVOD.js";import{a as ve,b as k}from"./chunk-7ETH4QC5.js";import{a as Se}from"./chunk-BBHSIDL7.js";import{createHash as ft}from"crypto";import{readFileSync as U}from"fs";import Oe from"path";import{gzipSync as ae,gunzipSync as gt}from"zlib";function _e(e){let t=(e||"").toLowerCase().split(";")[0].trim();return t?!(t.startsWith("image/")||t.startsWith("video/")||t.startsWith("audio/")||t==="font/woff2"||t==="application/font-woff2"||t==="application/zip"||t==="application/gzip"):!0}import{brotliCompressSync as rt,constants as st}from"node:zlib";var ot=9;function Pe(e){return rt(e,{params:{[st.BROTLI_PARAM_QUALITY]:ot}})}function oe(e,t){let r=new AbortController,o=setTimeout(()=>r.abort(new Error(`${t} timed out after ${e/1e3}s`)),e);return{signal:r.signal,cancel:()=>clearTimeout(o)}}async function it(e){let t=oe(12e4,`PUT ${e.url}`),r;try{r=await fetch(e.url,{method:"PUT",headers:{"content-type":e.contentType},body:e.bytes,signal:t.signal})}finally{t.cancel()}if(!r.ok){let o=await r.text().catch(()=>"");throw new Error(`PUT ${e.url} failed ${r.status}: ${o.slice(0,200)}`)}}async function at(e,t=8,r){let o=0,i=0,a=e.length;await Promise.all(Array.from({length:Math.min(t,a)},async()=>{for(;o<a;){let u=e[o++];await it(u),i++,r?.(i,a)}}))}function lt(e,t,r,o){let i=[];i.push({url:e.bundle.putUrl,contentType:e.bundle.contentType,bytes:t});for(let a of e.files){let u=r.get(a.urlhash);u&&i.push({url:a.putUrl,contentType:a.contentType,bytes:u})}e.events&&o?.eventsBytes&&i.push({url:e.events.putUrl,contentType:e.events.contentType,bytes:o.eventsBytes}),e.timeline&&o?.timelineBytes&&i.push({url:e.timeline.putUrl,contentType:e.timeline.contentType,bytes:o.timelineBytes}),e.flowVideo&&o?.videoBytes&&i.push({url:e.flowVideo.putUrl,contentType:e.flowVideo.contentType,bytes:o.videoBytes}),e.storage&&o?.storageBytes&&i.push({url:e.storage.putUrl,contentType:e.storage.contentType,bytes:o.storageBytes}),e.failureBundle&&o?.failureBundleBytes&&i.push({url:e.failureBundle.putUrl,contentType:e.failureBundle.contentType,bytes:o.failureBundleBytes});for(let a of e.snapshots??[]){let u=o?.snapshotBytes?.get(a.id);u&&i.push({url:a.putUrl,contentType:a.contentType,bytes:u})}return i}function ut(e){return e.replace(/\/+$/,"")}var J=class extends Error{constructor(r,o,i,a=""){super(r);this.status=o;this.phase=i;this.responseText=a;this.name="PresignedUploadError"}};async function Le(e){let t=ut(e.originBase),r={"content-type":"application/json"};e.authHeader&&(r.authorization=e.authHeader),e.adminBypassToken&&(r["x-soot-admin-upload-bypass"]=e.adminBypassToken);let o=oe(3e4,"init"),i;try{i=await fetch(`${t}/api/preview/upload/init`,{method:"POST",headers:r,body:JSON.stringify(e.initBody),signal:o.signal})}finally{o.cancel()}if(!i.ok){let g=await i.text().catch(()=>"");throw new J(`init failed: ${i.status} ${g.slice(0,200)}`,i.status,"init",g)}let a=await i.json(),u=lt(a,e.bundleBytes,e.filesByHash,e.extras);await at(u,e.concurrency??8,e.onPutProgress);let b=oe(3e4,"finalize"),f;try{f=await fetch(`${t}/api/preview/upload/finalize`,{method:"POST",headers:r,body:JSON.stringify({token:a.token}),signal:b.signal})}finally{b.cancel()}if(!f.ok){let g=await f.text().catch(()=>"");throw new J(`finalize failed: ${f.status} ${g.slice(0,200)}`,f.status,"finalize",g)}let C=await f.json();return{init:a,finalize:C}}function ct(e){return e!==null&&typeof e=="object"?e:null}function Fe(e){return typeof e=="number"&&Number.isFinite(e)?e:void 0}function ie(e){let t=ct(e);return t?t.schemaVersion===1&&Fe(t.t)!==void 0&&Fe(t.seq)!==void 0&&typeof t.context=="string"&&typeof t.kind=="string"&&"data"in t:!1}function dt(e,t){let r=[];for(let o of e.split(`
3
+ `)){let i=o.trim();if(i)try{let a=JSON.parse(i);t(a)&&r.push(a)}catch{}}return r}function $e(e){return dt(e,ie)}function ht(e){if(!e)return null;try{let t=JSON.parse(e);return typeof t.message=="string"&&t.message?t.message:null}catch{return null}}var je=process.env.SOOTSIM_UPLOAD_ORIGIN||"https://sootbean.com",He=process.env.SOOTSIM_PREVIEW_ORIGIN||"https://sootsim.com",ue="http://localhost:3000",yt=2e3;async function bt(e){if(e)return e;if(process.env.SOOTSIM_UPLOAD_ORIGIN)return process.env.SOOTSIM_UPLOAD_ORIGIN;try{let t=await fetch(`${ue}/api/preview/upload/init`,{method:"OPTIONS",signal:AbortSignal.timeout(yt)});if(t.ok||t.status===204||t.status===405)return ue}catch{}return je}function F(e){return e.replace(/\/$/,"")}function Mt(e){try{let r=new URL(e).hostname.replace(/^\[|\]$/g,"").toLowerCase();return r==="localhost"||r.endsWith(".localhost")||r==="0.0.0.0"||r==="::1"||/^127(?:\.\d{1,3}){3}$/.test(r)}catch{return!1}}function wt(e){try{let t=new URL(e).hostname.toLowerCase();return t==="sootbean.com"||t.endsWith(".sootbean.com")}catch{return!1}}function Tt(e,t){return t?F(t):process.env.SOOTSIM_PREVIEW_ORIGIN?F(process.env.SOOTSIM_PREVIEW_ORIGIN):Mt(e)?F(e):wt(e)?F(He):F(e)}function St(){console.log(`
4
4
  sootsim record upload \u2014 publish the current recorded bundle as a /preview/<id> link
5
5
 
6
6
  usage:
@@ -51,7 +51,7 @@ examples:
51
51
  sootsim record upload --events ./my-session.jsonl.gz
52
52
  sootsim record upload --origin http://localhost:3000 --events ./my-session.jsonl.gz --open
53
53
  sootsim record upload --video /tmp/soot-flow.mp4 --video-duration-ms 12000
54
- `)}function d(e,t){let r=e.findIndex(i=>i===t);if(r<0)return;let o=e[r+1];return e.splice(r,2),o}function Ce(e,t){let r=e.findIndex(o=>o===t);return r<0?!1:(e.splice(r,1),!0)}function Ne(e,t){if(!e)return;let r=Number(e);return(!Number.isFinite(r)||r<=0)&&(console.error(` invalid ${t}: ${e}`),process.exit(1)),Math.round(r)}function ze(e){let t=(e||"").toLowerCase().split(";")[0].trim();return t?!!(t.startsWith("image/")||t.startsWith("font/")||t.startsWith("video/")||t.startsWith("audio/")||t.startsWith("model/")||t==="text/css"||t==="application/javascript"||t==="text/javascript"||t==="application/wasm"||t==="application/font-woff"||t==="application/font-woff2"||t==="application/octet-stream"):!1}async function De(e){let t=await fetch(e);if(!t.ok)throw new Error(`fetch ${e} -> ${t.status} ${t.statusText}`);return new Uint8Array(await t.arrayBuffer())}function St(e){return/\.bundle($|\?)/.test(e)||/\.js($|\?)/.test(e)?"application/javascript":/\.zip($|\?)/.test(e)?"application/zip":"application/javascript"}function vt(e){try{return new URL(e).searchParams.get("appFonts")||""}catch{return""}}function xt(e){try{return new URL(e).searchParams.get("appSplash")||""}catch{return""}}function kt(e){try{let t=new URL(e);return t.searchParams.get("lazy")==="true"?(t.searchParams.set("lazy","false"),t.toString()):e}catch{return e}}async function Bt(e,t){let o=[];for(let i=0;i<t;i+=15e5){let a=Math.min(i+15e5,t),u=await B(e,`(window.__sootsimLastTransformedBundle?.text || "").slice(${i}, ${a})`);if(typeof u!="string")return null;o.push(u)}return o.join("")}function Et(e){return e.recordedDurationMs&&e.recordingStartedAtMs?{since:e.recordingStartedAtMs-1e4,until:e.recordingStartedAtMs+e.recordedDurationMs+5e3,limit:2e3}:{limit:2e3}}function Rt(e){let t=U(e),o=(t[0]===31&&t[1]===139?ft(t):t).toString("utf8");return $e(o)}function It(e){return JSON.parse(U(e,"utf8"))}function At(e){if(e===null||typeof e!="object")return[];let t=e,r=typeof t.startedAtEpochMs=="number"&&t.startedAtEpochMs>0?t.startedAtEpochMs:null;if(r===null||!Array.isArray(t.samples))return[];let o=[];for(let i of t.samples){if(!Array.isArray(i)||typeof i[0]!="number")continue;let a=u=>typeof u=="number"&&Number.isFinite(u)?Math.round(u*100)/100:0;o.push({schemaVersion:1,t:r+Math.round(i[0]),seq:o.length+1,context:"tenant",kind:"frame",data:{totalMs:a(i[1]),layoutMs:a(i[2]),renderMs:a(i[3]),copyMs:a(i[4])}})}return o}function Ut(e){if(e===null||typeof e!="object")return e;let{samples:t,...r}=e;return r}function le(e){let t=new Map;for(let r of e)t.set(r.urlhash||r.url,r);return Array.from(t.values())}async function Zt(e,t){(e.includes("--help")||e.includes("-h"))&&(Tt(),process.exit(0));let r=[...e],o=await yt(d(r,"--origin")),i=wt(o,d(r,"--public-origin")),a=d(r,"--events"),u=d(r,"--screenshot"),b=d(r,"--video"),f=d(r,"--timeline-events"),C=d(r,"--trace-frame-stats"),g=d(r,"--failure-bundle"),K=d(r,"--video-duration-ms"),ce=Ne(d(r,"--recorded-duration-ms"),"--recorded-duration-ms"),de=Ne(d(r,"--recording-started-at-ms"),"--recording-started-at-ms"),q=d(r,"--owner"),V=d(r,"--repo"),N=d(r,"--billing-kind"),Je=Ce(r,"--open");(q&&!V||!q&&V)&&(console.error(" --owner and --repo must be provided together"),process.exit(1)),N&&N!=="test_run"&&(console.error(` invalid --billing-kind: ${N}`),process.exit(1)),!a&&!b&&(console.error(" preview uploads require playback data: pass --events or --video.\n for a normal local preview, use `sootsim record --mode combined --open`\n or `sootsim maestro test --preview` instead of uploading a bundle-only snapshot."),process.exit(1));let pe=Ce(r,"--assets-only"),Ke=Be(r,{stripBooleanFlags:[],stripValueFlags:[]}),M=Ee(Ke),c,me=[],w=[],T=f?Rt(f):[],fe=C?It(C):null;T.push(...At(fe));let ge=T.length,W=null;try{if(c=await B(M,'(typeof window.__sootsimCaptureBundle === "function") ? window.__sootsimCaptureBundle() : null'),c?.bundleUrl){let l=new URL(c.bundleUrl).origin,[p,A]=await Promise.all([B(M,`(window.__sootsimPreviewRecorder?.list?.(${JSON.stringify(l)}) || [])`),B(M,`(async () => {
54
+ `)}function d(e,t){let r=e.findIndex(i=>i===t);if(r<0)return;let o=e[r+1];return e.splice(r,2),o}function Ce(e,t){let r=e.findIndex(o=>o===t);return r<0?!1:(e.splice(r,1),!0)}function Ne(e,t){if(!e)return;let r=Number(e);return(!Number.isFinite(r)||r<=0)&&(console.error(` invalid ${t}: ${e}`),process.exit(1)),Math.round(r)}function ze(e){let t=(e||"").toLowerCase().split(";")[0].trim();return t?!!(t.startsWith("image/")||t.startsWith("font/")||t.startsWith("video/")||t.startsWith("audio/")||t.startsWith("model/")||t==="text/css"||t==="application/javascript"||t==="text/javascript"||t==="application/wasm"||t==="application/font-woff"||t==="application/font-woff2"||t==="application/octet-stream"):!1}async function De(e){let t=await fetch(e);if(!t.ok)throw new Error(`fetch ${e} -> ${t.status} ${t.statusText}`);return new Uint8Array(await t.arrayBuffer())}function vt(e){return/\.bundle($|\?)/.test(e)||/\.js($|\?)/.test(e)?"application/javascript":/\.zip($|\?)/.test(e)?"application/zip":"application/javascript"}function xt(e){try{return new URL(e).searchParams.get("appFonts")||""}catch{return""}}function kt(e){try{return new URL(e).searchParams.get("appSplash")||""}catch{return""}}function Bt(e){try{let t=new URL(e);return t.searchParams.get("lazy")==="true"?(t.searchParams.set("lazy","false"),t.toString()):e}catch{return e}}async function Et(e,t){let o=[];for(let i=0;i<t;i+=15e5){let a=Math.min(i+15e5,t),u=await B(e,`(window.__sootsimLastTransformedBundle?.text || "").slice(${i}, ${a})`);if(typeof u!="string")return null;o.push(u)}return o.join("")}function Rt(e){return e.recordedDurationMs&&e.recordingStartedAtMs?{since:e.recordingStartedAtMs-1e4,until:e.recordingStartedAtMs+e.recordedDurationMs+5e3,limit:2e3}:{limit:2e3}}function It(e){let t=U(e),o=(t[0]===31&&t[1]===139?gt(t):t).toString("utf8");return $e(o)}function At(e){return JSON.parse(U(e,"utf8"))}function Ut(e){if(e===null||typeof e!="object")return[];let t=e,r=typeof t.startedAtEpochMs=="number"&&t.startedAtEpochMs>0?t.startedAtEpochMs:null;if(r===null||!Array.isArray(t.samples))return[];let o=[];for(let i of t.samples){if(!Array.isArray(i)||typeof i[0]!="number")continue;let a=u=>typeof u=="number"&&Number.isFinite(u)?Math.round(u*100)/100:0;o.push({schemaVersion:1,t:r+Math.round(i[0]),seq:o.length+1,context:"tenant",kind:"frame",data:{totalMs:a(i[1]),layoutMs:a(i[2]),renderMs:a(i[3]),copyMs:a(i[4])}})}return o}function _t(e){if(e===null||typeof e!="object")return e;let{samples:t,...r}=e;return r}function le(e){let t=new Map;for(let r of e)t.set(r.urlhash||r.url,r);return Array.from(t.values())}async function en(e,t){(e.includes("--help")||e.includes("-h"))&&(St(),process.exit(0));let r=[...e],o=await bt(d(r,"--origin")),i=Tt(o,d(r,"--public-origin")),a=d(r,"--events"),u=d(r,"--screenshot"),b=d(r,"--video"),f=d(r,"--timeline-events"),C=d(r,"--trace-frame-stats"),g=d(r,"--failure-bundle"),K=d(r,"--video-duration-ms"),ce=Ne(d(r,"--recorded-duration-ms"),"--recorded-duration-ms"),de=Ne(d(r,"--recording-started-at-ms"),"--recording-started-at-ms"),q=d(r,"--owner"),V=d(r,"--repo"),N=d(r,"--billing-kind"),Je=d(r,"--run-scope"),Ke=Ce(r,"--open");(q&&!V||!q&&V)&&(console.error(" --owner and --repo must be provided together"),process.exit(1)),N&&N!=="test_run"&&(console.error(` invalid --billing-kind: ${N}`),process.exit(1)),!a&&!b&&(console.error(" preview uploads require playback data: pass --events or --video.\n for a normal local preview, use `sootsim record --mode combined --open`\n or `sootsim maestro test --preview` instead of uploading a bundle-only snapshot."),process.exit(1));let pe=Ce(r,"--assets-only"),qe=Be(r,{stripBooleanFlags:[],stripValueFlags:[]}),M=Ee(qe),c,me=[],w=[],T=f?It(f):[],fe=C?At(C):null;T.push(...Ut(fe));let ge=T.length,W=null;try{if(c=await B(M,'(typeof window.__sootsimCaptureBundle === "function") ? window.__sootsimCaptureBundle() : null'),c?.bundleUrl){let l=new URL(c.bundleUrl).origin,[p,A]=await Promise.all([B(M,`(window.__sootsimPreviewRecorder?.list?.(${JSON.stringify(l)}) || [])`),B(M,`(async () => {
55
55
  const list = window.__sootsimListWorkerFetchRecorder
56
56
  return typeof list === 'function'
57
57
  ? await list(${JSON.stringify(l)})
@@ -86,12 +86,12 @@ examples:
86
86
  ? (await workerDump()).filter(keep)
87
87
  : [],
88
88
  }
89
- })()`);if(w=le([...m.main,...m.worker]),pe){let re=w.length;w=w.filter(se=>ze(se.contentType));let et=x.totalBytes-w.reduce((se,tt)=>se+(tt.size||0),0);console.log(` --assets-only: kept ${w.length}/${re} records (dropped ${(et/1024).toFixed(1)} KiB of API responses)`)}}}c?.transformedBundle&&(W=await Bt(M,c.transformedBundle.byteLength));let n=await B(M,`(() => {
89
+ })()`);if(w=le([...m.main,...m.worker]),pe){let re=w.length;w=w.filter(se=>ze(se.contentType));let tt=x.totalBytes-w.reduce((se,nt)=>se+(nt.size||0),0);console.log(` --assets-only: kept ${w.length}/${re} records (dropped ${(tt/1024).toFixed(1)} KiB of API responses)`)}}}c?.transformedBundle&&(W=await Et(M,c.transformedBundle.byteLength));let n=await B(M,`(() => {
90
90
  const bridge = window.SootSim?.bridges?.timeline ?? window.__sootsimTimeline
91
91
  if (!bridge || typeof bridge.recent !== 'function') return null
92
- return bridge.recent(${JSON.stringify(Et({recordedDurationMs:ce,recordingStartedAtMs:de}))})
92
+ return bridge.recent(${JSON.stringify(Rt({recordedDurationMs:ce,recordingStartedAtMs:de}))})
93
93
  })()`).catch(l=>(console.warn(` warning: failed to capture trace timeline: ${l instanceof Error?l.message:String(l)}`),null)),s=Array.isArray(n?.events)?n.events:[];T=[...T,...s.filter(ie)].sort((l,p)=>l.t-p.t||l.seq-p.seq)}finally{M.close()}c||(console.error(" could not read bundle snapshot \u2014 is sootsim running and is the bundle loaded?"),process.exit(2)),c.bundleUrl||(console.error(` no ?bundle= URL on the current sootsim tab.
94
- open the app you want to share first (e.g. sootsim open 8082), then run upload.`),process.exit(2));let h,G=!1;if(W!==null)h=new TextEncoder().encode(W),G=!0,console.log(` using post-transform bundle: ${(h.byteLength/1024).toFixed(1)} KiB`);else{let n=kt(c.bundleUrl);n!==c.bundleUrl&&console.log(" forcing lazy=false for self-contained bundle"),console.log(` capturing: ${n}`),h=await De(n),console.log(` main bundle: ${(h.byteLength/1024).toFixed(1)} KiB`)}let z=me.filter(n=>n.url!==c.bundleUrl);pe&&(z=z.filter(n=>ze(n.contentType))),console.log(` fetching ${z.length} extra files\u2026`);let D=(await Promise.all(z.map(async n=>{try{let s=await De(n.url);return{...n,bytes:s}}catch(s){return console.error(` warning: failed to re-fetch ${n.url}: ${s instanceof Error?s.message:s}`),null}}))).filter(n=>!!n),qe=D.reduce((n,s)=>n+s.bytes.byteLength,0);console.log(` ${D.length} extra files: ${(qe/1024).toFixed(1)} KiB`);let E;a&&(E=U(a)),T.sort((n,s)=>n.t-s.t||n.seq-s.seq);let he=T.map(n=>JSON.stringify(n)).join(`
94
+ open the app you want to share first (e.g. sootsim open 8082), then run upload.`),process.exit(2));let h,G=!1;if(W!==null)h=new TextEncoder().encode(W),G=!0,console.log(` using post-transform bundle: ${(h.byteLength/1024).toFixed(1)} KiB`);else{let n=Bt(c.bundleUrl);n!==c.bundleUrl&&console.log(" forcing lazy=false for self-contained bundle"),console.log(` capturing: ${n}`),h=await De(n),console.log(` main bundle: ${(h.byteLength/1024).toFixed(1)} KiB`)}let z=me.filter(n=>n.url!==c.bundleUrl);pe&&(z=z.filter(n=>ze(n.contentType))),console.log(` fetching ${z.length} extra files\u2026`);let D=(await Promise.all(z.map(async n=>{try{let s=await De(n.url);return{...n,bytes:s}}catch(s){return console.error(` warning: failed to re-fetch ${n.url}: ${s instanceof Error?s.message:s}`),null}}))).filter(n=>!!n),Ve=D.reduce((n,s)=>n+s.bytes.byteLength,0);console.log(` ${D.length} extra files: ${(Ve/1024).toFixed(1)} KiB`);let E;a&&(E=U(a)),T.sort((n,s)=>n.t-s.t||n.seq-s.seq);let he=T.map(n=>JSON.stringify(n)).join(`
95
95
  `),Y=ae(he?`${he}
96
- `:"");console.log(` trace timeline: ${T.length} events${ge?` (${ge} from runner sidecars)`:""}`);let y;u&&(y=U(u),console.log(` attaching screenshot: ${(y.byteLength/1024).toFixed(1)} KiB`));let R,I;if(g){let n=p=>{try{return U(Oe.join(g,p),"utf8")}catch{return null}},s=p=>{let A=n(p);if(A===null)return null;try{return JSON.parse(A)}catch{return A}},l={error:s("error.json"),describe:s("describe.json"),console:s("console.json"),a11y:n("a11y.txt"),tree:n("tree.txt")};Object.values(l).some(p=>p!==null)&&(R=ae(JSON.stringify(l)),console.log(` attaching failure bundle: ${(R.byteLength/1024).toFixed(1)} KiB gz`));try{I=U(Oe.join(g,"screenshot.png"))}catch{}}let S,$,ye;if(b){if(S=U(b),$=b.endsWith(".mp4")?"video/mp4":b.endsWith(".gif")?"image/gif":void 0,$||(console.error(" preview flow videos must be mp4 or gif"),await k(),process.exit(1)),K){let n=Number(K);(!Number.isFinite(n)||n<=0)&&(console.error(` invalid --video-duration-ms: ${K}`),await k(),process.exit(1)),ye=Math.round(n)}console.log(` attaching flow video: ${(S.byteLength/1024).toFixed(1)} KiB (${$})`)}let _=Ie(),P=Ue(_),Ve=Se();ve({event:"preview_upload_started",identity:{userId:_?.kind==="session"?Ve?.user?.id??null:null,repoId:P?.repoId??null,installationId:P?.installationId??null},properties:{origin:o,hasAuth:!!_,authMode:_?.kind??"none",bundleBytes:h.byteLength,isTransformed:G,extraFiles:D.length,recordedFetches:w.length,hasEvents:!!E,traceTimelineEvents:T.length,hasScreenshot:!!y,hasVideo:!!S}}),_||(console.error(" preview uploads need auth."),console.error(" set SOOTSIM_API_KEY=sk_sootsim_..., run `sootsim login`, or use the soot github runner."),await k(),process.exit(1));let We=Ae(_),Ge=(()=>{try{return new URL(c.bundleUrl).origin}catch{return null}})(),j=(n,s,l,p,A,L,Te,O)=>{let x=_e(L),m=x?ae(n):n;return{url:s,urlhash:l,method:p,bodyHash:A,requestVaryHash:O,contentType:L,responseHeaders:Te,bytes:m,encoding:x?"gzip":void 0}},be=[],Q=vt(c.pageHref)||"";if(Q){let n=await xe(Q,{onStaged:({url:s,byteLength:l})=>console.log(` staged app font: ${s} (${(l/1024).toFixed(1)} KiB)`),onError:(s,l)=>console.error(` warning: failed to fetch app font ${s}: ${l instanceof Error?l.message:l}`)});for(let s of n)be.push(j(Buffer.from(s.bytes),s.url,s.urlhash,"GET","-",s.contentType))}let Me=[],X=xt(c.pageHref)||"";if(X){let n=await ke(X,{onStaged:({url:s,byteLength:l})=>console.log(` staged splash image: ${s} (${(l/1024).toFixed(1)} KiB)`),onError:(s,l)=>console.error(` warning: failed to fetch splash image ${s}: ${l instanceof Error?l.message:l}`)});for(let s of n)Me.push(j(Buffer.from(s.bytes),s.url,s.urlhash,"GET","-",s.contentType))}let Z=[...D.map(n=>j(n.bytes,n.url,n.urlhash,"GET","-",n.contentType,n.responseHeaders,n.requestVaryHash)),...w.map(n=>j(Buffer.from(n.bodyBase64,"base64"),n.url,n.urlhash,n.method||"GET",n.bodyHash||"-",n.contentType,n.responseHeaders,n.requestVaryHash)),...be,...Me],ee=Pe(h),Ye=mt("sha256").update(h).digest("hex");console.log(` bundle raw=${(h.byteLength/1024).toFixed(1)} KiB br=${(ee.byteLength/1024).toFixed(1)} KiB`);let Qe={contentHash:Ye,bundleSizeBytes:h.byteLength,bundleContentType:St(c.bundleUrl),bundleEncoding:"br",bundleOrigin:Ge,runtimeVersion:c.runtimeVersion??void 0,appFonts:Q||void 0,appSplash:X||void 0,entry:c.entry,isTransformed:G,deviceSpec:c.deviceSpec,installationId:P?.installationId??void 0,repoId:P?.repoId,owner:q??P?.owner,repo:V??P?.repo,billingKind:N==="test_run"?"test_run":void 0,files:Z.map(n=>({url:n.url,urlhash:n.urlhash,method:n.method,bodyHash:n.bodyHash,contentType:n.contentType,responseHeaders:n.responseHeaders,requestVaryHash:n.requestVaryHash,encoding:n.encoding,sizeBytes:n.bytes.byteLength})),events:E?{sizeBytes:E.byteLength}:void 0,timeline:{sizeBytes:Y.byteLength,encoding:"gzip"},traceFrameStats:Ut(fe),recordedDurationMs:ce,recordingStartedAtMs:de,failureBundle:R?{sizeBytes:R.byteLength,encoding:"gzip"}:void 0,snapshots:(()=>{let n=[];return y&&n.push({id:"landing",label:"Landing",kind:"landing",t:0,contentType:"image/png",sizeBytes:y.byteLength}),I&&n.push({id:"failure",label:"Failure",kind:"failure",contentType:"image/png",sizeBytes:I.byteLength}),n.length>0?n:void 0})(),flowVideo:S&&$?{sizeBytes:S.byteLength,contentType:$,durationMs:ye}:void 0},we=new Map;for(let n of Z)we.set(n.urlhash,n.bytes);let te=new Map;y&&te.set("landing",y),I&&te.set("failure",I);let Xe=Date.now(),v=ee.byteLength;for(let n of Z)v+=n.bytes.byteLength;E&&(v+=E.byteLength),v+=Y.byteLength,y&&(v+=y.byteLength),I&&(v+=I.byteLength),R&&(v+=R.byteLength),S&&(v+=S.byteLength);let Ze=`${F(o)}/api/preview/upload/init`;console.log(` init: ${Ze}`);let H;try{let n=await Le({originBase:o,initBody:Qe,bundleBytes:ee,filesByHash:we,extras:{eventsBytes:E,timelineBytes:Y,videoBytes:S,failureBundleBytes:R,snapshotBytes:te},authHeader:We,concurrency:16});H=n.finalize;let s=1+n.init.files.length+(n.init.events?1:0)+(n.init.timeline?1:0)+n.init.snapshots.length+(n.init.flowVideo?1:0)+(n.init.failureBundle?1:0);console.log(` PUT ${s} objects in ${Date.now()-Xe}ms (${(v/1024).toFixed(1)} KiB)`)}catch(n){let s=n;s.phase==="init"&&s.status===401&&(console.error(" preview upload requires a valid login."),console.error(" run `sootsim login` and retry."),await k(),process.exit(1)),s.status===402&&(console.error(` ${gt(s.responseText)??"preview uploads require Personal, Team, or an active trial \u2014 upgrade from the billing dialog."}`),await k(),process.exit(1)),console.error(` ${s.message??`${s.phase??"upload"} failed: ${String(n)}`}`),await k(),process.exit(1)}let ne=`${i}${H.url}`;return console.log(`
97
- stored ${H.filesStored??0} extra files`),console.log(` preview: ${ne}`),Je&&await Re(ne),await k(),{previewUrl:ne,shareId:H.id}}export{yt as a,wt as b,Zt as c};
96
+ `:"");console.log(` trace timeline: ${T.length} events${ge?` (${ge} from runner sidecars)`:""}`);let y;u&&(y=U(u),console.log(` attaching screenshot: ${(y.byteLength/1024).toFixed(1)} KiB`));let R,I;if(g){let n=p=>{try{return U(Oe.join(g,p),"utf8")}catch{return null}},s=p=>{let A=n(p);if(A===null)return null;try{return JSON.parse(A)}catch{return A}},l={error:s("error.json"),describe:s("describe.json"),console:s("console.json"),a11y:n("a11y.txt"),tree:n("tree.txt")};Object.values(l).some(p=>p!==null)&&(R=ae(JSON.stringify(l)),console.log(` attaching failure bundle: ${(R.byteLength/1024).toFixed(1)} KiB gz`));try{I=U(Oe.join(g,"screenshot.png"))}catch{}}let S,$,ye;if(b){if(S=U(b),$=b.endsWith(".mp4")?"video/mp4":b.endsWith(".gif")?"image/gif":void 0,$||(console.error(" preview flow videos must be mp4 or gif"),await k(),process.exit(1)),K){let n=Number(K);(!Number.isFinite(n)||n<=0)&&(console.error(` invalid --video-duration-ms: ${K}`),await k(),process.exit(1)),ye=Math.round(n)}console.log(` attaching flow video: ${(S.byteLength/1024).toFixed(1)} KiB (${$})`)}let _=Ie(),P=Ue(_),We=Se();ve({event:"preview_upload_started",identity:{userId:_?.kind==="session"?We?.user?.id??null:null,repoId:P?.repoId??null,installationId:P?.installationId??null},properties:{origin:o,hasAuth:!!_,authMode:_?.kind??"none",bundleBytes:h.byteLength,isTransformed:G,extraFiles:D.length,recordedFetches:w.length,hasEvents:!!E,traceTimelineEvents:T.length,hasScreenshot:!!y,hasVideo:!!S}}),_||(console.error(" preview uploads need auth."),console.error(" set SOOTSIM_API_KEY=sk_sootsim_..., run `sootsim login`, or use the soot github runner."),await k(),process.exit(1));let Ge=Ae(_),Ye=(()=>{try{return new URL(c.bundleUrl).origin}catch{return null}})(),j=(n,s,l,p,A,L,Te,O)=>{let x=_e(L),m=x?ae(n):n;return{url:s,urlhash:l,method:p,bodyHash:A,requestVaryHash:O,contentType:L,responseHeaders:Te,bytes:m,encoding:x?"gzip":void 0}},be=[],Q=xt(c.pageHref)||"";if(Q){let n=await xe(Q,{onStaged:({url:s,byteLength:l})=>console.log(` staged app font: ${s} (${(l/1024).toFixed(1)} KiB)`),onError:(s,l)=>console.error(` warning: failed to fetch app font ${s}: ${l instanceof Error?l.message:l}`)});for(let s of n)be.push(j(Buffer.from(s.bytes),s.url,s.urlhash,"GET","-",s.contentType))}let Me=[],X=kt(c.pageHref)||"";if(X){let n=await ke(X,{onStaged:({url:s,byteLength:l})=>console.log(` staged splash image: ${s} (${(l/1024).toFixed(1)} KiB)`),onError:(s,l)=>console.error(` warning: failed to fetch splash image ${s}: ${l instanceof Error?l.message:l}`)});for(let s of n)Me.push(j(Buffer.from(s.bytes),s.url,s.urlhash,"GET","-",s.contentType))}let Z=[...D.map(n=>j(n.bytes,n.url,n.urlhash,"GET","-",n.contentType,n.responseHeaders,n.requestVaryHash)),...w.map(n=>j(Buffer.from(n.bodyBase64,"base64"),n.url,n.urlhash,n.method||"GET",n.bodyHash||"-",n.contentType,n.responseHeaders,n.requestVaryHash)),...be,...Me],ee=Pe(h),Qe=ft("sha256").update(h).digest("hex");console.log(` bundle raw=${(h.byteLength/1024).toFixed(1)} KiB br=${(ee.byteLength/1024).toFixed(1)} KiB`);let Xe={contentHash:Qe,bundleSizeBytes:h.byteLength,bundleContentType:vt(c.bundleUrl),bundleEncoding:"br",bundleOrigin:Ye,runtimeVersion:c.runtimeVersion??void 0,appFonts:Q||void 0,appSplash:X||void 0,entry:c.entry,isTransformed:G,deviceSpec:c.deviceSpec,installationId:P?.installationId??void 0,repoId:P?.repoId,owner:q??P?.owner,repo:V??P?.repo,billingKind:N==="test_run"?"test_run":void 0,runScope:Je||void 0,files:Z.map(n=>({url:n.url,urlhash:n.urlhash,method:n.method,bodyHash:n.bodyHash,contentType:n.contentType,responseHeaders:n.responseHeaders,requestVaryHash:n.requestVaryHash,encoding:n.encoding,sizeBytes:n.bytes.byteLength})),events:E?{sizeBytes:E.byteLength}:void 0,timeline:{sizeBytes:Y.byteLength,encoding:"gzip"},traceFrameStats:_t(fe),recordedDurationMs:ce,recordingStartedAtMs:de,failureBundle:R?{sizeBytes:R.byteLength,encoding:"gzip"}:void 0,snapshots:(()=>{let n=[];return y&&n.push({id:"landing",label:"Landing",kind:"landing",t:0,contentType:"image/png",sizeBytes:y.byteLength}),I&&n.push({id:"failure",label:"Failure",kind:"failure",contentType:"image/png",sizeBytes:I.byteLength}),n.length>0?n:void 0})(),flowVideo:S&&$?{sizeBytes:S.byteLength,contentType:$,durationMs:ye}:void 0},we=new Map;for(let n of Z)we.set(n.urlhash,n.bytes);let te=new Map;y&&te.set("landing",y),I&&te.set("failure",I);let Ze=Date.now(),v=ee.byteLength;for(let n of Z)v+=n.bytes.byteLength;E&&(v+=E.byteLength),v+=Y.byteLength,y&&(v+=y.byteLength),I&&(v+=I.byteLength),R&&(v+=R.byteLength),S&&(v+=S.byteLength);let et=`${F(o)}/api/preview/upload/init`;console.log(` init: ${et}`);let H;try{let n=await Le({originBase:o,initBody:Xe,bundleBytes:ee,filesByHash:we,extras:{eventsBytes:E,timelineBytes:Y,videoBytes:S,failureBundleBytes:R,snapshotBytes:te},authHeader:Ge,concurrency:16});H=n.finalize;let s=1+n.init.files.length+(n.init.events?1:0)+(n.init.timeline?1:0)+n.init.snapshots.length+(n.init.flowVideo?1:0)+(n.init.failureBundle?1:0);console.log(` PUT ${s} objects in ${Date.now()-Ze}ms (${(v/1024).toFixed(1)} KiB)`)}catch(n){let s=n;s.phase==="init"&&s.status===401&&(console.error(" preview upload requires a valid login."),console.error(" run `sootsim login` and retry."),await k(),process.exit(1)),s.status===402&&(console.error(` ${ht(s.responseText)??"preview uploads require Personal, Team, or an active trial \u2014 upgrade from the billing dialog."}`),await k(),process.exit(1)),console.error(` ${s.message??`${s.phase??"upload"} failed: ${String(n)}`}`),await k(),process.exit(1)}let ne=`${i}${H.url}`;return console.log(`
97
+ stored ${H.filesStored??0} extra files`),console.log(` preview: ${ne}`),Ke&&await Re(ne),await k(),{previewUrl:ne,shareId:H.id}}export{bt as a,Tt as b,en as c};
@@ -1,2 +1,2 @@
1
- /*! sootsim v0.1.211 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! sootsim v0.1.213 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  var o=!0,e="public beta",t=e,n="we send anonymous error and dependency data while you use it";export{o as a,e as b,t as c,n as d};
@@ -1,4 +1,4 @@
1
- /*! sootsim v0.1.211 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
- import{a as R}from"./chunk-FUUQJQ6D.js";import{o as D}from"./chunk-3AMN64TG.js";import{a as T}from"./chunk-UXJC5TWI.js";function Y(e){if(!e||typeof e!="object")return!1;let t=e;return typeof t.type=="string"&&typeof t.ts=="number"}function I(e){let t=e.trim();if(!t)return null;try{let r=JSON.parse(t);return Y(r)?r:null}catch{return null}}import{randomBytes as G,createHash as q}from"node:crypto";import m from"node:fs";import h from"node:path";var N=null;function _(){if(N)return N;let e=process.env.SOOTSIM_USER_DATA_DIR;return e||D()}function y(){return _()}function U(){return h.join(_(),"attached-projects.json")}function $(){return{version:1,attachedProjects:[],previewAttachments:[],agentSessions:[]}}function S(){let e=U(),t;try{t=m.readFileSync(e,"utf8")}catch(r){if(r.code==="ENOENT")return $();throw r}try{let r=JSON.parse(t);if(!r||typeof r!="object")throw new Error("not an object");return{version:1,attachedProjects:Array.isArray(r.attachedProjects)?r.attachedProjects:[],previewAttachments:Array.isArray(r.previewAttachments)?r.previewAttachments:[],agentSessions:Array.isArray(r.agentSessions)?r.agentSessions:[]}}catch(r){let n=`${e}.corrupt-${Date.now()}`;try{m.renameSync(e,n),console.warn(`[sootsim] attached-projects.json was unparseable; quarantined to ${n}. original error: ${r.message}`)}catch{}return $()}}function X(e){let t=U();m.mkdirSync(h.dirname(t),{recursive:!0});let r=`${t}.tmp-${process.pid}-${Date.now()}`,n=m.openSync(r,"w",384);try{m.writeFileSync(n,JSON.stringify(e,null,2)),m.fsyncSync(n)}finally{m.closeSync(n)}m.renameSync(r,t)}function w(e){let t=S();return e(t),X(t),t}function B(e){return q("sha256").update(h.resolve(e)).digest("hex").slice(0,16)}function K(){return`s_${G(10).toString("hex")}`}function ge(e){let t=h.resolve(e.cwd),r=B(t),n;return w(o=>{let s=o.attachedProjects.find(c=>c.id===r);if(s){let c={...s,...e,id:r,cwd:t,sourceRoots:e.sourceRoots??s.sourceRoots,knownBundleUrls:e.knownBundleUrls??s.knownBundleUrls,pinnedSourceResolutions:e.pinnedSourceResolutions??s.pinnedSourceResolutions,telemetry:e.telemetry??s.telemetry,updatedAt:Date.now(),createdAt:s.createdAt},g=o.attachedProjects.indexOf(s);o.attachedProjects[g]=c,n=c;return}let a=Date.now(),d={id:r,name:e.name??h.basename(t),cwd:t,repoRoot:e.repoRoot,sourceRoots:e.sourceRoots??[t],framework:e.framework??"unknown",bundleId:e.bundleId,knownBundleUrls:e.knownBundleUrls??[],preferredProvider:e.preferredProvider??"codex",preferredTransport:e.preferredTransport??"tmux",editorOpenCommand:e.editorOpenCommand,moshiWebhookToken:e.moshiWebhookToken,pinnedSourceResolutions:e.pinnedSourceResolutions??{},isolateDiscovery:e.isolateDiscovery,git:e.git,telemetry:e.telemetry??{lastOpened:0,runsCompleted:0},createdAt:a,updatedAt:a};o.attachedProjects.push(d),n=d}),n}function F(e){return S().attachedProjects.find(t=>t.id===e)??null}function he(){return S().attachedProjects}var Q=336*60*60*1e3;function ye(e,t={}){w(r=>{let n=r.attachedProjects.find(s=>s.id===e);if(!n)return;let o=t.ts??Date.now();if(n.telemetry.runsCompleted=(n.telemetry.runsCompleted??0)+1,typeof t.usd=="number"&&Number.isFinite(t.usd)&&t.usd>=0){let s=n.telemetry.costHistory??[],a=o-Q,d=s.filter(c=>c.ts>=a);d.push({ts:o,usd:t.usd}),n.telemetry.costHistory=d}n.updatedAt=o})}function Se(e,t=Date.now()){let r=t-6048e5,n=e.telemetry.costHistory??[],o=0;for(let s of n)s.ts>=r&&(o+=s.usd);return o}function we(e){w(t=>{t.attachedProjects=t.attachedProjects.filter(r=>r.id!==e),t.agentSessions=t.agentSessions.filter(r=>r.projectId!==e),t.previewAttachments=t.previewAttachments.filter(r=>r.projectId!==e)})}function M(e){let t;return w(r=>{if(e.id){let a=r.agentSessions.find(d=>d.id===e.id);if(a){let d={...a,...e,lastSeenAt:Date.now()},c=r.agentSessions.indexOf(a);r.agentSessions[c]=d,t=d;return}}let n=r.attachedProjects.find(a=>a.id===e.projectId);if(!n)throw new Error(`upsertSession: no AttachedProject with id=${e.projectId}`);let o=Date.now(),s={id:e.id??K(),projectId:e.projectId,provider:e.provider,transport:e.transport??n.preferredTransport,cwd:e.cwd??n.cwd,claudeSessionUuid:e.claudeSessionUuid,tmuxSessionName:e.tmuxSessionName,wrapperPid:e.wrapperPid,status:e.status??"idle",needsAttention:e.needsAttention??!1,lastPrompt:e.lastPrompt,lastSummary:e.lastSummary,lastTurnFiles:e.lastTurnFiles,currentlyEditing:e.currentlyEditing,lastSeenAt:o,createdAt:o};r.agentSessions.push(s),t=s}),t}function k(e){return S().agentSessions.find(t=>t.id===e)??null}function C(e){let t=S().agentSessions;return e?t.filter(r=>r.projectId===e):t}function v(e,t){w(r=>{let n=r.agentSessions.find(s=>s.id===e);if(!n)return;let o=r.agentSessions.indexOf(n);r.agentSessions[o]={...n,...t,id:n.id,projectId:n.projectId,createdAt:n.createdAt,lastSeenAt:Date.now()}})}async function ve(){if(S().attachedProjects.length>0)return;let{loadOptionalDemoApps:t}=await import("./optional-demo-registry-A27PORZB.js"),r=await t();r.length!==0&&w(n=>{for(let o of r){if(!m.existsSync(o.dir))continue;let s=h.resolve(o.dir),a=B(s);if(n.attachedProjects.some(c=>c.id===a))continue;let d=Date.now();n.attachedProjects.push({id:a,name:o.label,cwd:s,sourceRoots:[s],framework:o.framework,knownBundleUrls:[`http://localhost:${o.preferredPort}/index.bundle`],preferredProvider:"codex",preferredTransport:"tmux",pinnedSourceResolutions:{},telemetry:{lastOpened:0,runsCompleted:0},createdAt:d,updatedAt:d})}})}import{spawn as V,spawnSync as z}from"node:child_process";import{randomUUID as Z}from"node:crypto";import i,{constants as f}from"node:fs";import u from"node:path";import ee from"node:readline";function j(e){return u.join(y(),"sessions",e)}function W(e){return u.join(j(e),"prompt.in")}function J(e){return u.join(j(e),"events.out")}function te(e){return u.join(y(),"transcripts",`${e}.log`)}function O(e,t){if(!e)return!1;try{process.kill(e,0)}catch{return!1}return!(t&&!i.existsSync(j(t)))}function re(){if(process.env.SOOTSIM_BIN)return{cmd:process.env.SOOTSIM_BIN,prefixArgs:[]};if(process.versions.electron){let n=process.resourcesPath;if(n){let o=[u.join(n,"bin","sootsim"),u.join(n,"bin",`sootsim-${process.platform}-${process.arch}`)];for(let s of o)if(i.existsSync(s))return{cmd:s,prefixArgs:[]}}}let e=ne();if(e)return e;let t=process.argv[0],r=process.argv[1];if(r&&/\.(ts|tsx|mjs|cjs|js)$/.test(r))return{cmd:t,prefixArgs:[r]};if(!r||r.includes("/.bin/"))throw new Error("sootsim CLI not found. set SOOTSIM_BIN to the path of the sootsim binary, or build the workspace CLI via `bun run --cwd packages/sootsim build:cli`.");return{cmd:t,prefixArgs:[]}}function ne(){try{let e=se();if(!e)return null;let t=`sootsim-${process.platform}-${process.arch}`,r=u.join(e,"dist-bin",t);if(i.existsSync(r))return{cmd:r,prefixArgs:[]};let n=u.join(e,"dist-cli","bin.js");if(i.existsSync(n)){try{let o=u.join(e,"cli","commands","agent-wrapper.ts");if(i.existsSync(o)){let s=i.statSync(o).mtimeMs;i.statSync(n).mtimeMs<s&&console.warn("[sootsim] dist-cli/bin.js is older than agent-wrapper.ts \u2014 rebuild with `bun run --cwd packages/sootsim build:cli` (watch:cli:binary builds dist-bin/ instead).")}}catch{}return{cmd:process.execPath,prefixArgs:[n]}}return null}catch{return null}}function se(){try{let r=T.resolve("sootsim/package.json");return u.dirname(r)}catch{}let e=oe();if(!e)return null;let t=u.dirname(e);for(let r=0;r<8;r++){let n=u.join(t,"package.json");try{if(i.existsSync(n)&&JSON.parse(i.readFileSync(n,"utf8")).name==="sootsim")return t}catch{}let o=u.dirname(t);if(o===t)break;t=o}return null}function oe(){try{let e=import.meta.url;return!e||!e.startsWith("file://")?null:decodeURIComponent(e.slice(7))}catch{return null}}async function ie(e,t,r){let n=u.join(y(),"locks");i.mkdirSync(n,{recursive:!0});try{i.chmodSync(n,448)}catch{}let o=u.join(n,`start-${e}-${t}.lock`),s=Date.now()+4e3,a=null;for(;a===null;)try{a=i.openSync(o,f.O_WRONLY|f.O_CREAT|f.O_EXCL,384)}catch(d){if(d.code!=="EEXIST")throw d;try{let c=Number(i.readFileSync(o,"utf8").trim());if(c&&!ce(c)){i.unlinkSync(o);continue}}catch{}if(Date.now()>s)throw new Error(`another start is in progress for project=${e} provider=${t} (lock: ${o})`);await new Promise(c=>setTimeout(c,50))}try{return i.writeFileSync(a,String(process.pid)),await r()}finally{try{i.closeSync(a)}catch{}try{i.unlinkSync(o)}catch{}}}function ce(e){try{return process.kill(e,0),!0}catch{return!1}}function L(e){let t=u.dirname(e);i.mkdirSync(t,{recursive:!0});try{i.chmodSync(t,448)}catch{}if(i.existsSync(e))try{if(i.statSync(e).isFIFO()){try{i.chmodSync(e,384)}catch{}return}i.unlinkSync(e)}catch{i.unlinkSync(e)}let r=z("mkfifo",["-m","600",e]);if(r.status!==0)throw new Error(`mkfifo(${e}) failed: ${r.stderr?.toString().trim()||"unknown error"}`)}var l=class extends Error{code;constructor(t,r){super(r),this.code=t}};async function Te(e){let t=F(e.projectId);if(!t)throw new l("NO_PROJECT",`no project with id=${e.projectId}`);let r=e.provider||t.preferredProvider||"codex";return ie(t.id,r,async()=>{let n=C(t.id).find(p=>p.provider===r&&p.status!=="ended"&&O(p.wrapperPid,p.id));if(n)throw new l("ALREADY_RUNNING",`session already running for project=${t.id} provider=${r} (session ${n.id}, pid ${n.wrapperPid}). end it first with \`sootsim agent end <sessionId>\`.`);let o=r==="claude"?Z():void 0,s=M({projectId:t.id,provider:r,transport:"pty",cwd:t.cwd,status:"idle",claudeSessionUuid:o}),a=W(s.id),d=J(s.id),c=te(s.id);L(a),L(d);let g=u.dirname(c);i.mkdirSync(g,{recursive:!0});try{i.chmodSync(g,448)}catch{}let{cmd:A,prefixArgs:H}=re(),x=[...H,"agent-wrapper","--session-id",s.id,"--project-id",t.id,"--provider",r,"--cwd",t.cwd,"--prompt-in",a,"--events-out",d,"--transcript",c];e.codexBin&&x.push("--codex-bin",e.codexBin),e.claudeBin&&x.push("--claude-bin",e.claudeBin),e.freshThread&&x.push("--fresh-thread"),o&&x.push("--claude-session-uuid",o);let P=V(A,x,{detached:!0,stdio:"ignore",env:{...process.env,SOOTSIM_USER_DATA_DIR:y()}});P.unref();let E=e.readyTimeoutMs??6e3,b=await ae(d,p=>p.type==="ready"||p.type==="error",E);if(!b||b.type==="error"){if(P.pid)try{process.kill(P.pid,"SIGTERM")}catch{}try{i.rmSync(j(s.id),{recursive:!0,force:!0})}catch{}v(s.id,{status:"ended"});let p=b&&b.type==="error"?b.message:`no ready event within ${E}ms`;throw new l("WRAPPER_FAILED",p)}return v(s.id,{wrapperPid:P.pid,status:"idle"}),{session:k(s.id),wrapperPid:P.pid}})}async function De(e,t){let r=k(e);if(!r)throw new l("NO_SESSION",`no session with id=${e}`);if(!O(r.wrapperPid,e))throw v(e,{status:"ended"}),new l("NOT_ALIVE",`session wrapper is not alive (pid=${r.wrapperPid}). start a new session.`);let n=W(e);if(!i.existsSync(n))throw new l("NO_FIFO",`prompt FIFO missing: ${n}`);let o=i.openSync(n,f.O_WRONLY);try{let s=R(t);if(!s)throw new l("EMPTY_PROMPT","prompt text is empty");i.writeSync(o,s+`
1
+ /*! sootsim v0.1.213 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
+ import{a as R}from"./chunk-L6CUBNOP.js";import{o as D}from"./chunk-PMZU2MXQ.js";import{a as T}from"./chunk-DL5UW643.js";function Y(e){if(!e||typeof e!="object")return!1;let t=e;return typeof t.type=="string"&&typeof t.ts=="number"}function I(e){let t=e.trim();if(!t)return null;try{let r=JSON.parse(t);return Y(r)?r:null}catch{return null}}import{randomBytes as G,createHash as q}from"node:crypto";import m from"node:fs";import h from"node:path";var N=null;function _(){if(N)return N;let e=process.env.SOOTSIM_USER_DATA_DIR;return e||D()}function y(){return _()}function U(){return h.join(_(),"attached-projects.json")}function $(){return{version:1,attachedProjects:[],previewAttachments:[],agentSessions:[]}}function S(){let e=U(),t;try{t=m.readFileSync(e,"utf8")}catch(r){if(r.code==="ENOENT")return $();throw r}try{let r=JSON.parse(t);if(!r||typeof r!="object")throw new Error("not an object");return{version:1,attachedProjects:Array.isArray(r.attachedProjects)?r.attachedProjects:[],previewAttachments:Array.isArray(r.previewAttachments)?r.previewAttachments:[],agentSessions:Array.isArray(r.agentSessions)?r.agentSessions:[]}}catch(r){let n=`${e}.corrupt-${Date.now()}`;try{m.renameSync(e,n),console.warn(`[sootsim] attached-projects.json was unparseable; quarantined to ${n}. original error: ${r.message}`)}catch{}return $()}}function X(e){let t=U();m.mkdirSync(h.dirname(t),{recursive:!0});let r=`${t}.tmp-${process.pid}-${Date.now()}`,n=m.openSync(r,"w",384);try{m.writeFileSync(n,JSON.stringify(e,null,2)),m.fsyncSync(n)}finally{m.closeSync(n)}m.renameSync(r,t)}function w(e){let t=S();return e(t),X(t),t}function B(e){return q("sha256").update(h.resolve(e)).digest("hex").slice(0,16)}function K(){return`s_${G(10).toString("hex")}`}function ge(e){let t=h.resolve(e.cwd),r=B(t),n;return w(o=>{let s=o.attachedProjects.find(c=>c.id===r);if(s){let c={...s,...e,id:r,cwd:t,sourceRoots:e.sourceRoots??s.sourceRoots,knownBundleUrls:e.knownBundleUrls??s.knownBundleUrls,pinnedSourceResolutions:e.pinnedSourceResolutions??s.pinnedSourceResolutions,telemetry:e.telemetry??s.telemetry,updatedAt:Date.now(),createdAt:s.createdAt},g=o.attachedProjects.indexOf(s);o.attachedProjects[g]=c,n=c;return}let a=Date.now(),d={id:r,name:e.name??h.basename(t),cwd:t,repoRoot:e.repoRoot,sourceRoots:e.sourceRoots??[t],framework:e.framework??"unknown",bundleId:e.bundleId,knownBundleUrls:e.knownBundleUrls??[],preferredProvider:e.preferredProvider??"codex",preferredTransport:e.preferredTransport??"tmux",editorOpenCommand:e.editorOpenCommand,moshiWebhookToken:e.moshiWebhookToken,pinnedSourceResolutions:e.pinnedSourceResolutions??{},isolateDiscovery:e.isolateDiscovery,git:e.git,telemetry:e.telemetry??{lastOpened:0,runsCompleted:0},createdAt:a,updatedAt:a};o.attachedProjects.push(d),n=d}),n}function F(e){return S().attachedProjects.find(t=>t.id===e)??null}function he(){return S().attachedProjects}var Q=336*60*60*1e3;function ye(e,t={}){w(r=>{let n=r.attachedProjects.find(s=>s.id===e);if(!n)return;let o=t.ts??Date.now();if(n.telemetry.runsCompleted=(n.telemetry.runsCompleted??0)+1,typeof t.usd=="number"&&Number.isFinite(t.usd)&&t.usd>=0){let s=n.telemetry.costHistory??[],a=o-Q,d=s.filter(c=>c.ts>=a);d.push({ts:o,usd:t.usd}),n.telemetry.costHistory=d}n.updatedAt=o})}function Se(e,t=Date.now()){let r=t-6048e5,n=e.telemetry.costHistory??[],o=0;for(let s of n)s.ts>=r&&(o+=s.usd);return o}function we(e){w(t=>{t.attachedProjects=t.attachedProjects.filter(r=>r.id!==e),t.agentSessions=t.agentSessions.filter(r=>r.projectId!==e),t.previewAttachments=t.previewAttachments.filter(r=>r.projectId!==e)})}function M(e){let t;return w(r=>{if(e.id){let a=r.agentSessions.find(d=>d.id===e.id);if(a){let d={...a,...e,lastSeenAt:Date.now()},c=r.agentSessions.indexOf(a);r.agentSessions[c]=d,t=d;return}}let n=r.attachedProjects.find(a=>a.id===e.projectId);if(!n)throw new Error(`upsertSession: no AttachedProject with id=${e.projectId}`);let o=Date.now(),s={id:e.id??K(),projectId:e.projectId,provider:e.provider,transport:e.transport??n.preferredTransport,cwd:e.cwd??n.cwd,claudeSessionUuid:e.claudeSessionUuid,tmuxSessionName:e.tmuxSessionName,wrapperPid:e.wrapperPid,status:e.status??"idle",needsAttention:e.needsAttention??!1,lastPrompt:e.lastPrompt,lastSummary:e.lastSummary,lastTurnFiles:e.lastTurnFiles,currentlyEditing:e.currentlyEditing,lastSeenAt:o,createdAt:o};r.agentSessions.push(s),t=s}),t}function k(e){return S().agentSessions.find(t=>t.id===e)??null}function C(e){let t=S().agentSessions;return e?t.filter(r=>r.projectId===e):t}function v(e,t){w(r=>{let n=r.agentSessions.find(s=>s.id===e);if(!n)return;let o=r.agentSessions.indexOf(n);r.agentSessions[o]={...n,...t,id:n.id,projectId:n.projectId,createdAt:n.createdAt,lastSeenAt:Date.now()}})}async function ve(){if(S().attachedProjects.length>0)return;let{loadOptionalDemoApps:t}=await import("./optional-demo-registry-OYI5WQN4.js"),r=await t();r.length!==0&&w(n=>{for(let o of r){if(!m.existsSync(o.dir))continue;let s=h.resolve(o.dir),a=B(s);if(n.attachedProjects.some(c=>c.id===a))continue;let d=Date.now();n.attachedProjects.push({id:a,name:o.label,cwd:s,sourceRoots:[s],framework:o.framework,knownBundleUrls:[`http://localhost:${o.preferredPort}/index.bundle`],preferredProvider:"codex",preferredTransport:"tmux",pinnedSourceResolutions:{},telemetry:{lastOpened:0,runsCompleted:0},createdAt:d,updatedAt:d})}})}import{spawn as V,spawnSync as z}from"node:child_process";import{randomUUID as Z}from"node:crypto";import i,{constants as f}from"node:fs";import u from"node:path";import ee from"node:readline";function j(e){return u.join(y(),"sessions",e)}function W(e){return u.join(j(e),"prompt.in")}function J(e){return u.join(j(e),"events.out")}function te(e){return u.join(y(),"transcripts",`${e}.log`)}function O(e,t){if(!e)return!1;try{process.kill(e,0)}catch{return!1}return!(t&&!i.existsSync(j(t)))}function re(){if(process.env.SOOTSIM_BIN)return{cmd:process.env.SOOTSIM_BIN,prefixArgs:[]};if(process.versions.electron){let n=process.resourcesPath;if(n){let o=[u.join(n,"bin","sootsim"),u.join(n,"bin",`sootsim-${process.platform}-${process.arch}`)];for(let s of o)if(i.existsSync(s))return{cmd:s,prefixArgs:[]}}}let e=ne();if(e)return e;let t=process.argv[0],r=process.argv[1];if(r&&/\.(ts|tsx|mjs|cjs|js)$/.test(r))return{cmd:t,prefixArgs:[r]};if(!r||r.includes("/.bin/"))throw new Error("sootsim CLI not found. set SOOTSIM_BIN to the path of the sootsim binary, or build the workspace CLI via `bun run --cwd packages/sootsim build:cli`.");return{cmd:t,prefixArgs:[]}}function ne(){try{let e=se();if(!e)return null;let t=`sootsim-${process.platform}-${process.arch}`,r=u.join(e,"dist-bin",t);if(i.existsSync(r))return{cmd:r,prefixArgs:[]};let n=u.join(e,"dist-cli","bin.js");if(i.existsSync(n)){try{let o=u.join(e,"cli","commands","agent-wrapper.ts");if(i.existsSync(o)){let s=i.statSync(o).mtimeMs;i.statSync(n).mtimeMs<s&&console.warn("[sootsim] dist-cli/bin.js is older than agent-wrapper.ts \u2014 rebuild with `bun run --cwd packages/sootsim build:cli` (watch:cli:binary builds dist-bin/ instead).")}}catch{}return{cmd:process.execPath,prefixArgs:[n]}}return null}catch{return null}}function se(){try{let r=T.resolve("sootsim/package.json");return u.dirname(r)}catch{}let e=oe();if(!e)return null;let t=u.dirname(e);for(let r=0;r<8;r++){let n=u.join(t,"package.json");try{if(i.existsSync(n)&&JSON.parse(i.readFileSync(n,"utf8")).name==="sootsim")return t}catch{}let o=u.dirname(t);if(o===t)break;t=o}return null}function oe(){try{let e=import.meta.url;return!e||!e.startsWith("file://")?null:decodeURIComponent(e.slice(7))}catch{return null}}async function ie(e,t,r){let n=u.join(y(),"locks");i.mkdirSync(n,{recursive:!0});try{i.chmodSync(n,448)}catch{}let o=u.join(n,`start-${e}-${t}.lock`),s=Date.now()+4e3,a=null;for(;a===null;)try{a=i.openSync(o,f.O_WRONLY|f.O_CREAT|f.O_EXCL,384)}catch(d){if(d.code!=="EEXIST")throw d;try{let c=Number(i.readFileSync(o,"utf8").trim());if(c&&!ce(c)){i.unlinkSync(o);continue}}catch{}if(Date.now()>s)throw new Error(`another start is in progress for project=${e} provider=${t} (lock: ${o})`);await new Promise(c=>setTimeout(c,50))}try{return i.writeFileSync(a,String(process.pid)),await r()}finally{try{i.closeSync(a)}catch{}try{i.unlinkSync(o)}catch{}}}function ce(e){try{return process.kill(e,0),!0}catch{return!1}}function L(e){let t=u.dirname(e);i.mkdirSync(t,{recursive:!0});try{i.chmodSync(t,448)}catch{}if(i.existsSync(e))try{if(i.statSync(e).isFIFO()){try{i.chmodSync(e,384)}catch{}return}i.unlinkSync(e)}catch{i.unlinkSync(e)}let r=z("mkfifo",["-m","600",e]);if(r.status!==0)throw new Error(`mkfifo(${e}) failed: ${r.stderr?.toString().trim()||"unknown error"}`)}var l=class extends Error{code;constructor(t,r){super(r),this.code=t}};async function Te(e){let t=F(e.projectId);if(!t)throw new l("NO_PROJECT",`no project with id=${e.projectId}`);let r=e.provider||t.preferredProvider||"codex";return ie(t.id,r,async()=>{let n=C(t.id).find(p=>p.provider===r&&p.status!=="ended"&&O(p.wrapperPid,p.id));if(n)throw new l("ALREADY_RUNNING",`session already running for project=${t.id} provider=${r} (session ${n.id}, pid ${n.wrapperPid}). end it first with \`sootsim agent end <sessionId>\`.`);let o=r==="claude"?Z():void 0,s=M({projectId:t.id,provider:r,transport:"pty",cwd:t.cwd,status:"idle",claudeSessionUuid:o}),a=W(s.id),d=J(s.id),c=te(s.id);L(a),L(d);let g=u.dirname(c);i.mkdirSync(g,{recursive:!0});try{i.chmodSync(g,448)}catch{}let{cmd:A,prefixArgs:H}=re(),x=[...H,"agent-wrapper","--session-id",s.id,"--project-id",t.id,"--provider",r,"--cwd",t.cwd,"--prompt-in",a,"--events-out",d,"--transcript",c];e.codexBin&&x.push("--codex-bin",e.codexBin),e.claudeBin&&x.push("--claude-bin",e.claudeBin),e.freshThread&&x.push("--fresh-thread"),o&&x.push("--claude-session-uuid",o);let P=V(A,x,{detached:!0,stdio:"ignore",env:{...process.env,SOOTSIM_USER_DATA_DIR:y()}});P.unref();let E=e.readyTimeoutMs??6e3,b=await ae(d,p=>p.type==="ready"||p.type==="error",E);if(!b||b.type==="error"){if(P.pid)try{process.kill(P.pid,"SIGTERM")}catch{}try{i.rmSync(j(s.id),{recursive:!0,force:!0})}catch{}v(s.id,{status:"ended"});let p=b&&b.type==="error"?b.message:`no ready event within ${E}ms`;throw new l("WRAPPER_FAILED",p)}return v(s.id,{wrapperPid:P.pid,status:"idle"}),{session:k(s.id),wrapperPid:P.pid}})}async function De(e,t){let r=k(e);if(!r)throw new l("NO_SESSION",`no session with id=${e}`);if(!O(r.wrapperPid,e))throw v(e,{status:"ended"}),new l("NOT_ALIVE",`session wrapper is not alive (pid=${r.wrapperPid}). start a new session.`);let n=W(e);if(!i.existsSync(n))throw new l("NO_FIFO",`prompt FIFO missing: ${n}`);let o=i.openSync(n,f.O_WRONLY);try{let s=R(t);if(!s)throw new l("EMPTY_PROMPT","prompt text is empty");i.writeSync(o,s+`
3
3
  `)}finally{i.closeSync(o)}v(e,{lastPrompt:t.displayText??t.text,status:"working"})}async function Re(e){let t=k(e);if(!t)throw new l("NO_SESSION",`no session with id=${e}`);if(O(t.wrapperPid,e))try{process.kill(t.wrapperPid,"SIGTERM")}catch{}let r=j(e),n=y();if(r.startsWith(n))try{i.rmSync(r,{recursive:!0,force:!0})}catch{}v(e,{status:"ended",wrapperPid:void 0})}function Ne(e,t){let r=J(e);if(!i.existsSync(r))throw new l("NO_FIFO",`events FIFO missing: ${r}`);let n=i.openSync(r,f.O_RDWR),o=i.createReadStream("",{fd:n,autoClose:!0}),s=ee.createInterface({input:o,crlfDelay:1/0});s.on("line",d=>{let c=I(d);c&&t(c)});let a=!1;return()=>{if(!a){a=!0;try{s.close()}catch{}try{o.destroy()}catch{}}}}async function ae(e,t,r){let n=i.openSync(e,f.O_RDWR|f.O_NONBLOCK),o=Buffer.alloc(8192),s="",a=Date.now()+r;try{for(;Date.now()<a;){let d=0;try{d=i.readSync(n,o,0,o.length,null)}catch(c){if(c.code!=="EAGAIN")throw c;d=0}if(d>0){s+=o.subarray(0,d).toString("utf8");let c;for(;(c=s.indexOf(`
4
4
  `))>=0;){let g=s.slice(0,c);s=s.slice(c+1);let A=I(g);if(A&&t(A))return A}}else await new Promise(c=>setTimeout(c,30))}return null}finally{i.closeSync(n)}}export{I as a,y as b,ge as c,F as d,he as e,ye as f,Se as g,we as h,k as i,C as j,v as k,ve as l,j as m,W as n,J as o,te as p,O as q,re as r,l as s,Te as t,De as u,Re as v,Ne as w};
@@ -1,5 +1,5 @@
1
- /*! sootsim v0.1.211 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
- import{H as I,m as B,n as E,o as y,t as v,v as A}from"./chunk-VDLNYLQ3.js";import{h,l as N,m as P}from"./chunk-TBBKY5QW.js";var q={timeoutMs:1800,settleMs:48,startWindowMs:64};function w(e){return new Promise(t=>setTimeout(t,e))}function U(e){return e.includes("--json")}function Y(e){process.stdout.write(`${JSON.stringify(e??null,null,2)}
1
+ /*! sootsim v0.1.213 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
+ import{H as I,m as B,n as E,o as y,t as v,v as A}from"./chunk-6A64BUDU.js";import{h,l as N,m as P}from"./chunk-MBTZ72OK.js";var q={timeoutMs:1800,settleMs:48,startWindowMs:64};function w(e){return new Promise(t=>setTimeout(t,e))}function U(e){return e.includes("--json")}function Y(e){process.stdout.write(`${JSON.stringify(e??null,null,2)}
3
3
  `)}function V(e){process.stderr.write(`${e}
4
4
  `)}function b(e,t=Date.now()){let r=new Date(e),n=`${S(r.getHours())}:${S(r.getMinutes())}:${S(r.getSeconds())}`,s=t-e;if(s<0)return n;let o=Math.round(s/1e3);return o<60?`${n} +${o}s`:o<3600?`${n} +${Math.round(o/60)}m`:o<86400?`${n} +${Math.round(o/3600)}h`:`${n} +${Math.round(o/86400)}d`}function S(e){return e<10?`0${e}`:String(e)}async function D(e,t,...r){return N(e,`__sootsimTest.${t}`,...r)}async function k(e,t,...r){return P(e,`SootSim.bridges.mainShell.${t}`,...r)}async function z(e,t={}){try{let r=await D(e,"waitForScreenTransitions",q);if(!t.verbose||!r?.started)return;if(r.timedOut){console.log(` screen transition still active after ${r.waitedMs}ms; continuing`);return}r.waitedMs>0&&console.log(` waited ${r.waitedMs}ms for screen transition settle`)}catch{}}async function K(e,t,r,...n){let s=Date.now()+Math.max(0,r);for(;;)try{return await k(e,t,...n)}catch(o){if(!I(o)||Date.now()>=s)throw o;await w(50)}}async function Q(e,t,r,n={}){let s=n.attempts??30,o=n.intervalMs??500,l=n.minNodeCount??10;for(let a=0;a<s;a++){let u=h(e,{commandTimeoutMs:t,simId:r,simIdSource:n.simIdSource});try{let c=await u.send({type:"evaluate",code:"(async () => (await window.__sootsimTest?.getNodeCount()) || 0)()"});if(typeof c=="number"&&c>l)return{bridge:u,count:c}}catch{}u.close(),await w(o)}return null}async function X(e,t,r,n={}){let s=n.timeoutMs??8e3,o=n.intervalMs??250,l=Date.now()+s;for(;Date.now()<l;){let a=h(e,{commandTimeoutMs:t,simId:r,simIdSource:n.simIdSource});try{return await a.send({type:"evaluate",code:"1"}),a}catch{a.close()}await w(o)}return null}async function Z(e,t={}){let r=t.timeoutMs??1e4,n=t.errorGraceMs??3e3,s=t.pollIntervalMs??200,o=Date.now(),l=o+r,a=-1,u=o,c=null,d=!1,m={ready:!1,source:"timeout",elapsedMs:0,nodes:0,targets:0,flag:void 0,loadingText:"",externalReady:null,externalStatus:"",externalError:"",errors:0};for(;Date.now()<l;){try{let i=await e.send({type:"evaluate",code:B}),g=Date.now()-o,f=Number(i?.nodes)||0,$=Number(i?.targets)||0,x=Number(i?.errors)||0,C=i?.flag===!0,p=i?.externalReady,T=typeof i?.loadingText=="string"?i.loadingText.trim():"",W=typeof i?.externalStatus=="string"?i.externalStatus.trim():"",M=typeof i?.externalError=="string"?i.externalError.trim():"",R=typeof i?.externalError=="string"&&M.length>0;if(c=p,d=R,f!==a&&(a=f,u=g),m={ready:!1,source:"timeout",elapsedMs:g,nodes:f,targets:$,flag:i?.flag,loadingText:T,externalReady:typeof p=="boolean"?p:null,externalStatus:W,externalError:M,errors:x},C&&p!==!1&&!R&&!T&&y({nodes:f,targets:$})&&g-u>=E)return{...m,ready:!0,source:"flag"};if(g>=n&&x>0&&!C)return{...m,ready:!1,source:"error-bail"}}catch{}await w(s)}return c!==!1&&!d&&!m.loadingText&&y(m)?{...m,ready:!0,source:"nodes-fallback"}:{...m,ready:!1,source:"timeout",elapsedMs:Date.now()-o}}function O(e){let t=e.displayUrl||e.url;return e.status!=null?`${e.method} ${t} -> ${e.status}${e.statusText?` ${e.statusText}`:""}`:e.error?`${e.method} ${t} -> ${e.error}`:`${e.method} ${t}`}async function _(e,t,...r){return e.send({type:"call",path:`__sootsimTest.${t}`,args:r})}async function F(e,t={}){let r=await e.send({type:"evaluate",code:A});if(!r||typeof r!="object")return;let n=Math.max(0,Number(r.errors)||0),s=Math.max(0,Number(r.warnings)||0);if(n===0&&s===0)return;let o=[];if(n>0&&o.push(`${n} console error${n===1?"":"s"}`),s>0&&o.push(`${s} console warning${s===1?"":"s"}`),console.log(`
5
5
  console: ${o.join(", ")}`),t.errorsCommand&&console.log(` inspect: ${t.errorsCommand}`),s>0&&t.warningsCommand&&console.log(` inspect: ${t.warningsCommand}`),!t.includeTail||n===0)return;let l=await v(e,5);if(!(!Array.isArray(l)||l.length===0)){console.log(`
@@ -1,4 +1,4 @@
1
- /*! sootsim v0.1.211 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! sootsim v0.1.213 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  import{createInterface as i}from"readline";var c=()=>i({input:process.stdin,output:process.stdout});function s(o){return new Promise(n=>{let r=c();r.question(o,t=>{r.close(),n(t.trim())})})}async function u(o,n=!0){let r=n?"[Y/n]":"[y/N]";if(!process.stdin.isTTY)return console.log(` ${o} ${r} ${n?"y":"n"} (non-interactive)`),n;let t=await s(` ${o} ${r} `);return t===""?n:t.toLowerCase().startsWith("y")}async function a(o,n){console.log(`
3
3
  ${o}
4
4
  `);for(let e=0;e<n.length;e++)console.log(` ${e+1}. ${n[e]}`);if(console.log(),!process.stdin.isTTY)return console.log(` choose [1-${n.length}]: 1 (non-interactive)`),0;let r=await s(` choose [1-${n.length}]: `),t=parseInt(r,10);return t>=1&&t<=n.length?t-1:0}export{u as a,a as b};
@@ -1,5 +1,5 @@
1
- /*! sootsim v0.1.211 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
- import{a as x}from"./chunk-OEVW6X6O.js";import{a as k}from"./chunk-HYCIJ46S.js";import{spawn as v,spawnSync as u}from"child_process";import{chmodSync as S,copyFileSync as T,createWriteStream as E,existsSync as w,mkdirSync as y,rmSync as g,statSync as P,unlinkSync as D}from"fs";import{tmpdir as M}from"os";import{dirname as A,join as f,resolve as b}from"path";var h="https://sootbean.com/api/electron-release";function O(){let n=process.arch;if(process.platform==="darwin"){let o=n==="arm64"?"mac-arm64":"mac-x64",e=`sootsim-latest-${o}.dmg`;return{platform:o,filename:e,url:`${h}/${e}`,install:L}}if(process.platform==="linux"){let o=n==="arm64"?"linux-arm64":"linux-x64",e=`sootsim-latest-${o}.AppImage`;return{platform:o,filename:e,url:`${h}/${e}`,install:C}}if(process.platform==="win32"){let o="sootsim-latest-win-x64.exe";return{platform:"win-x64",filename:o,url:`${h}/${o}`,install:B}}return null}async function I({url:n,dest:o,onProgress:e}){let s=await fetch(n,{redirect:"follow"});if(!s.ok)throw new Error(`${s.status} ${s.statusText} (${n})`);let t=s.headers.get("content-length"),a=t?Number(t):null;if(!s.body)throw new Error(`empty response body (${n})`);y(A(o),{recursive:!0});let i=E(o),d=s.body.getReader(),c=0;try{for(;;){let{done:l,value:p}=await d.read();if(l)break;i.write(Buffer.from(p)),c+=p.byteLength,e?.(c,a)}}finally{await new Promise((l,p)=>{i.end(r=>r?p(r):l())})}}function _(n,o){let e=(n/1048576).toFixed(1);if(!o)return` ${e} MB`;let s=Math.min(100,Math.round(n/o*100)),t=(o/(1024*1024)).toFixed(1),a=24,i=Math.round(s/100*a);return` ${"\u2588".repeat(i)+"\u2591".repeat(a-i)} ${s}% ${e} / ${t} MB`}async function L(n){let o=u("hdiutil",["attach","-nobrowse","-readonly",n],{encoding:"utf8"});if(o.status!==0)throw new Error(`hdiutil attach failed: ${o.stderr||o.stdout}`.trim());let e=o.stdout.trim().split(`
1
+ /*! sootsim v0.1.213 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
+ import{a as x}from"./chunk-SNDRRWLJ.js";import{a as k}from"./chunk-W77R37C6.js";import{spawn as v,spawnSync as u}from"child_process";import{chmodSync as S,copyFileSync as T,createWriteStream as E,existsSync as w,mkdirSync as y,rmSync as g,statSync as P,unlinkSync as D}from"fs";import{tmpdir as M}from"os";import{dirname as A,join as f,resolve as b}from"path";var h="https://sootbean.com/api/electron-release";function O(){let n=process.arch;if(process.platform==="darwin"){let o=n==="arm64"?"mac-arm64":"mac-x64",e=`sootsim-latest-${o}.dmg`;return{platform:o,filename:e,url:`${h}/${e}`,install:L}}if(process.platform==="linux"){let o=n==="arm64"?"linux-arm64":"linux-x64",e=`sootsim-latest-${o}.AppImage`;return{platform:o,filename:e,url:`${h}/${e}`,install:C}}if(process.platform==="win32"){let o="sootsim-latest-win-x64.exe";return{platform:"win-x64",filename:o,url:`${h}/${o}`,install:B}}return null}async function I({url:n,dest:o,onProgress:e}){let s=await fetch(n,{redirect:"follow"});if(!s.ok)throw new Error(`${s.status} ${s.statusText} (${n})`);let t=s.headers.get("content-length"),a=t?Number(t):null;if(!s.body)throw new Error(`empty response body (${n})`);y(A(o),{recursive:!0});let i=E(o),d=s.body.getReader(),c=0;try{for(;;){let{done:l,value:p}=await d.read();if(l)break;i.write(Buffer.from(p)),c+=p.byteLength,e?.(c,a)}}finally{await new Promise((l,p)=>{i.end(r=>r?p(r):l())})}}function _(n,o){let e=(n/1048576).toFixed(1);if(!o)return` ${e} MB`;let s=Math.min(100,Math.round(n/o*100)),t=(o/(1024*1024)).toFixed(1),a=24,i=Math.round(s/100*a);return` ${"\u2588".repeat(i)+"\u2591".repeat(a-i)} ${s}% ${e} / ${t} MB`}async function L(n){let o=u("hdiutil",["attach","-nobrowse","-readonly",n],{encoding:"utf8"});if(o.status!==0)throw new Error(`hdiutil attach failed: ${o.stderr||o.stdout}`.trim());let e=o.stdout.trim().split(`
3
3
  `),t=e[e.length-1].split(" ").pop()?.trim();if(!t||!w(t))throw new Error(`could not determine dmg mount point (output: ${o.stdout})`);let a=f(t,"sootsim.app");if(!w(a))throw u("hdiutil",["detach","-force",t]),new Error(`sootsim.app not found inside ${t}`);let i="/Applications",d=b(process.env.HOME||"","Applications"),c=i;try{let m=f(i,`.sootsim-write-probe-${process.pid}`);u("touch",[m]),w(m)?g(m,{force:!0}):c=d}catch{c=d}c===d&&y(c,{recursive:!0});let l=f(c,"sootsim.app");w(l)&&g(l,{recursive:!0,force:!0});let p=u("cp",["-R",a,l]),r=u("hdiutil",["detach","-force",t]);if(p.status!==0)throw new Error(`copy to ${l} failed: ${p.stderr?.toString()||""}`.trim());return r.status!==0&&console.warn(` warning: failed to unmount ${t} (${r.stderr?.toString().trim()||"unknown error"})`),u("xattr",["-dr","com.apple.quarantine",l]),l}async function C(n){let o=b(process.env.HOME||"","Applications");y(o,{recursive:!0});let e=f(o,"sootsim.AppImage");return w(e)&&g(e,{force:!0}),T(n,e),D(n),S(e,493),e}async function B(n){return await new Promise((o,e)=>{let s=v("cmd",["/c","start",'""',"/wait",n],{stdio:"inherit"});s.once("error",e),s.once("exit",t=>{t===0?o():e(new Error(`installer exited with code ${t}`))})}),n}async function q(n){(n.includes("--help")||n.includes("-h"))&&(console.log(`
4
4
  sootsim desktop install \u2014 download and install the optional desktop GUI
5
5
 
@@ -20,4 +20,4 @@ examples:
20
20
  `),process.exit(0));let o=n.includes("--yes")||n.includes("-y")||process.env.SOOTSIM_NO_PROMPT==="1"||process.env.CI==="1"||!process.stdin.isTTY,e=n.includes("--force"),s=k();if(s&&!e){console.log(` sootsim desktop already installed at: ${s.path}`),console.log(" pass --force to reinstall.");return}let t=O();if(t||(console.error(` no desktop build available for ${process.platform}/${process.arch}.`),console.error(" supported: darwin-arm64, darwin-x64, linux-x64, linux-arm64, win32-x64"),process.exit(1)),console.log(` platform: ${t.platform}`),console.log(` download: ${t.url}`),console.log(),!o){if(!await x("download and install now?",!0)){console.log(" cancelled.");return}console.log()}let a=f(M(),`sootsim-install-${Date.now()}`),i=f(a,t.filename),d=0;process.stdout.write(` downloading ${t.filename}...
21
21
  `);try{await I({url:t.url,dest:i,onProgress:(r,m)=>{let $=Date.now();$-d<100&&r<(m??1/0)||(d=$,process.stdout.isTTY&&process.stdout.write(`\r\x1B[2K${_(r,m)}`))}})}catch(r){g(a,{recursive:!0,force:!0});let m=r instanceof Error?r.message:String(r);console.error(`
22
22
  download failed: ${m}`),console.error(` the ${t.platform} desktop build may not be published yet, or your`),console.error(" network blocked the request. check your connection and try again later;"),console.error(" the CLI + daemon work without the desktop app (run: sootsim --help)."),process.exit(1)}process.stdout.isTTY&&process.stdout.write(`
23
- `);let c=P(i).size;console.log(` downloaded ${(c/(1024*1024)).toFixed(1)} MB`),console.log(),console.log(" installing...");let{trackCliEvent:l,flushCliTelemetry:p}=await import("./telemetry-4DVRYGKH.js");try{let r=await t.install(i);l({event:"cli_install_desktop_succeeded",properties:{platform:t.platform,size_bytes:c}}),console.log(` installed: ${r}`)}catch(r){l({event:"cli_install_desktop_failed",properties:{platform:t.platform,error:r instanceof Error?r.message:String(r)}}),await p(),console.error(` install failed: ${r instanceof Error?r.message:String(r)}`),console.error(` keeping download at ${i} for manual install.`),process.exit(1)}finally{g(a,{recursive:!0,force:!0})}console.log(),console.log(" next steps:"),console.log(" sootsim desktop launch the desktop app"),console.log(" sootsim open <target> open a demo or bundle in it")}export{q as a};
23
+ `);let c=P(i).size;console.log(` downloaded ${(c/(1024*1024)).toFixed(1)} MB`),console.log(),console.log(" installing...");let{trackCliEvent:l,flushCliTelemetry:p}=await import("./telemetry-XQHZBPJE.js");try{let r=await t.install(i);l({event:"cli_install_desktop_succeeded",properties:{platform:t.platform,size_bytes:c}}),console.log(` installed: ${r}`)}catch(r){l({event:"cli_install_desktop_failed",properties:{platform:t.platform,error:r instanceof Error?r.message:String(r)}}),await p(),console.error(` install failed: ${r instanceof Error?r.message:String(r)}`),console.error(` keeping download at ${i} for manual install.`),process.exit(1)}finally{g(a,{recursive:!0,force:!0})}console.log(),console.log(" next steps:"),console.log(" sootsim desktop launch the desktop app"),console.log(" sootsim open <target> open a demo or bundle in it")}export{q as a};