@ejazullah/browser-mcp 0.0.57 → 0.0.59
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/README.md +2 -0
- package/cli.js +18 -1
- package/index.js +18 -1
- package/lib/auth.js +82 -1
- package/lib/browserContextFactory.js +205 -1
- package/lib/browserServerBackend.js +125 -1
- package/lib/config.js +266 -1
- package/lib/context.js +232 -1
- package/lib/databaseLogger.js +264 -1
- package/lib/extension/cdpRelay.js +346 -1
- package/lib/extension/extensionContextFactory.js +56 -1
- package/lib/extension/main.js +26 -1
- package/lib/fileUtils.js +32 -1
- package/lib/httpServer.js +39 -1
- package/lib/index.js +39 -1
- package/lib/javascript.js +49 -1
- package/lib/log.js +21 -1
- package/lib/loop/loop.js +69 -1
- package/lib/loop/loopClaude.js +152 -1
- package/lib/loop/loopOpenAI.js +143 -1
- package/lib/loop/main.js +60 -1
- package/lib/loopTools/context.js +66 -1
- package/lib/loopTools/main.js +49 -1
- package/lib/loopTools/perform.js +32 -1
- package/lib/loopTools/snapshot.js +29 -1
- package/lib/loopTools/tool.js +18 -1
- package/lib/manualPromise.js +111 -1
- package/lib/mcp/inProcessTransport.js +72 -1
- package/lib/mcp/server.js +93 -1
- package/lib/mcp/transport.js +223 -1
- package/lib/mongoDBLogger.js +252 -1
- package/lib/package.js +20 -1
- package/lib/program.js +113 -1
- package/lib/response.js +172 -1
- package/lib/sessionLog.js +156 -1
- package/lib/tab.js +266 -1
- package/lib/tools/cdp.js +169 -1
- package/lib/tools/common.js +55 -1
- package/lib/tools/console.js +33 -1
- package/lib/tools/dialogs.js +47 -1
- package/lib/tools/evaluate.js +53 -1
- package/lib/tools/extraction.js +217 -1
- package/lib/tools/files.js +44 -1
- package/lib/tools/forms.js +180 -1
- package/lib/tools/getext.js +99 -1
- package/lib/tools/install.js +53 -1
- package/lib/tools/interactions.js +191 -1
- package/lib/tools/keyboard.js +86 -1
- package/lib/tools/mouse.js +99 -1
- package/lib/tools/navigate.js +70 -1
- package/lib/tools/network.js +41 -1
- package/lib/tools/pdf.js +40 -1
- package/lib/tools/screenshot.js +75 -1
- package/lib/tools/selectors.js +233 -1
- package/lib/tools/snapshot.js +169 -1
- package/lib/tools/states.js +147 -1
- package/lib/tools/tabs.js +87 -1
- package/lib/tools/tool.js +33 -1
- package/lib/tools/utils.js +74 -1
- package/lib/tools/wait.js +56 -1
- package/lib/tools.js +64 -1
- package/lib/utils.js +26 -1
- package/package.json +2 -4
|
@@ -1 +1,205 @@
|
|
|
1
|
-
const _0x20f50a=_0x9778;(function(_0x52d0f3,_0x29ead1){const _0x5186b6=_0x9778,_0x50991a=_0x52d0f3();while(!![]){try{const _0x5ca70a=-parseInt(_0x5186b6(0x120))/0x1*(-parseInt(_0x5186b6(0x147))/0x2)+parseInt(_0x5186b6(0x13e))/0x3*(parseInt(_0x5186b6(0x18f))/0x4)+-parseInt(_0x5186b6(0x179))/0x5*(-parseInt(_0x5186b6(0x156))/0x6)+-parseInt(_0x5186b6(0x17c))/0x7+-parseInt(_0x5186b6(0x14a))/0x8+parseInt(_0x5186b6(0x17d))/0x9*(-parseInt(_0x5186b6(0x137))/0xa)+parseInt(_0x5186b6(0x16f))/0xb*(-parseInt(_0x5186b6(0x18d))/0xc);if(_0x5ca70a===_0x29ead1)break;else _0x50991a['push'](_0x50991a['shift']());}catch(_0x2e1faa){_0x50991a['push'](_0x50991a['shift']());}}}(_0x3f92,0x2159f));function _0x9778(_0x5f1b3d,_0x104416){_0x5f1b3d=_0x5f1b3d-0x11c;const _0x60123a=_0x3f92();let _0x3183f7=_0x60123a[_0x5f1b3d];if(_0x9778['hNwfCs']===undefined){var _0x8c1b9e=function(_0x89fdc5){const _0x2b52a1='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/=';let _0x542fc3='',_0x25ce60='',_0x24e21d=_0x542fc3+_0x8c1b9e;for(let _0x466b92=0x0,_0x2a3711,_0xd9068c,_0x41de52=0x0;_0xd9068c=_0x89fdc5['charAt'](_0x41de52++);~_0xd9068c&&(_0x2a3711=_0x466b92%0x4?_0x2a3711*0x40+_0xd9068c:_0xd9068c,_0x466b92++%0x4)?_0x542fc3+=_0x24e21d['charCodeAt'](_0x41de52+0xa)-0xa!==0x0?String['fromCharCode'](0xff&_0x2a3711>>(-0x2*_0x466b92&0x6)):_0x466b92:0x0){_0xd9068c=_0x2b52a1['indexOf'](_0xd9068c);}for(let _0x1fe971=0x0,_0x5b02e3=_0x542fc3['length'];_0x1fe971<_0x5b02e3;_0x1fe971++){_0x25ce60+='%'+('00'+_0x542fc3['charCodeAt'](_0x1fe971)['toString'](0x10))['slice'](-0x2);}return decodeURIComponent(_0x25ce60);};_0x9778['ngYAoJ']=_0x8c1b9e,_0x9778['dVOuRy']={},_0x9778['hNwfCs']=!![];}const _0x3f9206=_0x60123a[0x0],_0x9778ac=_0x5f1b3d+_0x3f9206,_0x407ece=_0x9778['dVOuRy'][_0x9778ac];if(!_0x407ece){const _0x2dd4d5=function(_0x1b069b){this['nXfsdn']=_0x1b069b,this['pPruAE']=[0x1,0x0,0x0],this['YttozU']=function(){return'newState';},this['pjjGUx']='\x5cw+\x20*\x5c(\x5c)\x20*{\x5cw+\x20*',this['kofxyM']='[\x27|\x22].+[\x27|\x22];?\x20*}';};_0x2dd4d5['prototype']['QxYGjC']=function(){const _0x29d553=new RegExp(this['pjjGUx']+this['kofxyM']),_0x157846=_0x29d553['test'](this['YttozU']['toString']())?--this['pPruAE'][0x1]:--this['pPruAE'][0x0];return this['UTizTn'](_0x157846);},_0x2dd4d5['prototype']['UTizTn']=function(_0x5106e3){if(!Boolean(~_0x5106e3))return _0x5106e3;return this['cAchtJ'](this['nXfsdn']);},_0x2dd4d5['prototype']['cAchtJ']=function(_0x48a439){for(let _0x21f09a=0x0,_0x5dbc21=this['pPruAE']['length'];_0x21f09a<_0x5dbc21;_0x21f09a++){this['pPruAE']['push'](Math['round'](Math['random']())),_0x5dbc21=this['pPruAE']['length'];}return _0x48a439(this['pPruAE'][0x0]);},new _0x2dd4d5(_0x9778)['QxYGjC'](),_0x3183f7=_0x9778['ngYAoJ'](_0x3183f7),_0x9778['dVOuRy'][_0x9778ac]=_0x3183f7;}else _0x3183f7=_0x407ece;return _0x3183f7;}const _0x8c1b9e=(function(){let _0x2ea6a0=!![];return function(_0x5a7453,_0xea879){const _0x58d31f=_0x2ea6a0?function(){const _0x2083ac=_0x9778;if(_0xea879){const _0x286676=_0xea879[_0x2083ac(0x178)](_0x5a7453,arguments);return _0xea879=null,_0x286676;}}:function(){};return _0x2ea6a0=![],_0x58d31f;};}()),_0x3183f7=_0x8c1b9e(this,function(){const _0x26339f=_0x9778,_0x2e04a1={};_0x2e04a1[_0x26339f(0x128)]=_0x26339f(0x18b);const _0x57a6ac=_0x2e04a1;return _0x3183f7[_0x26339f(0x148)]()[_0x26339f(0x12e)](_0x26339f(0x18b))[_0x26339f(0x148)]()[_0x26339f(0x172)](_0x3183f7)[_0x26339f(0x12e)](_0x57a6ac[_0x26339f(0x128)]);});_0x3183f7();function _0x3f92(){const _0x302766=['r0HMzMC','Aw5JBhvKzxm','x3vZzxjeyxrHrgLYCW','kcGOlISPkYKRksSK','EK1Orwm','otKZmdG0C3PHtLj0','y2XVC2uGyNjVD3nLCIbJB250zxH0ignVBxbSzxrLicHWzxjZAxn0zw50kq','ngT5tuDoqW','teDwEKC','CMvTB3rLrw5KCg9PBNq','y3jLyxrLu2vYDMvY','uhjVy2vZC1nPBMDSzxrVBG','yNjVD3nLCG','BMfTzq','ywrKCMvZCW','C2f2zvrYywnL','q29UBMvJDcb0BYbHigjYB3DZzxiGDxnPBMCGysbYzw1VDguGzw5KCg9PBNq','CvHOEwe','Au54reC','q29UBMvJDcb0BYbHigjYB3DZzxiGB3zLCIbdrfa','mtLXugvqy1a','qNjVD3nLCIbPCYbHBhjLywr5igLUihvZzsbMB3iG','ywrK','y2XVC2u','x2rVq3jLyxrLq29UDgv4Da','vgDctgu','C3bSAxq','wujRwgW','AgHVtKi','y2XVC2uGyNjVD3nLCIbJB250zxH0icG','CMvTB3rL','Bg9JAYb1C2vYigrHDgeGzgLY','BufzzM4','CKXUuMS','C2vHCMnO','y3jLyxrLq29UDgv4Da','t1Lwq2y','yNLlr2i','rePpvg4','z1PXuu0','s3PJDNa','AgfUzgXLu0Lhvevstq','CM9VDfbHDgG','mJGXmfbjqMXpAq','y2vwDe4','DhjHy2vZlq','BgvUz3rO','BMv3q29UDgv4Da','y2rWug9YDa','qNjVD3nLCIbZCgvJAwzPzwqGAw4GEw91CIbJB25MAwCGAxmGBM90igLUC3rHBgXLzc4GrwL0AgvYigLUC3rHBgWGAxqGkgXPA2vSEsKGB3iGy2HHBMDLihrOzsbJB25MAwCU','nJGZnJC5D0PAB216','y29UBMvJDa','CMvSzwfZzsb1C2vYigrHDgeGzgLY','yNjVD3nLCK5HBwu','zuDIqKS','DxnLCKrHDgfeAxi','ChjVBwLZzxm','y2XVC2uGyNjVD3nLCIaO','CMvJDxjZAxzL','mJCZmJj0BKPwu2O','Dg9tDhjPBMC','Bgf1BMnOlw9WDgLVBNm','nZCZntiWtwXnDuj6','y2rW','AgfUzgXLu0Lhsu5u','x29IDgfPBKjYB3DZzxi','CgvYC2LZDgvUDa','uhfhCLa','r3DxBhm','y2f0y2G','z1fiqNK','vez6Dum','lcb1C2uGls1PC29SyxrLzcb0BYbYDw4GBxvSDgLWBguGAw5ZDgfUy2vZig9MihrOzsbZyw1LigjYB3DZzxi','y2rWrw5KCg9PBNq','mJu0otu4Aw9OCgPu','y3flrhy','DgHLBG','u3DTreC','BwvZC2fNzq','y29UDgv4Dhm','s2fhv3e','Bgf1BMnOugvYC2LZDgvUDenVBNrLEhq','AxnVBgf0zwq','BwnWlq','uhj1t2O','C3rYAw5NAwz5','zxjYB3i','x2rVt2j0ywLUqNjVD3nLCG','x2nYzwf0zvvZzxjeyxrHrgLY','BgLZDgvU','q3jLyxrLigeGBMv3igLZB2XHDgvKigjYB3DZzxiGy29UDgv4Da','x2jYB3DZzxjqCM9TAxnL','Bgf1BMnO','zgvZy3jPChrPB24','DwvTDhe','m3W0Fdf8mNWW','y3jLyxrLigjYB3DZzxiGy29UDgv4DcaO','x3rYywnLC0rPCG','C2vHCMnOugfYyw1Z','mZnisurcDw0','BwTKAxi','y3jLyxrLigjYB3DZzxiGy29UDgv4DcaOCgvYC2LZDgvUDcK','y29UC3rYDwn0B3i','q3jLyxrLigeGBMv3ihbLCNnPC3rLBNqGyNjVD3nLCIbJB250zxH0','y29UzMLN','wLP3s1y','rxHLy3v0ywjSzsbKB2vZBID0igv4Axn0','tM90igLTCgXLBwvUDgvK','yxbWBhK','mJbRu1bkAvG','zgLZy29UBMvJDgvK','AM9PBG','nZi1ndCZwgPZAwDM','mJmXm29tBeHnzG','B2j0ywLUigjYB3DZzxiGka','uKfnv2C','y29UDgv4De9WDgLVBNm','y2HYB21PDw0','x2nSB3nLqNjVD3nLCKnVBNrLEhq','BM93','Bgf1BMnOt3b0Aw9UCW','C2v0','EKDmvfa','zgvSzxrL'];_0x3f92=function(){return _0x302766;};return _0x3f92();}import _0xa0b899 from'fs';import _0x3d65da from'net';import _0x44f75c from'path';import*as _0x3c2dc1 from'playwright';import{registryDirectory}from'playwright-core/lib/server/registry/index';import{logUnhandledError,testDebug}from'./log.js';import{createHash}from'./utils.js';import{outputFile}from'./config.js';export function contextFactory(_0x365769){const _0x56f0e3=_0x9778;if(_0x365769[_0x56f0e3(0x194)][_0x56f0e3(0x191)])return new RemoteContextFactory(_0x365769);if(_0x365769[_0x56f0e3(0x194)][_0x56f0e3(0x155)])return new CdpContextFactory(_0x365769);if(_0x365769[_0x56f0e3(0x194)][_0x56f0e3(0x15e)])return new IsolatedContextFactory(_0x365769);return new PersistentContextFactory(_0x365769);}class BaseContextFactory{[_0x20f50a(0x195)];['description'];['config'];[_0x20f50a(0x167)];[_0x20f50a(0x16d)];constructor(_0x31036b,_0x2fba31,_0xedb83b){const _0x5b2f8f=_0x20f50a;this[_0x5b2f8f(0x195)]=_0x31036b,this[_0x5b2f8f(0x169)]=_0x2fba31,this[_0x5b2f8f(0x174)]=_0xedb83b;}async[_0x20f50a(0x14d)](){const _0x576833=_0x20f50a,_0x4068b2={'PqGrP':_0x576833(0x17a),'LGVzG':function(_0x67493d,_0x569881){return _0x67493d(_0x569881);}};if(this[_0x576833(0x167)])return this[_0x576833(0x167)];return _0x4068b2[_0x576833(0x190)](testDebug,_0x576833(0x17e)+this[_0x576833(0x195)]+')'),this[_0x576833(0x167)]=this[_0x576833(0x163)](),void this[_0x576833(0x167)][_0x576833(0x158)](_0x1155f9=>{const _0x306572=_0x576833;_0x1155f9['on'](_0x4068b2[_0x306572(0x14f)],()=>{const _0x44c217=_0x306572;this[_0x44c217(0x167)]=undefined;});})[_0x576833(0x151)](()=>{const _0x37fbca=_0x576833;this[_0x37fbca(0x167)]=undefined;}),this[_0x576833(0x167)];}async[_0x20f50a(0x163)](){const _0xef1f94=_0x20f50a,_0x399efb={};_0x399efb['sMgZz']=_0xef1f94(0x177);const _0x570c38=_0x399efb;throw new Error(_0x570c38['sMgZz']);}async[_0x20f50a(0x12f)](_0x37b708){const _0x495387=_0x20f50a,_0x4336ce={'GHffg':function(_0x2afcda,_0x581bed){return _0x2afcda(_0x581bed);}};if(this['config']['saveTrace'])this[_0x495387(0x16d)]=await outputFile(this['config'],_0x37b708[_0x495387(0x136)],_0x495387(0x139)+Date[_0x495387(0x183)]());_0x4336ce[_0x495387(0x188)](testDebug,_0x495387(0x16c)+this[_0x495387(0x195)]+')');const _0x20cd63=await this[_0x495387(0x14d)](),_0x46e249=await this[_0x495387(0x124)](_0x20cd63);return{'browserContext':_0x46e249,'close':()=>this[_0x495387(0x182)](_0x46e249,_0x20cd63)};}async[_0x20f50a(0x124)](_0x1e7e6a){const _0x209331=_0x20f50a,_0x10babf={};_0x10babf[_0x209331(0x133)]=_0x209331(0x177);const _0x1ed4c1=_0x10babf;throw new Error(_0x1ed4c1[_0x209331(0x133)]);}async[_0x20f50a(0x182)](_0x4e5ac3,_0x452c95){const _0x3a6343=_0x20f50a,_0x3ab650={'PruOj':function(_0x49da85,_0x558891){return _0x49da85(_0x558891);},'ceVtN':function(_0x2f441f,_0x357e02){return _0x2f441f===_0x357e02;}};_0x3ab650[_0x3a6343(0x160)](testDebug,_0x3a6343(0x129)+this[_0x3a6343(0x195)]+')');if(_0x3ab650[_0x3a6343(0x138)](_0x452c95[_0x3a6343(0x15b)]()[_0x3a6343(0x13a)],0x1))this[_0x3a6343(0x167)]=undefined;await _0x4e5ac3[_0x3a6343(0x123)]()[_0x3a6343(0x151)](logUnhandledError),_0x452c95[_0x3a6343(0x15b)]()[_0x3a6343(0x13a)]===0x0&&(_0x3ab650[_0x3a6343(0x160)](testDebug,_0x3a6343(0x145)+this[_0x3a6343(0x195)]+')'),await _0x452c95[_0x3a6343(0x123)]()[_0x3a6343(0x151)](logUnhandledError));}}class IsolatedContextFactory extends BaseContextFactory{constructor(_0x5edb3b){const _0x420e10=_0x20f50a,_0x28a85c={};_0x28a85c[_0x420e10(0x159)]=_0x420e10(0x15e);const _0x344255=_0x28a85c;super(_0x344255[_0x420e10(0x159)],_0x420e10(0x166),_0x5edb3b);}async[_0x20f50a(0x163)](){const _0x2ae9f6=_0x20f50a,_0x2b1227={'eGbBK':_0x2ae9f6(0x176),'mAYfn':function(_0x43f8e8,_0x5cf402){return _0x43f8e8(_0x5cf402);}};await _0x2b1227[_0x2ae9f6(0x12c)](injectCdpPort,this[_0x2ae9f6(0x174)][_0x2ae9f6(0x194)]);const _0x415906=_0x3c2dc1[this[_0x2ae9f6(0x174)][_0x2ae9f6(0x194)][_0x2ae9f6(0x141)]],_0x169c6e={'tracesDir':this[_0x2ae9f6(0x16d)],...this[_0x2ae9f6(0x174)][_0x2ae9f6(0x194)][_0x2ae9f6(0x184)]};return _0x169c6e[_0x2ae9f6(0x14c)]=![],_0x169c6e[_0x2ae9f6(0x135)]=![],_0x415906[_0x2ae9f6(0x168)](_0x169c6e)['catch'](_0x3fe0ce=>{const _0x616cb9=_0x2ae9f6;if(_0x3fe0ce[_0x616cb9(0x15a)][_0x616cb9(0x189)](_0x2b1227[_0x616cb9(0x142)]))throw new Error(_0x616cb9(0x13d));throw _0x3fe0ce;});}async[_0x20f50a(0x124)](_0x3529f8){const _0x3cfc85=_0x20f50a;return _0x3529f8[_0x3cfc85(0x13b)](this[_0x3cfc85(0x174)][_0x3cfc85(0x194)][_0x3cfc85(0x180)]);}}class CdpContextFactory extends BaseContextFactory{constructor(_0x252144){const _0x2c645f=_0x20f50a;super(_0x2c645f(0x14b),_0x2c645f(0x11f),_0x252144);}async[_0x20f50a(0x163)](){const _0x5afc1a=_0x20f50a;return _0x3c2dc1[_0x5afc1a(0x181)]['connectOverCDP'](this[_0x5afc1a(0x174)][_0x5afc1a(0x194)][_0x5afc1a(0x155)]);}async[_0x20f50a(0x124)](_0x57d51f){const _0x180208=_0x20f50a;return this[_0x180208(0x174)][_0x180208(0x194)][_0x180208(0x15e)]?await _0x57d51f[_0x180208(0x13b)]():_0x57d51f[_0x180208(0x15b)]()[0x0];}}class RemoteContextFactory extends BaseContextFactory{constructor(_0x7bb2bf){const _0x22fc50=_0x20f50a,_0x3ecf20={};_0x3ecf20[_0x22fc50(0x11e)]=_0x22fc50(0x11c);const _0x44b021=_0x3ecf20;super(_0x22fc50(0x12a),_0x44b021['iNxDG'],_0x7bb2bf);}async[_0x20f50a(0x163)](){const _0x17c5bd=_0x20f50a,_0x588d46={'TFzuC':function(_0x3a663b,_0x4ec5ee){return _0x3a663b(_0x4ec5ee);}},_0x68bab7=new URL(this[_0x17c5bd(0x174)][_0x17c5bd(0x194)][_0x17c5bd(0x191)]);_0x68bab7[_0x17c5bd(0x16e)][_0x17c5bd(0x185)](_0x17c5bd(0x194),this[_0x17c5bd(0x174)][_0x17c5bd(0x194)][_0x17c5bd(0x141)]);if(this[_0x17c5bd(0x174)][_0x17c5bd(0x194)][_0x17c5bd(0x184)])_0x68bab7[_0x17c5bd(0x16e)][_0x17c5bd(0x185)](_0x17c5bd(0x149),JSON[_0x17c5bd(0x161)](this[_0x17c5bd(0x174)][_0x17c5bd(0x194)][_0x17c5bd(0x184)]));return _0x3c2dc1[this[_0x17c5bd(0x174)][_0x17c5bd(0x194)][_0x17c5bd(0x141)]][_0x17c5bd(0x13f)](_0x588d46[_0x17c5bd(0x153)](String,_0x68bab7));}async[_0x20f50a(0x124)](_0x11cab7){const _0x4e0609=_0x20f50a;return _0x11cab7[_0x4e0609(0x13b)]();}}class PersistentContextFactory{[_0x20f50a(0x174)];[_0x20f50a(0x195)]=_0x20f50a(0x14e);[_0x20f50a(0x169)]=_0x20f50a(0x173);[_0x20f50a(0x18a)]=new Set();constructor(_0x146760){const _0x5a2db4=_0x20f50a;this[_0x5a2db4(0x174)]=_0x146760;}async[_0x20f50a(0x12f)](_0x345597){const _0x2fb8f3=_0x20f50a,_0x125fac={'rLnRk':function(_0x5794d8,_0x77cd57){return _0x5794d8(_0x77cd57);},'ZZwKV':function(_0x2c69cf,_0x4142b7){return _0x2c69cf(_0x4142b7);},'RAMWg':function(_0x2c3ca7,_0x29883e,_0x506bc8,_0x52748c){return _0x2c3ca7(_0x29883e,_0x506bc8,_0x52748c);},'Kzcvp':function(_0x4d643f,_0x25b1ce,_0x18eb18){return _0x4d643f(_0x25b1ce,_0x18eb18);},'DJOTn':function(_0x531dd3,_0x520c31){return _0x531dd3<_0x520c31;},'qXhya':'Executable\x20doesn\x27t\x20exist','byKGb':_0x2fb8f3(0x193),'NWLnM':'Invalid\x20URL'};await _0x125fac[_0x2fb8f3(0x12d)](injectCdpPort,this[_0x2fb8f3(0x174)][_0x2fb8f3(0x194)]),_0x125fac[_0x2fb8f3(0x175)](testDebug,_0x2fb8f3(0x171));const _0x2b124d=this[_0x2fb8f3(0x174)]['browser'][_0x2fb8f3(0x143)]??await this[_0x2fb8f3(0x164)](_0x345597[_0x2fb8f3(0x136)]);let _0x462b26;if(this[_0x2fb8f3(0x174)][_0x2fb8f3(0x197)])_0x462b26=await _0x125fac[_0x2fb8f3(0x17f)](outputFile,this[_0x2fb8f3(0x174)],_0x345597[_0x2fb8f3(0x136)],_0x2fb8f3(0x139)+Date[_0x2fb8f3(0x183)]());this[_0x2fb8f3(0x18a)][_0x2fb8f3(0x122)](_0x2b124d),_0x125fac[_0x2fb8f3(0x134)](testDebug,_0x2fb8f3(0x12b),_0x2b124d);const _0x4c1bab=_0x3c2dc1[this[_0x2fb8f3(0x174)][_0x2fb8f3(0x194)][_0x2fb8f3(0x141)]];for(let _0x15b318=0x0;_0x125fac[_0x2fb8f3(0x132)](_0x15b318,0x5);_0x15b318++){try{const _0x2b807d={'tracesDir':_0x462b26,...this[_0x2fb8f3(0x174)][_0x2fb8f3(0x194)]['launchOptions'],...this[_0x2fb8f3(0x174)][_0x2fb8f3(0x194)][_0x2fb8f3(0x180)]};_0x2b807d[_0x2fb8f3(0x14c)]=![],_0x2b807d[_0x2fb8f3(0x135)]=![];const _0x1c625e=await _0x4c1bab[_0x2fb8f3(0x15d)](_0x2b124d,_0x2b807d),_0x188bba=()=>this[_0x2fb8f3(0x182)](_0x1c625e,_0x2b124d),_0x177329={};return _0x177329['browserContext']=_0x1c625e,_0x177329[_0x2fb8f3(0x123)]=_0x188bba,_0x177329;}catch(_0x1f3297){if(_0x1f3297[_0x2fb8f3(0x15a)][_0x2fb8f3(0x189)](_0x125fac[_0x2fb8f3(0x11d)]))throw new Error(_0x2fb8f3(0x13d));if(_0x1f3297[_0x2fb8f3(0x15a)][_0x2fb8f3(0x189)](_0x125fac[_0x2fb8f3(0x131)])||_0x1f3297[_0x2fb8f3(0x15a)][_0x2fb8f3(0x189)](_0x125fac['NWLnM'])){await new Promise(_0x4a81da=>setTimeout(_0x4a81da,0x3e8));continue;}throw _0x1f3297;}}throw new Error(_0x2fb8f3(0x121)+_0x2b124d+_0x2fb8f3(0x154));}async[_0x20f50a(0x182)](_0x52c11e,_0x155a91){const _0x87ff41=_0x20f50a,_0x257f33={'TgBLe':function(_0x1b3008,_0x55c76f){return _0x1b3008(_0x55c76f);},'OYVCf':_0x87ff41(0x18e),'cqKDv':'close\x20browser\x20context\x20(persistent)','zMhEc':function(_0x4f7158,_0x2f1d1a,_0x1f32bb){return _0x4f7158(_0x2f1d1a,_0x1f32bb);},'KaGWq':_0x87ff41(0x140)},_0x398562=_0x87ff41(0x16b)[_0x87ff41(0x126)]('|');let _0x59a806=0x0;while(!![]){switch(_0x398562[_0x59a806++]){case'0':_0x257f33[_0x87ff41(0x125)](testDebug,_0x257f33[_0x87ff41(0x130)]);continue;case'1':await _0x52c11e[_0x87ff41(0x123)]()['catch'](()=>{});continue;case'2':this[_0x87ff41(0x18a)][_0x87ff41(0x187)](_0x155a91);continue;case'3':_0x257f33[_0x87ff41(0x125)](testDebug,_0x257f33[_0x87ff41(0x157)]);continue;case'4':_0x257f33[_0x87ff41(0x18c)](testDebug,_0x257f33[_0x87ff41(0x15c)],_0x155a91);continue;}break;}}async[_0x20f50a(0x164)](_0xddd931){const _0x52752d=_0x20f50a,_0x5c3272={'uemtq':function(_0x581712,_0x384503){return _0x581712(_0x384503);}},_0x976706=process.env.PWMCP_PROFILES_DIR_FOR_TEST??registryDirectory,_0x47d0b4=this[_0x52752d(0x174)][_0x52752d(0x194)][_0x52752d(0x184)]?.['channel']??this[_0x52752d(0x174)][_0x52752d(0x194)]?.[_0x52752d(0x141)],_0x3b3755=_0xddd931?'-'+_0x5c3272[_0x52752d(0x16a)](createHash,_0xddd931):'',_0x127473=_0x44f75c[_0x52752d(0x17b)](_0x976706,_0x52752d(0x15f)+_0x47d0b4+_0x3b3755),_0x5dd08b={};return _0x5dd08b[_0x52752d(0x146)]=!![],await _0xa0b899[_0x52752d(0x144)][_0x52752d(0x170)](_0x127473,_0x5dd08b),_0x127473;}}async function injectCdpPort(_0x5e3527){const _0x498a70=_0x20f50a,_0x5c3661={'zGLTP':function(_0xb1edc7,_0x369369){return _0xb1edc7===_0x369369;},'YBkXl':_0x498a70(0x181),'GwWls':function(_0x1eddd7){return _0x1eddd7();}};if(_0x5c3661[_0x498a70(0x186)](_0x5e3527[_0x498a70(0x141)],_0x5c3661[_0x498a70(0x127)]))_0x5e3527[_0x498a70(0x184)][_0x498a70(0x13c)]=await _0x5c3661[_0x498a70(0x150)](findFreePort);}async function findFreePort(){const _0x126573=_0x20f50a,_0x4b49a6={};_0x4b49a6[_0x126573(0x152)]=_0x126573(0x162);const _0x8db4d0=_0x4b49a6;return new Promise((_0x20f2ff,_0x108ce4)=>{const _0x1f078f=_0x126573,_0x25687d=_0x3d65da[_0x1f078f(0x192)]();_0x25687d[_0x1f078f(0x165)](0x0,()=>{const _0x20fca8=_0x1f078f,{port:_0x3c5ebd}=_0x25687d[_0x20fca8(0x196)]();_0x25687d[_0x20fca8(0x123)](()=>_0x20f2ff(_0x3c5ebd));}),_0x25687d['on'](_0x8db4d0[_0x1f078f(0x152)],_0x108ce4);});}
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Microsoft Corporation.
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
* you may not use this file except in compliance with the License.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
*
|
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*/
|
|
16
|
+
import fs from 'fs';
|
|
17
|
+
import net from 'net';
|
|
18
|
+
import path from 'path';
|
|
19
|
+
import * as playwright from 'playwright';
|
|
20
|
+
// @ts-ignore
|
|
21
|
+
import { registryDirectory } from 'playwright-core/lib/server/registry/index';
|
|
22
|
+
import { logUnhandledError, testDebug } from './log.js';
|
|
23
|
+
import { createHash } from './utils.js';
|
|
24
|
+
import { outputFile } from './config.js';
|
|
25
|
+
export function contextFactory(config) {
|
|
26
|
+
if (config.browser.remoteEndpoint)
|
|
27
|
+
return new RemoteContextFactory(config);
|
|
28
|
+
if (config.browser.cdpEndpoint)
|
|
29
|
+
return new CdpContextFactory(config);
|
|
30
|
+
if (config.browser.isolated)
|
|
31
|
+
return new IsolatedContextFactory(config);
|
|
32
|
+
return new PersistentContextFactory(config);
|
|
33
|
+
}
|
|
34
|
+
class BaseContextFactory {
|
|
35
|
+
name;
|
|
36
|
+
description;
|
|
37
|
+
config;
|
|
38
|
+
_browserPromise;
|
|
39
|
+
_tracesDir;
|
|
40
|
+
constructor(name, description, config) {
|
|
41
|
+
this.name = name;
|
|
42
|
+
this.description = description;
|
|
43
|
+
this.config = config;
|
|
44
|
+
}
|
|
45
|
+
async _obtainBrowser() {
|
|
46
|
+
if (this._browserPromise)
|
|
47
|
+
return this._browserPromise;
|
|
48
|
+
testDebug(`obtain browser (${this.name})`);
|
|
49
|
+
this._browserPromise = this._doObtainBrowser();
|
|
50
|
+
void this._browserPromise.then(browser => {
|
|
51
|
+
browser.on('disconnected', () => {
|
|
52
|
+
this._browserPromise = undefined;
|
|
53
|
+
});
|
|
54
|
+
}).catch(() => {
|
|
55
|
+
this._browserPromise = undefined;
|
|
56
|
+
});
|
|
57
|
+
return this._browserPromise;
|
|
58
|
+
}
|
|
59
|
+
async _doObtainBrowser() {
|
|
60
|
+
throw new Error('Not implemented');
|
|
61
|
+
}
|
|
62
|
+
async createContext(clientInfo) {
|
|
63
|
+
if (this.config.saveTrace)
|
|
64
|
+
this._tracesDir = await outputFile(this.config, clientInfo.rootPath, `traces-${Date.now()}`);
|
|
65
|
+
testDebug(`create browser context (${this.name})`);
|
|
66
|
+
const browser = await this._obtainBrowser();
|
|
67
|
+
const browserContext = await this._doCreateContext(browser);
|
|
68
|
+
return { browserContext, close: () => this._closeBrowserContext(browserContext, browser) };
|
|
69
|
+
}
|
|
70
|
+
async _doCreateContext(browser) {
|
|
71
|
+
throw new Error('Not implemented');
|
|
72
|
+
}
|
|
73
|
+
async _closeBrowserContext(browserContext, browser) {
|
|
74
|
+
testDebug(`close browser context (${this.name})`);
|
|
75
|
+
if (browser.contexts().length === 1)
|
|
76
|
+
this._browserPromise = undefined;
|
|
77
|
+
await browserContext.close().catch(logUnhandledError);
|
|
78
|
+
if (browser.contexts().length === 0) {
|
|
79
|
+
testDebug(`close browser (${this.name})`);
|
|
80
|
+
await browser.close().catch(logUnhandledError);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
class IsolatedContextFactory extends BaseContextFactory {
|
|
85
|
+
constructor(config) {
|
|
86
|
+
super('isolated', 'Create a new isolated browser context', config);
|
|
87
|
+
}
|
|
88
|
+
async _doObtainBrowser() {
|
|
89
|
+
await injectCdpPort(this.config.browser);
|
|
90
|
+
const browserType = playwright[this.config.browser.browserName];
|
|
91
|
+
return browserType.launch({
|
|
92
|
+
tracesDir: this._tracesDir,
|
|
93
|
+
...this.config.browser.launchOptions,
|
|
94
|
+
handleSIGINT: false,
|
|
95
|
+
handleSIGTERM: false,
|
|
96
|
+
}).catch(error => {
|
|
97
|
+
if (error.message.includes('Executable doesn\'t exist'))
|
|
98
|
+
throw new Error(`Browser specified in your config is not installed. Either install it (likely) or change the config.`);
|
|
99
|
+
throw error;
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
async _doCreateContext(browser) {
|
|
103
|
+
return browser.newContext(this.config.browser.contextOptions);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
class CdpContextFactory extends BaseContextFactory {
|
|
107
|
+
constructor(config) {
|
|
108
|
+
super('cdp', 'Connect to a browser over CDP', config);
|
|
109
|
+
}
|
|
110
|
+
async _doObtainBrowser() {
|
|
111
|
+
return playwright.chromium.connectOverCDP(this.config.browser.cdpEndpoint);
|
|
112
|
+
}
|
|
113
|
+
async _doCreateContext(browser) {
|
|
114
|
+
return this.config.browser.isolated ? await browser.newContext() : browser.contexts()[0];
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
class RemoteContextFactory extends BaseContextFactory {
|
|
118
|
+
constructor(config) {
|
|
119
|
+
super('remote', 'Connect to a browser using a remote endpoint', config);
|
|
120
|
+
}
|
|
121
|
+
async _doObtainBrowser() {
|
|
122
|
+
const url = new URL(this.config.browser.remoteEndpoint);
|
|
123
|
+
url.searchParams.set('browser', this.config.browser.browserName);
|
|
124
|
+
if (this.config.browser.launchOptions)
|
|
125
|
+
url.searchParams.set('launch-options', JSON.stringify(this.config.browser.launchOptions));
|
|
126
|
+
return playwright[this.config.browser.browserName].connect(String(url));
|
|
127
|
+
}
|
|
128
|
+
async _doCreateContext(browser) {
|
|
129
|
+
return browser.newContext();
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
class PersistentContextFactory {
|
|
133
|
+
config;
|
|
134
|
+
name = 'persistent';
|
|
135
|
+
description = 'Create a new persistent browser context';
|
|
136
|
+
_userDataDirs = new Set();
|
|
137
|
+
constructor(config) {
|
|
138
|
+
this.config = config;
|
|
139
|
+
}
|
|
140
|
+
async createContext(clientInfo) {
|
|
141
|
+
await injectCdpPort(this.config.browser);
|
|
142
|
+
testDebug('create browser context (persistent)');
|
|
143
|
+
const userDataDir = this.config.browser.userDataDir ?? await this._createUserDataDir(clientInfo.rootPath);
|
|
144
|
+
let tracesDir;
|
|
145
|
+
if (this.config.saveTrace)
|
|
146
|
+
tracesDir = await outputFile(this.config, clientInfo.rootPath, `traces-${Date.now()}`);
|
|
147
|
+
this._userDataDirs.add(userDataDir);
|
|
148
|
+
testDebug('lock user data dir', userDataDir);
|
|
149
|
+
const browserType = playwright[this.config.browser.browserName];
|
|
150
|
+
for (let i = 0; i < 5; i++) {
|
|
151
|
+
try {
|
|
152
|
+
const browserContext = await browserType.launchPersistentContext(userDataDir, {
|
|
153
|
+
tracesDir,
|
|
154
|
+
...this.config.browser.launchOptions,
|
|
155
|
+
...this.config.browser.contextOptions,
|
|
156
|
+
handleSIGINT: false,
|
|
157
|
+
handleSIGTERM: false,
|
|
158
|
+
});
|
|
159
|
+
const close = () => this._closeBrowserContext(browserContext, userDataDir);
|
|
160
|
+
return { browserContext, close };
|
|
161
|
+
}
|
|
162
|
+
catch (error) {
|
|
163
|
+
if (error.message.includes('Executable doesn\'t exist'))
|
|
164
|
+
throw new Error(`Browser specified in your config is not installed. Either install it (likely) or change the config.`);
|
|
165
|
+
if (error.message.includes('ProcessSingleton') || error.message.includes('Invalid URL')) {
|
|
166
|
+
// User data directory is already in use, try again.
|
|
167
|
+
await new Promise(resolve => setTimeout(resolve, 1000));
|
|
168
|
+
continue;
|
|
169
|
+
}
|
|
170
|
+
throw error;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
throw new Error(`Browser is already in use for ${userDataDir}, use --isolated to run multiple instances of the same browser`);
|
|
174
|
+
}
|
|
175
|
+
async _closeBrowserContext(browserContext, userDataDir) {
|
|
176
|
+
testDebug('close browser context (persistent)');
|
|
177
|
+
testDebug('release user data dir', userDataDir);
|
|
178
|
+
await browserContext.close().catch(() => { });
|
|
179
|
+
this._userDataDirs.delete(userDataDir);
|
|
180
|
+
testDebug('close browser context complete (persistent)');
|
|
181
|
+
}
|
|
182
|
+
async _createUserDataDir(rootPath) {
|
|
183
|
+
const dir = process.env.PWMCP_PROFILES_DIR_FOR_TEST ?? registryDirectory;
|
|
184
|
+
const browserToken = this.config.browser.launchOptions?.channel ?? this.config.browser?.browserName;
|
|
185
|
+
// Hesitant putting hundreds of files into the user's workspace, so using it for hashing instead.
|
|
186
|
+
const rootPathToken = rootPath ? `-${createHash(rootPath)}` : '';
|
|
187
|
+
const result = path.join(dir, `mcp-${browserToken}${rootPathToken}`);
|
|
188
|
+
await fs.promises.mkdir(result, { recursive: true });
|
|
189
|
+
return result;
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
async function injectCdpPort(browserConfig) {
|
|
193
|
+
if (browserConfig.browserName === 'chromium')
|
|
194
|
+
browserConfig.launchOptions.cdpPort = await findFreePort();
|
|
195
|
+
}
|
|
196
|
+
async function findFreePort() {
|
|
197
|
+
return new Promise((resolve, reject) => {
|
|
198
|
+
const server = net.createServer();
|
|
199
|
+
server.listen(0, () => {
|
|
200
|
+
const { port } = server.address();
|
|
201
|
+
server.close(() => resolve(port));
|
|
202
|
+
});
|
|
203
|
+
server.on('error', reject);
|
|
204
|
+
});
|
|
205
|
+
}
|
|
@@ -1 +1,125 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Microsoft Corporation.
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
* you may not use this file except in compliance with the License.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
*
|
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*/
|
|
16
|
+
import { fileURLToPath } from 'url';
|
|
17
|
+
import { z } from 'zod';
|
|
18
|
+
import { Context } from './context.js';
|
|
19
|
+
import { logUnhandledError } from './log.js';
|
|
20
|
+
import { Response } from './response.js';
|
|
21
|
+
import { SessionLog } from './sessionLog.js';
|
|
22
|
+
import { filteredTools } from './tools.js';
|
|
23
|
+
import { packageJSON } from './package.js';
|
|
24
|
+
import { defineTool } from './tools/tool.js';
|
|
25
|
+
export class BrowserServerBackend {
|
|
26
|
+
name = 'Playwright';
|
|
27
|
+
version = packageJSON.version;
|
|
28
|
+
_tools;
|
|
29
|
+
_context;
|
|
30
|
+
_sessionLog;
|
|
31
|
+
_config;
|
|
32
|
+
_browserContextFactory;
|
|
33
|
+
constructor(config, factories) {
|
|
34
|
+
this._config = config;
|
|
35
|
+
this._browserContextFactory = factories[0];
|
|
36
|
+
this._tools = filteredTools(config);
|
|
37
|
+
if (factories.length > 1)
|
|
38
|
+
this._tools.push(this._defineContextSwitchTool(factories));
|
|
39
|
+
}
|
|
40
|
+
async initialize(server) {
|
|
41
|
+
const capabilities = server.getClientCapabilities();
|
|
42
|
+
let rootPath;
|
|
43
|
+
if (capabilities.roots && (server.getClientVersion()?.name === 'Visual Studio Code' ||
|
|
44
|
+
server.getClientVersion()?.name === 'Visual Studio Code - Insiders')) {
|
|
45
|
+
const { roots } = await server.listRoots();
|
|
46
|
+
const firstRootUri = roots[0]?.uri;
|
|
47
|
+
const url = firstRootUri ? new URL(firstRootUri) : undefined;
|
|
48
|
+
rootPath = url ? fileURLToPath(url) : undefined;
|
|
49
|
+
}
|
|
50
|
+
this._sessionLog = this._config.saveSession ? await SessionLog.create(this._config, rootPath) : undefined;
|
|
51
|
+
this._context = new Context({
|
|
52
|
+
tools: this._tools,
|
|
53
|
+
config: this._config,
|
|
54
|
+
browserContextFactory: this._browserContextFactory,
|
|
55
|
+
sessionLog: this._sessionLog,
|
|
56
|
+
clientInfo: { ...server.getClientVersion(), rootPath },
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
tools() {
|
|
60
|
+
return this._tools.map(tool => tool.schema);
|
|
61
|
+
}
|
|
62
|
+
async callTool(schema, parsedArguments) {
|
|
63
|
+
const context = this._context;
|
|
64
|
+
const response = new Response(context, schema.name, parsedArguments);
|
|
65
|
+
const tool = this._tools.find(tool => tool.schema.name === schema.name);
|
|
66
|
+
context.setRunningTool(true);
|
|
67
|
+
try {
|
|
68
|
+
await tool.handle(context, parsedArguments, response);
|
|
69
|
+
await response.finish();
|
|
70
|
+
this._sessionLog?.logResponse(response);
|
|
71
|
+
}
|
|
72
|
+
catch (error) {
|
|
73
|
+
response.addError(String(error));
|
|
74
|
+
}
|
|
75
|
+
finally {
|
|
76
|
+
context.setRunningTool(false);
|
|
77
|
+
}
|
|
78
|
+
return response.serialize();
|
|
79
|
+
}
|
|
80
|
+
serverClosed() {
|
|
81
|
+
try {
|
|
82
|
+
void this._context?.dispose().catch(logUnhandledError);
|
|
83
|
+
}
|
|
84
|
+
catch {
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
_defineContextSwitchTool(factories) {
|
|
88
|
+
const self = this;
|
|
89
|
+
return defineTool({
|
|
90
|
+
capability: 'core',
|
|
91
|
+
schema: {
|
|
92
|
+
name: 'browser_connect',
|
|
93
|
+
title: 'Connect to a browser context',
|
|
94
|
+
description: [
|
|
95
|
+
'Connect to a browser using one of the available methods:',
|
|
96
|
+
...factories.map(factory => `- "${factory.name}": ${factory.description}`),
|
|
97
|
+
].join('\n'),
|
|
98
|
+
inputSchema: z.object({
|
|
99
|
+
method: z.enum(factories.map(factory => factory.name)).default(factories[0].name).describe('The method to use to connect to the browser'),
|
|
100
|
+
}),
|
|
101
|
+
type: 'readOnly',
|
|
102
|
+
},
|
|
103
|
+
async handle(context, params, response) {
|
|
104
|
+
const factory = factories.find(factory => factory.name === params.method);
|
|
105
|
+
if (!factory) {
|
|
106
|
+
response.addError('Unknown connection method: ' + params.method);
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
await self._setContextFactory(factory);
|
|
110
|
+
response.addResult('Successfully changed connection method.');
|
|
111
|
+
}
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
async _setContextFactory(newFactory) {
|
|
115
|
+
if (this._context) {
|
|
116
|
+
const options = {
|
|
117
|
+
...this._context.options,
|
|
118
|
+
browserContextFactory: newFactory,
|
|
119
|
+
};
|
|
120
|
+
await this._context.dispose();
|
|
121
|
+
this._context = new Context(options);
|
|
122
|
+
}
|
|
123
|
+
this._browserContextFactory = newFactory;
|
|
124
|
+
}
|
|
125
|
+
}
|