diff --git a/package-lock.json b/package-lock.json index 2b02740..f2b6625 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,11 +1,11 @@ { - "name": "opencli", + "name": "@jackwener/opencli", "version": "0.1.0", "lockfileVersion": 3, "requires": true, "packages": { "": { - "name": "opencli", + "name": "@jackwener/opencli", "version": "0.1.0", "license": "MIT", "dependencies": { @@ -18,6 +18,7 @@ "opencli": "dist/main.js" }, "devDependencies": { + "@playwright/mcp": "^0.0.68", "@types/js-yaml": "^4.0.9", "@types/node": "^22.13.10", "tsx": "^4.19.3", @@ -476,6 +477,23 @@ "node": ">=18" } }, + "node_modules/@playwright/mcp": { + "version": "0.0.68", + "resolved": "https://registry.npmjs.org/@playwright/mcp/-/mcp-0.0.68.tgz", + "integrity": "sha512-oP9I9ghXKuQEBo4xaC7HgsS2gRTxyMzlBm3UEhYj4VqqrqbPQUX2shATPaNA/am9joBzq9v0OXISzeIgP+zmHA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "playwright": "1.59.0-alpha-1771104257000", + "playwright-core": "1.59.0-alpha-1771104257000" + }, + "bin": { + "playwright-mcp": "cli.js" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/@types/js-yaml": { "version": "4.0.9", "resolved": "https://registry.npmjs.org/@types/js-yaml/-/js-yaml-4.0.9.tgz", @@ -641,6 +659,53 @@ "js-yaml": "bin/js-yaml.js" } }, + "node_modules/playwright": { + "version": "1.59.0-alpha-1771104257000", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.59.0-alpha-1771104257000.tgz", + "integrity": "sha512-6SCMMMJaDRsSqiKVLmb2nhtLES7iTYawTWWrQK6UdIGNzXi8lka4sLKRec3L4DnTWwddAvCuRn8035dhNiHzbg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "playwright-core": "1.59.0-alpha-1771104257000" + }, + "bin": { + "playwright": "cli.js" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "fsevents": "2.3.2" + } + }, + "node_modules/playwright-core": { + "version": "1.59.0-alpha-1771104257000", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.59.0-alpha-1771104257000.tgz", + "integrity": "sha512-YiXup3pnpQUCBMSIW5zx8CErwRx4K6O5Kojkw2BzJui8MazoMUDU6E3xGsb1kzFviEAE09LFQ+y1a0RhIJQ5SA==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "playwright-core": "cli.js" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/playwright/node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, "node_modules/resolve-pkg-maps": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", diff --git a/package.json b/package.json index 266d146..31f73a2 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,9 @@ { - "name": "opencli", + "name": "@jackwener/opencli", "version": "0.1.0", + "publishConfig": { + "access": "public" + }, "description": "Make any website your CLI. AI-powered.", "type": "module", "main": "dist/main.js", @@ -35,6 +38,7 @@ "js-yaml": "^4.1.0" }, "devDependencies": { + "@playwright/mcp": "^0.0.68", "@types/js-yaml": "^4.0.9", "@types/node": "^22.13.10", "tsx": "^4.19.3", diff --git a/src/browser.ts b/src/browser.ts index ee2d1d0..c6f02af 100644 --- a/src/browser.ts +++ b/src/browser.ts @@ -4,6 +4,7 @@ */ import { spawn, execSync, type ChildProcess } from 'node:child_process'; +import { fileURLToPath } from 'node:url'; import * as fs from 'node:fs'; import * as os from 'node:os'; import * as path from 'node:path'; @@ -118,12 +119,12 @@ export class PlaywrightMCP { await this._acquireLock(); const timeout = opts.timeout ?? CONNECT_TIMEOUT; const mcpPath = findMcpServerPath(); - if (!mcpPath) throw new Error('Playwright MCP server not found. Install: npx @anthropic-ai/mcp-server-playwright'); + if (!mcpPath) throw new Error('Playwright MCP server not found. Install: npm install -D @playwright/mcp'); return new Promise((resolve, reject) => { const timer = setTimeout(() => reject(new Error(`Timed out connecting to browser (${timeout}s)`)), timeout * 1000); - this._proc = spawn('node', [mcpPath], { + this._proc = spawn('node', [mcpPath, '--extension'], { stdio: ['pipe', 'pipe', 'pipe'], env: { ...process.env, ...(process.env.PLAYWRIGHT_MCP_EXTENSION_TOKEN ? { PLAYWRIGHT_MCP_EXTENSION_TOKEN: process.env.PLAYWRIGHT_MCP_EXTENSION_TOKEN } : {}) }, }); @@ -218,6 +219,15 @@ export class PlaywrightMCP { } function findMcpServerPath(): string | null { + // Check local node_modules first (@playwright/mcp is the modern package) + const localMcp = path.resolve('node_modules', '@playwright', 'mcp', 'cli.js'); + if (fs.existsSync(localMcp)) return localMcp; + + // Check project-relative path + const __dirname2 = path.dirname(fileURLToPath(import.meta.url)); + const projectMcp = path.resolve(__dirname2, '..', 'node_modules', '@playwright', 'mcp', 'cli.js'); + if (fs.existsSync(projectMcp)) return projectMcp; + // Check common locations const candidates = [ path.join(os.homedir(), '.npm', '_npx'), @@ -225,9 +235,9 @@ function findMcpServerPath(): string | null { '/usr/local/lib/node_modules', ]; - // Try npx resolution + // Try npx resolution (legacy package name) try { - const result = execSync('npx -y --package=@anthropic-ai/mcp-server-playwright which mcp-server-playwright 2>/dev/null', { encoding: 'utf-8', timeout: 10000 }).trim(); + const result = execSync('npx -y --package=@playwright/mcp which mcp-server-playwright 2>/dev/null', { encoding: 'utf-8', timeout: 10000 }).trim(); if (result && fs.existsSync(result)) return result; } catch {} @@ -241,7 +251,7 @@ function findMcpServerPath(): string | null { for (const base of candidates) { if (!fs.existsSync(base)) continue; try { - const found = execSync(`find "${base}" -name "cli.js" -path "*mcp-server-playwright*" 2>/dev/null | head -1`, { encoding: 'utf-8', timeout: 5000 }).trim(); + const found = execSync(`find "${base}" -name "cli.js" -path "*playwright*mcp*" 2>/dev/null | head -1`, { encoding: 'utf-8', timeout: 5000 }).trim(); if (found) return found; } catch {} }