real-browser-mcp-server 1.2.0 → 1.2.2

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.
Files changed (120) hide show
  1. package/README.md +96 -9
  2. package/dist/lib/cjs/index.d.ts +2 -0
  3. package/dist/lib/cjs/index.d.ts.map +1 -0
  4. package/dist/lib/cjs/index.js +385 -0
  5. package/dist/lib/cjs/index.js.map +1 -0
  6. package/dist/lib/cjs/module/pageController.d.ts +2 -0
  7. package/dist/lib/cjs/module/pageController.d.ts.map +1 -0
  8. package/{lib → dist/lib}/cjs/module/pageController.js +28 -29
  9. package/dist/lib/cjs/module/pageController.js.map +1 -0
  10. package/dist/lib/cjs/module/turnstile.d.ts +2 -0
  11. package/dist/lib/cjs/module/turnstile.d.ts.map +1 -0
  12. package/{lib → dist/lib}/cjs/module/turnstile.js +24 -12
  13. package/dist/lib/cjs/module/turnstile.js.map +1 -0
  14. package/dist/src/index.d.ts +11 -0
  15. package/dist/src/index.d.ts.map +1 -0
  16. package/dist/src/index.js +118 -0
  17. package/dist/src/index.js.map +1 -0
  18. package/dist/src/mcp/handlers/browser.d.ts +30 -0
  19. package/dist/src/mcp/handlers/browser.d.ts.map +1 -0
  20. package/dist/src/mcp/handlers/browser.js +231 -0
  21. package/dist/src/mcp/handlers/browser.js.map +1 -0
  22. package/dist/src/mcp/handlers/dom.d.ts +134 -0
  23. package/dist/src/mcp/handlers/dom.d.ts.map +1 -0
  24. package/dist/src/mcp/handlers/dom.js +551 -0
  25. package/dist/src/mcp/handlers/dom.js.map +1 -0
  26. package/dist/src/mcp/handlers/extract.d.ts +59 -0
  27. package/dist/src/mcp/handlers/extract.d.ts.map +1 -0
  28. package/dist/src/mcp/handlers/extract.js +455 -0
  29. package/dist/src/mcp/handlers/extract.js.map +1 -0
  30. package/dist/src/mcp/handlers/form-handlers.d.ts +9 -0
  31. package/dist/src/mcp/handlers/form-handlers.d.ts.map +1 -0
  32. package/dist/src/mcp/handlers/form-handlers.js +56 -0
  33. package/dist/src/mcp/handlers/form-handlers.js.map +1 -0
  34. package/dist/src/mcp/handlers/helpers.d.ts +47 -0
  35. package/dist/src/mcp/handlers/helpers.d.ts.map +1 -0
  36. package/dist/src/mcp/handlers/helpers.js +515 -0
  37. package/dist/src/mcp/handlers/helpers.js.map +1 -0
  38. package/dist/src/mcp/handlers/index.d.ts +6 -0
  39. package/dist/src/mcp/handlers/index.d.ts.map +1 -0
  40. package/dist/src/mcp/handlers/index.js +61 -0
  41. package/dist/src/mcp/handlers/index.js.map +1 -0
  42. package/dist/src/mcp/handlers/media-handlers.d.ts +10 -0
  43. package/dist/src/mcp/handlers/media-handlers.d.ts.map +1 -0
  44. package/dist/src/mcp/handlers/media-handlers.js +535 -0
  45. package/dist/src/mcp/handlers/media-handlers.js.map +1 -0
  46. package/dist/src/mcp/handlers/network.d.ts +147 -0
  47. package/dist/src/mcp/handlers/network.d.ts.map +1 -0
  48. package/dist/src/mcp/handlers/network.js +1135 -0
  49. package/dist/src/mcp/handlers/network.js.map +1 -0
  50. package/dist/src/mcp/handlers/state.d.ts +34 -0
  51. package/dist/src/mcp/handlers/state.d.ts.map +1 -0
  52. package/dist/src/mcp/handlers/state.js +225 -0
  53. package/dist/src/mcp/handlers/state.js.map +1 -0
  54. package/dist/src/mcp/handlers/utility-handlers.d.ts +167 -0
  55. package/dist/src/mcp/handlers/utility-handlers.d.ts.map +1 -0
  56. package/dist/src/mcp/handlers/utility-handlers.js +280 -0
  57. package/dist/src/mcp/handlers/utility-handlers.js.map +1 -0
  58. package/dist/src/mcp/handlers/vision.d.ts +127 -0
  59. package/dist/src/mcp/handlers/vision.d.ts.map +1 -0
  60. package/dist/src/mcp/handlers/vision.js +483 -0
  61. package/dist/src/mcp/handlers/vision.js.map +1 -0
  62. package/dist/src/mcp/index.d.ts +3 -0
  63. package/dist/src/mcp/index.d.ts.map +1 -0
  64. package/dist/src/mcp/index.js +166 -0
  65. package/dist/src/mcp/index.js.map +1 -0
  66. package/dist/src/mcp/server.d.ts +2 -0
  67. package/dist/src/mcp/server.d.ts.map +1 -0
  68. package/dist/src/mcp/server.js +117 -0
  69. package/dist/src/mcp/server.js.map +1 -0
  70. package/dist/src/mcp/tools.d.ts +8 -0
  71. package/dist/src/mcp/tools.d.ts.map +1 -0
  72. package/{src → dist/src}/mcp/tools.js +12 -11
  73. package/dist/src/mcp/tools.js.map +1 -0
  74. package/dist/src/shared/cache-manager.d.ts +80 -0
  75. package/dist/src/shared/cache-manager.d.ts.map +1 -0
  76. package/dist/src/shared/cache-manager.js +221 -0
  77. package/dist/src/shared/cache-manager.js.map +1 -0
  78. package/dist/src/shared/tools.d.ts +2 -0
  79. package/dist/src/shared/tools.d.ts.map +1 -0
  80. package/dist/src/shared/tools.js +599 -0
  81. package/dist/src/shared/tools.js.map +1 -0
  82. package/dist/src/types.d.ts +365 -0
  83. package/dist/src/types.d.ts.map +1 -0
  84. package/dist/src/types.js +9 -0
  85. package/dist/src/types.js.map +1 -0
  86. package/dist/test/cjs/test.d.ts +11 -0
  87. package/dist/test/cjs/test.d.ts.map +1 -0
  88. package/dist/test/cjs/test.js +289 -0
  89. package/dist/test/cjs/test.js.map +1 -0
  90. package/dist/test/mcp/smoke-test.d.ts +29 -0
  91. package/dist/test/mcp/smoke-test.d.ts.map +1 -0
  92. package/dist/test/mcp/smoke-test.js +132 -0
  93. package/dist/test/mcp/smoke-test.js.map +1 -0
  94. package/lib/esm/index.mjs +232 -79
  95. package/lib/esm/module/pageController.mjs +21 -18
  96. package/lib/esm/module/turnstile.mjs +7 -0
  97. package/package.json +25 -15
  98. package/typings.d.ts +12 -6
  99. package/.github/ISSUE_TEMPLATE/general_issue.yaml +0 -58
  100. package/.github/SETUP.md +0 -111
  101. package/.github/workflows/publish.yml +0 -135
  102. package/Dockerfile +0 -79
  103. package/lib/cjs/adblocker.bin +0 -0
  104. package/lib/cjs/index.js +0 -249
  105. package/src/ai/action-parser.js +0 -274
  106. package/src/ai/core.js +0 -378
  107. package/src/ai/element-finder.js +0 -466
  108. package/src/ai/index.js +0 -82
  109. package/src/ai/page-analyzer.js +0 -304
  110. package/src/ai/selector-healer.js +0 -236
  111. package/src/index.js +0 -121
  112. package/src/mcp/handlers.js +0 -5071
  113. package/src/mcp/index.js +0 -190
  114. package/src/mcp/server.js +0 -144
  115. package/src/shared/tools.js +0 -618
  116. package/test/cjs/test.js +0 -259
  117. package/test/esm/package.json +0 -13
  118. package/test/esm/test.js +0 -226
  119. package/test/esm/test_option2.js +0 -46
  120. package/test/esm/test_playwright_ghost.js +0 -30
package/.github/SETUP.md DELETED
@@ -1,111 +0,0 @@
1
- # 🔧 GitHub Actions Setup Guide
2
-
3
- यह गाइड बताएगी कि GitHub Actions workflow को कैसे setup करना है।
4
-
5
- ## 🔐 Required Secrets
6
-
7
- आपको अपनी GitHub repository में निम्नलिखित secrets को add करना होगा:
8
-
9
- ### 1. GH_TOKEN
10
- - **Purpose**: Repository access और GitHub releases के लिए
11
- - **कैसे बनाएं**:
12
- 1. GitHub Settings → Developer settings → Personal access tokens → Tokens (classic)
13
- 2. "Generate new token (classic)" पर click करें
14
- 3. निम्नलिखित permissions select करें:
15
- - `repo` (Full control of private repositories)
16
- - `write:packages` (Write packages to GitHub Package Registry)
17
- - `workflow` (Update GitHub Action workflows)
18
- 4. Token generate करें और copy करें
19
-
20
- ### 2. NPM_TOKEN
21
- - **Purpose**: NPM पर package publish करने के लिए
22
- - **कैसे बनाएं**:
23
- 1. NPM website पर login करें (https://www.npmjs.com/)
24
- 2. Profile → Access Tokens → Generate New Token
25
- 3. "Automation" type select करें (recommended for CI/CD)
26
- 4. Token generate करें और copy करें
27
-
28
- ## 🛠️ Secrets को Repository में Add करना
29
-
30
- 1. GitHub repository पर जाएं
31
- 2. Settings → Secrets and variables → Actions
32
- 3. "New repository secret" पर click करें
33
- 4. निम्नलिखित secrets add करें:
34
-
35
- | Secret Name | Value |
36
- |-------------|-------|
37
- | `GH_TOKEN` | आपका GitHub Personal Access Token |
38
- | `NPM_TOKEN` | आपका NPM Automation Token |
39
-
40
- ## 🚀 Workflow Usage
41
-
42
- इस project में **2 workflows** हैं:
43
-
44
- ### 1. 🤖 Auto Increment & Publish (Recommended)
45
- **Simple Auto-Increment**: हमेशा patch version increment करता है
46
-
47
- #### Automatic Publishing:
48
- ```bash
49
- # कोई भी change push करें, automatic version increment होगा:
50
- git commit -m "any change"
51
- git push origin main # 1.5.0 → 1.5.1 → 1.5.2 → 1.5.3...
52
- ```
53
-
54
- #### Manual Publishing:
55
- 1. GitHub repository → Actions → "🤖 Auto Increment & Publish"
56
- 2. "Run workflow" click करें
57
- 3. "Publish to NPM?" = `true` रखें
58
- 4. "Run workflow" पर click करें
59
-
60
- ### 2. 🚀 Publish to NPM (Tag-based)
61
- Traditional tag-based publishing:
62
-
63
- ```bash
64
- # Manual tag push के लिए
65
- git tag v1.5.1
66
- git push origin v1.5.1
67
- ```
68
-
69
- ## 🔢 Simple Auto-Increment System
70
-
71
- **Current Version**: `1.5.0`
72
-
73
- हर workflow run पर automatic patch increment:
74
- - `1.5.0` → `1.5.1`
75
- - `1.5.1` → `1.5.2`
76
- - `1.5.2` → `1.5.3`
77
- - `1.5.3` → `1.5.4`
78
- - ... and so on
79
-
80
- **बिल्कुल simple!** 🚀 कोई complex commit message analysis नहीं चाहिए।
81
-
82
- ## 📋 Workflow Features
83
-
84
- ✅ **Automatic Triggers**: Version tags पर auto-publish
85
- ✅ **Manual Triggers**: GitHub UI से manual control
86
- ✅ **Security**: Secrets का safe उपयोग
87
- ✅ **Testing**: Publish से पहले automated tests
88
- ✅ **Version Management**: Automatic version bumping
89
- ✅ **GitHub Releases**: Auto-generated releases
90
- ✅ **Error Handling**: Comprehensive error reporting
91
- ✅ **Summary Reports**: Detailed workflow summaries
92
-
93
- ## 🔍 Troubleshooting
94
-
95
- ### Common Issues:
96
-
97
- 1. **Token Permissions**:
98
- - GH_TOKEN में सही permissions हों
99
- - NPM_TOKEN "Automation" type का हो
100
-
101
- 2. **Repository Access**:
102
- - Repository में Actions enabled हों
103
- - Secrets properly configured हों
104
-
105
- 3. **Publishing Errors**:
106
- - Package name conflicts check करें
107
- - NPM account verified हो
108
-
109
- ## 📞 Support
110
-
111
- अगर कोई issue आए तो GitHub Issues में report करें।
@@ -1,135 +0,0 @@
1
- name: 🚀 Build, Version & Publish to NPM
2
-
3
- on:
4
- push:
5
- branches: [main, master]
6
- paths-ignore:
7
- - 'README.md'
8
- - 'docs/**'
9
- - '*.md'
10
- - 'LICENSE.md'
11
- - '.gitignore'
12
-
13
- workflow_dispatch:
14
- inputs:
15
- increment_type:
16
- description: '📈 Version increment type'
17
- required: true
18
- default: 'patch'
19
- type: choice
20
- options:
21
- - patch
22
- - minor
23
- - major
24
- dry_run:
25
- description: '🧪 Dry run (check build/test without publishing to NPM)'
26
- required: false
27
- default: false
28
- type: boolean
29
-
30
- jobs:
31
- publish:
32
- name: 🚀 Publish to NPM
33
- runs-on: ubuntu-latest
34
- permissions:
35
- contents: write
36
- id-token: write
37
-
38
- steps:
39
- - name: 📥 Checkout Repository
40
- uses: actions/checkout@v4
41
- with:
42
- fetch-depth: 0
43
- token: ${{ secrets.GH_TOKEN || github.token }}
44
-
45
- - name: 🟢 Setup Node.js
46
- uses: actions/setup-node@v4
47
- with:
48
- node-version: '20'
49
- registry-url: 'https://registry.npmjs.org'
50
-
51
- - name: ⚙️ Configure Git
52
- run: |
53
- git config --global user.name "github-actions[bot]"
54
- git config --global user.email "41898282+github-actions[bot]@users.noreply.github.com"
55
-
56
- - name: 📦 Install Dependencies
57
- run: npm ci || npm install
58
-
59
- - name: 🧪 Pre-Publish Verification
60
- run: |
61
- echo "💡 Running basic syntax and file checks..."
62
- node -c lib/cjs/index.js
63
- node -c lib/esm/index.mjs
64
- echo "✅ Code syntax is valid."
65
-
66
- - name: 📈 Increment Version
67
- id: versioning
68
- run: |
69
- # Determine the increment type (major, minor, or patch)
70
- if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
71
- INCREMENT_TYPE="${{ github.event.inputs.increment_type }}"
72
- else
73
- COMMIT_MSG=$(git log -1 --pretty=%B)
74
- if echo "$COMMIT_MSG" | grep -qE "\[major\]|BREAKING CHANGE"; then
75
- INCREMENT_TYPE="major"
76
- elif echo "$COMMIT_MSG" | grep -qE "\[minor\]|feat:"; then
77
- INCREMENT_TYPE="minor"
78
- else
79
- INCREMENT_TYPE="patch"
80
- fi
81
- fi
82
-
83
- echo "📈 Selected increment type: $INCREMENT_TYPE"
84
-
85
- # Bump version, commit changes and create tag
86
- npm version $INCREMENT_TYPE -m "🔖 Release: v%s [skip ci]"
87
-
88
- # Capture new version for subsequent steps
89
- NEW_VERSION=$(node -p "require('./package.json').version")
90
- echo "NEW_VERSION=$NEW_VERSION" >> $GITHUB_ENV
91
- echo "version=v$NEW_VERSION" >> $GITHUB_OUTPUT
92
-
93
- - name: 🚀 Push Version Bump & Tag
94
- if: github.event.inputs.dry_run != 'true'
95
- run: |
96
- git push origin HEAD --follow-tags
97
-
98
- - name: 📦 Publish Package to NPM
99
- if: github.event.inputs.dry_run != 'true'
100
- run: |
101
- npm publish --access public
102
- env:
103
- NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
104
-
105
- - name: 📋 Create GitHub Release
106
- if: github.event.inputs.dry_run != 'true'
107
- run: |
108
- TAG="v${{ env.NEW_VERSION }}"
109
-
110
- cat > release_body.md << EOF
111
- ## 🚀 Real Browser MCP Server v${{ env.NEW_VERSION }}
112
-
113
- ### 📦 Published Packages
114
- - **NPM Package**: [real-browser-mcp-server](https://www.npmjs.com/package/real-browser-mcp-server)
115
- - **Stealth automation**: Powered by Patchright (undetected Playwright fork).
116
-
117
- ### 🛠️ Key Capabilities
118
- * **Turnstile Bypass**: Solves Cloudflare Turnstile automatically.
119
- * **Ad Blocker**: Integrated `@ghostery/adblocker-playwright` with binary caching.
120
- * **Stealth Evasion**: Passes advanced bot checkers like CreepJS, Datadome, Pixelscan, and FingerprintJS.
121
-
122
- ### 📥 Installation
123
- \`\`\`bash
124
- npm install real-browser-mcp-server@${{ env.NEW_VERSION }}
125
- \`\`\`
126
-
127
- ---
128
- *Auto-generated with ❤️ by GitHub Actions*
129
- EOF
130
-
131
- gh release create "$TAG" \
132
- --title "Release $TAG" \
133
- --notes-file release_body.md
134
- env:
135
- GITHUB_TOKEN: ${{ secrets.GH_TOKEN || github.token }}
package/Dockerfile DELETED
@@ -1,79 +0,0 @@
1
- # Stage 1: Build
2
- FROM node:20-slim AS builder
3
-
4
- WORKDIR /app
5
-
6
- # Copy package files first for better caching
7
- COPY package*.json ./
8
-
9
- # Install all dependencies (including devDependencies for build)
10
- RUN npm ci
11
-
12
- # Copy source files
13
- COPY . .
14
-
15
- # Stage 2: Production
16
- FROM node:20-slim AS production
17
-
18
- # Install Chromium and required dependencies
19
- RUN apt-get update && apt-get install -y \
20
- wget \
21
- gnupg \
22
- ca-certificates \
23
- apt-transport-https \
24
- chromium \
25
- fonts-liberation \
26
- libasound2 \
27
- libatk-bridge2.0-0 \
28
- libatk1.0-0 \
29
- libcups2 \
30
- libdbus-1-3 \
31
- libdrm2 \
32
- libgbm1 \
33
- libgtk-3-0 \
34
- libnspr4 \
35
- libnss3 \
36
- libxcomposite1 \
37
- libxdamage1 \
38
- libxfixes3 \
39
- libxkbcommon0 \
40
- libxrandr2 \
41
- xdg-utils \
42
- xvfb \
43
- && rm -rf /var/lib/apt/lists/* \
44
- && apt-get clean
45
-
46
- # Set Chrome binary path
47
- ENV CHROME_BIN=/usr/bin/chromium
48
-
49
- # Create non-root user for security
50
- RUN groupadd -r pptruser && useradd -r -g pptruser -G audio,video pptruser \
51
- && mkdir -p /home/pptruser/Downloads \
52
- && chown -R pptruser:pptruser /home/pptruser
53
-
54
- WORKDIR /app
55
-
56
- # Copy from builder stage
57
- COPY --from=builder /app/node_modules ./node_modules
58
- COPY --from=builder /app/package*.json ./
59
- COPY --from=builder /app/lib ./lib
60
- COPY --from=builder /app/test ./test
61
- COPY --from=builder /app/packages ./packages
62
- COPY --from=builder /app/typings.d.ts ./
63
-
64
- # Set ownership to non-root user
65
- RUN chown -R pptruser:pptruser /app
66
-
67
- # Switch to non-root user
68
- USER pptruser
69
-
70
- # Set headless mode for container
71
- ENV HEADLESS=true
72
- ENV NODE_ENV=production
73
-
74
- # Health check
75
- HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
76
- CMD node -e "console.log('OK')" || exit 1
77
-
78
- # Default command: run CJS tests
79
- CMD ["npm", "run", "cjs_test"]
Binary file
package/lib/cjs/index.js DELETED
@@ -1,249 +0,0 @@
1
- const { PlaywrightBlocker } = require("@ghostery/adblocker-playwright");
2
- const { pageController } = require("./module/pageController.js");
3
-
4
- // Dynamically load pure ESM playwright-ghost to be fully compatible with CommonJS
5
- const playwrightGhostPromise = import("playwright-ghost/patchright");
6
- const recommendedPromise = import("playwright-ghost/plugins/recommended");
7
- const fs = require('fs');
8
- const path = require('path');
9
-
10
- let adBlockerInstance = null;
11
- let adBlockerPromise = null;
12
- function getAdBlocker() {
13
- if (!adBlockerPromise) {
14
- const cachePath = path.join(__dirname, 'adblocker.bin');
15
- adBlockerPromise = PlaywrightBlocker.fromPrebuiltAdsAndTracking(fetch, {
16
- path: cachePath,
17
- read: fs.promises.readFile,
18
- write: fs.promises.writeFile,
19
- }).then(blocker => {
20
- adBlockerInstance = blocker;
21
- return blocker;
22
- }).catch(err => {
23
- console.error('[adblocker] Failed to initialize adblocker:', err.message);
24
- return null;
25
- });
26
- }
27
- return adBlockerPromise;
28
- }
29
-
30
- function loadEnvFile() {
31
- const envPaths = [
32
- path.join(process.cwd(), '.env'),
33
- ];
34
-
35
- let currentDir = process.cwd();
36
- for (let i = 0; i < 5; i++) {
37
- const envPath = path.join(currentDir, '.env');
38
- if (fs.existsSync(envPath) && !envPaths.includes(envPath)) {
39
- envPaths.push(envPath);
40
- }
41
- const parentDir = path.dirname(currentDir);
42
- if (parentDir === currentDir) break;
43
- currentDir = parentDir;
44
- }
45
-
46
- for (const envPath of envPaths) {
47
- try {
48
- if (fs.existsSync(envPath)) {
49
- const envContent = fs.readFileSync(envPath, 'utf-8');
50
- envContent.split('\n').forEach(line => {
51
- const trimmed = line.trim();
52
- if (trimmed && !trimmed.startsWith('#')) {
53
- const [key, ...valueParts] = trimmed.split('=');
54
- const value = valueParts.join('=').replace(/^["']|["']$/g, '');
55
- if (key && !process.env[key]) {
56
- process.env[key] = value;
57
- }
58
- }
59
- });
60
- break;
61
- }
62
- } catch (error) {
63
- // Silently ignore .env loading errors
64
- }
65
- }
66
- }
67
-
68
- loadEnvFile();
69
-
70
- function getDefaultHeadless() {
71
- const envHeadless = (process.env.HEADLESS || '').toLowerCase();
72
- return envHeadless === 'true';
73
- }
74
-
75
- function applyPuppeteerShims(browser, page) {
76
- if (page._shimsApplied) return page;
77
- page._shimsApplied = true;
78
-
79
- // Enable ad blocker
80
- if (adBlockerInstance) {
81
- adBlockerInstance.enableBlockingInPage(page).catch(() => {});
82
- } else {
83
- getAdBlocker().then(blocker => {
84
- if (blocker) {
85
- blocker.enableBlockingInPage(page).catch(() => {});
86
- }
87
- });
88
- }
89
-
90
- // Cookie shims (Puppeteer → Playwright context)
91
- if (!page.cookies) {
92
- page.cookies = async (urls) => {
93
- return await page.context().cookies(urls ? (Array.isArray(urls) ? urls : [urls]) : []);
94
- };
95
- }
96
-
97
- if (!page.setCookie) {
98
- page.setCookie = async (...cookies) => {
99
- const formatted = cookies.map(c => ({
100
- name: c.name,
101
- value: c.value,
102
- domain: c.domain || new URL(page.url()).hostname,
103
- path: c.path || '/',
104
- expires: c.expires || undefined,
105
- httpOnly: c.httpOnly,
106
- secure: c.secure,
107
- sameSite: c.sameSite
108
- }));
109
- await page.context().addCookies(formatted);
110
- };
111
- }
112
-
113
- if (!page.deleteCookie) {
114
- page.deleteCookie = async (...cookies) => {
115
- await page.context().clearCookies();
116
- };
117
- }
118
-
119
- // Navigation shims
120
- if (!page.waitForNetworkIdle) {
121
- page.waitForNetworkIdle = async (options = {}) => {
122
- try {
123
- await page.waitForLoadState('networkidle', { timeout: options.timeout });
124
- } catch (e) {
125
- // Ignore networkidle timeouts if they are non-fatal
126
- }
127
- };
128
- }
129
-
130
- if (!page.evaluateOnNewDocument) {
131
- page.evaluateOnNewDocument = async (fn, ...args) => {
132
- return await page.addInitScript(fn, ...args);
133
- };
134
- }
135
-
136
- // Ghost Cursor integration via playwright-ghost auto-hooking
137
- page.realCursor = {
138
- move: async (selector, options = {}) => {
139
- try {
140
- await page.hover(selector, options);
141
- } catch (e) {
142
- // Silently fallback if element is not found
143
- }
144
- }
145
- };
146
- page.realClick = async (selector, options = {}) => {
147
- await page.click(selector, options);
148
- };
149
-
150
- // Mouse wheel shim (Puppeteer object → Playwright positional args)
151
- if (page.mouse && page.mouse.wheel) {
152
- const originalWheel = page.mouse.wheel.bind(page.mouse);
153
- page.mouse.wheel = async (x, y) => {
154
- if (typeof x === 'object' && x !== null) {
155
- const deltaX = x.deltaX || 0;
156
- const deltaY = x.deltaY || 0;
157
- return await originalWheel(deltaX, deltaY);
158
- }
159
- return await originalWheel(x, y);
160
- };
161
- }
162
-
163
- // Browser shims
164
- if (!browser.process) {
165
- browser.process = () => ({
166
- pid: browser._childProcess?.pid || 1337
167
- });
168
- }
169
-
170
- if (!browser.pages) {
171
- browser.pages = async () => {
172
- return browser.contexts().flatMap(c => c.pages());
173
- };
174
- }
175
-
176
- return page;
177
- }
178
-
179
- async function connect({
180
- args = [],
181
- headless = getDefaultHeadless(),
182
- proxy = {},
183
- turnstile = false,
184
- } = {}) {
185
- let playwrightProxy = undefined;
186
- if (proxy && proxy.host && proxy.port) {
187
- playwrightProxy = {
188
- server: `${proxy.host}:${proxy.port}`
189
- };
190
- if (proxy.username && proxy.password) {
191
- playwrightProxy.username = proxy.username;
192
- playwrightProxy.password = proxy.password;
193
- }
194
- }
195
-
196
- const chromiumArgs = [
197
- '--disable-blink-features=AutomationControlled',
198
- '--no-sandbox',
199
- '--disable-setuid-sandbox',
200
- ...args
201
- ];
202
-
203
- // Load the dynamic ES Module imports
204
- const { default: playwright } = await playwrightGhostPromise;
205
- const { default: recommended } = await recommendedPromise;
206
- const { chromium } = playwright;
207
-
208
- const browser = await chromium.launch({
209
- headless,
210
- args: chromiumArgs,
211
- proxy: playwrightProxy,
212
- plugins: [recommended()]
213
- });
214
-
215
- // Ensure ad blocker is ready
216
- await getAdBlocker();
217
-
218
- const context = await browser.newContext({
219
- viewport: null,
220
- });
221
-
222
- let page = await context.newPage();
223
-
224
- applyPuppeteerShims(browser, page);
225
-
226
- page = await pageController({
227
- browser,
228
- page,
229
- proxy,
230
- turnstile,
231
- });
232
-
233
- context.on('page', async (newPage) => {
234
- applyPuppeteerShims(browser, newPage);
235
- await pageController({
236
- browser,
237
- page: newPage,
238
- proxy,
239
- turnstile,
240
- });
241
- });
242
-
243
- return {
244
- browser,
245
- page,
246
- };
247
- }
248
-
249
- module.exports = { connect };