🎩 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.10.0
to
0.11.0
+10
-9
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 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(`
`)){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 At(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,u]=n;if(s===String(e)&&/chrome|chromium|ms-playwright/i.test(u)&&!/crashpad/i.test(u))return{pid:parseInt(o,10),pgid:parseInt(c,10)}}return null}function Ft(e,t){let r;try{r=de.readdirSync(e)}catch{return}for(let n of r){if(!/^daemon(-.+)?\.json$/.test(n))continue;let o=Ot.join(e,n),s;try{s=JSON.parse(de.readFileSync(o,"utf8"))}catch{continue}if(!(!s||s.pid===t)&&!Ue(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{de.unlinkSync(o)}catch{}}}}function Pt(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 Nt(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:Ue,groupLooksLikeReflex:jt,daemonPidLooksLikeReflex:Pt,reapOrphans:Ft,reapState:Nt,findBrowserGroup:At}});var ze=D((ir,We)=>{"use strict";var Dt=require("http"),E=require("fs"),he=require("path"),Mt=require("os"),{spawn:qt}=require("child_process"),me=process.env.REFLEX_HOME||he.join(Mt.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=>he.join(me,e==="default"?"daemon.json":`daemon-${e}.json`),Ct=U(Z),Ye=he.join(__dirname,"daemon.js");function ye(e){try{return JSON.parse(E.readFileSync(U(e?z(e):Z),"utf8"))}catch{return null}}function Je(e,t,r,n){return new Promise((o,s)=>{let c=JSON.stringify({cmd:t,args:r}),u={"x-reflex-token":e.token||""};n&&(u["x-reflex-caller"]=n);let l=Dt.request({host:"127.0.0.1",port:e.port,method:"POST",path:"/",timeout:12e4,headers:u},f=>{let p="";f.on("data",g=>p+=g),f.on("end",()=>{try{o(JSON.parse(p))}catch{s(new Error("bad daemon response"))}})});l.on("error",s),l.on("timeout",()=>{l.destroy(),s(new Error("daemon timeout"))}),l.end(c)})}var He=e=>new Promise(t=>setTimeout(t,e));async function W(e){let t=ye(e);if(t)try{return await Je(t,"ping",{}),t}catch{}return null}function Ge(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),Ge(e)}catch{}return!1}}function $t(e){try{return E.statSync(e),!0}catch{return!1}}async function Xt(e,t){let r=e?z(e):Z,n=await W(r);if(n)return n;try{E.mkdirSync(me,{recursive:!0,mode:448})}catch{}let o=U(r).replace(/\.json$/,".lock");for(let s=0;s<2;s++){if(Ge(o))try{if(n=await W(r),n)return n;let c=ye(r);if(c)try{Ke().reapState(c)}catch{}try{E.unlinkSync(U(r))}catch{}let u=Object.assign({},process.env,t||{},{REFLEX_SESSION:r});qt(process.execPath,[Ye],{detached:!0,stdio:"ignore",windowsHide:!0,env:u}).unref();for(let f=0;f<100;f++)if(await He(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 He(100),n=await W(r),n)return n;if(!$t(o))break}}throw new Error("daemon failed to start (check ~/.reflex/daemon.log)")}function pe(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=>pe(r,t));if(e&&typeof e=="object"){let r={};for(let n in e)r[n]=pe(e[n],t);return r}return e}We.exports={readState:ye,rpc:Je,ensureDaemon:Xt,subEnv:pe,sanitizeSession:z,stateFileFor:U,HOME:me,SESSION:Z,STATE_FILE:Ct,DAEMON:Ye}});var ge=D((ar,rt)=>{"use strict";var M=require("fs"),Bt=require("os"),Ze=require("path"),Ut=require("http"),Kt=require("crypto"),{spawn:Ht}=require("child_process"),{URL:Yt}=require("url"),Ve=process.env.REFLEX_SITE_BASE||"https://reflexmcp.com",Qe=process.env.REFLEX_API_BASE||"https://reflex.openlabs.workers.dev",Jt=18e4;function et(){return process.env.REFLEX_HOME||Ze.join(Bt.homedir(),".reflex")}function q(){return Ze.join(et(),"auth.json")}function Gt(){try{let e=M.readFileSync(q(),"utf8"),t=JSON.parse(e);return t&&typeof t.api_key=="string"?t.api_key:null}catch{return null}}function tt({api_key:e,key_id:t}){let r=et();M.mkdirSync(r,{recursive:!0});let n=q()+".tmp",o=JSON.stringify({v:1,api_key:e,key_id:t||null,saved_at:new Date().toISOString()});M.writeFileSync(n,o,{mode:384}),M.renameSync(n,q());try{M.chmodSync(q(),384)}catch{}}function Wt(){try{return M.unlinkSync(q()),!0}catch(e){if(e&&e.code==="ENOENT")return!1;throw e}}function nt(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=Ht(t,r,{detached:!0,stdio:"ignore"});return n.on("error",()=>{}),n.unref(),!0}catch{return!1}}function zt(e){e=e||{};let t=(e.siteBase||Ve).replace(/\/+$/,""),r=(e.apiBase||Qe).replace(/\/+$/,""),n=e.timeoutMs||Jt,o=Kt.randomBytes(24).toString("base64url");return new Promise((s,c)=>{let u=!1,l=null,f=(g,h)=>{if(!u){u=!0,l&&clearTimeout(l);try{p.close()}catch{}g(h)}},p=Ut.createServer((g,h)=>{let $;try{$=new Yt(g.url,"http://127.0.0.1")}catch{h.writeHead(400),h.end();return}if($.pathname!=="/callback"){h.writeHead(404),h.end("not found");return}let Xe=$.searchParams.get("state"),Be=$.searchParams.get("code"),ue=$.searchParams.get("error");if(ue){h.writeHead(200,{"content-type":"text/html"}),h.end(V("Login failed",String(ue).slice(0,200))),f(c,new Error("login failed: "+ue));return}if(!Xe||Xe!==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(!Be){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.")),Zt(r,Be).then(fe=>f(s,fe),fe=>f(c,fe))});p.on("error",g=>f(c,g)),p.listen(0,"127.0.0.1",()=>{let g=p.address().port,h=`${t}/cli-auth?port=${g}&state=${encodeURIComponent(o)}`;if(typeof e.onUrl=="function")try{e.onUrl(h)}catch{}e.open!==!1&&nt(h),l=setTimeout(()=>f(c,new Error("timed out waiting for browser login (3 min)")),n),l.unref&&l.unref()})})}async function Zt(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 tt({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 D=(e,t)=>()=>{try{return t||e((t={exports:{}}).exports,t),t.exports}catch(r){throw t=0,r}};var Je=D((ar,X)=>{"use strict";var de=require("fs"),Ot=require("path"),{execFileSync:B}=require("child_process");function Ye(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(`
`)){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 Ft(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,u]=n;if(s===String(e)&&/chrome|chromium|ms-playwright/i.test(u)&&!/crashpad/i.test(u))return{pid:parseInt(o,10),pgid:parseInt(c,10)}}return null}function Nt(e,t){let r;try{r=de.readdirSync(e)}catch{return}for(let n of r){if(!/^daemon(-.+)?\.json$/.test(n))continue;let o=Ot.join(e,n),s;try{s=JSON.parse(de.readFileSync(o,"utf8"))}catch{continue}if(!(!s||s.pid===t)&&!Ye(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{de.unlinkSync(o)}catch{}}}}function Pt(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 Dt(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:Ye,groupLooksLikeReflex:jt,daemonPidLooksLikeReflex:Pt,reapOrphans:Nt,reapState:Dt,findBrowserGroup:Ft}});var Qe=D((cr,Ve)=>{"use strict";var Mt=require("http"),E=require("fs"),he=require("path"),qt=require("os"),{spawn:$t}=require("child_process"),me=process.env.REFLEX_HOME||he.join(qt.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=>he.join(me,e==="default"?"daemon.json":`daemon-${e}.json`),Ct=U(Z),We=he.join(__dirname,"daemon.js");function ye(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}),u={"x-reflex-token":e.token||""};n&&(u["x-reflex-caller"]=n);let f=Mt.request({host:"127.0.0.1",port:e.port,method:"POST",path:"/",timeout:12e4,headers:u},l=>{let p="";l.on("data",g=>p+=g),l.on("end",()=>{try{o(JSON.parse(p))}catch{s(new Error("bad daemon response"))}})});f.on("error",s),f.on("timeout",()=>{f.destroy(),s(new Error("daemon timeout"))}),f.end(c)})}var Ge=e=>new Promise(t=>setTimeout(t,e));async function W(e){let t=ye(e);if(t)try{return await ze(t,"ping",{}),t}catch{}return null}function Ze(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),Ze(e)}catch{}return!1}}function Xt(e){try{return E.statSync(e),!0}catch{return!1}}async function Bt(e,t){let r=e?z(e):Z,n=await W(r);if(n)return n;try{E.mkdirSync(me,{recursive:!0,mode:448})}catch{}let o=U(r).replace(/\.json$/,".lock");for(let s=0;s<2;s++){if(Ze(o))try{if(n=await W(r),n)return n;let c=ye(r);if(c)try{Je().reapState(c)}catch{}try{E.unlinkSync(U(r))}catch{}let u=Object.assign({},process.env,t||{},{REFLEX_SESSION:r});$t(process.execPath,[We],{detached:!0,stdio:"ignore",windowsHide:!0,env:u}).unref();for(let l=0;l<100;l++)if(await Ge(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 Ge(100),n=await W(r),n)return n;if(!Xt(o))break}}throw new Error("daemon failed to start (check ~/.reflex/daemon.log)")}function pe(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=>pe(r,t));if(e&&typeof e=="object"){let r={};for(let n in e)r[n]=pe(e[n],t);return r}return e}Ve.exports={readState:ye,rpc:ze,ensureDaemon:Bt,subEnv:pe,sanitizeSession:z,stateFileFor:U,HOME:me,SESSION:Z,STATE_FILE:Ct,DAEMON:We}});var ge=D((lr,it)=>{"use strict";var M=require("fs"),Ut=require("os"),et=require("path"),Kt=require("http"),Ht=require("crypto"),{spawn:Yt}=require("child_process"),{URL:Jt}=require("url"),tt=process.env.REFLEX_SITE_BASE||"https://reflexmcp.com",nt=process.env.REFLEX_API_BASE||"https://reflex.openlabs.workers.dev",Gt=18e4;function rt(){return process.env.REFLEX_HOME||et.join(Ut.homedir(),".reflex")}function q(){return et.join(rt(),"auth.json")}function Wt(){try{let e=M.readFileSync(q(),"utf8"),t=JSON.parse(e);return t&&typeof t.api_key=="string"?t.api_key:null}catch{return null}}function ot({api_key:e,key_id:t}){let r=rt();M.mkdirSync(r,{recursive:!0});let n=q()+".tmp",o=JSON.stringify({v:1,api_key:e,key_id:t||null,saved_at:new Date().toISOString()});M.writeFileSync(n,o,{mode:384}),M.renameSync(n,q());try{M.chmodSync(q(),384)}catch{}}function zt(){try{return M.unlinkSync(q()),!0}catch(e){if(e&&e.code==="ENOENT")return!1;throw e}}function st(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=Yt(t,r,{detached:!0,stdio:"ignore"});return n.on("error",()=>{}),n.unref(),!0}catch{return!1}}function Zt(e){e=e||{};let t=(e.siteBase||tt).replace(/\/+$/,""),r=(e.apiBase||nt).replace(/\/+$/,""),n=e.timeoutMs||Gt,o=Ht.randomBytes(24).toString("base64url");return new Promise((s,c)=>{let u=!1,f=null,l=(g,h)=>{if(!u){u=!0,f&&clearTimeout(f);try{p.close()}catch{}g(h)}},p=Kt.createServer((g,h)=>{let C;try{C=new Jt(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 Ke=C.searchParams.get("state"),He=C.searchParams.get("code"),ue=C.searchParams.get("error");if(ue){h.writeHead(200,{"content-type":"text/html"}),h.end(V("Login failed",String(ue).slice(0,200))),l(c,new Error("login failed: "+ue));return}if(!Ke||Ke!==o){h.writeHead(400,{"content-type":"text/html"}),h.end(V("Login error","Security check failed (state mismatch). Run reflex_auth login again.")),l(c,new Error("state mismatch"));return}if(!He){h.writeHead(400,{"content-type":"text/html"}),h.end(V("Login error","No login code received. Run reflex_auth login again.")),l(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.")),Vt(r,He).then(fe=>l(s,fe),fe=>l(c,fe))});p.on("error",g=>l(c,g)),p.listen(0,"127.0.0.1",()=>{let g=p.address().port,h=`${t}/cli-auth?port=${g}&state=${encodeURIComponent(o)}`;if(typeof e.onUrl=="function")try{e.onUrl(h)}catch{}e.open!==!1&&st(h),f=setTimeout(()=>l(c,new Error("timed out waiting for browser login (3 min)")),n),f.unref&&f.unref()})})}async function Vt(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 ot({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>
<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>`}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
<body><div class="c"><div class="t">${e}</div><div class="s">${t}</div></div></body></html>`}it.exports={login:Zt,logout:zt,loadKey:Wt,saveKey:ot,openBrowser:st,SITE_BASE:tt,API_BASE:nt,_authFile:q}});var _e=D((ur,Qt)=>{Qt.exports={name:"reflex-browser",version:"0.11.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/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 vt=D((fr,xt)=>{"use strict";var d=require("fs"),en=require("os"),j=require("path"),H=require("crypto"),tn=ge(),ke=process.env.REFLEX_API_BASE||"https://reflex.openlabs.workers.dev";function T(){return process.env.REFLEX_HOME||j.join(en.homedir(),".reflex")}function te(){return j.join(T(),"credits.json")}function ne(e){return j.join(T(),`usage-${e||process.pid}.json`)}function ut(){return j.join(T(),"credits.lock")}function we(){return j.join(T(),"device.json")}var be=/^rfx_(live|test)_[A-Za-z0-9]{32}$/,Se=25,nn="rfx_trial_loc";function rn(){return process.env.REFLEX_TRIAL!=="off"&&process.env.REFLEX_TRIAL!=="0"}var on={k1:process.env.REFLEX_PUBKEY_K1||"cU8LzUpIjro9cQo/A4o7BaOJ6QcDKloN6hffQISY28o="},sn=3,an=3e4,cn=250,Ee=6e4,ln=1e3,un=100,fn=10,dn=6e5,ft=3e5,Re=3e3,pn=5e3,hn=2e3,mn=3e5,yn=250,gn=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:

@@ -20,6 +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 gn(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,j=0,Y=0,xe=0,ve=0,I=!1,F=!1,v=!1,x=null,ee=!1;function ot(e){return Buffer.from(e.replace(/-/g,"+").replace(/_/g,"/"),"base64")}function _n(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 wn(e){return{v:1,pid:process.pid,key_prefix:e||null,buffer:[],overflow:{calls:0,from:null,to:null},pending_batch:null}}function lt(e){return e?e.slice(0,13):null}function ut(){try{let e=JSON.parse(d.readFileSync(te(),"utf8"));if(e&&(e.v===1||e.v===2))return e}catch{}return null}function bn(){try{let e=JSON.parse(d.readFileSync(ne(),"utf8"));if(e&&e.v===1&&Array.isArray(e.buffer))return e}catch{}return null}function Ie(){d.existsSync(T())||d.mkdirSync(T(),{recursive:!0})}function ft(){try{let e=JSON.parse(d.readFileSync(we(),"utf8"));if(e&&e.v===1&&typeof e.device_id=="string")return e}catch{}return null}function dt(e){try{Ie();let t=we()+".tmp";return d.writeFileSync(t,JSON.stringify(e),{mode:384}),d.renameSync(t,we()),!0}catch{return!1}}function xn(){let e=ft();if(e)return e;let t={v:1,device_id:H.randomUUID(),trial_key:null,claimed_at:null};return dt(t)?t:null}async function vn(){if(ee||!x||!v)return!1;ee=!0;try{let e=new AbortController,t=setTimeout(()=>e.abort(),Re),r;try{r=await fetch(ke+"/v1/trial/claim",{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({device_id:x.device_id,client_version:Le}),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||!be.test(n.api_key||""))return!1;m=n.api_key;let o=lt(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(),dt(x),P(),await J(),!0}catch{return!1}finally{ee=!1}}async function kn(e){let t=ft();if(!(!t||!e))try{let r=new AbortController,n=setTimeout(()=>r.abort(),Re);try{await fetch(ke+"/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 st(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 Sn(){let e=at(),t=Date.now()+mn;for(;;)try{return d.mkdirSync(e),!0}catch{try{let n=d.statSync(e);if(Date.now()-n.mtimeMs>yn){d.rmdirSync(e);continue}}catch{}if(Date.now()>=t)return!1;let r=Math.min(Date.now()+10,t);for(;Date.now()<r;);}}function En(){try{d.rmdirSync(at())}catch{}}function Te(){if(!a)return;let e=ut();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),st(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}st(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 Rn(){if(a)try{Ie();let e=Sn();try{Te();let t=te()+".tmp."+process.pid;d.writeFileSync(t,JSON.stringify(a),{mode:384}),d.renameSync(t,te())}finally{e&&En()}}catch{}}function Oe(){if(!i)return!1;try{Ie();let e=ne()+".tmp";return d.writeFileSync(e,JSON.stringify(i),{mode:384}),d.renameSync(e,ne()),!0}catch{return!1}}function P(){Oe(),Rn(),re=!1}function N(){re=!0,!y&&(y=setTimeout(()=>{y=null,re&&P()},an),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(ot(r).toString("utf8"))}catch{return null}let s=rn[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 u=Buffer.from("RFX1."+r,"ascii"),l=!1;try{l=H.verify(null,u,c,ot(n))}catch{return null}return l?o:null}function pt(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(),N()}function C(){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-ct/1e3)}async function ht(e,t,r,n){let o=new AbortController,s=setTimeout(()=>o.abort(),n);try{let c=await fetch(ke+t,{method:e,headers:{authorization:`Bearer ${m}`,"content-type":"application/json"},body:r?JSON.stringify(r):void 0,signal:o.signal}),u=null;try{u=await c.json()}catch{}return{status:c.status,json:u}}finally{clearTimeout(s)}}async function J(){let{status:e,json:t}=await ht("POST","/v1/validate",{client_version:Le},Re);if(e===401||e===403){_={reason:e===403?"key_revoked":"bad_key",message:w.badKey};try{d.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,pt(t.token,r,t.balance,i.buffer.length),!0}return!1}function Ln(){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,u={};for(let p of e){if(t[p.tool]=(t[p.tool]||0)+1,p.ok===!0)o++;else if(p.ok===!1){let g=p.cat||"other";s++,u[g]=(u[g]||0)+1}Number.isFinite(p.resp_chars)&&(c+=p.resp_chars),(!r||p.ts<r)&&(r=p.ts),(!n||p.ts>n)&&(n=p.ts)}let l=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||l,period_end:n||i.overflow.to||l,client_balance:a.balance,hit_zero:!!i._hitZeroPending,client_version:Le,_event_ids:e.map(p=>p.id)};return Object.keys(u).length&&(f.fail_cats=u),c>0&&(f.resp_chars=c),f.calls===0&&f.overflow_calls===0?null:f}async function je(){if(K||!a||!i||!C()&&!i.pending_batch)return;let e=Ln();if(!e)return;K=!0,i.pending_batch=e,Oe();let{_event_ids:t,...r}=e,n=null;try{n=await ht("POST","/v1/usage",r,dn)}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(l=>!s.has(l.id)),u=c.length;i.buffer=c,i.overflow={calls:0,from:null,to:null},i._hitZeroPending=!1,i.pending_batch=null,pt(n.json.token,o,n.json.balance,u),j=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),j=j?Math.min(j*2,hn):Ee,Y=Date.now()+j,K=!1,N()}function In(e){try{return process.kill(e,0),!0}catch(t){return t&&t.code!=="ESRCH"}}function mt(){if(!i)return;let e;try{e=d.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||In(n))continue;let o=A.join(T(),t),s=null;try{s=JSON.parse(d.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=A.join(T(),`usage-${n}.claimed-${process.pid}.json`);try{d.renameSync(o,c)}catch{continue}try{let u=JSON.parse(d.readFileSync(c,"utf8"));if(u&&Array.isArray(u.buffer)){if(i.buffer=i.buffer.concat(u.buffer),u.overflow&&u.overflow.calls){i.overflow.calls+=u.overflow.calls;let{from:l,to:f}=u.overflow;l&&(!i.overflow.from||l<i.overflow.from)&&(i.overflow.from=l),f&&(!i.overflow.to||f>i.overflow.to)&&(i.overflow.to=f)}u.pending_batch&&(i.pending_batch||(i.pending_batch=u.pending_batch)),u._hitZeroPending&&(i._hitZeroPending=!0)}Oe()&&d.unlinkSync(c)}catch{}}}async function oe(){if(!Q&&!(Date.now()<Y)&&!(!I||!a||!i)){Q=!0;try{if(v&&!await vn()||(C()?a.balance<=0&&Date.now()-xe>=Ee&&(xe=Date.now(),await J()):await J(),_))return;mt(),await je(),Te()}catch{}finally{Q=!1}}}function Tn(){if(!I)return;let e=i.buffer.length,t=e>=on;if(!t&&e>0){let r=new Date(i.buffer[0].ts).getTime();Date.now()-r>=sn&&(t=!0)}t&&setImmediate(oe)}function yt(){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,j=0,Y=0,xe=0,ve=0,F=!1,v=!1,x=null,ee=!1}async function gt(e){if(I)return;if(e=e||{},m=e.apiKey||process.env.REFLEX_API_KEY||en.loadKey()||null,!m&&nn()&&(x=xn(),x&&be.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&&!be.test(m)){_={reason:"no_key",message:w.noKey},I=!0;return}let t=v?tn:lt(m),r=bn();i=r&&r.key_prefix===t?r:wn(t);let n=ut(),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=_n(null,t),v&&(a.balance=Se,P())),I=!0,o&&P(),R||(R=setInterval(oe,Ee),R.unref&&R.unref()),setImmediate(()=>{oe()})}function On(){let e=Date.now(),t=a&&a.last_wall_clock?new Date(a.last_wall_clock).getTime():0;return!(t&&e<t-ct)}function jn(e){if(_)return{ok:!1,reason:_.reason,message:_.message};if(!a||!i)return{ok:!1,reason:"no_key",message:w.noKey};if(!v&&!On()&&!C())return{ok:!1,reason:"offline_grace_expired",message:it()};if(!v&&!C())return{ok:!1,reason:"offline_grace_expired",message:a.token?it():w.graceExpiredFirstRun};if(a.balance<=0)return i._hitZeroPending=!0,N(),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>cn){let n=i.buffer.splice(0,ln);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)}N();let r;if(a.balance<=un){let n=Date.now();n-ve>=fn&&(ve=n,r=gn(a.balance))}return Tn(),{ok:!0,warn:r,id:t.id}}function An(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)),N())}function Fn(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,N();return}a.balance+=1,N()}function Pn(){return{balance:a?a.balance:0,keyTail:m?m.slice(-4):null,trial:F,trialGrant:Se}}function it(){return w.graceExpired}async function Nn(){if(y&&(clearTimeout(y),y=null),P(),R&&(clearInterval(R),R=null),!(!I||_||!a||!i)){if(i.buffer.length===0&&!i.pending_batch&&i.overflow.calls===0){try{d.unlinkSync(ne())}catch{}return}await Promise.race([(async()=>{try{C()||await J(),await je()}catch{}})(),new Promise(e=>{let t=setTimeout(e,pn);t.unref&&t.unref()})]),P()}}async function Dn(e){let t=F;yt(),await gt(e),t&&!F&&m&&kn(m).catch(()=>{})}_t.exports={init:gt,reinit:Dn,spend:jn,refund:Fn,recordOutcome:An,status:Pn,shutdown:Nn,_MSG:w,_TRIAL_GRANT:Se,_verifyToken:se,_persistNow(){y&&(clearTimeout(y),y=null),P()},async _syncOnce(){j=0,Y=0;try{if(!I||!a||!i||(C()||await J(),_))return;mt(),await je(),Te()}catch{}},_reset:yt}});var xt=D((ur,bt)=>{"use strict";function Mn(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"}bt.exports={classifyFailure:Mn}});var Me=require("fs"),{Server:qn}=require("@modelcontextprotocol/sdk/server/index.js"),{StdioServerTransport:Cn}=require("@modelcontextprotocol/sdk/server/stdio.js"),{ListToolsRequestSchema:$n,CallToolRequestSchema:Xn}=require("@modelcontextprotocol/sdk/types.js"),{readState:G,rpc:O,ensureDaemon:Pe,subEnv:Bn,sanitizeSession:St,SESSION:S,HOME:Un}=ze(),vt=ge(),Ne=_e(),L=`mcp-${process.pid}`,Ae=e=>new Promise(t=>setTimeout(t,e)),b;try{b=wt()}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 qe=[{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 Ce(){let e=process.env.REFLEX_MCP_EVAL;return e!=="0"&&e!=="false"&&e!=="off"}Ce()&&qe.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 Et='Reflex drives a local Chrome. If you know the targets, do the whole flow in ONE reflex_act starting {"goto":url}; no reflex_open needed. Else reflex_open once, then one big reflex_act. Guard with expect; read the returned delta, do not re-read. On failure the report names a [ref]: fix it and resend that same turn. Targets: [refs] or visible labels. 1 credit per call.';function Kn(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 Hn={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(!Ce()&&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:Zn},reflex_tab:{map:e=>e.n===void 0?{cmd:"tabs",args:{}}:{cmd:"tab",args:{n:e.n,close:e.close}}},reflex_flow:{map:Kn},reflex_eval:{map:e=>({cmd:"eval",args:{js:e.js}})}},Yn=new Set(["read","check","tabs","extract","shot","flow_list","open"]);function Jn(e){let t=process.env.REFLEX_METER;return b.spend(e)}function Fe(e){let t=process.env.REFLEX_METER;if(!(!e||!e.id))try{b.refund(e.id)}catch{}}var{classifyFailure:Rt}=xt();function Gn(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:Rt(r),n)}catch{}}function Wn(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 zn(e){return/Executable doesn'?t exist|is not found at|playwright install|please run the following/i.test(e)}function Lt(e,t){if(e.ok){let n=t&&t.warn?`
`+t.warn:"";return{content:[{type:"text",text:e.text+n}]}}if(zn(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=Me.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 Zn(e,t,r){if(!e.ok)return Lt(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=Me.readFileSync(e.artifact)}catch{}let c=/(\d+)x(\d+)/.exec(e.text||""),u=c?+c[2]:0;return s&&s.length<=2*1024*1024&&u<=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 De(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 It=new Set,ae=null;function Vn(){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,De(S)),t=await O(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 Qn(e,t,r){r&&r!==S&&It.add(r);let n;try{n=await Pe(r,De(r))}catch{throw ie("spawn")}try{return await O(n,e,t,L)}catch(o){if(/timeout/i.test(String(o.message||o)))throw ie("timeout");if(Yn.has(e))try{let s=await Pe(r,De(r));return await O(s,e,t,L)}catch{throw ie("lost")}throw ie("lost")}}function er(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 tr(e){if(e.action==="stop"){if(!e.session)throw new Error("session required for stop");let n=St(e.session),o=G(n);if(!o)return{content:[{type:"text",text:`session ${n}: not running`}]};try{await O(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=Me.readdirSync(Un).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 O(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 nr(e){let t=e&&e.action;if(t==="logout"){let n=vt.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 vt.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 Tt(e,t){if(e==="reflex_session")try{return await tr(t||{})}catch(l){return k("bad arguments: "+String(l.message||l))}if(e==="reflex_auth")try{return await nr(t||{})}catch(l){return k("bad arguments: "+String(l.message||l))}let r=Hn[e];if(!r)return k(`unknown tool: ${e}`);if(e==="reflex_eval"&&!Ce())return k("reflex_eval is disabled (REFLEX_MCP_EVAL=0; unset to enable)");let n;t&&t.session!==void 0&&(n=St(t.session),t=Object.assign({},t),delete t.session);let o=Jn(e);if(!o.ok)return k(o.message);let s;try{s=r.map(t||{});let l={};s.args=Bn(s.args,l),s.cmd==="act"&&Object.keys(l).length&&(s.args.__env=l)}catch(l){return Fe(o),k("bad arguments: "+String(l.message||l))}n===void 0&&(n=await Vn());let c;try{c=await Qn(s.cmd,s.args,n)}catch(l){return l.transport?(Fe(o),k(er(l.kind))):(Fe(o),k("error: "+String(l.message||l)))}let u=r.shape?r.shape(c,t||{},o):Lt(c,o);return Gn(o,c.ok,c.text,Wn(u)),u}var $e=new qn({name:"reflex",version:Ne.version},{capabilities:{tools:{}},instructions:Et});$e.setRequestHandler($n,async()=>({tools:qe}));$e.setRequestHandler(Xn,async e=>{let{name:t,arguments:r}=e.params||{};try{return await Tt(t,r)}catch(n){return k("error: "+String(n.message||n))}});var kt=!1;async function le(){if(kt)return;kt=!0;try{await Promise.race([b.shutdown(),Ae(2100)])}catch{}let e=process.env.REFLEX_STOP_ON_EXIT==="1"?"stop":"detach";try{let t=G();t&&await Promise.race([O(t,e,{caller:L},L),Ae(2e3)])}catch{}for(let t of It)try{let r=G(t);r&&await Promise.race([O(r,e,{caller:L},L),Ae(1e3)])}catch{}process.exit(0)}async function rr(){try{let s=G();if(s){let c=await O(s,"ping",{});c&&c.v&&c.v!==Ne.version&&await O(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${Ne.version} session=${S} key=${e}`);let t=new Cn;await $e.connect(t);let r=t.onclose;t.onclose=()=>{if(r)try{r()}catch{}le()};let n=process.ppid,o=setInterval(()=>{n!==1&&process.ppid===1&&le()},5e3);o.unref&&o.unref()}process.on("SIGINT",le);process.on("SIGTERM",le);module.exports={TOOLS:qe,INSTRUCTIONS:Et,callTool:Tt,classifyFailure:Rt,start:rr};
(150 credits for $9). Then simply retry this call.`};function _n(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,xe=0,ve=0,I=!1,F=!1,v=!1,x=null,ee=!1;function at(e){return Buffer.from(e.replace(/-/g,"+").replace(/_/g,"/"),"base64")}function wn(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 bn(e){return{v:1,pid:process.pid,key_prefix:e||null,buffer:[],overflow:{calls:0,from:null,to:null},pending_batch:null}}function dt(e){return e?e.slice(0,13):null}function pt(){try{let e=JSON.parse(d.readFileSync(te(),"utf8"));if(e&&(e.v===1||e.v===2))return e}catch{}return null}function xn(){try{let e=JSON.parse(d.readFileSync(ne(),"utf8"));if(e&&e.v===1&&Array.isArray(e.buffer))return e}catch{}return null}function Ie(){d.existsSync(T())||d.mkdirSync(T(),{recursive:!0})}function ht(){try{let e=JSON.parse(d.readFileSync(we(),"utf8"));if(e&&e.v===1&&typeof e.device_id=="string")return e}catch{}return null}function mt(e){try{Ie();let t=we()+".tmp";return d.writeFileSync(t,JSON.stringify(e),{mode:384}),d.renameSync(t,we()),!0}catch{return!1}}function vn(){let e=ht();if(e)return e;let t={v:1,device_id:H.randomUUID(),trial_key:null,claimed_at:null};return mt(t)?t:null}async function kn(){if(ee||!x||!v)return!1;ee=!0;try{let e=new AbortController,t=setTimeout(()=>e.abort(),Re),r;try{r=await fetch(ke+"/v1/trial/claim",{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({device_id:x.device_id,client_version:Le}),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||!be.test(n.api_key||""))return!1;m=n.api_key;let o=dt(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(),mt(x),N(),await J(),!0}catch{return!1}finally{ee=!1}}async function Sn(e){let t=ht();if(!(!t||!e))try{let r=new AbortController,n=setTimeout(()=>r.abort(),Re);try{await fetch(ke+"/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 ct(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 En(){let e=ut(),t=Date.now()+yn;for(;;)try{return d.mkdirSync(e),!0}catch{try{let n=d.statSync(e);if(Date.now()-n.mtimeMs>gn){d.rmdirSync(e);continue}}catch{}if(Date.now()>=t)return!1;let r=Math.min(Date.now()+10,t);for(;Date.now()<r;);}}function Rn(){try{d.rmdirSync(ut())}catch{}}function Te(){if(!a)return;let e=pt();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),ct(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}ct(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 Ln(){if(a)try{Ie();let e=En();try{Te();let t=te()+".tmp."+process.pid;d.writeFileSync(t,JSON.stringify(a),{mode:384}),d.renameSync(t,te())}finally{e&&Rn()}}catch{}}function Ae(){if(!i)return!1;try{Ie();let e=ne()+".tmp";return d.writeFileSync(e,JSON.stringify(i),{mode:384}),d.renameSync(e,ne()),!0}catch{return!1}}function N(){Ae(),Ln(),re=!1}function P(){re=!0,!y&&(y=setTimeout(()=>{y=null,re&&N()},cn),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(at(r).toString("utf8"))}catch{return null}let s=on[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 u=Buffer.from("RFX1."+r,"ascii"),f=!1;try{f=H.verify(null,u,c,at(n))}catch{return null}return f?o:null}function yt(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-ft/1e3)}async function gt(e,t,r,n){let o=new AbortController,s=setTimeout(()=>o.abort(),n);try{let c=await fetch(ke+t,{method:e,headers:{authorization:`Bearer ${m}`,"content-type":"application/json"},body:r?JSON.stringify(r):void 0,signal:o.signal}),u=null;try{u=await c.json()}catch{}return{status:c.status,json:u}}finally{clearTimeout(s)}}async function J(){let{status:e,json:t}=await gt("POST","/v1/validate",{client_version:Le},Re);if(e===401||e===403){_={reason:e===403?"key_revoked":"bad_key",message:w.badKey};try{d.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,yt(t.token,r,t.balance,i.buffer.length),!0}return!1}function In(){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,u={};for(let p of e){if(t[p.tool]=(t[p.tool]||0)+1,p.ok===!0)o++;else if(p.ok===!1){let g=p.cat||"other";s++,u[g]=(u[g]||0)+1}Number.isFinite(p.resp_chars)&&(c+=p.resp_chars),(!r||p.ts<r)&&(r=p.ts),(!n||p.ts>n)&&(n=p.ts)}let f=new Date().toISOString(),l={batch_id:H.randomUUID(),calls:e.length,tools:t,ok:o,fail:s,overflow_calls:i.overflow.calls,period_start:r||i.overflow.from||f,period_end:n||i.overflow.to||f,client_balance:a.balance,hit_zero:!!i._hitZeroPending,client_version:Le,_event_ids:e.map(p=>p.id)};return Object.keys(u).length&&(l.fail_cats=u),c>0&&(l.resp_chars=c),l.calls===0&&l.overflow_calls===0?null:l}async function Oe(){if(K||!a||!i||!$()&&!i.pending_batch)return;let e=In();if(!e)return;K=!0,i.pending_batch=e,Ae();let{_event_ids:t,...r}=e,n=null;try{n=await gt("POST","/v1/usage",r,pn)}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(f=>!s.has(f.id)),u=c.length;i.buffer=c,i.overflow={calls:0,from:null,to:null},i._hitZeroPending=!1,i.pending_batch=null,yt(n.json.token,o,n.json.balance,u),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,mn):Ee,Y=Date.now()+O,K=!1,P()}function Tn(e){try{return process.kill(e,0),!0}catch(t){return t&&t.code!=="ESRCH"}}function _t(){if(!i)return;let e;try{e=d.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||Tn(n))continue;let o=j.join(T(),t),s=null;try{s=JSON.parse(d.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{d.renameSync(o,c)}catch{continue}try{let u=JSON.parse(d.readFileSync(c,"utf8"));if(u&&Array.isArray(u.buffer)){if(i.buffer=i.buffer.concat(u.buffer),u.overflow&&u.overflow.calls){i.overflow.calls+=u.overflow.calls;let{from:f,to:l}=u.overflow;f&&(!i.overflow.from||f<i.overflow.from)&&(i.overflow.from=f),l&&(!i.overflow.to||l>i.overflow.to)&&(i.overflow.to=l)}u.pending_batch&&(i.pending_batch||(i.pending_batch=u.pending_batch)),u._hitZeroPending&&(i._hitZeroPending=!0)}Ae()&&d.unlinkSync(c)}catch{}}}async function oe(){if(!Q&&!(Date.now()<Y)&&!(!I||!a||!i)){Q=!0;try{if(v&&!await kn()||($()?a.balance<=0&&Date.now()-xe>=Ee&&(xe=Date.now(),await J()):await J(),_))return;_t(),await Oe(),Te()}catch{}finally{Q=!1}}}function An(){if(!I)return;let e=i.buffer.length,t=e>=sn;if(!t&&e>0){let r=new Date(i.buffer[0].ts).getTime();Date.now()-r>=an&&(t=!0)}t&&setImmediate(oe)}function wt(){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,xe=0,ve=0,F=!1,v=!1,x=null,ee=!1}async function bt(e){if(I)return;if(e=e||{},m=e.apiKey||process.env.REFLEX_API_KEY||tn.loadKey()||null,!m&&rn()&&(x=vn(),x&&be.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&&!be.test(m)){_={reason:"no_key",message:w.noKey},I=!0;return}let t=v?nn:dt(m),r=xn();i=r&&r.key_prefix===t?r:bn(t);let n=pt(),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=wn(null,t),v&&(a.balance=Se,N())),I=!0,o&&N(),R||(R=setInterval(oe,Ee),R.unref&&R.unref()),setImmediate(()=>{oe()})}function On(){let e=Date.now(),t=a&&a.last_wall_clock?new Date(a.last_wall_clock).getTime():0;return!(t&&e<t-ft)}function jn(e){if(_)return{ok:!1,reason:_.reason,message:_.message};if(!a||!i)return{ok:!1,reason:"no_key",message:w.noKey};if(!v&&!On()&&!$())return{ok:!1,reason:"offline_grace_expired",message:lt()};if(!v&&!$())return{ok:!1,reason:"offline_grace_expired",message:a.token?lt():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>ln){let n=i.buffer.splice(0,un);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<=fn){let n=Date.now();n-ve>=dn&&(ve=n,r=_n(a.balance))}return An(),{ok:!0,warn:r,id:t.id}}function Fn(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 Nn(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 Pn(){return{balance:a?a.balance:0,keyTail:m?m.slice(-4):null,trial:F,trialGrant:Se}}function lt(){return w.graceExpired}async function Dn(){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{d.unlinkSync(ne())}catch{}return}await Promise.race([(async()=>{try{$()||await J(),await Oe()}catch{}})(),new Promise(e=>{let t=setTimeout(e,hn);t.unref&&t.unref()})]),N()}}async function Mn(e){let t=F;wt(),await bt(e),t&&!F&&m&&Sn(m).catch(()=>{})}xt.exports={init:bt,reinit:Mn,spend:jn,refund:Nn,recordOutcome:Fn,status:Pn,shutdown:Dn,_MSG:w,_TRIAL_GRANT:Se,_verifyToken:se,_persistNow(){y&&(clearTimeout(y),y=null),N()},async _syncOnce(){O=0,Y=0;try{if(!I||!a||!i||($()||await J(),_))return;_t(),await Oe(),Te()}catch{}},_reset:wt}});var St=D((dr,kt)=>{"use strict";function qn(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"}kt.exports={classifyFailure:qn}});var $e=require("fs"),{Server:$n}=require("@modelcontextprotocol/sdk/server/index.js"),{StdioServerTransport:Cn}=require("@modelcontextprotocol/sdk/server/stdio.js"),{ListToolsRequestSchema:Xn,CallToolRequestSchema:Bn}=require("@modelcontextprotocol/sdk/types.js"),{readState:G,rpc:A,ensureDaemon:Ne,subEnv:Un,sanitizeSession:Pe,SESSION:S,HOME:Kn}=Qe(),Et=ge(),De=_e(),L=`mcp-${process.pid}`,je=e=>new Promise(t=>setTimeout(t,e)),b;try{b=vt()}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 Ce=[{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 Xe(){let e=process.env.REFLEX_MCP_EVAL;return e!=="0"&&e!=="false"&&e!=="off"}Xe()&&Ce.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 Lt='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 Hn(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 Yn={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(!Xe()&&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:Vn},reflex_tab:{map:e=>e.n===void 0?{cmd:"tabs",args:{}}:{cmd:"tab",args:{n:e.n,close:e.close}}},reflex_flow:{map:Hn},reflex_eval:{map:e=>({cmd:"eval",args:{js:e.js}})}},Jn=new Set(["read","check","tabs","extract","shot","flow_list","open"]);function Gn(e){let t=process.env.REFLEX_METER;return b.spend(e)}function Fe(e){let t=process.env.REFLEX_METER;if(!(!e||!e.id))try{b.refund(e.id)}catch{}}var{classifyFailure:It}=St();function Wn(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:It(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 Zn(e){return/Executable doesn'?t exist|is not found at|playwright install|please run the following/i.test(e)}function Tt(e,t){if(e.ok){let n=t&&t.warn?`
`+t.warn:"";return{content:[{type:"text",text:e.text+n}]}}if(Zn(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 Vn(e,t,r){if(!e.ok)return Tt(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||""),u=c?+c[2]:0;return s&&s.length<=2*1024*1024&&u<=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 Me(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 Be=new Set,ae=null;function Qn(){return ae||(ae=(async()=>{if(process.env.REFLEX_AUTO_ISOLATE==="0"||process.env.REFLEX_SESSION&&S!=="default")return S;try{let e=await Ne(S,Me(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 er(e,t,r){r&&r!==S&&Be.add(r);let n;try{n=await Ne(r,Me(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(Jn.has(e))try{let s=await Ne(r,Me(r));return await A(s,e,t,L)}catch{throw ie("lost")}throw ie("lost")}}function tr(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 nr(e){if(e.action==="stop"){if(!e.session)throw new Error("session required for stop");let n=Pe(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(Kn).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 rr(e){let t=e&&e.action;if(t==="logout"){let n=Et.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 Et.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 At(e,t){if(e==="reflex_session")try{return await nr(t||{})}catch(l){return k("bad arguments: "+String(l.message||l))}if(e==="reflex_auth")try{return await rr(t||{})}catch(l){return k("bad arguments: "+String(l.message||l))}let r=Yn[e];if(!r)return k(`unknown tool: ${e}`);if(e==="reflex_eval"&&!Xe())return k("reflex_eval is disabled (REFLEX_MCP_EVAL=0; unset to enable)");let n;t&&t.session!==void 0&&(n=Pe(t.session),t=Object.assign({},t),delete t.session);let o=Gn(e);if(!o.ok)return k(o.message);let s;try{s=r.map(t||{});let l={};s.args=Un(s.args,l),s.cmd==="act"&&Object.keys(l).length&&(s.args.__env=l)}catch(l){return Fe(o),k("bad arguments: "+String(l.message||l))}let c="";n===void 0&&(qe>1?(n=Pe(`lane${process.pid}x${++or}`),Be.add(n),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 Qn());let u;try{u=await er(s.cmd,s.args,n)}catch(l){return l.transport?(Fe(o),k(tr(l.kind))):(Fe(o),k("error: "+String(l.message||l)))}let f=r.shape?r.shape(u,t||{},o):Tt(u,o);return Wn(o,u.ok,u.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 Ue=new $n({name:"reflex",version:De.version},{capabilities:{tools:{}},instructions:Lt});Ue.setRequestHandler(Xn,async()=>({tools:Ce}));var qe=0,or=0;Ue.setRequestHandler(Bn,async e=>{let{name:t,arguments:r}=e.params||{};qe++;try{return await At(t,r)}catch(n){return k("error: "+String(n.message||n))}finally{qe--}});var Rt=!1;async function le(){if(Rt)return;Rt=!0;try{await Promise.race([b.shutdown(),je(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),je(2e3)])}catch{}for(let t of Be)try{let r=G(t);r&&await Promise.race([A(r,e,{caller:L},L),je(1e3)])}catch{}process.exit(0)}async function sr(){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 Cn;await Ue.connect(t);let r=t.onclose;t.onclose=()=>{if(r)try{r()}catch{}le()};let n=process.ppid,o=setInterval(()=>{n!==1&&process.ppid===1&&le()},5e3);o.unref&&o.unref()}process.on("SIGINT",le);process.on("SIGTERM",le);module.exports={TOOLS:Ce,INSTRUCTIONS:Lt,callTool:At,classifyFailure:It,start:sr};
{
"name": "reflex-browser",
"version": "0.10.0",
"version": "0.11.0",
"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/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/memory.js && node test/teardown.js && node test/hygiene.js && node test/parallel.js && node test/concurrency.js",
"test:parallel": "node test/parallel.js",

@@ -28,0 +28,0 @@ "test:concurrency": "node test/concurrency.js",

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