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,638 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Computer Tool - Mouse, keyboard, and screenshot actions
|
|
4
|
+
*/
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.registerComputerTool = registerComputerTool;
|
|
7
|
+
const session_manager_1 = require("../session-manager");
|
|
8
|
+
const ref_id_manager_1 = require("../utils/ref-id-manager");
|
|
9
|
+
const screenshot_scheduler_1 = require("../cdp/screenshot-scheduler");
|
|
10
|
+
// Maximum screenshot dimensions to avoid API errors (2000px limit)
|
|
11
|
+
const MAX_SCREENSHOT_WIDTH = 1920;
|
|
12
|
+
const MAX_SCREENSHOT_HEIGHT = 1080;
|
|
13
|
+
const definition = {
|
|
14
|
+
name: 'computer',
|
|
15
|
+
description: 'Use mouse and keyboard to interact with a web browser, and take screenshots.',
|
|
16
|
+
inputSchema: {
|
|
17
|
+
type: 'object',
|
|
18
|
+
properties: {
|
|
19
|
+
tabId: {
|
|
20
|
+
type: 'string',
|
|
21
|
+
description: 'Tab ID to execute the action on',
|
|
22
|
+
},
|
|
23
|
+
action: {
|
|
24
|
+
type: 'string',
|
|
25
|
+
enum: [
|
|
26
|
+
'left_click',
|
|
27
|
+
'right_click',
|
|
28
|
+
'double_click',
|
|
29
|
+
'triple_click',
|
|
30
|
+
'type',
|
|
31
|
+
'screenshot',
|
|
32
|
+
'wait',
|
|
33
|
+
'scroll',
|
|
34
|
+
'key',
|
|
35
|
+
'scroll_to',
|
|
36
|
+
'hover',
|
|
37
|
+
],
|
|
38
|
+
description: 'The action to perform',
|
|
39
|
+
},
|
|
40
|
+
coordinate: {
|
|
41
|
+
type: 'array',
|
|
42
|
+
items: { type: 'number' },
|
|
43
|
+
description: '(x, y) coordinates for click/scroll actions',
|
|
44
|
+
},
|
|
45
|
+
text: {
|
|
46
|
+
type: 'string',
|
|
47
|
+
description: 'Text to type or key to press',
|
|
48
|
+
},
|
|
49
|
+
duration: {
|
|
50
|
+
type: 'number',
|
|
51
|
+
description: 'Wait duration in seconds',
|
|
52
|
+
},
|
|
53
|
+
scroll_direction: {
|
|
54
|
+
type: 'string',
|
|
55
|
+
enum: ['up', 'down', 'left', 'right'],
|
|
56
|
+
description: 'Scroll direction',
|
|
57
|
+
},
|
|
58
|
+
scroll_amount: {
|
|
59
|
+
type: 'number',
|
|
60
|
+
description: 'Number of scroll wheel ticks',
|
|
61
|
+
},
|
|
62
|
+
ref: {
|
|
63
|
+
type: 'string',
|
|
64
|
+
description: 'Element reference ID. Can be used for scroll_to or as an alternative to coordinate for click actions.',
|
|
65
|
+
},
|
|
66
|
+
},
|
|
67
|
+
required: ['action', 'tabId'],
|
|
68
|
+
},
|
|
69
|
+
};
|
|
70
|
+
const handler = async (sessionId, args) => {
|
|
71
|
+
const tabId = args.tabId;
|
|
72
|
+
const action = args.action;
|
|
73
|
+
const coordinate = args.coordinate;
|
|
74
|
+
const text = args.text;
|
|
75
|
+
const duration = args.duration;
|
|
76
|
+
const scrollDirection = args.scroll_direction;
|
|
77
|
+
const scrollAmount = args.scroll_amount || 3;
|
|
78
|
+
const ref = args.ref;
|
|
79
|
+
const sessionManager = (0, session_manager_1.getSessionManager)();
|
|
80
|
+
if (!tabId) {
|
|
81
|
+
return {
|
|
82
|
+
content: [{ type: 'text', text: 'Error: tabId is required' }],
|
|
83
|
+
isError: true,
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
try {
|
|
87
|
+
const page = await sessionManager.getPage(sessionId, tabId, undefined, 'computer');
|
|
88
|
+
if (!page) {
|
|
89
|
+
return {
|
|
90
|
+
content: [{ type: 'text', text: `Error: Tab ${tabId} not found` }],
|
|
91
|
+
isError: true,
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
switch (action) {
|
|
95
|
+
case 'screenshot': {
|
|
96
|
+
// Save original viewport to restore later
|
|
97
|
+
const originalViewport = page.viewport();
|
|
98
|
+
// ALWAYS ensure viewport is within limits before screenshot
|
|
99
|
+
// This prevents the 2000px API error regardless of current state
|
|
100
|
+
const currentWidth = originalViewport?.width ?? 1920;
|
|
101
|
+
const currentHeight = originalViewport?.height ?? 1080;
|
|
102
|
+
const needsResize = !originalViewport ||
|
|
103
|
+
currentWidth > MAX_SCREENSHOT_WIDTH ||
|
|
104
|
+
currentHeight > MAX_SCREENSHOT_HEIGHT;
|
|
105
|
+
if (needsResize) {
|
|
106
|
+
// Set viewport to max allowed size
|
|
107
|
+
const newWidth = Math.min(currentWidth, MAX_SCREENSHOT_WIDTH);
|
|
108
|
+
const newHeight = Math.min(currentHeight, MAX_SCREENSHOT_HEIGHT);
|
|
109
|
+
await page.setViewport({
|
|
110
|
+
width: newWidth,
|
|
111
|
+
height: newHeight,
|
|
112
|
+
deviceScaleFactor: 1, // Ensure 1:1 pixel ratio
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
// Use ScreenshotScheduler for concurrency-controlled capture
|
|
116
|
+
const cdpClient = (0, session_manager_1.getSessionManager)().getCDPClient();
|
|
117
|
+
const scheduler = (0, screenshot_scheduler_1.getScreenshotScheduler)();
|
|
118
|
+
const { data: screenshot } = await scheduler.capture(page, cdpClient, {
|
|
119
|
+
format: 'webp',
|
|
120
|
+
quality: 60,
|
|
121
|
+
clip: {
|
|
122
|
+
x: 0,
|
|
123
|
+
y: 0,
|
|
124
|
+
width: Math.min(currentWidth, MAX_SCREENSHOT_WIDTH),
|
|
125
|
+
height: Math.min(currentHeight, MAX_SCREENSHOT_HEIGHT),
|
|
126
|
+
scale: 1,
|
|
127
|
+
},
|
|
128
|
+
optimizeForSpeed: true,
|
|
129
|
+
});
|
|
130
|
+
// Restore original viewport if we changed it
|
|
131
|
+
if (needsResize && originalViewport) {
|
|
132
|
+
await page.setViewport(originalViewport);
|
|
133
|
+
}
|
|
134
|
+
return {
|
|
135
|
+
content: [
|
|
136
|
+
{
|
|
137
|
+
type: 'image',
|
|
138
|
+
data: screenshot,
|
|
139
|
+
mimeType: 'image/webp',
|
|
140
|
+
},
|
|
141
|
+
],
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
case 'left_click': {
|
|
145
|
+
// Support ref-based clicking
|
|
146
|
+
let clickCoord = coordinate || null;
|
|
147
|
+
let refInfo = '';
|
|
148
|
+
if (ref && !coordinate) {
|
|
149
|
+
const refIdManager = (0, ref_id_manager_1.getRefIdManager)();
|
|
150
|
+
const refEntry = refIdManager.getRef(sessionId, tabId, ref);
|
|
151
|
+
if (!refEntry) {
|
|
152
|
+
return {
|
|
153
|
+
content: [{ type: 'text', text: `Error: Element ${ref} not found` }],
|
|
154
|
+
isError: true,
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
// Scroll into view and get coordinates
|
|
158
|
+
const cdpClient = sessionManager.getCDPClient();
|
|
159
|
+
try {
|
|
160
|
+
await cdpClient.send(page, 'DOM.scrollIntoViewIfNeeded', {
|
|
161
|
+
backendNodeId: refEntry.backendDOMNodeId,
|
|
162
|
+
});
|
|
163
|
+
const { model } = await cdpClient.send(page, 'DOM.getBoxModel', {
|
|
164
|
+
backendNodeId: refEntry.backendDOMNodeId,
|
|
165
|
+
});
|
|
166
|
+
// content is [x1,y1, x2,y1, x2,y2, x1,y2] - get center
|
|
167
|
+
const x = (model.content[0] + model.content[2]) / 2;
|
|
168
|
+
const y = (model.content[1] + model.content[5]) / 2;
|
|
169
|
+
clickCoord = [Math.round(x), Math.round(y)];
|
|
170
|
+
refInfo = ` [${ref}]`;
|
|
171
|
+
}
|
|
172
|
+
catch (e) {
|
|
173
|
+
return {
|
|
174
|
+
content: [{ type: 'text', text: `Error: Could not get position for ${ref}: ${e instanceof Error ? e.message : String(e)}` }],
|
|
175
|
+
isError: true,
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
if (!clickCoord) {
|
|
180
|
+
return {
|
|
181
|
+
content: [{ type: 'text', text: 'Error: coordinate or ref is required for left_click' }],
|
|
182
|
+
isError: true,
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
const leftClickValidation = await validateCoordinates(page, clickCoord[0], clickCoord[1]);
|
|
186
|
+
if (!leftClickValidation.valid) {
|
|
187
|
+
return {
|
|
188
|
+
content: [{ type: 'text', text: `Error: ${leftClickValidation.warning}` }],
|
|
189
|
+
isError: true,
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
await page.mouse.click(clickCoord[0], clickCoord[1]);
|
|
193
|
+
const resultText = leftClickValidation.warning
|
|
194
|
+
? `Clicked at (${clickCoord[0]}, ${clickCoord[1]})${refInfo}. Warning: ${leftClickValidation.warning}`
|
|
195
|
+
: `Clicked at (${clickCoord[0]}, ${clickCoord[1]})${refInfo}`;
|
|
196
|
+
return {
|
|
197
|
+
content: [{ type: 'text', text: resultText }],
|
|
198
|
+
};
|
|
199
|
+
}
|
|
200
|
+
case 'right_click': {
|
|
201
|
+
// Support ref-based clicking
|
|
202
|
+
let clickCoord = coordinate || null;
|
|
203
|
+
let refInfo = '';
|
|
204
|
+
if (ref && !coordinate) {
|
|
205
|
+
const refIdManager = (0, ref_id_manager_1.getRefIdManager)();
|
|
206
|
+
const refEntry = refIdManager.getRef(sessionId, tabId, ref);
|
|
207
|
+
if (!refEntry) {
|
|
208
|
+
return {
|
|
209
|
+
content: [{ type: 'text', text: `Error: Element ${ref} not found` }],
|
|
210
|
+
isError: true,
|
|
211
|
+
};
|
|
212
|
+
}
|
|
213
|
+
const cdpClient = sessionManager.getCDPClient();
|
|
214
|
+
try {
|
|
215
|
+
await cdpClient.send(page, 'DOM.scrollIntoViewIfNeeded', {
|
|
216
|
+
backendNodeId: refEntry.backendDOMNodeId,
|
|
217
|
+
});
|
|
218
|
+
const { model } = await cdpClient.send(page, 'DOM.getBoxModel', {
|
|
219
|
+
backendNodeId: refEntry.backendDOMNodeId,
|
|
220
|
+
});
|
|
221
|
+
const x = (model.content[0] + model.content[2]) / 2;
|
|
222
|
+
const y = (model.content[1] + model.content[5]) / 2;
|
|
223
|
+
clickCoord = [Math.round(x), Math.round(y)];
|
|
224
|
+
refInfo = ` [${ref}]`;
|
|
225
|
+
}
|
|
226
|
+
catch (e) {
|
|
227
|
+
return {
|
|
228
|
+
content: [{ type: 'text', text: `Error: Could not get position for ${ref}: ${e instanceof Error ? e.message : String(e)}` }],
|
|
229
|
+
isError: true,
|
|
230
|
+
};
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
if (!clickCoord) {
|
|
234
|
+
return {
|
|
235
|
+
content: [{ type: 'text', text: 'Error: coordinate or ref is required for right_click' }],
|
|
236
|
+
isError: true,
|
|
237
|
+
};
|
|
238
|
+
}
|
|
239
|
+
const rightClickValidation = await validateCoordinates(page, clickCoord[0], clickCoord[1]);
|
|
240
|
+
if (!rightClickValidation.valid) {
|
|
241
|
+
return {
|
|
242
|
+
content: [{ type: 'text', text: `Error: ${rightClickValidation.warning}` }],
|
|
243
|
+
isError: true,
|
|
244
|
+
};
|
|
245
|
+
}
|
|
246
|
+
await page.mouse.click(clickCoord[0], clickCoord[1], { button: 'right' });
|
|
247
|
+
const rightClickText = rightClickValidation.warning
|
|
248
|
+
? `Right-clicked at (${clickCoord[0]}, ${clickCoord[1]})${refInfo}. Warning: ${rightClickValidation.warning}`
|
|
249
|
+
: `Right-clicked at (${clickCoord[0]}, ${clickCoord[1]})${refInfo}`;
|
|
250
|
+
return {
|
|
251
|
+
content: [{ type: 'text', text: rightClickText }],
|
|
252
|
+
};
|
|
253
|
+
}
|
|
254
|
+
case 'double_click': {
|
|
255
|
+
// Support ref-based clicking
|
|
256
|
+
let clickCoord = coordinate || null;
|
|
257
|
+
let refInfo = '';
|
|
258
|
+
if (ref && !coordinate) {
|
|
259
|
+
const refIdManager = (0, ref_id_manager_1.getRefIdManager)();
|
|
260
|
+
const refEntry = refIdManager.getRef(sessionId, tabId, ref);
|
|
261
|
+
if (!refEntry) {
|
|
262
|
+
return {
|
|
263
|
+
content: [{ type: 'text', text: `Error: Element ${ref} not found` }],
|
|
264
|
+
isError: true,
|
|
265
|
+
};
|
|
266
|
+
}
|
|
267
|
+
const cdpClient = sessionManager.getCDPClient();
|
|
268
|
+
try {
|
|
269
|
+
await cdpClient.send(page, 'DOM.scrollIntoViewIfNeeded', {
|
|
270
|
+
backendNodeId: refEntry.backendDOMNodeId,
|
|
271
|
+
});
|
|
272
|
+
const { model } = await cdpClient.send(page, 'DOM.getBoxModel', {
|
|
273
|
+
backendNodeId: refEntry.backendDOMNodeId,
|
|
274
|
+
});
|
|
275
|
+
const x = (model.content[0] + model.content[2]) / 2;
|
|
276
|
+
const y = (model.content[1] + model.content[5]) / 2;
|
|
277
|
+
clickCoord = [Math.round(x), Math.round(y)];
|
|
278
|
+
refInfo = ` [${ref}]`;
|
|
279
|
+
}
|
|
280
|
+
catch (e) {
|
|
281
|
+
return {
|
|
282
|
+
content: [{ type: 'text', text: `Error: Could not get position for ${ref}: ${e instanceof Error ? e.message : String(e)}` }],
|
|
283
|
+
isError: true,
|
|
284
|
+
};
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
if (!clickCoord) {
|
|
288
|
+
return {
|
|
289
|
+
content: [
|
|
290
|
+
{ type: 'text', text: 'Error: coordinate or ref is required for double_click' },
|
|
291
|
+
],
|
|
292
|
+
isError: true,
|
|
293
|
+
};
|
|
294
|
+
}
|
|
295
|
+
const doubleClickValidation = await validateCoordinates(page, clickCoord[0], clickCoord[1]);
|
|
296
|
+
if (!doubleClickValidation.valid) {
|
|
297
|
+
return {
|
|
298
|
+
content: [{ type: 'text', text: `Error: ${doubleClickValidation.warning}` }],
|
|
299
|
+
isError: true,
|
|
300
|
+
};
|
|
301
|
+
}
|
|
302
|
+
await page.mouse.click(clickCoord[0], clickCoord[1], { clickCount: 2 });
|
|
303
|
+
const doubleClickText = doubleClickValidation.warning
|
|
304
|
+
? `Double-clicked at (${clickCoord[0]}, ${clickCoord[1]})${refInfo}. Warning: ${doubleClickValidation.warning}`
|
|
305
|
+
: `Double-clicked at (${clickCoord[0]}, ${clickCoord[1]})${refInfo}`;
|
|
306
|
+
return {
|
|
307
|
+
content: [{ type: 'text', text: doubleClickText }],
|
|
308
|
+
};
|
|
309
|
+
}
|
|
310
|
+
case 'triple_click': {
|
|
311
|
+
// Support ref-based clicking
|
|
312
|
+
let clickCoord = coordinate || null;
|
|
313
|
+
let refInfo = '';
|
|
314
|
+
if (ref && !coordinate) {
|
|
315
|
+
const refIdManager = (0, ref_id_manager_1.getRefIdManager)();
|
|
316
|
+
const refEntry = refIdManager.getRef(sessionId, tabId, ref);
|
|
317
|
+
if (!refEntry) {
|
|
318
|
+
return {
|
|
319
|
+
content: [{ type: 'text', text: `Error: Element ${ref} not found` }],
|
|
320
|
+
isError: true,
|
|
321
|
+
};
|
|
322
|
+
}
|
|
323
|
+
const cdpClient = sessionManager.getCDPClient();
|
|
324
|
+
try {
|
|
325
|
+
await cdpClient.send(page, 'DOM.scrollIntoViewIfNeeded', {
|
|
326
|
+
backendNodeId: refEntry.backendDOMNodeId,
|
|
327
|
+
});
|
|
328
|
+
const { model } = await cdpClient.send(page, 'DOM.getBoxModel', {
|
|
329
|
+
backendNodeId: refEntry.backendDOMNodeId,
|
|
330
|
+
});
|
|
331
|
+
const x = (model.content[0] + model.content[2]) / 2;
|
|
332
|
+
const y = (model.content[1] + model.content[5]) / 2;
|
|
333
|
+
clickCoord = [Math.round(x), Math.round(y)];
|
|
334
|
+
refInfo = ` [${ref}]`;
|
|
335
|
+
}
|
|
336
|
+
catch (e) {
|
|
337
|
+
return {
|
|
338
|
+
content: [{ type: 'text', text: `Error: Could not get position for ${ref}: ${e instanceof Error ? e.message : String(e)}` }],
|
|
339
|
+
isError: true,
|
|
340
|
+
};
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
if (!clickCoord) {
|
|
344
|
+
return {
|
|
345
|
+
content: [
|
|
346
|
+
{ type: 'text', text: 'Error: coordinate or ref is required for triple_click' },
|
|
347
|
+
],
|
|
348
|
+
isError: true,
|
|
349
|
+
};
|
|
350
|
+
}
|
|
351
|
+
const tripleClickValidation = await validateCoordinates(page, clickCoord[0], clickCoord[1]);
|
|
352
|
+
if (!tripleClickValidation.valid) {
|
|
353
|
+
return {
|
|
354
|
+
content: [{ type: 'text', text: `Error: ${tripleClickValidation.warning}` }],
|
|
355
|
+
isError: true,
|
|
356
|
+
};
|
|
357
|
+
}
|
|
358
|
+
await page.mouse.click(clickCoord[0], clickCoord[1], { clickCount: 3 });
|
|
359
|
+
const tripleClickText = tripleClickValidation.warning
|
|
360
|
+
? `Triple-clicked at (${clickCoord[0]}, ${clickCoord[1]})${refInfo}. Warning: ${tripleClickValidation.warning}`
|
|
361
|
+
: `Triple-clicked at (${clickCoord[0]}, ${clickCoord[1]})${refInfo}`;
|
|
362
|
+
return {
|
|
363
|
+
content: [{ type: 'text', text: tripleClickText }],
|
|
364
|
+
};
|
|
365
|
+
}
|
|
366
|
+
case 'hover': {
|
|
367
|
+
// Support ref-based hovering
|
|
368
|
+
let hoverCoord = coordinate || null;
|
|
369
|
+
let refInfo = '';
|
|
370
|
+
if (ref && !coordinate) {
|
|
371
|
+
const refIdManager = (0, ref_id_manager_1.getRefIdManager)();
|
|
372
|
+
const refEntry = refIdManager.getRef(sessionId, tabId, ref);
|
|
373
|
+
if (!refEntry) {
|
|
374
|
+
return {
|
|
375
|
+
content: [{ type: 'text', text: `Error: Element ${ref} not found` }],
|
|
376
|
+
isError: true,
|
|
377
|
+
};
|
|
378
|
+
}
|
|
379
|
+
const cdpClient = sessionManager.getCDPClient();
|
|
380
|
+
try {
|
|
381
|
+
await cdpClient.send(page, 'DOM.scrollIntoViewIfNeeded', {
|
|
382
|
+
backendNodeId: refEntry.backendDOMNodeId,
|
|
383
|
+
});
|
|
384
|
+
const { model } = await cdpClient.send(page, 'DOM.getBoxModel', {
|
|
385
|
+
backendNodeId: refEntry.backendDOMNodeId,
|
|
386
|
+
});
|
|
387
|
+
const x = (model.content[0] + model.content[2]) / 2;
|
|
388
|
+
const y = (model.content[1] + model.content[5]) / 2;
|
|
389
|
+
hoverCoord = [Math.round(x), Math.round(y)];
|
|
390
|
+
refInfo = ` [${ref}]`;
|
|
391
|
+
}
|
|
392
|
+
catch (e) {
|
|
393
|
+
return {
|
|
394
|
+
content: [{ type: 'text', text: `Error: Could not get position for ${ref}: ${e instanceof Error ? e.message : String(e)}` }],
|
|
395
|
+
isError: true,
|
|
396
|
+
};
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
if (!hoverCoord) {
|
|
400
|
+
return {
|
|
401
|
+
content: [{ type: 'text', text: 'Error: coordinate or ref is required for hover' }],
|
|
402
|
+
isError: true,
|
|
403
|
+
};
|
|
404
|
+
}
|
|
405
|
+
const hoverValidation = await validateCoordinates(page, hoverCoord[0], hoverCoord[1]);
|
|
406
|
+
if (!hoverValidation.valid) {
|
|
407
|
+
return {
|
|
408
|
+
content: [{ type: 'text', text: `Error: ${hoverValidation.warning}` }],
|
|
409
|
+
isError: true,
|
|
410
|
+
};
|
|
411
|
+
}
|
|
412
|
+
await page.mouse.move(hoverCoord[0], hoverCoord[1]);
|
|
413
|
+
const hoverText = hoverValidation.warning
|
|
414
|
+
? `Hovered at (${hoverCoord[0]}, ${hoverCoord[1]})${refInfo}. Warning: ${hoverValidation.warning}`
|
|
415
|
+
: `Hovered at (${hoverCoord[0]}, ${hoverCoord[1]})${refInfo}`;
|
|
416
|
+
return {
|
|
417
|
+
content: [{ type: 'text', text: hoverText }],
|
|
418
|
+
};
|
|
419
|
+
}
|
|
420
|
+
case 'type': {
|
|
421
|
+
if (!text) {
|
|
422
|
+
return {
|
|
423
|
+
content: [{ type: 'text', text: 'Error: text is required for type action' }],
|
|
424
|
+
isError: true,
|
|
425
|
+
};
|
|
426
|
+
}
|
|
427
|
+
await page.keyboard.type(text);
|
|
428
|
+
return {
|
|
429
|
+
content: [{ type: 'text', text: `Typed: ${text}` }],
|
|
430
|
+
};
|
|
431
|
+
}
|
|
432
|
+
case 'key': {
|
|
433
|
+
if (!text) {
|
|
434
|
+
return {
|
|
435
|
+
content: [{ type: 'text', text: 'Error: text is required for key action' }],
|
|
436
|
+
isError: true,
|
|
437
|
+
};
|
|
438
|
+
}
|
|
439
|
+
// Handle multiple keys separated by space
|
|
440
|
+
const keys = text.split(' ');
|
|
441
|
+
for (const key of keys) {
|
|
442
|
+
if (key.includes('+')) {
|
|
443
|
+
// Handle modifier keys like ctrl+a
|
|
444
|
+
const parts = key.split('+');
|
|
445
|
+
const modifiers = parts.slice(0, -1);
|
|
446
|
+
const mainKey = parts[parts.length - 1];
|
|
447
|
+
for (const mod of modifiers) {
|
|
448
|
+
await page.keyboard.down(normalizeKey(mod));
|
|
449
|
+
}
|
|
450
|
+
await page.keyboard.press(normalizeKey(mainKey));
|
|
451
|
+
for (const mod of modifiers.reverse()) {
|
|
452
|
+
await page.keyboard.up(normalizeKey(mod));
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
else {
|
|
456
|
+
await page.keyboard.press(normalizeKey(key));
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
return {
|
|
460
|
+
content: [{ type: 'text', text: `Pressed: ${text}` }],
|
|
461
|
+
};
|
|
462
|
+
}
|
|
463
|
+
case 'wait': {
|
|
464
|
+
// Validate duration
|
|
465
|
+
if (duration !== undefined && duration < 0) {
|
|
466
|
+
return {
|
|
467
|
+
content: [{ type: 'text', text: 'Error: duration cannot be negative' }],
|
|
468
|
+
isError: true,
|
|
469
|
+
};
|
|
470
|
+
}
|
|
471
|
+
const waitTime = Math.min(Math.max((duration || 1) * 1000, 0), 30000);
|
|
472
|
+
await new Promise((resolve) => setTimeout(resolve, waitTime));
|
|
473
|
+
return {
|
|
474
|
+
content: [{ type: 'text', text: `Waited ${waitTime / 1000} seconds` }],
|
|
475
|
+
};
|
|
476
|
+
}
|
|
477
|
+
case 'scroll': {
|
|
478
|
+
if (!coordinate) {
|
|
479
|
+
return {
|
|
480
|
+
content: [{ type: 'text', text: 'Error: coordinate is required for scroll' }],
|
|
481
|
+
isError: true,
|
|
482
|
+
};
|
|
483
|
+
}
|
|
484
|
+
if (!scrollDirection) {
|
|
485
|
+
return {
|
|
486
|
+
content: [
|
|
487
|
+
{ type: 'text', text: 'Error: scroll_direction is required for scroll' },
|
|
488
|
+
],
|
|
489
|
+
isError: true,
|
|
490
|
+
};
|
|
491
|
+
}
|
|
492
|
+
const scrollValidation = await validateCoordinates(page, coordinate[0], coordinate[1]);
|
|
493
|
+
if (!scrollValidation.valid) {
|
|
494
|
+
return {
|
|
495
|
+
content: [{ type: 'text', text: `Error: ${scrollValidation.warning}` }],
|
|
496
|
+
isError: true,
|
|
497
|
+
};
|
|
498
|
+
}
|
|
499
|
+
const deltaMultiplier = 100;
|
|
500
|
+
let deltaX = 0;
|
|
501
|
+
let deltaY = 0;
|
|
502
|
+
switch (scrollDirection) {
|
|
503
|
+
case 'up':
|
|
504
|
+
deltaY = -scrollAmount * deltaMultiplier;
|
|
505
|
+
break;
|
|
506
|
+
case 'down':
|
|
507
|
+
deltaY = scrollAmount * deltaMultiplier;
|
|
508
|
+
break;
|
|
509
|
+
case 'left':
|
|
510
|
+
deltaX = -scrollAmount * deltaMultiplier;
|
|
511
|
+
break;
|
|
512
|
+
case 'right':
|
|
513
|
+
deltaX = scrollAmount * deltaMultiplier;
|
|
514
|
+
break;
|
|
515
|
+
}
|
|
516
|
+
// Try CDP mouse wheel first, fallback to JavaScript scroll if it times out
|
|
517
|
+
let usedFallback = false;
|
|
518
|
+
try {
|
|
519
|
+
await page.mouse.move(coordinate[0], coordinate[1]);
|
|
520
|
+
await page.mouse.wheel({ deltaX, deltaY });
|
|
521
|
+
}
|
|
522
|
+
catch (scrollError) {
|
|
523
|
+
// Fallback to JavaScript scroll if mouse.wheel fails (timeout, etc.)
|
|
524
|
+
usedFallback = true;
|
|
525
|
+
await page.evaluate((dx, dy) => {
|
|
526
|
+
window.scrollBy(dx, dy);
|
|
527
|
+
}, deltaX, deltaY);
|
|
528
|
+
}
|
|
529
|
+
const scrollMethod = usedFallback ? ' (via JavaScript fallback)' : '';
|
|
530
|
+
return {
|
|
531
|
+
content: [
|
|
532
|
+
{
|
|
533
|
+
type: 'text',
|
|
534
|
+
text: `Scrolled ${scrollDirection} at (${coordinate[0]}, ${coordinate[1]})${scrollMethod}`,
|
|
535
|
+
},
|
|
536
|
+
],
|
|
537
|
+
};
|
|
538
|
+
}
|
|
539
|
+
case 'scroll_to': {
|
|
540
|
+
if (!ref) {
|
|
541
|
+
return {
|
|
542
|
+
content: [{ type: 'text', text: 'Error: ref is required for scroll_to' }],
|
|
543
|
+
isError: true,
|
|
544
|
+
};
|
|
545
|
+
}
|
|
546
|
+
const refIdManager = (0, ref_id_manager_1.getRefIdManager)();
|
|
547
|
+
const refEntry = refIdManager.getRef(sessionId, tabId, ref);
|
|
548
|
+
if (!refEntry) {
|
|
549
|
+
return {
|
|
550
|
+
content: [{ type: 'text', text: `Error: Element ${ref} not found` }],
|
|
551
|
+
isError: true,
|
|
552
|
+
};
|
|
553
|
+
}
|
|
554
|
+
// Use CDP to scroll element into view
|
|
555
|
+
const cdpClient = sessionManager.getCDPClient();
|
|
556
|
+
await cdpClient.send(page, 'DOM.scrollIntoViewIfNeeded', {
|
|
557
|
+
backendNodeId: refEntry.backendDOMNodeId,
|
|
558
|
+
});
|
|
559
|
+
return {
|
|
560
|
+
content: [{ type: 'text', text: `Scrolled to ${ref}` }],
|
|
561
|
+
};
|
|
562
|
+
}
|
|
563
|
+
default:
|
|
564
|
+
return {
|
|
565
|
+
content: [{ type: 'text', text: `Error: Unknown action: ${action}` }],
|
|
566
|
+
isError: true,
|
|
567
|
+
};
|
|
568
|
+
}
|
|
569
|
+
}
|
|
570
|
+
catch (error) {
|
|
571
|
+
return {
|
|
572
|
+
content: [
|
|
573
|
+
{
|
|
574
|
+
type: 'text',
|
|
575
|
+
text: `Computer action error: ${error instanceof Error ? error.message : String(error)}`,
|
|
576
|
+
},
|
|
577
|
+
],
|
|
578
|
+
isError: true,
|
|
579
|
+
};
|
|
580
|
+
}
|
|
581
|
+
};
|
|
582
|
+
/**
|
|
583
|
+
* Validate and check coordinates against viewport bounds
|
|
584
|
+
*/
|
|
585
|
+
async function validateCoordinates(page, x, y) {
|
|
586
|
+
// Check for negative coordinates
|
|
587
|
+
if (x < 0 || y < 0) {
|
|
588
|
+
return {
|
|
589
|
+
valid: false,
|
|
590
|
+
warning: `Negative coordinates (${x}, ${y}) are not allowed`,
|
|
591
|
+
};
|
|
592
|
+
}
|
|
593
|
+
try {
|
|
594
|
+
// Get viewport dimensions
|
|
595
|
+
const viewport = page.viewport();
|
|
596
|
+
if (viewport) {
|
|
597
|
+
const { width, height } = viewport;
|
|
598
|
+
if (x > width || y > height) {
|
|
599
|
+
return {
|
|
600
|
+
valid: true,
|
|
601
|
+
warning: `Coordinates (${x}, ${y}) are outside visible viewport (${width}x${height}). The click may not hit the intended target.`,
|
|
602
|
+
};
|
|
603
|
+
}
|
|
604
|
+
}
|
|
605
|
+
}
|
|
606
|
+
catch {
|
|
607
|
+
// If we can't get viewport, just allow the operation
|
|
608
|
+
}
|
|
609
|
+
return { valid: true };
|
|
610
|
+
}
|
|
611
|
+
function normalizeKey(key) {
|
|
612
|
+
const keyMap = {
|
|
613
|
+
ctrl: 'Control',
|
|
614
|
+
cmd: 'Meta',
|
|
615
|
+
meta: 'Meta',
|
|
616
|
+
alt: 'Alt',
|
|
617
|
+
shift: 'Shift',
|
|
618
|
+
enter: 'Enter',
|
|
619
|
+
tab: 'Tab',
|
|
620
|
+
escape: 'Escape',
|
|
621
|
+
esc: 'Escape',
|
|
622
|
+
backspace: 'Backspace',
|
|
623
|
+
delete: 'Delete',
|
|
624
|
+
up: 'ArrowUp',
|
|
625
|
+
down: 'ArrowDown',
|
|
626
|
+
left: 'ArrowLeft',
|
|
627
|
+
right: 'ArrowRight',
|
|
628
|
+
home: 'Home',
|
|
629
|
+
end: 'End',
|
|
630
|
+
pageup: 'PageUp',
|
|
631
|
+
pagedown: 'PageDown',
|
|
632
|
+
};
|
|
633
|
+
return keyMap[key.toLowerCase()] || key;
|
|
634
|
+
}
|
|
635
|
+
function registerComputerTool(server) {
|
|
636
|
+
server.registerTool('computer', handler, definition);
|
|
637
|
+
}
|
|
638
|
+
//# sourceMappingURL=computer.js.map
|