@midscene/web 1.10.7-beta-20260722111246.0 → 1.10.7

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.
@@ -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\nconst NAVIGATION_COMPLETE_TIMEOUT_MS = 30_000;\n\nfunction isBlankUrl(url: string | undefined): boolean {\n if (!url) return true;\n return url === 'about:blank' || url.startsWith('chrome://newtab');\n}\n\n/**\n * Wait for the browser target to settle before sending CDP commands to it.\n *\n * A cross-origin redirect can replace the target after `tabs.update()`\n * resolves. Sending `Runtime.evaluate` during that hand-off intermittently\n * fails because Chrome has detached the debugger from the old target.\n */\nfunction waitForTabNavigationComplete(\n tabId: number,\n targetUrl: string,\n updatedTab?: chrome.tabs.Tab,\n timeoutMs = NAVIGATION_COMPLETE_TIMEOUT_MS,\n): Promise<void> {\n return new Promise((resolve) => {\n let settled = false;\n const finish = () => {\n if (settled) return;\n settled = true;\n chrome.tabs.onUpdated.removeListener(onUpdated);\n clearTimeout(timer);\n resolve();\n };\n\n const isTargetTab = (tab: chrome.tabs.Tab | undefined): boolean => {\n if (!tab) return false;\n return tab.url === targetUrl || tab.pendingUrl === targetUrl;\n };\n\n const isReady = (\n tab: chrome.tabs.Tab | undefined,\n navigationUpdateObserved: boolean,\n ): boolean => {\n if (!tab || tab.status !== 'complete') return false;\n const currentUrl = tab.url || tab.pendingUrl || '';\n const isExpectedUrlKind = isBlankUrl(targetUrl)\n ? isBlankUrl(currentUrl)\n : !isBlankUrl(currentUrl);\n return (\n isExpectedUrlKind && (navigationUpdateObserved || isTargetTab(tab))\n );\n };\n\n const onUpdated = (\n id: number,\n info: chrome.tabs.TabChangeInfo,\n tab: chrome.tabs.Tab,\n ) => {\n // This listener is registered after tabs.update(), so a completion\n // event received here belongs to the navigation we initiated.\n if (id === tabId && isReady(tab, info.status === 'complete')) finish();\n };\n\n chrome.tabs.onUpdated.addListener(onUpdated);\n const timer = setTimeout(finish, timeoutMs);\n\n // tabs.update() returns the updated target. A completed returned tab is\n // already a settled result of this navigation, including a fast redirect.\n if (isReady(updatedTab, true)) {\n finish();\n return;\n }\n\n // The tab may have completed before the listener was added. Only accept\n // the requested target here: a previous complete HTTPS page is not proof\n // that this navigation has settled.\n chrome.tabs\n .get(tabId)\n .then((tab) => {\n if (isReady(tab, false)) finish();\n })\n .catch(() => {});\n });\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 protected waterFlowAnimationEnabled = true;\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 if (!this.waterFlowAnimationEnabled) return;\n\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 if (!this.waterFlowAnimationEnabled) {\n return;\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 public async setWaterFlowAnimationEnabled(enabled: boolean) {\n this.waterFlowAnimationEnabled = enabled;\n if (!enabled) {\n const script = await injectStopWaterFlowAnimation();\n await this.sendCommandToDebugger('Runtime.evaluate', {\n expression: script,\n });\n }\n }\n\n /**\n * Returns the current water-flow animation enabled flag.\n */\n public getWaterFlowAnimationEnabled(): boolean {\n return this.waterFlowAnimationEnabled;\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 let result: any;\n try {\n result = await this.sendCommandToDebugger('Runtime.evaluate', {\n expression: 'document.readyState',\n });\n } catch (error) {\n // Navigation can replace the target between tabs.update() and this\n // probe. Chrome occasionally reports that race as an empty object,\n // which cannot be recognised by sendCommandToDebugger's message-based\n // detach detection. Reattach and keep waiting for the settled page.\n debug('Failed to probe document readyState; retrying after attach', {\n error,\n });\n try {\n await this.ensureDebuggerAttached();\n } catch (attachError) {\n debug('Failed to reattach debugger while waiting for navigation', {\n error: attachError,\n });\n }\n await sleep(300);\n continue;\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 const updatedTab = await chrome.tabs.update(tabId, { url });\n await waitForTabNavigationComplete(tabId, url, updatedTab);\n // Wait for navigation to complete. The tab-level wait above avoids sending\n // CDP commands during cross-origin target replacement.\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 // CDP uses `buttons` to represent the currently pressed mouse buttons.\n // HTML5 drag/drop needs this state to treat following moves as dragging.\n buttons: 1,\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 button: 'left',\n buttons: 1,\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 buttons: 0,\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","NAVIGATION_COMPLETE_TIMEOUT_MS","isBlankUrl","url","waitForTabNavigationComplete","tabId","targetUrl","updatedTab","timeoutMs","settled","finish","chrome","onUpdated","clearTimeout","timer","isTargetTab","tab","isReady","navigationUpdateObserved","currentUrl","isExpectedUrlKind","id","info","hasFlatNodeAttribute","attributes","name","i","serializeError","error","ChromeExtensionProxyPage","commonWebActionsForWebPage","Error","tabs","assert","console","errorMsg","err","x","y","pointerScript","tabIdToDetach","limitOpenNewTabScript","script","injectWaterFlowAnimation","injectStopWaterFlowAnimation","enabled","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","attachError","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\nconst NAVIGATION_COMPLETE_TIMEOUT_MS = 30_000;\n\nfunction isBlankUrl(url: string | undefined): boolean {\n if (!url) return true;\n return url === 'about:blank' || url.startsWith('chrome://newtab');\n}\n\n/**\n * Wait for the browser target to settle before sending CDP commands to it.\n *\n * A cross-origin redirect can replace the target after `tabs.update()`\n * resolves. Sending `Runtime.evaluate` during that hand-off intermittently\n * fails because Chrome has detached the debugger from the old target.\n */\nfunction waitForTabNavigationComplete(\n tabId: number,\n targetUrl: string,\n updatedTab?: chrome.tabs.Tab,\n timeoutMs = NAVIGATION_COMPLETE_TIMEOUT_MS,\n): Promise<void> {\n return new Promise((resolve) => {\n let settled = false;\n const finish = () => {\n if (settled) return;\n settled = true;\n chrome.tabs.onUpdated.removeListener(onUpdated);\n clearTimeout(timer);\n resolve();\n };\n\n const isTargetTab = (tab: chrome.tabs.Tab | undefined): boolean => {\n if (!tab) return false;\n return tab.url === targetUrl || tab.pendingUrl === targetUrl;\n };\n\n const isReady = (\n tab: chrome.tabs.Tab | undefined,\n navigationUpdateObserved: boolean,\n ): boolean => {\n if (!tab || tab.status !== 'complete') return false;\n const currentUrl = tab.url || tab.pendingUrl || '';\n const isExpectedUrlKind = isBlankUrl(targetUrl)\n ? isBlankUrl(currentUrl)\n : !isBlankUrl(currentUrl);\n return (\n isExpectedUrlKind && (navigationUpdateObserved || isTargetTab(tab))\n );\n };\n\n const onUpdated = (\n id: number,\n info: chrome.tabs.TabChangeInfo,\n tab: chrome.tabs.Tab,\n ) => {\n // This listener is registered after tabs.update(), so a completion\n // event received here belongs to the navigation we initiated.\n if (id === tabId && isReady(tab, info.status === 'complete')) finish();\n };\n\n chrome.tabs.onUpdated.addListener(onUpdated);\n const timer = setTimeout(finish, timeoutMs);\n\n // tabs.update() returns the updated target. A completed returned tab is\n // already a settled result of this navigation, including a fast redirect.\n if (isReady(updatedTab, true)) {\n finish();\n return;\n }\n\n // The tab may have completed before the listener was added. Only accept\n // the requested target here: a previous complete HTTPS page is not proof\n // that this navigation has settled.\n chrome.tabs\n .get(tabId)\n .then((tab) => {\n if (isReady(tab, false)) finish();\n })\n .catch(() => {});\n });\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 let result: any;\n try {\n result = await this.sendCommandToDebugger('Runtime.evaluate', {\n expression: 'document.readyState',\n });\n } catch (error) {\n // Navigation can replace the target between tabs.update() and this\n // probe. Chrome occasionally reports that race as an empty object,\n // which cannot be recognised by sendCommandToDebugger's message-based\n // detach detection. Reattach and keep waiting for the settled page.\n debug('Failed to probe document readyState; retrying after attach', {\n error,\n });\n try {\n await this.ensureDebuggerAttached();\n } catch (attachError) {\n debug('Failed to reattach debugger while waiting for navigation', {\n error: attachError,\n });\n }\n await sleep(300);\n continue;\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 const updatedTab = await chrome.tabs.update(tabId, { url });\n await waitForTabNavigationComplete(tabId, url, updatedTab);\n // Wait for navigation to complete. The tab-level wait above avoids sending\n // CDP commands during cross-origin target replacement.\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 // CDP uses `buttons` to represent the currently pressed mouse buttons.\n // HTML5 drag/drop needs this state to treat following moves as dragging.\n buttons: 1,\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 button: 'left',\n buttons: 1,\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 buttons: 0,\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","NAVIGATION_COMPLETE_TIMEOUT_MS","isBlankUrl","url","waitForTabNavigationComplete","tabId","targetUrl","updatedTab","timeoutMs","settled","finish","chrome","onUpdated","clearTimeout","timer","isTargetTab","tab","isReady","navigationUpdateObserved","currentUrl","isExpectedUrlKind","id","info","hasFlatNodeAttribute","attributes","name","i","serializeError","error","ChromeExtensionProxyPage","commonWebActionsForWebPage","Error","tabs","assert","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","attachError","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
@@ -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.10.7-beta-20260722111246.0",
21
+ version: "1.10.7",
22
22
  extraCommands: createReportCliCommands()
23
23
  });
24
24
  }).catch((e)=>{
@@ -168,20 +168,13 @@ const getBridgePageInCliSide = (options)=>{
168
168
  return proxyPage;
169
169
  };
170
170
  class AgentOverChromeBridge extends agent_namespaceObject.Agent {
171
- async configureWaterFlowAnimation() {
172
- if (!this.enableWaterFlowAnimation) await this.page.setWaterFlowAnimationEnabled(false);
173
- }
174
171
  async setDestroyOptionsAfterConnect() {
175
172
  if (this.destroyAfterDisconnectFlag) this.page.setDestroyOptions({
176
173
  closeTab: true
177
174
  });
178
175
  }
179
176
  async connectNewTabWithUrl(url, options) {
180
- await this.page.connectNewTabWithUrl(url, {
181
- ...options,
182
- enableWaterFlowAnimation: this.enableWaterFlowAnimation
183
- });
184
- await this.configureWaterFlowAnimation();
177
+ await this.page.connectNewTabWithUrl(url, options);
185
178
  await sleep(500);
186
179
  await this.setDestroyOptionsAfterConnect();
187
180
  }
@@ -192,11 +185,7 @@ class AgentOverChromeBridge extends agent_namespaceObject.Agent {
192
185
  return await this.page.setActiveTabId(Number.parseInt(tabId));
193
186
  }
194
187
  async connectCurrentTab(options) {
195
- await this.page.connectCurrentTab({
196
- ...options,
197
- enableWaterFlowAnimation: this.enableWaterFlowAnimation
198
- });
199
- await this.configureWaterFlowAnimation();
188
+ await this.page.connectCurrentTab(options);
200
189
  await sleep(500);
201
190
  await this.setDestroyOptionsAfterConnect();
202
191
  }
@@ -223,9 +212,8 @@ class AgentOverChromeBridge extends agent_namespaceObject.Agent {
223
212
  this.page.showStatusMessage(tip);
224
213
  if (originalOnTaskStartTip) originalOnTaskStartTip?.call(this, tip);
225
214
  }
226
- })), _define_property(this, "destroyAfterDisconnectFlag", void 0), _define_property(this, "enableWaterFlowAnimation", void 0);
215
+ })), _define_property(this, "destroyAfterDisconnectFlag", void 0);
227
216
  this.destroyAfterDisconnectFlag = opts?.closeNewTabsAfterDisconnect;
228
- this.enableWaterFlowAnimation = opts?.enableWaterFlowAnimation ?? true;
229
217
  }
230
218
  }
231
219
  exports.AgentOverChromeBridge = __webpack_exports__.AgentOverChromeBridge;
@@ -1 +1 @@
1
- {"version":3,"file":"bridge-mode/agent-cli-side.js","sources":["webpack/runtime/define_property_getters","webpack/runtime/has_own_property","webpack/runtime/make_namespace_object","../../../src/bridge-mode/agent-cli-side.ts"],"sourcesContent":["__webpack_require__.d = (exports, definition) => {\n\tfor(var key in definition) {\n if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n }\n }\n};","__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))","// define __esModule on exports\n__webpack_require__.r = (exports) => {\n\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\t}\n\tObject.defineProperty(exports, '__esModule', { value: true });\n};","import { Agent, type AgentOpt } from '@midscene/core/agent';\nimport type { FileChooserHandler } from '@midscene/core/device';\nimport { getDebug } from '@midscene/shared/logger';\nimport { assert } from '@midscene/shared/utils';\nimport { commonWebActionsForWebPage } from '../web-page';\nimport type { KeyboardAction, MouseAction } from '../web-page';\nimport {\n type BridgeConnectTabOptions,\n BridgeEvent,\n BridgePageType,\n DefaultBridgeServerHost,\n DefaultBridgeServerPort,\n KeyboardEvent,\n MouseEvent,\n getBridgeServerHost,\n} from './common';\nimport { BridgeServer } from './io-server';\nimport type { ExtensionBridgePageBrowserSide } from './page-browser-side';\n\ninterface ChromeExtensionPageCliSide extends ExtensionBridgePageBrowserSide {\n showStatusMessage: (message: string) => Promise<void>;\n}\n\ntype BridgeSerializedError = {\n message: string;\n name?: string;\n stack?: string;\n};\n\nconst sleep = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));\n\nconst debug = getDebug('web:bridge:agent-cli-side');\n\nfunction deserializeBridgeError(error: BridgeSerializedError): Error {\n const result = new Error(error.message);\n result.name = error.name || 'Error';\n result.stack = error.stack;\n return result;\n}\n\n// actually, this is a proxy to the page in browser side\nexport const getBridgePageInCliSide = (options?: {\n host?: string;\n port?: number;\n timeout?: number | false;\n closeConflictServer?: boolean;\n}): ChromeExtensionPageCliSide => {\n const host = options?.host || DefaultBridgeServerHost;\n const port = options?.port || DefaultBridgeServerPort;\n const server = new BridgeServer(\n host,\n port,\n undefined,\n undefined,\n options?.closeConflictServer,\n );\n server.listen({\n timeout: options?.timeout,\n });\n\n let fileChooserEnabled = false;\n let fileChooserError: Error | undefined;\n\n const fileChooserBridgeMethods = new Set<string>([\n BridgeEvent.RegisterFileChooserAccept,\n BridgeEvent.ClearFileChooserAccept,\n BridgeEvent.GetFileChooserError,\n ]);\n\n const syncFileChooserError = async () => {\n if (!fileChooserEnabled) return;\n try {\n const error = await server.call<BridgeSerializedError | undefined>(\n BridgeEvent.GetFileChooserError,\n [],\n 5000,\n );\n if (error) {\n fileChooserError = deserializeBridgeError(error);\n }\n } catch (error) {\n fileChooserError =\n error instanceof Error ? error : new Error(String(error));\n }\n };\n\n const bridgeCaller = (method: string, timeout?: number) => {\n return async (...args: any[]) => {\n try {\n const response = await server.call(method, args, timeout);\n if (!fileChooserBridgeMethods.has(method)) {\n await syncFileChooserError();\n }\n return response;\n } catch (error) {\n if (!fileChooserBridgeMethods.has(method)) {\n await syncFileChooserError();\n }\n throw error;\n }\n };\n };\n const page = {\n showStatusMessage: async (message: string) => {\n await server.call(BridgeEvent.UpdateAgentStatus, [message]);\n },\n };\n\n const proxyPage = new Proxy(page, {\n get(target, prop, receiver) {\n assert(typeof prop === 'string', 'prop must be a string');\n\n if (prop === 'toJSON') {\n return () => {\n return {\n interfaceType: BridgePageType,\n };\n };\n }\n\n if (prop === 'interfaceType') {\n return BridgePageType;\n }\n\n if (prop === 'actionSpace') {\n return () => commonWebActionsForWebPage(proxyPage);\n }\n\n if (Object.keys(page).includes(prop)) {\n return page[prop as keyof typeof page];\n }\n\n if (prop === 'registerFileChooserListener') {\n return async (\n handler: (chooser: FileChooserHandler) => Promise<void>,\n ) => {\n fileChooserEnabled = true;\n fileChooserError = undefined;\n try {\n await handler({\n accept: async (files: string[]) => {\n await server.call(BridgeEvent.RegisterFileChooserAccept, [\n files,\n ]);\n },\n });\n } catch (error) {\n fileChooserEnabled = false;\n fileChooserError =\n error instanceof Error ? error : new Error(String(error));\n throw fileChooserError;\n }\n\n return {\n dispose: () => {\n fileChooserEnabled = false;\n server\n .call(BridgeEvent.ClearFileChooserAccept, [], 5000)\n .catch((error) => {\n debug(\n 'failed to clear bridge file chooser accept: %O',\n error,\n );\n });\n },\n getError: async () => {\n await syncFileChooserError();\n return fileChooserError;\n },\n };\n };\n }\n\n if (prop === 'mouse') {\n const mouse: MouseAction = {\n click: bridgeCaller(MouseEvent.Click),\n wheel: bridgeCaller(MouseEvent.Wheel),\n move: bridgeCaller(MouseEvent.Move),\n drag: bridgeCaller(MouseEvent.Drag),\n };\n return mouse;\n }\n\n if (prop === 'keyboard') {\n const keyboard: KeyboardAction = {\n type: bridgeCaller(KeyboardEvent.Type),\n press: bridgeCaller(KeyboardEvent.Press),\n };\n return keyboard;\n }\n\n if (prop === 'destroy') {\n return async (...args: any[]) => {\n try {\n const caller = bridgeCaller('destroy');\n await caller(...args);\n } catch (e) {\n // console.error('error calling destroy', e);\n }\n return server.close();\n };\n }\n\n // Special handling for methods that support timeout in options\n if (prop === 'connectNewTabWithUrl') {\n return async (url: string, options?: BridgeConnectTabOptions) => {\n const timeout = options?.timeout;\n const caller = bridgeCaller(prop, timeout);\n return await caller(url, options);\n };\n }\n\n if (prop === 'connectCurrentTab') {\n return async (options?: BridgeConnectTabOptions) => {\n const timeout = options?.timeout;\n const caller = bridgeCaller(prop, timeout);\n return await caller(options);\n };\n }\n\n return bridgeCaller(prop);\n },\n }) as ChromeExtensionPageCliSide;\n\n return proxyPage;\n};\n\nexport class AgentOverChromeBridge extends Agent<ChromeExtensionPageCliSide> {\n private destroyAfterDisconnectFlag?: boolean;\n\n private enableWaterFlowAnimation: boolean;\n\n constructor(\n opts?: AgentOpt & {\n /**\n * Enable remote access to the bridge server.\n * - false (default): Only localhost can connect (most secure)\n * - true: Allow remote machines to connect (binds to 0.0.0.0)\n */\n allowRemoteAccess?: boolean;\n /**\n * Custom host to bind the bridge server to.\n * Overrides allowRemoteAccess if specified.\n */\n host?: string;\n /**\n * Custom port for the bridge server.\n * @default 3766\n */\n port?: number;\n closeNewTabsAfterDisconnect?: boolean;\n serverListeningTimeout?: number | false;\n closeConflictServer?: boolean;\n /**\n * Show the blue water-flow border and mouse pointer while controlling\n * the page.\n * @default true\n */\n enableWaterFlowAnimation?: boolean;\n },\n ) {\n const host = getBridgeServerHost({\n host: opts?.host,\n allowRemoteAccess: opts?.allowRemoteAccess,\n });\n const page = getBridgePageInCliSide({\n host,\n port: opts?.port,\n timeout: opts?.serverListeningTimeout,\n closeConflictServer: opts?.closeConflictServer,\n });\n const originalOnTaskStartTip = opts?.onTaskStartTip;\n super(\n page,\n Object.assign(opts || {}, {\n onTaskStartTip: (tip: string) => {\n this.page.showStatusMessage(tip);\n if (originalOnTaskStartTip) {\n originalOnTaskStartTip?.call(this, tip);\n }\n },\n }),\n );\n this.destroyAfterDisconnectFlag = opts?.closeNewTabsAfterDisconnect;\n this.enableWaterFlowAnimation = opts?.enableWaterFlowAnimation ?? true;\n }\n\n private async configureWaterFlowAnimation() {\n if (!this.enableWaterFlowAnimation) {\n await this.page.setWaterFlowAnimationEnabled(false);\n }\n }\n\n async setDestroyOptionsAfterConnect() {\n if (this.destroyAfterDisconnectFlag) {\n this.page.setDestroyOptions({\n closeTab: true,\n });\n }\n }\n\n async connectNewTabWithUrl(url: string, options?: BridgeConnectTabOptions) {\n await this.page.connectNewTabWithUrl(url, {\n ...options,\n enableWaterFlowAnimation: this.enableWaterFlowAnimation,\n });\n await this.configureWaterFlowAnimation();\n await sleep(500);\n await this.setDestroyOptionsAfterConnect();\n }\n\n async getBrowserTabList() {\n return await this.page.getBrowserTabList();\n }\n\n async setActiveTabId(tabId: string) {\n return await this.page.setActiveTabId(Number.parseInt(tabId));\n }\n\n async connectCurrentTab(options?: BridgeConnectTabOptions) {\n await this.page.connectCurrentTab({\n ...options,\n enableWaterFlowAnimation: this.enableWaterFlowAnimation,\n });\n await this.configureWaterFlowAnimation();\n await sleep(500);\n await this.setDestroyOptionsAfterConnect();\n }\n\n async destroy(closeNewTabsAfterDisconnect?: boolean) {\n if (typeof closeNewTabsAfterDisconnect === 'boolean') {\n await this.page.setDestroyOptions({\n closeTab: closeNewTabsAfterDisconnect,\n });\n }\n await super.destroy();\n }\n}\n"],"names":["__webpack_require__","definition","key","Object","obj","prop","Symbol","sleep","ms","Promise","resolve","setTimeout","debug","getDebug","deserializeBridgeError","error","result","Error","getBridgePageInCliSide","options","host","DefaultBridgeServerHost","port","DefaultBridgeServerPort","server","BridgeServer","undefined","fileChooserEnabled","fileChooserError","fileChooserBridgeMethods","Set","BridgeEvent","syncFileChooserError","String","bridgeCaller","method","timeout","args","response","page","message","proxyPage","Proxy","target","receiver","assert","BridgePageType","commonWebActionsForWebPage","handler","files","mouse","MouseEvent","keyboard","KeyboardEvent","caller","e","url","AgentOverChromeBridge","Agent","tabId","Number","closeNewTabsAfterDisconnect","opts","getBridgeServerHost","originalOnTaskStartTip","tip"],"mappings":"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"}
1
+ {"version":3,"file":"bridge-mode/agent-cli-side.js","sources":["webpack/runtime/define_property_getters","webpack/runtime/has_own_property","webpack/runtime/make_namespace_object","../../../src/bridge-mode/agent-cli-side.ts"],"sourcesContent":["__webpack_require__.d = (exports, definition) => {\n\tfor(var key in definition) {\n if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n }\n }\n};","__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))","// define __esModule on exports\n__webpack_require__.r = (exports) => {\n\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\t}\n\tObject.defineProperty(exports, '__esModule', { value: true });\n};","import { Agent, type AgentOpt } from '@midscene/core/agent';\nimport type { FileChooserHandler } from '@midscene/core/device';\nimport { getDebug } from '@midscene/shared/logger';\nimport { assert } from '@midscene/shared/utils';\nimport { commonWebActionsForWebPage } from '../web-page';\nimport type { KeyboardAction, MouseAction } from '../web-page';\nimport {\n type BridgeConnectTabOptions,\n BridgeEvent,\n BridgePageType,\n DefaultBridgeServerHost,\n DefaultBridgeServerPort,\n KeyboardEvent,\n MouseEvent,\n getBridgeServerHost,\n} from './common';\nimport { BridgeServer } from './io-server';\nimport type { ExtensionBridgePageBrowserSide } from './page-browser-side';\n\ninterface ChromeExtensionPageCliSide extends ExtensionBridgePageBrowserSide {\n showStatusMessage: (message: string) => Promise<void>;\n}\n\ntype BridgeSerializedError = {\n message: string;\n name?: string;\n stack?: string;\n};\n\nconst sleep = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));\n\nconst debug = getDebug('web:bridge:agent-cli-side');\n\nfunction deserializeBridgeError(error: BridgeSerializedError): Error {\n const result = new Error(error.message);\n result.name = error.name || 'Error';\n result.stack = error.stack;\n return result;\n}\n\n// actually, this is a proxy to the page in browser side\nexport const getBridgePageInCliSide = (options?: {\n host?: string;\n port?: number;\n timeout?: number | false;\n closeConflictServer?: boolean;\n}): ChromeExtensionPageCliSide => {\n const host = options?.host || DefaultBridgeServerHost;\n const port = options?.port || DefaultBridgeServerPort;\n const server = new BridgeServer(\n host,\n port,\n undefined,\n undefined,\n options?.closeConflictServer,\n );\n server.listen({\n timeout: options?.timeout,\n });\n\n let fileChooserEnabled = false;\n let fileChooserError: Error | undefined;\n\n const fileChooserBridgeMethods = new Set<string>([\n BridgeEvent.RegisterFileChooserAccept,\n BridgeEvent.ClearFileChooserAccept,\n BridgeEvent.GetFileChooserError,\n ]);\n\n const syncFileChooserError = async () => {\n if (!fileChooserEnabled) return;\n try {\n const error = await server.call<BridgeSerializedError | undefined>(\n BridgeEvent.GetFileChooserError,\n [],\n 5000,\n );\n if (error) {\n fileChooserError = deserializeBridgeError(error);\n }\n } catch (error) {\n fileChooserError =\n error instanceof Error ? error : new Error(String(error));\n }\n };\n\n const bridgeCaller = (method: string, timeout?: number) => {\n return async (...args: any[]) => {\n try {\n const response = await server.call(method, args, timeout);\n if (!fileChooserBridgeMethods.has(method)) {\n await syncFileChooserError();\n }\n return response;\n } catch (error) {\n if (!fileChooserBridgeMethods.has(method)) {\n await syncFileChooserError();\n }\n throw error;\n }\n };\n };\n const page = {\n showStatusMessage: async (message: string) => {\n await server.call(BridgeEvent.UpdateAgentStatus, [message]);\n },\n };\n\n const proxyPage = new Proxy(page, {\n get(target, prop, receiver) {\n assert(typeof prop === 'string', 'prop must be a string');\n\n if (prop === 'toJSON') {\n return () => {\n return {\n interfaceType: BridgePageType,\n };\n };\n }\n\n if (prop === 'interfaceType') {\n return BridgePageType;\n }\n\n if (prop === 'actionSpace') {\n return () => commonWebActionsForWebPage(proxyPage);\n }\n\n if (Object.keys(page).includes(prop)) {\n return page[prop as keyof typeof page];\n }\n\n if (prop === 'registerFileChooserListener') {\n return async (\n handler: (chooser: FileChooserHandler) => Promise<void>,\n ) => {\n fileChooserEnabled = true;\n fileChooserError = undefined;\n try {\n await handler({\n accept: async (files: string[]) => {\n await server.call(BridgeEvent.RegisterFileChooserAccept, [\n files,\n ]);\n },\n });\n } catch (error) {\n fileChooserEnabled = false;\n fileChooserError =\n error instanceof Error ? error : new Error(String(error));\n throw fileChooserError;\n }\n\n return {\n dispose: () => {\n fileChooserEnabled = false;\n server\n .call(BridgeEvent.ClearFileChooserAccept, [], 5000)\n .catch((error) => {\n debug(\n 'failed to clear bridge file chooser accept: %O',\n error,\n );\n });\n },\n getError: async () => {\n await syncFileChooserError();\n return fileChooserError;\n },\n };\n };\n }\n\n if (prop === 'mouse') {\n const mouse: MouseAction = {\n click: bridgeCaller(MouseEvent.Click),\n wheel: bridgeCaller(MouseEvent.Wheel),\n move: bridgeCaller(MouseEvent.Move),\n drag: bridgeCaller(MouseEvent.Drag),\n };\n return mouse;\n }\n\n if (prop === 'keyboard') {\n const keyboard: KeyboardAction = {\n type: bridgeCaller(KeyboardEvent.Type),\n press: bridgeCaller(KeyboardEvent.Press),\n };\n return keyboard;\n }\n\n if (prop === 'destroy') {\n return async (...args: any[]) => {\n try {\n const caller = bridgeCaller('destroy');\n await caller(...args);\n } catch (e) {\n // console.error('error calling destroy', e);\n }\n return server.close();\n };\n }\n\n // Special handling for methods that support timeout in options\n if (prop === 'connectNewTabWithUrl') {\n return async (url: string, options?: BridgeConnectTabOptions) => {\n const timeout = options?.timeout;\n const caller = bridgeCaller(prop, timeout);\n return await caller(url, options);\n };\n }\n\n if (prop === 'connectCurrentTab') {\n return async (options?: BridgeConnectTabOptions) => {\n const timeout = options?.timeout;\n const caller = bridgeCaller(prop, timeout);\n return await caller(options);\n };\n }\n\n return bridgeCaller(prop);\n },\n }) as ChromeExtensionPageCliSide;\n\n return proxyPage;\n};\n\nexport class AgentOverChromeBridge extends Agent<ChromeExtensionPageCliSide> {\n private destroyAfterDisconnectFlag?: boolean;\n\n constructor(\n opts?: AgentOpt & {\n /**\n * Enable remote access to the bridge server.\n * - false (default): Only localhost can connect (most secure)\n * - true: Allow remote machines to connect (binds to 0.0.0.0)\n */\n allowRemoteAccess?: boolean;\n /**\n * Custom host to bind the bridge server to.\n * Overrides allowRemoteAccess if specified.\n */\n host?: string;\n /**\n * Custom port for the bridge server.\n * @default 3766\n */\n port?: number;\n closeNewTabsAfterDisconnect?: boolean;\n serverListeningTimeout?: number | false;\n closeConflictServer?: boolean;\n },\n ) {\n const host = getBridgeServerHost({\n host: opts?.host,\n allowRemoteAccess: opts?.allowRemoteAccess,\n });\n const page = getBridgePageInCliSide({\n host,\n port: opts?.port,\n timeout: opts?.serverListeningTimeout,\n closeConflictServer: opts?.closeConflictServer,\n });\n const originalOnTaskStartTip = opts?.onTaskStartTip;\n super(\n page,\n Object.assign(opts || {}, {\n onTaskStartTip: (tip: string) => {\n this.page.showStatusMessage(tip);\n if (originalOnTaskStartTip) {\n originalOnTaskStartTip?.call(this, tip);\n }\n },\n }),\n );\n this.destroyAfterDisconnectFlag = opts?.closeNewTabsAfterDisconnect;\n }\n\n async setDestroyOptionsAfterConnect() {\n if (this.destroyAfterDisconnectFlag) {\n this.page.setDestroyOptions({\n closeTab: true,\n });\n }\n }\n\n async connectNewTabWithUrl(url: string, options?: BridgeConnectTabOptions) {\n await this.page.connectNewTabWithUrl(url, options);\n await sleep(500);\n await this.setDestroyOptionsAfterConnect();\n }\n\n async getBrowserTabList() {\n return await this.page.getBrowserTabList();\n }\n\n async setActiveTabId(tabId: string) {\n return await this.page.setActiveTabId(Number.parseInt(tabId));\n }\n\n async connectCurrentTab(options?: BridgeConnectTabOptions) {\n await this.page.connectCurrentTab(options);\n await sleep(500);\n await this.setDestroyOptionsAfterConnect();\n }\n\n async destroy(closeNewTabsAfterDisconnect?: boolean) {\n if (typeof closeNewTabsAfterDisconnect === 'boolean') {\n await this.page.setDestroyOptions({\n closeTab: closeNewTabsAfterDisconnect,\n });\n }\n await super.destroy();\n }\n}\n"],"names":["__webpack_require__","definition","key","Object","obj","prop","Symbol","sleep","ms","Promise","resolve","setTimeout","debug","getDebug","deserializeBridgeError","error","result","Error","getBridgePageInCliSide","options","host","DefaultBridgeServerHost","port","DefaultBridgeServerPort","server","BridgeServer","undefined","fileChooserEnabled","fileChooserError","fileChooserBridgeMethods","Set","BridgeEvent","syncFileChooserError","String","bridgeCaller","method","timeout","args","response","page","message","proxyPage","Proxy","target","receiver","assert","BridgePageType","commonWebActionsForWebPage","handler","files","mouse","MouseEvent","keyboard","KeyboardEvent","caller","e","url","AgentOverChromeBridge","Agent","tabId","Number","closeNewTabsAfterDisconnect","opts","getBridgeServerHost","originalOnTaskStartTip","tip"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"bridge-mode/common.js","sources":["webpack/runtime/define_property_getters","webpack/runtime/has_own_property","webpack/runtime/make_namespace_object","../../../src/bridge-mode/common.ts"],"sourcesContent":["__webpack_require__.d = (exports, definition) => {\n\tfor(var key in definition) {\n if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n }\n }\n};","__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))","// define __esModule on exports\n__webpack_require__.r = (exports) => {\n\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\t}\n\tObject.defineProperty(exports, '__esModule', { value: true });\n};","export const DefaultBridgeServerHost = '127.0.0.1';\nexport const DefaultBridgeServerPort = 3766;\nexport const DefaultLocalEndpoint = `http://${DefaultBridgeServerHost}:${DefaultBridgeServerPort}`;\nexport const BridgeCallTimeout = 30000;\n\n/**\n * Get the server host based on configuration options.\n * Priority: explicit host > allowRemoteAccess > default (127.0.0.1)\n */\nexport function getBridgeServerHost(options?: {\n host?: string;\n allowRemoteAccess?: boolean;\n}): string {\n if (options?.host) {\n return options.host;\n }\n if (options?.allowRemoteAccess) {\n return '0.0.0.0';\n }\n return DefaultBridgeServerHost;\n}\n\nexport enum BridgeEvent {\n Call = 'bridge-call',\n CallResponse = 'bridge-call-response',\n UpdateAgentStatus = 'bridge-update-agent-status',\n Message = 'bridge-message',\n Connected = 'bridge-connected',\n Refused = 'bridge-refused',\n ConnectNewTabWithUrl = 'connectNewTabWithUrl',\n ConnectCurrentTab = 'connectCurrentTab',\n GetBrowserTabList = 'getBrowserTabList',\n SetDestroyOptions = 'setDestroyOptions',\n SetActiveTabId = 'setActiveTabId',\n RegisterFileChooserAccept = 'registerFileChooserAccept',\n ClearFileChooserAccept = 'clearFileChooserAccept',\n GetFileChooserError = 'getFileChooserError',\n}\n\nexport const BridgeSignalKill = 'MIDSCENE_BRIDGE_SIGNAL_KILL';\n\nexport interface BridgeConnectTabOptions {\n /**\n * If true, the page will always track the active tab.\n * @default true\n */\n forceSameTabNavigation?: boolean;\n /**\n * Custom timeout for connecting to the tab in milliseconds.\n * @default 30000 (30 seconds)\n */\n timeout?: number;\n /**\n * Whether the blue water-flow animation border and mouse pointer\n * overlay should be shown while controlling the page.\n * @default true\n */\n enableWaterFlowAnimation?: boolean;\n}\n\nexport enum MouseEvent {\n PREFIX = 'mouse.',\n Click = 'mouse.click',\n Wheel = 'mouse.wheel',\n Move = 'mouse.move',\n Drag = 'mouse.drag',\n}\n\nexport enum KeyboardEvent {\n PREFIX = 'keyboard.',\n Type = 'keyboard.type',\n Press = 'keyboard.press',\n}\n\nexport const BridgePageType = 'page-over-chrome-extension-bridge';\n\nexport const BridgeErrorCodeNoClientConnected = 'no-client-connected';\n\nexport interface BridgeCall {\n method: string;\n args: any[];\n response: any;\n callTime: number;\n responseTime: number;\n callback: (error: Error | undefined, response: any) => void;\n error?: Error;\n}\n\nexport interface BridgeCallRequest {\n id: string;\n method: string;\n args: any[];\n}\n\nexport interface BridgeCallResponse {\n id: string;\n response: any;\n error?: any;\n}\n\nexport interface BridgeConnectedEventPayload {\n version: string;\n}\n"],"names":["__webpack_require__","definition","key","Object","obj","prop","Symbol","DefaultBridgeServerHost","DefaultBridgeServerPort","DefaultLocalEndpoint","BridgeCallTimeout","getBridgeServerHost","options","BridgeEvent","BridgeSignalKill","MouseEvent","KeyboardEvent","BridgePageType","BridgeErrorCodeNoClientConnected"],"mappings":";;;IAAAA,oBAAoB,CAAC,GAAG,CAAC,UAASC;QACjC,IAAI,IAAIC,OAAOD,WACR,IAAGD,oBAAoB,CAAC,CAACC,YAAYC,QAAQ,CAACF,oBAAoB,CAAC,CAAC,UAASE,MACzEC,OAAO,cAAc,CAAC,UAASD,KAAK;YAAE,YAAY;YAAM,KAAKD,UAAU,CAACC,IAAI;QAAC;IAGzF;;;ICNAF,oBAAoB,CAAC,GAAG,CAACI,KAAKC,OAAUF,OAAO,SAAS,CAAC,cAAc,CAAC,IAAI,CAACC,KAAKC;;;ICClFL,oBAAoB,CAAC,GAAG,CAAC;QACxB,IAAG,AAAkB,eAAlB,OAAOM,UAA0BA,OAAO,WAAW,EACrDH,OAAO,cAAc,CAAC,UAASG,OAAO,WAAW,EAAE;YAAE,OAAO;QAAS;QAEtEH,OAAO,cAAc,CAAC,UAAS,cAAc;YAAE,OAAO;QAAK;IAC5D;;;;;;;;;;;;;;;;;ACNO,MAAMI,0BAA0B;AAChC,MAAMC,0BAA0B;AAChC,MAAMC,uBAAuB,CAAC,OAAO,EAAEF,wBAAwB,CAAC,EAAEC,yBAAyB;AAC3F,MAAME,oBAAoB;AAM1B,SAASC,oBAAoBC,OAGnC;IACC,IAAIA,SAAS,MACX,OAAOA,QAAQ,IAAI;IAErB,IAAIA,SAAS,mBACX,OAAO;IAET,OAAOL;AACT;AAEO,IAAKM,cAAAA,WAAAA,GAAAA,SAAAA,WAAW;;;;;;;;;;;;;;;WAAXA;;AAiBL,MAAMC,mBAAmB;AAqBzB,IAAKC,aAAAA,WAAAA,GAAAA,SAAAA,UAAU;;;;;;WAAVA;;AAQL,IAAKC,gBAAAA,WAAAA,GAAAA,SAAAA,aAAa;;;;WAAbA;;AAML,MAAMC,iBAAiB;AAEvB,MAAMC,mCAAmC"}
1
+ {"version":3,"file":"bridge-mode/common.js","sources":["webpack/runtime/define_property_getters","webpack/runtime/has_own_property","webpack/runtime/make_namespace_object","../../../src/bridge-mode/common.ts"],"sourcesContent":["__webpack_require__.d = (exports, definition) => {\n\tfor(var key in definition) {\n if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n }\n }\n};","__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))","// define __esModule on exports\n__webpack_require__.r = (exports) => {\n\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\t}\n\tObject.defineProperty(exports, '__esModule', { value: true });\n};","export const DefaultBridgeServerHost = '127.0.0.1';\nexport const DefaultBridgeServerPort = 3766;\nexport const DefaultLocalEndpoint = `http://${DefaultBridgeServerHost}:${DefaultBridgeServerPort}`;\nexport const BridgeCallTimeout = 30000;\n\n/**\n * Get the server host based on configuration options.\n * Priority: explicit host > allowRemoteAccess > default (127.0.0.1)\n */\nexport function getBridgeServerHost(options?: {\n host?: string;\n allowRemoteAccess?: boolean;\n}): string {\n if (options?.host) {\n return options.host;\n }\n if (options?.allowRemoteAccess) {\n return '0.0.0.0';\n }\n return DefaultBridgeServerHost;\n}\n\nexport enum BridgeEvent {\n Call = 'bridge-call',\n CallResponse = 'bridge-call-response',\n UpdateAgentStatus = 'bridge-update-agent-status',\n Message = 'bridge-message',\n Connected = 'bridge-connected',\n Refused = 'bridge-refused',\n ConnectNewTabWithUrl = 'connectNewTabWithUrl',\n ConnectCurrentTab = 'connectCurrentTab',\n GetBrowserTabList = 'getBrowserTabList',\n SetDestroyOptions = 'setDestroyOptions',\n SetActiveTabId = 'setActiveTabId',\n RegisterFileChooserAccept = 'registerFileChooserAccept',\n ClearFileChooserAccept = 'clearFileChooserAccept',\n GetFileChooserError = 'getFileChooserError',\n}\n\nexport const BridgeSignalKill = 'MIDSCENE_BRIDGE_SIGNAL_KILL';\n\nexport interface BridgeConnectTabOptions {\n /**\n * If true, the page will always track the active tab.\n * @default true\n */\n forceSameTabNavigation?: boolean;\n /**\n * Custom timeout for connecting to the tab in milliseconds.\n * @default 30000 (30 seconds)\n */\n timeout?: number;\n}\n\nexport enum MouseEvent {\n PREFIX = 'mouse.',\n Click = 'mouse.click',\n Wheel = 'mouse.wheel',\n Move = 'mouse.move',\n Drag = 'mouse.drag',\n}\n\nexport enum KeyboardEvent {\n PREFIX = 'keyboard.',\n Type = 'keyboard.type',\n Press = 'keyboard.press',\n}\n\nexport const BridgePageType = 'page-over-chrome-extension-bridge';\n\nexport const BridgeErrorCodeNoClientConnected = 'no-client-connected';\n\nexport interface BridgeCall {\n method: string;\n args: any[];\n response: any;\n callTime: number;\n responseTime: number;\n callback: (error: Error | undefined, response: any) => void;\n error?: Error;\n}\n\nexport interface BridgeCallRequest {\n id: string;\n method: string;\n args: any[];\n}\n\nexport interface BridgeCallResponse {\n id: string;\n response: any;\n error?: any;\n}\n\nexport interface BridgeConnectedEventPayload {\n version: string;\n}\n"],"names":["__webpack_require__","definition","key","Object","obj","prop","Symbol","DefaultBridgeServerHost","DefaultBridgeServerPort","DefaultLocalEndpoint","BridgeCallTimeout","getBridgeServerHost","options","BridgeEvent","BridgeSignalKill","MouseEvent","KeyboardEvent","BridgePageType","BridgeErrorCodeNoClientConnected"],"mappings":";;;IAAAA,oBAAoB,CAAC,GAAG,CAAC,UAASC;QACjC,IAAI,IAAIC,OAAOD,WACR,IAAGD,oBAAoB,CAAC,CAACC,YAAYC,QAAQ,CAACF,oBAAoB,CAAC,CAAC,UAASE,MACzEC,OAAO,cAAc,CAAC,UAASD,KAAK;YAAE,YAAY;YAAM,KAAKD,UAAU,CAACC,IAAI;QAAC;IAGzF;;;ICNAF,oBAAoB,CAAC,GAAG,CAACI,KAAKC,OAAUF,OAAO,SAAS,CAAC,cAAc,CAAC,IAAI,CAACC,KAAKC;;;ICClFL,oBAAoB,CAAC,GAAG,CAAC;QACxB,IAAG,AAAkB,eAAlB,OAAOM,UAA0BA,OAAO,WAAW,EACrDH,OAAO,cAAc,CAAC,UAASG,OAAO,WAAW,EAAE;YAAE,OAAO;QAAS;QAEtEH,OAAO,cAAc,CAAC,UAAS,cAAc;YAAE,OAAO;QAAK;IAC5D;;;;;;;;;;;;;;;;;ACNO,MAAMI,0BAA0B;AAChC,MAAMC,0BAA0B;AAChC,MAAMC,uBAAuB,CAAC,OAAO,EAAEF,wBAAwB,CAAC,EAAEC,yBAAyB;AAC3F,MAAME,oBAAoB;AAM1B,SAASC,oBAAoBC,OAGnC;IACC,IAAIA,SAAS,MACX,OAAOA,QAAQ,IAAI;IAErB,IAAIA,SAAS,mBACX,OAAO;IAET,OAAOL;AACT;AAEO,IAAKM,cAAAA,WAAAA,GAAAA,SAAAA,WAAW;;;;;;;;;;;;;;;WAAXA;;AAiBL,MAAMC,mBAAmB;AAezB,IAAKC,aAAAA,WAAAA,GAAAA,SAAAA,UAAU;;;;;;WAAVA;;AAQL,IAAKC,gBAAAA,WAAAA,GAAAA,SAAAA,aAAa;;;;WAAbA;;AAML,MAAMC,iBAAiB;AAEvB,MAAMC,mCAAmC"}
@@ -51,7 +51,7 @@ class BridgeClient {
51
51
  ]
52
52
  } : {},
53
53
  query: {
54
- version: "1.10.7-beta-20260722111246.0"
54
+ version: "1.10.7"
55
55
  }
56
56
  });
57
57
  const timeout = setTimeout(()=>{
@@ -131,7 +131,7 @@ class BridgeServer {
131
131
  (0, shared_utils_namespaceObject.logMsg)('one client connected');
132
132
  this.socket = socket;
133
133
  const clientVersion = socket.handshake.query.version;
134
- (0, shared_utils_namespaceObject.logMsg)(`Bridge connected, cli-side version v1.10.7-beta-20260722111246.0, browser-side version v${clientVersion}`);
134
+ (0, shared_utils_namespaceObject.logMsg)(`Bridge connected, cli-side version v1.10.7, browser-side version v${clientVersion}`);
135
135
  socket.on(external_common_js_namespaceObject.BridgeEvent.CallResponse, (params)=>{
136
136
  const id = params.id;
137
137
  const response = params.response;
@@ -155,7 +155,7 @@ class BridgeServer {
155
155
  setTimeout(()=>{
156
156
  this.onConnect?.();
157
157
  const payload = {
158
- version: "1.10.7-beta-20260722111246.0"
158
+ version: "1.10.7"
159
159
  };
160
160
  socket.emit(external_common_js_namespaceObject.BridgeEvent.Connected, payload);
161
161
  Promise.resolve().then(()=>{