surf-cli 2.13.1 → 2.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +65 -34
- package/agents/gpt-pro.md +19 -0
- package/dist/content/index.js +116 -0
- package/dist/content/index.js.map +1 -0
- package/dist/icons/icon-128.png +0 -0
- package/dist/icons/icon-16.png +0 -0
- package/dist/icons/icon-48.png +0 -0
- package/dist/manifest.json +2 -11
- package/dist/options/options.js +3 -3
- package/dist/options/options.js.map +1 -1
- package/dist/service-worker/index.js +261 -61
- package/dist/service-worker/index.js.map +1 -1
- package/native/browser-scheduler.cjs +348 -0
- package/native/browser-session-store.cjs +271 -0
- package/native/chatgpt-client-selection.cjs +20 -10
- package/native/chatgpt-client-ui.cjs +35 -7
- package/native/cli.cjs +333 -62
- package/native/do-executor.cjs +5 -0
- package/native/host-helpers.cjs +19 -3
- package/native/host-sessions.cjs +8 -1
- package/native/host.cjs +766 -19
- package/native/mcp-server.cjs +1 -1
- package/native/oracle-cli.cjs +2 -2
- package/native/oracle-jobs.cjs +25 -3
- package/native/playbook-cli.cjs +16 -3
- package/native/surf-error.cjs +47 -0
- package/native/tool-scope.cjs +107 -0
- package/native/workflow-definition.cjs +7 -0
- package/package.json +8 -2
- package/pi-extension/surf.ts +275 -2
- package/skills/surf/SKILL.md +52 -23
- package/dist/content/accessibility-tree.js +0 -11
- package/dist/content/accessibility-tree.js.map +0 -1
- package/dist/content/visual-indicator.js +0 -111
- package/dist/content/visual-indicator.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../src/content/visual-indicator.ts","../../src/content/accessibility-tree.ts"],"sourcesContent":["export type VisualIndicatorMessageType =\n | \"SHOW_AGENT_INDICATORS\"\n | \"HIDE_AGENT_INDICATORS\"\n | \"HIDE_FOR_TOOL_USE\"\n | \"SHOW_AFTER_TOOL_USE\"\n | \"SHOW_STATIC_INDICATOR\"\n | \"HIDE_STATIC_INDICATOR\";\n\ndeclare global {\n interface Window {\n __piVisualIndicatorMessageHandler?: (type: VisualIndicatorMessageType) => void;\n }\n}\n\nconst PI_COLOR = \"59, 178, 191\";\nconst DEFAULT_HEARTBEAT_INTERVAL = 10000;\n\nlet glowBorder: HTMLDivElement | null = null;\nlet stopButton: HTMLDivElement | null = null;\nlet staticIndicator: HTMLDivElement | null = null;\nlet isActive = false;\nlet isStaticActive = false;\nlet wasActiveBeforeToolUse = false;\nlet wasStaticActiveBeforeToolUse = false;\nlet heartbeatIntervalId: number | null = null;\nlet heartbeatIntervalMs = DEFAULT_HEARTBEAT_INTERVAL;\nlet showIndicatorsWhenReady = false;\nlet showStaticIndicatorWhenReady = false;\nconst isTopFrame = window === window.top;\n\nif (isTopFrame) {\n chrome.storage.local.get(\"heartbeatInterval\").then(({ heartbeatInterval }) => {\n if (heartbeatInterval && typeof heartbeatInterval === \"number\") {\n heartbeatIntervalMs = heartbeatInterval * 1000;\n }\n });\n\n chrome.storage.onChanged.addListener((changes, areaName) => {\n if (areaName === \"local\" && changes.heartbeatInterval) {\n const newValue = changes.heartbeatInterval.newValue;\n if (newValue && typeof newValue === \"number\") {\n heartbeatIntervalMs = newValue * 1000;\n if (isStaticActive && heartbeatIntervalId) {\n clearInterval(heartbeatIntervalId);\n startHeartbeat();\n }\n }\n }\n });\n}\n\nfunction startHeartbeat() {\n heartbeatIntervalId = window.setInterval(async () => {\n try {\n const response = await chrome.runtime.sendMessage({ type: \"STATIC_INDICATOR_HEARTBEAT\" });\n if (!response?.success) hideStaticIndicator();\n } catch {\n hideStaticIndicator();\n }\n }, heartbeatIntervalMs);\n}\n\nfunction injectStyles() {\n if (document.getElementById(\"pi-agent-styles\")) return;\n\n const style = document.createElement(\"style\");\n style.id = \"pi-agent-styles\";\n style.textContent = `\n @keyframes pi-pulse {\n 0% {\n box-shadow: \n inset 0 0 10px rgba(${PI_COLOR}, 0.5),\n inset 0 0 20px rgba(${PI_COLOR}, 0.3),\n inset 0 0 30px rgba(${PI_COLOR}, 0.1);\n }\n 50% {\n box-shadow: \n inset 0 0 15px rgba(${PI_COLOR}, 0.7),\n inset 0 0 25px rgba(${PI_COLOR}, 0.5),\n inset 0 0 35px rgba(${PI_COLOR}, 0.2);\n }\n 100% {\n box-shadow: \n inset 0 0 10px rgba(${PI_COLOR}, 0.5),\n inset 0 0 20px rgba(${PI_COLOR}, 0.3),\n inset 0 0 30px rgba(${PI_COLOR}, 0.1);\n }\n }\n `;\n document.head.appendChild(style);\n}\n\nfunction createGlowBorder(): HTMLDivElement {\n const el = document.createElement(\"div\");\n el.id = \"pi-agent-glow\";\n el.style.cssText = `\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n pointer-events: none;\n z-index: 2147483646;\n opacity: 0;\n transition: opacity 0.3s ease-in-out;\n animation: pi-pulse 2s ease-in-out infinite;\n box-shadow: \n inset 0 0 10px rgba(${PI_COLOR}, 0.5),\n inset 0 0 20px rgba(${PI_COLOR}, 0.3),\n inset 0 0 30px rgba(${PI_COLOR}, 0.1);\n `;\n return el;\n}\n\nfunction createStopButton(): HTMLDivElement {\n const container = document.createElement(\"div\");\n container.id = \"pi-agent-stop-container\";\n container.style.cssText = `\n position: fixed;\n bottom: 16px;\n left: 50%;\n transform: translateX(-50%);\n display: flex;\n justify-content: center;\n align-items: center;\n pointer-events: none;\n z-index: 2147483647;\n `;\n\n const button = document.createElement(\"button\");\n button.id = \"pi-agent-stop-button\";\n button.innerHTML = `\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 256 256\" fill=\"currentColor\" style=\"margin-right: 12px; vertical-align: middle;\">\n <path d=\"M128,20A108,108,0,1,0,236,128,108.12,108.12,0,0,0,128,20Zm0,192a84,84,0,1,1,84-84A84.09,84.09,0,0,1,128,212Zm40-112v56a12,12,0,0,1-12,12H100a12,12,0,0,1-12-12V100a12,12,0,0,1,12-12h56A12,12,0,0,1,168,100Z\"></path>\n </svg>\n <span style=\"vertical-align: middle;\">Stop Surf</span>\n `;\n button.style.cssText = `\n position: relative;\n transform: translateY(100px);\n padding: 12px 16px;\n background: #FAF9F5;\n color: #141413;\n border: 0.5px solid rgba(31, 30, 29, 0.4);\n border-radius: 12px;\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, sans-serif;\n font-size: 14px;\n font-weight: 600;\n cursor: pointer;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n box-shadow: \n 0 40px 80px rgba(${PI_COLOR}, 0.24),\n 0 4px 14px rgba(${PI_COLOR}, 0.24);\n transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n opacity: 0;\n user-select: none;\n pointer-events: auto;\n white-space: nowrap;\n margin: 0 auto;\n `;\n\n button.addEventListener(\"mouseenter\", () => {\n if (isActive) button.style.background = \"#F5F4F0\";\n });\n\n button.addEventListener(\"mouseleave\", () => {\n if (isActive) button.style.background = \"#FAF9F5\";\n });\n\n button.addEventListener(\"click\", async () => {\n await chrome.runtime.sendMessage({ type: \"STOP_AGENT\", fromTabId: \"CURRENT_TAB\" });\n });\n\n container.appendChild(button);\n return container;\n}\n\nfunction createStaticIndicator(): HTMLDivElement {\n const container = document.createElement(\"div\");\n container.id = \"pi-agent-static-indicator\";\n container.innerHTML = `\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" style=\"width: 16px; height: 16px; margin-right: 8px; flex-shrink: 0;\">\n <circle cx=\"8\" cy=\"8\" r=\"7\" fill=\"rgb(${PI_COLOR})\"/>\n <text x=\"8\" y=\"11\" font-size=\"9\" fill=\"white\" text-anchor=\"middle\" font-weight=\"bold\">π</text>\n </svg>\n <span style=\"color: #141413; font-size: 14px;\">Surf is active in this tab group</span>\n <div style=\"width: 0.5px; height: 32px; background: rgba(31, 30, 29, 0.15); margin: 0 8px;\"></div>\n <button id=\"pi-static-chat-button\" style=\"display: inline-flex; align-items: center; justify-content: center; padding: 6px; background: transparent; border: none; cursor: pointer; width: 32px; height: 32px; border-radius: 8px; transition: background 0.2s;\">\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" fill=\"#141413\">\n <path d=\"M10 2.5C14.1421 2.5 17.5 5.85786 17.5 10C17.5 14.1421 14.1421 17.5 10 17.5H3C2.79779 17.5 2.61549 17.3782 2.53809 17.1914C2.4607 17.0046 2.50349 16.7895 2.64648 16.6465L4.35547 14.9365C3.20124 13.6175 2.5 11.8906 2.5 10C2.5 5.85786 5.85786 2.5 10 2.5Z\"/>\n </svg>\n </button>\n <button id=\"pi-static-close-button\" style=\"display: inline-flex; align-items: center; justify-content: center; padding: 6px; background: transparent; border: none; cursor: pointer; width: 32px; height: 32px; margin-left: 4px; border-radius: 8px; transition: background 0.2s;\">\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" fill=\"none\">\n <path d=\"M15.1464 4.14642C15.3417 3.95121 15.6582 3.95118 15.8534 4.14642C16.0486 4.34168 16.0486 4.65822 15.8534 4.85346L10.7069 9.99997L15.8534 15.1465C16.0486 15.3417 16.0486 15.6583 15.8534 15.8535C15.6826 16.0244 15.4186 16.0461 15.2245 15.918L15.1464 15.8535L9.99989 10.707L4.85338 15.8535C4.65813 16.0486 4.34155 16.0486 4.14634 15.8535C3.95115 15.6583 3.95129 15.3418 4.14634 15.1465L9.29286 9.99997L4.14634 4.85346C3.95129 4.65818 3.95115 4.34162 4.14634 4.14642C4.34154 3.95128 4.65812 3.95138 4.85338 4.14642L9.99989 9.29294L15.1464 4.14642Z\" fill=\"#141413\"/>\n </svg>\n </button>\n `;\n container.style.cssText = `\n position: fixed;\n bottom: 16px;\n left: 50%;\n transform: translateX(-50%);\n display: inline-flex;\n align-items: center;\n padding: 6px 6px 6px 16px;\n background: #FAF9F5;\n border: 0.5px solid rgba(31, 30, 29, 0.30);\n border-radius: 14px;\n box-shadow: 0 40px 80px 0 rgba(0, 0, 0, 0.15);\n z-index: 2147483647;\n pointer-events: none;\n white-space: nowrap;\n user-select: none;\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, sans-serif;\n `;\n\n const chatButton = container.querySelector(\"#pi-static-chat-button\") as HTMLButtonElement;\n const closeButton = container.querySelector(\"#pi-static-close-button\") as HTMLButtonElement;\n\n if (chatButton) {\n chatButton.style.pointerEvents = \"auto\";\n chatButton.addEventListener(\"mouseenter\", () => chatButton.style.background = \"#F0EEE6\");\n chatButton.addEventListener(\"mouseleave\", () => chatButton.style.background = \"transparent\");\n chatButton.addEventListener(\"click\", async () => {\n await chrome.runtime.sendMessage({ type: \"OPEN_SIDEPANEL\" });\n });\n }\n\n if (closeButton) {\n closeButton.style.pointerEvents = \"auto\";\n closeButton.addEventListener(\"mouseenter\", () => closeButton.style.background = \"#F0EEE6\");\n closeButton.addEventListener(\"mouseleave\", () => closeButton.style.background = \"transparent\");\n closeButton.addEventListener(\"click\", async () => {\n await chrome.runtime.sendMessage({ type: \"DISMISS_STATIC_INDICATOR\" });\n hideStaticIndicator();\n });\n }\n\n return container;\n}\n\nfunction showIndicators() {\n if (!document.body) {\n if (!showIndicatorsWhenReady) {\n showIndicatorsWhenReady = true;\n window.addEventListener(\n \"DOMContentLoaded\",\n () => {\n if (!showIndicatorsWhenReady) return;\n showIndicatorsWhenReady = false;\n showIndicators();\n },\n { once: true },\n );\n }\n return;\n }\n showIndicatorsWhenReady = false;\n if (isActive) return;\n isActive = true;\n\n injectStyles();\n\n if (!glowBorder) {\n glowBorder = createGlowBorder();\n document.body.appendChild(glowBorder);\n } else {\n glowBorder.style.display = \"\";\n }\n\n if (!stopButton) {\n stopButton = createStopButton();\n document.body.appendChild(stopButton);\n } else {\n stopButton.style.display = \"\";\n }\n\n requestAnimationFrame(() => {\n if (glowBorder) glowBorder.style.opacity = \"1\";\n if (stopButton) {\n const btn = stopButton.querySelector(\"#pi-agent-stop-button\") as HTMLElement;\n if (btn) {\n btn.style.transform = \"translateY(0)\";\n btn.style.opacity = \"1\";\n }\n }\n });\n}\n\nfunction hideIndicators() {\n showIndicatorsWhenReady = false;\n if (!isActive) return;\n isActive = false;\n\n if (glowBorder) glowBorder.style.opacity = \"0\";\n if (stopButton) {\n const btn = stopButton.querySelector(\"#pi-agent-stop-button\") as HTMLElement;\n if (btn) {\n btn.style.transform = \"translateY(100px)\";\n btn.style.opacity = \"0\";\n }\n }\n\n setTimeout(() => {\n if (!isActive) {\n if (glowBorder?.parentNode) {\n glowBorder.parentNode.removeChild(glowBorder);\n glowBorder = null;\n }\n if (stopButton?.parentNode) {\n stopButton.parentNode.removeChild(stopButton);\n stopButton = null;\n }\n }\n }, 300);\n}\n\nfunction showStaticIndicator() {\n if (!document.body) {\n if (!showStaticIndicatorWhenReady) {\n showStaticIndicatorWhenReady = true;\n window.addEventListener(\n \"DOMContentLoaded\",\n () => {\n if (!showStaticIndicatorWhenReady) return;\n showStaticIndicatorWhenReady = false;\n showStaticIndicator();\n },\n { once: true },\n );\n }\n return;\n }\n showStaticIndicatorWhenReady = false;\n if (isStaticActive) return;\n isStaticActive = true;\n\n if (!staticIndicator) {\n staticIndicator = createStaticIndicator();\n document.body.appendChild(staticIndicator);\n } else {\n staticIndicator.style.display = \"\";\n }\n\n if (heartbeatIntervalId) clearInterval(heartbeatIntervalId);\n startHeartbeat();\n}\n\nfunction hideStaticIndicator() {\n showStaticIndicatorWhenReady = false;\n if (!isStaticActive) return;\n isStaticActive = false;\n\n if (heartbeatIntervalId) {\n clearInterval(heartbeatIntervalId);\n heartbeatIntervalId = null;\n }\n\n if (staticIndicator?.parentNode) {\n staticIndicator.parentNode.removeChild(staticIndicator);\n staticIndicator = null;\n }\n}\n\nif (isTopFrame) {\n window.__piVisualIndicatorMessageHandler = (type) => {\n switch (type) {\n case \"SHOW_AGENT_INDICATORS\":\n showIndicators();\n break;\n case \"HIDE_AGENT_INDICATORS\":\n hideIndicators();\n break;\n case \"HIDE_FOR_TOOL_USE\":\n wasActiveBeforeToolUse = isActive || showIndicatorsWhenReady;\n wasStaticActiveBeforeToolUse = isStaticActive || showStaticIndicatorWhenReady;\n showIndicatorsWhenReady = false;\n showStaticIndicatorWhenReady = false;\n if (glowBorder) glowBorder.style.display = \"none\";\n if (stopButton) stopButton.style.display = \"none\";\n if (staticIndicator && isStaticActive) staticIndicator.style.display = \"none\";\n break;\n case \"SHOW_AFTER_TOOL_USE\":\n if (wasActiveBeforeToolUse) {\n if (isActive) {\n if (glowBorder) glowBorder.style.display = \"\";\n if (stopButton) stopButton.style.display = \"\";\n } else {\n showIndicators();\n }\n }\n if (wasStaticActiveBeforeToolUse) {\n if (isStaticActive && staticIndicator) {\n staticIndicator.style.display = \"\";\n } else {\n showStaticIndicator();\n }\n }\n wasActiveBeforeToolUse = false;\n wasStaticActiveBeforeToolUse = false;\n break;\n case \"SHOW_STATIC_INDICATOR\":\n showStaticIndicator();\n break;\n case \"HIDE_STATIC_INDICATOR\":\n hideStaticIndicator();\n break;\n }\n };\n\n window.addEventListener(\"beforeunload\", () => {\n hideIndicators();\n hideStaticIndicator();\n });\n}\n","import type { VisualIndicatorMessageType } from \"./visual-indicator.ts\";\n\nexport {};\n\ndeclare global {\n interface Window {\n __piElementMap?: Record<string, { element: WeakRef<Element>; role: string; name: string }>;\n __piLastSnapshot?: { content: string; timestamp: number };\n __piHelpers?: typeof piHelpersImpl;\n piHelpers?: typeof piHelpersImpl;\n __piRefs?: Record<string, Element>;\n }\n}\n\ninterface ModalState {\n type: 'dialog' | 'alertdialog';\n description: string;\n clearedBy: string;\n}\n\nconst VALID_ARIA_ROLES = new Set([\n \"alert\", \"alertdialog\", \"application\", \"article\", \"banner\", \"blockquote\",\n \"button\", \"caption\", \"cell\", \"checkbox\", \"code\", \"columnheader\", \"combobox\",\n \"complementary\", \"contentinfo\", \"definition\", \"deletion\", \"dialog\", \"directory\",\n \"document\", \"emphasis\", \"feed\", \"figure\", \"form\", \"generic\", \"grid\", \"gridcell\",\n \"group\", \"heading\", \"img\", \"insertion\", \"link\", \"list\", \"listbox\", \"listitem\",\n \"log\", \"main\", \"mark\", \"marquee\", \"math\", \"menu\", \"menubar\", \"menuitem\",\n \"menuitemcheckbox\", \"menuitemradio\", \"meter\", \"navigation\", \"none\", \"note\",\n \"option\", \"paragraph\", \"presentation\", \"progressbar\", \"radio\", \"radiogroup\",\n \"region\", \"row\", \"rowgroup\", \"rowheader\", \"scrollbar\", \"search\", \"searchbox\",\n \"separator\", \"slider\", \"spinbutton\", \"status\", \"strong\", \"subscript\",\n \"superscript\", \"switch\", \"tab\", \"table\", \"tablist\", \"tabpanel\", \"term\",\n \"textbox\", \"time\", \"timer\", \"toolbar\", \"tooltip\", \"tree\", \"treegrid\", \"treeitem\"\n]);\n\nfunction isFocusable(element: Element): boolean {\n const tagName = element.tagName.toLowerCase();\n if ([\"button\", \"input\", \"select\", \"textarea\"].includes(tagName)) {\n return !(element as HTMLButtonElement).disabled;\n }\n if (tagName === \"a\" && element.hasAttribute(\"href\")) return true;\n if (element.hasAttribute(\"tabindex\")) {\n const tabindex = parseInt(element.getAttribute(\"tabindex\") || \"\", 10);\n return !isNaN(tabindex) && tabindex >= 0;\n }\n if (element.getAttribute(\"contenteditable\") === \"true\") return true;\n return false;\n}\n\nfunction getExplicitRole(element: Element): string | null {\n const roleAttr = element.getAttribute(\"role\");\n if (!roleAttr) return null;\n const roles = roleAttr.split(/\\s+/).filter(r => r);\n for (const role of roles) {\n if (VALID_ARIA_ROLES.has(role)) {\n return role;\n }\n }\n return null;\n}\n\nfunction getImplicitRole(element: Element): string {\n const tag = element.tagName.toLowerCase();\n const type = element.getAttribute(\"type\");\n\n const tagRoles: Record<string, string | ((el: Element) => string)> = {\n a: (el) => el.hasAttribute(\"href\") ? \"link\" : \"generic\",\n article: \"article\",\n aside: \"complementary\",\n button: \"button\",\n datalist: \"listbox\",\n dd: \"definition\",\n details: \"group\",\n dialog: \"dialog\",\n dt: \"term\",\n fieldset: \"group\",\n figure: \"figure\",\n footer: (el) => el.closest(\"article, aside, main, nav, section\") ? \"generic\" : \"contentinfo\",\n form: (el) => el.hasAttribute(\"aria-label\") || el.hasAttribute(\"aria-labelledby\") ? \"form\" : \"generic\",\n h1: \"heading\", h2: \"heading\", h3: \"heading\", h4: \"heading\", h5: \"heading\", h6: \"heading\",\n header: (el) => el.closest(\"article, aside, main, nav, section\") ? \"generic\" : \"banner\",\n hr: \"separator\",\n img: (el) => el.getAttribute(\"alt\") === \"\" ? \"presentation\" : \"img\",\n li: \"listitem\",\n main: \"main\",\n math: \"math\",\n menu: \"list\",\n meter: \"meter\",\n nav: \"navigation\",\n ol: \"list\",\n optgroup: \"group\",\n option: \"option\",\n output: \"status\",\n p: \"paragraph\",\n progress: \"progressbar\",\n search: \"search\",\n section: (el) => el.hasAttribute(\"aria-label\") || el.hasAttribute(\"aria-labelledby\") ? \"region\" : \"generic\",\n select: (el) => {\n const s = el as HTMLSelectElement;\n return s.hasAttribute(\"multiple\") || (s.size && s.size > 1) ? \"listbox\" : \"combobox\";\n },\n table: \"table\",\n tbody: \"rowgroup\",\n td: \"cell\",\n textarea: \"textbox\",\n tfoot: \"rowgroup\",\n th: \"columnheader\",\n thead: \"rowgroup\",\n time: \"time\",\n tr: \"row\",\n ul: \"list\",\n };\n\n if (tag === \"input\") {\n const inputRoles: Record<string, string> = {\n button: \"button\",\n checkbox: \"checkbox\",\n email: \"textbox\",\n file: \"button\",\n image: \"button\",\n number: \"spinbutton\",\n radio: \"radio\",\n range: \"slider\",\n reset: \"button\",\n search: \"searchbox\",\n submit: \"button\",\n tel: \"textbox\",\n text: \"textbox\",\n url: \"textbox\",\n };\n return inputRoles[type || \"\"] || \"textbox\";\n }\n\n const roleOrFn = tagRoles[tag];\n if (typeof roleOrFn === \"function\") {\n return roleOrFn(element);\n }\n return roleOrFn || \"generic\";\n}\n\nfunction getResolvedRole(element: Element): string {\n const explicitRole = getExplicitRole(element);\n \n if (!explicitRole) {\n return getImplicitRole(element);\n }\n \n if ((explicitRole === \"none\" || explicitRole === \"presentation\") && isFocusable(element)) {\n return getImplicitRole(element);\n }\n \n return explicitRole;\n}\n\nif (!window.__piElementMap) window.__piElementMap = {};\n\ninterface ElementRef {\n role: string;\n name: string;\n ref: string;\n}\n\nconst elementRefs = new WeakMap<Element, ElementRef>();\nlet globalRefCounter = 0;\n\nfunction getOrAssignRef(element: Element, role: string, name: string): string {\n const existing = elementRefs.get(element);\n if (existing && existing.role === role && existing.name === name) {\n return existing.ref;\n }\n \n const ref = `e${++globalRefCounter}`;\n elementRefs.set(element, { role, name, ref });\n return ref;\n}\n\nfunction detectModalStates(): ModalState[] {\n const modals: ModalState[] = [];\n \n const dialogs = document.querySelectorAll('[role=\"dialog\"], [role=\"alertdialog\"], dialog[open]');\n dialogs.forEach(dialog => {\n const style = window.getComputedStyle(dialog);\n const isVisible = style.display !== 'none' && \n style.visibility !== 'hidden' && \n style.opacity !== '0' &&\n (dialog as HTMLElement).offsetWidth > 0 &&\n (dialog as HTMLElement).offsetHeight > 0;\n if (!isVisible) return;\n \n const role = dialog.getAttribute('role') || 'dialog';\n let title = dialog.getAttribute('aria-label') || \n dialog.querySelector('[role=\"heading\"], h1, h2, h3')?.textContent?.trim() ||\n 'Dialog';\n if (title.length > 100) title = title.substring(0, 100) + '...';\n modals.push({\n type: role as 'dialog' | 'alertdialog',\n description: `${role}: ${title}`,\n clearedBy: 'computer(action=key, text=Escape)',\n });\n });\n \n return modals;\n}\n\nconst piHelpersImpl = {\n wait(ms: number): Promise<void> {\n return new Promise(resolve => setTimeout(resolve, ms));\n },\n\n async waitForSelector(\n selector: string,\n options: { state?: 'visible' | 'hidden' | 'attached' | 'detached'; timeout?: number } = {}\n ): Promise<Element | null> {\n const { state = 'visible', timeout = 20000 } = options;\n\n const isElementVisible = (el: Element | null): boolean => {\n if (!el) return false;\n const style = window.getComputedStyle(el);\n return style.display !== 'none' && \n style.visibility !== 'hidden' && \n style.opacity !== '0' &&\n (el as HTMLElement).offsetWidth > 0 &&\n (el as HTMLElement).offsetHeight > 0;\n };\n\n const checkElement = (): Element | null => {\n const el = document.querySelector(selector);\n switch (state) {\n case 'attached':\n return el;\n case 'detached':\n return el ? null : document.body;\n case 'hidden':\n if (!el) return document.body;\n return isElementVisible(el) ? null : el;\n case 'visible':\n default:\n return isElementVisible(el) ? el : null;\n }\n };\n\n return new Promise((resolve, reject) => {\n const result = checkElement();\n if (result) {\n resolve(state === 'detached' || state === 'hidden' ? null : result);\n return;\n }\n\n const observer = new MutationObserver(() => {\n const result = checkElement();\n if (result) {\n observer.disconnect();\n clearTimeout(timeoutId);\n resolve(state === 'detached' || state === 'hidden' ? null : result);\n }\n });\n\n const timeoutId = setTimeout(() => {\n observer.disconnect();\n reject(new Error(`Timeout waiting for \"${selector}\" to be ${state}`));\n }, timeout);\n\n observer.observe(document.documentElement, {\n childList: true,\n subtree: true,\n attributes: true,\n attributeFilter: ['style', 'class', 'hidden']\n });\n });\n },\n\n async waitForText(\n text: string,\n options: { selector?: string; timeout?: number } = {}\n ): Promise<Element | null> {\n const { selector, timeout = 20000 } = options;\n\n const checkText = (): Element | null => {\n const root = selector ? document.querySelector(selector) : document.body;\n if (!root) return null;\n \n const walker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT);\n while (walker.nextNode()) {\n if (walker.currentNode.textContent?.includes(text)) {\n return walker.currentNode.parentElement;\n }\n }\n return null;\n };\n\n return new Promise((resolve, reject) => {\n const result = checkText();\n if (result) {\n resolve(result);\n return;\n }\n\n const observer = new MutationObserver(() => {\n const result = checkText();\n if (result) {\n observer.disconnect();\n clearTimeout(timeoutId);\n resolve(result);\n }\n });\n\n const timeoutId = setTimeout(() => {\n observer.disconnect();\n reject(new Error(`Timeout waiting for text \"${text}\"`));\n }, timeout);\n\n observer.observe(document.documentElement, {\n childList: true,\n subtree: true,\n characterData: true\n });\n });\n },\n\n async waitForHidden(selector: string, timeout = 20000): Promise<void> {\n await piHelpersImpl.waitForSelector(selector, { state: 'hidden', timeout });\n },\n\n getByRole(role: string, options: { name?: string } = {}): Element | null {\n const { name } = options;\n \n const implicitRoles: Record<string, string[]> = {\n button: ['button', 'input[type=\"button\"]', 'input[type=\"submit\"]', 'input[type=\"reset\"]'],\n link: ['a[href]'],\n textbox: ['input:not([type])', 'input[type=\"text\"]', 'input[type=\"email\"]', 'input[type=\"password\"]', 'input[type=\"search\"]', 'input[type=\"tel\"]', 'input[type=\"url\"]', 'textarea'],\n checkbox: ['input[type=\"checkbox\"]'],\n radio: ['input[type=\"radio\"]'],\n combobox: ['select'],\n heading: ['h1', 'h2', 'h3', 'h4', 'h5', 'h6'],\n list: ['ul', 'ol'],\n listitem: ['li'],\n navigation: ['nav'],\n main: ['main'],\n banner: ['header'],\n contentinfo: ['footer'],\n form: ['form'],\n img: ['img'],\n table: ['table'],\n };\n\n const candidates: Element[] = [];\n candidates.push(...document.querySelectorAll(`[role=\"${role}\"]`));\n \n const implicitSelectors = implicitRoles[role];\n if (implicitSelectors) {\n for (const sel of implicitSelectors) {\n candidates.push(...document.querySelectorAll(`${sel}:not([role])`));\n }\n }\n\n if (!name) return candidates[0] || null;\n\n const normalizedName = name.toLowerCase().trim();\n for (const el of candidates) {\n const ariaLabel = el.getAttribute('aria-label')?.toLowerCase().trim();\n const textContent = el.textContent?.toLowerCase().trim();\n const title = el.getAttribute('title')?.toLowerCase().trim();\n const placeholder = el.getAttribute('placeholder')?.toLowerCase().trim();\n\n if (ariaLabel === normalizedName || textContent === normalizedName || \n title === normalizedName || placeholder === normalizedName) {\n return el;\n }\n if (ariaLabel?.includes(normalizedName) || textContent?.includes(normalizedName)) {\n return el;\n }\n }\n\n return null;\n }\n};\n\nif (!window.__piHelpers) {\n window.__piHelpers = piHelpersImpl;\n window.piHelpers = piHelpersImpl;\n}\n\nfunction getElementMap() {\n return window.__piElementMap!;\n}\n\nfunction generateAccessibilityTree(\n filter: \"all\" | \"interactive\" = \"interactive\",\n maxDepth = 15,\n refId?: string,\n forceFullSnapshot = false,\n compact = false\n): { \n pageContent: string;\n diff?: string;\n viewport: { width: number; height: number }; \n error?: string;\n modalStates?: ModalState[];\n modalLimitations?: string;\n isIncremental?: boolean;\n} {\n try {\n window.__piRefs = {};\n\n function getRole(element: Element): string {\n return getResolvedRole(element);\n }\n\n function getName(element: Element): string {\n const tag = element.tagName.toLowerCase();\n\n const labelledBy = element.getAttribute('aria-labelledby');\n if (labelledBy) {\n const names = labelledBy.split(/\\s+/).map(id => {\n const el = document.getElementById(id);\n return el?.textContent?.trim() || '';\n }).filter(Boolean);\n if (names.length) {\n const joined = names.join(' ');\n return joined.length > 100 ? joined.substring(0, 100) + '...' : joined;\n }\n }\n\n if (tag === \"select\") {\n const select = element as HTMLSelectElement;\n const selected = select.querySelector(\"option[selected]\") || \n (select.selectedIndex >= 0 ? select.options[select.selectedIndex] : null);\n if (selected?.textContent?.trim()) return selected.textContent.trim();\n }\n\n const ariaLabel = element.getAttribute(\"aria-label\");\n if (ariaLabel?.trim()) return ariaLabel.trim();\n\n const placeholder = element.getAttribute(\"placeholder\");\n if (placeholder?.trim()) return placeholder.trim();\n\n const title = element.getAttribute(\"title\");\n if (title?.trim()) return title.trim();\n\n const alt = element.getAttribute(\"alt\");\n if (alt?.trim()) return alt.trim();\n\n if (element.id) {\n const label = document.querySelector(`label[for=\"${element.id}\"]`);\n if (label?.textContent?.trim()) return label.textContent.trim();\n }\n\n if (tag === \"input\") {\n const input = element as HTMLInputElement;\n const type = element.getAttribute(\"type\") || \"\";\n const value = element.getAttribute(\"value\");\n if (type === \"submit\" && value?.trim()) return value.trim();\n if (input.value && input.value.length < 50 && input.value.trim()) return input.value.trim();\n }\n\n if ([\"button\", \"a\", \"summary\"].includes(tag)) {\n const textContent = element.textContent || \"\";\n if (textContent.trim()) return textContent.trim();\n }\n\n if (/^h[1-6]$/.test(tag)) {\n const text = element.textContent;\n if (text?.trim()) {\n const t = text.trim();\n return t.length > 100 ? t.substring(0, 100) + \"...\" : t;\n }\n }\n\n if (tag === \"img\") return \"\";\n\n let directText = \"\";\n for (const node of element.childNodes) {\n if (node.nodeType === Node.TEXT_NODE) {\n directText += node.textContent;\n }\n }\n if (directText?.trim() && directText.trim().length >= 3) {\n const text = directText.trim();\n return text.length > 100 ? text.substring(0, 100) + \"...\" : text;\n }\n\n return \"\";\n }\n\n interface AriaProps {\n checked?: boolean | 'mixed';\n disabled?: boolean;\n expanded?: boolean;\n level?: number;\n pressed?: boolean | 'mixed';\n selected?: boolean;\n active?: boolean;\n }\n\n function getAriaProps(element: Element): AriaProps {\n const props: AriaProps = {};\n \n const checkedAttr = element.getAttribute('aria-checked');\n if (checkedAttr === 'true') props.checked = true;\n else if (checkedAttr === 'false') props.checked = false;\n else if (checkedAttr === 'mixed') props.checked = 'mixed';\n else if (element instanceof HTMLInputElement && (element.type === 'checkbox' || element.type === 'radio')) {\n if (element.type === 'checkbox' && element.indeterminate) {\n props.checked = 'mixed';\n } else {\n props.checked = element.checked;\n }\n }\n \n const isDisableable = element instanceof HTMLButtonElement || \n element instanceof HTMLInputElement || \n element instanceof HTMLSelectElement || \n element instanceof HTMLTextAreaElement;\n if (element.getAttribute('aria-disabled') === 'true' || \n (isDisableable && (element as HTMLButtonElement).disabled) ||\n element.closest('fieldset:disabled')) {\n props.disabled = true;\n }\n \n const expandedAttr = element.getAttribute('aria-expanded');\n if (expandedAttr === 'true') props.expanded = true;\n else if (expandedAttr === 'false') props.expanded = false;\n \n const pressedAttr = element.getAttribute('aria-pressed');\n if (pressedAttr === 'true') props.pressed = true;\n else if (pressedAttr === 'false') props.pressed = false;\n else if (pressedAttr === 'mixed') props.pressed = 'mixed';\n \n const selectedAttr = element.getAttribute('aria-selected');\n if (selectedAttr === 'true') props.selected = true;\n else if (selectedAttr === 'false') props.selected = false;\n \n const activeAttr = element.getAttribute('aria-current');\n if (activeAttr && activeAttr !== 'false') {\n props.active = true;\n }\n \n const tag = element.tagName.toLowerCase();\n if (/^h[1-6]$/.test(tag)) {\n props.level = parseInt(tag[1], 10);\n } else {\n const levelAttr = element.getAttribute('aria-level');\n if (levelAttr) props.level = parseInt(levelAttr, 10);\n }\n \n return props;\n }\n\n function formatAriaProps(props: AriaProps): string {\n const parts: string[] = [];\n \n if (props.checked !== undefined) {\n parts.push(props.checked === 'mixed' ? '[checked=mixed]' : props.checked ? '[checked]' : '[unchecked]');\n }\n if (props.disabled) parts.push('[disabled]');\n if (props.expanded !== undefined) {\n parts.push(props.expanded ? '[expanded]' : '[collapsed]');\n }\n if (props.pressed !== undefined) {\n parts.push(props.pressed === 'mixed' ? '[pressed=mixed]' : props.pressed ? '[pressed]' : '[not-pressed]');\n }\n if (props.selected !== undefined) {\n parts.push(props.selected ? '[selected]' : '[not-selected]');\n }\n if (props.active) parts.push('[active]');\n if (props.level !== undefined) {\n parts.push(`[level=${props.level}]`);\n }\n \n return parts.join(' ');\n }\n\n function isVisible(element: Element): boolean {\n const style = window.getComputedStyle(element);\n return (\n style.display !== \"none\" &&\n style.visibility !== \"hidden\" &&\n style.opacity !== \"0\" &&\n (element as HTMLElement).offsetWidth > 0 &&\n (element as HTMLElement).offsetHeight > 0\n );\n }\n\n function isInteractive(element: Element): boolean {\n const tag = element.tagName.toLowerCase();\n return (\n [\"a\", \"button\", \"input\", \"select\", \"textarea\", \"details\", \"summary\"].includes(tag) ||\n element.hasAttribute(\"onclick\") ||\n element.hasAttribute(\"tabindex\") ||\n element.getAttribute(\"role\") === \"button\" ||\n element.getAttribute(\"role\") === \"link\" ||\n element.getAttribute(\"contenteditable\") === \"true\"\n );\n }\n\n function isLandmark(element: Element): boolean {\n const tag = element.tagName.toLowerCase();\n return (\n [\"h1\", \"h2\", \"h3\", \"h4\", \"h5\", \"h6\", \"nav\", \"main\", \"header\", \"footer\", \"section\", \"article\", \"aside\"].includes(tag) ||\n element.hasAttribute(\"role\")\n );\n }\n\n function hasCursorPointer(element: Element): boolean {\n const style = window.getComputedStyle(element);\n return style.cursor === \"pointer\";\n }\n\n function shouldInclude(element: Element, options: { filter: string; refId: string | null; compact: boolean }): boolean {\n const tag = element.tagName.toLowerCase();\n if ([\"script\", \"style\", \"meta\", \"link\", \"title\", \"noscript\"].includes(tag)) return false;\n if (options.filter !== \"all\" && element.getAttribute(\"aria-hidden\") === \"true\") return false;\n if (options.filter !== \"all\" && !isVisible(element)) return false;\n\n if (options.filter !== \"all\" && !options.refId) {\n const rect = element.getBoundingClientRect();\n if (!(rect.top < window.innerHeight && rect.bottom > 0 && rect.left < window.innerWidth && rect.right > 0)) {\n return false;\n }\n }\n\n if (options.filter === \"interactive\") return isInteractive(element);\n if (isInteractive(element)) return true;\n if (isLandmark(element)) return true;\n if (getName(element).length > 0) return true;\n\n const role = getRole(element);\n \n // In compact mode, skip empty structural elements\n if (options.compact) {\n const emptyStructuralRoles = new Set([\"generic\", \"group\", \"region\", \"article\", \"section\", \"complementary\"]);\n if (emptyStructuralRoles.has(role) && getName(element).length === 0) {\n return false;\n }\n }\n \n return role !== \"generic\" && role !== \"img\";\n }\n\n function traverse(element: Element, depth: number): string[] {\n const lines: string[] = [];\n const options = { filter, refId: refId || null, compact };\n const elementMap = getElementMap();\n\n const include = shouldInclude(element, options) || (refId && depth === 0);\n\n if (include) {\n const role = getRole(element);\n const name = getName(element);\n const ariaProps = getAriaProps(element);\n\n const elemRefId = getOrAssignRef(element, role, name);\n window.__piRefs![elemRefId] = element;\n elementMap[elemRefId] = {\n element: new WeakRef(element),\n role,\n name,\n };\n\n const indent = \" \".repeat(depth);\n let line = `${indent}${role}`;\n if (name) {\n const escapedName = name.replace(/\\s+/g, \" \").replace(/\"/g, '\\\\\"');\n line += ` \"${escapedName}\"`;\n }\n line += ` [${elemRefId}]`;\n\n const propsStr = formatAriaProps(ariaProps);\n if (propsStr) line += ` ${propsStr}`;\n\n if (hasCursorPointer(element)) {\n line += \" [cursor=pointer]\";\n }\n\n const href = element.getAttribute(\"href\");\n if (href) line += ` href=\"${href}\"`;\n\n const type = element.getAttribute(\"type\");\n if (type) line += ` type=\"${type}\"`;\n\n const placeholder = element.getAttribute(\"placeholder\");\n if (placeholder) line += ` placeholder=\"${placeholder}\"`;\n\n lines.push(line);\n }\n\n if (depth < maxDepth) {\n for (const child of element.children) {\n lines.push(...traverse(child, include ? depth + 1 : depth));\n }\n }\n\n return lines;\n }\n\n function normalizeLineForDiff(line: string): string {\n return line.replace(/\\[e\\d+\\]/g, '[REF]');\n }\n\n function countOccurrences(lines: string[]): Map<string, number> {\n const counts = new Map<string, number>();\n for (const line of lines) {\n if (!line.trim()) continue;\n const norm = normalizeLineForDiff(line);\n counts.set(norm, (counts.get(norm) || 0) + 1);\n }\n return counts;\n }\n\n function computeSimpleDiff(oldContent: string, newContent: string): { diff: string; hasChanges: boolean } {\n const oldLines = oldContent.split('\\n');\n const newLines = newContent.split('\\n');\n \n const oldCounts = countOccurrences(oldLines);\n const newCounts = countOccurrences(newLines);\n \n const added: string[] = [];\n const removed: string[] = [];\n \n for (const line of newLines) {\n if (!line.trim()) continue;\n const norm = normalizeLineForDiff(line);\n const oldCount = oldCounts.get(norm) || 0;\n const newCount = newCounts.get(norm) || 0;\n if (newCount > oldCount) {\n added.push(line);\n oldCounts.set(norm, oldCount + 1);\n }\n }\n \n const oldCountsReset = countOccurrences(oldLines);\n for (const line of oldLines) {\n if (!line.trim()) continue;\n const norm = normalizeLineForDiff(line);\n const oldCount = oldCountsReset.get(norm) || 0;\n const newCount = newCounts.get(norm) || 0;\n if (oldCount > newCount) {\n removed.push(line);\n oldCountsReset.set(norm, oldCount - 1);\n }\n }\n \n if (added.length === 0 && removed.length === 0) {\n return { diff: '[NO CHANGES]', hasChanges: false };\n }\n \n const diffLines: string[] = [];\n if (removed.length > 0) {\n diffLines.push(...removed.map(l => `- ${l}`));\n }\n if (added.length > 0) {\n diffLines.push(...added.map(l => `+ ${l}`));\n }\n \n return { diff: diffLines.join('\\n'), hasChanges: true };\n }\n\n const elementMap = getElementMap();\n let startElement: Element | null = null;\n\n if (refId) {\n const elemRef = elementMap[refId];\n if (!elemRef) {\n return {\n error: `Element with ref_id '${refId}' not found. Use read_page without ref_id to get current elements.`,\n pageContent: \"\",\n viewport: { width: window.innerWidth, height: window.innerHeight },\n };\n }\n const element = elemRef.element.deref();\n if (!element) {\n delete elementMap[refId];\n return {\n error: `Element with ref_id '${refId}' no longer exists. Use read_page without ref_id to get current elements.`,\n pageContent: \"\",\n viewport: { width: window.innerWidth, height: window.innerHeight },\n };\n }\n startElement = element;\n } else {\n startElement = document.body;\n }\n\n const lines = startElement ? traverse(startElement, 0) : [];\n\n for (const id of Object.keys(elementMap)) {\n if (!elementMap[id].element.deref()) {\n delete elementMap[id];\n }\n }\n\n const content = lines.join(\"\\n\");\n\n if (content.length > 50000) {\n return {\n error: `Output exceeds 50000 character limit (${content.length} characters). Try using filter=\"interactive\" or specify a ref_id.`,\n pageContent: \"\",\n viewport: { width: window.innerWidth, height: window.innerHeight },\n };\n }\n\n const modalStates = detectModalStates();\n\n let diff: string | undefined;\n let isIncremental = false;\n const lastSnapshot = window.__piLastSnapshot;\n\n if (!forceFullSnapshot && !refId && lastSnapshot && \n Date.now() - lastSnapshot.timestamp < 5000) {\n const diffResult = computeSimpleDiff(lastSnapshot.content, content);\n diff = diffResult.diff;\n isIncremental = true;\n }\n\n window.__piLastSnapshot = { content, timestamp: Date.now() };\n\n return {\n pageContent: content + `\\n\\n[Viewport: ${window.innerWidth}x${window.innerHeight}]`,\n diff: isIncremental ? diff : undefined,\n viewport: { width: window.innerWidth, height: window.innerHeight },\n modalStates: modalStates.length > 0 ? modalStates : undefined,\n modalLimitations: 'Only custom modals ([role=dialog]) detected. Native alert/confirm/prompt dialogs and system file choosers cannot be detected from content scripts.',\n isIncremental,\n };\n } catch (err) {\n return {\n error: `Error generating accessibility tree: ${err instanceof Error ? err.message : \"Unknown error\"}`,\n pageContent: \"\",\n viewport: { width: window.innerWidth, height: window.innerHeight },\n };\n }\n}\n\nfunction yamlEscapeValue(str: string): string {\n if (!str.length) return '\"\"';\n if (/[\\n\\r]/.test(str) || /^[\\s]/.test(str) || /[\\s]$/.test(str) || /[:\"{}[\\]]/.test(str)) {\n return '\"' + str.replace(/\\\\/g, '\\\\\\\\').replace(/\"/g, '\\\\\"').replace(/\\n/g, '\\\\n').replace(/\\r/g, '\\\\r') + '\"';\n }\n return str;\n}\n\nfunction generateYamlTree(\n filter: \"all\" | \"interactive\" = \"interactive\",\n maxDepth = 15\n): { yaml: string; viewport: { width: number; height: number }; error?: string } {\n try {\n window.__piRefs = {};\n \n const lines: string[] = [];\n\n function getRole(element: Element): string {\n return getResolvedRole(element);\n }\n\n function getName(element: Element): string {\n const tag = element.tagName.toLowerCase();\n\n const labelledBy = element.getAttribute('aria-labelledby');\n if (labelledBy) {\n const names = labelledBy.split(/\\s+/).map(id => {\n const el = document.getElementById(id);\n return el?.textContent?.trim() || '';\n }).filter(Boolean);\n if (names.length) {\n const joined = names.join(' ');\n return joined.length > 100 ? joined.substring(0, 100) + '...' : joined;\n }\n }\n\n if (tag === \"select\") {\n const select = element as HTMLSelectElement;\n const selected = select.querySelector(\"option[selected]\") || \n (select.selectedIndex >= 0 ? select.options[select.selectedIndex] : null);\n if (selected?.textContent?.trim()) return selected.textContent.trim();\n }\n\n const ariaLabel = element.getAttribute(\"aria-label\");\n if (ariaLabel?.trim()) return ariaLabel.trim();\n\n const placeholder = element.getAttribute(\"placeholder\");\n if (placeholder?.trim()) return placeholder.trim();\n\n const title = element.getAttribute(\"title\");\n if (title?.trim()) return title.trim();\n\n const alt = element.getAttribute(\"alt\");\n if (alt?.trim()) return alt.trim();\n\n if (element.id) {\n const label = document.querySelector(`label[for=\"${element.id}\"]`);\n if (label?.textContent?.trim()) return label.textContent.trim();\n }\n\n if (tag === \"input\") {\n const input = element as HTMLInputElement;\n const type = element.getAttribute(\"type\") || \"\";\n const value = element.getAttribute(\"value\");\n if (type === \"submit\" && value?.trim()) return value.trim();\n if (input.value && input.value.length < 50 && input.value.trim()) return input.value.trim();\n }\n\n if ([\"button\", \"a\", \"summary\"].includes(tag)) {\n const textContent = element.textContent || \"\";\n if (textContent.trim()) return textContent.trim();\n }\n\n if (/^h[1-6]$/.test(tag)) {\n const text = element.textContent;\n if (text?.trim()) {\n const t = text.trim();\n return t.length > 100 ? t.substring(0, 100) + \"...\" : t;\n }\n }\n\n if (tag === \"img\") return \"\";\n\n let directText = \"\";\n for (const node of element.childNodes) {\n if (node.nodeType === Node.TEXT_NODE) {\n directText += node.textContent;\n }\n }\n if (directText?.trim() && directText.trim().length >= 3) {\n const text = directText.trim();\n return text.length > 100 ? text.substring(0, 100) + \"...\" : text;\n }\n\n return \"\";\n }\n\n interface AriaProps {\n checked?: boolean | 'mixed';\n disabled?: boolean;\n expanded?: boolean;\n level?: number;\n pressed?: boolean | 'mixed';\n selected?: boolean;\n active?: boolean;\n }\n\n function getAriaProps(element: Element): AriaProps {\n const props: AriaProps = {};\n \n const checkedAttr = element.getAttribute('aria-checked');\n if (checkedAttr === 'true') props.checked = true;\n else if (checkedAttr === 'false') props.checked = false;\n else if (checkedAttr === 'mixed') props.checked = 'mixed';\n else if (element instanceof HTMLInputElement && (element.type === 'checkbox' || element.type === 'radio')) {\n if (element.type === 'checkbox' && element.indeterminate) {\n props.checked = 'mixed';\n } else {\n props.checked = element.checked;\n }\n }\n \n const isDisableable = element instanceof HTMLButtonElement || \n element instanceof HTMLInputElement || \n element instanceof HTMLSelectElement || \n element instanceof HTMLTextAreaElement;\n if (element.getAttribute('aria-disabled') === 'true' || \n (isDisableable && (element as HTMLButtonElement).disabled) ||\n element.closest('fieldset:disabled')) {\n props.disabled = true;\n }\n \n const expandedAttr = element.getAttribute('aria-expanded');\n if (expandedAttr === 'true') props.expanded = true;\n else if (expandedAttr === 'false') props.expanded = false;\n \n const pressedAttr = element.getAttribute('aria-pressed');\n if (pressedAttr === 'true') props.pressed = true;\n else if (pressedAttr === 'false') props.pressed = false;\n else if (pressedAttr === 'mixed') props.pressed = 'mixed';\n \n const selectedAttr = element.getAttribute('aria-selected');\n if (selectedAttr === 'true') props.selected = true;\n else if (selectedAttr === 'false') props.selected = false;\n \n const activeAttr = element.getAttribute('aria-current');\n if (activeAttr && activeAttr !== 'false') {\n props.active = true;\n }\n \n const tag = element.tagName.toLowerCase();\n if (/^h[1-6]$/.test(tag)) {\n props.level = parseInt(tag[1], 10);\n } else {\n const levelAttr = element.getAttribute('aria-level');\n if (levelAttr) props.level = parseInt(levelAttr, 10);\n }\n \n return props;\n }\n\n function formatAriaProps(props: AriaProps): string {\n const parts: string[] = [];\n \n if (props.checked !== undefined) {\n parts.push(props.checked === 'mixed' ? '[checked=mixed]' : props.checked ? '[checked]' : '[unchecked]');\n }\n if (props.disabled) parts.push('[disabled]');\n if (props.expanded !== undefined) {\n parts.push(props.expanded ? '[expanded]' : '[collapsed]');\n }\n if (props.pressed !== undefined) {\n parts.push(props.pressed === 'mixed' ? '[pressed=mixed]' : props.pressed ? '[pressed]' : '[not-pressed]');\n }\n if (props.selected !== undefined) {\n parts.push(props.selected ? '[selected]' : '[not-selected]');\n }\n if (props.active) parts.push('[active]');\n if (props.level !== undefined) {\n parts.push(`[level=${props.level}]`);\n }\n \n return parts.join(' ');\n }\n\n function isVisible(element: Element): boolean {\n const style = window.getComputedStyle(element);\n return (\n style.display !== \"none\" &&\n style.visibility !== \"hidden\" &&\n style.opacity !== \"0\" &&\n (element as HTMLElement).offsetWidth > 0 &&\n (element as HTMLElement).offsetHeight > 0\n );\n }\n\n function isInteractive(element: Element): boolean {\n const tag = element.tagName.toLowerCase();\n return (\n [\"a\", \"button\", \"input\", \"select\", \"textarea\", \"details\", \"summary\"].includes(tag) ||\n element.hasAttribute(\"onclick\") ||\n element.hasAttribute(\"tabindex\") ||\n element.getAttribute(\"role\") === \"button\" ||\n element.getAttribute(\"role\") === \"link\" ||\n element.getAttribute(\"contenteditable\") === \"true\"\n );\n }\n\n function isLandmark(element: Element): boolean {\n const tag = element.tagName.toLowerCase();\n return (\n [\"h1\", \"h2\", \"h3\", \"h4\", \"h5\", \"h6\", \"nav\", \"main\", \"header\", \"footer\", \"section\", \"article\", \"aside\"].includes(tag) ||\n element.hasAttribute(\"role\")\n );\n }\n\n function hasCursorPointer(element: Element): boolean {\n const style = window.getComputedStyle(element);\n return style.cursor === \"pointer\";\n }\n\n function buildKey(role: string, name: string, element: Element, ariaProps: AriaProps): string {\n let key = role;\n if (name) {\n key += ' ' + yamlEscapeValue(name);\n }\n \n const ref = getOrAssignRef(element, role, name);\n window.__piRefs![ref] = element;\n key += ` [ref=${ref}]`;\n \n const propsStr = formatAriaProps(ariaProps);\n if (propsStr) key += ` ${propsStr}`;\n \n if (hasCursorPointer(element)) {\n key += ' [cursor=pointer]';\n }\n \n return key;\n }\n\n function getElementProps(element: Element): Record<string, string> {\n const props: Record<string, string> = {};\n const href = element.getAttribute(\"href\");\n if (href) props.url = href;\n const placeholder = element.getAttribute(\"placeholder\");\n if (placeholder) props.placeholder = placeholder;\n return props;\n }\n\n function traverse(element: Element, depth: number, parentIncluded: boolean): void {\n if (depth > maxDepth) return;\n \n const tag = element.tagName.toLowerCase();\n if ([\"script\", \"style\", \"meta\", \"link\", \"title\", \"noscript\"].includes(tag)) return;\n if (filter !== \"all\" && element.getAttribute(\"aria-hidden\") === \"true\") return;\n if (filter !== \"all\" && !isVisible(element)) return;\n \n if (filter !== \"all\") {\n const rect = element.getBoundingClientRect();\n if (!(rect.top < window.innerHeight && rect.bottom > 0 && rect.left < window.innerWidth && rect.right > 0)) {\n return;\n }\n }\n \n const role = getRole(element);\n const name = getName(element);\n const ariaProps = getAriaProps(element);\n \n const isInteractiveEl = isInteractive(element);\n const isLandmarkEl = isLandmark(element);\n const hasName = name.length > 0;\n \n let include: boolean;\n if (filter === \"interactive\") {\n include = isInteractiveEl;\n } else if (filter === \"all\") {\n include = true;\n } else {\n include = isInteractiveEl || isLandmarkEl || hasName || (role !== \"generic\" && role !== \"img\");\n }\n \n if (include) {\n const indent = \" \".repeat(depth);\n const key = buildKey(role, name, element, ariaProps);\n const props = getElementProps(element);\n \n const children: Element[] = [];\n for (const child of element.children) {\n children.push(child);\n }\n \n const hasChildren = children.length > 0;\n const hasProps = Object.keys(props).length > 0;\n \n if (!hasChildren && !hasProps) {\n lines.push(`${indent}- ${key}`);\n } else {\n lines.push(`${indent}- ${key}:`);\n for (const [propName, propValue] of Object.entries(props)) {\n lines.push(`${indent} - /${propName}: ${yamlEscapeValue(propValue)}`);\n }\n for (const child of children) {\n traverse(child, depth + 1, true);\n }\n }\n } else {\n for (const child of element.children) {\n traverse(child, depth, parentIncluded);\n }\n }\n }\n\n traverse(document.body, 0, false);\n\n const yaml = lines.join('\\n');\n \n if (yaml.length > 50000) {\n return {\n error: `Output exceeds 50000 character limit (${yaml.length} characters). Try using filter=\"interactive\".`,\n yaml: \"\",\n viewport: { width: window.innerWidth, height: window.innerHeight },\n };\n }\n\n return {\n yaml: yaml + `\\n\\n[Viewport: ${window.innerWidth}x${window.innerHeight}]`,\n viewport: { width: window.innerWidth, height: window.innerHeight },\n };\n } catch (err) {\n return {\n error: `Error generating YAML tree: ${err instanceof Error ? err.message : \"Unknown error\"}`,\n yaml: \"\",\n viewport: { width: window.innerWidth, height: window.innerHeight },\n };\n }\n}\n\nfunction getElementCoordinates(ref: string): { x: number; y: number; error?: string } {\n const elementMap = getElementMap();\n const elemRef = elementMap[ref];\n let element: Element | undefined;\n \n if (elemRef) {\n element = elemRef.element.deref();\n if (!element) {\n delete elementMap[ref];\n }\n }\n \n if (!element && window.__piRefs) {\n element = window.__piRefs[ref];\n }\n \n if (!element) {\n return { x: 0, y: 0, error: `Element ${ref} not found. Use read_page to get current elements.` };\n }\n\n const rect = element.getBoundingClientRect();\n const x = Math.round(rect.left + rect.width / 2);\n const y = Math.round(rect.top + rect.height / 2);\n\n return { x, y };\n}\n\nfunction setFormValue(ref: string, value: string | boolean | number): { success: boolean; error?: string } {\n const elementMap = getElementMap();\n const elemRef = elementMap[ref];\n let element: Element | undefined;\n \n if (elemRef) {\n element = elemRef.element.deref();\n if (!element) {\n delete elementMap[ref];\n }\n }\n \n if (!element && window.__piRefs) {\n element = window.__piRefs[ref];\n }\n \n if (!element) {\n return { success: false, error: `Element ${ref} not found. Use read_page to get current elements.` };\n }\n\n const tagName = element.tagName.toLowerCase();\n\n try {\n if (tagName === \"input\") {\n const input = element as HTMLInputElement;\n const type = input.type.toLowerCase();\n\n if (type === \"checkbox\" || type === \"radio\") {\n input.checked = Boolean(value);\n input.dispatchEvent(new Event(\"change\", { bubbles: true }));\n } else {\n input.value = String(value);\n input.dispatchEvent(new Event(\"input\", { bubbles: true }));\n input.dispatchEvent(new Event(\"change\", { bubbles: true }));\n }\n } else if (tagName === \"textarea\") {\n const textarea = element as HTMLTextAreaElement;\n textarea.value = String(value);\n textarea.dispatchEvent(new Event(\"input\", { bubbles: true }));\n textarea.dispatchEvent(new Event(\"change\", { bubbles: true }));\n } else if (tagName === \"select\") {\n const select = element as HTMLSelectElement;\n const strValue = String(value);\n\n let found = false;\n for (const option of select.options) {\n if (option.value === strValue || option.textContent?.trim() === strValue) {\n select.value = option.value;\n found = true;\n break;\n }\n }\n\n if (!found) {\n return { success: false, error: `Option \"${value}\" not found in select element ${ref}` };\n }\n\n select.dispatchEvent(new Event(\"change\", { bubbles: true }));\n } else if (element.getAttribute(\"contenteditable\") === \"true\") {\n element.textContent = String(value);\n element.dispatchEvent(new Event(\"input\", { bubbles: true }));\n } else {\n return { success: false, error: `Element ${ref} (${tagName}) is not a form field` };\n }\n\n return { success: true };\n } catch (err) {\n return { success: false, error: `Failed to set value: ${err instanceof Error ? err.message : \"Unknown error\"}` };\n }\n}\n\nfunction smartType(selector: string, text: string, clear = true, submit = false): { success: boolean; contentEditable?: boolean; error?: string } {\n try {\n const element = document.querySelector(selector) as HTMLElement | null;\n if (!element) return { success: false, error: `Element not found: ${selector}` };\n\n const contentEditableChild = element.querySelector<HTMLElement>('[contenteditable=\"true\"]');\n const target = contentEditableChild || element;\n const contentEditable = element.isContentEditable || !!contentEditableChild;\n target.focus();\n\n if (clear) {\n if (contentEditable) target.textContent = \"\";\n else (target as HTMLInputElement | HTMLTextAreaElement).value = \"\";\n }\n\n if (contentEditable) target.textContent = text;\n else (target as HTMLInputElement | HTMLTextAreaElement).value = text;\n\n target.dispatchEvent(new Event(\"input\", { bubbles: true }));\n target.dispatchEvent(new Event(\"change\", { bubbles: true }));\n\n if (submit) {\n const form = element.closest(\"form\");\n const submitButton = form?.querySelector<HTMLElement>('button[type=\"submit\"], input[type=\"submit\"]')\n || document.querySelector<HTMLElement>('button[type=\"submit\"], button[data-testid*=\"send\"], button[aria-label*=\"Send\"]');\n if (submitButton) submitButton.click();\n else if (form) form.dispatchEvent(new Event(\"submit\", { bubbles: true }));\n else target.dispatchEvent(new KeyboardEvent(\"keydown\", { key: \"Enter\", code: \"Enter\", keyCode: 13, bubbles: true }));\n }\n\n return { success: true, contentEditable };\n } catch (err) {\n return { success: false, error: err instanceof Error ? err.message : String(err) };\n }\n}\n\nfunction truncateToUtf8Bytes(input: string, maxBytes: number): string {\n const encoder = new TextEncoder();\n const encoded = encoder.encode(input);\n if (encoded.length <= maxBytes) return input;\n let end = maxBytes;\n while (end > 0 && (encoded[end] & 0xc0) === 0x80) end--;\n return new TextDecoder(\"utf-8\", { fatal: false }).decode(encoded.subarray(0, end));\n}\n\nfunction getPageText(options: { maxBytes?: number } = {}): { text: string; title: string; url: string; error?: string } {\n try {\n const article = document.querySelector(\"article\");\n const main = document.querySelector(\"main\");\n const content = article || main || document.body;\n\n const normalized = content.textContent\n ?.replace(/\\s+/g, \" \")\n .trim() || \"\";\n const text = Number.isFinite(options.maxBytes) && options.maxBytes! > 0\n ? truncateToUtf8Bytes(normalized, options.maxBytes!)\n : normalized.substring(0, 50000);\n\n return {\n text,\n title: document.title,\n url: window.location.href,\n };\n } catch (err) {\n return {\n text: \"\",\n title: \"\",\n url: \"\",\n error: `Failed to extract text: ${err instanceof Error ? err.message : \"Unknown error\"}`,\n };\n }\n}\n\nfunction scrollToElement(ref: string): { success: boolean; error?: string } {\n const elementMap = getElementMap();\n const elemRef = elementMap[ref];\n let element: Element | undefined;\n \n if (elemRef) {\n element = elemRef.element.deref();\n if (!element) {\n delete elementMap[ref];\n }\n }\n \n if (!element && window.__piRefs) {\n element = window.__piRefs[ref];\n }\n \n if (!element) {\n return { success: false, error: `Element ${ref} not found. Run read_page to get current element refs.` };\n }\n\n element.scrollIntoView({ behavior: \"smooth\", block: \"center\" });\n return { success: true };\n}\n\nfunction uploadImage(\n base64: string,\n ref?: string,\n coordinate?: [number, number],\n filename: string = \"screenshot.png\"\n): { success: boolean; error?: string } {\n try {\n const byteString = atob(base64);\n const ab = new ArrayBuffer(byteString.length);\n const ia = new Uint8Array(ab);\n for (let i = 0; i < byteString.length; i++) {\n ia[i] = byteString.charCodeAt(i);\n }\n const blob = new Blob([ab], { type: \"image/png\" });\n const file = new File([blob], filename, { type: \"image/png\" });\n\n let targetElement: HTMLElement | null = null;\n\n if (ref) {\n const elementMap = getElementMap();\n const elemRef = elementMap[ref];\n \n if (elemRef) {\n targetElement = elemRef.element.deref() as HTMLElement | null;\n if (!targetElement) {\n delete elementMap[ref];\n }\n }\n \n if (!targetElement && window.__piRefs) {\n targetElement = window.__piRefs[ref] as HTMLElement | null;\n }\n \n if (!targetElement) {\n return { success: false, error: `Element ${ref} not found. Run read_page to get current element refs.` };\n }\n } else if (coordinate) {\n targetElement = document.elementFromPoint(coordinate[0], coordinate[1]) as HTMLElement | null;\n if (!targetElement) {\n return { success: false, error: `No element at (${coordinate[0]}, ${coordinate[1]})` };\n }\n }\n\n if (!targetElement) {\n return { success: false, error: \"No target element\" };\n }\n\n if (targetElement.tagName === \"INPUT\" && (targetElement as HTMLInputElement).type === \"file\") {\n const input = targetElement as HTMLInputElement;\n const dt = new DataTransfer();\n dt.items.add(file);\n input.files = dt.files;\n input.dispatchEvent(new Event(\"change\", { bubbles: true }));\n return { success: true };\n }\n\n const dt = new DataTransfer();\n dt.items.add(file);\n\n const dropEvent = new DragEvent(\"drop\", {\n bubbles: true,\n cancelable: true,\n dataTransfer: dt,\n });\n\n targetElement.dispatchEvent(dropEvent);\n return { success: true };\n } catch (err) {\n return {\n success: false,\n error: err instanceof Error ? err.message : \"Upload failed\",\n };\n }\n}\n\nlet playbookWatch: { includeInputValues: boolean } | null = null;\n\nfunction watchSelector(element: Element): string {\n if (element.id) return `#${CSS.escape(element.id)}`;\n for (const name of [\"data-testid\", \"data-test-id\", \"name\", \"aria-label\"]) {\n const value = element.getAttribute(name);\n if (value) return `${element.tagName.toLowerCase()}[${name}=${JSON.stringify(value)}]`;\n }\n return element.tagName.toLowerCase();\n}\n\nfunction postWatchEvent(event: string, element?: Element, value?: string): void {\n if (!playbookWatch) return;\n chrome.runtime.sendMessage({\n type: \"PLAYBOOK_WATCH_EVENT\",\n event,\n selector: element ? watchSelector(element) : undefined,\n value,\n url: location.href,\n timestamp: new Date().toISOString(),\n }).catch(() => {});\n}\n\nif (typeof document.addEventListener === \"function\") {\n document.addEventListener(\"click\", (event) => {\n if (event.isTrusted && event.target instanceof Element) postWatchEvent(\"click\", event.target);\n }, true);\n document.addEventListener(\"change\", (event) => {\n if (!event.isTrusted || !(event.target instanceof HTMLInputElement || event.target instanceof HTMLTextAreaElement || event.target instanceof HTMLSelectElement)) return;\n const target = event.target;\n const secret = target instanceof HTMLInputElement && target.type === \"password\";\n const value = playbookWatch?.includeInputValues && !secret ? target.value : \"<input>\";\n postWatchEvent(\"input\", target, value);\n }, true);\n}\nif (typeof window.addEventListener === \"function\") {\n window.addEventListener(\"popstate\", () => postWatchEvent(\"navigation\"));\n window.addEventListener(\"hashchange\", () => postWatchEvent(\"navigation\"));\n}\n\nchrome.runtime.onMessage.addListener((message, sender, sendResponse) => {\n switch (message.type) {\n case \"PLAYBOOK_WATCH_START\":\n playbookWatch = { includeInputValues: message.includeInputValues === true };\n sendResponse({ success: true });\n break;\n case \"PLAYBOOK_WATCH_STOP\":\n playbookWatch = null;\n sendResponse({ success: true });\n break;\n case \"SHOW_AGENT_INDICATORS\":\n case \"HIDE_AGENT_INDICATORS\":\n case \"HIDE_FOR_TOOL_USE\":\n case \"SHOW_AFTER_TOOL_USE\":\n case \"SHOW_STATIC_INDICATOR\":\n case \"HIDE_STATIC_INDICATOR\": {\n if (!window.__piVisualIndicatorMessageHandler) {\n sendResponse({ error: \"Visual indicator content script not loaded.\" });\n break;\n }\n window.__piVisualIndicatorMessageHandler(message.type as VisualIndicatorMessageType);\n sendResponse({ success: true });\n break;\n }\n case \"GENERATE_ACCESSIBILITY_TREE\": {\n const options = message.options || {};\n \n if (options.format === \"yaml\") {\n const result = generateYamlTree(\n options.filter || \"interactive\",\n options.depth ?? 15\n );\n const modalStates = detectModalStates();\n if (result.error) {\n sendResponse({ error: result.error, pageContent: \"\", viewport: result.viewport });\n } else {\n sendResponse({ \n pageContent: result.yaml, \n viewport: result.viewport,\n modalStates: modalStates.length > 0 ? modalStates : undefined,\n modalLimitations: 'Only custom modals ([role=dialog]) detected. Native alert/confirm/prompt dialogs and system file choosers cannot be detected from content scripts.',\n });\n }\n } else {\n const result = generateAccessibilityTree(\n options.filter || \"interactive\",\n options.depth ?? 15,\n options.refId,\n options.forceFullSnapshot ?? false,\n options.compact ?? false\n );\n sendResponse(result);\n }\n break;\n }\n case \"GET_ELEMENT_COORDINATES\": {\n const result = getElementCoordinates(message.ref);\n sendResponse(result);\n break;\n }\n case \"CLICK_ELEMENT\": {\n const elementMap = getElementMap();\n const elemRef = elementMap[message.ref];\n let element: Element | undefined;\n if (elemRef) {\n element = elemRef.element.deref();\n if (!element) delete elementMap[message.ref];\n }\n if (!element && window.__piRefs) {\n element = window.__piRefs[message.ref];\n }\n if (!element) {\n sendResponse({ error: `Element ${message.ref} not found. Use read_page to get current elements.` });\n break;\n }\n if (message.button === \"triple\") {\n const tripleClick = new MouseEvent(\"click\", { bubbles: true, cancelable: true, view: window, detail: 3 });\n element.dispatchEvent(tripleClick);\n } else if (message.button === \"double\") {\n element.dispatchEvent(new MouseEvent(\"dblclick\", { bubbles: true, cancelable: true, view: window }));\n } else if (message.button === \"right\") {\n element.dispatchEvent(new MouseEvent(\"contextmenu\", { bubbles: true, cancelable: true, view: window }));\n } else {\n (element as HTMLElement).click();\n }\n sendResponse({ success: true });\n break;\n }\n case \"FORM_INPUT\": {\n const result = setFormValue(message.ref, message.value);\n sendResponse(result);\n break;\n }\n case \"EVAL_IN_PAGE\": {\n try {\n const script = document.createElement('script');\n script.textContent = `(function() { ${message.code} })();`;\n document.documentElement.appendChild(script);\n script.remove();\n sendResponse({ success: true });\n } catch (err) {\n sendResponse({ success: false, error: err instanceof Error ? err.message : String(err) });\n }\n break;\n }\n case \"GET_PAGE_TEXT\": {\n const result = getPageText(message.options || {});\n sendResponse(result);\n break;\n }\n case \"SMART_TYPE\": {\n sendResponse(smartType(message.selector, message.text, message.clear, message.submit));\n break;\n }\n case \"GET_FRAME_BY_SELECTOR\": {\n try {\n const iframe = document.querySelector(message.selector) as HTMLIFrameElement;\n if (!iframe || iframe.tagName.toLowerCase() !== 'iframe') {\n sendResponse({ error: `No iframe found with selector \"${message.selector}\"` });\n break;\n }\n // Return what info we can - the service worker will match by URL or name\n sendResponse({ \n url: iframe.src,\n name: iframe.name || undefined,\n });\n } catch (err) {\n sendResponse({ error: err instanceof Error ? err.message : String(err) });\n }\n break;\n }\n case \"GET_FRAME_NAME\": {\n // Return this frame's name (for frame matching by name)\n try {\n sendResponse({ name: window.name || null });\n } catch (err) {\n sendResponse({ name: null });\n }\n break;\n }\n case \"LOCATE_ROLE\": {\n try {\n const { role, name, all } = message;\n const elementMap = getElementMap();\n \n // Mapping of role to possible selectors\n const implicitRoles: Record<string, string[]> = {\n button: ['button', 'input[type=\"button\"]', 'input[type=\"submit\"]', 'input[type=\"reset\"]', '[role=\"button\"]'],\n link: ['a[href]', '[role=\"link\"]'],\n textbox: ['input:not([type])', 'input[type=\"text\"]', 'input[type=\"email\"]', 'input[type=\"password\"]', 'input[type=\"search\"]', 'input[type=\"tel\"]', 'input[type=\"url\"]', 'textarea', '[role=\"textbox\"]'],\n checkbox: ['input[type=\"checkbox\"]', '[role=\"checkbox\"]'],\n radio: ['input[type=\"radio\"]', '[role=\"radio\"]'],\n combobox: ['select', '[role=\"combobox\"]'],\n listbox: ['[role=\"listbox\"]', 'select[multiple]'],\n option: ['option', '[role=\"option\"]'],\n heading: ['h1', 'h2', 'h3', 'h4', 'h5', 'h6', '[role=\"heading\"]'],\n navigation: ['nav', '[role=\"navigation\"]'],\n main: ['main', '[role=\"main\"]'],\n img: ['img[alt]', '[role=\"img\"]'],\n dialog: ['dialog', '[role=\"dialog\"]', '[role=\"alertdialog\"]'],\n tab: ['[role=\"tab\"]'],\n tabpanel: ['[role=\"tabpanel\"]'],\n menu: ['[role=\"menu\"]'],\n menuitem: ['[role=\"menuitem\"]'],\n };\n \n // Build selectors for the role\n const selectors = implicitRoles[role] || [`[role=\"${role}\"]`];\n const candidates: Element[] = [];\n \n for (const sel of selectors) {\n try {\n candidates.push(...document.querySelectorAll(sel));\n } catch {}\n }\n \n // Filter by visibility\n const visible = candidates.filter(el => {\n const style = window.getComputedStyle(el);\n return style.display !== 'none' && \n style.visibility !== 'hidden' && \n (el as HTMLElement).offsetWidth > 0 &&\n (el as HTMLElement).offsetHeight > 0;\n });\n \n // Filter by name if provided\n let matches = visible;\n if (name) {\n const lowerName = name.toLowerCase();\n matches = visible.filter(el => {\n const ariaLabel = el.getAttribute('aria-label')?.toLowerCase();\n const text = el.textContent?.trim().toLowerCase();\n const title = el.getAttribute('title')?.toLowerCase();\n const placeholder = (el as HTMLInputElement).placeholder?.toLowerCase();\n const value = (el as HTMLInputElement).value?.toLowerCase();\n \n return ariaLabel?.includes(lowerName) || \n text?.includes(lowerName) || \n title?.includes(lowerName) ||\n placeholder?.includes(lowerName) ||\n value?.includes(lowerName);\n });\n }\n \n if (matches.length === 0) {\n sendResponse({ error: `No element found with role \"${role}\"${name ? ` and name \"${name}\"` : ''}` });\n break;\n }\n \n // Generate refs for matches\n const results = matches.map(el => {\n const ref = getOrAssignRef(el, role, name || '');\n window.__piRefs = window.__piRefs || {};\n window.__piRefs[ref] = el;\n elementMap[ref] = { element: new WeakRef(el), role, name: name || '' };\n return { ref, text: el.textContent?.trim().slice(0, 50) };\n });\n \n if (all) {\n sendResponse({ matches: results });\n } else {\n sendResponse({ ref: results[0].ref, text: results[0].text });\n }\n } catch (err) {\n sendResponse({ error: err instanceof Error ? err.message : String(err) });\n }\n break;\n }\n case \"LOCATE_TEXT\": {\n try {\n const { text, exact } = message;\n const elementMap = getElementMap();\n \n // Find elements containing the text\n const walker = document.createTreeWalker(document.body, NodeFilter.SHOW_TEXT);\n const matches: Element[] = [];\n \n while (walker.nextNode()) {\n const nodeText = walker.currentNode.textContent || '';\n const hasMatch = exact \n ? nodeText.trim() === text \n : nodeText.toLowerCase().includes(text.toLowerCase());\n \n if (hasMatch) {\n const parent = walker.currentNode.parentElement;\n if (parent && !matches.includes(parent)) {\n // Check visibility\n const style = window.getComputedStyle(parent);\n if (style.display !== 'none' && style.visibility !== 'hidden') {\n matches.push(parent);\n }\n }\n }\n }\n \n if (matches.length === 0) {\n sendResponse({ error: `No element found with text \"${text}\"` });\n break;\n }\n \n // Pick the most specific (smallest) element\n const el = matches.sort((a, b) => \n (a.textContent?.length || 0) - (b.textContent?.length || 0)\n )[0];\n \n const role = getResolvedRole(el);\n const ref = getOrAssignRef(el, role, text);\n window.__piRefs = window.__piRefs || {};\n window.__piRefs[ref] = el;\n elementMap[ref] = { element: new WeakRef(el), role, name: text };\n \n sendResponse({ ref, text: el.textContent?.trim().slice(0, 50) });\n } catch (err) {\n sendResponse({ error: err instanceof Error ? err.message : String(err) });\n }\n break;\n }\n case \"LOCATE_LABEL\": {\n try {\n const { label } = message;\n const elementMap = getElementMap();\n \n // Find label element\n const labels = document.querySelectorAll('label');\n let input: Element | null = null;\n \n for (const lbl of labels) {\n const lblText = lbl.textContent?.trim().toLowerCase();\n if (lblText?.includes(label.toLowerCase())) {\n // Check for 'for' attribute\n const forId = lbl.getAttribute('for');\n if (forId) {\n input = document.getElementById(forId);\n }\n // Check for nested input\n if (!input) {\n input = lbl.querySelector('input, select, textarea');\n }\n if (input) break;\n }\n }\n \n // Also check aria-label and placeholder\n if (!input) {\n const lowerLabel = label.toLowerCase();\n input = document.querySelector(\n `input[aria-label*=\"${label}\" i], input[placeholder*=\"${label}\" i], ` +\n `textarea[aria-label*=\"${label}\" i], textarea[placeholder*=\"${label}\" i], ` +\n `select[aria-label*=\"${label}\" i]`\n );\n }\n \n if (!input) {\n sendResponse({ error: `No form field found with label \"${label}\"` });\n break;\n }\n \n const role = getResolvedRole(input);\n const ref = getOrAssignRef(input, role, label);\n window.__piRefs = window.__piRefs || {};\n window.__piRefs[ref] = input;\n elementMap[ref] = { element: new WeakRef(input), role, name: label };\n \n sendResponse({ ref, label });\n } catch (err) {\n sendResponse({ error: err instanceof Error ? err.message : String(err) });\n }\n break;\n }\n case \"GET_ELEMENT_STYLES\": {\n try {\n const { selector } = message;\n const elementMap = getElementMap();\n \n // Helper to extract styles from an element\n const extractStyles = (el: Element) => {\n const s = getComputedStyle(el);\n const r = el.getBoundingClientRect();\n return {\n tag: el.tagName.toLowerCase(),\n text: (el as HTMLElement).innerText?.trim().slice(0, 80) || null,\n box: {\n x: Math.round(r.x),\n y: Math.round(r.y),\n width: Math.round(r.width),\n height: Math.round(r.height),\n },\n styles: {\n fontSize: s.fontSize,\n fontWeight: s.fontWeight,\n fontFamily: s.fontFamily.split(',')[0].trim().replace(/\"/g, ''),\n color: s.color,\n backgroundColor: s.backgroundColor,\n borderRadius: s.borderRadius,\n border: s.border !== 'none' && s.borderWidth !== '0px' ? s.border : null,\n boxShadow: s.boxShadow !== 'none' ? s.boxShadow : null,\n padding: s.padding,\n },\n };\n };\n \n // Check if selector is a ref (e.g., \"e5\")\n if (/^e\\d+$/.test(selector)) {\n const elemRef = elementMap[selector];\n let element: Element | undefined;\n if (elemRef) {\n element = elemRef.element.deref();\n if (!element) delete elementMap[selector];\n }\n if (!element && window.__piRefs) {\n element = window.__piRefs[selector];\n }\n \n if (!element) {\n sendResponse({ error: `Element ${selector} not found` });\n break;\n }\n \n sendResponse({ styles: [extractStyles(element)] });\n } else {\n // CSS selector - can match multiple elements\n const elements = document.querySelectorAll(selector);\n if (elements.length === 0) {\n sendResponse({ error: `No elements found matching \"${selector}\"` });\n break;\n }\n \n const styles = Array.from(elements).map(extractStyles);\n sendResponse({ styles });\n }\n } catch (err) {\n sendResponse({ error: err instanceof Error ? err.message : String(err) });\n }\n break;\n }\n case \"SELECT_OPTION\": {\n try {\n const { selector, values, by } = message;\n const elementMap = getElementMap();\n \n // Find the select element\n let selectEl: HTMLSelectElement | null = null;\n \n if (/^e\\d+$/.test(selector)) {\n const elemRef = elementMap[selector];\n let element: Element | undefined;\n if (elemRef) {\n element = elemRef.element.deref();\n if (!element) delete elementMap[selector];\n }\n if (!element && window.__piRefs) {\n element = window.__piRefs[selector];\n }\n \n if (!element) {\n sendResponse({ error: `Element ${selector} not found` });\n break;\n }\n if (element.tagName !== 'SELECT') {\n sendResponse({ error: `Element ${selector} is not a <select>` });\n break;\n }\n selectEl = element as HTMLSelectElement;\n } else {\n selectEl = document.querySelector(selector) as HTMLSelectElement;\n if (!selectEl) {\n sendResponse({ error: `No element found matching \"${selector}\"` });\n break;\n }\n if (selectEl.tagName !== 'SELECT') {\n sendResponse({ error: `Element \"${selector}\" is not a <select>` });\n break;\n }\n }\n \n // Clear current selection for multi-select\n if (selectEl.multiple) {\n for (const opt of selectEl.options) {\n opt.selected = false;\n }\n }\n \n const selected: string[] = [];\n const notFound: string[] = [];\n \n // For single-select, only use the first value\n const valuesToSelect = selectEl.multiple ? values : [values[0]];\n \n for (const val of valuesToSelect) {\n let found = false;\n \n for (const opt of selectEl.options) {\n let matches = false;\n \n if (by === 'index') {\n matches = opt.index === parseInt(val, 10);\n } else if (by === 'label') {\n matches = opt.text.toLowerCase().includes(val.toLowerCase());\n } else {\n // Default: match by value\n matches = opt.value === val;\n }\n \n if (matches) {\n opt.selected = true;\n selected.push(opt.value);\n found = true;\n break; // Found match for this value, move to next\n }\n }\n \n if (!found) notFound.push(val);\n }\n \n // Dispatch change event\n selectEl.dispatchEvent(new Event('change', { bubbles: true }));\n \n if (notFound.length > 0) {\n sendResponse({ \n selected, \n warning: `Values not found: ${notFound.join(', ')}` \n });\n } else {\n sendResponse({ selected });\n }\n } catch (err) {\n sendResponse({ error: err instanceof Error ? err.message : String(err) });\n }\n break;\n }\n case \"GET_ELEMENT_TEXT\": {\n try {\n const { ref } = message;\n const elementMap = getElementMap();\n const elemRef = elementMap[ref];\n \n let element: Element | undefined;\n if (elemRef) {\n element = elemRef.element.deref();\n if (!element) delete elementMap[ref];\n }\n if (!element && window.__piRefs) {\n element = window.__piRefs[ref];\n }\n \n if (!element) {\n sendResponse({ error: `Element ${ref} not found` });\n break;\n }\n \n sendResponse({ text: element.textContent?.trim() || '' });\n } catch (err) {\n sendResponse({ error: err instanceof Error ? err.message : String(err) });\n }\n break;\n }\n case \"SCROLL_TO_ELEMENT\": {\n const result = scrollToElement(message.ref);\n sendResponse(result);\n break;\n }\n case \"UPLOAD_IMAGE\": {\n const result = uploadImage(message.base64, message.ref, message.coordinate, message.filename);\n sendResponse(result);\n break;\n }\n case \"WAIT_FOR_ELEMENT\": {\n const { selector, state = 'visible', timeout = 20000 } = message;\n const maxTimeout = Math.min(timeout, 60000);\n\n const isElementVisible = (el: Element | null): boolean => {\n if (!el) return false;\n const style = window.getComputedStyle(el);\n return style.display !== 'none' && \n style.visibility !== 'hidden' && \n style.opacity !== '0' &&\n (el as HTMLElement).offsetWidth > 0 &&\n (el as HTMLElement).offsetHeight > 0;\n };\n\n const checkElement = (): boolean => {\n const el = document.querySelector(selector);\n switch (state) {\n case 'attached': return !!el;\n case 'detached': return !el;\n case 'hidden': return !el || !isElementVisible(el);\n case 'visible':\n default: return isElementVisible(el);\n }\n };\n\n const startTime = Date.now();\n \n const waitForCondition = (): Promise<{ success: boolean; waited: number; error?: string }> => {\n return new Promise((resolve) => {\n if (checkElement()) {\n resolve({ success: true, waited: Date.now() - startTime });\n return;\n }\n\n const observer = new MutationObserver(() => {\n if (checkElement()) {\n observer.disconnect();\n clearTimeout(timeoutId);\n resolve({ success: true, waited: Date.now() - startTime });\n }\n });\n\n const timeoutId = setTimeout(() => {\n observer.disconnect();\n resolve({ \n success: false, \n waited: Date.now() - startTime,\n error: `Timeout waiting for \"${selector}\" to be ${state}` \n });\n }, maxTimeout);\n\n observer.observe(document.documentElement, {\n childList: true,\n subtree: true,\n attributes: true,\n attributeFilter: ['style', 'class', 'hidden', 'disabled']\n });\n });\n };\n\n waitForCondition().then((waitResult) => {\n if (!waitResult.success) {\n sendResponse({ \n error: waitResult.error, \n waited: waitResult.waited,\n pageContent: \"\", \n viewport: { width: window.innerWidth, height: window.innerHeight } \n });\n return;\n }\n const treeResult = generateAccessibilityTree(\"interactive\", 15, undefined, true);\n sendResponse({ ...treeResult, waited: waitResult.waited });\n });\n return true;\n }\n case \"WAIT_FOR_URL\": {\n const { pattern, timeout = 20000 } = message;\n const maxTimeout = Math.min(timeout, 60000);\n\n const matchesPattern = (url: string): boolean => {\n if (pattern.includes('*')) {\n const regexPattern = pattern\n .replace(/[.+?^${}()|[\\]\\\\]/g, '\\\\$&')\n .replace(/\\*\\*/g, '<<<GLOBSTAR>>>')\n .replace(/\\*/g, '[^/]*')\n .replace(/<<<GLOBSTAR>>>/g, '.*');\n return new RegExp(`^${regexPattern}$`).test(url);\n }\n return url.includes(pattern);\n };\n\n const startTime = Date.now();\n\n const waitForUrl = (): Promise<{ success: boolean; waited: number; error?: string }> => {\n return new Promise((resolve) => {\n if (matchesPattern(window.location.href)) {\n resolve({ success: true, waited: Date.now() - startTime });\n return;\n }\n\n let resolved = false;\n const checkUrl = () => {\n if (resolved) return;\n if (matchesPattern(window.location.href)) {\n resolved = true;\n clearInterval(intervalId);\n clearTimeout(timeoutId);\n window.removeEventListener('popstate', checkUrl);\n window.removeEventListener('hashchange', checkUrl);\n resolve({ success: true, waited: Date.now() - startTime });\n }\n };\n\n const intervalId = setInterval(checkUrl, 100);\n const timeoutId = setTimeout(() => {\n if (resolved) return;\n resolved = true;\n clearInterval(intervalId);\n window.removeEventListener('popstate', checkUrl);\n window.removeEventListener('hashchange', checkUrl);\n resolve({ \n success: false, \n waited: Date.now() - startTime,\n error: `Timeout waiting for URL to match \"${pattern}\". Current: ${window.location.href}` \n });\n }, maxTimeout);\n\n window.addEventListener('popstate', checkUrl);\n window.addEventListener('hashchange', checkUrl);\n });\n };\n\n waitForUrl().then((waitResult) => {\n if (!waitResult.success) {\n sendResponse({ \n error: waitResult.error, \n waited: waitResult.waited,\n pageContent: \"\", \n viewport: { width: window.innerWidth, height: window.innerHeight } \n });\n return;\n }\n const treeResult = generateAccessibilityTree(\"interactive\", 15, undefined, true);\n sendResponse({ ...treeResult, waited: waitResult.waited });\n });\n return true;\n }\n case \"WAIT_FOR_DOM_STABLE\": {\n const { stable = 100, timeout = 5000 } = message;\n const maxTimeout = Math.min(timeout, 30000);\n const startTime = Date.now();\n\n const waitForStability = (): Promise<{ success: boolean; waited: number; error?: string }> => {\n return new Promise((resolve) => {\n let lastMutationTime = Date.now();\n let resolved = false;\n\n const checkStability = () => {\n if (resolved) return;\n const timeSinceLastMutation = Date.now() - lastMutationTime;\n if (timeSinceLastMutation >= stable) {\n resolved = true;\n observer.disconnect();\n clearTimeout(timeoutId);\n clearInterval(checkInterval);\n resolve({ success: true, waited: Date.now() - startTime });\n }\n };\n\n const observer = new MutationObserver(() => {\n lastMutationTime = Date.now();\n });\n\n const timeoutId = setTimeout(() => {\n if (resolved) return;\n resolved = true;\n observer.disconnect();\n clearInterval(checkInterval);\n resolve({\n success: false,\n waited: Date.now() - startTime,\n error: `Timeout: DOM did not stabilize within ${maxTimeout}ms`\n });\n }, maxTimeout);\n\n const checkInterval = setInterval(checkStability, Math.max(10, Math.min(50, stable / 2)));\n\n observer.observe(document.documentElement, {\n childList: true,\n subtree: true,\n attributes: true,\n characterData: true,\n });\n\n checkStability();\n });\n };\n\n waitForStability().then((waitResult) => {\n if (!waitResult.success) {\n sendResponse({\n error: waitResult.error,\n waited: waitResult.waited,\n pageContent: \"\",\n viewport: { width: window.innerWidth, height: window.innerHeight }\n });\n return;\n }\n const treeResult = generateAccessibilityTree(\"interactive\", 15, undefined, true);\n sendResponse({ ...treeResult, waited: waitResult.waited });\n });\n return true;\n }\n case \"FORM_FILL\": {\n const { data } = message;\n if (!Array.isArray(data)) {\n sendResponse({ error: \"data must be an array of {ref, value} pairs\" });\n return true;\n }\n const elementMap = getElementMap();\n const results: { ref: string; success: boolean; error?: string }[] = [];\n for (const item of data) {\n const { ref, value } = item;\n if (!ref) {\n results.push({ ref: ref || \"unknown\", success: false, error: \"Missing ref\" });\n continue;\n }\n const elemRef = elementMap[ref];\n if (!elemRef) {\n results.push({ ref, success: false, error: \"Element not found (run page.read first)\" });\n continue;\n }\n const el = elemRef.element.deref() as HTMLElement | null;\n if (!el) {\n delete elementMap[ref];\n results.push({ ref, success: false, error: \"Element no longer exists\" });\n continue;\n }\n try {\n if (el instanceof HTMLInputElement) {\n const inputType = el.type.toLowerCase();\n if (inputType === \"checkbox\" || inputType === \"radio\") {\n const shouldCheck = value === true || value === \"true\" || value === \"1\" || value === \"checked\";\n el.checked = shouldCheck;\n el.dispatchEvent(new Event(\"change\", { bubbles: true }));\n } else {\n el.focus();\n el.value = String(value);\n el.dispatchEvent(new Event(\"input\", { bubbles: true }));\n el.dispatchEvent(new Event(\"change\", { bubbles: true }));\n }\n results.push({ ref, success: true });\n } else if (el instanceof HTMLTextAreaElement) {\n el.focus();\n el.value = String(value);\n el.dispatchEvent(new Event(\"input\", { bubbles: true }));\n el.dispatchEvent(new Event(\"change\", { bubbles: true }));\n results.push({ ref, success: true });\n } else if (el instanceof HTMLSelectElement) {\n el.value = String(value);\n el.dispatchEvent(new Event(\"change\", { bubbles: true }));\n results.push({ ref, success: true });\n } else if (el.isContentEditable) {\n el.focus();\n el.textContent = String(value);\n el.dispatchEvent(new Event(\"input\", { bubbles: true }));\n results.push({ ref, success: true });\n } else {\n results.push({ ref, success: false, error: \"Element is not fillable\" });\n }\n } catch (e) {\n results.push({ ref, success: false, error: e instanceof Error ? e.message : String(e) });\n }\n }\n const failed = results.filter(r => !r.success);\n sendResponse({\n success: failed.length === 0,\n filled: results.filter(r => r.success).length,\n failed: failed.length,\n results,\n });\n return true;\n }\n case \"GET_FILE_INPUT_SELECTOR\": {\n const { ref } = message;\n if (!ref) {\n sendResponse({ error: \"No ref provided\" });\n return true;\n }\n const elementMap = getElementMap();\n const elemRef = elementMap[ref];\n if (!elemRef) {\n sendResponse({ error: \"Element not found (run page.read first)\" });\n return true;\n }\n const el = elemRef.element.deref() as HTMLElement | null;\n if (!el) {\n delete elementMap[ref];\n sendResponse({ error: \"Element no longer exists\" });\n return true;\n }\n if (!(el instanceof HTMLInputElement) || el.type !== \"file\") {\n sendResponse({ error: \"Element is not a file input\" });\n return true;\n }\n const uniqueId = `__pi_file_${Date.now()}`;\n el.setAttribute(\"data-pi-file-id\", uniqueId);\n sendResponse({ selector: `[data-pi-file-id=\"${uniqueId}\"]` });\n return true;\n }\n case \"WAIT_FOR_NETWORK_IDLE\": {\n const { timeout = 10000 } = message;\n const maxTimeout = Math.min(timeout, 60000);\n\n const adPatterns = [\n \"doubleclick.net\", \"googlesyndication.com\", \"googletagmanager.com\",\n \"google-analytics.com\", \"facebook.net\", \"connect.facebook.net\",\n \"analytics\", \"ads\", \"tracking\", \"pixel\", \"hotjar.com\", \"clarity.ms\",\n \"mixpanel.com\", \"segment.com\", \"newrelic.com\", \"nr-data.net\",\n \"/tracker/\", \"/collector/\", \"/beacon/\", \"/telemetry/\", \"/log/\",\n \"/events/\", \"/track.\", \"/metrics/\"\n ];\n\n const nonCriticalTypes = [\"img\", \"image\", \"font\", \"icon\"];\n\n const isAdOrTracking = (url: string): boolean => {\n return adPatterns.some(pattern => url.includes(pattern));\n };\n\n const isNonCritical = (entry: PerformanceResourceTiming): boolean => {\n const type = entry.initiatorType || \"unknown\";\n if (nonCriticalTypes.includes(type)) return true;\n if (/\\.(jpg|jpeg|png|gif|webp|svg|ico|woff|woff2|ttf|eot)(\\?|$)/i.test(entry.name)) return true;\n return false;\n };\n\n const getPendingRequests = (): PerformanceResourceTiming[] => {\n const now = performance.now();\n const resources = performance.getEntriesByType(\"resource\") as PerformanceResourceTiming[];\n return resources.filter(entry => {\n if (entry.responseEnd !== 0) return false;\n if (entry.name.startsWith(\"data:\")) return false;\n if (entry.name.length > 500) return false;\n if (isAdOrTracking(entry.name)) return false;\n const loadingDuration = now - entry.startTime;\n if (loadingDuration > 10000) return false;\n if (isNonCritical(entry) && loadingDuration > 3000) return false;\n return true;\n });\n };\n\n const startTime = Date.now();\n\n const waitForIdle = (): Promise<{ success: boolean; waited: number; pendingCount?: number }> => {\n return new Promise((resolve) => {\n const check = () => {\n const pending = getPendingRequests();\n const elapsed = Date.now() - startTime;\n \n if (pending.length === 0) {\n resolve({ success: true, waited: elapsed });\n return;\n }\n \n if (elapsed >= maxTimeout) {\n resolve({ success: false, waited: elapsed, pendingCount: pending.length });\n return;\n }\n \n setTimeout(check, 100);\n };\n check();\n });\n };\n\n waitForIdle().then((waitResult) => {\n if (!waitResult.success) {\n sendResponse({ \n error: `Network not idle after ${waitResult.waited}ms (${waitResult.pendingCount} requests pending)`,\n waited: waitResult.waited,\n pageContent: \"\", \n viewport: { width: window.innerWidth, height: window.innerHeight } \n });\n return;\n }\n const treeResult = generateAccessibilityTree(\"interactive\", 15, undefined, true);\n sendResponse({ ...treeResult, waited: waitResult.waited });\n });\n return true;\n }\n case \"SEARCH_PAGE\": {\n const { term, caseSensitive, limit } = message;\n const matches = searchPageText(term, caseSensitive || false, limit || 10);\n sendResponse({ query: term, count: matches.length, matches });\n break;\n }\n case \"GET_ELEMENT_BOUNDS_FOR_ANNOTATION\": {\n const elementMap = getElementMap();\n const elements: Array<{ ref: string; tag: string; bounds: { x: number; y: number; width: number; height: number } }> = [];\n \n for (const [ref, entry] of Object.entries(elementMap)) {\n const el = entry.element.deref();\n if (!el) continue;\n \n const rect = el.getBoundingClientRect();\n if (rect.width <= 0 || rect.height <= 0) continue;\n if (rect.bottom < 0 || rect.top > window.innerHeight) continue;\n if (rect.right < 0 || rect.left > window.innerWidth) continue;\n \n elements.push({\n ref,\n tag: el.tagName.toLowerCase(),\n bounds: {\n x: rect.x,\n y: rect.y,\n width: rect.width,\n height: rect.height,\n },\n });\n }\n \n sendResponse({ elements });\n break;\n }\n default:\n return false;\n }\n return false;\n});\n\nfunction searchPageText(term: string, caseSensitive: boolean, limit: number) {\n const matches: Array<{\n ref: string;\n text: string;\n context: string;\n bounds: { x: number; y: number; width: number; height: number };\n elementRef: string | null;\n }> = [];\n \n const searchTerm = caseSensitive ? term : term.toLowerCase();\n const walker = document.createTreeWalker(document.body, NodeFilter.SHOW_TEXT);\n const elementMap = getElementMap();\n let matchIndex = 0;\n \n while (walker.nextNode() && matches.length < limit) {\n const node = walker.currentNode;\n const textContent = node.textContent || \"\";\n const searchIn = caseSensitive ? textContent : textContent.toLowerCase();\n \n let pos = 0;\n while ((pos = searchIn.indexOf(searchTerm, pos)) !== -1 && matches.length < limit) {\n const parent = node.parentElement;\n if (!parent) { pos++; continue; }\n \n const range = document.createRange();\n range.setStart(node, pos);\n range.setEnd(node, Math.min(pos + term.length, textContent.length));\n const rect = range.getBoundingClientRect();\n \n if (rect.width === 0 || rect.height === 0) { pos++; continue; }\n \n const fullText = node.textContent || \"\";\n const contextStart = Math.max(0, pos - 30);\n const contextEnd = Math.min(fullText.length, pos + term.length + 30);\n const context = fullText.slice(contextStart, contextEnd).trim();\n \n let elementRef: string | null = null;\n for (const [ref, entry] of Object.entries(elementMap)) {\n const el = entry.element.deref();\n if (el && (el === parent || el.contains(parent))) {\n elementRef = ref;\n break;\n }\n }\n \n matches.push({\n ref: `m${++matchIndex}`,\n text: fullText.slice(pos, pos + term.length),\n context,\n bounds: {\n x: Math.round(rect.x),\n y: Math.round(rect.y),\n width: Math.round(rect.width),\n height: Math.round(rect.height),\n },\n elementRef,\n });\n \n pos++;\n }\n }\n \n return matches;\n}\n"],"mappings":"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"}
|
package/dist/icons/icon-128.png
CHANGED
|
Binary file
|
package/dist/icons/icon-16.png
CHANGED
|
Binary file
|
package/dist/icons/icon-48.png
CHANGED
|
Binary file
|
package/dist/manifest.json
CHANGED
|
@@ -24,15 +24,9 @@
|
|
|
24
24
|
"content_scripts": [
|
|
25
25
|
{
|
|
26
26
|
"matches": ["<all_urls>"],
|
|
27
|
-
"js": ["content/
|
|
27
|
+
"js": ["content/index.js"],
|
|
28
28
|
"run_at": "document_start",
|
|
29
29
|
"all_frames": true
|
|
30
|
-
},
|
|
31
|
-
{
|
|
32
|
-
"matches": ["<all_urls>"],
|
|
33
|
-
"js": ["content/visual-indicator.js"],
|
|
34
|
-
"run_at": "document_idle",
|
|
35
|
-
"all_frames": false
|
|
36
30
|
}
|
|
37
31
|
],
|
|
38
32
|
"permissions": [
|
|
@@ -60,10 +54,7 @@
|
|
|
60
54
|
"web_accessible_resources": [
|
|
61
55
|
{
|
|
62
56
|
"matches": ["<all_urls>"],
|
|
63
|
-
"resources": [
|
|
64
|
-
"content/accessibility-tree.js",
|
|
65
|
-
"content/visual-indicator.js"
|
|
66
|
-
],
|
|
57
|
+
"resources": ["content/index.js"],
|
|
67
58
|
"use_dynamic_url": false
|
|
68
59
|
}
|
|
69
60
|
]
|
package/dist/options/options.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
(function(){
|
|
1
|
+
(function(){let e=document.createElement(`link`).relList;if(e&&e.supports&&e.supports(`modulepreload`))return;for(let e of document.querySelectorAll(`link[rel="modulepreload"]`))n(e);new MutationObserver(e=>{for(let t of e)if(t.type===`childList`)for(let e of t.addedNodes)e.tagName===`LINK`&&e.rel===`modulepreload`&&n(e)}).observe(document,{childList:!0,subtree:!0});function t(e){let t={};return e.integrity&&(t.integrity=e.integrity),e.referrerPolicy&&(t.referrerPolicy=e.referrerPolicy),t.credentials=e.crossOrigin===`use-credentials`?`include`:e.crossOrigin===`anonymous`?`omit`:`same-origin`,t}function n(e){if(e.ep)return;e.ep=!0;let n=t(e);fetch(e.href,n)}})();var e=document.getElementById(`app`);e.innerHTML=`
|
|
2
2
|
<h1 style="font-size: 1.5rem; font-weight: bold; margin-bottom: 1.5rem;">Surf Settings</h1>
|
|
3
3
|
|
|
4
4
|
<section style="margin-bottom: 2rem;">
|
|
@@ -26,5 +26,5 @@
|
|
|
26
26
|
Surf v${chrome.runtime.getManifest().version}
|
|
27
27
|
</p>
|
|
28
28
|
</section>
|
|
29
|
-
`;
|
|
30
|
-
//# sourceMappingURL=options.js.map
|
|
29
|
+
`;var t=document.getElementById(`debug-mode`);t&&(chrome.storage.local.get(`debugMode`).then(({debugMode:e})=>{t.checked=!!e}),t.addEventListener(`change`,()=>{chrome.storage.local.set({debugMode:t.checked})}));var n=document.getElementById(`heartbeat-interval`);n&&(chrome.storage.local.get(`heartbeatInterval`).then(({heartbeatInterval:e})=>{n.value=String(e??10)}),n.addEventListener(`change`,()=>{let e=Math.max(5,Math.min(60,parseInt(n.value,10)||10));n.value=String(e),chrome.storage.local.set({heartbeatInterval:e})}));
|
|
30
|
+
//# sourceMappingURL=options.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"options.js","sources":["../../src/options/main.ts"],"sourcesContent":["const app = document.getElementById(\"app\")!;\n\napp.innerHTML = `\n <h1 style=\"font-size: 1.5rem; font-weight: bold; margin-bottom: 1.5rem;\">Surf Settings</h1>\n \n <section style=\"margin-bottom: 2rem;\">\n <h2 style=\"font-size: 1.125rem; font-weight: 600; margin-bottom: 1rem;\">Debug Mode</h2>\n <label style=\"display: flex; align-items: center; gap: 0.5rem;\">\n <input type=\"checkbox\" id=\"debug-mode\" style=\"width: 1rem; height: 1rem;\" />\n <span>Enable debug logging</span>\n </label>\n </section>\n \n <section style=\"margin-bottom: 2rem;\">\n <h2 style=\"font-size: 1.125rem; font-weight: 600; margin-bottom: 1rem;\">Static Indicator</h2>\n <label style=\"display: flex; align-items: center; gap: 0.5rem;\">\n <span>Heartbeat interval (seconds):</span>\n <input type=\"number\" id=\"heartbeat-interval\" min=\"5\" max=\"60\" value=\"10\" style=\"width: 4rem; padding: 0.25rem 0.5rem; border: 1px solid #ccc; border-radius: 0.25rem;\" />\n </label>\n <p class=\"muted\" style=\"font-size: 0.875rem; margin-top: 0.5rem;\">\n How often the static indicator checks if Surf is still active (5-60 seconds).\n </p>\n </section>\n \n <section style=\"margin-bottom: 2rem;\">\n <h2 style=\"font-size: 1.125rem; font-weight: 600; margin-bottom: 1rem;\">About</h2>\n <p class=\"muted\">\n Surf v${chrome.runtime.getManifest().version}\n </p>\n </section>\n`;\n\nconst debugCheckbox = document.getElementById(\"debug-mode\") as HTMLInputElement | null;\nif (debugCheckbox) {\n chrome.storage.local.get(\"debugMode\").then(({ debugMode }) => {\n debugCheckbox.checked = !!debugMode;\n });\n debugCheckbox.addEventListener(\"change\", () => {\n chrome.storage.local.set({ debugMode: debugCheckbox.checked });\n });\n}\n\nconst heartbeatInput = document.getElementById(\"heartbeat-interval\") as HTMLInputElement | null;\nif (heartbeatInput) {\n chrome.storage.local.get(\"heartbeatInterval\").then(({ heartbeatInterval }) => {\n heartbeatInput.value = String(heartbeatInterval ?? 10);\n });\n heartbeatInput.addEventListener(\"change\", () => {\n const value = Math.max(5, Math.min(60, parseInt(heartbeatInput.value, 10) || 10));\n heartbeatInput.value = String(value);\n chrome.storage.local.set({ heartbeatInterval: value });\n });\n}\n"],"
|
|
1
|
+
{"version":3,"file":"options.js","names":[],"sources":["../../src/options/main.ts"],"sourcesContent":["const app = document.getElementById(\"app\")!;\n\napp.innerHTML = `\n <h1 style=\"font-size: 1.5rem; font-weight: bold; margin-bottom: 1.5rem;\">Surf Settings</h1>\n \n <section style=\"margin-bottom: 2rem;\">\n <h2 style=\"font-size: 1.125rem; font-weight: 600; margin-bottom: 1rem;\">Debug Mode</h2>\n <label style=\"display: flex; align-items: center; gap: 0.5rem;\">\n <input type=\"checkbox\" id=\"debug-mode\" style=\"width: 1rem; height: 1rem;\" />\n <span>Enable debug logging</span>\n </label>\n </section>\n \n <section style=\"margin-bottom: 2rem;\">\n <h2 style=\"font-size: 1.125rem; font-weight: 600; margin-bottom: 1rem;\">Static Indicator</h2>\n <label style=\"display: flex; align-items: center; gap: 0.5rem;\">\n <span>Heartbeat interval (seconds):</span>\n <input type=\"number\" id=\"heartbeat-interval\" min=\"5\" max=\"60\" value=\"10\" style=\"width: 4rem; padding: 0.25rem 0.5rem; border: 1px solid #ccc; border-radius: 0.25rem;\" />\n </label>\n <p class=\"muted\" style=\"font-size: 0.875rem; margin-top: 0.5rem;\">\n How often the static indicator checks if Surf is still active (5-60 seconds).\n </p>\n </section>\n \n <section style=\"margin-bottom: 2rem;\">\n <h2 style=\"font-size: 1.125rem; font-weight: 600; margin-bottom: 1rem;\">About</h2>\n <p class=\"muted\">\n Surf v${chrome.runtime.getManifest().version}\n </p>\n </section>\n`;\n\nconst debugCheckbox = document.getElementById(\"debug-mode\") as HTMLInputElement | null;\nif (debugCheckbox) {\n chrome.storage.local.get(\"debugMode\").then(({ debugMode }) => {\n debugCheckbox.checked = !!debugMode;\n });\n debugCheckbox.addEventListener(\"change\", () => {\n chrome.storage.local.set({ debugMode: debugCheckbox.checked });\n });\n}\n\nconst heartbeatInput = document.getElementById(\"heartbeat-interval\") as HTMLInputElement | null;\nif (heartbeatInput) {\n chrome.storage.local.get(\"heartbeatInterval\").then(({ heartbeatInterval }) => {\n heartbeatInput.value = String(heartbeatInterval ?? 10);\n });\n heartbeatInput.addEventListener(\"change\", () => {\n const value = Math.max(5, Math.min(60, parseInt(heartbeatInput.value, 10) || 10));\n heartbeatInput.value = String(value);\n chrome.storage.local.set({ heartbeatInterval: value });\n });\n}\n"],"mappings":"8pBAAA,IAAM,EAAM,SAAS,eAAe,KAAK,EAEzC,EAAI,UAAY;;;;;;;;;;;;;;;;;;;;;;;;;cAyBF,OAAO,QAAQ,YAAY,CAAC,CAAC,QAAQ;;;EAKnD,IAAM,EAAgB,SAAS,eAAe,YAAY,EACtD,IACF,OAAO,QAAQ,MAAM,IAAI,WAAW,CAAC,CAAC,MAAM,CAAE,eAAgB,CAC5D,EAAc,QAAU,CAAC,CAAC,CAC5B,CAAC,EACD,EAAc,iBAAiB,aAAgB,CAC7C,OAAO,QAAQ,MAAM,IAAI,CAAE,UAAW,EAAc,OAAQ,CAAC,CAC/D,CAAC,GAGH,IAAM,EAAiB,SAAS,eAAe,oBAAoB,EAC/D,IACF,OAAO,QAAQ,MAAM,IAAI,mBAAmB,CAAC,CAAC,MAAM,CAAE,uBAAwB,CAC5E,EAAe,MAAQ,OAAO,GAAqB,EAAE,CACvD,CAAC,EACD,EAAe,iBAAiB,aAAgB,CAC9C,IAAM,EAAQ,KAAK,IAAI,EAAG,KAAK,IAAI,GAAI,SAAS,EAAe,MAAO,EAAE,GAAK,EAAE,CAAC,EAChF,EAAe,MAAQ,OAAO,CAAK,EACnC,OAAO,QAAQ,MAAM,IAAI,CAAE,kBAAmB,CAAM,CAAC,CACvD,CAAC"}
|