page-agent 0.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"page-agent.js","sources":["../../src/config/constants.ts","../../src/dom/dom_tree/index.js","../../src/dom/index.ts","../../src/dom/getPageInfo.ts","../../src/i18n/locales.ts","../../src/i18n/index.ts","../../src/utils/assert.ts","../../src/utils/bus.ts","../../src/llms/index.ts","../../src/patches/react.ts","../../src/prompts/system_prompt.md?raw","../../src/tools/actions.ts","../../src/tools/index.ts","../../src/utils/index.ts","../../src/ui/UIState.ts","../../src/ui/Panel.ts","../../src/utils/checkDarkMode.ts","../../src/ui/SimulatorMask.ts","../../src/PageAgent.ts"],"sourcesContent":["/**\n * @note Since isTopElement depends on elementFromPoint,\n * it returns null when out of viewport, this feature has no practical use, only differ between -1 and 0\n */\n// export const VIEWPORT_EXPANSION = 100\nexport const VIEWPORT_EXPANSION = -1\n\n// models\n\n// 🥇 GPT-4.1 (best so far)\nexport const DEFAULT_MODEL_NAME: string = 'gpt-41-mini-0414-global' // baseline 🌟\n// export const DEFAULT_MODEL_NAME: string = 'gpt-41-0414-global' // unnecessary\n\n// 🤞 qwen (tool call format often irregular)\n// export const DEFAULT_MODEL_NAME: string = 'qwen-plus-latest' // okay\n// export const DEFAULT_MODEL_NAME: string = 'qwen-turbo-latest' // BAD☠️\n\n// 👍 Anthropic\n// export const DEFAULT_MODEL_NAME: string = 'claude_sonnet4'\n\n// 👌 DeepSeek\n// export const DEFAULT_MODEL_NAME: string = 'DeepSeek-V3-671B'\n// export const DEFAULT_MODEL_NAME: string = 'deepseek-v3.1'\n// export const DEFAULT_MODEL_NAME: string = 'deepseek-v3'\n\n// ☠️❌🙂‍↔️ GPT-5 (slow as hell)\n// export const DEFAULT_MODEL_NAME: string = '_gpt-5-nano-0807-global'\n// export const DEFAULT_MODEL_NAME: string = '_gpt-5-mini-0807-global'\n// export const DEFAULT_MODEL_NAME: string = '_gpt-5-0807-global'\n\n// ❌ Gemini (incapable tool call json schema)\n// @todo need a special client for gemini\n// export const DEFAULT_MODEL_NAME: string = 'gemini-2.5-pro-06-17'\n\n// export const DEFAULT_MODEL_NAME: string = import.meta.env.OPEN_ROUTER_MODEL!\n\n// ak\nexport const DEFAULT_API_KEY: string = 'not-needed'\n// export const DEFAULT_API_KEY: string = import.meta.env.OPEN_ROUTER_KEY!\n\n// base url\nexport const DEFAULT_BASE_URL: string = 'http://localhost:3000/api/agent'\n// export const DEFAULT_BASE_URL: string = import.meta.env.OPEN_ROUTER_BASE_URL!\n\n// internal\n\nexport const MACRO_TOOL_NAME = 'AgentOutput' as const\nexport const LLM_MAX_RETRIES = 2\nexport const MAX_STEPS = 20\n","/**\n * @file port from browser-use\n * @see https://github.com/browser-use/browser-use/commits/main/browser_use/dom/dom_tree/index.js\n * @match 0.5.9 d51b6e73daff7165fdd3e44debd667e7f5f7fdc5\n *\n * search @edit for all the changed lines.\n *\n * @edit export\n * @edit add interactiveBlacklist interactiveWhitelist\n * @edit adjustable opacity\n * @edit direct dom ref\n * @edit @workaround input.checked\n * @edit smaller zIndex for highlight\n * @edit no need for xpath\n * @edit add `extra` field for extra data\n * @edit scrollable element detection\n * @edit add `data-browser-use-ignore` attribute\n * @edit improve `sampleRect`, filter out rects with 0 area\n */\n\nexport default (\n\targs = {\n\t\tdoHighlightElements: true,\n\t\tfocusHighlightIndex: -1,\n\t\tviewportExpansion: 0,\n\t\tdebugMode: false,\n\n\t\t/**\n\t\t * @edit\n\t\t */\n\t\t/** @type {Element[]} */\n\t\tinteractiveBlacklist: [],\n\t\t/** @type {Element[]} */\n\t\tinteractiveWhitelist: [],\n\t\thighlightOpacity: 0.1,\n\t\thighlightLabelOpacity: 0.5,\n\t}\n) => {\n\t/**\n\t * @edit\n\t */\n\tconst { interactiveBlacklist, interactiveWhitelist, highlightOpacity, highlightLabelOpacity } =\n\t\targs\n\n\tconst { doHighlightElements, focusHighlightIndex, viewportExpansion, debugMode } = args\n\tlet highlightIndex = 0 // Reset highlight index\n\n\t/**\n\t * @edit add `extra` field for extra data\n\t */\n\tconst extraData = new WeakMap()\n\tfunction addExtraData(element, data) {\n\t\tif (!element || element.nodeType !== Node.ELEMENT_NODE) return\n\t\textraData.set(element, { ...extraData.get(element), ...data })\n\t}\n\n\t// Add caching mechanisms at the top level\n\tconst DOM_CACHE = {\n\t\tboundingRects: new WeakMap(),\n\t\tclientRects: new WeakMap(),\n\t\tcomputedStyles: new WeakMap(),\n\t\tclearCache: () => {\n\t\t\tDOM_CACHE.boundingRects = new WeakMap()\n\t\t\tDOM_CACHE.clientRects = new WeakMap()\n\t\t\tDOM_CACHE.computedStyles = new WeakMap()\n\t\t},\n\t}\n\n\t/**\n\t * Gets the cached bounding rect for an element.\n\t *\n\t * @param {HTMLElement} element - The element to get the bounding rect for.\n\t * @returns {DOMRect | null} The cached bounding rect, or null if the element is not found.\n\t */\n\tfunction getCachedBoundingRect(element) {\n\t\tif (!element) return null\n\n\t\tif (DOM_CACHE.boundingRects.has(element)) {\n\t\t\treturn DOM_CACHE.boundingRects.get(element)\n\t\t}\n\n\t\tconst rect = element.getBoundingClientRect()\n\n\t\tif (rect) {\n\t\t\tDOM_CACHE.boundingRects.set(element, rect)\n\t\t}\n\t\treturn rect\n\t}\n\n\t/**\n\t * Gets the cached computed style for an element.\n\t *\n\t * @param {HTMLElement} element - The element to get the computed style for.\n\t * @returns {CSSStyleDeclaration | null} The cached computed style, or null if the element is not found.\n\t */\n\tfunction getCachedComputedStyle(element) {\n\t\tif (!element) return null\n\n\t\tif (DOM_CACHE.computedStyles.has(element)) {\n\t\t\treturn DOM_CACHE.computedStyles.get(element)\n\t\t}\n\n\t\tconst style = window.getComputedStyle(element)\n\n\t\tif (style) {\n\t\t\tDOM_CACHE.computedStyles.set(element, style)\n\t\t}\n\t\treturn style\n\t}\n\n\t/**\n\t * Gets the cached client rects for an element.\n\t *\n\t * @param {HTMLElement} element - The element to get the client rects for.\n\t * @returns {DOMRectList | null} The cached client rects, or null if the element is not found.\n\t */\n\tfunction getCachedClientRects(element) {\n\t\tif (!element) return null\n\n\t\tif (DOM_CACHE.clientRects.has(element)) {\n\t\t\treturn DOM_CACHE.clientRects.get(element)\n\t\t}\n\n\t\tconst rects = element.getClientRects()\n\n\t\tif (rects) {\n\t\t\tDOM_CACHE.clientRects.set(element, rects)\n\t\t}\n\t\treturn rects\n\t}\n\n\t/**\n\t * Hash map of DOM nodes indexed by their highlight index.\n\t *\n\t * @type {Object<string, any>}\n\t */\n\tconst DOM_HASH_MAP = {}\n\n\tconst ID = { current: 0 }\n\n\tconst HIGHLIGHT_CONTAINER_ID = 'playwright-highlight-container'\n\n\t// Add a WeakMap cache for XPath strings\n\tconst xpathCache = new WeakMap()\n\n\t// // Initialize once and reuse\n\t// const viewportObserver = new IntersectionObserver(\n\t// (entries) => {\n\t// entries.forEach(entry => {\n\t// elementVisibilityMap.set(entry.target, entry.isIntersecting);\n\t// });\n\t// },\n\t// { rootMargin: `${viewportExpansion}px` }\n\t// );\n\n\t/**\n\t * Highlights an element in the DOM and returns the index of the next element.\n\t *\n\t * @param {HTMLElement} element - The element to highlight.\n\t * @param {number} index - The index of the element.\n\t * @param {HTMLElement | null} parentIframe - The parent iframe node.\n\t * @returns {number} The index of the next element.\n\t */\n\tfunction highlightElement(element, index, parentIframe = null) {\n\t\tif (!element) return index\n\n\t\tconst overlays = []\n\t\t/**\n\t\t * @type {HTMLElement | null}\n\t\t */\n\t\tlet label = null\n\t\tlet labelWidth = 20\n\t\tlet labelHeight = 16\n\t\tlet cleanupFn = null\n\n\t\ttry {\n\t\t\t// Create or get highlight container\n\t\t\tlet container = document.getElementById(HIGHLIGHT_CONTAINER_ID)\n\t\t\tif (!container) {\n\t\t\t\tcontainer = document.createElement('div')\n\t\t\t\tcontainer.id = HIGHLIGHT_CONTAINER_ID\n\t\t\t\tcontainer.style.position = 'fixed'\n\t\t\t\tcontainer.style.pointerEvents = 'none'\n\t\t\t\tcontainer.style.top = '0'\n\t\t\t\tcontainer.style.left = '0'\n\t\t\t\tcontainer.style.width = '100%'\n\t\t\t\tcontainer.style.height = '100%'\n\n\t\t\t\t/**\n\t\t\t\t * @edit smaller zIndex for highlight\n\t\t\t\t */\n\t\t\t\t// Use the maximum valid value in zIndex to ensure the element is not blocked by overlapping elements.\n\t\t\t\t// container.style.zIndex = \"2147483647\";\n\t\t\t\tcontainer.style.zIndex = '2147483640'\n\n\t\t\t\tcontainer.style.backgroundColor = 'transparent'\n\t\t\t\tdocument.body.appendChild(container)\n\t\t\t}\n\n\t\t\t// Get element client rects\n\t\t\tconst rects = element.getClientRects() // Use getClientRects()\n\n\t\t\tif (!rects || rects.length === 0) return index // Exit if no rects\n\n\t\t\t// Generate a color based on the index\n\t\t\tconst colors = [\n\t\t\t\t'#FF0000',\n\t\t\t\t'#00FF00',\n\t\t\t\t'#0000FF',\n\t\t\t\t'#FFA500',\n\t\t\t\t'#800080',\n\t\t\t\t'#008080',\n\t\t\t\t'#FF69B4',\n\t\t\t\t'#4B0082',\n\t\t\t\t'#FF4500',\n\t\t\t\t'#2E8B57',\n\t\t\t\t'#DC143C',\n\t\t\t\t'#4682B4',\n\t\t\t]\n\t\t\tconst colorIndex = index % colors.length\n\t\t\tlet baseColor = colors[colorIndex]\n\n\t\t\t/**\n\t\t\t * @edit adjustable opacity\n\t\t\t */\n\t\t\t// const backgroundColor = baseColor + \"1A\"; // 10% opacity version of the color\n\t\t\tconst backgroundColor =\n\t\t\t\tbaseColor +\n\t\t\t\tMath.floor(highlightOpacity * 255)\n\t\t\t\t\t.toString(16)\n\t\t\t\t\t.padStart(2, '0')\n\t\t\tbaseColor =\n\t\t\t\tbaseColor +\n\t\t\t\tMath.floor(highlightLabelOpacity * 255)\n\t\t\t\t\t.toString(16)\n\t\t\t\t\t.padStart(2, '0')\n\n\t\t\t// Get iframe offset if necessary\n\t\t\tlet iframeOffset = { x: 0, y: 0 }\n\t\t\tif (parentIframe) {\n\t\t\t\tconst iframeRect = parentIframe.getBoundingClientRect() // Keep getBoundingClientRect for iframe offset\n\t\t\t\tiframeOffset.x = iframeRect.left\n\t\t\t\tiframeOffset.y = iframeRect.top\n\t\t\t}\n\n\t\t\t// Create fragment to hold overlay elements\n\t\t\tconst fragment = document.createDocumentFragment()\n\n\t\t\t// Create highlight overlays for each client rect\n\t\t\tfor (const rect of rects) {\n\t\t\t\tif (rect.width === 0 || rect.height === 0) continue // Skip empty rects\n\n\t\t\t\tconst overlay = document.createElement('div')\n\t\t\t\toverlay.style.position = 'fixed'\n\t\t\t\toverlay.style.border = `2px solid ${baseColor}`\n\t\t\t\toverlay.style.backgroundColor = backgroundColor\n\t\t\t\toverlay.style.pointerEvents = 'none'\n\t\t\t\toverlay.style.boxSizing = 'border-box'\n\n\t\t\t\tconst top = rect.top + iframeOffset.y\n\t\t\t\tconst left = rect.left + iframeOffset.x\n\n\t\t\t\toverlay.style.top = `${top}px`\n\t\t\t\toverlay.style.left = `${left}px`\n\t\t\t\toverlay.style.width = `${rect.width}px`\n\t\t\t\toverlay.style.height = `${rect.height}px`\n\n\t\t\t\tfragment.appendChild(overlay)\n\t\t\t\toverlays.push({ element: overlay, initialRect: rect }) // Store overlay and its rect\n\t\t\t}\n\n\t\t\t// Create and position a single label relative to the first rect\n\t\t\tconst firstRect = rects[0]\n\t\t\tlabel = document.createElement('div')\n\t\t\tlabel.className = 'playwright-highlight-label'\n\t\t\tlabel.style.position = 'fixed'\n\t\t\tlabel.style.background = baseColor\n\t\t\tlabel.style.color = 'white'\n\t\t\tlabel.style.padding = '1px 4px'\n\t\t\tlabel.style.borderRadius = '4px'\n\t\t\tlabel.style.fontSize = `${Math.min(12, Math.max(8, firstRect.height / 2))}px`\n\t\t\tlabel.textContent = index.toString()\n\n\t\t\tlabelWidth = label.offsetWidth > 0 ? label.offsetWidth : labelWidth // Update actual width if possible\n\t\t\tlabelHeight = label.offsetHeight > 0 ? label.offsetHeight : labelHeight // Update actual height if possible\n\n\t\t\tconst firstRectTop = firstRect.top + iframeOffset.y\n\t\t\tconst firstRectLeft = firstRect.left + iframeOffset.x\n\n\t\t\tlet labelTop = firstRectTop + 2\n\t\t\tlet labelLeft = firstRectLeft + firstRect.width - labelWidth - 2\n\n\t\t\t// Adjust label position if first rect is too small\n\t\t\tif (firstRect.width < labelWidth + 4 || firstRect.height < labelHeight + 4) {\n\t\t\t\tlabelTop = firstRectTop - labelHeight - 2\n\t\t\t\tlabelLeft = firstRectLeft + firstRect.width - labelWidth // Align with right edge\n\t\t\t\tif (labelLeft < iframeOffset.x) labelLeft = firstRectLeft // Prevent going off-left\n\t\t\t}\n\n\t\t\t// Ensure label stays within viewport bounds slightly better\n\t\t\tlabelTop = Math.max(0, Math.min(labelTop, window.innerHeight - labelHeight))\n\t\t\tlabelLeft = Math.max(0, Math.min(labelLeft, window.innerWidth - labelWidth))\n\n\t\t\tlabel.style.top = `${labelTop}px`\n\t\t\tlabel.style.left = `${labelLeft}px`\n\n\t\t\tfragment.appendChild(label)\n\n\t\t\t// Update positions on scroll/resize\n\t\t\tconst updatePositions = () => {\n\t\t\t\tconst newRects = element.getClientRects() // Get fresh rects\n\t\t\t\tlet newIframeOffset = { x: 0, y: 0 }\n\n\t\t\t\tif (parentIframe) {\n\t\t\t\t\tconst iframeRect = parentIframe.getBoundingClientRect() // Keep getBoundingClientRect for iframe\n\t\t\t\t\tnewIframeOffset.x = iframeRect.left\n\t\t\t\t\tnewIframeOffset.y = iframeRect.top\n\t\t\t\t}\n\n\t\t\t\t// Update each overlay\n\t\t\t\toverlays.forEach((overlayData, i) => {\n\t\t\t\t\tif (i < newRects.length) {\n\t\t\t\t\t\t// Check if rect still exists\n\t\t\t\t\t\tconst newRect = newRects[i]\n\t\t\t\t\t\tconst newTop = newRect.top + newIframeOffset.y\n\t\t\t\t\t\tconst newLeft = newRect.left + newIframeOffset.x\n\n\t\t\t\t\t\toverlayData.element.style.top = `${newTop}px`\n\t\t\t\t\t\toverlayData.element.style.left = `${newLeft}px`\n\t\t\t\t\t\toverlayData.element.style.width = `${newRect.width}px`\n\t\t\t\t\t\toverlayData.element.style.height = `${newRect.height}px`\n\t\t\t\t\t\toverlayData.element.style.display =\n\t\t\t\t\t\t\tnewRect.width === 0 || newRect.height === 0 ? 'none' : 'block'\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// If fewer rects now, hide extra overlays\n\t\t\t\t\t\toverlayData.element.style.display = 'none'\n\t\t\t\t\t}\n\t\t\t\t})\n\n\t\t\t\t// If there are fewer new rects than overlays, hide the extras\n\t\t\t\tif (newRects.length < overlays.length) {\n\t\t\t\t\tfor (let i = newRects.length; i < overlays.length; i++) {\n\t\t\t\t\t\toverlays[i].element.style.display = 'none'\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Update label position based on the first new rect\n\t\t\t\tif (label && newRects.length > 0) {\n\t\t\t\t\tconst firstNewRect = newRects[0]\n\t\t\t\t\tconst firstNewRectTop = firstNewRect.top + newIframeOffset.y\n\t\t\t\t\tconst firstNewRectLeft = firstNewRect.left + newIframeOffset.x\n\n\t\t\t\t\tlet newLabelTop = firstNewRectTop + 2\n\t\t\t\t\tlet newLabelLeft = firstNewRectLeft + firstNewRect.width - labelWidth - 2\n\n\t\t\t\t\tif (firstNewRect.width < labelWidth + 4 || firstNewRect.height < labelHeight + 4) {\n\t\t\t\t\t\tnewLabelTop = firstNewRectTop - labelHeight - 2\n\t\t\t\t\t\tnewLabelLeft = firstNewRectLeft + firstNewRect.width - labelWidth\n\t\t\t\t\t\tif (newLabelLeft < newIframeOffset.x) newLabelLeft = firstNewRectLeft\n\t\t\t\t\t}\n\n\t\t\t\t\t// Ensure label stays within viewport bounds\n\t\t\t\t\tnewLabelTop = Math.max(0, Math.min(newLabelTop, window.innerHeight - labelHeight))\n\t\t\t\t\tnewLabelLeft = Math.max(0, Math.min(newLabelLeft, window.innerWidth - labelWidth))\n\n\t\t\t\t\tlabel.style.top = `${newLabelTop}px`\n\t\t\t\t\tlabel.style.left = `${newLabelLeft}px`\n\t\t\t\t\tlabel.style.display = 'block'\n\t\t\t\t} else if (label) {\n\t\t\t\t\t// Hide label if element has no rects anymore\n\t\t\t\t\tlabel.style.display = 'none'\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst throttleFunction = (func, delay) => {\n\t\t\t\tlet lastCall = 0\n\t\t\t\treturn (...args) => {\n\t\t\t\t\tconst now = performance.now()\n\t\t\t\t\tif (now - lastCall < delay) return\n\t\t\t\t\tlastCall = now\n\t\t\t\t\treturn func(...args)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst throttledUpdatePositions = throttleFunction(updatePositions, 16) // ~60fps\n\t\t\twindow.addEventListener('scroll', throttledUpdatePositions, true)\n\t\t\twindow.addEventListener('resize', throttledUpdatePositions)\n\n\t\t\t// Add cleanup function\n\t\t\tcleanupFn = () => {\n\t\t\t\twindow.removeEventListener('scroll', throttledUpdatePositions, true)\n\t\t\t\twindow.removeEventListener('resize', throttledUpdatePositions)\n\t\t\t\t// Remove overlay elements if needed\n\t\t\t\toverlays.forEach((overlay) => overlay.element.remove())\n\t\t\t\tif (label) label.remove()\n\t\t\t}\n\n\t\t\t// Then add fragment to container in one operation\n\t\t\tcontainer.appendChild(fragment)\n\n\t\t\treturn index + 1\n\t\t} finally {\n\t\t\t// Store cleanup function for later use\n\t\t\tif (cleanupFn) {\n\t\t\t\t// Keep a reference to cleanup functions in a global array\n\t\t\t\t;(window._highlightCleanupFunctions = window._highlightCleanupFunctions || []).push(\n\t\t\t\t\tcleanupFn\n\t\t\t\t)\n\t\t\t}\n\t\t}\n\t}\n\n\t// // Add this function to perform cleanup when needed\n\t// function cleanupHighlights() {\n\t// if (window._highlightCleanupFunctions && window._highlightCleanupFunctions.length) {\n\t// window._highlightCleanupFunctions.forEach(fn => fn());\n\t// window._highlightCleanupFunctions = [];\n\t// }\n\n\t// // Also remove the container\n\t// const container = document.getElementById(HIGHLIGHT_CONTAINER_ID);\n\t// if (container) container.remove();\n\t// }\n\n\t/**\n\t * Gets the position of an element in its parent.\n\t *\n\t * @param {HTMLElement} currentElement - The element to get the position for.\n\t * @returns {number} The position of the element in its parent.\n\t */\n\tfunction getElementPosition(currentElement) {\n\t\tif (!currentElement.parentElement) {\n\t\t\treturn 0 // No parent means no siblings\n\t\t}\n\n\t\tconst tagName = currentElement.nodeName.toLowerCase()\n\n\t\tconst siblings = Array.from(currentElement.parentElement.children).filter(\n\t\t\t(sib) => sib.nodeName.toLowerCase() === tagName\n\t\t)\n\n\t\tif (siblings.length === 1) {\n\t\t\treturn 0 // Only element of its type\n\t\t}\n\n\t\tconst index = siblings.indexOf(currentElement) + 1 // 1-based index\n\t\treturn index\n\t}\n\n\tfunction getXPathTree(element, stopAtBoundary = true) {\n\t\tif (xpathCache.has(element)) return xpathCache.get(element)\n\n\t\tconst segments = []\n\t\tlet currentElement = element\n\n\t\twhile (currentElement && currentElement.nodeType === Node.ELEMENT_NODE) {\n\t\t\t// Stop if we hit a shadow root or iframe\n\t\t\tif (\n\t\t\t\tstopAtBoundary &&\n\t\t\t\t(currentElement.parentNode instanceof ShadowRoot ||\n\t\t\t\t\tcurrentElement.parentNode instanceof HTMLIFrameElement)\n\t\t\t) {\n\t\t\t\tbreak\n\t\t\t}\n\n\t\t\tconst position = getElementPosition(currentElement)\n\t\t\tconst tagName = currentElement.nodeName.toLowerCase()\n\t\t\tconst xpathIndex = position > 0 ? `[${position}]` : ''\n\t\t\tsegments.unshift(`${tagName}${xpathIndex}`)\n\n\t\t\tcurrentElement = currentElement.parentNode\n\t\t}\n\n\t\tconst result = segments.join('/')\n\t\txpathCache.set(element, result)\n\t\treturn result\n\t}\n\n\t/**\n\t * @edit scrollable element detection\n\t * Checks if an element is scrollable. if so, return the scrollable distance on each direction (left right top bottom). if not return null.\n\t * @note distance smaller than 4 will be considered as not scrollable.\n\t * @note only check block elements, not inline elements.\n\t */\n\tfunction isScrollableElement(element) {\n\t\tif (!element || element.nodeType !== Node.ELEMENT_NODE) {\n\t\t\treturn null // Not a valid element\n\t\t}\n\n\t\tconst style = getCachedComputedStyle(element)\n\t\tif (!style) return null\n\n\t\t// Check if the element is a block-level element\n\t\tconst display = style.display\n\t\tif (display === 'inline' || display === 'inline-block') {\n\t\t\treturn null // Not a block-level element\n\t\t}\n\n\t\t// Check overflow properties\n\t\tconst overflowX = style.overflowX\n\t\tconst overflowY = style.overflowY\n\n\t\t// Check scrollable distances\n\t\tconst scrollableX = overflowX === 'auto' || overflowX === 'scroll'\n\t\tconst scrollableY = overflowY === 'auto' || overflowY === 'scroll'\n\n\t\tif (!scrollableX && !scrollableY) {\n\t\t\treturn null // Not scrollable in any direction\n\t\t}\n\n\t\tconst scrollWidth = element.scrollWidth - element.clientWidth\n\t\tconst scrollHeight = element.scrollHeight - element.clientHeight\n\n\t\t// Consider small distances as not scrollable\n\t\tconst threshold = 4\n\n\t\tif (scrollWidth < threshold && scrollHeight < threshold) {\n\t\t\treturn null // Not scrollable\n\t\t}\n\n\t\tif (!scrollableY && scrollWidth < threshold) {\n\t\t\treturn null // Not scrollable horizontally\n\t\t}\n\n\t\tif (!scrollableX && scrollHeight < threshold) {\n\t\t\treturn null // Not scrollable vertically\n\t\t}\n\n\t\tconst distanceToTop = element.scrollTop\n\t\tconst distanceToLeft = element.scrollLeft\n\t\tconst distanceToRight = element.scrollWidth - element.clientWidth - element.scrollLeft\n\t\tconst distanceToBottom = element.scrollHeight - element.clientHeight - element.scrollTop\n\n\t\tconst scrollData = {\n\t\t\ttop: distanceToTop,\n\t\t\tright: distanceToRight,\n\t\t\tbottom: distanceToBottom,\n\t\t\tleft: distanceToLeft,\n\t\t}\n\n\t\t// Store extra data for the element\n\t\taddExtraData(element, {\n\t\t\tscrollable: true,\n\t\t\tscrollData: scrollData,\n\t\t})\n\n\t\treturn scrollData\n\t}\n\n\t/**\n\t * Checks if a text node is visible.\n\t *\n\t * @param {Text} textNode - The text node to check.\n\t * @returns {boolean} Whether the text node is visible.\n\t */\n\tfunction isTextNodeVisible(textNode) {\n\t\ttry {\n\t\t\t// Special case: when viewportExpansion is -1, consider all text nodes as visible\n\t\t\tif (viewportExpansion === -1) {\n\t\t\t\t// Still check parent visibility for basic filtering\n\t\t\t\tconst parentElement = textNode.parentElement\n\t\t\t\tif (!parentElement) return false\n\n\t\t\t\ttry {\n\t\t\t\t\treturn parentElement.checkVisibility({\n\t\t\t\t\t\tcheckOpacity: true,\n\t\t\t\t\t\tcheckVisibilityCSS: true,\n\t\t\t\t\t})\n\t\t\t\t} catch (e) {\n\t\t\t\t\t// Fallback if checkVisibility is not supported\n\t\t\t\t\tconst style = window.getComputedStyle(parentElement)\n\t\t\t\t\treturn style.display !== 'none' && style.visibility !== 'hidden' && style.opacity !== '0'\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst range = document.createRange()\n\t\t\trange.selectNodeContents(textNode)\n\t\t\tconst rects = range.getClientRects() // Use getClientRects for Range\n\n\t\t\tif (!rects || rects.length === 0) {\n\t\t\t\treturn false\n\t\t\t}\n\n\t\t\tlet isAnyRectVisible = false\n\t\t\tlet isAnyRectInViewport = false\n\n\t\t\tfor (const rect of rects) {\n\t\t\t\t// Check size\n\t\t\t\tif (rect.width > 0 && rect.height > 0) {\n\t\t\t\t\tisAnyRectVisible = true\n\n\t\t\t\t\t// Viewport check for this rect\n\t\t\t\t\tif (\n\t\t\t\t\t\t!(\n\t\t\t\t\t\t\trect.bottom < -viewportExpansion ||\n\t\t\t\t\t\t\trect.top > window.innerHeight + viewportExpansion ||\n\t\t\t\t\t\t\trect.right < -viewportExpansion ||\n\t\t\t\t\t\t\trect.left > window.innerWidth + viewportExpansion\n\t\t\t\t\t\t)\n\t\t\t\t\t) {\n\t\t\t\t\t\tisAnyRectInViewport = true\n\t\t\t\t\t\tbreak // Found a visible rect in viewport, no need to check others\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (!isAnyRectVisible || !isAnyRectInViewport) {\n\t\t\t\treturn false\n\t\t\t}\n\n\t\t\t// Check parent visibility\n\t\t\tconst parentElement = textNode.parentElement\n\t\t\tif (!parentElement) return false\n\n\t\t\ttry {\n\t\t\t\treturn parentElement.checkVisibility({\n\t\t\t\t\tcheckOpacity: true,\n\t\t\t\t\tcheckVisibilityCSS: true,\n\t\t\t\t})\n\t\t\t} catch (e) {\n\t\t\t\t// Fallback if checkVisibility is not supported\n\t\t\t\tconst style = window.getComputedStyle(parentElement)\n\t\t\t\treturn style.display !== 'none' && style.visibility !== 'hidden' && style.opacity !== '0'\n\t\t\t}\n\t\t} catch (e) {\n\t\t\tconsole.warn('Error checking text node visibility:', e)\n\t\t\treturn false\n\t\t}\n\t}\n\n\t/**\n\t * Checks if an element is accepted.\n\t *\n\t * @param {HTMLElement} element - The element to check.\n\t * @returns {boolean} Whether the element is accepted.\n\t */\n\tfunction isElementAccepted(element) {\n\t\tif (!element || !element.tagName) return false\n\n\t\t// Always accept body and common container elements\n\t\tconst alwaysAccept = new Set([\n\t\t\t'body',\n\t\t\t'div',\n\t\t\t'main',\n\t\t\t'article',\n\t\t\t'section',\n\t\t\t'nav',\n\t\t\t'header',\n\t\t\t'footer',\n\t\t])\n\t\tconst tagName = element.tagName.toLowerCase()\n\n\t\tif (alwaysAccept.has(tagName)) return true\n\n\t\tconst leafElementDenyList = new Set([\n\t\t\t'svg',\n\t\t\t'script',\n\t\t\t'style',\n\t\t\t'link',\n\t\t\t'meta',\n\t\t\t'noscript',\n\t\t\t'template',\n\t\t])\n\n\t\treturn !leafElementDenyList.has(tagName)\n\t}\n\n\t/**\n\t * Checks if an element is visible.\n\t *\n\t * @param {HTMLElement} element - The element to check.\n\t * @returns {boolean} Whether the element is visible.\n\t */\n\tfunction isElementVisible(element) {\n\t\tconst style = getCachedComputedStyle(element)\n\t\treturn (\n\t\t\telement.offsetWidth > 0 &&\n\t\t\telement.offsetHeight > 0 &&\n\t\t\tstyle?.visibility !== 'hidden' &&\n\t\t\tstyle?.display !== 'none'\n\t\t)\n\t}\n\n\t/**\n\t * Checks if an element is interactive.\n\t *\n\t * lots of comments, and uncommented code - to show the logic of what we already tried\n\t *\n\t * One of the things we tried at the beginning was also to use event listeners, and other fancy class, style stuff -> what actually worked best was just combining most things with computed cursor style :)\n\t *\n\t * @param {HTMLElement} element - The element to check.\n\t */\n\tfunction isInteractiveElement(element) {\n\t\tif (!element || element.nodeType !== Node.ELEMENT_NODE) {\n\t\t\treturn false\n\t\t}\n\n\t\t/**\n\t\t * @edit add interactiveBlacklist interactiveWhitelist\n\t\t */\n\t\tif (interactiveBlacklist.includes(element)) {\n\t\t\treturn false // Skip blacklisted elements\n\t\t}\n\t\tif (interactiveWhitelist.includes(element)) {\n\t\t\treturn true // Skip whitelisted elements\n\t\t}\n\n\t\t// Cache the tagName and style lookups\n\t\tconst tagName = element.tagName.toLowerCase()\n\t\tconst style = getCachedComputedStyle(element)\n\n\t\t// Define interactive cursors\n\t\tconst interactiveCursors = new Set([\n\t\t\t'pointer', // Link/clickable elements\n\t\t\t'move', // Movable elements\n\t\t\t'text', // Text selection\n\t\t\t'grab', // Grabbable elements\n\t\t\t'grabbing', // Currently grabbing\n\t\t\t'cell', // Table cell selection\n\t\t\t'copy', // Copy operation\n\t\t\t'alias', // Alias creation\n\t\t\t'all-scroll', // Scrollable content\n\t\t\t'col-resize', // Column resize\n\t\t\t'context-menu', // Context menu available\n\t\t\t'crosshair', // Precise selection\n\t\t\t'e-resize', // East resize\n\t\t\t'ew-resize', // East-west resize\n\t\t\t'help', // Help available\n\t\t\t'n-resize', // North resize\n\t\t\t'ne-resize', // Northeast resize\n\t\t\t'nesw-resize', // Northeast-southwest resize\n\t\t\t'ns-resize', // North-south resize\n\t\t\t'nw-resize', // Northwest resize\n\t\t\t'nwse-resize', // Northwest-southeast resize\n\t\t\t'row-resize', // Row resize\n\t\t\t's-resize', // South resize\n\t\t\t'se-resize', // Southeast resize\n\t\t\t'sw-resize', // Southwest resize\n\t\t\t'vertical-text', // Vertical text selection\n\t\t\t'w-resize', // West resize\n\t\t\t'zoom-in', // Zoom in\n\t\t\t'zoom-out', // Zoom out\n\t\t])\n\n\t\t// Define non-interactive cursors\n\t\tconst nonInteractiveCursors = new Set([\n\t\t\t'not-allowed', // Action not allowed\n\t\t\t'no-drop', // Drop not allowed\n\t\t\t'wait', // Processing\n\t\t\t'progress', // In progress\n\t\t\t'initial', // Initial value\n\t\t\t'inherit', // Inherited value\n\t\t\t//? Let's just include all potentially clickable elements that are not specifically blocked\n\t\t\t// 'none', // No cursor\n\t\t\t// 'default', // Default cursor\n\t\t\t// 'auto', // Browser default\n\t\t])\n\n\t\t/**\n\t\t * Checks if an element has an interactive pointer.\n\t\t *\n\t\t * @param {HTMLElement} element - The element to check.\n\t\t * @returns {boolean} Whether the element has an interactive pointer.\n\t\t */\n\t\tfunction doesElementHaveInteractivePointer(element) {\n\t\t\tif (element.tagName.toLowerCase() === 'html') return false\n\n\t\t\tif (style?.cursor && interactiveCursors.has(style.cursor)) return true\n\n\t\t\treturn false\n\t\t}\n\n\t\tlet isInteractiveCursor = doesElementHaveInteractivePointer(element)\n\n\t\t// Genius fix for almost all interactive elements\n\t\tif (isInteractiveCursor) {\n\t\t\treturn true\n\t\t}\n\n\t\tconst interactiveElements = new Set([\n\t\t\t'a', // Links\n\t\t\t'button', // Buttons\n\t\t\t'input', // All input types (text, checkbox, radio, etc.)\n\t\t\t'select', // Dropdown menus\n\t\t\t'textarea', // Text areas\n\t\t\t'details', // Expandable details\n\t\t\t'summary', // Summary element (clickable part of details)\n\t\t\t'label', // Form labels (often clickable)\n\t\t\t'option', // Select options\n\t\t\t'optgroup', // Option groups\n\t\t\t'fieldset', // Form fieldsets (can be interactive with legend)\n\t\t\t'legend', // Fieldset legends\n\t\t])\n\n\t\t// Define explicit disable attributes and properties\n\t\tconst explicitDisableTags = new Set([\n\t\t\t'disabled', // Standard disabled attribute\n\t\t\t// 'aria-disabled', // ARIA disabled state\n\t\t\t'readonly', // Read-only state\n\t\t\t// 'aria-readonly', // ARIA read-only state\n\t\t\t// 'aria-hidden', // Hidden from accessibility\n\t\t\t// 'hidden', // Hidden attribute\n\t\t\t// 'inert', // Inert attribute\n\t\t\t// 'aria-inert', // ARIA inert state\n\t\t\t// 'tabindex=\"-1\"', // Removed from tab order\n\t\t\t// 'aria-hidden=\"true\"' // Hidden from screen readers\n\t\t])\n\n\t\t// handle inputs, select, checkbox, radio, textarea, button and make sure they are not cursor style disabled/not-allowed\n\t\tif (interactiveElements.has(tagName)) {\n\t\t\t// Check for non-interactive cursor\n\t\t\tif (style?.cursor && nonInteractiveCursors.has(style.cursor)) {\n\t\t\t\treturn false\n\t\t\t}\n\n\t\t\t// Check for explicit disable attributes\n\t\t\tfor (const disableTag of explicitDisableTags) {\n\t\t\t\tif (\n\t\t\t\t\telement.hasAttribute(disableTag) ||\n\t\t\t\t\telement.getAttribute(disableTag) === 'true' ||\n\t\t\t\t\telement.getAttribute(disableTag) === ''\n\t\t\t\t) {\n\t\t\t\t\treturn false\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Check for disabled property on form elements\n\t\t\tif (element.disabled) {\n\t\t\t\treturn false\n\t\t\t}\n\n\t\t\t// Check for readonly property on form elements\n\t\t\tif (element.readOnly) {\n\t\t\t\treturn false\n\t\t\t}\n\n\t\t\t// Check for inert property\n\t\t\tif (element.inert) {\n\t\t\t\treturn false\n\t\t\t}\n\n\t\t\treturn true\n\t\t}\n\n\t\tconst role = element.getAttribute('role')\n\t\tconst ariaRole = element.getAttribute('aria-role')\n\n\t\t// Check for contenteditable attribute\n\t\tif (element.getAttribute('contenteditable') === 'true' || element.isContentEditable) {\n\t\t\treturn true\n\t\t}\n\n\t\t// Added enhancement to capture dropdown interactive elements\n\t\tif (\n\t\t\telement.classList &&\n\t\t\t(element.classList.contains('button') ||\n\t\t\t\telement.classList.contains('dropdown-toggle') ||\n\t\t\t\telement.getAttribute('data-index') ||\n\t\t\t\telement.getAttribute('data-toggle') === 'dropdown' ||\n\t\t\t\telement.getAttribute('aria-haspopup') === 'true')\n\t\t) {\n\t\t\treturn true\n\t\t}\n\n\t\tconst interactiveRoles = new Set([\n\t\t\t'button', // Directly clickable element\n\t\t\t// 'link', // Clickable link\n\t\t\t'menu', // Menu container (ARIA menus)\n\t\t\t'menubar', // Menu bar container\n\t\t\t'menuitem', // Clickable menu item\n\t\t\t'menuitemradio', // Radio-style menu item (selectable)\n\t\t\t'menuitemcheckbox', // Checkbox-style menu item (toggleable)\n\t\t\t'radio', // Radio button (selectable)\n\t\t\t'checkbox', // Checkbox (toggleable)\n\t\t\t'tab', // Tab (clickable to switch content)\n\t\t\t'switch', // Toggle switch (clickable to change state)\n\t\t\t'slider', // Slider control (draggable)\n\t\t\t'spinbutton', // Number input with up/down controls\n\t\t\t'combobox', // Dropdown with text input\n\t\t\t'searchbox', // Search input field\n\t\t\t'textbox', // Text input field\n\t\t\t'listbox', // Selectable list\n\t\t\t'option', // Selectable option in a list\n\t\t\t'scrollbar', // Scrollable control\n\t\t])\n\n\t\t// Basic role/attribute checks\n\t\tconst hasInteractiveRole =\n\t\t\tinteractiveElements.has(tagName) ||\n\t\t\t(role && interactiveRoles.has(role)) ||\n\t\t\t(ariaRole && interactiveRoles.has(ariaRole))\n\n\t\tif (hasInteractiveRole) return true\n\n\t\t// check whether element has event listeners by window.getEventListeners\n\t\ttry {\n\t\t\tif (typeof getEventListeners === 'function') {\n\t\t\t\tconst listeners = getEventListeners(element)\n\t\t\t\tconst mouseEvents = ['click', 'mousedown', 'mouseup', 'dblclick']\n\t\t\t\tfor (const eventType of mouseEvents) {\n\t\t\t\t\tif (listeners[eventType] && listeners[eventType].length > 0) {\n\t\t\t\t\t\treturn true // Found a mouse interaction listener\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst getEventListenersForNode =\n\t\t\t\telement?.ownerDocument?.defaultView?.getEventListenersForNode ||\n\t\t\t\twindow.getEventListenersForNode\n\t\t\tif (typeof getEventListenersForNode === 'function') {\n\t\t\t\tconst listeners = getEventListenersForNode(element)\n\t\t\t\tconst interactionEvents = [\n\t\t\t\t\t'click',\n\t\t\t\t\t'mousedown',\n\t\t\t\t\t'mouseup',\n\t\t\t\t\t'keydown',\n\t\t\t\t\t'keyup',\n\t\t\t\t\t'submit',\n\t\t\t\t\t'change',\n\t\t\t\t\t'input',\n\t\t\t\t\t'focus',\n\t\t\t\t\t'blur',\n\t\t\t\t]\n\t\t\t\tfor (const eventType of interactionEvents) {\n\t\t\t\t\tfor (const listener of listeners) {\n\t\t\t\t\t\tif (listener.type === eventType) {\n\t\t\t\t\t\t\treturn true // Found a common interaction listener\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t// Fallback: Check common event attributes if getEventListeners is not available (getEventListeners doesn't work in page.evaluate context)\n\t\t\tconst commonMouseAttrs = ['onclick', 'onmousedown', 'onmouseup', 'ondblclick']\n\t\t\tfor (const attr of commonMouseAttrs) {\n\t\t\t\tif (element.hasAttribute(attr) || typeof element[attr] === 'function') {\n\t\t\t\t\treturn true\n\t\t\t\t}\n\t\t\t}\n\t\t} catch (e) {\n\t\t\t// console.warn(`Could not check event listeners for ${element.tagName}:`, e);\n\t\t\t// If checking listeners fails, rely on other checks\n\t\t}\n\n\t\t/**\n\t\t * @edit scrollable element detection\n\t\t */\n\t\tif (isScrollableElement(element)) {\n\t\t\treturn true\n\t\t}\n\n\t\treturn false\n\t}\n\n\t/**\n\t * Checks if an element is the topmost element at its position.\n\t *\n\t * @param {HTMLElement} element - The element to check.\n\t * @returns {boolean} Whether the element is the topmost element at its position.\n\t */\n\tfunction isTopElement(element) {\n\t\t// Special case: when viewportExpansion is -1, consider all elements as \"top\" elements\n\t\tif (viewportExpansion === -1) {\n\t\t\treturn true\n\t\t}\n\n\t\tconst rects = getCachedClientRects(element) // Replace element.getClientRects()\n\n\t\tif (!rects || rects.length === 0) {\n\t\t\treturn false // No geometry, cannot be top\n\t\t}\n\n\t\tlet isAnyRectInViewport = false\n\t\tfor (const rect of rects) {\n\t\t\t// Use the same logic as isInExpandedViewport check\n\t\t\tif (\n\t\t\t\trect.width > 0 &&\n\t\t\t\trect.height > 0 &&\n\t\t\t\t!(\n\t\t\t\t\t// Only check non-empty rects\n\t\t\t\t\t(\n\t\t\t\t\t\trect.bottom < -viewportExpansion ||\n\t\t\t\t\t\trect.top > window.innerHeight + viewportExpansion ||\n\t\t\t\t\t\trect.right < -viewportExpansion ||\n\t\t\t\t\t\trect.left > window.innerWidth + viewportExpansion\n\t\t\t\t\t)\n\t\t\t\t)\n\t\t\t) {\n\t\t\t\tisAnyRectInViewport = true\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\n\t\tif (!isAnyRectInViewport) {\n\t\t\treturn false // All rects are outside the viewport area\n\t\t}\n\n\t\t// Find the correct document context and root element\n\t\tlet doc = element.ownerDocument\n\n\t\t// If we're in an iframe, elements are considered top by default\n\t\tif (doc !== window.document) {\n\t\t\treturn true\n\t\t}\n\n\t\t/**\n\t\t * @edit improve `sampleRect`, filter out rects with 0 area\n\t\t */\n\t\t// find a rect that has width and height as sample\n\t\tlet rect = Array.from(rects).find((r) => r.width > 0 && r.height > 0)\n\t\tif (!rect) {\n\t\t\treturn false // No valid rect found\n\t\t}\n\n\t\t// For shadow DOM, we need to check within its own root context\n\t\tconst shadowRoot = element.getRootNode()\n\t\tif (shadowRoot instanceof ShadowRoot) {\n\t\t\tconst centerX = rect.left + rect.width / 2\n\t\t\tconst centerY = rect.top + rect.height / 2\n\n\t\t\ttry {\n\t\t\t\tconst topEl = shadowRoot.elementFromPoint(centerX, centerY)\n\t\t\t\tif (!topEl) return false\n\n\t\t\t\tlet current = topEl\n\t\t\t\twhile (current && current !== shadowRoot) {\n\t\t\t\t\tif (current === element) return true\n\t\t\t\t\tcurrent = current.parentElement\n\t\t\t\t}\n\t\t\t\treturn false\n\t\t\t} catch (e) {\n\t\t\t\treturn true\n\t\t\t}\n\t\t}\n\n\t\tconst margin = 5\n\n\t\t// For elements in viewport, check if they're topmost. Do the check in the\n\t\t// center of the element and at the corners to ensure we catch more cases.\n\t\tconst checkPoints = [\n\t\t\t// Initially only this was used, but it was not enough\n\t\t\t{ x: rect.left + rect.width / 2, y: rect.top + rect.height / 2 },\n\t\t\t{ x: rect.left + margin, y: rect.top + margin }, // top left\n\t\t\t// { x: rect.right - margin, y: rect.top + margin }, // top right\n\t\t\t// { x: rect.left + margin, y: rect.bottom - margin }, // bottom left\n\t\t\t{ x: rect.right - margin, y: rect.bottom - margin }, // bottom right\n\t\t]\n\n\t\treturn checkPoints.some(({ x, y }) => {\n\t\t\ttry {\n\t\t\t\tconst topEl = document.elementFromPoint(x, y)\n\t\t\t\tif (!topEl) return false\n\n\t\t\t\tlet current = topEl\n\t\t\t\twhile (current && current !== document.documentElement) {\n\t\t\t\t\tif (current === element) return true\n\t\t\t\t\tcurrent = current.parentElement\n\t\t\t\t}\n\t\t\t\treturn false\n\t\t\t} catch (e) {\n\t\t\t\treturn true\n\t\t\t}\n\t\t})\n\t}\n\n\t/**\n\t * Checks if an element is within the expanded viewport.\n\t *\n\t * @param {HTMLElement} element - The element to check.\n\t * @param {number} viewportExpansion - The viewport expansion.\n\t * @returns {boolean} Whether the element is within the expanded viewport.\n\t */\n\tfunction isInExpandedViewport(element, viewportExpansion) {\n\t\tif (viewportExpansion === -1) {\n\t\t\treturn true\n\t\t}\n\n\t\tconst rects = element.getClientRects() // Use getClientRects\n\n\t\tif (!rects || rects.length === 0) {\n\t\t\t// Fallback to getBoundingClientRect if getClientRects is empty,\n\t\t\t// useful for elements like <svg> that might not have client rects but have a bounding box.\n\t\t\tconst boundingRect = getCachedBoundingRect(element)\n\t\t\tif (!boundingRect || boundingRect.width === 0 || boundingRect.height === 0) {\n\t\t\t\treturn false\n\t\t\t}\n\t\t\treturn !(\n\t\t\t\tboundingRect.bottom < -viewportExpansion ||\n\t\t\t\tboundingRect.top > window.innerHeight + viewportExpansion ||\n\t\t\t\tboundingRect.right < -viewportExpansion ||\n\t\t\t\tboundingRect.left > window.innerWidth + viewportExpansion\n\t\t\t)\n\t\t}\n\n\t\t// Check if *any* client rect is within the viewport\n\t\tfor (const rect of rects) {\n\t\t\tif (rect.width === 0 || rect.height === 0) continue // Skip empty rects\n\n\t\t\tif (\n\t\t\t\t!(\n\t\t\t\t\trect.bottom < -viewportExpansion ||\n\t\t\t\t\trect.top > window.innerHeight + viewportExpansion ||\n\t\t\t\t\trect.right < -viewportExpansion ||\n\t\t\t\t\trect.left > window.innerWidth + viewportExpansion\n\t\t\t\t)\n\t\t\t) {\n\t\t\t\treturn true // Found at least one rect in the viewport\n\t\t\t}\n\t\t}\n\n\t\treturn false // No rects were found in the viewport\n\t}\n\n\t// /**\n\t// * Gets the effective scroll of an element.\n\t// *\n\t// * @param {HTMLElement} element - The element to get the effective scroll for.\n\t// * @returns {Object} The effective scroll of the element.\n\t// */\n\t// function getEffectiveScroll(element) {\n\t// let currentEl = element;\n\t// let scrollX = 0;\n\t// let scrollY = 0;\n\n\t// while (currentEl && currentEl !== document.documentElement) {\n\t// if (currentEl.scrollLeft || currentEl.scrollTop) {\n\t// scrollX += currentEl.scrollLeft;\n\t// scrollY += currentEl.scrollTop;\n\t// }\n\t// currentEl = currentEl.parentElement;\n\t// }\n\n\t// scrollX += window.scrollX;\n\t// scrollY += window.scrollY;\n\n\t// return { scrollX, scrollY };\n\t// }\n\n\t/**\n\t * Checks if an element is an interactive candidate.\n\t *\n\t * @param {HTMLElement} element - The element to check.\n\t * @returns {boolean} Whether the element is an interactive candidate.\n\t */\n\tfunction isInteractiveCandidate(element) {\n\t\tif (!element || element.nodeType !== Node.ELEMENT_NODE) return false\n\n\t\tconst tagName = element.tagName.toLowerCase()\n\n\t\t// Fast-path for common interactive elements\n\t\tconst interactiveElements = new Set([\n\t\t\t'a',\n\t\t\t'button',\n\t\t\t'input',\n\t\t\t'select',\n\t\t\t'textarea',\n\t\t\t'details',\n\t\t\t'summary',\n\t\t\t'label',\n\t\t])\n\n\t\tif (interactiveElements.has(tagName)) return true\n\n\t\t// Quick attribute checks without getting full lists\n\t\tconst hasQuickInteractiveAttr =\n\t\t\telement.hasAttribute('onclick') ||\n\t\t\telement.hasAttribute('role') ||\n\t\t\telement.hasAttribute('tabindex') ||\n\t\t\telement.hasAttribute('aria-') ||\n\t\t\telement.hasAttribute('data-action') ||\n\t\t\telement.getAttribute('contenteditable') === 'true'\n\n\t\treturn hasQuickInteractiveAttr\n\t}\n\n\t// --- Define constants for distinct interaction check ---\n\tconst DISTINCT_INTERACTIVE_TAGS = new Set([\n\t\t'a',\n\t\t'button',\n\t\t'input',\n\t\t'select',\n\t\t'textarea',\n\t\t'summary',\n\t\t'details',\n\t\t'label',\n\t\t'option',\n\t])\n\tconst INTERACTIVE_ROLES = new Set([\n\t\t'button',\n\t\t'link',\n\t\t'menuitem',\n\t\t'menuitemradio',\n\t\t'menuitemcheckbox',\n\t\t'radio',\n\t\t'checkbox',\n\t\t'tab',\n\t\t'switch',\n\t\t'slider',\n\t\t'spinbutton',\n\t\t'combobox',\n\t\t'searchbox',\n\t\t'textbox',\n\t\t'listbox',\n\t\t'option',\n\t\t'scrollbar',\n\t])\n\n\t/**\n\t * Heuristically determines if an element should be considered as independently interactive,\n\t * even if it's nested inside another interactive container.\n\t *\n\t * This function helps detect deeply nested actionable elements (e.g., menu items within a button)\n\t * that may not be picked up by strict interactivity checks.\n\t *\n\t * @param {HTMLElement} element - The element to check.\n\t * @returns {boolean} Whether the element is heuristically interactive.\n\t */\n\tfunction isHeuristicallyInteractive(element) {\n\t\tif (!element || element.nodeType !== Node.ELEMENT_NODE) return false\n\n\t\t// Skip non-visible elements early for performance\n\t\tif (!isElementVisible(element)) return false\n\n\t\t// Check for common attributes that often indicate interactivity\n\t\tconst hasInteractiveAttributes =\n\t\t\telement.hasAttribute('role') ||\n\t\t\telement.hasAttribute('tabindex') ||\n\t\t\telement.hasAttribute('onclick') ||\n\t\t\ttypeof element.onclick === 'function'\n\n\t\t// Check for semantic class names suggesting interactivity\n\t\tconst hasInteractiveClass = /\\b(btn|clickable|menu|item|entry|link)\\b/i.test(\n\t\t\telement.className || ''\n\t\t)\n\n\t\t// Determine whether the element is inside a known interactive container\n\t\tconst isInKnownContainer = Boolean(\n\t\t\telement.closest('button,a,[role=\"button\"],.menu,.dropdown,.list,.toolbar')\n\t\t)\n\n\t\t// Ensure the element has at least one visible child (to avoid marking empty wrappers)\n\t\tconst hasVisibleChildren = [...element.children].some(isElementVisible)\n\n\t\t// Avoid highlighting elements whose parent is <body> (top-level wrappers)\n\t\tconst isParentBody = element.parentElement && element.parentElement.isSameNode(document.body)\n\n\t\treturn (\n\t\t\t(isInteractiveElement(element) || hasInteractiveAttributes || hasInteractiveClass) &&\n\t\t\thasVisibleChildren &&\n\t\t\tisInKnownContainer &&\n\t\t\t!isParentBody\n\t\t)\n\t}\n\n\t/**\n\t * Checks if an element likely represents a distinct interaction\n\t * separate from its parent (if the parent is also interactive).\n\t *\n\t * @param {HTMLElement} element - The element to check.\n\t * @returns {boolean} Whether the element is a distinct interaction.\n\t */\n\tfunction isElementDistinctInteraction(element) {\n\t\tif (!element || element.nodeType !== Node.ELEMENT_NODE) {\n\t\t\treturn false\n\t\t}\n\n\t\tconst tagName = element.tagName.toLowerCase()\n\t\tconst role = element.getAttribute('role')\n\n\t\t// Check if it's an iframe - always distinct boundary\n\t\tif (tagName === 'iframe') {\n\t\t\treturn true\n\t\t}\n\n\t\t// Check tag name\n\t\tif (DISTINCT_INTERACTIVE_TAGS.has(tagName)) {\n\t\t\treturn true\n\t\t}\n\t\t// Check interactive roles\n\t\tif (role && INTERACTIVE_ROLES.has(role)) {\n\t\t\treturn true\n\t\t}\n\t\t// Check contenteditable\n\t\tif (element.isContentEditable || element.getAttribute('contenteditable') === 'true') {\n\t\t\treturn true\n\t\t}\n\t\t// Check for common testing/automation attributes\n\t\tif (\n\t\t\telement.hasAttribute('data-testid') ||\n\t\t\telement.hasAttribute('data-cy') ||\n\t\t\telement.hasAttribute('data-test')\n\t\t) {\n\t\t\treturn true\n\t\t}\n\t\t// Check for explicit onclick handler (attribute or property)\n\t\tif (element.hasAttribute('onclick') || typeof element.onclick === 'function') {\n\t\t\treturn true\n\t\t}\n\n\t\t// return false\n\n\t\t// Check for other common interaction event listeners\n\t\ttry {\n\t\t\tconst getEventListenersForNode =\n\t\t\t\telement?.ownerDocument?.defaultView?.getEventListenersForNode ||\n\t\t\t\twindow.getEventListenersForNode\n\t\t\tif (typeof getEventListenersForNode === 'function') {\n\t\t\t\tconst listeners = getEventListenersForNode(element)\n\t\t\t\tconst interactionEvents = [\n\t\t\t\t\t'click',\n\t\t\t\t\t'mousedown',\n\t\t\t\t\t'mouseup',\n\t\t\t\t\t'keydown',\n\t\t\t\t\t'keyup',\n\t\t\t\t\t'submit',\n\t\t\t\t\t'change',\n\t\t\t\t\t'input',\n\t\t\t\t\t'focus',\n\t\t\t\t\t'blur',\n\t\t\t\t]\n\t\t\t\tfor (const eventType of interactionEvents) {\n\t\t\t\t\tfor (const listener of listeners) {\n\t\t\t\t\t\tif (listener.type === eventType) {\n\t\t\t\t\t\t\treturn true // Found a common interaction listener\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t// Fallback: Check common event attributes if getEventListeners is not available (getEventListenersForNode doesn't work in page.evaluate context)\n\t\t\tconst commonEventAttrs = [\n\t\t\t\t'onmousedown',\n\t\t\t\t'onmouseup',\n\t\t\t\t'onkeydown',\n\t\t\t\t'onkeyup',\n\t\t\t\t'onsubmit',\n\t\t\t\t'onchange',\n\t\t\t\t'oninput',\n\t\t\t\t'onfocus',\n\t\t\t\t'onblur',\n\t\t\t]\n\t\t\tif (commonEventAttrs.some((attr) => element.hasAttribute(attr))) {\n\t\t\t\treturn true\n\t\t\t}\n\t\t} catch (e) {\n\t\t\t// console.warn(`Could not check event listeners for ${element.tagName}:`, e);\n\t\t\t// If checking listeners fails, rely on other checks\n\t\t}\n\n\t\t// if the element is not strictly interactive but appears clickable based on heuristic signals\n\t\tif (isHeuristicallyInteractive(element)) {\n\t\t\treturn true\n\t\t}\n\n\t\t// Default to false: if it's interactive but doesn't match above,\n\t\t// assume it triggers the same action as the parent.\n\t\treturn false\n\t}\n\t// --- End distinct interaction check ---\n\n\t/**\n * Handles the logic for deciding whether to highlight an element and performing the highlight.\n * @param {\n {\n tagName: string;\n attributes: Record<string, string>;\n xpath: any;\n children: never[];\n isVisible?: boolean;\n isTopElement?: boolean;\n isInteractive?: boolean;\n isInViewport?: boolean;\n highlightIndex?: number;\n shadowRoot?: boolean;\n }} nodeData - The node data object.\n * @param {HTMLElement} node - The node to highlight.\n * @param {HTMLElement | null} parentIframe - The parent iframe node.\n * @param {boolean} isParentHighlighted - Whether the parent node is highlighted.\n * @returns {boolean} Whether the element was highlighted.\n */\n\tfunction handleHighlighting(nodeData, node, parentIframe, isParentHighlighted) {\n\t\tif (!nodeData.isInteractive) return false // Not interactive, definitely don't highlight\n\n\t\tlet shouldHighlight = false\n\t\tif (!isParentHighlighted) {\n\t\t\t// Parent wasn't highlighted, this interactive node can be highlighted.\n\t\t\tshouldHighlight = true\n\t\t} else {\n\t\t\t// Parent *was* highlighted. Only highlight this node if it represents a distinct interaction.\n\t\t\tif (isElementDistinctInteraction(node)) {\n\t\t\t\tshouldHighlight = true\n\t\t\t} else {\n\t\t\t\t// console.log(`Skipping highlight for ${nodeData.tagName} (parent highlighted)`);\n\t\t\t\tshouldHighlight = false\n\t\t\t}\n\t\t}\n\n\t\tif (shouldHighlight) {\n\t\t\t// Check viewport status before assigning index and highlighting\n\t\t\tnodeData.isInViewport = isInExpandedViewport(node, viewportExpansion)\n\n\t\t\t// When viewportExpansion is -1, all interactive elements should get a highlight index\n\t\t\t// regardless of viewport status\n\t\t\tif (nodeData.isInViewport || viewportExpansion === -1) {\n\t\t\t\tnodeData.highlightIndex = highlightIndex++\n\n\t\t\t\tif (doHighlightElements) {\n\t\t\t\t\tif (focusHighlightIndex >= 0) {\n\t\t\t\t\t\tif (focusHighlightIndex === nodeData.highlightIndex) {\n\t\t\t\t\t\t\thighlightElement(node, nodeData.highlightIndex, parentIframe)\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\thighlightElement(node, nodeData.highlightIndex, parentIframe)\n\t\t\t\t\t}\n\t\t\t\t\treturn true // Successfully highlighted\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// console.log(`Skipping highlight for ${nodeData.tagName} (outside viewport)`);\n\t\t\t}\n\t\t}\n\n\t\treturn false // Did not highlight\n\t}\n\n\t/**\n\t * Creates a node data object for a given node and its descendants.\n\t *\n\t * @param {HTMLElement} node - The node to process.\n\t * @param {HTMLElement | null} parentIframe - The parent iframe node.\n\t * @param {boolean} isParentHighlighted - Whether the parent node is highlighted.\n\t * @returns {string | null} The ID of the node data object, or null if the node is not processed.\n\t */\n\tfunction buildDomTree(node, parentIframe = null, isParentHighlighted = false) {\n\t\t// Fast rejection checks first\n\t\tif (\n\t\t\t!node ||\n\t\t\tnode.id === HIGHLIGHT_CONTAINER_ID ||\n\t\t\t(node.nodeType !== Node.ELEMENT_NODE && node.nodeType !== Node.TEXT_NODE)\n\t\t) {\n\t\t\treturn null\n\t\t}\n\n\t\tif (!node || node.id === HIGHLIGHT_CONTAINER_ID) {\n\t\t\treturn null\n\t\t}\n\n\t\t/**\n\t\t * @edit add `data-browser-use-ignore` attribute\n\t\t */\n\t\tif (node.dataset?.browserUseIgnore === 'true') {\n\t\t\treturn true // Skip this node and its children\n\t\t}\n\n\t\t// Special handling for root node (body)\n\t\tif (node === document.body) {\n\t\t\tconst nodeData = {\n\t\t\t\ttagName: 'body',\n\t\t\t\tattributes: {},\n\t\t\t\txpath: '/body',\n\t\t\t\tchildren: [],\n\t\t\t}\n\n\t\t\t// Process children of body\n\t\t\tfor (const child of node.childNodes) {\n\t\t\t\tconst domElement = buildDomTree(child, parentIframe, false) // Body's children have no highlighted parent initially\n\t\t\t\tif (domElement) nodeData.children.push(domElement)\n\t\t\t}\n\n\t\t\tconst id = `${ID.current++}`\n\t\t\tDOM_HASH_MAP[id] = nodeData\n\t\t\treturn id\n\t\t}\n\n\t\t// Early bailout for non-element nodes except text\n\t\tif (node.nodeType !== Node.ELEMENT_NODE && node.nodeType !== Node.TEXT_NODE) {\n\t\t\treturn null\n\t\t}\n\n\t\t// Process text nodes\n\t\tif (node.nodeType === Node.TEXT_NODE) {\n\t\t\tconst textContent = node.textContent?.trim()\n\t\t\tif (!textContent) {\n\t\t\t\treturn null\n\t\t\t}\n\n\t\t\t// Only check visibility for text nodes that might be visible\n\t\t\tconst parentElement = node.parentElement\n\t\t\tif (!parentElement || parentElement.tagName.toLowerCase() === 'script') {\n\t\t\t\treturn null\n\t\t\t}\n\n\t\t\tconst id = `${ID.current++}`\n\t\t\tDOM_HASH_MAP[id] = {\n\t\t\t\ttype: 'TEXT_NODE',\n\t\t\t\ttext: textContent,\n\t\t\t\tisVisible: isTextNodeVisible(node),\n\t\t\t}\n\t\t\treturn id\n\t\t}\n\n\t\t// Quick checks for element nodes\n\t\tif (node.nodeType === Node.ELEMENT_NODE && !isElementAccepted(node)) {\n\t\t\treturn null\n\t\t}\n\n\t\t// Early viewport check - only filter out elements clearly outside viewport\n\t\t// The getBoundingClientRect() of the Shadow DOM host element may return width/height = 0\n\t\tif (viewportExpansion !== -1 && !node.shadowRoot) {\n\t\t\tconst rect = getCachedBoundingRect(node) // Keep for initial quick check\n\t\t\tconst style = getCachedComputedStyle(node)\n\n\t\t\t// Skip viewport check for fixed/sticky elements as they may appear anywhere\n\t\t\tconst isFixedOrSticky = style && (style.position === 'fixed' || style.position === 'sticky')\n\n\t\t\t// Check if element has actual dimensions using offsetWidth/Height (quick check)\n\t\t\tconst hasSize = node.offsetWidth > 0 || node.offsetHeight > 0\n\n\t\t\t// Use getBoundingClientRect for the quick OUTSIDE check.\n\t\t\t// isInExpandedViewport will do the more accurate check later if needed.\n\t\t\tif (\n\t\t\t\t!rect ||\n\t\t\t\t(!isFixedOrSticky &&\n\t\t\t\t\t!hasSize &&\n\t\t\t\t\t(rect.bottom < -viewportExpansion ||\n\t\t\t\t\t\trect.top > window.innerHeight + viewportExpansion ||\n\t\t\t\t\t\trect.right < -viewportExpansion ||\n\t\t\t\t\t\trect.left > window.innerWidth + viewportExpansion))\n\t\t\t) {\n\t\t\t\t// console.log(\"Skipping node outside viewport (quick check):\", node.tagName, rect);\n\t\t\t\treturn null\n\t\t\t}\n\t\t}\n\n\t\t/**\n * @type {\n {\n tagName: string;\n attributes: Record<string, string | null>;\n xpath: any;\n children: never[];\n isVisible?: boolean;\n isTopElement?: boolean;\n isInteractive?: boolean;\n isInViewport?: boolean;\n highlightIndex?: number;\n shadowRoot?: boolean;\n }\n } nodeData - The node data object.\n */\n\t\tconst nodeData = {\n\t\t\ttagName: node.tagName.toLowerCase(),\n\t\t\tattributes: {},\n\n\t\t\t/**\n\t\t\t * @edit no need for xpath\n\t\t\t */\n\t\t\t// xpath: getXPathTree(node, true),\n\n\t\t\tchildren: [],\n\t\t}\n\n\t\t// Get attributes for interactive elements or potential text containers\n\t\tif (\n\t\t\tisInteractiveCandidate(node) ||\n\t\t\tnode.tagName.toLowerCase() === 'iframe' ||\n\t\t\tnode.tagName.toLowerCase() === 'body'\n\t\t) {\n\t\t\tconst attributeNames = node.getAttributeNames?.() || []\n\t\t\tfor (const name of attributeNames) {\n\t\t\t\tconst value = node.getAttribute(name)\n\t\t\t\tnodeData.attributes[name] = value\n\t\t\t}\n\n\t\t\t/**\n\t\t\t * @edit @workaround input.checked\n\t\t\t */\n\t\t\tif (\n\t\t\t\tnode.tagName.toLowerCase() === 'input' &&\n\t\t\t\t(node.type === 'checkbox' || node.type === 'radio')\n\t\t\t) {\n\t\t\t\tnodeData.attributes.checked = node.checked ? 'true' : 'false' // Store as string for consistency\n\t\t\t}\n\t\t}\n\n\t\tlet nodeWasHighlighted = false\n\t\t// Perform visibility, interactivity, and highlighting checks\n\t\tif (node.nodeType === Node.ELEMENT_NODE) {\n\t\t\tnodeData.isVisible = isElementVisible(node) // isElementVisible uses offsetWidth/Height, which is fine\n\t\t\tif (nodeData.isVisible) {\n\t\t\t\tnodeData.isTopElement = isTopElement(node)\n\n\t\t\t\t// Special handling for ARIA menu containers - check interactivity even if not top element\n\t\t\t\tconst role = node.getAttribute('role')\n\t\t\t\tconst isMenuContainer = role === 'menu' || role === 'menubar' || role === 'listbox'\n\n\t\t\t\tif (nodeData.isTopElement || isMenuContainer) {\n\t\t\t\t\tnodeData.isInteractive = isInteractiveElement(node)\n\t\t\t\t\t// Call the dedicated highlighting function\n\t\t\t\t\tnodeWasHighlighted = handleHighlighting(nodeData, node, parentIframe, isParentHighlighted)\n\n\t\t\t\t\t/**\n\t\t\t\t\t * @edit direct dom ref\n\t\t\t\t\t */\n\t\t\t\t\tnodeData.ref = node\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Process children, with special handling for iframes and rich text editors\n\t\tif (node.tagName) {\n\t\t\tconst tagName = node.tagName.toLowerCase()\n\n\t\t\t// Handle iframes\n\t\t\tif (tagName === 'iframe') {\n\t\t\t\ttry {\n\t\t\t\t\tconst iframeDoc = node.contentDocument || node.contentWindow?.document\n\t\t\t\t\tif (iframeDoc) {\n\t\t\t\t\t\tfor (const child of iframeDoc.childNodes) {\n\t\t\t\t\t\t\tconst domElement = buildDomTree(child, node, false)\n\t\t\t\t\t\t\tif (domElement) nodeData.children.push(domElement)\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} catch (e) {\n\t\t\t\t\tconsole.warn('Unable to access iframe:', e)\n\t\t\t\t}\n\t\t\t}\n\t\t\t// Handle rich text editors and contenteditable elements\n\t\t\telse if (\n\t\t\t\tnode.isContentEditable ||\n\t\t\t\tnode.getAttribute('contenteditable') === 'true' ||\n\t\t\t\tnode.id === 'tinymce' ||\n\t\t\t\tnode.classList.contains('mce-content-body') ||\n\t\t\t\t(tagName === 'body' && node.getAttribute('data-id')?.startsWith('mce_'))\n\t\t\t) {\n\t\t\t\t// Process all child nodes to capture formatted text\n\t\t\t\tfor (const child of node.childNodes) {\n\t\t\t\t\tconst domElement = buildDomTree(child, parentIframe, nodeWasHighlighted)\n\t\t\t\t\tif (domElement) nodeData.children.push(domElement)\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// Handle shadow DOM\n\t\t\t\tif (node.shadowRoot) {\n\t\t\t\t\tnodeData.shadowRoot = true\n\t\t\t\t\tfor (const child of node.shadowRoot.childNodes) {\n\t\t\t\t\t\tconst domElement = buildDomTree(child, parentIframe, nodeWasHighlighted)\n\t\t\t\t\t\tif (domElement) nodeData.children.push(domElement)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t// Handle regular elements\n\t\t\t\tfor (const child of node.childNodes) {\n\t\t\t\t\t// Pass the highlighted status of the *current* node to its children\n\t\t\t\t\tconst passHighlightStatusToChild = nodeWasHighlighted || isParentHighlighted\n\t\t\t\t\tconst domElement = buildDomTree(child, parentIframe, passHighlightStatusToChild)\n\t\t\t\t\tif (domElement) nodeData.children.push(domElement)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Skip empty anchor tags only if they have no dimensions and no children\n\t\tif (nodeData.tagName === 'a' && nodeData.children.length === 0 && !nodeData.attributes.href) {\n\t\t\t// Check if the anchor has actual dimensions\n\t\t\tconst rect = getCachedBoundingRect(node)\n\t\t\tconst hasSize =\n\t\t\t\t(rect && rect.width > 0 && rect.height > 0) || node.offsetWidth > 0 || node.offsetHeight > 0\n\n\t\t\tif (!hasSize) {\n\t\t\t\treturn null\n\t\t\t}\n\t\t}\n\n\t\t/**\n\t\t * @edit add `extra` field for extra data\n\t\t */\n\t\tnodeData.extra = extraData.get(node) || null\n\n\t\tconst id = `${ID.current++}`\n\t\tDOM_HASH_MAP[id] = nodeData\n\t\treturn id\n\t}\n\n\tconst rootId = buildDomTree(document.body)\n\n\t// Clear the cache before starting\n\tDOM_CACHE.clearCache()\n\n\treturn { rootId, map: DOM_HASH_MAP }\n}\n","import { VIEWPORT_EXPANSION } from '@/config/constants'\nimport domTree from '@/dom/dom_tree/index'\nimport {\n\tElementDomNode,\n\tFlatDomTree,\n\tInteractiveElementDomNode,\n\tTextDomNode,\n} from '@/dom/dom_tree/type'\n\nexport interface DomConfig {\n\tinteractiveBlacklist?: (Element | (() => Element))[]\n\tinteractiveWhitelist?: (Element | (() => Element))[]\n\tinclude_attributes?: string[]\n\thighlightOpacity?: number\n\thighlightLabelOpacity?: number\n}\n\n/**\n * 用于检测可交互元素是否是新出现的。\n */\nconst newElementsCache = new WeakMap<HTMLElement, string>()\n\nexport function getFlatTree(config: DomConfig): FlatDomTree {\n\tconst interactiveBlacklist = [] as Element[]\n\tfor (const item of config.interactiveBlacklist || []) {\n\t\tif (typeof item === 'function') {\n\t\t\tinteractiveBlacklist.push(item())\n\t\t} else {\n\t\t\tinteractiveBlacklist.push(item)\n\t\t}\n\t}\n\n\tconst interactiveWhitelist = [] as Element[]\n\tfor (const item of config.interactiveWhitelist || []) {\n\t\tif (typeof item === 'function') {\n\t\t\tinteractiveWhitelist.push(item())\n\t\t} else {\n\t\t\tinteractiveWhitelist.push(item)\n\t\t}\n\t}\n\n\tconst elements = domTree({\n\t\tdoHighlightElements: true,\n\t\tdebugMode: true,\n\t\tfocusHighlightIndex: -1,\n\t\tviewportExpansion: VIEWPORT_EXPANSION,\n\t\tinteractiveBlacklist,\n\t\tinteractiveWhitelist,\n\t\thighlightOpacity: config.highlightOpacity ?? 0.0,\n\t\thighlightLabelOpacity: config.highlightLabelOpacity ?? 0.1,\n\t}) as FlatDomTree\n\n\tconst currentUrl = window.location.href\n\n\t/**\n\t * 标记新出现的元素\n\t * @todo browser-use 使用 hash(位置,属性等信息) 来判断是否同一个元素,\n\t * 能够解决 1. 元素被删除后重新添加 2. 页面卸载 等问题。\n\t * 这里先简单做.\n\t */\n\tfor (const nodeId in elements.map) {\n\t\tconst node = elements.map[nodeId]\n\t\tif (node.isInteractive && node.ref) {\n\t\t\tconst ref = node.ref as HTMLElement\n\t\t\t// @note 这样太严格,元素是可以跨页面存在的\n\t\t\t// if (newElementsCache.get(ref) !== currentUrl) {\n\t\t\tif (!newElementsCache.has(ref)) {\n\t\t\t\tnewElementsCache.set(ref, currentUrl)\n\t\t\t\tnode.isNew = true\n\t\t\t}\n\t\t}\n\t}\n\n\treturn elements\n}\n\n/**\n * elementsToString 内部使用的类型\n */\ninterface TreeNode {\n\ttype: 'text' | 'element'\n\tparent: TreeNode | null\n\tchildren: TreeNode[]\n\tisVisible: boolean\n\t// Text node properties\n\ttext?: string\n\t// Element node properties\n\ttagName?: string\n\tattributes?: Record<string, string>\n\tisInteractive?: boolean\n\tisTopElement?: boolean\n\tisNew?: boolean\n\thighlightIndex?: number\n\textra?: Record<string, any>\n}\n\n/**\n * 对应 python 中的 views::clickable_elements_to_string,\n * 将 dom 信息处理成适合 llm 阅读的文本格式\n * @形如\n * ``` text\n * [0]<a aria-label=page-agent.js 首页 />\n * [1]<div >P />\n * [2]<div >page-agent.js\n * UI Agent in your webpage />\n * [3]<a >文档 />\n * [4]<a aria-label=查看源码(在新窗口打开)>源码 />\n * UI Agent in your webpage\n * 用户输入需求,AI 理解页面并自动操作。\n * [5]<a role=button>快速开始 />\n * [6]<a role=button>查看文档 />\n * 无需后端\n * ```\n * 其中可交互元素用序号标出,提示llm可以用序号操作。\n * 缩进代表父子关系。\n * 普通文本则直接列出来。\n *\n * @todo 数据脱敏过滤器\n */\nexport function flatTreeToString(flatTree: FlatDomTree, include_attributes?: string[]): string {\n\tconst DEFAULT_INCLUDE_ATTRIBUTES = [\n\t\t'title',\n\t\t'type',\n\t\t'checked',\n\t\t'name',\n\t\t'role',\n\t\t'value',\n\t\t'placeholder',\n\t\t'data-date-format',\n\t\t'alt',\n\t\t'aria-label',\n\t\t'aria-expanded',\n\t\t'data-state',\n\t\t'aria-checked',\n\n\t\t// @edit added for better form handling\n\t\t'id',\n\t\t'for',\n\n\t\t// for jump check\n\t\t'target',\n\n\t\t// absolute 定位的下拉菜单\n\t\t'aria-haspopup',\n\t\t'aria-controls',\n\t\t'aria-owns',\n\t]\n\n\tconst includeAttrs = [...(include_attributes || []), ...DEFAULT_INCLUDE_ATTRIBUTES]\n\n\t// Helper function to cap text length\n\tconst capTextLength = (text: string, maxLength: number): string => {\n\t\tif (text.length > maxLength) {\n\t\t\treturn text.substring(0, maxLength) + '...'\n\t\t}\n\t\treturn text\n\t}\n\n\t// Build tree structure from flat map\n\tconst buildTreeNode = (nodeId: string): TreeNode | null => {\n\t\tconst node = flatTree.map[nodeId]\n\t\tif (!node) return null\n\n\t\tif (node.type === 'TEXT_NODE') {\n\t\t\tconst textNode = node as TextDomNode\n\t\t\treturn {\n\t\t\t\ttype: 'text',\n\t\t\t\ttext: textNode.text,\n\t\t\t\tisVisible: textNode.isVisible,\n\t\t\t\tparent: null,\n\t\t\t\tchildren: [],\n\t\t\t}\n\t\t} else {\n\t\t\tconst elementNode = node as ElementDomNode\n\t\t\tconst children: TreeNode[] = []\n\n\t\t\tif (elementNode.children) {\n\t\t\t\tfor (const childId of elementNode.children) {\n\t\t\t\t\tconst child = buildTreeNode(childId)\n\t\t\t\t\tif (child) {\n\t\t\t\t\t\tchild.parent = null // Will be set later\n\t\t\t\t\t\tchildren.push(child)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\ttype: 'element',\n\t\t\t\ttagName: elementNode.tagName,\n\t\t\t\tattributes: elementNode.attributes ?? {},\n\t\t\t\tisVisible: elementNode.isVisible ?? false,\n\t\t\t\tisInteractive: elementNode.isInteractive ?? false,\n\t\t\t\tisTopElement: elementNode.isTopElement ?? false,\n\t\t\t\tisNew: elementNode.isNew ?? false,\n\t\t\t\thighlightIndex: elementNode.highlightIndex,\n\t\t\t\tparent: null,\n\t\t\t\tchildren,\n\t\t\t\textra: elementNode.extra ?? {},\n\t\t\t}\n\t\t}\n\t}\n\n\t// Set parent references\n\tconst setParentReferences = (node: TreeNode, parent: TreeNode | null = null) => {\n\t\tnode.parent = parent\n\t\tfor (const child of node.children) {\n\t\t\tsetParentReferences(child, node)\n\t\t}\n\t}\n\n\t// Build root node\n\tconst rootNode = buildTreeNode(flatTree.rootId)\n\tif (!rootNode) return ''\n\n\tsetParentReferences(rootNode)\n\n\t// Helper to check if text node has parent with highlight index\n\tconst hasParentWithHighlightIndex = (node: TreeNode): boolean => {\n\t\tlet current = node.parent\n\t\twhile (current) {\n\t\t\tif (current.type === 'element' && current.highlightIndex !== undefined) {\n\t\t\t\treturn true\n\t\t\t}\n\t\t\tcurrent = current.parent\n\t\t}\n\t\treturn false\n\t}\n\n\t// Helper to check if parent is top element\n\t// const isParentTopElement = (node: TreeNode): boolean => {\n\t// \treturn node.parent?.type === 'element' && node.parent.isTopElement === true\n\t// }\n\n\t// Main processing function\n\tconst processNode = (node: TreeNode, depth: number, result: string[]): void => {\n\t\tlet nextDepth = depth\n\t\tconst depthStr = '\\t'.repeat(depth)\n\n\t\tif (node.type === 'element') {\n\t\t\t// Add element with highlight_index\n\t\t\tif (node.highlightIndex !== undefined) {\n\t\t\t\tnextDepth += 1\n\n\t\t\t\tconst text = getAllTextTillNextClickableElement(node)\n\t\t\t\tlet attributesHtmlStr = ''\n\n\t\t\t\tif (includeAttrs.length > 0 && node.attributes) {\n\t\t\t\t\tconst attributesToInclude: Record<string, string> = {}\n\n\t\t\t\t\t// Filter attributes\n\t\t\t\t\tfor (const key of includeAttrs) {\n\t\t\t\t\t\tconst value = node.attributes[key]\n\t\t\t\t\t\tif (value && value.trim() !== '') {\n\t\t\t\t\t\t\tattributesToInclude[key] = value.trim()\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Remove duplicate values (for attributes longer than 5 chars)\n\t\t\t\t\tconst orderedKeys = includeAttrs.filter((key) => key in attributesToInclude)\n\t\t\t\t\tif (orderedKeys.length > 1) {\n\t\t\t\t\t\tconst keysToRemove = new Set<string>()\n\t\t\t\t\t\tconst seenValues: Record<string, string> = {}\n\n\t\t\t\t\t\tfor (const key of orderedKeys) {\n\t\t\t\t\t\t\tconst value = attributesToInclude[key]\n\t\t\t\t\t\t\tif (value.length > 5) {\n\t\t\t\t\t\t\t\tif (value in seenValues) {\n\t\t\t\t\t\t\t\t\tkeysToRemove.add(key)\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tseenValues[value] = key\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tfor (const key of keysToRemove) {\n\t\t\t\t\t\t\tdelete attributesToInclude[key]\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Remove role if it matches tagName\n\t\t\t\t\tif (attributesToInclude.role === node.tagName) {\n\t\t\t\t\t\tdelete attributesToInclude.role\n\t\t\t\t\t}\n\n\t\t\t\t\t// Remove attributes that duplicate text content\n\t\t\t\t\tconst attrsToRemoveIfTextMatches = ['aria-label', 'placeholder', 'title']\n\t\t\t\t\tfor (const attr of attrsToRemoveIfTextMatches) {\n\t\t\t\t\t\tif (\n\t\t\t\t\t\t\tattributesToInclude[attr] &&\n\t\t\t\t\t\t\tattributesToInclude[attr].toLowerCase().trim() === text.toLowerCase().trim()\n\t\t\t\t\t\t) {\n\t\t\t\t\t\t\tdelete attributesToInclude[attr]\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif (Object.keys(attributesToInclude).length > 0) {\n\t\t\t\t\t\tattributesHtmlStr = Object.entries(attributesToInclude)\n\t\t\t\t\t\t\t.map(([key, value]) => `${key}=${capTextLength(value, 20)}`)\n\t\t\t\t\t\t\t.join(' ')\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Build the line\n\t\t\t\tconst highlightIndicator = node.isNew\n\t\t\t\t\t? `*[${node.highlightIndex}]`\n\t\t\t\t\t: `[${node.highlightIndex}]`\n\t\t\t\tlet line = `${depthStr}${highlightIndicator}<${node.tagName ?? ''}`\n\n\t\t\t\tif (attributesHtmlStr) {\n\t\t\t\t\tline += ` ${attributesHtmlStr}`\n\t\t\t\t}\n\n\t\t\t\t/**\n\t\t\t\t * @edit scrollable 数据\n\t\t\t\t */\n\t\t\t\tif (node.extra) {\n\t\t\t\t\tif (node.extra.scrollable) {\n\t\t\t\t\t\tlet scrollDataText = ''\n\t\t\t\t\t\tif (node.extra.scrollData?.left)\n\t\t\t\t\t\t\tscrollDataText += `left=${node.extra.scrollData.left}, `\n\t\t\t\t\t\tif (node.extra.scrollData?.top) scrollDataText += `top=${node.extra.scrollData.top}, `\n\t\t\t\t\t\tif (node.extra.scrollData?.right)\n\t\t\t\t\t\t\tscrollDataText += `right=${node.extra.scrollData.right}, `\n\t\t\t\t\t\tif (node.extra.scrollData?.bottom)\n\t\t\t\t\t\t\tscrollDataText += `bottom=${node.extra.scrollData.bottom}`\n\n\t\t\t\t\t\tline += ` data-scrollable=\"${scrollDataText}\"`\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (text) {\n\t\t\t\t\tconst trimmedText = text.trim()\n\t\t\t\t\tif (!attributesHtmlStr) {\n\t\t\t\t\t\tline += ' '\n\t\t\t\t\t}\n\t\t\t\t\tline += `>${trimmedText}`\n\t\t\t\t} else if (!attributesHtmlStr) {\n\t\t\t\t\tline += ' '\n\t\t\t\t}\n\n\t\t\t\tline += ' />'\n\t\t\t\tresult.push(line)\n\t\t\t}\n\n\t\t\t// Process children regardless\n\t\t\tfor (const child of node.children) {\n\t\t\t\tprocessNode(child, nextDepth, result)\n\t\t\t}\n\t\t} else if (node.type === 'text') {\n\t\t\t// Add text only if it doesn't have a highlighted parent\n\t\t\tif (hasParentWithHighlightIndex(node)) {\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tif (\n\t\t\t\tnode.parent &&\n\t\t\t\tnode.parent.type === 'element' &&\n\t\t\t\tnode.parent.isVisible &&\n\t\t\t\tnode.parent.isTopElement\n\t\t\t) {\n\t\t\t\tresult.push(`${depthStr}${node.text ?? ''}`)\n\t\t\t}\n\t\t}\n\t}\n\n\tconst result: string[] = []\n\tprocessNode(rootNode, 0, result)\n\treturn result.join('\\n')\n}\n\n// Get all text until next clickable element\nexport const getAllTextTillNextClickableElement = (node: TreeNode, maxDepth = -1): string => {\n\tconst textParts: string[] = []\n\n\tconst collectText = (currentNode: TreeNode, currentDepth: number) => {\n\t\tif (maxDepth !== -1 && currentDepth > maxDepth) {\n\t\t\treturn\n\t\t}\n\n\t\t// Skip this branch if we hit a highlighted element (except for the current node)\n\t\tif (\n\t\t\tcurrentNode.type === 'element' &&\n\t\t\tcurrentNode !== node &&\n\t\t\tcurrentNode.highlightIndex !== undefined\n\t\t) {\n\t\t\treturn\n\t\t}\n\n\t\tif (currentNode.type === 'text' && currentNode.text) {\n\t\t\ttextParts.push(currentNode.text)\n\t\t} else if (currentNode.type === 'element') {\n\t\t\tfor (const child of currentNode.children) {\n\t\t\t\tcollectText(child, currentDepth + 1)\n\t\t\t}\n\t\t}\n\t}\n\n\tcollectText(node, 0)\n\treturn textParts.join('\\n').trim()\n}\n\nexport function getSelectorMap(flatTree: FlatDomTree): Map<number, InteractiveElementDomNode> {\n\tconst selectorMap = new Map<number, InteractiveElementDomNode>()\n\n\tconst keys = Object.keys(flatTree.map)\n\tfor (const key of keys) {\n\t\tconst node = flatTree.map[key]\n\t\tif (node.isInteractive && typeof node.highlightIndex === 'number') {\n\t\t\tselectorMap.set(node.highlightIndex, node as InteractiveElementDomNode)\n\t\t}\n\t}\n\n\treturn selectorMap\n}\n\nexport function getElementTextMap(simplifiedHTML: string) {\n\tconst lines = simplifiedHTML\n\t\t.split('\\n')\n\t\t.map((line) => line.trim())\n\t\t.filter((line) => line.length > 0)\n\tconst elementTextMap = new Map<number, string>()\n\tfor (const line of lines) {\n\t\tconst regex = /^\\[(\\d+)\\]<[^>]+>([^<]*)/\n\t\tconst match = regex.exec(line)\n\t\tif (match) {\n\t\t\tconst index = parseInt(match[1], 10)\n\t\t\telementTextMap.set(index, line)\n\t\t}\n\t}\n\n\treturn elementTextMap\n}\n\nexport function cleanUpHighlights() {\n\tconst cleanupFunctions = (window as any)._highlightCleanupFunctions || []\n\tfor (const cleanup of cleanupFunctions) {\n\t\tif (typeof cleanup === 'function') {\n\t\t\tcleanup()\n\t\t}\n\t}\n\n\t;(window as any)._highlightCleanupFunctions = []\n}\n\n// 监听 URL 的任何变化,立刻清空 highLights\nwindow.addEventListener('popstate', () => {\n\t// console.log('URL changed (popstate), highlights cleaned up.')\n\tcleanUpHighlights()\n})\nwindow.addEventListener('hashchange', () => {\n\t// console.log('URL changed (hashchange), highlights cleaned up.')\n\tcleanUpHighlights()\n})\nwindow.addEventListener('beforeunload', () => {\n\t// console.log('Page is unloading, highlights cleaned up.')\n\tcleanUpHighlights()\n})\n\nconst navigation = (window as any).navigation\nif (navigation && typeof navigation.addEventListener === 'function') {\n\tnavigation.addEventListener('navigate', () => {\n\t\t// console.log('Navigation event detected, highlights cleaned up.')\n\t\tcleanUpHighlights()\n\t})\n} else {\n\t// 定时器\n\tlet currentUrl = window.location.href\n\tsetInterval(() => {\n\t\tif (window.location.href !== currentUrl) {\n\t\t\tcurrentUrl = window.location.href\n\t\t\t// console.log('URL changed (interval), highlights cleaned up.')\n\t\t\tcleanUpHighlights()\n\t\t}\n\t}, 500)\n}\n","export function getPageInfo() {\n\tconst viewport_width = window.innerWidth\n\tconst viewport_height = window.innerHeight\n\n\tconst page_width = Math.max(document.documentElement.scrollWidth, document.body.scrollWidth || 0)\n\tconst page_height = Math.max(\n\t\tdocument.documentElement.scrollHeight,\n\t\tdocument.body.scrollHeight || 0\n\t)\n\n\tconst scroll_x = window.scrollX || window.pageXOffset || document.documentElement.scrollLeft || 0\n\tconst scroll_y = window.scrollY || window.pageYOffset || document.documentElement.scrollTop || 0\n\n\tconst pixels_below = Math.max(0, page_height - (window.innerHeight + scroll_y))\n\tconst pixels_right = Math.max(0, page_width - (window.innerWidth + scroll_x))\n\n\treturn {\n\t\t// Current viewport dimensions\n\t\tviewport_width,\n\t\tviewport_height,\n\n\t\t// Total page dimensions\n\t\tpage_width,\n\t\tpage_height,\n\n\t\t// Current scroll position\n\t\tscroll_x,\n\t\tscroll_y,\n\n\t\tpixels_above: scroll_y,\n\t\tpixels_below,\n\n\t\tpages_above: viewport_height > 0 ? scroll_y / viewport_height : 0,\n\t\tpages_below: viewport_height > 0 ? pixels_below / viewport_height : 0,\n\t\ttotal_pages: viewport_height > 0 ? page_height / viewport_height : 0,\n\n\t\tcurrent_page_position: scroll_y / Math.max(1, page_height - viewport_height),\n\n\t\tpixels_left: scroll_x,\n\t\tpixels_right,\n\t}\n}\n","import type { TranslationSchema } from './types'\n\n// 中文翻译(作为基准)\nconst zhCN: TranslationSchema = {\n\tui: {\n\t\tpanel: {\n\t\t\tready: '准备就绪',\n\t\t\tthinking: '正在思考...',\n\t\t\tpaused: '暂停中,稍后',\n\t\t\ttaskInput: '输入新任务,详细描述步骤,回车提交',\n\t\t\tuserAnswerPrompt: '请回答上面问题,回车提交',\n\t\t\ttaskTerminated: '任务已终止',\n\t\t\ttaskCompleted: '任务结束',\n\t\t\tcontinueExecution: '继续执行',\n\t\t\tuserAnswer: '用户回答: {{input}}',\n\t\t\tpause: '暂停',\n\t\t\tcontinue: '继续',\n\t\t\tstop: '终止',\n\t\t\texpand: '展开历史',\n\t\t\tcollapse: '收起历史',\n\t\t\tstep: '步骤 {{number}} · {{time}}{{duration}}',\n\t\t},\n\t\ttools: {\n\t\t\tclicking: '正在点击元素 [{{index}}]...',\n\t\t\tinputting: '正在输入文本到元素 [{{index}}]...',\n\t\t\tselecting: '正在选择选项 \"{{text}}\"...',\n\t\t\tscrolling: '正在滚动页面...',\n\t\t\twaiting: '等待 {{seconds}} 秒...',\n\t\t\tdone: '结束任务',\n\t\t\tclicked: '🖱️ 已点击元素 [{{index}}]',\n\t\t\tinputted: '⌨️ 已输入文本 \"{{text}}\"',\n\t\t\tselected: '☑️ 已选择选项 \"{{text}}\"',\n\t\t\tscrolled: '🛞 页面滚动完成',\n\t\t\twaited: '⌛️ 等待完成',\n\t\t\texecuting: '正在执行 {{toolName}}...',\n\t\t},\n\t\terrors: {\n\t\t\telementNotFound: '未找到索引为 {{index}} 的交互元素',\n\t\t\ttaskRequired: '任务描述不能为空',\n\t\t\texecutionFailed: '任务执行失败',\n\t\t\tnotInputElement: '元素不是输入框或文本域',\n\t\t\tnotSelectElement: '元素不是选择框',\n\t\t\toptionNotFound: '未找到选项 \"{{text}}\"',\n\t\t},\n\t},\n} as const\n\n// 英文翻译(必须符合相同的结构)\nconst enUS: TranslationSchema = {\n\tui: {\n\t\tpanel: {\n\t\t\tready: 'Ready',\n\t\t\tthinking: 'Thinking...',\n\t\t\tpaused: 'Paused',\n\t\t\ttaskInput: 'Enter new task, describe steps in detail, press Enter to submit',\n\t\t\tuserAnswerPrompt: 'Please answer the question above, press Enter to submit',\n\t\t\ttaskTerminated: 'Task terminated',\n\t\t\ttaskCompleted: 'Task completed',\n\t\t\tcontinueExecution: 'Continue execution',\n\t\t\tuserAnswer: 'User answer: {{input}}',\n\t\t\tpause: 'Pause',\n\t\t\tcontinue: 'Continue',\n\t\t\tstop: 'Stop',\n\t\t\texpand: 'Expand history',\n\t\t\tcollapse: 'Collapse history',\n\t\t\tstep: 'Step {{number}} · {{time}}{{duration}}',\n\t\t},\n\t\ttools: {\n\t\t\tclicking: 'Clicking element [{{index}}]...',\n\t\t\tinputting: 'Inputting text to element [{{index}}]...',\n\t\t\tselecting: 'Selecting option \"{{text}}\"...',\n\t\t\tscrolling: 'Scrolling page...',\n\t\t\twaiting: 'Waiting {{seconds}} seconds...',\n\t\t\tdone: 'Task done',\n\t\t\tclicked: '🖱️ Clicked element [{{index}}]',\n\t\t\tinputted: '⌨️ Inputted text \"{{text}}\"',\n\t\t\tselected: '☑️ Selected option \"{{text}}\"',\n\t\t\tscrolled: '🛞 Page scrolled',\n\t\t\twaited: '⌛️ Wait completed',\n\t\t\texecuting: '正在执行 {{toolName}}...',\n\t\t},\n\t\terrors: {\n\t\t\telementNotFound: 'No interactive element found at index {{index}}',\n\t\t\ttaskRequired: 'Task description is required',\n\t\t\texecutionFailed: 'Task execution failed',\n\t\t\tnotInputElement: 'Element is not an input or textarea',\n\t\t\tnotSelectElement: 'Element is not a select element',\n\t\t\toptionNotFound: 'Option \"{{text}}\" not found',\n\t\t},\n\t},\n} as const\n\nexport const locales = {\n\t'zh-CN': zhCN,\n\t'en-US': enUS,\n} as const\n\nexport type SupportedLanguage = keyof typeof locales\n","import { type SupportedLanguage, locales } from './locales'\nimport type { TranslationKey, TranslationParams, TranslationSchema } from './types'\n\nexport class I18n {\n\tprivate language: SupportedLanguage\n\tprivate translations: TranslationSchema\n\n\tconstructor(language: SupportedLanguage = 'en-US') {\n\t\tthis.language = language in locales ? language : 'en-US'\n\t\tthis.translations = locales[language]\n\t}\n\n\t// 类型安全的翻译方法\n\tt(key: TranslationKey, params?: TranslationParams): string {\n\t\tconst value = this.getNestedValue(this.translations, key)\n\t\tif (!value) {\n\t\t\tconsole.warn(`Translation key \"${key}\" not found for language \"${this.language}\"`)\n\t\t\treturn key\n\t\t}\n\n\t\tif (params) {\n\t\t\treturn this.interpolate(value, params)\n\t\t}\n\t\treturn value\n\t}\n\n\tprivate getNestedValue(obj: any, path: string): string | undefined {\n\t\treturn path.split('.').reduce((current, key) => current?.[key], obj)\n\t}\n\n\tprivate interpolate(template: string, params: TranslationParams): string {\n\t\treturn template.replace(/\\{\\{(\\w+)\\}\\}/g, (match, key) => {\n\t\t\treturn params[key]?.toString() || match\n\t\t})\n\t}\n\n\tgetLanguage(): SupportedLanguage {\n\t\treturn this.language\n\t}\n}\n\n// 导出类型和实例创建函数\nexport type { TranslationKey, SupportedLanguage, TranslationParams }\nexport { locales }\n","import chalk from 'chalk'\n\n/**\n * Simple assertion function that throws an error if the condition is falsy\n * @param condition - The condition to assert\n * @param message - Optional error message\n * @throws Error if condition is falsy\n */\nexport function assert(condition: unknown, message?: string, silent?: boolean): asserts condition {\n\tif (!condition) {\n\t\tconst errorMessage = message ?? 'Assertion failed'\n\n\t\tif (!silent) console.error(chalk.red(`❌ assert: ${errorMessage}`))\n\n\t\tthrow new Error(errorMessage)\n\t}\n}\n","/**\n * Type-safe event bus for decoupling PageAgent and Panel\n */\nimport type { Step } from '@/ui/UIState'\n\n/**\n * Event mapping definitions\n * @note Event bus callbacks must be repeatable without errors\n */\nexport interface PageAgentEventMap {\n\t// Panel control events\n\t// call panel.show()\n\t'panel:show': { params: undefined }\n\t// call panel.hide()\n\t'panel:hide': { params: undefined }\n\t// call panel.reset()\n\t'panel:reset': { params: undefined }\n\t// call panel.update()\n\t'panel:update': { params: Omit<Step, 'id' | 'stepNumber' | 'timestamp'> }\n\t// call panel.expand()\n\t'panel:expand': { params: undefined }\n\t// call panel.collapse()\n\t'panel:collapse': { params: undefined }\n\n\t// PageAgent status events\n\t// 'agent:beforeUpdate': { params: undefined }\n\t// 'agent:afterUpdate': { params: undefined }\n\t// 'agent:execute': { params: { task: string } }\n\t// 'agent:done': { params: { text: string; success: boolean } }\n\t// 'agent:paused': { params: undefined }\n\t// 'agent:resumed': { params: undefined }\n\t// 'agent:disposed': { params: undefined }\n\t// 'agent:error': { params: { error: string | Error } }\n\n\t// Task status change events\n\t// 'task:start': { params: { task: string } }\n\t// 'task:step': { params: Omit<AgentStep, 'id' | 'stepNumber' | 'timestamp'> }\n\t// 'task:complete': { params: { text: string; success: boolean } }\n\t// 'task:error': { params: { error: string | Error } }\n\n\t// Index signature for dynamic event names\n\t// [key: string]: { params: any }\n}\n\n/**\n * Event handler type definitions\n */\nexport type EventHandler<T extends keyof PageAgentEventMap> =\n\tPageAgentEventMap[T]['params'] extends undefined\n\t\t? () => void\n\t\t: (params: PageAgentEventMap[T]['params']) => void\n\n/**\n * Async event handler type definitions\n */\nexport type AsyncEventHandler<T extends keyof PageAgentEventMap> =\n\tPageAgentEventMap[T]['params'] extends undefined\n\t\t? () => Promise<void>\n\t\t: (params: PageAgentEventMap[T]['params']) => Promise<void>\n\n/**\n * Type-safe event bus\n * @note Mainly used to decouple logic and UI\n * @note All modules of a PageAgent instance share the same EventBus instance for communication\n * @note Use with caution if delivery guarantee is needed for logic communication\n * @note `on` `once` `emit` methods handle built-in events with type protection, use `addEventListener` for other events\n */\nclass EventBus extends EventTarget {\n\t/**\n\t * Listen to built-in events\n\t */\n\ton<T extends keyof PageAgentEventMap>(\n\t\tevent: T,\n\t\thandler: EventHandler<T & keyof PageAgentEventMap>\n\t): void {\n\t\tconst wrappedHandler = (e: Event) => {\n\t\t\tconst customEvent = e as CustomEvent\n\t\t\tconst params = customEvent.detail?.[0]\n\t\t\treturn handler(params)\n\t\t}\n\t\tthis.addEventListener(event, wrappedHandler)\n\t}\n\n\t/**\n\t * Listen to built-in events (one-time)\n\t */\n\tonce<T extends keyof PageAgentEventMap>(\n\t\tevent: T,\n\t\thandler: EventHandler<T & keyof PageAgentEventMap>\n\t): void {\n\t\tconst wrappedHandler = (e: Event) => {\n\t\t\tconst customEvent = e as CustomEvent\n\t\t\tconst params = customEvent.detail?.[0]\n\t\t\treturn handler(params)\n\t\t}\n\t\tthis.addEventListener(event, wrappedHandler, { once: true })\n\t}\n\n\t/**\n\t * Emit built-in events\n\t */\n\temit<T extends keyof PageAgentEventMap>(\n\t\tevent: T,\n\t\t...args: PageAgentEventMap[T]['params'] extends undefined\n\t\t\t? []\n\t\t\t: [PageAgentEventMap[T]['params']]\n\t): void {\n\t\tconst customEvent = new CustomEvent(event, { detail: args })\n\t\tthis.dispatchEvent(customEvent)\n\t\treturn\n\t}\n}\n\nconst buses = new Map<string, EventBus>()\n\n/**\n * Get the event bus for a given channel\n */\nexport function getEventBus(channel: string) {\n\tif (buses.has(channel)) {\n\t\treturn buses.get(channel)!\n\t}\n\tconst bus = new EventBus()\n\tbuses.set(channel, bus)\n\treturn bus\n}\n\nexport type { EventBus }\n","/**\n * @topic LLM 与主流程的隔离\n * @reasoning\n * 将 llm 的调用和主流程分开是复杂的,\n * 因为 agent 的 tool call 通常集成在 llm 模块中,而而先得到 llm 返回,然后处理工具调用\n * tools 和 llm 调用的逻辑不可避免地耦合在一起,tool 的执行又和主流程耦合在一起\n * 而 history 的维护和更新逻辑,又必须嵌入多轮 tool call 中\n * @reasoning\n * - 放弃框架提供的自动的多轮调用,每轮调用都由主流程发起\n * - 理想情况下,llm 调用应该获得 structured output,然后由额外的模块触发 tool call,目前模型和框架都无法实现\n * - 当前只能将 llm api 和 本地 tool call 耦合在一起,不关心其中的衔接方式\n * @conclusion\n * - @llm responsibility boundary:\n * - call llm api with given messages and tools\n * - invoke tool call and get the result of the tool\n * - return the result to main loop\n * - @main_loop responsibility boundary:\n * - maintain all behaviors of an **agent**\n * @conclusion\n * - 这里的 llm 模块不是 agent,只负责一轮 llm 调用和工具调用,无状态\n */\n/**\n * @topic 结构化输出\n * @facts\n * - 几乎所有模型都支持 tool call schema\n * - 几乎所有模型都支持返回 json\n * - 只有 openAI/grok/gemini 支持 schema 并保证格式\n * - 主流模型都支持 tool_choice: required\n * - 除了 qwen 必须指定一个函数名 (9月上新后支持)\n * @conclusion\n * - 永远使用 tool call 来返回结构化数据,禁止模型直接返回(视为出错)\n * - 不能假设 tool 参数合法,必须有修复机制,而且修复也应该使用 tool call 返回\n */\nimport { OpenAIProvider, OpenAIResponsesProviderOptions, createOpenAI } from '@ai-sdk/openai'\nimport type { LanguageModelV2, LanguageModelV2ToolCall } from '@ai-sdk/provider'\nimport type { LanguageModelUsage, ModelMessage, TypedToolCall, TypedToolResult } from 'ai'\nimport { ToolSet, generateText, stepCountIs } from 'ai'\nimport chalk from 'chalk'\n\nimport {\n\tDEFAULT_API_KEY,\n\tDEFAULT_BASE_URL,\n\tDEFAULT_MODEL_NAME,\n\tLLM_MAX_RETRIES,\n\tMACRO_TOOL_NAME,\n} from '@/config/constants'\nimport { assert } from '@/utils/assert'\nimport { EventBus, getEventBus } from '@/utils/bus'\n\nexport interface LLMConfig {\n\tbaseURL?: string\n\tapiKey?: string\n\tmodelName?: string\n\tmaxRetries?: number\n}\n\nexport class LLM {\n\tconfig: Required<LLMConfig>\n\tid: string\n\t#openai: OpenAIProvider\n\t#model: LanguageModelV2\n\t#bus: EventBus\n\n\tconstructor(config: LLMConfig, id: string) {\n\t\tthis.config = {\n\t\t\tbaseURL: DEFAULT_BASE_URL,\n\t\t\tapiKey: DEFAULT_API_KEY,\n\t\t\tmodelName: DEFAULT_MODEL_NAME,\n\t\t\tmaxRetries: LLM_MAX_RETRIES,\n\t\t\t...config,\n\t\t}\n\t\tthis.id = id\n\n\t\tthis.#bus = getEventBus(id)\n\n\t\tthis.#openai = createOpenAI({ baseURL: this.config.baseURL, apiKey: this.config.apiKey })\n\t\tthis.#model = this.#openai.chat(this.config.modelName)\n\n\t\t// @note Will throw JSON parsing error\n\t\t// this.#model = this.#openai.responses(modelName)\n\t}\n\n\t/**\n\t * - call llm api *once*\n\t * - invoke tool call *once*\n\t * - return the result of the tool\n\t */\n\tasync invoke<T extends ToolSet>(\n\t\tmessages: ModelMessage[],\n\t\ttools: T,\n\t\tabortSignal: AbortSignal\n\t): Promise<{\n\t\ttoolCall: TypedToolCall<T>\n\t\ttoolResult: TypedToolResult<T>\n\t\tusage: LanguageModelUsage\n\t}> {\n\t\tconst isClaude = this.config.modelName.slice(0, 8).includes('claude')\n\t\tconst isQwen = this.config.modelName.slice(0, 6).includes('qwen')\n\t\tconst isGPT = this.config.modelName.slice(0, 5).includes('gpt')\n\n\t\treturn await withRetry(\n\t\t\tasync () => {\n\t\t\t\t// try {\n\t\t\t\tconst result = await generateText({\n\t\t\t\t\tmodel: this.#model,\n\t\t\t\t\tmessages,\n\t\t\t\t\ttools,\n\t\t\t\t\tabortSignal,\n\t\t\t\t\t/**\n\t\t\t\t\t * 文档中没有说明,从源码看,@facts\n\t\t\t\t\t * - 只会重试被识别为 retryable 的 API_CALL_ERROR\n\t\t\t\t\t * - 返回无法解析的 json 应该不会重试\n\t\t\t\t\t * - experimental_repairToolCall 只会执行一次,不算作重试\n\t\t\t\t\t * @facts\n\t\t\t\t\t * - 许多 proxy 过的 openAI 兼容接口返回的错误格式并不规范,通常不会被识别为 retryable\n\t\t\t\t\t * @conclusion\n\t\t\t\t\t * - 看起来并不实用,不如完全手工控制粗粒度重试\n\t\t\t\t\t */\n\t\t\t\t\t// maxRetries: this.config.maxRetries,\n\t\t\t\t\tmaxRetries: 0,\n\t\t\t\t\t// toolChoice: 'required',\n\t\t\t\t\t// @note incompatible to Claude\n\t\t\t\t\ttoolChoice: isClaude ? undefined : { type: 'tool', toolName: MACRO_TOOL_NAME as any },\n\t\t\t\t\t/**\n\t\t\t\t\t * controlled by main loop. our method only call api once\n\t\t\t\t\t */\n\t\t\t\t\t// stopWhen: [hasToolCall('done'), stepCountIs(100)],\n\t\t\t\t\tstopWhen: [stepCountIs(1)],\n\t\t\t\t\t// stopWhen: [hasToolCall('AgentOutput')],\n\t\t\t\t\tproviderOptions: {\n\t\t\t\t\t\topenai: {\n\t\t\t\t\t\t\t// @note this one needs all fields in tool schema must be `required`\n\t\t\t\t\t\t\t// strictJsonSchema: true,\n\t\t\t\t\t\t\t// This way only at most one tool can be called at a time\n\t\t\t\t\t\t\tparallelToolCalls: false,\n\t\t\t\t\t\t\treasoningEffort: 'minimal',\n\t\t\t\t\t\t\t// @note not working\n\t\t\t\t\t\t\t// serviceTier: 'priority',\n\t\t\t\t\t\t\ttextVerbosity: 'low',\n\t\t\t\t\t\t\t// @note Optimize OpenAI model caching, should be unique per user, currently has no effect\n\t\t\t\t\t\t\tpromptCacheKey: 'page-agent:' + this.id,\n\t\t\t\t\t\t} as OpenAIResponsesProviderOptions,\n\t\t\t\t\t},\n\t\t\t\t\t/**\n\t\t\t\t\t * schema 出错时执行一次,不确定是否计入重试\n\t\t\t\t\t * 目前看起来像是会直接抛错,被 withRetry 处理\n\t\t\t\t\t * @note\n\t\t\t\t\t * 如果不提供,则 ai-sdk 会把 tool-error 加入 message 中重新调用一次,\n\t\t\t\t\t * 配合 stepCountIs 或者 hasToolCall 都会导致错误被 silent,toolResults 永远为 0\n\t\t\t\t\t * 遗憾的是,这里没有办法抛错(抛错后回到默认逻辑),只要这里 repair 不好,就会导致 silent error\n\t\t\t\t\t * 更糟糕的是,只要传入了 tools,无论 stopWhen 如何设置,都会被当作 multi-step,\n\t\t\t\t\t * 本质上就和我们 single step 的逻辑冲突\n\t\t\t\t\t * 长远来看必须删掉 ai-sdk,直接用 openAI API 实现\n\t\t\t\t\t */\n\t\t\t\t\t// experimental_repairToolCall: (options): Promise<LanguageModelV2ToolCall | null> => {\n\t\t\t\t\t// \tconsole.error('hahhah', options)\n\t\t\t\t\t// \tthrow options.error\n\t\t\t\t\t// },\n\t\t\t\t})\n\n\t\t\t\tconsole.log(chalk.blue.bold('LLM:invoke finished'), result)\n\n\t\t\t\tconst toolError: any = result.content.find((part) => part.type === 'tool-error')\n\t\t\t\tif (toolError) throw toolError.error\n\n\t\t\t\tassert(!result.text, 'Model returned text without calling done tool', true)\n\t\t\t\tassert(result.toolCalls.length === 1, 'Model must call exactly one tool', true)\n\t\t\t\tassert(result.toolResults.length === 1, 'Step must have exactly one tool result', true)\n\n\t\t\t\tconst toolCall = result.toolCalls[0]\n\t\t\t\tconst toolResult = result.toolResults[0]\n\t\t\t\tconst usage = result.totalUsage\n\n\t\t\t\treturn {\n\t\t\t\t\ttoolCall,\n\t\t\t\t\ttoolResult,\n\t\t\t\t\tusage,\n\t\t\t\t}\n\n\t\t\t\t// } catch (error) {\n\t\t\t\t// \t// handle ai-sdk internal error here\n\t\t\t\t// \t// currently useless since we bypassed most of ai-sdk logic\n\t\t\t\t// \tconsole.log('generateText error', error)\n\t\t\t\t// \tconsole.log('APICallError', APICallError.isInstance(error))\n\t\t\t\t// \tconsole.log('isNoSuchModelError', NoSuchModelError.isInstance(error))\n\n\t\t\t\t// \tthrow error\n\t\t\t\t// }\n\t\t\t},\n\t\t\t// retry settings\n\t\t\t{\n\t\t\t\tmaxRetries: this.config.maxRetries,\n\t\t\t\tonRetry: (retries: number) => {\n\t\t\t\t\tthis.#bus.emit('panel:update', {\n\t\t\t\t\t\ttype: 'retry',\n\t\t\t\t\t\tdisplayText: `retry-ing (${retries} / ${this.config.maxRetries})`,\n\t\t\t\t\t})\n\t\t\t\t},\n\t\t\t\tonError: (error: Error, withRetry: boolean) => {\n\t\t\t\t\tthis.#bus.emit('panel:update', {\n\t\t\t\t\t\ttype: 'error',\n\t\t\t\t\t\tdisplayText: `step failed: ${(error as Error).message}`,\n\t\t\t\t\t})\n\t\t\t\t},\n\t\t\t}\n\t\t)\n\t}\n}\n\nasync function withRetry<T>(\n\tfn: () => Promise<T>,\n\tsettings: {\n\t\tmaxRetries: number\n\t\tonRetry: (retries: number) => void\n\t\tonError: (error: Error, withRetry: boolean) => void\n\t}\n): Promise<T> {\n\tlet retries = 0\n\tlet lastError: Error | null = null\n\twhile (retries <= settings.maxRetries) {\n\t\tif (retries > 0) {\n\t\t\tsettings.onRetry(retries)\n\t\t\tawait new Promise((resolve) => setTimeout(resolve, 100))\n\t\t}\n\n\t\ttry {\n\t\t\treturn await fn()\n\t\t} catch (error: any) {\n\t\t\tconsole.error(error)\n\t\t\tsettings.onError(error as Error, retries < settings.maxRetries)\n\n\t\t\t// do not retry if aborted by user\n\t\t\tif (error?.name === 'AbortError') throw error\n\n\t\t\tlastError = error as Error\n\t\t\tretries++\n\n\t\t\tawait new Promise((resolve) => setTimeout(resolve, 100))\n\t\t}\n\t}\n\n\tthrow lastError!\n}\n","import type { PageAgent } from '@/PageAgent'\n\n// Find common React root elements and add data-page-agent-not-interactive attribute\nexport function patchReact(pageAgent: PageAgent) {\n\tconst reactRootElements = document.querySelectorAll(\n\t\t'[data-reactroot], [data-reactid], [data-react-checksum], #root, #app, [id^=\"root-\"], [id^=\"app-\"], #adex-wrapper, #adex-root'\n\t)\n\n\tfor (const element of reactRootElements) {\n\t\telement.setAttribute('data-page-agent-not-interactive', 'true')\n\t}\n}\n\n/**\n * @todo (Heavy, might have false negatives) Interaction detection, if element width/height equals body offsetWidth/Height, consider it root element and non-interactive (React often attaches many events to root elements, causing false positives)\n */\n","export default \"You are an AI agent designed to operate in an iterative loop to automate browser tasks. Your ultimate goal is accomplishing the task provided in <user_request>.\\n\\n<intro>\\nYou excel at following tasks:\\n1. Navigating complex websites and extracting precise information\\n2. Automating form submissions and interactive web actions\\n3. Gathering and saving information \\n4. Operate effectively in an agent loop\\n5. Efficiently performing diverse web tasks\\n</intro>\\n\\n<language_settings>\\n- Default working language: **中文**\\n- Use the language that user is using. Return in user's language.\\n</language_settings>\\n\\n<input>\\nAt every step, your input will consist of: \\n1. <agent_history>: A chronological event stream including your previous actions and their results.\\n2. <agent_state>: Current <user_request> and <step_info>.\\n3. <browser_state>: Current URL, interactive elements indexed for actions, and visible page content.\\n</input>\\n\\n<agent_history>\\nAgent history will be given as a list of step information as follows:\\n\\n<step_{step_number}>:\\nEvaluation of Previous Step: Assessment of last action\\nMemory: Your memory of this step\\nNext Goal: Your goal for this step\\nAction Results: Your actions and their results\\n</step_{step_number}>\\n\\nand system messages wrapped in <sys> tag.\\n</agent_history>\\n\\n<user_request>\\nUSER REQUEST: This is your ultimate objective and always remains visible.\\n- This has the highest priority. Make the user happy.\\n- If the user request is very specific - then carefully follow each step and dont skip or hallucinate steps.\\n- If the task is open ended you can plan yourself how to get it done.\\n</user_request>\\n\\n<browser_state>\\n1. Browser State will be given as:\\n\\nCurrent URL: URL of the page you are currently viewing.\\nInteractive Elements: All interactive elements will be provided in format as [index]<type>text</type> where\\n- index: Numeric identifier for interaction\\n- type: HTML element type (button, input, etc.)\\n- text: Element description\\n\\nExamples:\\n[33]<div>User form</div>\\n\\\\t*[35]<button aria-label='Submit form'>Submit</button>\\n\\nNote that:\\n- Only elements with numeric indexes in [] are interactive\\n- (stacked) indentation (with \\\\t) is important and means that the element is a (html) child of the element above (with a lower index)\\n- Elements tagged with `*[` are the new clickable elements that appeared on the website since the last step - if url has not changed.\\n- Pure text elements without [] are not interactive.\\n</browser_state>\\n\\n<browser_rules>\\nStrictly follow these rules while using the browser and navigating the web:\\n- Only interact with elements that have a numeric [index] assigned.\\n- Only use indexes that are explicitly provided.\\n- If the page changes after, for example, an input text action, analyze if you need to interact with new elements, e.g. selecting the right option from the list.\\n- By default, only elements in the visible viewport are listed. Use scrolling actions if you suspect relevant content is offscreen which you need to interact with. Scroll ONLY if there are more pixels below or above the page.\\n- You can scroll by a specific number of pages using the num_pages parameter (e.g., 0.5 for half page, 2.0 for two pages).\\n- All the elements that are scrollable are marked with `data-scrollable` attribute. Including the scrollable distance in every directions. You can scroll *the element* in case some area are overflowed.\\n- If a captcha appears, tell user you can not solve captcha. finished the task and ask user to solve it.\\n- If expected elements are missing, try scrolling, or navigating back.\\n- If the page is not fully loaded, use the `wait` action.\\n- Do not repeat one action for more than 3 times unless some conditions changed.\\n- If you fill an input field and your action sequence is interrupted, most often something changed e.g. suggestions popped up under the field.\\n- If the <user_request> includes specific page information such as product type, rating, price, location, etc., try to apply filters to be more efficient.\\n- The <user_request> is the ultimate goal. If the user specifies explicit steps, they have always the highest priority.\\n- If you input_text into a field, you might need to press enter, click the search button, or select from dropdown for completion.\\n- Don't login into a page if you don't have to. Don't login if you don't have the credentials. \\n- There are 2 types of tasks always first think which type of request you are dealing with:\\n1. Very specific step by step instructions:\\n- Follow them as very precise and don't skip steps. Try to complete everything as requested.\\n2. Open ended tasks. Plan yourself, be creative in achieving them.\\n- If you get stuck e.g. with logins or captcha in open-ended tasks you can re-evaluate the task and try alternative ways, e.g. sometimes accidentally login pops up, even though there some part of the page is accessible or you get some information via web search.\\n</browser_rules>\\n\\n<capability>\\n- You can only handle single page app. Do not jump out of current page.\\n- Do not click on link if it will open in a new page (etc. <a target=\\\"_blank\\\">)\\n- It is ok to fail the task.\\n\\t- User can be wrong. If the request of user is not achievable, inappropriate or you do not have enough information or tools to achieve it. Tell user to make a better request.\\n\\t- Webpage can be broken. All webpages or apps have bugs. Some bug will make it hard for your job. It's encouraged to tell user the problem of current page. Your feedbacks (including failing) are valuable for user.\\n\\t- Trying to hard can be harmful. Repeating some action back and forth or pushing for a complex procedure with little knowledge can cause unwanted result and harmful side-effects. User would rather you to complete the task with a fail.\\n- If you are not clear about the request or steps. `ask_user` to clarify it.\\n- If you do not have knowledge for the current webpage or task. You must require user to give specific instructions and detailed steps.\\n</capability>\\n\\n<task_completion_rules>\\nYou must call the `done` action in one of three cases:\\n- When you have fully completed the USER REQUEST.\\n- When you reach the final allowed step (`max_steps`), even if the task is incomplete.\\n- When you feel stuck or unable to solve user request. Or user request is not clear or contains inappropriate content.\\n- If it is ABSOLUTELY IMPOSSIBLE to continue.\\n\\nThe `done` action is your opportunity to terminate and share your findings with the user.\\n- Set `success` to `true` only if the full USER REQUEST has been completed with no missing components.\\n- If any part of the request is missing, incomplete, or uncertain, set `success` to `false`.\\n- You can use the `text` field of the `done` action to communicate your findings and to provide a coherent reply to the user and fulfill the USER REQUEST.\\n- You are ONLY ALLOWED to call `done` as a single action. Don't call it together with other actions.\\n- If the user asks for specified format, such as \\\"return JSON with following structure\\\", \\\"return a list of format...\\\", MAKE sure to use the right format in your answer.\\n- If the user asks for a structured output, your `done` action's schema may be modified. Take this schema into account when solving the task!\\n</task_completion_rules>\\n\\n<reasoning_rules>\\nExhibit the following reasoning patterns to successfully achieve the <user_request>:\\n\\n- Reason about <agent_history> to track progress and context toward <user_request>.\\n- Analyze the most recent \\\"Next Goal\\\" and \\\"Action Result\\\" in <agent_history> and clearly state what you previously tried to achieve.\\n- Analyze all relevant items in <agent_history> and <browser_state> to understand your state.\\n- Explicitly judge success/failure/uncertainty of the last action. Never assume an action succeeded just because it appears to be executed in your last step in <agent_history>. If the expected change is missing, mark the last action as failed (or uncertain) and plan a recovery.\\n- Analyze whether you are stuck, e.g. when you repeat the same actions multiple times without any progress. Then consider alternative approaches e.g. scrolling for more context or ask user for help.\\n- `ask_user` for help if you have any difficulty. Users want to be kept in the loop.\\n- If you see information relevant to <user_request>, plan saving the information to memory.\\n- Always reason about the <user_request>. Make sure to carefully analyze the specific steps and information required. E.g. specific filters, specific form fields, specific information to search. Make sure to always compare the current trajectory with the user request and think carefully if thats how the user requested it.\\n</reasoning_rules>\\n\\n<examples>\\nHere are examples of good output patterns. Use them as reference but never copy them directly.\\n\\n<evaluation_examples>\\n- Positive Examples:\\n\\\"evaluation_previous_goal\\\": \\\"Successfully navigated to the product page and found the target information. Verdict: Success\\\"\\n\\\"evaluation_previous_goal\\\": \\\"Clicked the login button and user authentication form appeared. Verdict: Success\\\"\\n</evaluation_examples>\\n\\n<memory_examples>\\n\\\"memory\\\": \\\"Found many pending reports that need to be analyzed in the main page. Successfully processed the first 2 reports on quarterly sales data and moving on to inventory analysis and customer feedback reports.\\\"\\n</memory_examples>\\n\\n<next_goal_examples>\\n\\\"next_goal\\\": \\\"Click on the 'Add to Cart' button to proceed with the purchase flow.\\\"\\n\\\"next_goal\\\": \\\"Extract details from the first item on the page.\\\"\\n</next_goal_examples>\\n</examples>\\n\\n<output>\\nYou must ALWAYS respond with a valid JSON in this exact format:\\n\\n{\\n \\\"evaluation_previous_goal\\\": \\\"Concise one-sentence analysis of your last action. Clearly state success, failure, or uncertain.\\\",\\n \\\"memory\\\": \\\"1-3 concise sentences of specific memory of this step and overall progress. You should put here everything that will help you track progress in future steps. Like counting pages visited, items found, etc.\\\",\\n \\\"next_goal\\\": \\\"State the next immediate goal and action to achieve it, in one clear sentence.\\\"\\n \\\"action\\\":{\\\"one_action_name\\\": {// action-specific parameter}}\\n}\\n</output>\\n\"","/**\n * Copyright (C) 2025 Alibaba Group Holding Limited\n * All rights reserved.\n */\nimport type { PageAgent } from '../PageAgent'\n\n// ======= general utils =======\n\nexport async function waitFor(seconds: number): Promise<void> {\n\tawait new Promise((resolve) => setTimeout(resolve, seconds * 1000))\n}\n\nlet currentUrl = window.location.href\nexport async function getSystemInfo() {\n\t// If current URL is already up to date, no need to add message\n\tif (currentUrl === window.location.href) return ''\n\n\tawait waitFor(0.3) // Wait a bit longer for page to load\n\n\tcurrentUrl = window.location.href\n\n\treturn `\\n<sys> Current URL changed to: ${currentUrl} </sys>`\n}\n\n// ======= dom utils =======\n\nexport async function movePointerToElement(element: HTMLElement) {\n\tconst rect = element.getBoundingClientRect()\n\tconst x = rect.left + rect.width / 2\n\tconst y = rect.top + rect.height / 2\n\n\twindow.dispatchEvent(new CustomEvent('PageAgent::MovePointerTo', { detail: { x, y } }))\n\n\tawait waitFor(0.3)\n}\n\n/**\n * Get the HTMLElement by index from the selectorMap in PageAgent.\n */\nexport function getElementByIndex(pageAgent: PageAgent, index: number): HTMLElement {\n\tconst interactiveNode = pageAgent.selectorMap.get(index)\n\tif (!interactiveNode) {\n\t\tthrow new Error(`No interactive element found at index ${index}`)\n\t}\n\n\tconst element = interactiveNode.ref\n\tif (!element) {\n\t\tthrow new Error(`Element at index ${index} does not have a reference`)\n\t}\n\n\tif (!(element instanceof HTMLElement)) {\n\t\tthrow new Error(`Element at index ${index} is not an HTMLElement`)\n\t}\n\n\treturn element\n}\n\nlet lastClickedElement: HTMLElement | null = null\n\nfunction blurLastClickedElement() {\n\tif (lastClickedElement) {\n\t\tlastClickedElement.blur()\n\t\tlastClickedElement.dispatchEvent(\n\t\t\tnew MouseEvent('mouseout', { bubbles: true, cancelable: true })\n\t\t)\n\t\tlastClickedElement = null\n\t}\n}\n\n/**\n * Simulate a click on the element\n */\nexport async function clickElement(element: HTMLElement) {\n\tblurLastClickedElement()\n\n\tlastClickedElement = element\n\tawait scrollIntoViewIfNeeded(element)\n\tawait movePointerToElement(element)\n\twindow.dispatchEvent(new CustomEvent('PageAgent::ClickPointer'))\n\tawait waitFor(0.1)\n\n\t// hover it\n\telement.dispatchEvent(new MouseEvent('mouseenter', { bubbles: true, cancelable: true }))\n\telement.dispatchEvent(new MouseEvent('mouseover', { bubbles: true, cancelable: true }))\n\n\t// dispatch a sequence of events to ensure all listeners are triggered\n\telement.dispatchEvent(new MouseEvent('mousedown', { bubbles: true, cancelable: true }))\n\n\t// focus it to ensure it gets the click event\n\telement.focus()\n\n\telement.dispatchEvent(new MouseEvent('mouseup', { bubbles: true, cancelable: true }))\n\telement.dispatchEvent(new MouseEvent('click', { bubbles: true, cancelable: true }))\n\n\t// dispatch a click event\n\t// element.click()\n\n\tawait waitFor(0.1) // Wait to ensure click event processing completes\n}\n\n// eslint-disable-next-line @typescript-eslint/unbound-method\nconst nativeInputValueSetter = Object.getOwnPropertyDescriptor(\n\twindow.HTMLInputElement.prototype,\n\t'value'\n)!.set!\n\n// eslint-disable-next-line @typescript-eslint/unbound-method\nconst nativeTextAreaValueSetter = Object.getOwnPropertyDescriptor(\n\twindow.HTMLTextAreaElement.prototype,\n\t'value'\n)!.set!\n\n/**\n * create a synthetic keyboard event\n * with key keycode code\n */\nexport async function createSyntheticInputEvent(elem: HTMLElement, key: string) {\n\telem.dispatchEvent(new KeyboardEvent('keydown', { bubbles: true, cancelable: true, key }))\n\tawait waitFor(0.01)\n\n\tif (elem instanceof HTMLInputElement || elem instanceof HTMLTextAreaElement) {\n\t\telem.dispatchEvent(new Event('beforeinput', { bubbles: true }))\n\t\tawait waitFor(0.01)\n\t\telem.dispatchEvent(new Event('input', { bubbles: true }))\n\t\tawait waitFor(0.01)\n\t}\n\n\telem.dispatchEvent(new KeyboardEvent('keyup', { bubbles: true, cancelable: true, key }))\n}\n\nexport async function inputTextElement(element: HTMLElement, text: string) {\n\tif (!(element instanceof HTMLInputElement || element instanceof HTMLTextAreaElement)) {\n\t\tthrow new Error('Element is not an input or textarea')\n\t}\n\n\tawait clickElement(element)\n\n\tif (element instanceof HTMLTextAreaElement) {\n\t\tnativeTextAreaValueSetter.call(element, text)\n\t} else {\n\t\tnativeInputValueSetter.call(element, text)\n\t}\n\n\tconst inputEvent = new Event('input', { bubbles: true })\n\telement.dispatchEvent(inputEvent)\n\n\tawait waitFor(0.1) // Wait to ensure input event processing completes\n\n\tblurLastClickedElement()\n}\n\n/**\n * @todo browser-use version is very complex and supports menu tags, need to follow up\n */\nexport async function selectOptionElement(selectElement: HTMLSelectElement, optionText: string) {\n\tif (!(selectElement instanceof HTMLSelectElement)) {\n\t\tthrow new Error('Element is not a select element')\n\t}\n\n\tconst options = Array.from(selectElement.options)\n\tconst option = options.find((opt) => opt.textContent?.trim() === optionText.trim())\n\n\tif (!option) {\n\t\tthrow new Error(`Option with text \"${optionText}\" not found in select element`)\n\t}\n\n\tselectElement.value = option.value\n\tselectElement.dispatchEvent(new Event('change', { bubbles: true }))\n\n\tawait waitFor(0.1) // Wait to ensure change event processing completes\n}\n\n// eslint-disable-next-line @typescript-eslint/require-await\nexport async function scrollIntoViewIfNeeded(element: HTMLElement) {\n\tconst el = element as any\n\tif (el.scrollIntoViewIfNeeded) {\n\t\tel.scrollIntoViewIfNeeded()\n\t\t// await waitFor(0.5) // Animation playback\n\t} else {\n\t\t// @todo visibility check\n\t\tel.scrollIntoView({ behavior: 'auto', block: 'center', inline: 'nearest' })\n\t\t// await waitFor(0.5) // Animation playback\n\t}\n}\n\nexport async function scrollVertically(\n\tdown: boolean,\n\tscroll_amount: number,\n\telement?: HTMLElement | null\n) {\n\t// Element-specific scrolling if element is provided\n\tif (element) {\n\t\tconst targetElement = element\n\t\tconsole.log(\n\t\t\t'[SCROLL DEBUG] Starting direct container scroll for element:',\n\t\t\ttargetElement.tagName\n\t\t)\n\n\t\tlet currentElement = targetElement as HTMLElement | null\n\t\tlet scrollSuccess = false\n\t\tlet scrolledElement: HTMLElement | null = null\n\t\tlet scrollDelta = 0\n\t\tlet attempts = 0\n\t\tconst dy = scroll_amount\n\n\t\twhile (currentElement && attempts < 10) {\n\t\t\tconst computedStyle = window.getComputedStyle(currentElement)\n\t\t\tconst hasScrollableY = /(auto|scroll|overlay)/.test(computedStyle.overflowY)\n\t\t\tconst canScrollVertically = currentElement.scrollHeight > currentElement.clientHeight\n\n\t\t\tconsole.log(\n\t\t\t\t'[SCROLL DEBUG] Checking element:',\n\t\t\t\tcurrentElement.tagName,\n\t\t\t\t'hasScrollableY:',\n\t\t\t\thasScrollableY,\n\t\t\t\t'canScrollVertically:',\n\t\t\t\tcanScrollVertically,\n\t\t\t\t'scrollHeight:',\n\t\t\t\tcurrentElement.scrollHeight,\n\t\t\t\t'clientHeight:',\n\t\t\t\tcurrentElement.clientHeight\n\t\t\t)\n\n\t\t\tif (hasScrollableY && canScrollVertically) {\n\t\t\t\tconst beforeScroll = currentElement.scrollTop\n\t\t\t\tconst maxScroll = currentElement.scrollHeight - currentElement.clientHeight\n\n\t\t\t\tlet scrollAmount = dy / 3\n\n\t\t\t\tif (scrollAmount > 0) {\n\t\t\t\t\tscrollAmount = Math.min(scrollAmount, maxScroll - beforeScroll)\n\t\t\t\t} else {\n\t\t\t\t\tscrollAmount = Math.max(scrollAmount, -beforeScroll)\n\t\t\t\t}\n\n\t\t\t\tcurrentElement.scrollTop = beforeScroll + scrollAmount\n\n\t\t\t\tconst afterScroll = currentElement.scrollTop\n\t\t\t\tconst actualScrollDelta = afterScroll - beforeScroll\n\n\t\t\t\tconsole.log(\n\t\t\t\t\t'[SCROLL DEBUG] Scroll attempt:',\n\t\t\t\t\tcurrentElement.tagName,\n\t\t\t\t\t'before:',\n\t\t\t\t\tbeforeScroll,\n\t\t\t\t\t'after:',\n\t\t\t\t\tafterScroll,\n\t\t\t\t\t'delta:',\n\t\t\t\t\tactualScrollDelta\n\t\t\t\t)\n\n\t\t\t\tif (Math.abs(actualScrollDelta) > 0.5) {\n\t\t\t\t\tscrollSuccess = true\n\t\t\t\t\tscrolledElement = currentElement\n\t\t\t\t\tscrollDelta = actualScrollDelta\n\t\t\t\t\tconsole.log(\n\t\t\t\t\t\t'[SCROLL DEBUG] Successfully scrolled container:',\n\t\t\t\t\t\tcurrentElement.tagName,\n\t\t\t\t\t\t'delta:',\n\t\t\t\t\t\tactualScrollDelta\n\t\t\t\t\t)\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (currentElement === document.body || currentElement === document.documentElement) {\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tcurrentElement = currentElement.parentElement\n\t\t\tattempts++\n\t\t}\n\n\t\tif (scrollSuccess) {\n\t\t\treturn `Scrolled container (${scrolledElement?.tagName}) by ${scrollDelta}px`\n\t\t} else {\n\t\t\treturn `No scrollable container found for element (${targetElement.tagName})`\n\t\t}\n\t}\n\n\t// Page-level scrolling (default or fallback)\n\n\tconst dy = scroll_amount\n\tconst bigEnough = (el: HTMLElement) => el.clientHeight >= window.innerHeight * 0.5\n\tconst canScroll = (el: HTMLElement | null) =>\n\t\tel &&\n\t\t/(auto|scroll|overlay)/.test(getComputedStyle(el).overflowY) &&\n\t\tel.scrollHeight > el.clientHeight &&\n\t\tbigEnough(el)\n\n\tlet el: HTMLElement | null = document.activeElement as HTMLElement | null\n\twhile (el && !canScroll(el) && el !== document.body) el = el.parentElement\n\n\tel = canScroll(el)\n\t\t? el\n\t\t: Array.from(document.querySelectorAll<HTMLElement>('*')).find(canScroll) ||\n\t\t\t(document.scrollingElement as HTMLElement) ||\n\t\t\t(document.documentElement as HTMLElement)\n\n\tif (el === document.scrollingElement || el === document.documentElement || el === document.body) {\n\t\twindow.scrollBy(0, dy)\n\t\treturn `✅ Scrolled page by ${dy}px.`\n\t} else {\n\t\tel!.scrollBy({ top: dy, behavior: 'smooth' })\n\t\tawait waitFor(0.1) // Animation playback\n\t\treturn `✅ Scrolled container (${el!.tagName}) by ${dy}px.`\n\t}\n}\n\nexport async function scrollHorizontally(\n\tright: boolean,\n\tscroll_amount: number,\n\telement?: HTMLElement | null\n) {\n\t// Element-specific scrolling if element is provided\n\tif (element) {\n\t\tconst targetElement = element\n\t\tconsole.log(\n\t\t\t'[SCROLL DEBUG] Starting direct container scroll for element:',\n\t\t\ttargetElement.tagName\n\t\t)\n\n\t\tlet currentElement = targetElement as HTMLElement | null\n\t\tlet scrollSuccess = false\n\t\tlet scrolledElement: HTMLElement | null = null\n\t\tlet scrollDelta = 0\n\t\tlet attempts = 0\n\t\tconst dx = right ? scroll_amount : -scroll_amount\n\n\t\twhile (currentElement && attempts < 10) {\n\t\t\tconst computedStyle = window.getComputedStyle(currentElement)\n\t\t\tconst hasScrollableX = /(auto|scroll|overlay)/.test(computedStyle.overflowX)\n\t\t\tconst canScrollHorizontally = currentElement.scrollWidth > currentElement.clientWidth\n\n\t\t\tconsole.log(\n\t\t\t\t'[SCROLL DEBUG] Checking element:',\n\t\t\t\tcurrentElement.tagName,\n\t\t\t\t'hasScrollableX:',\n\t\t\t\thasScrollableX,\n\t\t\t\t'canScrollHorizontally:',\n\t\t\t\tcanScrollHorizontally,\n\t\t\t\t'scrollWidth:',\n\t\t\t\tcurrentElement.scrollWidth,\n\t\t\t\t'clientWidth:',\n\t\t\t\tcurrentElement.clientWidth\n\t\t\t)\n\n\t\t\tif (hasScrollableX && canScrollHorizontally) {\n\t\t\t\tconst beforeScroll = currentElement.scrollLeft\n\t\t\t\tconst maxScroll = currentElement.scrollWidth - currentElement.clientWidth\n\n\t\t\t\tlet scrollAmount = dx / 3\n\n\t\t\t\tif (scrollAmount > 0) {\n\t\t\t\t\tscrollAmount = Math.min(scrollAmount, maxScroll - beforeScroll)\n\t\t\t\t} else {\n\t\t\t\t\tscrollAmount = Math.max(scrollAmount, -beforeScroll)\n\t\t\t\t}\n\n\t\t\t\tcurrentElement.scrollLeft = beforeScroll + scrollAmount\n\n\t\t\t\tconst afterScroll = currentElement.scrollLeft\n\t\t\t\tconst actualScrollDelta = afterScroll - beforeScroll\n\n\t\t\t\tconsole.log(\n\t\t\t\t\t'[SCROLL DEBUG] Scroll attempt:',\n\t\t\t\t\tcurrentElement.tagName,\n\t\t\t\t\t'before:',\n\t\t\t\t\tbeforeScroll,\n\t\t\t\t\t'after:',\n\t\t\t\t\tafterScroll,\n\t\t\t\t\t'delta:',\n\t\t\t\t\tactualScrollDelta\n\t\t\t\t)\n\n\t\t\t\tif (Math.abs(actualScrollDelta) > 0.5) {\n\t\t\t\t\tscrollSuccess = true\n\t\t\t\t\tscrolledElement = currentElement\n\t\t\t\t\tscrollDelta = actualScrollDelta\n\t\t\t\t\tconsole.log(\n\t\t\t\t\t\t'[SCROLL DEBUG] Successfully scrolled container:',\n\t\t\t\t\t\tcurrentElement.tagName,\n\t\t\t\t\t\t'delta:',\n\t\t\t\t\t\tactualScrollDelta\n\t\t\t\t\t)\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (currentElement === document.body || currentElement === document.documentElement) {\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tcurrentElement = currentElement.parentElement\n\t\t\tattempts++\n\t\t}\n\n\t\tif (scrollSuccess) {\n\t\t\treturn `Scrolled container (${scrolledElement?.tagName}) horizontally by ${scrollDelta}px`\n\t\t} else {\n\t\t\treturn `No horizontally scrollable container found for element (${targetElement.tagName})`\n\t\t}\n\t}\n\n\t// Page-level scrolling (default or fallback)\n\n\tconst dx = right ? scroll_amount : -scroll_amount\n\tconst bigEnough = (el: HTMLElement) => el.clientWidth >= window.innerWidth * 0.5\n\tconst canScroll = (el: HTMLElement | null) =>\n\t\tel &&\n\t\t/(auto|scroll|overlay)/.test(getComputedStyle(el).overflowX) &&\n\t\tel.scrollWidth > el.clientWidth &&\n\t\tbigEnough(el)\n\n\tlet el: HTMLElement | null = document.activeElement as HTMLElement | null\n\twhile (el && !canScroll(el) && el !== document.body) el = el.parentElement\n\n\tel = canScroll(el)\n\t\t? el\n\t\t: Array.from(document.querySelectorAll<HTMLElement>('*')).find(canScroll) ||\n\t\t\t(document.scrollingElement as HTMLElement) ||\n\t\t\t(document.documentElement as HTMLElement)\n\n\tif (el === document.scrollingElement || el === document.documentElement || el === document.body) {\n\t\twindow.scrollBy(dx, 0)\n\t\treturn `✅ Scrolled page horizontally by ${dx}px`\n\t} else {\n\t\tel!.scrollBy({ left: dx, behavior: 'smooth' })\n\t\tawait waitFor(0.1) // Animation playback\n\t\treturn `✅ Scrolled container (${el!.tagName}) horizontally by ${dx}px`\n\t}\n}\n","/**\n * Internal tools for PageAgent.\n * @note Adapted from browser-use\n */\nimport { Tool, tool } from 'ai'\nimport zod from 'zod'\n\nimport type { PageAgent } from '@/PageAgent'\n\nimport {\n\tclickElement,\n\tgetElementByIndex,\n\tgetSystemInfo,\n\tinputTextElement,\n\tscrollHorizontally,\n\tscrollVertically,\n\tselectOptionElement,\n\twaitFor,\n} from './actions'\n// debug\nimport * as utils from './actions'\n\n// @ts-expect-error debug only\nwindow.utils = utils\n\n/**\n * Internal tools for PageAgent.\n */\nexport const tools = new Map<string, Tool>()\n\n// tools.set(\n// \t'get_current_html',\n// \ttool({\n// \t\tdescription: 'Get the current (updated) simplified HTML of the page',\n// \t\tinputSchema: zod.object({}),\n// \t\texecute: function (this: PageAgent) {\n// \t\t\tthis.updateTree()\n// \t\t\treturn this.simplifiedHTML\n// \t\t},\n// \t})\n// )\n\ntools.set(\n\t'done',\n\ttool({\n\t\tdescription:\n\t\t\t'Complete task - provide a summary of results for the user. Set success=True if task completed successfully, false otherwise. Text should be your response to the user summarizing results.',\n\t\tinputSchema: zod.object({\n\t\t\ttext: zod.string(),\n\t\t\tsuccess: zod.boolean().default(true),\n\t\t}),\n\t\texecute: function (this: PageAgent, input) {\n\t\t\t// @note main loop will handle this one\n\t\t\t// this.onDone(input.text, input.success)\n\t\t},\n\t})\n)\n\ntools.set(\n\t'wait',\n\ttool({\n\t\tdescription:\n\t\t\t'Wait for x seconds. default 1s (max 10 seconds, min 1 second). This can be used to wait until the page or data is fully loaded.',\n\t\tinputSchema: zod.object({\n\t\t\tseconds: zod.number().min(1).max(10).default(1),\n\t\t}),\n\t\texecute: async function (this: PageAgent, input) {\n\t\t\tconst lastTimeUpdate = this.lastTimeUpdate\n\t\t\tconst actualWaitTime = Math.max(0, input.seconds - (Date.now() - lastTimeUpdate) / 1000)\n\t\t\tconsole.log(`actualWaitTime: ${actualWaitTime} seconds`)\n\t\t\tawait waitFor(actualWaitTime)\n\t\t\treturn `✅ Waited for ${input.seconds} seconds.` + (await getSystemInfo())\n\t\t},\n\t})\n)\n\ntools.set(\n\t'ask_user',\n\ttool({\n\t\tdescription:\n\t\t\t'Ask the user a question and wait for their answer. Use this if you need more information or clarification.',\n\t\tinputSchema: zod.object({\n\t\t\tquestion: zod.string(),\n\t\t}),\n\t\texecute: async function (this: PageAgent, input) {\n\t\t\tconst answer = await this.panel.askUser(input.question)\n\t\t\treturn `✅ Received user answer: ${answer}` + (await getSystemInfo())\n\t\t},\n\t})\n)\n\ntools.set(\n\t'click_element_by_index',\n\ttool({\n\t\tdescription: 'Click element by index',\n\t\tinputSchema: zod.object({\n\t\t\tindex: zod.int().min(0),\n\t\t}),\n\t\texecute: async function (this: PageAgent, input) {\n\t\t\tconst element = getElementByIndex(this, input.index)\n\t\t\tconst elemText = this.elementTextMap.get(input.index)\n\t\t\tawait clickElement(element)\n\n\t\t\t// @workaround: Handle links that open in new tabs\n\t\t\tif (element instanceof HTMLAnchorElement && element.target === '_blank') {\n\t\t\t\treturn `⚠️ Clicked link that opens in a new tab (${elemText ? elemText : input.index}). You are not capable of reading new tabs.`\n\t\t\t}\n\n\t\t\treturn `✅ Clicked element (${elemText ? elemText : input.index}).` + (await getSystemInfo())\n\t\t},\n\t})\n)\n\ntools.set(\n\t'input_text',\n\ttool({\n\t\tdescription: 'Click and input text into a input interactive element',\n\t\tinputSchema: zod.object({\n\t\t\tindex: zod.int().min(0),\n\t\t\ttext: zod.string(),\n\t\t}),\n\t\texecute: async function (this: PageAgent, input) {\n\t\t\tconst element = getElementByIndex(this, input.index)\n\t\t\tconst elemText = this.elementTextMap.get(input.index)\n\t\t\tawait inputTextElement(element, input.text)\n\t\t\treturn (\n\t\t\t\t`✅ Input text (${input.text}) into element (${elemText ? elemText : input.index}).` +\n\t\t\t\t(await getSystemInfo())\n\t\t\t)\n\t\t},\n\t})\n)\n\ntools.set(\n\t'select_dropdown_option',\n\ttool({\n\t\tdescription:\n\t\t\t'Select dropdown option for interactive element index by the text of the option you want to select',\n\t\tinputSchema: zod.object({\n\t\t\tindex: zod.int().min(0),\n\t\t\ttext: zod.string(),\n\t\t}),\n\t\texecute: async function (this: PageAgent, input) {\n\t\t\tconst element = getElementByIndex(this, input.index)\n\t\t\tconst elemText = this.elementTextMap.get(input.index)\n\t\t\tawait selectOptionElement(element as any, input.text)\n\t\t\treturn (\n\t\t\t\t`✅ Selected option (${input.text}) in element (${elemText ? elemText : input.index}).` +\n\t\t\t\t(await getSystemInfo())\n\t\t\t)\n\t\t},\n\t})\n)\n\n/**\n * @note Reference from browser-use\n */\ntools.set(\n\t'scroll',\n\ttool({\n\t\tdescription:\n\t\t\t'Scroll the page by specified number of pages (set down=True to scroll down, down=False to scroll up, num_pages=number of pages to scroll like 0.5 for half page, 1.0 for one page, etc.). Optional index parameter to scroll within a specific element or its scroll container (works well for dropdowns and custom UI components). Optional pixels parameter to scroll by a specific number of pixels instead of pages.',\n\t\tinputSchema: zod.object({\n\t\t\tdown: zod.boolean().default(true),\n\t\t\tnum_pages: zod.number().min(0).max(10).optional().default(0.1),\n\t\t\tpixels: zod.number().int().min(0).optional(),\n\t\t\tindex: zod.number().int().min(0).optional(),\n\t\t}),\n\t\texecute: async function (this: PageAgent, input) {\n\t\t\tconst { down, num_pages, index, pixels } = input\n\n\t\t\tconst scroll_amount = pixels ? pixels : num_pages * (down ? 1 : -1) * window.innerHeight\n\n\t\t\tconst element = index !== undefined ? getElementByIndex(this, index) : null\n\n\t\t\treturn (await scrollVertically(down, scroll_amount, element)) + (await getSystemInfo())\n\t\t},\n\t})\n)\n\ntools.set(\n\t'scroll_horizontally',\n\ttool({\n\t\tdescription:\n\t\t\t'Scroll the page or element horizontally (set right=True to scroll right, right=False to scroll left, pixels=number of pixels to scroll). Optional index parameter to scroll within a specific element or its scroll container (works well for wide tables).',\n\t\tinputSchema: zod.object({\n\t\t\tright: zod.boolean().default(true),\n\t\t\tpixels: zod.number().int().min(0),\n\t\t\tindex: zod.number().int().min(0).optional(),\n\t\t}),\n\t\texecute: async function (this: PageAgent, input) {\n\t\t\tconst { right, pixels, index } = input\n\n\t\t\tconst scroll_amount = pixels * (right ? 1 : -1)\n\n\t\t\tconst element = index !== undefined ? getElementByIndex(this, index) : null\n\n\t\t\treturn (await scrollHorizontally(right, scroll_amount, element)) + (await getSystemInfo())\n\t\t},\n\t})\n)\n\n// @todo get_dropdown_options\n// @todo select_dropdown_option\n// @todo send_keys\n// @todo upload_file\n// @todo go_back\n// @todo extract_structured_data\n","/**\n * Wait until condition becomes true\n * @returns Returns when condition becomes true, throws otherwise\n * @param timeout Timeout in milliseconds, default 0 means no timeout, throws error on timeout\n */\nexport async function waitUntil(check: () => boolean, timeout = 60 * 60_1000): Promise<boolean> {\n\tif (check()) return true\n\n\treturn new Promise((resolve, reject) => {\n\t\tconst start = Date.now()\n\t\tconst interval = setInterval(() => {\n\t\t\tif (check()) {\n\t\t\t\tclearInterval(interval)\n\t\t\t\tresolve(true)\n\t\t\t} else if (Date.now() - start > timeout) {\n\t\t\t\tclearInterval(interval)\n\t\t\t\treject(new Error('Timeout waiting for condition to become true'))\n\t\t\t}\n\t\t}, 100)\n\t})\n}\n\n//\n\nexport function truncate(text: string, maxLength: number): string {\n\tif (text.length > maxLength) {\n\t\treturn text.substring(0, maxLength) + '...'\n\t}\n\treturn text\n}\n\n//\n\nexport function trimLines(text: string): string {\n\treturn text\n\t\t.split('\\n')\n\t\t.map((line) => line.trim())\n\t\t.join('\\n')\n}\n\n//\n\nexport function randomID(existingIDs?: string[]): string {\n\tlet id = Math.random().toString(36).substring(2, 11)\n\n\tif (!existingIDs) {\n\t\treturn id\n\t}\n\n\tconst MAX_TRY = 1000\n\tlet tryCount = 0\n\n\twhile (existingIDs.includes(id)) {\n\t\tid = Math.random().toString(36).substring(2, 11)\n\t\ttryCount++\n\t\tif (tryCount > MAX_TRY) {\n\t\t\tthrow new Error('randomID: too many try')\n\t\t}\n\t}\n\n\treturn id\n}\n\n//\n\nif (!window.__PAGE_AGENT_IDS__) {\n\twindow.__PAGE_AGENT_IDS__ = []\n}\n\nconst ids = window.__PAGE_AGENT_IDS__\n\n/**\n * Generate a random ID.\n * @note Unique within this window.\n */\nexport function uid() {\n\tconst id = randomID(ids)\n\tids.push(id)\n\treturn id\n}\n","/**\n * Agent execution state management\n */\n\nexport interface Step {\n\tid: string\n\tstepNumber: number\n\ttimestamp: Date\n\ttype: 'thinking' | 'tool_executing' | 'completed' | 'error' | 'output' | 'input' | 'retry'\n\n\t// Tool execution related\n\ttoolName?: string\n\ttoolArgs?: any\n\ttoolResult?: any\n\n\t// Display data\n\tdisplayText: string\n\tduration?: number\n}\n\nexport type AgentStatus = 'idle' | 'running' | 'paused' | 'completed' | 'error'\n\nexport class UIState {\n\tprivate steps: Step[] = []\n\tprivate currentStep: Step | null = null\n\tprivate status: AgentStatus = 'idle'\n\tprivate stepCounter = 0\n\n\taddStep(stepData: Omit<Step, 'id' | 'stepNumber' | 'timestamp'>): Step {\n\t\tconst step: Step = {\n\t\t\tid: this.generateId(),\n\t\t\tstepNumber: ++this.stepCounter,\n\t\t\ttimestamp: new Date(),\n\t\t\t...stepData,\n\t\t}\n\n\t\tthis.steps.push(step)\n\t\tthis.currentStep = step\n\n\t\t// Update overall status\n\t\tthis.updateStatus(step.type)\n\n\t\treturn step\n\t}\n\n\tupdateCurrentStep(updates: Partial<Step>): Step | null {\n\t\tif (!this.currentStep) return null\n\n\t\tObject.assign(this.currentStep, updates)\n\t\treturn this.currentStep\n\t}\n\n\tgetCurrentStep(): Step | null {\n\t\treturn this.currentStep\n\t}\n\n\tgetAllSteps(): Step[] {\n\t\treturn [...this.steps]\n\t}\n\n\tgetStatus(): AgentStatus {\n\t\treturn this.status\n\t}\n\n\treset(): void {\n\t\tthis.steps = []\n\t\tthis.currentStep = null\n\t\tthis.status = 'idle'\n\t\tthis.stepCounter = 0\n\t}\n\n\tprivate updateStatus(stepType: Step['type']): void {\n\t\tswitch (stepType) {\n\t\t\tcase 'thinking':\n\t\t\tcase 'tool_executing':\n\t\t\tcase 'output':\n\t\t\tcase 'input':\n\t\t\tcase 'retry':\n\t\t\t\tthis.status = 'running'\n\t\t\t\tbreak\n\t\t\tcase 'completed':\n\t\t\t\tthis.status = 'completed'\n\t\t\t\tbreak\n\t\t\tcase 'error':\n\t\t\t\tthis.status = 'error'\n\t\t\t\tbreak\n\t\t}\n\t}\n\n\tprivate generateId(): string {\n\t\treturn `step_${Date.now()}_${Math.random().toString(36).substring(2, 11)}`\n\t}\n}\n","import type { PageAgent } from '@/PageAgent'\nimport type { I18n } from '@/i18n'\nimport { truncate } from '@/utils'\nimport type { EventBus } from '@/utils/bus'\n\nimport { type Step, UIState } from './UIState'\n\nimport styles from './Panel.module.css'\n\n/**\n * Agent control panel\n */\nexport class Panel {\n\t#wrapper: HTMLElement\n\t#indicator: HTMLElement\n\t#statusText: HTMLElement\n\t#historySection: HTMLElement\n\t#expandButton: HTMLElement\n\t#pauseButton: HTMLElement\n\t#stopButton: HTMLElement\n\t#inputSection: HTMLElement\n\t#taskInput: HTMLInputElement\n\t#bus: EventBus\n\n\t#state = new UIState()\n\t#isExpanded = false\n\t#pageAgent: PageAgent\n\t#userAnswerResolver: ((input: string) => void) | null = null\n\t#isWaitingForUserAnswer: boolean = false\n\n\tget wrapper(): HTMLElement {\n\t\treturn this.#wrapper\n\t}\n\n\tconstructor(pageAgent: PageAgent) {\n\t\tthis.#pageAgent = pageAgent\n\t\tthis.#bus = pageAgent.bus\n\t\tthis.#wrapper = this.#createWrapper()\n\t\tthis.#indicator = this.#wrapper.querySelector(`.${styles.indicator}`)!\n\t\tthis.#statusText = this.#wrapper.querySelector(`.${styles.statusText}`)!\n\t\tthis.#historySection = this.#wrapper.querySelector(`.${styles.historySection}`)!\n\t\tthis.#expandButton = this.#wrapper.querySelector(`.${styles.expandButton}`)!\n\t\tthis.#pauseButton = this.#wrapper.querySelector(`.${styles.pauseButton}`)!\n\t\tthis.#stopButton = this.#wrapper.querySelector(`.${styles.stopButton}`)!\n\t\tthis.#inputSection = this.#wrapper.querySelector(`.${styles.inputSectionWrapper}`)!\n\t\tthis.#taskInput = this.#wrapper.querySelector(`.${styles.taskInput}`)!\n\n\t\tthis.#setupEventListeners()\n\t\t// this.#expand() // debug\n\n\t\tthis.#showInputArea()\n\n\t\tthis.#bus.on('panel:show', () => this.#show())\n\t\tthis.#bus.on('panel:hide', () => this.#hide())\n\t\tthis.#bus.on('panel:reset', () => this.#reset())\n\t\tthis.#bus.on('panel:update', (stepData) => this.#update(stepData))\n\t\tthis.#bus.on('panel:expand', () => this.#expand())\n\t\tthis.#bus.on('panel:collapse', () => this.#collapse())\n\t}\n\n\t/**\n\t * Ask for user input\n\t */\n\tasync askUser(question: string): Promise<string> {\n\t\treturn new Promise((resolve) => {\n\t\t\t// Set `waiting for user answer` state\n\t\t\tthis.#isWaitingForUserAnswer = true\n\t\t\tthis.#userAnswerResolver = resolve\n\n\t\t\t// Update state to `running`\n\t\t\tthis.#update({\n\t\t\t\ttype: 'output',\n\t\t\t\tdisplayText: `询问: ${question}`,\n\t\t\t})\n\n\t\t\t// Expand history panel\n\t\t\tif (!this.#isExpanded) {\n\t\t\t\tthis.#expand()\n\t\t\t}\n\n\t\t\tthis.#showInputArea(this.#pageAgent.i18n.t('ui.panel.userAnswerPrompt'))\n\t\t})\n\t}\n\n\t/**\n\t * Dispose panel\n\t */\n\tdispose(): void {\n\t\tthis.#isWaitingForUserAnswer = false\n\t\tthis.wrapper.remove()\n\t}\n\n\t/**\n\t * Update status\n\t */\n\tasync #update(stepData: Omit<Step, 'id' | 'stepNumber' | 'timestamp'>): Promise<void> {\n\t\tconst step = this.#state.addStep(stepData)\n\n\t\t// Show animation if text changes\n\t\tconst headerText = truncate(step.displayText, 20)\n\t\tif (this.#statusText.textContent !== headerText) {\n\t\t\tawait this.#animateTextChange(headerText)\n\t\t}\n\n\t\tthis.#updateStatusIndicator(step.type)\n\t\tthis.#updateHistory()\n\n\t\t// Auto-expand history after task completion\n\t\tif (step.type === 'completed' || step.type === 'error') {\n\t\t\tif (!this.#isExpanded) {\n\t\t\t\tthis.#expand()\n\t\t\t}\n\t\t}\n\n\t\t// Control input area display based on status\n\t\tif (this.#shouldShowInputArea()) {\n\t\t\tthis.#showInputArea()\n\t\t} else {\n\t\t\tthis.#hideInputArea()\n\t\t}\n\t}\n\n\t/**\n\t * Show panel\n\t */\n\t#show(): void {\n\t\tthis.wrapper.style.display = 'block'\n\t\t// Force reflow to trigger animation\n\t\tvoid this.wrapper.offsetHeight\n\t\tthis.wrapper.style.opacity = '1'\n\t\tthis.wrapper.style.transform = 'translateX(-50%) translateY(0)'\n\t}\n\n\t/**\n\t * 隐藏面板\n\t */\n\t#hide(): void {\n\t\tthis.wrapper.style.opacity = '0'\n\t\tthis.wrapper.style.transform = 'translateX(-50%) translateY(20px)'\n\t\tthis.wrapper.style.display = 'none'\n\t}\n\n\t/**\n\t * 重置状态\n\t */\n\t#reset(): void {\n\t\tthis.#state.reset()\n\t\tthis.#statusText.textContent = this.#pageAgent.i18n.t('ui.panel.ready')\n\t\tthis.#updateStatusIndicator('thinking')\n\t\tthis.#updateHistory()\n\t\tthis.#collapse()\n\t\t// Reset pause state\n\t\tthis.#pageAgent.paused = false\n\t\tthis.#updatePauseButton()\n\t\t// Reset user input state\n\t\tthis.#isWaitingForUserAnswer = false\n\t\tthis.#userAnswerResolver = null\n\t\t// Show input area\n\t\tthis.#showInputArea()\n\t}\n\n\t/**\n\t * Toggle pause state\n\t */\n\t#togglePause(): void {\n\t\tthis.#pageAgent.paused = !this.#pageAgent.paused\n\t\tthis.#updatePauseButton()\n\n\t\t// Update status display\n\t\tif (this.#pageAgent.paused) {\n\t\t\tthis.#statusText.textContent = '暂停中,稍后'\n\t\t\tthis.#updateStatusIndicator('thinking') // Use existing thinking state\n\t\t} else {\n\t\t\tthis.#statusText.textContent = '继续执行'\n\t\t\tthis.#updateStatusIndicator('tool_executing') // Restore to execution state\n\t\t}\n\t}\n\n\t/**\n\t * 更新暂停按钮状态\n\t */\n\t#updatePauseButton(): void {\n\t\tif (this.#pageAgent.paused) {\n\t\t\tthis.#pauseButton.textContent = '▶'\n\t\t\tthis.#pauseButton.title = '继续'\n\t\t\tthis.#pauseButton.classList.add(styles.paused)\n\t\t} else {\n\t\t\tthis.#pauseButton.textContent = '⏸︎'\n\t\t\tthis.#pauseButton.title = '暂停'\n\t\t\tthis.#pauseButton.classList.remove(styles.paused)\n\t\t}\n\t}\n\n\t/**\n\t * 终止 Agent\n\t */\n\t#stopAgent(): void {\n\t\t// Update status display\n\t\tthis.#update({\n\t\t\ttype: 'error',\n\t\t\tdisplayText: '任务已终止',\n\t\t})\n\n\t\tthis.#pageAgent.dispose()\n\t}\n\n\t/**\n\t * 提交任务\n\t */\n\t#submitTask() {\n\t\tconst input = this.#taskInput.value.trim()\n\t\tif (!input) return\n\n\t\t// Hide input area\n\t\tthis.#hideInputArea()\n\n\t\tif (this.#isWaitingForUserAnswer) {\n\t\t\t// Handle user input mode\n\t\t\tthis.#handleUserAnswer(input)\n\t\t} else {\n\t\t\tthis.#pageAgent.execute(input)\n\t\t}\n\t}\n\n\t/**\n\t * 处理用户回答\n\t */\n\t#handleUserAnswer(input: string): void {\n\t\t// Add user input to history\n\t\tthis.#update({\n\t\t\ttype: 'input',\n\t\t\tdisplayText: `用户回答: ${input}`,\n\t\t})\n\n\t\t// Reset state\n\t\tthis.#isWaitingForUserAnswer = false\n\n\t\t// Call resolver to return user input\n\t\tif (this.#userAnswerResolver) {\n\t\t\tthis.#userAnswerResolver(input)\n\t\t\tthis.#userAnswerResolver = null\n\t\t}\n\t}\n\n\t/**\n\t * 显示输入区域\n\t */\n\t#showInputArea(placeholder?: string): void {\n\t\t// Clear input field\n\t\tthis.#taskInput.value = ''\n\t\tthis.#taskInput.placeholder = placeholder || '输入新任务,详细描述步骤,回车提交'\n\t\tthis.#inputSection.classList.remove(styles.hidden)\n\t\t// Focus on input field\n\t\tsetTimeout(() => {\n\t\t\tthis.#taskInput.focus()\n\t\t}, 100)\n\t}\n\n\t/**\n\t * 隐藏输入区域\n\t */\n\t#hideInputArea(): void {\n\t\tthis.#inputSection.classList.add(styles.hidden)\n\t}\n\n\t/**\n\t * 检查是否应该显示输入区域\n\t */\n\t#shouldShowInputArea(): boolean {\n\t\t// Always show input area if waiting for user input\n\t\tif (this.#isWaitingForUserAnswer) return true\n\n\t\tconst steps = this.#state.getAllSteps()\n\t\tif (steps.length === 0) {\n\t\t\treturn true // Initial state\n\t\t}\n\n\t\tconst lastStep = steps[steps.length - 1]\n\t\treturn lastStep.type === 'completed' || lastStep.type === 'error'\n\t}\n\n\t#createWrapper(): HTMLElement {\n\t\tconst wrapper = document.createElement('div')\n\t\twrapper.id = 'page-agent-runtime_agent-panel'\n\t\twrapper.className = `${styles.wrapper} ${styles.collapsed}`\n\t\twrapper.setAttribute('data-browser-use-ignore', 'true')\n\n\t\twrapper.innerHTML = `\n\t\t\t<div class=\"${styles.background}\"></div>\n\t\t\t<div class=\"${styles.historySectionWrapper}\">\n\t\t\t\t<div class=\"${styles.historySection}\">\n\t\t\t\t\t${this.#createHistoryItem({\n\t\t\t\t\t\tid: 'placeholder',\n\t\t\t\t\t\tstepNumber: 0,\n\t\t\t\t\t\ttimestamp: new Date(),\n\t\t\t\t\t\ttype: 'thinking',\n\t\t\t\t\t\tdisplayText: '等待任务开始...',\n\t\t\t\t\t})}\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t<div class=\"${styles.header}\">\n\t\t\t\t<div class=\"${styles.statusSection}\">\n\t\t\t\t\t<div class=\"${styles.indicator} ${styles.thinking}\"></div>\n\t\t\t\t\t<div class=\"${styles.statusText}\">准备就绪</div>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"${styles.controls}\">\n\t\t\t\t\t<button class=\"${styles.controlButton} ${styles.expandButton}\" title=\"展开历史\">\n\t\t\t\t\t\t▼\n\t\t\t\t\t</button>\n\t\t\t\t\t<button class=\"${styles.controlButton} ${styles.pauseButton}\" title=\"暂停\">\n\t\t\t\t\t\t⏸︎\n\t\t\t\t\t</button>\n\t\t\t\t\t<button class=\"${styles.controlButton} ${styles.stopButton}\" title=\"终止\">\n\t\t\t\t\t\tX\n\t\t\t\t\t</button>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t<div class=\"${styles.inputSectionWrapper} ${styles.hidden}\">\n\t\t\t\t<div class=\"${styles.inputSection}\">\n\t\t\t\t\t<input \n\t\t\t\t\t\ttype=\"text\" \n\t\t\t\t\t\tclass=\"${styles.taskInput}\" \n\t\t\t\t\t\tmaxlength=\"200\"\n\t\t\t\t\t/>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t`\n\n\t\tdocument.body.appendChild(wrapper)\n\t\treturn wrapper\n\t}\n\n\t#setupEventListeners(): void {\n\t\t// Click header area to expand/collapse\n\t\tconst header = this.wrapper.querySelector(`.${styles.header}`)!\n\t\theader.addEventListener('click', (e) => {\n\t\t\t// Don't trigger expand/collapse if clicking on buttons\n\t\t\tif ((e.target as HTMLElement).closest(`.${styles.controlButton}`)) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tthis.#toggle()\n\t\t})\n\n\t\t// Expand button\n\t\tthis.#expandButton.addEventListener('click', (e) => {\n\t\t\te.stopPropagation()\n\t\t\tthis.#toggle()\n\t\t})\n\n\t\t// Pause/continue button\n\t\tthis.#pauseButton.addEventListener('click', (e) => {\n\t\t\te.stopPropagation()\n\t\t\tthis.#togglePause()\n\t\t})\n\n\t\t// Stop button\n\t\tthis.#stopButton.addEventListener('click', (e) => {\n\t\t\te.stopPropagation()\n\t\t\tthis.#stopAgent()\n\t\t})\n\n\t\t// Submit on Enter key in input field\n\t\tthis.#taskInput.addEventListener('keydown', (e) => {\n\t\t\tif (e.isComposing) return // Ignore IME composition keys\n\t\t\tif (e.key === 'Enter') {\n\t\t\t\te.preventDefault()\n\t\t\t\tthis.#submitTask()\n\t\t\t}\n\t\t})\n\n\t\t// Prevent input area click event bubbling\n\t\tthis.#inputSection.addEventListener('click', (e) => {\n\t\t\te.stopPropagation()\n\t\t})\n\t}\n\n\t#toggle(): void {\n\t\tif (this.#isExpanded) {\n\t\t\tthis.#collapse()\n\t\t} else {\n\t\t\tthis.#expand()\n\t\t}\n\t}\n\n\t#expand(): void {\n\t\tthis.#isExpanded = true\n\t\tthis.wrapper.classList.remove(styles.collapsed)\n\t\tthis.wrapper.classList.add(styles.expanded)\n\t\tthis.#expandButton.textContent = '▲'\n\t}\n\n\t#collapse(): void {\n\t\tthis.#isExpanded = false\n\t\tthis.wrapper.classList.remove(styles.expanded)\n\t\tthis.wrapper.classList.add(styles.collapsed)\n\t\tthis.#expandButton.textContent = '▼'\n\t}\n\n\tasync #animateTextChange(newText: string): Promise<void> {\n\t\treturn new Promise((resolve) => {\n\t\t\t// Fade out current text\n\t\t\tthis.#statusText.classList.add(styles.fadeOut)\n\n\t\t\tsetTimeout(() => {\n\t\t\t\t// Update text content\n\t\t\t\tthis.#statusText.textContent = newText\n\n\t\t\t\t// Fade in new text\n\t\t\t\tthis.#statusText.classList.remove(styles.fadeOut)\n\t\t\t\tthis.#statusText.classList.add(styles.fadeIn)\n\n\t\t\t\tsetTimeout(() => {\n\t\t\t\t\tthis.#statusText.classList.remove(styles.fadeIn)\n\t\t\t\t\tresolve()\n\t\t\t\t}, 300)\n\t\t\t}, 150) // Half the duration of fade out animation\n\t\t})\n\t}\n\n\t#updateStatusIndicator(type: Step['type']): void {\n\t\t// Clear all status classes\n\t\tthis.#indicator.className = styles.indicator\n\n\t\t// Add corresponding status class\n\t\tthis.#indicator.classList.add(styles[type])\n\t}\n\n\t#updateHistory(): void {\n\t\tconst steps = this.#state.getAllSteps()\n\n\t\tthis.#historySection.innerHTML = steps\n\t\t\t.slice(-10) // Only show last 10 items\n\t\t\t.map((step) => this.#createHistoryItem(step))\n\t\t\t.join('')\n\n\t\t// Scroll to bottom to show latest records\n\t\tthis.#scrollToBottom()\n\t}\n\n\t#scrollToBottom(): void {\n\t\t// Execute in next event loop to ensure DOM update completion\n\t\tsetTimeout(() => {\n\t\t\tthis.#historySection.scrollTop = this.#historySection.scrollHeight\n\t\t}, 0)\n\t}\n\n\t#createHistoryItem(step: Step): string {\n\t\tconst time = step.timestamp.toLocaleTimeString('zh-CN', {\n\t\t\thour12: false,\n\t\t\thour: '2-digit',\n\t\t\tminute: '2-digit',\n\t\t\tsecond: '2-digit',\n\t\t})\n\n\t\tlet typeClass = ''\n\t\tlet statusIcon = ''\n\n\t\t// Set styles and icons based on step type\n\t\tif (step.type === 'completed') {\n\t\t\t// Check if this is a result from done tool\n\t\t\tif (step.toolName === 'done') {\n\t\t\t\t// @todo not right\n\t\t\t\t// Judge success or failure based on result\n\t\t\t\tconst isSuccess =\n\t\t\t\t\t!step.toolResult ||\n\t\t\t\t\t(!step.toolResult.includes('失败') && !step.toolResult.includes('错误'))\n\t\t\t\ttypeClass = isSuccess ? styles.doneSuccess : styles.doneError\n\t\t\t\tstatusIcon = isSuccess ? '🎉' : '❌'\n\t\t\t} else {\n\t\t\t\ttypeClass = styles.completed\n\t\t\t\tstatusIcon = '✅'\n\t\t\t}\n\t\t} else if (step.type === 'error') {\n\t\t\ttypeClass = styles.error\n\t\t\tstatusIcon = '❌'\n\t\t} else if (step.type === 'tool_executing') {\n\t\t\tstatusIcon = '⚙️'\n\t\t} else if (step.type === 'output') {\n\t\t\ttypeClass = styles.output\n\t\t\tstatusIcon = '🤖'\n\t\t} else if (step.type === 'input') {\n\t\t\ttypeClass = styles.input\n\t\t\tstatusIcon = '🎯'\n\t\t} else if (step.type === 'retry') {\n\t\t\ttypeClass = styles.retry\n\t\t\tstatusIcon = '🔄'\n\t\t} else {\n\t\t\tstatusIcon = '🧠'\n\t\t}\n\n\t\treturn `\n\t\t\t<div class=\"${styles.historyItem} ${typeClass}\">\n\t\t\t\t<div class=\"${styles.historyContent}\">\n\t\t\t\t\t<span class=\"${styles.statusIcon}\">${statusIcon}</span>\n\t\t\t\t\t<span>${step.displayText}</span>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"${styles.historyMeta}\">\n\t\t\t\t\t步骤 ${step.stepNumber} · ${time}\n\t\t\t\t\t${step.duration ? ` · ${step.duration}ms` : ''}\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t`\n\t}\n}\n\n/**\n * 获取工具执行时的显示文本\n */\nexport function getToolExecutingText(toolName: string, args: any, i18n: I18n): string {\n\tswitch (toolName) {\n\t\tcase 'click_element_by_index':\n\t\t\treturn i18n.t('ui.tools.clicking', { index: args.index })\n\t\tcase 'input_text':\n\t\t\treturn i18n.t('ui.tools.inputting', { index: args.index })\n\t\tcase 'select_dropdown_option':\n\t\t\treturn i18n.t('ui.tools.selecting', { text: args.text })\n\t\tcase 'scroll':\n\t\t\treturn i18n.t('ui.tools.scrolling')\n\t\tcase 'wait':\n\t\t\treturn i18n.t('ui.tools.waiting', { seconds: args.seconds })\n\t\tcase 'done':\n\t\t\treturn i18n.t('ui.tools.done')\n\t\tdefault:\n\t\t\treturn i18n.t('ui.tools.executing', { toolName })\n\t}\n}\n\n/**\n * 获取工具完成时的显示文本\n */\nexport function getToolCompletedText(toolName: string, args: any, i18n: I18n): string | null {\n\tswitch (toolName) {\n\t\tcase 'click_element_by_index':\n\t\t\treturn i18n.t('ui.tools.clicked', { index: args.index })\n\t\tcase 'input_text':\n\t\t\treturn i18n.t('ui.tools.inputted', { text: args.text })\n\t\tcase 'select_dropdown_option':\n\t\t\treturn i18n.t('ui.tools.selected', { text: args.text })\n\t\tcase 'scroll':\n\t\t\treturn i18n.t('ui.tools.scrolled')\n\t\tcase 'wait':\n\t\t\treturn i18n.t('ui.tools.waited')\n\t\tcase 'done':\n\t\t\treturn null\n\t\tdefault:\n\t\t\treturn null\n\t}\n}\n","/**\n * Checks for common dark mode CSS classes on the html or body elements.\n * @returns {boolean} - True if a common dark mode class is found.\n */\nfunction hasDarkModeClass() {\n\tconst DFEAULT_DARK_MODE_CLASSES = ['dark', 'dark-mode', 'theme-dark', 'night', 'night-mode']\n\n\tconst htmlElement = document.documentElement\n\tconst bodyElement = document.body\n\n\t// Check class names on <html> and <body>\n\tfor (const className of DFEAULT_DARK_MODE_CLASSES) {\n\t\tif (htmlElement.classList.contains(className) || bodyElement.classList.contains(className)) {\n\t\t\treturn true\n\t\t}\n\t}\n\n\t// Some sites use data attributes\n\tconst darkThemeAttribute = htmlElement.getAttribute('data-theme')\n\tif (darkThemeAttribute?.toLowerCase().includes('dark')) {\n\t\treturn true\n\t}\n\n\treturn false\n}\n\n/**\n * Parses an RGB or RGBA color string and returns an object with r, g, b properties.\n * @param {string} colorString - e.g., \"rgb(34, 34, 34)\" or \"rgba(0, 0, 0, 0.5)\"\n * @returns {{r: number, g: number, b: number}|null}\n */\nfunction parseRgbColor(colorString: string) {\n\tconst rgbMatch = /rgba?\\((\\d+),\\s*(\\d+),\\s*(\\d+)/.exec(colorString)\n\tif (!rgbMatch) {\n\t\treturn null // Not a valid rgb/rgba string\n\t}\n\treturn {\n\t\tr: parseInt(rgbMatch[1]),\n\t\tg: parseInt(rgbMatch[2]),\n\t\tb: parseInt(rgbMatch[3]),\n\t}\n}\n\n/**\n * Determines if a color is \"dark\" based on its calculated luminance.\n * @param {string} colorString - The CSS color string (e.g., \"rgb(50, 50, 50)\").\n * @param {number} threshold - A value between 0 and 255. Colors with luminance below this will be considered dark. Default is 128.\n * @returns {boolean} - True if the color is considered dark.\n */\nfunction isColorDark(colorString: string, threshold = 128) {\n\tif (!colorString || colorString === 'transparent' || colorString.startsWith('rgba(0, 0, 0, 0)')) {\n\t\treturn false // Transparent is not dark\n\t}\n\n\tconst rgb = parseRgbColor(colorString)\n\tif (!rgb) {\n\t\treturn false // Could not parse color\n\t}\n\n\t// Calculate perceived luminance using the standard formula\n\tconst luminance = 0.299 * rgb.r + 0.587 * rgb.g + 0.114 * rgb.b\n\n\treturn luminance < threshold\n}\n\n/**\n * Checks the background color of the body element to determine if the page is dark.\n * @returns {boolean}\n */\nfunction isBackgroundDark() {\n\t// We check both <html> and <body> because some pages set the color on <html>\n\tconst htmlStyle = window.getComputedStyle(document.documentElement)\n\tconst bodyStyle = window.getComputedStyle(document.body)\n\n\t// Get background colors\n\tconst htmlBgColor = htmlStyle.backgroundColor\n\tconst bodyBgColor = bodyStyle.backgroundColor\n\n\t// The body's background might be transparent, in which case we should\n\t// fall back to the html element's background.\n\tif (isColorDark(bodyBgColor)) {\n\t\treturn true\n\t} else if (bodyBgColor === 'transparent' || bodyBgColor.startsWith('rgba(0, 0, 0, 0)')) {\n\t\treturn isColorDark(htmlBgColor)\n\t}\n\n\treturn false\n}\n\n/**\n * A comprehensive function to determine if the page is currently in a dark theme.\n * It combines class checking and background color analysis.\n * @returns {boolean} - True if the page is likely dark.\n */\nexport function isPageDark() {\n\t// Strategy 1: Check for common dark mode classes\n\tif (hasDarkModeClass()) {\n\t\treturn true\n\t}\n\n\t// Strategy 2: Analyze the computed background color\n\tif (isBackgroundDark()) {\n\t\treturn true\n\t}\n\n\t// @TODO add more checks here, e.g., analyzing text color,\n\t// or checking the background of major layout elements like <main> or #app.\n\n\treturn false\n}\n","import { Motion } from 'ai-motion'\n\nimport { isPageDark } from '@/utils/checkDarkMode'\n\nimport styles from './SimulatorMask.module.css'\nimport cursorStyles from './cursor.module.css'\n\nexport class SimulatorMask {\n\twrapper = document.createElement('div')\n\tmotion = new Motion({\n\t\tmode: isPageDark() ? 'dark' : 'light',\n\t\tstyles: {\n\t\t\tposition: 'absolute',\n\t\t\tinset: '0',\n\t\t},\n\t})\n\n\t#cursor = document.createElement('div')\n\n\t#currentCursorX = 0\n\t#currentCursorY = 0\n\n\t#targetCursorX = 0\n\t#targetCursorY = 0\n\n\tconstructor() {\n\t\tthis.wrapper.id = 'page-agent-runtime_simulator-mask'\n\t\tthis.wrapper.className = styles.wrapper\n\t\tthis.wrapper.setAttribute('data-browser-use-ignore', 'true')\n\n\t\tthis.wrapper.appendChild(this.motion.element)\n\t\tthis.motion.autoResize(this.wrapper)\n\n\t\t// Capture all mouse, keyboard, and wheel events\n\t\tthis.wrapper.addEventListener('click', (e) => {\n\t\t\te.stopPropagation()\n\t\t\te.preventDefault()\n\t\t})\n\t\tthis.wrapper.addEventListener('mousedown', (e) => {\n\t\t\te.stopPropagation()\n\t\t\te.preventDefault()\n\t\t})\n\t\tthis.wrapper.addEventListener('mouseup', (e) => {\n\t\t\te.stopPropagation()\n\t\t\te.preventDefault()\n\t\t})\n\t\tthis.wrapper.addEventListener('mousemove', (e) => {\n\t\t\te.stopPropagation()\n\t\t\te.preventDefault()\n\t\t})\n\t\tthis.wrapper.addEventListener('wheel', (e) => {\n\t\t\te.stopPropagation()\n\t\t\te.preventDefault()\n\t\t})\n\t\tthis.wrapper.addEventListener('keydown', (e) => {\n\t\t\te.stopPropagation()\n\t\t\te.preventDefault()\n\t\t})\n\t\tthis.wrapper.addEventListener('keyup', (e) => {\n\t\t\te.stopPropagation()\n\t\t\te.preventDefault()\n\t\t})\n\n\t\t// Create AI cursor\n\t\tthis.#createCursor()\n\t\t// this.show()\n\n\t\tdocument.body.appendChild(this.wrapper)\n\n\t\tthis.#moveCursorToTarget()\n\n\t\twindow.addEventListener('PageAgent::MovePointerTo', (event: Event) => {\n\t\t\tconst { x, y } = (event as CustomEvent).detail\n\t\t\tthis.setCursorPosition(x, y)\n\t\t})\n\n\t\twindow.addEventListener('PageAgent::ClickPointer', (event: Event) => {\n\t\t\tthis.triggerClickAnimation()\n\t\t})\n\t}\n\n\t#createCursor() {\n\t\tthis.#cursor.className = cursorStyles.cursor\n\n\t\t// Create ripple effect container\n\t\tconst rippleContainer = document.createElement('div')\n\t\trippleContainer.className = cursorStyles.cursorRipple\n\t\tthis.#cursor.appendChild(rippleContainer)\n\n\t\t// Create filling layer\n\t\tconst fillingLayer = document.createElement('div')\n\t\tfillingLayer.className = cursorStyles.cursorFilling\n\t\tthis.#cursor.appendChild(fillingLayer)\n\n\t\t// Create border layer\n\t\tconst borderLayer = document.createElement('div')\n\t\tborderLayer.className = cursorStyles.cursorBorder\n\t\tthis.#cursor.appendChild(borderLayer)\n\n\t\tthis.wrapper.appendChild(this.#cursor)\n\t}\n\n\t#moveCursorToTarget() {\n\t\tconst newX = this.#currentCursorX + (this.#targetCursorX - this.#currentCursorX) * 0.2\n\t\tconst newY = this.#currentCursorY + (this.#targetCursorY - this.#currentCursorY) * 0.2\n\n\t\tconst xDistance = Math.abs(newX - this.#targetCursorX)\n\t\tif (xDistance > 0) {\n\t\t\tif (xDistance < 2) {\n\t\t\t\tthis.#currentCursorX = this.#targetCursorX\n\t\t\t} else {\n\t\t\t\tthis.#currentCursorX = newX\n\t\t\t}\n\t\t\tthis.#cursor.style.left = `${this.#currentCursorX}px`\n\t\t}\n\n\t\tconst yDistance = Math.abs(newY - this.#targetCursorY)\n\t\tif (yDistance > 0) {\n\t\t\tif (yDistance < 2) {\n\t\t\t\tthis.#currentCursorY = this.#targetCursorY\n\t\t\t} else {\n\t\t\t\tthis.#currentCursorY = newY\n\t\t\t}\n\t\t\tthis.#cursor.style.top = `${this.#currentCursorY}px`\n\t\t}\n\n\t\trequestAnimationFrame(() => this.#moveCursorToTarget())\n\t}\n\n\tsetCursorPosition(x: number, y: number) {\n\t\tthis.#targetCursorX = x\n\t\tthis.#targetCursorY = y\n\t}\n\n\ttriggerClickAnimation() {\n\t\tthis.#cursor.classList.remove(cursorStyles.clicking)\n\t\t// Force reflow to restart animation\n\t\tvoid this.#cursor.offsetHeight\n\t\tthis.#cursor.classList.add(cursorStyles.clicking)\n\t}\n\n\tshow() {\n\t\tthis.motion.start()\n\t\tthis.motion.fadeIn()\n\n\t\tthis.wrapper.style.display = 'block'\n\n\t\t// Initialize cursor position\n\t\tthis.#currentCursorX = window.innerWidth / 2\n\t\tthis.#currentCursorY = window.innerHeight / 2\n\t\tthis.#targetCursorX = this.#currentCursorX\n\t\tthis.#targetCursorY = this.#currentCursorY\n\t\tthis.#cursor.style.left = `${this.#currentCursorX}px`\n\t\tthis.#cursor.style.top = `${this.#currentCursorY}px`\n\t}\n\n\thide() {\n\t\tthis.motion.fadeOut()\n\t\tthis.motion.pause()\n\n\t\tthis.#cursor.classList.remove(cursorStyles.clicking)\n\n\t\tsetTimeout(() => {\n\t\t\tthis.wrapper.style.display = 'none'\n\t\t}, 800) // Match the animation duration\n\t}\n\n\tdispose() {\n\t\tthis.motion.dispose()\n\t\tthis.wrapper.remove()\n\t}\n}\n","/**\n * Copyright (C) 2025 Alibaba Group Holding Limited\n * All rights reserved.\n */\nimport { tool } from 'ai'\nimport type { LanguageModelUsage, ToolSet } from 'ai'\nimport chalk from 'chalk'\nimport zod from 'zod'\n\nimport type { PageAgentConfig } from './config'\nimport { MACRO_TOOL_NAME, MAX_STEPS, VIEWPORT_EXPANSION } from './config/constants'\nimport * as dom from './dom'\nimport { FlatDomTree, InteractiveElementDomNode } from './dom/dom_tree/type'\nimport { getPageInfo } from './dom/getPageInfo'\nimport { I18n } from './i18n'\nimport { LLM } from './llms'\nimport { patchReact } from './patches/react'\nimport SYSTEM_PROMPT from './prompts/system_prompt.md?raw'\nimport { tools } from './tools'\nimport { Panel, getToolCompletedText, getToolExecutingText } from './ui/Panel'\nimport { SimulatorMask } from './ui/SimulatorMask'\nimport { trimLines, uid, waitUntil } from './utils'\nimport { assert } from './utils/assert'\nimport { getEventBus } from './utils/bus'\n\nexport type { PageAgentConfig }\n\nexport interface AgentBrain {\n\t// thinking?: string\n\tevaluation_previous_goal: string\n\tmemory: string\n\tnext_goal: string\n}\n\nexport interface AgentHistory {\n\tbrain: AgentBrain\n\taction: {\n\t\tname: string\n\t\tinput: any\n\t\toutput: any\n\t}\n\tusage: LanguageModelUsage\n}\n\nexport interface ExecutionResult {\n\tsuccess: boolean\n\tdata: string\n\thistory: AgentHistory[]\n}\n\nexport class PageAgent extends EventTarget {\n\tconfig: PageAgentConfig\n\tid = uid()\n\tbus = getEventBus(this.id)\n\ti18n: I18n\n\tpaused = false\n\tdisposed = false\n\ttask = ''\n\n\t#llm: LLM\n\t#totalWaitTime = 0\n\t#abortController = new AbortController()\n\n\t/** Corresponds to eval_page in browser-use */\n\tflatTree: FlatDomTree | null = null\n\t/**\n\t * All highlighted index-mapped interactive elements\n\t * Corresponds to DOMState.selector_map in browser-use\n\t */\n\tselectorMap = new Map<number, InteractiveElementDomNode>()\n\t/** highlight index -> element text */\n\telementTextMap = new Map<number, string>()\n\t/** Corresponds to clickable_elements_to_string in browser-use */\n\tsimplifiedHTML = '<EMPTY>'\n\t/** last time the tree was updated */\n\tlastTimeUpdate = 0\n\n\t/** Corresponds to actions in browser-use */\n\ttools = new Map(tools)\n\t/** Fullscreen mask */\n\tmask = new SimulatorMask()\n\t/** Interactive panel */\n\tpanel = new Panel(this)\n\t/** History records */\n\thistory: AgentHistory[] = []\n\n\tconstructor(config: PageAgentConfig = {}) {\n\t\tsuper()\n\n\t\tthis.config = config\n\t\tthis.#llm = new LLM(this.config, this.id)\n\t\tthis.i18n = new I18n(this.config.language)\n\n\t\tpatchReact(this)\n\t}\n\n\t/**\n\t * @todo maybe return something?\n\t */\n\tasync execute(task: string): Promise<ExecutionResult> {\n\t\tif (!task) throw new Error('Task is required')\n\t\tthis.task = task\n\n\t\t// Show mask and panel\n\t\tthis.mask.show()\n\n\t\tthis.bus.emit('panel:show')\n\t\tthis.bus.emit('panel:reset')\n\n\t\tthis.bus.emit('panel:update', {\n\t\t\ttype: 'input',\n\t\t\tdisplayText: task,\n\t\t})\n\n\t\tif (this.#abortController) {\n\t\t\tthis.#abortController.abort()\n\t\t\tthis.#abortController = new AbortController()\n\t\t}\n\n\t\tthis.history = []\n\n\t\ttry {\n\t\t\tlet step = 0\n\n\t\t\twhile (true) {\n\t\t\t\tconsole.group(`step: ${step + 1}`)\n\n\t\t\t\t// abort\n\t\t\t\tif (this.#abortController.signal.aborted) throw new Error('AbortError')\n\t\t\t\t// pause\n\t\t\t\tawait waitUntil(() => !this.paused)\n\n\t\t\t\t// Update status to thinking\n\t\t\t\tconsole.log(chalk.blue('Thinking...'))\n\t\t\t\tthis.bus.emit('panel:update', {\n\t\t\t\t\ttype: 'thinking',\n\t\t\t\t\tdisplayText: this.i18n.t('ui.panel.thinking'),\n\t\t\t\t})\n\n\t\t\t\tconst result = await this.#llm.invoke(\n\t\t\t\t\t[\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\trole: 'system',\n\t\t\t\t\t\t\tcontent: this.#getSystemPrompt(),\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\trole: 'user',\n\t\t\t\t\t\t\tcontent: this.#assembleUserPrompt(),\n\t\t\t\t\t\t},\n\t\t\t\t\t],\n\t\t\t\t\t// tools,\n\t\t\t\t\tthis.#packMacroTool(),\n\t\t\t\t\tthis.#abortController.signal\n\t\t\t\t)\n\n\t\t\t\tconst toolResult = result.toolResult\n\t\t\t\tconst input = toolResult.input\n\t\t\t\tconst output = toolResult.output\n\t\t\t\tconst brain = {\n\t\t\t\t\tthinking: input.thinking,\n\t\t\t\t\tevaluation_previous_goal: input.evaluation_previous_goal,\n\t\t\t\t\tmemory: input.memory,\n\t\t\t\t\tnext_goal: input.next_goal,\n\t\t\t\t}\n\t\t\t\tconst actionName = Object.keys(input.action)[0]\n\t\t\t\tconst action = {\n\t\t\t\t\tname: actionName,\n\t\t\t\t\tinput: input.action[actionName],\n\t\t\t\t\toutput: output,\n\t\t\t\t}\n\n\t\t\t\tthis.history.push({\n\t\t\t\t\tbrain,\n\t\t\t\t\taction,\n\t\t\t\t\tusage: result.usage,\n\t\t\t\t})\n\n\t\t\t\tconsole.log(chalk.green('Step finished:'), actionName)\n\t\t\t\tconsole.groupEnd()\n\n\t\t\t\tstep++\n\t\t\t\tif (step > MAX_STEPS) {\n\t\t\t\t\tthis.#onDone('Step count exceeded maximum limit', false)\n\t\t\t\t\treturn {\n\t\t\t\t\t\tsuccess: false,\n\t\t\t\t\t\tdata: 'Step count exceeded maximum limit',\n\t\t\t\t\t\thistory: this.history,\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (actionName === 'done') {\n\t\t\t\t\tconst success = action.input.success || false\n\t\t\t\t\tconst text = action.input.text || 'no text provided'\n\t\t\t\t\tconsole.log(chalk.green.bold('Task completed'), success, text)\n\t\t\t\t\tthis.#onDone(text, success)\n\t\t\t\t\treturn {\n\t\t\t\t\t\tsuccess,\n\t\t\t\t\t\tdata: text,\n\t\t\t\t\t\thistory: this.history,\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t} catch (error: unknown) {\n\t\t\tconsole.error('Task failed', error)\n\t\t\tthis.#onDone(String(error), false)\n\t\t\treturn {\n\t\t\t\tsuccess: false,\n\t\t\t\tdata: String(error),\n\t\t\t\thistory: this.history,\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Merge all tools into a single MacroTool with the following input:\n\t * - thinking: string\n\t * - evaluation_previous_goal: string\n\t * - memory: string\n\t * - next_goal: string\n\t * - action: { toolName: toolInput }\n\t * where action must be selected from tools defined in this.tools\n\t *\n\t * @topic 要不要合并成一个 tool?\n\t * @facts\n\t * - 我们需要模型每步返回 evaluation/memory/goal 等思考过程\n\t * - browser use 合并成一个巨大的 tool\n\t * ```json\n\t * {\n\t * \"memory\": \"...\",\n\t * \"goal\": \"...\",\n\t * \"actions\": [\n\t * {\n\t * \"name\": \"...\",\n\t * \"args\": \"...\"\n\t * }\n\t * // ...\n\t * ]\n\t * }\n\t * ```\n\t * - qwen 目前必须指定 function name 来确保 tool call\n\t * @reasoning\n\t * - 不能为了 qwen 的缺陷而设计系统\n\t * - 更复杂的 tool 更容易出错\n\t * - 分散的 tool 更容易利用 ai-sdk 的重试机制,也更容易处理错误\n\t * - 不能用额外的步骤生成这些数据,不仅性能过差,而且 goal 之类的必须和 call 一起生成\n\t * @options\n\t * - Plan @A\n\t * - 和 browser use 使用完全一致的做法,合并成一个大 tool,要求每次调用\n\t * - 会把 tool 定义变得非常复杂,增加出错率\n\t * - Plan @B\n\t * - 每次调用两个 tool,其中一个用来输出思考\n\t * - 很难用提示词 enforce 这么复杂的规则\n\t * - Plan @C\n\t * - 自动为每个 tool 增加固定的 reasoning/memory/goal 等输入,并自动拦截提取这些数据\n\t * - 会让 tool 定义变得很长\n\t * @conclusion\n\t * - 使用 @A\n\t */\n\t#packMacroTool(): ToolSet {\n\t\tconst tools = this.tools\n\t\t// discriminated version\n\t\t// @note Success rate ~0, model seems unable to understand discriminated union\n\n\t\t// // Create discriminated union schemas from tools\n\t\t// const actionSchemas = Array.from(tools.entries()).map(([toolName, tool]) => {\n\t\t// \treturn zod.object({\n\t\t// \t\tname: zod.literal(toolName),\n\t\t// \t\tinput: tool.inputSchema,\n\t\t// \t})\n\t\t// })\n\n\t\t// // Ensure at least one tool exists\n\t\t// assert(actionSchemas.length, 'No tools available to create macro tool')\n\n\t\t// const actionSchema = zod.discriminatedUnion('name', actionSchemas as any)\n\n\t\t// union version\n\t\tconst actionSchemas = Array.from(tools.entries()).map(([toolName, tool]) => {\n\t\t\treturn zod.object({\n\t\t\t\t[toolName]: tool.inputSchema,\n\t\t\t})\n\t\t})\n\n\t\tconst actionSchema = zod.union(actionSchemas)\n\n\t\treturn {\n\t\t\t[MACRO_TOOL_NAME]: tool({\n\t\t\t\t// description: 'Output the result of the agent',\n\t\t\t\tinputSchema: zod.object({\n\t\t\t\t\t// thinking: zod.string().optional(),\n\t\t\t\t\tevaluation_previous_goal: zod.string().optional(),\n\t\t\t\t\tmemory: zod.string().optional(),\n\t\t\t\t\tnext_goal: zod.string().optional(),\n\t\t\t\t\taction: actionSchema,\n\t\t\t\t}),\n\t\t\t\texecute: async (input, options) => {\n\t\t\t\t\t// abort\n\t\t\t\t\tif (this.#abortController.signal.aborted) throw new Error('AbortError')\n\t\t\t\t\t// pause\n\t\t\t\t\tawait waitUntil(() => !this.paused)\n\n\t\t\t\t\tconsole.log(chalk.blue.bold('MacroTool execute'), input)\n\t\t\t\t\tconst action = input.action!\n\n\t\t\t\t\tconst toolName = Object.keys(action)[0]\n\t\t\t\t\tconst toolInput = action[toolName]\n\t\t\t\t\tconst brain = trimLines(`✅: ${input.evaluation_previous_goal}\n\t\t\t\t\t\t💾: ${input.memory}\n\t\t\t\t\t\t🎯: ${input.next_goal}\n\t\t\t\t\t`)\n\n\t\t\t\t\tconsole.log(brain)\n\t\t\t\t\tthis.bus.emit('panel:update', {\n\t\t\t\t\t\ttype: 'thinking',\n\t\t\t\t\t\tdisplayText: brain,\n\t\t\t\t\t})\n\n\t\t\t\t\t// Find the corresponding tool\n\t\t\t\t\tconst tool = tools.get(toolName)\n\t\t\t\t\tassert(tool, `Tool ${toolName} not found. (@note should have been caught before this!!!)`)\n\n\t\t\t\t\tconsole.log(chalk.blue.bold(`Executing tool: ${toolName}`), toolInput, options)\n\t\t\t\t\tthis.bus.emit('panel:update', {\n\t\t\t\t\t\ttype: 'tool_executing',\n\t\t\t\t\t\ttoolName,\n\t\t\t\t\t\ttoolArgs: toolInput,\n\t\t\t\t\t\tdisplayText: getToolExecutingText(toolName, toolInput, this.i18n),\n\t\t\t\t\t})\n\n\t\t\t\t\tconst startTime = Date.now()\n\n\t\t\t\t\t// Execute tool, passing options parameter\n\t\t\t\t\tlet result = await tool.execute!.bind(this)(toolInput, options)\n\n\t\t\t\t\tconst duration = Date.now() - startTime\n\t\t\t\t\tconsole.log(chalk.green.bold(`Tool (${toolName}) executed for ${duration}ms`), result)\n\n\t\t\t\t\tif (toolName === 'wait') {\n\t\t\t\t\t\tthis.#totalWaitTime += Math.round(toolInput.seconds + duration / 1000)\n\t\t\t\t\t\tresult += `\\n<sys> You have waited ${this.#totalWaitTime} seconds accumulatively.`\n\t\t\t\t\t\tif (this.#totalWaitTime >= 3)\n\t\t\t\t\t\t\tresult += '\\nDo NOT wait any longer unless you have a good reason.\\n'\n\t\t\t\t\t\tresult += '</sys>'\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// For other tools, reset wait time\n\t\t\t\t\t\tthis.#totalWaitTime = 0\n\t\t\t\t\t}\n\n\t\t\t\t\t// Briefly display execution result\n\t\t\t\t\tconst displayResult = getToolCompletedText(toolName, toolInput, this.i18n)\n\t\t\t\t\tif (displayResult)\n\t\t\t\t\t\tthis.bus.emit('panel:update', {\n\t\t\t\t\t\t\ttype: 'tool_executing',\n\t\t\t\t\t\t\ttoolName,\n\t\t\t\t\t\t\ttoolArgs: toolInput,\n\t\t\t\t\t\t\ttoolResult: result,\n\t\t\t\t\t\t\tdisplayText: displayResult,\n\t\t\t\t\t\t\tduration,\n\t\t\t\t\t\t})\n\n\t\t\t\t\t// Wait a moment to let user see the result\n\t\t\t\t\tawait new Promise((resolve) => setTimeout(resolve, 100))\n\n\t\t\t\t\treturn result\n\t\t\t\t},\n\t\t\t}),\n\t\t}\n\t}\n\n\t/**\n\t * Get system prompt, dynamically replace language settings based on configured language\n\t */\n\t#getSystemPrompt(): string {\n\t\tlet systemPrompt = SYSTEM_PROMPT\n\n\t\tconst targetLanguage = this.config.language === 'zh-CN' ? '中文' : 'English'\n\t\tsystemPrompt = systemPrompt.replace(\n\t\t\t/Default working language: \\*\\*.*?\\*\\*/,\n\t\t\t`Default working language: **${targetLanguage}**`\n\t\t)\n\n\t\treturn systemPrompt\n\t}\n\n\t#assembleUserPrompt(): string {\n\t\tlet prompt = ''\n\n\t\t// <agent_history>\n\t\t// - <step_>\n\n\t\tprompt += '<agent_history>\\n'\n\n\t\tthis.history.forEach((history, index) => {\n\t\t\tprompt += `<step_${index + 1}>\n\t\t\t\tEvaluation of Previous Step: ${history.brain.evaluation_previous_goal}\n\t\t\t\tMemory: ${history.brain.memory}\n\t\t\t\tNext Goal: ${history.brain.next_goal}\n\t\t\t\tAction Results: ${history.action.output}\n\t\t\t\t</step_${index + 1}>\n\t\t\t`\n\t\t})\n\n\t\tprompt += '</agent_history>\\n\\n'\n\n\t\t// <agent_state>\n\t\t// - <user_request>\n\t\t// - <step_info>\n\t\t// <agent_state>\n\n\t\tprompt += `<agent_state>\n\t\t\t<user_request>\n\t\t\t${this.task}\n\t\t\t</user_request>\n\t\t\t<step_info>\n\t\t\tStep ${this.history.length + 1} of ${MAX_STEPS} max possible steps\n\t\t\tCurrent date and time: ${new Date().toISOString()}\n\t\t\t</step_info>\n\t\t\t</agent_state>\n\t\t`\n\n\t\t// <browser_state>\n\n\t\tprompt += this.#getBrowserState()\n\n\t\treturn trimLines(prompt)\n\t}\n\n\t#onDone(text: string, success = true) {\n\t\tdom.cleanUpHighlights()\n\n\t\t// Update panel status\n\t\tthis.bus.emit('panel:update', {\n\t\t\ttype: success ? 'output' : 'error',\n\t\t\tdisplayText: text,\n\t\t})\n\n\t\t// Task completed\n\t\tthis.bus.emit('panel:update', {\n\t\t\ttype: 'completed',\n\t\t\tdisplayText: this.i18n.t('ui.panel.taskCompleted'),\n\t\t})\n\n\t\tthis.mask.hide()\n\n\t\tthis.#abortController.abort()\n\t}\n\n\t#getBrowserState(): string {\n\t\tconst pageUrl = window.location.href\n\t\tconst pageTitle = document.title\n\t\tconst pi = getPageInfo()\n\n\t\tthis.#updateTree()\n\n\t\tlet prompt = trimLines(`<browser_state>\n\t\t\tCurrent Page: [${pageTitle}](${pageUrl})\n\n\t\t\tPage info: ${pi.viewport_width}x${pi.viewport_height}px viewport, ${pi.page_width}x${pi.page_height}px total page size, ${pi.pages_above.toFixed(1)} pages above, ${pi.pages_below.toFixed(1)} pages below, ${pi.total_pages.toFixed(1)} total pages, at ${(pi.current_page_position * 100).toFixed(0)}% of page\n\n\t\t\t${VIEWPORT_EXPANSION === -1 ? 'Interactive elements from top layer of the current page (full page):' : 'Interactive elements from top layer of the current page inside the viewport:'}\n\n\t\t`)\n\n\t\t// Page header info\n\t\tconst has_content_above = pi.pixels_above > 4\n\t\tif (has_content_above && VIEWPORT_EXPANSION !== -1) {\n\t\t\tprompt += `... ${pi.pixels_above} pixels above (${pi.pages_above.toFixed(1)} pages) - scroll to see more ...\\n`\n\t\t} else {\n\t\t\tprompt += `[Start of page]\\n`\n\t\t}\n\n\t\t// Current viewport info\n\t\tprompt += this.simplifiedHTML\n\t\tprompt += `\\n`\n\n\t\t// Page footer info\n\t\tconst has_content_below = pi.pixels_below > 4\n\t\tif (has_content_below && VIEWPORT_EXPANSION !== -1) {\n\t\t\tprompt += `... ${pi.pixels_below} pixels below (${pi.pages_below.toFixed(1)} pages) - scroll to see more ...\\n`\n\t\t} else {\n\t\t\tprompt += `[End of page]\\n`\n\t\t}\n\n\t\tprompt += `</browser_state>\\n`\n\n\t\treturn prompt\n\t}\n\n\t/**\n\t * Update document tree\n\t */\n\t#updateTree() {\n\t\tthis.dispatchEvent(new Event('beforeUpdate'))\n\t\tthis.lastTimeUpdate = Date.now()\n\t\tdom.cleanUpHighlights()\n\t\tthis.mask.wrapper.style.pointerEvents = 'none'\n\t\tthis.flatTree = dom.getFlatTree({\n\t\t\t...this.config,\n\t\t\tinteractiveBlacklist: [\n\t\t\t\t...(this.config.interactiveBlacklist || []),\n\t\t\t\t...document.querySelectorAll('[data-page-agent-not-interactive]').values(),\n\t\t\t],\n\t\t})\n\t\tthis.mask.wrapper.style.pointerEvents = 'auto'\n\t\tthis.simplifiedHTML = dom.flatTreeToString(this.flatTree, this.config.include_attributes)\n\t\tthis.selectorMap.clear()\n\t\tthis.selectorMap = dom.getSelectorMap(this.flatTree)\n\t\tthis.elementTextMap.clear()\n\t\tthis.elementTextMap = dom.getElementTextMap(this.simplifiedHTML)\n\t\tthis.dispatchEvent(new Event('afterUpdate'))\n\t}\n\n\tdispose() {\n\t\tconsole.log('Disposing PageAgent...')\n\t\tthis.disposed = true\n\t\tdom.cleanUpHighlights()\n\t\tthis.flatTree = null\n\t\tthis.selectorMap.clear()\n\t\tthis.elementTextMap.clear()\n\t\tthis.panel.dispose()\n\t\tthis.mask.dispose()\n\t\tthis.history = []\n\t\tthis.#abortController.abort('PageAgent disposed')\n\t}\n}\n"],"names":["args","parentElement","element","rect","viewportExpansion","nodeData","id","currentUrl","result","tools","error","withRetry","dy","el","dx","input","_bus","styles","wrapper","header","statusIcon","output","dom.cleanUpHighlights","tool","dom.getFlatTree","dom.flatTreeToString","dom.getSelectorMap","dom.getElementTextMap"],"mappings":"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"}