sootsim 0.1.38 → 0.1.39

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 (127) hide show
  1. package/dist-cli/bin.js +3 -3
  2. package/dist-cli/chunks/{agent-CGQWOOOL.js → agent-HZP3LUGJ.js} +2 -2
  3. package/dist-cli/chunks/{agent-wrapper-M6P53GJ2.js → agent-wrapper-CS6TV5UR.js} +2 -2
  4. package/dist-cli/chunks/{assert-O7N2SYJZ.js → assert-WVTX4CNR.js} +2 -2
  5. package/dist-cli/chunks/auto-bootstrap-3TUCG2BC.js +2 -0
  6. package/dist-cli/chunks/beta-3SCMB3IN.js +2 -0
  7. package/dist-cli/chunks/{chunk-NSZBULGG.js → chunk-223TXYOC.js} +3 -3
  8. package/dist-cli/chunks/{chunk-P32FCOS3.js → chunk-2ESCYOZW.js} +2 -2
  9. package/dist-cli/chunks/chunk-4LHQRDSN.js +2 -0
  10. package/dist-cli/chunks/chunk-4UI5OHEO.js +1 -0
  11. package/dist-cli/chunks/{chunk-UD5ILFN5.js → chunk-4YUHJ5FX.js} +2 -2
  12. package/dist-cli/chunks/{chunk-JJVZMGRM.js → chunk-5L5SZXXG.js} +2 -2
  13. package/dist-cli/chunks/chunk-5RSSCKBF.js +1 -0
  14. package/dist-cli/chunks/{chunk-NKYTISAN.js → chunk-6TSUQHSC.js} +2 -2
  15. package/dist-cli/chunks/{chunk-ZEVZN3S4.js → chunk-7J4UIBA5.js} +1 -1
  16. package/dist-cli/chunks/{chunk-HNAGYNWN.js → chunk-B2SCT4DL.js} +2 -2
  17. package/dist-cli/chunks/chunk-B3OEHV2C.js +1 -0
  18. package/dist-cli/chunks/{chunk-G23GIRBM.js → chunk-C6GUAXKO.js} +1 -1
  19. package/dist-cli/chunks/{chunk-IKVIHHWE.js → chunk-CBPTHIJV.js} +1 -1
  20. package/dist-cli/chunks/{chunk-FXY5FWVY.js → chunk-DSDLGFWH.js} +2 -2
  21. package/dist-cli/chunks/{chunk-5HNZO5AI.js → chunk-E5RYQUFB.js} +3 -3
  22. package/dist-cli/chunks/{chunk-6UJXRT7F.js → chunk-ECDPQ6S7.js} +1 -1
  23. package/dist-cli/chunks/{chunk-VVUEWU2P.js → chunk-FEMOLCB5.js} +2 -2
  24. package/dist-cli/chunks/{chunk-Z2PBRNJP.js → chunk-GUHXSXNO.js} +2 -2
  25. package/dist-cli/chunks/{chunk-TR554AIH.js → chunk-HWRR23AJ.js} +2 -2
  26. package/dist-cli/chunks/{chunk-H6CG42HE.js → chunk-JXKW62SL.js} +2 -2
  27. package/dist-cli/chunks/{chunk-5XI3AB4I.js → chunk-MGVTLDI3.js} +2 -2
  28. package/dist-cli/chunks/{chunk-PFRPXFSL.js → chunk-MIE6NMPJ.js} +1 -1
  29. package/dist-cli/chunks/{chunk-ARH3T5NK.js → chunk-NF65BNJR.js} +2 -2
  30. package/dist-cli/chunks/chunk-NFJDHJHK.js +1 -0
  31. package/dist-cli/chunks/{chunk-LNRBXCUI.js → chunk-NJ4WXWKO.js} +2 -2
  32. package/dist-cli/chunks/{chunk-IE2WYVJF.js → chunk-NYZGZDHI.js} +1 -1
  33. package/dist-cli/chunks/{chunk-B4VH67D3.js → chunk-OB3TB4AN.js} +1 -1
  34. package/dist-cli/chunks/{chunk-SKNHJDYO.js → chunk-P6F636LU.js} +1 -1
  35. package/dist-cli/chunks/{chunk-MTPWS4JK.js → chunk-RJQ73DLG.js} +2 -2
  36. package/dist-cli/chunks/{chunk-2ABGQIW7.js → chunk-RLGCJT2D.js} +1 -1
  37. package/dist-cli/chunks/{chunk-FCOCFEBU.js → chunk-SLQ2GTYF.js} +2 -2
  38. package/dist-cli/chunks/{chunk-BEY2QVU5.js → chunk-UWRBEBML.js} +2 -2
  39. package/dist-cli/chunks/{chunk-67K3WAEZ.js → chunk-VLUFTHBB.js} +2 -2
  40. package/dist-cli/chunks/{chunk-GWQUPWVO.js → chunk-W4QHQT64.js} +2 -2
  41. package/dist-cli/chunks/{chunk-VIEK76DX.js → chunk-WD54RD4K.js} +1 -1
  42. package/dist-cli/chunks/{chunk-CHMHTTI7.js → chunk-WHQWINDB.js} +2 -2
  43. package/dist-cli/chunks/{chunk-T442FYM5.js → chunk-XYTDYBXJ.js} +1 -1
  44. package/dist-cli/chunks/{chunk-QI4VLQ3A.js → chunk-YGUQSPU6.js} +1 -1
  45. package/dist-cli/chunks/{chunk-P722XCFT.js → chunk-YHYSOUIJ.js} +2 -2
  46. package/dist-cli/chunks/{chunk-E473YTRQ.js → chunk-YUKH7HF6.js} +1 -1
  47. package/dist-cli/chunks/chunk-ZBB7YS6C.js +5 -0
  48. package/dist-cli/chunks/{compat-DNQWSPFQ.js → compat-UMJ2IXUW.js} +2 -2
  49. package/dist-cli/chunks/{config-ABR5BGUO.js → config-YMJK426V.js} +2 -2
  50. package/dist-cli/chunks/control-DJR3DUAB.js +2 -0
  51. package/dist-cli/chunks/{cpu-profile-Y5YDH6X2.js → cpu-profile-67MCPAA2.js} +2 -2
  52. package/dist-cli/chunks/{daemon-2Z4DAJT6.js → daemon-LIVCJZR3.js} +2 -2
  53. package/dist-cli/chunks/{debug-R36UPOJP.js → debug-EV73WC7H.js} +3 -3
  54. package/dist-cli/chunks/demo-app-registry-NZBZVJ52.js +2 -0
  55. package/dist-cli/chunks/{detox-FQJWEWLT.js → detox-NBT5BVX3.js} +2 -2
  56. package/dist-cli/chunks/{device-SXKLDZEC.js → device-MMROWQZ3.js} +2 -2
  57. package/dist-cli/chunks/{diagnose-M7RKNI2H.js → diagnose-WXOKGBAJ.js} +2 -2
  58. package/dist-cli/chunks/drivers-NSPV5S6T.js +2 -0
  59. package/dist-cli/chunks/{electron-YUAKGT4H.js → electron-F5DT7CFY.js} +3 -3
  60. package/dist-cli/chunks/flow-T6DZQWHE.js +2 -0
  61. package/dist-cli/chunks/{hints-SDD7L3VS.js → hints-RODH4XE4.js} +2 -2
  62. package/dist-cli/chunks/{home-paths-QMCX2227.js → home-paths-PCUMN33Z.js} +2 -2
  63. package/dist-cli/chunks/{inspect-6FPPW7GS.js → inspect-BIMFJFDR.js} +3 -3
  64. package/dist-cli/chunks/install-5YPVP466.js +2 -0
  65. package/dist-cli/chunks/{install-desktop-EKMYRDQH.js → install-desktop-ASRNFHZU.js} +3 -3
  66. package/dist-cli/chunks/{keys-ODG3TDUP.js → keys-DOOCGNTD.js} +2 -2
  67. package/dist-cli/chunks/{launch-7HUL745I.js → launch-DTVAQMZG.js} +3 -3
  68. package/dist-cli/chunks/{login-BJKQMJYT.js → login-JA6VEDEP.js} +4 -4
  69. package/dist-cli/chunks/{logout-7NG3KGJD.js → logout-H4WFWTPC.js} +2 -2
  70. package/dist-cli/chunks/{maestro-VFEUWV3Q.js → maestro-4TR7U6TS.js} +2 -2
  71. package/dist-cli/chunks/{preview-WZ6XNOBC.js → preview-GP7XXDW6.js} +2 -2
  72. package/dist-cli/chunks/{profile-DXFEZOHB.js → profile-3FESGAZD.js} +2 -2
  73. package/dist-cli/chunks/{react-QP7PL5CZ.js → react-SJD2DQQV.js} +2 -2
  74. package/dist-cli/chunks/{record-AFE25EMH.js → record-PQUAMW5K.js} +2 -2
  75. package/dist-cli/chunks/{runtime-GFWS3QLZ.js → runtime-YJPWA3XA.js} +3 -3
  76. package/dist-cli/chunks/{screenshot-U6VFOVFW.js → screenshot-45SAK7EW.js} +2 -2
  77. package/dist-cli/chunks/{screenshot-mode-HNGV3AFC.js → screenshot-mode-TCY7FBGR.js} +2 -2
  78. package/dist-cli/chunks/{screenshots-GYMRDUJR.js → screenshots-KZ364S2O.js} +2 -2
  79. package/dist-cli/chunks/{server-3Q22YYM6.js → server-S5CRYXXZ.js} +7 -7
  80. package/dist-cli/chunks/setup-repo-TH3GXOP7.js +2 -0
  81. package/dist-cli/chunks/{skills-FT76ZVAV.js → skills-SMXCCJCM.js} +2 -2
  82. package/dist-cli/chunks/{start-N573LFCF.js → start-KLSAQM3C.js} +3 -3
  83. package/dist-cli/chunks/store-E2N5NOUS.js +2 -0
  84. package/dist-cli/chunks/telemetry-RJXVYJSN.js +2 -0
  85. package/dist-cli/chunks/{test-AJPY2Q6W.js → test-ZXTSA5GV.js} +3 -3
  86. package/dist-cli/chunks/{three-mode-JZZVOMTG.js → three-mode-4Q65J2ZA.js} +2 -2
  87. package/dist-cli/chunks/{timeline-GTSCF5P6.js → timeline-ISEDS6XR.js} +2 -2
  88. package/dist-cli/chunks/upload-KB7INQRC.js +2 -0
  89. package/dist-cli/chunks/{what-happened-N3AQ6I7O.js → what-happened-STY3AOCQ.js} +2 -2
  90. package/dist-cli/chunks/{whoami-FOIMN6UC.js → whoami-VKRQOG2U.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-sessions.cjs +1 -1
  94. package/dist-lib/attached-projects.cjs +1 -1
  95. package/dist-lib/auth/shared-session.cjs +1 -1
  96. package/dist-lib/backend-origin.cjs +1 -1
  97. package/dist-lib/bridge-constants.cjs +1 -1
  98. package/dist-lib/cli-constants.cjs +1 -1
  99. package/dist-lib/config.cjs +1 -1
  100. package/dist-lib/dev-bundle-resolution.cjs +1 -1
  101. package/dist-lib/home-paths.cjs +1 -1
  102. package/dist-lib/host/bridge-host.cjs +7 -2
  103. package/dist-lib/host/fetch-proxy-handler.cjs +1 -1
  104. package/dist-lib/index.cjs +1 -1
  105. package/dist-lib/metro.cjs +1 -1
  106. package/dist-lib/profiles.cjs +1 -1
  107. package/dist-lib/render-mode.cjs +1 -1
  108. package/dist-lib/vite-base.cjs +8 -3
  109. package/dist-lib/vite.cjs +1 -1
  110. package/package.json +1 -1
  111. package/dist-cli/chunks/auto-bootstrap-DF4KYGPS.js +0 -2
  112. package/dist-cli/chunks/beta-AK25X3AU.js +0 -2
  113. package/dist-cli/chunks/chunk-23YMXBQ2.js +0 -1
  114. package/dist-cli/chunks/chunk-CB4PUMI2.js +0 -1
  115. package/dist-cli/chunks/chunk-FRE5TY3C.js +0 -1
  116. package/dist-cli/chunks/chunk-FX3PPKSJ.js +0 -2
  117. package/dist-cli/chunks/chunk-G62Q2MQI.js +0 -1
  118. package/dist-cli/chunks/chunk-QD22CQLH.js +0 -5
  119. package/dist-cli/chunks/control-DEHRU4XZ.js +0 -2
  120. package/dist-cli/chunks/demo-app-registry-DMMWYL7G.js +0 -2
  121. package/dist-cli/chunks/drivers-NSCX5CRA.js +0 -2
  122. package/dist-cli/chunks/flow-UQSRNEZD.js +0 -2
  123. package/dist-cli/chunks/install-TTH3PM3B.js +0 -2
  124. package/dist-cli/chunks/setup-repo-NNDWIGZR.js +0 -2
  125. package/dist-cli/chunks/store-6NTDGLPH.js +0 -2
  126. package/dist-cli/chunks/telemetry-SNZBIRGL.js +0 -2
  127. package/dist-cli/chunks/upload-UHTVCGGR.js +0 -2
@@ -1,19 +1,19 @@
1
- /*! sootsim v0.1.38 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
- import{b as Y,c as D,d as X,e as H,f as Z,h as Q,i as w,j as ee,k as te,l as ie,p as re,s as A,t as ne,u as se,v as oe,w as ae}from"./chunk-P32FCOS3.js";import"./chunk-IE2WYVJF.js";import{a as E}from"./chunk-QD22CQLH.js";import"./chunk-E473YTRQ.js";import"./chunk-VVUEWU2P.js";import{e as z}from"./chunk-NKYTISAN.js";import{a as V,b as G}from"./chunk-67K3WAEZ.js";import"./chunk-BEY2QVU5.js";import{d as q}from"./chunk-G23GIRBM.js";import"./chunk-23YMXBQ2.js";import{A as W,B as O,D as F,E as j,F as $,G as J,H as K,I as N,u as _,v as U,y as T,z as M}from"./chunk-6UJXRT7F.js";import"./chunk-VIEK76DX.js";import{spawn as Te}from"child_process";import v from"fs";import{createServer as Ee}from"http";import S from"path";import{WebSocket as m,WebSocketServer as Ie}from"ws";import ce from"node:fs";import I from"node:path";var P=1;function ge(){return[Number(process.env.VITE_PORT_WEB||process.env.PORT||3e3),Number(process.env.VITE_PORT_ZERO||7849),Number(process.env.VITE_PORT_POSTGRES||7432),Number(process.env.VITE_PORT_R2||9500)].filter(a=>Number.isFinite(a)&&a>0)}var x=class{subscriptions=new Map;sessionsBySocket=new Map;allSockets=new Set;pendingPromptEchoes=new Map;pendingTurns=new Map;opts;constructor(e={}){this.opts=e}registerSocket(e){this.allSockets.add(e)}unregisterSocket(e){let t=this.sessionsBySocket.get(e);if(t){for(let i of t)this.decrementSubscription(i);this.sessionsBySocket.delete(e)}this.allSockets.delete(e)}async handleMessage(e,t){let i=t?.type;if(typeof i!="string"||!i.startsWith("agent:"))return!1;let s=t.id;try{let n=await this.dispatch(e,i,t);this.respond(e,s,n)}catch(n){n instanceof A?this.respondError(e,s,n.message,n.code):this.respondError(e,s,n instanceof Error?n.message:String(n))}return!0}async seedOnBoot(){try{await ie()}catch(e){process.stderr.write(`[sootsim-agent] seedFromDemoAppRegistry failed: ${e instanceof Error?e.message:String(e)}
1
+ /*! sootsim v0.1.39 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
+ import{b as Y,c as D,d as X,e as H,f as Z,h as Q,i as w,j as ee,k as te,l as ie,p as re,s as A,t as ne,u as se,v as oe,w as ae}from"./chunk-2ESCYOZW.js";import"./chunk-NYZGZDHI.js";import{a as E}from"./chunk-ZBB7YS6C.js";import"./chunk-YUKH7HF6.js";import"./chunk-FEMOLCB5.js";import{e as z}from"./chunk-6TSUQHSC.js";import{a as V,b as G}from"./chunk-VLUFTHBB.js";import"./chunk-UWRBEBML.js";import{d as q}from"./chunk-C6GUAXKO.js";import"./chunk-B3OEHV2C.js";import{A as W,B as _,D as F,E as j,F as $,G as J,H as K,I as N,u as L,v as U,y as T,z as M}from"./chunk-ECDPQ6S7.js";import"./chunk-WD54RD4K.js";import{spawn as Te}from"child_process";import v from"fs";import{createServer as Ee}from"http";import S from"path";import{WebSocket as m,WebSocketServer as Ie}from"ws";import ce from"node:fs";import I from"node:path";var P=1;function ge(){return[Number(process.env.VITE_PORT_WEB||process.env.PORT||3e3),Number(process.env.VITE_PORT_ZERO||7849),Number(process.env.VITE_PORT_POSTGRES||7432),Number(process.env.VITE_PORT_R2||9500)].filter(a=>Number.isFinite(a)&&a>0)}var x=class{subscriptions=new Map;sessionsBySocket=new Map;allSockets=new Set;pendingPromptEchoes=new Map;pendingTurns=new Map;opts;constructor(e={}){this.opts=e}registerSocket(e){this.allSockets.add(e)}unregisterSocket(e){let t=this.sessionsBySocket.get(e);if(t){for(let i of t)this.decrementSubscription(i);this.sessionsBySocket.delete(e)}this.allSockets.delete(e)}async handleMessage(e,t){let i=t?.type;if(typeof i!="string"||!i.startsWith("agent:"))return!1;let s=t.id;try{let n=await this.dispatch(e,i,t);this.respond(e,s,n)}catch(n){n instanceof A?this.respondError(e,s,n.message,n.code):this.respondError(e,s,n instanceof Error?n.message:String(n))}return!0}async seedOnBoot(){try{await ie()}catch(e){process.stderr.write(`[sootsim-agent] seedFromDemoAppRegistry failed: ${e instanceof Error?e.message:String(e)}
3
3
  `)}}close(){for(let e of this.subscriptions.values())try{e.unsubscribe()}catch{}this.subscriptions.clear(),this.sessionsBySocket.clear(),this.allSockets.clear()}async dispatch(e,t,i){switch(t){case"agent:list-projects":return H();case"agent:upsert-project":return D(i.input??{});case"agent:delete-project":return Q(String(i.projectId)),{ok:!0};case"agent:auto-attach-for-url":return this.autoAttachForUrl(i.input??{});case"agent:list-sessions":return ee(i.projectId?String(i.projectId):void 0);case"agent:start-session":return this.doStartSession(i.input??{});case"agent:send-prompt":{let n=String(i.sessionId),o=w(n);if(!o)throw new A("NO_SESSION",`no session: ${n}`);let r=this.normalizePromptEnvelope(i);return await se(n,r),this.notePromptAccepted(n,r,o.status==="working")}case"agent:end-session":this.dropSessionFanout(String(i.sessionId)),await oe(String(i.sessionId));let s=w(String(i.sessionId));return s&&this.broadcastSessionStatus(s),{ok:!0};case"agent:get-transcript":return this.getTranscript(String(i.sessionId));case"agent:get-paths":return this.getPaths();case"agent:subscribe-events":return this.subscribeSocket(e,String(i.sessionId));case"agent:unsubscribe-events":return this.unsubscribeSocket(e,String(i.sessionId));default:throw new A("UNKNOWN_AGENT_MSG",`unknown agent message: ${t}`)}}async doStartSession(e){if(!X(e.projectId))throw new A("NO_PROJECT",`no project: ${e.projectId}`);let i=await ne(e);return this.broadcastSessionStatus(i.session),i}async autoAttachForUrl(e){let t=e.bundleUrl??"",i=(()=>{try{return new URL(t).port||null}catch{return null}})();if(!i)return{project:null};let s=this.opts.getExcludePorts?.()??ge(),o=(await E({excludePorts:s})).find(l=>String(l.port)===i);if(!o||!o.cwd)return{project:null};let r=H().find(l=>l.cwd===o.cwd)??null,c=Array.from(new Set([...r?.knownBundleUrls??[],o.bundleUrl,t]));return{project:D({cwd:o.cwd,name:o.projectName??I.basename(o.cwd),preferredProvider:e.provider??r?.preferredProvider,sourceRoots:r?.sourceRoots??[o.cwd],knownBundleUrls:c,framework:r?.framework??Se(o.framework),bundleId:o.bundleId??r?.bundleId})}}getTranscript(e){let t=re(e);return ce.existsSync(t)?ce.readFileSync(t,"utf8"):{error:"transcript not found",code:"NO_TRANSCRIPT"}}getPaths(){let e=Y();return{userDataDir:e,storeFile:I.join(e,"attached-projects.json"),sessionsDir:I.join(e,"sessions"),transcriptsDir:I.join(e,"transcripts")}}subscribeSocket(e,t){let i=this.sessionsBySocket.get(e);if(i||(i=new Set,this.sessionsBySocket.set(e,i)),i.has(t))return{ok:!0,refCount:this.subscriptions.get(t)?.refCount??1};i.add(t);let s=this.subscriptions.get(t);if(s)return s.refCount++,{ok:!0,refCount:s.refCount};let n=ae(t,o=>{let r=this.coalescePromptEcho(t,o);if(r&&(this.applySessionEvent(t,r),this.fanOutEvent(t,r)),o.type==="turn-completed"){let c=w(t);if(c)try{Z(c.projectId,{usd:o.costUsd,ts:o.ts})}catch(d){process.stderr.write(`[sootsim-agent] recordTurnTelemetry failed: ${d instanceof Error?d.message:String(d)}
4
- `)}}});return this.subscriptions.set(t,{unsubscribe:n,refCount:1}),{ok:!0,refCount:1}}unsubscribeSocket(e,t){let i=this.sessionsBySocket.get(e);return!i||!i.has(t)?{ok:!0,refCount:0}:(i.delete(t),this.decrementSubscription(t))}decrementSubscription(e){let t=this.subscriptions.get(e);if(!t)return{ok:!0,refCount:0};if(t.refCount--,t.refCount<=0){try{t.unsubscribe()}catch{}return this.subscriptions.delete(e),{ok:!0,refCount:0}}return{ok:!0,refCount:t.refCount}}dropSessionFanout(e){let t=this.subscriptions.get(e);if(t){try{t.unsubscribe()}catch{}this.subscriptions.delete(e)}for(let i of this.sessionsBySocket.values())i.delete(e);this.clearPromptTracking(e)}normalizePromptEnvelope(e){if(e?.prompt&&typeof e.prompt=="object"){let t=e.prompt;return{text:String(t.text??""),...typeof t.displayText=="string"?{displayText:t.displayText}:{},...typeof t.inspectSummary=="string"?{inspectSummary:t.inspectSummary}:{},...typeof t.inspectTrace=="string"?{inspectTrace:t.inspectTrace}:{}}}return{text:String(e?.text??""),...typeof e?.displayText=="string"?{displayText:e.displayText}:{},...typeof e?.inspectSummary=="string"?{inspectSummary:e.inspectSummary}:{},...typeof e?.inspectTrace=="string"?{inspectTrace:e.inspectTrace}:{}}}notePromptAccepted(e,t,i){let s=Date.now(),n=this.pendingPromptEchoes.get(e)??[];n.push({sentAt:s}),this.pendingPromptEchoes.set(e,n);let o=Math.max(this.pendingTurns.get(e)??0,i?1:0)+1;this.pendingTurns.set(e,o);let r=t.displayText??t.text;return this.patchSession(e,{lastPrompt:r,status:"working",needsAttention:!1}),this.fanOutEvent(e,{type:"prompt-received",text:r,...t.inspectSummary?{inspectSummary:t.inspectSummary}:{},...t.inspectTrace?{inspectTrace:t.inspectTrace}:{},ts:s}),{ok:!0,queued:o>1,pendingTurns:o,queueDepth:Math.max(0,o-1)}}applySessionEvent(e,t){switch(t.type){case"prompt-received":case"turn-started":this.patchSession(e,{status:"working",needsAttention:!1});return;case"turn-completed":{let i=this.consumeSettledTurn(e);this.patchSession(e,{status:i>0?"working":"idle",needsAttention:!1,lastTurnFiles:t.filesTouched,currentlyEditing:void 0});return}case"approval-needed":this.patchSession(e,{status:"needs-attention",needsAttention:!0});return;case"error":{let i=this.consumeSettledTurn(e);this.patchSession(e,{status:i>0?"working":"needs-attention",needsAttention:i<=0,currentlyEditing:void 0});return}case"exited":this.clearPromptTracking(e),this.patchSession(e,{status:"ended",needsAttention:!1,wrapperPid:void 0,currentlyEditing:void 0});return;case"ready":case"turn-reasoning":case"turn-message":case"turn-plan":case"tool-call":case"file-edited":case"file-diff-delta":return}}patchSession(e,t){te(e,t);let i=w(e);i&&this.broadcastSessionStatus(i)}coalescePromptEcho(e,t){if(t.type!=="prompt-received")return t;let i=this.pendingPromptEchoes.get(e);if(!i||i.length===0)return t;for(;i.length>0&&Date.now()-i[0].sentAt>15e3;)i.shift();return i.length===0?(this.pendingPromptEchoes.delete(e),t):(i.shift(),i.length===0?this.pendingPromptEchoes.delete(e):this.pendingPromptEchoes.set(e,i),null)}consumeSettledTurn(e){let t=Math.max(0,(this.pendingTurns.get(e)??1)-1);return t>0?this.pendingTurns.set(e,t):this.pendingTurns.delete(e),t}clearPromptTracking(e){this.pendingPromptEchoes.delete(e),this.pendingTurns.delete(e)}fanOutEvent(e,t){let i=JSON.stringify({type:"agent:event",sessionId:e,event:t});for(let[s,n]of this.sessionsBySocket)if(n.has(e)&&s.readyState===P)try{s.send(i)}catch{}}broadcastSessionStatus(e){let t=JSON.stringify({type:"agent:session-status",session:e});for(let i of this.allSockets)if(i.readyState===P)try{i.send(t)}catch{}}respond(e,t,i){if(e.readyState===P)try{e.send(JSON.stringify({id:t,result:i}))}catch{}}respondError(e,t,i,s){if(e.readyState===P)try{e.send(JSON.stringify({id:t,error:i,...s?{code:s}:{}}))}catch{}}};function Se(a){return a==="expo"?"expo":a==="one"||a==="vxrn"?"one":"unknown"}import ye from"http";import ve from"https";var be="sootsim",we=new Set(["host","origin","referer","user-agent","cookie","connection","keep-alive","transfer-encoding","upgrade","content-length","sec-fetch-site","sec-fetch-mode","sec-fetch-dest","sec-ch-ua","sec-ch-ua-mobile","sec-ch-ua-platform"]),Ae={"access-control-allow-origin":"*","access-control-allow-methods":"GET,POST,PUT,DELETE,PATCH,OPTIONS","access-control-allow-headers":"*","access-control-expose-headers":"*","access-control-max-age":"3600"};function k(a){for(let[e,t]of Object.entries(Ae))a.setHeader(e,t)}function ke(a,e){let t=[],i=e;i?.code&&t.push(i.code),i?.message&&t.push(i.message),i?.cause?.code&&t.push(i.cause.code),i?.cause?.message&&t.push(i.cause.message);let n=[...new Set(t.filter(Boolean))].join(" | ")||String(e);return a.includes("stored-in-.env.local")?`${n} | upstream url still contains placeholder env values`:n}function Ce(a){let e={};for(let[t,i]of Object.entries(a))i&&(we.has(t.toLowerCase())||(e[t]=Array.isArray(i)?i.join(", "):i));return e["user-agent"]=be,e}function de(a){return a?.startsWith("/__fetch-proxy?")||a?.startsWith("/__proxy?")||!1}function le(a){return a?!!(a.startsWith("/__app-api?")||a.startsWith("/__app-api/")):!1}async function ue(a,e){if(a.method==="OPTIONS"){k(e),e.writeHead(204),e.end();return}let i=new URLSearchParams((a.url||"").split("?")[1]||"").get("url");if(!i){k(e),e.writeHead(400,{"Content-Type":"text/plain"}),e.end("missing url param");return}let s;try{s=new URL(i)}catch{k(e),e.writeHead(400,{"Content-Type":"text/plain"}),e.end("invalid url param");return}let n=Ce(a.headers),o;if(a.method!=="GET"&&a.method!=="HEAD"){let l=[];for await(let u of a)l.push(Buffer.isBuffer(u)?u:Buffer.from(u));l.length>0&&(o=Buffer.concat(l))}let r;try{r=await fetch(s.href,{method:a.method,headers:n,body:o,redirect:"follow"})}catch(l){k(e),e.writeHead(502,{"Content-Type":"text/plain"}),e.end(`fetch proxy error: ${ke(s.href,l)}`);return}r.headers.forEach((l,u)=>{let p=u.toLowerCase();p==="content-encoding"||p==="transfer-encoding"||p==="content-length"||p==="set-cookie"||p.startsWith("access-control-")||e.setHeader(u,l)}),k(e);let c=r.headers.getSetCookie?.()??[];c.length>0&&e.setHeader("x-sootsim-set-cookie",c.join(", ")),e.statusCode=r.status;let d=Buffer.from(await r.arrayBuffer());e.end(d)}function pe(a,e){let t=a.url||"",i="",s="";if(t.startsWith("/__app-api?")){let d=new URL(t,"http://sootsim.local");i=d.searchParams.get("path")||"",s=d.searchParams.get("origin")?.trim()||""}else if(t.startsWith("/__app-api/"))i=t.slice(10);else return!1;if(!s)return e.writeHead(400,{"Content-Type":"text/plain"}),e.end("app-api: missing origin query param"),!0;if(a.method==="OPTIONS")return e.writeHead(204,{"Access-Control-Allow-Origin":a.headers.origin||"*","Access-Control-Allow-Methods":"GET,POST,PUT,PATCH,DELETE,OPTIONS","Access-Control-Allow-Headers":a.headers["access-control-request-headers"]||"*","Access-Control-Allow-Credentials":"true","Access-Control-Max-Age":"86400"}),e.end(),!0;let n;try{n=new URL(i,s)}catch{return e.writeHead(400,{"Content-Type":"text/plain"}),e.end("app-api: invalid origin or path"),!0}let o=n.protocol==="https:"?ve:ye,r={...a.headers};delete r.host,r.host=n.host;let c=o.request({hostname:n.hostname,port:n.port||(n.protocol==="https:"?443:80),path:n.pathname+n.search,method:a.method,headers:r},d=>{let l=Object.keys(d.headers).filter(u=>{let p=u.toLowerCase();return!p.startsWith("access-control-")&&p!=="set-cookie"}).join(", ");e.writeHead(d.statusCode??502,{...d.headers,"access-control-allow-origin":a.headers.origin||"*","access-control-allow-credentials":"true","access-control-expose-headers":l}),d.pipe(e)});return c.on("error",d=>{e.statusCode=502,e.end(`app proxy error: ${d.message}`)}),a.pipe(c),!0}var Pe=new Set(["tap","keyboard","close"]);function xe(a){return!a||typeof a.type!="string"?!1:a.acquireLock===!0?!0:a.readOnly===!0?!1:Pe.has(a.type)}var Re=5e3,Be=3600*1e3,Le="SOOTSIM_RUNTIME_UPDATE_INTERVAL_MS",_e={".html":"text/html; charset=utf-8",".js":"application/javascript",".cjs":"application/javascript",".mjs":"application/javascript",".css":"text/css; charset=utf-8",".json":"application/json; charset=utf-8",".png":"image/png",".jpg":"image/jpeg",".jpeg":"image/jpeg",".gif":"image/gif",".svg":"image/svg+xml",".webp":"image/webp",".avif":"image/avif",".ico":"image/x-icon",".wasm":"application/wasm",".ttf":"font/ttf",".otf":"font/otf",".woff":"font/woff",".woff2":"font/woff2",".map":"application/json",".txt":"text/plain; charset=utf-8"};function he(a){let e;try{let s=_();e=JSON.stringify(s)}catch{e="{}"}let t=`<script>window.__sootsimSharedConfig=${e};</script>`,i=a.toString("utf8");return i.includes("</head>")?i.replace("</head>",t+"</head>"):i.includes("</body>")?i.replace("</body>",t+"</body>"):t+i}var R=class a{port;openUrlHandler;httpServer=null;wss=null;nextCommandId=1;nextSimNumber=161;sims=new Map;primarySimId=null;pendingCommands=new Map;cliBySentId=new Map;cliSimBySocket=new Map;cliLastCommandAt=new Map;cliIdentityKeyBySocket=new Map;cliLabelBySocket=new Map;restorableSims=new Map;nextCliFallbackId=1;cliIdleTimer=null;agentHost;static CLI_IDLE_TIMEOUT_MS=6e4;static CLI_LEASE_TTL_MS=6e5;static USER_ACTIVE_LEASE_TTL_MS=8e3;static USER_BOOT_LEASE_TTL_MS=6e4;static SIM_RECONNECT_TTL_MS=3e4;preferredPort;portFallbackCount;shouldWriteLockfile;effectivePort=0;startedAt=0;heartbeatTimer=null;wsHeartbeatTimer=null;wsIsAlive=new WeakMap;static WS_HEARTBEAT_INTERVAL_MS=3e4;runtimeUpdateTimer=null;runtimeUpdateInFlight=null;activeRuntimeVersion=null;activeRuntimeDirPath=null;scanCache=null;scanCacheAt=0;inflightScan=null;static SCAN_FRESH_MS=2e3;constructor(e={}){this.preferredPort=e.port||7668,this.port=this.preferredPort,this.shouldWriteLockfile=e.writeLockfile===!0,this.portFallbackCount=Math.max(1,e.portFallbackCount??10),this.openUrlHandler=e.openUrl,this.agentHost=new x({getExcludePorts:e.agentScanExcludes})}getAgentHost(){return this.agentHost}start(e){this.startAsync(e)}async startAsync(e){if(this.httpServer||this.wss)return this.effectivePort;this.refreshActiveRuntime();for(let t=0;t<this.portFallbackCount;t++){let i=this.preferredPort+t;try{return await this.bindOnce(i,e?.silent===!0),this.effectivePort=i,this.port=i,this.startedAt=Date.now(),t>0&&!e?.silent&&process.stderr.write(`ws bridge bound to port ${i} (preferred ${this.preferredPort} was taken)
4
+ `)}}});return this.subscriptions.set(t,{unsubscribe:n,refCount:1}),{ok:!0,refCount:1}}unsubscribeSocket(e,t){let i=this.sessionsBySocket.get(e);return!i||!i.has(t)?{ok:!0,refCount:0}:(i.delete(t),this.decrementSubscription(t))}decrementSubscription(e){let t=this.subscriptions.get(e);if(!t)return{ok:!0,refCount:0};if(t.refCount--,t.refCount<=0){try{t.unsubscribe()}catch{}return this.subscriptions.delete(e),{ok:!0,refCount:0}}return{ok:!0,refCount:t.refCount}}dropSessionFanout(e){let t=this.subscriptions.get(e);if(t){try{t.unsubscribe()}catch{}this.subscriptions.delete(e)}for(let i of this.sessionsBySocket.values())i.delete(e);this.clearPromptTracking(e)}normalizePromptEnvelope(e){if(e?.prompt&&typeof e.prompt=="object"){let t=e.prompt;return{text:String(t.text??""),...typeof t.displayText=="string"?{displayText:t.displayText}:{},...typeof t.inspectSummary=="string"?{inspectSummary:t.inspectSummary}:{},...typeof t.inspectTrace=="string"?{inspectTrace:t.inspectTrace}:{}}}return{text:String(e?.text??""),...typeof e?.displayText=="string"?{displayText:e.displayText}:{},...typeof e?.inspectSummary=="string"?{inspectSummary:e.inspectSummary}:{},...typeof e?.inspectTrace=="string"?{inspectTrace:e.inspectTrace}:{}}}notePromptAccepted(e,t,i){let s=Date.now(),n=this.pendingPromptEchoes.get(e)??[];n.push({sentAt:s}),this.pendingPromptEchoes.set(e,n);let o=Math.max(this.pendingTurns.get(e)??0,i?1:0)+1;this.pendingTurns.set(e,o);let r=t.displayText??t.text;return this.patchSession(e,{lastPrompt:r,status:"working",needsAttention:!1}),this.fanOutEvent(e,{type:"prompt-received",text:r,...t.inspectSummary?{inspectSummary:t.inspectSummary}:{},...t.inspectTrace?{inspectTrace:t.inspectTrace}:{},ts:s}),{ok:!0,queued:o>1,pendingTurns:o,queueDepth:Math.max(0,o-1)}}applySessionEvent(e,t){switch(t.type){case"prompt-received":case"turn-started":this.patchSession(e,{status:"working",needsAttention:!1});return;case"turn-completed":{let i=this.consumeSettledTurn(e);this.patchSession(e,{status:i>0?"working":"idle",needsAttention:!1,lastTurnFiles:t.filesTouched,currentlyEditing:void 0});return}case"approval-needed":this.patchSession(e,{status:"needs-attention",needsAttention:!0});return;case"error":{let i=this.consumeSettledTurn(e);this.patchSession(e,{status:i>0?"working":"needs-attention",needsAttention:i<=0,currentlyEditing:void 0});return}case"exited":this.clearPromptTracking(e),this.patchSession(e,{status:"ended",needsAttention:!1,wrapperPid:void 0,currentlyEditing:void 0});return;case"ready":case"turn-reasoning":case"turn-message":case"turn-plan":case"tool-call":case"file-edited":case"file-diff-delta":return}}patchSession(e,t){te(e,t);let i=w(e);i&&this.broadcastSessionStatus(i)}coalescePromptEcho(e,t){if(t.type!=="prompt-received")return t;let i=this.pendingPromptEchoes.get(e);if(!i||i.length===0)return t;for(;i.length>0&&Date.now()-i[0].sentAt>15e3;)i.shift();return i.length===0?(this.pendingPromptEchoes.delete(e),t):(i.shift(),i.length===0?this.pendingPromptEchoes.delete(e):this.pendingPromptEchoes.set(e,i),null)}consumeSettledTurn(e){let t=Math.max(0,(this.pendingTurns.get(e)??1)-1);return t>0?this.pendingTurns.set(e,t):this.pendingTurns.delete(e),t}clearPromptTracking(e){this.pendingPromptEchoes.delete(e),this.pendingTurns.delete(e)}fanOutEvent(e,t){let i=JSON.stringify({type:"agent:event",sessionId:e,event:t});for(let[s,n]of this.sessionsBySocket)if(n.has(e)&&s.readyState===P)try{s.send(i)}catch{}}broadcastSessionStatus(e){let t=JSON.stringify({type:"agent:session-status",session:e});for(let i of this.allSockets)if(i.readyState===P)try{i.send(t)}catch{}}respond(e,t,i){if(e.readyState===P)try{e.send(JSON.stringify({id:t,result:i}))}catch{}}respondError(e,t,i,s){if(e.readyState===P)try{e.send(JSON.stringify({id:t,error:i,...s?{code:s}:{}}))}catch{}}};function Se(a){return a==="expo"?"expo":a==="one"||a==="vxrn"?"one":"unknown"}import ye from"http";import ve from"https";var be="sootsim",we=new Set(["host","origin","referer","user-agent","cookie","connection","keep-alive","transfer-encoding","upgrade","content-length","sec-fetch-site","sec-fetch-mode","sec-fetch-dest","sec-ch-ua","sec-ch-ua-mobile","sec-ch-ua-platform"]),Ae={"access-control-allow-origin":"*","access-control-allow-methods":"GET,POST,PUT,DELETE,PATCH,OPTIONS","access-control-allow-headers":"*","access-control-expose-headers":"*","access-control-max-age":"3600"};function k(a){for(let[e,t]of Object.entries(Ae))a.setHeader(e,t)}function ke(a,e){let t=[],i=e;i?.code&&t.push(i.code),i?.message&&t.push(i.message),i?.cause?.code&&t.push(i.cause.code),i?.cause?.message&&t.push(i.cause.message);let n=[...new Set(t.filter(Boolean))].join(" | ")||String(e);return a.includes("stored-in-.env.local")?`${n} | upstream url still contains placeholder env values`:n}function Ce(a){let e={};for(let[t,i]of Object.entries(a))i&&(we.has(t.toLowerCase())||(e[t]=Array.isArray(i)?i.join(", "):i));return e["user-agent"]=be,e}function de(a){return a?.startsWith("/__fetch-proxy?")||a?.startsWith("/__proxy?")||!1}function le(a){return a?!!(a.startsWith("/__app-api?")||a.startsWith("/__app-api/")):!1}async function ue(a,e){if(a.method==="OPTIONS"){k(e),e.writeHead(204),e.end();return}let i=new URLSearchParams((a.url||"").split("?")[1]||"").get("url");if(!i){k(e),e.writeHead(400,{"Content-Type":"text/plain"}),e.end("missing url param");return}let s;try{s=new URL(i)}catch{k(e),e.writeHead(400,{"Content-Type":"text/plain"}),e.end("invalid url param");return}let n=Ce(a.headers),o;if(a.method!=="GET"&&a.method!=="HEAD"){let l=[];for await(let u of a)l.push(Buffer.isBuffer(u)?u:Buffer.from(u));l.length>0&&(o=Buffer.concat(l))}let r;try{r=await fetch(s.href,{method:a.method,headers:n,body:o,redirect:"follow"})}catch(l){k(e),e.writeHead(502,{"Content-Type":"text/plain"}),e.end(`fetch proxy error: ${ke(s.href,l)}`);return}r.headers.forEach((l,u)=>{let p=u.toLowerCase();p==="content-encoding"||p==="transfer-encoding"||p==="content-length"||p==="set-cookie"||p.startsWith("access-control-")||e.setHeader(u,l)}),k(e);let c=r.headers.getSetCookie?.()??[];c.length>0&&e.setHeader("x-sootsim-set-cookie",c.join(", ")),e.statusCode=r.status;let d=Buffer.from(await r.arrayBuffer());e.end(d)}function pe(a,e){let t=a.url||"",i="",s="";if(t.startsWith("/__app-api?")){let d=new URL(t,"http://sootsim.local");i=d.searchParams.get("path")||"",s=d.searchParams.get("origin")?.trim()||""}else if(t.startsWith("/__app-api/"))i=t.slice(10);else return!1;if(!s)return e.writeHead(400,{"Content-Type":"text/plain"}),e.end("app-api: missing origin query param"),!0;if(a.method==="OPTIONS")return e.writeHead(204,{"Access-Control-Allow-Origin":a.headers.origin||"*","Access-Control-Allow-Methods":"GET,POST,PUT,PATCH,DELETE,OPTIONS","Access-Control-Allow-Headers":a.headers["access-control-request-headers"]||"*","Access-Control-Allow-Credentials":"true","Access-Control-Max-Age":"86400"}),e.end(),!0;let n;try{n=new URL(i,s)}catch{return e.writeHead(400,{"Content-Type":"text/plain"}),e.end("app-api: invalid origin or path"),!0}let o=n.protocol==="https:"?ve:ye,r={...a.headers};delete r.host,r.host=n.host;let c=o.request({hostname:n.hostname,port:n.port||(n.protocol==="https:"?443:80),path:n.pathname+n.search,method:a.method,headers:r},d=>{let l=Object.keys(d.headers).filter(u=>{let p=u.toLowerCase();return!p.startsWith("access-control-")&&p!=="set-cookie"}).join(", ");e.writeHead(d.statusCode??502,{...d.headers,"access-control-allow-origin":a.headers.origin||"*","access-control-allow-credentials":"true","access-control-expose-headers":l}),d.pipe(e)});return c.on("error",d=>{e.statusCode=502,e.end(`app proxy error: ${d.message}`)}),a.pipe(c),!0}var Pe=new Set(["tap","keyboard","close"]);function xe(a){return!a||typeof a.type!="string"?!1:a.acquireLock===!0?!0:a.readOnly===!0?!1:Pe.has(a.type)}var Re=5e3,Be=3600*1e3,Oe="SOOTSIM_RUNTIME_UPDATE_INTERVAL_MS",Le={".html":"text/html; charset=utf-8",".js":"application/javascript",".cjs":"application/javascript",".mjs":"application/javascript",".css":"text/css; charset=utf-8",".json":"application/json; charset=utf-8",".png":"image/png",".jpg":"image/jpeg",".jpeg":"image/jpeg",".gif":"image/gif",".svg":"image/svg+xml",".webp":"image/webp",".avif":"image/avif",".ico":"image/x-icon",".wasm":"application/wasm",".ttf":"font/ttf",".otf":"font/otf",".woff":"font/woff",".woff2":"font/woff2",".map":"application/json",".txt":"text/plain; charset=utf-8"};function he(a){let e;try{let s=L();e=JSON.stringify(s)}catch{e="{}"}let t=`<script>window.__sootsimSharedConfig=${e};</script>`,i=a.toString("utf8");return i.includes("</head>")?i.replace("</head>",t+"</head>"):i.includes("</body>")?i.replace("</body>",t+"</body>"):t+i}var R=class a{port;openUrlHandler;httpServer=null;wss=null;nextCommandId=1;nextSimNumber=161;sims=new Map;primarySimId=null;pendingCommands=new Map;cliBySentId=new Map;cliSimBySocket=new Map;cliLastCommandAt=new Map;cliIdentityKeyBySocket=new Map;cliLabelBySocket=new Map;restorableSims=new Map;nextCliFallbackId=1;cliIdleTimer=null;agentHost;static CLI_IDLE_TIMEOUT_MS=6e4;static CLI_LEASE_TTL_MS=6e5;static USER_ACTIVE_LEASE_TTL_MS=8e3;static USER_BOOT_LEASE_TTL_MS=6e4;static SIM_RECONNECT_TTL_MS=3e4;preferredPort;portFallbackCount;shouldWriteLockfile;effectivePort=0;startedAt=0;heartbeatTimer=null;wsHeartbeatTimer=null;wsIsAlive=new WeakMap;static WS_HEARTBEAT_INTERVAL_MS=3e4;runtimeUpdateTimer=null;runtimeUpdateInFlight=null;activeRuntimeVersion=null;activeRuntimeDirPath=null;scanCache=null;scanCacheAt=0;inflightScan=null;static SCAN_FRESH_MS=2e3;constructor(e={}){this.preferredPort=e.port||7668,this.port=this.preferredPort,this.shouldWriteLockfile=e.writeLockfile===!0,this.portFallbackCount=Math.max(1,e.portFallbackCount??10),this.openUrlHandler=e.openUrl,this.agentHost=new x({getExcludePorts:e.agentScanExcludes})}getAgentHost(){return this.agentHost}start(e){this.startAsync(e)}async startAsync(e){if(this.httpServer||this.wss)return this.effectivePort;this.refreshActiveRuntime();for(let t=0;t<this.portFallbackCount;t++){let i=this.preferredPort+t;try{return await this.bindOnce(i,e?.silent===!0),this.effectivePort=i,this.port=i,this.startedAt=Date.now(),t>0&&!e?.silent&&process.stderr.write(`ws bridge bound to port ${i} (preferred ${this.preferredPort} was taken)
5
5
  `),this.afterBind(),i}catch(s){if(s?.code!=="EADDRINUSE")throw s;e?.silent||process.stderr.write(`ws bridge port ${i} already in use, trying ${i+1}
6
6
  `)}}throw new Error(`could not bind ws bridge after ${this.portFallbackCount} attempts starting at ${this.preferredPort}`)}bindOnce(e,t){return new Promise((i,s)=>{let n=Ee((c,d)=>this.handleHttpRequest(c,d)),o=!1,r=c=>{if(!o){o=!0;try{n.close()}catch{}this.httpServer=null,this.wss=null,s(c)}};n.once("error",r),n.listen(e,"127.0.0.1",()=>{o||(o=!0,n.removeListener("error",r),n.on("error",c=>{process.stderr.write(`ws bridge http error: ${String(c)}
7
- `)}),this.httpServer=n,this.wss=new Ie({server:n}),this.wireWebSocketServer(),i())})})}wireWebSocketServer(){this.wss&&this.wss.on("connection",(e,t)=>{let i=t.headers.origin,s=i?"sim":"cli",n=null;if(e.on("error",()=>{}),this.wsIsAlive.set(e,!0),e.on("pong",()=>{this.wsIsAlive.set(e,!0)}),this.agentHost.registerSocket(e),s==="sim")n={id:this.allocateSimId(),ws:e,origin:i,connectedAt:Date.now(),lastSeenAt:Date.now(),lastActiveAt:0,recentActions:[]},this.sims.set(n.id,n),this.shouldPromoteSim(n)&&(this.primarySimId=n.id),this.broadcastSimAssignments(),this.broadcastSimClientStates();else{let o=`ws-${this.nextCliFallbackId++}`;this.cliIdentityKeyBySocket.set(e,o)}e.on("message",o=>{let r;try{r=JSON.parse(o.toString())}catch{return}if(!(!r||typeof r!="object")){if(typeof r.type=="string"&&r.type.startsWith("agent:")){this.agentHost.handleMessage(e,r);return}if(r.type==="runtime:list"){let c=O(),d=this.getActiveRuntime(),l={type:"runtime:list:ok",id:r.id,installed:c,active:d.version,activeRuntimeDir:d.runtimeDir};try{e.send(JSON.stringify(l))}catch{}return}if(r.type==="runtime:use"){let c=typeof r.version=="string"?r.version:"";if(!O().includes(c)){try{e.send(JSON.stringify({type:"runtime:use:error",id:r.id,error:`runtime ${c||"(missing)"} is not installed`}))}catch{}return}let l=this.setActiveRuntime(c);try{e.send(JSON.stringify({type:"runtime:use:ok",id:r.id,version:l.version,runtimeDir:l.runtimeDir}))}catch{}return}if(r.type==="runtime:get"){let c=this.getActiveRuntime();try{e.send(JSON.stringify({type:"runtime:get:ok",id:r.id,active:c.version,activeRuntimeDir:c.runtimeDir}))}catch{}return}if(s==="sim"){if(n&&(n.lastSeenAt=Date.now()),r.type==="bridge:register"&&n){let l=r,u=this.tryRestoreSimId(n,l.simId);n.url=l.url,n.title=l.title,n.userAgent=l.userAgent,u&&(this.broadcastSimAssignments(),this.broadcastSimClientStates());return}if(r.type==="bridge:user-focus-state"&&n){let l=r;this.updateUserFocusLease(n,l.focused===!0);return}if(r.type==="bridge:user-interact"&&n){this.updateUserActivity(n);return}if(r.type==="bridge:write-shared-config"){let l=r.patch&&typeof r.patch=="object"?r.patch:null;if(!l)return;let u;try{u=U(l)}catch(h){process.stderr.write(`sootsim: bridge:write-shared-config failed: ${h instanceof Error?h.message:String(h)}
7
+ `)}),this.httpServer=n,this.wss=new Ie({server:n}),this.wireWebSocketServer(),i())})})}wireWebSocketServer(){this.wss&&this.wss.on("connection",(e,t)=>{let i=t.headers.origin,s=i?"sim":"cli",n=null;if(e.on("error",()=>{}),this.wsIsAlive.set(e,!0),e.on("pong",()=>{this.wsIsAlive.set(e,!0)}),this.agentHost.registerSocket(e),s==="sim")n={id:this.allocateSimId(),ws:e,origin:i,connectedAt:Date.now(),lastSeenAt:Date.now(),lastActiveAt:0,recentActions:[]},this.sims.set(n.id,n),this.shouldPromoteSim(n)&&(this.primarySimId=n.id),this.broadcastSimAssignments(),this.broadcastSimClientStates();else{let o=`ws-${this.nextCliFallbackId++}`;this.cliIdentityKeyBySocket.set(e,o)}e.on("message",o=>{let r;try{r=JSON.parse(o.toString())}catch{return}if(!(!r||typeof r!="object")){if(typeof r.type=="string"&&r.type.startsWith("agent:")){this.agentHost.handleMessage(e,r);return}if(r.type==="runtime:list"){let c=_(),d=this.getActiveRuntime(),l={type:"runtime:list:ok",id:r.id,installed:c,active:d.version,activeRuntimeDir:d.runtimeDir};try{e.send(JSON.stringify(l))}catch{}return}if(r.type==="runtime:use"){let c=typeof r.version=="string"?r.version:"";if(!_().includes(c)){try{e.send(JSON.stringify({type:"runtime:use:error",id:r.id,error:`runtime ${c||"(missing)"} is not installed`}))}catch{}return}let l=this.setActiveRuntime(c);try{e.send(JSON.stringify({type:"runtime:use:ok",id:r.id,version:l.version,runtimeDir:l.runtimeDir}))}catch{}return}if(r.type==="runtime:get"){let c=this.getActiveRuntime();try{e.send(JSON.stringify({type:"runtime:get:ok",id:r.id,active:c.version,activeRuntimeDir:c.runtimeDir}))}catch{}return}if(s==="sim"){if(n&&(n.lastSeenAt=Date.now()),r.type==="bridge:register"&&n){let l=r,u=this.tryRestoreSimId(n,l.simId);n.url=l.url,n.title=l.title,n.userAgent=l.userAgent,u&&(this.broadcastSimAssignments(),this.broadcastSimClientStates());return}if(r.type==="bridge:user-focus-state"&&n){let l=r;this.updateUserFocusLease(n,l.focused===!0);return}if(r.type==="bridge:user-interact"&&n){this.updateUserActivity(n);return}if(r.type==="bridge:write-shared-config"){let l=r.patch&&typeof r.patch=="object"?r.patch:null;if(!l)return;let u;try{u=U(l)}catch(h){process.stderr.write(`sootsim: bridge:write-shared-config failed: ${h instanceof Error?h.message:String(h)}
8
8
  `);return}let p=JSON.stringify({type:"bridge:shared-config-changed",config:u});for(let h of this.sims.values())if(h.ws.readyState===m.OPEN)try{h.ws.send(p)}catch{}return}if(r.type==="bridge:open-path"){let l=typeof r.path=="string"?r.path:"",u=typeof r.line=="number"&&Number.isFinite(r.line)?r.line:void 0,p=typeof r.column=="number"&&Number.isFinite(r.column)?r.column:void 0;l&&this.openPathInEditor(l,u,p);return}if(r.type==="bridge:boot-clients"&&n){let l=[];for(let[p,h]of this.cliSimBySocket)h===n.id&&l.push(p);for(let p of l){this.cliSimBySocket.delete(p);try{p.close(1e3,"booted by sim")}catch{}}let u=!!n.cliLease;n.cliLease={kind:"user-active",cliIdentityKey:"__user-active__",cliLabel:"active user",expiresAt:Date.now()+a.USER_BOOT_LEASE_TTL_MS},process.stderr.write(`sootsim booted ${l.length} cli client(s)${u?" (overrode prior lease)":""}; held sim for user [${n.id}]
9
9
  `),this.recordSimAction(n.id,"sim booted cli clients"),this.broadcastSimClientStates();return}let c=this.pendingCommands.get(r.id);if(c){this.pendingCommands.delete(r.id),r.error?c.reject(new Error(r.error)):c.resolve(r.result);return}let d=this.cliBySentId.get(r.id);if(d&&(this.cliBySentId.delete(r.id),d.ws.readyState===m.OPEN)){let l=this.getOtherCliIdentityCount(d.ws,d.simId),u=l>0?{...r,id:d.originalId,i:l}:{...r,id:d.originalId};d.ws.send(JSON.stringify(u))}return}(async()=>{this.cliLastCommandAt.set(e,Date.now());try{if(r.type==="bridge:bye"){let p=this.cliSimBySocket.delete(e);this.cliLastCommandAt.delete(e),this.cliIdentityKeyBySocket.delete(e),this.cliLabelBySocket.delete(e);for(let[h,g]of this.cliBySentId)g.ws===e&&this.cliBySentId.delete(h);p&&this.broadcastSimClientStates();return}if(r.type==="bridge:hello"){let p=typeof r.cliIdentityKey=="string"&&r.cliIdentityKey.trim()?r.cliIdentityKey.trim():this.cliIdentityKeyBySocket.get(e)||`ws-${this.nextCliFallbackId++}`;this.cliIdentityKeyBySocket.set(e,p),typeof r.cliLabel=="string"&&r.cliLabel.trim()&&this.cliLabelBySocket.set(e,r.cliLabel.trim()),e.readyState===m.OPEN&&e.send(JSON.stringify({id:r.id,result:{cliIdentityKey:p,leaseTtlMs:a.CLI_LEASE_TTL_MS,leasing:!0}}));return}if(r.type==="bridge:list-sims"){e.readyState===m.OPEN&&e.send(JSON.stringify({id:r.id,result:this.listSims()}));return}if(r.type==="bridge:open"){if(typeof r.url!="string"||!r.url)throw new Error("bridge:open requires a url");await this.openUrl(r.url,{newWindow:r.newWindow===!0}),e.readyState===m.OPEN&&e.send(JSON.stringify({id:r.id,result:{ok:!0,url:r.url}}));return}if(r.type==="bridge:claim"){let p=await this.waitForSim(r.simId),h=this.tryAcquireLease(e,p,{force:r.force===!0});if(!h.granted){e.readyState===m.OPEN&&e.send(JSON.stringify({id:r.id,error:`sim ${p.id} is locked by another cli`,o:h.lock}));return}this.setCliSimTarget(e,p.id),this.recordSimAction(p.id,h.bootedCount>0?`cli force-claimed sim (booted ${h.bootedCount})`:"cli claimed sim"),e.readyState===m.OPEN&&e.send(JSON.stringify({id:r.id,result:{simId:p.id,lockedBy:h.lease.cliIdentityKey,lockExpiresAt:h.lease.expiresAt,bootedCount:h.bootedCount}}));return}let c=await this.waitForSim(r.simId);if(xe(r)){let p=this.tryAcquireLease(e,c);if(!p.granted){e.readyState===m.OPEN&&e.send(JSON.stringify({id:r.id,error:`sim ${c.id} is locked by another cli \u2014 use \`sootsim claim ${c.id} --force\` or \`sootsim open --new\``,o:p.lock}));return}}else this.ensureCliIdentityKey(e);this.setCliSimTarget(e,c.id),this.recordSimAction(c.id,this.describeForwardedCommand(r));let d=this.nextCommandId++;this.cliBySentId.set(d,{simId:c.id,ws:e,originalId:r.id});let{simId:l,...u}=r;c.ws.send(JSON.stringify({...u,id:d}))}catch(c){e.readyState===m.OPEN&&e.send(JSON.stringify({id:r.id,error:c instanceof Error?c.message:String(c)}))}})()}}),e.on("close",()=>{if(this.agentHost.unregisterSocket(e),s==="sim"&&n){this.rememberDisconnectedSim(n),this.primarySimId===n.id&&(this.primarySimId=this.getOpenSim()?.id??null);for(let[o,r]of this.pendingCommands)r.simId===n.id&&(r.reject(new Error("sim disconnected")),this.pendingCommands.delete(o));for(let[o,r]of this.cliBySentId)r.simId===n.id&&(r.ws.readyState===m.OPEN&&r.ws.send(JSON.stringify({id:r.originalId,error:"sim disconnected before responding"})),this.cliBySentId.delete(o));this.broadcastSimAssignments(),this.broadcastSimClientStates()}else if(s==="cli"){let o=this.cliSimBySocket.delete(e);this.cliLastCommandAt.delete(e),this.cliIdentityKeyBySocket.delete(e),this.cliLabelBySocket.delete(e);for(let[r,c]of this.cliBySentId)c.ws===e&&this.cliBySentId.delete(r);o&&this.broadcastSimClientStates()}})})}afterBind(){if(process.stderr.write(`ws bridge listening on port ${this.port}
10
10
  `),this.cliIdleTimer=setInterval(()=>this.sweepIdleCliClients(),3e4),this.cliIdleTimer.unref(),this.wsHeartbeatTimer=setInterval(()=>this.sweepDeadWebSockets(),a.WS_HEARTBEAT_INTERVAL_MS),this.wsHeartbeatTimer.unref(),this.shouldWriteLockfile){try{if(T(),!K(this.buildLockfileSnapshot()))throw new Error("another sootsim daemon wrote the lockfile during startup \u2014 aborting")}catch(e){throw process.stderr.write(`ws bridge failed to claim daemon lockfile: ${String(e)}
11
- `),e}this.heartbeatTimer=setInterval(()=>{try{this.writeLockfileSnapshot()}catch{}},Re),this.heartbeatTimer.unref(),this.startRuntimeUpdater()}this.agentHost.seedOnBoot()}bootstrapping=!0;buildLockfileSnapshot(){return{schema:1,pid:process.pid,platform:process.platform,bridgePort:this.effectivePort,runtimePort:this.effectivePort,activeRuntime:this.activeRuntimeVersion,activeRuntimeDir:this.activeRuntimeDirPath,startedAt:this.startedAt,heartbeatAt:Date.now(),bootstrapping:this.bootstrapping}}writeLockfileSnapshot(){J(this.buildLockfileSnapshot())}refreshActiveRuntime(){this.activeRuntimeVersion=M(),this.activeRuntimeDirPath=F()}runServerScan(){if(this.inflightScan)return this.inflightScan;let e=this.effectivePort>0?[this.effectivePort]:[];return this.inflightScan=E({excludePorts:e,buildIconProxyUrl:t=>`/__bundle-proxy?url=${encodeURIComponent(t)}`}).then(t=>(this.scanCache=t,this.scanCacheAt=Date.now(),t)).catch(t=>{let i=t instanceof Error?t.message:String(t);return console.error("[sootsim] /__server-scan failed:",i),this.scanCache??[]}).finally(()=>{this.inflightScan=null}),this.inflightScan}handleServerScan(e){let t=s=>{e.writeHead(200,{"Content-Type":"application/json; charset=utf-8","Cache-Control":"no-store"}),e.end(JSON.stringify(s))},i=Date.now()-this.scanCacheAt;if(this.scanCache&&i<a.SCAN_FRESH_MS){t(this.scanCache);return}if(this.scanCache){t(this.scanCache),this.runServerScan().catch(()=>{});return}this.runServerScan().then(s=>t(s))}resolveRuntimeUpdateIntervalMs(){let e=Number(process.env[Le]);return Number.isFinite(e)&&e>0?Math.max(100,Math.round(e)):Be}startRuntimeUpdater(){if(!this.shouldWriteLockfile||this.runtimeUpdateTimer)return;this.runRuntimeUpdate("startup");let e=this.resolveRuntimeUpdateIntervalMs();this.runtimeUpdateTimer=setInterval(()=>{this.runRuntimeUpdate("periodic")},e),this.runtimeUpdateTimer.unref()}runRuntimeUpdate(e){return this.runtimeUpdateInFlight?this.runtimeUpdateInFlight:(this.runtimeUpdateInFlight=(async()=>{try{e==="startup"&&process.stderr.write(`sootsim: checking for runtime updates\u2026
11
+ `),e}this.heartbeatTimer=setInterval(()=>{try{this.writeLockfileSnapshot()}catch{}},Re),this.heartbeatTimer.unref(),this.startRuntimeUpdater()}this.agentHost.seedOnBoot()}bootstrapping=!0;buildLockfileSnapshot(){return{schema:1,pid:process.pid,platform:process.platform,bridgePort:this.effectivePort,runtimePort:this.effectivePort,activeRuntime:this.activeRuntimeVersion,activeRuntimeDir:this.activeRuntimeDirPath,startedAt:this.startedAt,heartbeatAt:Date.now(),bootstrapping:this.bootstrapping}}writeLockfileSnapshot(){J(this.buildLockfileSnapshot())}refreshActiveRuntime(){this.activeRuntimeVersion=M(),this.activeRuntimeDirPath=F()}runServerScan(){if(this.inflightScan)return this.inflightScan;let e=this.effectivePort>0?[this.effectivePort]:[];return this.inflightScan=E({excludePorts:e,buildIconProxyUrl:t=>`/__bundle-proxy?url=${encodeURIComponent(t)}`}).then(t=>(this.scanCache=t,this.scanCacheAt=Date.now(),t)).catch(t=>{let i=t instanceof Error?t.message:String(t);return console.error("[sootsim] /__server-scan failed:",i),this.scanCache??[]}).finally(()=>{this.inflightScan=null}),this.inflightScan}handleServerScan(e){let t=s=>{e.writeHead(200,{"Content-Type":"application/json; charset=utf-8","Cache-Control":"no-store"}),e.end(JSON.stringify(s))},i=Date.now()-this.scanCacheAt;if(this.scanCache&&i<a.SCAN_FRESH_MS){t(this.scanCache);return}if(this.scanCache){t(this.scanCache),this.runServerScan().catch(()=>{});return}this.runServerScan().then(s=>t(s))}resolveRuntimeUpdateIntervalMs(){let e=Number(process.env[Oe]);return Number.isFinite(e)&&e>0?Math.max(100,Math.round(e)):Be}startRuntimeUpdater(){if(!this.shouldWriteLockfile||this.runtimeUpdateTimer)return;this.runRuntimeUpdate("startup");let e=this.resolveRuntimeUpdateIntervalMs();this.runtimeUpdateTimer=setInterval(()=>{this.runRuntimeUpdate("periodic")},e),this.runtimeUpdateTimer.unref()}runRuntimeUpdate(e){return this.runtimeUpdateInFlight?this.runtimeUpdateInFlight:(this.runtimeUpdateInFlight=(async()=>{try{e==="startup"&&process.stderr.write(`sootsim: checking for runtime updates\u2026
12
12
  `);let t=await z();if(!t.updated||!t.latestVersion){e==="startup"&&process.stderr.write(`sootsim: runtime ${this.activeRuntimeVersion??"(none)"} is current
13
13
  `);return}let i=this.setActiveRuntime(t.latestVersion);process.stderr.write(`sootsim runtime updated to ${i.version} (${e})
14
14
  `)}catch(t){process.stderr.write(`sootsim runtime update failed (${e}): ${t instanceof Error?t.message:String(t)}
15
15
  `)}finally{if(this.runtimeUpdateInFlight=null,e==="startup"&&this.bootstrapping){if(this.bootstrapping=!1,this.shouldWriteLockfile&&this.httpServer)try{this.writeLockfileSnapshot()}catch{}process.stderr.write(`sootsim: ready
16
- `)}}})(),this.runtimeUpdateInFlight)}setActiveRuntime(e){if(W(e),this.refreshActiveRuntime(),this.shouldWriteLockfile&&this.httpServer)try{this.writeLockfileSnapshot()}catch{}let t=JSON.stringify({type:"runtime:changed",version:e,runtimeDir:this.activeRuntimeDirPath});for(let i of this.sims.values())if(i.ws.readyState===m.OPEN)try{i.ws.send(t)}catch{}return{version:e,runtimeDir:this.activeRuntimeDirPath}}getActiveRuntime(){return{version:this.activeRuntimeVersion,runtimeDir:this.activeRuntimeDirPath}}removeLockfile(){if(this.shouldWriteLockfile)try{N()}catch{}}handleHttpRequest(e,t){if(de(e.url)){ue(e,t);return}if(le(e.url)&&pe(e,t))return;let i=(e.method||"GET").toUpperCase();if(i!=="GET"&&i!=="HEAD"){t.writeHead(405,{Allow:"GET, HEAD"}),t.end("method not allowed");return}let s=new URL(e.url||"/","http://localhost");if(s.pathname==="/__bundle-proxy"){let d=s.searchParams.get("url");if(!d){t.writeHead(400,{"Content-Type":"text/plain"}),t.end("bundle-proxy: missing url query param");return}let l;try{l=new URL(d)}catch{t.writeHead(400,{"Content-Type":"text/plain"}),t.end("bundle-proxy: invalid url");return}let u=l.hostname;if(!(u==="localhost"||u==="127.0.0.1"||u==="::1"||u.endsWith(".localhost"))){t.writeHead(403,{"Content-Type":"text/plain"}),t.end("bundle-proxy: only loopback targets allowed");return}(async()=>{try{let h=await fetch(l.toString(),{redirect:"follow"}),g={},f=h.headers.get("content-type");if(f&&(g["Content-Type"]=f),g["Cache-Control"]="no-store",t.writeHead(h.status,g),!h.body){t.end();return}let b=h.body.getReader();for(;;){let{done:C,value:y}=await b.read();if(C)break;t.write(Buffer.from(y))}t.end()}catch(h){t.writeHead(502,{"Content-Type":"text/plain"}),t.end(`bundle-proxy: upstream fetch failed: ${h instanceof Error?h.message:String(h)}`)}})();return}if(s.pathname==="/__server-scan"){this.handleServerScan(t);return}if(s.pathname==="/healthz"){t.writeHead(200,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify({ok:!0,pid:process.pid,platform:process.platform,bridgePort:this.effectivePort,runtimePort:this.effectivePort,activeRuntime:this.activeRuntimeVersion,startedAt:this.startedAt,uptimeMs:this.startedAt>0?Date.now()-this.startedAt:0}));return}if(s.pathname==="/__sootsim/shared-config"){if(t.setHeader("Access-Control-Allow-Origin","*"),t.setHeader("Cache-Control","no-store"),i==="GET"||i==="HEAD"){let d="{}";try{d=JSON.stringify(_())}catch{}t.writeHead(200,{"Content-Type":"application/json"}),i==="HEAD"?t.end():t.end(d);return}t.writeHead(405,{Allow:"GET, HEAD"}),t.end("method not allowed (use the bridge over WS for writes)");return}this.refreshActiveRuntime();let n=this.activeRuntimeDirPath;if(!n){t.writeHead(503,{"Content-Type":"text/plain; charset=utf-8"}),t.end("sootsim: no active runtime installed. run `sootsim runtime install` to fetch one.");return}let o=s.pathname;if(o==="/runtime"||o==="/runtime/"?o="/":o.startsWith("/runtime/")&&(o=o.slice(8)),(o===""||o==="/")&&(o="/index.html"),o.includes("\0")){t.writeHead(400),t.end("bad request");return}if(process.platform!=="win32"&&o.includes("\\")){t.writeHead(400),t.end("bad request");return}for(let d of o.split("/"))if(d===".."){t.writeHead(403),t.end("forbidden");return}let r=S.resolve(n,"."+o),c=n.endsWith(S.sep)?n:n+S.sep;if(!r.startsWith(c)&&r!==n){t.writeHead(403),t.end("forbidden");return}v.realpath(r,(d,l)=>{let u=d?r:l,p=u.endsWith(S.sep)?u:u+S.sep;if(!d){let h=(()=>{try{let g=v.realpathSync(n);return g.endsWith(S.sep)?g:g+S.sep}catch{return c}})();if(!p.startsWith(h)&&u+S.sep!==h){t.writeHead(403),t.end("forbidden");return}}v.stat(u,(h,g)=>{if(h||!g?.isFile()){let y=S.extname(o).toLowerCase();if(y&&y!==".html"){t.writeHead(404),t.end("not found");return}if(o.startsWith("/__")||o.startsWith("/api/")||o==="/api"){t.writeHead(404,{"Content-Type":"text/plain; charset=utf-8"}),t.end("not found");return}let L=S.join(n,"index.html");v.readFile(L,(me,fe)=>{if(me){t.writeHead(404),t.end("not found");return}if(t.writeHead(200,{"Content-Type":"text/html; charset=utf-8","Cache-Control":"no-store"}),i==="HEAD"){t.end();return}t.end(he(fe))});return}let f=S.extname(u).toLowerCase(),b=_e[f]||"application/octet-stream";if(t.writeHead(200,{"Content-Type":b,"Cache-Control":"no-store"}),i==="HEAD"){t.end();return}if(f===".html"){v.readFile(u,(y,L)=>{if(y){try{t.end()}catch{}return}t.end(he(L))});return}let C=v.createReadStream(u);C.pipe(t),C.on("error",()=>{try{t.end()}catch{}})})})}sweepIdleCliClients(){let e=Date.now(),t=!1;for(let[i,s]of this.cliSimBySocket){let n=this.cliLastCommandAt.get(i)??0;if(!(e-n<a.CLI_IDLE_TIMEOUT_MS)){this.cliSimBySocket.delete(i),this.cliLastCommandAt.delete(i);for(let[o,r]of this.cliBySentId)r.ws===i&&this.cliBySentId.delete(o);try{i.close(1e3,"idle timeout")}catch{}t=!0}}t&&this.broadcastSimClientStates(),this.sweepRestorableSims(e)}sweepDeadWebSockets(){if(this.wss)for(let e of this.wss.clients){if(e.readyState!==m.OPEN)continue;if(this.wsIsAlive.get(e)===!1){try{e.terminate()}catch{}continue}this.wsIsAlive.set(e,!1);try{e.ping()}catch{try{e.terminate()}catch{}}}}listSims(){return Array.from(this.sims.values()).sort((e,t)=>e.id===this.primarySimId?-1:t.id===this.primarySimId?1:e.connectedAt-t.connectedAt).map(e=>this.describeSim(e))}async sendCommand(e){let t=await this.waitForSim(e.simId),i=this.nextCommandId++;return new Promise((s,n)=>{let o=setTimeout(()=>{this.pendingCommands.delete(i),this.broadcastSimClientStates(),n(new Error("command timed out after 30s"))},3e4);this.pendingCommands.set(i,{simId:t.id,resolve:d=>{clearTimeout(o),this.pendingCommands.delete(i),this.broadcastSimClientStates(),s(d)},reject:d=>{clearTimeout(o),this.pendingCommands.delete(i),this.broadcastSimClientStates(),n(d)}}),this.broadcastSimClientStates();let{simId:r,...c}=e;t.ws.send(JSON.stringify({...c,id:i}))})}async evaluate(e,t){return this.sendCommand({type:"evaluate",code:e,simId:t})}async focusSim(e){return this.sendCommand({type:"focus",simId:e})}async closeSim(e){return this.sendCommand({type:"close",simId:e})}async openPathInEditor(e,t,i){let s=t!=null?`:${t}${i!=null?`:${i}`:""}`:"",n=`${e}${s}`,o=(c,d)=>new Promise(l=>{try{let u=Te(c,d,{detached:!0,stdio:"ignore"}),p=!1;u.on("error",()=>{p||(p=!0,l(!1))}),u.on("spawn",()=>{p||(p=!0,u.unref(),l(!0))})}catch{l(!1)}}),r=process.env.REACT_EDITOR||process.env.EDITOR;if(r){let c=r.split(" ").filter(Boolean);if(c.length&&await o(c[0],[...c.slice(1),"-g",n]))return}await o("cursor",["-g",n])||await o("code",["-g",n])||await this.openUrl(e)}async openUrl(e,t={}){if(this.openUrlHandler){await this.openUrlHandler(e,t);return}await q(e,t)}async close(){if(this.cliIdleTimer&&(clearInterval(this.cliIdleTimer),this.cliIdleTimer=null),this.heartbeatTimer&&(clearInterval(this.heartbeatTimer),this.heartbeatTimer=null),this.wsHeartbeatTimer&&(clearInterval(this.wsHeartbeatTimer),this.wsHeartbeatTimer=null),this.runtimeUpdateTimer&&(clearInterval(this.runtimeUpdateTimer),this.runtimeUpdateTimer=null),this.shouldWriteLockfile)try{N()}catch{}this.effectivePort=0,this.startedAt=0,this.agentHost.close();for(let[i,s]of this.pendingCommands)s.reject(new Error("server closing")),this.pendingCommands.delete(i);for(let i of this.sims.values())i.ws.close();this.sims.clear(),this.primarySimId=null;let e=this.wss,t=this.httpServer;if(this.wss=null,this.httpServer=null,e)try{e.close()}catch{}if(t)try{t.close()}catch{}}describeSim(e){let t;try{t=e.ws.readyState}catch{t=m.CLOSED}let i=this.getActiveLease(e);return{id:e.id,origin:e.origin,url:e.url,title:e.title,userAgent:e.userAgent,connectedAt:e.connectedAt,lastSeenAt:e.lastSeenAt,lastActiveAt:e.lastActiveAt||void 0,isPrimary:e.id===this.primarySimId,readyState:t===m.OPEN?"open":t===m.CLOSING?"closing":"closed",attachedCliCount:this.getAttachedCliCount(e.id),lockedBy:i?i.cliLabel||i.cliIdentityKey:void 0,lockedByKind:i?i.kind:void 0,lockExpiresAt:i?i.expiresAt:void 0,userFocused:e.userFocused||void 0}}getActiveLease(e){let t=e.cliLease;return t?Date.now()>=t.expiresAt?(e.cliLease=void 0,null):t:null}tryAcquireLease(e,t,i={}){let s=this.cliIdentityKeyBySocket.get(e)??(()=>{let u=`ws-${this.nextCliFallbackId++}`;return this.cliIdentityKeyBySocket.set(e,u),u})(),n=this.cliLabelBySocket.get(e),o=Date.now(),r=this.getActiveLease(t),c=r&&r.cliIdentityKey===s,d=0;if(r&&!c&&!i.force)return{granted:!1,lease:r,lock:{by:r.cliLabel||r.cliIdentityKey,expiresInMs:Math.max(0,r.expiresAt-o)},bootedCount:0};if(r&&!c&&i.force)for(let[u,p]of this.cliSimBySocket){if(p!==t.id)continue;let h=this.cliIdentityKeyBySocket.get(u);if(h&&h!==s){this.cliSimBySocket.delete(u);try{u.close(1e3,"lease claimed by another cli")}catch{}d++}}let l={kind:"cli",cliIdentityKey:s,cliLabel:n,expiresAt:o+a.CLI_LEASE_TTL_MS};return t.cliLease=l,{granted:!0,lease:l,bootedCount:d}}updateUserFocusLease(e,t){let i=t;e.userFocused!==i&&(e.userFocused=i,this.broadcastSimClientStates())}updateUserActivity(e){let t=this.getActiveLease(e);if(t&&t.kind==="cli")return;let s=Date.now()+a.USER_ACTIVE_LEASE_TTL_MS,n=t&&t.kind==="user-active"?Math.max(t.expiresAt,s):s;e.cliLease={kind:"user-active",cliIdentityKey:"__user-active__",cliLabel:"active user",expiresAt:n},this.broadcastSimClientStates()}ensureCliIdentityKey(e){let t=this.cliIdentityKeyBySocket.get(e);if(t)return t;let i=`ws-${this.nextCliFallbackId++}`;return this.cliIdentityKeyBySocket.set(e,i),i}getOpenSim(e){if(e){let i=this.sims.get(e);return i?.ws.readyState===m.OPEN?i:null}let t=this.primarySimId!=null?this.sims.get(this.primarySimId):null;if(t?.ws.readyState===m.OPEN)return t;for(let i of this.sims.values())if(i.ws.readyState===m.OPEN)return i;return null}async waitForSim(e,t={}){let i=t.attempts??10,s=t.intervalMs??200;for(let n=0;n<i;n++){let o=this.getOpenSim(e);if(o)return o;await new Promise(r=>setTimeout(r,s))}throw new Error(e?`no sim connected with id ${e}`:"no sim connected")}shouldPromoteSim(e){let t=this.primarySimId?this.sims.get(this.primarySimId):null,i=e.origin?.includes(":5173"),s=t?.origin?.includes(":5173");return!t||t.ws.readyState!==m.OPEN||!!i||!s}broadcastSimAssignments(){for(let e of this.sims.values())e.ws.readyState===m.OPEN&&e.ws.send(JSON.stringify({type:"bridge:welcome",simId:e.id,isPrimary:e.id===this.primarySimId}))}broadcastSimClientStates(){for(let e of this.sims.values()){if(e.ws.readyState!==m.OPEN)continue;let t=this.getActiveLease(e),i={type:"bridge:client-state",attachedCliCount:this.getAttachedCliCount(e.id),activeAgentCommandCount:this.getActiveAgentCommandCount(e.id),recentActions:e.recentActions,lockedBy:t?t.cliLabel||t.cliIdentityKey:void 0,lockedByKind:t?t.kind:void 0,lockExpiresAt:t?t.expiresAt:void 0,userFocused:e.userFocused||void 0};e.ws.send(JSON.stringify(i))}}setCliSimTarget(e,t){let i=this.cliSimBySocket.get(e);i!==t&&(this.cliSimBySocket.set(e,t),this.recordSimAction(t,i?"cli switched sims":"cli connected",!1),this.broadcastSimClientStates())}recordSimAction(e,t,i=!0){let s=t?.trim();if(!s)return;let n=this.sims.get(e);if(!n)return;let o=Date.now();n.lastActiveAt=o,n.recentActions=[{label:s,at:o},...n.recentActions.filter(r=>r.label!==s)].slice(0,4),i&&this.broadcastSimClientStates()}describeForwardedCommand(e){switch(e?.type){case"evaluate":return"evaluated page state";case"screenshot":return"captured screenshot";case"tap":return"sent tap event";case"keyboard":return e?.action==="type"?"typed text":"used keyboard";case"tree":return"dumped tree";case"focus":return"focused sim";case"close":return"requested close";default:return typeof e?.type=="string"?e.type:null}}getAttachedCliCount(e){let t=new Set;for(let[i,s]of this.cliSimBySocket){if(s!==e||i.readyState!==m.OPEN)continue;let n=this.cliIdentityKeyBySocket.get(i);t.add(n??`ws-unknown-${t.size}`)}return t.size}getOtherCliIdentityCount(e,t){let i=this.cliIdentityKeyBySocket.get(e),s=new Set;for(let[n,o]of this.cliSimBySocket){if(o!==t||n.readyState!==m.OPEN)continue;let r=this.cliIdentityKeyBySocket.get(n);r&&r===i||s.add(r??`ws-unknown-${s.size}`)}return s.size}getActiveAgentCommandCount(e){let t=0;for(let i of this.pendingCommands.values())i.simId===e&&t++;return t}allocateSimId(){for(;;){let e=this.nextSimNumber.toString(16);if(this.nextSimNumber++,!this.sims.has(e)&&!this.restorableSims.has(e))return e}}tryRestoreSimId(e,t){let i=t?.trim();if(!i||i===e.id)return!1;let s=this.sims.get(i);if(s&&s!==e&&s.ws.readyState===m.OPEN)return!1;let n=this.getRestorableSimState(i),o=e.id;this.sims.delete(o),e.id=i,n&&(e.recentActions=n.recentActions.map(r=>({...r})),e.lastActiveAt=n.lastActiveAt,e.cliLease=n.cliLease?{...n.cliLease}:void 0,this.restorableSims.delete(i)),this.sims.set(e.id,e),this.primarySimId===o&&(this.primarySimId=e.id);for(let[r,c]of this.cliSimBySocket)c===o&&this.cliSimBySocket.set(r,e.id);return!0}rememberDisconnectedSim(e){let t=this.getActiveLease(e);this.restorableSims.set(e.id,{recentActions:e.recentActions.map(i=>({...i})),lastActiveAt:e.lastActiveAt,cliLease:t&&t.kind==="cli"?{...t}:void 0,expiresAt:Date.now()+a.SIM_RECONNECT_TTL_MS}),this.sims.delete(e.id)}getRestorableSimState(e){let t=this.restorableSims.get(e);return t?t.expiresAt<=Date.now()?(this.restorableSims.delete(e),null):(t.cliLease&&t.cliLease.expiresAt<=Date.now()&&(t.cliLease=void 0),t):null}sweepRestorableSims(e=Date.now()){for(let[t,i]of this.restorableSims)if(!(i.expiresAt>e)){this.restorableSims.delete(t);for(let[s,n]of this.cliSimBySocket)n===t&&this.cliSimBySocket.delete(s)}}resetServerState(){this.cliIdleTimer&&(clearInterval(this.cliIdleTimer),this.cliIdleTimer=null),this.wsHeartbeatTimer&&(clearInterval(this.wsHeartbeatTimer),this.wsHeartbeatTimer=null),this.runtimeUpdateTimer&&(clearInterval(this.runtimeUpdateTimer),this.runtimeUpdateTimer=null);let e=this.wss,t=this.httpServer;if(this.wss=null,this.httpServer=null,e)try{e.close()}catch{}if(t)try{t.close()}catch{}}};function Oe(){let a=process.env.XPC_SERVICE_NAME||"";return!!(a.includes("dev.sootsim.daemon")||a.includes("dev.sootsim.server")||process.env.INVOCATION_ID)}async function at(a,e={}){(a.includes("--help")||a.includes("-h"))&&(console.log(`
16
+ `)}}})(),this.runtimeUpdateInFlight)}setActiveRuntime(e){if(W(e),this.refreshActiveRuntime(),this.shouldWriteLockfile&&this.httpServer)try{this.writeLockfileSnapshot()}catch{}let t=JSON.stringify({type:"runtime:changed",version:e,runtimeDir:this.activeRuntimeDirPath});for(let i of this.sims.values())if(i.ws.readyState===m.OPEN)try{i.ws.send(t)}catch{}return{version:e,runtimeDir:this.activeRuntimeDirPath}}getActiveRuntime(){return{version:this.activeRuntimeVersion,runtimeDir:this.activeRuntimeDirPath}}removeLockfile(){if(this.shouldWriteLockfile)try{N()}catch{}}handleHttpRequest(e,t){if(t.setHeader("Cross-Origin-Opener-Policy","same-origin"),t.setHeader("Cross-Origin-Embedder-Policy","credentialless"),t.setHeader("Cross-Origin-Resource-Policy","cross-origin"),t.setHeader("Document-Policy","js-profiling"),de(e.url)){ue(e,t);return}if(le(e.url)&&pe(e,t))return;let i=(e.method||"GET").toUpperCase();if(i!=="GET"&&i!=="HEAD"){t.writeHead(405,{Allow:"GET, HEAD"}),t.end("method not allowed");return}let s=new URL(e.url||"/","http://localhost");if(s.pathname==="/__bundle-proxy"){let d=s.searchParams.get("url");if(!d){t.writeHead(400,{"Content-Type":"text/plain"}),t.end("bundle-proxy: missing url query param");return}let l;try{l=new URL(d)}catch{t.writeHead(400,{"Content-Type":"text/plain"}),t.end("bundle-proxy: invalid url");return}let u=l.hostname;if(!(u==="localhost"||u==="127.0.0.1"||u==="::1"||u.endsWith(".localhost"))){t.writeHead(403,{"Content-Type":"text/plain"}),t.end("bundle-proxy: only loopback targets allowed");return}(async()=>{try{let h=await fetch(l.toString(),{redirect:"follow"}),g={},f=h.headers.get("content-type");if(f&&(g["Content-Type"]=f),g["Cache-Control"]="no-store",t.writeHead(h.status,g),!h.body){t.end();return}let b=h.body.getReader();for(;;){let{done:C,value:y}=await b.read();if(C)break;t.write(Buffer.from(y))}t.end()}catch(h){t.writeHead(502,{"Content-Type":"text/plain"}),t.end(`bundle-proxy: upstream fetch failed: ${h instanceof Error?h.message:String(h)}`)}})();return}if(s.pathname==="/__server-scan"){this.handleServerScan(t);return}if(s.pathname==="/healthz"){t.writeHead(200,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify({ok:!0,pid:process.pid,platform:process.platform,bridgePort:this.effectivePort,runtimePort:this.effectivePort,activeRuntime:this.activeRuntimeVersion,startedAt:this.startedAt,uptimeMs:this.startedAt>0?Date.now()-this.startedAt:0}));return}if(s.pathname==="/__sootsim/shared-config"){if(t.setHeader("Access-Control-Allow-Origin","*"),t.setHeader("Cache-Control","no-store"),i==="GET"||i==="HEAD"){let d="{}";try{d=JSON.stringify(L())}catch{}t.writeHead(200,{"Content-Type":"application/json"}),i==="HEAD"?t.end():t.end(d);return}t.writeHead(405,{Allow:"GET, HEAD"}),t.end("method not allowed (use the bridge over WS for writes)");return}this.refreshActiveRuntime();let n=this.activeRuntimeDirPath;if(!n){t.writeHead(503,{"Content-Type":"text/plain; charset=utf-8"}),t.end("sootsim: no active runtime installed. run `sootsim runtime install` to fetch one.");return}let o=s.pathname;if(o==="/runtime"||o==="/runtime/"?o="/":o.startsWith("/runtime/")&&(o=o.slice(8)),(o===""||o==="/")&&(o="/index.html"),o.includes("\0")){t.writeHead(400),t.end("bad request");return}if(process.platform!=="win32"&&o.includes("\\")){t.writeHead(400),t.end("bad request");return}for(let d of o.split("/"))if(d===".."){t.writeHead(403),t.end("forbidden");return}let r=S.resolve(n,"."+o),c=n.endsWith(S.sep)?n:n+S.sep;if(!r.startsWith(c)&&r!==n){t.writeHead(403),t.end("forbidden");return}v.realpath(r,(d,l)=>{let u=d?r:l,p=u.endsWith(S.sep)?u:u+S.sep;if(!d){let h=(()=>{try{let g=v.realpathSync(n);return g.endsWith(S.sep)?g:g+S.sep}catch{return c}})();if(!p.startsWith(h)&&u+S.sep!==h){t.writeHead(403),t.end("forbidden");return}}v.stat(u,(h,g)=>{if(h||!g?.isFile()){let y=S.extname(o).toLowerCase();if(y&&y!==".html"){t.writeHead(404),t.end("not found");return}if(o.startsWith("/__")||o.startsWith("/api/")||o==="/api"){t.writeHead(404,{"Content-Type":"text/plain; charset=utf-8"}),t.end("not found");return}let O=S.join(n,"index.html");v.readFile(O,(me,fe)=>{if(me){t.writeHead(404),t.end("not found");return}if(t.writeHead(200,{"Content-Type":"text/html; charset=utf-8","Cache-Control":"no-store"}),i==="HEAD"){t.end();return}t.end(he(fe))});return}let f=S.extname(u).toLowerCase(),b=Le[f]||"application/octet-stream";if(t.writeHead(200,{"Content-Type":b,"Cache-Control":"no-store"}),i==="HEAD"){t.end();return}if(f===".html"){v.readFile(u,(y,O)=>{if(y){try{t.end()}catch{}return}t.end(he(O))});return}let C=v.createReadStream(u);C.pipe(t),C.on("error",()=>{try{t.end()}catch{}})})})}sweepIdleCliClients(){let e=Date.now(),t=!1;for(let[i,s]of this.cliSimBySocket){let n=this.cliLastCommandAt.get(i)??0;if(!(e-n<a.CLI_IDLE_TIMEOUT_MS)){this.cliSimBySocket.delete(i),this.cliLastCommandAt.delete(i);for(let[o,r]of this.cliBySentId)r.ws===i&&this.cliBySentId.delete(o);try{i.close(1e3,"idle timeout")}catch{}t=!0}}t&&this.broadcastSimClientStates(),this.sweepRestorableSims(e)}sweepDeadWebSockets(){if(this.wss)for(let e of this.wss.clients){if(e.readyState!==m.OPEN)continue;if(this.wsIsAlive.get(e)===!1){try{e.terminate()}catch{}continue}this.wsIsAlive.set(e,!1);try{e.ping()}catch{try{e.terminate()}catch{}}}}listSims(){return Array.from(this.sims.values()).sort((e,t)=>e.id===this.primarySimId?-1:t.id===this.primarySimId?1:e.connectedAt-t.connectedAt).map(e=>this.describeSim(e))}async sendCommand(e){let t=await this.waitForSim(e.simId),i=this.nextCommandId++;return new Promise((s,n)=>{let o=setTimeout(()=>{this.pendingCommands.delete(i),this.broadcastSimClientStates(),n(new Error("command timed out after 30s"))},3e4);this.pendingCommands.set(i,{simId:t.id,resolve:d=>{clearTimeout(o),this.pendingCommands.delete(i),this.broadcastSimClientStates(),s(d)},reject:d=>{clearTimeout(o),this.pendingCommands.delete(i),this.broadcastSimClientStates(),n(d)}}),this.broadcastSimClientStates();let{simId:r,...c}=e;t.ws.send(JSON.stringify({...c,id:i}))})}async evaluate(e,t){return this.sendCommand({type:"evaluate",code:e,simId:t})}async focusSim(e){return this.sendCommand({type:"focus",simId:e})}async closeSim(e){return this.sendCommand({type:"close",simId:e})}async openPathInEditor(e,t,i){let s=t!=null?`:${t}${i!=null?`:${i}`:""}`:"",n=`${e}${s}`,o=(c,d)=>new Promise(l=>{try{let u=Te(c,d,{detached:!0,stdio:"ignore"}),p=!1;u.on("error",()=>{p||(p=!0,l(!1))}),u.on("spawn",()=>{p||(p=!0,u.unref(),l(!0))})}catch{l(!1)}}),r=process.env.REACT_EDITOR||process.env.EDITOR;if(r){let c=r.split(" ").filter(Boolean);if(c.length&&await o(c[0],[...c.slice(1),"-g",n]))return}await o("cursor",["-g",n])||await o("code",["-g",n])||await this.openUrl(e)}async openUrl(e,t={}){if(this.openUrlHandler){await this.openUrlHandler(e,t);return}await q(e,t)}async close(){if(this.cliIdleTimer&&(clearInterval(this.cliIdleTimer),this.cliIdleTimer=null),this.heartbeatTimer&&(clearInterval(this.heartbeatTimer),this.heartbeatTimer=null),this.wsHeartbeatTimer&&(clearInterval(this.wsHeartbeatTimer),this.wsHeartbeatTimer=null),this.runtimeUpdateTimer&&(clearInterval(this.runtimeUpdateTimer),this.runtimeUpdateTimer=null),this.shouldWriteLockfile)try{N()}catch{}this.effectivePort=0,this.startedAt=0,this.agentHost.close();for(let[i,s]of this.pendingCommands)s.reject(new Error("server closing")),this.pendingCommands.delete(i);for(let i of this.sims.values())i.ws.close();this.sims.clear(),this.primarySimId=null;let e=this.wss,t=this.httpServer;if(this.wss=null,this.httpServer=null,e)try{e.close()}catch{}if(t)try{t.close()}catch{}}describeSim(e){let t;try{t=e.ws.readyState}catch{t=m.CLOSED}let i=this.getActiveLease(e);return{id:e.id,origin:e.origin,url:e.url,title:e.title,userAgent:e.userAgent,connectedAt:e.connectedAt,lastSeenAt:e.lastSeenAt,lastActiveAt:e.lastActiveAt||void 0,isPrimary:e.id===this.primarySimId,readyState:t===m.OPEN?"open":t===m.CLOSING?"closing":"closed",attachedCliCount:this.getAttachedCliCount(e.id),lockedBy:i?i.cliLabel||i.cliIdentityKey:void 0,lockedByKind:i?i.kind:void 0,lockExpiresAt:i?i.expiresAt:void 0,userFocused:e.userFocused||void 0}}getActiveLease(e){let t=e.cliLease;return t?Date.now()>=t.expiresAt?(e.cliLease=void 0,null):t:null}tryAcquireLease(e,t,i={}){let s=this.cliIdentityKeyBySocket.get(e)??(()=>{let u=`ws-${this.nextCliFallbackId++}`;return this.cliIdentityKeyBySocket.set(e,u),u})(),n=this.cliLabelBySocket.get(e),o=Date.now(),r=this.getActiveLease(t),c=r&&r.cliIdentityKey===s,d=0;if(r&&!c&&!i.force)return{granted:!1,lease:r,lock:{by:r.cliLabel||r.cliIdentityKey,expiresInMs:Math.max(0,r.expiresAt-o)},bootedCount:0};if(r&&!c&&i.force)for(let[u,p]of this.cliSimBySocket){if(p!==t.id)continue;let h=this.cliIdentityKeyBySocket.get(u);if(h&&h!==s){this.cliSimBySocket.delete(u);try{u.close(1e3,"lease claimed by another cli")}catch{}d++}}let l={kind:"cli",cliIdentityKey:s,cliLabel:n,expiresAt:o+a.CLI_LEASE_TTL_MS};return t.cliLease=l,{granted:!0,lease:l,bootedCount:d}}updateUserFocusLease(e,t){let i=t;e.userFocused!==i&&(e.userFocused=i,this.broadcastSimClientStates())}updateUserActivity(e){let t=this.getActiveLease(e);if(t&&t.kind==="cli")return;let s=Date.now()+a.USER_ACTIVE_LEASE_TTL_MS,n=t&&t.kind==="user-active"?Math.max(t.expiresAt,s):s;e.cliLease={kind:"user-active",cliIdentityKey:"__user-active__",cliLabel:"active user",expiresAt:n},this.broadcastSimClientStates()}ensureCliIdentityKey(e){let t=this.cliIdentityKeyBySocket.get(e);if(t)return t;let i=`ws-${this.nextCliFallbackId++}`;return this.cliIdentityKeyBySocket.set(e,i),i}getOpenSim(e){if(e){let i=this.sims.get(e);return i?.ws.readyState===m.OPEN?i:null}let t=this.primarySimId!=null?this.sims.get(this.primarySimId):null;if(t?.ws.readyState===m.OPEN)return t;for(let i of this.sims.values())if(i.ws.readyState===m.OPEN)return i;return null}async waitForSim(e,t={}){let i=t.attempts??10,s=t.intervalMs??200;for(let n=0;n<i;n++){let o=this.getOpenSim(e);if(o)return o;await new Promise(r=>setTimeout(r,s))}throw new Error(e?`no sim connected with id ${e}`:"no sim connected")}shouldPromoteSim(e){let t=this.primarySimId?this.sims.get(this.primarySimId):null,i=e.origin?.includes(":5173"),s=t?.origin?.includes(":5173");return!t||t.ws.readyState!==m.OPEN||!!i||!s}broadcastSimAssignments(){for(let e of this.sims.values())e.ws.readyState===m.OPEN&&e.ws.send(JSON.stringify({type:"bridge:welcome",simId:e.id,isPrimary:e.id===this.primarySimId}))}broadcastSimClientStates(){for(let e of this.sims.values()){if(e.ws.readyState!==m.OPEN)continue;let t=this.getActiveLease(e),i={type:"bridge:client-state",attachedCliCount:this.getAttachedCliCount(e.id),activeAgentCommandCount:this.getActiveAgentCommandCount(e.id),recentActions:e.recentActions,lockedBy:t?t.cliLabel||t.cliIdentityKey:void 0,lockedByKind:t?t.kind:void 0,lockExpiresAt:t?t.expiresAt:void 0,userFocused:e.userFocused||void 0};e.ws.send(JSON.stringify(i))}}setCliSimTarget(e,t){let i=this.cliSimBySocket.get(e);i!==t&&(this.cliSimBySocket.set(e,t),this.recordSimAction(t,i?"cli switched sims":"cli connected",!1),this.broadcastSimClientStates())}recordSimAction(e,t,i=!0){let s=t?.trim();if(!s)return;let n=this.sims.get(e);if(!n)return;let o=Date.now();n.lastActiveAt=o,n.recentActions=[{label:s,at:o},...n.recentActions.filter(r=>r.label!==s)].slice(0,4),i&&this.broadcastSimClientStates()}describeForwardedCommand(e){switch(e?.type){case"evaluate":return"evaluated page state";case"screenshot":return"captured screenshot";case"tap":return"sent tap event";case"keyboard":return e?.action==="type"?"typed text":"used keyboard";case"tree":return"dumped tree";case"focus":return"focused sim";case"close":return"requested close";default:return typeof e?.type=="string"?e.type:null}}getAttachedCliCount(e){let t=new Set;for(let[i,s]of this.cliSimBySocket){if(s!==e||i.readyState!==m.OPEN)continue;let n=this.cliIdentityKeyBySocket.get(i);t.add(n??`ws-unknown-${t.size}`)}return t.size}getOtherCliIdentityCount(e,t){let i=this.cliIdentityKeyBySocket.get(e),s=new Set;for(let[n,o]of this.cliSimBySocket){if(o!==t||n.readyState!==m.OPEN)continue;let r=this.cliIdentityKeyBySocket.get(n);r&&r===i||s.add(r??`ws-unknown-${s.size}`)}return s.size}getActiveAgentCommandCount(e){let t=0;for(let i of this.pendingCommands.values())i.simId===e&&t++;return t}allocateSimId(){for(;;){let e=this.nextSimNumber.toString(16);if(this.nextSimNumber++,!this.sims.has(e)&&!this.restorableSims.has(e))return e}}tryRestoreSimId(e,t){let i=t?.trim();if(!i||i===e.id)return!1;let s=this.sims.get(i);if(s&&s!==e&&s.ws.readyState===m.OPEN)return!1;let n=this.getRestorableSimState(i),o=e.id;this.sims.delete(o),e.id=i,n&&(e.recentActions=n.recentActions.map(r=>({...r})),e.lastActiveAt=n.lastActiveAt,e.cliLease=n.cliLease?{...n.cliLease}:void 0,this.restorableSims.delete(i)),this.sims.set(e.id,e),this.primarySimId===o&&(this.primarySimId=e.id);for(let[r,c]of this.cliSimBySocket)c===o&&this.cliSimBySocket.set(r,e.id);return!0}rememberDisconnectedSim(e){let t=this.getActiveLease(e);this.restorableSims.set(e.id,{recentActions:e.recentActions.map(i=>({...i})),lastActiveAt:e.lastActiveAt,cliLease:t&&t.kind==="cli"?{...t}:void 0,expiresAt:Date.now()+a.SIM_RECONNECT_TTL_MS}),this.sims.delete(e.id)}getRestorableSimState(e){let t=this.restorableSims.get(e);return t?t.expiresAt<=Date.now()?(this.restorableSims.delete(e),null):(t.cliLease&&t.cliLease.expiresAt<=Date.now()&&(t.cliLease=void 0),t):null}sweepRestorableSims(e=Date.now()){for(let[t,i]of this.restorableSims)if(!(i.expiresAt>e)){this.restorableSims.delete(t);for(let[s,n]of this.cliSimBySocket)n===t&&this.cliSimBySocket.delete(s)}}resetServerState(){this.cliIdleTimer&&(clearInterval(this.cliIdleTimer),this.cliIdleTimer=null),this.wsHeartbeatTimer&&(clearInterval(this.wsHeartbeatTimer),this.wsHeartbeatTimer=null),this.runtimeUpdateTimer&&(clearInterval(this.runtimeUpdateTimer),this.runtimeUpdateTimer=null);let e=this.wss,t=this.httpServer;if(this.wss=null,this.httpServer=null,e)try{e.close()}catch{}if(t)try{t.close()}catch{}}};function _e(){let a=process.env.XPC_SERVICE_NAME||"";return!!(a.includes("dev.sootsim.daemon")||a.includes("dev.sootsim.server")||process.env.INVOCATION_ID)}async function at(a,e={}){(a.includes("--help")||a.includes("-h"))&&(console.log(`
17
17
  sootsim server \u2014 run the sootsim bridge daemon in the foreground
18
18
 
19
19
  hosts the WS bridge that CLI commands talk to. once running, any sootsim
@@ -31,5 +31,5 @@ examples:
31
31
  sootsim server
32
32
  sootsim server --port 7668 --quiet
33
33
  `),process.exit(0));let t=a.indexOf("--port"),i=t>=0&&a[t+1]?Number(a[t+1]):e.port??7668;Number.isNaN(i)&&(console.error(` invalid --port value: ${a[t+1]}`),process.exit(1));let s=a.includes("--quiet")||a.includes("-q"),n=j();n&&$(n)&&(console.error(` a sootsim daemon is already running (pid ${n.pid}, port ${n.bridgePort})`),console.error(" stop it with 'sootsim daemon stop' first"),process.exit(1)),T();let o=new R({port:i,writeLockfile:!0}),r=await o.startAsync({silent:s}),c=Date.now(),d=h=>{s||process.stdout.write(`${h}
34
- `)},l=new Set,u=setInterval(()=>{let h=o.listSims(),g=new Set(h.map(f=>f.id));for(let f of h)if(!l.has(f.id)){let b=f.title||f.url||f.origin||"(unknown)";d(` + ${f.id} ${b}`)}for(let f of l)g.has(f)||d(` - ${f}`);l.clear();for(let f of g)l.add(f)},500);V({event:"daemon_heartbeat",properties:{bridge_port:r,under_daemon:Oe(),platform:process.platform,subsource:"daemon"}}),G(),d(`sootsim bridge listening on ws://localhost:${r} (runtime http on same port)`),r!==i&&d(` (preferred port ${i} was taken \u2014 fell back to ${r})`),d(" ready for browser, electron, or headless playwright sims to connect"),d(" (ctrl-c to stop)");let p=async h=>{clearInterval(u),d(`
34
+ `)},l=new Set,u=setInterval(()=>{let h=o.listSims(),g=new Set(h.map(f=>f.id));for(let f of h)if(!l.has(f.id)){let b=f.title||f.url||f.origin||"(unknown)";d(` + ${f.id} ${b}`)}for(let f of l)g.has(f)||d(` - ${f}`);l.clear();for(let f of g)l.add(f)},500);V({event:"daemon_heartbeat",properties:{bridge_port:r,under_daemon:_e(),platform:process.platform,subsource:"daemon"}}),G(),d(`sootsim bridge listening on ws://localhost:${r} (runtime http on same port)`),r!==i&&d(` (preferred port ${i} was taken \u2014 fell back to ${r})`),d(" ready for browser, electron, or headless playwright sims to connect"),d(" (ctrl-c to stop)");let p=async h=>{clearInterval(u),d(`
35
35
  ${h} received \u2014 shutting down after ${Math.round((Date.now()-c)/1e3)}s`);try{await o.close()}catch{}process.exit(0)};process.on("SIGINT",()=>p("SIGINT")),process.on("SIGTERM",()=>p("SIGTERM")),process.on("SIGHUP",()=>p("SIGHUP")),process.on("exit",()=>{try{o.removeLockfile()}catch{}}),await new Promise(()=>{})}export{at as runServer};
@@ -0,0 +1,2 @@
1
+ /*! sootsim v0.1.39 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
+ import{a}from"./chunk-DSDLGFWH.js";import"./chunk-OB3TB4AN.js";import"./chunk-E5RYQUFB.js";import"./chunk-VLUFTHBB.js";import"./chunk-UWRBEBML.js";import"./chunk-HWRR23AJ.js";import"./chunk-RLGCJT2D.js";import"./chunk-B3OEHV2C.js";import"./chunk-ECDPQ6S7.js";import"./chunk-WD54RD4K.js";export{a as runSetupRepo};
@@ -1,5 +1,5 @@
1
- /*! sootsim v0.1.38 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
- import"./chunk-VIEK76DX.js";import*as l from"fs";import*as i from"path";import{fileURLToPath as f}from"url";function g(){try{let s=f(import.meta.resolve("sootsim/package.json"));return i.join(i.dirname(s),"skills")}catch{let s=i.dirname(f(import.meta.url));return i.resolve(s,"../../skills")}}var m=g();function d(s){let n=s.match(/^---\n([\s\S]*?)\n---/);if(!n)return null;let e=n[1],o=e.match(/^name:\s*(.+)$/m),r=e.match(/^description:\s*(.+)$/m);return o?{name:o[1].trim(),description:r?.[1]?.trim()||""}:null}function p(){if(!l.existsSync(m))return[];let s=l.readdirSync(m).filter(e=>e.endsWith(".md")),n=[];for(let e of s){let o=l.readFileSync(i.join(m,e),"utf8"),r=d(o);r&&n.push({...r,filename:e})}return n}function u(s,n){let e=i.join(m,s.filename),o=i.join(n,s.filename);l.copyFileSync(e,o),console.log(` copied ${s.name} \u2192 ${o}`)}async function h(s){if(s.includes("--list")||s.includes("-l")||s.length===0){let t=p();if(t.length===0){console.log(" no skills found");return}console.log(`
1
+ /*! sootsim v0.1.39 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
+ import"./chunk-WD54RD4K.js";import*as l from"fs";import*as i from"path";import{fileURLToPath as f}from"url";function g(){try{let s=f(import.meta.resolve("sootsim/package.json"));return i.join(i.dirname(s),"skills")}catch{let s=i.dirname(f(import.meta.url));return i.resolve(s,"../../skills")}}var m=g();function d(s){let n=s.match(/^---\n([\s\S]*?)\n---/);if(!n)return null;let e=n[1],o=e.match(/^name:\s*(.+)$/m),r=e.match(/^description:\s*(.+)$/m);return o?{name:o[1].trim(),description:r?.[1]?.trim()||""}:null}function p(){if(!l.existsSync(m))return[];let s=l.readdirSync(m).filter(e=>e.endsWith(".md")),n=[];for(let e of s){let o=l.readFileSync(i.join(m,e),"utf8"),r=d(o);r&&n.push({...r,filename:e})}return n}function u(s,n){let e=i.join(m,s.filename),o=i.join(n,s.filename);l.copyFileSync(e,o),console.log(` copied ${s.name} \u2192 ${o}`)}async function h(s){if(s.includes("--list")||s.includes("-l")||s.length===0){let t=p();if(t.length===0){console.log(" no skills found");return}console.log(`
3
3
  available skills:
4
4
  `);for(let c of t)console.log(` ${c.name}`),console.log(` ${c.description}
5
5
  `);console.log(" usage: sootsim skills <target-dir> [skill-name...]"),console.log(" example: sootsim skills ./my-project"),console.log(` example: sootsim skills ./my-project debug perf
@@ -1,5 +1,5 @@
1
- /*! sootsim v0.1.38 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
- import{d as _}from"./chunk-G23GIRBM.js";import"./chunk-TR554AIH.js";import"./chunk-2ABGQIW7.js";import"./chunk-23YMXBQ2.js";import{E as b,F as v,i as D,y as O,z as $}from"./chunk-6UJXRT7F.js";import"./chunk-VIEK76DX.js";import{spawn as N}from"child_process";import{existsSync as F}from"fs";import{WebSocket as B}from"ws";var k=["\u280B","\u2819","\u2839","\u2838","\u283C","\u2834","\u2826","\u2827","\u2807","\u280F"];var A={reset:"\x1B[0m",dim:"\x1B[2m",red:"\x1B[31m",green:"\x1B[32m",yellow:"\x1B[33m",cyan:"\x1B[36m",bold:"\x1B[1m"};function T(){return process.stderr.isTTY===!0}function l(t,e){return T()?`${A[t]}${e}${A.reset}`:e}function L(t,e){switch(t){case"pending":return l("dim","\xB7");case"running":return l("cyan",e);case"done":return l("green","\u2713");case"fail":return l("red","\u2717");case"skip":return l("yellow","\u25CB")}}var E=class{constructor(e,s){this.stepper=e;this.data=s}start(e){this.data.state="running",e!==void 0&&(this.data.detail=e),this.stepper.render()}update(e){this.data.detail=e,this.stepper.render()}done(e){this.data.state="done",e!==void 0&&(this.data.detail=e),this.stepper.render()}fail(e){this.data.state="fail",e!==void 0&&(this.data.detail=e),this.stepper.render()}skip(e){this.data.state="skip",e!==void 0&&(this.data.detail=e),this.stepper.render()}},S=class{steps=[];bannerText="";frame=0;timer=null;lastLineCount=0;paused=!1;finished=!1;banner(e){this.bannerText=e}add(e){let s={label:e,state:"pending"};return this.steps.push(s),new E(this,s)}render(){this.paused||this.finished||(this.startSpinner(),this.draw())}pause(){this.paused||(this.paused=!0,this.stopSpinner(),this.eraseRendered(),this.lastLineCount=0)}resume(){this.paused&&(this.paused=!1,this.draw(),this.startSpinner())}finish(){this.finished||(this.finished=!0,this.stopSpinner(),this.draw())}startSpinner(){this.timer||!T()||this.steps.some(e=>e.state==="running")&&(this.timer=setInterval(()=>{this.frame=(this.frame+1)%k.length,this.draw()},80),this.timer?.unref?.())}stopSpinner(){this.timer&&(clearInterval(this.timer),this.timer=null)}draw(){if(!T()){this.drawForwardOnly();return}this.eraseRendered();let e=[];this.bannerText&&(e.push(l("bold",this.bannerText)),e.push(""));let s=k[this.frame],i=Math.max(...this.steps.map(r=>r.label.length),0);for(let r of this.steps){let n=L(r.state,s),u=r.label.padEnd(i),y=r.detail?` ${l("dim",r.detail)}`:"";e.push(` ${n} ${u}${y}`)}process.stderr.write(e.join(`
1
+ /*! sootsim v0.1.39 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
+ import{d as _}from"./chunk-C6GUAXKO.js";import"./chunk-HWRR23AJ.js";import"./chunk-RLGCJT2D.js";import"./chunk-B3OEHV2C.js";import{E as b,F as v,i as D,y as O,z as $}from"./chunk-ECDPQ6S7.js";import"./chunk-WD54RD4K.js";import{spawn as N}from"child_process";import{existsSync as F}from"fs";import{WebSocket as B}from"ws";var k=["\u280B","\u2819","\u2839","\u2838","\u283C","\u2834","\u2826","\u2827","\u2807","\u280F"];var A={reset:"\x1B[0m",dim:"\x1B[2m",red:"\x1B[31m",green:"\x1B[32m",yellow:"\x1B[33m",cyan:"\x1B[36m",bold:"\x1B[1m"};function T(){return process.stderr.isTTY===!0}function l(t,e){return T()?`${A[t]}${e}${A.reset}`:e}function L(t,e){switch(t){case"pending":return l("dim","\xB7");case"running":return l("cyan",e);case"done":return l("green","\u2713");case"fail":return l("red","\u2717");case"skip":return l("yellow","\u25CB")}}var E=class{constructor(e,s){this.stepper=e;this.data=s}start(e){this.data.state="running",e!==void 0&&(this.data.detail=e),this.stepper.render()}update(e){this.data.detail=e,this.stepper.render()}done(e){this.data.state="done",e!==void 0&&(this.data.detail=e),this.stepper.render()}fail(e){this.data.state="fail",e!==void 0&&(this.data.detail=e),this.stepper.render()}skip(e){this.data.state="skip",e!==void 0&&(this.data.detail=e),this.stepper.render()}},S=class{steps=[];bannerText="";frame=0;timer=null;lastLineCount=0;paused=!1;finished=!1;banner(e){this.bannerText=e}add(e){let s={label:e,state:"pending"};return this.steps.push(s),new E(this,s)}render(){this.paused||this.finished||(this.startSpinner(),this.draw())}pause(){this.paused||(this.paused=!0,this.stopSpinner(),this.eraseRendered(),this.lastLineCount=0)}resume(){this.paused&&(this.paused=!1,this.draw(),this.startSpinner())}finish(){this.finished||(this.finished=!0,this.stopSpinner(),this.draw())}startSpinner(){this.timer||!T()||this.steps.some(e=>e.state==="running")&&(this.timer=setInterval(()=>{this.frame=(this.frame+1)%k.length,this.draw()},80),this.timer?.unref?.())}stopSpinner(){this.timer&&(clearInterval(this.timer),this.timer=null)}draw(){if(!T()){this.drawForwardOnly();return}this.eraseRendered();let e=[];this.bannerText&&(e.push(l("bold",this.bannerText)),e.push(""));let s=k[this.frame],i=Math.max(...this.steps.map(r=>r.label.length),0);for(let r of this.steps){let n=L(r.state,s),u=r.label.padEnd(i),y=r.detail?` ${l("dim",r.detail)}`:"";e.push(` ${n} ${u}${y}`)}process.stderr.write(e.join(`
3
3
  `)+`
4
4
  `),this.lastLineCount=e.length,this.steps.some(r=>r.state==="running")||this.stopSpinner()}bannerPrinted=!1;lastEmitted=new Map;drawForwardOnly(){this.bannerText&&!this.bannerPrinted&&(process.stderr.write(this.bannerText+`
5
5
 
@@ -18,6 +18,6 @@ usage:
18
18
  options:
19
19
  --port <n> bridge port (default: ${7668})
20
20
  --no-open don't open the browser at the end
21
- `);return}O();let s=t.indexOf("--port"),i=s>=0&&t[s+1]?Number(t[s+1]):e.port??7668;Number.isNaN(i)&&(console.error(` invalid --port value: ${t[s+1]}`),process.exit(1));let r=t.includes("--no-open"),n=new S,{IS_BETA:u,BETA_TAGLINE:y}=await import("./beta-AK25X3AU.js");n.banner(u?`sootsim \u2014 ${y}`:"sootsim \u2014 starting up");let c=n.add("runtime"),d=n.add("server"),x=n.add("ready"),f=n.add("open");n.render();let g=null;try{c.start("checking\u2026");let a=$();if(a&&F(D(a)))g=a,c.done(`v${a}`);else{c.start("downloading engine (~6 MB)\u2026");let{runRuntime:h}=await import("./runtime-GFWS3QLZ.js");n.pause(),await h(["install"],{}),n.resume(),g=$(),c.done(g?`v${g}`:"installed")}}catch(a){c.fail(m(a)),n.finish(),process.exit(1)}let o=i,p="standalone";try{d.start("checking\u2026");let a=b();if(v(a)&&await P(a.bridgePort,800))o=a.bridgePort,p="daemon-existing",d.done(`already running (port ${o})`);else if(process.platform==="darwin"||process.platform==="linux"){d.start("registering background daemon\u2026");try{let{daemonInstall:h}=await import("./daemon-2Z4DAJT6.js");n.pause(),await h({port:i,force:!0}),n.resume();let R=b();o=v(R)?R.bridgePort:i,p="daemon-installed",d.done(`daemon registered (port ${o})`)}catch(h){n.resume(),d.start("daemon unavailable, starting standalone server\u2026"),o=await C(i),p="standalone",d.done(`standalone (port ${o}) \u2014 ${m(h)}`)}}else d.start("starting standalone server\u2026"),o=await C(i),p="standalone",d.done(`standalone (port ${o})`)}catch(a){d.fail(m(a)),n.finish(),process.exit(1)}try{if(x.start("waiting for bridge\u2026"),!await V(o,U))throw new Error(`bridge never came online on port ${o}`);x.done(`ws://localhost:${o}`)}catch(a){x.fail(m(a)),n.finish(),process.exit(1)}let w=`http://localhost:${o}/`;if(r){f.skip(w),n.finish();return}try{f.start("launching browser\u2026"),await _(w),f.done(w)}catch(a){f.skip(`${w} (open it manually \u2014 ${m(a)})`)}n.finish(),p==="standalone"?(console.log(`
21
+ `);return}O();let s=t.indexOf("--port"),i=s>=0&&t[s+1]?Number(t[s+1]):e.port??7668;Number.isNaN(i)&&(console.error(` invalid --port value: ${t[s+1]}`),process.exit(1));let r=t.includes("--no-open"),n=new S,{IS_BETA:u,BETA_TAGLINE:y}=await import("./beta-3SCMB3IN.js");n.banner(u?`sootsim \u2014 ${y}`:"sootsim \u2014 starting up");let c=n.add("runtime"),d=n.add("server"),x=n.add("ready"),f=n.add("open");n.render();let g=null;try{c.start("checking\u2026");let a=$();if(a&&F(D(a)))g=a,c.done(`v${a}`);else{c.start("downloading engine (~6 MB)\u2026");let{runRuntime:h}=await import("./runtime-YJPWA3XA.js");n.pause(),await h(["install"],{}),n.resume(),g=$(),c.done(g?`v${g}`:"installed")}}catch(a){c.fail(m(a)),n.finish(),process.exit(1)}let o=i,p="standalone";try{d.start("checking\u2026");let a=b();if(v(a)&&await P(a.bridgePort,800))o=a.bridgePort,p="daemon-existing",d.done(`already running (port ${o})`);else if(process.platform==="darwin"||process.platform==="linux"){d.start("registering background daemon\u2026");try{let{daemonInstall:h}=await import("./daemon-LIVCJZR3.js");n.pause(),await h({port:i,force:!0}),n.resume();let R=b();o=v(R)?R.bridgePort:i,p="daemon-installed",d.done(`daemon registered (port ${o})`)}catch(h){n.resume(),d.start("daemon unavailable, starting standalone server\u2026"),o=await C(i),p="standalone",d.done(`standalone (port ${o}) \u2014 ${m(h)}`)}}else d.start("starting standalone server\u2026"),o=await C(i),p="standalone",d.done(`standalone (port ${o})`)}catch(a){d.fail(m(a)),n.finish(),process.exit(1)}try{if(x.start("waiting for bridge\u2026"),!await V(o,U))throw new Error(`bridge never came online on port ${o}`);x.done(`ws://localhost:${o}`)}catch(a){x.fail(m(a)),n.finish(),process.exit(1)}let w=`http://localhost:${o}/`;if(r){f.skip(w),n.finish();return}try{f.start("launching browser\u2026"),await _(w),f.done(w)}catch(a){f.skip(`${w} (open it manually \u2014 ${m(a)})`)}n.finish(),p==="standalone"?(console.log(`
22
22
  running in standalone mode. sootsim will exit when this process does.
23
23
  press ctrl-c to stop.`),await new Promise(()=>{})):p==="daemon-installed"&&console.log("\n installed as a background daemon \u2014 it'll restart on login.\n manage it with `sootsim daemon status / restart / uninstall`.")}function P(t,e){return new Promise(s=>{let i=new B(`ws://127.0.0.1:${t}`,{handshakeTimeout:e}),r=!1,n=u=>{if(!r){r=!0;try{i.close()}catch{}s(u)}};i.once("open",()=>n(!0)),i.once("error",()=>n(!1)),setTimeout(()=>n(!1),e)})}async function V(t,e){let s=Date.now()+e;for(;Date.now()<s;){if(await P(t,500))return!0;await new Promise(i=>setTimeout(i,200))}return!1}async function C(t){let e=W();N(e,["server","--quiet","--port",String(t)],{detached:!0,stdio:"ignore",env:process.env}).unref();let i=Date.now()+I;for(;Date.now()<i;){let r=b();if(v(r))return r.bridgePort;await new Promise(n=>setTimeout(n,150))}if(await P(t,800))return t;throw new Error(`standalone server didn't come online within ${Math.round(I/1e3)}s`)}function W(){let t=process.argv[1];return t&&F(t)?t:"sootsim"}function m(t){return t instanceof Error?t.message:String(t)}export{Z as runStart};
@@ -0,0 +1,2 @@
1
+ /*! sootsim v0.1.39 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
+ import{a}from"./chunk-W4QHQT64.js";import"./chunk-7J4UIBA5.js";import"./chunk-WD54RD4K.js";export{a as settingsStore};
@@ -0,0 +1,2 @@
1
+ /*! sootsim v0.1.39 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
+ import{a,b}from"./chunk-VLUFTHBB.js";import"./chunk-UWRBEBML.js";import"./chunk-ECDPQ6S7.js";import"./chunk-WD54RD4K.js";export{b as flushCliTelemetry,a as trackCliEvent};
@@ -1,5 +1,5 @@
1
- /*! sootsim v0.1.38 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
- import"./chunk-VIEK76DX.js";import{spawn as m}from"child_process";import{existsSync as h,readdirSync as w}from"fs";import{resolve as u,dirname as x}from"path";import{fileURLToPath as y}from"url";var d=x(y(import.meta.resolve("sootsim-engine/package.json")));async function v(t,r){let l=t.includes("--flows"),f=t.includes("--detox"),c=t.includes("--parallel"),i=t.includes("--watch"),a=t.find((e,o)=>t[o-1]==="--reporter")||"console";if((t.includes("--help")||t.includes("-h"))&&(console.log(`
1
+ /*! sootsim v0.1.39 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
+ import"./chunk-WD54RD4K.js";import{spawn as m}from"child_process";import{existsSync as h,readdirSync as w}from"fs";import{resolve as u,dirname as x}from"path";import{fileURLToPath as y}from"url";var d=x(y(import.meta.resolve("sootsim-engine/package.json")));async function v(t,r){let l=t.includes("--flows"),f=t.includes("--detox"),c=t.includes("--parallel"),i=t.includes("--watch"),a=t.find((e,o)=>t[o-1]==="--reporter")||"console";if((t.includes("--help")||t.includes("-h"))&&(console.log(`
3
3
  sootsim test \u2014 run tests against sootsim
4
4
 
5
5
  usage:
@@ -26,6 +26,6 @@ examples:
26
26
  notes:
27
27
  playwright is best for smoke and package-local debugging
28
28
  --detox is the preferred parity lane for behavior that should match real RN
29
- `),process.exit(0)),l)await b(t,r,c,a);else if(f){let{runDetox:e}=await import("./detox-FQJWEWLT.js");await e(t.filter(o=>o!=="--detox"),r)}else await g(t,r)}async function g(t,r){let l=["playwright","test"],f=t.find((e,o)=>t[o-1]==="-t")||t.find((e,o)=>t[o-1]==="--testNamePattern")||t.find((e,o)=>t[o-1]==="--grep");f&&l.push("-g",f),t.includes("--watch")&&l.push("--ui");let c=new Set(["--flows","--detox","--parallel","--watch","--reporter","-t","--testNamePattern","--grep"]);for(let e=0;e<t.length;e++){if(c.has(t[e])){(t[e]==="-t"||t[e]==="--testNamePattern"||t[e]==="--grep"||t[e]==="--reporter")&&e++;continue}l.push(t[e])}console.log(` running: npx ${l.join(" ")}`);let i=m("npx",l,{cwd:d,stdio:"inherit",env:{...process.env}}),a=await new Promise(e=>{i.on("exit",o=>e(o||0))});process.exit(a)}async function b(t,r,l,f){let c=["flows","test/flows","e2e/flows",".maestro","maestro"],i=[];for(let o of c){let s=u(d,o);if(h(s)){let p=w(s).filter(n=>n.endsWith(".yaml")||n.endsWith(".yml"));for(let n of p)i.push(u(s,n))}}for(let o of c){let s=u(process.cwd(),o);if(!s.startsWith(d)&&h(s)){let p=w(s).filter(n=>n.endsWith(".yaml")||n.endsWith(".yml"));for(let n of p)i.push(u(s,n))}}i.length===0&&(console.log(" no flow files found in flows/, test/flows/, or e2e/flows/"),process.exit(0)),console.log(` found ${i.length} flow(s)`);let a=0,e=0;for(let o of i)try{let{runFlowPlayback:s}=await import("./flow-UQSRNEZD.js"),p=r.port?`http://localhost:${r.port}`:"http://localhost:5173";if(await s([o,"--url",p,"--new"])!==0){e++;continue}a++}catch{e++}console.log(`
29
+ `),process.exit(0)),l)await b(t,r,c,a);else if(f){let{runDetox:e}=await import("./detox-NBT5BVX3.js");await e(t.filter(o=>o!=="--detox"),r)}else await g(t,r)}async function g(t,r){let l=["playwright","test"],f=t.find((e,o)=>t[o-1]==="-t")||t.find((e,o)=>t[o-1]==="--testNamePattern")||t.find((e,o)=>t[o-1]==="--grep");f&&l.push("-g",f),t.includes("--watch")&&l.push("--ui");let c=new Set(["--flows","--detox","--parallel","--watch","--reporter","-t","--testNamePattern","--grep"]);for(let e=0;e<t.length;e++){if(c.has(t[e])){(t[e]==="-t"||t[e]==="--testNamePattern"||t[e]==="--grep"||t[e]==="--reporter")&&e++;continue}l.push(t[e])}console.log(` running: npx ${l.join(" ")}`);let i=m("npx",l,{cwd:d,stdio:"inherit",env:{...process.env}}),a=await new Promise(e=>{i.on("exit",o=>e(o||0))});process.exit(a)}async function b(t,r,l,f){let c=["flows","test/flows","e2e/flows",".maestro","maestro"],i=[];for(let o of c){let s=u(d,o);if(h(s)){let p=w(s).filter(n=>n.endsWith(".yaml")||n.endsWith(".yml"));for(let n of p)i.push(u(s,n))}}for(let o of c){let s=u(process.cwd(),o);if(!s.startsWith(d)&&h(s)){let p=w(s).filter(n=>n.endsWith(".yaml")||n.endsWith(".yml"));for(let n of p)i.push(u(s,n))}}i.length===0&&(console.log(" no flow files found in flows/, test/flows/, or e2e/flows/"),process.exit(0)),console.log(` found ${i.length} flow(s)`);let a=0,e=0;for(let o of i)try{let{runFlowPlayback:s}=await import("./flow-T6DZQWHE.js"),p=r.port?`http://localhost:${r.port}`:"http://localhost:5173";if(await s([o,"--url",p,"--new"])!==0){e++;continue}a++}catch{e++}console.log(`
30
30
  results: ${a} passed, ${e} failed (${i.length} total)
31
31
  `),process.exit(e>0?1:0)}export{v as runTest};
@@ -1,5 +1,5 @@
1
- /*! sootsim v0.1.38 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
- import{a as k}from"./chunk-HNAGYNWN.js";import{c as b,e as v,i as w}from"./chunk-TR554AIH.js";import"./chunk-2ABGQIW7.js";import"./chunk-23YMXBQ2.js";import"./chunk-6UJXRT7F.js";import"./chunk-VIEK76DX.js";async function z(e,o){if((e.includes("--help")||e.includes("-h"))&&(console.log(`
1
+ /*! sootsim v0.1.39 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
+ import{a as k}from"./chunk-B2SCT4DL.js";import{c as b,e as v,i as w}from"./chunk-HWRR23AJ.js";import"./chunk-RLGCJT2D.js";import"./chunk-B3OEHV2C.js";import"./chunk-ECDPQ6S7.js";import"./chunk-WD54RD4K.js";async function z(e,o){if((e.includes("--help")||e.includes("-h"))&&(console.log(`
3
3
  sootsim three-mode \u2014 toggle the 3d device stage
4
4
 
5
5
  usage:
@@ -1,5 +1,5 @@
1
- /*! sootsim v0.1.38 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
- import{c as m,e as d,h as s}from"./chunk-TR554AIH.js";import"./chunk-2ABGQIW7.js";import"./chunk-23YMXBQ2.js";import"./chunk-6UJXRT7F.js";import"./chunk-VIEK76DX.js";import{writeFileSync as g}from"fs";function u(){console.log(`
1
+ /*! sootsim v0.1.39 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
+ import{c as m,e as d,h as s}from"./chunk-HWRR23AJ.js";import"./chunk-RLGCJT2D.js";import"./chunk-B3OEHV2C.js";import"./chunk-ECDPQ6S7.js";import"./chunk-WD54RD4K.js";import{writeFileSync as g}from"fs";function u(){console.log(`
3
3
  sootsim timeline \u2014 control the semantic event timeline
4
4
 
5
5
  usage:
@@ -0,0 +1,2 @@
1
+ /*! sootsim v0.1.39 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
+ import{a,b,c}from"./chunk-NF65BNJR.js";import"./chunk-4YUHJ5FX.js";import"./chunk-4UI5OHEO.js";import"./chunk-VLUFTHBB.js";import"./chunk-UWRBEBML.js";import"./chunk-C6GUAXKO.js";import"./chunk-HWRR23AJ.js";import"./chunk-RLGCJT2D.js";import"./chunk-B3OEHV2C.js";import"./chunk-ECDPQ6S7.js";import"./chunk-WD54RD4K.js";export{a as resolveDefaultUploadOrigin,b as resolvePublicPreviewOrigin,c as runUpload};
@@ -1,5 +1,5 @@
1
- /*! sootsim v0.1.38 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
- import{c as w,e as b,h as d}from"./chunk-TR554AIH.js";import{b as S}from"./chunk-2ABGQIW7.js";import"./chunk-23YMXBQ2.js";import"./chunk-6UJXRT7F.js";import"./chunk-VIEK76DX.js";function T(n){let e=[];for(let t=0;t<n.length;t++)if(n[t]==="--since"&&t+1<n.length){e.push(t,t+1);let o=n[t+1].trim(),i=/^(\d+(?:\.\d+)?)(ms|s|m)?$/.exec(o);if(i){let l=Number(i[1]),u=i[2]??"ms",r=u==="s"?l*1e3:u==="m"?l*6e4:l;return{since:Date.now()-r,consumed:e}}let s=Number(o);if(Number.isFinite(s)&&s>1e12)return{since:s,consumed:e}}return{consumed:e}}function x(n){let e=[];for(let t=0;t<n.length;t++)if(n[t]==="--kinds"&&t+1<n.length)return e.push(t,t+1),{kinds:n[t+1].split(",").map(o=>o.trim()).filter(Boolean),consumed:e};return{consumed:e}}function A(n){let e=[];for(let t=0;t<n.length;t++)if(n[t]==="--limit"&&t+1<n.length){e.push(t,t+1);let o=Number(n[t+1]);if(Number.isFinite(o)&&o>0)return{limit:o,consumed:e}}return{consumed:e}}function M(n,e){if(e===null)return new Date(n).toLocaleTimeString();let t=(n-e)/1e3;return`${t>=0?"+":""}${t.toFixed(2)}s`}function E(n,e){switch(n){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 t=e.slowest;return`${e.fiberCount??"?"} fibers ${e.durationMs??"?"}ms${t?.displayName?` \xB7 ${t.displayName} ${t.durationMs??"?"}ms`:""}`}case"reanimated":case"animation":return`${e.kind??""} ${e.target??""}${e.durationMs?` ${e.durationMs}ms`:""}`}}function y(n,e){let t=M(n.t,e).padStart(8),o=n.context.padEnd(6),i=`[${n.kind}]`.padEnd(15),s="",l=n.data;return l&&typeof l=="object"&&(s=E(n.kind,l)),` ${t} ${o} ${i} ${s}`}function k(n){let e=[],t={label:"initial state",events:[],startedAt:n[0]?.t??null};e.push(t);for(let o of n)if(t.events.push(o),o.kind==="screen"||o.kind==="route"){let i=o.data,s=i?.phase;if(!s||s==="enter"||s==="appear"||s==="active"){let l=i?.name||i?.activeName||i?.path||i?.pathname||o.kind;e.length===1&&t.events.length===1?t.label=`${o.kind}: ${l}`:(t={label:`${o.kind}: ${l}`,events:[],startedAt:o.t},e.push(t))}}return e}function R(n){if(n.total===0)return"nothing recorded";let e=[],t=["error","warning","console","fetch","toast","alert","actionsheet","picker","notification","screen","route","keyboard","app-launch","shell","scroll","gesture","text-input","react-commit","animation","reanimated"],o=new Set;for(let i of t){let s=n.byKind[i];s&&(e.push(`${s} ${i}${s===1?"":"s"}`),o.add(i))}for(let[i,s]of Object.entries(n.byKind))!o.has(i)&&s&&e.push(`${s} ${i}${s===1?"":"s"}`);return e.join(" \xB7 ")}async function B(n,e){let t=w(n,{port:e.port,stripBooleanFlags:["--summary","--all","--json","--no-advance","--help","-h","--flow"],stripValueFlags:["--since","--kinds","--limit"]});(n.includes("--help")||n.includes("-h"))&&(console.log(`
1
+ /*! sootsim v0.1.39 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
+ import{c as w,e as b,h as d}from"./chunk-HWRR23AJ.js";import{b as S}from"./chunk-RLGCJT2D.js";import"./chunk-B3OEHV2C.js";import"./chunk-ECDPQ6S7.js";import"./chunk-WD54RD4K.js";function T(n){let e=[];for(let t=0;t<n.length;t++)if(n[t]==="--since"&&t+1<n.length){e.push(t,t+1);let o=n[t+1].trim(),i=/^(\d+(?:\.\d+)?)(ms|s|m)?$/.exec(o);if(i){let l=Number(i[1]),u=i[2]??"ms",r=u==="s"?l*1e3:u==="m"?l*6e4:l;return{since:Date.now()-r,consumed:e}}let s=Number(o);if(Number.isFinite(s)&&s>1e12)return{since:s,consumed:e}}return{consumed:e}}function x(n){let e=[];for(let t=0;t<n.length;t++)if(n[t]==="--kinds"&&t+1<n.length)return e.push(t,t+1),{kinds:n[t+1].split(",").map(o=>o.trim()).filter(Boolean),consumed:e};return{consumed:e}}function A(n){let e=[];for(let t=0;t<n.length;t++)if(n[t]==="--limit"&&t+1<n.length){e.push(t,t+1);let o=Number(n[t+1]);if(Number.isFinite(o)&&o>0)return{limit:o,consumed:e}}return{consumed:e}}function M(n,e){if(e===null)return new Date(n).toLocaleTimeString();let t=(n-e)/1e3;return`${t>=0?"+":""}${t.toFixed(2)}s`}function E(n,e){switch(n){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 t=e.slowest;return`${e.fiberCount??"?"} fibers ${e.durationMs??"?"}ms${t?.displayName?` \xB7 ${t.displayName} ${t.durationMs??"?"}ms`:""}`}case"reanimated":case"animation":return`${e.kind??""} ${e.target??""}${e.durationMs?` ${e.durationMs}ms`:""}`}}function y(n,e){let t=M(n.t,e).padStart(8),o=n.context.padEnd(6),i=`[${n.kind}]`.padEnd(15),s="",l=n.data;return l&&typeof l=="object"&&(s=E(n.kind,l)),` ${t} ${o} ${i} ${s}`}function k(n){let e=[],t={label:"initial state",events:[],startedAt:n[0]?.t??null};e.push(t);for(let o of n)if(t.events.push(o),o.kind==="screen"||o.kind==="route"){let i=o.data,s=i?.phase;if(!s||s==="enter"||s==="appear"||s==="active"){let l=i?.name||i?.activeName||i?.path||i?.pathname||o.kind;e.length===1&&t.events.length===1?t.label=`${o.kind}: ${l}`:(t={label:`${o.kind}: ${l}`,events:[],startedAt:o.t},e.push(t))}}return e}function R(n){if(n.total===0)return"nothing recorded";let e=[],t=["error","warning","console","fetch","toast","alert","actionsheet","picker","notification","screen","route","keyboard","app-launch","shell","scroll","gesture","text-input","react-commit","animation","reanimated"],o=new Set;for(let i of t){let s=n.byKind[i];s&&(e.push(`${s} ${i}${s===1?"":"s"}`),o.add(i))}for(let[i,s]of Object.entries(n.byKind))!o.has(i)&&s&&e.push(`${s} ${i}${s===1?"":"s"}`);return e.join(" \xB7 ")}async function B(n,e){let t=w(n,{port:e.port,stripBooleanFlags:["--summary","--all","--json","--no-advance","--help","-h","--flow"],stripValueFlags:["--since","--kinds","--limit"]});(n.includes("--help")||n.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.38 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
- import{d as n}from"./chunk-BEY2QVU5.js";import"./chunk-6UJXRT7F.js";import"./chunk-VIEK76DX.js";async function s(){let o=await n();o?.token||(console.log(" not signed in"),process.exit(1));let e=o.user;console.log(` ${e?.email||e?.name||e?.id||"signed in"}`),console.log(` origin: ${o.origin}`),console.log(` updated: ${o.updatedAt}`)}export{s as runWhoami};
1
+ /*! sootsim v0.1.39 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
+ import{d as n}from"./chunk-UWRBEBML.js";import"./chunk-ECDPQ6S7.js";import"./chunk-WD54RD4K.js";async function s(){let o=await n();o?.token||(console.log(" not signed in"),process.exit(1));let e=o.user;console.log(` ${e?.email||e?.name||e?.id||"signed in"}`),console.log(` origin: ${o.origin}`),console.log(` updated: ${o.updatedAt}`)}export{s as runWhoami};
@@ -1,4 +1,4 @@
1
- /*! sootsim v0.1.38 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! sootsim v0.1.39 | (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.38 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! sootsim v0.1.39 | (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.38 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! sootsim v0.1.39 | (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.38 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! sootsim v0.1.39 | (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.38 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! sootsim v0.1.39 | (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.38 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! sootsim v0.1.39 | (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.38 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! sootsim v0.1.39 | (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.38 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! sootsim v0.1.39 | (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.38 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! sootsim v0.1.39 | (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.38 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! sootsim v0.1.39 | (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.38 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! sootsim v0.1.39 | (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.38 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! sootsim v0.1.39 | (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;
@@ -856,6 +856,7 @@ var APPS = [
856
856
  // scripts/dev-server-scanner.ts
857
857
  var execP = (0, import_util.promisify)(import_child_process.exec);
858
858
  var TIMEOUT_MS = 250;
859
+ var MANIFEST_TIMEOUT_MS = 1500;
859
860
  var TCP_GATE_MS = 120;
860
861
  function tcpPing(port, timeout = TCP_GATE_MS) {
861
862
  return new Promise((resolve2) => {
@@ -1061,7 +1062,7 @@ async function probePort(port, buildIconProxyUrl) {
1061
1062
  knownNonPatched.has(port) ? Promise.resolve(null) : httpGet(port, "/__soot/"),
1062
1063
  httpGet(port, "/status"),
1063
1064
  httpGet(port, onePath, "HEAD"),
1064
- knownOne.has(port) ? Promise.resolve(null) : httpGet(port, "/", "GET", TIMEOUT_MS, { "expo-platform": "ios" }),
1065
+ knownOne.has(port) ? Promise.resolve(null) : httpGet(port, "/", "GET", MANIFEST_TIMEOUT_MS, { "expo-platform": "ios" }),
1065
1066
  knownNonExpo.has(port) ? Promise.resolve(null) : httpGet(port, "/_expo/status")
1066
1067
  ]);
1067
1068
  if (expoRes && expoRes.statusCode === 200) {
@@ -3944,6 +3945,10 @@ var SootSimBridgeHost = class _SootSimBridgeHost {
3944
3945
  * non-upgrade routes that don't match serve index.html (SPA behavior) so
3945
3946
  * electron's webContents can navigate freely inside the runtime. */
3946
3947
  handleHttpRequest(req, res) {
3948
+ res.setHeader("Cross-Origin-Opener-Policy", "same-origin");
3949
+ res.setHeader("Cross-Origin-Embedder-Policy", "credentialless");
3950
+ res.setHeader("Cross-Origin-Resource-Policy", "cross-origin");
3951
+ res.setHeader("Document-Policy", "js-profiling");
3947
3952
  if (isFetchProxyRequestUrl(req.url)) {
3948
3953
  void handleFetchProxyRequest(req, res);
3949
3954
  return;
@@ -1,4 +1,4 @@
1
- /*! sootsim v0.1.38 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! sootsim v0.1.39 | (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.38 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! sootsim v0.1.39 | (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.38 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! sootsim v0.1.39 | (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.38 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! sootsim v0.1.39 | (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.38 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! sootsim v0.1.39 | (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.38 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! sootsim v0.1.39 | (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;
@@ -1054,7 +1054,7 @@ async function probePort(port, buildIconProxyUrl) {
1054
1054
  knownNonPatched.has(port) ? Promise.resolve(null) : httpGet(port, "/__soot/"),
1055
1055
  httpGet(port, "/status"),
1056
1056
  httpGet(port, onePath, "HEAD"),
1057
- knownOne.has(port) ? Promise.resolve(null) : httpGet(port, "/", "GET", TIMEOUT_MS, { "expo-platform": "ios" }),
1057
+ knownOne.has(port) ? Promise.resolve(null) : httpGet(port, "/", "GET", MANIFEST_TIMEOUT_MS, { "expo-platform": "ios" }),
1058
1058
  knownNonExpo.has(port) ? Promise.resolve(null) : httpGet(port, "/_expo/status")
1059
1059
  ]);
1060
1060
  if (expoRes && expoRes.statusCode === 200) {
@@ -1211,7 +1211,7 @@ async function scanDevServers(opts = {}) {
1211
1211
  }
1212
1212
  return results.filter((r) => !isSootSelfServer(r));
1213
1213
  }
1214
- var import_child_process, import_http, import_net, import_util, execP, TIMEOUT_MS, TCP_GATE_MS, FALLBACK_PORTS, cwdByPid, knownNonPatched, knownNonExpo, knownOne, portCache, NEGATIVE_CACHE_TTL_MS, WEAK_RESULT_CACHE_TTL_MS;
1214
+ var import_child_process, import_http, import_net, import_util, execP, TIMEOUT_MS, MANIFEST_TIMEOUT_MS, TCP_GATE_MS, FALLBACK_PORTS, cwdByPid, knownNonPatched, knownNonExpo, knownOne, portCache, NEGATIVE_CACHE_TTL_MS, WEAK_RESULT_CACHE_TTL_MS;
1215
1215
  var init_dev_server_scanner = __esm({
1216
1216
  "scripts/dev-server-scanner.ts"() {
1217
1217
  "use strict";
@@ -1224,6 +1224,7 @@ var init_dev_server_scanner = __esm({
1224
1224
  init_demo_app_registry();
1225
1225
  execP = (0, import_util.promisify)(import_child_process.exec);
1226
1226
  TIMEOUT_MS = 250;
1227
+ MANIFEST_TIMEOUT_MS = 1500;
1227
1228
  TCP_GATE_MS = 120;
1228
1229
  FALLBACK_PORTS = [
1229
1230
  8081,
@@ -4042,6 +4043,10 @@ var init_bridge_host = __esm({
4042
4043
  * non-upgrade routes that don't match serve index.html (SPA behavior) so
4043
4044
  * electron's webContents can navigate freely inside the runtime. */
4044
4045
  handleHttpRequest(req, res) {
4046
+ res.setHeader("Cross-Origin-Opener-Policy", "same-origin");
4047
+ res.setHeader("Cross-Origin-Embedder-Policy", "credentialless");
4048
+ res.setHeader("Cross-Origin-Resource-Policy", "cross-origin");
4049
+ res.setHeader("Document-Policy", "js-profiling");
4045
4050
  if (isFetchProxyRequestUrl(req.url)) {
4046
4051
  void handleFetchProxyRequest(req, res);
4047
4052
  return;
package/dist-lib/vite.cjs CHANGED
@@ -1,4 +1,4 @@
1
- /*! sootsim v0.1.38 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! sootsim v0.1.39 | (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.38",
3
+ "version": "0.1.39",
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",