rnxsim 0.1.338 → 0.1.340
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/cli/app-config.ts +21 -1
- package/dist-cli/bin.js +5 -5
- package/dist-cli/chunks/{agent-G3HSUEJN.js → agent-DZRALHKK.js} +2 -2
- package/dist-cli/chunks/{agent-wrapper-ZENL34KG.js → agent-wrapper-FFCII533.js} +2 -2
- package/dist-cli/chunks/{app-fonts-NTEGG7VL.js → app-fonts-P5TIE2BI.js} +2 -2
- package/dist-cli/chunks/{assert-RHXGX3N6.js → assert-L6YWZZH7.js} +2 -2
- package/dist-cli/chunks/{auth-VTG6JRJU.js → auth-2QUOSD3D.js} +2 -2
- package/dist-cli/chunks/{beta-AJV7FIZT.js → beta-DSQASQV7.js} +2 -2
- package/dist-cli/chunks/{camera-AUFHAGV5.js → camera-KONNW6GF.js} +2 -2
- package/dist-cli/chunks/{chunk-OHBAH7R5.js → chunk-2C7MJXES.js} +1 -1
- package/dist-cli/chunks/{chunk-6XWHJHRR.js → chunk-2FT3GZ2P.js} +2 -2
- package/dist-cli/chunks/{chunk-ZFVOCM7E.js → chunk-3KDMR5FE.js} +2 -2
- package/dist-cli/chunks/{chunk-NWUML3LH.js → chunk-52LBSDBQ.js} +3 -3
- package/dist-cli/chunks/{chunk-ETGM26S2.js → chunk-5JKZGU2L.js} +1 -1
- package/dist-cli/chunks/{chunk-YYJRLMSR.js → chunk-5ULMLFND.js} +1 -1
- package/dist-cli/chunks/{chunk-3KNPTXSK.js → chunk-6HQ2CUG5.js} +1 -1
- package/dist-cli/chunks/{chunk-GGDORRTI.js → chunk-7IBTDBHW.js} +2 -2
- package/dist-cli/chunks/{chunk-T47EKPO2.js → chunk-AV323BT6.js} +2 -2
- package/dist-cli/chunks/{chunk-ZERYUNU4.js → chunk-AVGWPMGX.js} +1 -1
- package/dist-cli/chunks/{chunk-G3W7FC3J.js → chunk-AZWECMXO.js} +2 -2
- package/dist-cli/chunks/{chunk-OQVGMLDW.js → chunk-BCGO3XWB.js} +2 -2
- package/dist-cli/chunks/{chunk-63H3GSZP.js → chunk-CA3D6BWR.js} +2 -2
- package/dist-cli/chunks/{chunk-Q4NOTYIM.js → chunk-CKK6IEZD.js} +1 -1
- package/dist-cli/chunks/{chunk-6WP2UV2D.js → chunk-CKKJUPAA.js} +1 -1
- package/dist-cli/chunks/{chunk-7ISR3ZYK.js → chunk-CYAEO7E3.js} +2 -2
- package/dist-cli/chunks/{chunk-BQG5LZKW.js → chunk-DB4DBTM2.js} +2 -2
- package/dist-cli/chunks/{chunk-4D345WIF.js → chunk-DEK47I44.js} +3 -3
- package/dist-cli/chunks/{chunk-OK6SVPSL.js → chunk-DMAUBOZ2.js} +1 -1
- package/dist-cli/chunks/{chunk-VYRYAB3X.js → chunk-EZ2WX6EK.js} +3 -3
- package/dist-cli/chunks/{chunk-BK7DKLML.js → chunk-F4SGYRAP.js} +1 -1
- package/dist-cli/chunks/chunk-HWIUC6SX.js +4 -0
- package/dist-cli/chunks/{chunk-UOJDJDCM.js → chunk-J2EHW26I.js} +2 -2
- package/dist-cli/chunks/{chunk-XFELRGXJ.js → chunk-JJKRVEA6.js} +1 -1
- package/dist-cli/chunks/{chunk-OVPCCCEU.js → chunk-JRJDACNV.js} +2 -2
- package/dist-cli/chunks/{chunk-BQY3EZKT.js → chunk-JX5LGYG2.js} +2 -2
- package/dist-cli/chunks/{chunk-3FI5EY2N.js → chunk-L6FANSWV.js} +1 -1
- package/dist-cli/chunks/{chunk-N4PXLKEX.js → chunk-LQIMPJRD.js} +2 -2
- package/dist-cli/chunks/{chunk-AVPACXQK.js → chunk-LXED7YNR.js} +1 -1
- package/dist-cli/chunks/{chunk-MQFPZ7KI.js → chunk-M76E72WP.js} +2 -2
- package/dist-cli/chunks/{chunk-4MTCA7VV.js → chunk-MKFOWHFO.js} +1 -1
- package/dist-cli/chunks/{chunk-6QRPJ7QO.js → chunk-MXXR5IDW.js} +3 -3
- package/dist-cli/chunks/{chunk-5QAP5T2V.js → chunk-MYTUISZ3.js} +2 -2
- package/dist-cli/chunks/{chunk-MAPLEBCD.js → chunk-NAG3Y5BF.js} +1 -1
- package/dist-cli/chunks/{chunk-HJLU4FAF.js → chunk-NZVA5ZGD.js} +1 -1
- package/dist-cli/chunks/{chunk-SVMKZXCM.js → chunk-PH37P7G2.js} +2 -2
- package/dist-cli/chunks/{chunk-FJXYAQK6.js → chunk-PYZHCZFD.js} +2 -2
- package/dist-cli/chunks/{chunk-JR4ASV7X.js → chunk-QRHLTYK7.js} +2 -2
- package/dist-cli/chunks/{chunk-Q53GTRNP.js → chunk-RYXIRFY2.js} +2 -2
- package/dist-cli/chunks/{chunk-XYABVE4V.js → chunk-TAPZRN4C.js} +1 -1
- package/dist-cli/chunks/{chunk-D27DTXJU.js → chunk-TRGIXJN4.js} +2 -2
- package/dist-cli/chunks/{chunk-ABEKWF72.js → chunk-U4ZHMDGL.js} +1 -1
- package/dist-cli/chunks/{chunk-FRX3JK7N.js → chunk-UH2S5SLV.js} +2 -2
- package/dist-cli/chunks/{chunk-2PFMT5AC.js → chunk-UKKT5KM4.js} +2 -2
- package/dist-cli/chunks/{chunk-OF2LP2DA.js → chunk-UOK37RTL.js} +1 -1
- package/dist-cli/chunks/{chunk-YUX3I7IO.js → chunk-VP7D322G.js} +1 -1
- package/dist-cli/chunks/{chunk-DU3JBQ5L.js → chunk-W34ZT5MF.js} +2 -2
- package/dist-cli/chunks/{chunk-5RB27SUB.js → chunk-WRNCAZIB.js} +2 -2
- package/dist-cli/chunks/{chunk-XDIAP767.js → chunk-WRPLAFZP.js} +2 -2
- package/dist-cli/chunks/{chunk-5RSKW7VT.js → chunk-X5C3SLYU.js} +1 -1
- package/dist-cli/chunks/{chunk-AFJL467O.js → chunk-YNS55EN5.js} +2 -2
- package/dist-cli/chunks/{chunk-WN3NNF46.js → chunk-Z7ILCEXG.js} +2 -2
- package/dist-cli/chunks/{chunk-NBA5FHEJ.js → chunk-ZEU5RFAH.js} +2 -2
- package/dist-cli/chunks/{cleanup-FQMQ47H7.js → cleanup-BPGPA6WN.js} +2 -2
- package/dist-cli/chunks/cli-version-GJ55D3JI.js +4 -0
- package/dist-cli/chunks/{compat-R5FQB2ZB.js → compat-2L5FPDKU.js} +2 -2
- package/dist-cli/chunks/{config-ZRS3QCQJ.js → config-NRXBYFB7.js} +2 -2
- package/dist-cli/chunks/{control-XTYASILQ.js → control-G5SMCB2U.js} +2 -2
- package/dist-cli/chunks/daemon-HDNSS5A3.js +4 -0
- package/dist-cli/chunks/{debug-FYSQEAS7.js → debug-CTYLINPI.js} +3 -3
- package/dist-cli/chunks/{desktop-VX3UUDUZ.js → desktop-JNYUDHX5.js} +3 -3
- package/dist-cli/chunks/{detox-BIFMEK3W.js → detox-ZWP5MUPJ.js} +2 -2
- package/dist-cli/chunks/{device-TRZDOVET.js → device-Y7ANIQJY.js} +2 -2
- package/dist-cli/chunks/{diagnose-TOIYZFHR.js → diagnose-GFPN44ER.js} +2 -2
- package/dist-cli/chunks/{disk-cleanup-QFZDBLIK.js → disk-cleanup-OUHB2MKC.js} +2 -2
- package/dist-cli/chunks/drivers-3PUAZF6B.js +4 -0
- package/dist-cli/chunks/{film-3PDSRZRE.js → film-RNPYZHQA.js} +3 -3
- package/dist-cli/chunks/flow-XQUTMOQZ.js +4 -0
- package/dist-cli/chunks/help-C7Y5IENX.js +4 -0
- package/dist-cli/chunks/{hidden-runtime-alias-OWQOMYHE.js → hidden-runtime-alias-DGMIDDY6.js} +2 -2
- package/dist-cli/chunks/{home-paths-QPFJMOU3.js → home-paths-YEFW63N5.js} +2 -2
- package/dist-cli/chunks/inspect-4NF3PPRZ.js +4 -0
- package/dist-cli/chunks/install-desktop-66LPKLQI.js +4 -0
- package/dist-cli/chunks/{login-BP6PCAAP.js → login-ASAFHSEL.js} +4 -4
- package/dist-cli/chunks/{logout-F6BR2WA3.js → logout-F3B5TUCU.js} +2 -2
- package/dist-cli/chunks/{maestro-IQTNAPMZ.js → maestro-MJD54Z7R.js} +3 -3
- package/dist-cli/chunks/{maestro-generate-E5ZM2CYW.js → maestro-generate-PQZ33V42.js} +3 -3
- package/dist-cli/chunks/{mode-2LXFTCJS.js → mode-TKOOHJNS.js} +2 -2
- package/dist-cli/chunks/{optional-demo-registry-SZOI4M4R.js → optional-demo-registry-VX3WVJXT.js} +2 -2
- package/dist-cli/chunks/{perf-EVZFEIYZ.js → perf-JRREHJB6.js} +2 -2
- package/dist-cli/chunks/{permissions-JCUAAO2E.js → permissions-RQZLGYVF.js} +2 -2
- package/dist-cli/chunks/{record-RTM7BU3G.js → record-LBNBJ6U4.js} +3 -3
- package/dist-cli/chunks/{report-issue-ITCSZI37.js → report-issue-O63Z4GXO.js} +2 -2
- package/dist-cli/chunks/reset-734HPURU.js +4 -0
- package/dist-cli/chunks/runtime-PRF4VZAB.js +4 -0
- package/dist-cli/chunks/{screenshot-command-KZWCLIE5.js → screenshot-command-OLZIGKZR.js} +3 -3
- package/dist-cli/chunks/{screenshot-layers-4ZPGWQA5.js → screenshot-layers-ZCKD62ME.js} +2 -2
- package/dist-cli/chunks/{screenshots-capture-6LP2Q7EJ.js → screenshots-capture-CJFJACD7.js} +2 -2
- package/dist-cli/chunks/serve-L6QW4B55.js +118 -0
- package/dist-cli/chunks/{setup-JS3YUIDS.js → setup-CHUHRWKS.js} +2 -2
- package/dist-cli/chunks/{skills-7JXM6WME.js → skills-J44O4CRY.js} +2 -2
- package/dist-cli/chunks/{state-VZOMFRIR.js → state-MSTCUB5E.js} +2 -2
- package/dist-cli/chunks/{storage-U5ORNYJL.js → storage-23Y5YSD3.js} +2 -2
- package/dist-cli/chunks/store-IK5DQZ2G.js +4 -0
- package/dist-cli/chunks/telemetry-SCC2A4KF.js +4 -0
- package/dist-cli/chunks/{timeline-NDQ74JBZ.js → timeline-R7VNARZ5.js} +2 -2
- package/dist-cli/chunks/{upgrade-QKR4MCC5.js → upgrade-YUASBYYN.js} +2 -2
- package/dist-cli/chunks/upload-BFCTC54P.js +4 -0
- package/dist-cli/chunks/{version-XI54TYIM.js → version-FSV3NQBN.js} +2 -2
- package/dist-cli/chunks/{web-OGA7GXQV.js → web-LZH2QIJ5.js} +2 -2
- package/dist-cli/chunks/{what-happened-BMSZA2Y4.js → what-happened-F45IZ34K.js} +2 -2
- package/dist-lib/agent-daemon-client.cjs +1 -1
- package/dist-lib/agent-events.cjs +1 -1
- package/dist-lib/agent-identity.cjs +1 -1
- package/dist-lib/agent-sessions.cjs +1 -1
- package/dist-lib/attached-projects.cjs +1 -1
- package/dist-lib/auth/shared-session.cjs +1 -1
- package/dist-lib/backend-origin.cjs +1 -1
- package/dist-lib/beta.cjs +1 -1
- package/dist-lib/beta.mjs +1 -1
- package/dist-lib/bridge-constants.cjs +1 -1
- package/dist-lib/bridge-contract.cjs +1 -1
- package/dist-lib/cli-constants.cjs +1 -1
- package/dist-lib/config.cjs +1 -1
- package/dist-lib/detox/index.cjs +1 -1
- package/dist-lib/dev-bundle-resolution.cjs +1 -1
- package/dist-lib/home-paths.cjs +1 -1
- package/dist-lib/host/bridge-host.cjs +203 -8
- package/dist-lib/host/fetch-proxy-handler.cjs +1 -1
- package/dist-lib/host/fetch-proxy-overrides.cjs +1 -1
- package/dist-lib/host/fetch-proxy-overrides.mjs +1 -1
- package/dist-lib/host/replacement-module-handler.cjs +236 -0
- package/dist-lib/host/websocket-proxy.cjs +1 -1
- package/dist-lib/index.cjs +195 -8
- package/dist-lib/jump-to-source-babel.cjs +1 -1
- package/dist-lib/menu.cjs +1 -1
- package/dist-lib/menu.mjs +1 -1
- package/dist-lib/metro-production-bundle.cjs +1 -1
- package/dist-lib/metro-production-bundle.mjs +1 -1
- package/dist-lib/metro.cjs +1 -1
- package/dist-lib/profiles.cjs +1 -1
- package/dist-lib/public-brand.cjs +1 -1
- package/dist-lib/react-native-host-modules.cjs +1 -1
- package/dist-lib/react-native-host-modules.mjs +1 -1
- package/dist-lib/render-mode.cjs +1 -1
- package/dist-lib/scripts/dev-server-scanner.cjs +1 -1
- package/dist-lib/sdk.cjs +1 -1
- package/dist-lib/sdk.mjs +1 -1
- package/dist-lib/skills.cjs +371 -155
- package/dist-lib/vite.cjs +188 -1
- package/package.json +6 -2
- package/src/host/bridge-host.ts +9 -0
- package/src/host/replacement-module-handler.ts +220 -0
- package/src/vite-plugin-one.ts +7 -0
- package/dist-cli/chunks/chunk-K2OH5YB6.js +0 -4
- package/dist-cli/chunks/cli-version-D4SIGBIX.js +0 -4
- package/dist-cli/chunks/daemon-TEADGBF4.js +0 -4
- package/dist-cli/chunks/drivers-KWT23MPE.js +0 -4
- package/dist-cli/chunks/flow-AYXLKDJR.js +0 -4
- package/dist-cli/chunks/help-47DWCNK3.js +0 -4
- package/dist-cli/chunks/inspect-HFXM4CFS.js +0 -4
- package/dist-cli/chunks/install-desktop-CVEMNOP7.js +0 -4
- package/dist-cli/chunks/reset-VJGTLBQK.js +0 -4
- package/dist-cli/chunks/runtime-VJ6MCWZ4.js +0 -4
- package/dist-cli/chunks/serve-4UUCD73E.js +0 -44
- package/dist-cli/chunks/store-LQNKXV7U.js +0 -4
- package/dist-cli/chunks/telemetry-R6WP54HP.js +0 -4
- package/dist-cli/chunks/upload-AUD6TX4C.js +0 -4
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
/*! rnx v0.1.338 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
|
|
2
|
-
import { createRequire as __sootsimCreateRequire } from 'node:module'
|
|
3
|
-
var require = __sootsimCreateRequire(import.meta.url)
|
|
4
|
-
import{b as ye,c as J,d as ve,e as V,f as be,h as we,i as P,j as Ae,k as Te,l as Ce,m as ke,q as Ie,t as C,u as Ee,v as Pe,w as Re,x as xe}from"./chunk-5RB27SUB.js";import"./chunk-MAPLEBCD.js";import{a as pe,b as he,d as me,e as L,f as fe}from"./chunk-ZFVOCM7E.js";import{e as Se}from"./chunk-SVMKZXCM.js";import"./chunk-MQFPZ7KI.js";import{d as ge}from"./chunk-GGDORRTI.js";import{g as _}from"./chunk-OVPCCCEU.js";import"./chunk-Q4NOTYIM.js";import"./chunk-ZERYUNU4.js";import{a as F,b as G,c as ae,d as ce}from"./chunk-G3W7FC3J.js";import"./chunk-2PFMT5AC.js";import{f as O}from"./chunk-BQY3EZKT.js";import{c as le,d as ue}from"./chunk-5QAP5T2V.js";import"./chunk-YUX3I7IO.js";import{A as W,B as Y,G as Z,I as x,J as $,K as Q,L as ee,M as te,O as ie,R as re,S as ne,T as se,U as j,V as oe,g as z,h as q,r as X}from"./chunk-OK6SVPSL.js";import{a as de}from"./chunk-N4PXLKEX.js";import"./chunk-OF2LP2DA.js";import"./chunk-XFELRGXJ.js";import{spawn as wt}from"child_process";import T from"fs";import{createServer as At}from"http";import b from"path";import{WebSocket as S,WebSocketServer as Tt}from"ws";import _e from"node:fs";import M from"node:path";import{spawn as qe}from"node:child_process";function Xe(a){return typeof a.text=="string"?a.text.trim():""}function Ye(a){let e=a?.trim();return e||"tm"}async function Oe(a){let e=a.sessionId.trim();if(!G(e))throw new Error(`invalid Team Machine session id: ${e||"<empty>"}`);let t=Xe(a.prompt);if(!t)throw new Error("prompt text is empty");let i=Ye(a.command),s=a.timeoutMs??15e3;await new Promise((n,c)=>{let r=qe(i,["send",e,t],{stdio:["ignore","ignore","pipe"],env:process.env}),o="",l=setTimeout(()=>{try{r.kill("SIGTERM")}catch{}c(new Error(`tm send timed out after ${Math.round(s/1e3)}s`))},s);r.stderr?.setEncoding("utf8"),r.stderr?.on("data",d=>{o.length<4e3&&(o+=String(d))}),r.on("error",d=>{clearTimeout(l),c(d)}),r.on("exit",(d,u)=>{if(clearTimeout(l),d===0){n();return}let p=o.trim();c(new Error(p||`tm send exited with ${u?`signal ${u}`:`code ${d??"unknown"}`}`))})})}var B=1,Ze=25;function Qe(){return[Number(process.env.VITE_PORT_WEB||process.env.PORT||3e3),Number(process.env.VITE_PORT_ZERO||7849),Number(process.env.VITE_PORT_R2||9500)].filter(a=>Number.isFinite(a)&&a>0)}var D=class{subscriptions=new Map;sessionsBySocket=new Map;allSockets=new Set;pendingPromptEchoes=new Map;pendingTurns=new Map;pendingSessionStates=new Map;pendingSessionPatches=new Map;sessionStatusPersistTimer=null;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 C?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 ke()}catch(e){process.stderr.write(`[sootsim-agent] seedFromDemoAppRegistry failed: ${e instanceof Error?e.message:String(e)}
|
|
5
|
-
`)}}close(){this.sessionStatusPersistTimer&&(clearTimeout(this.sessionStatusPersistTimer),this.sessionStatusPersistTimer=null),this.flushSessionStatuses();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 V();case"agent:upsert-project":return J(i.input??{});case"agent:delete-project":return we(String(i.projectId)),{ok:!0};case"agent:auto-attach-for-url":return this.autoAttachForUrl(i.input??{});case"agent:list-sessions":return Ae(i.projectId?String(i.projectId):void 0);case"agent:start-session":return this.doStartSession(i.input??{});case"agent:send-claimed-prompt":return this.sendClaimedPrompt(i);case"agent:send-prompt":{let n=String(i.sessionId),c=P(n);if(!c)throw new C("NO_SESSION",`no session: ${n}`);let r=this.normalizePromptEnvelope(i);return await Pe(n,r),this.notePromptAccepted(n,r,c.status==="working")}case"agent:end-session":this.dropSessionFanout(String(i.sessionId)),await Re(String(i.sessionId));let s=P(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 C("UNKNOWN_AGENT_MSG",`unknown agent message: ${t}`)}}async sendClaimedPrompt(e){let t=typeof e.simId=="string"?e.simId.trim():"";if(!t)throw new C("NO_SIM","agent:send-claimed-prompt requires simId");let i=this.opts.resolveCliLease?.(t)??null;if(!i||i.kind!=="cli"||i.expiresAt<=Date.now())throw new C("NO_CLAIM",`sim ${t} has no active CLI claim`);let s=F(i.cliIdentityKey);if(!s)throw new C("UNSUPPORTED_CLAIM",`sim ${t} is claimed by a CLI identity that is not promptable`);return await Oe({sessionId:s,prompt:this.normalizePromptEnvelope(e)}),{ok:!0,routed:"team-machine",sessionId:s}}async doStartSession(e){if(!ve(e.projectId))throw new C("NO_PROJECT",`no project: ${e.projectId}`);let i=await Ee(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?.()??Qe(),c=(await _({excludePorts:s})).find(d=>String(d.port)===i);if(!c||!c.cwd)return{project:null};let r=V().find(d=>d.cwd===c.cwd)??null,o=Array.from(new Set([...r?.knownBundleUrls??[],c.bundleUrl,t]));return{project:J({cwd:c.cwd,name:c.projectName??M.basename(c.cwd),preferredProvider:e.provider??r?.preferredProvider,sourceRoots:r?.sourceRoots??[c.cwd],knownBundleUrls:o,framework:r?.framework??et(c.framework),bundleId:c.bundleId??r?.bundleId})}}getTranscript(e){let t=Ie(e);return _e.existsSync(t)?_e.readFileSync(t,"utf8"):{error:"transcript not found",code:"NO_TRANSCRIPT"}}getPaths(){let e=ye();return{userDataDir:e,storeFile:M.join(e,"attached-projects.json"),sessionsDir:M.join(e,"sessions"),transcriptsDir:M.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=xe(t,c=>{let r=this.coalescePromptEcho(t,c);if(r&&(this.applySessionEvent(t,r),this.fanOutEvent(t,r)),c.type==="turn-completed"){let o=P(t);if(o)try{be(o.projectId,{usd:c.costUsd,ts:c.ts})}catch(l){process.stderr.write(`[sootsim-agent] recordTurnTelemetry failed: ${l instanceof Error?l.message:String(l)}
|
|
6
|
-
`)}}});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 c=Math.max(this.pendingTurns.get(e)??0,i?1:0)+1;this.pendingTurns.set(e,c);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:c>1,pendingTurns:c,queueDepth:Math.max(0,c-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){let i=this.pendingSessionStates.get(e)??P(e);if(!i)return;let s=Te(i,t);this.pendingSessionStates.set(e,s),this.pendingSessionPatches.set(e,{...this.pendingSessionPatches.get(e),...t}),this.broadcastSessionStatus(s),!this.sessionStatusPersistTimer&&(this.sessionStatusPersistTimer=setTimeout(()=>{this.sessionStatusPersistTimer=null,this.flushSessionStatuses()},Ze))}flushSessionStatuses(){if(this.pendingSessionPatches.size===0)return;let e=this.pendingSessionStates,t=this.pendingSessionPatches;this.pendingSessionStates=new Map,this.pendingSessionPatches=new Map;try{Ce([...t].map(([i,s])=>({id:i,patch:s})))}catch(i){for(let[s,n]of e)this.pendingSessionStates.has(s)||this.pendingSessionStates.set(s,n);for(let[s,n]of t)this.pendingSessionPatches.set(s,{...n,...this.pendingSessionPatches.get(s)});process.stderr.write(`[sootsim-agent] session status persistence failed: ${i instanceof Error?i.message:String(i)}
|
|
7
|
-
`)}}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===B)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===B)try{i.send(t)}catch{}}respond(e,t,i){if(e.readyState===B)try{e.send(JSON.stringify({id:t,result:i}))}catch{}}respondError(e,t,i,s){if(e.readyState===B)try{e.send(JSON.stringify({id:t,error:i,...s?{code:s}:{}}))}catch{}}};function et(a){return a==="expo"?"expo":a==="one"||a==="vxrn"?"one":"unknown"}import Me from"http";import Be from"https";import{finished as rt,pipeline as nt}from"stream/promises";var K="Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36",tt=[{hostSuffix:"uniswap.org",headers:{origin:"https://app.uniswap.org",referer:"https://app.uniswap.org/"},suppressBrowserUserAgent:!0}];function it(a){let e=a.toLowerCase();for(let t of tt)if(e===t.hostSuffix||e.endsWith(`.${t.hostSuffix}`))return t}function Le(a){let e=it(a.hostname);return{"accept-encoding":"identity",...e?.suppressBrowserUserAgent?{}:{"user-agent":K},...e?.headers}}var st=new Set(["host","origin","referer","user-agent","accept-encoding","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"]),ot={"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"},at=new Set(["host","origin","referer","sec-fetch-site","sec-fetch-mode","sec-fetch-dest"]);function De(a){return a.protocol!=="https:"?{}:pe(a.hostname)?{rejectUnauthorized:!1}:{}}function R(a){for(let[e,t]of Object.entries(ot))a.setHeader(e,t)}function ct(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 dt(a,e){let t={};for(let[i,s]of Object.entries(a))s&&(st.has(i.toLowerCase())||(t[i]=Array.isArray(s)?s.join(", "):s));return Object.assign(t,e?Le(e):{"user-agent":K}),t}function lt(a,e){let t={};for(let[i,s]of Object.entries(a))s&&(at.has(i.toLowerCase())||(t[i]=s));return t.host=e.host,t.origin=e.origin,t.referer=`${e.origin}/`,t}function Ne(a){return a?.startsWith("/__fetch-proxy?")||a?.startsWith("/__proxy?")||!1}function He(a){return a?!!(a.startsWith("/__app-api?")||a.startsWith("/__app-api/")):!1}async function Ue(a,e){if(a.method==="OPTIONS"){R(e),e.writeHead(204),e.end();return}let i=new URLSearchParams((a.url||"").split("?")[1]||"").get("url");if(!i){R(e),e.writeHead(400,{"Content-Type":"text/plain"}),e.end("missing url param");return}let s;try{s=new URL(i)}catch{R(e),e.writeHead(400,{"Content-Type":"text/plain"}),e.end("invalid url param");return}let n;if(a.method!=="GET"&&a.method!=="HEAD"){let o=[];for await(let l of a)o.push(Buffer.isBuffer(l)?l:Buffer.from(l));o.length>0&&(n=Buffer.concat(o))}let c=a.method||"GET",r=async(o,l,d,u)=>{let p=o.protocol==="https:"?Be:Me,h=dt(a.headers,o);o.origin!==s.origin&&(delete h.authorization,delete h["proxy-authorization"]),l==="GET"||l==="HEAD"?(delete h["content-length"],delete h["content-type"]):d&&(h["content-length"]=String(d.byteLength));let f=await new Promise((w,A)=>{let y=p.request({hostname:o.hostname,port:o.port||(o.protocol==="https:"?443:80),path:o.pathname+o.search,method:l,headers:h,...De(o)},w),I=()=>y.destroy(new Error("fetch proxy client disconnected"));a.once("aborted",I),y.once("close",()=>a.off("aborted",I)),y.once("error",A),d===void 0?y.end():y.end(d)}),m=f.statusCode??502,g=f.headers.location;if(g&&(m===301||m===302||m===303||m===307||m===308)){if(u>=10)throw f.destroy(),new Error("too many redirects");let w=(m===301||m===302)&&l==="POST"||m===303&&l!=="GET"&&l!=="HEAD",A=new URL(g,o);f.resume(),await rt(f),await r(A,w?"GET":l,w?void 0:d,u+1);return}for(let[w,A]of Object.entries(f.headers)){let y=w.toLowerCase();A===void 0||y==="set-cookie"||y==="connection"||y==="keep-alive"||y==="proxy-authenticate"||y==="proxy-authorization"||y==="te"||y==="trailer"||y==="transfer-encoding"||y==="upgrade"||y.startsWith("access-control-")||e.setHeader(w,A)}R(e);let v=f.headers["set-cookie"]??[];v.length>0&&e.setHeader("x-sootsim-set-cookie",(Array.isArray(v)?v:[v]).join(", ")),e.statusCode=m,await nt(f,e)};try{await r(s,c,n,0)}catch(o){if(e.headersSent){e.destroy(o instanceof Error?o:new Error(String(o)));return}R(e),e.writeHead(502,{"Content-Type":"text/plain"}),e.end(`fetch proxy error: ${ct(s.href,o)}`)}}function Fe(a,e){let t=a.url||"",i="",s="";if(t.startsWith("/__app-api?")){let l=new URL(t,"http://sootsim.local");i=l.searchParams.get("path")||"",s=l.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 c=n.protocol==="https:"?Be:Me,r=lt(a.headers,n),o=c.request({hostname:n.hostname,port:n.port||(n.protocol==="https:"?443:80),path:n.pathname+n.search,method:a.method,headers:r,...De(n)},l=>{let d=Object.keys(l.headers).filter(u=>{let p=u.toLowerCase();return!p.startsWith("access-control-")&&p!=="set-cookie"}).join(", ");e.writeHead(l.statusCode??502,{...l.headers,"access-control-allow-origin":a.headers.origin||"*","access-control-allow-credentials":"true","access-control-expose-headers":d}),l.pipe(e)});return o.on("error",l=>{e.statusCode=502,e.end(`app proxy error: ${l.message}`)}),a.pipe(o),!0}import{WebSocket as k,WebSocketServer as ut}from"ws";var pt="/__websocket-proxy",ht=new Set(["host","connection","upgrade","transfer-encoding","content-length","sec-websocket-accept","sec-websocket-extensions","sec-websocket-key","sec-websocket-protocol","sec-websocket-version"]);function E(a,e,t){try{a.write(`HTTP/1.1 ${e} ${t}\r
|
|
8
|
-
Connection: close\r
|
|
9
|
-
Content-Type: text/plain\r
|
|
10
|
-
Content-Length: ${t.length}\r
|
|
11
|
-
\r
|
|
12
|
-
${t}`)}catch{}a.destroy()}function mt(a){let e=a.headers.origin,t=a.headers.host;if(!e||!t)return!1;try{return new URL(e).host===t}catch{return!1}}function ft(a){if(!a)return{};let e=a.replace(/-/g,"+").replace(/_/g,"/"),t=e+"=".repeat((4-e.length%4)%4),i=JSON.parse(Buffer.from(t,"base64").toString("utf8"));if(!i||typeof i!="object"||Array.isArray(i))return{};let s={};for(let[n,c]of Object.entries(i))c!=null&&(ht.has(n.toLowerCase())||(s[n]=Array.isArray(c)?c.join(", "):String(c)));return s}function gt(a){let e=new URL(a.href);return e.protocol=a.protocol==="wss:"?"https:":"http:",e.origin}function St(a){let e=a.headers["sec-websocket-protocol"];return(Array.isArray(e)?e.join(","):e||"").split(",").map(i=>i.trim()).filter(Boolean)}function N(a,e,t){if(!(a.readyState===k.CLOSED||a.readyState===k.CLOSING))try{a.close(e,t)}catch{a.terminate()}}function yt(a,e){let t=!1,i=(s,n,c,r)=>{t||(t=!0,N(n,c,r.toString()),s.readyState===k.OPEN&&N(s,c,r.toString()))};a.on("message",(s,n)=>{e.readyState===k.OPEN&&e.send(s,{binary:n})}),e.on("message",(s,n)=>{a.readyState===k.OPEN&&a.send(s,{binary:n})}),a.on("close",(s,n)=>i(a,e,s,n)),e.on("close",(s,n)=>i(e,a,s,n)),a.on("error",()=>N(e,1011,"proxy client error")),e.on("error",()=>N(a,1011,"upstream websocket error"))}function vt(a,e,t,i){let s={...t},n=Object.keys(s).filter(c=>c.toLowerCase()==="origin");if(i&&n.length===0)s.origin=gt(a);else if(!i)for(let c of n)delete s[c];return Object.keys(s).length===0?new k(a.href,e):new k(a.href,e,{headers:s})}function bt(a){if(!a)return!1;try{return new URL(a,"http://localhost").pathname===pt}catch{return!1}}function We(a,e,t,i=!0){if(!bt(a.url))return!1;if(!mt(a))return E(e,403,"forbidden websocket proxy origin"),!0;let s,n;try{let l=new URL(a.url||"/","http://localhost"),d=l.searchParams.get("url");if(!d)return E(e,400,"missing websocket proxy url"),!0;if(s=new URL(d),s.protocol!=="ws:"&&s.protocol!=="wss:")return E(e,400,"invalid websocket proxy protocol"),!0;n=ft(l.searchParams.get("headers"))}catch{return E(e,400,"invalid websocket proxy request"),!0}let c=St(a),r=vt(s,c,n,i),o=!1;return e.once("close",()=>{o||r.terminate()}),r.once("open",()=>{if(o)return;o=!0;let l=r.protocol;new ut({noServer:!0,clientTracking:!1,handleProtocols(u){return l||u.values().next().value||!1}}).handleUpgrade(a,e,t,u=>{yt(u,r)})}),r.once("error",()=>{o||(o=!0,E(e,502,"upstream websocket error"))}),r.once("close",()=>{o||(o=!0,E(e,502,"upstream websocket closed"))}),!0}var Ct="require-corp",kt=new Set(["tap","keyboard","longPress","perform","reset","camera"]),It=2e3,Et=1e3;function Pt(a){return!a||typeof a.type!="string"?!1:a.acquireLock===!0?!0:a.readOnly===!0?!1:kt.has(a.type)}var $e=5e3,Rt=3600*1e3,xt="SOOTSIM_RUNTIME_UPDATE_INTERVAL_MS",je={".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",".mp4":"video/mp4",".m4v":"video/mp4",".webm":"video/webm",".mov":"video/quicktime"},Je="/__camera-fixtures/",Ot=/^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/;function Ve(a,e,t){let i;try{let o=W();i=JSON.stringify(o)}catch{i="{}"}let s=e>0?`window.__sootsimBridgePort=${e};`:"",n=t?`window.__sootsimContrastOrigin=${JSON.stringify(t)};`:"",c=`<script>window.__sootsimSharedConfig=${i};`+s+n+`window.__sootsimCliVersion=${JSON.stringify(de())};</script>`,r=a.toString("utf8");return r.includes("<head>")?r.replace("<head>",`<head>${c}`):r.includes("</head>")?r.replace("</head>",c+"</head>"):r.includes("</body>")?r.replace("</body>",c+"</body>"):c+r}function Ke(a){typeof a=="object"&&a!==null&&"unref"in a&&a.unref()}var H=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;static SIM_IDLE_REAP_TTL_MS=30*6e4;static AUTOMATION_SIM_IDLE_REAP_TTL_MS=10*6e4;static MAX_CONCURRENT_AUTOMATION_SIMS=6;static AUTOMATION_SIM_ACTIVE_GRACE_MS=6e4;preferredPort;portFallbackCount;simIdleReapTtlMs;automationSimIdleReapTtlMs;maxConcurrentAutomationSims;automationSimActiveGraceMs;shouldWriteLockfile;shouldWriteDevLockfile;getShellPort;contrastOrigin=null;effectivePort=0;startedAt=0;heartbeatTimer=null;devHeartbeatTimer=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.shouldWriteDevLockfile=e.writeDevLockfile===!0,this.getShellPort=e.getShellPort??null,this.portFallbackCount=Math.max(1,e.portFallbackCount??10),this.openUrlHandler=e.openUrl,this.agentHost=new D({getExcludePorts:e.agentScanExcludes,resolveCliLease:t=>{let i=this.sims.get(t),s=i?this.getActiveLease(i):null;return s?{kind:s.kind,cliIdentityKey:s.cliIdentityKey,expiresAt:s.expiresAt}:null}}),this.contrastOrigin=e.contrastOrigin?.replace(/\/$/,"")||null,this.simIdleReapTtlMs=e.simIdleReapTtlMs??a.SIM_IDLE_REAP_TTL_MS,this.automationSimIdleReapTtlMs=e.automationSimIdleReapTtlMs??a.AUTOMATION_SIM_IDLE_REAP_TTL_MS,this.maxConcurrentAutomationSims=e.maxConcurrentAutomationSims??a.MAX_CONCURRENT_AUTOMATION_SIMS,this.automationSimActiveGraceMs=e.automationSimActiveGraceMs??a.AUTOMATION_SIM_ACTIVE_GRACE_MS}getAgentHost(){return this.agentHost}reapIdleSimsForTest(e=Date.now()){this.reapIdleSims(e)}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)
|
|
13
|
-
`),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}
|
|
14
|
-
`)}}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=At((o,l)=>this.handleHttpRequest(o,l)),c=!1,r=o=>{if(!c){c=!0;try{n.close()}catch{}this.httpServer=null,this.wss=null,s(o)}};n.once("error",r),n.listen(e,"127.0.0.1",()=>{c||(c=!0,n.removeListener("error",r),n.on("error",o=>{process.stderr.write(`ws bridge http error: ${String(o)}
|
|
15
|
-
`)}),this.httpServer=n,this.wss=new Tt({noServer:!0}),this.wireWebSocketServer(),n.on("upgrade",(o,l,d)=>{We(o,l,d)||this.wss?.handleUpgrade(o,l,d,u=>{this.wss?.emit("connection",u,o)})}),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.writeConnectedRuntimeSnapshot(),this.shouldPromoteSim(n)&&(this.primarySimId=n.id),this.broadcastSimAssignments(),this.broadcastSimClientStates();else{let c=`ws-${this.nextCliFallbackId++}`;this.cliIdentityKeyBySocket.set(e,c)}e.on("message",c=>{let r;try{r=JSON.parse(c.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 o=O.listInstalled(),l=this.getActiveRuntime(),d={type:"runtime:list:ok",id:r.id,installed:o,active:l.version,activeRuntimeDir:l.runtimeDir};try{e.send(JSON.stringify(d))}catch{}return}if(r.type==="runtime:use"){let o=typeof r.version=="string"?r.version:"";if(!O.listInstalled().includes(o)){try{e.send(JSON.stringify({type:"runtime:use:error",id:r.id,error:`runtime ${o||"(missing)"} is not installed`}))}catch{}return}let d=this.setActiveRuntime(o);try{e.send(JSON.stringify({type:"runtime:use:ok",id:r.id,version:d.version,runtimeDir:d.runtimeDir}))}catch{}return}if(r.type==="runtime:get"){let o=this.getActiveRuntime();try{e.send(JSON.stringify({type:"runtime:get:ok",id:r.id,active:o.version,activeRuntimeDir:o.runtimeDir}))}catch{}return}if(s==="sim"&&r.type==="bridge:hello"&&n&&!n.url){let o=n.id;this.sims.delete(o),this.primarySimId===o&&(this.primarySimId=this.getOpenSim()?.id??null),n=null,s="cli",this.cliIdentityKeyBySocket.set(e,`ws-${this.nextCliFallbackId++}`),this.writeConnectedRuntimeSnapshot(),this.broadcastSimAssignments(),this.broadcastSimClientStates()}if(s==="sim"){if(n&&(n.lastSeenAt=Date.now()),r.type==="bridge:register"&&n){let d=r,u=this.tryRestoreSimId(n,d.simId);n.url=d.url,n.title=d.title,n.userAgent=d.userAgent,this.writeConnectedRuntimeSnapshot(),typeof d.kind=="string"&&d.kind.trim()&&(n.kind=d.kind.trim()),d.meta&&typeof d.meta=="object"&&(n.meta=d.meta);let p=this.primarySimId!==n.id&&this.shouldPromoteSim(n);p&&(this.primarySimId=n.id),(u||p)&&(this.broadcastSimAssignments(),this.broadcastSimClientStates());return}if(r.type==="bridge:user-focus-state"&&n){let d=r;this.updateUserFocusLease(n,d);return}if(r.type==="bridge:user-interact"&&n){this.updateUserActivity(n);return}if(r.type==="bridge:write-shared-config"){if(!r.patch||typeof r.patch!="object"||Array.isArray(r.patch))return;let d=Object.fromEntries(Object.entries(r.patch));try{this.writeAndBroadcastSharedConfig(d)}catch(u){process.stderr.write(`sootsim: bridge:write-shared-config failed: ${u instanceof Error?u.message:String(u)}
|
|
16
|
-
`);return}return}if(r.type==="bridge:open-path"){let d=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;d&&this.openPathInEditor(d,u,p);return}if(r.type==="bridge:boot-clients"&&n){let d=[];for(let[p,h]of this.cliSimBySocket)h===n.id&&d.push(p);for(let p of d){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(`rnx booted ${d.length} cli client(s)${u?" (overrode prior lease)":""}; held sim for user [${n.id}]
|
|
17
|
-
`),this.recordSimAction(n.id,"sim booted cli clients"),this.broadcastSimClientStates();return}let o=this.pendingCommands.get(r.id);if(o){this.pendingCommands.delete(r.id),r.error?o.reject(new Error(r.error)):o.resolve(r.result);return}let l=this.cliBySentId.get(r.id);if(l&&(this.cliBySentId.delete(r.id),l.ws.readyState===S.OPEN)){let d=this.getOtherCliIdentityCount(l.ws,l.simId),u=d>0?{...r,id:l.originalId,_otherCliCount:d}:{...r,id:l.originalId};l.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,f]of this.cliBySentId)f.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===S.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===S.OPEN&&e.send(JSON.stringify({id:r.id,result:this.listSims()}));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===S.OPEN&&e.send(JSON.stringify({id:r.id,error:`sim ${p.id} is locked by another cli`,_locked: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===S.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 o=await this.waitForSim(r.simId);if(Pt(r)){let p=this.tryAcquireLease(e,o);if(!p.granted){e.readyState===S.OPEN&&e.send(JSON.stringify({id:r.id,error:`sim ${o.id} is locked by another cli \u2014 use \`rnx claim ${o.id} --force\` or \`rnx open --new\``,_locked:p.lock}));return}}else this.ensureCliIdentityKey(e);this.setCliSimTarget(e,o.id),this.recordSimAction(o.id,this.describeForwardedCommand(r));let l=this.nextCommandId++;this.cliBySentId.set(l,{simId:o.id,ws:e,originalId:r.id});let{simId:d,...u}=r;if(o.ws.send(JSON.stringify({...u,id:l})),u.type==="close"){this.cliBySentId.delete(l),e.readyState===S.OPEN&&e.send(JSON.stringify({id:r.id,result:{requested:!0,simId:o.id}}));let p=o.ws,h=setTimeout(()=>{this.closeSimSocketFromHost(p)},It);Ke(h)}}catch(o){e.readyState===S.OPEN&&e.send(JSON.stringify({id:r.id,error:o instanceof Error?o.message:String(o)}))}})()}}),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[c,r]of this.pendingCommands)r.simId===n.id&&(r.reject(new Error("sim disconnected")),this.pendingCommands.delete(c));for(let[c,r]of this.cliBySentId)r.simId===n.id&&(r.ws.readyState===S.OPEN&&r.ws.send(JSON.stringify({id:r.originalId,error:"sim disconnected before responding"})),this.cliBySentId.delete(c));this.broadcastSimAssignments(),this.broadcastSimClientStates()}else if(s==="cli"){let c=this.cliSimBySocket.delete(e);this.cliLastCommandAt.delete(e),this.cliIdentityKeyBySocket.delete(e),this.cliLabelBySocket.delete(e);for(let[r,o]of this.cliBySentId)o.ws===e&&this.cliBySentId.delete(r);c&&this.broadcastSimClientStates()}})})}afterBind(){if(process.stderr.write(`ws bridge listening on port ${this.port}
|
|
18
|
-
`),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(x(),!se(this.buildLockfileSnapshot()))throw new Error("another rnx daemon wrote the lockfile during startup \u2014 aborting")}catch(e){throw process.stderr.write(`ws bridge failed to claim daemon lockfile: ${String(e)}
|
|
19
|
-
`),e}this.heartbeatTimer=setInterval(()=>{try{this.writeLockfileSnapshot()}catch{}},$e),this.heartbeatTimer.unref(),this.startRuntimeUpdater()}if(this.shouldWriteDevLockfile){try{this.writeDevLockfileSnapshot()}catch(e){process.stderr.write(`ws bridge failed to write dev bridge lockfile: ${String(e)}
|
|
20
|
-
`)}this.devHeartbeatTimer=setInterval(()=>{try{this.writeDevLockfileSnapshot()}catch{}},$e),this.devHeartbeatTimer.unref()}this.agentHost.seedOnBoot()}bootstrapping=!0;connectedRuntimeVersions(){let e=new Set;for(let t of this.sims.values())try{let i=new URL(t.url||t.origin||"http://localhost"),s=L(i.hostname);s&&e.add(s)}catch{}return[...e].sort()}buildLockfileSnapshot(){return{schema:1,pid:process.pid,platform:process.platform,bridgePort:this.effectivePort,runtimePort:this.effectivePort,activeRuntime:this.activeRuntimeVersion,activeRuntimeDir:this.activeRuntimeDirPath,servedRuntimes:this.connectedRuntimeVersions(),startedAt:this.startedAt,heartbeatAt:Date.now(),bootstrapping:this.bootstrapping}}buildDevLockfileSnapshot(){let e=this.getShellPort?.()??null;return{schema:1,pid:process.pid,platform:process.platform,bridgePort:this.effectivePort,runtimePort:this.effectivePort,...e&&e>0?{shellPort:e}:{},cwd:process.cwd(),startedAt:this.startedAt,heartbeatAt:Date.now(),source:"vite-dev",servedRuntimes:this.connectedRuntimeVersions()}}writeLockfileSnapshot(){re(this.buildLockfileSnapshot())}writeDevLockfileSnapshot(){ne(this.buildDevLockfileSnapshot())}writeConnectedRuntimeSnapshot(){if(this.shouldWriteLockfile&&this.httpServer)try{this.writeLockfileSnapshot()}catch{}if(this.shouldWriteDevLockfile&&this.httpServer)try{this.writeDevLockfileSnapshot()}catch{}}refreshActiveRuntime(){this.activeRuntimeVersion=$(),this.activeRuntimeDirPath=he()??ee()}runServerScan(){if(this.inflightScan)return this.inflightScan;let e=this.effectivePort>0?[this.effectivePort]:[];return this.inflightScan=_({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("[rnx] /__server-scan failed:",i),this.scanCache??[]}).finally(()=>{this.inflightScan=null}),this.inflightScan}handleCameraFixture(e,t,i){let s=(t.method||"GET").toUpperCase(),n={"Access-Control-Allow-Origin":"*","Cache-Control":"no-store"};if(s==="OPTIONS"){i.writeHead(204,{...n,"Access-Control-Allow-Methods":"GET, HEAD, OPTIONS","Access-Control-Allow-Headers":"range"}),i.end();return}if(s!=="GET"&&s!=="HEAD"){i.writeHead(405,n),i.end();return}if(!Ot.test(e)){i.writeHead(400,{...n,"Content-Type":"text/plain; charset=utf-8"}),i.end("bad fixture name");return}let c=X(),r=b.join(c,e),o;try{o=T.lstatSync(r)}catch{i.writeHead(404,{...n,"Content-Type":"text/plain; charset=utf-8"}),i.end("not found");return}if(!o.isFile()){i.writeHead(403,{...n,"Content-Type":"text/plain; charset=utf-8"}),i.end("forbidden");return}let l=je[b.extname(r).toLowerCase()]||"application/octet-stream",d=o.size,u=/^bytes=(\d*)-(\d*)$/.exec(t.headers.range||"");if(u){let[,p,h]=u,f=p?Number(p):0,m=h?Math.min(Number(h),d-1):d-1;if(!Number.isFinite(f)||f>m||f>=d){i.writeHead(416,{...n,"Content-Range":`bytes */${d}`}),i.end();return}if(i.writeHead(206,{...n,"Content-Type":l,"Content-Range":`bytes ${f}-${m}/${d}`,"Accept-Ranges":"bytes","Content-Length":String(m-f+1)}),s==="HEAD"){i.end();return}T.createReadStream(r,{start:f,end:m}).pipe(i);return}if(i.writeHead(200,{...n,"Content-Type":l,"Accept-Ranges":"bytes","Content-Length":String(d)}),s==="HEAD"){i.end();return}T.createReadStream(r).pipe(i)}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[xt]);return Number.isFinite(e)&&e>0?Math.max(100,Math.round(e)):Rt}startRuntimeUpdater(){if(!this.shouldWriteLockfile||this.runtimeUpdateTimer||T.existsSync(b.join(z(),"runtime-update-disabled"))||process.env.SOOTSIM_HOME&&q()&&!$())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(`rnx: checking for runtime updates\u2026
|
|
21
|
-
`);let t=await O.updateToLatest({protectVersions:this.connectedRuntimeVersions()});if(!t.updated||!t.latestVersion){e==="startup"&&process.stderr.write(`rnx: runtime ${this.activeRuntimeVersion??"(none)"} is current
|
|
22
|
-
`);return}let i=this.activeRuntimeVersion,s=this.setActiveRuntime(t.latestVersion);process.stderr.write(`rnx runtime updated to ${s.version} (${e})
|
|
23
|
-
`);try{Z({from:i,to:s.version,at:Date.now()})}catch{}}catch(t){process.stderr.write(`rnx runtime update failed (${e}): ${t instanceof Error?t.message:String(t)}
|
|
24
|
-
`)}finally{if(this.runtimeUpdateInFlight=null,e==="startup"&&this.bootstrapping){if(this.bootstrapping=!1,this.shouldWriteLockfile&&this.httpServer)try{this.writeLockfileSnapshot()}catch{}process.stderr.write(`rnx: ready
|
|
25
|
-
`)}}})(),this.runtimeUpdateInFlight)}setActiveRuntime(e){if(Q(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()){try{let s=new URL(i.url||i.origin||"http://localhost");if(L(s.hostname))continue}catch{}if(i.ws.readyState===S.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{j()}catch{}}handleHttpRequest(e,t){if(t.setHeader("Cross-Origin-Opener-Policy","same-origin"),t.setHeader("Cross-Origin-Embedder-Policy",Ct),t.setHeader("Cross-Origin-Resource-Policy","cross-origin"),t.setHeader("Document-Policy","js-profiling"),Ne(e.url)){Ue(e,t);return}if(He(e.url)&&Fe(e,t))return;let i=(e.method||"GET").toUpperCase(),s;try{s=new URL(e.url||"/",`http://${e.headers.host||"localhost"}`)}catch{t.writeHead(400,{"Content-Type":"text/plain; charset=utf-8"}),t.end("invalid request URL or host");return}if(s.pathname==="/__sootsim/shared-config"){if(t.setHeader("Access-Control-Allow-Origin","*"),t.setHeader("Access-Control-Allow-Headers","Content-Type"),t.setHeader("Cache-Control","no-store"),i==="OPTIONS"){t.writeHead(204,{Allow:"GET, HEAD, POST, OPTIONS"}),t.end();return}if(i==="GET"||i==="HEAD"){let u="{}";try{u=JSON.stringify(W())}catch{}t.writeHead(200,{"Content-Type":"application/json"}),i==="HEAD"?t.end():t.end(u);return}if(i==="POST"){(async()=>{try{let u=[],p=0;for await(let g of e){let v=Buffer.isBuffer(g)?g:Buffer.from(g);if(p+=v.byteLength,p>8*1024*1024){t.writeHead(413,{"Content-Type":"text/plain; charset=utf-8"}),t.end("shared config patch is too large");return}u.push(v)}let h=JSON.parse(Buffer.concat(u).toString("utf8"));if(!h||typeof h!="object"||Array.isArray(h))throw new Error("shared config patch must be an object");let f=Object.fromEntries(Object.entries(h)),m=this.writeAndBroadcastSharedConfig(f);t.writeHead(200,{"Content-Type":"application/json"}),t.end(JSON.stringify(m))}catch(u){t.writeHead(400,{"Content-Type":"text/plain; charset=utf-8"}),t.end(`invalid shared config patch: ${u instanceof Error?u.message:String(u)}`)}})();return}t.writeHead(405,{Allow:"GET, HEAD, POST, OPTIONS"}),t.end("method not allowed");return}if(s.pathname.startsWith(Je)){this.handleCameraFixture(s.pathname.slice(Je.length),e,t);return}if(i!=="GET"&&i!=="HEAD"){t.writeHead(405,{Allow:"GET, HEAD"}),t.end("method not allowed");return}if(s.pathname==="/__bundle-proxy"){let u=s.searchParams.get("url");if(!u){t.writeHead(400,{"Content-Type":"text/plain"}),t.end("bundle-proxy: missing url query param");return}let p;try{p=new URL(u)}catch{t.writeHead(400,{"Content-Type":"text/plain"}),t.end("bundle-proxy: invalid url");return}let h=p.hostname;if(!(h==="localhost"||h==="127.0.0.1"||h==="::1"||h.endsWith(".localhost"))){t.writeHead(403,{"Content-Type":"text/plain"}),t.end("bundle-proxy: only loopback targets allowed");return}(async()=>{try{let m=await fetch(p.toString(),{redirect:"follow"}),g={},v=m.headers.get("content-type");if(v&&(g["Content-Type"]=v),g["Cache-Control"]="no-store",t.writeHead(m.status,g),!m.body){t.end();return}let w=m.body.getReader();for(;;){let{done:A,value:y}=await w.read();if(A)break;t.write(Buffer.from(y))}t.end()}catch(m){t.writeHead(502,{"Content-Type":"text/plain"}),t.end(`bundle-proxy: upstream fetch failed: ${m instanceof Error?m.message:String(m)}`)}})();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,bridgeSource:this.shouldWriteDevLockfile?"vite-dev":this.shouldWriteLockfile?"daemon":"embedded",startedAt:this.startedAt,uptimeMs:this.startedAt>0?Date.now()-this.startedAt:0}));return}let n=me(s.hostname),c=L(s.hostname);n||this.refreshActiveRuntime();let r=n?fe(s.hostname):this.activeRuntimeDirPath;if(!r){t.writeHead(503,{"Content-Type":"text/plain; charset=utf-8"}),t.end(n?`rnx: runtime ${c??"(invalid version origin)"} is not installed. run \`rnx open\` from that app again.`:"rnx: no active runtime installed. run `rnx runtime install` to fetch one.");return}let o=s.pathname;if(o==="/runtime"||o==="/runtime/"?o="/":o.startsWith("/runtime/")?o=o.slice(8):o==="/sootsim"||o==="/sootsim/"?o="/":o.startsWith("/sootsim/")&&(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 u of o.split("/"))if(u===".."){t.writeHead(403),t.end("forbidden");return}let l=b.resolve(r,"."+o),d=r.endsWith(b.sep)?r:r+b.sep;if(!l.startsWith(d)&&l!==r){t.writeHead(403),t.end("forbidden");return}T.realpath(l,(u,p)=>{let h=u?l:p,f=h.endsWith(b.sep)?h:h+b.sep;if(!u){let m=(()=>{try{let g=T.realpathSync(r);return g.endsWith(b.sep)?g:g+b.sep}catch{return d}})();if(!f.startsWith(m)&&h+b.sep!==m){t.writeHead(403),t.end("forbidden");return}}T.stat(h,(m,g)=>{if(m||!g?.isFile()){let y=b.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 I=b.join(r,"index.html");T.readFile(I,(Ge,ze)=>{if(Ge){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(Ve(ze,this.effectivePort,this.contrastOrigin))});return}let v=b.extname(h).toLowerCase(),w=je[v]||"application/octet-stream";if(t.writeHead(200,{"Content-Type":w,"Cache-Control":"no-store"}),i==="HEAD"){t.end();return}if(v===".html"){T.readFile(h,(y,I)=>{if(y){try{t.end()}catch{}return}t.end(Ve(I,this.effectivePort,this.contrastOrigin))});return}let A=T.createReadStream(h);A.pipe(t),A.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)continue;let c=!1;for(let r of this.cliBySentId.values())if(r.ws===i){c=!0;break}if(!c){this.cliSimBySocket.delete(i),this.cliLastCommandAt.delete(i);for(let[r,o]of this.cliBySentId)o.ws===i&&this.cliBySentId.delete(r);try{i.close(1e3,"idle timeout")}catch{}t=!0}}t&&this.broadcastSimClientStates(),this.sweepRestorableSims(e),this.reapIdleSims(e)}isAutomationSim(e){return e.meta?.sootsimHostDriver==="playwright"}automationSimOwnerAlive(e){let t=Number(e.meta?.sootsimHostPid);if(!Number.isInteger(t)||t<=1||t===process.pid)return!1;try{return process.kill(t,0),!0}catch(i){return i.code==="EPERM"}}reapIdleSims(e=Date.now()){let t=new Set(this.cliSimBySocket.values()),i=[];for(let n of this.sims.values()){if(n.id===this.primarySimId||t.has(n.id)||this.getActiveLease(n))continue;let c=Math.max(n.lastActiveAt,n.connectedAt),r=e-c,o=this.isAutomationSim(n);if(o&&this.automationSimOwnerAlive(n))continue;let l=o?this.automationSimIdleReapTtlMs:this.simIdleReapTtlMs;if(r>=l){this.closeSimSocketFromHost(n.ws);continue}o&&i.push({sim:n,idleMs:r})}let s=this.maxConcurrentAutomationSims;if(i.length>s){i.sort((n,c)=>c.idleMs-n.idleMs);for(let{sim:n,idleMs:c}of i.slice(0,i.length-s))c<this.automationSimActiveGraceMs||this.closeSimSocketFromHost(n.ws)}}sweepDeadWebSockets(){if(this.wss)for(let e of this.wss.clients){if(e.readyState!==S.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{}}}}closeSimSocketFromHost(e){if(e.readyState!==S.OPEN)return;try{e.close(le,ue)}catch{try{e.terminate()}catch{}return}let t=setTimeout(()=>{if(e.readyState!==S.CLOSED)try{e.terminate()}catch{}},Et);Ke(t)}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 c=setTimeout(()=>{this.pendingCommands.delete(i),this.broadcastSimClientStates(),n(new Error("command timed out after 30s"))},3e4);this.pendingCommands.set(i,{simId:t.id,resolve:l=>{clearTimeout(c),this.pendingCommands.delete(i),this.broadcastSimClientStates(),s(l)},reject:l=>{clearTimeout(c),this.pendingCommands.delete(i),this.broadcastSimClientStates(),n(l)}}),this.broadcastSimClientStates();let{simId:r,...o}=e;t.ws.send(JSON.stringify({...o,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}`,c=(o,l)=>new Promise(d=>{try{let u=wt(o,l,{detached:!0,stdio:"ignore"}),p=!1;u.on("error",()=>{p||(p=!0,d(!1))}),u.on("spawn",()=>{p||(p=!0,u.unref(),d(!0))})}catch{d(!1)}}),r=process.env.REACT_EDITOR||process.env.EDITOR;if(r){let o=r.split(" ").filter(Boolean);if(o.length&&await c(o[0],[...o.slice(1),"-g",n]))return}await c("cursor",["-g",n])||await c("code",["-g",n])||await this.openUrl(e)}async openUrl(e,t={}){if(this.openUrlHandler){await this.openUrlHandler(e,t);return}await ge(e,t)}async close(){if(this.cliIdleTimer&&(clearInterval(this.cliIdleTimer),this.cliIdleTimer=null),this.heartbeatTimer&&(clearInterval(this.heartbeatTimer),this.heartbeatTimer=null),this.devHeartbeatTimer&&(clearInterval(this.devHeartbeatTimer),this.devHeartbeatTimer=null),this.wsHeartbeatTimer&&(clearInterval(this.wsHeartbeatTimer),this.wsHeartbeatTimer=null),this.runtimeUpdateTimer&&(clearInterval(this.runtimeUpdateTimer),this.runtimeUpdateTimer=null),this.shouldWriteLockfile)try{j()}catch{}if(this.shouldWriteDevLockfile)try{oe({bridgePort:this.effectivePort,pid:process.pid,startedAt:this.startedAt})}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=S.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===S.OPEN?"open":t===S.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,userVisible:e.userVisible,visibilityState:e.visibilityState,documentFocused:e.documentFocused,kind:e.kind,meta:e.meta}}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),c=Date.now(),r=this.getActiveLease(t),o=r&&r.cliIdentityKey===s,l=0;if(r&&!o&&!i.force)return{granted:!1,lease:r,lock:{by:r.cliLabel||r.cliIdentityKey,expiresInMs:Math.max(0,r.expiresAt-c)},bootedCount:0};if(r&&!o&&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{}l++}}let d={kind:"cli",cliIdentityKey:s,cliLabel:n,expiresAt:c+a.CLI_LEASE_TTL_MS};return t.cliLease=d,{granted:!0,lease:d,bootedCount:l}}updateUserFocusLease(e,t){let i=t.focused===!0,s=typeof t.visible=="boolean"?t.visible:void 0,n=typeof t.visibilityState=="string"?t.visibilityState:void 0,c=typeof t.documentFocused=="boolean"?t.documentFocused:void 0;e.userFocused===i&&e.userVisible===s&&e.visibilityState===n&&e.documentFocused===c||(e.userFocused=i,e.userVisible=s,e.visibilityState=n,e.documentFocused=c,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===S.OPEN?i:null}let t=this.getDefaultSimCandidates();return t.find(i=>i.id===this.primarySimId)??t[0]??null}getDefaultSimCandidates(){let e=Array.from(this.sims.values()).filter(i=>i.ws.readyState===S.OPEN),t=e.filter(i=>i.url);return t.length>0?t:e}async waitForSim(e,t={}){let i=t.attempts??10,s=t.intervalMs??200;for(let c=0;c<i;c++){if(e){let r=this.getOpenSim(e);if(r)return r}else{let r=this.getDefaultSimCandidates();if(r.length>1)throw new Error(`multiple sims are connected: ${r.map(l=>l.id).join(", ")}; run \`rnx use <sim>\` or pass \`--sim <sim>\``);let o=r[0];if(o)return o}await new Promise(r=>setTimeout(r,s))}if(!e)throw new Error("no sim connected");let n=this.getDefaultSimCandidates().map(c=>c.id);throw new Error(`no sim connected with id ${e}`+(n.length>0?`; connected sims: ${n.join(", ")}`:""))}shouldPromoteSim(e){let t=this.primarySimId?this.sims.get(this.primarySimId):null;if(!e.url)return!t;let i=t?.ws.readyState===S.OPEN;if(!t||!i||!t.url)return!0;let s=e.origin?.includes(":5173"),n=t.origin?.includes(":5173");return!!s||!n}broadcastSimAssignments(){for(let e of this.sims.values())e.ws.readyState===S.OPEN&&e.ws.send(JSON.stringify({type:"bridge:welcome",simId:e.id,isPrimary:e.id===this.primarySimId}))}writeAndBroadcastSharedConfig(e){let t=Y(e),i=JSON.stringify({type:"bridge:shared-config-changed",config:t});for(let s of this.sims.values())if(s.ws.readyState===S.OPEN)try{s.ws.send(i)}catch{}return t}broadcastSimClientStates(){for(let e of this.sims.values()){if(e.ws.readyState!==S.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,userVisible:e.userVisible,visibilityState:e.visibilityState,documentFocused:e.documentFocused};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 c=Date.now();n.lastActiveAt=c,n.recentActions=[{label:s,at:c},...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!==S.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,c]of this.cliSimBySocket){if(c!==t||n.readyState!==S.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===S.OPEN)return!1;let n=this.getRestorableSimState(i),c=e.id;this.sims.delete(c),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===c&&(this.primarySimId=e.id);for(let[r,o]of this.cliSimBySocket)o===c&&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),this.writeConnectedRuntimeSnapshot()}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 _t(){return!!((process.env.XPC_SERVICE_NAME||"").includes("dev.sootsim.daemon")||process.env.INVOCATION_ID)}async function wi(a,e={}){(a.includes("--help")||a.includes("-h"))&&(console.log(`
|
|
26
|
-
rnx serve \u2014 run the rnx bridge in the foreground
|
|
27
|
-
|
|
28
|
-
hosts the WS bridge that CLI commands talk to. once running, any rnx
|
|
29
|
-
renderer (browser, electron, headless playwright) that connects to port 7668
|
|
30
|
-
becomes drivable from 'rnx describe', 'rnx do tap', etc.
|
|
31
|
-
|
|
32
|
-
usage:
|
|
33
|
-
rnx serve [options]
|
|
34
|
-
|
|
35
|
-
options:
|
|
36
|
-
--port <n> bridge port (defaults to ${7668})
|
|
37
|
-
--quiet suppress per-connection logging
|
|
38
|
-
|
|
39
|
-
examples:
|
|
40
|
-
rnx serve
|
|
41
|
-
rnx serve --port 7668 --quiet
|
|
42
|
-
`),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=te();n&&ie(n)&&(console.error(` an rnx bridge is already running (pid ${n.pid}, port ${n.bridgePort})`),console.error(" stop it with 'rnx daemon stop' first"),process.exit(1)),x();let c=await Se(),r=new H({port:i,writeLockfile:!0,contrastOrigin:c}),o=await r.startAsync({silent:s}),l=Date.now(),d=f=>{s||process.stdout.write(`${f}
|
|
43
|
-
`)},u=new Set,p=setInterval(()=>{let f=r.listSims(),m=new Set(f.map(g=>g.id));for(let g of f)if(!u.has(g.id)){let v=g.title||g.url||g.origin||"(unknown)";d(` + ${g.id} ${v}`)}for(let g of u)m.has(g)||d(` - ${g}`);u.clear();for(let g of m)u.add(g)},500);ae({event:"daemon_heartbeat",properties:{bridge_port:o,under_daemon:_t(),platform:process.platform,subsource:"daemon"}}),ce(),d(`rnx bridge listening on ws://localhost:${o} (runtime http on same port)`),o!==i&&d(` (preferred port ${i} was taken \u2014 fell back to ${o})`),d(" ready for browser, electron, or headless playwright sims to connect"),d(" (ctrl-c to stop)");let h=async f=>{clearInterval(p),d(`
|
|
44
|
-
${f} received \u2014 shutting down after ${Math.round((Date.now()-l)/1e3)}s`);try{await r.close()}catch{}process.exit(0)};process.on("SIGINT",()=>h("SIGINT")),process.on("SIGTERM",()=>h("SIGTERM")),process.on("SIGHUP",()=>h("SIGHUP")),process.on("exit",()=>{try{r.removeLockfile()}catch{}}),await new Promise(()=>{})}export{wi as runServe};
|
|
@@ -1,4 +0,0 @@
|
|
|
1
|
-
/*! rnx v0.1.338 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
|
|
2
|
-
import { createRequire as __sootsimCreateRequire } from 'node:module'
|
|
3
|
-
var require = __sootsimCreateRequire(import.meta.url)
|
|
4
|
-
import{a}from"./chunk-UOJDJDCM.js";import"./chunk-D27DTXJU.js";import"./chunk-XFELRGXJ.js";export{a as settingsStore};
|
|
@@ -1,4 +0,0 @@
|
|
|
1
|
-
/*! rnx v0.1.338 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
|
|
2
|
-
import { createRequire as __sootsimCreateRequire } from 'node:module'
|
|
3
|
-
var require = __sootsimCreateRequire(import.meta.url)
|
|
4
|
-
import{c as a,d as b}from"./chunk-G3W7FC3J.js";import"./chunk-2PFMT5AC.js";import"./chunk-OK6SVPSL.js";import"./chunk-XFELRGXJ.js";export{b as flushCliTelemetry,a as trackCliEvent};
|
|
@@ -1,4 +0,0 @@
|
|
|
1
|
-
/*! rnx v0.1.338 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
|
|
2
|
-
import { createRequire as __sootsimCreateRequire } from 'node:module'
|
|
3
|
-
var require = __sootsimCreateRequire(import.meta.url)
|
|
4
|
-
import{e as a,f as b,g as c}from"./chunk-SVMKZXCM.js";import"./chunk-MQFPZ7KI.js";import"./chunk-GGDORRTI.js";import"./chunk-OVPCCCEU.js";import"./chunk-Q4NOTYIM.js";import"./chunk-ZERYUNU4.js";import"./chunk-G3W7FC3J.js";import"./chunk-2PFMT5AC.js";import"./chunk-5QAP5T2V.js";import"./chunk-YUX3I7IO.js";import"./chunk-OK6SVPSL.js";import"./chunk-OF2LP2DA.js";import"./chunk-XFELRGXJ.js";export{a as resolveDefaultUploadOrigin,b as resolvePublicPreviewOrigin,c as runUpload};
|