reflex-browser
Advanced tools
+1
-1
@@ -8,3 +8,3 @@ "use strict";var D=(e,t)=>()=>{try{return t||e((t={exports:{}}).exports,t),t.exports}catch(r){throw t=0,r}};var Ke=D((sr,X)=>{"use strict";var de=require("fs"),Ot=require("path"),{execFileSync:B}=require("child_process");function Ue(e){if(!e||e<1)return!1;try{return process.kill(e,0),!0}catch(t){return t.code==="EPERM"}}function jt(e){if(process.platform==="win32")return!1;let t="";try{t=B("ps",["-e","-o","pgid=,command="],{encoding:"utf8",stdio:["ignore","pipe","ignore"],timeout:4e3})}catch{return!1}let r=String(e);for(let n of t.split(` | ||
| .s{margin-top:.5rem;color:#9fb3a8}</style></head> | ||
| <body><div class="c"><div class="t">${e}</div><div class="s">${t}</div></div></body></html>`}rt.exports={login:zt,logout:Wt,loadKey:Gt,saveKey:tt,openBrowser:nt,SITE_BASE:Ve,API_BASE:Qe,_authFile:q}});var _e=D((cr,Vt)=>{Vt.exports={name:"reflex-browser",version:"0.9.0",mcpName:"com.reflexmcp/reflex",description:"Token-efficient browser automation for AI agents. Local MCP server + CLI: compressed page snapshots, batched actions, forensic failures.",license:"SEE LICENSE IN LICENSE",bin:{reflex:"./dist/reflex.js","reflex-browser":"./dist/reflex-browser.js"},files:["dist","README.md","LICENSE"],scripts:{bench:"node bench/run.js","bench:h2h":"node bench/h2h-run.js",smoke:"node test/smoke.js","test:engine":"node test/engine.js","test:tenx":"node test/tenx.js","test:mcp":"node test/mcp.js","test:profile":"node test/profile.js","test:memory":"node test/memory.js",test:"node test/profile.js && node test/smoke.js && node test/engine.js && node test/tenx.js && node test/mcp.js && node test/credits.js && node test/memory.js && node test/teardown.js && node test/hygiene.js && node test/parallel.js && node test/concurrency.js","test:parallel":"node test/parallel.js","test:concurrency":"node test/concurrency.js",check:"npm run check:all","check:all":"mkdir -p checks-outputs && npm run check:root && npm run check:server && npm run check:web","check:root":"bash -c 'set -o pipefail; node bin/reflex.js stop 2>/dev/null || true; npm test 2>&1 | tee checks-outputs/root-test.txt'","check:server":"bash -c 'set -o pipefail; cd server && npm test 2>&1 | tee ../checks-outputs/server-test.txt && npm run typecheck 2>&1 | tee ../checks-outputs/server-type.txt'","check:web":"bash -c 'set -o pipefail; cd web && npm run typecheck 2>&1 | tee ../checks-outputs/web-type.txt && rm -rf .next && npm run build 2>&1 | tee ../checks-outputs/web-build.txt'",build:"node scripts/build-dist.mjs",prepack:"npm run build","test:dist":"npm run build && REFLEX_TEST_CLI=dist/reflex.js REFLEX_TEST_BIN=dist/reflex-browser.js npm test"},dependencies:{"@modelcontextprotocol/sdk":"^1.29.0","playwright-core":"^1.50.0"},homepage:"https://reflexmcp.com",repository:{type:"git",url:"git+https://github.com/nitaiaharoni1/reflex-browser.git"},keywords:["mcp","browser-automation","playwright","claude-desktop","cursor","ai-agent","model-context-protocol"],devDependencies:{esbuild:"^0.28.1"}}});var wt=D((lr,_t)=>{"use strict";var d=require("fs"),Qt=require("os"),A=require("path"),H=require("crypto"),en=ge(),ke=process.env.REFLEX_API_BASE||"https://reflex.openlabs.workers.dev";function T(){return process.env.REFLEX_HOME||A.join(Qt.homedir(),".reflex")}function te(){return A.join(T(),"credits.json")}function ne(e){return A.join(T(),`usage-${e||process.pid}.json`)}function at(){return A.join(T(),"credits.lock")}function we(){return A.join(T(),"device.json")}var be=/^rfx_(live|test)_[A-Za-z0-9]{32}$/,Se=25,tn="rfx_trial_loc";function nn(){return process.env.REFLEX_TRIAL!=="off"&&process.env.REFLEX_TRIAL!=="0"}var rn={k1:process.env.REFLEX_PUBKEY_K1||"cU8LzUpIjro9cQo/A4o7BaOJ6QcDKloN6hffQISY28o="},on=3,sn=3e4,an=250,Ee=6e4,cn=1e3,ln=100,un=10,fn=6e5,ct=3e5,Re=3e3,dn=5e3,pn=2e3,hn=3e5,mn=250,yn=5e3,Le=(()=>{try{return _e().version}catch{return"0.0.0"}})(),w={noKey:'Reflex is not signed in, so this call was not run and was not charged. Please tell the user to sign in: run the reflex_auth tool with {"action":"login"} and it will open their browser to sign in (free, 30 starter credits at https://reflexmcp.com). Then retry this call. (CI/headless: set REFLEX_API_KEY in the MCP client config instead.)',badKey:"This Reflex API key is invalid or has been revoked. Check your key at https://reflexmcp.com/dashboard or generate a new one, then update REFLEX_API_KEY and restart.",outOfCredits:`Reflex is out of credits, so this call was not run and was not charged. Your | ||
| <body><div class="c"><div class="t">${e}</div><div class="s">${t}</div></div></body></html>`}rt.exports={login:zt,logout:Wt,loadKey:Gt,saveKey:tt,openBrowser:nt,SITE_BASE:Ve,API_BASE:Qe,_authFile:q}});var _e=D((cr,Vt)=>{Vt.exports={name:"reflex-browser",version:"0.10.0",mcpName:"com.reflexmcp/reflex",description:"Token-efficient browser automation for AI agents. Local MCP server + CLI: compressed page snapshots, batched actions, forensic failures.",license:"SEE LICENSE IN LICENSE",bin:{reflex:"./dist/reflex.js","reflex-browser":"./dist/reflex-browser.js"},files:["dist","README.md","LICENSE"],scripts:{bench:"node bench/run.js","bench:h2h":"node bench/h2h-run.js",smoke:"node test/smoke.js","test:engine":"node test/engine.js","test:tenx":"node test/tenx.js","test:mcp":"node test/mcp.js","test:profile":"node test/profile.js","test:memory":"node test/memory.js",test:"node test/profile.js && node test/smoke.js && node test/engine.js && node test/tenx.js && node test/mcp.js && node test/credits.js && node test/memory.js && node test/teardown.js && node test/hygiene.js && node test/parallel.js && node test/concurrency.js","test:parallel":"node test/parallel.js","test:concurrency":"node test/concurrency.js",check:"npm run check:all","check:all":"mkdir -p checks-outputs && npm run check:root && npm run check:server && npm run check:web","check:root":"bash -c 'set -o pipefail; node bin/reflex.js stop 2>/dev/null || true; npm test 2>&1 | tee checks-outputs/root-test.txt'","check:server":"bash -c 'set -o pipefail; cd server && npm test 2>&1 | tee ../checks-outputs/server-test.txt && npm run typecheck 2>&1 | tee ../checks-outputs/server-type.txt'","check:web":"bash -c 'set -o pipefail; cd web && npm run typecheck 2>&1 | tee ../checks-outputs/web-type.txt && rm -rf .next && npm run build 2>&1 | tee ../checks-outputs/web-build.txt'",build:"node scripts/build-dist.mjs",prepack:"npm run build","test:dist":"npm run build && REFLEX_TEST_CLI=dist/reflex.js REFLEX_TEST_BIN=dist/reflex-browser.js npm test"},dependencies:{"@modelcontextprotocol/sdk":"^1.29.0","playwright-core":"^1.50.0"},homepage:"https://reflexmcp.com",repository:{type:"git",url:"git+https://github.com/nitaiaharoni1/reflex-browser.git"},keywords:["mcp","browser-automation","playwright","claude-desktop","cursor","ai-agent","model-context-protocol"],devDependencies:{esbuild:"^0.28.1"}}});var wt=D((lr,_t)=>{"use strict";var d=require("fs"),Qt=require("os"),A=require("path"),H=require("crypto"),en=ge(),ke=process.env.REFLEX_API_BASE||"https://reflex.openlabs.workers.dev";function T(){return process.env.REFLEX_HOME||A.join(Qt.homedir(),".reflex")}function te(){return A.join(T(),"credits.json")}function ne(e){return A.join(T(),`usage-${e||process.pid}.json`)}function at(){return A.join(T(),"credits.lock")}function we(){return A.join(T(),"device.json")}var be=/^rfx_(live|test)_[A-Za-z0-9]{32}$/,Se=25,tn="rfx_trial_loc";function nn(){return process.env.REFLEX_TRIAL!=="off"&&process.env.REFLEX_TRIAL!=="0"}var rn={k1:process.env.REFLEX_PUBKEY_K1||"cU8LzUpIjro9cQo/A4o7BaOJ6QcDKloN6hffQISY28o="},on=3,sn=3e4,an=250,Ee=6e4,cn=1e3,ln=100,un=10,fn=6e5,ct=3e5,Re=3e3,dn=5e3,pn=2e3,hn=3e5,mn=250,yn=5e3,Le=(()=>{try{return _e().version}catch{return"0.0.0"}})(),w={noKey:'Reflex is not signed in, so this call was not run and was not charged. Please tell the user to sign in: run the reflex_auth tool with {"action":"login"} and it will open their browser to sign in (free, 30 starter credits at https://reflexmcp.com). Then retry this call. (CI/headless: set REFLEX_API_KEY in the MCP client config instead.)',badKey:"This Reflex API key is invalid or has been revoked. Check your key at https://reflexmcp.com/dashboard or generate a new one, then update REFLEX_API_KEY and restart.",outOfCredits:`Reflex is out of credits, so this call was not run and was not charged. Your | ||
| browser, open tabs, and login sessions are untouched. Please tell the user: | ||
@@ -11,0 +11,0 @@ top up at https://reflexmcp.com/pricing (150 credits for $9, 500 for $19), and |
+15
-9
| #!/usr/bin/env node | ||
| "use strict";var S=(e,t)=>()=>{try{return t||e((t={exports:{}}).exports,t),t.exports}catch(r){throw t=0,r}};var he=S((Lr,v)=>{"use strict";var G=require("fs"),ft=require("path"),{execFileSync:L}=require("child_process");function me(e){if(!e||e<1)return!1;try{return process.kill(e,0),!0}catch(t){return t.code==="EPERM"}}function dt(e){if(process.platform==="win32")return!1;let t="";try{t=L("ps",["-e","-o","pgid=,command="],{encoding:"utf8",stdio:["ignore","pipe","ignore"],timeout:4e3})}catch{return!1}let r=String(e);for(let n of t.split(` | ||
| `)){let s=n.match(/^\s*(\d+)\s+(.*)$/);if(s&&s[1]===r&&/chrome|chromium|ms-playwright|playwright[\/\\]/i.test(s[2]))return!0}return!1}function pt(e){if(process.platform==="win32")return null;let t="";try{t=L("ps",["-Ao","pid=,ppid=,pgid=,command="],{encoding:"utf8",stdio:["ignore","pipe","ignore"],timeout:4e3})}catch{return null}for(let r of t.split(` | ||
| `)){let n=r.match(/^\s*(\d+)\s+(\d+)\s+(\d+)\s+(.*)$/);if(!n)continue;let[,s,o,i,l]=n;if(o===String(e)&&/chrome|chromium|ms-playwright/i.test(l)&&!/crashpad/i.test(l))return{pid:parseInt(s,10),pgid:parseInt(i,10)}}return null}function mt(e,t){let r;try{r=G.readdirSync(e)}catch{return}for(let n of r){if(!/^daemon(-.+)?\.json$/.test(n))continue;let s=ft.join(e,n),o;try{o=JSON.parse(G.readFileSync(s,"utf8"))}catch{continue}if(!(!o||o.pid===t)&&!me(o.pid)){try{let i=o.pgid||o.pid;!i||i<1||(process.platform==="win32"?o.browserPid&&L("taskkill",["/PID",String(o.browserPid),"/T","/F"],{stdio:"ignore",timeout:8e3}):v.exports.groupLooksLikeReflex(i)&&process.kill(-i,"SIGKILL"))}catch{}try{G.unlinkSync(s)}catch{}}}}function ht(e){if(!e||e<2||process.platform==="win32")return!1;let t="";try{t=L("ps",["-p",String(e),"-o","command="],{encoding:"utf8",stdio:["ignore","pipe","ignore"],timeout:4e3})}catch{return!1}return/reflex[\/\\]|reflex-browser|daemon\.js/i.test(t)}function gt(e){if(e)try{if(process.platform==="win32"){if(e.browserPid)try{L("taskkill",["/PID",String(e.browserPid),"/T","/F"],{stdio:"ignore",timeout:8e3})}catch{}return}if(e.pid&&e.pid>1&&e.pid!==process.pid&&v.exports.daemonPidLooksLikeReflex(e.pid))try{process.kill(e.pid,"SIGKILL")}catch{}let t=e.pgid;if(t&&t>1&&t!==process.pid&&v.exports.groupLooksLikeReflex(t))try{process.kill(-t,"SIGKILL")}catch{}}catch{}}v.exports={isAlive:me,groupLooksLikeReflex:dt,daemonPidLooksLikeReflex:ht,reapOrphans:mt,reapState:gt,findBrowserGroup:pt}});var xe=S((Or,we)=>{"use strict";var yt=require("http"),g=require("fs"),Y=require("path"),St=require("os"),{spawn:Et}=require("child_process"),V=process.env.REFLEX_HOME||Y.join(St.homedir(),".reflex"),P=e=>String(e||"default").replace(/[^a-zA-Z0-9_-]/g,"_").slice(0,40)||"default",M=P(process.env.REFLEX_SESSION),O=e=>Y.join(V,e==="default"?"daemon.json":`daemon-${e}.json`),wt=O(M),ye=Y.join(__dirname,"daemon.js");function W(e){try{return JSON.parse(g.readFileSync(O(e?P(e):M),"utf8"))}catch{return null}}function Se(e,t,r,n){return new Promise((s,o)=>{let i=JSON.stringify({cmd:t,args:r}),l={"x-reflex-token":e.token||""};n&&(l["x-reflex-caller"]=n);let c=yt.request({host:"127.0.0.1",port:e.port,method:"POST",path:"/",timeout:12e4,headers:l},a=>{let u="";a.on("data",d=>u+=d),a.on("end",()=>{try{s(JSON.parse(u))}catch{o(new Error("bad daemon response"))}})});c.on("error",o),c.on("timeout",()=>{c.destroy(),o(new Error("daemon timeout"))}),c.end(i)})}var ge=e=>new Promise(t=>setTimeout(t,e));async function I(e){let t=W(e);if(t)try{return await Se(t,"ping",{}),t}catch{}return null}function Ee(e){try{let t=g.openSync(e,"wx");return g.writeSync(t,String(process.pid)),g.closeSync(t),!0}catch(t){if(t.code!=="EEXIST")return!1;try{if(Date.now()-g.statSync(e).mtimeMs>15e3)return g.unlinkSync(e),Ee(e)}catch{}return!1}}function xt(e){try{return g.statSync(e),!0}catch{return!1}}async function bt(e,t){let r=e?P(e):M,n=await I(r);if(n)return n;try{g.mkdirSync(V,{recursive:!0,mode:448})}catch{}let s=O(r).replace(/\.json$/,".lock");for(let o=0;o<2;o++){if(Ee(s))try{if(n=await I(r),n)return n;let i=W(r);if(i)try{he().reapState(i)}catch{}try{g.unlinkSync(O(r))}catch{}let l=Object.assign({},process.env,t||{},{REFLEX_SESSION:r});Et(process.execPath,[ye],{detached:!0,stdio:"ignore",windowsHide:!0,env:l}).unref();for(let a=0;a<100;a++)if(await ge(100),n=await I(r),n)return n;throw new Error("daemon failed to start (check ~/.reflex/daemon.log)")}finally{try{g.unlinkSync(s)}catch{}}for(let i=0;i<100;i++){if(await ge(100),n=await I(r),n)return n;if(!xt(s))break}}throw new Error("daemon failed to start (check ~/.reflex/daemon.log)")}function K(e,t){if(typeof e=="string")return e.replace(/\{\{env:(\w+)\}\}/g,(r,n)=>process.env[n]===void 0?r:(t&&(t[n]=process.env[n]),process.env[n]));if(Array.isArray(e))return e.map(r=>K(r,t));if(e&&typeof e=="object"){let r={};for(let n in e)r[n]=K(e[n],t);return r}return e}we.exports={readState:W,rpc:Se,ensureDaemon:bt,subEnv:K,sanitizeSession:P,stateFileFor:O,HOME:V,SESSION:M,STATE_FILE:wt,DAEMON:ye}});var Fe=S((Rr,Re)=>{"use strict";var E=require("fs"),kt=require("os"),be=require("path"),_t=require("http"),vt=require("crypto"),{spawn:Lt}=require("child_process"),{URL:Ot}=require("url"),ke=process.env.REFLEX_SITE_BASE||"https://reflexmcp.com",_e=process.env.REFLEX_API_BASE||"https://reflex.openlabs.workers.dev",Rt=18e4;function ve(){return process.env.REFLEX_HOME||be.join(kt.homedir(),".reflex")}function w(){return be.join(ve(),"auth.json")}function Ft(){try{let e=E.readFileSync(w(),"utf8"),t=JSON.parse(e);return t&&typeof t.api_key=="string"?t.api_key:null}catch{return null}}function Le({api_key:e,key_id:t}){let r=ve();E.mkdirSync(r,{recursive:!0});let n=w()+".tmp",s=JSON.stringify({v:1,api_key:e,key_id:t||null,saved_at:new Date().toISOString()});E.writeFileSync(n,s,{mode:384}),E.renameSync(n,w());try{E.chmodSync(w(),384)}catch{}}function jt(){try{return E.unlinkSync(w()),!0}catch(e){if(e&&e.code==="ENOENT")return!1;throw e}}function Oe(e){let t,r;process.platform==="darwin"?(t="open",r=[e]):process.platform==="win32"?(t="cmd",r=["/c","start","",e]):(t="xdg-open",r=[e]);try{let n=Lt(t,r,{detached:!0,stdio:"ignore"});return n.on("error",()=>{}),n.unref(),!0}catch{return!1}}function At(e){e=e||{};let t=(e.siteBase||ke).replace(/\/+$/,""),r=(e.apiBase||_e).replace(/\/+$/,""),n=e.timeoutMs||Rt,s=vt.randomBytes(24).toString("base64url");return new Promise((o,i)=>{let l=!1,c=null,a=(d,f)=>{if(!l){l=!0,c&&clearTimeout(c);try{u.close()}catch{}d(f)}},u=_t.createServer((d,f)=>{let h;try{h=new Ot(d.url,"http://127.0.0.1")}catch{f.writeHead(400),f.end();return}if(h.pathname!=="/callback"){f.writeHead(404),f.end("not found");return}let _=h.searchParams.get("state"),pe=h.searchParams.get("code"),z=h.searchParams.get("error");if(z){f.writeHead(200,{"content-type":"text/html"}),f.end(T("Login failed",String(z).slice(0,200))),a(i,new Error("login failed: "+z));return}if(!_||_!==s){f.writeHead(400,{"content-type":"text/html"}),f.end(T("Login error","Security check failed (state mismatch). Run reflex_auth login again.")),a(i,new Error("state mismatch"));return}if(!pe){f.writeHead(400,{"content-type":"text/html"}),f.end(T("Login error","No login code received. Run reflex_auth login again.")),a(i,new Error("no code"));return}f.writeHead(200,{"content-type":"text/html"}),f.end(T("You are signed in to Reflex","You can close this tab and return to your agent.")),It(r,pe).then(J=>a(o,J),J=>a(i,J))});u.on("error",d=>a(i,d)),u.listen(0,"127.0.0.1",()=>{let d=u.address().port,f=`${t}/cli-auth?port=${d}&state=${encodeURIComponent(s)}`;if(typeof e.onUrl=="function")try{e.onUrl(f)}catch{}e.open!==!1&&Oe(f),c=setTimeout(()=>a(i,new Error("timed out waiting for browser login (3 min)")),n),c.unref&&c.unref()})})}async function It(e,t){let r;try{r=await fetch(e+"/v1/auth/cli-exchange",{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({code:t})})}catch(s){throw new Error("could not reach the Reflex login server: "+(s&&s.message?s.message:s))}let n=null;try{n=await r.json()}catch{}if(!r.ok){let s=n&&n.error&&n.error.message?n.error.message:`login exchange failed (HTTP ${r.status})`;throw new Error(s)}if(!n||typeof n.api_key!="string")throw new Error("login exchange returned no key");return Le({api_key:n.api_key,key_id:n.key_id}),n}function T(e,t){return`<!doctype html><html><head><meta charset="utf-8"><title>${e}</title> | ||
| "use strict";var S=(e,t)=>()=>{try{return t||e((t={exports:{}}).exports,t),t.exports}catch(r){throw t=0,r}};var he=S((Lr,v)=>{"use strict";var G=require("fs"),ft=require("path"),{execFileSync:L}=require("child_process");function me(e){if(!e||e<1)return!1;try{return process.kill(e,0),!0}catch(t){return t.code==="EPERM"}}function pt(e){if(process.platform==="win32")return!1;let t="";try{t=L("ps",["-e","-o","pgid=,command="],{encoding:"utf8",stdio:["ignore","pipe","ignore"],timeout:4e3})}catch{return!1}let r=String(e);for(let n of t.split(` | ||
| `)){let s=n.match(/^\s*(\d+)\s+(.*)$/);if(s&&s[1]===r&&/chrome|chromium|ms-playwright|playwright[\/\\]/i.test(s[2]))return!0}return!1}function dt(e){if(process.platform==="win32")return null;let t="";try{t=L("ps",["-Ao","pid=,ppid=,pgid=,command="],{encoding:"utf8",stdio:["ignore","pipe","ignore"],timeout:4e3})}catch{return null}for(let r of t.split(` | ||
| `)){let n=r.match(/^\s*(\d+)\s+(\d+)\s+(\d+)\s+(.*)$/);if(!n)continue;let[,s,o,i,l]=n;if(o===String(e)&&/chrome|chromium|ms-playwright/i.test(l)&&!/crashpad/i.test(l))return{pid:parseInt(s,10),pgid:parseInt(i,10)}}return null}function mt(e,t){let r;try{r=G.readdirSync(e)}catch{return}for(let n of r){if(!/^daemon(-.+)?\.json$/.test(n))continue;let s=ft.join(e,n),o;try{o=JSON.parse(G.readFileSync(s,"utf8"))}catch{continue}if(!(!o||o.pid===t)&&!me(o.pid)){try{let i=o.pgid||o.pid;!i||i<1||(process.platform==="win32"?o.browserPid&&L("taskkill",["/PID",String(o.browserPid),"/T","/F"],{stdio:"ignore",timeout:8e3}):v.exports.groupLooksLikeReflex(i)&&process.kill(-i,"SIGKILL"))}catch{}try{G.unlinkSync(s)}catch{}}}}function ht(e){if(!e||e<2||process.platform==="win32")return!1;let t="";try{t=L("ps",["-p",String(e),"-o","command="],{encoding:"utf8",stdio:["ignore","pipe","ignore"],timeout:4e3})}catch{return!1}return/reflex[\/\\]|reflex-browser|daemon\.js/i.test(t)}function gt(e){if(e)try{if(process.platform==="win32"){if(e.browserPid)try{L("taskkill",["/PID",String(e.browserPid),"/T","/F"],{stdio:"ignore",timeout:8e3})}catch{}return}if(e.pid&&e.pid>1&&e.pid!==process.pid&&v.exports.daemonPidLooksLikeReflex(e.pid))try{process.kill(e.pid,"SIGKILL")}catch{}let t=e.pgid;if(t&&t>1&&t!==process.pid&&v.exports.groupLooksLikeReflex(t))try{process.kill(-t,"SIGKILL")}catch{}}catch{}}v.exports={isAlive:me,groupLooksLikeReflex:pt,daemonPidLooksLikeReflex:ht,reapOrphans:mt,reapState:gt,findBrowserGroup:dt}});var xe=S((Or,Ee)=>{"use strict";var yt=require("http"),g=require("fs"),Y=require("path"),St=require("os"),{spawn:wt}=require("child_process"),W=process.env.REFLEX_HOME||Y.join(St.homedir(),".reflex"),P=e=>String(e||"default").replace(/[^a-zA-Z0-9_-]/g,"_").slice(0,40)||"default",M=P(process.env.REFLEX_SESSION),O=e=>Y.join(W,e==="default"?"daemon.json":`daemon-${e}.json`),Et=O(M),ye=Y.join(__dirname,"daemon.js");function V(e){try{return JSON.parse(g.readFileSync(O(e?P(e):M),"utf8"))}catch{return null}}function Se(e,t,r,n){return new Promise((s,o)=>{let i=JSON.stringify({cmd:t,args:r}),l={"x-reflex-token":e.token||""};n&&(l["x-reflex-caller"]=n);let c=yt.request({host:"127.0.0.1",port:e.port,method:"POST",path:"/",timeout:12e4,headers:l},a=>{let u="";a.on("data",p=>u+=p),a.on("end",()=>{try{s(JSON.parse(u))}catch{o(new Error("bad daemon response"))}})});c.on("error",o),c.on("timeout",()=>{c.destroy(),o(new Error("daemon timeout"))}),c.end(i)})}var ge=e=>new Promise(t=>setTimeout(t,e));async function I(e){let t=V(e);if(t)try{return await Se(t,"ping",{}),t}catch{}return null}function we(e){try{let t=g.openSync(e,"wx");return g.writeSync(t,String(process.pid)),g.closeSync(t),!0}catch(t){if(t.code!=="EEXIST")return!1;try{if(Date.now()-g.statSync(e).mtimeMs>15e3)return g.unlinkSync(e),we(e)}catch{}return!1}}function xt(e){try{return g.statSync(e),!0}catch{return!1}}async function bt(e,t){let r=e?P(e):M,n=await I(r);if(n)return n;try{g.mkdirSync(W,{recursive:!0,mode:448})}catch{}let s=O(r).replace(/\.json$/,".lock");for(let o=0;o<2;o++){if(we(s))try{if(n=await I(r),n)return n;let i=V(r);if(i)try{he().reapState(i)}catch{}try{g.unlinkSync(O(r))}catch{}let l=Object.assign({},process.env,t||{},{REFLEX_SESSION:r});wt(process.execPath,[ye],{detached:!0,stdio:"ignore",windowsHide:!0,env:l}).unref();for(let a=0;a<100;a++)if(await ge(100),n=await I(r),n)return n;throw new Error("daemon failed to start (check ~/.reflex/daemon.log)")}finally{try{g.unlinkSync(s)}catch{}}for(let i=0;i<100;i++){if(await ge(100),n=await I(r),n)return n;if(!xt(s))break}}throw new Error("daemon failed to start (check ~/.reflex/daemon.log)")}function K(e,t){if(typeof e=="string")return e.replace(/\{\{env:(\w+)\}\}/g,(r,n)=>process.env[n]===void 0?r:(t&&(t[n]=process.env[n]),process.env[n]));if(Array.isArray(e))return e.map(r=>K(r,t));if(e&&typeof e=="object"){let r={};for(let n in e)r[n]=K(e[n],t);return r}return e}Ee.exports={readState:V,rpc:Se,ensureDaemon:bt,subEnv:K,sanitizeSession:P,stateFileFor:O,HOME:W,SESSION:M,STATE_FILE:Et,DAEMON:ye}});var Fe=S((Rr,Re)=>{"use strict";var w=require("fs"),kt=require("os"),be=require("path"),_t=require("http"),vt=require("crypto"),{spawn:Lt}=require("child_process"),{URL:Ot}=require("url"),ke=process.env.REFLEX_SITE_BASE||"https://reflexmcp.com",_e=process.env.REFLEX_API_BASE||"https://reflex.openlabs.workers.dev",Rt=18e4;function ve(){return process.env.REFLEX_HOME||be.join(kt.homedir(),".reflex")}function E(){return be.join(ve(),"auth.json")}function Ft(){try{let e=w.readFileSync(E(),"utf8"),t=JSON.parse(e);return t&&typeof t.api_key=="string"?t.api_key:null}catch{return null}}function Le({api_key:e,key_id:t}){let r=ve();w.mkdirSync(r,{recursive:!0});let n=E()+".tmp",s=JSON.stringify({v:1,api_key:e,key_id:t||null,saved_at:new Date().toISOString()});w.writeFileSync(n,s,{mode:384}),w.renameSync(n,E());try{w.chmodSync(E(),384)}catch{}}function jt(){try{return w.unlinkSync(E()),!0}catch(e){if(e&&e.code==="ENOENT")return!1;throw e}}function Oe(e){let t,r;process.platform==="darwin"?(t="open",r=[e]):process.platform==="win32"?(t="cmd",r=["/c","start","",e]):(t="xdg-open",r=[e]);try{let n=Lt(t,r,{detached:!0,stdio:"ignore"});return n.on("error",()=>{}),n.unref(),!0}catch{return!1}}function At(e){e=e||{};let t=(e.siteBase||ke).replace(/\/+$/,""),r=(e.apiBase||_e).replace(/\/+$/,""),n=e.timeoutMs||Rt,s=vt.randomBytes(24).toString("base64url");return new Promise((o,i)=>{let l=!1,c=null,a=(p,f)=>{if(!l){l=!0,c&&clearTimeout(c);try{u.close()}catch{}p(f)}},u=_t.createServer((p,f)=>{let h;try{h=new Ot(p.url,"http://127.0.0.1")}catch{f.writeHead(400),f.end();return}if(h.pathname!=="/callback"){f.writeHead(404),f.end("not found");return}let _=h.searchParams.get("state"),de=h.searchParams.get("code"),z=h.searchParams.get("error");if(z){f.writeHead(200,{"content-type":"text/html"}),f.end(T("Login failed",String(z).slice(0,200))),a(i,new Error("login failed: "+z));return}if(!_||_!==s){f.writeHead(400,{"content-type":"text/html"}),f.end(T("Login error","Security check failed (state mismatch). Run reflex_auth login again.")),a(i,new Error("state mismatch"));return}if(!de){f.writeHead(400,{"content-type":"text/html"}),f.end(T("Login error","No login code received. Run reflex_auth login again.")),a(i,new Error("no code"));return}f.writeHead(200,{"content-type":"text/html"}),f.end(T("You are signed in to Reflex","You can close this tab and return to your agent.")),It(r,de).then(J=>a(o,J),J=>a(i,J))});u.on("error",p=>a(i,p)),u.listen(0,"127.0.0.1",()=>{let p=u.address().port,f=`${t}/cli-auth?port=${p}&state=${encodeURIComponent(s)}`;if(typeof e.onUrl=="function")try{e.onUrl(f)}catch{}e.open!==!1&&Oe(f),c=setTimeout(()=>a(i,new Error("timed out waiting for browser login (3 min)")),n),c.unref&&c.unref()})})}async function It(e,t){let r;try{r=await fetch(e+"/v1/auth/cli-exchange",{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({code:t})})}catch(s){throw new Error("could not reach the Reflex login server: "+(s&&s.message?s.message:s))}let n=null;try{n=await r.json()}catch{}if(!r.ok){let s=n&&n.error&&n.error.message?n.error.message:`login exchange failed (HTTP ${r.status})`;throw new Error(s)}if(!n||typeof n.api_key!="string")throw new Error("login exchange returned no key");return Le({api_key:n.api_key,key_id:n.key_id}),n}function T(e,t){return`<!doctype html><html><head><meta charset="utf-8"><title>${e}</title> | ||
| <style>html{color-scheme:dark}body{margin:0;display:grid;place-items:center;min-height:100vh; | ||
@@ -9,8 +9,8 @@ background:#0a1410;color:#e6f2ec;font:16px/1.5 system-ui,sans-serif} | ||
| .s{margin-top:.5rem;color:#9fb3a8}</style></head> | ||
| <body><div class="c"><div class="t">${e}</div><div class="s">${t}</div></div></body></html>`}Re.exports={login:At,logout:jt,loadKey:Ft,saveKey:Le,openBrowser:Oe,SITE_BASE:ke,API_BASE:_e,_authFile:w}});var re=S((Fr,De)=>{"use strict";var m=require("fs"),p=require("path"),je=require("os"),{execFileSync:Ae}=require("child_process"),Q=process.env.REFLEX_HOME||p.join(je.homedir(),".reflex"),Ie=p.join(Q,"profile-config.json");function Pt(){return process.platform==="darwin"?{rootFiles:[],files:["Bookmarks","Bookmarks.bak"],dirs:[],sqlite:new Set}:{rootFiles:["Local State"],files:["Cookies","Network/Cookies","Network/TransportSecurity","Login Data","Login Data For Account","Bookmarks","Bookmarks.bak"],dirs:["Local Storage"],sqlite:new Set(["Cookies","Network/Cookies","Login Data","Login Data For Account"])}}function N(){if(process.env.REFLEX_CHROME_USER_DATA)return process.env.REFLEX_CHROME_USER_DATA;let e=je.homedir();return process.platform==="darwin"?p.join(e,"Library","Application Support","Google","Chrome"):process.platform==="win32"?p.join(process.env.LOCALAPPDATA||p.join(e,"AppData","Local"),"Google","Chrome","User Data"):p.join(e,".config","google-chrome")}function Pe(){try{return JSON.parse(m.readFileSync(Ie,"utf8"))||{}}catch{return{}}}function Mt(e){m.mkdirSync(Q,{recursive:!0,mode:448}),m.writeFileSync(Ie,JSON.stringify(e,null,1),{mode:384})}function D(){return process.env.REFLEX_CHROME_PROFILE||Pe().source||"Default"}function ee(){let e=N(),t={};try{t=(JSON.parse(m.readFileSync(p.join(e,"Local State"),"utf8")).profile||{}).info_cache||{}}catch{}let r=[];try{r=m.readdirSync(e).filter(s=>/^(Default|Profile \d+)$/.test(s)&&m.existsSync(p.join(e,s,"Preferences")))}catch{}let n=[];for(let s of new Set([...Object.keys(t),...r]))m.existsSync(p.join(e,s))&&n.push({dir:s,name:t[s]&&t[s].name||s,email:t[s]&&t[s].user_name||""});return n}function Me(e){let t=ee(),r=String(e||"").toLowerCase();return t.find(n=>n.dir===e)||t.find(n=>n.name.toLowerCase()===r)||t.find(n=>n.email.toLowerCase()===r)||null}function $(){let e=N();if(!m.existsSync(e))return null;let t=D(),r=Me(t);return r?{udd:e,dir:r.dir}:m.existsSync(p.join(e,t))?{udd:e,dir:t}:null}function Te(){let e=String(process.env.REFLEX_PROFILE||"").toLowerCase();return!(e==="off"||e==="0"||e==="false"||e==="no")}function q(e){let t=process.env.REFLEX_PROFILE_DIR||p.join(Q,"profile"),r=e&&e!=="default"?String(e).replace(/[^a-zA-Z0-9_-]/g,"_"):"";return r?`${t}-${r}`:t}function Tt(e,t){if(process.platform!=="darwin")return!1;try{return Ae("/bin/cp",["-c",e,t],{stdio:"ignore"}),!0}catch{return!1}}function Z(e,t,r){if(m.existsSync(e)){if(m.mkdirSync(p.dirname(t),{recursive:!0}),!Tt(e,t))try{m.copyFileSync(e,t)}catch{return}r&&r.push(t)}}function Nt(e,t,r){if(m.existsSync(e)){if(m.mkdirSync(p.dirname(t),{recursive:!0}),process.platform==="darwin")try{Ae("/bin/cp",["-Rc",e,t],{stdio:"ignore"}),r&&r.push(t+"/");return}catch{}try{m.cpSync(e,t,{recursive:!0}),r&&r.push(t+"/")}catch{}}}function C(e){try{return m.readdirSync(e).length>0}catch{return!1}}function te(e){let t=$();if(!t)return{seeded:!1,reason:"no-source",message:`Chrome profile "${D()}" not found (is Google Chrome installed?)`};let r=p.join(t.udd,t.dir),n=p.join(e,"Default");m.mkdirSync(n,{recursive:!0,mode:448});let s=Pt(),o=[];for(let i of s.rootFiles)Z(p.join(t.udd,i),p.join(e,i),o);for(let i of s.files)if(Z(p.join(r,i),p.join(n,i),o),s.sqlite.has(i))for(let l of["-wal","-shm","-journal"])Z(p.join(r,i+l),p.join(n,i+l),null);for(let i of s.dirs)Nt(p.join(r,i),p.join(n,i),o);try{m.chmodSync(e,448)}catch{}return{seeded:!0,copied:o,source:t.dir,dir:e}}function Dt(e){return C(e)?{seeded:!1,reason:"exists",dir:e}:te(e)}function Ne(e){try{m.rmSync(e,{recursive:!0,force:!0})}catch{}}function $t(e){let t=q(e===void 0?process.env.REFLEX_SESSION:e);if(Ne(t),C(t))return{ok:!1,text:`profile sync: could not clear ${t} \u2014 a Reflex browser may still be running. Try: reflex stop`};let r=te(t);return r.seeded?{ok:!0,text:`profile synced: ${r.copied.length} item(s) from Chrome "${r.source}" -> ${t}`}:{ok:!1,text:`profile sync failed: ${r.message||r.reason}`}}function qt(e){let t=q(e===void 0?process.env.REFLEX_SESSION:e);return Ne(t),C(t)?{ok:!1,text:`profile reset: could not fully remove ${t} \u2014 a browser may still be using it. Try: reflex stop`}:{ok:!0,text:`profile reset: removed ${t}; it will re-seed from Chrome on next open`}}function Ct(e){let t=Me(e);if(!t)return{ok:!1,text:`no Chrome profile matches "${e}". Run: reflex profile list`};let r=Pe();return r.source=t.dir,Mt(r),{ok:!0,text:`source profile set to "${t.name}" (dir ${t.dir}). Run: reflex profile sync (or reflex stop) to apply.`}}function Xt(){let e=Te(),t=$(),r=q(process.env.REFLEX_SESSION),n=[];return n.push(e?"profile mode: on (persistent browser \u2014 log into each site once, it stays signed in across runs)":"profile mode: off (clean browser each run; set REFLEX_PROFILE=on to enable)"),process.platform==="darwin"?n.push("macOS: cookies/passwords are NOT copied from Chrome (they are Keychain-encrypted and an automation browser cannot decrypt them). Bookmarks are seeded; sign into each site once."):n.push(`seeds logins from Chrome profile: ${D()}${t?` (dir "${t.dir}")`:" \u2014 NOT FOUND"}`),n.push(`reflex profile dir: ${r} (${C(r)?"active":"created on next open"})`),n.join(` | ||
| <body><div class="c"><div class="t">${e}</div><div class="s">${t}</div></div></body></html>`}Re.exports={login:At,logout:jt,loadKey:Ft,saveKey:Le,openBrowser:Oe,SITE_BASE:ke,API_BASE:_e,_authFile:E}});var re=S((Fr,De)=>{"use strict";var m=require("fs"),d=require("path"),je=require("os"),{execFileSync:Ae}=require("child_process"),Q=process.env.REFLEX_HOME||d.join(je.homedir(),".reflex"),Ie=d.join(Q,"profile-config.json");function Pt(){return process.platform==="darwin"?{rootFiles:[],files:["Bookmarks","Bookmarks.bak"],dirs:[],sqlite:new Set}:{rootFiles:["Local State"],files:["Cookies","Network/Cookies","Network/TransportSecurity","Login Data","Login Data For Account","Bookmarks","Bookmarks.bak"],dirs:["Local Storage"],sqlite:new Set(["Cookies","Network/Cookies","Login Data","Login Data For Account"])}}function N(){if(process.env.REFLEX_CHROME_USER_DATA)return process.env.REFLEX_CHROME_USER_DATA;let e=je.homedir();return process.platform==="darwin"?d.join(e,"Library","Application Support","Google","Chrome"):process.platform==="win32"?d.join(process.env.LOCALAPPDATA||d.join(e,"AppData","Local"),"Google","Chrome","User Data"):d.join(e,".config","google-chrome")}function Pe(){try{return JSON.parse(m.readFileSync(Ie,"utf8"))||{}}catch{return{}}}function Mt(e){m.mkdirSync(Q,{recursive:!0,mode:448}),m.writeFileSync(Ie,JSON.stringify(e,null,1),{mode:384})}function D(){return process.env.REFLEX_CHROME_PROFILE||Pe().source||"Default"}function ee(){let e=N(),t={};try{t=(JSON.parse(m.readFileSync(d.join(e,"Local State"),"utf8")).profile||{}).info_cache||{}}catch{}let r=[];try{r=m.readdirSync(e).filter(s=>/^(Default|Profile \d+)$/.test(s)&&m.existsSync(d.join(e,s,"Preferences")))}catch{}let n=[];for(let s of new Set([...Object.keys(t),...r]))m.existsSync(d.join(e,s))&&n.push({dir:s,name:t[s]&&t[s].name||s,email:t[s]&&t[s].user_name||""});return n}function Me(e){let t=ee(),r=String(e||"").toLowerCase();return t.find(n=>n.dir===e)||t.find(n=>n.name.toLowerCase()===r)||t.find(n=>n.email.toLowerCase()===r)||null}function $(){let e=N();if(!m.existsSync(e))return null;let t=D(),r=Me(t);return r?{udd:e,dir:r.dir}:m.existsSync(d.join(e,t))?{udd:e,dir:t}:null}function Te(){let e=String(process.env.REFLEX_PROFILE||"").toLowerCase();return!(e==="off"||e==="0"||e==="false"||e==="no")}function q(e){let t=process.env.REFLEX_PROFILE_DIR||d.join(Q,"profile"),r=e&&e!=="default"?String(e).replace(/[^a-zA-Z0-9_-]/g,"_"):"";return r?`${t}-${r}`:t}function Tt(e,t){if(process.platform!=="darwin")return!1;try{return Ae("/bin/cp",["-c",e,t],{stdio:"ignore"}),!0}catch{return!1}}function Z(e,t,r){if(m.existsSync(e)){if(m.mkdirSync(d.dirname(t),{recursive:!0}),!Tt(e,t))try{m.copyFileSync(e,t)}catch{return}r&&r.push(t)}}function Nt(e,t,r){if(m.existsSync(e)){if(m.mkdirSync(d.dirname(t),{recursive:!0}),process.platform==="darwin")try{Ae("/bin/cp",["-Rc",e,t],{stdio:"ignore"}),r&&r.push(t+"/");return}catch{}try{m.cpSync(e,t,{recursive:!0}),r&&r.push(t+"/")}catch{}}}function C(e){try{return m.readdirSync(e).length>0}catch{return!1}}function te(e){let t=$();if(!t)return{seeded:!1,reason:"no-source",message:`Chrome profile "${D()}" not found (is Google Chrome installed?)`};let r=d.join(t.udd,t.dir),n=d.join(e,"Default");m.mkdirSync(n,{recursive:!0,mode:448});let s=Pt(),o=[];for(let i of s.rootFiles)Z(d.join(t.udd,i),d.join(e,i),o);for(let i of s.files)if(Z(d.join(r,i),d.join(n,i),o),s.sqlite.has(i))for(let l of["-wal","-shm","-journal"])Z(d.join(r,i+l),d.join(n,i+l),null);for(let i of s.dirs)Nt(d.join(r,i),d.join(n,i),o);try{m.chmodSync(e,448)}catch{}return{seeded:!0,copied:o,source:t.dir,dir:e}}function Dt(e){return C(e)?{seeded:!1,reason:"exists",dir:e}:te(e)}function Ne(e){try{m.rmSync(e,{recursive:!0,force:!0})}catch{}}function $t(e){let t=q(e===void 0?process.env.REFLEX_SESSION:e);if(Ne(t),C(t))return{ok:!1,text:`profile sync: could not clear ${t} \u2014 a Reflex browser may still be running. Try: reflex stop`};let r=te(t);return r.seeded?{ok:!0,text:`profile synced: ${r.copied.length} item(s) from Chrome "${r.source}" -> ${t}`}:{ok:!1,text:`profile sync failed: ${r.message||r.reason}`}}function qt(e){let t=q(e===void 0?process.env.REFLEX_SESSION:e);return Ne(t),C(t)?{ok:!1,text:`profile reset: could not fully remove ${t} \u2014 a browser may still be using it. Try: reflex stop`}:{ok:!0,text:`profile reset: removed ${t}; it will re-seed from Chrome on next open`}}function Ct(e){let t=Me(e);if(!t)return{ok:!1,text:`no Chrome profile matches "${e}". Run: reflex profile list`};let r=Pe();return r.source=t.dir,Mt(r),{ok:!0,text:`source profile set to "${t.name}" (dir ${t.dir}). Run: reflex profile sync (or reflex stop) to apply.`}}function Xt(){let e=Te(),t=$(),r=q(process.env.REFLEX_SESSION),n=[];return n.push(e?"profile mode: on (persistent browser \u2014 log into each site once, it stays signed in across runs)":"profile mode: off (clean browser each run; set REFLEX_PROFILE=on to enable)"),process.platform==="darwin"?n.push("macOS: cookies/passwords are NOT copied from Chrome (they are Keychain-encrypted and an automation browser cannot decrypt them). Bookmarks are seeded; sign into each site once."):n.push(`seeds logins from Chrome profile: ${D()}${t?` (dir "${t.dir}")`:" \u2014 NOT FOUND"}`),n.push(`reflex profile dir: ${r} (${C(r)?"active":"created on next open"})`),n.join(` | ||
| `)}function Ht(){let e=ee();if(!e.length)return`no Chrome profiles found under ${N()}`;let t=($()||{}).dir;return["Chrome profiles available to copy from:",...e.map(n=>` ${n.dir.padEnd(11)} ${String(n.name).padEnd(16)} ${n.email||""}${n.dir===t?" <- current source":""}`),"",'use: reflex profile use "<name or dir>"'].join(` | ||
| `)}De.exports={enabled:Te,targetDir:q,seedIfNeeded:Dt,seed:te,sync:$t,reset:qt,use:Ct,listSources:ee,resolveSourceDir:$,sourceSelector:D,statusText:Xt,listSourcesText:Ht,chromeUserDataDir:N}});var Qe=S((jr,Ze)=>{"use strict";var x=require("fs"),Bt=require("os"),B=require("path"),U=1,Xe=150,X=8e3,Ut=30,ne=3,se=100,oe=10,zt=12,He=2,ie=500,Jt=40,Be=new Set(["fill","type","click","dblclick","check","uncheck","select","press"]),ae="paths seen here before (use ONLY if they match your current goal, else ignore and use the live snapshot below; act by name):";function Gt(){return process.env.REFLEX_HOME||B.join(Bt.homedir(),".reflex")}function Kt(){return B.join(Gt(),"memory")}function j(e){return B.join(Kt(),e+".json")}function b(e){let t="";try{let r=new URL(e);r.protocol==="file:"?t=r.pathname.split("/").filter(Boolean).pop()||"":t=(r.hostname||"").replace(/^www\./,"")}catch{return null}return t=t.toLowerCase().replace(/[^a-z0-9.-]/g,"_"),/^\.+$/.test(t)?null:t||null}function Yt(e){let t=5381;for(let r=0;r<e.length;r++)t=(t*33^e.charCodeAt(r))>>>0;return t.toString(36)}function ce(e){return Yt(e.map(t=>t.k+"|"+t.name).join(">"))}function Ue(e){return String(e||"").trim().replace(/\s+/g," ").toLowerCase()}var Vt=1e3,Wt=3,y=new Map,R=null,$e=!1;function H(e){try{let t=x.statSync(e);return{mtimeMs:t.mtimeMs,size:t.size}}catch{return null}}function ze(e){try{let t=JSON.parse(x.readFileSync(e,"utf8"));if(t&&t.v===U&&Array.isArray(t.paths))return t}catch{}return null}function k(e){let t=j(e),r=y.get(t);if(r&&r.pending.length)return r.obj;let n=H(t);if(r&&n&&n.mtimeMs===r.mtimeMs&&n.size===r.size)return r.obj;let s=n?ze(t):null;return s&&n?y.set(t,{file:t,domain:e,obj:s,mtimeMs:n.mtimeMs,size:n.size,pending:[]}):y.delete(t),s}function Je(){return Date.now()-Ut*864e5}function Ge(e){try{return new URL(e).pathname.replace(/\d+/g,"*")||"/"}catch{return null}}function Zt(e){if(!e.length)return X;let t=[...e].sort((r,n)=>r-n);return t[Math.min(t.length-1,Math.floor(t.length*.9))]}function Qt(e){let t=b(e);if(!t)return null;let r=k(t);if(!r||!r.settle)return null;let n=Je(),s=(r.settle.times||[]).filter(l=>l&&l.at&&Date.parse(l.at)>n).map(l=>l.ms),o=(r.settle.heartbeats||[]).filter(l=>l&&l.pattern&&l.lastSeen&&Date.parse(l.lastSeen)>n&&(l.hits||0)>=2).map(l=>l.pattern);return s.length<ne&&!o.length?null:{capMs:s.length>=ne?Math.max(Xe,Math.min(X,Math.ceil(Zt(s)*1.1))):X,heartbeats:o}}function Ke(e,t){e.settle||(e.settle={times:[],heartbeats:[]});let r=e.settle;if(r.times.push({ms:t.ms,at:t.at}),r.times.length>se&&(r.times=r.times.slice(-se)),t.activeUrls){let s=new Map((r.heartbeats||[]).map(o=>[o.pattern,o]));for(let o of t.activeUrls){let i=Ge(o);if(!i)continue;let l=s.get(i)||{pattern:i,hits:0,firstSeen:t.at,lastSeen:t.at};l.hits=(l.hits||0)+1,l.lastSeen=t.at,s.set(i,l)}r.heartbeats=[...s.values()].slice(-40)}let n=Je();r.times=r.times.filter(s=>s.at&&Date.parse(s.at)>n),r.heartbeats=(r.heartbeats||[]).filter(s=>s.lastSeen&&Date.parse(s.lastSeen)>n)}function er(e,{ms:t,activeUrls:r,domChanged:n}){let s=b(e);if(!s||!Number.isFinite(t))return;let o={ms:t,at:new Date().toISOString(),activeUrls:!n&&Array.isArray(r)?r.slice():null},i=j(s),l=k(s)||{v:U,domain:s,paths:[]};Ke(l,o);let c=y.get(i);(!c||c.obj!==l)&&(c={file:i,domain:s,obj:l,mtimeMs:0,size:0,pending:[]},y.set(i,c)),c.pending.push(o),c.pending.length>=Wt?le(c):tr()}function le(e){if(!e||!e.pending.length)return;let t=H(e.file);if((t?t.mtimeMs:0)!==e.mtimeMs||(t?t.size:0)!==e.size){let n=(t?ze(e.file):null)||{v:U,domain:e.domain,paths:[]};for(let s of e.pending)Ke(n,s);e.obj=n}let r=e.pending;if(e.pending=[],Ye(e.file,e.obj)){let n=H(e.file);e.mtimeMs=n?n.mtimeMs:0,e.size=n?n.size:0}else e.pending=r.slice(-se)}function qe(){for(let e of[...y.values()])try{le(e)}catch{}}function tr(){if(!R&&(R=setTimeout(()=>{R=null,qe()},Vt),R.unref&&R.unref(),!$e)){$e=!0;try{process.once("exit",qe)}catch{}}}function Ye(e,t){try{let r=B.dirname(e);x.mkdirSync(r,{recursive:!0,mode:448});try{x.chmodSync(r,448)}catch{}let n=e+".tmp."+process.pid;return x.writeFileSync(n,JSON.stringify(t),{mode:384}),x.renameSync(n,e),!0}catch{return!1}}function rr(e,t){let r=j(e);if(!Ye(r,t))return;let n=H(r);y.set(r,{file:r,domain:e,obj:t,mtimeMs:n?n.mtimeMs:0,size:n?n.size:0,pending:[]})}var nr=new Set(["fill","type","select"]),Ce=/^[a-z0-9]{5}$/,sr=/^\s*(?:css|xpath)\s*=/i;function Ve(e){let t=e&&e.step;if(!t||typeof t!="object")return"";let r=Object.keys(t)[0];if(!Be.has(r))return"";let n=t[r],s=nr.has(r),o="";if(Array.isArray(n)?o=n[0]:n&&typeof n=="object"?o=n.target:!s&&typeof n=="string"&&(o=n),o=typeof o=="string"?o.trim():"",o&&!Ce.test(o)&&!sr.test(o))return o.slice(0,80);if(!s){let i=(e.resolvedName||"").trim();if(i&&!Ce.test(i))return i.slice(0,80)}return""}function We(e){let t=[];for(let r of e||[]){let n=r&&r.step&&typeof r.step=="object"?Object.keys(r.step)[0]:null;if(!n||!Be.has(n))continue;let s=Ve(r);if(s&&(t.push({k:n,name:s}),t.length>=zt))break}return t}function F(e,t){if(e.length>t.length)return!1;for(let r=0;r<e.length;r++)if(e[r].k!==t[r].k||e[r].name!==t[r].name)return!1;return!0}var or=2;function ir(e,t){let r=e.replace(/[^a-zA-Z0-9_-]/g,"_");if(!t||t==="/")return r;let n=t.replace(/^\/+|\/+$/g,"").replace(/[^a-zA-Z0-9_-]+/g,"_").slice(0,40);return n?`${r}_${n}`:r}function ar(e,t){let r=b(e);if(!r)return null;let n=We(t);if(n.length<or)return null;let s="/";try{s=new URL(e).pathname||"/"}catch{}let o=new Date().toISOString(),i=y.get(j(r));i&&i.pending.length&&le(i);let l=k(r)||{v:U,domain:r,paths:[]},c=ce(n),a=null,u=l.paths.find(f=>f.sig===c);if(u)u.count=(u.count||1)+1,u.lastSeen=o,u.steps=n,u.entryPath=s,a=u;else{let f=l.paths.find(h=>F(h.steps,n)||F(n,h.steps));if(f){let h=n.length>=f.steps.length?n:f.steps;f.steps=h,f.sig=ce(h),f.count=(f.count||1)+1,f.lastSeen=o,f.entryPath=s,a=f}else l.paths.push({sig:c,steps:n,entryPath:s,count:1,firstSeen:o,lastSeen:o}),a=l.paths[l.paths.length-1]}l.paths.sort((f,h)=>Date.parse(h.lastSeen)-Date.parse(f.lastSeen)||(h.count||0)-(f.count||0)),l.paths.length>oe&&(l.paths.length=oe);let d=null;return a&&a.count===3&&a.steps.length>=3&&!a.suggested&&(a.suggested=!0,d=`note: 3rd time on this path; save it: flow save ${ir(r,a.entryPath||s)} --last ${t.length} (replays with 0 turns)`),rr(r,l),d}function cr(e){let t=b(e);if(!t)return[];let r=k(t);return r?r.paths:[]}function lr(e){let t=new Set;if(e&&Array.isArray(e.interactives))for(let r of e.interactives)r&&r.vis!==!1&&r.name&&t.add(Ue(r.name));return t}function ur(e){return e.steps.map(t=>`${t.k} "${t.name.slice(0,Jt)}"`).join(" -> ")}function fr(e,t){let r=b(e);if(!r)return null;let n=k(r);if(!n||!n.paths.length)return null;let s=lr(t),o=n.paths.filter(a=>a.steps.some(u=>!s.has(Ue(u.name))));if(!o.length)return null;let i="";try{i=new URL(e).pathname||"/"}catch{}o.sort((a,u)=>{let d=a.entryPath===i?1:0,f=u.entryPath===i?1:0;return d!==f?f-d:Date.parse(u.lastSeen)-Date.parse(a.lastSeen)||(u.count||0)-(a.count||0)});let l=[];for(let a of o){if(l.length>=He)break;l.some(u=>u.sig===a.sig||F(a.steps,u.steps)||F(u.steps,a.steps))||l.push(a)}let c=[ae];for(let a of l){let u="- "+ur(a);if(c.concat(u).join(` | ||
| `).length<=ie)c.push(u);else if(c.length===1){let d=ie-ae.length-1;d>16&&c.push(u.slice(0,d-4)+" ...");break}else break}return c.length===1?null:c.join(` | ||
| `)}Ze.exports={record:ar,recall:fr,paths:cr,domainOf:b,getSettleProfile:Qt,recordSettleObservation:er,urlPattern:Ge,_sig:ce,_read:k,_domainFile:j,_pathFromHistory:We,_landmark:Ve,_isPrefix:F,_HEADER:ae,MEMORY_BLOCK_MAX:ie,MAX_PATHS_PER_DOMAIN:oe,RECALL_N:He,SETTLE_FLOOR_MS:Xe,SETTLE_GLOBAL_CAP:X,SETTLE_MIN_SAMPLES:ne}});var tt=S((Ar,et)=>{"use strict";function dr(e){let t=String(e||"").split(/\n(?:url:|changes before failure:|screenshot:)/)[0];return/needs a target|provide (?:ms|a)|must be a|bad step|non-empty|file not found on disk|invalid (?:css|xpath) selector/i.test(t)?"baduse":/expect failed/i.test(t)?"assertion":/ambiguous|candidates:|near miss|no (?:exact )?match|no element|not found|could not (?:find|resolve)|couldn'?t resolve|(?:target|ref) not (?:resolved|found)/i.test(t)?"resolution":/disconnected|browser (?:restarted|disconnected)|page state was lost|net::|ERR_|navigation/i.test(t)?"navigation":/intercepts pointer events|not clickable|is hidden|resolved but not visible|outside of the viewport|element is not|not actionable|not stable/i.test(t)?"interaction":/expect|expected|assertion|still (?:visible|present)|not visible/i.test(t)?"assertion":/timed out|timeout|time limit|exceeded.*s/i.test(t)?"timeout":"other"}et.exports={classifyFailure:dr}});var at=S((Ir,it)=>{"use strict";var A=require("fs"),pr=require("os"),nt=require("path"),{domainOf:mr}=Qe(),{classifyFailure:hr}=tt(),rt=1;function st(){return process.env.REFLEX_HOME||nt.join(pr.homedir(),".reflex")}function ue(){return nt.join(st(),"failure-rollup.json")}function fe(){try{let e=JSON.parse(A.readFileSync(ue(),"utf8"));if(e&&e.v===rt&&e.domains&&typeof e.domains=="object")return e}catch{}return{v:rt,domains:{},updated:null}}function gr(e){try{let t=st();A.mkdirSync(t,{recursive:!0,mode:448});try{A.chmodSync(t,448)}catch{}let r=ue(),n=r+".tmp."+process.pid;e.updated=new Date().toISOString(),A.writeFileSync(n,JSON.stringify(e,null,2),{mode:384}),A.renameSync(n,r)}catch{}}function ot(e,t){let r=mr(e);if(!r||!t)return;let n=fe();n.domains[r]||(n.domains[r]={total:0,cats:{}});let s=n.domains[r];s.total=(s.total||0)+1,s.cats[t]=(s.cats[t]||0)+1,s.lastSeen=new Date().toISOString(),gr(n)}function yr(e,t){try{ot(e,hr(t))}catch{}}function Sr(){let e=fe(),t=Object.entries(e.domains||{});if(!t.length)return"failure rollup: (empty \u2014 no recorded failures yet)";t.sort((n,s)=>(s[1].total||0)-(n[1].total||0));let r=["failure rollup (local only, category counts per domain):"];for(let[n,s]of t.slice(0,20)){let o=Object.entries(s.cats||{}).sort((i,l)=>l[1]-i[1]).map(([i,l])=>`${i}:${l}`).join(", ");r.push(` ${n}: ${s.total||0} (${o})`)}return t.length>20&&r.push(` \u2026 ${t.length-20} more domains`),e.updated&&r.push(`updated: ${e.updated}`),r.join(` | ||
| `)}it.exports={recordFailure:ot,recordForensic:yr,format:Sr,_read:fe,rollupFile:ue}});var ct=require("fs"),{readState:lt,rpc:de,ensureDaemon:Er,subEnv:wr,STATE_FILE:xr}=xe(),br=`reflex: token-efficient browser automation for AI agents | ||
| `)}De.exports={enabled:Te,targetDir:q,seedIfNeeded:Dt,seed:te,sync:$t,reset:qt,use:Ct,listSources:ee,resolveSourceDir:$,sourceSelector:D,statusText:Xt,listSourcesText:Ht,chromeUserDataDir:N}});var Qe=S((jr,Ze)=>{"use strict";var x=require("fs"),Ut=require("os"),U=require("path"),B=1,Xe=150,X=8e3,Bt=30,ne=3,se=100,oe=10,zt=12,He=2,ie=500,Jt=40,Ue=new Set(["fill","type","click","dblclick","check","uncheck","select","press"]),ae="paths seen here before (use ONLY if they match your current goal, else ignore and use the live snapshot below; act by name):";function Gt(){return process.env.REFLEX_HOME||U.join(Ut.homedir(),".reflex")}function Kt(){return U.join(Gt(),"memory")}function j(e){return U.join(Kt(),e+".json")}function b(e){let t="";try{let r=new URL(e);r.protocol==="file:"?t=r.pathname.split("/").filter(Boolean).pop()||"":t=(r.hostname||"").replace(/^www\./,"")}catch{return null}return t=t.toLowerCase().replace(/[^a-z0-9.-]/g,"_"),/^\.+$/.test(t)?null:t||null}function Yt(e){let t=5381;for(let r=0;r<e.length;r++)t=(t*33^e.charCodeAt(r))>>>0;return t.toString(36)}function ce(e){return Yt(e.map(t=>t.k+"|"+t.name).join(">"))}function Be(e){return String(e||"").trim().replace(/\s+/g," ").toLowerCase()}var Wt=1e3,Vt=3,y=new Map,R=null,$e=!1;function H(e){try{let t=x.statSync(e);return{mtimeMs:t.mtimeMs,size:t.size}}catch{return null}}function ze(e){try{let t=JSON.parse(x.readFileSync(e,"utf8"));if(t&&t.v===B&&Array.isArray(t.paths))return t}catch{}return null}function k(e){let t=j(e),r=y.get(t);if(r&&r.pending.length)return r.obj;let n=H(t);if(r&&n&&n.mtimeMs===r.mtimeMs&&n.size===r.size)return r.obj;let s=n?ze(t):null;return s&&n?y.set(t,{file:t,domain:e,obj:s,mtimeMs:n.mtimeMs,size:n.size,pending:[]}):y.delete(t),s}function Je(){return Date.now()-Bt*864e5}function Ge(e){try{return new URL(e).pathname.replace(/\d+/g,"*")||"/"}catch{return null}}function Zt(e){if(!e.length)return X;let t=[...e].sort((r,n)=>r-n);return t[Math.min(t.length-1,Math.floor(t.length*.9))]}function Qt(e){let t=b(e);if(!t)return null;let r=k(t);if(!r||!r.settle)return null;let n=Je(),s=(r.settle.times||[]).filter(l=>l&&l.at&&Date.parse(l.at)>n).map(l=>l.ms),o=(r.settle.heartbeats||[]).filter(l=>l&&l.pattern&&l.lastSeen&&Date.parse(l.lastSeen)>n&&(l.hits||0)>=2).map(l=>l.pattern);return s.length<ne&&!o.length?null:{capMs:s.length>=ne?Math.max(Xe,Math.min(X,Math.ceil(Zt(s)*1.1))):X,heartbeats:o}}function Ke(e,t){e.settle||(e.settle={times:[],heartbeats:[]});let r=e.settle;if(r.times.push({ms:t.ms,at:t.at}),r.times.length>se&&(r.times=r.times.slice(-se)),t.activeUrls){let s=new Map((r.heartbeats||[]).map(o=>[o.pattern,o]));for(let o of t.activeUrls){let i=Ge(o);if(!i)continue;let l=s.get(i)||{pattern:i,hits:0,firstSeen:t.at,lastSeen:t.at};l.hits=(l.hits||0)+1,l.lastSeen=t.at,s.set(i,l)}r.heartbeats=[...s.values()].slice(-40)}let n=Je();r.times=r.times.filter(s=>s.at&&Date.parse(s.at)>n),r.heartbeats=(r.heartbeats||[]).filter(s=>s.lastSeen&&Date.parse(s.lastSeen)>n)}function er(e,{ms:t,activeUrls:r,domChanged:n}){let s=b(e);if(!s||!Number.isFinite(t))return;let o={ms:t,at:new Date().toISOString(),activeUrls:!n&&Array.isArray(r)?r.slice():null},i=j(s),l=k(s)||{v:B,domain:s,paths:[]};Ke(l,o);let c=y.get(i);(!c||c.obj!==l)&&(c={file:i,domain:s,obj:l,mtimeMs:0,size:0,pending:[]},y.set(i,c)),c.pending.push(o),c.pending.length>=Vt?le(c):tr()}function le(e){if(!e||!e.pending.length)return;let t=H(e.file);if((t?t.mtimeMs:0)!==e.mtimeMs||(t?t.size:0)!==e.size){let n=(t?ze(e.file):null)||{v:B,domain:e.domain,paths:[]};for(let s of e.pending)Ke(n,s);e.obj=n}let r=e.pending;if(e.pending=[],Ye(e.file,e.obj)){let n=H(e.file);e.mtimeMs=n?n.mtimeMs:0,e.size=n?n.size:0}else e.pending=r.slice(-se)}function qe(){for(let e of[...y.values()])try{le(e)}catch{}}function tr(){if(!R&&(R=setTimeout(()=>{R=null,qe()},Wt),R.unref&&R.unref(),!$e)){$e=!0;try{process.once("exit",qe)}catch{}}}function Ye(e,t){try{let r=U.dirname(e);x.mkdirSync(r,{recursive:!0,mode:448});try{x.chmodSync(r,448)}catch{}let n=e+".tmp."+process.pid;return x.writeFileSync(n,JSON.stringify(t),{mode:384}),x.renameSync(n,e),!0}catch{return!1}}function rr(e,t){let r=j(e);if(!Ye(r,t))return;let n=H(r);y.set(r,{file:r,domain:e,obj:t,mtimeMs:n?n.mtimeMs:0,size:n?n.size:0,pending:[]})}var nr=new Set(["fill","type","select"]),Ce=/^[a-z0-9]{5}$/,sr=/^\s*(?:css|xpath)\s*=/i;function We(e){let t=e&&e.step;if(!t||typeof t!="object")return"";let r=Object.keys(t)[0];if(!Ue.has(r))return"";let n=t[r],s=nr.has(r),o="";if(Array.isArray(n)?o=n[0]:n&&typeof n=="object"?o=n.target:!s&&typeof n=="string"&&(o=n),o=typeof o=="string"?o.trim():"",o&&!Ce.test(o)&&!sr.test(o))return o.slice(0,80);if(!s){let i=(e.resolvedName||"").trim();if(i&&!Ce.test(i))return i.slice(0,80)}return""}function Ve(e){let t=[];for(let r of e||[]){let n=r&&r.step&&typeof r.step=="object"?Object.keys(r.step)[0]:null;if(!n||!Ue.has(n))continue;let s=We(r);if(s&&(t.push({k:n,name:s}),t.length>=zt))break}return t}function F(e,t){if(e.length>t.length)return!1;for(let r=0;r<e.length;r++)if(e[r].k!==t[r].k||e[r].name!==t[r].name)return!1;return!0}var or=2;function ir(e,t){let r=e.replace(/[^a-zA-Z0-9_-]/g,"_");if(!t||t==="/")return r;let n=t.replace(/^\/+|\/+$/g,"").replace(/[^a-zA-Z0-9_-]+/g,"_").slice(0,40);return n?`${r}_${n}`:r}function ar(e,t){let r=b(e);if(!r)return null;let n=Ve(t);if(n.length<or)return null;let s="/";try{s=new URL(e).pathname||"/"}catch{}let o=new Date().toISOString(),i=y.get(j(r));i&&i.pending.length&&le(i);let l=k(r)||{v:B,domain:r,paths:[]},c=ce(n),a=null,u=l.paths.find(f=>f.sig===c);if(u)u.count=(u.count||1)+1,u.lastSeen=o,u.steps=n,u.entryPath=s,a=u;else{let f=l.paths.find(h=>F(h.steps,n)||F(n,h.steps));if(f){let h=n.length>=f.steps.length?n:f.steps;f.steps=h,f.sig=ce(h),f.count=(f.count||1)+1,f.lastSeen=o,f.entryPath=s,a=f}else l.paths.push({sig:c,steps:n,entryPath:s,count:1,firstSeen:o,lastSeen:o}),a=l.paths[l.paths.length-1]}l.paths.sort((f,h)=>Date.parse(h.lastSeen)-Date.parse(f.lastSeen)||(h.count||0)-(f.count||0)),l.paths.length>oe&&(l.paths.length=oe);let p=null;return a&&a.count===3&&a.steps.length>=3&&!a.suggested&&(a.suggested=!0,p={slug:ir(r,a.entryPath||s),steps:a.steps.length}),rr(r,l),p}function cr(e){let t=b(e);if(!t)return[];let r=k(t);return r?r.paths:[]}function lr(e){let t=new Set;if(e&&Array.isArray(e.interactives))for(let r of e.interactives)r&&r.vis!==!1&&r.name&&t.add(Be(r.name));return t}function ur(e){return e.steps.map(t=>`${t.k} "${t.name.slice(0,Jt)}"`).join(" -> ")}function fr(e,t){let r=b(e);if(!r)return null;let n=k(r);if(!n||!n.paths.length)return null;let s=lr(t),o=n.paths.filter(a=>a.steps.some(u=>!s.has(Be(u.name))));if(!o.length)return null;let i="";try{i=new URL(e).pathname||"/"}catch{}o.sort((a,u)=>{let p=a.entryPath===i?1:0,f=u.entryPath===i?1:0;return p!==f?f-p:Date.parse(u.lastSeen)-Date.parse(a.lastSeen)||(u.count||0)-(a.count||0)});let l=[];for(let a of o){if(l.length>=He)break;l.some(u=>u.sig===a.sig||F(a.steps,u.steps)||F(u.steps,a.steps))||l.push(a)}let c=[ae];for(let a of l){let u="- "+ur(a);if(c.concat(u).join(` | ||
| `).length<=ie)c.push(u);else if(c.length===1){let p=ie-ae.length-1;p>16&&c.push(u.slice(0,p-4)+" ...");break}else break}return c.length===1?null:c.join(` | ||
| `)}Ze.exports={record:ar,recall:fr,paths:cr,domainOf:b,getSettleProfile:Qt,recordSettleObservation:er,urlPattern:Ge,_sig:ce,_read:k,_domainFile:j,_pathFromHistory:Ve,_landmark:We,_isPrefix:F,_HEADER:ae,MEMORY_BLOCK_MAX:ie,MAX_PATHS_PER_DOMAIN:oe,RECALL_N:He,SETTLE_FLOOR_MS:Xe,SETTLE_GLOBAL_CAP:X,SETTLE_MIN_SAMPLES:ne}});var tt=S((Ar,et)=>{"use strict";function pr(e){let t=String(e||"").split(/\n(?:url:|changes before failure:|screenshot:)/)[0];return/needs a target|provide (?:ms|a)|must be a|bad step|non-empty|file not found on disk|invalid (?:css|xpath) selector/i.test(t)?"baduse":/expect failed/i.test(t)?"assertion":/ambiguous|candidates:|near miss|no (?:exact )?match|no element|not found|could not (?:find|resolve)|couldn'?t resolve|(?:target|ref) not (?:resolved|found)/i.test(t)?"resolution":/disconnected|browser (?:restarted|disconnected)|page state was lost|net::|ERR_|navigation/i.test(t)?"navigation":/intercepts pointer events|not clickable|is hidden|resolved but not visible|outside of the viewport|element is not|not actionable|not stable/i.test(t)?"interaction":/expect|expected|assertion|still (?:visible|present)|not visible/i.test(t)?"assertion":/timed out|timeout|time limit|exceeded.*s/i.test(t)?"timeout":"other"}et.exports={classifyFailure:pr}});var at=S((Ir,it)=>{"use strict";var A=require("fs"),dr=require("os"),nt=require("path"),{domainOf:mr}=Qe(),{classifyFailure:hr}=tt(),rt=1;function st(){return process.env.REFLEX_HOME||nt.join(dr.homedir(),".reflex")}function ue(){return nt.join(st(),"failure-rollup.json")}function fe(){try{let e=JSON.parse(A.readFileSync(ue(),"utf8"));if(e&&e.v===rt&&e.domains&&typeof e.domains=="object")return e}catch{}return{v:rt,domains:{},updated:null}}function gr(e){try{let t=st();A.mkdirSync(t,{recursive:!0,mode:448});try{A.chmodSync(t,448)}catch{}let r=ue(),n=r+".tmp."+process.pid;e.updated=new Date().toISOString(),A.writeFileSync(n,JSON.stringify(e,null,2),{mode:384}),A.renameSync(n,r)}catch{}}function ot(e,t){let r=mr(e);if(!r||!t)return;let n=fe();n.domains[r]||(n.domains[r]={total:0,cats:{}});let s=n.domains[r];s.total=(s.total||0)+1,s.cats[t]=(s.cats[t]||0)+1,s.lastSeen=new Date().toISOString(),gr(n)}function yr(e,t){try{ot(e,hr(t))}catch{}}function Sr(){let e=fe(),t=Object.entries(e.domains||{});if(!t.length)return"failure rollup: (empty \u2014 no recorded failures yet)";t.sort((n,s)=>(s[1].total||0)-(n[1].total||0));let r=["failure rollup (local only, category counts per domain):"];for(let[n,s]of t.slice(0,20)){let o=Object.entries(s.cats||{}).sort((i,l)=>l[1]-i[1]).map(([i,l])=>`${i}:${l}`).join(", ");r.push(` ${n}: ${s.total||0} (${o})`)}return t.length>20&&r.push(` \u2026 ${t.length-20} more domains`),e.updated&&r.push(`updated: ${e.updated}`),r.join(` | ||
| `)}it.exports={recordFailure:ot,recordForensic:yr,format:Sr,_read:fe,rollupFile:ue}});var ct=require("fs"),{readState:lt,rpc:pe,ensureDaemon:wr,subEnv:Er,STATE_FILE:xr}=xe(),br=`reflex: token-efficient browser automation for AI agents | ||
@@ -50,2 +50,6 @@ PERCEIVE | ||
| reflex state save <name> save cookies/localStorage (reuse: open --state) | ||
| Saving always includes the starting URL, so a flow replays from a cold browser. | ||
| Walk the same path 3 times and it is saved for you as auto-<slug>, with every typed value | ||
| replaced by a {{param}} you supply at replay time (REFLEX_AUTO_FLOW=0 to opt out). | ||
| Flows for the current site are listed when you open it, so you can replay instead of redoing. | ||
@@ -86,5 +90,7 @@ TABS (popups/target=_blank are followed automatically) | ||
| REFLEX_SITE_MEMORY set to 0 to disable per-site action-path priming on open (default on) | ||
| REFLEX_AUTO_FLOW set to 0 to stop auto-saving a path repeated 3x as a flow (default on; | ||
| auto flows are named auto-<slug> and store {{params}}, never typed values) | ||
| REFLEX_RAISE set to 0/false/no to stop open/tab from raising the browser and stealing focus (CLI default on; MCP defaults off) | ||
| REFLEX_OP_TIMEOUT_MS per-operation wall-clock cap in ms before abort + browser recycle (default 120000) | ||
| REFLEX_BATCH_DEADLINE_MS max wall-clock for one act batch before forensic abort (default 90000) | ||
| REFLEX_REAP_INTERVAL_MIN how often to reap orphaned browsers from dead daemons (default 30; 0 = off)`;function kr(e){let t={},r=[];for(let n=0;n<e.length;n++){let s=e[n];if(s.startsWith("--")){let o=s.slice(2);n+1<e.length&&!e[n+1].startsWith("--")?t[o]=t[o]!==void 0?[].concat(t[o],e[++n]):e[++n]:t[o]=!0}else r.push(s)}return{flags:t,pos:r}}function ut(e,t){try{return JSON.parse(e)}catch(r){console.error(`error: ${t} must be valid JSON: ${r.message}`),process.exit(2)}}async function _r(){let e=process.argv.slice(2),t=e[0];if(!t||t==="help"||t==="--help"||t==="-h"){console.log(br);return}let{flags:r,pos:n}=kr(e.slice(1));if(t==="login"||t==="logout"||t==="whoami"){let c=Fe();if(t==="logout"){console.log(c.logout()?"signed out":"not signed in");return}if(t==="whoami"){let a=c.loadKey();console.log(a?`signed in (key \u2026${a.slice(-4)})`:"not signed in (run: reflex login)");return}if(process.env.REFLEX_API_KEY){console.log("using REFLEX_API_KEY from the environment; no login needed");return}try{let a=await c.login({onUrl:u=>console.error("opening browser to: "+u)});console.log(`signed in${typeof a.balance=="number"?` (${a.balance} credits)`:""}`)}catch(a){console.error("login failed: "+a.message),process.exit(1)}return}if(t==="profile"){let c=re(),a=n[0]||"status";if(a==="status"){console.log(c.statusText());return}if(a==="list"){console.log(c.listSourcesText());return}if(a==="use"){n[1]||(console.error("usage: reflex profile use <name|dir>"),process.exit(2));let u=c.use(n.slice(1).join(" "));console.log(u.text),u.ok||process.exit(1);return}if(a==="sync"||a==="reset"){let u=lt();if(u&&u.pid){try{await de(u,"stop",{})}catch{}for(let f=0;f<60;f++){let h=!1;try{process.kill(u.pid,0),h=!0}catch{}if(!h)break;await new Promise(_=>setTimeout(_,100))}}let d=a==="sync"?c.sync():c.reset();console.log(d.text),d.ok===!1&&process.exit(1);return}console.error("usage: reflex profile status|list|use <name>|sync|reset"),process.exit(2)}if(t==="rollup"){console.log(at().format());return}let s;switch(t){case"open":{n[0]||(console.error("usage: reflex open <url>"),process.exit(2));let c=r.headless?!1:r.headed?!0:void 0;r.state&&re().enabled()&&console.error("note: --state is ignored while profile mode is on (the persistent profile is your session). Use REFLEX_PROFILE=off to load a saved --state."),s={cmd:"open",args:{url:n[0],headed:c,state:r.state,new_tab:!!r["new-tab"]}};break}case"read":s={cmd:"read",args:{query:r.query,full:!!r.full}};break;case"act":{let c=ut(n[0]==="-"?ct.readFileSync(0,"utf8"):n[0],"steps");s={cmd:"act",args:{steps:Array.isArray(c)?c:[c],quiet:!!r.quiet}};break}case"goto":s={cmd:"act",args:{steps:[{goto:n[0]}]}};break;case"click":s={cmd:"act",args:{steps:[{click:n.join(" ")}]}};break;case"dblclick":s={cmd:"act",args:{steps:[{dblclick:n.join(" ")}]}};break;case"hover":s={cmd:"act",args:{steps:[{hover:n.join(" ")}]}};break;case"fill":s={cmd:"act",args:{steps:[{fill:[n[0],n.slice(1).join(" ")]}]}};break;case"type":s={cmd:"act",args:{steps:[{type:[n[0],n.slice(1).join(" ")]}]}};break;case"press":s={cmd:"act",args:{steps:[{press:n[0]}]}};break;case"select":s={cmd:"act",args:{steps:[{select:[n[0],n.slice(1).join(" ")]}]}};break;case"upload":s={cmd:"act",args:{steps:[{upload:[n[0],n.slice(1).join(" ")]}]}};break;case"check-box":s={cmd:"act",args:{steps:[{check:n.join(" ")}]}};break;case"uncheck":s={cmd:"act",args:{steps:[{uncheck:n.join(" ")}]}};break;case"scroll":{r.to?s={cmd:"act",args:{steps:[{scroll:{to:r.to}}]}}:s={cmd:"act",args:{steps:[{scroll:{by:n[0]?parseInt(n[0],10):600}}]}};break}case"expect":s={cmd:"act",args:{steps:[{expect:ut(n[0],"expect")}]}};break;case"extract":{let c=null;try{c=JSON.parse(n[0])}catch{}s={cmd:"extract",args:c&&typeof c=="object"&&!Array.isArray(c)?c:{target:n[0]}};break}case"fetch":{s={cmd:"act",args:{steps:[r.method?{fetch:{url:n[0],method:r.method}}:{fetch:n[0]}],quiet:!0}};break}case"check":s={cmd:"check",args:{visual:!0}};break;case"inspect":s={cmd:"inspect",args:{ref:n.join(" ")}};break;case"shot":s={cmd:"shot",args:{full:!!r.full,region:r.region,label:r.label}};break;case"console":s={cmd:"console",args:{clear:!!r.clear}};break;case"requests":s={cmd:"requests",args:{clear:!!r.clear}};break;case"eval":s={cmd:"eval",args:{js:n.join(" ")}};break;case"status":s={cmd:"status",args:{}};break;case"trail":s={cmd:"trail",args:{}};break;case"stop":s={cmd:"stop",args:{}};break;case"tabs":s={cmd:"tabs",args:{}};break;case"tab":{n[0]||(console.error("usage: reflex tab <n> [--close]"),process.exit(2)),s={cmd:"tab",args:{n:n[0],close:!!r.close}};break}case"state":{n[0]==="save"&&n[1]?s={cmd:"state_save",args:{name:n[1]}}:(console.error("usage: reflex state save <name>"),process.exit(2));break}case"flow":{let c=n[0];if(c==="save"&&n[1])s={cmd:"flow_save",args:{name:n[1],params:r.params?String(r.params).split(","):[],last:r.last}};else if(c==="run"&&n[1]){let a={};for(let u of[].concat(r.param||[])){let d=u.indexOf("=");d>0&&(a[u.slice(0,d)]=u.slice(d+1))}s={cmd:"flow_run",args:{name:n[1],params:a,api:!!r.api}}}else c==="list"?s={cmd:"flow_list",args:{}}:(console.error("usage: reflex flow save|run|list"),process.exit(2));break}default:console.error(`unknown command: ${t} (try: reflex help)`),process.exit(2)}if(s.cmd==="stop"){let c=lt();if(!c){console.log("daemon not running");return}try{let a=await de(c,"stop",{});console.log(a.text)}catch{console.log("daemon not responding; removing state");try{ct.unlinkSync(xr)}catch{}}return}let o={};s.args=wr(s.args,o),s.cmd==="act"&&Object.keys(o).length&&(s.args.__env=o);let i=await Er(),l=await de(i,s.cmd,s.args);console.log(l.text),l.ok||process.exit(1)}_r().catch(e=>{console.error("error: "+e.message),process.exit(1)}); | ||
| REFLEX_REAP_INTERVAL_MIN how often to reap orphaned browsers from dead daemons (default 30; 0 = off)`;function kr(e){let t={},r=[];for(let n=0;n<e.length;n++){let s=e[n];if(s.startsWith("--")){let o=s.slice(2);n+1<e.length&&!e[n+1].startsWith("--")?t[o]=t[o]!==void 0?[].concat(t[o],e[++n]):e[++n]:t[o]=!0}else r.push(s)}return{flags:t,pos:r}}function ut(e,t){try{return JSON.parse(e)}catch(r){console.error(`error: ${t} must be valid JSON: ${r.message}`),process.exit(2)}}async function _r(){let e=process.argv.slice(2),t=e[0];if(!t||t==="help"||t==="--help"||t==="-h"){console.log(br);return}let{flags:r,pos:n}=kr(e.slice(1));if(t==="login"||t==="logout"||t==="whoami"){let c=Fe();if(t==="logout"){console.log(c.logout()?"signed out":"not signed in");return}if(t==="whoami"){let a=c.loadKey();console.log(a?`signed in (key \u2026${a.slice(-4)})`:"not signed in (run: reflex login)");return}if(process.env.REFLEX_API_KEY){console.log("using REFLEX_API_KEY from the environment; no login needed");return}try{let a=await c.login({onUrl:u=>console.error("opening browser to: "+u)});console.log(`signed in${typeof a.balance=="number"?` (${a.balance} credits)`:""}`)}catch(a){console.error("login failed: "+a.message),process.exit(1)}return}if(t==="profile"){let c=re(),a=n[0]||"status";if(a==="status"){console.log(c.statusText());return}if(a==="list"){console.log(c.listSourcesText());return}if(a==="use"){n[1]||(console.error("usage: reflex profile use <name|dir>"),process.exit(2));let u=c.use(n.slice(1).join(" "));console.log(u.text),u.ok||process.exit(1);return}if(a==="sync"||a==="reset"){let u=lt();if(u&&u.pid){try{await pe(u,"stop",{})}catch{}for(let f=0;f<60;f++){let h=!1;try{process.kill(u.pid,0),h=!0}catch{}if(!h)break;await new Promise(_=>setTimeout(_,100))}}let p=a==="sync"?c.sync():c.reset();console.log(p.text),p.ok===!1&&process.exit(1);return}console.error("usage: reflex profile status|list|use <name>|sync|reset"),process.exit(2)}if(t==="rollup"){console.log(at().format());return}let s;switch(t){case"open":{n[0]||(console.error("usage: reflex open <url>"),process.exit(2));let c=r.headless?!1:r.headed?!0:void 0;r.state&&re().enabled()&&console.error("note: --state is ignored while profile mode is on (the persistent profile is your session). Use REFLEX_PROFILE=off to load a saved --state."),s={cmd:"open",args:{url:n[0],headed:c,state:r.state,new_tab:!!r["new-tab"]}};break}case"read":s={cmd:"read",args:{query:r.query,full:!!r.full}};break;case"act":{let c=ut(n[0]==="-"?ct.readFileSync(0,"utf8"):n[0],"steps");s={cmd:"act",args:{steps:Array.isArray(c)?c:[c],quiet:!!r.quiet}};break}case"goto":s={cmd:"act",args:{steps:[{goto:n[0]}]}};break;case"click":s={cmd:"act",args:{steps:[{click:n.join(" ")}]}};break;case"dblclick":s={cmd:"act",args:{steps:[{dblclick:n.join(" ")}]}};break;case"hover":s={cmd:"act",args:{steps:[{hover:n.join(" ")}]}};break;case"fill":s={cmd:"act",args:{steps:[{fill:[n[0],n.slice(1).join(" ")]}]}};break;case"type":s={cmd:"act",args:{steps:[{type:[n[0],n.slice(1).join(" ")]}]}};break;case"press":s={cmd:"act",args:{steps:[{press:n[0]}]}};break;case"select":s={cmd:"act",args:{steps:[{select:[n[0],n.slice(1).join(" ")]}]}};break;case"upload":s={cmd:"act",args:{steps:[{upload:[n[0],n.slice(1).join(" ")]}]}};break;case"check-box":s={cmd:"act",args:{steps:[{check:n.join(" ")}]}};break;case"uncheck":s={cmd:"act",args:{steps:[{uncheck:n.join(" ")}]}};break;case"scroll":{r.to?s={cmd:"act",args:{steps:[{scroll:{to:r.to}}]}}:s={cmd:"act",args:{steps:[{scroll:{by:n[0]?parseInt(n[0],10):600}}]}};break}case"expect":s={cmd:"act",args:{steps:[{expect:ut(n[0],"expect")}]}};break;case"extract":{let c=null;try{c=JSON.parse(n[0])}catch{}s={cmd:"extract",args:c&&typeof c=="object"&&!Array.isArray(c)?c:{target:n[0]}};break}case"fetch":{s={cmd:"act",args:{steps:[r.method?{fetch:{url:n[0],method:r.method}}:{fetch:n[0]}],quiet:!0}};break}case"check":s={cmd:"check",args:{visual:!0}};break;case"inspect":s={cmd:"inspect",args:{ref:n.join(" ")}};break;case"shot":s={cmd:"shot",args:{full:!!r.full,region:r.region,label:r.label}};break;case"console":s={cmd:"console",args:{clear:!!r.clear}};break;case"requests":s={cmd:"requests",args:{clear:!!r.clear}};break;case"eval":s={cmd:"eval",args:{js:n.join(" ")}};break;case"status":s={cmd:"status",args:{}};break;case"trail":s={cmd:"trail",args:{}};break;case"stop":s={cmd:"stop",args:{}};break;case"tabs":s={cmd:"tabs",args:{}};break;case"tab":{n[0]||(console.error("usage: reflex tab <n> [--close]"),process.exit(2)),s={cmd:"tab",args:{n:n[0],close:!!r.close}};break}case"state":{n[0]==="save"&&n[1]?s={cmd:"state_save",args:{name:n[1]}}:(console.error("usage: reflex state save <name>"),process.exit(2));break}case"flow":{let c=n[0];if(c==="save"&&n[1])s={cmd:"flow_save",args:{name:n[1],params:r.params?String(r.params).split(","):[],last:r.last}};else if(c==="run"&&n[1]){let a={};for(let u of[].concat(r.param||[])){let p=u.indexOf("=");p>0&&(a[u.slice(0,p)]=u.slice(p+1))}s={cmd:"flow_run",args:{name:n[1],params:a,api:!!r.api}}}else c==="list"?s={cmd:"flow_list",args:{}}:(console.error("usage: reflex flow save|run|list"),process.exit(2));break}default:console.error(`unknown command: ${t} (try: reflex help)`),process.exit(2)}if(s.cmd==="stop"){let c=lt();if(!c){console.log("daemon not running");return}try{let a=await pe(c,"stop",{});console.log(a.text)}catch{console.log("daemon not responding; removing state");try{ct.unlinkSync(xr)}catch{}}return}let o={};s.args=Er(s.args,o),s.cmd==="act"&&Object.keys(o).length&&(s.args.__env=o);let i=await wr(),l=await pe(i,s.cmd,s.args);console.log(l.text),l.ok||process.exit(1)}_r().catch(e=>{console.error("error: "+e.message),process.exit(1)}); |
+1
-1
| { | ||
| "name": "reflex-browser", | ||
| "version": "0.9.0", | ||
| "version": "0.10.0", | ||
| "mcpName": "com.reflexmcp/reflex", | ||
@@ -5,0 +5,0 @@ "description": "Token-efficient browser automation for AI agents. Local MCP server + CLI: compressed page snapshots, batched actions, forensic failures.", |
Sorry, the diff of this file is too big to display
AI-detected potential code anomaly
Supply chain riskAI has identified unusual behaviors that may pose a security risk.
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
AI-detected potential code anomaly
Supply chain riskAI has identified unusual behaviors that may pose a security risk.
Found 3 instances
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
212289
1.11%848
1.31%108
-1.82%