mirror of
https://github.com/microsoft/playwright-mcp.git
synced 2026-01-29 22:12:04 +00:00
chore: add "playwright-cli" binary (#1330)
This commit is contained in:
500
package-lock.json
generated
500
package-lock.json
generated
@@ -299,431 +299,6 @@
|
||||
"node": ">=6.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/aix-ppc64": {
|
||||
"version": "0.24.2",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.24.2.tgz",
|
||||
"integrity": "sha512-thpVCb/rhxE/BnMLQ7GReQLLN8q9qbHmI55F4489/ByVg2aQaQ6kbcLb6FHkocZzQhxc4gx0sCk0tJkKBFzDhA==",
|
||||
"cpu": [
|
||||
"ppc64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"aix"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/android-arm": {
|
||||
"version": "0.24.2",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.24.2.tgz",
|
||||
"integrity": "sha512-tmwl4hJkCfNHwFB3nBa8z1Uy3ypZpxqxfTQOcHX+xRByyYgunVbZ9MzUUfb0RxaHIMnbHagwAxuTL+tnNM+1/Q==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"android"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/android-arm64": {
|
||||
"version": "0.24.2",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.24.2.tgz",
|
||||
"integrity": "sha512-cNLgeqCqV8WxfcTIOeL4OAtSmL8JjcN6m09XIgro1Wi7cF4t/THaWEa7eL5CMoMBdjoHOTh/vwTO/o2TRXIyzg==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"android"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/android-x64": {
|
||||
"version": "0.24.2",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.24.2.tgz",
|
||||
"integrity": "sha512-B6Q0YQDqMx9D7rvIcsXfmJfvUYLoP722bgfBlO5cGvNVb5V/+Y7nhBE3mHV9OpxBf4eAS2S68KZztiPaWq4XYw==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"android"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/darwin-arm64": {
|
||||
"version": "0.24.2",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.24.2.tgz",
|
||||
"integrity": "sha512-kj3AnYWc+CekmZnS5IPu9D+HWtUI49hbnyqk0FLEJDbzCIQt7hg7ucF1SQAilhtYpIujfaHr6O0UHlzzSPdOeA==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/darwin-x64": {
|
||||
"version": "0.24.2",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.24.2.tgz",
|
||||
"integrity": "sha512-WeSrmwwHaPkNR5H3yYfowhZcbriGqooyu3zI/3GGpF8AyUdsrrP0X6KumITGA9WOyiJavnGZUwPGvxvwfWPHIA==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/freebsd-arm64": {
|
||||
"version": "0.24.2",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.24.2.tgz",
|
||||
"integrity": "sha512-UN8HXjtJ0k/Mj6a9+5u6+2eZ2ERD7Edt1Q9IZiB5UZAIdPnVKDoG7mdTVGhHJIeEml60JteamR3qhsr1r8gXvg==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"freebsd"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/freebsd-x64": {
|
||||
"version": "0.24.2",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.24.2.tgz",
|
||||
"integrity": "sha512-TvW7wE/89PYW+IevEJXZ5sF6gJRDY/14hyIGFXdIucxCsbRmLUcjseQu1SyTko+2idmCw94TgyaEZi9HUSOe3Q==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"freebsd"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-arm": {
|
||||
"version": "0.24.2",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.24.2.tgz",
|
||||
"integrity": "sha512-n0WRM/gWIdU29J57hJyUdIsk0WarGd6To0s+Y+LwvlC55wt+GT/OgkwoXCXvIue1i1sSNWblHEig00GBWiJgfA==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-arm64": {
|
||||
"version": "0.24.2",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.24.2.tgz",
|
||||
"integrity": "sha512-7HnAD6074BW43YvvUmE/35Id9/NB7BeX5EoNkK9obndmZBUk8xmJJeU7DwmUeN7tkysslb2eSl6CTrYz6oEMQg==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-ia32": {
|
||||
"version": "0.24.2",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.24.2.tgz",
|
||||
"integrity": "sha512-sfv0tGPQhcZOgTKO3oBE9xpHuUqguHvSo4jl+wjnKwFpapx+vUDcawbwPNuBIAYdRAvIDBfZVvXprIj3HA+Ugw==",
|
||||
"cpu": [
|
||||
"ia32"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-loong64": {
|
||||
"version": "0.24.2",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.24.2.tgz",
|
||||
"integrity": "sha512-CN9AZr8kEndGooS35ntToZLTQLHEjtVB5n7dl8ZcTZMonJ7CCfStrYhrzF97eAecqVbVJ7APOEe18RPI4KLhwQ==",
|
||||
"cpu": [
|
||||
"loong64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-mips64el": {
|
||||
"version": "0.24.2",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.24.2.tgz",
|
||||
"integrity": "sha512-iMkk7qr/wl3exJATwkISxI7kTcmHKE+BlymIAbHO8xanq/TjHaaVThFF6ipWzPHryoFsesNQJPE/3wFJw4+huw==",
|
||||
"cpu": [
|
||||
"mips64el"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-ppc64": {
|
||||
"version": "0.24.2",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.24.2.tgz",
|
||||
"integrity": "sha512-shsVrgCZ57Vr2L8mm39kO5PPIb+843FStGt7sGGoqiiWYconSxwTiuswC1VJZLCjNiMLAMh34jg4VSEQb+iEbw==",
|
||||
"cpu": [
|
||||
"ppc64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-riscv64": {
|
||||
"version": "0.24.2",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.24.2.tgz",
|
||||
"integrity": "sha512-4eSFWnU9Hhd68fW16GD0TINewo1L6dRrB+oLNNbYyMUAeOD2yCK5KXGK1GH4qD/kT+bTEXjsyTCiJGHPZ3eM9Q==",
|
||||
"cpu": [
|
||||
"riscv64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-s390x": {
|
||||
"version": "0.24.2",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.24.2.tgz",
|
||||
"integrity": "sha512-S0Bh0A53b0YHL2XEXC20bHLuGMOhFDO6GN4b3YjRLK//Ep3ql3erpNcPlEFed93hsQAjAQDNsvcK+hV90FubSw==",
|
||||
"cpu": [
|
||||
"s390x"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-x64": {
|
||||
"version": "0.24.2",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.24.2.tgz",
|
||||
"integrity": "sha512-8Qi4nQcCTbLnK9WoMjdC9NiTG6/E38RNICU6sUNqK0QFxCYgoARqVqxdFmWkdonVsvGqWhmm7MO0jyTqLqwj0Q==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/netbsd-arm64": {
|
||||
"version": "0.24.2",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.24.2.tgz",
|
||||
"integrity": "sha512-wuLK/VztRRpMt9zyHSazyCVdCXlpHkKm34WUyinD2lzK07FAHTq0KQvZZlXikNWkDGoT6x3TD51jKQ7gMVpopw==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"netbsd"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/netbsd-x64": {
|
||||
"version": "0.24.2",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.24.2.tgz",
|
||||
"integrity": "sha512-VefFaQUc4FMmJuAxmIHgUmfNiLXY438XrL4GDNV1Y1H/RW3qow68xTwjZKfj/+Plp9NANmzbH5R40Meudu8mmw==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"netbsd"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/openbsd-arm64": {
|
||||
"version": "0.24.2",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.24.2.tgz",
|
||||
"integrity": "sha512-YQbi46SBct6iKnszhSvdluqDmxCJA+Pu280Av9WICNwQmMxV7nLRHZfjQzwbPs3jeWnuAhE9Jy0NrnJ12Oz+0A==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"openbsd"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/openbsd-x64": {
|
||||
"version": "0.24.2",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.24.2.tgz",
|
||||
"integrity": "sha512-+iDS6zpNM6EnJyWv0bMGLWSWeXGN/HTaF/LXHXHwejGsVi+ooqDfMCCTerNFxEkM3wYVcExkeGXNqshc9iMaOA==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"openbsd"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/sunos-x64": {
|
||||
"version": "0.24.2",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.24.2.tgz",
|
||||
"integrity": "sha512-hTdsW27jcktEvpwNHJU4ZwWFGkz2zRJUz8pvddmXPtXDzVKTTINmlmga3ZzwcuMpUvLw7JkLy9QLKyGpD2Yxig==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"sunos"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/win32-arm64": {
|
||||
"version": "0.24.2",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.24.2.tgz",
|
||||
"integrity": "sha512-LihEQ2BBKVFLOC9ZItT9iFprsE9tqjDjnbulhHoFxYQtQfai7qfluVODIYxt1PgdoyQkz23+01rzwNwYfutxUQ==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/win32-ia32": {
|
||||
"version": "0.24.2",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.24.2.tgz",
|
||||
"integrity": "sha512-q+iGUwfs8tncmFC9pcnD5IvRHAzmbwQ3GPS5/ceCyHdjXubwQWI12MKWSNSMYLJMq23/IUCvJMS76PDqXe1fxA==",
|
||||
"cpu": [
|
||||
"ia32"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/win32-x64": {
|
||||
"version": "0.24.2",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.24.2.tgz",
|
||||
"integrity": "sha512-7VTgWzgMGvup6aSqDPLiW5zHaxYJGTO4OokMjIlrCtf+VpEL+cXKtCvg723iguPYI5oaUNdS+/V7OU2gvXVWEg==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@hono/node-server": {
|
||||
"version": "1.19.9",
|
||||
"resolved": "https://registry.npmjs.org/@hono/node-server/-/node-server-1.19.9.tgz",
|
||||
@@ -827,10 +402,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@playwright/cli": {
|
||||
"resolved": "packages/playwright-cli",
|
||||
"link": true
|
||||
},
|
||||
"node_modules/@playwright/mcp": {
|
||||
"resolved": "packages/playwright-mcp",
|
||||
"link": true
|
||||
@@ -1268,16 +839,6 @@
|
||||
"@types/har-format": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/debug": {
|
||||
"version": "4.1.12",
|
||||
"resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz",
|
||||
"integrity": "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/ms": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/estree": {
|
||||
"version": "1.0.8",
|
||||
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz",
|
||||
@@ -1309,20 +870,6 @@
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/minimist": {
|
||||
"version": "1.2.5",
|
||||
"resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.5.tgz",
|
||||
"integrity": "sha512-hov8bUuiLiyFPGyFPE1lwWhmzYbirOXQNNo40+y3zow8aFVTeyn3VWL0VFFfdNddA8S4Vf0Tc062rzyNr7Paag==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/ms": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/ms/-/ms-2.1.0.tgz",
|
||||
"integrity": "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/node": {
|
||||
"version": "24.3.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-24.3.1.tgz",
|
||||
@@ -1813,47 +1360,6 @@
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/esbuild": {
|
||||
"version": "0.24.2",
|
||||
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.24.2.tgz",
|
||||
"integrity": "sha512-+9egpBW8I3CD5XPe0n6BfT5fxLzxrlDzqydF3aviG+9ni1lDC/OvMHcxqEFV0+LANZG5R1bFMWfUrjVsdwxJvA==",
|
||||
"dev": true,
|
||||
"hasInstallScript": true,
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"esbuild": "bin/esbuild"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@esbuild/aix-ppc64": "0.24.2",
|
||||
"@esbuild/android-arm": "0.24.2",
|
||||
"@esbuild/android-arm64": "0.24.2",
|
||||
"@esbuild/android-x64": "0.24.2",
|
||||
"@esbuild/darwin-arm64": "0.24.2",
|
||||
"@esbuild/darwin-x64": "0.24.2",
|
||||
"@esbuild/freebsd-arm64": "0.24.2",
|
||||
"@esbuild/freebsd-x64": "0.24.2",
|
||||
"@esbuild/linux-arm": "0.24.2",
|
||||
"@esbuild/linux-arm64": "0.24.2",
|
||||
"@esbuild/linux-ia32": "0.24.2",
|
||||
"@esbuild/linux-loong64": "0.24.2",
|
||||
"@esbuild/linux-mips64el": "0.24.2",
|
||||
"@esbuild/linux-ppc64": "0.24.2",
|
||||
"@esbuild/linux-riscv64": "0.24.2",
|
||||
"@esbuild/linux-s390x": "0.24.2",
|
||||
"@esbuild/linux-x64": "0.24.2",
|
||||
"@esbuild/netbsd-arm64": "0.24.2",
|
||||
"@esbuild/netbsd-x64": "0.24.2",
|
||||
"@esbuild/openbsd-arm64": "0.24.2",
|
||||
"@esbuild/openbsd-x64": "0.24.2",
|
||||
"@esbuild/sunos-x64": "0.24.2",
|
||||
"@esbuild/win32-arm64": "0.24.2",
|
||||
"@esbuild/win32-ia32": "0.24.2",
|
||||
"@esbuild/win32-x64": "0.24.2"
|
||||
}
|
||||
},
|
||||
"node_modules/escalade": {
|
||||
"version": "3.2.0",
|
||||
"resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz",
|
||||
@@ -2435,7 +1941,6 @@
|
||||
"version": "1.2.8",
|
||||
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz",
|
||||
"integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
@@ -3835,6 +3340,7 @@
|
||||
"packages/playwright-cli": {
|
||||
"name": "@playwright/cli",
|
||||
"version": "0.0.56",
|
||||
"extraneous": true,
|
||||
"license": "Apache-2.0",
|
||||
"devDependencies": {
|
||||
"@types/debug": "^4.1.12",
|
||||
@@ -3853,11 +3359,13 @@
|
||||
"version": "0.0.56",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"minimist": "^1.2.5",
|
||||
"playwright": "1.59.0-alpha-1769176698000",
|
||||
"playwright-core": "1.59.0-alpha-1769176698000"
|
||||
},
|
||||
"bin": {
|
||||
"mcp-server-playwright": "cli.js"
|
||||
"mcp-server-playwright": "cli.js",
|
||||
"playwright-cli": "playwright-cli.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
|
||||
1
packages/playwright-cli/.gitignore
vendored
1
packages/playwright-cli/.gitignore
vendored
@@ -1 +0,0 @@
|
||||
lib/
|
||||
@@ -1,32 +0,0 @@
|
||||
{
|
||||
"name": "@playwright/cli",
|
||||
"version": "0.0.56",
|
||||
"description": "Playwright CLI",
|
||||
"private": true,
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/microsoft/playwright-mcp.git"
|
||||
},
|
||||
"homepage": "https://playwright.dev",
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
},
|
||||
"author": {
|
||||
"name": "Microsoft Corporation"
|
||||
},
|
||||
"license": "Apache-2.0",
|
||||
"scripts": {
|
||||
"lint": "tsc --project .",
|
||||
"build": "esbuild src/cli.ts --bundle --platform=node --target=node18 --format=cjs --outfile=lib/cli.js",
|
||||
"watch": "esbuild src/cli.ts --bundle --platform=node --target=node18 --format=cjs --outfile=lib/cli.js --watch",
|
||||
"clean": "rm -rf lib"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/debug": "^4.1.12",
|
||||
"@types/minimist": "^1.2.5",
|
||||
"debug": "^4.4.3",
|
||||
"esbuild": "^0.24.0",
|
||||
"minimist": "^1.2.8",
|
||||
"typescript": "^5.8.2"
|
||||
}
|
||||
}
|
||||
@@ -1,331 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) Microsoft Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/* eslint-disable no-console */
|
||||
/* eslint-disable no-restricted-properties */
|
||||
|
||||
import { spawn } from 'child_process';
|
||||
import crypto from 'crypto';
|
||||
import fs from 'fs';
|
||||
import net from 'net';
|
||||
import os from 'os';
|
||||
import path from 'path';
|
||||
import { debug } from 'debug';
|
||||
import minimist from 'minimist';
|
||||
import { SocketConnection } from './socketConnection';
|
||||
|
||||
const debugCli = debug('pw:cli');
|
||||
|
||||
const packageJSON = require('../package.json');
|
||||
|
||||
async function runCliCommand(sessionName: string, args: any) {
|
||||
const session = await connectToDaemon(sessionName);
|
||||
const result = await session.runCliCommand(args);
|
||||
console.log(result);
|
||||
session.dispose();
|
||||
}
|
||||
|
||||
async function socketExists(socketPath: string): Promise<boolean> {
|
||||
try {
|
||||
const stat = await fs.promises.stat(socketPath);
|
||||
if (stat?.isSocket())
|
||||
return true;
|
||||
} catch (e) {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
class SocketSession {
|
||||
private _connection: SocketConnection;
|
||||
private _nextMessageId = 1;
|
||||
private _callbacks = new Map<number, { resolve: (o: any) => void, reject: (e: Error) => void }>();
|
||||
|
||||
constructor(connection: SocketConnection) {
|
||||
this._connection = connection;
|
||||
this._connection.onmessage = message => this._onMessage(message);
|
||||
this._connection.onclose = () => this.dispose();
|
||||
}
|
||||
|
||||
async runCliCommand(args: any): Promise<string> {
|
||||
return await this._send('runCliCommand', { args });
|
||||
}
|
||||
|
||||
private async _send(method: string, params: any = {}): Promise<any> {
|
||||
const messageId = this._nextMessageId++;
|
||||
const message = {
|
||||
id: messageId,
|
||||
method,
|
||||
params,
|
||||
};
|
||||
await this._connection.send(message);
|
||||
return new Promise<any>((resolve, reject) => {
|
||||
this._callbacks.set(messageId, { resolve, reject });
|
||||
});
|
||||
}
|
||||
|
||||
dispose() {
|
||||
for (const callback of this._callbacks.values())
|
||||
callback.reject(new Error('Disposed'));
|
||||
this._callbacks.clear();
|
||||
this._connection.close();
|
||||
}
|
||||
|
||||
private _onMessage(object: any) {
|
||||
if (object.id && this._callbacks.has(object.id)) {
|
||||
const callback = this._callbacks.get(object.id)!;
|
||||
this._callbacks.delete(object.id);
|
||||
if (object.error)
|
||||
callback.reject(new Error(object.error));
|
||||
else
|
||||
callback.resolve(object.result);
|
||||
} else if (object.id) {
|
||||
throw new Error(`Unexpected message id: ${object.id}`);
|
||||
} else {
|
||||
throw new Error(`Unexpected message without id: ${JSON.stringify(object)}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function localCacheDir(): string {
|
||||
if (process.platform === 'linux')
|
||||
return process.env.XDG_CACHE_HOME || path.join(os.homedir(), '.cache');
|
||||
if (process.platform === 'darwin')
|
||||
return path.join(os.homedir(), 'Library', 'Caches');
|
||||
if (process.platform === 'win32')
|
||||
return process.env.LOCALAPPDATA || path.join(os.homedir(), 'AppData', 'Local');
|
||||
throw new Error('Unsupported platform: ' + process.platform);
|
||||
}
|
||||
|
||||
function playwrightCacheDir(): string {
|
||||
return path.join(localCacheDir(), 'ms-playwright');
|
||||
}
|
||||
|
||||
function calculateSha1(buffer: Buffer | string): string {
|
||||
const hash = crypto.createHash('sha1');
|
||||
hash.update(buffer);
|
||||
return hash.digest('hex');
|
||||
}
|
||||
|
||||
function socketDirHash(): string {
|
||||
return calculateSha1(__dirname);
|
||||
}
|
||||
|
||||
function daemonSocketDir(): string {
|
||||
return path.resolve(playwrightCacheDir(), 'daemon', socketDirHash());
|
||||
}
|
||||
|
||||
function daemonSocketPath(sessionName: string): string {
|
||||
const socketName = `${sessionName}.sock`;
|
||||
if (os.platform() === 'win32')
|
||||
return `\\\\.\\pipe\\${socketDirHash()}-${socketName}`;
|
||||
return path.resolve(daemonSocketDir(), socketName);
|
||||
}
|
||||
|
||||
async function connectToDaemon(sessionName: string): Promise<SocketSession> {
|
||||
const socketPath = daemonSocketPath(sessionName);
|
||||
debugCli(`Connecting to daemon at ${socketPath}`);
|
||||
|
||||
if (await socketExists(socketPath)) {
|
||||
debugCli(`Socket file exists, attempting to connect...`);
|
||||
try {
|
||||
return await connectToSocket(socketPath);
|
||||
} catch (e) {
|
||||
// Connection failed, delete the stale socket file.
|
||||
if (os.platform() !== 'win32')
|
||||
await fs.promises.unlink(socketPath).catch(() => {});
|
||||
}
|
||||
}
|
||||
|
||||
debugCli(`Will launch daemon process: npx playwright run-mcp-server`);
|
||||
const userDataDir = path.resolve(daemonSocketDir(), `${sessionName}-user-data`);
|
||||
const child = spawn('npx', ['playwright', 'run-mcp-server', `--daemon=${socketPath}`, `--user-data-dir=${userDataDir}`], {
|
||||
detached: true,
|
||||
stdio: 'ignore',
|
||||
cwd: process.cwd(), // Will be used as root.
|
||||
});
|
||||
child.unref();
|
||||
|
||||
// Wait for the socket to become available with retries.
|
||||
const maxRetries = 50;
|
||||
const retryDelay = 100; // ms
|
||||
for (let i = 0; i < maxRetries; i++) {
|
||||
await new Promise(resolve => setTimeout(resolve, 100));
|
||||
try {
|
||||
return await connectToSocket(socketPath);
|
||||
} catch (e: any) {
|
||||
if (e.code !== 'ENOENT')
|
||||
throw e;
|
||||
debugCli(`Retrying to connect to daemon at ${socketPath} (${i + 1}/${maxRetries})`);
|
||||
}
|
||||
}
|
||||
throw new Error(`Failed to connect to daemon at ${socketPath} after ${maxRetries * retryDelay}ms`);
|
||||
}
|
||||
|
||||
async function connectToSocket(socketPath: string): Promise<SocketSession> {
|
||||
const socket = await new Promise<net.Socket>((resolve, reject) => {
|
||||
const socket = net.createConnection(socketPath, () => {
|
||||
debugCli(`Connected to daemon at ${socketPath}`);
|
||||
resolve(socket);
|
||||
});
|
||||
socket.on('error', reject);
|
||||
});
|
||||
return new SocketSession(new SocketConnection(socket));
|
||||
}
|
||||
|
||||
function currentSessionPath(): string {
|
||||
return path.resolve(daemonSocketDir(), 'current-session');
|
||||
}
|
||||
|
||||
async function getCurrentSession(): Promise<string> {
|
||||
try {
|
||||
const session = await fs.promises.readFile(currentSessionPath(), 'utf-8');
|
||||
return session.trim() || 'default';
|
||||
} catch {
|
||||
return 'default';
|
||||
}
|
||||
}
|
||||
|
||||
async function setCurrentSession(sessionName: string): Promise<void> {
|
||||
await fs.promises.mkdir(daemonSocketDir(), { recursive: true });
|
||||
await fs.promises.writeFile(currentSessionPath(), sessionName);
|
||||
}
|
||||
|
||||
async function canConnectToSocket(socketPath: string): Promise<boolean> {
|
||||
return new Promise<boolean>(resolve => {
|
||||
const socket = net.createConnection(socketPath, () => {
|
||||
socket.destroy();
|
||||
resolve(true);
|
||||
});
|
||||
socket.on('error', () => {
|
||||
resolve(false);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
async function listSessions(): Promise<{ name: string, live: boolean }[]> {
|
||||
const dir = daemonSocketDir();
|
||||
try {
|
||||
const files = await fs.promises.readdir(dir);
|
||||
const sessions: { name: string, live: boolean }[] = [];
|
||||
for (const file of files) {
|
||||
if (file.endsWith('-user-data')) {
|
||||
const sessionName = file.slice(0, -'-user-data'.length);
|
||||
const socketPath = daemonSocketPath(sessionName);
|
||||
const live = await canConnectToSocket(socketPath);
|
||||
sessions.push({ name: sessionName, live });
|
||||
}
|
||||
}
|
||||
return sessions;
|
||||
} catch {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
function resolveSessionName(args: any): string {
|
||||
if (args.session)
|
||||
return args.session;
|
||||
if (process.env.PLAYWRIGHT_CLI_SESSION)
|
||||
return process.env.PLAYWRIGHT_CLI_SESSION;
|
||||
return 'default';
|
||||
}
|
||||
|
||||
async function handleSessionCommand(args: any): Promise<void> {
|
||||
const subcommand = args._[1];
|
||||
|
||||
if (!subcommand) {
|
||||
// Show current session
|
||||
const current = await getCurrentSession();
|
||||
console.log(current);
|
||||
return;
|
||||
}
|
||||
|
||||
if (subcommand === 'list') {
|
||||
const sessions = await listSessions();
|
||||
const current = await getCurrentSession();
|
||||
console.log('Sessions:');
|
||||
for (const session of sessions) {
|
||||
const marker = session.name === current ? '->' : ' ';
|
||||
const liveMarker = session.live ? ' (live)' : '';
|
||||
console.log(`${marker} ${session.name}${liveMarker}`);
|
||||
}
|
||||
if (sessions.length === 0)
|
||||
console.log(' (no sessions)');
|
||||
return;
|
||||
}
|
||||
|
||||
if (subcommand === 'set') {
|
||||
const sessionName = args._[2];
|
||||
if (!sessionName) {
|
||||
console.error('Usage: playwright-cli session set <session-name>');
|
||||
process.exit(1);
|
||||
}
|
||||
await setCurrentSession(sessionName);
|
||||
console.log(`Current session set to: ${sessionName}`);
|
||||
return;
|
||||
}
|
||||
|
||||
console.error(`Unknown session subcommand: ${subcommand}`);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
async function main() {
|
||||
const argv = process.argv.slice(2);
|
||||
const args = minimist(argv);
|
||||
const commandName = args._[0];
|
||||
|
||||
if (args.version || args.v) {
|
||||
console.log(packageJSON.version);
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
// Handle 'session' command specially - it doesn't need daemon connection
|
||||
if (commandName === 'session') {
|
||||
await handleSessionCommand(args);
|
||||
return;
|
||||
}
|
||||
|
||||
const help = require('./help.json');
|
||||
const command = help.commands[commandName];
|
||||
if (args.help || args.h) {
|
||||
if (command) {
|
||||
console.log(command);
|
||||
} else {
|
||||
console.log('playwright-cli - run playwright mcp commands from terminal\n');
|
||||
console.log(help.global);
|
||||
}
|
||||
process.exit(0);
|
||||
}
|
||||
if (!command) {
|
||||
console.error(`Unknown command: ${commandName}\n`);
|
||||
console.log(help.global);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
// Resolve session name: --session flag > PLAYWRIGHT_CLI_SESSION env > current session > 'default'
|
||||
let sessionName = resolveSessionName(args);
|
||||
if (sessionName === 'default' && !args.session && !process.env.PLAYWRIGHT_CLI_SESSION)
|
||||
sessionName = await getCurrentSession();
|
||||
|
||||
runCliCommand(sessionName, args).catch(e => {
|
||||
console.error(e.message);
|
||||
process.exit(1);
|
||||
});
|
||||
}
|
||||
|
||||
main().catch(e => {
|
||||
console.error(e.message);
|
||||
process.exit(1);
|
||||
});
|
||||
@@ -1,32 +0,0 @@
|
||||
{
|
||||
"global": "Usage: playwright-cli <command> [options]\nCommands:\n click <ref> perform click on a web page\n close close the page\n dblclick <ref> perform double click on a web page\n console <level> returns all console messages\n drag <startRef> <endRef> perform drag and drop between two elements\n evaluate <function> <ref> evaluate javascript expression on page or element\n upload-file upload one or multiple files\n handle-dialog <accept> <promptText> handle a dialog\n hover <ref> hover over element on page\n open <url> open url\n go-back go back to the previous page\n network-requests returns all network requests since loading the page\n press-key <key> press a key on the keyboard\n resize <width> <height> resize the browser window\n run-code <code> run playwright code snippet\n select-option <ref> <values> select an option in a dropdown\n snapshot capture accessibility snapshot of the current page, this is better than screenshot\n screenshot <ref> take a screenshot of the current page. you can't perform actions based on the screenshot, use browser_snapshot for actions.\n type <ref> <text> type text into editable element\n wait-for wait for text to appear or disappear or a specified time to pass\n tab <action> <index> close a browser tab\n mouse-click-xy <x> <y> click left mouse button at a given position\n mouse-drag-xy <startX> <startY> <endX> <endY> drag left mouse button to a given position\n mouse-move-xy <x> <y> move mouse to a given position\n pdf-save save page as pdf\n start-tracing start trace recording\n stop-tracing stop trace recording",
|
||||
"commands": {
|
||||
"click": "playwright-cli click <ref>\n\nPerform click on a web page\n\nArguments:\n <ref>\tExact target element reference from the page snapshot\nOptions:\n --button\tbutton to click, defaults to left\n --modifiers\tmodifier keys to press",
|
||||
"close": "playwright-cli close \n\nClose the page\n",
|
||||
"dblclick": "playwright-cli dblclick <ref>\n\nPerform double click on a web page\n\nArguments:\n <ref>\tExact target element reference from the page snapshot\nOptions:\n --button\tbutton to click, defaults to left\n --modifiers\tmodifier keys to press",
|
||||
"console": "playwright-cli console <level>\n\nReturns all console messages\n\nArguments:\n <level>\tLevel of the console messages to return. Each level includes the messages of more severe levels. Defaults to \"info\".",
|
||||
"drag": "playwright-cli drag <startRef> <endRef>\n\nPerform drag and drop between two elements\n\nArguments:\n <startRef>\tExact source element reference from the page snapshot\n <endRef>\tExact target element reference from the page snapshot\nOptions:\n --headed\trun browser in headed mode",
|
||||
"evaluate": "playwright-cli evaluate <function> <ref>\n\nEvaluate JavaScript expression on page or element\n\nArguments:\n <function>\t() => { /* code */ } or (element) => { /* code */ } when element is provided\n <ref>\tExact target element reference from the page snapshot",
|
||||
"upload-file": "playwright-cli upload-file \n\nUpload one or multiple files\n\nOptions:\n --paths\tthe absolute paths to the files to upload. can be single file or multiple files. if omitted, file chooser is cancelled.",
|
||||
"handle-dialog": "playwright-cli handle-dialog <accept> <promptText>\n\nHandle a dialog\n\nArguments:\n <accept>\tWhether to accept the dialog.\n <promptText>\tThe text of the prompt in case of a prompt dialog.",
|
||||
"hover": "playwright-cli hover <ref>\n\nHover over element on page\n\nArguments:\n <ref>\tExact target element reference from the page snapshot",
|
||||
"open": "playwright-cli open <url>\n\nOpen URL\n\nArguments:\n <url>\tThe URL to navigate to\nOptions:\n --headed\trun browser in headed mode",
|
||||
"go-back": "playwright-cli go-back \n\nGo back to the previous page\n",
|
||||
"network-requests": "playwright-cli network-requests \n\nReturns all network requests since loading the page\n\nOptions:\n --includeStatic\twhether to include successful static resources like images, fonts, scripts, etc. defaults to false.",
|
||||
"press-key": "playwright-cli press-key <key>\n\nPress a key on the keyboard\n\nArguments:\n <key>\tName of the key to press or a character to generate, such as `ArrowLeft` or `a`",
|
||||
"resize": "playwright-cli resize <width> <height>\n\nResize the browser window\n\nArguments:\n <width>\tWidth of the browser window\n <height>\tHeight of the browser window",
|
||||
"run-code": "playwright-cli run-code <code>\n\nRun Playwright code snippet\n\nArguments:\n <code>\tA JavaScript function containing Playwright code to execute. It will be invoked with a single argument, page, which you can use for any page interaction.",
|
||||
"select-option": "playwright-cli select-option <ref> <values>\n\nSelect an option in a dropdown\n\nArguments:\n <ref>\tExact target element reference from the page snapshot\n <values>\tArray of values to select in the dropdown. This can be a single value or multiple values.",
|
||||
"snapshot": "playwright-cli snapshot \n\nCapture accessibility snapshot of the current page, this is better than screenshot\n\nOptions:\n --filename\tsave snapshot to markdown file instead of returning it in the response.",
|
||||
"screenshot": "playwright-cli screenshot <ref>\n\nTake a screenshot of the current page. You can't perform actions based on the screenshot, use browser_snapshot for actions.\n\nArguments:\n <ref>\tExact target element reference from the page snapshot.\nOptions:\n --filename\tfile name to save the screenshot to. defaults to `page-{timestamp}.{png|jpeg}` if not specified.\n --fullPage\twhen true, takes a screenshot of the full scrollable page, instead of the currently visible viewport.",
|
||||
"type": "playwright-cli type <ref> <text>\n\nType text into editable element\n\nArguments:\n <ref>\tExact target element reference from the page snapshot\n <text>\tText to type into the element\nOptions:\n --submit\twhether to submit entered text (press enter after)\n --slowly\twhether to type one character at a time. useful for triggering key handlers in the page.",
|
||||
"wait-for": "playwright-cli wait-for \n\nWait for text to appear or disappear or a specified time to pass\n\nOptions:\n --time\tthe time to wait in seconds\n --text\tthe text to wait for\n --textGone\tthe text to wait for to disappear",
|
||||
"tab": "playwright-cli tab <action> <index>\n\nClose a browser tab\n\nArguments:\n <action>\tAction to perform on tabs, 'list' | 'new' | 'close' | 'select'\n <index>\tTab index. If omitted, current tab is closed.",
|
||||
"mouse-click-xy": "playwright-cli mouse-click-xy <x> <y>\n\nClick left mouse button at a given position\n\nArguments:\n <x>\tX coordinate\n <y>\tY coordinate",
|
||||
"mouse-drag-xy": "playwright-cli mouse-drag-xy <startX> <startY> <endX> <endY>\n\nDrag left mouse button to a given position\n\nArguments:\n <startX>\tStart X coordinate\n <startY>\tStart Y coordinate\n <endX>\tEnd X coordinate\n <endY>\tEnd Y coordinate",
|
||||
"mouse-move-xy": "playwright-cli mouse-move-xy <x> <y>\n\nMove mouse to a given position\n\nArguments:\n <x>\tX coordinate\n <y>\tY coordinate",
|
||||
"pdf-save": "playwright-cli pdf-save \n\nSave page as PDF\n\nOptions:\n --filename\tfile name to save the pdf to. defaults to `page-{timestamp}.pdf` if not specified.",
|
||||
"start-tracing": "playwright-cli start-tracing \n\nStart trace recording\n",
|
||||
"stop-tracing": "playwright-cli stop-tracing \n\nStop trace recording\n"
|
||||
}
|
||||
}
|
||||
@@ -1,82 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) Microsoft Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import net from 'net';
|
||||
|
||||
import { debug } from 'debug';
|
||||
|
||||
const daemonDebug = debug('pw:daemon');
|
||||
|
||||
export class SocketConnection {
|
||||
private _socket: net.Socket;
|
||||
private _pendingBuffers: Buffer[] = [];
|
||||
|
||||
onclose?: () => void;
|
||||
onmessage?: (message: any) => void;
|
||||
|
||||
constructor(socket: net.Socket) {
|
||||
this._socket = socket;
|
||||
socket.on('data', buffer => this._onData(buffer));
|
||||
socket.on('close', () => {
|
||||
this.onclose?.();
|
||||
});
|
||||
socket.on('error', e => daemonDebug(`error: ${e.message}`));
|
||||
}
|
||||
|
||||
async send(message: any) {
|
||||
await new Promise((resolve, reject) => {
|
||||
this._socket.write(`${JSON.stringify(message)}\n`, error => {
|
||||
if (error)
|
||||
reject(error);
|
||||
else
|
||||
resolve(undefined);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
close() {
|
||||
this._socket.destroy();
|
||||
}
|
||||
|
||||
private _onData(buffer: Buffer) {
|
||||
let end = buffer.indexOf('\n');
|
||||
if (end === -1) {
|
||||
this._pendingBuffers.push(buffer);
|
||||
return;
|
||||
}
|
||||
this._pendingBuffers.push(buffer.slice(0, end));
|
||||
const message = Buffer.concat(this._pendingBuffers).toString();
|
||||
this._dispatchMessage(message);
|
||||
|
||||
let start = end + 1;
|
||||
end = buffer.indexOf('\n', start);
|
||||
while (end !== -1) {
|
||||
const message = buffer.toString(undefined, start, end);
|
||||
this._dispatchMessage(message);
|
||||
start = end + 1;
|
||||
end = buffer.indexOf('\n', start);
|
||||
}
|
||||
this._pendingBuffers = [buffer.slice(start)];
|
||||
}
|
||||
|
||||
private _dispatchMessage(message: string) {
|
||||
try {
|
||||
this.onmessage?.(JSON.parse(message));
|
||||
} catch (e) {
|
||||
daemonDebug('failed to dispatch message', e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "ESNext",
|
||||
"esModuleInterop": true,
|
||||
"moduleResolution": "node",
|
||||
"strict": true,
|
||||
"module": "ESNext",
|
||||
"rootDir": "src",
|
||||
"outDir": "./lib",
|
||||
"resolveJsonModule": true,
|
||||
"types": ["node"],
|
||||
"noEmit": true
|
||||
},
|
||||
"include": [
|
||||
"src",
|
||||
]
|
||||
}
|
||||
@@ -2,5 +2,6 @@
|
||||
!README.md
|
||||
!LICENSE
|
||||
!cli.js
|
||||
!playwright-cli.js
|
||||
!index.*
|
||||
!config.d.ts
|
||||
|
||||
@@ -15,14 +15,13 @@
|
||||
},
|
||||
"license": "Apache-2.0",
|
||||
"scripts": {
|
||||
"lint": "npm run update-readme",
|
||||
"update-readme": "node update-readme.js",
|
||||
"lint": "node update-readme.js",
|
||||
"test": "playwright test",
|
||||
"ctest": "playwright test --project=chrome",
|
||||
"ftest": "playwright test --project=firefox",
|
||||
"wtest": "playwright test --project=webkit",
|
||||
"dtest": "MCP_IN_DOCKER=1 playwright test --project=chromium-docker",
|
||||
"npm-publish": "npm run clean && npm run lint && npm run test && npm publish",
|
||||
"npm-publish": "npm run lint && npm run test && npm publish",
|
||||
"copy-config": "cp ../../../playwright/packages/playwright/src/mcp/config.d.ts . && perl -pi -e \"s|import type \\* as playwright from 'playwright-core';|import type * as playwright from 'playwright';|\" ./config.d.ts",
|
||||
"roll": "npm run copy-config && npm run lint"
|
||||
},
|
||||
@@ -34,10 +33,12 @@
|
||||
}
|
||||
},
|
||||
"dependencies": {
|
||||
"minimist": "^1.2.5",
|
||||
"playwright": "1.59.0-alpha-1769176698000",
|
||||
"playwright-core": "1.59.0-alpha-1769176698000"
|
||||
},
|
||||
"bin": {
|
||||
"mcp-server-playwright": "cli.js"
|
||||
"mcp": "cli.js",
|
||||
"playwright-cli": "./playwright-cli.js"
|
||||
}
|
||||
}
|
||||
|
||||
23
packages/playwright-mcp/playwright-cli.js
Executable file
23
packages/playwright-mcp/playwright-cli.js
Executable file
@@ -0,0 +1,23 @@
|
||||
#!/usr/bin/env node
|
||||
/**
|
||||
* Copyright (c) Microsoft Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
const { program } = require('playwright/lib/mcp/terminal/program');
|
||||
const packageJSON = require('./package.json');
|
||||
program({ version: packageJSON.version }).catch(e => {
|
||||
console.error(e.message);
|
||||
process.exit(1);
|
||||
});
|
||||
32
packages/playwright-mcp/tests/cli.spec.ts
Normal file
32
packages/playwright-mcp/tests/cli.spec.ts
Normal file
@@ -0,0 +1,32 @@
|
||||
/**
|
||||
* Copyright (c) Microsoft Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { test, expect } from '@playwright/test';
|
||||
import childProcess from 'child_process';
|
||||
|
||||
function runCLI(args: string[]) {
|
||||
return childProcess.spawnSync(process.execPath, [require.resolve('../playwright-cli'), ...args], { encoding: 'utf-8' });
|
||||
}
|
||||
|
||||
test('prints help', async () => {
|
||||
const { stdout } = runCLI(['--help']);
|
||||
expect(stdout).toContain('Usage: playwright-cli <command>');
|
||||
});
|
||||
|
||||
test('prints version', async () => {
|
||||
const { stdout } = runCLI(['--version']);
|
||||
expect(stdout).toContain(require('../package.json').version);
|
||||
});
|
||||
Reference in New Issue
Block a user