@midscene/web 1.9.8-beta-20260618014851.0 → 1.9.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (67) hide show
  1. package/dist/es/bridge-mode/io-client.mjs +1 -1
  2. package/dist/es/bridge-mode/io-server.mjs +2 -2
  3. package/dist/es/bridge-mode/io-server.mjs.map +1 -1
  4. package/dist/es/bridge-mode/page-browser-side.mjs +1 -1
  5. package/dist/es/bridge-mode/page-browser-side.mjs.map +1 -1
  6. package/dist/es/cdp-proxy-constants.mjs.map +1 -1
  7. package/dist/es/cdp-proxy-manager.mjs +1 -1
  8. package/dist/es/cdp-proxy-manager.mjs.map +1 -1
  9. package/dist/es/cdp-proxy.mjs.map +1 -1
  10. package/dist/es/cdp-target-store.mjs +1 -1
  11. package/dist/es/cdp-target-store.mjs.map +1 -1
  12. package/dist/es/chrome-extension/page.mjs +1 -0
  13. package/dist/es/chrome-extension/page.mjs.map +1 -1
  14. package/dist/es/cli.mjs +4 -4
  15. package/dist/es/cli.mjs.map +1 -1
  16. package/dist/es/index.mjs +2 -2
  17. package/dist/es/{agent-init-args.mjs → mcp-agent-init-args.mjs} +2 -2
  18. package/dist/es/{agent-init-args.mjs.map → mcp-agent-init-args.mjs.map} +1 -1
  19. package/dist/es/mcp-server.mjs +35 -0
  20. package/dist/es/mcp-server.mjs.map +1 -0
  21. package/dist/es/{agent-tools-cdp.mjs → mcp-tools-cdp.mjs} +5 -5
  22. package/dist/es/mcp-tools-cdp.mjs.map +1 -0
  23. package/dist/es/{agent-tools-puppeteer.mjs → mcp-tools-puppeteer.mjs} +7 -7
  24. package/dist/es/mcp-tools-puppeteer.mjs.map +1 -0
  25. package/dist/es/{agent-tools.mjs → mcp-tools.mjs} +4 -4
  26. package/dist/es/mcp-tools.mjs.map +1 -0
  27. package/dist/lib/bridge-mode/io-client.js +1 -1
  28. package/dist/lib/bridge-mode/io-server.js +2 -2
  29. package/dist/lib/bridge-mode/io-server.js.map +1 -1
  30. package/dist/lib/bridge-mode/page-browser-side.js +1 -1
  31. package/dist/lib/bridge-mode/page-browser-side.js.map +1 -1
  32. package/dist/lib/cdp-proxy-constants.js.map +1 -1
  33. package/dist/lib/cdp-proxy-manager.js +1 -1
  34. package/dist/lib/cdp-proxy-manager.js.map +1 -1
  35. package/dist/lib/cdp-proxy.js.map +1 -1
  36. package/dist/lib/cdp-target-store.js +1 -1
  37. package/dist/lib/cdp-target-store.js.map +1 -1
  38. package/dist/lib/chrome-extension/page.js +1 -0
  39. package/dist/lib/chrome-extension/page.js.map +1 -1
  40. package/dist/lib/cli.js +5 -5
  41. package/dist/lib/cli.js.map +1 -1
  42. package/dist/lib/index.js +4 -4
  43. package/dist/lib/{agent-init-args.js → mcp-agent-init-args.js} +2 -2
  44. package/dist/lib/{agent-init-args.js.map → mcp-agent-init-args.js.map} +1 -1
  45. package/dist/lib/mcp-server.js +75 -0
  46. package/dist/lib/mcp-server.js.map +1 -0
  47. package/dist/lib/{agent-tools-cdp.js → mcp-tools-cdp.js} +7 -7
  48. package/dist/lib/mcp-tools-cdp.js.map +1 -0
  49. package/dist/lib/{agent-tools-puppeteer.js → mcp-tools-puppeteer.js} +9 -9
  50. package/dist/lib/mcp-tools-puppeteer.js.map +1 -0
  51. package/dist/lib/{agent-tools.js → mcp-tools.js} +6 -6
  52. package/dist/lib/mcp-tools.js.map +1 -0
  53. package/dist/types/cdp-proxy-manager.d.ts +1 -1
  54. package/dist/types/cdp-proxy.d.ts +1 -1
  55. package/dist/types/index.d.ts +2 -2
  56. package/dist/types/{agent-init-args.d.ts → mcp-agent-init-args.d.ts} +1 -1
  57. package/dist/types/mcp-server.d.ts +26 -0
  58. package/dist/types/{agent-tools-cdp.d.ts → mcp-tools-cdp.d.ts} +4 -4
  59. package/dist/types/{agent-tools-puppeteer.d.ts → mcp-tools-puppeteer.d.ts} +4 -4
  60. package/dist/types/{agent-tools.d.ts → mcp-tools.d.ts} +4 -4
  61. package/package.json +9 -4
  62. package/dist/es/agent-tools-cdp.mjs.map +0 -1
  63. package/dist/es/agent-tools-puppeteer.mjs.map +0 -1
  64. package/dist/es/agent-tools.mjs.map +0 -1
  65. package/dist/lib/agent-tools-cdp.js.map +0 -1
  66. package/dist/lib/agent-tools-puppeteer.js.map +0 -1
  67. package/dist/lib/agent-tools.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"chrome-extension/page.mjs","sources":["../../../src/chrome-extension/page.ts"],"sourcesContent":["/// <reference types=\"chrome\" />\n\n/*\n It is used to interact with the page tab from the chrome extension.\n The page must be active when interacting with it.\n*/\n\nimport { limitOpenNewTabScript } from '@/web-element';\nimport type {\n ElementCacheFeature,\n ElementTreeNode,\n Point,\n Rect,\n Size,\n} from '@midscene/core';\nimport type {\n AbstractInterface,\n DeviceAction,\n FileChooserHandler,\n FileChooserRegistration,\n} from '@midscene/core/device';\nimport type { ElementInfo } from '@midscene/shared/extractor';\nimport { treeToList } from '@midscene/shared/extractor';\nimport { createImgBase64ByFormat } from '@midscene/shared/img';\nimport { getDebug } from '@midscene/shared/logger';\nimport { assert } from '@midscene/shared/utils';\nimport type { Protocol as CDPTypes } from 'devtools-protocol';\nimport {\n type CacheFeatureOptions,\n type WebElementCacheFeature,\n buildRectFromElementInfo,\n judgeOrderSensitive,\n sanitizeXpaths,\n} from '../common/cache-helper';\nimport {\n type KeyInput,\n type MouseButton,\n commonWebActionsForWebPage,\n} from '../web-page';\nimport { CdpKeyboard } from './cdpInput';\nimport {\n getHtmlElementScript,\n injectStopWaterFlowAnimation,\n injectWaterFlowAnimation,\n} from './dynamic-scripts';\n\nconst debug = getDebug('web:chrome-extension:page');\n\nfunction sleep(ms: number) {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\nfunction hasFlatNodeAttribute(\n attributes: string[] | undefined,\n name: string,\n): boolean {\n if (!attributes) return false;\n for (let i = 0; i < attributes.length; i += 2) {\n if (attributes[i] === name) return true;\n }\n return false;\n}\n\nfunction serializeError(error: Error): {\n message: string;\n name?: string;\n stack?: string;\n} {\n return {\n message: error.message,\n name: error.name,\n stack: error.stack,\n };\n}\n\nexport default class ChromeExtensionProxyPage implements AbstractInterface {\n interfaceType = 'chrome-extension-proxy';\n\n public forceSameTabNavigation: boolean;\n\n private viewportSize?: Size;\n\n private activeTabId: number | null = null;\n\n private destroyed = false;\n\n private fileChooserEventHandler?: Parameters<\n typeof chrome.debugger.onEvent.addListener\n >[0];\n\n private fileChooserRegistrationVersion = 0;\n\n private bridgeFileChooserDispose?: () => void;\n\n private bridgeFileChooserGetError?: FileChooserRegistration['getError'];\n\n private isMobileEmulation: boolean | null = null;\n\n public _continueWhenFailedToAttachDebugger = false;\n\n constructor(forceSameTabNavigation: boolean) {\n this.forceSameTabNavigation = forceSameTabNavigation;\n }\n\n actionSpace(): DeviceAction[] {\n return commonWebActionsForWebPage(this);\n }\n\n public async setActiveTabId(tabId: number) {\n if (this.activeTabId) {\n throw new Error(\n `Active tab id is already set, which is ${this.activeTabId}, cannot set it to ${tabId}`,\n );\n }\n await chrome.tabs.update(tabId, { active: true });\n this.activeTabId = tabId;\n }\n\n public async getActiveTabId() {\n return this.activeTabId;\n }\n\n /**\n * Get a list of current tabs\n * @returns {Promise<Array<{id: number, title: string, url: string}>>}\n */\n public async getBrowserTabList(): Promise<\n { id: string; title: string; url: string; currentActiveTab: boolean }[]\n > {\n const tabs = await chrome.tabs.query({ currentWindow: true });\n return tabs\n .map((tab) => ({\n id: `${tab.id}`,\n title: tab.title,\n url: tab.url,\n currentActiveTab: tab.active,\n }))\n .filter((tab) => tab.id && tab.title && tab.url) as {\n id: string;\n title: string;\n url: string;\n currentActiveTab: boolean;\n }[];\n }\n\n public async getTabIdOrConnectToCurrentTab() {\n if (this.activeTabId) {\n // alway keep on the connected tab\n return this.activeTabId;\n }\n const tabId = await chrome.tabs\n .query({ active: true, currentWindow: true })\n .then((tabs) => tabs[0]?.id);\n this.activeTabId = tabId || 0;\n return this.activeTabId;\n }\n\n /**\n * Ensure debugger is attached to the current tab.\n * Uses lazy attach pattern - only attaches when needed.\n */\n private async ensureDebuggerAttached() {\n assert(!this.destroyed, 'Page is destroyed');\n\n const url = await this.url();\n if (url.startsWith('chrome://')) {\n throw new Error(\n 'Cannot attach debugger to chrome:// pages, please use Midscene in a normal page with http://, https:// or file://',\n );\n }\n\n const tabId = await this.getTabIdOrConnectToCurrentTab();\n\n try {\n await chrome.debugger.attach({ tabId }, '1.3');\n console.log('Debugger attached to tab:', tabId);\n } catch (error) {\n const errorMsg = (error as Error)?.message || '';\n // Already attached is OK, we can continue\n if (errorMsg.includes('Another debugger is already attached')) {\n console.log('Debugger already attached to tab:', tabId);\n return;\n }\n\n if (this._continueWhenFailedToAttachDebugger) {\n console.warn(\n 'Failed to attach debugger, but continuing due to _continueWhenFailedToAttachDebugger flag',\n error,\n );\n return;\n }\n\n throw error;\n }\n\n // Wait for debugger banner in Chrome to appear\n await sleep(500);\n\n // Enable water flow animation. Non-fatal: this is a purely visual\n // overlay, and Chrome can briefly detach the debugger between\n // attach() and the eval below (cross-origin navigation / Site\n // Isolation race). If we awaited it and it threw \"Debugger is not\n // attached\", the error would propagate out of the catch block in\n // sendCommandToDebugger, preventing the actual CDP command from\n // ever being retried. Fire-and-forget here so the lazy-attach\n // retry can succeed even when the animation fails.\n this.enableWaterFlowAnimation().catch((err) => {\n console.warn('Failed to enable water flow animation:', err);\n });\n }\n\n private async showMousePointer(x: number, y: number) {\n // update mouse pointer while redirecting\n const pointerScript = `(() => {\n if(typeof window.midsceneWaterFlowAnimation !== 'undefined') {\n window.midsceneWaterFlowAnimation.enable();\n window.midsceneWaterFlowAnimation.showMousePointer(${x}, ${y});\n } else {\n console.log('midsceneWaterFlowAnimation is not defined');\n }\n })()`;\n\n await this.sendCommandToDebugger('Runtime.evaluate', {\n expression: `${pointerScript}`,\n });\n }\n\n private async hideMousePointer() {\n await this.sendCommandToDebugger('Runtime.evaluate', {\n expression: `(() => {\n if(typeof window.midsceneWaterFlowAnimation !== 'undefined') {\n window.midsceneWaterFlowAnimation.hideMousePointer();\n }\n })()`,\n });\n }\n\n /**\n * Public method to detach debugger without destroying the page instance.\n * Useful for error recovery scenarios where we want to remove the debugger banner\n * without completely destroying the page.\n */\n public async detachDebugger(tabId?: number) {\n const tabIdToDetach = tabId || (await this.getTabIdOrConnectToCurrentTab());\n console.log('detaching debugger from tab:', tabIdToDetach);\n\n try {\n await this.disableWaterFlowAnimation(tabIdToDetach);\n await sleep(200); // wait for the animation to stop\n } catch (error) {\n console.warn('Failed to disable water flow animation', error);\n }\n\n try {\n await chrome.debugger.detach({ tabId: tabIdToDetach });\n console.log('Debugger detached successfully from tab:', tabIdToDetach);\n } catch (error) {\n // Tab might be closed or debugger already detached - this is OK\n console.warn(\n 'Failed to detach debugger (may already be detached):',\n error,\n );\n }\n }\n\n private async enableWaterFlowAnimation() {\n const tabId = await this.getTabIdOrConnectToCurrentTab();\n\n // limit open page in new tab\n if (this.forceSameTabNavigation) {\n await chrome.debugger.sendCommand({ tabId }, 'Runtime.evaluate', {\n expression: limitOpenNewTabScript,\n });\n }\n\n const script = await injectWaterFlowAnimation();\n // we will call this function in sendCommandToDebugger, so we have to use the chrome.debugger.sendCommand\n await chrome.debugger.sendCommand({ tabId }, 'Runtime.evaluate', {\n expression: script,\n });\n }\n\n private async disableWaterFlowAnimation(tabId: number) {\n const script = await injectStopWaterFlowAnimation();\n\n await chrome.debugger.sendCommand({ tabId }, 'Runtime.evaluate', {\n expression: script,\n });\n }\n\n /**\n * Send a command to the debugger with automatic attach and retry on detachment.\n * Uses lazy attach pattern - will automatically attach if not already attached.\n */\n private async sendCommandToDebugger<ResponseType = any, RequestType = any>(\n command: string,\n params: RequestType,\n retryCount = 0,\n ): Promise<ResponseType> {\n const MAX_RETRIES = 2;\n const tabId = await this.getTabIdOrConnectToCurrentTab();\n\n try {\n // Try to send command directly first\n const result = (await chrome.debugger.sendCommand(\n { tabId },\n command,\n params as any,\n )) as ResponseType;\n\n // Enable water flow animation after successful command (don't await)\n this.enableWaterFlowAnimation().catch((err) => {\n console.warn('Failed to enable water flow animation:', err);\n });\n\n return result;\n } catch (error) {\n // If command failed, check if it's because debugger is not attached\n const errorMsg = (error as Error)?.message || '';\n const isDetachError =\n errorMsg.includes('Debugger is not attached') ||\n errorMsg.includes('Cannot access a Target') ||\n errorMsg.includes('No target with given id');\n\n if (isDetachError && retryCount < MAX_RETRIES) {\n console.log(\n `Debugger not attached for command \"${command}\", attempting to attach (retry ${retryCount + 1}/${MAX_RETRIES})`,\n );\n\n // Try to attach and retry\n await this.ensureDebuggerAttached();\n\n return this.sendCommandToDebugger<ResponseType, RequestType>(\n command,\n params,\n retryCount + 1,\n );\n }\n\n // Not a detach error or out of retries\n throw error;\n }\n }\n\n private async getPageContentByCDP() {\n const script = await getHtmlElementScript();\n\n // check tab url\n await this.sendCommandToDebugger<\n CDPTypes.Runtime.EvaluateResponse,\n CDPTypes.Runtime.EvaluateRequest\n >('Runtime.evaluate', {\n expression: script,\n });\n\n const expression = () => {\n const tree = (\n window as any\n ).midscene_element_inspector.webExtractNodeTree();\n\n return {\n tree,\n size: {\n width: document.documentElement.clientWidth,\n height: document.documentElement.clientHeight,\n },\n };\n };\n const returnValue = await this.sendCommandToDebugger<\n CDPTypes.Runtime.EvaluateResponse,\n CDPTypes.Runtime.EvaluateRequest\n >('Runtime.evaluate', {\n expression: `(${expression.toString()})()`,\n returnByValue: true,\n });\n\n if (!returnValue.result.value) {\n const errorDescription =\n returnValue.exceptionDetails?.exception?.description || '';\n if (!errorDescription) {\n console.error('returnValue from cdp', returnValue);\n }\n throw new Error(\n `Failed to get page content from page, error: ${errorDescription}`,\n );\n }\n\n return returnValue.result.value as {\n tree: ElementTreeNode<ElementInfo>;\n size: Size;\n };\n }\n\n public async evaluateJavaScript(script: string) {\n return this.sendCommandToDebugger('Runtime.evaluate', {\n expression: script,\n awaitPromise: true,\n });\n }\n\n async registerFileChooserListener(\n handler: (chooser: FileChooserHandler) => Promise<void>,\n ): Promise<FileChooserRegistration> {\n const registrationVersion = ++this.fileChooserRegistrationVersion;\n const tabId = await this.getTabIdOrConnectToCurrentTab();\n\n await this.sendCommandToDebugger('Page.enable', {});\n await this.sendCommandToDebugger('DOM.enable', {});\n await this.sendCommandToDebugger('Page.setInterceptFileChooserDialog', {\n enabled: true,\n });\n\n if (this.fileChooserEventHandler) {\n chrome.debugger.onEvent.removeListener(this.fileChooserEventHandler);\n this.fileChooserEventHandler = undefined;\n }\n\n let capturedError: Error | undefined;\n let pendingFileChooserHandling = Promise.resolve();\n\n const fileChooserEventHandler: Parameters<\n typeof chrome.debugger.onEvent.addListener\n >[0] = (source, method, params) => {\n if (source.tabId !== tabId || method !== 'Page.fileChooserOpened') {\n return;\n }\n\n const event = params as CDPTypes.Page.FileChooserOpenedEvent;\n if (event.backendNodeId === undefined) {\n debug(\n 'chrome extension file chooser opened without backendNodeId, skip',\n );\n return;\n }\n\n const currentFileChooserHandling = (async () => {\n try {\n await handler({\n accept: async (files: string[]) => {\n const { node } = await this.sendCommandToDebugger<\n CDPTypes.DOM.DescribeNodeResponse,\n CDPTypes.DOM.DescribeNodeRequest\n >('DOM.describeNode', {\n backendNodeId: event.backendNodeId,\n });\n\n const hasWebkitDirectory =\n hasFlatNodeAttribute(node.attributes, 'webkitdirectory') ||\n hasFlatNodeAttribute(node.attributes, 'directory');\n if (hasWebkitDirectory) {\n throw new Error(\n 'Directory upload (webkitdirectory) is not supported in Chrome extension bridge mode. Please use Playwright instead, which supports directory upload since version 1.45.',\n );\n }\n\n if (\n files.length > 1 &&\n !hasFlatNodeAttribute(node.attributes, 'multiple')\n ) {\n throw new Error(\n 'Non-multiple file input can only accept single file',\n );\n }\n\n await this.sendCommandToDebugger('DOM.setFileInputFiles', {\n files,\n backendNodeId: event.backendNodeId,\n });\n },\n });\n } catch (error) {\n capturedError =\n error instanceof Error ? error : new Error(String(error));\n }\n })();\n const previousFileChooserHandling = pendingFileChooserHandling;\n pendingFileChooserHandling = Promise.all([\n previousFileChooserHandling,\n currentFileChooserHandling,\n ]).then(() => {});\n };\n\n this.fileChooserEventHandler = fileChooserEventHandler;\n chrome.debugger.onEvent.addListener(fileChooserEventHandler);\n\n return {\n dispose: () => {\n if (this.fileChooserEventHandler !== fileChooserEventHandler) {\n return;\n }\n chrome.debugger.onEvent.removeListener(fileChooserEventHandler);\n this.fileChooserEventHandler = undefined;\n Promise.resolve()\n .then(() => {\n if (this.fileChooserRegistrationVersion !== registrationVersion) {\n return;\n }\n return this.sendCommandToDebugger(\n 'Page.setInterceptFileChooserDialog',\n {\n enabled: false,\n },\n );\n })\n .catch((error) => {\n debug('failed to disable file chooser interception: %O', error);\n });\n },\n getError: async () => {\n await pendingFileChooserHandling;\n return capturedError;\n },\n };\n }\n\n async registerFileChooserAccept(files: string[]): Promise<void> {\n this.clearFileChooserAccept();\n const { dispose, getError } = await this.registerFileChooserListener(\n async (chooser) => {\n await chooser.accept(files);\n },\n );\n this.bridgeFileChooserDispose = dispose;\n this.bridgeFileChooserGetError = getError;\n }\n\n clearFileChooserAccept(): void {\n this.bridgeFileChooserDispose?.();\n this.bridgeFileChooserDispose = undefined;\n this.bridgeFileChooserGetError = undefined;\n }\n\n async getFileChooserError(): Promise<\n { message: string; name?: string; stack?: string } | undefined\n > {\n const error = await this.bridgeFileChooserGetError?.();\n return error ? serializeError(error) : undefined;\n }\n\n async beforeInvokeAction(): Promise<void> {\n // current implementation is wait until domReadyState is complete\n try {\n await this.waitUntilNetworkIdle();\n } catch (error) {\n // console.warn('Failed to wait until network idle', error);\n }\n }\n\n private async waitUntilNetworkIdle() {\n const timeout = 10000;\n const startTime = Date.now();\n let lastReadyState = '';\n while (Date.now() - startTime < timeout) {\n const result = await this.sendCommandToDebugger('Runtime.evaluate', {\n expression: 'document.readyState',\n });\n lastReadyState = result.result.value;\n if (lastReadyState === 'complete') {\n await new Promise((resolve) => setTimeout(resolve, 300));\n return;\n }\n await new Promise((resolve) => setTimeout(resolve, 300));\n }\n throw new Error(\n `Failed to wait until network idle, last readyState: ${lastReadyState}`,\n );\n }\n\n // @deprecated\n async getElementsInfo() {\n const tree = await this.getElementsNodeTree();\n return treeToList(tree);\n }\n\n async getXpathsByPoint(point: Point, isOrderSensitive = false) {\n const script = await getHtmlElementScript();\n\n await this.sendCommandToDebugger<\n CDPTypes.Runtime.EvaluateResponse,\n CDPTypes.Runtime.EvaluateRequest\n >('Runtime.evaluate', {\n expression: script,\n });\n\n const result = await this.sendCommandToDebugger('Runtime.evaluate', {\n expression: `window.midscene_element_inspector.getXpathsByPoint({left: ${point.left}, top: ${point.top}}, ${isOrderSensitive})`,\n returnByValue: true,\n });\n return result.result.value;\n }\n\n async getElementInfoByXpath(xpath: string) {\n const script = await getHtmlElementScript();\n\n // check tab url\n await this.sendCommandToDebugger<\n CDPTypes.Runtime.EvaluateResponse,\n CDPTypes.Runtime.EvaluateRequest\n >('Runtime.evaluate', {\n expression: script,\n });\n const result = await this.sendCommandToDebugger('Runtime.evaluate', {\n expression: `window.midscene_element_inspector.getElementInfoByXpath(${JSON.stringify(xpath)})`,\n returnByValue: true,\n });\n return result.result.value;\n }\n\n async cacheFeatureForPoint(\n center: [number, number],\n options?: CacheFeatureOptions,\n ): Promise<ElementCacheFeature> {\n const point: Point = { left: center[0], top: center[1] };\n\n try {\n const isOrderSensitive = await judgeOrderSensitive(options, debug);\n const xpaths = await this.getXpathsByPoint(point, isOrderSensitive);\n return { xpaths: sanitizeXpaths(xpaths) };\n } catch (error) {\n debug('cacheFeatureForPoint failed: %O', error);\n return { xpaths: [] };\n }\n }\n\n async rectMatchesCacheFeature(feature: ElementCacheFeature): Promise<Rect> {\n const xpaths = sanitizeXpaths((feature as WebElementCacheFeature).xpaths);\n\n for (const xpath of xpaths) {\n try {\n const elementInfo = await this.getElementInfoByXpath(xpath);\n if (elementInfo?.rect) {\n return buildRectFromElementInfo(elementInfo);\n }\n } catch (error) {\n debug('rectMatchesCacheFeature failed for xpath %s: %O', xpath, error);\n }\n }\n\n throw new Error(\n `No matching element rect found for cache feature (tried ${xpaths.length} xpath(s))`,\n );\n }\n\n async getElementsNodeTree() {\n await this.hideMousePointer();\n const content = await this.getPageContentByCDP();\n if (content?.size) {\n this.viewportSize = content.size;\n }\n\n return content?.tree || { node: null, children: [] };\n }\n\n async size() {\n if (this.viewportSize) return this.viewportSize;\n\n const result = await this.sendCommandToDebugger('Runtime.evaluate', {\n expression: '({width: window.innerWidth, height: window.innerHeight})',\n returnByValue: true,\n });\n\n const sizeInfo: Size = result.result.value;\n console.log('sizeInfo', sizeInfo);\n\n this.viewportSize = sizeInfo;\n return sizeInfo;\n }\n\n async screenshotBase64() {\n // screenshot by cdp\n await this.hideMousePointer();\n const format = 'jpeg';\n const base64 = await this.sendCommandToDebugger('Page.captureScreenshot', {\n format,\n quality: 90,\n });\n return createImgBase64ByFormat(format, base64.data);\n }\n\n async url() {\n const tabId = await this.getTabIdOrConnectToCurrentTab();\n const url = await chrome.tabs.get(tabId).then((tab) => tab.url);\n return url || '';\n }\n\n async navigate(url: string): Promise<void> {\n const tabId = await this.getTabIdOrConnectToCurrentTab();\n await chrome.tabs.update(tabId, { url });\n // Wait for navigation to complete\n // Note: debugger will auto-reattach on next command if detached during navigation\n await this.waitUntilNetworkIdle();\n }\n\n async reload(): Promise<void> {\n const tabId = await this.getTabIdOrConnectToCurrentTab();\n await chrome.tabs.reload(tabId);\n // Wait for reload to complete\n await this.waitUntilNetworkIdle();\n }\n\n async goBack(): Promise<void> {\n const tabId = await this.getTabIdOrConnectToCurrentTab();\n await chrome.tabs.goBack(tabId);\n // Wait for navigation to complete\n await this.waitUntilNetworkIdle();\n }\n\n async goForward(): Promise<void> {\n const tabId = await this.getTabIdOrConnectToCurrentTab();\n await chrome.tabs.goForward(tabId);\n // Wait for navigation to complete\n await this.waitUntilNetworkIdle();\n }\n\n async stopLoading(): Promise<void> {\n await this.sendCommandToDebugger('Page.stopLoading', {});\n }\n\n async navigationState(): Promise<{ isLoading: boolean }> {\n const tabId = await this.getTabIdOrConnectToCurrentTab();\n const tab = await chrome.tabs.get(tabId);\n return { isLoading: tab.status === 'loading' };\n }\n\n async scrollUntilTop(startingPoint?: Point) {\n if (startingPoint) {\n await this.mouse.move(startingPoint.left, startingPoint.top);\n }\n return this.mouse.wheel(0, -9999999);\n }\n\n async scrollUntilBottom(startingPoint?: Point) {\n if (startingPoint) {\n await this.mouse.move(startingPoint.left, startingPoint.top);\n }\n return this.mouse.wheel(0, 9999999);\n }\n\n async scrollUntilLeft(startingPoint?: Point) {\n if (startingPoint) {\n await this.mouse.move(startingPoint.left, startingPoint.top);\n }\n return this.mouse.wheel(-9999999, 0);\n }\n\n async scrollUntilRight(startingPoint?: Point) {\n if (startingPoint) {\n await this.mouse.move(startingPoint.left, startingPoint.top);\n }\n return this.mouse.wheel(9999999, 0);\n }\n\n async scrollUp(distance?: number, startingPoint?: Point) {\n const { height } = await this.size();\n const scrollDistance = distance || height * 0.7;\n return this.mouse.wheel(\n 0,\n -scrollDistance,\n startingPoint?.left,\n startingPoint?.top,\n );\n }\n\n async scrollDown(distance?: number, startingPoint?: Point) {\n const { height } = await this.size();\n const scrollDistance = distance || height * 0.7;\n return this.mouse.wheel(\n 0,\n scrollDistance,\n startingPoint?.left,\n startingPoint?.top,\n );\n }\n\n async scrollLeft(distance?: number, startingPoint?: Point) {\n const { width } = await this.size();\n const scrollDistance = distance || width * 0.7;\n return this.mouse.wheel(\n -scrollDistance,\n 0,\n startingPoint?.left,\n startingPoint?.top,\n );\n }\n\n async scrollRight(distance?: number, startingPoint?: Point) {\n const { width } = await this.size();\n const scrollDistance = distance || width * 0.7;\n return this.mouse.wheel(\n scrollDistance,\n 0,\n startingPoint?.left,\n startingPoint?.top,\n );\n }\n\n async clearInput(element: ElementInfo) {\n if (!element) {\n console.warn('No element to clear input');\n return;\n }\n\n await this.mouse.click(element.center[0], element.center[1]);\n\n await this.sendCommandToDebugger('Input.dispatchKeyEvent', {\n type: 'keyDown',\n commands: ['selectAll'],\n });\n\n await this.sendCommandToDebugger('Input.dispatchKeyEvent', {\n type: 'keyUp',\n commands: ['selectAll'],\n });\n\n await sleep(100);\n\n await this.keyboard.press({\n key: 'Backspace',\n });\n }\n\n private latestMouseX = 100;\n private latestMouseY = 100;\n\n mouse = {\n click: async (\n x: number,\n y: number,\n options?: { button?: MouseButton; count?: number },\n ) => {\n const { button = 'left', count = 1 } = options || {};\n await this.mouse.move(x, y);\n // detect if the page is in mobile emulation mode\n if (this.isMobileEmulation === null) {\n const result = await this.sendCommandToDebugger('Runtime.evaluate', {\n expression: `(() => {\n return /Android|iPhone|iPad|iPod|Mobile/i.test(navigator.userAgent);\n })()`,\n returnByValue: true,\n });\n this.isMobileEmulation = result?.result?.value;\n }\n\n if (this.isMobileEmulation && button === 'left') {\n // in mobile emulation mode, directly inject click event\n const touchPoints = [{ x: Math.round(x), y: Math.round(y) }];\n await this.sendCommandToDebugger('Input.dispatchTouchEvent', {\n type: 'touchStart',\n touchPoints,\n modifiers: 0,\n });\n\n await this.sendCommandToDebugger('Input.dispatchTouchEvent', {\n type: 'touchEnd',\n touchPoints: [],\n modifiers: 0,\n });\n } else {\n // standard mousePressed + mouseReleased\n for (let i = 0; i < count; i++) {\n const clickCount = i + 1;\n await this.sendCommandToDebugger('Input.dispatchMouseEvent', {\n type: 'mousePressed',\n x,\n y,\n button,\n clickCount,\n });\n await this.sendCommandToDebugger('Input.dispatchMouseEvent', {\n type: 'mouseReleased',\n x,\n y,\n button,\n clickCount,\n });\n if (i < count - 1) {\n await sleep(50);\n }\n }\n }\n },\n wheel: async (\n deltaX: number,\n deltaY: number,\n startX?: number,\n startY?: number,\n ) => {\n const finalX = startX || this.latestMouseX;\n const finalY = startY || this.latestMouseY;\n await this.showMousePointer(finalX, finalY);\n await this.sendCommandToDebugger('Input.dispatchMouseEvent', {\n type: 'mouseWheel',\n x: finalX,\n y: finalY,\n deltaX,\n deltaY,\n });\n this.latestMouseX = finalX;\n this.latestMouseY = finalY;\n },\n move: async (x: number, y: number) => {\n await this.showMousePointer(x, y);\n await this.sendCommandToDebugger('Input.dispatchMouseEvent', {\n type: 'mouseMoved',\n x,\n y,\n });\n this.latestMouseX = x;\n this.latestMouseY = y;\n },\n drag: async (\n from: { x: number; y: number },\n to: { x: number; y: number },\n ) => {\n await this.mouse.move(from.x, from.y);\n\n await sleep(200);\n await this.sendCommandToDebugger('Input.dispatchMouseEvent', {\n type: 'mousePressed',\n x: from.x,\n y: from.y,\n button: 'left',\n clickCount: 1,\n });\n\n await sleep(300);\n\n await this.sendCommandToDebugger('Input.dispatchMouseEvent', {\n type: 'mouseMoved',\n x: to.x,\n y: to.y,\n });\n\n await sleep(500);\n\n await this.sendCommandToDebugger('Input.dispatchMouseEvent', {\n type: 'mouseReleased',\n x: to.x,\n y: to.y,\n button: 'left',\n clickCount: 1,\n });\n\n await sleep(200);\n\n await this.mouse.move(to.x, to.y);\n },\n };\n\n keyboard = {\n type: async (text: string) => {\n const cdpKeyboard = new CdpKeyboard({\n send: this.sendCommandToDebugger.bind(this),\n });\n await cdpKeyboard.type(text, { delay: 0 });\n },\n press: async (\n action:\n | { key: KeyInput; command?: string }\n | { key: KeyInput; command?: string }[],\n ) => {\n const cdpKeyboard = new CdpKeyboard({\n send: this.sendCommandToDebugger.bind(this),\n });\n const keys = Array.isArray(action) ? action : [action];\n for (const k of keys) {\n const commands = k.command ? [k.command] : [];\n await cdpKeyboard.down(k.key, { commands });\n }\n for (const k of [...keys].reverse()) {\n await cdpKeyboard.up(k.key);\n }\n },\n };\n\n async destroy(): Promise<void> {\n this.destroyed = true;\n this.clearFileChooserAccept();\n const tabIdToDetach = this.activeTabId;\n this.activeTabId = null;\n if (tabIdToDetach) {\n await this.detachDebugger(tabIdToDetach);\n }\n }\n\n async longPress(x: number, y: number, duration?: number) {\n duration = duration || 500;\n // Keep a lower bound so the press is registered as a long press rather than\n // a click, but never cap the upper bound: the duration is the caller's\n // intent (e.g. \"hold for 6 seconds\").\n const MIN_LONG_PRESS_DURATION = 300;\n if (duration < MIN_LONG_PRESS_DURATION) {\n duration = MIN_LONG_PRESS_DURATION;\n }\n await this.mouse.move(x, y);\n\n if (this.isMobileEmulation === null) {\n const result = await this.sendCommandToDebugger('Runtime.evaluate', {\n expression: `(() => {\n return /Android|iPhone|iPad|iPod|Mobile/i.test(navigator.userAgent);\n })()`,\n returnByValue: true,\n });\n this.isMobileEmulation = result?.result?.value;\n }\n\n if (this.isMobileEmulation) {\n const touchPoints = [{ x: Math.round(x), y: Math.round(y) }];\n await this.sendCommandToDebugger('Input.dispatchTouchEvent', {\n type: 'touchStart',\n touchPoints,\n modifiers: 0,\n });\n await new Promise((res) => setTimeout(res, duration));\n await this.sendCommandToDebugger('Input.dispatchTouchEvent', {\n type: 'touchEnd',\n touchPoints: [],\n modifiers: 0,\n });\n } else {\n await this.sendCommandToDebugger('Input.dispatchMouseEvent', {\n type: 'mousePressed',\n x,\n y,\n button: 'left',\n clickCount: 1,\n });\n await new Promise((res) => setTimeout(res, duration));\n await this.sendCommandToDebugger('Input.dispatchMouseEvent', {\n type: 'mouseReleased',\n x,\n y,\n button: 'left',\n clickCount: 1,\n });\n }\n this.latestMouseX = x;\n this.latestMouseY = y;\n }\n\n async swipe(\n from: { x: number; y: number },\n to: { x: number; y: number },\n duration?: number,\n ) {\n const LONG_PRESS_THRESHOLD = 500;\n const MIN_PRESS_THRESHOLD = 150;\n duration = duration || 300;\n if (duration < MIN_PRESS_THRESHOLD) {\n duration = MIN_PRESS_THRESHOLD;\n }\n if (duration > LONG_PRESS_THRESHOLD) {\n duration = LONG_PRESS_THRESHOLD;\n }\n\n if (this.isMobileEmulation === null) {\n const result = await this.sendCommandToDebugger('Runtime.evaluate', {\n expression: `(() => {\n return /Android|iPhone|iPad|iPod|Mobile/i.test(navigator.userAgent);\n })()`,\n returnByValue: true,\n });\n this.isMobileEmulation = result?.result?.value;\n }\n\n const steps = 30;\n const delay = duration / steps;\n\n if (this.isMobileEmulation) {\n await this.sendCommandToDebugger('Input.dispatchTouchEvent', {\n type: 'touchStart',\n touchPoints: [{ x: Math.round(from.x), y: Math.round(from.y) }],\n modifiers: 0,\n });\n\n for (let i = 1; i <= steps; i++) {\n const x = from.x + (to.x - from.x) * (i / steps);\n const y = from.y + (to.y - from.y) * (i / steps);\n await this.sendCommandToDebugger('Input.dispatchTouchEvent', {\n type: 'touchMove',\n touchPoints: [{ x: Math.round(x), y: Math.round(y) }],\n modifiers: 0,\n });\n await new Promise((res) => setTimeout(res, delay));\n }\n\n await this.sendCommandToDebugger('Input.dispatchTouchEvent', {\n type: 'touchEnd',\n touchPoints: [],\n modifiers: 0,\n });\n } else {\n await this.mouse.move(from.x, from.y);\n await this.sendCommandToDebugger('Input.dispatchMouseEvent', {\n type: 'mousePressed',\n x: from.x,\n y: from.y,\n button: 'left',\n clickCount: 1,\n });\n\n for (let i = 1; i <= steps; i++) {\n const x = from.x + (to.x - from.x) * (i / steps);\n const y = from.y + (to.y - from.y) * (i / steps);\n await this.mouse.move(x, y);\n await new Promise((res) => setTimeout(res, delay));\n }\n\n await this.sendCommandToDebugger('Input.dispatchMouseEvent', {\n type: 'mouseReleased',\n x: to.x,\n y: to.y,\n button: 'left',\n clickCount: 1,\n });\n }\n\n this.latestMouseX = to.x;\n this.latestMouseY = to.y;\n }\n\n async pinch(\n centerX: number,\n centerY: number,\n startDistance: number,\n endDistance: number,\n duration = 500,\n ): Promise<void> {\n const steps = 30;\n const delay = duration / steps;\n\n const halfStart = startDistance / 2;\n const halfEnd = endDistance / 2;\n\n await this.sendCommandToDebugger('Input.dispatchTouchEvent', {\n type: 'touchStart',\n touchPoints: [\n {\n x: Math.round(centerX),\n y: Math.round(centerY - halfStart),\n id: 0,\n },\n {\n x: Math.round(centerX),\n y: Math.round(centerY + halfStart),\n id: 1,\n },\n ],\n modifiers: 0,\n });\n\n for (let i = 1; i <= steps; i++) {\n const progress = i / steps;\n const currentHalf = halfStart + (halfEnd - halfStart) * progress;\n await this.sendCommandToDebugger('Input.dispatchTouchEvent', {\n type: 'touchMove',\n touchPoints: [\n {\n x: Math.round(centerX),\n y: Math.round(centerY - currentHalf),\n id: 0,\n },\n {\n x: Math.round(centerX),\n y: Math.round(centerY + currentHalf),\n id: 1,\n },\n ],\n modifiers: 0,\n });\n await new Promise((res) => setTimeout(res, delay));\n }\n\n await this.sendCommandToDebugger('Input.dispatchTouchEvent', {\n type: 'touchEnd',\n touchPoints: [],\n modifiers: 0,\n });\n }\n}\n"],"names":["debug","getDebug","sleep","ms","Promise","resolve","setTimeout","hasFlatNodeAttribute","attributes","name","i","serializeError","error","ChromeExtensionProxyPage","commonWebActionsForWebPage","tabId","Error","chrome","tabs","tab","assert","url","console","errorMsg","err","x","y","pointerScript","tabIdToDetach","limitOpenNewTabScript","script","injectWaterFlowAnimation","injectStopWaterFlowAnimation","command","params","retryCount","MAX_RETRIES","result","isDetachError","getHtmlElementScript","expression","tree","window","document","returnValue","errorDescription","handler","registrationVersion","undefined","capturedError","pendingFileChooserHandling","fileChooserEventHandler","source","method","event","currentFileChooserHandling","files","node","hasWebkitDirectory","String","previousFileChooserHandling","dispose","getError","chooser","timeout","startTime","Date","lastReadyState","treeToList","point","isOrderSensitive","xpath","JSON","center","options","judgeOrderSensitive","xpaths","sanitizeXpaths","feature","elementInfo","buildRectFromElementInfo","content","sizeInfo","format","base64","createImgBase64ByFormat","startingPoint","distance","height","scrollDistance","width","element","duration","MIN_LONG_PRESS_DURATION","touchPoints","Math","res","from","to","LONG_PRESS_THRESHOLD","MIN_PRESS_THRESHOLD","steps","delay","centerX","centerY","startDistance","endDistance","halfStart","halfEnd","progress","currentHalf","forceSameTabNavigation","button","count","clickCount","deltaX","deltaY","startX","startY","finalX","finalY","text","cdpKeyboard","CdpKeyboard","action","keys","Array","k","commands"],"mappings":"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"}
1
+ {"version":3,"file":"chrome-extension/page.mjs","sources":["../../../src/chrome-extension/page.ts"],"sourcesContent":["/// <reference types=\"chrome\" />\n\n/*\n It is used to interact with the page tab from the chrome extension.\n The page must be active when interacting with it.\n*/\n\nimport { limitOpenNewTabScript } from '@/web-element';\nimport type {\n ElementCacheFeature,\n ElementTreeNode,\n Point,\n Rect,\n Size,\n} from '@midscene/core';\nimport type {\n AbstractInterface,\n DeviceAction,\n FileChooserHandler,\n FileChooserRegistration,\n} from '@midscene/core/device';\nimport type { ElementInfo } from '@midscene/shared/extractor';\nimport { treeToList } from '@midscene/shared/extractor';\nimport { createImgBase64ByFormat } from '@midscene/shared/img';\nimport { getDebug } from '@midscene/shared/logger';\nimport { assert } from '@midscene/shared/utils';\nimport type { Protocol as CDPTypes } from 'devtools-protocol';\nimport {\n type CacheFeatureOptions,\n type WebElementCacheFeature,\n buildRectFromElementInfo,\n judgeOrderSensitive,\n sanitizeXpaths,\n} from '../common/cache-helper';\nimport {\n type KeyInput,\n type MouseButton,\n commonWebActionsForWebPage,\n} from '../web-page';\nimport { CdpKeyboard } from './cdpInput';\nimport {\n getHtmlElementScript,\n injectStopWaterFlowAnimation,\n injectWaterFlowAnimation,\n} from './dynamic-scripts';\n\nconst debug = getDebug('web:chrome-extension:page');\n\nfunction sleep(ms: number) {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\nfunction hasFlatNodeAttribute(\n attributes: string[] | undefined,\n name: string,\n): boolean {\n if (!attributes) return false;\n for (let i = 0; i < attributes.length; i += 2) {\n if (attributes[i] === name) return true;\n }\n return false;\n}\n\nfunction serializeError(error: Error): {\n message: string;\n name?: string;\n stack?: string;\n} {\n return {\n message: error.message,\n name: error.name,\n stack: error.stack,\n };\n}\n\nexport default class ChromeExtensionProxyPage implements AbstractInterface {\n interfaceType = 'chrome-extension-proxy';\n\n public forceSameTabNavigation: boolean;\n\n private viewportSize?: Size;\n\n private activeTabId: number | null = null;\n\n private destroyed = false;\n\n private fileChooserEventHandler?: Parameters<\n typeof chrome.debugger.onEvent.addListener\n >[0];\n\n private fileChooserRegistrationVersion = 0;\n\n private bridgeFileChooserDispose?: () => void;\n\n private bridgeFileChooserGetError?: FileChooserRegistration['getError'];\n\n private isMobileEmulation: boolean | null = null;\n\n public _continueWhenFailedToAttachDebugger = false;\n\n constructor(forceSameTabNavigation: boolean) {\n this.forceSameTabNavigation = forceSameTabNavigation;\n }\n\n actionSpace(): DeviceAction[] {\n return commonWebActionsForWebPage(this);\n }\n\n public async setActiveTabId(tabId: number) {\n if (this.activeTabId) {\n throw new Error(\n `Active tab id is already set, which is ${this.activeTabId}, cannot set it to ${tabId}`,\n );\n }\n await chrome.tabs.update(tabId, { active: true });\n this.activeTabId = tabId;\n }\n\n public async getActiveTabId() {\n return this.activeTabId;\n }\n\n /**\n * Get a list of current tabs\n * @returns {Promise<Array<{id: number, title: string, url: string}>>}\n */\n public async getBrowserTabList(): Promise<\n { id: string; title: string; url: string; currentActiveTab: boolean }[]\n > {\n const tabs = await chrome.tabs.query({ currentWindow: true });\n return tabs\n .map((tab) => ({\n id: `${tab.id}`,\n title: tab.title,\n url: tab.url,\n currentActiveTab: tab.active,\n }))\n .filter((tab) => tab.id && tab.title && tab.url) as {\n id: string;\n title: string;\n url: string;\n currentActiveTab: boolean;\n }[];\n }\n\n public async getTabIdOrConnectToCurrentTab() {\n if (this.activeTabId) {\n // alway keep on the connected tab\n return this.activeTabId;\n }\n const tabId = await chrome.tabs\n .query({ active: true, currentWindow: true })\n .then((tabs) => tabs[0]?.id);\n this.activeTabId = tabId || 0;\n return this.activeTabId;\n }\n\n /**\n * Ensure debugger is attached to the current tab.\n * Uses lazy attach pattern - only attaches when needed.\n */\n private async ensureDebuggerAttached() {\n assert(!this.destroyed, 'Page is destroyed');\n\n const url = await this.url();\n if (url.startsWith('chrome://')) {\n throw new Error(\n 'Cannot attach debugger to chrome:// pages, please use Midscene in a normal page with http://, https:// or file://',\n );\n }\n\n const tabId = await this.getTabIdOrConnectToCurrentTab();\n\n try {\n await chrome.debugger.attach({ tabId }, '1.3');\n console.log('Debugger attached to tab:', tabId);\n } catch (error) {\n const errorMsg = (error as Error)?.message || '';\n // Already attached is OK, we can continue\n if (errorMsg.includes('Another debugger is already attached')) {\n console.log('Debugger already attached to tab:', tabId);\n return;\n }\n\n if (this._continueWhenFailedToAttachDebugger) {\n console.warn(\n 'Failed to attach debugger, but continuing due to _continueWhenFailedToAttachDebugger flag',\n error,\n );\n return;\n }\n\n throw error;\n }\n\n // Wait for debugger banner in Chrome to appear\n await sleep(500);\n\n // Enable water flow animation. Non-fatal: this is a purely visual\n // overlay, and Chrome can briefly detach the debugger between\n // attach() and the eval below (cross-origin navigation / Site\n // Isolation race). If we awaited it and it threw \"Debugger is not\n // attached\", the error would propagate out of the catch block in\n // sendCommandToDebugger, preventing the actual CDP command from\n // ever being retried. Fire-and-forget here so the lazy-attach\n // retry can succeed even when the animation fails.\n this.enableWaterFlowAnimation().catch((err) => {\n console.warn('Failed to enable water flow animation:', err);\n });\n }\n\n private async showMousePointer(x: number, y: number) {\n // update mouse pointer while redirecting\n const pointerScript = `(() => {\n if(typeof window.midsceneWaterFlowAnimation !== 'undefined') {\n window.midsceneWaterFlowAnimation.enable();\n window.midsceneWaterFlowAnimation.showMousePointer(${x}, ${y});\n } else {\n console.log('midsceneWaterFlowAnimation is not defined');\n }\n })()`;\n\n await this.sendCommandToDebugger('Runtime.evaluate', {\n expression: `${pointerScript}`,\n });\n }\n\n private async hideMousePointer() {\n await this.sendCommandToDebugger('Runtime.evaluate', {\n expression: `(() => {\n if(typeof window.midsceneWaterFlowAnimation !== 'undefined') {\n window.midsceneWaterFlowAnimation.hideMousePointer();\n }\n })()`,\n });\n }\n\n /**\n * Public method to detach debugger without destroying the page instance.\n * Useful for error recovery scenarios where we want to remove the debugger banner\n * without completely destroying the page.\n */\n public async detachDebugger(tabId?: number) {\n const tabIdToDetach = tabId || (await this.getTabIdOrConnectToCurrentTab());\n console.log('detaching debugger from tab:', tabIdToDetach);\n\n try {\n await this.disableWaterFlowAnimation(tabIdToDetach);\n await sleep(200); // wait for the animation to stop\n } catch (error) {\n console.warn('Failed to disable water flow animation', error);\n }\n\n try {\n await chrome.debugger.detach({ tabId: tabIdToDetach });\n console.log('Debugger detached successfully from tab:', tabIdToDetach);\n } catch (error) {\n // Tab might be closed or debugger already detached - this is OK\n console.warn(\n 'Failed to detach debugger (may already be detached):',\n error,\n );\n }\n }\n\n private async enableWaterFlowAnimation() {\n const tabId = await this.getTabIdOrConnectToCurrentTab();\n\n // limit open page in new tab\n if (this.forceSameTabNavigation) {\n await chrome.debugger.sendCommand({ tabId }, 'Runtime.evaluate', {\n expression: limitOpenNewTabScript,\n });\n }\n\n const script = await injectWaterFlowAnimation();\n // we will call this function in sendCommandToDebugger, so we have to use the chrome.debugger.sendCommand\n await chrome.debugger.sendCommand({ tabId }, 'Runtime.evaluate', {\n expression: script,\n });\n }\n\n private async disableWaterFlowAnimation(tabId: number) {\n const script = await injectStopWaterFlowAnimation();\n\n await chrome.debugger.sendCommand({ tabId }, 'Runtime.evaluate', {\n expression: script,\n });\n }\n\n /**\n * Send a command to the debugger with automatic attach and retry on detachment.\n * Uses lazy attach pattern - will automatically attach if not already attached.\n */\n private async sendCommandToDebugger<ResponseType = any, RequestType = any>(\n command: string,\n params: RequestType,\n retryCount = 0,\n ): Promise<ResponseType> {\n const MAX_RETRIES = 2;\n const tabId = await this.getTabIdOrConnectToCurrentTab();\n\n try {\n // Try to send command directly first\n const result = (await chrome.debugger.sendCommand(\n { tabId },\n command,\n params as any,\n )) as ResponseType;\n\n // Enable water flow animation after successful command (don't await)\n this.enableWaterFlowAnimation().catch((err) => {\n console.warn('Failed to enable water flow animation:', err);\n });\n\n return result;\n } catch (error) {\n // If command failed, check if it's because debugger is not attached\n const errorMsg = (error as Error)?.message || '';\n const isDetachError =\n errorMsg.includes('Debugger is not attached') ||\n errorMsg.includes('Cannot access a Target') ||\n errorMsg.includes('No target with given id');\n\n if (isDetachError && retryCount < MAX_RETRIES) {\n console.log(\n `Debugger not attached for command \"${command}\", attempting to attach (retry ${retryCount + 1}/${MAX_RETRIES})`,\n );\n\n // Try to attach and retry\n await this.ensureDebuggerAttached();\n\n return this.sendCommandToDebugger<ResponseType, RequestType>(\n command,\n params,\n retryCount + 1,\n );\n }\n\n // Not a detach error or out of retries\n throw error;\n }\n }\n\n private async getPageContentByCDP() {\n const script = await getHtmlElementScript();\n\n // check tab url\n await this.sendCommandToDebugger<\n CDPTypes.Runtime.EvaluateResponse,\n CDPTypes.Runtime.EvaluateRequest\n >('Runtime.evaluate', {\n expression: script,\n });\n\n const expression = () => {\n const tree = (\n window as any\n ).midscene_element_inspector.webExtractNodeTree();\n\n return {\n tree,\n size: {\n width: document.documentElement.clientWidth,\n height: document.documentElement.clientHeight,\n },\n };\n };\n const returnValue = await this.sendCommandToDebugger<\n CDPTypes.Runtime.EvaluateResponse,\n CDPTypes.Runtime.EvaluateRequest\n >('Runtime.evaluate', {\n expression: `(${expression.toString()})()`,\n returnByValue: true,\n });\n\n if (!returnValue.result.value) {\n const errorDescription =\n returnValue.exceptionDetails?.exception?.description || '';\n if (!errorDescription) {\n console.error('returnValue from cdp', returnValue);\n }\n throw new Error(\n `Failed to get page content from page, error: ${errorDescription}`,\n );\n }\n\n return returnValue.result.value as {\n tree: ElementTreeNode<ElementInfo>;\n size: Size;\n };\n }\n\n public async evaluateJavaScript(script: string) {\n return this.sendCommandToDebugger('Runtime.evaluate', {\n expression: script,\n awaitPromise: true,\n });\n }\n\n async registerFileChooserListener(\n handler: (chooser: FileChooserHandler) => Promise<void>,\n ): Promise<FileChooserRegistration> {\n const registrationVersion = ++this.fileChooserRegistrationVersion;\n const tabId = await this.getTabIdOrConnectToCurrentTab();\n\n await this.ensureDebuggerAttached();\n await this.sendCommandToDebugger('Page.enable', {});\n await this.sendCommandToDebugger('DOM.enable', {});\n await this.sendCommandToDebugger('Page.setInterceptFileChooserDialog', {\n enabled: true,\n });\n\n if (this.fileChooserEventHandler) {\n chrome.debugger.onEvent.removeListener(this.fileChooserEventHandler);\n this.fileChooserEventHandler = undefined;\n }\n\n let capturedError: Error | undefined;\n let pendingFileChooserHandling = Promise.resolve();\n\n const fileChooserEventHandler: Parameters<\n typeof chrome.debugger.onEvent.addListener\n >[0] = (source, method, params) => {\n if (source.tabId !== tabId || method !== 'Page.fileChooserOpened') {\n return;\n }\n\n const event = params as CDPTypes.Page.FileChooserOpenedEvent;\n if (event.backendNodeId === undefined) {\n debug(\n 'chrome extension file chooser opened without backendNodeId, skip',\n );\n return;\n }\n\n const currentFileChooserHandling = (async () => {\n try {\n await handler({\n accept: async (files: string[]) => {\n const { node } = await this.sendCommandToDebugger<\n CDPTypes.DOM.DescribeNodeResponse,\n CDPTypes.DOM.DescribeNodeRequest\n >('DOM.describeNode', {\n backendNodeId: event.backendNodeId,\n });\n\n const hasWebkitDirectory =\n hasFlatNodeAttribute(node.attributes, 'webkitdirectory') ||\n hasFlatNodeAttribute(node.attributes, 'directory');\n if (hasWebkitDirectory) {\n throw new Error(\n 'Directory upload (webkitdirectory) is not supported in Chrome extension bridge mode. Please use Playwright instead, which supports directory upload since version 1.45.',\n );\n }\n\n if (\n files.length > 1 &&\n !hasFlatNodeAttribute(node.attributes, 'multiple')\n ) {\n throw new Error(\n 'Non-multiple file input can only accept single file',\n );\n }\n\n await this.sendCommandToDebugger('DOM.setFileInputFiles', {\n files,\n backendNodeId: event.backendNodeId,\n });\n },\n });\n } catch (error) {\n capturedError =\n error instanceof Error ? error : new Error(String(error));\n }\n })();\n const previousFileChooserHandling = pendingFileChooserHandling;\n pendingFileChooserHandling = Promise.all([\n previousFileChooserHandling,\n currentFileChooserHandling,\n ]).then(() => {});\n };\n\n this.fileChooserEventHandler = fileChooserEventHandler;\n chrome.debugger.onEvent.addListener(fileChooserEventHandler);\n\n return {\n dispose: () => {\n if (this.fileChooserEventHandler !== fileChooserEventHandler) {\n return;\n }\n chrome.debugger.onEvent.removeListener(fileChooserEventHandler);\n this.fileChooserEventHandler = undefined;\n Promise.resolve()\n .then(() => {\n if (this.fileChooserRegistrationVersion !== registrationVersion) {\n return;\n }\n return this.sendCommandToDebugger(\n 'Page.setInterceptFileChooserDialog',\n {\n enabled: false,\n },\n );\n })\n .catch((error) => {\n debug('failed to disable file chooser interception: %O', error);\n });\n },\n getError: async () => {\n await pendingFileChooserHandling;\n return capturedError;\n },\n };\n }\n\n async registerFileChooserAccept(files: string[]): Promise<void> {\n this.clearFileChooserAccept();\n const { dispose, getError } = await this.registerFileChooserListener(\n async (chooser) => {\n await chooser.accept(files);\n },\n );\n this.bridgeFileChooserDispose = dispose;\n this.bridgeFileChooserGetError = getError;\n }\n\n clearFileChooserAccept(): void {\n this.bridgeFileChooserDispose?.();\n this.bridgeFileChooserDispose = undefined;\n this.bridgeFileChooserGetError = undefined;\n }\n\n async getFileChooserError(): Promise<\n { message: string; name?: string; stack?: string } | undefined\n > {\n const error = await this.bridgeFileChooserGetError?.();\n return error ? serializeError(error) : undefined;\n }\n\n async beforeInvokeAction(): Promise<void> {\n // current implementation is wait until domReadyState is complete\n try {\n await this.waitUntilNetworkIdle();\n } catch (error) {\n // console.warn('Failed to wait until network idle', error);\n }\n }\n\n private async waitUntilNetworkIdle() {\n const timeout = 10000;\n const startTime = Date.now();\n let lastReadyState = '';\n while (Date.now() - startTime < timeout) {\n const result = await this.sendCommandToDebugger('Runtime.evaluate', {\n expression: 'document.readyState',\n });\n lastReadyState = result.result.value;\n if (lastReadyState === 'complete') {\n await new Promise((resolve) => setTimeout(resolve, 300));\n return;\n }\n await new Promise((resolve) => setTimeout(resolve, 300));\n }\n throw new Error(\n `Failed to wait until network idle, last readyState: ${lastReadyState}`,\n );\n }\n\n // @deprecated\n async getElementsInfo() {\n const tree = await this.getElementsNodeTree();\n return treeToList(tree);\n }\n\n async getXpathsByPoint(point: Point, isOrderSensitive = false) {\n const script = await getHtmlElementScript();\n\n await this.sendCommandToDebugger<\n CDPTypes.Runtime.EvaluateResponse,\n CDPTypes.Runtime.EvaluateRequest\n >('Runtime.evaluate', {\n expression: script,\n });\n\n const result = await this.sendCommandToDebugger('Runtime.evaluate', {\n expression: `window.midscene_element_inspector.getXpathsByPoint({left: ${point.left}, top: ${point.top}}, ${isOrderSensitive})`,\n returnByValue: true,\n });\n return result.result.value;\n }\n\n async getElementInfoByXpath(xpath: string) {\n const script = await getHtmlElementScript();\n\n // check tab url\n await this.sendCommandToDebugger<\n CDPTypes.Runtime.EvaluateResponse,\n CDPTypes.Runtime.EvaluateRequest\n >('Runtime.evaluate', {\n expression: script,\n });\n const result = await this.sendCommandToDebugger('Runtime.evaluate', {\n expression: `window.midscene_element_inspector.getElementInfoByXpath(${JSON.stringify(xpath)})`,\n returnByValue: true,\n });\n return result.result.value;\n }\n\n async cacheFeatureForPoint(\n center: [number, number],\n options?: CacheFeatureOptions,\n ): Promise<ElementCacheFeature> {\n const point: Point = { left: center[0], top: center[1] };\n\n try {\n const isOrderSensitive = await judgeOrderSensitive(options, debug);\n const xpaths = await this.getXpathsByPoint(point, isOrderSensitive);\n return { xpaths: sanitizeXpaths(xpaths) };\n } catch (error) {\n debug('cacheFeatureForPoint failed: %O', error);\n return { xpaths: [] };\n }\n }\n\n async rectMatchesCacheFeature(feature: ElementCacheFeature): Promise<Rect> {\n const xpaths = sanitizeXpaths((feature as WebElementCacheFeature).xpaths);\n\n for (const xpath of xpaths) {\n try {\n const elementInfo = await this.getElementInfoByXpath(xpath);\n if (elementInfo?.rect) {\n return buildRectFromElementInfo(elementInfo);\n }\n } catch (error) {\n debug('rectMatchesCacheFeature failed for xpath %s: %O', xpath, error);\n }\n }\n\n throw new Error(\n `No matching element rect found for cache feature (tried ${xpaths.length} xpath(s))`,\n );\n }\n\n async getElementsNodeTree() {\n await this.hideMousePointer();\n const content = await this.getPageContentByCDP();\n if (content?.size) {\n this.viewportSize = content.size;\n }\n\n return content?.tree || { node: null, children: [] };\n }\n\n async size() {\n if (this.viewportSize) return this.viewportSize;\n\n const result = await this.sendCommandToDebugger('Runtime.evaluate', {\n expression: '({width: window.innerWidth, height: window.innerHeight})',\n returnByValue: true,\n });\n\n const sizeInfo: Size = result.result.value;\n console.log('sizeInfo', sizeInfo);\n\n this.viewportSize = sizeInfo;\n return sizeInfo;\n }\n\n async screenshotBase64() {\n // screenshot by cdp\n await this.hideMousePointer();\n const format = 'jpeg';\n const base64 = await this.sendCommandToDebugger('Page.captureScreenshot', {\n format,\n quality: 90,\n });\n return createImgBase64ByFormat(format, base64.data);\n }\n\n async url() {\n const tabId = await this.getTabIdOrConnectToCurrentTab();\n const url = await chrome.tabs.get(tabId).then((tab) => tab.url);\n return url || '';\n }\n\n async navigate(url: string): Promise<void> {\n const tabId = await this.getTabIdOrConnectToCurrentTab();\n await chrome.tabs.update(tabId, { url });\n // Wait for navigation to complete\n // Note: debugger will auto-reattach on next command if detached during navigation\n await this.waitUntilNetworkIdle();\n }\n\n async reload(): Promise<void> {\n const tabId = await this.getTabIdOrConnectToCurrentTab();\n await chrome.tabs.reload(tabId);\n // Wait for reload to complete\n await this.waitUntilNetworkIdle();\n }\n\n async goBack(): Promise<void> {\n const tabId = await this.getTabIdOrConnectToCurrentTab();\n await chrome.tabs.goBack(tabId);\n // Wait for navigation to complete\n await this.waitUntilNetworkIdle();\n }\n\n async goForward(): Promise<void> {\n const tabId = await this.getTabIdOrConnectToCurrentTab();\n await chrome.tabs.goForward(tabId);\n // Wait for navigation to complete\n await this.waitUntilNetworkIdle();\n }\n\n async stopLoading(): Promise<void> {\n await this.sendCommandToDebugger('Page.stopLoading', {});\n }\n\n async navigationState(): Promise<{ isLoading: boolean }> {\n const tabId = await this.getTabIdOrConnectToCurrentTab();\n const tab = await chrome.tabs.get(tabId);\n return { isLoading: tab.status === 'loading' };\n }\n\n async scrollUntilTop(startingPoint?: Point) {\n if (startingPoint) {\n await this.mouse.move(startingPoint.left, startingPoint.top);\n }\n return this.mouse.wheel(0, -9999999);\n }\n\n async scrollUntilBottom(startingPoint?: Point) {\n if (startingPoint) {\n await this.mouse.move(startingPoint.left, startingPoint.top);\n }\n return this.mouse.wheel(0, 9999999);\n }\n\n async scrollUntilLeft(startingPoint?: Point) {\n if (startingPoint) {\n await this.mouse.move(startingPoint.left, startingPoint.top);\n }\n return this.mouse.wheel(-9999999, 0);\n }\n\n async scrollUntilRight(startingPoint?: Point) {\n if (startingPoint) {\n await this.mouse.move(startingPoint.left, startingPoint.top);\n }\n return this.mouse.wheel(9999999, 0);\n }\n\n async scrollUp(distance?: number, startingPoint?: Point) {\n const { height } = await this.size();\n const scrollDistance = distance || height * 0.7;\n return this.mouse.wheel(\n 0,\n -scrollDistance,\n startingPoint?.left,\n startingPoint?.top,\n );\n }\n\n async scrollDown(distance?: number, startingPoint?: Point) {\n const { height } = await this.size();\n const scrollDistance = distance || height * 0.7;\n return this.mouse.wheel(\n 0,\n scrollDistance,\n startingPoint?.left,\n startingPoint?.top,\n );\n }\n\n async scrollLeft(distance?: number, startingPoint?: Point) {\n const { width } = await this.size();\n const scrollDistance = distance || width * 0.7;\n return this.mouse.wheel(\n -scrollDistance,\n 0,\n startingPoint?.left,\n startingPoint?.top,\n );\n }\n\n async scrollRight(distance?: number, startingPoint?: Point) {\n const { width } = await this.size();\n const scrollDistance = distance || width * 0.7;\n return this.mouse.wheel(\n scrollDistance,\n 0,\n startingPoint?.left,\n startingPoint?.top,\n );\n }\n\n async clearInput(element: ElementInfo) {\n if (!element) {\n console.warn('No element to clear input');\n return;\n }\n\n await this.mouse.click(element.center[0], element.center[1]);\n\n await this.sendCommandToDebugger('Input.dispatchKeyEvent', {\n type: 'keyDown',\n commands: ['selectAll'],\n });\n\n await this.sendCommandToDebugger('Input.dispatchKeyEvent', {\n type: 'keyUp',\n commands: ['selectAll'],\n });\n\n await sleep(100);\n\n await this.keyboard.press({\n key: 'Backspace',\n });\n }\n\n private latestMouseX = 100;\n private latestMouseY = 100;\n\n mouse = {\n click: async (\n x: number,\n y: number,\n options?: { button?: MouseButton; count?: number },\n ) => {\n const { button = 'left', count = 1 } = options || {};\n await this.mouse.move(x, y);\n // detect if the page is in mobile emulation mode\n if (this.isMobileEmulation === null) {\n const result = await this.sendCommandToDebugger('Runtime.evaluate', {\n expression: `(() => {\n return /Android|iPhone|iPad|iPod|Mobile/i.test(navigator.userAgent);\n })()`,\n returnByValue: true,\n });\n this.isMobileEmulation = result?.result?.value;\n }\n\n if (this.isMobileEmulation && button === 'left') {\n // in mobile emulation mode, directly inject click event\n const touchPoints = [{ x: Math.round(x), y: Math.round(y) }];\n await this.sendCommandToDebugger('Input.dispatchTouchEvent', {\n type: 'touchStart',\n touchPoints,\n modifiers: 0,\n });\n\n await this.sendCommandToDebugger('Input.dispatchTouchEvent', {\n type: 'touchEnd',\n touchPoints: [],\n modifiers: 0,\n });\n } else {\n // standard mousePressed + mouseReleased\n for (let i = 0; i < count; i++) {\n const clickCount = i + 1;\n await this.sendCommandToDebugger('Input.dispatchMouseEvent', {\n type: 'mousePressed',\n x,\n y,\n button,\n clickCount,\n });\n await this.sendCommandToDebugger('Input.dispatchMouseEvent', {\n type: 'mouseReleased',\n x,\n y,\n button,\n clickCount,\n });\n if (i < count - 1) {\n await sleep(50);\n }\n }\n }\n },\n wheel: async (\n deltaX: number,\n deltaY: number,\n startX?: number,\n startY?: number,\n ) => {\n const finalX = startX || this.latestMouseX;\n const finalY = startY || this.latestMouseY;\n await this.showMousePointer(finalX, finalY);\n await this.sendCommandToDebugger('Input.dispatchMouseEvent', {\n type: 'mouseWheel',\n x: finalX,\n y: finalY,\n deltaX,\n deltaY,\n });\n this.latestMouseX = finalX;\n this.latestMouseY = finalY;\n },\n move: async (x: number, y: number) => {\n await this.showMousePointer(x, y);\n await this.sendCommandToDebugger('Input.dispatchMouseEvent', {\n type: 'mouseMoved',\n x,\n y,\n });\n this.latestMouseX = x;\n this.latestMouseY = y;\n },\n drag: async (\n from: { x: number; y: number },\n to: { x: number; y: number },\n ) => {\n await this.mouse.move(from.x, from.y);\n\n await sleep(200);\n await this.sendCommandToDebugger('Input.dispatchMouseEvent', {\n type: 'mousePressed',\n x: from.x,\n y: from.y,\n button: 'left',\n clickCount: 1,\n });\n\n await sleep(300);\n\n await this.sendCommandToDebugger('Input.dispatchMouseEvent', {\n type: 'mouseMoved',\n x: to.x,\n y: to.y,\n });\n\n await sleep(500);\n\n await this.sendCommandToDebugger('Input.dispatchMouseEvent', {\n type: 'mouseReleased',\n x: to.x,\n y: to.y,\n button: 'left',\n clickCount: 1,\n });\n\n await sleep(200);\n\n await this.mouse.move(to.x, to.y);\n },\n };\n\n keyboard = {\n type: async (text: string) => {\n const cdpKeyboard = new CdpKeyboard({\n send: this.sendCommandToDebugger.bind(this),\n });\n await cdpKeyboard.type(text, { delay: 0 });\n },\n press: async (\n action:\n | { key: KeyInput; command?: string }\n | { key: KeyInput; command?: string }[],\n ) => {\n const cdpKeyboard = new CdpKeyboard({\n send: this.sendCommandToDebugger.bind(this),\n });\n const keys = Array.isArray(action) ? action : [action];\n for (const k of keys) {\n const commands = k.command ? [k.command] : [];\n await cdpKeyboard.down(k.key, { commands });\n }\n for (const k of [...keys].reverse()) {\n await cdpKeyboard.up(k.key);\n }\n },\n };\n\n async destroy(): Promise<void> {\n this.destroyed = true;\n this.clearFileChooserAccept();\n const tabIdToDetach = this.activeTabId;\n this.activeTabId = null;\n if (tabIdToDetach) {\n await this.detachDebugger(tabIdToDetach);\n }\n }\n\n async longPress(x: number, y: number, duration?: number) {\n duration = duration || 500;\n // Keep a lower bound so the press is registered as a long press rather than\n // a click, but never cap the upper bound: the duration is the caller's\n // intent (e.g. \"hold for 6 seconds\").\n const MIN_LONG_PRESS_DURATION = 300;\n if (duration < MIN_LONG_PRESS_DURATION) {\n duration = MIN_LONG_PRESS_DURATION;\n }\n await this.mouse.move(x, y);\n\n if (this.isMobileEmulation === null) {\n const result = await this.sendCommandToDebugger('Runtime.evaluate', {\n expression: `(() => {\n return /Android|iPhone|iPad|iPod|Mobile/i.test(navigator.userAgent);\n })()`,\n returnByValue: true,\n });\n this.isMobileEmulation = result?.result?.value;\n }\n\n if (this.isMobileEmulation) {\n const touchPoints = [{ x: Math.round(x), y: Math.round(y) }];\n await this.sendCommandToDebugger('Input.dispatchTouchEvent', {\n type: 'touchStart',\n touchPoints,\n modifiers: 0,\n });\n await new Promise((res) => setTimeout(res, duration));\n await this.sendCommandToDebugger('Input.dispatchTouchEvent', {\n type: 'touchEnd',\n touchPoints: [],\n modifiers: 0,\n });\n } else {\n await this.sendCommandToDebugger('Input.dispatchMouseEvent', {\n type: 'mousePressed',\n x,\n y,\n button: 'left',\n clickCount: 1,\n });\n await new Promise((res) => setTimeout(res, duration));\n await this.sendCommandToDebugger('Input.dispatchMouseEvent', {\n type: 'mouseReleased',\n x,\n y,\n button: 'left',\n clickCount: 1,\n });\n }\n this.latestMouseX = x;\n this.latestMouseY = y;\n }\n\n async swipe(\n from: { x: number; y: number },\n to: { x: number; y: number },\n duration?: number,\n ) {\n const LONG_PRESS_THRESHOLD = 500;\n const MIN_PRESS_THRESHOLD = 150;\n duration = duration || 300;\n if (duration < MIN_PRESS_THRESHOLD) {\n duration = MIN_PRESS_THRESHOLD;\n }\n if (duration > LONG_PRESS_THRESHOLD) {\n duration = LONG_PRESS_THRESHOLD;\n }\n\n if (this.isMobileEmulation === null) {\n const result = await this.sendCommandToDebugger('Runtime.evaluate', {\n expression: `(() => {\n return /Android|iPhone|iPad|iPod|Mobile/i.test(navigator.userAgent);\n })()`,\n returnByValue: true,\n });\n this.isMobileEmulation = result?.result?.value;\n }\n\n const steps = 30;\n const delay = duration / steps;\n\n if (this.isMobileEmulation) {\n await this.sendCommandToDebugger('Input.dispatchTouchEvent', {\n type: 'touchStart',\n touchPoints: [{ x: Math.round(from.x), y: Math.round(from.y) }],\n modifiers: 0,\n });\n\n for (let i = 1; i <= steps; i++) {\n const x = from.x + (to.x - from.x) * (i / steps);\n const y = from.y + (to.y - from.y) * (i / steps);\n await this.sendCommandToDebugger('Input.dispatchTouchEvent', {\n type: 'touchMove',\n touchPoints: [{ x: Math.round(x), y: Math.round(y) }],\n modifiers: 0,\n });\n await new Promise((res) => setTimeout(res, delay));\n }\n\n await this.sendCommandToDebugger('Input.dispatchTouchEvent', {\n type: 'touchEnd',\n touchPoints: [],\n modifiers: 0,\n });\n } else {\n await this.mouse.move(from.x, from.y);\n await this.sendCommandToDebugger('Input.dispatchMouseEvent', {\n type: 'mousePressed',\n x: from.x,\n y: from.y,\n button: 'left',\n clickCount: 1,\n });\n\n for (let i = 1; i <= steps; i++) {\n const x = from.x + (to.x - from.x) * (i / steps);\n const y = from.y + (to.y - from.y) * (i / steps);\n await this.mouse.move(x, y);\n await new Promise((res) => setTimeout(res, delay));\n }\n\n await this.sendCommandToDebugger('Input.dispatchMouseEvent', {\n type: 'mouseReleased',\n x: to.x,\n y: to.y,\n button: 'left',\n clickCount: 1,\n });\n }\n\n this.latestMouseX = to.x;\n this.latestMouseY = to.y;\n }\n\n async pinch(\n centerX: number,\n centerY: number,\n startDistance: number,\n endDistance: number,\n duration = 500,\n ): Promise<void> {\n const steps = 30;\n const delay = duration / steps;\n\n const halfStart = startDistance / 2;\n const halfEnd = endDistance / 2;\n\n await this.sendCommandToDebugger('Input.dispatchTouchEvent', {\n type: 'touchStart',\n touchPoints: [\n {\n x: Math.round(centerX),\n y: Math.round(centerY - halfStart),\n id: 0,\n },\n {\n x: Math.round(centerX),\n y: Math.round(centerY + halfStart),\n id: 1,\n },\n ],\n modifiers: 0,\n });\n\n for (let i = 1; i <= steps; i++) {\n const progress = i / steps;\n const currentHalf = halfStart + (halfEnd - halfStart) * progress;\n await this.sendCommandToDebugger('Input.dispatchTouchEvent', {\n type: 'touchMove',\n touchPoints: [\n {\n x: Math.round(centerX),\n y: Math.round(centerY - currentHalf),\n id: 0,\n },\n {\n x: Math.round(centerX),\n y: Math.round(centerY + currentHalf),\n id: 1,\n },\n ],\n modifiers: 0,\n });\n await new Promise((res) => setTimeout(res, delay));\n }\n\n await this.sendCommandToDebugger('Input.dispatchTouchEvent', {\n type: 'touchEnd',\n touchPoints: [],\n modifiers: 0,\n });\n }\n}\n"],"names":["debug","getDebug","sleep","ms","Promise","resolve","setTimeout","hasFlatNodeAttribute","attributes","name","i","serializeError","error","ChromeExtensionProxyPage","commonWebActionsForWebPage","tabId","Error","chrome","tabs","tab","assert","url","console","errorMsg","err","x","y","pointerScript","tabIdToDetach","limitOpenNewTabScript","script","injectWaterFlowAnimation","injectStopWaterFlowAnimation","command","params","retryCount","MAX_RETRIES","result","isDetachError","getHtmlElementScript","expression","tree","window","document","returnValue","errorDescription","handler","registrationVersion","undefined","capturedError","pendingFileChooserHandling","fileChooserEventHandler","source","method","event","currentFileChooserHandling","files","node","hasWebkitDirectory","String","previousFileChooserHandling","dispose","getError","chooser","timeout","startTime","Date","lastReadyState","treeToList","point","isOrderSensitive","xpath","JSON","center","options","judgeOrderSensitive","xpaths","sanitizeXpaths","feature","elementInfo","buildRectFromElementInfo","content","sizeInfo","format","base64","createImgBase64ByFormat","startingPoint","distance","height","scrollDistance","width","element","duration","MIN_LONG_PRESS_DURATION","touchPoints","Math","res","from","to","LONG_PRESS_THRESHOLD","MIN_PRESS_THRESHOLD","steps","delay","centerX","centerY","startDistance","endDistance","halfStart","halfEnd","progress","currentHalf","forceSameTabNavigation","button","count","clickCount","deltaX","deltaY","startX","startY","finalX","finalY","text","cdpKeyboard","CdpKeyboard","action","keys","Array","k","commands"],"mappings":"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"}
package/dist/es/cli.mjs CHANGED
@@ -3,10 +3,10 @@ import { join } from "node:path";
3
3
  import { createReportCliCommands } from "@midscene/core";
4
4
  import { reportCLIError, runToolsCLI } from "@midscene/shared/cli";
5
5
  import dotenv from "dotenv";
6
- import { WebMidsceneTools } from "./agent-tools.mjs";
7
- import { WebCdpMidsceneTools } from "./agent-tools-cdp.mjs";
8
- import { WebPuppeteerMidsceneTools } from "./agent-tools-puppeteer.mjs";
9
6
  import { parseWebCliOptions } from "./cli-options.mjs";
7
+ import { WebMidsceneTools } from "./mcp-tools.mjs";
8
+ import { WebCdpMidsceneTools } from "./mcp-tools-cdp.mjs";
9
+ import { WebPuppeteerMidsceneTools } from "./mcp-tools-puppeteer.mjs";
10
10
  const envFile = join(process.cwd(), '.env');
11
11
  if (existsSync(envFile)) dotenv.config({
12
12
  path: envFile
@@ -18,7 +18,7 @@ Promise.resolve().then(()=>{
18
18
  return runToolsCLI(tools, 'midscene-web', {
19
19
  stripPrefix: 'web_',
20
20
  argv: parsedOptions.argv,
21
- version: "1.9.8-beta-20260618014851.0",
21
+ version: "1.9.8",
22
22
  extraCommands: createReportCliCommands()
23
23
  });
24
24
  }).catch((e)=>{
@@ -1 +1 @@
1
- {"version":3,"file":"cli.mjs","sources":["../../src/cli.ts"],"sourcesContent":["import { existsSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { createReportCliCommands } from '@midscene/core';\nimport { reportCLIError, runToolsCLI } from '@midscene/shared/cli';\nimport dotenv from 'dotenv';\nimport { WebMidsceneTools } from './agent-tools';\nimport { WebCdpMidsceneTools } from './agent-tools-cdp';\nimport { WebPuppeteerMidsceneTools } from './agent-tools-puppeteer';\nimport { parseWebCliOptions } from './cli-options';\n\n// Load .env early so MIDSCENE_CDP_ENDPOINT is available during arg parsing\nconst envFile = join(process.cwd(), '.env');\nif (existsSync(envFile)) {\n dotenv.config({ path: envFile });\n}\n\ndeclare const __VERSION__: string;\n\nPromise.resolve()\n .then(() => {\n const parsedOptions = parseWebCliOptions(process.argv.slice(2));\n\n let tools:\n | WebMidsceneTools\n | WebPuppeteerMidsceneTools\n | WebCdpMidsceneTools;\n if (parsedOptions.mode === 'bridge') {\n tools = new WebMidsceneTools();\n } else if (parsedOptions.mode === 'cdp') {\n tools = new WebCdpMidsceneTools(parsedOptions.cdpEndpoint!);\n } else {\n tools = new WebPuppeteerMidsceneTools(parsedOptions.viewport);\n }\n\n return runToolsCLI(tools, 'midscene-web', {\n stripPrefix: 'web_',\n argv: parsedOptions.argv,\n version: __VERSION__,\n extraCommands: createReportCliCommands(),\n });\n })\n .catch((e) => {\n process.exit(reportCLIError(e));\n });\n"],"names":["envFile","join","process","existsSync","dotenv","Promise","parsedOptions","parseWebCliOptions","tools","WebMidsceneTools","WebCdpMidsceneTools","WebPuppeteerMidsceneTools","runToolsCLI","__VERSION__","createReportCliCommands","e","reportCLIError"],"mappings":";;;;;;;;;AAWA,MAAMA,UAAUC,KAAKC,QAAQ,GAAG,IAAI;AACpC,IAAIC,WAAWH,UACbI,OAAO,MAAM,CAAC;IAAE,MAAMJ;AAAQ;AAKhCK,QAAQ,OAAO,GACZ,IAAI,CAAC;IACJ,MAAMC,gBAAgBC,mBAAmBL,QAAQ,IAAI,CAAC,KAAK,CAAC;IAE5D,IAAIM;IAKFA,QADEF,AAAuB,aAAvBA,cAAc,IAAI,GACZ,IAAIG,qBACHH,AAAuB,UAAvBA,cAAc,IAAI,GACnB,IAAII,oBAAoBJ,cAAc,WAAW,IAEjD,IAAIK,0BAA0BL,cAAc,QAAQ;IAG9D,OAAOM,YAAYJ,OAAO,gBAAgB;QACxC,aAAa;QACb,MAAMF,cAAc,IAAI;QACxB,SAASO;QACT,eAAeC;IACjB;AACF,GACC,KAAK,CAAC,CAACC;IACNb,QAAQ,IAAI,CAACc,eAAeD;AAC9B"}
1
+ {"version":3,"file":"cli.mjs","sources":["../../src/cli.ts"],"sourcesContent":["import { existsSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { createReportCliCommands } from '@midscene/core';\nimport { reportCLIError, runToolsCLI } from '@midscene/shared/cli';\nimport dotenv from 'dotenv';\nimport { parseWebCliOptions } from './cli-options';\nimport { WebMidsceneTools } from './mcp-tools';\nimport { WebCdpMidsceneTools } from './mcp-tools-cdp';\nimport { WebPuppeteerMidsceneTools } from './mcp-tools-puppeteer';\n\n// Load .env early so MIDSCENE_CDP_ENDPOINT is available during arg parsing\nconst envFile = join(process.cwd(), '.env');\nif (existsSync(envFile)) {\n dotenv.config({ path: envFile });\n}\n\ndeclare const __VERSION__: string;\n\nPromise.resolve()\n .then(() => {\n const parsedOptions = parseWebCliOptions(process.argv.slice(2));\n\n let tools:\n | WebMidsceneTools\n | WebPuppeteerMidsceneTools\n | WebCdpMidsceneTools;\n if (parsedOptions.mode === 'bridge') {\n tools = new WebMidsceneTools();\n } else if (parsedOptions.mode === 'cdp') {\n tools = new WebCdpMidsceneTools(parsedOptions.cdpEndpoint!);\n } else {\n tools = new WebPuppeteerMidsceneTools(parsedOptions.viewport);\n }\n\n return runToolsCLI(tools, 'midscene-web', {\n stripPrefix: 'web_',\n argv: parsedOptions.argv,\n version: __VERSION__,\n extraCommands: createReportCliCommands(),\n });\n })\n .catch((e) => {\n process.exit(reportCLIError(e));\n });\n"],"names":["envFile","join","process","existsSync","dotenv","Promise","parsedOptions","parseWebCliOptions","tools","WebMidsceneTools","WebCdpMidsceneTools","WebPuppeteerMidsceneTools","runToolsCLI","__VERSION__","createReportCliCommands","e","reportCLIError"],"mappings":";;;;;;;;;AAWA,MAAMA,UAAUC,KAAKC,QAAQ,GAAG,IAAI;AACpC,IAAIC,WAAWH,UACbI,OAAO,MAAM,CAAC;IAAE,MAAMJ;AAAQ;AAKhCK,QAAQ,OAAO,GACZ,IAAI,CAAC;IACJ,MAAMC,gBAAgBC,mBAAmBL,QAAQ,IAAI,CAAC,KAAK,CAAC;IAE5D,IAAIM;IAKFA,QADEF,AAAuB,aAAvBA,cAAc,IAAI,GACZ,IAAIG,qBACHH,AAAuB,UAAvBA,cAAc,IAAI,GACnB,IAAII,oBAAoBJ,cAAc,WAAW,IAEjD,IAAIK,0BAA0BL,cAAc,QAAQ;IAG9D,OAAOM,YAAYJ,OAAO,gBAAgB;QACxC,aAAa;QACb,MAAMF,cAAc,IAAI;QACxB,SAASO;QACT,eAAeC;IACjB;AACF,GACC,KAAK,CAAC,CAACC;IACNb,QAAQ,IAAI,CAACc,eAAeD;AAC9B"}
package/dist/es/index.mjs CHANGED
@@ -2,7 +2,7 @@ import { PlaywrightAgent, PlaywrightAiFixture } from "./playwright/index.mjs";
2
2
  import { Agent } from "@midscene/core/agent";
3
3
  import { PuppeteerAgent } from "./puppeteer/index.mjs";
4
4
  import { StaticPage, StaticPageAgent } from "./static/index.mjs";
5
- import { WebMidsceneTools } from "./agent-tools.mjs";
5
+ import { WebMidsceneTools } from "./mcp-tools.mjs";
6
6
  import { webPlaygroundPlatform } from "./platform.mjs";
7
- import { WebCdpMidsceneTools } from "./agent-tools-cdp.mjs";
7
+ import { WebCdpMidsceneTools } from "./mcp-tools-cdp.mjs";
8
8
  export { Agent as PageAgent, PlaywrightAgent, PlaywrightAiFixture, PuppeteerAgent, StaticPage, StaticPageAgent, WebCdpMidsceneTools, WebMidsceneTools, webPlaygroundPlatform };
@@ -1,5 +1,5 @@
1
1
  import { z } from "@midscene/core";
2
- import { agentBehaviorInitArgShape, extractAgentBehaviorInitArgs } from "@midscene/shared/agent-tools/agent-behavior-init-args";
2
+ import { agentBehaviorInitArgShape, extractAgentBehaviorInitArgs } from "@midscene/shared/mcp/agent-behavior-init-args";
3
3
  const webAgentInitArgShape = {
4
4
  url: z.string().url().optional().describe('URL to open in new tab (omit to use current page)'),
5
5
  ...agentBehaviorInitArgShape
@@ -16,4 +16,4 @@ function adaptWebAgentInitArgs(extracted) {
16
16
  }
17
17
  export { adaptWebAgentInitArgs, webAgentInitArgShape };
18
18
 
19
- //# sourceMappingURL=agent-init-args.mjs.map
19
+ //# sourceMappingURL=mcp-agent-init-args.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"agent-init-args.mjs","sources":["../../src/agent-init-args.ts"],"sourcesContent":["import { z } from '@midscene/core';\nimport {\n type AgentBehaviorInitArgs,\n agentBehaviorInitArgShape,\n extractAgentBehaviorInitArgs,\n} from '@midscene/shared/agent-tools/agent-behavior-init-args';\n\nexport type WebAgentInitArgs = AgentBehaviorInitArgs & {\n url?: string;\n};\n\nexport const webAgentInitArgShape = {\n url: z\n .string()\n .url()\n .optional()\n .describe('URL to open in new tab (omit to use current page)'),\n ...agentBehaviorInitArgShape,\n};\n\nexport function adaptWebAgentInitArgs(\n extracted: Record<string, unknown> | undefined,\n): WebAgentInitArgs | undefined {\n if (!extracted) {\n return undefined;\n }\n\n const initArgs: WebAgentInitArgs = {\n ...(typeof extracted.url === 'string' ? { url: extracted.url } : {}),\n ...(extractAgentBehaviorInitArgs(extracted as AgentBehaviorInitArgs) ?? {}),\n };\n\n return Object.keys(initArgs).length > 0 ? initArgs : undefined;\n}\n"],"names":["webAgentInitArgShape","z","agentBehaviorInitArgShape","adaptWebAgentInitArgs","extracted","initArgs","extractAgentBehaviorInitArgs","Object","undefined"],"mappings":";;AAWO,MAAMA,uBAAuB;IAClC,KAAKC,EAAAA,MACI,GACN,GAAG,GACH,QAAQ,GACR,QAAQ,CAAC;IACZ,GAAGC,yBAAyB;AAC9B;AAEO,SAASC,sBACdC,SAA8C;IAE9C,IAAI,CAACA,WACH;IAGF,MAAMC,WAA6B;QACjC,GAAI,AAAyB,YAAzB,OAAOD,UAAU,GAAG,GAAgB;YAAE,KAAKA,UAAU,GAAG;QAAC,IAAI,CAAC,CAAC;QACnE,GAAIE,6BAA6BF,cAAuC,CAAC,CAAC;IAC5E;IAEA,OAAOG,OAAO,IAAI,CAACF,UAAU,MAAM,GAAG,IAAIA,WAAWG;AACvD"}
1
+ {"version":3,"file":"mcp-agent-init-args.mjs","sources":["../../src/mcp-agent-init-args.ts"],"sourcesContent":["import { z } from '@midscene/core';\nimport {\n type AgentBehaviorInitArgs,\n agentBehaviorInitArgShape,\n extractAgentBehaviorInitArgs,\n} from '@midscene/shared/mcp/agent-behavior-init-args';\n\nexport type WebAgentInitArgs = AgentBehaviorInitArgs & {\n url?: string;\n};\n\nexport const webAgentInitArgShape = {\n url: z\n .string()\n .url()\n .optional()\n .describe('URL to open in new tab (omit to use current page)'),\n ...agentBehaviorInitArgShape,\n};\n\nexport function adaptWebAgentInitArgs(\n extracted: Record<string, unknown> | undefined,\n): WebAgentInitArgs | undefined {\n if (!extracted) {\n return undefined;\n }\n\n const initArgs: WebAgentInitArgs = {\n ...(typeof extracted.url === 'string' ? { url: extracted.url } : {}),\n ...(extractAgentBehaviorInitArgs(extracted as AgentBehaviorInitArgs) ?? {}),\n };\n\n return Object.keys(initArgs).length > 0 ? initArgs : undefined;\n}\n"],"names":["webAgentInitArgShape","z","agentBehaviorInitArgShape","adaptWebAgentInitArgs","extracted","initArgs","extractAgentBehaviorInitArgs","Object","undefined"],"mappings":";;AAWO,MAAMA,uBAAuB;IAClC,KAAKC,EAAAA,MACI,GACN,GAAG,GACH,QAAQ,GACR,QAAQ,CAAC;IACZ,GAAGC,yBAAyB;AAC9B;AAEO,SAASC,sBACdC,SAA8C;IAE9C,IAAI,CAACA,WACH;IAGF,MAAMC,WAA6B;QACjC,GAAI,AAAyB,YAAzB,OAAOD,UAAU,GAAG,GAAgB;YAAE,KAAKA,UAAU,GAAG;QAAC,IAAI,CAAC,CAAC;QACnE,GAAIE,6BAA6BF,cAAuC,CAAC,CAAC;IAC5E;IAEA,OAAOG,OAAO,IAAI,CAACF,UAAU,MAAM,GAAG,IAAIA,WAAWG;AACvD"}
@@ -0,0 +1,35 @@
1
+ import { BaseMCPServer, createMCPServerLauncher } from "@midscene/shared/mcp";
2
+ import { WebMidsceneTools } from "./mcp-tools.mjs";
3
+ class WebMCPServer extends BaseMCPServer {
4
+ createToolsManager() {
5
+ return new WebMidsceneTools();
6
+ }
7
+ constructor(toolsManager){
8
+ super({
9
+ name: '@midscene/web-bridge-mcp',
10
+ version: "1.9.8",
11
+ description: 'Control the browser using natural language commands'
12
+ }, toolsManager);
13
+ }
14
+ }
15
+ function mcpServerForAgent(agent) {
16
+ return createMCPServerLauncher({
17
+ agent,
18
+ platformName: 'Web',
19
+ ToolsManagerClass: WebMidsceneTools,
20
+ MCPServerClass: WebMCPServer
21
+ });
22
+ }
23
+ async function mcpKitForAgent(agent) {
24
+ const toolsManager = new WebMidsceneTools();
25
+ const webAgent = agent;
26
+ toolsManager.setAgent(webAgent);
27
+ await toolsManager.initTools();
28
+ return {
29
+ description: 'Midscene Bridge MCP Server: Control the browser using natural language commands for navigation, clicking, input, hovering, screenshots waitFor, and achieving goals.',
30
+ tools: toolsManager.getToolDefinitions()
31
+ };
32
+ }
33
+ export { WebMCPServer, mcpKitForAgent, mcpServerForAgent };
34
+
35
+ //# sourceMappingURL=mcp-server.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp-server.mjs","sources":["../../src/mcp-server.ts"],"sourcesContent":["import type { GenericAgent } from '@midscene/shared/mcp';\nimport {\n BaseMCPServer,\n type Tool,\n createMCPServerLauncher,\n} from '@midscene/shared/mcp';\nimport type { AgentOverChromeBridge } from './bridge-mode';\nimport { WebMidsceneTools } from './mcp-tools';\n\ndeclare const __VERSION__: string;\n\n/**\n * Web MCP Server class\n */\nexport class WebMCPServer extends BaseMCPServer {\n constructor(toolsManager?: WebMidsceneTools) {\n super(\n {\n name: '@midscene/web-bridge-mcp',\n version: __VERSION__,\n description: 'Control the browser using natural language commands',\n },\n toolsManager,\n );\n }\n\n protected createToolsManager(): WebMidsceneTools {\n return new WebMidsceneTools();\n }\n}\n\n/**\n * Create an MCP server launcher for a specific Agent\n */\nexport function mcpServerForAgent(agent: GenericAgent) {\n return createMCPServerLauncher({\n agent,\n platformName: 'Web',\n ToolsManagerClass: WebMidsceneTools,\n MCPServerClass: WebMCPServer,\n });\n}\n\n/**\n * Create MCP kit for a specific Agent\n */\nexport async function mcpKitForAgent(agent: GenericAgent): Promise<{\n description: string;\n tools: Tool[];\n}> {\n const toolsManager = new WebMidsceneTools();\n\n // Convert to AgentOverChromeBridge for Web tools manager\n const webAgent = agent as AgentOverChromeBridge;\n toolsManager.setAgent(webAgent);\n await toolsManager.initTools();\n\n return {\n description:\n 'Midscene Bridge MCP Server: Control the browser using natural language commands for navigation, clicking, input, hovering, screenshots waitFor, and achieving goals.',\n tools: toolsManager.getToolDefinitions(),\n };\n}\n"],"names":["WebMCPServer","BaseMCPServer","WebMidsceneTools","toolsManager","__VERSION__","mcpServerForAgent","agent","createMCPServerLauncher","mcpKitForAgent","webAgent"],"mappings":";;AAcO,MAAMA,qBAAqBC;IAYtB,qBAAuC;QAC/C,OAAO,IAAIC;IACb;IAbA,YAAYC,YAA+B,CAAE;QAC3C,KAAK,CACH;YACE,MAAM;YACN,SAASC;YACT,aAAa;QACf,GACAD;IAEJ;AAKF;AAKO,SAASE,kBAAkBC,KAAmB;IACnD,OAAOC,wBAAwB;QAC7BD;QACA,cAAc;QACd,mBAAmBJ;QACnB,gBAAgBF;IAClB;AACF;AAKO,eAAeQ,eAAeF,KAAmB;IAItD,MAAMH,eAAe,IAAID;IAGzB,MAAMO,WAAWH;IACjBH,aAAa,QAAQ,CAACM;IACtB,MAAMN,aAAa,SAAS;IAE5B,OAAO;QACL,aACE;QACF,OAAOA,aAAa,kBAAkB;IACxC;AACF"}
@@ -1,12 +1,12 @@
1
1
  import { ScreenshotItem } from "@midscene/core";
2
- import { extractAgentBehaviorInitArgs, getAgentInitArgsSignature, shouldRebuildAgentForInitArgs } from "@midscene/shared/agent-tools/agent-behavior-init-args";
3
- import { BaseMidsceneTools } from "@midscene/shared/agent-tools/base-tools";
4
2
  import { getDebug } from "@midscene/shared/logger";
3
+ import { extractAgentBehaviorInitArgs, getAgentInitArgsSignature, shouldRebuildAgentForInitArgs } from "@midscene/shared/mcp/agent-behavior-init-args";
4
+ import { BaseMidsceneTools } from "@midscene/shared/mcp/base-tools";
5
5
  import puppeteer_core from "puppeteer-core";
6
- import { adaptWebAgentInitArgs, webAgentInitArgShape } from "./agent-init-args.mjs";
7
6
  import { getProxyEndpoint } from "./cdp-proxy-manager.mjs";
8
7
  import { cleanupTargetIdFile, readSavedTargetId, saveTargetId } from "./cdp-target-store.mjs";
9
8
  import { defaultStaticPageViewportSize } from "./common/viewport.mjs";
9
+ import { adaptWebAgentInitArgs, webAgentInitArgShape } from "./mcp-agent-init-args.mjs";
10
10
  import { PuppeteerAgent } from "./puppeteer/index.mjs";
11
11
  import { StaticPage } from "./static/index.mjs";
12
12
  function _define_property(obj, key, value) {
@@ -19,7 +19,7 @@ function _define_property(obj, key, value) {
19
19
  else obj[key] = value;
20
20
  return obj;
21
21
  }
22
- const debug = getDebug('agent-tools:cdp');
22
+ const debug = getDebug('mcp:cdp');
23
23
  const CDP_TARGET_DISCOVERY_DELAY_MS = 500;
24
24
  function getTargetId(page) {
25
25
  return page.target()._targetId;
@@ -179,4 +179,4 @@ class WebCdpMidsceneTools extends BaseMidsceneTools {
179
179
  }
180
180
  export { WebCdpMidsceneTools };
181
181
 
182
- //# sourceMappingURL=agent-tools-cdp.mjs.map
182
+ //# sourceMappingURL=mcp-tools-cdp.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp-tools-cdp.mjs","sources":["../../src/mcp-tools-cdp.ts"],"sourcesContent":["import { ScreenshotItem } from '@midscene/core';\nimport { getDebug } from '@midscene/shared/logger';\nimport {\n extractAgentBehaviorInitArgs,\n getAgentInitArgsSignature,\n shouldRebuildAgentForInitArgs,\n} from '@midscene/shared/mcp/agent-behavior-init-args';\nimport {\n BaseMidsceneTools,\n type InitArgSpec,\n} from '@midscene/shared/mcp/base-tools';\nimport type { ToolDefinition } from '@midscene/shared/mcp/types';\nimport type { Page as PuppeteerPage } from 'puppeteer';\nimport puppeteer from 'puppeteer-core';\nimport type { Browser, Page } from 'puppeteer-core';\nimport { getProxyEndpoint } from './cdp-proxy-manager';\nimport {\n cleanupTargetIdFile,\n readSavedTargetId,\n saveTargetId,\n} from './cdp-target-store';\nimport { defaultStaticPageViewportSize } from './common/viewport';\nimport {\n type WebAgentInitArgs,\n adaptWebAgentInitArgs,\n webAgentInitArgShape,\n} from './mcp-agent-init-args';\nimport { PuppeteerAgent } from './puppeteer';\nimport { StaticPage } from './static';\n\nconst debug = getDebug('mcp:cdp');\n\n/** CDP target discovery may need a brief moment after WebSocket open. */\nconst CDP_TARGET_DISCOVERY_DELAY_MS = 500;\n\n/**\n * puppeteer-core does not expose a public method for the underlying CDP\n * target id, so we reach into `_targetId`. Centralised here so a future\n * puppeteer release exposing this properly only requires one change.\n * Callers must treat the result as optional.\n */\nfunction getTargetId(page: Page): string | undefined {\n return (page.target() as unknown as { _targetId?: string })._targetId;\n}\n\n/**\n * Tools manager for Web CDP-mode MCP.\n * Connects to an existing Chrome browser via CDP (Chrome DevTools Protocol) endpoint.\n * Unlike WebPuppeteerMidsceneTools which launches its own Chrome, this connects\n * to a browser that is already running with remote debugging enabled.\n *\n * Uses a persistent WebSocket proxy to avoid repeated Chrome permission popups\n * when Chrome's settings-based remote debugging is used.\n */\nexport class WebCdpMidsceneTools extends BaseMidsceneTools<\n PuppeteerAgent,\n WebAgentInitArgs\n> {\n protected getCliReportSessionName() {\n return 'midscene-web';\n }\n private cdpEndpoint: string;\n private activeBrowser: Browser | null = null;\n private lastInitArgsSignature?: string;\n\n constructor(cdpEndpoint: string) {\n super();\n this.cdpEndpoint = cdpEndpoint;\n }\n\n protected readonly initArgSpec: InitArgSpec<WebAgentInitArgs> = {\n namespace: 'web',\n shape: webAgentInitArgShape,\n cli: {\n preferBareKeys: true,\n },\n adapt: adaptWebAgentInitArgs,\n };\n\n protected createTemporaryDevice() {\n return new StaticPage({\n screenshot: ScreenshotItem.create('', Date.now()),\n shotSize: defaultStaticPageViewportSize,\n shrunkShotToLogicalRatio: 1,\n });\n }\n\n protected async ensureAgent(\n initArgs?: WebAgentInitArgs,\n ): Promise<PuppeteerAgent> {\n const navigateToUrl = initArgs?.url;\n const nextSignature = getAgentInitArgsSignature(initArgs);\n const shouldNavigateToUrl = typeof navigateToUrl === 'string';\n\n if (\n this.agent &&\n (shouldNavigateToUrl ||\n shouldRebuildAgentForInitArgs(\n this.lastInitArgsSignature,\n nextSignature,\n ))\n ) {\n try {\n await this.agent?.destroy?.();\n } catch (error) {\n console.debug('Failed to destroy agent during re-init:', error);\n }\n this.agent = undefined;\n }\n\n if (this.agent) return this.agent;\n\n // Connect via proxy to avoid repeated Chrome permission popups\n if (!this.activeBrowser) {\n const endpoint = await getProxyEndpoint(this.cdpEndpoint);\n this.activeBrowser = await puppeteer.connect({\n browserWSEndpoint: endpoint,\n defaultViewport: null,\n });\n }\n\n const browser = this.activeBrowser;\n let pages = await browser.pages();\n\n // If no pages discovered, wait briefly and retry — some CDP targets\n // need a moment to appear after the WebSocket connection is established.\n if (pages.length === 0) {\n await new Promise((r) => setTimeout(r, CDP_TARGET_DISCOVERY_DELAY_MS));\n pages = await browser.pages();\n }\n\n const webPages = pages.filter((p) => /^https?:\\/\\//.test(p.url()));\n debug(\n 'Found %d page(s), %d web page(s): %o',\n pages.length,\n webPages.length,\n pages.map((p) => p.url()),\n );\n let page: Page;\n\n if (navigateToUrl) {\n if (webPages.length > 0) {\n // Reuse an existing page and navigate it — avoids creating invisible\n // tabs when Chrome uses settings-based remote debugging (no HTTP\n // discovery endpoints, /devtools/page/* returns 403).\n page = webPages[webPages.length - 1];\n await page.bringToFront();\n await page.goto(navigateToUrl, {\n timeout: 30000,\n waitUntil: 'domcontentloaded',\n });\n } else {\n // No existing web pages — fall back to creating a new tab\n page = await browser.newPage();\n await page.goto(navigateToUrl, {\n timeout: 30000,\n waitUntil: 'domcontentloaded',\n });\n }\n } else {\n // Try to find the exact tab from a previous `connect` command via saved targetId.\n const savedTargetId = readSavedTargetId();\n let matchedPage: Page | undefined;\n\n if (savedTargetId && pages.length > 0) {\n matchedPage = pages.find((p) => getTargetId(p) === savedTargetId);\n if (matchedPage) {\n debug('Matched saved targetId %s', savedTargetId);\n } else {\n debug(\n 'Saved targetId %s not found among %d pages, falling back',\n savedTargetId,\n pages.length,\n );\n }\n }\n\n if (matchedPage) {\n page = matchedPage;\n } else if (webPages.length > 0) {\n page = webPages[webPages.length - 1];\n } else if (pages.length > 0) {\n page = pages[pages.length - 1];\n } else {\n page = await browser.newPage();\n }\n\n await page.bringToFront();\n }\n\n // Persist the targetId so subsequent CLI commands can find this exact tab\n const targetId = getTargetId(page);\n if (targetId) {\n saveTargetId(targetId);\n } else {\n // If puppeteer ever drops the private _targetId field, this branch\n // makes the regression visible instead of silently disabling the\n // cross-command tab reuse path.\n debug(\n 'No targetId on page.target(); cross-command tab reuse disabled until puppeteer integration is updated.',\n );\n }\n\n const reportOptions = this.readCliReportAgentOptions();\n this.agent = new PuppeteerAgent(page as unknown as PuppeteerPage, {\n ...(extractAgentBehaviorInitArgs(initArgs) ?? {}),\n ...(reportOptions ?? {}),\n });\n this.lastInitArgsSignature = nextSignature;\n return this.agent;\n }\n\n public async destroy(): Promise<void> {\n await super.destroy();\n if (this.activeBrowser) {\n this.activeBrowser.disconnect();\n this.activeBrowser = null;\n }\n }\n\n protected preparePlatformTools(): ToolDefinition[] {\n return [\n {\n name: 'web_connect',\n description:\n 'Connect to a web page via CDP. Opens a new tab with the given URL, or reuses the current page.',\n schema: this.getAgentInitArgSchema(),\n cli: this.getAgentInitArgCliMetadata(),\n handler: async (args) => {\n const initArgs = this.extractAgentInitParam(args);\n const url = initArgs?.url;\n\n // Explicit connect always starts a fresh page session.\n if (this.agent) {\n try {\n await this.agent.destroy?.();\n } catch (e) {\n console.debug('Failed to destroy agent during connect:', e);\n }\n this.agent = undefined;\n this.lastInitArgsSignature = undefined;\n }\n\n const reportSession = this.createNewCliReportSession(\n url ?? 'current-page',\n );\n this.commitCliReportSession(reportSession);\n this.agent = await this.ensureAgent(initArgs);\n\n const screenshot = await this.agent.page?.screenshotBase64();\n const label = url ?? 'current page';\n\n return {\n content: [\n { type: 'text', text: `Connected via CDP to: ${label}` },\n ...(screenshot ? this.buildScreenshotContent(screenshot) : []),\n ],\n };\n },\n },\n {\n name: 'web_disconnect',\n description:\n 'Disconnect from current web page. The browser stays running (managed externally).',\n schema: {},\n handler: async () => {\n if (this.agent) {\n try {\n await this.agent.destroy?.();\n } catch (e) {\n console.debug('Failed to destroy agent during disconnect:', e);\n }\n this.agent = undefined;\n this.lastInitArgsSignature = undefined;\n }\n if (this.activeBrowser) {\n this.activeBrowser.disconnect();\n this.activeBrowser = null;\n }\n cleanupTargetIdFile();\n return this.buildTextResult(\n 'Disconnected from web page (browser still running externally)',\n );\n },\n },\n ];\n }\n}\n"],"names":["debug","getDebug","CDP_TARGET_DISCOVERY_DELAY_MS","getTargetId","page","WebCdpMidsceneTools","BaseMidsceneTools","StaticPage","ScreenshotItem","Date","defaultStaticPageViewportSize","initArgs","navigateToUrl","nextSignature","getAgentInitArgsSignature","shouldNavigateToUrl","shouldRebuildAgentForInitArgs","error","console","undefined","endpoint","getProxyEndpoint","puppeteer","browser","pages","Promise","r","setTimeout","webPages","p","savedTargetId","readSavedTargetId","matchedPage","targetId","saveTargetId","reportOptions","PuppeteerAgent","extractAgentBehaviorInitArgs","args","url","e","reportSession","screenshot","label","cleanupTargetIdFile","cdpEndpoint","webAgentInitArgShape","adaptWebAgentInitArgs"],"mappings":"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"}
@@ -4,12 +4,12 @@ import { mkdir, readFile, unlink, writeFile } from "node:fs/promises";
4
4
  import { tmpdir } from "node:os";
5
5
  import { join } from "node:path";
6
6
  import { ScreenshotItem } from "@midscene/core";
7
- import { extractAgentBehaviorInitArgs, getAgentInitArgsSignature, shouldRebuildAgentForInitArgs } from "@midscene/shared/agent-tools/agent-behavior-init-args";
8
- import { BaseMidsceneTools } from "@midscene/shared/agent-tools/base-tools";
9
- import { resolveChromePath } from "@midscene/shared/agent-tools/chrome-path";
7
+ import { extractAgentBehaviorInitArgs, getAgentInitArgsSignature, shouldRebuildAgentForInitArgs } from "@midscene/shared/mcp/agent-behavior-init-args";
8
+ import { BaseMidsceneTools } from "@midscene/shared/mcp/base-tools";
9
+ import { resolveChromePath } from "@midscene/shared/mcp/chrome-path";
10
10
  import puppeteer_core from "puppeteer-core";
11
- import { adaptWebAgentInitArgs, webAgentInitArgShape } from "./agent-init-args.mjs";
12
11
  import { defaultPuppeteerWindowViewportSize, defaultStaticPageViewportSize } from "./common/viewport.mjs";
12
+ import { adaptWebAgentInitArgs, webAgentInitArgShape } from "./mcp-agent-init-args.mjs";
13
13
  import { PuppeteerAgent } from "./puppeteer/index.mjs";
14
14
  import { StaticPage } from "./static/index.mjs";
15
15
  function _define_property(obj, key, value) {
@@ -156,10 +156,10 @@ class PuppeteerBrowserManager {
156
156
  };
157
157
  proc.stderr.on('data', onData);
158
158
  const onExit = (code, signal)=>{
159
- rejectOnce(new Error(`Chrome exited with code ${code ?? signal} before DevTools was ready.\nChrome stderr: ${output}\nTip: if running in a container, launch Chrome with sandbox-compatible arguments.`));
159
+ rejectOnce(new Error(`Chrome exited with code ${code ?? signal} before DevTools was ready.\nChrome stderr: ${output}\nTip: try setting MIDSCENE_MCP_NO_SANDBOX=1 if running in a container.`));
160
160
  };
161
161
  proc.on('exit', onExit);
162
- const timeout = setTimeout(()=>rejectOnce(new Error(`Chrome launch timeout.\nChrome stderr: ${output}\nTip: if running in a container, launch Chrome with sandbox-compatible arguments.`), true), DETACHED_CHROME_LAUNCH_TIMEOUT_MS);
162
+ const timeout = setTimeout(()=>rejectOnce(new Error(`Chrome launch timeout.\nChrome stderr: ${output}\nTip: try setting MIDSCENE_MCP_NO_SANDBOX=1 if running in a container.`), true), DETACHED_CHROME_LAUNCH_TIMEOUT_MS);
163
163
  });
164
164
  }
165
165
  constructor(persistence = {}){
@@ -305,4 +305,4 @@ class WebPuppeteerMidsceneTools extends BaseMidsceneTools {
305
305
  }
306
306
  export { PUPPETEER_ENDPOINT_FILE, WebPuppeteerMidsceneTools, buildDetachedChromeArgs };
307
307
 
308
- //# sourceMappingURL=agent-tools-puppeteer.mjs.map
308
+ //# sourceMappingURL=mcp-tools-puppeteer.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp-tools-puppeteer.mjs","sources":["../../src/mcp-tools-puppeteer.ts"],"sourcesContent":["import { type ChildProcess, spawn } from 'node:child_process';\nimport { existsSync } from 'node:fs';\nimport { mkdir, readFile, unlink, writeFile } from 'node:fs/promises';\nimport { tmpdir } from 'node:os';\nimport { join } from 'node:path';\nimport { ScreenshotItem } from '@midscene/core';\nimport {\n extractAgentBehaviorInitArgs,\n getAgentInitArgsSignature,\n shouldRebuildAgentForInitArgs,\n} from '@midscene/shared/mcp/agent-behavior-init-args';\nimport {\n BaseMidsceneTools,\n type InitArgSpec,\n} from '@midscene/shared/mcp/base-tools';\nimport { resolveChromePath } from '@midscene/shared/mcp/chrome-path';\nimport type { ToolDefinition } from '@midscene/shared/mcp/types';\nimport type { Page as PuppeteerPage } from 'puppeteer';\nimport puppeteer from 'puppeteer-core';\nimport type { Browser, Page } from 'puppeteer-core';\nimport {\n type ViewportSize,\n defaultPuppeteerWindowViewportSize,\n defaultStaticPageViewportSize,\n} from './common/viewport';\nimport {\n type WebAgentInitArgs,\n adaptWebAgentInitArgs,\n webAgentInitArgShape,\n} from './mcp-agent-init-args';\nimport { PuppeteerAgent } from './puppeteer';\nimport { StaticPage } from './static';\n\nconst ENDPOINT_FILE = join(tmpdir(), 'midscene-puppeteer-endpoint');\nconst USER_DATA_DIR = join(tmpdir(), 'midscene-puppeteer-profile');\nconst DETACHED_CHROME_LAUNCH_TIMEOUT_MS = 30_000;\n\nexport const PUPPETEER_ENDPOINT_FILE = ENDPOINT_FILE;\n\nexport interface PuppeteerPersistenceOptions {\n endpointFile?: string;\n userDataDir?: string;\n}\n\nexport interface WebPuppeteerMidsceneToolsOptions {\n persistence?: PuppeteerPersistenceOptions;\n}\n\nexport function buildDetachedChromeArgs(options: {\n userDataDir: string;\n viewport?: ViewportSize;\n}): string[] {\n const viewport = options.viewport ?? defaultPuppeteerWindowViewportSize;\n\n return [\n '--headless=new',\n `--user-data-dir=${options.userDataDir}`,\n '--remote-debugging-port=0',\n '--no-first-run',\n '--no-default-browser-check',\n '--disable-extensions',\n '--disable-default-apps',\n '--disable-sync',\n '--disable-background-networking',\n '--password-store=basic',\n '--use-mock-keychain',\n `--window-size=${viewport.width},${viewport.height}`,\n '--force-color-profile=srgb',\n ];\n}\n\nfunction terminateDetachedChrome(proc: ChildProcess): void {\n if (proc.killed || proc.exitCode !== null || proc.signalCode !== null) {\n return;\n }\n\n if (process.platform !== 'win32' && proc.pid) {\n try {\n process.kill(-proc.pid, 'SIGKILL');\n return;\n } catch {}\n }\n\n try {\n proc.kill('SIGKILL');\n } catch {}\n}\n\n/**\n * Persistent Puppeteer browser manager.\n * Launches a detached Chrome and persists the WS endpoint across CLI calls.\n */\nclass PuppeteerBrowserManager {\n activeBrowser: Browser | null = null;\n\n constructor(private readonly persistence: PuppeteerPersistenceOptions = {}) {}\n\n private get endpointFile() {\n return this.persistence.endpointFile || ENDPOINT_FILE;\n }\n\n private get userDataDir() {\n return this.persistence.userDataDir || USER_DATA_DIR;\n }\n\n async getOrLaunch(\n viewport?: ViewportSize,\n ): Promise<{ browser: Browser; reused: boolean }> {\n const endpointFile = this.endpointFile;\n if (existsSync(endpointFile)) {\n try {\n const endpoint = (await readFile(endpointFile, 'utf-8')).trim();\n const browser = await puppeteer.connect({\n browserWSEndpoint: endpoint,\n defaultViewport: null,\n });\n return { browser, reused: true };\n } catch {\n try {\n await unlink(endpointFile);\n } catch {}\n }\n }\n\n const wsEndpoint = await this.launchDetachedChrome(viewport);\n await writeFile(endpointFile, wsEndpoint);\n\n const browser = await puppeteer.connect({\n browserWSEndpoint: wsEndpoint,\n defaultViewport: null,\n });\n return { browser, reused: false };\n }\n\n async closeBrowser(): Promise<void> {\n const endpointFile = this.endpointFile;\n if (!existsSync(endpointFile)) return;\n try {\n const endpoint = (await readFile(endpointFile, 'utf-8')).trim();\n const browser = await puppeteer.connect({\n browserWSEndpoint: endpoint,\n });\n await browser.close();\n } catch {}\n try {\n await unlink(endpointFile);\n } catch {}\n }\n\n disconnect(): void {\n if (this.activeBrowser) {\n this.activeBrowser.disconnect();\n this.activeBrowser = null;\n }\n }\n\n async launchDetachedChrome(viewport?: ViewportSize): Promise<string> {\n const chromePath = resolveChromePath();\n const userDataDir = this.userDataDir;\n\n await mkdir(userDataDir, { recursive: true });\n\n const args = buildDetachedChromeArgs({\n userDataDir,\n viewport,\n });\n\n const proc = spawn(chromePath, args, {\n detached: true,\n stdio: ['ignore', 'ignore', 'pipe'],\n });\n proc.unref();\n\n return new Promise<string>((resolve, reject) => {\n let output = '';\n let settled = false;\n const cleanup = () => {\n clearTimeout(timeout);\n proc.stderr!.removeListener('data', onData);\n proc.removeListener('exit', onExit);\n };\n const resolveOnce = (value: string) => {\n if (settled) return;\n settled = true;\n cleanup();\n resolve(value);\n };\n const rejectOnce = (error: Error, terminate = false) => {\n if (settled) return;\n settled = true;\n if (terminate) {\n terminateDetachedChrome(proc);\n }\n cleanup();\n reject(error);\n };\n const onData = (data: Buffer) => {\n output += data.toString();\n const match = output.match(/DevTools listening on (ws:\\/\\/[^\\s]+)/);\n if (match) {\n resolveOnce(match[1]);\n }\n };\n proc.stderr!.on('data', onData);\n\n const onExit = (code: number | null, signal: NodeJS.Signals | null) => {\n rejectOnce(\n new Error(\n `Chrome exited with code ${code ?? signal} before DevTools was ready.\\nChrome stderr: ${output}\\nTip: try setting MIDSCENE_MCP_NO_SANDBOX=1 if running in a container.`,\n ),\n );\n };\n proc.on('exit', onExit);\n\n const timeout = setTimeout(\n () =>\n rejectOnce(\n new Error(\n `Chrome launch timeout.\\nChrome stderr: ${output}\\nTip: try setting MIDSCENE_MCP_NO_SANDBOX=1 if running in a container.`,\n ),\n true,\n ),\n DETACHED_CHROME_LAUNCH_TIMEOUT_MS,\n );\n });\n }\n}\n\nconst defaultBrowserManager = new PuppeteerBrowserManager();\n\n/**\n * Tools manager for Web Puppeteer-mode MCP.\n * Uses a persistent headless Chrome browser that survives across CLI calls.\n */\nexport class WebPuppeteerMidsceneTools extends BaseMidsceneTools<\n PuppeteerAgent,\n WebAgentInitArgs\n> {\n private readonly viewport?: ViewportSize;\n private readonly browserManager: PuppeteerBrowserManager;\n private lastInitArgsSignature?: string;\n\n constructor(\n viewport?: ViewportSize,\n options: WebPuppeteerMidsceneToolsOptions = {},\n ) {\n super();\n this.viewport = viewport ? { ...viewport } : undefined;\n this.browserManager = options.persistence\n ? new PuppeteerBrowserManager(options.persistence)\n : defaultBrowserManager;\n }\n\n protected getCliReportSessionName() {\n return 'midscene-web';\n }\n\n protected readonly initArgSpec: InitArgSpec<WebAgentInitArgs> = {\n namespace: 'web',\n shape: webAgentInitArgShape,\n cli: {\n preferBareKeys: true,\n },\n adapt: adaptWebAgentInitArgs,\n };\n\n protected createTemporaryDevice() {\n return new StaticPage({\n screenshot: ScreenshotItem.create('', Date.now()),\n shotSize: this.viewport ?? defaultStaticPageViewportSize,\n shrunkShotToLogicalRatio: 1,\n });\n }\n\n protected async ensureAgent(\n initArgs?: WebAgentInitArgs,\n ): Promise<PuppeteerAgent> {\n const navigateToUrl = initArgs?.url;\n const nextSignature = getAgentInitArgsSignature(initArgs);\n const shouldOpenUrl = typeof navigateToUrl === 'string';\n\n if (\n this.agent &&\n (shouldOpenUrl ||\n shouldRebuildAgentForInitArgs(\n this.lastInitArgsSignature,\n nextSignature,\n ))\n ) {\n try {\n await this.agent?.destroy?.();\n } catch {}\n this.agent = undefined;\n }\n\n if (this.agent) return this.agent;\n\n const { browser, reused } = await this.browserManager.getOrLaunch(\n this.viewport,\n );\n this.browserManager.activeBrowser = browser;\n\n const pages = await browser.pages();\n let page: Page;\n\n if (navigateToUrl) {\n page = await browser.newPage();\n if (this.viewport) {\n await page.setViewport(this.viewport);\n }\n await page.goto(navigateToUrl, {\n timeout: 30000,\n waitUntil: 'domcontentloaded',\n });\n } else {\n // Reuse the last web page\n const webPages = pages.filter((p) => /^https?:\\/\\//.test(p.url()));\n page =\n webPages.length > 0\n ? webPages[webPages.length - 1]\n : pages[pages.length - 1] || (await browser.newPage());\n\n if (reused) {\n await page.bringToFront();\n }\n if (this.viewport) {\n await page.setViewport(this.viewport);\n }\n }\n\n const reportOptions = this.readCliReportAgentOptions();\n this.agent = new PuppeteerAgent(page as unknown as PuppeteerPage, {\n ...(extractAgentBehaviorInitArgs(initArgs) ?? {}),\n ...(reportOptions ?? {}),\n });\n this.lastInitArgsSignature = nextSignature;\n return this.agent;\n }\n\n public async destroy(): Promise<void> {\n await super.destroy();\n this.browserManager.disconnect();\n }\n\n protected preparePlatformTools(): ToolDefinition[] {\n return [\n {\n name: 'web_connect',\n description:\n 'Connect to a web page. Opens a new tab with the given URL, or reuses the current page.',\n schema: this.getAgentInitArgSchema(),\n cli: this.getAgentInitArgCliMetadata(),\n handler: async (args) => {\n const initArgs = this.extractAgentInitParam(args);\n const url = initArgs?.url;\n\n // Explicit connect always starts a fresh page session.\n if (this.agent) {\n try {\n await this.agent.destroy?.();\n } catch {}\n this.agent = undefined;\n this.lastInitArgsSignature = undefined;\n }\n\n const reportSession = this.createNewCliReportSession(\n url ?? 'current-page',\n );\n this.commitCliReportSession(reportSession);\n this.agent = await this.ensureAgent(initArgs);\n\n const screenshot = await this.agent.page?.screenshotBase64();\n const label = url ?? 'current page';\n\n return {\n content: [\n { type: 'text', text: `Connected to: ${label}` },\n ...(screenshot ? this.buildScreenshotContent(screenshot) : []),\n ],\n };\n },\n },\n {\n name: 'web_disconnect',\n description:\n 'Disconnect from current web page. The browser stays running for future calls.',\n schema: {},\n handler: async () => {\n if (this.agent) {\n try {\n await this.agent.destroy?.();\n } catch {}\n this.agent = undefined;\n this.lastInitArgsSignature = undefined;\n }\n this.browserManager.disconnect();\n return this.buildTextResult(\n 'Disconnected from web page (browser still running)',\n );\n },\n },\n {\n name: 'web_close',\n description: 'Close the browser completely and release all resources.',\n schema: {},\n handler: async () => {\n if (this.agent) {\n try {\n await this.agent.destroy?.();\n } catch {}\n this.agent = undefined;\n this.lastInitArgsSignature = undefined;\n }\n await this.browserManager.closeBrowser();\n return this.buildTextResult('Browser closed');\n },\n },\n ];\n }\n}\n"],"names":["ENDPOINT_FILE","join","tmpdir","USER_DATA_DIR","DETACHED_CHROME_LAUNCH_TIMEOUT_MS","PUPPETEER_ENDPOINT_FILE","buildDetachedChromeArgs","options","viewport","defaultPuppeteerWindowViewportSize","terminateDetachedChrome","proc","process","PuppeteerBrowserManager","endpointFile","existsSync","endpoint","readFile","browser","puppeteer","unlink","wsEndpoint","writeFile","chromePath","resolveChromePath","userDataDir","mkdir","args","spawn","Promise","resolve","reject","output","settled","cleanup","clearTimeout","timeout","onData","onExit","resolveOnce","value","rejectOnce","error","terminate","data","match","code","signal","Error","setTimeout","persistence","defaultBrowserManager","WebPuppeteerMidsceneTools","BaseMidsceneTools","StaticPage","ScreenshotItem","Date","defaultStaticPageViewportSize","initArgs","navigateToUrl","nextSignature","getAgentInitArgsSignature","shouldOpenUrl","shouldRebuildAgentForInitArgs","undefined","reused","pages","page","webPages","p","reportOptions","PuppeteerAgent","extractAgentBehaviorInitArgs","url","reportSession","screenshot","label","webAgentInitArgShape","adaptWebAgentInitArgs"],"mappings":"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"}
@@ -1,9 +1,9 @@
1
1
  import { ScreenshotItem } from "@midscene/core";
2
- import { extractAgentBehaviorInitArgs, getAgentInitArgsSignature, shouldRebuildAgentForInitArgs } from "@midscene/shared/agent-tools/agent-behavior-init-args";
3
- import { BaseMidsceneTools } from "@midscene/shared/agent-tools/base-tools";
4
- import { adaptWebAgentInitArgs, webAgentInitArgShape } from "./agent-init-args.mjs";
2
+ import { extractAgentBehaviorInitArgs, getAgentInitArgsSignature, shouldRebuildAgentForInitArgs } from "@midscene/shared/mcp/agent-behavior-init-args";
3
+ import { BaseMidsceneTools } from "@midscene/shared/mcp/base-tools";
5
4
  import { AgentOverChromeBridge } from "./bridge-mode/index.mjs";
6
5
  import { defaultStaticPageViewportSize } from "./common/viewport.mjs";
6
+ import { adaptWebAgentInitArgs, webAgentInitArgShape } from "./mcp-agent-init-args.mjs";
7
7
  import { StaticPage } from "./static/index.mjs";
8
8
  function _define_property(obj, key, value) {
9
9
  if (key in obj) Object.defineProperty(obj, key, {
@@ -116,4 +116,4 @@ class WebMidsceneTools extends BaseMidsceneTools {
116
116
  }
117
117
  export { WebMidsceneTools };
118
118
 
119
- //# sourceMappingURL=agent-tools.mjs.map
119
+ //# sourceMappingURL=mcp-tools.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp-tools.mjs","sources":["../../src/mcp-tools.ts"],"sourcesContent":["import { ScreenshotItem } from '@midscene/core';\nimport {\n extractAgentBehaviorInitArgs,\n getAgentInitArgsSignature,\n shouldRebuildAgentForInitArgs,\n} from '@midscene/shared/mcp/agent-behavior-init-args';\nimport {\n BaseMidsceneTools,\n type InitArgSpec,\n} from '@midscene/shared/mcp/base-tools';\nimport type { ToolDefinition } from '@midscene/shared/mcp/types';\nimport { AgentOverChromeBridge } from './bridge-mode';\nimport { defaultStaticPageViewportSize } from './common/viewport';\nimport {\n type WebAgentInitArgs,\n adaptWebAgentInitArgs,\n webAgentInitArgShape,\n} from './mcp-agent-init-args';\nimport { StaticPage } from './static';\n\n/**\n * Tools manager for Web bridge-mode MCP\n */\nexport class WebMidsceneTools extends BaseMidsceneTools<\n AgentOverChromeBridge,\n WebAgentInitArgs\n> {\n private lastInitArgsSignature?: string;\n\n protected getCliReportSessionName() {\n return 'midscene-web';\n }\n\n protected readonly initArgSpec: InitArgSpec<WebAgentInitArgs> = {\n namespace: 'web',\n shape: webAgentInitArgShape,\n cli: {\n preferBareKeys: true,\n },\n adapt: adaptWebAgentInitArgs,\n };\n\n protected createTemporaryDevice() {\n // Use require to avoid type incompatibility with DeviceAction vs ActionSpaceItem\n // StaticPage.actionSpace() returns DeviceAction[] which is compatible at runtime\n // Use screenshotBase64 field to avoid async ScreenshotItem.create()\n return new StaticPage({\n screenshot: ScreenshotItem.create('', Date.now()),\n shotSize: defaultStaticPageViewportSize,\n shrunkShotToLogicalRatio: 1,\n });\n }\n\n protected async ensureAgent(\n initArgs?: WebAgentInitArgs,\n ): Promise<AgentOverChromeBridge> {\n const nextSignature = getAgentInitArgsSignature(initArgs);\n const shouldOpenUrl = typeof initArgs?.url === 'string';\n\n if (\n this.agent &&\n (shouldOpenUrl ||\n shouldRebuildAgentForInitArgs(\n this.lastInitArgsSignature,\n nextSignature,\n ))\n ) {\n try {\n await this.agent?.destroy?.();\n } catch (error) {\n console.debug('Failed to destroy agent during re-init:', error);\n }\n this.agent = undefined;\n }\n\n if (this.agent) return this.agent;\n\n // Connect to current tab when no URL provided (handles CLI stateless calls)\n this.agent = await this.initBridgeModeAgent(initArgs);\n this.lastInitArgsSignature = nextSignature;\n\n return this.agent;\n }\n\n private async initBridgeModeAgent(\n initArgs?: WebAgentInitArgs,\n ): Promise<AgentOverChromeBridge> {\n const url = initArgs?.url;\n const reportOptions = this.readCliReportAgentOptions();\n const agent = new AgentOverChromeBridge({\n closeConflictServer: true,\n ...(extractAgentBehaviorInitArgs(initArgs) ?? {}),\n ...(reportOptions ?? {}),\n });\n\n if (!url) {\n await agent.connectCurrentTab();\n } else {\n await agent.connectNewTabWithUrl(url);\n }\n\n return agent;\n }\n\n protected preparePlatformTools(): ToolDefinition[] {\n return [\n {\n name: 'web_connect',\n description:\n 'Connect to web page. If URL provided, opens new tab; otherwise connects to current tab.',\n schema: this.getAgentInitArgSchema(),\n cli: this.getAgentInitArgCliMetadata(),\n handler: async (args) => {\n const initArgs = this.extractAgentInitParam(args);\n const url = initArgs?.url;\n\n // Explicit connect always starts a fresh bridge session.\n if (this.agent) {\n try {\n await this.agent.destroy?.();\n } catch {}\n this.agent = undefined;\n this.lastInitArgsSignature = undefined;\n }\n const reportSession = this.createNewCliReportSession(\n url ?? 'current-tab',\n );\n this.commitCliReportSession(reportSession);\n this.agent = await this.ensureAgent(initArgs);\n\n const screenshot = await this.agent.page?.screenshotBase64();\n const label = url ?? 'current tab';\n\n return {\n content: [\n { type: 'text', text: `Connected to: ${label}` },\n ...(screenshot ? this.buildScreenshotContent(screenshot) : []),\n ],\n };\n },\n },\n {\n name: 'web_disconnect',\n description:\n 'Disconnect from current web page and release browser resources',\n schema: {},\n handler: async () => {\n if (!this.agent) {\n return this.buildTextResult('No active connection to disconnect');\n }\n\n try {\n await this.agent.destroy?.();\n } catch {}\n this.agent = undefined;\n this.lastInitArgsSignature = undefined;\n\n return this.buildTextResult('Disconnected from web page');\n },\n },\n ];\n }\n}\n"],"names":["WebMidsceneTools","BaseMidsceneTools","StaticPage","ScreenshotItem","Date","defaultStaticPageViewportSize","initArgs","nextSignature","getAgentInitArgsSignature","shouldOpenUrl","shouldRebuildAgentForInitArgs","error","console","undefined","url","reportOptions","agent","AgentOverChromeBridge","extractAgentBehaviorInitArgs","args","reportSession","screenshot","label","webAgentInitArgShape","adaptWebAgentInitArgs"],"mappings":"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"}