@gaiventures/pilotfish-mcp 0.1.6 → 0.1.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/cli.js +7 -7
- package/package.json +1 -1
package/cli.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
var cr=Object.defineProperty;var l=(n,e)=>cr(n,"name",{value:e,configurable:!0});import{parseArgs as ku}from"node:util";import{createServer as vu}from"node:http";import{randomUUID as xu}from"node:crypto";import{StdioServerTransport as _u}from"@modelcontextprotocol/sdk/server/stdio.js";import{StreamableHTTPServerTransport as Su}from"@modelcontextprotocol/sdk/server/streamableHttp.js";import{isInitializeRequest as $u}from"@modelcontextprotocol/sdk/types.js";import{z as Ge}from"zod";var lr=/^[a-zA-Z0-9_.-]+$/,dr=/^[A-Za-z2-7\s=-]+$/,ur=Ge.object({value:Ge.string().min(1).optional(),totp:Ge.string().regex(dr).optional(),allowedHosts:Ge.array(Ge.string().min(1)).optional()}).strict().refine(n=>n.value!==void 0||n.totp!==void 0);function hr(n){if(!n?.trim())return{};let e;try{e=JSON.parse(n)}catch{throw new Error("PILOTFISH_SECRETS is not valid JSON (expected an object of name \u2192 value or {value?, totp?, allowedHosts?})")}if(!e||typeof e!="object"||Array.isArray(e))throw new Error("PILOTFISH_SECRETS must be a JSON object of name \u2192 value or {value?, totp?, allowedHosts?}");let t={};for(let[s,o]of Object.entries(e)){if(!lr.test(s))throw new Error(`PILOTFISH_SECRETS: secret name "${s.slice(0,40)}" may only use letters, digits, "_", "." and "-"`);if(typeof o=="string"){if(!o)throw new Error(`PILOTFISH_SECRETS: secret "${s}" is empty`);t[s]={value:o};continue}let i=ur.safeParse(o);if(!i.success)throw new Error(`PILOTFISH_SECRETS: secret "${s}" must be a string or {value?: string, totp?: base32 seed, allowedHosts?: string[]} with value or totp set`);t[s]={...i.data,...i.data.allowedHosts?{allowedHosts:i.data.allowedHosts.map(r=>r.trim().toLowerCase())}:{}}}return t}l(hr,"parseSecrets");function pr(n){return(n??"").split(",").map(e=>e.trim().toLowerCase()).filter(Boolean)}l(pr,"parseHosts");function os(n,e){return n===void 0||n.trim()===""?e:!/^(0|false|no|off)$/i.test(n.trim())}l(os,"flag");function fr(n,e){return e==="win32"||e==="darwin"?!0:!!(n.DISPLAY?.trim()||n.WAYLAND_DISPLAY?.trim())}l(fr,"hasDisplay");function wt(n=process.env,e=process.platform){let t=hr(n.PILOTFISH_SECRETS),s=Number(n.PILOTFISH_INTERVENTION_TIMEOUT_MS);return{headless:os(n.PILOTFISH_HEADLESS,!fr(n,e)),allowedHosts:pr(n.PILOTFISH_ALLOWED_HOSTS),allowPrivateNetwork:os(n.PILOTFISH_ALLOW_PRIVATE,!1),secrets:t,interventionTimeoutMs:Number.isFinite(s)&&s>0?s:18e4,allowScreenshots:os(n.PILOTFISH_ALLOW_SCREENSHOTS,Object.keys(t).length===0)}}l(wt,"configFromEnv");import{execFile as oa,spawn as ia}from"node:child_process";import{existsSync as Qn,mkdtempSync as ra,readdirSync as Zn,statSync as aa}from"node:fs";import{rm as ca}from"node:fs/promises";import{tmpdir as la,homedir as Jn,platform as ot}from"node:os";import{dirname as da,join as ce}from"node:path";import{EventEmitter as mr}from"node:events";var te=class extends Error{static{l(this,"CDPError")}method;code;data;sessionId;constructor(e,t,s,o,i){super(`${e}: ${s}${o?` (${o})`:""}`),this.method=e,this.code=t,this.data=o,this.sessionId=i,this.name="CDPError"}},pe=class extends Error{static{l(this,"SessionClosedError")}method;reason;constructor(e,t){super(`${e}: session closed (${t})`),this.method=e,this.reason=t,this.name="SessionClosedError"}},gr=new Set(["Runtime.enable","Console.enable"]),Ve=class{static{l(this,"CDPSession")}connection;sessionId;targetInfo;parentSessionId;emitter=new mr({captureRejections:!1});closedReason=null;constructor(e,t,s,o){this.connection=e,this.sessionId=t,this.targetInfo=s,this.parentSessionId=o,this.emitter.setMaxListeners(200)}get closed(){return this.closedReason!==null}send(e,t,s){return this.closedReason?Promise.reject(new pe(e,this.closedReason)):this.connection.rawSend(e,t,this.sessionId,s)}on(e,t){return this.emitter.on(e,t),()=>this.emitter.off(e,t)}once(e,t){return this.emitter.once(e,t),()=>this.emitter.off(e,t)}off(e,t){this.emitter.off(e,t)}waitFor(e,t,s=3e4){return new Promise((o,i)=>{let r=s>0?setTimeout(()=>{d(),i(new Error(`Timed out after ${s}ms waiting for ${e}`))},s):void 0,a=l(()=>{r&&clearTimeout(r),d(),i(new pe(e,this.closedReason??"closed"))},"onClose"),c=l(u=>{t&&!t(u)||(r&&clearTimeout(r),d(),o(u))},"listener"),d=l(()=>{this.emitter.off(e,c),this.emitter.off("__closed",a)},"off");this.emitter.on(e,c),this.emitter.once("__closed",a)})}_dispatchEvent(e,t){this.emitter.emit(e,t)}_close(e){this.closedReason||(this.closedReason=e,this.emitter.emit("__closed",e),this.emitter.removeAllListeners())}},Ke=class{static{l(this,"Connection")}transport;options;nextId=1;pending=new Map;sessions=new Map;rootSession;closedReason=null;closeListeners=new Set;sessionListeners=new Set;rawListeners=new Set;constructor(e,t={}){this.transport=e,this.options=t,this.rootSession=new Ve(this,void 0,null),e.onMessage=s=>this.onMessage(s),e.onClose=s=>this.onTransportClose(s??"transport closed")}get closed(){return this.closedReason!==null}session(e){return this.sessions.get(e)}allSessions(){return[this.rootSession,...this.sessions.values()]}onClose(e){return this.closeListeners.add(e),()=>this.closeListeners.delete(e)}onRawMessage(e){return this.rawListeners.add(e),()=>this.rawListeners.delete(e)}onSession(e){return this.sessionListeners.add(e),()=>this.sessionListeners.delete(e)}rawSend(e,t,s,o){if(gr.has(e)&&!this.options.allowRuntimeEnable&&!o?.allowFingerprintingMethods)return Promise.reject(new Error(`${e} is disabled: it is a well-known automation fingerprint and nothing in pilotfish requires it. Pass allowRuntimeEnable: true to the Connection if you really need it.`));if(this.closedReason)return Promise.reject(new pe(e,this.closedReason));let i=this.nextId++,r=JSON.stringify(s?{id:i,method:e,params:t,sessionId:s}:{id:i,method:e,params:t}),a=o?.timeoutMs??this.options.defaultTimeoutMs??3e4;return new Promise((c,d)=>{let u={method:e,sessionId:s,resolve:c,reject:d};a>0&&(u.timer=setTimeout(()=>{this.pending.delete(i),d(new te(e,-1,`timed out after ${a}ms`,void 0,s))},a)),this.pending.set(i,u),this.options.onWire?.("send",r);try{this.transport.send(r)}catch(h){this.pending.delete(i),u.timer&&clearTimeout(u.timer),d(h instanceof Error?h:new Error(String(h)))}})}close(e="closed by client"){this.closedReason||(this.transport.close(),this.onTransportClose(e))}onMessage(e){this.options.onWire?.("recv",e);for(let o of this.rawListeners)o(e);let t;try{t=JSON.parse(e)}catch{return}if(t.id!==void 0){let o=this.pending.get(t.id);if(!o)return;this.pending.delete(t.id),o.timer&&clearTimeout(o.timer),t.error?o.reject(new te(o.method,t.error.code,t.error.message,t.error.data,o.sessionId)):o.resolve(t.result);return}if(!t.method)return;if(t.method==="Target.attachedToTarget"){let o=t.params,i=new Ve(this,o.sessionId,o.targetInfo,t.sessionId);this.sessions.set(o.sessionId,i);for(let r of this.sessionListeners)r(i,"attached")}else if(t.method==="Target.detachedFromTarget"){let o=t.params,i=this.sessions.get(o.sessionId);if(i){this.sessions.delete(o.sessionId);for(let[r,a]of this.pending)a.sessionId===o.sessionId&&(a.timer&&clearTimeout(a.timer),a.reject(new pe(a.method,"detached")),this.pending.delete(r));i._close("detached");for(let r of this.sessionListeners)r(i,"detached")}}(t.sessionId?this.sessions.get(t.sessionId):this.rootSession)?._dispatchEvent(t.method,t.params),t.sessionId&&(t.method==="Target.attachedToTarget"||t.method)}onTransportClose(e){if(!this.closedReason){this.closedReason=e;for(let[t,s]of this.pending)s.timer&&clearTimeout(s.timer),s.reject(new pe(s.method,e)),this.pending.delete(t);for(let t of this.sessions.values())t._close(e);this.sessions.clear(),this.rootSession._close(e);for(let t of this.closeListeners)t(e);this.closeListeners.clear()}}};import{WebSocket as Hu}from"ws";var Ye=class{static{l(this,"PipeTransport")}writable;readable;onMessage=null;onClose=null;closed=!1;buffer=[];pendingBytes=0;constructor(e,t){this.writable=e,this.readable=t,t.on("data",s=>this.onData(s)),t.once("close",()=>this.handleClose("pipe closed")),t.once("error",s=>this.handleClose(`pipe error: ${s.message}`)),e.once("error",s=>this.handleClose(`pipe error: ${s.message}`))}send(e){if(this.closed)throw new Error("PipeTransport is closed");this.writable.write(e+"\0")}close(){this.handleClose("closed by client")}onData(e){let t=0;for(;;){let s=e.indexOf(0,t);if(s===-1){let r=e.subarray(t);r.length&&(this.buffer.push(r),this.pendingBytes+=r.length);return}let o=e.subarray(t,s),i;this.buffer.length?(this.buffer.push(o),i=Buffer.concat(this.buffer,this.pendingBytes+o.length).toString("utf8"),this.buffer=[],this.pendingBytes=0):i=o.toString("utf8"),this.onMessage?.(i),t=s+1}}handleClose(e){this.closed||(this.closed=!0,this.onClose?.(e))}};import{lookup as Gu}from"node:dns/promises";import{createServer as Ku,request as Yu}from"node:http";import{BlockList as yr,connect as Xu,isIP as br}from"node:net";var Je=new yr;for(let[n,e]of[["0.0.0.0",8],["10.0.0.0",8],["100.64.0.0",10],["127.0.0.0",8],["169.254.0.0",16],["172.16.0.0",12],["192.0.0.0",24],["192.168.0.0",16],["198.18.0.0",15],["224.0.0.0",4],["240.0.0.0",4]])Je.addSubnet(n,e,"ipv4");for(let[n,e]of[["::",128],["::1",128],["64:ff9b:1::",48],["fc00::",7],["fe80::",10],["fec0::",10],["ff00::",8]])Je.addSubnet(n,e,"ipv6");function kr(n){let e=/(\d+)\.(\d+)\.(\d+)\.(\d+)$/.exec(n),t=e?`${n.slice(0,e.index)}${(+e[1]<<8|+e[2]).toString(16)}:${(+e[3]<<8|+e[4]).toString(16)}`:n,[s="",o]=t.split("::"),i=l(c=>c?c.split(":").map(d=>parseInt(d,16)):[],"groups"),r=i(s),a=o===void 0?[]:i(o);return[...r,...new Array(Math.max(0,8-r.length-a.length)).fill(0),...a]}l(kr,"v6Groups");function vr(n){let e=l((s,o)=>n.slice(s,o).every(i=>i===0),"zero"),t=l((s,o)=>`${s>>8}.${s&255}.${o>>8}.${o&255}`,"v4");return e(0,5)&&n[5]===65535||e(0,4)&&n[4]===65535&&n[5]===0||e(0,6)||n[0]===100&&n[1]===65435&&e(2,6)?t(n[6],n[7]):n[0]===8194?t(n[1],n[2]):null}l(vr,"embeddedV4");function yt(n){let e=n.trim().replace(/^\[|\]$/g,"").replace(/%.*$/,""),t=br(e);if(t===4)return Je.check(e,"ipv4");if(t!==6)return!0;let s=vr(kr(e.toLowerCase()));return s!==null&&Je.check(s,"ipv4")||Je.check(e,"ipv6")}l(yt,"isNonPublicAddress");var yn=l(n=>{throw new Error(n+" is not part of the open pilotfish MCP (the hosted service only)")},"refuse"),Xe=[];function Qe(){return yn("proxyHasAuth")}l(Qe,"proxyHasAuth");function Ze(){return yn("startProxyForwarder")}l(Ze,"startProxyForwarder");var _e=l(n=>{throw new Error(n+" is not part of the open pilotfish MCP (the hosted service only)")},"refuse");function bn(){return _e("exitGeoUrl")}l(bn,"exitGeoUrl");function kn(){return _e("lookupExitGeo")}l(kn,"lookupExitGeo");function is(){return _e("newProxySession")}l(is,"newProxySession");function et(){return _e("proxyRefusedStatus")}l(et,"proxyRefusedStatus");function bt(){return _e("proxyUrlFor")}l(bt,"proxyUrlFor");function vn(){return _e("regionFor")}l(vn,"regionFor");function xn(){return _e("templateTakesCity")}l(xn,"templateTakesCity");var xr=l(n=>{throw new Error(n+" is not part of the open pilotfish MCP (the hosted service only)")},"refuse");function _n(){return xr("startVirtualDisplay")}l(_n,"startVirtualDisplay");import{mkdirSync as Xr}from"node:fs";import{rm as Qr}from"node:fs/promises";import{join as Fn}from"node:path";import{EventEmitter as Zr}from"node:events";import{randomBytes as Mr}from"node:crypto";import{EventEmitter as Rr}from"node:events";import{parse as _r}from"tldts";var Sn=/(^|\.)(unagi[\w-]*|fls-[\w-]*|aax[\w-]*|[\w-]*analytics[\w-]*|[\w-]*telemetry[\w-]*|[\w-]*metrics[\w-]*|[\w-]*beacon[\w-]*|[\w-]*pixel[\w-]*|[\w-]*tracking[\w-]*|[\w-]*adsystem[\w-]*|doubleclick|googletagmanager|google-analytics|sentry|datadoghq|newrelic|hotjar|segment|mixpanel|amplitude)\./i,Sr=/((^|[\/_-])(marketing|analytics|tracking|tracker|data-?layer)|\/events?(\/|$)|\/log(ging)?(\/|$)|metric|beacon|telemetry|\/track(ing)?(\/|$)|\/collect(\/|$)|\/batch(\/|$)|uedata|\/csm(\/|$)|impression|\/rd\/|\/pixel|\/ping(\/|$)|\/v\d+\/(t|e|p)(\/|$))/i;function D(n){let e=n.trim().toLowerCase().replace(/^\[|\]$/g,"").replace(/\.$/,"");if(!e)return"";let t=_r(e,{allowPrivateDomains:!0});return t.isIp?e:t.domain??e}l(D,"siteOf");function $n(n){try{return new URL(n).hostname}catch{return""}}l($n,"hostOf");var $r=/(^|\.)(doubleclick\.net|googlesyndication\.com|googleadservices\.com|adtrafficquality\.google|amazon-adsystem\.com|adnxs\.com|criteo\.(com|net)|taboola\.com|outbrain\.com|pubmatic\.com|rubiconproject\.com|openx\.net|casalemedia\.com|moatads\.com|scorecardresearch\.com|adsrvr\.org|teads\.tv|yieldmo\.com|3lift\.com|sharethrough\.com|indexww\.com|bidswitch\.net|smartadserver\.com|media\.net|innovid\.com|serving-sys\.com)$/i;function we(n){let e=$n(n);return!!e&&($r.test(e)||Sn.test(e+"."))}l(we,"isAdFrameUrl");var Tr=/^\/(assets?|static|images?|img|icons?|fonts?|media|dist|build)\/.*\.(json|svg|png|jpe?g|gif|webp|avif|woff2?|ttf|otf|css|m?js|map)$/i;function Re(n,e){let t=$n(n);if(!t||e&&D(t)!==D(e)||Sn.test(t+"."))return!0;let s="";try{s=new URL(n).pathname}catch{return!0}return Sr.test(s)||Tr.test(s)}l(Re,"isNoiseRequest");var tt=class{static{l(this,"NetworkTracker")}session;inflight=new Map;writes=new Map;recent=[];total=0;failed=0;lastActivityAt=Date.now();disposers=[];longPollMs=8e3;constructor(e){this.session=e,this.disposers.push(e.on("Network.requestWillBeSent",t=>{this.inflight.set(t.requestId,{url:t.request.url,type:t.type??"Other",startedAt:Date.now()}),this.recent.push({t:Date.now(),url:t.request.url,type:t.type??"Other"}),this.recent.length>400&&this.recent.shift(),this.total++,this.lastActivityAt=Date.now();let s=t.request.method.toUpperCase(),o=t.request.postData??"",i=/\bmutation\b/.test(o.slice(0,2e3)),r=/graphql/i.test(t.request.url);t.type!=="Ping"&&!["GET","HEAD","OPTIONS"].includes(s)&&(!r||i)&&(this.writes.set(t.requestId,{requestId:t.requestId,method:s,url:t.request.url,startedAt:Date.now(),mutation:i}),this.writes.size>300&&this.writes.delete(this.writes.keys().next().value))}),e.on("Network.responseReceived",t=>{let s=this.writes.get(t.requestId);s&&(s.status=t.response.status)}),e.on("Network.loadingFinished",t=>this.finish(t.requestId)),e.on("Network.loadingFailed",t=>{t.canceled||this.failed++;let s=this.writes.get(t.requestId);s&&(s.failed=t.canceled?"canceled":t.errorText),this.finish(t.requestId)}),e.on("Network.requestServedFromCache",t=>this.finish(t.requestId)),e.on("Network.webSocketCreated",t=>this.inflight.delete(t.requestId)),e.on("Network.eventSourceMessageReceived",t=>this.inflight.delete(t.requestId)))}finish(e){let t=this.writes.get(e);t&&!t.endedAt&&(t.endedAt=Date.now()),this.inflight.delete(e)&&(this.lastActivityAt=Date.now())}pendingCount(e=Date.now(),t){let s=0;for(let o of this.inflight.values())o.type==="WebSocket"||o.type==="EventSource"||o.type==="Media"||e-o.startedAt>this.longPollMs||t?.(o.url)||s++;return s}pendingData(e=Date.now(),t,s=this.longPollMs){let o=0;for(let i of this.inflight.values())i.type!=="XHR"&&i.type!=="Fetch"||e-i.startedAt>s||t?.(i.url)||o++;return o}inflightTotal(){let e=0;for(let t of this.inflight.values())t.type!=="WebSocket"&&t.type!=="EventSource"&&e++;return e}pendingSince(e,t,s=Date.now()){let o=0;for(let i of this.inflight.values())i.startedAt<e||s-i.startedAt>this.longPollMs||i.type==="WebSocket"||i.type==="EventSource"||i.type==="Media"||i.type==="Ping"||t?.(i.url)||o++;return o}requestsSince(e,t){let s=0;for(let o=this.recent.length-1;o>=0;o--){let i=this.recent[o];if(i.t<e)break;i.type==="WebSocket"||i.type==="EventSource"||i.type==="Ping"||t?.(i.url)||s++}return s}writesSince(e,t){return[...this.writes.values()].filter(s=>s.startedAt>=e&&!Re(s.url,t))}stats(){return{inflight:this.pendingCount(),totalRequests:this.total,failed:this.failed,lastActivityAt:this.lastActivityAt}}mark(){return{total:this.total,failed:this.failed}}dispose(){for(let e of this.disposers)e();this.disposers.length=0}};async function kt(n,{quietMs:e=500,timeoutMs:t=3e3,maxPending:s=0,ignore:o}={}){let i=[...n],r=Date.now()+t,a=null;for(;Date.now()<r;){let c=Date.now();if(i.reduce((u,h)=>u+h.pendingCount(c,o),0)<=s){if(a??=Date.now(),Date.now()-a>=e)return!0}else a=null;await new Promise(u=>setTimeout(u,50))}return!1}l(kt,"waitForNetworkIdle");var rs={Enter:{key:"Enter",code:"Enter",keyCode:13,text:"\r"},Return:{key:"Enter",code:"Enter",keyCode:13,text:"\r"},Tab:{key:"Tab",code:"Tab",keyCode:9},Escape:{key:"Escape",code:"Escape",keyCode:27},Esc:{key:"Escape",code:"Escape",keyCode:27},Backspace:{key:"Backspace",code:"Backspace",keyCode:8},Delete:{key:"Delete",code:"Delete",keyCode:46},Space:{key:" ",code:"Space",keyCode:32,text:" "},ArrowUp:{key:"ArrowUp",code:"ArrowUp",keyCode:38},ArrowDown:{key:"ArrowDown",code:"ArrowDown",keyCode:40},ArrowLeft:{key:"ArrowLeft",code:"ArrowLeft",keyCode:37},ArrowRight:{key:"ArrowRight",code:"ArrowRight",keyCode:39},Home:{key:"Home",code:"Home",keyCode:36},End:{key:"End",code:"End",keyCode:35},PageUp:{key:"PageUp",code:"PageUp",keyCode:33},PageDown:{key:"PageDown",code:"PageDown",keyCode:34},Insert:{key:"Insert",code:"Insert",keyCode:45},Shift:{key:"Shift",code:"ShiftLeft",keyCode:16,location:1},Control:{key:"Control",code:"ControlLeft",keyCode:17,location:1},Alt:{key:"Alt",code:"AltLeft",keyCode:18,location:1},Meta:{key:"Meta",code:"MetaLeft",keyCode:91,location:1},F1:{key:"F1",code:"F1",keyCode:112},F2:{key:"F2",code:"F2",keyCode:113},F3:{key:"F3",code:"F3",keyCode:114},F4:{key:"F4",code:"F4",keyCode:115},F5:{key:"F5",code:"F5",keyCode:116},F12:{key:"F12",code:"F12",keyCode:123}},Tn={Alt:1,Control:2,Meta:4,Shift:8},Ir={ctrl:"Control",control:"Control",alt:"Alt",option:"Alt",shift:"Shift",meta:"Meta",cmd:"Meta",command:"Meta",super:"Meta",win:"Meta",mod:process.platform==="darwin"?"Meta":"Control"};function In(n){let e=n.split("+").map(r=>r.trim()).filter(Boolean);if(e.length===0)throw new Error("Empty key shortcut");let t=0,s=[],o=e[e.length-1];for(let r of e.slice(0,-1)){let a=Ir[r.toLowerCase()]??r,c=Tn[a];if(c===void 0)throw new Error(`Unknown modifier "${r}" in "${n}"`);t|=c,s.push(rs[a])}let i=as(o,(t&Tn.Shift)!==0);return{modifiers:t,modifierKeys:s,key:i}}l(In,"parseShortcut");function as(n,e=!1){let t=rs[n]??rs[n.charAt(0).toUpperCase()+n.slice(1)];if(t)return t;if(n.length===1){let s=e?n.toUpperCase():n,o=n.toUpperCase(),i=/^[a-z]$/i.test(n),r=/^[0-9]$/.test(n),a=Er[s],c=i?s!==s.toLowerCase():!!a&&a[1]!==s;return{key:s,code:i?`Key${o}`:r?`Digit${n}`:a?.[0]??"",keyCode:i||r?o.charCodeAt(0):Cr[s]??0,text:s,...c?{shift:!0,unshifted:i?s.toLowerCase():a[1]}:{}}}throw new Error(`Unknown key "${n}"`)}l(as,"describeKey");var Er={" ":["Space"," "],")":["Digit0","0"],"!":["Digit1","1"],"@":["Digit2","2"],"#":["Digit3","3"],$:["Digit4","4"],"%":["Digit5","5"],"^":["Digit6","6"],"&":["Digit7","7"],"*":["Digit8","8"],"(":["Digit9","9"],";":["Semicolon",";"],":":["Semicolon",";"],"=":["Equal","="],"+":["Equal","="],",":["Comma",","],"<":["Comma",","],"-":["Minus","-"],_:["Minus","-"],".":["Period","."],">":["Period","."],"/":["Slash","/"],"?":["Slash","/"],"`":["Backquote","`"],"~":["Backquote","`"],"[":["BracketLeft","["],"{":["BracketLeft","["],"\\":["Backslash","\\"],"|":["Backslash","\\"],"]":["BracketRight","]"],"}":["BracketRight","]"],"'":["Quote","'"],'"':["Quote","'"]},Cr={" ":32,")":48,"!":49,"@":50,"#":51,$:52,"%":53,"^":54,"&":55,"*":56,"(":57,";":186,":":186,"=":187,"+":187,",":188,"<":188,"-":189,_:189,".":190,">":190,"/":191,"?":191,"`":192,"~":192,"[":219,"{":219,"\\":220,"|":220,"]":221,"}":221,"'":222,'"':222};var En=new WeakMap,ye=class n{static{l(this,"RequestInterceptor")}session;handlers=[];off=null;patternsKey="";current=Promise.resolve();constructor(e){this.session=e}static for(e){let t=En.get(e);return t||(t=new n(e),En.set(e,t)),t}get size(){return this.handlers.length}add(e){return this.handlers.push(e),this.off??=this.session.on("Fetch.requestPaused",s=>{this.paused(s)}),{enabled:this.sync(),remove:l(()=>{let s=this.handlers.indexOf(e);s<0||(this.handlers.splice(s,1),this.sync().catch(()=>{}))},"remove")}}sync(){let e=[...new Set(this.handlers.flatMap(s=>s.types))].sort(),t=e.join(",");return t===this.patternsKey?this.current:(this.patternsKey=t,e.length?(this.current=this.session.send("Fetch.enable",{patterns:e.map(s=>({urlPattern:"*",resourceType:s,requestStage:"Request"}))}).then(()=>{}),this.current):(this.off?.(),this.off=null,this.current=this.session.send("Fetch.disable").then(()=>{},()=>{}),this.current))}async paused(e){let t=this.handlers.filter(i=>i.types.includes(e.resourceType)),s=await Promise.all(t.map(async i=>{try{return await i.onRequest(e)??void 0}catch{return}})),o=this.session;try{let i=s.find(a=>a&&a.action!=="continue");if(i?.action==="fail")return void await o.send("Fetch.failRequest",{requestId:e.requestId,errorReason:i.reason??"BlockedByClient"});if(i?.action==="fulfill")return void await o.send("Fetch.fulfillRequest",{requestId:e.requestId,responseCode:i.responseCode,responseHeaders:i.responseHeaders??[],...i.body!==void 0?{body:i.body}:{}});let r={};for(let a of s)a?.action==="continue"&&a.headers&&Object.assign(r,a.headers);if(!Object.keys(r).length)return void await o.send("Fetch.continueRequest",{requestId:e.requestId});await o.send("Fetch.continueRequest",{requestId:e.requestId,headers:Cn(e.request.headers,r)})}catch{await o.send("Fetch.continueRequest",{requestId:e.requestId}).catch(()=>{})}}};function Cn(n,e){let t=new Set(Object.keys(e).map(o=>o.toLowerCase())),s=Object.entries(n).filter(([o])=>!t.has(o.toLowerCase())).map(([o,i])=>({name:o,value:i}));for(let[o,i]of Object.entries(e))s.push({name:o,value:i});return s}l(Cn,"mergeHeaders");var Ar=new Set(["POST","PUT","PATCH","DELETE"]);async function cs(n){let e={types:["Document","XHR","Fetch","Ping","Other"],onRequest:l(i=>Ar.has(i.request.method)?{action:"fail",reason:"BlockedByClient"}:void 0,"onRequest")},t=[],s=l(i=>(i.session.send("Network.setBypassServiceWorker",{bypass:!0}).catch(()=>{}),ye.for(i.session).add(e)),"arm"),o=n.browser.addSessionInitializer(async i=>{i.page===n&&!i.isMain&&t.push(s(i))});for(let i of n.main.walk())t.push(s(i));return await Promise.all(t.map(i=>i.enabled)),()=>{o();for(let i of t.splice(0))i.remove()}}l(cs,"blockPageWrites");var An=`(() => {
|
|
2
|
+
var cr=Object.defineProperty;var l=(n,e)=>cr(n,"name",{value:e,configurable:!0});import{parseArgs as ku}from"node:util";import{createServer as vu}from"node:http";import{randomUUID as xu}from"node:crypto";import{StdioServerTransport as _u}from"@modelcontextprotocol/sdk/server/stdio.js";import{StreamableHTTPServerTransport as Su}from"@modelcontextprotocol/sdk/server/streamableHttp.js";import{isInitializeRequest as $u}from"@modelcontextprotocol/sdk/types.js";import{z as Ge}from"zod";var lr=/^[a-zA-Z0-9_.-]+$/,dr=/^[A-Za-z2-7\s=-]+$/,ur=Ge.object({value:Ge.string().min(1).optional(),totp:Ge.string().regex(dr).optional(),allowedHosts:Ge.array(Ge.string().min(1)).optional()}).strict().refine(n=>n.value!==void 0||n.totp!==void 0);function hr(n){if(!n?.trim())return{};let e;try{e=JSON.parse(n)}catch{throw new Error("PILOTFISH_SECRETS is not valid JSON (expected an object of name \u2192 value or {value?, totp?, allowedHosts?})")}if(!e||typeof e!="object"||Array.isArray(e))throw new Error("PILOTFISH_SECRETS must be a JSON object of name \u2192 value or {value?, totp?, allowedHosts?}");let t={};for(let[s,o]of Object.entries(e)){if(!lr.test(s))throw new Error(`PILOTFISH_SECRETS: secret name "${s.slice(0,40)}" may only use letters, digits, "_", "." and "-"`);if(typeof o=="string"){if(!o)throw new Error(`PILOTFISH_SECRETS: secret "${s}" is empty`);t[s]={value:o};continue}let i=ur.safeParse(o);if(!i.success)throw new Error(`PILOTFISH_SECRETS: secret "${s}" must be a string or {value?: string, totp?: base32 seed, allowedHosts?: string[]} with value or totp set`);t[s]={...i.data,...i.data.allowedHosts?{allowedHosts:i.data.allowedHosts.map(r=>r.trim().toLowerCase())}:{}}}return t}l(hr,"parseSecrets");function pr(n){return(n??"").split(",").map(e=>e.trim().toLowerCase()).filter(Boolean)}l(pr,"parseHosts");function os(n,e){return n===void 0||n.trim()===""?e:!/^(0|false|no|off)$/i.test(n.trim())}l(os,"flag");function fr(n,e){return e==="win32"||e==="darwin"?!0:!!(n.DISPLAY?.trim()||n.WAYLAND_DISPLAY?.trim())}l(fr,"hasDisplay");function wt(n=process.env,e=process.platform){let t=hr(n.PILOTFISH_SECRETS),s=Number(n.PILOTFISH_INTERVENTION_TIMEOUT_MS);return{headless:os(n.PILOTFISH_HEADLESS,!fr(n,e)),allowedHosts:pr(n.PILOTFISH_ALLOWED_HOSTS),allowPrivateNetwork:os(n.PILOTFISH_ALLOW_PRIVATE,!1),secrets:t,interventionTimeoutMs:Number.isFinite(s)&&s>0?s:18e4,allowScreenshots:os(n.PILOTFISH_ALLOW_SCREENSHOTS,Object.keys(t).length===0)}}l(wt,"configFromEnv");import{execFile as oa,spawn as ia}from"node:child_process";import{existsSync as Qn,mkdtempSync as ra,readdirSync as Zn,statSync as aa}from"node:fs";import{rm as ca}from"node:fs/promises";import{tmpdir as la,homedir as Jn,platform as ot}from"node:os";import{dirname as da,join as ce}from"node:path";import{EventEmitter as mr}from"node:events";var te=class extends Error{static{l(this,"CDPError")}method;code;data;sessionId;constructor(e,t,s,o,i){super(`${e}: ${s}${o?` (${o})`:""}`),this.method=e,this.code=t,this.data=o,this.sessionId=i,this.name="CDPError"}},pe=class extends Error{static{l(this,"SessionClosedError")}method;reason;constructor(e,t){super(`${e}: session closed (${t})`),this.method=e,this.reason=t,this.name="SessionClosedError"}},gr=new Set(["Runtime.enable","Console.enable"]),Ve=class{static{l(this,"CDPSession")}connection;sessionId;targetInfo;parentSessionId;emitter=new mr({captureRejections:!1});closedReason=null;constructor(e,t,s,o){this.connection=e,this.sessionId=t,this.targetInfo=s,this.parentSessionId=o,this.emitter.setMaxListeners(200)}get closed(){return this.closedReason!==null}send(e,t,s){return this.closedReason?Promise.reject(new pe(e,this.closedReason)):this.connection.rawSend(e,t,this.sessionId,s)}on(e,t){return this.emitter.on(e,t),()=>this.emitter.off(e,t)}once(e,t){return this.emitter.once(e,t),()=>this.emitter.off(e,t)}off(e,t){this.emitter.off(e,t)}waitFor(e,t,s=3e4){return new Promise((o,i)=>{let r=s>0?setTimeout(()=>{d(),i(new Error(`Timed out after ${s}ms waiting for ${e}`))},s):void 0,a=l(()=>{r&&clearTimeout(r),d(),i(new pe(e,this.closedReason??"closed"))},"onClose"),c=l(u=>{t&&!t(u)||(r&&clearTimeout(r),d(),o(u))},"listener"),d=l(()=>{this.emitter.off(e,c),this.emitter.off("__closed",a)},"off");this.emitter.on(e,c),this.emitter.once("__closed",a)})}_dispatchEvent(e,t){this.emitter.emit(e,t)}_close(e){this.closedReason||(this.closedReason=e,this.emitter.emit("__closed",e),this.emitter.removeAllListeners())}},Ke=class{static{l(this,"Connection")}transport;options;nextId=1;pending=new Map;sessions=new Map;rootSession;closedReason=null;closeListeners=new Set;sessionListeners=new Set;rawListeners=new Set;constructor(e,t={}){this.transport=e,this.options=t,this.rootSession=new Ve(this,void 0,null),e.onMessage=s=>this.onMessage(s),e.onClose=s=>this.onTransportClose(s??"transport closed")}get closed(){return this.closedReason!==null}session(e){return this.sessions.get(e)}allSessions(){return[this.rootSession,...this.sessions.values()]}onClose(e){return this.closeListeners.add(e),()=>this.closeListeners.delete(e)}onRawMessage(e){return this.rawListeners.add(e),()=>this.rawListeners.delete(e)}onSession(e){return this.sessionListeners.add(e),()=>this.sessionListeners.delete(e)}rawSend(e,t,s,o){if(gr.has(e)&&!this.options.allowRuntimeEnable&&!o?.allowFingerprintingMethods)return Promise.reject(new Error(`${e} is disabled: it is a well-known automation fingerprint and nothing in pilotfish requires it. Pass allowRuntimeEnable: true to the Connection if you really need it.`));if(this.closedReason)return Promise.reject(new pe(e,this.closedReason));let i=this.nextId++,r=JSON.stringify(s?{id:i,method:e,params:t,sessionId:s}:{id:i,method:e,params:t}),a=o?.timeoutMs??this.options.defaultTimeoutMs??3e4;return new Promise((c,d)=>{let u={method:e,sessionId:s,resolve:c,reject:d};a>0&&(u.timer=setTimeout(()=>{this.pending.delete(i),d(new te(e,-1,`timed out after ${a}ms`,void 0,s))},a)),this.pending.set(i,u),this.options.onWire?.("send",r);try{this.transport.send(r)}catch(h){this.pending.delete(i),u.timer&&clearTimeout(u.timer),d(h instanceof Error?h:new Error(String(h)))}})}close(e="closed by client"){this.closedReason||(this.transport.close(),this.onTransportClose(e))}onMessage(e){this.options.onWire?.("recv",e);for(let o of this.rawListeners)o(e);let t;try{t=JSON.parse(e)}catch{return}if(t.id!==void 0){let o=this.pending.get(t.id);if(!o)return;this.pending.delete(t.id),o.timer&&clearTimeout(o.timer),t.error?o.reject(new te(o.method,t.error.code,t.error.message,t.error.data,o.sessionId)):o.resolve(t.result);return}if(!t.method)return;if(t.method==="Target.attachedToTarget"){let o=t.params,i=new Ve(this,o.sessionId,o.targetInfo,t.sessionId);this.sessions.set(o.sessionId,i);for(let r of this.sessionListeners)r(i,"attached")}else if(t.method==="Target.detachedFromTarget"){let o=t.params,i=this.sessions.get(o.sessionId);if(i){this.sessions.delete(o.sessionId);for(let[r,a]of this.pending)a.sessionId===o.sessionId&&(a.timer&&clearTimeout(a.timer),a.reject(new pe(a.method,"detached")),this.pending.delete(r));i._close("detached");for(let r of this.sessionListeners)r(i,"detached")}}(t.sessionId?this.sessions.get(t.sessionId):this.rootSession)?._dispatchEvent(t.method,t.params),t.sessionId&&(t.method==="Target.attachedToTarget"||t.method)}onTransportClose(e){if(!this.closedReason){this.closedReason=e;for(let[t,s]of this.pending)s.timer&&clearTimeout(s.timer),s.reject(new pe(s.method,e)),this.pending.delete(t);for(let t of this.sessions.values())t._close(e);this.sessions.clear(),this.rootSession._close(e);for(let t of this.closeListeners)t(e);this.closeListeners.clear()}}};import{WebSocket as Hu}from"ws";var Ye=class{static{l(this,"PipeTransport")}writable;readable;onMessage=null;onClose=null;closed=!1;buffer=[];pendingBytes=0;constructor(e,t){this.writable=e,this.readable=t,t.on("data",s=>this.onData(s)),t.once("close",()=>this.handleClose("pipe closed")),t.once("error",s=>this.handleClose(`pipe error: ${s.message}`)),e.once("error",s=>this.handleClose(`pipe error: ${s.message}`))}send(e){if(this.closed)throw new Error("PipeTransport is closed");this.writable.write(e+"\0")}close(){this.handleClose("closed by client")}onData(e){let t=0;for(;;){let s=e.indexOf(0,t);if(s===-1){let r=e.subarray(t);r.length&&(this.buffer.push(r),this.pendingBytes+=r.length);return}let o=e.subarray(t,s),i;this.buffer.length?(this.buffer.push(o),i=Buffer.concat(this.buffer,this.pendingBytes+o.length).toString("utf8"),this.buffer=[],this.pendingBytes=0):i=o.toString("utf8"),this.onMessage?.(i),t=s+1}}handleClose(e){this.closed||(this.closed=!0,this.onClose?.(e))}};import{lookup as Gu}from"node:dns/promises";import{createServer as Ku,request as Yu}from"node:http";import{BlockList as yr,connect as Xu,isIP as br}from"node:net";var Je=new yr;for(let[n,e]of[["0.0.0.0",8],["10.0.0.0",8],["100.64.0.0",10],["127.0.0.0",8],["169.254.0.0",16],["172.16.0.0",12],["192.0.0.0",24],["192.168.0.0",16],["198.18.0.0",15],["224.0.0.0",4],["240.0.0.0",4]])Je.addSubnet(n,e,"ipv4");for(let[n,e]of[["::",128],["::1",128],["64:ff9b:1::",48],["fc00::",7],["fe80::",10],["fec0::",10],["ff00::",8]])Je.addSubnet(n,e,"ipv6");function kr(n){let e=/(\d+)\.(\d+)\.(\d+)\.(\d+)$/.exec(n),t=e?`${n.slice(0,e.index)}${(+e[1]<<8|+e[2]).toString(16)}:${(+e[3]<<8|+e[4]).toString(16)}`:n,[s="",o]=t.split("::"),i=l(c=>c?c.split(":").map(d=>parseInt(d,16)):[],"groups"),r=i(s),a=o===void 0?[]:i(o);return[...r,...new Array(Math.max(0,8-r.length-a.length)).fill(0),...a]}l(kr,"v6Groups");function vr(n){let e=l((s,o)=>n.slice(s,o).every(i=>i===0),"zero"),t=l((s,o)=>`${s>>8}.${s&255}.${o>>8}.${o&255}`,"v4");return e(0,5)&&n[5]===65535||e(0,4)&&n[4]===65535&&n[5]===0||e(0,6)||n[0]===100&&n[1]===65435&&e(2,6)?t(n[6],n[7]):n[0]===8194?t(n[1],n[2]):null}l(vr,"embeddedV4");function yt(n){let e=n.trim().replace(/^\[|\]$/g,"").replace(/%.*$/,""),t=br(e);if(t===4)return Je.check(e,"ipv4");if(t!==6)return!0;let s=vr(kr(e.toLowerCase()));return s!==null&&Je.check(s,"ipv4")||Je.check(e,"ipv6")}l(yt,"isNonPublicAddress");var yn=l(n=>{throw new Error(n+" is not part of the open pilotfish MCP (the hosted service only)")},"refuse"),Xe=[];function Qe(){return yn("proxyHasAuth")}l(Qe,"proxyHasAuth");function Ze(){return yn("startProxyForwarder")}l(Ze,"startProxyForwarder");var Se=l(n=>{throw new Error(n+" is not part of the open pilotfish MCP (the hosted service only)")},"refuse");function bn(){return Se("exitGeoUrl")}l(bn,"exitGeoUrl");function kn(){return Se("lookupExitGeo")}l(kn,"lookupExitGeo");function is(){return Se("newProxySession")}l(is,"newProxySession");function et(){return Se("proxyRefusedStatus")}l(et,"proxyRefusedStatus");function bt(){return Se("proxyUrlFor")}l(bt,"proxyUrlFor");function vn(){return Se("regionFor")}l(vn,"regionFor");function xn(){return Se("templateTakesCity")}l(xn,"templateTakesCity");var xr=l(n=>{throw new Error(n+" is not part of the open pilotfish MCP (the hosted service only)")},"refuse");function _n(){return xr("startVirtualDisplay")}l(_n,"startVirtualDisplay");import{mkdirSync as Xr}from"node:fs";import{rm as Qr}from"node:fs/promises";import{join as Fn}from"node:path";import{EventEmitter as Zr}from"node:events";import{randomBytes as Mr}from"node:crypto";import{EventEmitter as Rr}from"node:events";import{parse as _r}from"tldts";var Sn=/(^|\.)(unagi[\w-]*|fls-[\w-]*|aax[\w-]*|[\w-]*analytics[\w-]*|[\w-]*telemetry[\w-]*|[\w-]*metrics[\w-]*|[\w-]*beacon[\w-]*|[\w-]*pixel[\w-]*|[\w-]*tracking[\w-]*|[\w-]*adsystem[\w-]*|doubleclick|googletagmanager|google-analytics|sentry|datadoghq|newrelic|hotjar|segment|mixpanel|amplitude)\./i,Sr=/((^|[\/_-])(marketing|analytics|tracking|tracker|data-?layer)|\/events?(\/|$)|\/log(ging)?(\/|$)|metric|beacon|telemetry|\/track(ing)?(\/|$)|\/collect(\/|$)|\/batch(\/|$)|uedata|\/csm(\/|$)|impression|\/rd\/|\/pixel|\/ping(\/|$)|\/v\d+\/(t|e|p)(\/|$))/i;function D(n){let e=n.trim().toLowerCase().replace(/^\[|\]$/g,"").replace(/\.$/,"");if(!e)return"";let t=_r(e,{allowPrivateDomains:!0});return t.isIp?e:t.domain??e}l(D,"siteOf");function $n(n){try{return new URL(n).hostname}catch{return""}}l($n,"hostOf");var $r=/(^|\.)(doubleclick\.net|googlesyndication\.com|googleadservices\.com|adtrafficquality\.google|amazon-adsystem\.com|adnxs\.com|criteo\.(com|net)|taboola\.com|outbrain\.com|pubmatic\.com|rubiconproject\.com|openx\.net|casalemedia\.com|moatads\.com|scorecardresearch\.com|adsrvr\.org|teads\.tv|yieldmo\.com|3lift\.com|sharethrough\.com|indexww\.com|bidswitch\.net|smartadserver\.com|media\.net|innovid\.com|serving-sys\.com)$/i;function we(n){let e=$n(n);return!!e&&($r.test(e)||Sn.test(e+"."))}l(we,"isAdFrameUrl");var Tr=/^\/(assets?|static|images?|img|icons?|fonts?|media|dist|build)\/.*\.(json|svg|png|jpe?g|gif|webp|avif|woff2?|ttf|otf|css|m?js|map)$/i;function Re(n,e){let t=$n(n);if(!t||e&&D(t)!==D(e)||Sn.test(t+"."))return!0;let s="";try{s=new URL(n).pathname}catch{return!0}return Sr.test(s)||Tr.test(s)}l(Re,"isNoiseRequest");var tt=class{static{l(this,"NetworkTracker")}session;inflight=new Map;writes=new Map;recent=[];total=0;failed=0;lastActivityAt=Date.now();disposers=[];longPollMs=8e3;constructor(e){this.session=e,this.disposers.push(e.on("Network.requestWillBeSent",t=>{this.inflight.set(t.requestId,{url:t.request.url,type:t.type??"Other",startedAt:Date.now()}),this.recent.push({t:Date.now(),url:t.request.url,type:t.type??"Other"}),this.recent.length>400&&this.recent.shift(),this.total++,this.lastActivityAt=Date.now();let s=t.request.method.toUpperCase(),o=t.request.postData??"",i=/\bmutation\b/.test(o.slice(0,2e3)),r=/graphql/i.test(t.request.url);t.type!=="Ping"&&!["GET","HEAD","OPTIONS"].includes(s)&&(!r||i)&&(this.writes.set(t.requestId,{requestId:t.requestId,method:s,url:t.request.url,startedAt:Date.now(),mutation:i}),this.writes.size>300&&this.writes.delete(this.writes.keys().next().value))}),e.on("Network.responseReceived",t=>{let s=this.writes.get(t.requestId);s&&(s.status=t.response.status)}),e.on("Network.loadingFinished",t=>this.finish(t.requestId)),e.on("Network.loadingFailed",t=>{t.canceled||this.failed++;let s=this.writes.get(t.requestId);s&&(s.failed=t.canceled?"canceled":t.errorText),this.finish(t.requestId)}),e.on("Network.requestServedFromCache",t=>this.finish(t.requestId)),e.on("Network.webSocketCreated",t=>this.inflight.delete(t.requestId)),e.on("Network.eventSourceMessageReceived",t=>this.inflight.delete(t.requestId)))}finish(e){let t=this.writes.get(e);t&&!t.endedAt&&(t.endedAt=Date.now()),this.inflight.delete(e)&&(this.lastActivityAt=Date.now())}pendingCount(e=Date.now(),t){let s=0;for(let o of this.inflight.values())o.type==="WebSocket"||o.type==="EventSource"||o.type==="Media"||e-o.startedAt>this.longPollMs||t?.(o.url)||s++;return s}pendingData(e=Date.now(),t,s=this.longPollMs){let o=0;for(let i of this.inflight.values())i.type!=="XHR"&&i.type!=="Fetch"||e-i.startedAt>s||t?.(i.url)||o++;return o}inflightTotal(){let e=0;for(let t of this.inflight.values())t.type!=="WebSocket"&&t.type!=="EventSource"&&e++;return e}pendingSince(e,t,s=Date.now()){let o=0;for(let i of this.inflight.values())i.startedAt<e||s-i.startedAt>this.longPollMs||i.type==="WebSocket"||i.type==="EventSource"||i.type==="Media"||i.type==="Ping"||t?.(i.url)||o++;return o}requestsSince(e,t){let s=0;for(let o=this.recent.length-1;o>=0;o--){let i=this.recent[o];if(i.t<e)break;i.type==="WebSocket"||i.type==="EventSource"||i.type==="Ping"||t?.(i.url)||s++}return s}writesSince(e,t){return[...this.writes.values()].filter(s=>s.startedAt>=e&&!Re(s.url,t))}stats(){return{inflight:this.pendingCount(),totalRequests:this.total,failed:this.failed,lastActivityAt:this.lastActivityAt}}mark(){return{total:this.total,failed:this.failed}}dispose(){for(let e of this.disposers)e();this.disposers.length=0}};async function kt(n,{quietMs:e=500,timeoutMs:t=3e3,maxPending:s=0,ignore:o}={}){let i=[...n],r=Date.now()+t,a=null;for(;Date.now()<r;){let c=Date.now();if(i.reduce((u,h)=>u+h.pendingCount(c,o),0)<=s){if(a??=Date.now(),Date.now()-a>=e)return!0}else a=null;await new Promise(u=>setTimeout(u,50))}return!1}l(kt,"waitForNetworkIdle");var rs={Enter:{key:"Enter",code:"Enter",keyCode:13,text:"\r"},Return:{key:"Enter",code:"Enter",keyCode:13,text:"\r"},Tab:{key:"Tab",code:"Tab",keyCode:9},Escape:{key:"Escape",code:"Escape",keyCode:27},Esc:{key:"Escape",code:"Escape",keyCode:27},Backspace:{key:"Backspace",code:"Backspace",keyCode:8},Delete:{key:"Delete",code:"Delete",keyCode:46},Space:{key:" ",code:"Space",keyCode:32,text:" "},ArrowUp:{key:"ArrowUp",code:"ArrowUp",keyCode:38},ArrowDown:{key:"ArrowDown",code:"ArrowDown",keyCode:40},ArrowLeft:{key:"ArrowLeft",code:"ArrowLeft",keyCode:37},ArrowRight:{key:"ArrowRight",code:"ArrowRight",keyCode:39},Home:{key:"Home",code:"Home",keyCode:36},End:{key:"End",code:"End",keyCode:35},PageUp:{key:"PageUp",code:"PageUp",keyCode:33},PageDown:{key:"PageDown",code:"PageDown",keyCode:34},Insert:{key:"Insert",code:"Insert",keyCode:45},Shift:{key:"Shift",code:"ShiftLeft",keyCode:16,location:1},Control:{key:"Control",code:"ControlLeft",keyCode:17,location:1},Alt:{key:"Alt",code:"AltLeft",keyCode:18,location:1},Meta:{key:"Meta",code:"MetaLeft",keyCode:91,location:1},F1:{key:"F1",code:"F1",keyCode:112},F2:{key:"F2",code:"F2",keyCode:113},F3:{key:"F3",code:"F3",keyCode:114},F4:{key:"F4",code:"F4",keyCode:115},F5:{key:"F5",code:"F5",keyCode:116},F12:{key:"F12",code:"F12",keyCode:123}},Tn={Alt:1,Control:2,Meta:4,Shift:8},Ir={ctrl:"Control",control:"Control",alt:"Alt",option:"Alt",shift:"Shift",meta:"Meta",cmd:"Meta",command:"Meta",super:"Meta",win:"Meta",mod:process.platform==="darwin"?"Meta":"Control"};function In(n){let e=n.split("+").map(r=>r.trim()).filter(Boolean);if(e.length===0)throw new Error("Empty key shortcut");let t=0,s=[],o=e[e.length-1];for(let r of e.slice(0,-1)){let a=Ir[r.toLowerCase()]??r,c=Tn[a];if(c===void 0)throw new Error(`Unknown modifier "${r}" in "${n}"`);t|=c,s.push(rs[a])}let i=as(o,(t&Tn.Shift)!==0);return{modifiers:t,modifierKeys:s,key:i}}l(In,"parseShortcut");function as(n,e=!1){let t=rs[n]??rs[n.charAt(0).toUpperCase()+n.slice(1)];if(t)return t;if(n.length===1){let s=e?n.toUpperCase():n,o=n.toUpperCase(),i=/^[a-z]$/i.test(n),r=/^[0-9]$/.test(n),a=Er[s],c=i?s!==s.toLowerCase():!!a&&a[1]!==s;return{key:s,code:i?`Key${o}`:r?`Digit${n}`:a?.[0]??"",keyCode:i||r?o.charCodeAt(0):Cr[s]??0,text:s,...c?{shift:!0,unshifted:i?s.toLowerCase():a[1]}:{}}}throw new Error(`Unknown key "${n}"`)}l(as,"describeKey");var Er={" ":["Space"," "],")":["Digit0","0"],"!":["Digit1","1"],"@":["Digit2","2"],"#":["Digit3","3"],$:["Digit4","4"],"%":["Digit5","5"],"^":["Digit6","6"],"&":["Digit7","7"],"*":["Digit8","8"],"(":["Digit9","9"],";":["Semicolon",";"],":":["Semicolon",";"],"=":["Equal","="],"+":["Equal","="],",":["Comma",","],"<":["Comma",","],"-":["Minus","-"],_:["Minus","-"],".":["Period","."],">":["Period","."],"/":["Slash","/"],"?":["Slash","/"],"`":["Backquote","`"],"~":["Backquote","`"],"[":["BracketLeft","["],"{":["BracketLeft","["],"\\":["Backslash","\\"],"|":["Backslash","\\"],"]":["BracketRight","]"],"}":["BracketRight","]"],"'":["Quote","'"],'"':["Quote","'"]},Cr={" ":32,")":48,"!":49,"@":50,"#":51,$:52,"%":53,"^":54,"&":55,"*":56,"(":57,";":186,":":186,"=":187,"+":187,",":188,"<":188,"-":189,_:189,".":190,">":190,"/":191,"?":191,"`":192,"~":192,"[":219,"{":219,"\\":220,"|":220,"]":221,"}":221,"'":222,'"':222};var En=new WeakMap,ye=class n{static{l(this,"RequestInterceptor")}session;handlers=[];off=null;patternsKey="";current=Promise.resolve();constructor(e){this.session=e}static for(e){let t=En.get(e);return t||(t=new n(e),En.set(e,t)),t}get size(){return this.handlers.length}add(e){return this.handlers.push(e),this.off??=this.session.on("Fetch.requestPaused",s=>{this.paused(s)}),{enabled:this.sync(),remove:l(()=>{let s=this.handlers.indexOf(e);s<0||(this.handlers.splice(s,1),this.sync().catch(()=>{}))},"remove")}}sync(){let e=[...new Set(this.handlers.flatMap(s=>s.types))].sort(),t=e.join(",");return t===this.patternsKey?this.current:(this.patternsKey=t,e.length?(this.current=this.session.send("Fetch.enable",{patterns:e.map(s=>({urlPattern:"*",resourceType:s,requestStage:"Request"}))}).then(()=>{}),this.current):(this.off?.(),this.off=null,this.current=this.session.send("Fetch.disable").then(()=>{},()=>{}),this.current))}async paused(e){let t=this.handlers.filter(i=>i.types.includes(e.resourceType)),s=await Promise.all(t.map(async i=>{try{return await i.onRequest(e)??void 0}catch{return}})),o=this.session;try{let i=s.find(a=>a&&a.action!=="continue");if(i?.action==="fail")return void await o.send("Fetch.failRequest",{requestId:e.requestId,errorReason:i.reason??"BlockedByClient"});if(i?.action==="fulfill")return void await o.send("Fetch.fulfillRequest",{requestId:e.requestId,responseCode:i.responseCode,responseHeaders:i.responseHeaders??[],...i.body!==void 0?{body:i.body}:{}});let r={};for(let a of s)a?.action==="continue"&&a.headers&&Object.assign(r,a.headers);if(!Object.keys(r).length)return void await o.send("Fetch.continueRequest",{requestId:e.requestId});await o.send("Fetch.continueRequest",{requestId:e.requestId,headers:Cn(e.request.headers,r)})}catch{await o.send("Fetch.continueRequest",{requestId:e.requestId}).catch(()=>{})}}};function Cn(n,e){let t=new Set(Object.keys(e).map(o=>o.toLowerCase())),s=Object.entries(n).filter(([o])=>!t.has(o.toLowerCase())).map(([o,i])=>({name:o,value:i}));for(let[o,i]of Object.entries(e))s.push({name:o,value:i});return s}l(Cn,"mergeHeaders");var Ar=new Set(["POST","PUT","PATCH","DELETE"]);async function cs(n){let e={types:["Document","XHR","Fetch","Ping","Other"],onRequest:l(i=>Ar.has(i.request.method)?{action:"fail",reason:"BlockedByClient"}:void 0,"onRequest")},t=[],s=l(i=>(i.session.send("Network.setBypassServiceWorker",{bypass:!0}).catch(()=>{}),ye.for(i.session).add(e)),"arm"),o=n.browser.addSessionInitializer(async i=>{i.page===n&&!i.isMain&&t.push(s(i))});for(let i of n.main.walk())t.push(s(i));return await Promise.all(t.map(i=>i.enabled)),()=>{o();for(let i of t.splice(0))i.remove()}}l(cs,"blockPageWrites");var An=`(() => {
|
|
3
3
|
const refuse = (what) => function () { throw new Error("read-only: " + what + " is not allowed here; act with the click, type, select_option or press tools"); };
|
|
4
4
|
const lock = (obj, key) => { try { if (obj && key in obj) Object.defineProperty(obj, key, { value: refuse(key + "()"), writable: false, configurable: false }); } catch {} };
|
|
5
5
|
const calls = [
|
|
@@ -107,7 +107,7 @@ var cr=Object.defineProperty;var l=(n,e)=>cr(n,"name",{value:e,configurable:!0})
|
|
|
107
107
|
if ((o === 'auto' || o === 'scroll' || o === 'overlay') && el.scrollHeight > el.clientHeight + 1) return false;
|
|
108
108
|
}
|
|
109
109
|
return true;
|
|
110
|
-
}`,Yr=4e3;function Jr(n){let e=(n??Math.floor(Math.random()*4294967296))>>>0,t=l(()=>{e=e+1831565813>>>0;let s=e;return s=Math.imul(s^s>>>15,s|1),s^=s+Math.imul(s^s>>>7,s|61),((s^s>>>14)>>>0)/4294967296},"rng");return{speed:J(.85,1.2,t),dwellMs:J(60,160,t),restMs:J(500,1400,t),driftPx:J(2,6,t)}}l(Jr,"motorProfile");function Rn(n,e,{targetWidth:t=40,viewport:s,rng:o=Math.random,speed:i=1}={}){let r={x:Math.round(e.x),y:Math.round(e.y)},a=r.x-n.x,c=r.y-n.y,d=Math.hypot(a,c);if(d<2)return[{...r,delayMs:0}];let u=Math.log2(d/Math.max(4,t)+1),h=Math.min(1e3,Math.max(120,(150+110*u)*i*J(.85,1.15,o))),p=a/d,f=c/d,b=d>80,k=o()>=.35,m=b?k?Math.min(25,d*J(.02,.06,o),Math.max(2,t*.4)):-Math.min(25,d*J(.02,.06,o)):0,y=b?Math.max(-t*.3,Math.min(t*.3,J(-.015,.015,o)*d)):0,v={x:r.x+p*m-f*y,y:r.y+f*m+p*y},_=b?h*J(.72,.85,o):h,C=J(-.2,.2,o)*Math.min(d,600),N={x:n.x+a*.3-f*C,y:n.y+c*.3+p*C},M={x:n.x+a*.75-f*C*.5,y:n.y+c*.75+p*C*.5},x=l(g=>{let A=Math.pow(g,.8);return A*A*A*(10-15*A+6*A*A)},"jerk"),T=l(g=>{if(g<_){let I=x(g/_),R=1-I;return{x:R*R*R*n.x+3*R*R*I*N.x+3*R*I*I*M.x+I*I*I*v.x,y:R*R*R*n.y+3*R*R*I*N.y+3*R*I*I*M.y+I*I*I*v.y}}let A=x(Math.min(1,(g-_)/Math.max(1,h-_)));return{x:v.x+(r.x-v.x)*A,y:v.y+(r.y-v.y)*A}},"at"),w=s?s.width-1:1/0,S=s?s.height-1:1/0,E=J(8,16,o),$=[];for(let g=Math.round(E);g<h;g+=Math.max(6,Math.round(E+J(-1,1,o)))){let A=T(g),I={x:Math.min(w,Math.max(0,Math.round(A.x))),y:Math.min(S,Math.max(0,Math.round(A.y)))},R=$.at(-1);(!R||R.x!==I.x||R.y!==I.y)&&$.push({...I,t:g})}return(!$.length||$.at(-1).x!==r.x||$.at(-1).y!==r.y)&&$.push({...r,t:h}),$.map((g,A)=>({x:g.x,y:g.y,delayMs:A+1<$.length?Math.max(1,Math.round($[A+1].t-g.t)):0}))}l(Rn,"humanPath");function On(n,e){let t=Math.min(e.width*.15,5),s=Math.min(e.height*.15,5);return{x:Math.round(n.x+J(-t,t)),y:Math.round(n.y+J(-s,s))}}l(On,"nearCentre");function Pn(n,e=Math.random,t="windows"){if(!n)return[];let s=Math.sign(n);if(t==="windows")return Array.from({length:Math.max(1,Math.round(Math.abs(n)/100))},()=>s*100);let o=J(.86,.92,e),i=[],r=Math.abs(n),a=r*(1-o);for(;r>=1;){let c=Math.min(r,Math.max(1,Math.round(a*10)/10));i.push(s*c),r=Math.round((r-c)*10)/10,a*=o}return r>0&&(i.length?i[i.length-1]=Math.round((i[i.length-1]+s*r)*10)/10:i.push(s*r)),i}l(Pn,"wheelTicks");function vt(n){try{return new URL(n).hostname}catch{return""}}l(vt,"safeHost");function U(n){return new Promise(e=>setTimeout(e,n))}l(U,"sleep");var ea=["challenges.cloudflare.com","www.recaptcha.net","recaptcha.net","www.google.com","www.gstatic.com","*.awswaf.com","*.geetest.com","*.geevisit.com","*.px-cloud.net","*.px-cdn.net","*.px-client.net","*.perimeterx.net","*.pxchk.net","*.humansecurity.com","*.captcha-delivery.com","*.datadome.co","*.hcaptcha.com","*.arkoselabs.com","*.funcaptcha.com"];function Hn(n){let e=n.toLowerCase().replace(/\.$/,"");return ea.some(t=>t.startsWith("*.")?e===t.slice(2)||e.endsWith(t.slice(1)):e===t)}l(Hn,"isCheckServiceHost");function Se(n){let e=n.trim();if(e.includes("://"))try{let s=new URL(e);return s.protocol==="http:"||s.protocol==="https:"?D(s.hostname):""}catch{return""}let t=/^\[?([a-z0-9.:-]+?)\]?(?::\d+)?$/i.exec(e)?.[1];return t&&t.includes(".")?D(t.toLowerCase()):t==="localhost"?"localhost":""}l(Se,"siteOfTarget");var _t=class{static{l(this,"Browser")}connection;launched;options;pages=new Map;emitter=new Zr().setMaxListeners(500);downloadsByGuid=new Map;closedReason=null;cleanedUp=!1;cleanups=[];contextForwarders=new Map;viewport;sessionInitializers=[];initializing=new Set;addSessionInitializer(e){this.sessionInitializers.push(e);for(let t of this.pages.values())for(let s of t.frames()){let o=e(s).catch(()=>{}).finally(()=>this.initializing.delete(o));this.initializing.add(o)}return()=>{let t=this.sessionInitializers.indexOf(e);t>=0&&this.sessionInitializers.splice(t,1)}}async initialized(){for(;this.initializing.size;)await Promise.all([...this.initializing])}constructor(e,t,s){this.connection=e,this.launched=t,this.options=s,this.viewport=s.viewport??{width:1280,height:800},e.onClose(o=>{this.closedReason=o,this.clockTimer&&clearTimeout(this.clockTimer);for(let i of this.pages.values())i._markClosed(o);this.pages.clear(),this.emitter.emit("disconnected",o)}),this.addSessionInitializer(o=>this.applyClock(o.session)),Dn(this,async o=>{let i=o.targetInfo?.type;i!=="shared_worker"&&i!=="service_worker"||(this.clockWorkers.add(o),this.applyClock(o))})}clockWorkers=new Set;async applyClock(e){let t=this.options.timezoneId,s=this.options.locale,o={timeoutMs:5e3};await Promise.all([t?e.send("Emulation.setTimezoneOverride",{timezoneId:t},o).catch(()=>{}):void 0,s?e.send("Emulation.setLocaleOverride",{locale:s},o).catch(()=>{}):void 0])}clockTimer=null;reapplyClock(){let e=l(()=>[...this.allPages().flatMap(s=>s.frames().map(o=>o.session)),...[...this.clockWorkers].filter(s=>!s.closed)],"sessions");return Promise.all(e().map(s=>this.applyClock(s))).then(()=>Promise.all(e().map(s=>this.applyClock(s)))).then(()=>{})}_clockOwnerMayHaveLeft(){this.clockTimer||this.closed||(this.clockTimer=setTimeout(()=>{this.clockTimer=null,this.closed||this.reapplyClock()},100),this.clockTimer.unref?.())}get downloadsDir(){return this.options.downloadsPath??(this.launched?Fn(this.launched.userDataDir,"downloads"):void 0)}downloadsSince(e){return[...this.downloadsByGuid.values()].filter(t=>t.startedAt>=e)}get root(){return this.connection.rootSession}get closed(){return this.closedReason!==null}on(e,t){return this.emitter.on(e,t),()=>this.emitter.off(e,t)}async _initialize(){this.connection.onSession((o,i)=>{i==="attached"?this.onAttached(o):i==="detached"&&this.clockWorkers.delete(o)&&this._clockOwnerMayHaveLeft()}),this.root.on("Target.targetDestroyed",o=>{let i=this.pages.get(o.targetId);i&&(this.pages.delete(o.targetId),i._markClosed("target destroyed"),this.emitter.emit("pageClosed",i),this._clockOwnerMayHaveLeft())}),this.root.on("Target.targetCrashed",o=>{this.pages.get(o.targetId)?._markCrashed(`${o.status} (${o.errorCode})`)}),this.root.on("Browser.downloadWillBegin",o=>{let i={guid:o.guid,url:o.url,suggestedFilename:o.suggestedFilename,frameId:o.frameId,state:"inProgress",receivedBytes:0,totalBytes:0,startedAt:Date.now(),path:this.downloadsDir?Fn(this.downloadsDir,o.guid):void 0};this.downloadsByGuid.set(o.guid,i),this.emitter.emit("download",i)}),this.root.on("Browser.downloadProgress",o=>{let i=this.downloadsByGuid.get(o.guid);i&&(i.state=o.state,i.receivedBytes=o.receivedBytes,i.totalBytes=o.totalBytes,o.state!=="inProgress"&&this.emitter.emit("download",i))}),await this.root.send("Target.setDiscoverTargets",{discover:!0}),await this.root.send("Target.setAutoAttach",{autoAttach:!0,waitForDebuggerOnStart:!0,flatten:!0});let e=this.downloadsDir;if(e){try{Xr(e,{recursive:!0})}catch{}await this.root.send("Browser.setDownloadBehavior",{behavior:"allowAndName",downloadPath:e,eventsEnabled:!0}).catch(()=>{})}let t=l(o=>Promise.race([o.whenReady,new Promise(i=>setTimeout(i,15e3).unref?.())]),"ready"),s=this.allPages()[0];s?await t(s):await new Promise(o=>{let i=setTimeout(o,15e3);i.unref?.();let r=this.on("page",a=>{r(),clearTimeout(i),t(a).then(o)})})}onAttached(e){let t=e.targetInfo;if(t&&e.parentSessionId===void 0){if(t.type==="page"){let s=new nt(this,e,t);this.pages.set(t.targetId,s),s._initialize().then(()=>this.emitter.emit("page",s),o=>{this.pages.delete(t.targetId),s._markClosed(`init failed: ${o.message}`)});return}if(t.type!=="iframe"){if(t.type==="shared_worker"||t.type==="service_worker"){xt(this,e);return}e.send("Runtime.runIfWaitingForDebugger").catch(()=>{})}}}allPages(){return[...this.pages.values()].filter(e=>!e.closed)}async newPage(e={}){let{targetId:t}=await this.root.send("Target.createTarget",{url:e.url??"about:blank",browserContextId:e.browserContextId,...e.background?{background:!0}:{}});return this.waitForPage(t)}async waitForPage(e,t=15e3){let s=this.pages.get(e);return s?.ready?s:new Promise((o,i)=>{let r=setTimeout(()=>{a(),i(new Error(`Page ${e} did not initialize within ${t}ms`))},t),a=this.on("page",c=>{c.targetId===e&&(clearTimeout(r),a(),o(c))})})}async createContext(e={}){let t=e.proxyServer&&Qe(e.proxyServer)?await Ze(e.proxyServer):null;try{let{browserContextId:s}=await this.root.send("Target.createBrowserContext",{disposeOnDetach:!0,proxyServer:t?.url??e.proxyServer,...e.proxyServer?{proxyBypassList:[...Xe,...e.proxyBypassList?[e.proxyBypassList]:[]].join(";")}:e.proxyBypassList?{proxyBypassList:e.proxyBypassList}:{}});return t&&(this.contextForwarders.set(s,t),this.gate(t)),s}catch(s){throw await t?.close(),s}}async disposeContext(e){await this.root.send("Target.disposeBrowserContext",{browserContextId:e}),await this.contextForwarders.get(e)?.close(),this.contextForwarders.delete(e)}addCleanup(e){this.cleanups.push(e)}byteCounters=[];addByteCounter(e){this.byteCounters.push(e)}useForwarder(e){this.addCleanup(()=>e.close()),this.addByteCounter(()=>e.bytes()),this.gate(e),this.launchForwarder=e}gated=new Set;launchForwarder=null;gate(e){this.gated.add(e),e.onData=()=>this.checkTraffic(),e.route=t=>this.proxiedHost(t),e.onUpstreamDown=t=>this.emitter.emit("upstreamDown",t),e.onTunnelFailed=t=>this.emitter.emit("tunnelFailed",t),this.holding&&e.hold()}get paidProxy(){return this.gated.size>0}routing=null;offDocuments=null;never=new Set;pinned=new Map;get exitCountry(){return this.options.region?.country?.toLowerCase()??null}offExit(e){if(this.never.has(e))return!0;if(!this.pinned.has(e))return!1;let t=this.pinned.get(e);return!t||t!==this.exitCountry}pinnedHere(e){let t=Se(e);return!!t&&this.pinned.has(t)&&!this.offExit(t)}routable(e){let t=Se(e);return!!t&&!this.offExit(t)}setProxyRouting(e){e?.never&&(this.never=new Set(e.never.map(Se).filter(Boolean))),this.routing=e?{sites:new Set((e.sites??[]).map(Se).filter(t=>t&&!this.offExit(t))),documents:e.documents??"none",directOnly:!1}:null,this.routing&&(this.routing.documents!=="none"||this._exit?.looked===!1||[...this.pinned.keys()].some(t=>!this.offExit(t)))&&this.watchDocuments();for(let t of this.gated)t.dropDirect(s=>this.proxiedHost(s)),t.dropProxied(s=>!this.proxiedHost(s));(!this.routing||this.routing.sites.size>0)&&this.lookUpExit()}watchDocuments(){this.offDocuments||(this.offDocuments=this.addSessionInitializer(async e=>{let t=new Set;await ye.for(e.session).add({types:["Document"],onRequest:l(async o=>{let i=this.routing?.documents,r=e.isMain&&o.frameId===e.page.targetId;we(o.request.url)||!!o.networkId&&t.has(o.networkId)||!!o.redirectedRequestId&&t.has(o.redirectedRequestId)?(o.networkId&&t.add(o.networkId),t.add(o.requestId)):(i==="all"||i==="main"&&r||i==="frames"&&!r||this.pinnedHere(o.request.url))&&this.routeSite(o.request.url),this.exitLookup&&this.proxiedUrl(o.request.url)&&await this.exitLookup},"onRequest")}).enabled}))}pinSite(e,t){let s=Se(e);if(s&&(this.pinned.set(s,t?.toLowerCase()||null),!!this.routing)){if(!this.offExit(s))return this.watchDocuments();if(this.routing.sites.delete(s))for(let o of this.gated)o.dropProxied(i=>D(i)===s)}}proxiedHost(e){if(!this.paidProxy)return!1;let t=this.routing;return t?t.directOnly?!1:t.sites.has(D(e))||t.sites.size>0&&Hn(e):!0}proxiedUrl(e){try{let t=new URL(e);return(t.protocol==="http:"||t.protocol==="https:"||t.protocol==="ws:"||t.protocol==="wss:")&&this.proxiedHost(t.hostname)}catch{return!1}}get proxiedSites(){return this.routing?[...this.routing.sites]:null}routeSite(e){if(!this.routing||this.routing.directOnly)return;let t=Se(e);if(!t||this.routing.sites.has(t)||this.offExit(t))return;let s=this.routing.sites.size===0;this.routing.sites.add(t);for(let o of this.gated)o.dropDirect(i=>D(i)===t||s&&Hn(i));this.lookUpExit()}setDirectOnly(){this.routing={sites:new Set,documents:this.routing?.documents??"none",directOnly:!0};for(let e of this.gated)e.dropProxied()}_exit=null;exitLookup=null;exitCoords=null;offGeolocation=null;rotateExit(){let e=this._exit,t=this.launchForwarder;if(!e?.reroll||!t)return!1;let s=e.reroll();return e.upstream=s.url,t.setUpstream(s.url),this.options.region&&(this.options.region={...this.options.region,session:s.session}),t.dropProxied(),e.looked=!1,(!this.routing||this.routing.sites.size>0)&&this.lookUpExit(),!0}exitReady(){return this.exitApplied??Promise.resolve()}exitApplied=null;lookUpExit(){let e=this._exit;if(!e?.lookup||e.looked)return this.exitLookup;e.looked=!0;let t=e.upstream,s=Promise.resolve(),o=e.lookup(t).then(i=>{i&&this._exit?.upstream===t&&(s=this._applyExitGeo(i,{geolocation:!0}))},i=>{et(i)&&this.emitter.emit("upstreamDown","login")});return this.exitLookup=o,this.exitApplied=o.then(()=>s),o}async _applyExitGeo(e,t){let s=this.options.region;s&&(this.options.region={...s,...e.ip?{exitIp:e.ip}:{},...e.timezone?{exitTimezone:e.timezone}:{},...e.city?{exitCity:e.city}:{},...e.latitude!==void 0&&e.longitude!==void 0?{exitLat:e.latitude,exitLong:e.longitude}:{}});let o=[];if(e.timezone&&e.timezone!==this.options.timezoneId&&!this.options.keepTimezone&&(this.options.timezoneId=e.timezone,o.push(this.reapplyClock())),t.geolocation&&this.options.stealth&&e.latitude!==void 0&&e.longitude!==void 0){let i={latitude:e.latitude,longitude:e.longitude};this.exitCoords=i;let r=l(a=>a.send("Emulation.setGeolocationOverride",{...i,accuracy:50}).catch(()=>{}),"apply");this.offGeolocation||(this.offGeolocation=this.addSessionInitializer(async a=>{this.exitCoords&&await r(a.session)}));for(let a of this.allPages())for(let c of a.frames())o.push(r(c.session))}await Promise.all(o)}limit=null;softFired=!1;hardFired=!1;holding=!1;challenges=new Set;suspended=null;allowanceUsed=0;lastUsed=0;setTrafficLimit(e,t=()=>{}){this.limit=typeof e=="number"?{softBytes:1/0,hardBytes:e,challengeAllowanceBytes:0,onHard:t}:e,this.softFired=!1,this.hardFired=!1,this.allowanceUsed=0,this.lastUsed=this.proxyBytes(),this.setHeld(!1,!0),this.checkTraffic()}challengeActive(e,t){let s=Se(e)||e.toLowerCase();t?this.challenges.add(s):this.challenges.delete(s),this.checkTraffic()}suspendHold(e){this.suspended=e||"suspended",this.checkTraffic()}resumeHold(){this.suspended=null,this.checkTraffic()}isHeld(){return this.holding}setHeld(e,t=!1){if(!(e===this.holding&&!t)){this.holding=e;for(let s of this.gated)e?s.hold():s.release()}}checkTraffic(){let e=this.proxyBytes(),t=Math.max(0,e-this.lastUsed);this.lastUsed=e;let s=this.limit;if(!s||(!this.softFired&&e>=s.softBytes&&(this.softFired=!0,s.onSoft?.(e)),e<s.hardBytes))return;let o=this.challenges.size>0,i=o||!!this.suspended;if(i&&(this.allowanceUsed+=Math.min(t,e-s.hardBytes)),!(this.hardFired&&this.holding&&!o||!i||this.allowanceUsed>s.challengeAllowanceBytes))return this.setHeld(!1);this.setHeld(!0),!this.hardFired&&(this.hardFired=!0,s.onHard?.(e))}async cancelDownload(e){await this.root.send("Browser.cancelDownload",{guid:e}).catch(()=>{})}proxyBytes(){let e=0;for(let t of this.byteCounters)e+=t();for(let t of this.contextForwarders.values())e+=t.bytes();return e}proxyBytesByHost(){let e=new Map;for(let t of[...this.launchForwarder?[this.launchForwarder]:[],...this.contextForwarders.values()])for(let[s,o]of t.bytesByHost())e.set(s,(e.get(s)??0)+o);return e}exitProxyUrl(){return this.launchForwarder?.url??null}async version(){return this.root.send("Browser.getVersion")}async close(){if(this.cleanedUp)return;if(this.cleanedUp=!0,!this.closedReason)try{await Promise.race([this.root.send("Browser.close",void 0,{timeoutMs:3e3}),new Promise(t=>setTimeout(t,3e3))])}catch{}this.connection.close("browser closed");let e=this.launched?.process;e&&e.exitCode===null&&await new Promise(t=>{let s=setTimeout(()=>{try{e.kill("SIGKILL")}catch{}t()},3e3);e.once("exit",()=>{clearTimeout(s),t()})});for(let t of this.contextForwarders.values())await t.close().catch(()=>{});this.contextForwarders.clear();for(let t of this.cleanups.splice(0))await Promise.resolve(t()).catch(()=>{});this.launched?.ownsUserDataDir&&await Qr(this.launched.userDataDir,{recursive:!0,force:!0,maxRetries:10,retryDelay:200}).catch(()=>{})}};var Un=l(n=>{throw new Error(n+" is not part of the open pilotfish MCP (the hosted service only)")},"refuse");function jn(){return Un("buildUserAgent")}l(jn,"buildUserAgent");function Bn(){return Un("stealthChromePath")}l(Bn,"stealthChromePath");import{existsSync as qn,mkdirSync as ta,readFileSync as Wn,writeFileSync as zn}from"node:fs";import{join as St}from"node:path";var sa={net:{network_prediction_options:2}},hs="pilotfish-model-manifest.json";function na(n,e){let t="";for(let s of n)s.startsWith("--profile-directory=")&&(t=s.slice(20).replace(/^"|"$/g,"")||t);if(t)return t;try{let s=e?JSON.parse(Wn(St(e,"Local State"),"utf8"))?.profile?.last_used:void 0;if(typeof s=="string"&&s&&!/[\\/]|^\.\.?$|^System Profile$/.test(s))return s}catch{}return"Default"}l(na,"profileDirectory");function us(n,e){let t={...n};for(let[s,o]of Object.entries(e)){let i=t[s];t[s]=o&&typeof o=="object"&&!Array.isArray(o)?us(i&&typeof i=="object"&&!Array.isArray(i)?i:{},o):o}return t}l(us,"merged");function Gn(n,e=[],t){try{let s=St(n,hs);qn(s)||zn(s,`{}
|
|
110
|
+
}`,Yr=4e3;function Jr(n){let e=(n??Math.floor(Math.random()*4294967296))>>>0,t=l(()=>{e=e+1831565813>>>0;let s=e;return s=Math.imul(s^s>>>15,s|1),s^=s+Math.imul(s^s>>>7,s|61),((s^s>>>14)>>>0)/4294967296},"rng");return{speed:J(.85,1.2,t),dwellMs:J(60,160,t),restMs:J(500,1400,t),driftPx:J(2,6,t)}}l(Jr,"motorProfile");function Rn(n,e,{targetWidth:t=40,viewport:s,rng:o=Math.random,speed:i=1}={}){let r={x:Math.round(e.x),y:Math.round(e.y)},a=r.x-n.x,c=r.y-n.y,d=Math.hypot(a,c);if(d<2)return[{...r,delayMs:0}];let u=Math.log2(d/Math.max(4,t)+1),h=Math.min(1e3,Math.max(120,(150+110*u)*i*J(.85,1.15,o))),p=a/d,f=c/d,b=d>80,k=o()>=.35,m=b?k?Math.min(25,d*J(.02,.06,o),Math.max(2,t*.4)):-Math.min(25,d*J(.02,.06,o)):0,y=b?Math.max(-t*.3,Math.min(t*.3,J(-.015,.015,o)*d)):0,v={x:r.x+p*m-f*y,y:r.y+f*m+p*y},_=b?h*J(.72,.85,o):h,C=J(-.2,.2,o)*Math.min(d,600),N={x:n.x+a*.3-f*C,y:n.y+c*.3+p*C},M={x:n.x+a*.75-f*C*.5,y:n.y+c*.75+p*C*.5},x=l(g=>{let A=Math.pow(g,.8);return A*A*A*(10-15*A+6*A*A)},"jerk"),T=l(g=>{if(g<_){let I=x(g/_),R=1-I;return{x:R*R*R*n.x+3*R*R*I*N.x+3*R*I*I*M.x+I*I*I*v.x,y:R*R*R*n.y+3*R*R*I*N.y+3*R*I*I*M.y+I*I*I*v.y}}let A=x(Math.min(1,(g-_)/Math.max(1,h-_)));return{x:v.x+(r.x-v.x)*A,y:v.y+(r.y-v.y)*A}},"at"),w=s?s.width-1:1/0,S=s?s.height-1:1/0,E=J(8,16,o),$=[];for(let g=Math.round(E);g<h;g+=Math.max(6,Math.round(E+J(-1,1,o)))){let A=T(g),I={x:Math.min(w,Math.max(0,Math.round(A.x))),y:Math.min(S,Math.max(0,Math.round(A.y)))},R=$.at(-1);(!R||R.x!==I.x||R.y!==I.y)&&$.push({...I,t:g})}return(!$.length||$.at(-1).x!==r.x||$.at(-1).y!==r.y)&&$.push({...r,t:h}),$.map((g,A)=>({x:g.x,y:g.y,delayMs:A+1<$.length?Math.max(1,Math.round($[A+1].t-g.t)):0}))}l(Rn,"humanPath");function On(n,e){let t=Math.min(e.width*.15,5),s=Math.min(e.height*.15,5);return{x:Math.round(n.x+J(-t,t)),y:Math.round(n.y+J(-s,s))}}l(On,"nearCentre");function Pn(n,e=Math.random,t="windows"){if(!n)return[];let s=Math.sign(n);if(t==="windows")return Array.from({length:Math.max(1,Math.round(Math.abs(n)/100))},()=>s*100);let o=J(.86,.92,e),i=[],r=Math.abs(n),a=r*(1-o);for(;r>=1;){let c=Math.min(r,Math.max(1,Math.round(a*10)/10));i.push(s*c),r=Math.round((r-c)*10)/10,a*=o}return r>0&&(i.length?i[i.length-1]=Math.round((i[i.length-1]+s*r)*10)/10:i.push(s*r)),i}l(Pn,"wheelTicks");function vt(n){try{return new URL(n).hostname}catch{return""}}l(vt,"safeHost");function U(n){return new Promise(e=>setTimeout(e,n))}l(U,"sleep");var ea=["challenges.cloudflare.com","www.recaptcha.net","recaptcha.net","www.google.com","www.gstatic.com","*.awswaf.com","*.geetest.com","*.geevisit.com","*.px-cloud.net","*.px-cdn.net","*.px-client.net","*.perimeterx.net","*.pxchk.net","*.humansecurity.com","*.captcha-delivery.com","*.datadome.co","*.hcaptcha.com","*.arkoselabs.com","*.funcaptcha.com"];function Hn(n){let e=n.toLowerCase().replace(/\.$/,"");return ea.some(t=>t.startsWith("*.")?e===t.slice(2)||e.endsWith(t.slice(1)):e===t)}l(Hn,"isCheckServiceHost");function xe(n){let e=n.trim();if(e.includes("://"))try{let s=new URL(e);return s.protocol==="http:"||s.protocol==="https:"?D(s.hostname):""}catch{return""}let t=/^\[?([a-z0-9.:-]+?)\]?(?::\d+)?$/i.exec(e)?.[1];return t&&t.includes(".")?D(t.toLowerCase()):t==="localhost"?"localhost":""}l(xe,"siteOfTarget");var _t=class{static{l(this,"Browser")}connection;launched;options;pages=new Map;emitter=new Zr().setMaxListeners(500);downloadsByGuid=new Map;closedReason=null;cleanedUp=!1;cleanups=[];contextForwarders=new Map;viewport;sessionInitializers=[];initializing=new Set;addSessionInitializer(e){this.sessionInitializers.push(e);for(let t of this.pages.values())for(let s of t.frames()){let o=e(s).catch(()=>{}).finally(()=>this.initializing.delete(o));this.initializing.add(o)}return()=>{let t=this.sessionInitializers.indexOf(e);t>=0&&this.sessionInitializers.splice(t,1)}}async initialized(){for(;this.initializing.size;)await Promise.all([...this.initializing])}constructor(e,t,s){this.connection=e,this.launched=t,this.options=s,this.viewport=s.viewport??{width:1280,height:800},e.onClose(o=>{this.closedReason=o,this.clockTimer&&clearTimeout(this.clockTimer);for(let i of this.pages.values())i._markClosed(o);this.pages.clear(),this.emitter.emit("disconnected",o)}),this.addSessionInitializer(o=>this.applyClock(o.session)),Dn(this,async o=>{let i=o.targetInfo?.type;i!=="shared_worker"&&i!=="service_worker"||(this.clockWorkers.add(o),this.applyClock(o))})}clockWorkers=new Set;async applyClock(e){let t=this.options.timezoneId,s=this.options.locale,o={timeoutMs:5e3};await Promise.all([t?e.send("Emulation.setTimezoneOverride",{timezoneId:t},o).catch(()=>{}):void 0,s?e.send("Emulation.setLocaleOverride",{locale:s},o).catch(()=>{}):void 0])}clockTimer=null;reapplyClock(){let e=l(()=>[...this.allPages().flatMap(s=>s.frames().map(o=>o.session)),...[...this.clockWorkers].filter(s=>!s.closed)],"sessions");return Promise.all(e().map(s=>this.applyClock(s))).then(()=>Promise.all(e().map(s=>this.applyClock(s)))).then(()=>{})}_clockOwnerMayHaveLeft(){this.clockTimer||this.closed||(this.clockTimer=setTimeout(()=>{this.clockTimer=null,this.closed||this.reapplyClock()},100),this.clockTimer.unref?.())}get downloadsDir(){return this.options.downloadsPath??(this.launched?Fn(this.launched.userDataDir,"downloads"):void 0)}downloadsSince(e){return[...this.downloadsByGuid.values()].filter(t=>t.startedAt>=e)}get root(){return this.connection.rootSession}get closed(){return this.closedReason!==null}on(e,t){return this.emitter.on(e,t),()=>this.emitter.off(e,t)}async _initialize(){this.connection.onSession((o,i)=>{i==="attached"?this.onAttached(o):i==="detached"&&this.clockWorkers.delete(o)&&this._clockOwnerMayHaveLeft()}),this.root.on("Target.targetDestroyed",o=>{let i=this.pages.get(o.targetId);i&&(this.pages.delete(o.targetId),i._markClosed("target destroyed"),this.emitter.emit("pageClosed",i),this._clockOwnerMayHaveLeft())}),this.root.on("Target.targetCrashed",o=>{this.pages.get(o.targetId)?._markCrashed(`${o.status} (${o.errorCode})`)}),this.root.on("Browser.downloadWillBegin",o=>{let i={guid:o.guid,url:o.url,suggestedFilename:o.suggestedFilename,frameId:o.frameId,state:"inProgress",receivedBytes:0,totalBytes:0,startedAt:Date.now(),path:this.downloadsDir?Fn(this.downloadsDir,o.guid):void 0};this.downloadsByGuid.set(o.guid,i),this.emitter.emit("download",i)}),this.root.on("Browser.downloadProgress",o=>{let i=this.downloadsByGuid.get(o.guid);i&&(i.state=o.state,i.receivedBytes=o.receivedBytes,i.totalBytes=o.totalBytes,o.state!=="inProgress"&&this.emitter.emit("download",i))}),await this.root.send("Target.setDiscoverTargets",{discover:!0}),await this.root.send("Target.setAutoAttach",{autoAttach:!0,waitForDebuggerOnStart:!0,flatten:!0});let e=this.downloadsDir;if(e){try{Xr(e,{recursive:!0})}catch{}await this.root.send("Browser.setDownloadBehavior",{behavior:"allowAndName",downloadPath:e,eventsEnabled:!0}).catch(()=>{})}let t=l(o=>Promise.race([o.whenReady,new Promise(i=>setTimeout(i,15e3).unref?.())]),"ready"),s=this.allPages()[0];s?await t(s):await new Promise(o=>{let i=setTimeout(o,15e3);i.unref?.();let r=this.on("page",a=>{r(),clearTimeout(i),t(a).then(o)})})}onAttached(e){let t=e.targetInfo;if(t&&e.parentSessionId===void 0){if(t.type==="page"){let s=new nt(this,e,t);this.pages.set(t.targetId,s),s._initialize().then(()=>this.emitter.emit("page",s),o=>{this.pages.delete(t.targetId),s._markClosed(`init failed: ${o.message}`)});return}if(t.type!=="iframe"){if(t.type==="shared_worker"||t.type==="service_worker"){xt(this,e);return}e.send("Runtime.runIfWaitingForDebugger").catch(()=>{})}}}allPages(){return[...this.pages.values()].filter(e=>!e.closed)}async newPage(e={}){let{targetId:t}=await this.root.send("Target.createTarget",{url:e.url??"about:blank",browserContextId:e.browserContextId,...e.background?{background:!0}:{}});return this.waitForPage(t)}async waitForPage(e,t=15e3){let s=this.pages.get(e);return s?.ready?s:new Promise((o,i)=>{let r=setTimeout(()=>{a(),i(new Error(`Page ${e} did not initialize within ${t}ms`))},t),a=this.on("page",c=>{c.targetId===e&&(clearTimeout(r),a(),o(c))})})}async createContext(e={}){let t=e.proxyServer&&Qe(e.proxyServer)?await Ze(e.proxyServer):null;try{let{browserContextId:s}=await this.root.send("Target.createBrowserContext",{disposeOnDetach:!0,proxyServer:t?.url??e.proxyServer,...e.proxyServer?{proxyBypassList:[...Xe,...e.proxyBypassList?[e.proxyBypassList]:[]].join(";")}:e.proxyBypassList?{proxyBypassList:e.proxyBypassList}:{}});return t&&(this.contextForwarders.set(s,t),this.gate(t)),s}catch(s){throw await t?.close(),s}}async disposeContext(e){await this.root.send("Target.disposeBrowserContext",{browserContextId:e}),await this.contextForwarders.get(e)?.close(),this.contextForwarders.delete(e)}addCleanup(e){this.cleanups.push(e)}byteCounters=[];addByteCounter(e){this.byteCounters.push(e)}useForwarder(e){this.addCleanup(()=>e.close()),this.addByteCounter(()=>e.bytes()),this.gate(e),this.launchForwarder=e}gated=new Set;launchForwarder=null;gate(e){this.gated.add(e),e.onData=()=>this.checkTraffic(),e.route=t=>this.proxiedHost(t),e.onUpstreamDown=t=>this.emitter.emit("upstreamDown",t),e.onTunnelFailed=t=>this.emitter.emit("tunnelFailed",t),e.onRefused=t=>this.refusedTunnel(t),this.holding&&e.hold()}refused=new Set;refusedPolicy=null;setRefusedPolicy(e){this.refusedPolicy=e}refusedTunnel(e){let t=D(e.host)||e.host.toLowerCase();if(this.refused.has(t))return!0;let s=this.refusedPolicy?.(t,e.host)==="direct";return s&&this.leaveExit(t),this.emitter.emit("proxyRefused",{host:e.host,site:t,answer:e.answer,direct:s}),s}routeDirect(e){let t=xe(e);t&&this.leaveExit(t)}leaveExit(e){this.refused.add(e),this.routing?.sites.delete(e);for(let t of this.gated)t.dropProxied(s=>(D(s)||s.toLowerCase())===e)}get paidProxy(){return this.gated.size>0}routing=null;offDocuments=null;never=new Set;pinned=new Map;get exitCountry(){return this.options.region?.country?.toLowerCase()??null}offExit(e){if(this.never.has(e)||this.refused.has(e))return!0;if(!this.pinned.has(e))return!1;let t=this.pinned.get(e);return!t||t!==this.exitCountry}pinnedHere(e){let t=xe(e);return!!t&&this.pinned.has(t)&&!this.offExit(t)}routable(e){let t=xe(e);return!!t&&!this.offExit(t)}setProxyRouting(e){e?.never&&(this.never=new Set(e.never.map(xe).filter(Boolean))),this.routing=e?{sites:new Set((e.sites??[]).map(xe).filter(t=>t&&!this.offExit(t))),documents:e.documents??"none",directOnly:!1}:null,this.routing&&(this.routing.documents!=="none"||this._exit?.looked===!1||[...this.pinned.keys()].some(t=>!this.offExit(t)))&&this.watchDocuments();for(let t of this.gated)t.dropDirect(s=>this.proxiedHost(s)),t.dropProxied(s=>!this.proxiedHost(s));(!this.routing||this.routing.sites.size>0)&&this.lookUpExit()}watchDocuments(){this.offDocuments||(this.offDocuments=this.addSessionInitializer(async e=>{let t=new Set;await ye.for(e.session).add({types:["Document"],onRequest:l(async o=>{let i=this.routing?.documents,r=e.isMain&&o.frameId===e.page.targetId;we(o.request.url)||!!o.networkId&&t.has(o.networkId)||!!o.redirectedRequestId&&t.has(o.redirectedRequestId)?(o.networkId&&t.add(o.networkId),t.add(o.requestId)):(i==="all"||i==="main"&&r||i==="frames"&&!r||this.pinnedHere(o.request.url))&&this.routeSite(o.request.url),this.exitLookup&&this.proxiedUrl(o.request.url)&&await this.exitLookup},"onRequest")}).enabled}))}pinSite(e,t){let s=xe(e);if(s&&(this.pinned.set(s,t?.toLowerCase()||null),!!this.routing)){if(!this.offExit(s))return this.watchDocuments();if(this.routing.sites.delete(s))for(let o of this.gated)o.dropProxied(i=>D(i)===s)}}proxiedHost(e){if(!this.paidProxy||this.refused.size&&this.refused.has(D(e)||e.toLowerCase()))return!1;let t=this.routing;return t?t.directOnly?!1:t.sites.has(D(e))||t.sites.size>0&&Hn(e):!0}proxiedUrl(e){try{let t=new URL(e);return(t.protocol==="http:"||t.protocol==="https:"||t.protocol==="ws:"||t.protocol==="wss:")&&this.proxiedHost(t.hostname)}catch{return!1}}get proxiedSites(){return this.routing?[...this.routing.sites]:null}routeSite(e){if(!this.routing||this.routing.directOnly)return;let t=xe(e);if(!t||this.routing.sites.has(t)||this.offExit(t))return;let s=this.routing.sites.size===0;this.routing.sites.add(t);for(let o of this.gated)o.dropDirect(i=>D(i)===t||s&&Hn(i));this.lookUpExit()}setDirectOnly(){this.routing={sites:new Set,documents:this.routing?.documents??"none",directOnly:!0};for(let e of this.gated)e.dropProxied()}_exit=null;exitLookup=null;exitCoords=null;offGeolocation=null;rotateExit(){let e=this._exit,t=this.launchForwarder;if(!e?.reroll||!t)return!1;let s=e.reroll();return e.upstream=s.url,t.setUpstream(s.url),this.options.region&&(this.options.region={...this.options.region,session:s.session}),t.dropProxied(),e.looked=!1,(!this.routing||this.routing.sites.size>0)&&this.lookUpExit(),!0}exitReady(){return this.exitApplied??Promise.resolve()}exitApplied=null;lookUpExit(){let e=this._exit;if(!e?.lookup||e.looked)return this.exitLookup;e.looked=!0;let t=e.upstream,s=Promise.resolve(),o=e.lookup(t).then(i=>{i&&this._exit?.upstream===t&&(s=this._applyExitGeo(i,{geolocation:!0}))},i=>{et(i)&&this.emitter.emit("upstreamDown","login")});return this.exitLookup=o,this.exitApplied=o.then(()=>s),o}async _applyExitGeo(e,t){let s=this.options.region;s&&(this.options.region={...s,...e.ip?{exitIp:e.ip}:{},...e.timezone?{exitTimezone:e.timezone}:{},...e.city?{exitCity:e.city}:{},...e.latitude!==void 0&&e.longitude!==void 0?{exitLat:e.latitude,exitLong:e.longitude}:{}});let o=[];if(e.timezone&&e.timezone!==this.options.timezoneId&&!this.options.keepTimezone&&(this.options.timezoneId=e.timezone,o.push(this.reapplyClock())),t.geolocation&&this.options.stealth&&e.latitude!==void 0&&e.longitude!==void 0){let i={latitude:e.latitude,longitude:e.longitude};this.exitCoords=i;let r=l(a=>a.send("Emulation.setGeolocationOverride",{...i,accuracy:50}).catch(()=>{}),"apply");this.offGeolocation||(this.offGeolocation=this.addSessionInitializer(async a=>{this.exitCoords&&await r(a.session)}));for(let a of this.allPages())for(let c of a.frames())o.push(r(c.session))}await Promise.all(o)}limit=null;softFired=!1;hardFired=!1;holding=!1;challenges=new Set;suspended=null;allowanceUsed=0;lastUsed=0;setTrafficLimit(e,t=()=>{}){this.limit=typeof e=="number"?{softBytes:1/0,hardBytes:e,challengeAllowanceBytes:0,onHard:t}:e,this.softFired=!1,this.hardFired=!1,this.allowanceUsed=0,this.lastUsed=this.proxyBytes(),this.setHeld(!1,!0),this.checkTraffic()}challengeActive(e,t){let s=xe(e)||e.toLowerCase();t?this.challenges.add(s):this.challenges.delete(s),this.checkTraffic()}suspendHold(e){this.suspended=e||"suspended",this.checkTraffic()}resumeHold(){this.suspended=null,this.checkTraffic()}isHeld(){return this.holding}setHeld(e,t=!1){if(!(e===this.holding&&!t)){this.holding=e;for(let s of this.gated)e?s.hold():s.release()}}checkTraffic(){let e=this.proxyBytes(),t=Math.max(0,e-this.lastUsed);this.lastUsed=e;let s=this.limit;if(!s||(!this.softFired&&e>=s.softBytes&&(this.softFired=!0,s.onSoft?.(e)),e<s.hardBytes))return;let o=this.challenges.size>0,i=o||!!this.suspended;if(i&&(this.allowanceUsed+=Math.min(t,e-s.hardBytes)),!(this.hardFired&&this.holding&&!o||!i||this.allowanceUsed>s.challengeAllowanceBytes))return this.setHeld(!1);this.setHeld(!0),!this.hardFired&&(this.hardFired=!0,s.onHard?.(e))}async cancelDownload(e){await this.root.send("Browser.cancelDownload",{guid:e}).catch(()=>{})}proxyBytes(){let e=0;for(let t of this.byteCounters)e+=t();for(let t of this.contextForwarders.values())e+=t.bytes();return e}proxyBytesByHost(){let e=new Map;for(let t of[...this.launchForwarder?[this.launchForwarder]:[],...this.contextForwarders.values()])for(let[s,o]of t.bytesByHost())e.set(s,(e.get(s)??0)+o);return e}exitProxyUrl(){return this.launchForwarder?.url??null}async version(){return this.root.send("Browser.getVersion")}async close(){if(this.cleanedUp)return;if(this.cleanedUp=!0,!this.closedReason)try{await Promise.race([this.root.send("Browser.close",void 0,{timeoutMs:3e3}),new Promise(t=>setTimeout(t,3e3))])}catch{}this.connection.close("browser closed");let e=this.launched?.process;e&&e.exitCode===null&&await new Promise(t=>{let s=setTimeout(()=>{try{e.kill("SIGKILL")}catch{}t()},3e3);e.once("exit",()=>{clearTimeout(s),t()})});for(let t of this.contextForwarders.values())await t.close().catch(()=>{});this.contextForwarders.clear();for(let t of this.cleanups.splice(0))await Promise.resolve(t()).catch(()=>{});this.launched?.ownsUserDataDir&&await Qr(this.launched.userDataDir,{recursive:!0,force:!0,maxRetries:10,retryDelay:200}).catch(()=>{})}};var Un=l(n=>{throw new Error(n+" is not part of the open pilotfish MCP (the hosted service only)")},"refuse");function jn(){return Un("buildUserAgent")}l(jn,"buildUserAgent");function Bn(){return Un("stealthChromePath")}l(Bn,"stealthChromePath");import{existsSync as qn,mkdirSync as ta,readFileSync as Wn,writeFileSync as zn}from"node:fs";import{join as St}from"node:path";var sa={net:{network_prediction_options:2}},hs="pilotfish-model-manifest.json";function na(n,e){let t="";for(let s of n)s.startsWith("--profile-directory=")&&(t=s.slice(20).replace(/^"|"$/g,"")||t);if(t)return t;try{let s=e?JSON.parse(Wn(St(e,"Local State"),"utf8"))?.profile?.last_used:void 0;if(typeof s=="string"&&s&&!/[\\/]|^\.\.?$|^System Profile$/.test(s))return s}catch{}return"Default"}l(na,"profileDirectory");function us(n,e){let t={...n};for(let[s,o]of Object.entries(e)){let i=t[s];t[s]=o&&typeof o=="object"&&!Array.isArray(o)?us(i&&typeof i=="object"&&!Array.isArray(i)?i:{},o):o}return t}l(us,"merged");function Gn(n,e=[],t){try{let s=St(n,hs);qn(s)||zn(s,`{}
|
|
111
111
|
`);let o=St(n,na(e,n)),i=St(o,"Preferences"),r={};if(qn(i)){let c=JSON.parse(Wn(i,"utf8"));if(!c||typeof c!="object"||Array.isArray(c))return!1;r=c}else ta(o,{recursive:!0});let a=us(us(r,sa),t??{});return JSON.stringify(a)!==JSON.stringify(r)&&zn(i,JSON.stringify(a)),!0}catch{return!1}}l(Gn,"seedProfile");var Vn=l(n=>{throw new Error(n+" is not part of the open pilotfish MCP (the hosted service only)")},"refuse");function Kn(){return Vn("osFontConfig")}l(Kn,"osFontConfig");function Yn(){return Vn("osFontPrefs")}l(Yn,"osFontPrefs");function ua(n,e){return n==="darwin"?["/Applications/Google Chrome.app/Contents/MacOS/Google Chrome"]:n==="linux"?["/usr/bin/google-chrome","/usr/bin/google-chrome-stable","/opt/google/chrome/chrome"]:["C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe","C:\\Program Files (x86)\\Google\\Chrome\\Application\\chrome.exe",...e.LOCALAPPDATA?[ce(e.LOCALAPPDATA,"Google","Chrome","Application","chrome.exe")]:[]]}l(ua,"googleChromeCandidates");function ha(n){return n==="darwin"?["/Applications/Google Chrome Canary.app/Contents/MacOS/Google Chrome Canary","/Applications/Chromium.app/Contents/MacOS/Chromium","/Applications/Microsoft Edge.app/Contents/MacOS/Microsoft Edge","/Applications/Brave Browser.app/Contents/MacOS/Brave Browser"]:n==="linux"?["/usr/bin/chromium","/usr/bin/chromium-browser","/usr/bin/microsoft-edge"]:["C:\\Program Files (x86)\\Microsoft\\Edge\\Application\\msedge.exe"]}l(ha,"otherChromiumCandidates");function pa(n,e,t){let s=[e.PLAYWRIGHT_BROWSERS_PATH,n==="darwin"?ce(Jn(),"Library/Caches/ms-playwright"):void 0,n==="linux"?ce(Jn(),".cache/ms-playwright"):void 0,n==="win32"?ce(e.LOCALAPPDATA??"","ms-playwright"):void 0].filter(i=>!!i&&t(i)),o=[];for(let i of s){let r=[];try{r=Zn(i)}catch{continue}let a=r.filter(c=>/^chromium-\d+$/.test(c)).sort().reverse();for(let c of a){let d=ce(i,c);o.push(ce(d,"chrome-mac-arm64/Google Chrome for Testing.app/Contents/MacOS/Google Chrome for Testing"),ce(d,"chrome-mac/Google Chrome for Testing.app/Contents/MacOS/Google Chrome for Testing"),ce(d,"chrome-linux/chrome"),ce(d,"chrome-linux64/chrome"),ce(d,"chrome-win/chrome.exe"),ce(d,"chrome-win64/chrome.exe"))}}return o}l(pa,"playwrightChromiumCandidates");function eo(n={}){let e=n.env??process.env,t=n.exists??Qn,s=n.os??ot(),o=e.PILOTFISH_CHROME;if(o&&t(o))return o;for(let i of[...ua(s,e),...pa(s,e,t),...ha(s)])if(t(i))return i}l(eo,"findChromium");function to(n,e){let{width:t,height:s}=n.viewport??{width:1280,height:800},o=["--remote-debugging-pipe",`--user-data-dir=${e}`,`--window-size=${t},${s}`,"--no-first-run","--no-default-browser-check","--disable-background-networking","--disable-background-timer-throttling","--disable-backgrounding-occluded-windows","--disable-renderer-backgrounding","--disable-breakpad","--disable-component-update","--disable-default-apps","--disable-domain-reliability","--disable-sync","--disable-client-side-phishing-detection","--disable-hang-monitor","--disable-popup-blocking","--disable-prompt-on-repost","--disable-search-engine-choice-screen","--disable-session-crashed-bubble","--metrics-recording-only","--password-store=basic","--use-mock-keychain","--mute-audio","--disable-infobars","--disable-blink-features=AutomationControlled",`--disable-features=Translate,OptimizationHints,MediaRouter,DialMediaRouteProvider,AcceptCHFrame,AutoExpandDetailsElement,CertificateTransparencyComponentUpdater,DestroyProfileOnBrowserClose,HttpsUpgrades,PrivacySandboxSettings4,LensOverlay,AimEnabled,SafeBrowsingHashPrefixRealTimeLookups,NetworkTimeServiceQuerying${n.stealth?",IsolateSandboxedIframes":""}`,"--enable-features=NetworkService,NetworkServiceInProcess2",`--optimization-guide-manifest-override=${ce(e,hs)}`];n.headless!==!1?o.push("--headless=new",...n.stealth?[]:["--hide-scrollbars"]):o.push("--test-type"),ot()==="linux"&&o.push("--disable-dev-shm-usage"),n.headless===!1&&ot()==="linux"&&o.push("--enable-unsafe-swiftshader"),n.stealth&&n.persona?.webgpu&&ot()==="linux"&&o.push("--enable-unsafe-webgpu","--disable-dawn-features=allow_unsafe_apis"),n.stealth&&n.persona&&ot()==="linux"&&o.push("--use-fake-device-for-media-stream"),n.stealth&&o.push("--force-webrtc-ip-handling-policy=disable_non_proxied_udp","--webrtc-ip-handling-policy=disable_non_proxied_udp"),n.userAgent&&o.push(`--user-agent=${n.userAgent}`),n.proxyServer&&o.push(`--proxy-server=${n.proxyServer}`),n.proxyServer&&o.push(`--proxy-bypass-list=${[...Xe,...n.proxyBypass??[]].join(";")}`),n.locale&&o.push(`--lang=${n.locale}`);let i=n.persona?.languages.length?n.persona.languages.join(","):n.locale?wa(n.locale):void 0;return i&&o.push(`--accept-lang=${i}`),n.ignoreHTTPSErrors&&o.push("--ignore-certificate-errors"),o.push(...n.args??[]),o.push("about:blank"),o}l(to,"defaultArgs");var fs=new Map;function fa(n){let e=n.map(s=>/^(\d+)\.(\d+)\.(\d+)\.(\d+)(?:\.manifest)?$/.exec(s)).filter(s=>!!s);e.sort((s,o)=>{for(let i=1;i<=4;i++)if(Number(s[i])!==Number(o[i]))return Number(o[i])-Number(s[i]);return 0});let t=e[0];return t?`${t[1]}.${t[2]}.${t[3]}.${t[4]}`:null}l(fa,"newestVersionName");async function so(n){let e="";try{let o=aa(n);e=`${o.size}:${o.mtimeMs}`}catch{if(process.platform==="win32"||/[\\/]/.test(n))return null}if(process.platform!=="win32")return new Promise(o=>{oa(n,["--version"],{timeout:1e4,windowsHide:!0},(i,r)=>{o(i?null:/(\d+\.\d+\.\d+\.\d+)/.exec(String(r))?.[1]??null)})});let t=fs.get(n);if(t&&t.stamp===e)return t.version;let s=null;try{s=fa(Zn(da(n)))}catch{s=null}return fs.set(n,{stamp:e,version:s}),s}l(so,"chromeVersionOf");var Xn=new Set;function ma(n){Xn.has(n)||/[\\/]/.test(n)&&!Qn(n)||(Xn.add(n),process.emitWarning(`pilotfish: could not read the Chrome version of ${n} before launch: it starts with its own user agent, so the script fetches of service and nested workers, and a service worker's update checks, carry the host's`,{code:"PILOTFISH_UA_VERSION"}))}l(ma,"warnUnreadVersion");function ga(n,e){let t=fs.get(n);t&&(t.version=e)}l(ga,"noteLiveVersion");function wa(n){let e=n.split("-")[0];return e&&e!==n?`${n},${e}`:n}l(wa,"acceptLanguage");async function ps(n){await ca(n,{recursive:!0,force:!0,maxRetries:10,retryDelay:200}).catch(()=>{})}l(ps,"removeProfile");async function gs(n={}){let e=n,t=n.region?.proxy&&(!n.timezoneId||n.keepTimezone)?bn(n.region.proxy):null,s=e.proxyRouting,o=!!s&&!(s.sites??[]).length&&s.documents!=="all"&&s.documents!=="main",i=n.region?.city&&n.region.proxy&&xn(n.region.proxy)&&t&&!o?n.region.city:void 0;if(e.region){let R=vn(e.region.country),F=e.region.session??is(),{city:H,...O}=e.region;e={...e,region:{...O,country:R.country,session:F,...i?{city:i}:{}},timezoneId:e.timezoneId??R.timezoneId,locale:e.locale??R.locale,...e.region.proxy?{proxyServer:bt(e.region.proxy,{country:R.country,session:F,...i?{city:i}:{}})}:{}}}let r=e.proxyServer&&Qe(e.proxyServer)?e.proxyServer:null,a=r?await Ze(r,{allowPrivateDirect:!!e.proxyRouting?.privateNetwork}):null;a&&(e={...e,proxyServer:a.url});let c=e.region?.proxy?{proxy:e.region.proxy,country:e.region.country}:null,d=c?()=>(R=>({url:bt(c.proxy,{country:c.country,session:R,...i?{city:i}:{}}),session:R}))(is()):null,u=t&&r?R=>kn(R,t,3e3):null,h=l(R=>u(R).then(F=>({geo:F}),F=>({error:F})),"look"),p=l(()=>(i=void 0,r=bt(c.proxy,{country:c.country,session:e.region.session}),a.setUpstream(r),a.dropProxied(),h(r)),"byCountry"),f=null,b=l(()=>{i=void 0;let R=d();return f=R.session,r=R.url,a.setUpstream(r),a.dropProxied(),h(r)},"fresh"),k=l(R=>"error"in R&&!et(R.error),"dead"),m=u&&r&&!o?h(r).then(R=>i&&c&&a&&!("geo"in R&&R.geo)?p():R).then(R=>d&&a&&k(R)?b():R):null,y=l(async()=>{let R=await m,F=R&&"error"in R?et(R.error):null;return F?new $t(F):null},"refusedLogin"),v=e.executablePath??(e.stealth?Bn():void 0)??eo();if(!v)throw await a?.close().catch(()=>{}),await y()??new Error("No Chromium executable found. Set PILOTFISH_CHROME, pass executablePath, install Google Chrome, or run `npx playwright install chromium`.");let _=null;e.persona&&!e.userAgent&&(_=(await so(v))?.split(".")[0]??null,_?e={...e,userAgent:jn(e.persona,_)}:ma(v));let C=!e.userDataDir,N=e.userDataDir??ra(ce(la(),"pilotfish-profile-")),M=to(e,N),x=e.persona?Kn(e.persona.os):void 0;Gn(N,M,x&&e.persona?Yn(e.persona.os):void 0)||process.emitWarning(`pilotfish: could not set the launch prefs in ${N} (its Preferences is not valid JSON, or not writable): Chrome starts with "Preload pages" on, and may connect to a site directly before its first page is routed`,{code:"PILOTFISH_PROFILE_PREFS"});let T=null;if(e.headless===!1&&process.platform==="linux"&&!process.env.DISPLAY){let{width:R,height:F}=e.viewport??{width:1280,height:800};try{T=await _n({width:R,height:F},void 0,e.screen)}catch(H){throw await a?.close().catch(()=>{}),C&&await ps(N),await y()??H}}let w;try{w=ia(v,M,{stdio:["ignore",e.dumpio?"inherit":"ignore",e.dumpio?"inherit":"pipe","pipe","pipe"],env:{...process.env,...e.timezoneId?{TZ:e.timezoneId}:{},...T?.env??{},...x?{FONTCONFIG_FILE:x}:{}},detached:process.platform!=="win32"})}catch(R){throw await a?.close().catch(()=>{}),T?.close(),C&&await ps(N),await y()??R}let S=[];e.dumpio||w.stderr?.on("data",R=>{S.length<200&&S.push(R.toString())});let E=new Ye(w.stdio[3],w.stdio[4]),$=new Ke(E,{...e.connection,onWire:e.debugWire?(R,F)=>process.stderr.write(`${R==="send"?"\u2192":"\u2190"} ${F.slice(0,400)}
|
|
112
112
|
`):e.connection?.onWire}),g=new Promise((R,F)=>{w.once("exit",(H,O)=>{F(new Error(ms(v,H,O,S.join(""))))}),w.once("error",H=>F(new Error(`Failed to spawn Chromium at ${v}: ${H.message}`)))}),A={process:w,userDataDir:N,ownsUserDataDir:C,executablePath:v},I=new _t($,A,e);a&&r&&(I.useForwarder(a),I._exit={upstream:r,lookup:u,looked:!o,reroll:d},e.proxyRouting&&I.setProxyRouting(e.proxyRouting)),T&&I.addCleanup(()=>T.close());try{await Promise.race([I._initialize(),g,new Promise((R,F)=>setTimeout(()=>F(new Error(`Browser did not become ready within ${e.launchTimeoutMs??3e4}ms`)),e.launchTimeoutMs??3e4).unref())])}catch(R){let F=w.exitCode!==null||w.signalCode!==null?!0:await new Promise(O=>{let L=setTimeout(()=>O(!1),1e3);w.once("exit",()=>{clearTimeout(L),O(!0)})});try{w.kill("SIGKILL")}catch{}await a?.close().catch(()=>{}),T?.close(),C&&await ps(N);let H=await y();throw H||(F?new Error(ms(v,w.exitCode,w.signalCode,S.join(""))):R)}if(_){let R=/Chrome\/(\d+(?:\.\d+){1,3})/.exec((await I.version().catch(()=>null))?.product??"")?.[1];R&&R.split(".")[0]!==_&&(ga(v,R),process.emitWarning(`pilotfish: ${v} was read as Chrome ${_} before launch but runs ${R}; its own user agent named the wrong major this time`,{code:"PILOTFISH_UA_VERSION"}))}if(m){let R=await m,F=await y();if(F)throw await I.close(),F;if(!i&&I.options.region?.city){let{city:H,...O}=I.options.region;I.options.region=O,I._exit&&r&&(I._exit.upstream=r)}f&&I.options.region&&(I.options.region={...I.options.region,session:f},I._exit&&r&&(I._exit.upstream=r)),"geo"in R&&R.geo&&await I._applyExitGeo(R.geo,{geolocation:!1})}return I}l(gs,"launch");var $t=class extends Error{static{l(this,"ProxyAuthError")}status;constructor(e){super(`The residential proxy refused its login (HTTP ${e}). Check the provider account (traffic left on the plan) and its username and password.`),this.name="ProxyAuthError",this.status=e}};function ms(n,e,t,s){let o=[];return/No usable sandbox|setuid sandbox|namespace|zygote/i.test(s)&&o.push("Chromium's sandbox could not start. On Ubuntu 23.10+ (incl. GitHub ubuntu-24.04 runners) unprivileged user namespaces are blocked by AppArmor: run `sudo sysctl -w kernel.apparmor_restrict_unprivileged_userns=0`, or install an AppArmor profile for Chrome. Do not disable the sandbox for untrusted pages."),/PR_SET_NO_NEW_PRIVS/i.test(s)&&/Failed to move to new namespace/i.test(s)&&o.push("If this runs under systemd, remove NoNewPrivileges=true from the unit: with no_new_privs set, AppArmor cannot apply the profile that grants Chrome user namespaces."),/error while loading shared libraries/i.test(s)&&o.push("Missing system libraries: run `npx playwright install-deps chromium` or use the provided Docker image."),/Missing X server|cannot open display/i.test(s)&&o.push("Headed mode needs a display: run under Xvfb (xvfb-run) or use headless."),[`Chromium exited during launch (code=${e} signal=${t}) \u2014 ${n}`,...o.map(i=>`Hint: ${i}`),s?`stderr:
|
|
113
113
|
${s.trim().split(`
|
|
@@ -411,7 +411,7 @@ return __pfClassify("Accept all") === "accept" && __pfClassify("Reject all") ===
|
|
|
411
411
|
return click.call(this);
|
|
412
412
|
};
|
|
413
413
|
})();
|
|
414
|
-
${Zt(tr(nr,"autoconsent.playwright.js"),"utf8")}`,tu=3,su=2500,nu=6500,ou=6e3,iu=3e3,ru=1500,au=3e3,cu=4e3;function lu(n,e){if(n.doneAt)return"opted_out";if(n.optOut===!1)return"failed";if(n.optOut===!0)return e-n.optOutAt>iu?"opted_out":"pending";if(n.popupAt)return"pending";if(n.detectedAt)return e-n.detectedAt<nu?"pending":"no_cmp";let t=n.topLifecycle!=="nothingDetected",s=l((o,i)=>e-o>=su&&i!==void 0&&n.topAttempts>=i+tu,"quiet");return n.cmpRequestAt&&e-n.cmpRequestAt<ou&&t&&!s(n.cmpRequestAt,n.roundAtCmpRequest)||!n.topInitAt&&/^https?:/.test(n.url)&&e-n.navAt<ru||n.topInitAt&&n.topAttempts<2&&e-n.topInitAt<au||n.patternsAt&&e-n.patternsAt<cu&&t&&!s(n.patternsAt,n.roundAtPatterns)?"pending":"no_cmp"}l(lu,"outcomeOf");var Qt=class{static{l(this,"ConsentEngine")}opts;emitter=new Vd;pages=new WeakMap;disposers=new Set;armed=new WeakSet;retried=new WeakSet;retryTimers=new Set;disposed=!1;config;constructor(e={}){if(this.opts=e,this.config=Qd(e),this.config.autoAction!=="optOut"||!["off","reject"].includes(this.config.heuristicMode))throw new Error("ConsentEngine only ever opts out")}on(e,t){return this.emitter.on(e,t),()=>this.emitter.off(e,t)}consentStatus(e){let t=this.state(e),s=Date.now(),o=lu(t,s),i=o==="opted_out"?t.doneAt??t.optOutAt:s;return{cmp:t.cmp,outcome:o,ms:Math.max(0,i-t.navAt),url:t.url,...t.cosmetic!==void 0?{cosmetic:t.cosmetic}:{},...t.selfTest!==void 0?{selfTest:t.selfTest}:{},refusedClicks:t.refused,frames:t.frames.size}}async waitForConsent(e,t=1e4){let s=Date.now()+t;for(;;){let o=this.consentStatus(e);if(o.outcome!=="pending"||Date.now()>=s||e.closed)return o;await new Promise(i=>setTimeout(i,Math.min(100,Math.max(1,s-Date.now()))))}}dispose(){this.disposed=!0;for(let e of this.retryTimers)clearTimeout(e);this.retryTimers.clear();for(let e of this.disposers)e();this.disposers.clear()}initSession=l(async e=>{let t=e.session,s=e.page;if(!e.isMain&&we(e.url)||this.armed.has(t))return;this.armed.add(t);let o=new Map,i=[()=>this.armed.delete(t)],r;try{[,r]=await Promise.all([t.send("Runtime.addBinding",{name:ze,executionContextName:dn},{timeoutMs:5e3}),t.send("Page.addScriptToEvaluateOnNewDocument",{source:eu,worldName:dn,runImmediately:!0},{timeoutMs:5e3})])}catch(p){if(this.armed.delete(t),e.isMain&&!this.retried.has(t)&&!this.disposed){this.retried.add(t);let f=setTimeout(()=>{this.retryTimers.delete(f),this.disposed||this.initSession(e).catch(()=>{})},2e3);f.unref?.(),this.retryTimers.add(f)}throw p}let a=l(()=>{for(let p of i)p();t.send("Page.removeScriptToEvaluateOnNewDocument",{identifier:r.identifier}).catch(()=>{}),t.send("Runtime.removeBinding",{name:ze}).catch(()=>{})},"dispose");this.disposers.add(a),i.push(()=>this.disposers.delete(a));let c=l(async(p,f,b)=>{if(!/^https?:/.test(f)||!b&&we(f))return;let{executionContextId:k}=await t.send("Page.createIsolatedWorld",{frameId:p,worldName:dn,grantUniveralAccess:!1},{timeoutMs:5e3});o.set(k,{frameId:p,mainFrame:b}),await t.send("Runtime.addBinding",{name:ze,executionContextId:k},{timeoutMs:5e3}),await t.send("Runtime.evaluate",{contextId:k,expression:"globalThis.__pfAcFlush && __pfAcFlush()",returnByValue:!0},{timeoutMs:5e3})},"arm"),d=l((p,f,b)=>{c(p,f,b).catch(k=>{/not found|Cannot find|No frame|detached|closed|destroyed|navigated/i.test(String(k))||this.emit("error",{page:s,frameId:p,url:f,error:`arm: ${String(k)}`})})},"armSafe");i.push(t.on("Page.frameNavigated",p=>{let f=e.isMain&&!p.frame.parentId;f&&this.reset(s,p.frame.url),d(p.frame.id,p.frame.url,f)}),t.on("Runtime.bindingCalled",p=>{if(p.name!==ze)return;let f=o.get(p.executionContextId);f&&this.onMessage(t,s,p.executionContextId,f,p.payload).catch(()=>{})}),t.on("Network.requestWillBeSent",p=>{if(!Fi(p.request.url))return;let f=this.state(s);f.cmpRequestAt===void 0&&(f.cmpRequestAt=Date.now(),f.roundAtCmpRequest=f.topAttempts)}));let{frameTree:u}=await t.send("Page.getFrameTree"),h=l((p,f)=>{d(p.frame.id,p.frame.url,f);for(let b of p.childFrames??[])h(b,!1)},"walk");h(u,e.isMain)},"initSession");async onMessage(e,t,s,o,i){let r;try{r=JSON.parse(i)}catch{return}let a=this.state(t),c=typeof r.url=="string"?r.url:"",d={page:t,frameId:o.frameId,url:c},u=typeof r.cmp=="string"?r.cmp:"";switch(r.type){case"init":{a.frames.add(o.frameId),o.mainFrame&&(a.topInitAt??=Date.now());let h={autoconsent:[],compact:Jd(or,{url:c,mainFrame:o.mainFrame})};await this.reply(e,s,{type:"initResp",config:this.config,rules:h});return}case"eval":await this.reply(e,s,{type:"evalResp",id:r.id,result:await this.runSnippet(e,t,s,o,r.snippetId)});return;case"cmpDetected":a.cmp??=u,a.detectedAt??=Date.now(),this.emit("cmpDetected",{...d,cmp:u});return;case"popupFound":a.cmp=u,a.popupAt??=Date.now(),this.emit("popupFound",{...d,cmp:u});return;case"optOutResult":a.cmp=u||a.cmp,a.optOut=r.result===!0,a.optOutAt=Date.now(),r.result===!0&&r.scheduleSelfTest===!0&&(a.selfTestTarget={s:e,contextId:s}),this.emit("optOutResult",{...d,cmp:u,result:r.result===!0});return;case"autoconsentDone":{a.cmp=u||a.cmp,a.doneAt=Date.now(),a.cosmetic=r.isCosmetic===!0,this.emit("autoconsentDone",{...d,cmp:u,cosmetic:a.cosmetic,durationMs:Number(r.duration)||0,clicks:Number(r.totalClicks)||0});let h=a.selfTestTarget;a.selfTestTarget=void 0,this.opts.selfTest!==!1&&h&&await this.reply(h.s,h.contextId,{type:"selfTest"});return}case"selfTestResult":a.selfTest=r.result===!0,this.emit("selfTestResult",{...d,cmp:u,result:a.selfTest});return;case"optInResult":this.emit("error",{...d,error:"unexpected optInResult",details:r});return;case"autoconsentError":this.emit("error",{...d,error:"autoconsent",details:r.details});return;case"pfRefusedClick":a.refused++,this.emit("error",{...d,error:`refused to click an accept button: "${String(r.text)}"`});return;case"report":{let h=r.state??{};if(!o.mainFrame||r.mainFrame!==!0)return;a.topLifecycle=h.lifecycle,a.topAttempts=Math.max(a.topAttempts,Number(h.findCmpAttempts)||0),h.heuristicPatterns?.length&&a.patternsAt===void 0&&(a.patternsAt=Date.now(),a.roundAtPatterns=a.topAttempts);return}default:return}}reply(e,t,s){return e.send("Runtime.evaluate",{contextId:t,expression:`autoconsentReceiveMessage(${JSON.stringify(s)})`,returnByValue:!0}).catch(()=>{})}async runSnippet(e,t,s,o,i){let r=typeof i=="string"?sr[i]:void 0;if(!r||Xd.has(i))return this.emit("error",{page:t,frameId:o.frameId,error:`refused eval snippet ${String(i)}`}),!1;let a=await e.send("Runtime.evaluate",{contextId:s,expression:"document",returnByValue:!1});if(!a.result.objectId)return!1;try{let{node:c}=await e.send("DOM.describeNode",{objectId:a.result.objectId}),{object:d}=await e.send("DOM.resolveNode",{backendNodeId:c.backendNodeId});if(!d.objectId)return!1;try{return(await e.send("Runtime.callFunctionOn",{objectId:d.objectId,functionDeclaration:`async function () { try { return !!(await (${r.toString()}).call(window)); } catch (e) { return false; } }`,returnByValue:!0,awaitPromise:!0})).result.value===!0}finally{e.send("Runtime.releaseObject",{objectId:d.objectId}).catch(()=>{})}}catch{return!1}finally{e.send("Runtime.releaseObject",{objectId:a.result.objectId}).catch(()=>{})}}state(e){let t=this.pages.get(e);return t||(t={navAt:Date.now(),url:e.url,cmp:null,refused:0,frames:new Set,topAttempts:0},this.pages.set(e,t)),t}reset(e,t){this.pages.set(e,{navAt:Date.now(),url:t,cmp:null,refused:0,frames:new Set,topAttempts:0})}emit(e,t){e==="error"&&this.emitter.listenerCount("error")===0||this.emitter.emit(e,t)}};var du=["cmpDetected","popupFound","optOutResult","autoconsentDone","selfTestResult","error"],uu=["blocked","error"];async function hn(n,e={}){let t=e.consent===!1?null:new Qt(typeof e.consent=="object"?e.consent:{}),s=e.adblock===!1?null:await Xt.create(typeof e.adblock=="object"?e.adblock:{}),o=[];if(e.onEvent){let r=e.onEvent;if(t)for(let a of du)o.push(t.on(a,(c=>r({source:"consent",type:a,data:c}))));if(s)for(let a of uu)o.push(s.on(a,(c=>r({source:"adblock",type:a,data:c}))))}let i=l(async r=>{await Promise.all([t?.initSession(r),s?.initSession(r)])},"init");return o.push(n.addSessionInitializer(i)),{consent:t,adblock:s,detach(){for(let r of o)r();t?.dispose(),s?.dispose()}}}l(hn,"attachInterrupts");var hu="pilotfish's open MCP makes no model calls: the MCP client's own model reads the page and decides the next step",pu=l(()=>{let n=l(async()=>{throw new Error(hu)},"refuse");return{messages:{create:n},beta:{messages:{create:n}}}},"noModelClient"),pn=class{static{l(this,"ConfirmThrough")}inner;canAsk;constructor(e,t){this.inner=e,this.canAsk=t}async check(e){let t=await this.inner.check(e);return t.kind!=="confirm"||this.canAsk()?t:{kind:"deny",reason:`${t.reason}. This needs a person's confirmation, and this MCP client cannot ask for one (no elicitation support)`}}},We=class{static{l(this,"BrowserSession")}config;opts;browser=null;launching=null;interrupts=null;tabs=null;agent=null;queue=Promise.resolve();policy;asker;constructor(e,t={}){this.config=e,this.opts=t,this.policy=new Ce({allowedHosts:e.allowedHosts,allowPrivateNetwork:e.allowPrivateNetwork})}get launched(){return!!this.browser&&!this.browser.closed}async page(){return await this.ensure(),this.tabs.current}get tabTable(){return this.tabs}async ensure(){return this.browser&&!this.browser.closed?this.browser:(this.launching??=this.start().finally(()=>{this.launching=null}),this.launching)}async start(){let e=await gs({...this.opts.launch,headless:this.config.headless});this.interrupts=await hn(e,{consent:!0,adblock:!0}).catch(()=>null);let t=e.allPages()[0]??await e.newPage();return this.tabs=new Ae(t),this.browser=e,e.on("disconnected",()=>{this.browser===e&&this.reset()}),e}reset(){this.agent?.dispose(),this.agent=null,this.tabs?.dispose(),this.tabs=null,this.interrupts?.detach(),this.interrupts=null,this.browser=null}executor(){return this.agent??=new ut(this.tabs.current,{tabs:this.tabs,client:pu(),secrets:this.config.secrets,policy:new pn(this.policy,()=>!!this.asker),consent:this.interrupts?.consent??void 0,allowScreenshots:this.config.allowScreenshots,askUser:l(e=>this.asker?.(e)??Promise.resolve(null),"askUser"),fastSettle:!0,enableQuery:!0,compactSnapshots:!0,autoDismiss:!0,awaitLoading:!0,actionSnapshotBand:0,snapshotMoreHint:"browser_scroll for the next screen, browser_get_text for the page's text, or browser_snapshot (whole_page) for every element"}),this.agent}async act(e,t,s={}){let o=this.queue.then(async()=>(await this.ensure(),this.executor().act(e,t,"",s)));return this.queue=o.catch(()=>{}),o}async obstacle(e={}){if(!this.launched)return null;let t=this.queue.then(()=>this.executor().obstacle(e));return this.queue=t.catch(()=>{}),t.catch(()=>null)}async close(){let e=this.browser??(this.launching?await this.launching.catch(()=>null):null);return e?(this.reset(),await e.close().catch(()=>{}),!0):!1}};import{McpServer as fu}from"@modelcontextprotocol/sdk/server/mcp.js";import{ListToolsRequestSchema as mu}from"@modelcontextprotocol/sdk/types.js";import{z as B}from"zod";var es="0.1.6";var ts=Ie.click.shape.ref.describe('From the latest snapshot, e.g. "e12" or "f1e3"'),ir=B.enum(["down","up","left","right"]),gu={click:["ref"],type:["ref","text","submit"],select:["ref","values"],press:["key"],scroll:["direction"],wait:["seconds"]},wu={click:1,type:2,select:2,press:1,scroll:1,wait:1},yu=B.object({action:B.enum(["click","type","select","press","scroll","wait"]).describe("click, select, type take ref; type: text (submit: Enter after); select: values; press: key; scroll: direction; wait: seconds"),ref:ts.optional(),text:B.string().max(2e4).optional(),submit:B.boolean().optional(),values:B.array(B.string()).min(1).max(50).optional(),key:B.string().min(1).max(40).optional(),direction:ir.optional(),seconds:B.number().min(.5).max(10).optional()}).strict().superRefine((n,e)=>{let t=gu[n.action];for(let s of t.slice(0,wu[n.action]))n[s]===void 0&&e.addIssue({code:"custom",path:[s],message:`${n.action} needs ${s}`});for(let s of Object.keys(n))s!=="action"&&!t.includes(s)&&e.addIssue({code:"custom",path:[s],message:`${s} is not a field of ${n.action} (it takes ${t.join(", ")})`})}),ne={browser_navigate:B.object({url:B.url({protocol:/^https?$/}).describe("Absolute http(s) URL"),snapshot:B.boolean().optional().describe("Default true. false: no page snapshot, only what happened (title, counts). Only when this same reply also reads the page with browser_query and you will not act on it; keep it for a page you have not seen or whose tabs, sorts, filters or forms you may use.")}).strict(),browser_snapshot:B.object({whole_page:B.boolean().optional()}).strict(),browser_click:B.object({ref:ts}).strict(),browser_type:B.object({ref:ts,text:B.string().max(2e4),submit:B.boolean().optional().describe("Press Enter afterwards")}).strict(),browser_select:B.object({ref:ts,values:B.array(B.string()).min(1).max(50)}).strict(),browser_press:B.object({key:B.string().min(1).max(40).describe('e.g. "Enter", "Escape", "Tab", "ArrowDown", "Control+a"')}).strict(),browser_scroll:B.object({direction:ir}).strict(),browser_screenshot:B.object({}).strict(),browser_get_text:B.object({max_chars:B.number().int().min(500).max(6e4).optional().describe("Default 20000. Ask for less when the start of the page is enough."),selector:B.string().min(1).max(300).optional().describe(`CSS selector: only the first match's text, e.g. "main" or "#results"`)}).strict(),browser_query:B.object({expression:B.string().min(1).max(4e3).describe("e.g. [...document.querySelectorAll('.result')].slice(0,10).map(e => e.innerText)")}).strict(),browser_find:B.object({query:B.string().min(1).max(300).describe('Words naming the element(s), e.g. "Sort by" or "price max input, Go button"')}).strict(),browser_wait:B.object({seconds:B.number().min(.5).max(10)}).strict(),browser_resume:B.object({timeout_s:B.number().int().min(5).max(900).optional().describe("Default 300")}).strict(),browser_actions:B.object({actions:B.array(yu).min(1).max(10)}).strict(),browser_tabs:B.object({switch_to:B.string().min(1).max(10).optional().describe('Tab id to work in from now on, e.g. "t2"')}).strict(),browser_close:B.object({}).strict()};function xe(n,e=!1){return{content:[{type:"text",text:n}],...e?{isError:!0}:{}}}l(xe,"text");function bu(n){let e=Object.keys(n.secrets);return["Words like cheapest, latest, highest-rated or most mean the site's own sort or tab for that order (a list's default order is usually something else, e.g. 'Best' or 'Featured'): apply it, then read the top.",e.length?`Secrets are typed as placeholders and never shown: ${e.map(t=>`{{${t}}}`).join(", ")}.`:"",n.allowedHosts.length?`Navigation is limited to: ${n.allowedHosts.join(", ")}.`:"","When a result says NEEDS A PERSON (a sign-in, a one-time code or 2FA, a device approval, a CAPTCHA), tell the user in your reply what the page needs and that the pilotfish browser window is open on it; when they have done it there, call browser_resume and carry on. BLOCKED and STOP mean the site cannot be continued that way."].filter(Boolean).join(`
|
|
414
|
+
${Zt(tr(nr,"autoconsent.playwright.js"),"utf8")}`,tu=3,su=2500,nu=6500,ou=6e3,iu=3e3,ru=1500,au=3e3,cu=4e3;function lu(n,e){if(n.doneAt)return"opted_out";if(n.optOut===!1)return"failed";if(n.optOut===!0)return e-n.optOutAt>iu?"opted_out":"pending";if(n.popupAt)return"pending";if(n.detectedAt)return e-n.detectedAt<nu?"pending":"no_cmp";let t=n.topLifecycle!=="nothingDetected",s=l((o,i)=>e-o>=su&&i!==void 0&&n.topAttempts>=i+tu,"quiet");return n.cmpRequestAt&&e-n.cmpRequestAt<ou&&t&&!s(n.cmpRequestAt,n.roundAtCmpRequest)||!n.topInitAt&&/^https?:/.test(n.url)&&e-n.navAt<ru||n.topInitAt&&n.topAttempts<2&&e-n.topInitAt<au||n.patternsAt&&e-n.patternsAt<cu&&t&&!s(n.patternsAt,n.roundAtPatterns)?"pending":"no_cmp"}l(lu,"outcomeOf");var Qt=class{static{l(this,"ConsentEngine")}opts;emitter=new Vd;pages=new WeakMap;disposers=new Set;armed=new WeakSet;retried=new WeakSet;retryTimers=new Set;disposed=!1;config;constructor(e={}){if(this.opts=e,this.config=Qd(e),this.config.autoAction!=="optOut"||!["off","reject"].includes(this.config.heuristicMode))throw new Error("ConsentEngine only ever opts out")}on(e,t){return this.emitter.on(e,t),()=>this.emitter.off(e,t)}consentStatus(e){let t=this.state(e),s=Date.now(),o=lu(t,s),i=o==="opted_out"?t.doneAt??t.optOutAt:s;return{cmp:t.cmp,outcome:o,ms:Math.max(0,i-t.navAt),url:t.url,...t.cosmetic!==void 0?{cosmetic:t.cosmetic}:{},...t.selfTest!==void 0?{selfTest:t.selfTest}:{},refusedClicks:t.refused,frames:t.frames.size}}async waitForConsent(e,t=1e4){let s=Date.now()+t;for(;;){let o=this.consentStatus(e);if(o.outcome!=="pending"||Date.now()>=s||e.closed)return o;await new Promise(i=>setTimeout(i,Math.min(100,Math.max(1,s-Date.now()))))}}dispose(){this.disposed=!0;for(let e of this.retryTimers)clearTimeout(e);this.retryTimers.clear();for(let e of this.disposers)e();this.disposers.clear()}initSession=l(async e=>{let t=e.session,s=e.page;if(!e.isMain&&we(e.url)||this.armed.has(t))return;this.armed.add(t);let o=new Map,i=[()=>this.armed.delete(t)],r;try{[,r]=await Promise.all([t.send("Runtime.addBinding",{name:ze,executionContextName:dn},{timeoutMs:5e3}),t.send("Page.addScriptToEvaluateOnNewDocument",{source:eu,worldName:dn,runImmediately:!0},{timeoutMs:5e3})])}catch(p){if(this.armed.delete(t),e.isMain&&!this.retried.has(t)&&!this.disposed){this.retried.add(t);let f=setTimeout(()=>{this.retryTimers.delete(f),this.disposed||this.initSession(e).catch(()=>{})},2e3);f.unref?.(),this.retryTimers.add(f)}throw p}let a=l(()=>{for(let p of i)p();t.send("Page.removeScriptToEvaluateOnNewDocument",{identifier:r.identifier}).catch(()=>{}),t.send("Runtime.removeBinding",{name:ze}).catch(()=>{})},"dispose");this.disposers.add(a),i.push(()=>this.disposers.delete(a));let c=l(async(p,f,b)=>{if(!/^https?:/.test(f)||!b&&we(f))return;let{executionContextId:k}=await t.send("Page.createIsolatedWorld",{frameId:p,worldName:dn,grantUniveralAccess:!1},{timeoutMs:5e3});o.set(k,{frameId:p,mainFrame:b}),await t.send("Runtime.addBinding",{name:ze,executionContextId:k},{timeoutMs:5e3}),await t.send("Runtime.evaluate",{contextId:k,expression:"globalThis.__pfAcFlush && __pfAcFlush()",returnByValue:!0},{timeoutMs:5e3})},"arm"),d=l((p,f,b)=>{c(p,f,b).catch(k=>{/not found|Cannot find|No frame|detached|closed|destroyed|navigated/i.test(String(k))||this.emit("error",{page:s,frameId:p,url:f,error:`arm: ${String(k)}`})})},"armSafe");i.push(t.on("Page.frameNavigated",p=>{let f=e.isMain&&!p.frame.parentId;f&&this.reset(s,p.frame.url),d(p.frame.id,p.frame.url,f)}),t.on("Runtime.bindingCalled",p=>{if(p.name!==ze)return;let f=o.get(p.executionContextId);f&&this.onMessage(t,s,p.executionContextId,f,p.payload).catch(()=>{})}),t.on("Network.requestWillBeSent",p=>{if(!Fi(p.request.url))return;let f=this.state(s);f.cmpRequestAt===void 0&&(f.cmpRequestAt=Date.now(),f.roundAtCmpRequest=f.topAttempts)}));let{frameTree:u}=await t.send("Page.getFrameTree"),h=l((p,f)=>{d(p.frame.id,p.frame.url,f);for(let b of p.childFrames??[])h(b,!1)},"walk");h(u,e.isMain)},"initSession");async onMessage(e,t,s,o,i){let r;try{r=JSON.parse(i)}catch{return}let a=this.state(t),c=typeof r.url=="string"?r.url:"",d={page:t,frameId:o.frameId,url:c},u=typeof r.cmp=="string"?r.cmp:"";switch(r.type){case"init":{a.frames.add(o.frameId),o.mainFrame&&(a.topInitAt??=Date.now());let h={autoconsent:[],compact:Jd(or,{url:c,mainFrame:o.mainFrame})};await this.reply(e,s,{type:"initResp",config:this.config,rules:h});return}case"eval":await this.reply(e,s,{type:"evalResp",id:r.id,result:await this.runSnippet(e,t,s,o,r.snippetId)});return;case"cmpDetected":a.cmp??=u,a.detectedAt??=Date.now(),this.emit("cmpDetected",{...d,cmp:u});return;case"popupFound":a.cmp=u,a.popupAt??=Date.now(),this.emit("popupFound",{...d,cmp:u});return;case"optOutResult":a.cmp=u||a.cmp,a.optOut=r.result===!0,a.optOutAt=Date.now(),r.result===!0&&r.scheduleSelfTest===!0&&(a.selfTestTarget={s:e,contextId:s}),this.emit("optOutResult",{...d,cmp:u,result:r.result===!0});return;case"autoconsentDone":{a.cmp=u||a.cmp,a.doneAt=Date.now(),a.cosmetic=r.isCosmetic===!0,this.emit("autoconsentDone",{...d,cmp:u,cosmetic:a.cosmetic,durationMs:Number(r.duration)||0,clicks:Number(r.totalClicks)||0});let h=a.selfTestTarget;a.selfTestTarget=void 0,this.opts.selfTest!==!1&&h&&await this.reply(h.s,h.contextId,{type:"selfTest"});return}case"selfTestResult":a.selfTest=r.result===!0,this.emit("selfTestResult",{...d,cmp:u,result:a.selfTest});return;case"optInResult":this.emit("error",{...d,error:"unexpected optInResult",details:r});return;case"autoconsentError":this.emit("error",{...d,error:"autoconsent",details:r.details});return;case"pfRefusedClick":a.refused++,this.emit("error",{...d,error:`refused to click an accept button: "${String(r.text)}"`});return;case"report":{let h=r.state??{};if(!o.mainFrame||r.mainFrame!==!0)return;a.topLifecycle=h.lifecycle,a.topAttempts=Math.max(a.topAttempts,Number(h.findCmpAttempts)||0),h.heuristicPatterns?.length&&a.patternsAt===void 0&&(a.patternsAt=Date.now(),a.roundAtPatterns=a.topAttempts);return}default:return}}reply(e,t,s){return e.send("Runtime.evaluate",{contextId:t,expression:`autoconsentReceiveMessage(${JSON.stringify(s)})`,returnByValue:!0}).catch(()=>{})}async runSnippet(e,t,s,o,i){let r=typeof i=="string"?sr[i]:void 0;if(!r||Xd.has(i))return this.emit("error",{page:t,frameId:o.frameId,error:`refused eval snippet ${String(i)}`}),!1;let a=await e.send("Runtime.evaluate",{contextId:s,expression:"document",returnByValue:!1});if(!a.result.objectId)return!1;try{let{node:c}=await e.send("DOM.describeNode",{objectId:a.result.objectId}),{object:d}=await e.send("DOM.resolveNode",{backendNodeId:c.backendNodeId});if(!d.objectId)return!1;try{return(await e.send("Runtime.callFunctionOn",{objectId:d.objectId,functionDeclaration:`async function () { try { return !!(await (${r.toString()}).call(window)); } catch (e) { return false; } }`,returnByValue:!0,awaitPromise:!0})).result.value===!0}finally{e.send("Runtime.releaseObject",{objectId:d.objectId}).catch(()=>{})}}catch{return!1}finally{e.send("Runtime.releaseObject",{objectId:a.result.objectId}).catch(()=>{})}}state(e){let t=this.pages.get(e);return t||(t={navAt:Date.now(),url:e.url,cmp:null,refused:0,frames:new Set,topAttempts:0},this.pages.set(e,t)),t}reset(e,t){this.pages.set(e,{navAt:Date.now(),url:t,cmp:null,refused:0,frames:new Set,topAttempts:0})}emit(e,t){e==="error"&&this.emitter.listenerCount("error")===0||this.emitter.emit(e,t)}};var du=["cmpDetected","popupFound","optOutResult","autoconsentDone","selfTestResult","error"],uu=["blocked","error"];async function hn(n,e={}){let t=e.consent===!1?null:new Qt(typeof e.consent=="object"?e.consent:{}),s=e.adblock===!1?null:await Xt.create(typeof e.adblock=="object"?e.adblock:{}),o=[];if(e.onEvent){let r=e.onEvent;if(t)for(let a of du)o.push(t.on(a,(c=>r({source:"consent",type:a,data:c}))));if(s)for(let a of uu)o.push(s.on(a,(c=>r({source:"adblock",type:a,data:c}))))}let i=l(async r=>{await Promise.all([t?.initSession(r),s?.initSession(r)])},"init");return o.push(n.addSessionInitializer(i)),{consent:t,adblock:s,detach(){for(let r of o)r();t?.dispose(),s?.dispose()}}}l(hn,"attachInterrupts");var hu="pilotfish's open MCP makes no model calls: the MCP client's own model reads the page and decides the next step",pu=l(()=>{let n=l(async()=>{throw new Error(hu)},"refuse");return{messages:{create:n},beta:{messages:{create:n}}}},"noModelClient"),pn=class{static{l(this,"ConfirmThrough")}inner;canAsk;constructor(e,t){this.inner=e,this.canAsk=t}async check(e){let t=await this.inner.check(e);return t.kind!=="confirm"||this.canAsk()?t:{kind:"deny",reason:`${t.reason}. This needs a person's confirmation, and this MCP client cannot ask for one (no elicitation support)`}}},We=class{static{l(this,"BrowserSession")}config;opts;browser=null;launching=null;interrupts=null;tabs=null;agent=null;queue=Promise.resolve();policy;asker;constructor(e,t={}){this.config=e,this.opts=t,this.policy=new Ce({allowedHosts:e.allowedHosts,allowPrivateNetwork:e.allowPrivateNetwork})}get launched(){return!!this.browser&&!this.browser.closed}async page(){return await this.ensure(),this.tabs.current}get tabTable(){return this.tabs}async ensure(){return this.browser&&!this.browser.closed?this.browser:(this.launching??=this.start().finally(()=>{this.launching=null}),this.launching)}async start(){let e=await gs({...this.opts.launch,headless:this.config.headless});this.interrupts=await hn(e,{consent:!0,adblock:!0}).catch(()=>null);let t=e.allPages()[0]??await e.newPage();return this.tabs=new Ae(t),this.browser=e,e.on("disconnected",()=>{this.browser===e&&this.reset()}),e}reset(){this.agent?.dispose(),this.agent=null,this.tabs?.dispose(),this.tabs=null,this.interrupts?.detach(),this.interrupts=null,this.browser=null}executor(){return this.agent??=new ut(this.tabs.current,{tabs:this.tabs,client:pu(),secrets:this.config.secrets,policy:new pn(this.policy,()=>!!this.asker),consent:this.interrupts?.consent??void 0,allowScreenshots:this.config.allowScreenshots,askUser:l(e=>this.asker?.(e)??Promise.resolve(null),"askUser"),fastSettle:!0,enableQuery:!0,compactSnapshots:!0,autoDismiss:!0,awaitLoading:!0,actionSnapshotBand:0,snapshotMoreHint:"browser_scroll for the next screen, browser_get_text for the page's text, or browser_snapshot (whole_page) for every element"}),this.agent}async act(e,t,s={}){let o=this.queue.then(async()=>(await this.ensure(),this.executor().act(e,t,"",s)));return this.queue=o.catch(()=>{}),o}async obstacle(e={}){if(!this.launched)return null;let t=this.queue.then(()=>this.executor().obstacle(e));return this.queue=t.catch(()=>{}),t.catch(()=>null)}async close(){let e=this.browser??(this.launching?await this.launching.catch(()=>null):null);return e?(this.reset(),await e.close().catch(()=>{}),!0):!1}};import{McpServer as fu}from"@modelcontextprotocol/sdk/server/mcp.js";import{ListToolsRequestSchema as mu}from"@modelcontextprotocol/sdk/types.js";import{z as B}from"zod";var es="0.1.7";var ts=Ie.click.shape.ref.describe('From the latest snapshot, e.g. "e12" or "f1e3"'),ir=B.enum(["down","up","left","right"]),gu={click:["ref"],type:["ref","text","submit"],select:["ref","values"],press:["key"],scroll:["direction"],wait:["seconds"]},wu={click:1,type:2,select:2,press:1,scroll:1,wait:1},yu=B.object({action:B.enum(["click","type","select","press","scroll","wait"]).describe("click, select, type take ref; type: text (submit: Enter after); select: values; press: key; scroll: direction; wait: seconds"),ref:ts.optional(),text:B.string().max(2e4).optional(),submit:B.boolean().optional(),values:B.array(B.string()).min(1).max(50).optional(),key:B.string().min(1).max(40).optional(),direction:ir.optional(),seconds:B.number().min(.5).max(10).optional()}).strict().superRefine((n,e)=>{let t=gu[n.action];for(let s of t.slice(0,wu[n.action]))n[s]===void 0&&e.addIssue({code:"custom",path:[s],message:`${n.action} needs ${s}`});for(let s of Object.keys(n))s!=="action"&&!t.includes(s)&&e.addIssue({code:"custom",path:[s],message:`${s} is not a field of ${n.action} (it takes ${t.join(", ")})`})}),ne={browser_navigate:B.object({url:B.url({protocol:/^https?$/}).describe("Absolute http(s) URL"),snapshot:B.boolean().optional().describe("Default true. false: no page snapshot, only what happened (title, counts). Only when this same reply also reads the page with browser_query and you will not act on it; keep it for a page you have not seen or whose tabs, sorts, filters or forms you may use.")}).strict(),browser_snapshot:B.object({whole_page:B.boolean().optional()}).strict(),browser_click:B.object({ref:ts}).strict(),browser_type:B.object({ref:ts,text:B.string().max(2e4),submit:B.boolean().optional().describe("Press Enter afterwards")}).strict(),browser_select:B.object({ref:ts,values:B.array(B.string()).min(1).max(50)}).strict(),browser_press:B.object({key:B.string().min(1).max(40).describe('e.g. "Enter", "Escape", "Tab", "ArrowDown", "Control+a"')}).strict(),browser_scroll:B.object({direction:ir}).strict(),browser_screenshot:B.object({}).strict(),browser_get_text:B.object({max_chars:B.number().int().min(500).max(6e4).optional().describe("Default 20000. Ask for less when the start of the page is enough."),selector:B.string().min(1).max(300).optional().describe(`CSS selector: only the first match's text, e.g. "main" or "#results"`)}).strict(),browser_query:B.object({expression:B.string().min(1).max(4e3).describe("e.g. [...document.querySelectorAll('.result')].slice(0,10).map(e => e.innerText)")}).strict(),browser_find:B.object({query:B.string().min(1).max(300).describe('Words naming the element(s), e.g. "Sort by" or "price max input, Go button"')}).strict(),browser_wait:B.object({seconds:B.number().min(.5).max(10)}).strict(),browser_resume:B.object({timeout_s:B.number().int().min(5).max(900).optional().describe("Default 300")}).strict(),browser_actions:B.object({actions:B.array(yu).min(1).max(10)}).strict(),browser_tabs:B.object({switch_to:B.string().min(1).max(10).optional().describe('Tab id to work in from now on, e.g. "t2"')}).strict(),browser_close:B.object({}).strict()};function _e(n,e=!1){return{content:[{type:"text",text:n}],...e?{isError:!0}:{}}}l(_e,"text");function bu(n){let e=Object.keys(n.secrets);return["Words like cheapest, latest, highest-rated or most mean the site's own sort or tab for that order (a list's default order is usually something else, e.g. 'Best' or 'Featured'): apply it, then read the top.",e.length?`Secrets are typed as placeholders and never shown: ${e.map(t=>`{{${t}}}`).join(", ")}.`:"",n.allowedHosts.length?`Navigation is limited to: ${n.allowedHosts.join(", ")}.`:"","When a result says NEEDS A PERSON (a sign-in, a one-time code or 2FA, a device approval, a CAPTCHA), tell the user in your reply what the page needs and that the pilotfish browser window is open on it; when they have done it there, call browser_resume and carry on. BLOCKED and STOP mean the site cannot be continued that way."].filter(Boolean).join(`
|
|
415
415
|
`)}l(bu,"serverInstructions");function fn(n={}){let e=n.config??n.session?.config??wt(),t=!n.session,s=n.session??new We(e,n),o=new fu({name:"pilotfish",version:n.version??es},{capabilities:{logging:{}},instructions:bu(e)}),i=Object.keys(e.secrets),r=i.length?` Secrets: ${i.map(w=>`{{${w}}}`).join(", ")}.`:"",a=l(()=>!!o.server.getClientCapabilities()?.elicitation?.form,"canElicit"),c=l(w=>a()?async S=>{let E=await o.server.elicitInput({message:S,requestedSchema:{type:"object",properties:{answer:{type:"string",title:"Answer",description:'Reply "yes" to allow an action'}},required:["answer"]}},{relatedRequestId:w.requestId,timeout:e.interventionTimeoutMs}).catch(()=>null);return E?.action==="accept"&&typeof E.content?.answer=="string"?E.content.answer:null}:void 0,"askerFor"),d=l(w=>w.replace(/in the live view/g,"in the pilotfish browser window").replace(/Please send the code, or type it/,"Please type the code"),"forWindow"),u=l(w=>w.needs==="solve_in_live_view"||w.needs==="login_in_live_view"||w.needs==="code"||w.needs==="credentials","byHand"),h=l((w,S="")=>[`NEEDS A PERSON (${w.category}${w.vendor?`, ${w.vendor}`:""}): ${d(w.message)}`,S,u(w)&&e.headless?"This browser is headless, so it cannot be done by hand here: tell the user, and that the pilotfish server needs PILOTFISH_HEADLESS=0 (a visible window) for steps like this one.":`Tell the user now, in your reply: what the page needs, and that the pilotfish browser window is open on it (${w.url}). Ask them to do it there and to tell you when it is done. Then call browser_resume: it waits for the page to move on and returns it.`,"Do not try to get past it yourself: pilotfish does not type passwords or codes it was not given, and does not solve CAPTCHAs."].filter(Boolean).join(`
|
|
416
416
|
`),"needsPerson"),p=l(async()=>{let w=await s.act("read_page",{}).catch(()=>null);return w?w.text||w.summary:""},"pageNow"),f=l(async(w,S=1e3)=>{let E=Date.now()+w,$=await s.obstacle({fresh:!0});for(;$&&Date.now()<E;)await new Promise(g=>setTimeout(g,S)),$=await s.obstacle({fresh:!0});return $},"untilClear"),b=l((w,S)=>({...w,content:[...w.content,{type:"text",text:S}]}),"withNote"),k=l(async(w,S)=>{let E=await s.obstacle();if(!E)return S;if(E.autoResolvable&&!E.neverAutomate&&(E=await f(12e3),!E))return b(S,`A browser check was showing and cleared by itself. The page now:
|
|
417
417
|
${await p()}`);if(E.neverAutomate)return b(S,`STOP: ${E.host} shows a bot check, and this site is never automated past one (ticket sellers: the US BOTS Act; UIDAI: the Aadhaar Act). Do not continue on it; tell the user.`);if(E.category==="hard_block"||E.needs==="none_possible")return b(S,`BLOCKED: ${d(E.message)} A person cannot fix this from the browser window: try another way (another page or site), or tell the user.`);if(a()&&!(u(E)&&e.headless)){let $=await o.server.elicitInput({message:`${d(E.message)} (${E.url})`,requestedSchema:{type:"object",properties:{done:{type:"boolean",title:"I have done it in the pilotfish browser window"}},required:["done"]}},{relatedRequestId:w.requestId,timeout:e.interventionTimeoutMs}).catch(()=>null);if($?.action==="accept"&&$.content?.done!==!1){let g=await f(15e3);return g?b(S,h(g,"The person said it is done, but the page still shows it.")):b(S,`The person handled it. The page now:
|
|
@@ -419,12 +419,12 @@ ${await p()}`)}return b(S,h(E,$?"The person was asked in this client and decline
|
|
|
419
419
|
${S.note}${$.text}`:`the same as ${I}; its refs still work.${S.note?`
|
|
420
420
|
${S.note.trimEnd()}`:""}`;return[w.content,`${A} ${R}`].filter(Boolean).join(`
|
|
421
421
|
|
|
422
|
-
`)},"pageText"),C=l(async(w,S,E,$=!0,g={})=>{s.asker=c(w);let A=await s.act(S,E,g),I=
|
|
422
|
+
`)},"pageText"),C=l(async(w,S,E,$=!0,g={})=>{s.asker=c(w);let A=await s.act(S,E,g),I=_e(_(A),!A.ok);return $||S==="wait"||S==="read_page"?k(w,I):I},"direct"),N=new Map,M=l((w,S,E)=>{let $=o.registerTool(w,S,E);return N.set(w,$),$},"tool"),x={readOnlyHint:!0,destructiveHint:!1,openWorldHint:!0},T={readOnlyHint:!1,destructiveHint:!0,openWorldHint:!0};return M("browser_navigate",{title:"Open a URL",description:"Open an http(s) URL in the current tab. Returns evidence and a snapshot of the visible screen (elements carry refs like e12), with counts of what is above and below.",inputSchema:ne.browser_navigate,annotations:T},(w,S)=>C(S,"navigate",{url:w.url},!0,w.snapshot===!1?{snapshot:!1}:{})),M("browser_snapshot",{title:"Read the page",description:"The current page as a compact tree of headings, text and elements with refs (e12) to act on: three screens around the viewport, or everything with whole_page. Refs stay valid while their element is on the page.",inputSchema:ne.browser_snapshot,annotations:x},(w,S)=>C(S,"read_page",w.whole_page?{whole_page:!0}:{},!1)),M("browser_click",{title:"Click",description:"Click an element by ref. Refuses with a reason (obscured, stale, not visible) instead of clicking the wrong thing. Returns evidence of what changed.",inputSchema:ne.browser_click,annotations:T},(w,S)=>C(S,"click",{ref:w.ref})),M("browser_type",{title:"Type",description:`Type into an input, textarea or editable element by ref, replacing its text. Returns evidence.${r}`,inputSchema:ne.browser_type,annotations:T},(w,S)=>C(S,"type",{ref:w.ref,text:w.text,...w.submit?{submit:!0}:{}})),M("browser_select",{title:"Select options",description:"Choose option(s) of a <select> by label or value. Returns evidence.",inputSchema:ne.browser_select,annotations:T},(w,S)=>C(S,"select_option",{ref:w.ref,values:w.values})),M("browser_press",{title:"Press a key",description:"Press a key or shortcut on the focused element. Returns evidence.",inputSchema:ne.browser_press,annotations:T},(w,S)=>C(S,"press",{key:w.key})),M("browser_scroll",{title:"Scroll",description:"Scroll about one screen. Returns evidence and the newly visible elements.",inputSchema:ne.browser_scroll,annotations:{...x,readOnlyHint:!1,destructiveHint:!1}},(w,S)=>C(S,"scroll",{direction:w.direction},!1)),M("browser_screenshot",{title:"Screenshot",description:"JPEG of the current viewport. Prefer browser_snapshot (cheaper, has refs); use this when layout or images matter.",inputSchema:ne.browser_screenshot,annotations:x},async()=>{if(!e.allowScreenshots)return _e("Screenshots are off because secrets are configured (the image could show them). Set PILOTFISH_ALLOW_SCREENSHOTS=1 on the server to allow them.",!0);let w=await s.page(),S=await w.screenshot({format:"jpeg",quality:70}),E=w.browser.viewport;return{content:[{type:"image",data:S.toString("base64"),mimeType:"image/jpeg"},{type:"text",text:`Viewport ${E.width}x${E.height} CSS px. URL: ${w.url}`}]}}),M("browser_get_text",{title:"Page text",description:"Readable text of the page (PDFs too), secrets masked, without refs. To read a few values or a list, browser_query is far smaller.",inputSchema:ne.browser_get_text,annotations:x},(w,S)=>C(S,"get_text",{...w.max_chars?{max_chars:w.max_chars}:{},...w.selector?{selector:w.selector}:{}},!1)),M("browser_query",{title:"Read values with JavaScript",description:"Read just the values you need (prices, counts, titles, a results list) with a read-only JavaScript expression returning JSON (at most 4000 characters): the cheapest way to read, far smaller than browser_get_text or a snapshot. It runs in a world of its own where clicks, typing, submits and network writes are refused.",inputSchema:ne.browser_query,annotations:x},(w,S)=>C(S,"query",{expression:w.expression},!1)),M("browser_find",{title:"Find elements",description:"Refs of elements anywhere on the page, outside the visible screen too, by the words they show or are labelled with, best match first. Separate several targets by commas.",inputSchema:ne.browser_find,annotations:x},(w,S)=>C(S,"find",{query:w.query},!1)),M("browser_actions",{title:"Several actions in one call",description:"Several steps in order in one call, e.g. fill a form's fields and submit it; each gets the same checks as its own tool. Stops at the first that fails, or after one that moves the page to another address (later refs would belong to the old page). Returns a line per step and the evidence and visible screen after the last one run.",inputSchema:ne.browser_actions,annotations:T},async(w,S)=>{s.asker=c(S);let E=[],$=null,g=!1;for(let[A,I]of w.actions.entries()){let R=(await s.page()).lastDocumentAt,[F,H]=I.action==="click"?["click",{ref:I.ref}]:I.action==="type"?["type",{ref:I.ref,text:I.text,...I.submit?{submit:!0}:{}}]:I.action==="select"?["select_option",{ref:I.ref,values:I.values}]:I.action==="press"?["press",{key:I.key}]:I.action==="scroll"?["scroll",{direction:I.direction}]:["wait",{seconds:I.seconds}],O=await s.act(F,H);if(E.push(`${A+1}. ${O.ok?"":"FAILED "}${O.summary}`),$=O,!O.ok){g=!0,A<w.actions.length-1&&E.push(`Stopped: steps ${A+2}-${w.actions.length} were not run.`);break}let L=await s.page();if(L.lastDocumentAt!==R&&A<w.actions.length-1){E.push(`Stopped: the page moved to ${L.url}; steps ${A+2}-${w.actions.length} were not run (their refs belong to the previous page).`);break}}return k(S,_e(`${E.join(`
|
|
423
423
|
`)}
|
|
424
424
|
|
|
425
|
-
${$?_($):""}`,g))}),M("browser_resume",{title:"Continue after the person",description:"After NEEDS A PERSON, once the user was asked to do it in the pilotfish browser window (when they say it is done, or right after asking): waits until the page has moved on, then returns it.",inputSchema:ne.browser_resume,annotations:x},async w=>{if(!s.launched)return
|
|
426
|
-
${await p()}`)}),M("browser_wait",{title:"Wait",description:"Wait 0.5-10 seconds, then return what changed. Only for a page that is visibly still loading: every action already waits for the requests it started.",inputSchema:ne.browser_wait,annotations:x},(w,S)=>C(S,"wait",{seconds:w.seconds},!1)),M("browser_tabs",{title:"Tabs",description:"List the open tabs (the current one is marked). switch_to makes another tab current and returns its snapshot.",inputSchema:ne.browser_tabs,annotations:{...x,readOnlyHint:!1,destructiveHint:!1}},async(w,S)=>{if(w.switch_to)return C(S,"switch_tab",{tab:w.switch_to});await s.page();let E=s.tabTable?.describe()??"";return
|
|
427
|
-
`):"No open tabs.")}),M("browser_close",{title:"Close the browser",description:"Only to start over: closes the browser, and the next call starts a fresh one (cookies and logins are gone). It closes by itself when the client disconnects.",inputSchema:ne.browser_close,annotations:{readOnlyHint:!1,destructiveHint:!0,openWorldHint:!1}},async()=>
|
|
425
|
+
${$?_($):""}`,g))}),M("browser_resume",{title:"Continue after the person",description:"After NEEDS A PERSON, once the user was asked to do it in the pilotfish browser window (when they say it is done, or right after asking): waits until the page has moved on, then returns it.",inputSchema:ne.browser_resume,annotations:x},async w=>{if(!s.launched)return _e("No browser is open.",!0);let S=w.timeout_s??300,E=await f(S*1e3,1500);return _e(E?h(E,`Still waiting after ${S} s.`):`The page needs nobody now. The page:
|
|
426
|
+
${await p()}`)}),M("browser_wait",{title:"Wait",description:"Wait 0.5-10 seconds, then return what changed. Only for a page that is visibly still loading: every action already waits for the requests it started.",inputSchema:ne.browser_wait,annotations:x},(w,S)=>C(S,"wait",{seconds:w.seconds},!1)),M("browser_tabs",{title:"Tabs",description:"List the open tabs (the current one is marked). switch_to makes another tab current and returns its snapshot.",inputSchema:ne.browser_tabs,annotations:{...x,readOnlyHint:!1,destructiveHint:!1}},async(w,S)=>{if(w.switch_to)return C(S,"switch_tab",{tab:w.switch_to});await s.page();let E=s.tabTable?.describe()??"";return _e(E?E.split(" | ").join(`
|
|
427
|
+
`):"No open tabs.")}),M("browser_close",{title:"Close the browser",description:"Only to start over: closes the browser, and the next call starts a fresh one (cookies and logins are gone). It closes by itself when the client disconnects.",inputSchema:ne.browser_close,annotations:{readOnlyHint:!1,destructiveHint:!0,openWorldHint:!1}},async()=>_e(await s.close()?"Closed the browser.":"No browser was open.")),o.server.setRequestHandler(mu,()=>({tools:[...N].filter(([,w])=>w.enabled).map(([w,S])=>{let{$schema:E,...$}=B.toJSONSchema(S.inputSchema,{target:"draft-07",io:"input"});return{name:w,title:S.title,description:S.description,inputSchema:$,annotations:S.annotations,execution:S.execution,_meta:S._meta}})})),{server:o,session:s,async close(){await o.close().catch(()=>{}),t&&await s.close()}}}l(fn,"createMcpServer");var Tu=`pilotfish-mcp \u2014 pilotfish browser automation as an open MCP server
|
|
428
428
|
Your MCP client's own model drives the browser: no API key, no model calls here.
|
|
429
429
|
|
|
430
430
|
pilotfish-mcp serve over stdio (default)
|
package/package.json
CHANGED