🎩 You're Invited:Meet the Socket team at Black Hat in Las Vegas, August 3-6.RSVP
Sign In

reflex-browser

Package Overview
Dependencies
Maintainers
1
Versions
34
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

reflex-browser - npm Package Compare versions

Comparing version
0.11.2
to
0.11.3
+10
-10
dist/mcp.js

@@ -1,4 +0,4 @@

"use strict";var D=(e,t)=>()=>{try{return t||e((t={exports:{}}).exports,t),t.exports}catch(r){throw t=0,r}};var Ge=D((lr,X)=>{"use strict";var pe=require("fs"),jt=require("path"),{execFileSync:B}=require("child_process");function Je(e){if(!e||e<1)return!1;try{return process.kill(e,0),!0}catch(t){return t.code==="EPERM"}}function Ft(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(`
`)){let o=n.match(/^\s*(\d+)\s+(.*)$/);if(o&&o[1]===r&&/chrome|chromium|ms-playwright|playwright[\/\\]/i.test(o[2]))return!0}return!1}function Nt(e){if(process.platform==="win32")return null;let t="";try{t=B("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[,o,s,c,l]=n;if(s===String(e)&&/chrome|chromium|ms-playwright/i.test(l)&&!/crashpad/i.test(l))return{pid:parseInt(o,10),pgid:parseInt(c,10)}}return null}function Pt(e,t){let r;try{r=pe.readdirSync(e)}catch{return}for(let n of r){if(!/^daemon(-.+)?\.json$/.test(n))continue;let o=jt.join(e,n),s;try{s=JSON.parse(pe.readFileSync(o,"utf8"))}catch{continue}if(!(!s||s.pid===t)&&!Je(s.pid)){try{let c=s.pgid||s.pid;!c||c<1||(process.platform==="win32"?s.browserPid&&B("taskkill",["/PID",String(s.browserPid),"/T","/F"],{stdio:"ignore",timeout:8e3}):X.exports.groupLooksLikeReflex(c)&&process.kill(-c,"SIGKILL"))}catch{}try{pe.unlinkSync(o)}catch{}}}}function Dt(e){if(!e||e<2||process.platform==="win32")return!1;let t="";try{t=B("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 qt(e){if(e)try{if(process.platform==="win32"){if(e.browserPid)try{B("taskkill",["/PID",String(e.browserPid),"/T","/F"],{stdio:"ignore",timeout:8e3})}catch{}return}if(e.pid&&e.pid>1&&e.pid!==process.pid&&X.exports.daemonPidLooksLikeReflex(e.pid))try{process.kill(e.pid,"SIGKILL")}catch{}let t=e.pgid;if(t&&t>1&&t!==process.pid&&X.exports.groupLooksLikeReflex(t))try{process.kill(-t,"SIGKILL")}catch{}}catch{}}X.exports={isAlive:Je,groupLooksLikeReflex:Ft,daemonPidLooksLikeReflex:Dt,reapOrphans:Pt,reapState:qt,findBrowserGroup:Nt}});var et=D((ur,Qe)=>{"use strict";var Mt=require("http"),E=require("fs"),me=require("path"),$t=require("os"),{spawn:Ct}=require("child_process"),ye=process.env.REFLEX_HOME||me.join($t.homedir(),".reflex"),z=e=>String(e||"default").replace(/[^a-zA-Z0-9_-]/g,"_").slice(0,40)||"default",Z=z(process.env.REFLEX_SESSION),U=e=>me.join(ye,e==="default"?"daemon.json":`daemon-${e}.json`),Xt=U(Z),ze=me.join(__dirname,"daemon.js");function ge(e){try{return JSON.parse(E.readFileSync(U(e?z(e):Z),"utf8"))}catch{return null}}function Ze(e,t,r,n){return new Promise((o,s)=>{let c=JSON.stringify({cmd:t,args:r}),l={"x-reflex-token":e.token||""};n&&(l["x-reflex-caller"]=n);let d=Mt.request({host:"127.0.0.1",port:e.port,method:"POST",path:"/",timeout:12e4,headers:l},f=>{let u="";f.on("data",g=>u+=g),f.on("end",()=>{try{o(JSON.parse(u))}catch{s(new Error("bad daemon response"))}})});d.on("error",s),d.on("timeout",()=>{d.destroy(),s(new Error("daemon timeout"))}),d.end(c)})}var We=e=>new Promise(t=>setTimeout(t,e));async function W(e){let t=ge(e);if(t)try{return await Ze(t,"ping",{}),t}catch{}return null}function Ve(e){try{let t=E.openSync(e,"wx");return E.writeSync(t,String(process.pid)),E.closeSync(t),!0}catch(t){if(t.code!=="EEXIST")return!1;try{if(Date.now()-E.statSync(e).mtimeMs>15e3)return E.unlinkSync(e),Ve(e)}catch{}return!1}}function Bt(e){try{return E.statSync(e),!0}catch{return!1}}async function Ut(e,t){let r=e?z(e):Z,n=await W(r);if(n)return n;try{E.mkdirSync(ye,{recursive:!0,mode:448})}catch{}let o=U(r).replace(/\.json$/,".lock");for(let s=0;s<2;s++){if(Ve(o))try{if(n=await W(r),n)return n;let c=ge(r);if(c)try{Ge().reapState(c)}catch{}try{E.unlinkSync(U(r))}catch{}let l=Object.assign({},process.env,t||{},{REFLEX_SESSION:r});Ct(process.execPath,[ze],{detached:!0,stdio:"ignore",windowsHide:!0,env:l}).unref();for(let f=0;f<100;f++)if(await We(100),n=await W(r),n)return n;throw new Error("daemon failed to start (check ~/.reflex/daemon.log)")}finally{try{E.unlinkSync(o)}catch{}}for(let c=0;c<100;c++){if(await We(100),n=await W(r),n)return n;if(!Bt(o))break}}throw new Error("daemon failed to start (check ~/.reflex/daemon.log)")}function he(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=>he(r,t));if(e&&typeof e=="object"){let r={};for(let n in e)r[n]=he(e[n],t);return r}return e}Qe.exports={readState:ge,rpc:Ze,ensureDaemon:Ut,subEnv:he,sanitizeSession:z,stateFileFor:U,HOME:ye,SESSION:Z,STATE_FILE:Xt,DAEMON:ze}});var _e=D((fr,at)=>{"use strict";var q=require("fs"),Kt=require("os"),tt=require("path"),Ht=require("http"),Yt=require("crypto"),{spawn:Jt}=require("child_process"),{URL:Gt}=require("url"),nt=process.env.REFLEX_SITE_BASE||"https://reflexmcp.com",rt=process.env.REFLEX_API_BASE||"https://reflex.openlabs.workers.dev",Wt=18e4;function ot(){return process.env.REFLEX_HOME||tt.join(Kt.homedir(),".reflex")}function M(){return tt.join(ot(),"auth.json")}function zt(){try{let e=q.readFileSync(M(),"utf8"),t=JSON.parse(e);return t&&typeof t.api_key=="string"?t.api_key:null}catch{return null}}function st({api_key:e,key_id:t}){let r=ot();q.mkdirSync(r,{recursive:!0});let n=M()+".tmp",o=JSON.stringify({v:1,api_key:e,key_id:t||null,saved_at:new Date().toISOString()});q.writeFileSync(n,o,{mode:384}),q.renameSync(n,M());try{q.chmodSync(M(),384)}catch{}}function Zt(){try{return q.unlinkSync(M()),!0}catch(e){if(e&&e.code==="ENOENT")return!1;throw e}}function it(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=Jt(t,r,{detached:!0,stdio:"ignore"});return n.on("error",()=>{}),n.unref(),!0}catch{return!1}}function Vt(e){e=e||{};let t=(e.siteBase||nt).replace(/\/+$/,""),r=(e.apiBase||rt).replace(/\/+$/,""),n=e.timeoutMs||Wt,o=Yt.randomBytes(24).toString("base64url");return new Promise((s,c)=>{let l=!1,d=null,f=(g,h)=>{if(!l){l=!0,d&&clearTimeout(d);try{u.close()}catch{}g(h)}},u=Ht.createServer((g,h)=>{let C;try{C=new Gt(g.url,"http://127.0.0.1")}catch{h.writeHead(400),h.end();return}if(C.pathname!=="/callback"){h.writeHead(404),h.end("not found");return}let He=C.searchParams.get("state"),Ye=C.searchParams.get("code"),fe=C.searchParams.get("error");if(fe){h.writeHead(200,{"content-type":"text/html"}),h.end(V("Login failed",String(fe).slice(0,200))),f(c,new Error("login failed: "+fe));return}if(!He||He!==o){h.writeHead(400,{"content-type":"text/html"}),h.end(V("Login error","Security check failed (state mismatch). Run reflex_auth login again.")),f(c,new Error("state mismatch"));return}if(!Ye){h.writeHead(400,{"content-type":"text/html"}),h.end(V("Login error","No login code received. Run reflex_auth login again.")),f(c,new Error("no code"));return}h.writeHead(200,{"content-type":"text/html"}),h.end(V("You are signed in to Reflex","You can close this tab and return to your agent.")),Qt(r,Ye).then(de=>f(s,de),de=>f(c,de))});u.on("error",g=>f(c,g)),u.listen(0,"127.0.0.1",()=>{let g=u.address().port,h=`${t}/cli-auth?port=${g}&state=${encodeURIComponent(o)}`;if(typeof e.onUrl=="function")try{e.onUrl(h)}catch{}e.open!==!1&&it(h),d=setTimeout(()=>f(c,new Error("timed out waiting for browser login (3 min)")),n),d.unref&&d.unref()})})}async function Qt(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(o){throw new Error("could not reach the Reflex login server: "+(o&&o.message?o.message:o))}let n=null;try{n=await r.json()}catch{}if(!r.ok){let o=n&&n.error&&n.error.message?n.error.message:`login exchange failed (HTTP ${r.status})`;throw new Error(o)}if(!n||typeof n.api_key!="string")throw new Error("login exchange returned no key");return st({api_key:n.api_key,key_id:n.key_id}),n}function V(e,t){return`<!doctype html><html><head><meta charset="utf-8"><title>${e}</title>
"use strict";var C=(e,t)=>()=>{try{return t||e((t={exports:{}}).exports,t),t.exports}catch(r){throw t=0,r}};var Ze=C((yr,K)=>{"use strict";var ye=require("fs"),Ct=require("path"),{execFileSync:H}=require("child_process");function ze(e){if(!e||e<1)return!1;try{return process.kill(e,0),!0}catch(t){return t.code==="EPERM"}}function $t(e){if(process.platform==="win32")return!1;let t="";try{t=H("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 Xt(e){if(process.platform==="win32")return null;let t="";try{t=H("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,c,l]=n;if(o===String(e)&&/chrome|chromium|ms-playwright/i.test(l)&&!/crashpad/i.test(l))return{pid:parseInt(s,10),pgid:parseInt(c,10)}}return null}function Bt(e,t){let r;try{r=ye.readdirSync(e)}catch{return}for(let n of r){if(!/^daemon(-.+)?\.json$/.test(n))continue;let s=Ct.join(e,n),o;try{o=JSON.parse(ye.readFileSync(s,"utf8"))}catch{continue}if(!(!o||o.pid===t)&&!ze(o.pid)){try{let c=o.pgid||o.pid;!c||c<1||(process.platform==="win32"?o.browserPid&&H("taskkill",["/PID",String(o.browserPid),"/T","/F"],{stdio:"ignore",timeout:8e3}):K.exports.groupLooksLikeReflex(c)&&process.kill(-c,"SIGKILL"))}catch{}try{ye.unlinkSync(s)}catch{}}}}function Ut(e){if(!e||e<2||process.platform==="win32")return!1;let t="";try{t=H("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 Kt(e){if(e)try{if(process.platform==="win32"){if(e.browserPid)try{H("taskkill",["/PID",String(e.browserPid),"/T","/F"],{stdio:"ignore",timeout:8e3})}catch{}return}if(e.pid&&e.pid>1&&e.pid!==process.pid&&K.exports.daemonPidLooksLikeReflex(e.pid))try{process.kill(e.pid,"SIGKILL")}catch{}let t=e.pgid;if(t&&t>1&&t!==process.pid&&K.exports.groupLooksLikeReflex(t))try{process.kill(-t,"SIGKILL")}catch{}}catch{}}K.exports={isAlive:ze,groupLooksLikeReflex:$t,daemonPidLooksLikeReflex:Ut,reapOrphans:Bt,reapState:Kt,findBrowserGroup:Xt}});var rt=C((gr,nt)=>{"use strict";var Ht=require("http"),E=require("fs"),_e=require("path"),Yt=require("os"),{spawn:Jt}=require("child_process"),we=process.env.REFLEX_HOME||_e.join(Yt.homedir(),".reflex"),Z=e=>String(e||"default").replace(/[^a-zA-Z0-9_-]/g,"_").slice(0,40)||"default",V=Z(process.env.REFLEX_SESSION),Y=e=>_e.join(we,e==="default"?"daemon.json":`daemon-${e}.json`),Gt=Y(V),Qe=_e.join(__dirname,"daemon.js");function be(e){try{return JSON.parse(E.readFileSync(Y(e?Z(e):V),"utf8"))}catch{return null}}function et(e,t,r,n){return new Promise((s,o)=>{let c=JSON.stringify({cmd:t,args:r}),l={"x-reflex-token":e.token||""};n&&(l["x-reflex-caller"]=n);let d=Ht.request({host:"127.0.0.1",port:e.port,method:"POST",path:"/",timeout:12e4,headers:l},u=>{let p="";u.on("data",y=>p+=y),u.on("end",()=>{try{s(JSON.parse(p))}catch{o(new Error("bad daemon response"))}})});d.on("error",o),d.on("timeout",()=>{d.destroy(),o(new Error("daemon timeout"))}),d.end(c)})}var Ve=e=>new Promise(t=>setTimeout(t,e));async function z(e){let t=be(e);if(t)try{return await et(t,"ping",{}),t}catch{}return null}function tt(e){try{let t=E.openSync(e,"wx");return E.writeSync(t,String(process.pid)),E.closeSync(t),!0}catch(t){if(t.code!=="EEXIST")return!1;try{if(Date.now()-E.statSync(e).mtimeMs>15e3)return E.unlinkSync(e),tt(e)}catch{}return!1}}function Wt(e){try{return E.statSync(e),!0}catch{return!1}}async function zt(e,t){let r=e?Z(e):V,n=await z(r);if(n)return n;try{E.mkdirSync(we,{recursive:!0,mode:448})}catch{}let s=Y(r).replace(/\.json$/,".lock");for(let o=0;o<2;o++){if(tt(s))try{if(n=await z(r),n)return n;let c=be(r);if(c)try{Ze().reapState(c)}catch{}try{E.unlinkSync(Y(r))}catch{}let l=Object.assign({},process.env,t||{},{REFLEX_SESSION:r});Jt(process.execPath,[Qe],{detached:!0,stdio:"ignore",windowsHide:!0,env:l}).unref();for(let u=0;u<100;u++)if(await Ve(100),n=await z(r),n)return n;throw new Error("daemon failed to start (check ~/.reflex/daemon.log)")}finally{try{E.unlinkSync(s)}catch{}}for(let c=0;c<100;c++){if(await Ve(100),n=await z(r),n)return n;if(!Wt(s))break}}throw new Error("daemon failed to start (check ~/.reflex/daemon.log)")}function ge(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=>ge(r,t));if(e&&typeof e=="object"){let r={};for(let n in e)r[n]=ge(e[n],t);return r}return e}nt.exports={readState:be,rpc:et,ensureDaemon:zt,subEnv:ge,sanitizeSession:Z,stateFileFor:Y,HOME:we,SESSION:V,STATE_FILE:Gt,DAEMON:Qe}});var xe=C((_r,ut)=>{"use strict";var $=require("fs"),Zt=require("os"),st=require("path"),Vt=require("http"),Qt=require("crypto"),{spawn:en}=require("child_process"),{URL:tn}=require("url"),ot=process.env.REFLEX_SITE_BASE||"https://reflexmcp.com",it=process.env.REFLEX_API_BASE||"https://reflex.openlabs.workers.dev",nn=18e4;function at(){return process.env.REFLEX_HOME||st.join(Zt.homedir(),".reflex")}function X(){return st.join(at(),"auth.json")}function rn(){try{let e=$.readFileSync(X(),"utf8"),t=JSON.parse(e);return t&&typeof t.api_key=="string"?t.api_key:null}catch{return null}}function ct({api_key:e,key_id:t}){let r=at();$.mkdirSync(r,{recursive:!0});let n=X()+".tmp",s=JSON.stringify({v:1,api_key:e,key_id:t||null,saved_at:new Date().toISOString()});$.writeFileSync(n,s,{mode:384}),$.renameSync(n,X());try{$.chmodSync(X(),384)}catch{}}function sn(){try{return $.unlinkSync(X()),!0}catch(e){if(e&&e.code==="ENOENT")return!1;throw e}}function lt(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=en(t,r,{detached:!0,stdio:"ignore"});return n.on("error",()=>{}),n.unref(),!0}catch{return!1}}function on(e){e=e||{};let t=(e.siteBase||ot).replace(/\/+$/,""),r=(e.apiBase||it).replace(/\/+$/,""),n=e.timeoutMs||nn,s=Qt.randomBytes(24).toString("base64url");return new Promise((o,c)=>{let l=!1,d=null,u=(y,f)=>{if(!l){l=!0,d&&clearTimeout(d);try{p.close()}catch{}y(f)}},p=Vt.createServer((y,f)=>{let O;try{O=new tn(y.url,"http://127.0.0.1")}catch{f.writeHead(400),f.end();return}if(O.pathname!=="/callback"){f.writeHead(404),f.end("not found");return}let Ge=O.searchParams.get("state"),We=O.searchParams.get("code"),he=O.searchParams.get("error");if(he){f.writeHead(200,{"content-type":"text/html"}),f.end(Q("Login failed",String(he).slice(0,200))),u(c,new Error("login failed: "+he));return}if(!Ge||Ge!==s){f.writeHead(400,{"content-type":"text/html"}),f.end(Q("Login error","Security check failed (state mismatch). Run reflex_auth login again.")),u(c,new Error("state mismatch"));return}if(!We){f.writeHead(400,{"content-type":"text/html"}),f.end(Q("Login error","No login code received. Run reflex_auth login again.")),u(c,new Error("no code"));return}f.writeHead(200,{"content-type":"text/html"}),f.end(Q("You are signed in to Reflex","You can close this tab and return to your agent.")),an(r,We).then(me=>u(o,me),me=>u(c,me))});p.on("error",y=>u(c,y)),p.listen(0,"127.0.0.1",()=>{let y=p.address().port,f=`${t}/cli-auth?port=${y}&state=${encodeURIComponent(s)}`;if(typeof e.onUrl=="function")try{e.onUrl(f)}catch{}e.open!==!1&&lt(f),d=setTimeout(()=>u(c,new Error("timed out waiting for browser login (3 min)")),n),d.unref&&d.unref()})})}async function an(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 ct({api_key:n.api_key,key_id:n.key_id}),n}function Q(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;

@@ -8,3 +8,3 @@ 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>`}at.exports={login:Vt,logout:Zt,loadKey:zt,saveKey:st,openBrowser:it,SITE_BASE:nt,API_BASE:rt,_authFile:M}});var we=D((dr,en)=>{en.exports={name:"reflex-browser",version:"0.11.2",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/trial.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 kt=D((pr,vt)=>{"use strict";var p=require("fs"),tn=require("os"),j=require("path"),H=require("crypto"),nn=_e(),Se=process.env.REFLEX_API_BASE||"https://reflex.openlabs.workers.dev";function T(){return process.env.REFLEX_HOME||j.join(tn.homedir(),".reflex")}function te(){return j.join(T(),"credits.json")}function ne(e){return j.join(T(),`usage-${e||process.pid}.json`)}function ft(){return j.join(T(),"credits.lock")}function be(){return j.join(T(),"device.json")}var xe=/^rfx_(live|test)_[A-Za-z0-9]{32}$/,Ee=25,rn="rfx_trial_loc";function on(){return process.env.REFLEX_TRIAL!=="off"&&process.env.REFLEX_TRIAL!=="0"}var sn={k1:process.env.REFLEX_PUBKEY_K1||"cU8LzUpIjro9cQo/A4o7BaOJ6QcDKloN6hffQISY28o="},an=3,cn=3e4,ln=250,Re=6e4,un=1e3,fn=100,dn=10,pn=6e5,dt=3e5,Le=3e3,hn=5e3,mn=2e3,yn=3e5,gn=250,_n=5e3,Ie=(()=>{try{return we().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>`}ut.exports={login:on,logout:sn,loadKey:rn,saveKey:ct,openBrowser:lt,SITE_BASE:ot,API_BASE:it,_authFile:X}});var ve=C((wr,cn)=>{cn.exports={name:"reflex-browser",version:"0.11.3",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/trial.js && node test/flush.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.62.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 At=C((br,Tt)=>{"use strict";var h=require("fs"),ln=require("os"),P=require("path"),J=require("crypto"),un=xe(),Le=process.env.REFLEX_API_BASE||"https://reflex.openlabs.workers.dev";function T(){return process.env.REFLEX_HOME||P.join(ln.homedir(),".reflex")}function re(){return P.join(T(),"credits.json")}function se(e){return P.join(T(),`usage-${e||process.pid}.json`)}function mt(){return P.join(T(),"credits.lock")}function ke(){return P.join(T(),"device.json")}var oe=/^rfx_(live|test)_[A-Za-z0-9]{32}$/,Ie=25,fn="rfx_trial_loc";function dn(){return process.env.REFLEX_TRIAL!=="off"&&process.env.REFLEX_TRIAL!=="0"}var pn={k1:process.env.REFLEX_PUBKEY_K1||"cU8LzUpIjro9cQo/A4o7BaOJ6QcDKloN6hffQISY28o="},hn=3,mn=3e4,yt=3,yn=2e3,ft=4,gn=250,Te=6e4,_n=1e3,wn=100,bn=10,xn=6e5,gt=3e5,Ae=3e3,vn=5e3,kn=2e3,Sn=3e5,En=250,Rn=5e3,Oe=(()=>{try{return ve().version}catch{return"0.0.0"}})(),x={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:

@@ -20,7 +20,7 @@ top up at https://reflexmcp.com/pricing (150 credits for $9, 500 for $19), and

and adds 30 more credits), or buy a pack from https://reflexmcp.com/pricing
(150 credits for $9). Then simply retry this call.`};function wn(e){return`[reflex: ${e} credits left. Top up: https://reflexmcp.com/pricing]`}var m=null,_=null,a=null,i=null,re=!1,y=null,R=null,Q=!1,K=!1,O=0,Y=0,ve=0,ke=0,I=!1,F=!1,v=!1,x=null,ee=!1;function ct(e){return Buffer.from(e.replace(/-/g,"+").replace(/_/g,"/"),"base64")}function bn(e,t){return{v:2,key_id:e||null,key_prefix:t||null,token:null,balance:0,free_expires_at:null,last_sync_at:null,max_token_iat:0,last_wall_clock:new Date().toISOString()}}function xn(e){return{v:1,pid:process.pid,key_prefix:e||null,buffer:[],overflow:{calls:0,from:null,to:null},pending_batch:null}}function pt(e){return e?e.slice(0,13):null}function ht(){try{let e=JSON.parse(p.readFileSync(te(),"utf8"));if(e&&(e.v===1||e.v===2))return e}catch{}return null}function vn(){try{let e=JSON.parse(p.readFileSync(ne(),"utf8"));if(e&&e.v===1&&Array.isArray(e.buffer))return e}catch{}return null}function Te(){p.existsSync(T())||p.mkdirSync(T(),{recursive:!0})}function mt(){try{let e=JSON.parse(p.readFileSync(be(),"utf8"));if(e&&e.v===1&&typeof e.device_id=="string")return e}catch{}return null}function yt(e){try{Te();let t=be()+".tmp";return p.writeFileSync(t,JSON.stringify(e),{mode:384}),p.renameSync(t,be()),!0}catch{return!1}}function kn(){let e=mt();if(e)return e;let t={v:1,device_id:H.randomUUID(),trial_key:null,claimed_at:null};return yt(t)?t:null}async function Sn(){if(ee||!x||!v)return!1;ee=!0;try{let e=new AbortController,t=setTimeout(()=>e.abort(),Le),r;try{r=await fetch(Se+"/v1/trial/claim",{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({device_id:x.device_id,client_version:Ie}),signal:e.signal})}finally{clearTimeout(t)}if(r.status===429)return _={reason:"no_key",message:w.noKey},v=!1,!1;let n=await r.json().catch(()=>null);if(!r.ok||!n||!xe.test(n.api_key||""))return!1;m=n.api_key;let o=pt(m);return a.key_prefix=o,i.key_prefix=o,typeof n.balance=="number"&&(a.balance=Math.max(0,n.balance-i.buffer.length)),v=!1,x.trial_key=m,x.claimed_at=new Date().toISOString(),yt(x),N(),await J(),!0}catch{return!1}finally{ee=!1}}async function En(e){let t=mt();if(!(!t||!e))try{let r=new AbortController,n=setTimeout(()=>r.abort(),Le);try{await fetch(Se+"/v1/trial/convert",{method:"POST",headers:{authorization:`Bearer ${e}`,"content-type":"application/json"},body:JSON.stringify({device_id:t.device_id}),signal:r.signal})}finally{clearTimeout(n)}}catch{}}function lt(e,t){let r=e?Date.parse(e):NaN,n=t?Date.parse(t):NaN;return Number.isNaN(r)?!1:Number.isNaN(n)?!0:r>n}function Rn(){let e=ft(),t=Date.now()+gn;for(;;)try{return p.mkdirSync(e),!0}catch{try{let n=p.statSync(e);if(Date.now()-n.mtimeMs>_n){p.rmdirSync(e);continue}}catch{}if(Date.now()>=t)return!1;let r=Math.min(Date.now()+10,t);for(;Date.now()<r;);}}function Ln(){try{p.rmdirSync(ft())}catch{}}function Ae(){if(!a)return;let e=ht();if(!(!e||e.v!==2||e.key_prefix!==a.key_prefix)){if((e.max_token_iat||0)>(a.max_token_iat||0)&&e.token&&(a.token=e.token,a.max_token_iat=e.max_token_iat,a.free_expires_at=e.free_expires_at||a.free_expires_at),lt(e.last_sync_at,a.last_sync_at)){let t=i?i.buffer.length:0;a.balance=(e.balance||0)-t,a.last_sync_at=e.last_sync_at}lt(e.last_wall_clock,a.last_wall_clock)&&(a.last_wall_clock=e.last_wall_clock),a.key_id=a.key_id||e.key_id}}function In(){if(a)try{Te();let e=Rn();try{Ae();let t=te()+".tmp."+process.pid;p.writeFileSync(t,JSON.stringify(a),{mode:384}),p.renameSync(t,te())}finally{e&&Ln()}}catch{}}function Oe(){if(!i)return!1;try{Te();let e=ne()+".tmp";return p.writeFileSync(e,JSON.stringify(i),{mode:384}),p.renameSync(e,ne()),!0}catch{return!1}}function N(){Oe(),In(),re=!1}function P(){re=!0,!y&&(y=setTimeout(()=>{y=null,re&&N()},ln),y.unref&&y.unref())}function se(e){if(typeof e!="string")return null;let t=e.split(".");if(t.length!==3||t[0]!=="RFX1")return null;let[,r,n]=t,o;try{o=JSON.parse(ct(r).toString("utf8"))}catch{return null}let s=sn[o.kid];if(!s||s.startsWith("REPLACE_"))return null;let c;try{c=H.createPublicKey({key:Buffer.concat([Buffer.from("302a300506032b6570032100","hex"),Buffer.from(s,"base64")]),format:"der",type:"spki"})}catch{return null}let l=Buffer.from("RFX1."+r,"ascii"),d=!1;try{d=H.verify(null,l,c,ct(n))}catch{return null}return d?o:null}function gt(e,t,r,n){a.token=e,a.max_token_iat=Math.max(a.max_token_iat||0,t.iat||0),a.balance=r-(n||0),a.free_expires_at=t.fxp?new Date(t.fxp*1e3).toISOString():null,a.last_sync_at=new Date().toISOString(),P()}function $(){if(!a||!a.token)return!1;let e=se(a.token);if(!e||(e.iat||0)<(a.max_token_iat||0))return!1;let t=Math.floor(Date.now()/1e3);return!(e.exp<=t-dt/1e3)}async function _t(e,t,r,n){let o=new AbortController,s=setTimeout(()=>o.abort(),n);try{let c=await fetch(Se+t,{method:e,headers:{authorization:`Bearer ${m}`,"content-type":"application/json"},body:r?JSON.stringify(r):void 0,signal:o.signal}),l=null;try{l=await c.json()}catch{}return{status:c.status,json:l}}finally{clearTimeout(s)}}async function J(){let{status:e,json:t}=await _t("POST","/v1/validate",{client_version:Ie},Le);if(e===401||e===403){_={reason:e===403?"key_revoked":"bad_key",message:w.badKey};try{p.unlinkSync(te())}catch{}return!1}if(e===200&&t&&t.ok&&t.token){let r=se(t.token);if(r&&(r.iat||0)>=(a.max_token_iat||0))return _=null,a.key_id=t.key_id||a.key_id,gt(t.token,r,t.balance,i.buffer.length),!0}return!1}function Tn(){if(i.pending_batch)return i.pending_batch;if(i.buffer.length===0&&i.overflow.calls===0)return null;let e=i.buffer.slice(),t={},r=null,n=null,o=0,s=0,c=0,l={};for(let u of e){if(t[u.tool]=(t[u.tool]||0)+1,u.ok===!0)o++;else if(u.ok===!1){let g=u.cat||"other";s++,l[g]=(l[g]||0)+1}Number.isFinite(u.resp_chars)&&(c+=u.resp_chars),(!r||u.ts<r)&&(r=u.ts),(!n||u.ts>n)&&(n=u.ts)}let d=new Date().toISOString(),f={batch_id:H.randomUUID(),calls:e.length,tools:t,ok:o,fail:s,overflow_calls:i.overflow.calls,period_start:r||i.overflow.from||d,period_end:n||i.overflow.to||d,client_balance:a.balance,hit_zero:!!i._hitZeroPending,client_version:Ie,_event_ids:e.map(u=>u.id)};return Object.keys(l).length&&(f.fail_cats=l),c>0&&(f.resp_chars=c),f.calls===0&&f.overflow_calls===0?null:f}async function je(){if(K||!a||!i||!$()&&!i.pending_batch)return;let e=Tn();if(!e)return;K=!0,i.pending_batch=e,Oe();let{_event_ids:t,...r}=e,n=null;try{n=await _t("POST","/v1/usage",r,hn)}catch{n=null}if(n&&n.status===200&&n.json&&n.json.ok&&n.json.token){let o=se(n.json.token);if(o&&(o.iat||0)>=(a.max_token_iat||0)){let s=new Set(t),c=i.buffer.filter(d=>!s.has(d.id)),l=c.length;i.buffer=c,i.overflow={calls:0,from:null,to:null},i._hitZeroPending=!1,i.pending_batch=null,gt(n.json.token,o,n.json.balance,l),O=0,Y=0,K=!1;return}}n&&(n.status===401||n.status===403)&&(_={reason:n.status===403?"key_revoked":"bad_key",message:w.badKey},i.pending_batch=null),O=O?Math.min(O*2,yn):Re,Y=Date.now()+O,K=!1,P()}function An(e){try{return process.kill(e,0),!0}catch(t){return t&&t.code!=="ESRCH"}}function wt(){if(!i)return;let e;try{e=p.readdirSync(T())}catch{return}for(let t of e){let r=/^usage-(\d+)\.json$/.exec(t);if(!r)continue;let n=Number(r[1]);if(n===process.pid||An(n))continue;let o=j.join(T(),t),s=null;try{s=JSON.parse(p.readFileSync(o,"utf8"))}catch{continue}if(!s||s.v!==1||!Array.isArray(s.buffer)||s.key_prefix&&i.key_prefix&&s.key_prefix!==i.key_prefix)continue;let c=j.join(T(),`usage-${n}.claimed-${process.pid}.json`);try{p.renameSync(o,c)}catch{continue}try{let l=JSON.parse(p.readFileSync(c,"utf8"));if(l&&Array.isArray(l.buffer)){if(i.buffer=i.buffer.concat(l.buffer),l.overflow&&l.overflow.calls){i.overflow.calls+=l.overflow.calls;let{from:d,to:f}=l.overflow;d&&(!i.overflow.from||d<i.overflow.from)&&(i.overflow.from=d),f&&(!i.overflow.to||f>i.overflow.to)&&(i.overflow.to=f)}l.pending_batch&&(i.pending_batch||(i.pending_batch=l.pending_batch)),l._hitZeroPending&&(i._hitZeroPending=!0)}Oe()&&p.unlinkSync(c)}catch{}}}async function oe(){if(!Q&&!(Date.now()<Y)&&!(!I||!a||!i)){Q=!0;try{if(v&&!await Sn()||($()?a.balance<=0&&Date.now()-ve>=Re&&(ve=Date.now(),await J()):await J(),_))return;wt(),await je(),Ae()}catch{}finally{Q=!1}}}function On(){if(!I)return;let e=i.buffer.length,t=e>=an;if(!t&&e>0){let r=new Date(i.buffer[0].ts).getTime();Date.now()-r>=cn&&(t=!0)}t&&setImmediate(oe)}function bt(){m=null,_=null,a=null,i=null,I=!1,re=!1,y&&clearTimeout(y),R&&clearInterval(R),y=null,R=null,Q=!1,K=!1,O=0,Y=0,ve=0,ke=0,F=!1,v=!1,x=null,ee=!1}async function xt(e){if(I)return;if(e=e||{},m=e.apiKey||process.env.REFLEX_API_KEY||nn.loadKey()||null,!m&&on()&&(x=kn(),x&&xe.test(x.trial_key||"")?(m=x.trial_key,F=!0):x&&(F=!0,v=!0)),!m&&!v){_={reason:"no_key",message:w.noKey},I=!0;return}if(m&&!xe.test(m)){_={reason:"no_key",message:w.noKey},I=!0;return}let t=v?rn:pt(m),r=vn();i=r&&r.key_prefix===t?r:xn(t);let n=ht(),o=!1;n&&n.key_prefix&&n.key_prefix===t?n.v===1&&Array.isArray(n.buffer)?(i.buffer=i.buffer.concat(n.buffer),n.overflow&&n.overflow.calls&&(i.overflow.calls+=n.overflow.calls,n.overflow.from&&(i.overflow.from=i.overflow.from||n.overflow.from),n.overflow.to&&(i.overflow.to=n.overflow.to)),n.pending_batch&&!i.pending_batch&&(i.pending_batch=n.pending_batch),n._hitZeroPending&&(i._hitZeroPending=!0),a={v:2,key_id:n.key_id||null,key_prefix:n.key_prefix,token:n.token||null,balance:n.balance||0,free_expires_at:n.free_expires_at||null,last_sync_at:n.last_sync_at||null,max_token_iat:n.max_token_iat||0,last_wall_clock:n.last_wall_clock||new Date().toISOString()},o=!0):a=n:(a=bn(null,t),v&&(a.balance=Ee,N())),I=!0,o&&N(),R||(R=setInterval(oe,Re),R.unref&&R.unref()),setImmediate(()=>{oe()})}function jn(){let e=Date.now(),t=a&&a.last_wall_clock?new Date(a.last_wall_clock).getTime():0;return!(t&&e<t-dt)}function Fn(e){if(_)return{ok:!1,reason:_.reason,message:_.message};if(!a||!i)return{ok:!1,reason:"no_key",message:w.noKey};if(!v&&!jn()&&!$())return{ok:!1,reason:"offline_grace_expired",message:ut()};if(!v&&!$())return{ok:!1,reason:"offline_grace_expired",message:a.token?ut():w.graceExpiredFirstRun};if(a.balance<=0)return i._hitZeroPending=!0,P(),setImmediate(oe),F?{ok:!1,reason:"trial_exhausted",message:w.trialExhausted}:{ok:!1,reason:"out_of_credits",message:a.free_expires_at&&new Date(a.free_expires_at).getTime()<=Date.now()?w.outOfCreditsExpired:w.outOfCredits};a.balance-=1;let t={id:H.randomUUID(),tool:e,ts:new Date().toISOString()};if(i.buffer.push(t),a.last_wall_clock=t.ts,i.buffer.length>un){let n=i.buffer.splice(0,fn);i.overflow.calls+=n.length;let o=n[0].ts,s=n[n.length-1].ts;(!i.overflow.from||o<i.overflow.from)&&(i.overflow.from=o),(!i.overflow.to||s>i.overflow.to)&&(i.overflow.to=s)}P();let r;if(a.balance<=dn){let n=Date.now();n-ke>=pn&&(ke=n,r=wn(a.balance))}return On(),{ok:!0,warn:r,id:t.id}}function Nn(e,t,r,n){if(!i||!e)return;let o=i.buffer.find(s=>s.id===e);o&&(o.ok=!!t,!t&&r&&(o.cat=String(r).slice(0,24)),Number.isFinite(n)&&n>=0&&(o.resp_chars=Math.floor(n)),P())}function Pn(e){if(!a||!i||!e)return;let t=i.buffer.findIndex(r=>r.id===e);if(t>=0&&!(i.pending_batch&&Array.isArray(i.pending_batch._event_ids)&&i.pending_batch._event_ids.includes(e))){i.buffer.splice(t,1),a.balance+=1,P();return}a.balance+=1,P()}function Dn(){return{balance:a?a.balance:0,keyTail:m?m.slice(-4):null,trial:F,trialGrant:Ee}}function ut(){return w.graceExpired}async function qn(){if(y&&(clearTimeout(y),y=null),N(),R&&(clearInterval(R),R=null),!(!I||_||!a||!i)){if(i.buffer.length===0&&!i.pending_batch&&i.overflow.calls===0){try{p.unlinkSync(ne())}catch{}return}await Promise.race([(async()=>{try{$()||await J(),await je()}catch{}})(),new Promise(e=>{let t=setTimeout(e,mn);t.unref&&t.unref()})]),N()}}async function Mn(e){let t=F;bt(),await xt(e),t&&!F&&m&&En(m).catch(()=>{})}vt.exports={init:xt,reinit:Mn,spend:Fn,refund:Pn,recordOutcome:Nn,status:Dn,shutdown:qn,_MSG:w,_TRIAL_GRANT:Ee,_verifyToken:se,_persistNow(){y&&(clearTimeout(y),y=null),N()},async _syncOnce(){O=0,Y=0;try{if(!I||!a||!i||($()||await J(),_))return;wt(),await je(),Ae()}catch{}},_reset:bt}});var Et=D((hr,St)=>{"use strict";function $n(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"}St.exports={classifyFailure:$n}});var $e=require("fs"),{Server:Cn}=require("@modelcontextprotocol/sdk/server/index.js"),{StdioServerTransport:Xn}=require("@modelcontextprotocol/sdk/server/stdio.js"),{ListToolsRequestSchema:Bn,CallToolRequestSchema:Un}=require("@modelcontextprotocol/sdk/types.js"),{readState:G,rpc:A,ensureDaemon:Pe,subEnv:Kn,sanitizeSession:Ce,SESSION:S,HOME:Hn}=et(),Rt=_e(),De=we(),L=`mcp-${process.pid}`,Fe=e=>new Promise(t=>setTimeout(t,e)),b;try{b=kt()}catch{b={init:async()=>{},spend:()=>({ok:!0}),refund:()=>{},recordOutcome:()=>{},status:()=>({}),shutdown:async()=>{},_MSG:{}}}process.env.REFLEX_RAISE===void 0&&(process.env.REFLEX_RAISE="0");var Xe=[{name:"reflex_open",description:"Open a URL in the local Chrome and return a distilled snapshot with element refs like [a3f2]. new_tab opens in a new tab, keeping the current one open.",inputSchema:{type:"object",properties:{url:{type:"string"},new_tab:{type:"boolean",description:"open in a new tab, keeping existing tabs open"},state:{type:"string",description:"saved auth state to load (via reflex_flow state_save)"},headed:{type:"boolean",description:"show the browser window (default true; false = headless)"},session:{type:"string",description:"isolated parallel browser; same name on every call that uses it"}},required:["url"]}},{name:"reflex_act",description:'Run a batch of browser steps in one call; stops at the first failure with a forensic report (reason, near-miss candidates, console/network errors, pre-failure page changes). Success returns only what changed, not the full page. A batch may start cold with {"goto":url}, which opens the browser too, so a flow whose targets you can already name needs no reflex_open.',inputSchema:{type:"object",properties:{steps:{type:"array",items:{type:"object"},description:'Each step is one object: {"goto":url} {"click":t} {"dblclick":t} {"hover":t} {"focus":t} {"fill":[t,value]} {"type":[t,text]} {"press":key} {"select":[t,option]} {"upload":[t,path]} {"check":t} {"uncheck":t} {"scroll":{"by":px}} {"scroll":{"to":t}} {"wait":ms} {"wait":{"text":s}} {"wait":{"url_contains":s}} {"expect":{"visible":t | "hidden":t | "text":s | "url_contains":s | "value":v,"target":t | "download":"*.pdf"}} {"shot":label} {"eval":js}. Target t: ref (a3f2), accessible name, or css=/xpath=. Secrets: {{env:VAR}}. Use expect guards between actions. Downloads auto-save (path in response). Compounds: {"if":{"visible":t,"then":[],"else":[]}} {"try":[steps]} {"repeat":{"do":[],"until":cond,"max":N}} {"extract":t} {"fetch":url}.'},quiet:{type:"boolean",description:"self-guarded batch returns only the result, not a page snapshot"},session:{type:"string"}},required:["steps"]}},{name:"reflex_read",description:"Re-read the current page. Returns only the delta since the last look, '(page unchanged)', or a full snapshot.",inputSchema:{type:"object",properties:{query:{type:"string",description:"only return lines matching this"},full:{type:"boolean",description:"force a full snapshot"},session:{type:"string"}}}},{name:"reflex_extract",description:"Extract data a snapshot folds (table/list/region), a captured JSON feed by its net<id> handle, or a collection. mode:'crawl' = same-domain link manifest; mode:'media' = verified page-media manifest (optional save:true). >6KB spills to a file.",inputSchema:{type:"object",properties:{target:{type:"string",description:"ref, name, or css=/xpath=; omit for main content"},mode:{type:"string",enum:["crawl","media"],description:"crawl: link manifest (maxDepth/maxWidth/maxPages); media: page-media manifest (save:true downloads)"},session:{type:"string"}}}},{name:"reflex_check",description:"Audit the page: visual defects (overlaps, low contrast, clipped text, broken images) plus recent console errors and failed network requests.",inputSchema:{type:"object",properties:{session:{type:"string"}}}},{name:"reflex_shot",description:"Screenshot the page or one element. Returns the image and its path.",inputSchema:{type:"object",properties:{region:{type:"string",description:"ref or name to crop to"},full:{type:"boolean",description:"full page height"},path_only:{type:"boolean",description:"return only the file path, no image tokens"},session:{type:"string"}}}},{name:"reflex_tab",description:"List, switch to, or close browser tabs. Popups and target=_blank are followed automatically.",inputSchema:{type:"object",properties:{n:{type:"integer",description:"tab number to switch to; omit to list"},close:{type:"boolean",description:"close tab n instead of switching"},session:{type:"string"}}}},{name:"reflex_flow",description:"Reusable automation: save this session's recorded steps as a flow, run a saved flow (deterministic replay, no page reading needed), list flows, or save auth state (cookies + localStorage) for reflex_open.",inputSchema:{type:"object",properties:{action:{type:"string",enum:["save","run","list","state_save"]},name:{type:"string",description:"flow or state name"},params:{type:"array",items:{type:"string"},description:"save: values to parameterize as {{name}}"},values:{type:"object",description:"run: parameter values"},last:{type:"integer",description:"save: keep only the last N steps"},session:{type:"string"}},required:["action"]}},{name:"reflex_session",description:"List or stop parallel browser sessions. Free (no credit). Sessions spawn on demand on first use; each is an isolated browser, safe for concurrent agents.",inputSchema:{type:"object",properties:{action:{type:"string",enum:["list","stop"]},session:{type:"string",description:"stop: which session"}},required:["action"]}},{name:"reflex_auth",description:"Sign in to Reflex (required before billed calls). Free. login opens a browser to sign in and stores the key; logout clears it; status shows account + credits. Tell the user to finish sign-in in the browser tab.",inputSchema:{type:"object",properties:{action:{type:"string",enum:["login","logout","status"]}},required:["action"]}}];function Be(){let e=process.env.REFLEX_MCP_EVAL;return e!=="0"&&e!=="false"&&e!=="off"}Be()&&Xe.push({name:"reflex_eval",description:"Run page JavaScript and return the result. Prefer act {eval} for side effects.",inputSchema:{type:"object",properties:{js:{type:"string"}},required:["js"]}});var It='Reflex drives a local Chrome. Do the whole task in ONE reflex_act that starts {"goto":url}, with expect guards. Only call reflex_open first if you truly cannot guess the target labels. A wrong guess is cheap: the failure report names the right [ref], so fix it and resend that same turn. Read the returned delta, do not re-read. 1 credit per call.';function Yn(e){switch(e.action){case"save":return{cmd:"flow_save",args:{name:e.name,params:e.params,last:e.last}};case"run":return{cmd:"flow_run",args:{name:e.name,params:e.values||{}}};case"list":return{cmd:"flow_list",args:{}};case"state_save":return{cmd:"state_save",args:{name:e.name}};default:throw new Error("action must be save|run|list|state_save")}}function ce(e,t){if(t=t||new Set,!Array.isArray(e))return t;for(let r of e){if(!r||typeof r!="object")continue;let n=Object.keys(r)[0];t.add(n);let o=r[n];if(Array.isArray(o))ce(o,t);else if(o&&typeof o=="object"){for(let s of["then","else","do","steps"])Array.isArray(o[s])&&ce(o[s],t);n==="optional"&&ce([o],t)}}return t}var Jn={reflex_open:{map:e=>{if(!e.url)throw new Error("url required");return{cmd:"open",args:{url:e.url,state:e.state,headed:e.headed,new_tab:e.new_tab}}}},reflex_act:{map:e=>{if(!Array.isArray(e.steps))throw new Error("steps must be an array");if(!Be()&&ce(e.steps).has("eval"))throw new Error("eval steps are disabled (REFLEX_MCP_EVAL=0; unset to enable)");return{cmd:"act",args:{steps:e.steps,quiet:e.quiet}}}},reflex_read:{map:e=>({cmd:"read",args:{query:e.query,full:e.full}})},reflex_extract:{map:e=>({cmd:"extract",args:{target:e.target,mode:e.mode,maxDepth:e.maxDepth,maxWidth:e.maxWidth,maxPages:e.maxPages,save:e.save,includeAuth:e.includeAuth}})},reflex_check:{map:()=>({cmd:"check",args:{visual:!0}})},reflex_shot:{map:e=>({cmd:"shot",args:{region:e.region,full:e.full}}),shape:Qn},reflex_tab:{map:e=>e.n===void 0?{cmd:"tabs",args:{}}:{cmd:"tab",args:{n:e.n,close:e.close}}},reflex_flow:{map:Yn},reflex_eval:{map:e=>({cmd:"eval",args:{js:e.js}})}},Gn=new Set(["read","check","tabs","extract","shot","flow_list","open"]);function Wn(e){let t=process.env.REFLEX_METER;return b.spend(e)}function Ne(e){let t=process.env.REFLEX_METER;if(!(!e||!e.id))try{b.refund(e.id)}catch{}}var{classifyFailure:Tt}=Et();function zn(e,t,r,n){let o=process.env.REFLEX_METER;if(!(!e||!e.id||typeof b.recordOutcome!="function"))try{b.recordOutcome(e.id,t,t?null:Tt(r),n)}catch{}}function Zn(e){return!e||!Array.isArray(e.content)?0:e.content.reduce((t,r)=>t+(r&&r.type==="text"?String(r.text||"").length:0),0)}var k=e=>({isError:!0,content:[{type:"text",text:e}]});function Vn(e){return/Executable doesn'?t exist|is not found at|playwright install|please run the following/i.test(e)}function At(e,t){if(e.ok){let n=t&&t.warn?`
`+t.warn:"";return{content:[{type:"text",text:e.text+n}]}}if(Vn(e.text))return k("Reflex needs Google Chrome installed (it drives your real browser). Install Chrome and retry.");let r=e.text;if(process.env.REFLEX_FAIL_SHOT==="inline"&&e.artifact){let n=[{type:"text",text:r}];try{let o=$e.readFileSync(e.artifact);n.push({type:"image",data:o.toString("base64"),mimeType:"image/png"})}catch{}return{isError:!0,content:n}}return r=r.replace(/^screenshot: .*$/m,"screenshot saved (call reflex_shot to view the page)"),{isError:!0,content:[{type:"text",text:r}]}}function Qn(e,t,r){if(!e.ok)return At(e,r);let n=r&&r.warn?`
`+r.warn:"",o=e.text+n;if(t.path_only)return{content:[{type:"text",text:o}]};let s=null;try{s=$e.readFileSync(e.artifact)}catch{}let c=/(\d+)x(\d+)/.exec(e.text||""),l=c?+c[2]:0;return s&&s.length<=2*1024*1024&&l<=2e3?{content:[{type:"text",text:o},{type:"image",data:s.toString("base64"),mimeType:"image/png"}]}:{content:[{type:"text",text:o+`
image too large to inline; retry with region or path_only`}]}}function ie(e){let t=new Error(e);return t.transport=!0,t.kind=e,t}function qe(e){let t={};return process.env.REFLEX_IDLE_EXIT_MIN||(t.REFLEX_IDLE_EXIT_MIN=!e||e===S?"20":"15"),process.env.REFLEX_RAISE===void 0&&(t.REFLEX_RAISE="0"),Object.keys(t).length?t:void 0}var Ue=new Set,Me=0,le=[];function er(e){return le.find(t=>t.name===e)||null}function tr(){let e=le.find(t=>t.n===0);return e||(e={name:Ce(`lane${process.pid}x${le.length+1}`),n:0},le.push(e)),Ue.add(e.name),e}var ae=null;function nr(){return ae||(ae=(async()=>{if(process.env.REFLEX_AUTO_ISOLATE==="0"||process.env.REFLEX_SESSION&&S!=="default")return S;try{let e=await Pe(S,qe(S)),t=await A(e,"claim",{caller:L},L),r=t&&t.owned?S:`a${process.pid}`;return r!==S&&console.error(`reflex: default session in use by another agent; auto-isolated to session=${r}`),r}catch{return S}})(),ae)}async function rr(e,t,r){r&&r!==S&&Ue.add(r);let n;try{n=await Pe(r,qe(r))}catch{throw ie("spawn")}try{return await A(n,e,t,L)}catch(o){if(/timeout/i.test(String(o.message||o)))throw ie("timeout");if(Gn.has(e))try{let s=await Pe(r,qe(r));return await A(s,e,t,L)}catch{throw ie("lost")}throw ie("lost")}}function or(e){return e==="timeout"?"browser call timed out after 120s; the page may still be loading. Use reflex_read to see the current state.":"browser restarted; page state was lost. Use reflex_open to reopen the page, then retry."}async function sr(e){if(e.action==="stop"){if(!e.session)throw new Error("session required for stop");let n=Ce(e.session),o=G(n);if(!o)return{content:[{type:"text",text:`session ${n}: not running`}]};try{await A(o,"stop",{},L)}catch{}return{content:[{type:"text",text:`session ${n}: stopped`}]}}if(e.action!=="list")throw new Error("action must be list|stop");let t=$e.readdirSync(Hn).map(n=>{let o=/^daemon(?:-([A-Za-z0-9_-]+))?\.json$/.exec(n);return o?o[1]||"default":null}).filter(Boolean),r=[];for(let n of t){let o=G(n);if(o)try{let c=(((await A(o,"status",{},L)).text||"").match(/^page: (.*)$/m)||[])[1];r.push(`${n}${n===S?" (default)":""}: ${c||"no page open"}`)}catch{}}return{content:[{type:"text",text:r.length?r.join(`
`):"(no active sessions)"}]}}async function ir(e){let t=e&&e.action;if(t==="logout"){let n=Rt.logout();return await b.reinit({}).catch(()=>{}),{content:[{type:"text",text:n?"Signed out of Reflex. Run reflex_auth login to sign back in.":"Not signed in."}]}}if(t==="status"){let n=!!process.env.REFLEX_API_KEY,o=(()=>{try{return b.status()}catch{return{}}})();return o.trial?{content:[{type:"text",text:`Running on the free install trial, no account needed: ${o.balance} of ${o.trialGrant} calls left. Run reflex_auth login to create a free account and keep going.`}]}:o.keyTail?{content:[{type:"text",text:`Signed in (${n?"env REFLEX_API_KEY":"browser login"}); key \u2026${o.keyTail}, ${o.balance} credits.`}]}:{content:[{type:"text",text:"Not signed in. Run reflex_auth login to sign in (opens your browser)."}]}}if(t!=="login")throw new Error("action must be login|logout|status");if(process.env.REFLEX_API_KEY)return{content:[{type:"text",text:"Already authenticated via the REFLEX_API_KEY environment variable; no browser login needed."}]};let r=null;try{let n=await Rt.login({onUrl:s=>{r=s,console.error("reflex login url: "+s)}});return await b.reinit({}).catch(()=>{}),{content:[{type:"text",text:`Signed in to Reflex${typeof n.balance=="number"?`, ${n.balance} credits`:""}. You can retry the call you wanted to make.`}]}}catch(n){let o=r?` If your browser did not open, sign in here: ${r}`:"";return k(`Reflex sign-in did not complete: ${String(n.message||n)}.${o}`)}}async function Ot(e,t){if(e==="reflex_session")try{return await sr(t||{})}catch(u){return k("bad arguments: "+String(u.message||u))}if(e==="reflex_auth")try{return await ir(t||{})}catch(u){return k("bad arguments: "+String(u.message||u))}let r=Jn[e];if(!r)return k(`unknown tool: ${e}`);if(e==="reflex_eval"&&!Be())return k("reflex_eval is disabled (REFLEX_MCP_EVAL=0; unset to enable)");let n;t&&t.session!==void 0&&(n=Ce(t.session),t=Object.assign({},t),delete t.session);let o=Wn(e);if(!o.ok)return k(o.message);let s;try{s=r.map(t||{});let u={};s.args=Kn(s.args,u),s.cmd==="act"&&Object.keys(u).length&&(s.args.__env=u)}catch(u){return Ne(o),k("bad arguments: "+String(u.message||u))}let c="",l=null;n===void 0?Me>1?(l=tr(),n=l.name,c=`[reflex: another browser call was already running, so this one got its own browser, session "${n}". Pass session:"${n}" on the rest of this task to stay in it.]
`):n=await nr():l=er(n),l&&l.n++;let d;try{d=await rr(s.cmd,s.args,n)}catch(u){return u.transport?(Ne(o),k(or(u.kind))):(Ne(o),k("error: "+String(u.message||u)))}finally{l&&l.n--}let f=r.shape?r.shape(d,t||{},o):At(d,o);return zn(o,d.ok,d.text,Zn(f)),c&&Array.isArray(f.content)&&f.content[0]&&f.content[0].type==="text"&&(f.content[0].text=c+f.content[0].text),f}var Ke=new Cn({name:"reflex",version:De.version},{capabilities:{tools:{}},instructions:It});Ke.setRequestHandler(Bn,async()=>({tools:Xe}));Ke.setRequestHandler(Un,async e=>{let{name:t,arguments:r}=e.params||{},n=t!=="reflex_auth"&&t!=="reflex_session";n&&Me++;try{return await Ot(t,r)}catch(o){return k("error: "+String(o.message||o))}finally{n&&Me--}});var Lt=!1;async function ue(){if(Lt)return;Lt=!0;try{await Promise.race([b.shutdown(),Fe(2100)])}catch{}let e=process.env.REFLEX_STOP_ON_EXIT==="1"?"stop":"detach";try{let t=G();t&&await Promise.race([A(t,e,{caller:L},L),Fe(2e3)])}catch{}for(let t of Ue)try{let r=G(t);r&&await Promise.race([A(r,e,{caller:L},L),Fe(1e3)])}catch{}process.exit(0)}async function ar(){try{let s=G();if(s){let c=await A(s,"ping",{});c&&c.v&&c.v!==De.version&&await A(s,"stop",{}).catch(()=>{})}}catch{}b.init({apiKey:process.env.REFLEX_API_KEY}).catch(()=>{});let e=process.env.REFLEX_API_KEY?"set":"none";try{let s=b.status();s&&s.keyTail&&(e=s.keyTail)}catch{}console.error(`reflex mcp v${De.version} session=${S} key=${e}`);let t=new Xn;await Ke.connect(t);let r=t.onclose;t.onclose=()=>{if(r)try{r()}catch{}ue()};let n=process.ppid,o=setInterval(()=>{n!==1&&process.ppid===1&&ue()},5e3);o.unref&&o.unref()}process.on("SIGINT",ue);process.on("SIGTERM",ue);module.exports={TOOLS:Xe,INSTRUCTIONS:It,callTool:Ot,classifyFailure:Tt,start:ar};
(150 credits for $9). Then simply retry this call.`};function Ln(e){return`[reflex: ${e} credits left. Top up: https://reflexmcp.com/pricing]`}var m=null,b=null,a=null,i=null,ie=!1,_=null,R=null,ee=!1,N=!1,B=null,Se=yt,F=0,G=0,Ee=0,Re=0,I=!1,D=!1,w=!1,g=null,te=!1,ne=null;function dt(e){return Buffer.from(e.replace(/-/g,"+").replace(/_/g,"/"),"base64")}function In(e,t){return{v:2,key_id:e||null,key_prefix:t||null,token:null,balance:0,free_expires_at:null,last_sync_at:null,max_token_iat:0,last_wall_clock:new Date().toISOString()}}function Tn(e){return{v:1,pid:process.pid,key_prefix:e||null,buffer:[],overflow:{calls:0,from:null,to:null},pending_batch:null}}function _t(e){return e?e.slice(0,13):null}function wt(){try{let e=JSON.parse(h.readFileSync(re(),"utf8"));if(e&&(e.v===1||e.v===2))return e}catch{}return null}function An(){try{let e=JSON.parse(h.readFileSync(se(),"utf8"));if(e&&e.v===1&&Array.isArray(e.buffer))return e}catch{}return null}function je(){h.existsSync(T())||h.mkdirSync(T(),{recursive:!0})}function bt(){try{let e=JSON.parse(h.readFileSync(ke(),"utf8"));if(e&&e.v===1&&typeof e.device_id=="string")return e}catch{}return null}function xt(e){try{je();let t=ke()+".tmp";return h.writeFileSync(t,JSON.stringify(e),{mode:384}),h.renameSync(t,ke()),!0}catch{return!1}}function On(){let e=bt();if(e)return e;let t={v:1,device_id:J.randomUUID(),trial_key:null,claimed_at:null};return xt(t)?t:null}async function vt(){if(te||!g||!w)return!1;te=!0;try{if(g.trial_key&&oe.test(g.trial_key)){m=g.trial_key;let o=await U();return o&&j()&&(w=!1),o}let e=new AbortController,t=setTimeout(()=>e.abort(),Ae),r;try{r=await fetch(Le+"/v1/trial/claim",{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({device_id:g.device_id,client_version:Oe}),signal:e.signal})}finally{clearTimeout(t)}if(r.status===429)return b={reason:"no_key",message:x.noKey},w=!1,!1;let n=await r.json().catch(()=>null);if(!r.ok||!n||!oe.test(n.api_key||""))return!1;m=n.api_key;let s=_t(m);return a.key_prefix=s,i.key_prefix=s,typeof n.balance=="number"&&(a.balance=Math.max(0,n.balance-i.buffer.length)),g.trial_key=m,g.claimed_at=new Date().toISOString(),xt(g),M(),await U(),j()&&(w=!1),!0}catch{return!1}finally{te=!1}}async function jn(e){let t=bt();if(!(!t||!e))try{let r=new AbortController,n=setTimeout(()=>r.abort(),Ae);try{await fetch(Le+"/v1/trial/convert",{method:"POST",headers:{authorization:`Bearer ${e}`,"content-type":"application/json"},body:JSON.stringify({device_id:t.device_id}),signal:r.signal})}finally{clearTimeout(n)}}catch{}}function pt(e,t){let r=e?Date.parse(e):NaN,n=t?Date.parse(t):NaN;return Number.isNaN(r)?!1:Number.isNaN(n)?!0:r>n}function Fn(){let e=mt(),t=Date.now()+En;for(;;)try{return h.mkdirSync(e),!0}catch{try{let n=h.statSync(e);if(Date.now()-n.mtimeMs>Rn){h.rmdirSync(e);continue}}catch{}if(Date.now()>=t)return!1;let r=Math.min(Date.now()+10,t);for(;Date.now()<r;);}}function Nn(){try{h.rmdirSync(mt())}catch{}}function Fe(){if(!a)return;let e=wt();if(!(!e||e.v!==2||e.key_prefix!==a.key_prefix)){if((e.max_token_iat||0)>(a.max_token_iat||0)&&e.token&&(a.token=e.token,a.max_token_iat=e.max_token_iat,a.free_expires_at=e.free_expires_at||a.free_expires_at),pt(e.last_sync_at,a.last_sync_at)){let t=i?i.buffer.length:0;a.balance=(e.balance||0)-t,a.last_sync_at=e.last_sync_at}pt(e.last_wall_clock,a.last_wall_clock)&&(a.last_wall_clock=e.last_wall_clock),a.key_id=a.key_id||e.key_id}}function Pn(){if(a)try{je();let e=Fn();try{Fe();let t=re()+".tmp."+process.pid;h.writeFileSync(t,JSON.stringify(a),{mode:384}),h.renameSync(t,re())}finally{e&&Nn()}}catch{}}function Ne(){if(!i)return!1;try{je();let e=se()+".tmp";return h.writeFileSync(e,JSON.stringify(i),{mode:384}),h.renameSync(e,se()),!0}catch{return!1}}function M(){Ne(),Pn(),ie=!1}function q(){ie=!0,!_&&(_=setTimeout(()=>{_=null,ie&&M()},gn),_.unref&&_.unref())}function ce(e){if(typeof e!="string")return null;let t=e.split(".");if(t.length!==3||t[0]!=="RFX1")return null;let[,r,n]=t,s;try{s=JSON.parse(dt(r).toString("utf8"))}catch{return null}let o=pn[s.kid];if(!o||o.startsWith("REPLACE_"))return null;let c;try{c=J.createPublicKey({key:Buffer.concat([Buffer.from("302a300506032b6570032100","hex"),Buffer.from(o,"base64")]),format:"der",type:"spki"})}catch{return null}let l=Buffer.from("RFX1."+r,"ascii"),d=!1;try{d=J.verify(null,l,c,dt(n))}catch{return null}return d?s:null}function kt(e,t,r,n){a.token=e,a.max_token_iat=Math.max(a.max_token_iat||0,t.iat||0),a.balance=r-(n||0),a.free_expires_at=t.fxp?new Date(t.fxp*1e3).toISOString():null,a.last_sync_at=new Date().toISOString(),q()}function j(){if(!a||!a.token)return!1;let e=ce(a.token);if(!e||(e.iat||0)<(a.max_token_iat||0))return!1;let t=Math.floor(Date.now()/1e3);return!(e.exp<=t-gt/1e3)}async function St(e,t,r,n){let s=new AbortController,o=setTimeout(()=>s.abort(),n);try{let c=await fetch(Le+t,{method:e,headers:{authorization:`Bearer ${m}`,"content-type":"application/json"},body:r?JSON.stringify(r):void 0,signal:s.signal}),l=null;try{l=await c.json()}catch{}return{status:c.status,json:l}}finally{clearTimeout(o)}}async function U(){let{status:e,json:t}=await St("POST","/v1/validate",{client_version:Oe},Ae);if(e===401||e===403){b={reason:e===403?"key_revoked":"bad_key",message:x.badKey};try{h.unlinkSync(re())}catch{}return!1}if(e===200&&t&&t.ok&&t.token){let r=ce(t.token);if(r&&(r.iat||0)>=(a.max_token_iat||0))return b=null,a.key_id=t.key_id||a.key_id,kt(t.token,r,t.balance,i.buffer.length),!0}return!1}function Dn(e){if(i.pending_batch)return i.pending_batch;if(i.buffer.length===0&&i.overflow.calls===0)return null;let t=e?1/0:Date.now()-yn,r=i.buffer.filter(f=>f.ok!==void 0||new Date(f.ts).getTime()<=t);if(r.length===0&&i.overflow.calls===0)return null;let n={},s=null,o=null,c=0,l=0,d=0,u={};for(let f of r){if(n[f.tool]=(n[f.tool]||0)+1,f.ok===!0)c++;else if(f.ok===!1){let O=f.cat||"other";l++,u[O]=(u[O]||0)+1}Number.isFinite(f.resp_chars)&&(d+=f.resp_chars),(!s||f.ts<s)&&(s=f.ts),(!o||f.ts>o)&&(o=f.ts)}let p=new Date().toISOString(),y={batch_id:J.randomUUID(),calls:r.length,tools:n,ok:c,fail:l,overflow_calls:i.overflow.calls,period_start:s||i.overflow.from||p,period_end:o||i.overflow.to||p,client_balance:a.balance,hit_zero:!!i._hitZeroPending,client_version:Oe,_event_ids:r.map(f=>f.id)};return Object.keys(u).length&&(y.fail_cats=u),d>0&&(y.resp_chars=d),y.calls===0&&y.overflow_calls===0?null:y}async function Pe(e){for(let t=0;t<ft&&N&&B;t++)try{await B}catch{}if(!N)for(let t=0;t<ft;t++){let r=Mn(e);B=r;let n=!1;try{n=await r}finally{B===r&&(B=null)}if(!n||i.buffer.length===0&&i.overflow.calls===0)return}}async function Mn(e){if(N||!a||!i||!j()&&!i.pending_batch)return!1;let t=Dn(e);if(!t)return!1;N=!0,i.pending_batch=t,Ne();let{_event_ids:r,...n}=t,s=null;try{s=await St("POST","/v1/usage",n,vn)}catch{s=null}if(s&&s.status===200&&s.json&&s.json.ok&&s.json.token){let o=ce(s.json.token);if(o&&(o.iat||0)>=(a.max_token_iat||0)){let c=new Set(r),l=i.buffer.filter(u=>!c.has(u.id)),d=l.length;return i.buffer=l,i.overflow={calls:0,from:null,to:null},i._hitZeroPending=!1,i.pending_batch=null,kt(s.json.token,o,s.json.balance,d),F=0,G=0,N=!1,!0}}return s&&(s.status===401||s.status===403)&&(b={reason:s.status===403?"key_revoked":"bad_key",message:x.badKey},i.pending_batch=null),F=F?Math.min(F*2,Sn):Te,G=Date.now()+F,N=!1,q(),!1}function qn(e){try{return process.kill(e,0),!0}catch(t){return t&&t.code!=="ESRCH"}}function Et(){if(!i)return;let e;try{e=h.readdirSync(T())}catch{return}for(let t of e){let r=/^usage-(\d+)\.json$/.exec(t);if(!r)continue;let n=Number(r[1]);if(n===process.pid||qn(n))continue;let s=P.join(T(),t),o=null;try{o=JSON.parse(h.readFileSync(s,"utf8"))}catch{continue}if(!o||o.v!==1||!Array.isArray(o.buffer)||o.key_prefix&&i.key_prefix&&o.key_prefix!==i.key_prefix)continue;let c=P.join(T(),`usage-${n}.claimed-${process.pid}.json`);try{h.renameSync(s,c)}catch{continue}try{let l=JSON.parse(h.readFileSync(c,"utf8"));if(l&&Array.isArray(l.buffer)){if(i.buffer=i.buffer.concat(l.buffer),l.overflow&&l.overflow.calls){i.overflow.calls+=l.overflow.calls;let{from:d,to:u}=l.overflow;d&&(!i.overflow.from||d<i.overflow.from)&&(i.overflow.from=d),u&&(!i.overflow.to||u>i.overflow.to)&&(i.overflow.to=u)}l.pending_batch&&(i.pending_batch||(i.pending_batch=l.pending_batch)),l._hitZeroPending&&(i._hitZeroPending=!0)}Ne()&&h.unlinkSync(c)}catch{}}}async function ae(){if(!ee&&!(Date.now()<G)&&!(!I||!a||!i)){ee=!0;try{if(w&&(ne=vt(),!await ne.finally(()=>{ne=null}))||(j()?a.balance<=0&&Date.now()-Ee>=Te&&(Ee=Date.now(),await U()):await U(),b))return;Et(),await Pe(),Fe()}catch{}finally{ee=!1}}}function Rt(){if(!I)return;let e=i.buffer.length,t=e>=hn;if(!t&&e>0){let r=new Date(i.buffer[0].ts).getTime();Date.now()-r>=mn&&(t=!0)}!t&&Se>0&&i.buffer.some(r=>r.ok!==void 0)&&(Se--,t=!0),t&&setImmediate(ae)}function Lt(){m=null,b=null,a=null,i=null,I=!1,ie=!1,_&&clearTimeout(_),R&&clearInterval(R),_=null,R=null,ee=!1,N=!1,B=null,Se=yt,F=0,G=0,Ee=0,Re=0,D=!1,w=!1,g=null,te=!1}async function It(e){if(I)return;if(e=e||{},m=e.apiKey||process.env.REFLEX_API_KEY||un.loadKey()||null,!m&&dn()&&(g=On(),g&&oe.test(g.trial_key||"")?(m=g.trial_key,D=!0):g&&(D=!0,w=!0)),!m&&!w){b={reason:"no_key",message:x.noKey},I=!0;return}if(m&&!oe.test(m)){b={reason:"no_key",message:x.noKey},I=!0;return}let t=w?fn:_t(m),r=An();i=r&&r.key_prefix===t?r:Tn(t);let n=wt(),s=!1;n&&n.key_prefix&&n.key_prefix===t?n.v===1&&Array.isArray(n.buffer)?(i.buffer=i.buffer.concat(n.buffer),n.overflow&&n.overflow.calls&&(i.overflow.calls+=n.overflow.calls,n.overflow.from&&(i.overflow.from=i.overflow.from||n.overflow.from),n.overflow.to&&(i.overflow.to=n.overflow.to)),n.pending_batch&&!i.pending_batch&&(i.pending_batch=n.pending_batch),n._hitZeroPending&&(i._hitZeroPending=!0),a={v:2,key_id:n.key_id||null,key_prefix:n.key_prefix,token:n.token||null,balance:n.balance||0,free_expires_at:n.free_expires_at||null,last_sync_at:n.last_sync_at||null,max_token_iat:n.max_token_iat||0,last_wall_clock:n.last_wall_clock||new Date().toISOString()},s=!0):a=n:(a=In(null,t),w&&(a.balance=Ie,M())),I=!0,s&&M(),R||(R=setInterval(ae,Te),R.unref&&R.unref()),setImmediate(()=>{ae()})}function Cn(){let e=Date.now(),t=a&&a.last_wall_clock?new Date(a.last_wall_clock).getTime():0;return!(t&&e<t-gt)}function $n(e){if(b)return{ok:!1,reason:b.reason,message:b.message};if(!a||!i)return{ok:!1,reason:"no_key",message:x.noKey};if(!w&&!Cn()&&!j())return{ok:!1,reason:"offline_grace_expired",message:ht()};if(!w&&!j())return{ok:!1,reason:"offline_grace_expired",message:a.token?ht():x.graceExpiredFirstRun};if(a.balance<=0)return i._hitZeroPending=!0,q(),setImmediate(ae),D?{ok:!1,reason:"trial_exhausted",message:x.trialExhausted}:{ok:!1,reason:"out_of_credits",message:a.free_expires_at&&new Date(a.free_expires_at).getTime()<=Date.now()?x.outOfCreditsExpired:x.outOfCredits};a.balance-=1;let t={id:J.randomUUID(),tool:e,ts:new Date().toISOString()};if(i.buffer.push(t),a.last_wall_clock=t.ts,i.buffer.length>_n){let n=i.buffer.splice(0,wn);i.overflow.calls+=n.length;let s=n[0].ts,o=n[n.length-1].ts;(!i.overflow.from||s<i.overflow.from)&&(i.overflow.from=s),(!i.overflow.to||o>i.overflow.to)&&(i.overflow.to=o)}q();let r;if(a.balance<=bn){let n=Date.now();n-Re>=xn&&(Re=n,r=Ln(a.balance))}return Rt(),{ok:!0,warn:r,id:t.id}}function Xn(e,t,r,n){if(!i||!e)return;let s=i.buffer.find(o=>o.id===e);s&&(s.ok=!!t,!t&&r&&(s.cat=String(r).slice(0,24)),Number.isFinite(n)&&n>=0&&(s.resp_chars=Math.floor(n)),q(),Rt())}function Bn(e){if(!a||!i||!e)return;let t=i.buffer.findIndex(r=>r.id===e);if(t>=0&&!(i.pending_batch&&Array.isArray(i.pending_batch._event_ids)&&i.pending_batch._event_ids.includes(e))){i.buffer.splice(t,1),a.balance+=1,q();return}a.balance+=1,q()}function Un(){return{balance:a?a.balance:0,keyTail:m?m.slice(-4):null,trial:D,trialGrant:Ie}}function ht(){return x.graceExpired}async function Kn(){if(_&&(clearTimeout(_),_=null),M(),R&&(clearInterval(R),R=null),!(!I||b||!a||!i)){if(i.buffer.length===0&&!i.pending_batch&&i.overflow.calls===0){try{h.unlinkSync(se())}catch{}return}await Promise.race([(async()=>{try{if(w)try{await(ne||vt())}catch{}m&&!j()&&await U(),await Pe(!0)}catch{}})(),new Promise(e=>{let t=setTimeout(e,kn);t.unref&&t.unref()})]),M()}}async function Hn(e){let t=D;Lt(),await It(e),t&&!D&&m&&jn(m).catch(()=>{})}Tt.exports={init:It,reinit:Hn,spend:$n,refund:Bn,recordOutcome:Xn,status:Un,shutdown:Kn,_MSG:x,_TRIAL_GRANT:Ie,_verifyToken:ce,_persistNow(){_&&(clearTimeout(_),_=null),M()},async _syncOnce(){F=0,G=0;try{if(!I||!a||!i||(j()||await U(),b))return;Et(),await Pe(),Fe()}catch{}},_reset:Lt}});var jt=C((xr,Ot)=>{"use strict";function Yn(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"}Ot.exports={classifyFailure:Yn}});var Be=require("fs"),{Server:Jn}=require("@modelcontextprotocol/sdk/server/index.js"),{StdioServerTransport:Gn}=require("@modelcontextprotocol/sdk/server/stdio.js"),{ListToolsRequestSchema:Wn,CallToolRequestSchema:zn}=require("@modelcontextprotocol/sdk/types.js"),{readState:W,rpc:A,ensureDaemon:qe,subEnv:Zn,sanitizeSession:Ue,SESSION:S,HOME:Vn}=rt(),Ft=xe(),Ce=ve(),L=`mcp-${process.pid}`,De=e=>new Promise(t=>setTimeout(t,e)),v;try{v=At()}catch{v={init:async()=>{},spend:()=>({ok:!0}),refund:()=>{},recordOutcome:()=>{},status:()=>({}),shutdown:async()=>{},_MSG:{}}}process.env.REFLEX_RAISE===void 0&&(process.env.REFLEX_RAISE="0");var Ke=[{name:"reflex_open",description:"Open a URL in the local Chrome and return a distilled snapshot with element refs like [a3f2]. new_tab opens in a new tab, keeping the current one open.",inputSchema:{type:"object",properties:{url:{type:"string"},new_tab:{type:"boolean",description:"open in a new tab, keeping existing tabs open"},state:{type:"string",description:"saved auth state to load (via reflex_flow state_save)"},headed:{type:"boolean",description:"show the browser window (default true; false = headless)"},session:{type:"string",description:"isolated parallel browser; same name on every call that uses it"}},required:["url"]}},{name:"reflex_act",description:'Run a batch of browser steps in one call; stops at the first failure with a forensic report (reason, near-miss candidates, console/network errors, pre-failure page changes). Success returns only what changed, not the full page. A batch may start cold with {"goto":url}, which opens the browser too, so a flow whose targets you can already name needs no reflex_open.',inputSchema:{type:"object",properties:{steps:{type:"array",items:{type:"object"},description:'Each step is one object: {"goto":url} {"click":t} {"dblclick":t} {"hover":t} {"focus":t} {"fill":[t,value]} {"type":[t,text]} {"press":key} {"select":[t,option]} {"upload":[t,path]} {"check":t} {"uncheck":t} {"scroll":{"by":px}} {"scroll":{"to":t}} {"wait":ms} {"wait":{"text":s}} {"wait":{"url_contains":s}} {"expect":{"visible":t | "hidden":t | "text":s | "url_contains":s | "value":v,"target":t | "download":"*.pdf"}} {"shot":label} {"eval":js}. Target t: ref (a3f2), accessible name, or css=/xpath=. Secrets: {{env:VAR}}. Use expect guards between actions. Downloads auto-save (path in response). Compounds: {"if":{"visible":t,"then":[],"else":[]}} {"try":[steps]} {"repeat":{"do":[],"until":cond,"max":N}} {"extract":t} {"fetch":url}.'},quiet:{type:"boolean",description:"self-guarded batch returns only the result, not a page snapshot"},session:{type:"string"}},required:["steps"]}},{name:"reflex_read",description:"Re-read the current page. Returns only the delta since the last look, '(page unchanged)', or a full snapshot.",inputSchema:{type:"object",properties:{query:{type:"string",description:"only return lines matching this"},full:{type:"boolean",description:"force a full snapshot"},session:{type:"string"}}}},{name:"reflex_extract",description:"Extract data a snapshot folds (table/list/region), a captured JSON feed by its net<id> handle, or a collection. mode:'crawl' = same-domain link manifest; mode:'media' = verified page-media manifest (optional save:true). >6KB spills to a file.",inputSchema:{type:"object",properties:{target:{type:"string",description:"ref, name, or css=/xpath=; omit for main content"},mode:{type:"string",enum:["crawl","media"],description:"crawl: link manifest (maxDepth/maxWidth/maxPages); media: page-media manifest (save:true downloads)"},session:{type:"string"}}}},{name:"reflex_check",description:"Audit the page: visual defects (overlaps, low contrast, clipped text, broken images) plus recent console errors and failed network requests.",inputSchema:{type:"object",properties:{session:{type:"string"}}}},{name:"reflex_shot",description:"Screenshot the page or one element. Returns the image and its path.",inputSchema:{type:"object",properties:{region:{type:"string",description:"ref or name to crop to"},full:{type:"boolean",description:"full page height"},path_only:{type:"boolean",description:"return only the file path, no image tokens"},session:{type:"string"}}}},{name:"reflex_tab",description:"List, switch to, or close browser tabs. Popups and target=_blank are followed automatically.",inputSchema:{type:"object",properties:{n:{type:"integer",description:"tab number to switch to; omit to list"},close:{type:"boolean",description:"close tab n instead of switching"},session:{type:"string"}}}},{name:"reflex_flow",description:"Reusable automation: save this session's recorded steps as a flow, run a saved flow (deterministic replay, no page reading needed), list flows, or save auth state (cookies + localStorage) for reflex_open.",inputSchema:{type:"object",properties:{action:{type:"string",enum:["save","run","list","state_save"]},name:{type:"string",description:"flow or state name"},params:{type:"array",items:{type:"string"},description:"save: values to parameterize as {{name}}"},values:{type:"object",description:"run: parameter values"},last:{type:"integer",description:"save: keep only the last N steps"},session:{type:"string"}},required:["action"]}},{name:"reflex_session",description:"List or stop parallel browser sessions. Free (no credit). Sessions spawn on demand on first use; each is an isolated browser, safe for concurrent agents.",inputSchema:{type:"object",properties:{action:{type:"string",enum:["list","stop"]},session:{type:"string",description:"stop: which session"}},required:["action"]}},{name:"reflex_auth",description:"Sign in to Reflex (required before billed calls). Free. login opens a browser to sign in and stores the key; logout clears it; status shows account + credits. Tell the user to finish sign-in in the browser tab.",inputSchema:{type:"object",properties:{action:{type:"string",enum:["login","logout","status"]}},required:["action"]}}];function He(){let e=process.env.REFLEX_MCP_EVAL;return e!=="0"&&e!=="false"&&e!=="off"}He()&&Ke.push({name:"reflex_eval",description:"Run page JavaScript and return the result. Prefer act {eval} for side effects.",inputSchema:{type:"object",properties:{js:{type:"string"}},required:["js"]}});var Pt='Reflex drives a local Chrome. Do the whole task in ONE reflex_act that starts {"goto":url}, with expect guards. Only call reflex_open first if you truly cannot guess the target labels. A wrong guess is cheap: the failure report names the right [ref], so fix it and resend that same turn. Read the returned delta, do not re-read. 1 credit per call.';function Qn(e){switch(e.action){case"save":return{cmd:"flow_save",args:{name:e.name,params:e.params,last:e.last}};case"run":return{cmd:"flow_run",args:{name:e.name,params:e.values||{}}};case"list":return{cmd:"flow_list",args:{}};case"state_save":return{cmd:"state_save",args:{name:e.name}};default:throw new Error("action must be save|run|list|state_save")}}function fe(e,t){if(t=t||new Set,!Array.isArray(e))return t;for(let r of e){if(!r||typeof r!="object")continue;let n=Object.keys(r)[0];t.add(n);let s=r[n];if(Array.isArray(s))fe(s,t);else if(s&&typeof s=="object"){for(let o of["then","else","do","steps"])Array.isArray(s[o])&&fe(s[o],t);n==="optional"&&fe([s],t)}}return t}var er={reflex_open:{map:e=>{if(!e.url)throw new Error("url required");return{cmd:"open",args:{url:e.url,state:e.state,headed:e.headed,new_tab:e.new_tab}}}},reflex_act:{map:e=>{if(!Array.isArray(e.steps))throw new Error("steps must be an array");if(!He()&&fe(e.steps).has("eval"))throw new Error("eval steps are disabled (REFLEX_MCP_EVAL=0; unset to enable)");return{cmd:"act",args:{steps:e.steps,quiet:e.quiet}}}},reflex_read:{map:e=>({cmd:"read",args:{query:e.query,full:e.full}})},reflex_extract:{map:e=>({cmd:"extract",args:{target:e.target,mode:e.mode,maxDepth:e.maxDepth,maxWidth:e.maxWidth,maxPages:e.maxPages,save:e.save,includeAuth:e.includeAuth}})},reflex_check:{map:()=>({cmd:"check",args:{visual:!0}})},reflex_shot:{map:e=>({cmd:"shot",args:{region:e.region,full:e.full}}),shape:ir},reflex_tab:{map:e=>e.n===void 0?{cmd:"tabs",args:{}}:{cmd:"tab",args:{n:e.n,close:e.close}}},reflex_flow:{map:Qn},reflex_eval:{map:e=>({cmd:"eval",args:{js:e.js}})}},tr=new Set(["read","check","tabs","extract","shot","flow_list","open"]);function nr(e){let t=process.env.REFLEX_METER;return v.spend(e)}function Me(e){let t=process.env.REFLEX_METER;if(!(!e||!e.id))try{v.refund(e.id)}catch{}}var{classifyFailure:Dt}=jt();function rr(e,t,r,n){let s=process.env.REFLEX_METER;if(!(!e||!e.id||typeof v.recordOutcome!="function"))try{v.recordOutcome(e.id,t,t?null:Dt(r),n)}catch{}}function sr(e){return!e||!Array.isArray(e.content)?0:e.content.reduce((t,r)=>t+(r&&r.type==="text"?String(r.text||"").length:0),0)}var k=e=>({isError:!0,content:[{type:"text",text:e}]});function or(e){return/Executable doesn'?t exist|is not found at|playwright install|please run the following/i.test(e)}function Mt(e,t){if(e.ok){let n=t&&t.warn?`
`+t.warn:"";return{content:[{type:"text",text:e.text+n}]}}if(or(e.text))return k("Reflex needs Google Chrome installed (it drives your real browser). Install Chrome and retry.");let r=e.text;if(process.env.REFLEX_FAIL_SHOT==="inline"&&e.artifact){let n=[{type:"text",text:r}];try{let s=Be.readFileSync(e.artifact);n.push({type:"image",data:s.toString("base64"),mimeType:"image/png"})}catch{}return{isError:!0,content:n}}return r=r.replace(/^screenshot: .*$/m,"screenshot saved (call reflex_shot to view the page)"),{isError:!0,content:[{type:"text",text:r}]}}function ir(e,t,r){if(!e.ok)return Mt(e,r);let n=r&&r.warn?`
`+r.warn:"",s=e.text+n;if(t.path_only)return{content:[{type:"text",text:s}]};let o=null;try{o=Be.readFileSync(e.artifact)}catch{}let c=/(\d+)x(\d+)/.exec(e.text||""),l=c?+c[2]:0;return o&&o.length<=2*1024*1024&&l<=2e3?{content:[{type:"text",text:s},{type:"image",data:o.toString("base64"),mimeType:"image/png"}]}:{content:[{type:"text",text:s+`
image too large to inline; retry with region or path_only`}]}}function le(e){let t=new Error(e);return t.transport=!0,t.kind=e,t}function $e(e){let t={};return process.env.REFLEX_IDLE_EXIT_MIN||(t.REFLEX_IDLE_EXIT_MIN=!e||e===S?"20":"15"),process.env.REFLEX_RAISE===void 0&&(t.REFLEX_RAISE="0"),Object.keys(t).length?t:void 0}var Ye=new Set,Xe=0,de=[];function ar(e){return de.find(t=>t.name===e)||null}function cr(){let e=de.find(t=>t.n===0);return e||(e={name:Ue(`lane${process.pid}x${de.length+1}`),n:0},de.push(e)),Ye.add(e.name),e}var ue=null;function lr(){return ue||(ue=(async()=>{if(process.env.REFLEX_AUTO_ISOLATE==="0"||process.env.REFLEX_SESSION&&S!=="default")return S;try{let e=await qe(S,$e(S)),t=await A(e,"claim",{caller:L},L),r=t&&t.owned?S:`a${process.pid}`;return r!==S&&console.error(`reflex: default session in use by another agent; auto-isolated to session=${r}`),r}catch{return S}})(),ue)}async function ur(e,t,r){r&&r!==S&&Ye.add(r);let n;try{n=await qe(r,$e(r))}catch{throw le("spawn")}try{return await A(n,e,t,L)}catch(s){if(/timeout/i.test(String(s.message||s)))throw le("timeout");if(tr.has(e))try{let o=await qe(r,$e(r));return await A(o,e,t,L)}catch{throw le("lost")}throw le("lost")}}function fr(e){return e==="timeout"?"browser call timed out after 120s; the page may still be loading. Use reflex_read to see the current state.":"browser restarted; page state was lost. Use reflex_open to reopen the page, then retry."}async function dr(e){if(e.action==="stop"){if(!e.session)throw new Error("session required for stop");let n=Ue(e.session),s=W(n);if(!s)return{content:[{type:"text",text:`session ${n}: not running`}]};try{await A(s,"stop",{},L)}catch{}return{content:[{type:"text",text:`session ${n}: stopped`}]}}if(e.action!=="list")throw new Error("action must be list|stop");let t=Be.readdirSync(Vn).map(n=>{let s=/^daemon(?:-([A-Za-z0-9_-]+))?\.json$/.exec(n);return s?s[1]||"default":null}).filter(Boolean),r=[];for(let n of t){let s=W(n);if(s)try{let c=(((await A(s,"status",{},L)).text||"").match(/^page: (.*)$/m)||[])[1];r.push(`${n}${n===S?" (default)":""}: ${c||"no page open"}`)}catch{}}return{content:[{type:"text",text:r.length?r.join(`
`):"(no active sessions)"}]}}async function pr(e){let t=e&&e.action;if(t==="logout"){let n=Ft.logout();return await v.reinit({}).catch(()=>{}),{content:[{type:"text",text:n?"Signed out of Reflex. Run reflex_auth login to sign back in.":"Not signed in."}]}}if(t==="status"){let n=!!process.env.REFLEX_API_KEY,s=(()=>{try{return v.status()}catch{return{}}})();return s.trial?{content:[{type:"text",text:`Running on the free install trial, no account needed: ${s.balance} of ${s.trialGrant} calls left. Run reflex_auth login to create a free account and keep going.`}]}:s.keyTail?{content:[{type:"text",text:`Signed in (${n?"env REFLEX_API_KEY":"browser login"}); key \u2026${s.keyTail}, ${s.balance} credits.`}]}:{content:[{type:"text",text:"Not signed in. Run reflex_auth login to sign in (opens your browser)."}]}}if(t!=="login")throw new Error("action must be login|logout|status");if(process.env.REFLEX_API_KEY)return{content:[{type:"text",text:"Already authenticated via the REFLEX_API_KEY environment variable; no browser login needed."}]};let r=null;try{let n=await Ft.login({onUrl:o=>{r=o,console.error("reflex login url: "+o)}});return await v.reinit({}).catch(()=>{}),{content:[{type:"text",text:`Signed in to Reflex${typeof n.balance=="number"?`, ${n.balance} credits`:""}. You can retry the call you wanted to make.`}]}}catch(n){let s=r?` If your browser did not open, sign in here: ${r}`:"";return k(`Reflex sign-in did not complete: ${String(n.message||n)}.${s}`)}}async function qt(e,t){if(e==="reflex_session")try{return await dr(t||{})}catch(p){return k("bad arguments: "+String(p.message||p))}if(e==="reflex_auth")try{return await pr(t||{})}catch(p){return k("bad arguments: "+String(p.message||p))}let r=er[e];if(!r)return k(`unknown tool: ${e}`);if(e==="reflex_eval"&&!He())return k("reflex_eval is disabled (REFLEX_MCP_EVAL=0; unset to enable)");let n;t&&t.session!==void 0&&(n=Ue(t.session),t=Object.assign({},t),delete t.session);let s=nr(e);if(!s.ok)return k(s.message);let o;try{o=r.map(t||{});let p={};o.args=Zn(o.args,p),o.cmd==="act"&&Object.keys(p).length&&(o.args.__env=p)}catch(p){return Me(s),k("bad arguments: "+String(p.message||p))}let c="",l=null;n===void 0?Xe>1?(l=cr(),n=l.name,c=`[reflex: another browser call was already running, so this one got its own browser, session "${n}". Pass session:"${n}" on the rest of this task to stay in it.]
`):n=await lr():l=ar(n),l&&l.n++;let d;try{d=await ur(o.cmd,o.args,n)}catch(p){return p.transport?(Me(s),k(fr(p.kind))):(Me(s),k("error: "+String(p.message||p)))}finally{l&&l.n--}let u=r.shape?r.shape(d,t||{},s):Mt(d,s);return rr(s,d.ok,d.text,sr(u)),c&&Array.isArray(u.content)&&u.content[0]&&u.content[0].type==="text"&&(u.content[0].text=c+u.content[0].text),u}var Je=new Jn({name:"reflex",version:Ce.version},{capabilities:{tools:{}},instructions:Pt});Je.setRequestHandler(Wn,async()=>({tools:Ke}));Je.setRequestHandler(zn,async e=>{let{name:t,arguments:r}=e.params||{},n=t!=="reflex_auth"&&t!=="reflex_session";n&&Xe++;try{return await qt(t,r)}catch(s){return k("error: "+String(s.message||s))}finally{n&&Xe--}});var Nt=!1;async function pe(){if(Nt)return;Nt=!0;try{await Promise.race([v.shutdown(),De(2100)])}catch{}let e=process.env.REFLEX_STOP_ON_EXIT==="1"?"stop":"detach";try{let t=W();t&&await Promise.race([A(t,e,{caller:L},L),De(2e3)])}catch{}for(let t of Ye)try{let r=W(t);r&&await Promise.race([A(r,e,{caller:L},L),De(1e3)])}catch{}process.exit(0)}async function hr(){try{let o=W();if(o){let c=await A(o,"ping",{});c&&c.v&&c.v!==Ce.version&&await A(o,"stop",{}).catch(()=>{})}}catch{}v.init({apiKey:process.env.REFLEX_API_KEY}).catch(()=>{});let e=process.env.REFLEX_API_KEY?"set":"none";try{let o=v.status();o&&o.keyTail&&(e=o.keyTail)}catch{}console.error(`reflex mcp v${Ce.version} session=${S} key=${e}`);let t=new Gn;await Je.connect(t);let r=t.onclose;t.onclose=()=>{if(r)try{r()}catch{}pe()};let n=process.ppid,s=setInterval(()=>{n!==1&&process.ppid===1&&pe()},5e3);s.unref&&s.unref()}process.on("SIGINT",pe);process.on("SIGTERM",pe);module.exports={TOOLS:Ke,INSTRUCTIONS:Pt,callTool:qt,classifyFailure:Dt,start:hr};
{
"name": "reflex-browser",
"version": "0.11.2",
"version": "0.11.3",
"mcpName": "com.reflexmcp/reflex",

@@ -25,3 +25,3 @@ "description": "Token-efficient browser automation for AI agents. Local MCP server + CLI: compressed page snapshots, batched actions, forensic failures.",

"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/trial.js && node test/memory.js && node test/teardown.js && node test/hygiene.js && node test/parallel.js && node test/concurrency.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/trial.js && node test/flush.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",

@@ -40,3 +40,3 @@ "test:concurrency": "node test/concurrency.js",

"@modelcontextprotocol/sdk": "^1.29.0",
"playwright-core": "^1.50.0"
"playwright-core": "^1.62.0"
},

@@ -43,0 +43,0 @@ "homepage": "https://reflexmcp.com",

Sorry, the diff of this file is too big to display