claude-chrome-parallel 1.0.0
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/LICENSE +21 -0
- package/README.md +501 -0
- package/assets/demo.svg +278 -0
- package/dist/cdp/client.d.ts +218 -0
- package/dist/cdp/client.d.ts.map +1 -0
- package/dist/cdp/client.js +797 -0
- package/dist/cdp/client.js.map +1 -0
- package/dist/cdp/connection-pool.d.ts +125 -0
- package/dist/cdp/connection-pool.d.ts.map +1 -0
- package/dist/cdp/connection-pool.js +443 -0
- package/dist/cdp/connection-pool.js.map +1 -0
- package/dist/cdp/screenshot-scheduler.d.ts +54 -0
- package/dist/cdp/screenshot-scheduler.d.ts.map +1 -0
- package/dist/cdp/screenshot-scheduler.js +87 -0
- package/dist/cdp/screenshot-scheduler.js.map +1 -0
- package/dist/chrome/launcher.d.ts +55 -0
- package/dist/chrome/launcher.d.ts.map +1 -0
- package/dist/chrome/launcher.js +383 -0
- package/dist/chrome/launcher.js.map +1 -0
- package/dist/chrome/pool.d.ts +54 -0
- package/dist/chrome/pool.d.ts.map +1 -0
- package/dist/chrome/pool.js +301 -0
- package/dist/chrome/pool.js.map +1 -0
- package/dist/chrome/profile-detector.d.ts +52 -0
- package/dist/chrome/profile-detector.d.ts.map +1 -0
- package/dist/chrome/profile-detector.js +246 -0
- package/dist/chrome/profile-detector.js.map +1 -0
- package/dist/cli/claude-session.d.ts +11 -0
- package/dist/cli/claude-session.js +349 -0
- package/dist/cli/claude-session.js.map +1 -0
- package/dist/cli/index.d.ts +14 -0
- package/dist/cli/index.js +858 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/install.d.ts +16 -0
- package/dist/cli/install.js +185 -0
- package/dist/cli/install.js.map +1 -0
- package/dist/cli/uninstall.d.ts +7 -0
- package/dist/cli/uninstall.js +126 -0
- package/dist/cli/uninstall.js.map +1 -0
- package/dist/cli/update-check.d.ts +9 -0
- package/dist/cli/update-check.js +141 -0
- package/dist/cli/update-check.js.map +1 -0
- package/dist/config/config-recovery.d.ts +69 -0
- package/dist/config/config-recovery.d.ts.map +1 -0
- package/dist/config/config-recovery.js +302 -0
- package/dist/config/config-recovery.js.map +1 -0
- package/dist/config/global.d.ts +49 -0
- package/dist/config/global.d.ts.map +1 -0
- package/dist/config/global.js +24 -0
- package/dist/config/global.js.map +1 -0
- package/dist/config/index.d.ts +7 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +23 -0
- package/dist/config/index.js.map +1 -0
- package/dist/config/session-isolator.d.ts +76 -0
- package/dist/config/session-isolator.d.ts.map +1 -0
- package/dist/config/session-isolator.js +268 -0
- package/dist/config/session-isolator.js.map +1 -0
- package/dist/dashboard/activity-tracker.d.ts +76 -0
- package/dist/dashboard/activity-tracker.d.ts.map +1 -0
- package/dist/dashboard/activity-tracker.js +219 -0
- package/dist/dashboard/activity-tracker.js.map +1 -0
- package/dist/dashboard/ansi.d.ts +117 -0
- package/dist/dashboard/ansi.d.ts.map +1 -0
- package/dist/dashboard/ansi.js +199 -0
- package/dist/dashboard/ansi.js.map +1 -0
- package/dist/dashboard/index.d.ts +110 -0
- package/dist/dashboard/index.d.ts.map +1 -0
- package/dist/dashboard/index.js +412 -0
- package/dist/dashboard/index.js.map +1 -0
- package/dist/dashboard/keyboard-handler.d.ts +43 -0
- package/dist/dashboard/keyboard-handler.d.ts.map +1 -0
- package/dist/dashboard/keyboard-handler.js +215 -0
- package/dist/dashboard/keyboard-handler.js.map +1 -0
- package/dist/dashboard/operation-controller.d.ts +76 -0
- package/dist/dashboard/operation-controller.d.ts.map +1 -0
- package/dist/dashboard/operation-controller.js +167 -0
- package/dist/dashboard/operation-controller.js.map +1 -0
- package/dist/dashboard/renderer.d.ts +76 -0
- package/dist/dashboard/renderer.d.ts.map +1 -0
- package/dist/dashboard/renderer.js +193 -0
- package/dist/dashboard/renderer.js.map +1 -0
- package/dist/dashboard/types.d.ts +56 -0
- package/dist/dashboard/types.d.ts.map +1 -0
- package/dist/dashboard/types.js +12 -0
- package/dist/dashboard/types.js.map +1 -0
- package/dist/dashboard/views/main-view.d.ts +23 -0
- package/dist/dashboard/views/main-view.d.ts.map +1 -0
- package/dist/dashboard/views/main-view.js +143 -0
- package/dist/dashboard/views/main-view.js.map +1 -0
- package/dist/dashboard/views/sessions-view.d.ts +22 -0
- package/dist/dashboard/views/sessions-view.d.ts.map +1 -0
- package/dist/dashboard/views/sessions-view.js +104 -0
- package/dist/dashboard/views/sessions-view.js.map +1 -0
- package/dist/dashboard/views/tabs-view.d.ts +21 -0
- package/dist/dashboard/views/tabs-view.d.ts.map +1 -0
- package/dist/dashboard/views/tabs-view.js +92 -0
- package/dist/dashboard/views/tabs-view.js.map +1 -0
- package/dist/hints/hint-engine.d.ts +77 -0
- package/dist/hints/hint-engine.d.ts.map +1 -0
- package/dist/hints/hint-engine.js +191 -0
- package/dist/hints/hint-engine.js.map +1 -0
- package/dist/hints/index.d.ts +8 -0
- package/dist/hints/index.d.ts.map +1 -0
- package/dist/hints/index.js +11 -0
- package/dist/hints/index.js.map +1 -0
- package/dist/hints/pattern-learner.d.ts +76 -0
- package/dist/hints/pattern-learner.d.ts.map +1 -0
- package/dist/hints/pattern-learner.js +254 -0
- package/dist/hints/pattern-learner.js.map +1 -0
- package/dist/hints/rules/composite-suggestions.d.ts +6 -0
- package/dist/hints/rules/composite-suggestions.d.ts.map +1 -0
- package/dist/hints/rules/composite-suggestions.js +66 -0
- package/dist/hints/rules/composite-suggestions.js.map +1 -0
- package/dist/hints/rules/error-recovery.d.ts +7 -0
- package/dist/hints/rules/error-recovery.d.ts.map +1 -0
- package/dist/hints/rules/error-recovery.js +55 -0
- package/dist/hints/rules/error-recovery.js.map +1 -0
- package/dist/hints/rules/learned-rules.d.ts +13 -0
- package/dist/hints/rules/learned-rules.d.ts.map +1 -0
- package/dist/hints/rules/learned-rules.js +27 -0
- package/dist/hints/rules/learned-rules.js.map +1 -0
- package/dist/hints/rules/repetition-detection.d.ts +7 -0
- package/dist/hints/rules/repetition-detection.d.ts.map +1 -0
- package/dist/hints/rules/repetition-detection.js +82 -0
- package/dist/hints/rules/repetition-detection.js.map +1 -0
- package/dist/hints/rules/sequence-detection.d.ts +6 -0
- package/dist/hints/rules/sequence-detection.d.ts.map +1 -0
- package/dist/hints/rules/sequence-detection.js +89 -0
- package/dist/hints/rules/sequence-detection.js.map +1 -0
- package/dist/hints/rules/success-hints.d.ts +6 -0
- package/dist/hints/rules/success-hints.d.ts.map +1 -0
- package/dist/hints/rules/success-hints.js +62 -0
- package/dist/hints/rules/success-hints.js.map +1 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +272 -0
- package/dist/index.js.map +1 -0
- package/dist/lightpanda/launcher.d.ts +58 -0
- package/dist/lightpanda/launcher.d.ts.map +1 -0
- package/dist/lightpanda/launcher.js +199 -0
- package/dist/lightpanda/launcher.js.map +1 -0
- package/dist/mcp-server.d.ts +129 -0
- package/dist/mcp-server.d.ts.map +1 -0
- package/dist/mcp-server.js +641 -0
- package/dist/mcp-server.js.map +1 -0
- package/dist/memory/domain-memory.d.ts +68 -0
- package/dist/memory/domain-memory.d.ts.map +1 -0
- package/dist/memory/domain-memory.js +227 -0
- package/dist/memory/domain-memory.js.map +1 -0
- package/dist/orchestration/plan-executor.d.ts +19 -0
- package/dist/orchestration/plan-executor.d.ts.map +1 -0
- package/dist/orchestration/plan-executor.js +284 -0
- package/dist/orchestration/plan-executor.js.map +1 -0
- package/dist/orchestration/plan-registry.d.ts +55 -0
- package/dist/orchestration/plan-registry.d.ts.map +1 -0
- package/dist/orchestration/plan-registry.js +255 -0
- package/dist/orchestration/plan-registry.js.map +1 -0
- package/dist/orchestration/state-manager.d.ts +127 -0
- package/dist/orchestration/state-manager.d.ts.map +1 -0
- package/dist/orchestration/state-manager.js +438 -0
- package/dist/orchestration/state-manager.js.map +1 -0
- package/dist/orchestration/workflow-engine.d.ts +162 -0
- package/dist/orchestration/workflow-engine.d.ts.map +1 -0
- package/dist/orchestration/workflow-engine.js +731 -0
- package/dist/orchestration/workflow-engine.js.map +1 -0
- package/dist/resources/usage-guide.d.ts +13 -0
- package/dist/resources/usage-guide.d.ts.map +1 -0
- package/dist/resources/usage-guide.js +101 -0
- package/dist/resources/usage-guide.js.map +1 -0
- package/dist/router/browser-router.d.ts +51 -0
- package/dist/router/browser-router.d.ts.map +1 -0
- package/dist/router/browser-router.js +178 -0
- package/dist/router/browser-router.js.map +1 -0
- package/dist/router/cookie-sync.d.ts +48 -0
- package/dist/router/cookie-sync.d.ts.map +1 -0
- package/dist/router/cookie-sync.js +106 -0
- package/dist/router/cookie-sync.js.map +1 -0
- package/dist/router/index.d.ts +5 -0
- package/dist/router/index.d.ts.map +1 -0
- package/dist/router/index.js +10 -0
- package/dist/router/index.js.map +1 -0
- package/dist/router/tool-routing-registry.d.ts +21 -0
- package/dist/router/tool-routing-registry.d.ts.map +1 -0
- package/dist/router/tool-routing-registry.js +90 -0
- package/dist/router/tool-routing-registry.js.map +1 -0
- package/dist/session-manager.d.ts +251 -0
- package/dist/session-manager.d.ts.map +1 -0
- package/dist/session-manager.js +912 -0
- package/dist/session-manager.js.map +1 -0
- package/dist/tools/batch-execute.d.ts +11 -0
- package/dist/tools/batch-execute.d.ts.map +1 -0
- package/dist/tools/batch-execute.js +226 -0
- package/dist/tools/batch-execute.js.map +1 -0
- package/dist/tools/click-element.d.ts +8 -0
- package/dist/tools/click-element.d.ts.map +1 -0
- package/dist/tools/click-element.js +455 -0
- package/dist/tools/click-element.js.map +1 -0
- package/dist/tools/computer.d.ts +6 -0
- package/dist/tools/computer.d.ts.map +1 -0
- package/dist/tools/computer.js +638 -0
- package/dist/tools/computer.js.map +1 -0
- package/dist/tools/console-capture.d.ts +6 -0
- package/dist/tools/console-capture.d.ts.map +1 -0
- package/dist/tools/console-capture.js +320 -0
- package/dist/tools/console-capture.js.map +1 -0
- package/dist/tools/cookies.d.ts +6 -0
- package/dist/tools/cookies.d.ts.map +1 -0
- package/dist/tools/cookies.js +263 -0
- package/dist/tools/cookies.js.map +1 -0
- package/dist/tools/drag-drop.d.ts +6 -0
- package/dist/tools/drag-drop.d.ts.map +1 -0
- package/dist/tools/drag-drop.js +252 -0
- package/dist/tools/drag-drop.js.map +1 -0
- package/dist/tools/emulate-device.d.ts +6 -0
- package/dist/tools/emulate-device.d.ts.map +1 -0
- package/dist/tools/emulate-device.js +221 -0
- package/dist/tools/emulate-device.js.map +1 -0
- package/dist/tools/file-upload.d.ts +6 -0
- package/dist/tools/file-upload.d.ts.map +1 -0
- package/dist/tools/file-upload.js +208 -0
- package/dist/tools/file-upload.js.map +1 -0
- package/dist/tools/fill-form.d.ts +8 -0
- package/dist/tools/fill-form.d.ts.map +1 -0
- package/dist/tools/fill-form.js +342 -0
- package/dist/tools/fill-form.js.map +1 -0
- package/dist/tools/find.d.ts +6 -0
- package/dist/tools/find.d.ts.map +1 -0
- package/dist/tools/find.js +330 -0
- package/dist/tools/find.js.map +1 -0
- package/dist/tools/form-input.d.ts +6 -0
- package/dist/tools/form-input.d.ts.map +1 -0
- package/dist/tools/form-input.js +181 -0
- package/dist/tools/form-input.js.map +1 -0
- package/dist/tools/geolocation.d.ts +6 -0
- package/dist/tools/geolocation.d.ts.map +1 -0
- package/dist/tools/geolocation.js +172 -0
- package/dist/tools/geolocation.js.map +1 -0
- package/dist/tools/http-auth.d.ts +6 -0
- package/dist/tools/http-auth.d.ts.map +1 -0
- package/dist/tools/http-auth.js +136 -0
- package/dist/tools/http-auth.js.map +1 -0
- package/dist/tools/index.d.ts +6 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +104 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/javascript.d.ts +6 -0
- package/dist/tools/javascript.d.ts.map +1 -0
- package/dist/tools/javascript.js +138 -0
- package/dist/tools/javascript.js.map +1 -0
- package/dist/tools/lightweight-scroll.d.ts +11 -0
- package/dist/tools/lightweight-scroll.d.ts.map +1 -0
- package/dist/tools/lightweight-scroll.js +266 -0
- package/dist/tools/lightweight-scroll.js.map +1 -0
- package/dist/tools/memory.d.ts +10 -0
- package/dist/tools/memory.d.ts.map +1 -0
- package/dist/tools/memory.js +141 -0
- package/dist/tools/memory.js.map +1 -0
- package/dist/tools/navigate.d.ts +6 -0
- package/dist/tools/navigate.d.ts.map +1 -0
- package/dist/tools/navigate.js +241 -0
- package/dist/tools/navigate.js.map +1 -0
- package/dist/tools/network.d.ts +6 -0
- package/dist/tools/network.d.ts.map +1 -0
- package/dist/tools/network.js +215 -0
- package/dist/tools/network.js.map +1 -0
- package/dist/tools/orchestration.d.ts +6 -0
- package/dist/tools/orchestration.d.ts.map +1 -0
- package/dist/tools/orchestration.js +746 -0
- package/dist/tools/orchestration.js.map +1 -0
- package/dist/tools/page-content.d.ts +6 -0
- package/dist/tools/page-content.d.ts.map +1 -0
- package/dist/tools/page-content.js +120 -0
- package/dist/tools/page-content.js.map +1 -0
- package/dist/tools/page-pdf.d.ts +6 -0
- package/dist/tools/page-pdf.d.ts.map +1 -0
- package/dist/tools/page-pdf.js +245 -0
- package/dist/tools/page-pdf.js.map +1 -0
- package/dist/tools/page-reload.d.ts +6 -0
- package/dist/tools/page-reload.d.ts.map +1 -0
- package/dist/tools/page-reload.js +89 -0
- package/dist/tools/page-reload.js.map +1 -0
- package/dist/tools/performance-metrics.d.ts +6 -0
- package/dist/tools/performance-metrics.d.ts.map +1 -0
- package/dist/tools/performance-metrics.js +158 -0
- package/dist/tools/performance-metrics.js.map +1 -0
- package/dist/tools/read-page.d.ts +6 -0
- package/dist/tools/read-page.d.ts.map +1 -0
- package/dist/tools/read-page.js +287 -0
- package/dist/tools/read-page.js.map +1 -0
- package/dist/tools/request-intercept.d.ts +6 -0
- package/dist/tools/request-intercept.d.ts.map +1 -0
- package/dist/tools/request-intercept.js +439 -0
- package/dist/tools/request-intercept.js.map +1 -0
- package/dist/tools/selector-query.d.ts +6 -0
- package/dist/tools/selector-query.d.ts.map +1 -0
- package/dist/tools/selector-query.js +206 -0
- package/dist/tools/selector-query.js.map +1 -0
- package/dist/tools/shutdown.d.ts +12 -0
- package/dist/tools/shutdown.d.ts.map +1 -0
- package/dist/tools/shutdown.js +120 -0
- package/dist/tools/shutdown.js.map +1 -0
- package/dist/tools/storage.d.ts +6 -0
- package/dist/tools/storage.d.ts.map +1 -0
- package/dist/tools/storage.js +264 -0
- package/dist/tools/storage.js.map +1 -0
- package/dist/tools/tabs-close.d.ts +6 -0
- package/dist/tools/tabs-close.d.ts.map +1 -0
- package/dist/tools/tabs-close.js +124 -0
- package/dist/tools/tabs-close.js.map +1 -0
- package/dist/tools/tabs-context.d.ts +6 -0
- package/dist/tools/tabs-context.d.ts.map +1 -0
- package/dist/tools/tabs-context.js +92 -0
- package/dist/tools/tabs-context.js.map +1 -0
- package/dist/tools/tabs-create.d.ts +6 -0
- package/dist/tools/tabs-create.d.ts.map +1 -0
- package/dist/tools/tabs-create.js +73 -0
- package/dist/tools/tabs-create.js.map +1 -0
- package/dist/tools/user-agent.d.ts +6 -0
- package/dist/tools/user-agent.d.ts.map +1 -0
- package/dist/tools/user-agent.js +128 -0
- package/dist/tools/user-agent.js.map +1 -0
- package/dist/tools/wait-and-click.d.ts +8 -0
- package/dist/tools/wait-and-click.d.ts.map +1 -0
- package/dist/tools/wait-and-click.js +290 -0
- package/dist/tools/wait-and-click.js.map +1 -0
- package/dist/tools/wait-for.d.ts +6 -0
- package/dist/tools/wait-for.d.ts.map +1 -0
- package/dist/tools/wait-for.js +248 -0
- package/dist/tools/wait-for.js.map +1 -0
- package/dist/tools/worker-create.d.ts +7 -0
- package/dist/tools/worker-create.d.ts.map +1 -0
- package/dist/tools/worker-create.js +62 -0
- package/dist/tools/worker-create.js.map +1 -0
- package/dist/tools/worker-delete.d.ts +6 -0
- package/dist/tools/worker-delete.d.ts.map +1 -0
- package/dist/tools/worker-delete.js +80 -0
- package/dist/tools/worker-delete.js.map +1 -0
- package/dist/tools/worker-list.d.ts +6 -0
- package/dist/tools/worker-list.d.ts.map +1 -0
- package/dist/tools/worker-list.js +67 -0
- package/dist/tools/worker-list.js.map +1 -0
- package/dist/tools/xpath-query.d.ts +6 -0
- package/dist/tools/xpath-query.d.ts.map +1 -0
- package/dist/tools/xpath-query.js +230 -0
- package/dist/tools/xpath-query.js.map +1 -0
- package/dist/types/browser-backend.d.ts +30 -0
- package/dist/types/browser-backend.d.ts.map +1 -0
- package/dist/types/browser-backend.js +9 -0
- package/dist/types/browser-backend.js.map +1 -0
- package/dist/types/index.d.ts +3 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +19 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/mcp.d.ts +54 -0
- package/dist/types/mcp.d.ts.map +1 -0
- package/dist/types/mcp.js +14 -0
- package/dist/types/mcp.js.map +1 -0
- package/dist/types/plan-cache.d.ts +121 -0
- package/dist/types/plan-cache.d.ts.map +1 -0
- package/dist/types/plan-cache.js +9 -0
- package/dist/types/plan-cache.js.map +1 -0
- package/dist/types/profile.d.ts +76 -0
- package/dist/types/profile.d.ts.map +1 -0
- package/dist/types/profile.js +35 -0
- package/dist/types/profile.js.map +1 -0
- package/dist/types/session.d.ts +65 -0
- package/dist/types/session.d.ts.map +1 -0
- package/dist/types/session.js +6 -0
- package/dist/types/session.js.map +1 -0
- package/dist/types/tool-manifest.d.ts +52 -0
- package/dist/types/tool-manifest.d.ts.map +1 -0
- package/dist/types/tool-manifest.js +37 -0
- package/dist/types/tool-manifest.js.map +1 -0
- package/dist/utils/atomic-file.d.ts +50 -0
- package/dist/utils/atomic-file.d.ts.map +1 -0
- package/dist/utils/atomic-file.js +217 -0
- package/dist/utils/atomic-file.js.map +1 -0
- package/dist/utils/index.d.ts +6 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +22 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/json-validator.d.ts +40 -0
- package/dist/utils/json-validator.d.ts.map +1 -0
- package/dist/utils/json-validator.js +295 -0
- package/dist/utils/json-validator.js.map +1 -0
- package/dist/utils/ref-id-manager.d.ts +26 -0
- package/dist/utils/ref-id-manager.d.ts.map +1 -0
- package/dist/utils/ref-id-manager.js +81 -0
- package/dist/utils/ref-id-manager.js.map +1 -0
- package/dist/utils/request-queue.d.ts +37 -0
- package/dist/utils/request-queue.d.ts.map +1 -0
- package/dist/utils/request-queue.js +110 -0
- package/dist/utils/request-queue.js.map +1 -0
- package/package.json +78 -0
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Screenshot Scheduler - Concurrency-controlled screenshot pipeline
|
|
3
|
+
*
|
|
4
|
+
* Prevents GPU/renderer contention when multiple tabs request
|
|
5
|
+
* screenshots simultaneously. Without this, 20 concurrent screenshot
|
|
6
|
+
* requests serialize through Chrome's renderer, causing 185s+ timeouts.
|
|
7
|
+
*
|
|
8
|
+
* Performance impact: 20 concurrent screenshots from 4000ms to ~800ms
|
|
9
|
+
*/
|
|
10
|
+
import { Page } from 'puppeteer-core';
|
|
11
|
+
import { CDPClient } from './client';
|
|
12
|
+
export interface ScreenshotOptions {
|
|
13
|
+
format?: 'webp' | 'png' | 'jpeg';
|
|
14
|
+
quality?: number;
|
|
15
|
+
fullPage?: boolean;
|
|
16
|
+
clip?: {
|
|
17
|
+
x: number;
|
|
18
|
+
y: number;
|
|
19
|
+
width: number;
|
|
20
|
+
height: number;
|
|
21
|
+
scale?: number;
|
|
22
|
+
};
|
|
23
|
+
optimizeForSpeed?: boolean;
|
|
24
|
+
}
|
|
25
|
+
export interface ScreenshotResult {
|
|
26
|
+
data: string;
|
|
27
|
+
durationMs: number;
|
|
28
|
+
waitMs: number;
|
|
29
|
+
}
|
|
30
|
+
export interface SchedulerStats {
|
|
31
|
+
pending: number;
|
|
32
|
+
active: number;
|
|
33
|
+
completed: number;
|
|
34
|
+
totalWaitMs: number;
|
|
35
|
+
totalCaptureMs: number;
|
|
36
|
+
concurrency: number;
|
|
37
|
+
}
|
|
38
|
+
export declare class ScreenshotScheduler {
|
|
39
|
+
private readonly concurrency;
|
|
40
|
+
private active;
|
|
41
|
+
private queue;
|
|
42
|
+
private completed;
|
|
43
|
+
private totalWaitMs;
|
|
44
|
+
private totalCaptureMs;
|
|
45
|
+
constructor(concurrency?: number);
|
|
46
|
+
/**
|
|
47
|
+
* Capture a screenshot with concurrency control.
|
|
48
|
+
* Queues the request if too many are already in flight.
|
|
49
|
+
*/
|
|
50
|
+
capture(page: Page, cdpClient: CDPClient, options?: ScreenshotOptions): Promise<ScreenshotResult>;
|
|
51
|
+
getStats(): SchedulerStats;
|
|
52
|
+
}
|
|
53
|
+
export declare function getScreenshotScheduler(): ScreenshotScheduler;
|
|
54
|
+
//# sourceMappingURL=screenshot-scheduler.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"screenshot-scheduler.d.ts","sourceRoot":"","sources":["../../src/cdp/screenshot-scheduler.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,gBAAgB,CAAC;AACtC,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAErC,MAAM,WAAW,iBAAiB;IAChC,MAAM,CAAC,EAAE,MAAM,GAAG,KAAK,GAAG,MAAM,CAAC;IACjC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,IAAI,CAAC,EAAE;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC/E,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B;AAED,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,MAAM,CAAC;IACvB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,qBAAa,mBAAmB;IAQ5B,OAAO,CAAC,QAAQ,CAAC,WAAW;IAP9B,OAAO,CAAC,MAAM,CAAK;IACnB,OAAO,CAAC,KAAK,CAAyB;IACtC,OAAO,CAAC,SAAS,CAAK;IACtB,OAAO,CAAC,WAAW,CAAK;IACxB,OAAO,CAAC,cAAc,CAAK;gBAGR,WAAW,GAAE,MAAU;IAG1C;;;OAGG;IACG,OAAO,CACX,IAAI,EAAE,IAAI,EACV,SAAS,EAAE,SAAS,EACpB,OAAO,GAAE,iBAAsB,GAC9B,OAAO,CAAC,gBAAgB,CAAC;IAmD5B,QAAQ,IAAI,cAAc;CAU3B;AAKD,wBAAgB,sBAAsB,IAAI,mBAAmB,CAM5D"}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Screenshot Scheduler - Concurrency-controlled screenshot pipeline
|
|
4
|
+
*
|
|
5
|
+
* Prevents GPU/renderer contention when multiple tabs request
|
|
6
|
+
* screenshots simultaneously. Without this, 20 concurrent screenshot
|
|
7
|
+
* requests serialize through Chrome's renderer, causing 185s+ timeouts.
|
|
8
|
+
*
|
|
9
|
+
* Performance impact: 20 concurrent screenshots from 4000ms to ~800ms
|
|
10
|
+
*/
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.ScreenshotScheduler = void 0;
|
|
13
|
+
exports.getScreenshotScheduler = getScreenshotScheduler;
|
|
14
|
+
class ScreenshotScheduler {
|
|
15
|
+
concurrency;
|
|
16
|
+
active = 0;
|
|
17
|
+
queue = [];
|
|
18
|
+
completed = 0;
|
|
19
|
+
totalWaitMs = 0;
|
|
20
|
+
totalCaptureMs = 0;
|
|
21
|
+
constructor(concurrency = 5) {
|
|
22
|
+
this.concurrency = concurrency;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Capture a screenshot with concurrency control.
|
|
26
|
+
* Queues the request if too many are already in flight.
|
|
27
|
+
*/
|
|
28
|
+
async capture(page, cdpClient, options = {}) {
|
|
29
|
+
const queuedAt = Date.now();
|
|
30
|
+
// Wait for a slot if at capacity
|
|
31
|
+
if (this.active >= this.concurrency) {
|
|
32
|
+
await new Promise((resolve) => this.queue.push(resolve));
|
|
33
|
+
}
|
|
34
|
+
this.active++;
|
|
35
|
+
const waitMs = Date.now() - queuedAt;
|
|
36
|
+
const captureStart = Date.now();
|
|
37
|
+
try {
|
|
38
|
+
const format = options.format || 'webp';
|
|
39
|
+
const quality = options.quality ?? 60;
|
|
40
|
+
const params = {
|
|
41
|
+
format,
|
|
42
|
+
quality,
|
|
43
|
+
optimizeForSpeed: options.optimizeForSpeed ?? true,
|
|
44
|
+
};
|
|
45
|
+
if (options.clip) {
|
|
46
|
+
params.clip = options.clip;
|
|
47
|
+
}
|
|
48
|
+
if (options.fullPage) {
|
|
49
|
+
params.captureBeyondViewport = true;
|
|
50
|
+
}
|
|
51
|
+
const { data } = await cdpClient.send(page, 'Page.captureScreenshot', params);
|
|
52
|
+
const durationMs = Date.now() - captureStart;
|
|
53
|
+
this.completed++;
|
|
54
|
+
this.totalWaitMs += waitMs;
|
|
55
|
+
this.totalCaptureMs += durationMs;
|
|
56
|
+
return { data, durationMs, waitMs };
|
|
57
|
+
}
|
|
58
|
+
finally {
|
|
59
|
+
this.active--;
|
|
60
|
+
if (this.queue.length > 0) {
|
|
61
|
+
const next = this.queue.shift();
|
|
62
|
+
next();
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
getStats() {
|
|
67
|
+
return {
|
|
68
|
+
pending: this.queue.length,
|
|
69
|
+
active: this.active,
|
|
70
|
+
completed: this.completed,
|
|
71
|
+
totalWaitMs: this.totalWaitMs,
|
|
72
|
+
totalCaptureMs: this.totalCaptureMs,
|
|
73
|
+
concurrency: this.concurrency,
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
exports.ScreenshotScheduler = ScreenshotScheduler;
|
|
78
|
+
// Singleton instance
|
|
79
|
+
let schedulerInstance = null;
|
|
80
|
+
function getScreenshotScheduler() {
|
|
81
|
+
if (!schedulerInstance) {
|
|
82
|
+
const concurrency = parseInt(process.env.SCREENSHOT_CONCURRENCY || '5', 10);
|
|
83
|
+
schedulerInstance = new ScreenshotScheduler(concurrency);
|
|
84
|
+
}
|
|
85
|
+
return schedulerInstance;
|
|
86
|
+
}
|
|
87
|
+
//# sourceMappingURL=screenshot-scheduler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"screenshot-scheduler.js","sourceRoot":"","sources":["../../src/cdp/screenshot-scheduler.ts"],"names":[],"mappings":";AAAA;;;;;;;;GAQG;;;AAiHH,wDAMC;AA3FD,MAAa,mBAAmB;IAQX;IAPX,MAAM,GAAG,CAAC,CAAC;IACX,KAAK,GAAsB,EAAE,CAAC;IAC9B,SAAS,GAAG,CAAC,CAAC;IACd,WAAW,GAAG,CAAC,CAAC;IAChB,cAAc,GAAG,CAAC,CAAC;IAE3B,YACmB,cAAsB,CAAC;QAAvB,gBAAW,GAAX,WAAW,CAAY;IACvC,CAAC;IAEJ;;;OAGG;IACH,KAAK,CAAC,OAAO,CACX,IAAU,EACV,SAAoB,EACpB,UAA6B,EAAE;QAE/B,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAE5B,iCAAiC;QACjC,IAAI,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;YACpC,MAAM,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC;QACjE,CAAC;QAED,IAAI,CAAC,MAAM,EAAE,CAAC;QACd,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,QAAQ,CAAC;QACrC,MAAM,YAAY,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAEhC,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,MAAM,CAAC;YACxC,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,IAAI,EAAE,CAAC;YAEtC,MAAM,MAAM,GAA4B;gBACtC,MAAM;gBACN,OAAO;gBACP,gBAAgB,EAAE,OAAO,CAAC,gBAAgB,IAAI,IAAI;aACnD,CAAC;YAEF,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC;gBACjB,MAAM,CAAC,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;YAC7B,CAAC;YAED,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC;gBACrB,MAAM,CAAC,qBAAqB,GAAG,IAAI,CAAC;YACtC,CAAC;YAED,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,SAAS,CAAC,IAAI,CACnC,IAAI,EACJ,wBAAwB,EACxB,MAAM,CACP,CAAC;YAEF,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,YAAY,CAAC;YAC7C,IAAI,CAAC,SAAS,EAAE,CAAC;YACjB,IAAI,CAAC,WAAW,IAAI,MAAM,CAAC;YAC3B,IAAI,CAAC,cAAc,IAAI,UAAU,CAAC;YAElC,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,EAAE,CAAC;QACtC,CAAC;gBAAS,CAAC;YACT,IAAI,CAAC,MAAM,EAAE,CAAC;YACd,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAC1B,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,EAAG,CAAC;gBACjC,IAAI,EAAE,CAAC;YACT,CAAC;QACH,CAAC;IACH,CAAC;IAED,QAAQ;QACN,OAAO;YACL,OAAO,EAAE,IAAI,CAAC,KAAK,CAAC,MAAM;YAC1B,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,SAAS,EAAE,IAAI,CAAC,SAAS;YACzB,WAAW,EAAE,IAAI,CAAC,WAAW;YAC7B,cAAc,EAAE,IAAI,CAAC,cAAc;YACnC,WAAW,EAAE,IAAI,CAAC,WAAW;SAC9B,CAAC;IACJ,CAAC;CACF;AAhFD,kDAgFC;AAED,qBAAqB;AACrB,IAAI,iBAAiB,GAA+B,IAAI,CAAC;AAEzD,SAAgB,sBAAsB;IACpC,IAAI,CAAC,iBAAiB,EAAE,CAAC;QACvB,MAAM,WAAW,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,sBAAsB,IAAI,GAAG,EAAE,EAAE,CAAC,CAAC;QAC5E,iBAAiB,GAAG,IAAI,mBAAmB,CAAC,WAAW,CAAC,CAAC;IAC3D,CAAC;IACD,OAAO,iBAAiB,CAAC;AAC3B,CAAC"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Chrome Launcher - Manages Chrome process with remote debugging
|
|
3
|
+
*/
|
|
4
|
+
import { ChildProcess } from 'child_process';
|
|
5
|
+
export interface ChromeInstance {
|
|
6
|
+
wsEndpoint: string;
|
|
7
|
+
httpEndpoint: string;
|
|
8
|
+
process?: ChildProcess;
|
|
9
|
+
userDataDir?: string;
|
|
10
|
+
}
|
|
11
|
+
export interface LaunchOptions {
|
|
12
|
+
port?: number;
|
|
13
|
+
userDataDir?: string;
|
|
14
|
+
headless?: boolean;
|
|
15
|
+
/** If false, don't auto-launch Chrome when not running (default: false) */
|
|
16
|
+
autoLaunch?: boolean;
|
|
17
|
+
/** If true, force using a temp directory instead of real Chrome profile */
|
|
18
|
+
useTempProfile?: boolean;
|
|
19
|
+
}
|
|
20
|
+
export declare class ChromeLauncher {
|
|
21
|
+
private instance;
|
|
22
|
+
private port;
|
|
23
|
+
private usingRealProfile;
|
|
24
|
+
constructor(port?: number);
|
|
25
|
+
/**
|
|
26
|
+
* Ensure Chrome with remote debugging is available
|
|
27
|
+
*/
|
|
28
|
+
ensureChrome(options?: LaunchOptions): Promise<ChromeInstance>;
|
|
29
|
+
/**
|
|
30
|
+
* Get debug endpoint URL
|
|
31
|
+
*/
|
|
32
|
+
getDebugEndpoint(): Promise<string>;
|
|
33
|
+
/**
|
|
34
|
+
* Get WebSocket endpoint
|
|
35
|
+
*/
|
|
36
|
+
getWsEndpoint(): Promise<string>;
|
|
37
|
+
/**
|
|
38
|
+
* Close Chrome instance (only if we launched it)
|
|
39
|
+
*/
|
|
40
|
+
close(): Promise<void>;
|
|
41
|
+
/**
|
|
42
|
+
* Check if connected
|
|
43
|
+
*/
|
|
44
|
+
isConnected(): boolean;
|
|
45
|
+
/**
|
|
46
|
+
* Get the real Chrome profile directory for the current platform
|
|
47
|
+
*/
|
|
48
|
+
private getRealChromeProfileDir;
|
|
49
|
+
/**
|
|
50
|
+
* Check if a Chrome profile directory is locked by another Chrome instance
|
|
51
|
+
*/
|
|
52
|
+
private isProfileLocked;
|
|
53
|
+
}
|
|
54
|
+
export declare function getChromeLauncher(port?: number): ChromeLauncher;
|
|
55
|
+
//# sourceMappingURL=launcher.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"launcher.d.ts","sourceRoot":"","sources":["../../src/chrome/launcher.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAS,YAAY,EAAY,MAAM,eAAe,CAAC;AAO9D,MAAM,WAAW,cAAc;IAC7B,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,YAAY,CAAC;IACvB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,2EAA2E;IAC3E,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,2EAA2E;IAC3E,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AA0HD,qBAAa,cAAc;IACzB,OAAO,CAAC,QAAQ,CAA+B;IAC/C,OAAO,CAAC,IAAI,CAAS;IACrB,OAAO,CAAC,gBAAgB,CAAS;gBAErB,IAAI,GAAE,MAAqB;IAIvC;;OAEG;IACG,YAAY,CAAC,OAAO,GAAE,aAAkB,GAAG,OAAO,CAAC,cAAc,CAAC;IAuJxE;;OAEG;IACG,gBAAgB,IAAI,OAAO,CAAC,MAAM,CAAC;IAOzC;;OAEG;IACG,aAAa,IAAI,OAAO,CAAC,MAAM,CAAC;IAOtC;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAiB5B;;OAEG;IACH,WAAW,IAAI,OAAO;IAItB;;OAEG;IACH,OAAO,CAAC,uBAAuB;IAkB/B;;OAEG;IACH,OAAO,CAAC,eAAe;CAiBxB;AAKD,wBAAgB,iBAAiB,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,cAAc,CAK/D"}
|
|
@@ -0,0 +1,383 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Chrome Launcher - Manages Chrome process with remote debugging
|
|
4
|
+
*/
|
|
5
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
6
|
+
if (k2 === undefined) k2 = k;
|
|
7
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
8
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
9
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
10
|
+
}
|
|
11
|
+
Object.defineProperty(o, k2, desc);
|
|
12
|
+
}) : (function(o, m, k, k2) {
|
|
13
|
+
if (k2 === undefined) k2 = k;
|
|
14
|
+
o[k2] = m[k];
|
|
15
|
+
}));
|
|
16
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
17
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
18
|
+
}) : function(o, v) {
|
|
19
|
+
o["default"] = v;
|
|
20
|
+
});
|
|
21
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
22
|
+
var ownKeys = function(o) {
|
|
23
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
24
|
+
var ar = [];
|
|
25
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
26
|
+
return ar;
|
|
27
|
+
};
|
|
28
|
+
return ownKeys(o);
|
|
29
|
+
};
|
|
30
|
+
return function (mod) {
|
|
31
|
+
if (mod && mod.__esModule) return mod;
|
|
32
|
+
var result = {};
|
|
33
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
34
|
+
__setModuleDefault(result, mod);
|
|
35
|
+
return result;
|
|
36
|
+
};
|
|
37
|
+
})();
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.ChromeLauncher = void 0;
|
|
40
|
+
exports.getChromeLauncher = getChromeLauncher;
|
|
41
|
+
const child_process_1 = require("child_process");
|
|
42
|
+
const path = __importStar(require("path"));
|
|
43
|
+
const fs = __importStar(require("fs"));
|
|
44
|
+
const os = __importStar(require("os"));
|
|
45
|
+
const http = __importStar(require("http"));
|
|
46
|
+
const global_1 = require("../config/global");
|
|
47
|
+
const DEFAULT_PORT = 9222;
|
|
48
|
+
/**
|
|
49
|
+
* Find Chrome executable path based on platform
|
|
50
|
+
*/
|
|
51
|
+
function findChromePath() {
|
|
52
|
+
const platform = os.platform();
|
|
53
|
+
if (platform === 'win32') {
|
|
54
|
+
const paths = [
|
|
55
|
+
process.env['PROGRAMFILES(X86)'] + '\\Google\\Chrome\\Application\\chrome.exe',
|
|
56
|
+
process.env['PROGRAMFILES'] + '\\Google\\Chrome\\Application\\chrome.exe',
|
|
57
|
+
process.env['LOCALAPPDATA'] + '\\Google\\Chrome\\Application\\chrome.exe',
|
|
58
|
+
];
|
|
59
|
+
for (const p of paths) {
|
|
60
|
+
if (fs.existsSync(p))
|
|
61
|
+
return p;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
else if (platform === 'darwin') {
|
|
65
|
+
const paths = [
|
|
66
|
+
'/Applications/Google Chrome.app/Contents/MacOS/Google Chrome',
|
|
67
|
+
'/Applications/Chromium.app/Contents/MacOS/Chromium',
|
|
68
|
+
];
|
|
69
|
+
for (const p of paths) {
|
|
70
|
+
if (fs.existsSync(p))
|
|
71
|
+
return p;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
else {
|
|
75
|
+
// Linux
|
|
76
|
+
try {
|
|
77
|
+
return (0, child_process_1.execSync)('which google-chrome || which chromium-browser || which chromium', {
|
|
78
|
+
encoding: 'utf8',
|
|
79
|
+
}).trim();
|
|
80
|
+
}
|
|
81
|
+
catch {
|
|
82
|
+
return null;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
return null;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Find chrome-headless-shell binary
|
|
89
|
+
*/
|
|
90
|
+
function findChromeHeadlessShell() {
|
|
91
|
+
// Check environment variable first
|
|
92
|
+
const envPath = process.env['CHROME_HEADLESS_SHELL'];
|
|
93
|
+
if (envPath && fs.existsSync(envPath)) {
|
|
94
|
+
return envPath;
|
|
95
|
+
}
|
|
96
|
+
// Check PATH using which (Linux/Mac) or where (Windows)
|
|
97
|
+
const platform = os.platform();
|
|
98
|
+
try {
|
|
99
|
+
const cmd = platform === 'win32'
|
|
100
|
+
? 'where chrome-headless-shell'
|
|
101
|
+
: 'which chrome-headless-shell';
|
|
102
|
+
const result = (0, child_process_1.execSync)(cmd, { encoding: 'utf8' }).trim();
|
|
103
|
+
if (result && fs.existsSync(result)) {
|
|
104
|
+
return result;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
catch {
|
|
108
|
+
// Not found in PATH
|
|
109
|
+
}
|
|
110
|
+
return null;
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Check if Chrome debug port is already available
|
|
114
|
+
*/
|
|
115
|
+
async function checkDebugPort(port) {
|
|
116
|
+
return new Promise((resolve) => {
|
|
117
|
+
const req = http.request({
|
|
118
|
+
hostname: '127.0.0.1',
|
|
119
|
+
port,
|
|
120
|
+
path: '/json/version',
|
|
121
|
+
method: 'GET',
|
|
122
|
+
timeout: 2000,
|
|
123
|
+
}, (res) => {
|
|
124
|
+
let data = '';
|
|
125
|
+
res.on('data', (chunk) => (data += chunk));
|
|
126
|
+
res.on('end', () => {
|
|
127
|
+
try {
|
|
128
|
+
const json = JSON.parse(data);
|
|
129
|
+
resolve(json.webSocketDebuggerUrl || null);
|
|
130
|
+
}
|
|
131
|
+
catch {
|
|
132
|
+
resolve(null);
|
|
133
|
+
}
|
|
134
|
+
});
|
|
135
|
+
});
|
|
136
|
+
req.on('error', () => resolve(null));
|
|
137
|
+
req.on('timeout', () => {
|
|
138
|
+
req.destroy();
|
|
139
|
+
resolve(null);
|
|
140
|
+
});
|
|
141
|
+
req.end();
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Wait for debug port to become available
|
|
146
|
+
*/
|
|
147
|
+
async function waitForDebugPort(port, timeout = 30000) {
|
|
148
|
+
const startTime = Date.now();
|
|
149
|
+
while (Date.now() - startTime < timeout) {
|
|
150
|
+
const wsEndpoint = await checkDebugPort(port);
|
|
151
|
+
if (wsEndpoint) {
|
|
152
|
+
return wsEndpoint;
|
|
153
|
+
}
|
|
154
|
+
await new Promise((r) => setTimeout(r, 500));
|
|
155
|
+
}
|
|
156
|
+
throw new Error(`Chrome debug port ${port} not available after ${timeout}ms`);
|
|
157
|
+
}
|
|
158
|
+
class ChromeLauncher {
|
|
159
|
+
instance = null;
|
|
160
|
+
port;
|
|
161
|
+
usingRealProfile = false;
|
|
162
|
+
constructor(port = DEFAULT_PORT) {
|
|
163
|
+
this.port = port;
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Ensure Chrome with remote debugging is available
|
|
167
|
+
*/
|
|
168
|
+
async ensureChrome(options = {}) {
|
|
169
|
+
const port = options.port || this.port;
|
|
170
|
+
// Check if already connected and instance is still valid
|
|
171
|
+
if (this.instance) {
|
|
172
|
+
// Verify the cached instance is still valid by checking the debug port
|
|
173
|
+
const currentWs = await checkDebugPort(port);
|
|
174
|
+
if (currentWs && currentWs === this.instance.wsEndpoint) {
|
|
175
|
+
return this.instance;
|
|
176
|
+
}
|
|
177
|
+
// Instance is stale, clear it
|
|
178
|
+
console.error('[ChromeLauncher] Cached instance is stale, refreshing...');
|
|
179
|
+
this.instance = null;
|
|
180
|
+
}
|
|
181
|
+
// Check if Chrome is already running with debug port
|
|
182
|
+
const existingWs = await checkDebugPort(port);
|
|
183
|
+
if (existingWs) {
|
|
184
|
+
console.error(`[ChromeLauncher] Found existing Chrome on port ${port}`);
|
|
185
|
+
this.instance = {
|
|
186
|
+
wsEndpoint: existingWs,
|
|
187
|
+
httpEndpoint: `http://127.0.0.1:${port}`,
|
|
188
|
+
};
|
|
189
|
+
return this.instance;
|
|
190
|
+
}
|
|
191
|
+
// If autoLaunch is false (default), don't start Chrome automatically
|
|
192
|
+
if (!options.autoLaunch) {
|
|
193
|
+
throw new Error(`Chrome is not running with remote debugging on port ${port}.\n\n` +
|
|
194
|
+
`Please start Chrome manually with:\n` +
|
|
195
|
+
` chrome --remote-debugging-port=${port}\n\n` +
|
|
196
|
+
`Or use --auto-launch flag to start Chrome automatically.`);
|
|
197
|
+
}
|
|
198
|
+
// Launch new Chrome instance
|
|
199
|
+
console.error(`[ChromeLauncher] Launching Chrome with debug port ${port}...`);
|
|
200
|
+
const globalConfig = (0, global_1.getGlobalConfig)();
|
|
201
|
+
// Resolve Chrome binary: explicit override > headless-shell > standard Chrome
|
|
202
|
+
let chromePath = null;
|
|
203
|
+
let usingHeadlessShell = false;
|
|
204
|
+
if (globalConfig.chromeBinary) {
|
|
205
|
+
chromePath = globalConfig.chromeBinary;
|
|
206
|
+
console.error(`[ChromeLauncher] Using custom Chrome binary: ${chromePath}`);
|
|
207
|
+
}
|
|
208
|
+
else if (globalConfig.useHeadlessShell) {
|
|
209
|
+
chromePath = findChromeHeadlessShell();
|
|
210
|
+
if (chromePath) {
|
|
211
|
+
usingHeadlessShell = true;
|
|
212
|
+
console.error(`[ChromeLauncher] Using chrome-headless-shell: ${chromePath}`);
|
|
213
|
+
}
|
|
214
|
+
else {
|
|
215
|
+
console.error('[ChromeLauncher] chrome-headless-shell not found, falling back to standard Chrome');
|
|
216
|
+
chromePath = findChromePath();
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
else {
|
|
220
|
+
chromePath = findChromePath();
|
|
221
|
+
}
|
|
222
|
+
if (!chromePath) {
|
|
223
|
+
throw new Error('Chrome not found. Please install Google Chrome or set CHROME_PATH environment variable.');
|
|
224
|
+
}
|
|
225
|
+
// Determine user data directory:
|
|
226
|
+
// 1. Explicit option from CLI/config/global
|
|
227
|
+
// 2. Real Chrome profile (macOS: ~/Library/Application Support/Google/Chrome)
|
|
228
|
+
// (skipped when using headless-shell, which doesn't support extensions)
|
|
229
|
+
// 3. Fallback to temp directory
|
|
230
|
+
let userDataDir = options.userDataDir || globalConfig.userDataDir;
|
|
231
|
+
let usingRealProfile = false;
|
|
232
|
+
if (!userDataDir && !options.useTempProfile && !usingHeadlessShell) {
|
|
233
|
+
const realProfileDir = this.getRealChromeProfileDir();
|
|
234
|
+
if (realProfileDir && !this.isProfileLocked(realProfileDir)) {
|
|
235
|
+
userDataDir = realProfileDir;
|
|
236
|
+
usingRealProfile = true;
|
|
237
|
+
this.usingRealProfile = true;
|
|
238
|
+
console.error(`[ChromeLauncher] Using real Chrome profile: ${realProfileDir}`);
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
if (!userDataDir) {
|
|
242
|
+
userDataDir = path.join(os.tmpdir(), `claude-chrome-parallel-${Date.now()}`);
|
|
243
|
+
this.usingRealProfile = false;
|
|
244
|
+
console.error(`[ChromeLauncher] Using temp profile: ${userDataDir}`);
|
|
245
|
+
}
|
|
246
|
+
fs.mkdirSync(userDataDir, { recursive: true });
|
|
247
|
+
const args = [
|
|
248
|
+
`--remote-debugging-port=${port}`,
|
|
249
|
+
`--user-data-dir=${userDataDir}`,
|
|
250
|
+
'--no-first-run',
|
|
251
|
+
'--no-default-browser-check',
|
|
252
|
+
// IMPORTANT: Start maximized for proper debugging experience
|
|
253
|
+
'--start-maximized',
|
|
254
|
+
// Fallback window size if maximize doesn't work
|
|
255
|
+
'--window-size=1920,1080',
|
|
256
|
+
// Memory-saving flags (applies to all profile types)
|
|
257
|
+
'--disable-gpu',
|
|
258
|
+
'--disable-dev-shm-usage',
|
|
259
|
+
'--renderer-process-limit=16',
|
|
260
|
+
'--js-flags=--max-old-space-size=1024',
|
|
261
|
+
'--disable-backgrounding-occluded-windows',
|
|
262
|
+
'--disable-ipc-flooding-protection',
|
|
263
|
+
];
|
|
264
|
+
// Only disable background features for temp profiles
|
|
265
|
+
if (!usingRealProfile) {
|
|
266
|
+
args.push('--disable-background-networking', '--disable-sync', '--disable-translate', '--metrics-recording-only', '--disable-extensions', '--disable-component-extensions-with-background-pages', '--disable-default-apps');
|
|
267
|
+
}
|
|
268
|
+
if (options.headless) {
|
|
269
|
+
args.push('--headless=new');
|
|
270
|
+
// For headless, set explicit window size
|
|
271
|
+
args.push('--window-size=1920,1080');
|
|
272
|
+
}
|
|
273
|
+
const chromeProcess = (0, child_process_1.spawn)(chromePath, args, {
|
|
274
|
+
detached: true,
|
|
275
|
+
stdio: ['ignore', 'ignore', 'ignore'],
|
|
276
|
+
});
|
|
277
|
+
chromeProcess.unref();
|
|
278
|
+
// Wait for debug port
|
|
279
|
+
const wsEndpoint = await waitForDebugPort(port);
|
|
280
|
+
this.instance = {
|
|
281
|
+
wsEndpoint,
|
|
282
|
+
httpEndpoint: `http://127.0.0.1:${port}`,
|
|
283
|
+
process: chromeProcess,
|
|
284
|
+
userDataDir,
|
|
285
|
+
};
|
|
286
|
+
console.error(`[ChromeLauncher] Chrome ready at ${wsEndpoint}`);
|
|
287
|
+
return this.instance;
|
|
288
|
+
}
|
|
289
|
+
/**
|
|
290
|
+
* Get debug endpoint URL
|
|
291
|
+
*/
|
|
292
|
+
async getDebugEndpoint() {
|
|
293
|
+
if (!this.instance) {
|
|
294
|
+
await this.ensureChrome();
|
|
295
|
+
}
|
|
296
|
+
return this.instance.httpEndpoint;
|
|
297
|
+
}
|
|
298
|
+
/**
|
|
299
|
+
* Get WebSocket endpoint
|
|
300
|
+
*/
|
|
301
|
+
async getWsEndpoint() {
|
|
302
|
+
if (!this.instance) {
|
|
303
|
+
await this.ensureChrome();
|
|
304
|
+
}
|
|
305
|
+
return this.instance.wsEndpoint;
|
|
306
|
+
}
|
|
307
|
+
/**
|
|
308
|
+
* Close Chrome instance (only if we launched it)
|
|
309
|
+
*/
|
|
310
|
+
async close() {
|
|
311
|
+
if (this.instance?.process) {
|
|
312
|
+
console.error('[ChromeLauncher] Closing Chrome...');
|
|
313
|
+
this.instance.process.kill();
|
|
314
|
+
// Clean up user data dir (only if using temp profile, never delete real profile)
|
|
315
|
+
if (this.instance.userDataDir && !this.usingRealProfile) {
|
|
316
|
+
try {
|
|
317
|
+
fs.rmSync(this.instance.userDataDir, { recursive: true, force: true });
|
|
318
|
+
}
|
|
319
|
+
catch {
|
|
320
|
+
// Ignore cleanup errors
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
this.instance = null;
|
|
325
|
+
}
|
|
326
|
+
/**
|
|
327
|
+
* Check if connected
|
|
328
|
+
*/
|
|
329
|
+
isConnected() {
|
|
330
|
+
return this.instance !== null;
|
|
331
|
+
}
|
|
332
|
+
/**
|
|
333
|
+
* Get the real Chrome profile directory for the current platform
|
|
334
|
+
*/
|
|
335
|
+
getRealChromeProfileDir() {
|
|
336
|
+
const platform = os.platform();
|
|
337
|
+
const home = os.homedir();
|
|
338
|
+
if (platform === 'darwin') {
|
|
339
|
+
const profileDir = path.join(home, 'Library', 'Application Support', 'Google', 'Chrome');
|
|
340
|
+
if (fs.existsSync(profileDir))
|
|
341
|
+
return profileDir;
|
|
342
|
+
}
|
|
343
|
+
else if (platform === 'win32') {
|
|
344
|
+
const profileDir = path.join(home, 'AppData', 'Local', 'Google', 'Chrome', 'User Data');
|
|
345
|
+
if (fs.existsSync(profileDir))
|
|
346
|
+
return profileDir;
|
|
347
|
+
}
|
|
348
|
+
else {
|
|
349
|
+
const profileDir = path.join(home, '.config', 'google-chrome');
|
|
350
|
+
if (fs.existsSync(profileDir))
|
|
351
|
+
return profileDir;
|
|
352
|
+
}
|
|
353
|
+
return null;
|
|
354
|
+
}
|
|
355
|
+
/**
|
|
356
|
+
* Check if a Chrome profile directory is locked by another Chrome instance
|
|
357
|
+
*/
|
|
358
|
+
isProfileLocked(profileDir) {
|
|
359
|
+
// Chrome uses a "SingletonLock" file (Linux) or "lockfile" to prevent concurrent access
|
|
360
|
+
const lockFiles = [
|
|
361
|
+
path.join(profileDir, 'SingletonLock'),
|
|
362
|
+
path.join(profileDir, 'SingletonSocket'),
|
|
363
|
+
path.join(profileDir, 'SingletonCookie'),
|
|
364
|
+
];
|
|
365
|
+
for (const lockFile of lockFiles) {
|
|
366
|
+
if (fs.existsSync(lockFile)) {
|
|
367
|
+
console.error(`[ChromeLauncher] Profile locked: ${lockFile} exists`);
|
|
368
|
+
return true;
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
return false;
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
exports.ChromeLauncher = ChromeLauncher;
|
|
375
|
+
// Singleton instance
|
|
376
|
+
let launcherInstance = null;
|
|
377
|
+
function getChromeLauncher(port) {
|
|
378
|
+
if (!launcherInstance) {
|
|
379
|
+
launcherInstance = new ChromeLauncher(port);
|
|
380
|
+
}
|
|
381
|
+
return launcherInstance;
|
|
382
|
+
}
|
|
383
|
+
//# sourceMappingURL=launcher.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"launcher.js","sourceRoot":"","sources":["../../src/chrome/launcher.ts"],"names":[],"mappings":";AAAA;;GAEG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAkZH,8CAKC;AArZD,iDAA8D;AAC9D,2CAA6B;AAC7B,uCAAyB;AACzB,uCAAyB;AACzB,2CAA6B;AAC7B,6CAAmD;AAmBnD,MAAM,YAAY,GAAG,IAAI,CAAC;AAE1B;;GAEG;AACH,SAAS,cAAc;IACrB,MAAM,QAAQ,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC;IAE/B,IAAI,QAAQ,KAAK,OAAO,EAAE,CAAC;QACzB,MAAM,KAAK,GAAG;YACZ,OAAO,CAAC,GAAG,CAAC,mBAAmB,CAAC,GAAG,2CAA2C;YAC9E,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,GAAG,2CAA2C;YACzE,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,GAAG,2CAA2C;SAC1E,CAAC;QACF,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;YACtB,IAAI,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC;gBAAE,OAAO,CAAC,CAAC;QACjC,CAAC;IACH,CAAC;SAAM,IAAI,QAAQ,KAAK,QAAQ,EAAE,CAAC;QACjC,MAAM,KAAK,GAAG;YACZ,8DAA8D;YAC9D,oDAAoD;SACrD,CAAC;QACF,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;YACtB,IAAI,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC;gBAAE,OAAO,CAAC,CAAC;QACjC,CAAC;IACH,CAAC;SAAM,CAAC;QACN,QAAQ;QACR,IAAI,CAAC;YACH,OAAO,IAAA,wBAAQ,EAAC,iEAAiE,EAAE;gBACjF,QAAQ,EAAE,MAAM;aACjB,CAAC,CAAC,IAAI,EAAE,CAAC;QACZ,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;GAEG;AACH,SAAS,uBAAuB;IAC9B,mCAAmC;IACnC,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,uBAAuB,CAAC,CAAC;IACrD,IAAI,OAAO,IAAI,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;QACtC,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,wDAAwD;IACxD,MAAM,QAAQ,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC;IAC/B,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,QAAQ,KAAK,OAAO;YAC9B,CAAC,CAAC,6BAA6B;YAC/B,CAAC,CAAC,6BAA6B,CAAC;QAClC,MAAM,MAAM,GAAG,IAAA,wBAAQ,EAAC,GAAG,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;QAC1D,IAAI,MAAM,IAAI,EAAE,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;YACpC,OAAO,MAAM,CAAC;QAChB,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,oBAAoB;IACtB,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;GAEG;AACH,KAAK,UAAU,cAAc,CAAC,IAAY;IACxC,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;QAC7B,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CACtB;YACE,QAAQ,EAAE,WAAW;YACrB,IAAI;YACJ,IAAI,EAAE,eAAe;YACrB,MAAM,EAAE,KAAK;YACb,OAAO,EAAE,IAAI;SACd,EACD,CAAC,GAAG,EAAE,EAAE;YACN,IAAI,IAAI,GAAG,EAAE,CAAC;YACd,GAAG,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,IAAI,IAAI,KAAK,CAAC,CAAC,CAAC;YAC3C,GAAG,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE;gBACjB,IAAI,CAAC;oBACH,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;oBAC9B,OAAO,CAAC,IAAI,CAAC,oBAAoB,IAAI,IAAI,CAAC,CAAC;gBAC7C,CAAC;gBAAC,MAAM,CAAC;oBACP,OAAO,CAAC,IAAI,CAAC,CAAC;gBAChB,CAAC;YACH,CAAC,CAAC,CAAC;QACL,CAAC,CACF,CAAC;QAEF,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;QACrC,GAAG,CAAC,EAAE,CAAC,SAAS,EAAE,GAAG,EAAE;YACrB,GAAG,CAAC,OAAO,EAAE,CAAC;YACd,OAAO,CAAC,IAAI,CAAC,CAAC;QAChB,CAAC,CAAC,CAAC;QAEH,GAAG,CAAC,GAAG,EAAE,CAAC;IACZ,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;GAEG;AACH,KAAK,UAAU,gBAAgB,CAAC,IAAY,EAAE,OAAO,GAAG,KAAK;IAC3D,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAE7B,OAAO,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,GAAG,OAAO,EAAE,CAAC;QACxC,MAAM,UAAU,GAAG,MAAM,cAAc,CAAC,IAAI,CAAC,CAAC;QAC9C,IAAI,UAAU,EAAE,CAAC;YACf,OAAO,UAAU,CAAC;QACpB,CAAC;QACD,MAAM,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC;IAC/C,CAAC;IAED,MAAM,IAAI,KAAK,CAAC,qBAAqB,IAAI,wBAAwB,OAAO,IAAI,CAAC,CAAC;AAChF,CAAC;AAED,MAAa,cAAc;IACjB,QAAQ,GAA0B,IAAI,CAAC;IACvC,IAAI,CAAS;IACb,gBAAgB,GAAG,KAAK,CAAC;IAEjC,YAAY,OAAe,YAAY;QACrC,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IACnB,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,YAAY,CAAC,UAAyB,EAAE;QAC5C,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,IAAI,IAAI,CAAC,IAAI,CAAC;QAEvC,yDAAyD;QACzD,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YAClB,uEAAuE;YACvE,MAAM,SAAS,GAAG,MAAM,cAAc,CAAC,IAAI,CAAC,CAAC;YAC7C,IAAI,SAAS,IAAI,SAAS,KAAK,IAAI,CAAC,QAAQ,CAAC,UAAU,EAAE,CAAC;gBACxD,OAAO,IAAI,CAAC,QAAQ,CAAC;YACvB,CAAC;YACD,8BAA8B;YAC9B,OAAO,CAAC,KAAK,CAAC,0DAA0D,CAAC,CAAC;YAC1E,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC;QACvB,CAAC;QAED,qDAAqD;QACrD,MAAM,UAAU,GAAG,MAAM,cAAc,CAAC,IAAI,CAAC,CAAC;QAC9C,IAAI,UAAU,EAAE,CAAC;YACf,OAAO,CAAC,KAAK,CAAC,kDAAkD,IAAI,EAAE,CAAC,CAAC;YACxE,IAAI,CAAC,QAAQ,GAAG;gBACd,UAAU,EAAE,UAAU;gBACtB,YAAY,EAAE,oBAAoB,IAAI,EAAE;aACzC,CAAC;YACF,OAAO,IAAI,CAAC,QAAQ,CAAC;QACvB,CAAC;QAED,qEAAqE;QACrE,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE,CAAC;YACxB,MAAM,IAAI,KAAK,CACb,uDAAuD,IAAI,OAAO;gBAClE,sCAAsC;gBACtC,oCAAoC,IAAI,MAAM;gBAC9C,0DAA0D,CAC3D,CAAC;QACJ,CAAC;QAED,6BAA6B;QAC7B,OAAO,CAAC,KAAK,CAAC,qDAAqD,IAAI,KAAK,CAAC,CAAC;QAE9E,MAAM,YAAY,GAAG,IAAA,wBAAe,GAAE,CAAC;QAEvC,8EAA8E;QAC9E,IAAI,UAAU,GAAkB,IAAI,CAAC;QACrC,IAAI,kBAAkB,GAAG,KAAK,CAAC;QAE/B,IAAI,YAAY,CAAC,YAAY,EAAE,CAAC;YAC9B,UAAU,GAAG,YAAY,CAAC,YAAY,CAAC;YACvC,OAAO,CAAC,KAAK,CAAC,gDAAgD,UAAU,EAAE,CAAC,CAAC;QAC9E,CAAC;aAAM,IAAI,YAAY,CAAC,gBAAgB,EAAE,CAAC;YACzC,UAAU,GAAG,uBAAuB,EAAE,CAAC;YACvC,IAAI,UAAU,EAAE,CAAC;gBACf,kBAAkB,GAAG,IAAI,CAAC;gBAC1B,OAAO,CAAC,KAAK,CAAC,iDAAiD,UAAU,EAAE,CAAC,CAAC;YAC/E,CAAC;iBAAM,CAAC;gBACN,OAAO,CAAC,KAAK,CAAC,mFAAmF,CAAC,CAAC;gBACnG,UAAU,GAAG,cAAc,EAAE,CAAC;YAChC,CAAC;QACH,CAAC;aAAM,CAAC;YACN,UAAU,GAAG,cAAc,EAAE,CAAC;QAChC,CAAC;QAED,IAAI,CAAC,UAAU,EAAE,CAAC;YAChB,MAAM,IAAI,KAAK,CACb,yFAAyF,CAC1F,CAAC;QACJ,CAAC;QAED,iCAAiC;QACjC,4CAA4C;QAC5C,8EAA8E;QAC9E,2EAA2E;QAC3E,gCAAgC;QAChC,IAAI,WAAW,GAAG,OAAO,CAAC,WAAW,IAAI,YAAY,CAAC,WAAW,CAAC;QAClE,IAAI,gBAAgB,GAAG,KAAK,CAAC;QAE7B,IAAI,CAAC,WAAW,IAAI,CAAC,OAAO,CAAC,cAAc,IAAI,CAAC,kBAAkB,EAAE,CAAC;YACnE,MAAM,cAAc,GAAG,IAAI,CAAC,uBAAuB,EAAE,CAAC;YACtD,IAAI,cAAc,IAAI,CAAC,IAAI,CAAC,eAAe,CAAC,cAAc,CAAC,EAAE,CAAC;gBAC5D,WAAW,GAAG,cAAc,CAAC;gBAC7B,gBAAgB,GAAG,IAAI,CAAC;gBACxB,IAAI,CAAC,gBAAgB,GAAG,IAAI,CAAC;gBAC7B,OAAO,CAAC,KAAK,CAAC,+CAA+C,cAAc,EAAE,CAAC,CAAC;YACjF,CAAC;QACH,CAAC;QAED,IAAI,CAAC,WAAW,EAAE,CAAC;YACjB,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,0BAA0B,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;YAC7E,IAAI,CAAC,gBAAgB,GAAG,KAAK,CAAC;YAC9B,OAAO,CAAC,KAAK,CAAC,wCAAwC,WAAW,EAAE,CAAC,CAAC;QACvE,CAAC;QAED,EAAE,CAAC,SAAS,CAAC,WAAW,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAE/C,MAAM,IAAI,GAAG;YACX,2BAA2B,IAAI,EAAE;YACjC,mBAAmB,WAAW,EAAE;YAChC,gBAAgB;YAChB,4BAA4B;YAC5B,6DAA6D;YAC7D,mBAAmB;YACnB,gDAAgD;YAChD,yBAAyB;YACzB,qDAAqD;YACrD,eAAe;YACf,yBAAyB;YACzB,6BAA6B;YAC7B,sCAAsC;YACtC,0CAA0C;YAC1C,mCAAmC;SACpC,CAAC;QAEF,qDAAqD;QACrD,IAAI,CAAC,gBAAgB,EAAE,CAAC;YACtB,IAAI,CAAC,IAAI,CACP,iCAAiC,EACjC,gBAAgB,EAChB,qBAAqB,EACrB,0BAA0B,EAC1B,sBAAsB,EACtB,sDAAsD,EACtD,wBAAwB,CACzB,CAAC;QACJ,CAAC;QAED,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC;YACrB,IAAI,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;YAC5B,yCAAyC;YACzC,IAAI,CAAC,IAAI,CAAC,yBAAyB,CAAC,CAAC;QACvC,CAAC;QAED,MAAM,aAAa,GAAG,IAAA,qBAAK,EAAC,UAAU,EAAE,IAAI,EAAE;YAC5C,QAAQ,EAAE,IAAI;YACd,KAAK,EAAE,CAAC,QAAQ,EAAE,QAAQ,EAAE,QAAQ,CAAC;SACtC,CAAC,CAAC;QAEH,aAAa,CAAC,KAAK,EAAE,CAAC;QAEtB,sBAAsB;QACtB,MAAM,UAAU,GAAG,MAAM,gBAAgB,CAAC,IAAI,CAAC,CAAC;QAEhD,IAAI,CAAC,QAAQ,GAAG;YACd,UAAU;YACV,YAAY,EAAE,oBAAoB,IAAI,EAAE;YACxC,OAAO,EAAE,aAAa;YACtB,WAAW;SACZ,CAAC;QAEF,OAAO,CAAC,KAAK,CAAC,oCAAoC,UAAU,EAAE,CAAC,CAAC;QAChE,OAAO,IAAI,CAAC,QAAQ,CAAC;IACvB,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,gBAAgB;QACpB,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC;YACnB,MAAM,IAAI,CAAC,YAAY,EAAE,CAAC;QAC5B,CAAC;QACD,OAAO,IAAI,CAAC,QAAS,CAAC,YAAY,CAAC;IACrC,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,aAAa;QACjB,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC;YACnB,MAAM,IAAI,CAAC,YAAY,EAAE,CAAC;QAC5B,CAAC;QACD,OAAO,IAAI,CAAC,QAAS,CAAC,UAAU,CAAC;IACnC,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,KAAK;QACT,IAAI,IAAI,CAAC,QAAQ,EAAE,OAAO,EAAE,CAAC;YAC3B,OAAO,CAAC,KAAK,CAAC,oCAAoC,CAAC,CAAC;YACpD,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;YAE7B,iFAAiF;YACjF,IAAI,IAAI,CAAC,QAAQ,CAAC,WAAW,IAAI,CAAC,IAAI,CAAC,gBAAgB,EAAE,CAAC;gBACxD,IAAI,CAAC;oBACH,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,WAAW,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;gBACzE,CAAC;gBAAC,MAAM,CAAC;oBACP,wBAAwB;gBAC1B,CAAC;YACH,CAAC;QACH,CAAC;QACD,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC;IACvB,CAAC;IAED;;OAEG;IACH,WAAW;QACT,OAAO,IAAI,CAAC,QAAQ,KAAK,IAAI,CAAC;IAChC,CAAC;IAED;;OAEG;IACK,uBAAuB;QAC7B,MAAM,QAAQ,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC;QAC/B,MAAM,IAAI,GAAG,EAAE,CAAC,OAAO,EAAE,CAAC;QAE1B,IAAI,QAAQ,KAAK,QAAQ,EAAE,CAAC;YAC1B,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,SAAS,EAAE,qBAAqB,EAAE,QAAQ,EAAE,QAAQ,CAAC,CAAC;YACzF,IAAI,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC;gBAAE,OAAO,UAAU,CAAC;QACnD,CAAC;aAAM,IAAI,QAAQ,KAAK,OAAO,EAAE,CAAC;YAChC,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,WAAW,CAAC,CAAC;YACxF,IAAI,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC;gBAAE,OAAO,UAAU,CAAC;QACnD,CAAC;aAAM,CAAC;YACN,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,SAAS,EAAE,eAAe,CAAC,CAAC;YAC/D,IAAI,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC;gBAAE,OAAO,UAAU,CAAC;QACnD,CAAC;QAED,OAAO,IAAI,CAAC;IACd,CAAC;IAED;;OAEG;IACK,eAAe,CAAC,UAAkB;QACxC,wFAAwF;QACxF,MAAM,SAAS,GAAG;YAChB,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,eAAe,CAAC;YACtC,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,iBAAiB,CAAC;YACxC,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,iBAAiB,CAAC;SACzC,CAAC;QAEF,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE,CAAC;YACjC,IAAI,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;gBAC5B,OAAO,CAAC,KAAK,CAAC,oCAAoC,QAAQ,SAAS,CAAC,CAAC;gBACrE,OAAO,IAAI,CAAC;YACd,CAAC;QACH,CAAC;QAED,OAAO,KAAK,CAAC;IACf,CAAC;CACF;AA3PD,wCA2PC;AAED,qBAAqB;AACrB,IAAI,gBAAgB,GAA0B,IAAI,CAAC;AAEnD,SAAgB,iBAAiB,CAAC,IAAa;IAC7C,IAAI,CAAC,gBAAgB,EAAE,CAAC;QACtB,gBAAgB,GAAG,IAAI,cAAc,CAAC,IAAI,CAAC,CAAC;IAC9C,CAAC;IACD,OAAO,gBAAgB,CAAC;AAC1B,CAAC"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ChromePool - Manages multiple Chrome instances on different ports
|
|
3
|
+
* to solve the CDP same-origin renderer process contention issue.
|
|
4
|
+
*/
|
|
5
|
+
import { ChromeLauncher } from './launcher';
|
|
6
|
+
export interface ChromePoolConfig {
|
|
7
|
+
maxInstances: number;
|
|
8
|
+
basePort: number;
|
|
9
|
+
autoLaunch: boolean;
|
|
10
|
+
}
|
|
11
|
+
export interface PooledInstance {
|
|
12
|
+
port: number;
|
|
13
|
+
launcher: ChromeLauncher;
|
|
14
|
+
origins: Set<string>;
|
|
15
|
+
tabCount: number;
|
|
16
|
+
isPreExisting: boolean;
|
|
17
|
+
}
|
|
18
|
+
export declare class ChromePool {
|
|
19
|
+
private config;
|
|
20
|
+
private instances;
|
|
21
|
+
constructor(config?: Partial<ChromePoolConfig>);
|
|
22
|
+
/**
|
|
23
|
+
* Acquire a Chrome instance that does NOT already have a tab open to the given origin.
|
|
24
|
+
* If all instances have the origin, launch a new one (up to maxInstances).
|
|
25
|
+
*/
|
|
26
|
+
acquireInstance(origin: string): Promise<PooledInstance>;
|
|
27
|
+
/**
|
|
28
|
+
* Mark that an origin is no longer using a port.
|
|
29
|
+
*/
|
|
30
|
+
releaseInstance(port: number, origin: string): void;
|
|
31
|
+
/**
|
|
32
|
+
* Get the current instance assignment for an origin.
|
|
33
|
+
* Returns the first instance that has this origin registered, or null.
|
|
34
|
+
*/
|
|
35
|
+
getInstanceForOrigin(origin: string): PooledInstance | null;
|
|
36
|
+
/**
|
|
37
|
+
* Copy cookies between two Chrome instances for a given domain.
|
|
38
|
+
* Uses CDP Network.getAllCookies / Network.setCookies via WebSocket.
|
|
39
|
+
* This is a best-effort operation; failures are logged but not thrown.
|
|
40
|
+
*/
|
|
41
|
+
copyCookiesBetweenInstances(sourcePort: number, destPort: number, domain: string): Promise<void>;
|
|
42
|
+
/**
|
|
43
|
+
* Close all instances we launched (not pre-existing ones).
|
|
44
|
+
*/
|
|
45
|
+
cleanup(): Promise<void>;
|
|
46
|
+
/**
|
|
47
|
+
* Get all current pool instances (read-only snapshot).
|
|
48
|
+
*/
|
|
49
|
+
getInstances(): ReadonlyMap<number, PooledInstance>;
|
|
50
|
+
private launchNewInstance;
|
|
51
|
+
private nextAvailablePort;
|
|
52
|
+
}
|
|
53
|
+
export declare function getChromePool(config?: Partial<ChromePoolConfig>): ChromePool;
|
|
54
|
+
//# sourceMappingURL=pool.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pool.d.ts","sourceRoot":"","sources":["../../src/chrome/pool.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,cAAc,EAAiC,MAAM,YAAY,CAAC;AAE3E,MAAM,WAAW,gBAAgB;IAC/B,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,OAAO,CAAC;CACrB;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,cAAc,CAAC;IACzB,OAAO,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,OAAO,CAAC;CACxB;AAkFD,qBAAa,UAAU;IACrB,OAAO,CAAC,MAAM,CAAmB;IACjC,OAAO,CAAC,SAAS,CAA0C;gBAE/C,MAAM,GAAE,OAAO,CAAC,gBAAgB,CAAM;IAIlD;;;OAGG;IACG,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;IA6C9D;;OAEG;IACH,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI;IAenD;;;OAGG;IACH,oBAAoB,CAAC,MAAM,EAAE,MAAM,GAAG,cAAc,GAAG,IAAI;IAS3D;;;;OAIG;IACG,2BAA2B,CAC/B,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,IAAI,CAAC;IA4ChB;;OAEG;IACG,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAmB9B;;OAEG;IACH,YAAY,IAAI,WAAW,CAAC,MAAM,EAAE,cAAc,CAAC;YAQrC,iBAAiB;IAoC/B,OAAO,CAAC,iBAAiB;CAW1B;AAQD,wBAAgB,aAAa,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC,gBAAgB,CAAC,GAAG,UAAU,CAK5E"}
|